1
0
mirror of https://github.com/nmap/nmap.git synced 2025-12-06 04:31:29 +00:00

Update libpcap to 1.10.5

This commit is contained in:
dmiller
2025-04-14 19:06:54 +00:00
parent 2bc341de52
commit aed27d094e
141 changed files with 12626 additions and 9811 deletions

View File

@@ -19,9 +19,7 @@
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
*/
#ifdef HAVE_CONFIG_H
#include <config.h>
#endif
#ifdef _WIN32
#include <ws2tcpip.h>
@@ -67,7 +65,7 @@
#include "scanner.h"
#if defined(linux)
#if defined(__linux__)
#include <linux/types.h>
#include <linux/if_packet.h>
#include <linux/filter.h>
@@ -218,7 +216,7 @@ enum e_offrel {
};
/*
* We divy out chunks of memory rather than call malloc each time so
* We divvy out chunks of memory rather than call malloc each time so
* we don't have to worry about leaking memory. It's probably
* not a big deal if all this memory was wasted but if this ever
* goes into a library that would probably not be a good idea.
@@ -670,7 +668,7 @@ sdup(compiler_state_t *cstate, const char *s)
if (cp == NULL)
return (NULL);
pcap_strlcpy(cp, s, n);
pcapint_strlcpy(cp, s, n);
return (cp);
}
@@ -724,22 +722,23 @@ pcap_compile(pcap_t *p, struct bpf_program *program,
yyscan_t scanner = NULL;
volatile YY_BUFFER_STATE in_buffer = NULL;
u_int len;
int rc;
int rc;
/*
* If this pcap_t hasn't been activated, it doesn't have a
* link-layer type, so we can't use it.
*/
if (!p->activated) {
snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
(void)snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
"not-yet-activated pcap_t passed to pcap_compile");
return (PCAP_ERROR);
}
#ifdef _WIN32
if (!done)
if (!done) {
pcap_wsockinit();
done = 1;
done = 1;
}
#endif
#ifdef ENABLE_REMOTE
@@ -779,15 +778,18 @@ pcap_compile(pcap_t *p, struct bpf_program *program,
cstate.snaplen = pcap_snapshot(p);
if (cstate.snaplen == 0) {
snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
(void)snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
"snaplen of 0 rejects all packets");
rc = PCAP_ERROR;
goto quit;
}
if (pcap_lex_init(&scanner) != 0)
pcap_fmt_errmsg_for_errno(p->errbuf, PCAP_ERRBUF_SIZE,
if (pcap_lex_init(&scanner) != 0) {
pcapint_fmt_errmsg_for_errno(p->errbuf, PCAP_ERRBUF_SIZE,
errno, "can't initialize scanner");
rc = PCAP_ERROR;
goto quit;
}
in_buffer = pcap__scan_string(xbuf ? xbuf : "", scanner);
/*
@@ -871,7 +873,7 @@ quit:
int
pcap_compile_nopcap(int snaplen_arg, int linktype_arg,
struct bpf_program *program,
const char *buf, int optimize, bpf_u_int32 mask)
const char *buf, int optimize, bpf_u_int32 mask)
{
pcap_t *p;
int ret;
@@ -1707,15 +1709,15 @@ init_linktype(compiler_state_t *cstate, pcap_t *p)
* For values in the range in which we've assigned new
* DLT_ values, only raw "link[N:M]" filtering is supported.
*/
if (cstate->linktype >= DLT_MATCHING_MIN &&
cstate->linktype <= DLT_MATCHING_MAX) {
if (cstate->linktype >= DLT_HIGH_MATCHING_MIN &&
cstate->linktype <= DLT_HIGH_MATCHING_MAX) {
cstate->off_linktype.constant_part = OFFSET_NOT_SET;
cstate->off_linkpl.constant_part = OFFSET_NOT_SET;
cstate->off_nl = OFFSET_NOT_SET;
cstate->off_nl_nosnap = OFFSET_NOT_SET;
} else {
bpf_set_error(cstate, "unknown data link type %d (min %d, max %d)",
cstate->linktype, DLT_MATCHING_MIN, DLT_MATCHING_MAX);
cstate->linktype, DLT_HIGH_MATCHING_MIN, DLT_HIGH_MATCHING_MAX);
return (-1);
}
break;
@@ -1834,7 +1836,7 @@ gen_load_a(compiler_state_t *cstate, enum e_offrel offrel, u_int offset,
/*
* Load the item at {offset of the link-layer payload} +
* {offset, relative to the start of the link-layer
* paylod, of the IPv4 header} + {length of the IPv4 header} +
* payload, of the IPv4 header} + {length of the IPv4 header} +
* {specified offset}.
*
* If the offset of the link-layer payload is variable,
@@ -1897,7 +1899,7 @@ gen_loadx_iphdrlen(compiler_state_t *cstate)
} else {
/*
* The offset of the link-layer payload is a constant,
* so no code was generated to load the (non-existent)
* so no code was generated to load the (nonexistent)
* variable part of that offset.
*
* This means we can use the 4*([k]&0xf) addressing
@@ -4087,7 +4089,16 @@ gen_hostop6(compiler_state_t *cstate, struct in6_addr *addr,
{
struct block *b0, *b1;
u_int offset;
uint32_t *a, *m;
/*
* Code below needs to access four separate 32-bit parts of the 128-bit
* IPv6 address and mask. In some OSes this is as simple as using the
* s6_addr32 pseudo-member of struct in6_addr, which contains a union of
* 8-, 16- and 32-bit arrays. In other OSes this is not the case, as
* far as libpcap sees it. Hence copy the data before use to avoid
* potential unaligned memory access and the associated compiler
* warnings (whether genuine or not).
*/
bpf_u_int32 a[4], m[4];
switch (dir) {
@@ -4141,8 +4152,8 @@ gen_hostop6(compiler_state_t *cstate, struct in6_addr *addr,
/*NOTREACHED*/
}
/* this order is important */
a = (uint32_t *)addr;
m = (uint32_t *)mask;
memcpy(a, addr, sizeof(a));
memcpy(m, mask, sizeof(m));
b1 = gen_mcmp(cstate, OR_LINKPL, offset + 12, BPF_W, ntohl(a[3]), ntohl(m[3]));
b0 = gen_mcmp(cstate, OR_LINKPL, offset + 8, BPF_W, ntohl(a[2]), ntohl(m[2]));
gen_and(b0, b1);
@@ -5290,7 +5301,6 @@ gen_gateway(compiler_state_t *cstate, const u_char *eaddr,
*/
bpf_error(cstate,
"'gateway' supported only on ethernet/FDDI/token ring/802.11/ATM LANE/Fibre Channel");
break;
case DLT_IP_OVER_FC:
b0 = gen_ipfchostop(cstate, eaddr, Q_OR);
break;
@@ -6117,7 +6127,7 @@ gen_protochain(compiler_state_t *cstate, bpf_u_int32 v, int proto)
/*
* To quote a comment in optimize.c:
*
* "These data structures are used in a Cocke and Shwarz style
* "These data structures are used in a Cocke and Schwartz style
* value numbering scheme. Since the flowgraph is acyclic,
* exit values can be propagated from a node's predecessors
* provided it is uniquely defined."
@@ -6658,6 +6668,277 @@ gen_proto(compiler_state_t *cstate, bpf_u_int32 v, int proto, int dir)
/*NOTREACHED*/
}
/*
* Convert a non-numeric name to a port number.
*/
static int
nametoport(compiler_state_t *cstate, const char *name, int ipproto)
{
struct addrinfo hints, *res, *ai;
int error;
struct sockaddr_in *in4;
#ifdef INET6
struct sockaddr_in6 *in6;
#endif
int port = -1;
/*
* We check for both TCP and UDP in case there are
* ambiguous entries.
*/
memset(&hints, 0, sizeof(hints));
hints.ai_family = PF_UNSPEC;
hints.ai_socktype = (ipproto == IPPROTO_TCP) ? SOCK_STREAM : SOCK_DGRAM;
hints.ai_protocol = ipproto;
error = getaddrinfo(NULL, name, &hints, &res);
if (error != 0) {
switch (error) {
case EAI_NONAME:
case EAI_SERVICE:
/*
* No such port. Just return -1.
*/
break;
#ifdef EAI_SYSTEM
case EAI_SYSTEM:
/*
* We don't use strerror() because it's not
* guaranteed to be thread-safe on all platforms
* (probably because it might use a non-thread-local
* buffer into which to format an error message
* if the error code isn't one for which it has
* a canned string; three cheers for C string
* handling).
*/
bpf_set_error(cstate, "getaddrinfo(\"%s\" fails with system error: %d",
name, errno);
port = -2; /* a real error */
break;
#endif
default:
/*
* This is a real error, not just "there's
* no such service name".
*
* We don't use gai_strerror() because it's not
* guaranteed to be thread-safe on all platforms
* (probably because it might use a non-thread-local
* buffer into which to format an error message
* if the error code isn't one for which it has
* a canned string; three cheers for C string
* handling).
*/
bpf_set_error(cstate, "getaddrinfo(\"%s\") fails with error: %d",
name, error);
port = -2; /* a real error */
break;
}
} else {
/*
* OK, we found it. Did it find anything?
*/
for (ai = res; ai != NULL; ai = ai->ai_next) {
/*
* Does it have an address?
*/
if (ai->ai_addr != NULL) {
/*
* Yes. Get a port number; we're done.
*/
if (ai->ai_addr->sa_family == AF_INET) {
in4 = (struct sockaddr_in *)ai->ai_addr;
port = ntohs(in4->sin_port);
break;
}
#ifdef INET6
if (ai->ai_addr->sa_family == AF_INET6) {
in6 = (struct sockaddr_in6 *)ai->ai_addr;
port = ntohs(in6->sin6_port);
break;
}
#endif
}
}
freeaddrinfo(res);
}
return port;
}
/*
* Convert a string to a port number.
*/
static bpf_u_int32
stringtoport(compiler_state_t *cstate, const char *string, size_t string_size,
int *proto)
{
stoulen_ret ret;
char *cpy;
bpf_u_int32 val;
int tcp_port = -1;
int udp_port = -1;
/*
* See if it's a number.
*/
ret = stoulen(string, string_size, &val, cstate);
switch (ret) {
case STOULEN_OK:
/* Unknown port type - it's just a number. */
*proto = PROTO_UNDEF;
break;
case STOULEN_NOT_OCTAL_NUMBER:
case STOULEN_NOT_HEX_NUMBER:
case STOULEN_NOT_DECIMAL_NUMBER:
/*
* Not a valid number; try looking it up as a port.
*/
cpy = malloc(string_size + 1); /* +1 for terminating '\0' */
memcpy(cpy, string, string_size);
cpy[string_size] = '\0';
tcp_port = nametoport(cstate, cpy, IPPROTO_TCP);
if (tcp_port == -2) {
/*
* We got a hard error; the error string has
* already been set.
*/
free(cpy);
longjmp(cstate->top_ctx, 1);
/*NOTREACHED*/
}
udp_port = nametoport(cstate, cpy, IPPROTO_UDP);
if (udp_port == -2) {
/*
* We got a hard error; the error string has
* already been set.
*/
free(cpy);
longjmp(cstate->top_ctx, 1);
/*NOTREACHED*/
}
/*
* We need to check /etc/services for ambiguous entries.
* If we find an ambiguous entry, and it has the
* same port number, change the proto to PROTO_UNDEF
* so both TCP and UDP will be checked.
*/
if (tcp_port >= 0) {
val = (bpf_u_int32)tcp_port;
*proto = IPPROTO_TCP;
if (udp_port >= 0) {
if (udp_port == tcp_port)
*proto = PROTO_UNDEF;
#ifdef notdef
else
/* Can't handle ambiguous names that refer
to different port numbers. */
warning("ambiguous port %s in /etc/services",
cpy);
#endif
}
free(cpy);
break;
}
if (udp_port >= 0) {
val = (bpf_u_int32)udp_port;
*proto = IPPROTO_UDP;
free(cpy);
break;
}
#if defined(ultrix) || defined(__osf__)
/* Special hack in case NFS isn't in /etc/services */
if (strcmp(cpy, "nfs") == 0) {
val = 2049;
*proto = PROTO_UNDEF;
free(cpy);
break;
}
#endif
bpf_set_error(cstate, "'%s' is not a valid port", cpy);
free(cpy);
longjmp(cstate->top_ctx, 1);
/*NOTREACHED*/
case STOULEN_ERROR:
/* Error already set. */
longjmp(cstate->top_ctx, 1);
/*NOTREACHED*/
default:
/* Should not happen */
bpf_set_error(cstate, "stoulen returned %d - this should not happen", ret);
longjmp(cstate->top_ctx, 1);
/*NOTREACHED*/
}
return (val);
}
/*
* Convert a string in the form PPP-PPP, which correspond to ports, to
* a starting and ending port in a port range.
*/
static void
stringtoportrange(compiler_state_t *cstate, const char *string,
bpf_u_int32 *port1, bpf_u_int32 *port2, int *proto)
{
char *hyphen_off;
const char *first, *second;
size_t first_size, second_size;
int save_proto;
if ((hyphen_off = strchr(string, '-')) == NULL)
bpf_error(cstate, "port range '%s' contains no hyphen", string);
/*
* Make sure there are no other hyphens.
*
* XXX - we support named ports, but there are some port names
* in /etc/services that include hyphens, so this would rule
* that out.
*/
if (strchr(hyphen_off + 1, '-') != NULL)
bpf_error(cstate, "port range '%s' contains more than one hyphen",
string);
/*
* Get the length of the first port.
*/
first = string;
first_size = hyphen_off - string;
if (first_size == 0) {
/* Range of "-port", which we don't support. */
bpf_error(cstate, "port range '%s' has no starting port", string);
}
/*
* Try to convert it to a port.
*/
*port1 = stringtoport(cstate, first, first_size, proto);
save_proto = *proto;
/*
* Get the length of the second port.
*/
second = hyphen_off + 1;
second_size = strlen(second);
if (second_size == 0) {
/* Range of "port-", which we don't support. */
bpf_error(cstate, "port range '%s' has no ending port", string);
}
/*
* Try to convert it to a port.
*/
*port2 = stringtoport(cstate, second, second_size, proto);
if (*proto != save_proto)
*proto = PROTO_UNDEF;
}
struct block *
gen_scode(compiler_state_t *cstate, const char *name, struct qual q)
{
@@ -6675,7 +6956,7 @@ gen_scode(compiler_state_t *cstate, const char *name, struct qual q)
#endif /*INET6*/
struct block *b, *tmp;
int port, real_proto;
int port1, port2;
bpf_u_int32 port1, port2;
/*
* Catch errors reported by us and routines below us, and return NULL
@@ -6884,8 +7165,7 @@ gen_scode(compiler_state_t *cstate, const char *name, struct qual q)
if (proto != Q_DEFAULT &&
proto != Q_UDP && proto != Q_TCP && proto != Q_SCTP)
bpf_error(cstate, "illegal qualifier of 'portrange'");
if (pcap_nametoportrange(name, &port1, &port2, &real_proto) == 0)
bpf_error(cstate, "unknown port in range '%s'", name);
stringtoportrange(cstate, name, &port1, &port2, &real_proto);
if (proto == Q_UDP) {
if (real_proto == IPPROTO_TCP)
bpf_error(cstate, "port in range '%s' is tcp", name);
@@ -6913,12 +7193,8 @@ gen_scode(compiler_state_t *cstate, const char *name, struct qual q)
/* override PROTO_UNDEF */
real_proto = IPPROTO_SCTP;
}
if (port1 < 0)
bpf_error(cstate, "illegal port number %d < 0", port1);
if (port1 > 65535)
bpf_error(cstate, "illegal port number %d > 65535", port1);
if (port2 < 0)
bpf_error(cstate, "illegal port number %d < 0", port2);
if (port2 > 65535)
bpf_error(cstate, "illegal port number %d > 65535", port2);
@@ -7151,14 +7427,14 @@ gen_ncode(compiler_state_t *cstate, const char *s, bpf_u_int32 v, struct qual q)
#ifdef INET6
struct block *
gen_mcode6(compiler_state_t *cstate, const char *s1, const char *s2,
bpf_u_int32 masklen, struct qual q)
gen_mcode6(compiler_state_t *cstate, const char *s, bpf_u_int32 masklen,
struct qual q)
{
struct addrinfo *res;
struct in6_addr *addr;
struct in6_addr mask;
struct block *b;
uint32_t *a, *m;
bpf_u_int32 a[4], m[4]; /* Same as in gen_hostop6(). */
/*
* Catch errors reported by us and routines below us, and return NULL
@@ -7167,19 +7443,16 @@ gen_mcode6(compiler_state_t *cstate, const char *s1, const char *s2,
if (setjmp(cstate->top_ctx))
return (NULL);
if (s2)
bpf_error(cstate, "no mask %s supported", s2);
res = pcap_nametoaddrinfo(s1);
res = pcap_nametoaddrinfo(s);
if (!res)
bpf_error(cstate, "invalid ip6 address %s", s1);
bpf_error(cstate, "invalid ip6 address %s", s);
cstate->ai = res;
if (res->ai_next)
bpf_error(cstate, "%s resolved to multiple address", s1);
bpf_error(cstate, "%s resolved to multiple address", s);
addr = &((struct sockaddr_in6 *)res->ai_addr)->sin6_addr;
if (masklen > sizeof(mask.s6_addr) * 8)
bpf_error(cstate, "mask length must be <= %u", (unsigned int)(sizeof(mask.s6_addr) * 8));
bpf_error(cstate, "mask length must be <= %zu", sizeof(mask.s6_addr) * 8);
memset(&mask, 0, sizeof(mask));
memset(&mask.s6_addr, 0xff, masklen / 8);
if (masklen % 8) {
@@ -7187,11 +7460,11 @@ gen_mcode6(compiler_state_t *cstate, const char *s1, const char *s2,
(0xff << (8 - masklen % 8)) & 0xff;
}
a = (uint32_t *)addr;
m = (uint32_t *)&mask;
memcpy(a, addr, sizeof(a));
memcpy(m, &mask, sizeof(m));
if ((a[0] & ~m[0]) || (a[1] & ~m[1])
|| (a[2] & ~m[2]) || (a[3] & ~m[3])) {
bpf_error(cstate, "non-network bits set in \"%s/%d\"", s1, masklen);
bpf_error(cstate, "non-network bits set in \"%s/%d\"", s, masklen);
}
switch (q.addr) {
@@ -7524,58 +7797,54 @@ gen_load_internal(compiler_state_t *cstate, int proto, struct arth *inst,
inst->b = b;
break;
case Q_ICMPV6:
/*
* Do the computation only if the packet contains
* the protocol in question.
*/
b = gen_proto_abbrev_internal(cstate, Q_IPV6);
if (inst->b) {
gen_and(inst->b, b);
}
inst->b = b;
/*
* Do the computation only if the packet contains
* the protocol in question.
*/
b = gen_proto_abbrev_internal(cstate, Q_IPV6);
if (inst->b)
gen_and(inst->b, b);
inst->b = b;
/*
* Check if we have an icmp6 next header
*/
b = gen_cmp(cstate, OR_LINKPL, 6, BPF_B, 58);
if (inst->b) {
gen_and(inst->b, b);
}
inst->b = b;
/*
* Check if we have an icmp6 next header
*/
b = gen_cmp(cstate, OR_LINKPL, 6, BPF_B, 58);
if (inst->b)
gen_and(inst->b, b);
inst->b = b;
s = gen_abs_offset_varpart(cstate, &cstate->off_linkpl);
/*
* If "s" is non-null, it has code to arrange that the
* X register contains the variable part of the offset
* of the link-layer payload. Add to it the offset
* computed into the register specified by "index",
* and move that into the X register. Otherwise, just
* load into the X register the offset computed into
* the register specified by "index".
*/
if (s != NULL) {
sappend(s, xfer_to_a(cstate, inst));
sappend(s, new_stmt(cstate, BPF_ALU|BPF_ADD|BPF_X));
sappend(s, new_stmt(cstate, BPF_MISC|BPF_TAX));
} else
s = xfer_to_x(cstate, inst);
s = gen_abs_offset_varpart(cstate, &cstate->off_linkpl);
/*
* If "s" is non-null, it has code to arrange that the
* X register contains the variable part of the offset
* of the link-layer payload. Add to it the offset
* computed into the register specified by "index",
* and move that into the X register. Otherwise, just
* load into the X register the offset computed into
* the register specified by "index".
*/
if (s != NULL) {
sappend(s, xfer_to_a(cstate, inst));
sappend(s, new_stmt(cstate, BPF_ALU|BPF_ADD|BPF_X));
sappend(s, new_stmt(cstate, BPF_MISC|BPF_TAX));
} else {
s = xfer_to_x(cstate, inst);
}
/*
* Load the item at the sum of the offset we've put in the
* X register, the offset of the start of the network
* layer header from the beginning of the link-layer
* payload, and the constant part of the offset of the
* start of the link-layer payload.
*/
tmp = new_stmt(cstate, BPF_LD|BPF_IND|size_code);
tmp->s.k = cstate->off_linkpl.constant_part + cstate->off_nl + 40;
/*
* Load the item at the sum of the offset we've put in the
* X register, the offset of the start of the network
* layer header from the beginning of the link-layer
* payload, and the constant part of the offset of the
* start of the link-layer payload.
*/
tmp = new_stmt(cstate, BPF_LD|BPF_IND|size_code);
tmp->s.k = cstate->off_linkpl.constant_part + cstate->off_nl + 40;
sappend(s, tmp);
sappend(inst->s, s);
sappend(s, tmp);
sappend(inst->s, s);
break;
break;
}
inst->regno = regno;
s = new_stmt(cstate, BPF_ST);
@@ -8235,8 +8504,8 @@ gen_ifindex(compiler_state_t *cstate, int ifindex)
/* match packets on this interface */
b0 = gen_cmp(cstate, OR_LINKHDR, 4, BPF_W, ifindex);
break;
default:
#if defined(linux)
default:
#if defined(__linux__)
/*
* This is Linux; we require PF_PACKET support.
* If this is a *live* capture, we can look at
@@ -8247,17 +8516,16 @@ gen_ifindex(compiler_state_t *cstate, int ifindex)
/* We have a FILE *, so this is a savefile */
bpf_error(cstate, "ifindex not supported on %s when reading savefiles",
pcap_datalink_val_to_description_or_dlt(cstate->linktype));
b0 = NULL;
/*NOTREACHED*/
}
/* match ifindex */
b0 = gen_cmp(cstate, OR_LINKHDR, SKF_AD_OFF + SKF_AD_IFINDEX, BPF_W,
ifindex);
#else /* defined(linux) */
#else /* defined(__linux__) */
bpf_error(cstate, "ifindex not supported on %s",
pcap_datalink_val_to_description_or_dlt(cstate->linktype));
/*NOTREACHED*/
#endif /* defined(linux) */
#endif /* defined(__linux__) */
}
return (b0);
}
@@ -8387,7 +8655,7 @@ gen_inbound(compiler_state_t *cstate, int dir)
* with newer capture APIs, allowing it to be saved
* in pcapng files.
*/
#if defined(linux)
#if defined(__linux__)
/*
* This is Linux; we require PF_PACKET support.
* If this is a *live* capture, we can look at
@@ -8407,11 +8675,11 @@ gen_inbound(compiler_state_t *cstate, int dir)
/* to filter on inbound traffic, invert the match */
gen_not(b0);
}
#else /* defined(linux) */
#else /* defined(__linux__) */
bpf_error(cstate, "inbound/outbound not supported on %s",
pcap_datalink_val_to_description_or_dlt(cstate->linktype));
/*NOTREACHED*/
#endif /* defined(linux) */
#endif /* defined(__linux__) */
}
return (b0);
}
@@ -8837,7 +9105,7 @@ gen_vlan_patch_vid_test(compiler_state_t *cstate, struct block *b_vid)
/* Jump to the test in b_vid. We need to jump one instruction before
* the end of the b_vid block so that we only skip loading the TCI
* from packet data and not the 'and' instruction extractging VID.
* from packet data and not the 'and' instruction extracting VID.
*/
cnt = 0;
for (s2 = b_vid->stmts; s2; s2 = s2->next)
@@ -8977,7 +9245,7 @@ gen_vlan(compiler_state_t *cstate, bpf_u_int32 vlan_num, int has_vlan_tag)
#endif
b0 = gen_vlan_no_bpf_extensions(cstate, vlan_num,
has_vlan_tag);
break;
break;
case DLT_IEEE802_11:
case DLT_PRISM_HEADER:
@@ -8992,7 +9260,7 @@ gen_vlan(compiler_state_t *cstate, bpf_u_int32 vlan_num, int has_vlan_tag)
/*NOTREACHED*/
}
cstate->vlan_stack_depth++;
cstate->vlan_stack_depth++;
return (b0);
}
@@ -9018,38 +9286,38 @@ gen_mpls(compiler_state_t *cstate, bpf_u_int32 label_num_arg,
if (setjmp(cstate->top_ctx))
return (NULL);
if (cstate->label_stack_depth > 0) {
/* just match the bottom-of-stack bit clear */
b0 = gen_mcmp(cstate, OR_PREVMPLSHDR, 2, BPF_B, 0, 0x01);
} else {
/*
* We're not in an MPLS stack yet, so check the link-layer
* type against MPLS.
*/
switch (cstate->linktype) {
if (cstate->label_stack_depth > 0) {
/* just match the bottom-of-stack bit clear */
b0 = gen_mcmp(cstate, OR_PREVMPLSHDR, 2, BPF_B, 0, 0x01);
} else {
/*
* We're not in an MPLS stack yet, so check the link-layer
* type against MPLS.
*/
switch (cstate->linktype) {
case DLT_C_HDLC: /* fall through */
case DLT_HDLC:
case DLT_EN10MB:
case DLT_NETANALYZER:
case DLT_NETANALYZER_TRANSPARENT:
b0 = gen_linktype(cstate, ETHERTYPE_MPLS);
break;
case DLT_C_HDLC: /* fall through */
case DLT_HDLC:
case DLT_EN10MB:
case DLT_NETANALYZER:
case DLT_NETANALYZER_TRANSPARENT:
b0 = gen_linktype(cstate, ETHERTYPE_MPLS);
break;
case DLT_PPP:
b0 = gen_linktype(cstate, PPP_MPLS_UCAST);
break;
case DLT_PPP:
b0 = gen_linktype(cstate, PPP_MPLS_UCAST);
break;
/* FIXME add other DLT_s ...
* for Frame-Relay/and ATM this may get messy due to SNAP headers
* leave it for now */
/* FIXME add other DLT_s ...
* for Frame-Relay/and ATM this may get messy due to SNAP headers
* leave it for now */
default:
bpf_error(cstate, "no MPLS support for %s",
pcap_datalink_val_to_description_or_dlt(cstate->linktype));
/*NOTREACHED*/
}
}
default:
bpf_error(cstate, "no MPLS support for %s",
pcap_datalink_val_to_description_or_dlt(cstate->linktype));
/*NOTREACHED*/
}
}
/* If a specific MPLS label is requested, check it */
if (has_label_num) {
@@ -9064,23 +9332,23 @@ gen_mpls(compiler_state_t *cstate, bpf_u_int32 label_num_arg,
b0 = b1;
}
/*
* Change the offsets to point to the type and data fields within
* the MPLS packet. Just increment the offsets, so that we
* can support a hierarchy, e.g. "mpls 100000 && mpls 1024" to
* capture packets with an outer label of 100000 and an inner
* label of 1024.
*
* Increment the MPLS stack depth as well; this indicates that
* we're checking MPLS-encapsulated headers, to make sure higher
* level code generators don't try to match against IP-related
* protocols such as Q_ARP, Q_RARP etc.
*
* XXX - this is a bit of a kludge. See comments in gen_vlan().
*/
cstate->off_nl_nosnap += 4;
cstate->off_nl += 4;
cstate->label_stack_depth++;
/*
* Change the offsets to point to the type and data fields within
* the MPLS packet. Just increment the offsets, so that we
* can support a hierarchy, e.g. "mpls 100000 && mpls 1024" to
* capture packets with an outer label of 100000 and an inner
* label of 1024.
*
* Increment the MPLS stack depth as well; this indicates that
* we're checking MPLS-encapsulated headers, to make sure higher
* level code generators don't try to match against IP-related
* protocols such as Q_ARP, Q_RARP etc.
*
* XXX - this is a bit of a kludge. See comments in gen_vlan().
*/
cstate->off_nl_nosnap += 4;
cstate->off_nl += 4;
cstate->label_stack_depth++;
return (b0);
}
@@ -9795,8 +10063,8 @@ gen_mtp3field_code(compiler_state_t *cstate, int mtp3field,
bpf_error(cstate, "'sio' supported only on SS7");
/* sio coded on 1 byte so max value 255 */
if(jvalue > 255)
bpf_error(cstate, "sio value %u too big; max value = 255",
jvalue);
bpf_error(cstate, "sio value %u too big; max value = 255",
jvalue);
b0 = gen_ncmp(cstate, OR_PACKET, newoff_sio, BPF_B, 0xffffffffU,
jtype, reverse, jvalue);
break;
@@ -9805,13 +10073,13 @@ gen_mtp3field_code(compiler_state_t *cstate, int mtp3field,
newoff_opc += 3;
/* FALLTHROUGH */
case M_OPC:
if (cstate->off_opc == OFFSET_NOT_SET)
case M_OPC:
if (cstate->off_opc == OFFSET_NOT_SET)
bpf_error(cstate, "'opc' supported only on SS7");
/* opc coded on 14 bits so max value 16383 */
if (jvalue > 16383)
bpf_error(cstate, "opc value %u too big; max value = 16383",
jvalue);
bpf_error(cstate, "opc value %u too big; max value = 16383",
jvalue);
/* the following instructions are made to convert jvalue
* to the form used to write opc in an ss7 message*/
val1 = jvalue & 0x00003c00;
@@ -9830,12 +10098,12 @@ gen_mtp3field_code(compiler_state_t *cstate, int mtp3field,
/* FALLTHROUGH */
case M_DPC:
if (cstate->off_dpc == OFFSET_NOT_SET)
if (cstate->off_dpc == OFFSET_NOT_SET)
bpf_error(cstate, "'dpc' supported only on SS7");
/* dpc coded on 14 bits so max value 16383 */
if (jvalue > 16383)
bpf_error(cstate, "dpc value %u too big; max value = 16383",
jvalue);
bpf_error(cstate, "dpc value %u too big; max value = 16383",
jvalue);
/* the following instructions are made to convert jvalue
* to the forme used to write dpc in an ss7 message*/
val1 = jvalue & 0x000000ff;
@@ -9852,12 +10120,12 @@ gen_mtp3field_code(compiler_state_t *cstate, int mtp3field,
/* FALLTHROUGH */
case M_SLS:
if (cstate->off_sls == OFFSET_NOT_SET)
if (cstate->off_sls == OFFSET_NOT_SET)
bpf_error(cstate, "'sls' supported only on SS7");
/* sls coded on 4 bits so max value 15 */
if (jvalue > 15)
bpf_error(cstate, "sls value %u too big; max value = 15",
jvalue);
bpf_error(cstate, "sls value %u too big; max value = 15",
jvalue);
/* the following instruction is made to convert jvalue
* to the forme used to write sls in an ss7 message*/
jvalue = jvalue << 4;