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:
@@ -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;
|
||||
|
||||
Reference in New Issue
Block a user