#include "pcap-int.h"
+#include "extract.h"
+
#include "ethertype.h"
#include "nlpid.h"
#include "llc.h"
#define offsetof(s, e) ((size_t)&((s *)0)->e)
#endif
-#ifdef INET6
#ifdef _WIN32
-#if defined(__MINGW32__) && defined(DEFINE_ADDITIONAL_IPV6_STUFF)
+ #ifdef INET6
+ #if defined(__MINGW32__) && defined(DEFINE_ADDITIONAL_IPV6_STUFF)
/* IPv6 address */
struct in6_addr
{
struct in6_addr sin6_addr; /* IPv6 address */
};
-#ifndef EAI_ADDRFAMILY
+ #ifndef EAI_ADDRFAMILY
struct addrinfo {
int ai_flags; /* AI_PASSIVE, AI_CANONNAME */
int ai_family; /* PF_xxx */
struct sockaddr *ai_addr; /* binary address */
struct addrinfo *ai_next; /* next structure in linked list */
};
-#endif /* EAI_ADDRFAMILY */
-#endif /* defined(__MINGW32__) && defined(DEFINE_ADDITIONAL_IPV6_STUFF) */
+ #endif /* EAI_ADDRFAMILY */
+ #endif /* defined(__MINGW32__) && defined(DEFINE_ADDITIONAL_IPV6_STUFF) */
+ #endif /* INET6 */
#else /* _WIN32 */
-#include <netdb.h> /* for "struct addrinfo" */
+ #include <netdb.h> /* for "struct addrinfo" */
#endif /* _WIN32 */
-#endif /* INET6 */
#include <pcap/namedb.h>
#include "nametoaddr.h"
/* XXX */
u_int pcap_fddipad;
-#ifdef INET6
/*
* As errors are handled by a longjmp, anything allocated must
* be freed in the longjmp handler, so it must be reachable
* any addrinfo structure that would need to be freed.
*/
struct addrinfo *ai;
-#endif
+
+ /*
+ * Another thing that's allocated is the result of pcap_ether_aton();
+ * it must be freed with free(). This variable points to any
+ * address that would need to be freed.
+ */
+ u_char *e;
/*
* Various code constructs need to know the layout of the packet.
int cur_chunk;
};
+void PCAP_NORETURN
+bpf_parser_error(compiler_state_t *cstate, const char *msg)
+{
+ bpf_error(cstate, "can't parse filter expression: %s", msg);
+ /* NOTREACHED */
+}
+
+/*
+ * For use by the optimizer, which needs to do its *own* cleanup before
+ * delivering a longjmp-based exception.
+ */
void
-bpf_syntax_error(compiler_state_t *cstate, const char *msg)
+bpf_vset_error(compiler_state_t *cstate, const char *fmt, va_list ap)
{
- bpf_error(cstate, "syntax error in filter expression: %s", msg);
+ if (cstate->bpf_pcap != NULL)
+ (void)pcap_vsnprintf(pcap_geterr(cstate->bpf_pcap),
+ PCAP_ERRBUF_SIZE, fmt, ap);
+}
+
+void PCAP_NORETURN
+bpf_abort_compilation(compiler_state_t *cstate)
+{
+ longjmp(cstate->top_ctx, 1);
/* NOTREACHED */
}
/* VARARGS */
-void
+void PCAP_NORETURN
bpf_error(compiler_state_t *cstate, const char *fmt, ...)
{
va_list ap;
va_start(ap, fmt);
- if (cstate->bpf_pcap != NULL)
- (void)pcap_vsnprintf(pcap_geterr(cstate->bpf_pcap),
- PCAP_ERRBUF_SIZE, fmt, ap);
+ bpf_vset_error(cstate, fmt, ap);
va_end(ap);
- longjmp(cstate->top_ctx, 1);
+ bpf_abort_compilation(cstate);
/* NOTREACHED */
}
#endif
#ifndef INET6
static struct block *gen_gateway(compiler_state_t *, const u_char *,
- bpf_u_int32 **, int, int);
+ struct addrinfo *, int, int);
#endif
static struct block *gen_ipfrag(compiler_state_t *);
static struct block *gen_portatom(compiler_state_t *, int, bpf_int32);
cp = &cstate->chunks[cstate->cur_chunk];
if (n > cp->n_left) {
- ++cp, k = ++cstate->cur_chunk;
+ ++cp;
+ k = ++cstate->cur_chunk;
if (k >= NCHUNKS)
bpf_error(cstate, "out of memory");
size = CHUNK0SIZE << k;
size_t n = strlen(s) + 1;
char *cp = newchunk(cstate, n);
- strlcpy(cp, s, n);
+ pcap_strlcpy(cp, s, n);
return (cp);
}
return b;
}
-static inline void
+static inline PCAP_NORETURN_DEF void
syntax(compiler_state_t *cstate)
{
bpf_error(cstate, "syntax error in filter expression");
compiler_state_t cstate;
const char * volatile xbuf = buf;
yyscan_t scanner = NULL;
- YY_BUFFER_STATE in_buffer = NULL;
+ volatile YY_BUFFER_STATE in_buffer = NULL;
u_int len;
int rc;
#ifdef INET6
cstate.ai = NULL;
#endif
+ cstate.e = NULL;
cstate.ic.root = NULL;
cstate.ic.cur_mark = 0;
cstate.bpf_pcap = p;
if (cstate.ai != NULL)
freeaddrinfo(cstate.ai);
#endif
+ if (cstate.e != NULL)
+ free(cstate.e);
rc = -1;
goto quit;
}
}
if (pcap_lex_init(&scanner) != 0)
- bpf_error(&cstate, "can't initialize scanner: %s", pcap_strerror(errno));
+ pcap_fmt_errmsg_for_errno(p->errbuf, PCAP_ERRBUF_SIZE,
+ errno, "can't initialize scanner");
in_buffer = pcap__scan_string(xbuf ? xbuf : "", scanner);
/*
* in each block is already resolved.
*/
static void
-backpatch(list, target)
- struct block *list, *target;
+backpatch(struct block *list, struct block *target)
{
struct block *next;
* which of jt and jf is the link.
*/
static void
-merge(b0, b1)
- struct block *b0, *b1;
+merge(struct block *b0, struct block *b1)
{
register struct block **p = &b0;
}
void
-gen_and(b0, b1)
- struct block *b0, *b1;
+gen_and(struct block *b0, struct block *b1)
{
backpatch(b0, b1->head);
b0->sense = !b0->sense;
}
void
-gen_or(b0, b1)
- struct block *b0, *b1;
+gen_or(struct block *b0, struct block *b1)
{
b0->sense = !b0->sense;
backpatch(b0, b1->head);
}
void
-gen_not(b)
- struct block *b;
+gen_not(struct block *b)
{
b->sense = !b->sense;
}
{
register struct block *b, *tmp;
+ /*
+ * XXX - the actual *instructions* do unsigned comparisons on
+ * most platforms, and the load instructions don't do sign
+ * extension, so gen_cmp() should really take an unsigned
+ * value argument.
+ *
+ * As the load instructons also don't do sign-extension, we
+ * fetch the values from the byte array as unsigned. We don't
+ * want to use the signed versions of the extract calls.
+ */
b = NULL;
while (size >= 4) {
register const u_char *p = &v[size - 4];
- bpf_int32 w = ((bpf_int32)p[0] << 24) |
- ((bpf_int32)p[1] << 16) | ((bpf_int32)p[2] << 8) | p[3];
- tmp = gen_cmp(cstate, offrel, offset + size - 4, BPF_W, w);
+ tmp = gen_cmp(cstate, offrel, offset + size - 4, BPF_W,
+ (bpf_int32)EXTRACT_BE_U_4(p));
if (b != NULL)
gen_and(b, tmp);
b = tmp;
}
while (size >= 2) {
register const u_char *p = &v[size - 2];
- bpf_int32 w = ((bpf_int32)p[0] << 8) | p[1];
- tmp = gen_cmp(cstate, offrel, offset + size - 2, BPF_H, w);
+ tmp = gen_cmp(cstate, offrel, offset + size - 2, BPF_H,
+ (bpf_int32)EXTRACT_BE_U_2(p));
if (b != NULL)
gen_and(b, tmp);
b = tmp;
* Assume it's not raw ATM with a pseudo-header, for now.
*/
cstate->is_atm = 0;
- cstate->off_vpi = -1;
- cstate->off_vci = -1;
- cstate->off_proto = -1;
- cstate->off_payload = -1;
+ cstate->off_vpi = OFFSET_NOT_SET;
+ cstate->off_vci = OFFSET_NOT_SET;
+ cstate->off_proto = OFFSET_NOT_SET;
+ cstate->off_payload = OFFSET_NOT_SET;
/*
* And not Geneve.
/*
* And assume we're not doing SS7.
*/
- cstate->off_li = -1;
- cstate->off_li_hsl = -1;
- cstate->off_sio = -1;
- cstate->off_opc = -1;
- cstate->off_dpc = -1;
- cstate->off_sls = -1;
+ cstate->off_li = OFFSET_NOT_SET;
+ cstate->off_li_hsl = OFFSET_NOT_SET;
+ cstate->off_sio = OFFSET_NOT_SET;
+ cstate->off_opc = OFFSET_NOT_SET;
+ cstate->off_dpc = OFFSET_NOT_SET;
+ cstate->off_sls = OFFSET_NOT_SET;
cstate->label_stack_depth = 0;
cstate->vlan_stack_depth = 0;
case DLT_ARCNET:
cstate->off_linktype.constant_part = 2;
cstate->off_linkpl.constant_part = 6;
- cstate->off_nl = 0; /* XXX in reality, variable! */
+ cstate->off_nl = 0; /* XXX in reality, variable! */
cstate->off_nl_nosnap = 0; /* no 802.2 LLC */
break;
cstate->off_nl_nosnap = 0; /* no 802.2 LLC */
break;
- case DLT_LINUX_SLL: /* fake header for Linux cooked socket */
+ case DLT_LINUX_SLL: /* fake header for Linux cooked socket v1 */
cstate->off_linktype.constant_part = 14;
cstate->off_linkpl.constant_part = 16;
cstate->off_nl = 0;
cstate->off_nl_nosnap = 0; /* no 802.2 LLC */
break;
+ case DLT_LINUX_SLL2: /* fake header for Linux cooked socket v2 */
+ cstate->off_linktype.constant_part = 0;
+ cstate->off_linkpl.constant_part = 20;
+ cstate->off_nl = 0;
+ cstate->off_nl_nosnap = 0; /* no 802.2 LLC */
+ break;
+
case DLT_LTALK:
/*
* LocalTalk does have a 1-byte type field in the LLAP header,
cstate->off_linktype.constant_part = 4;
cstate->off_linkpl.constant_part = 4;
cstate->off_nl = 0;
- cstate->off_nl_nosnap = -1; /* no 802.2 LLC */
+ cstate->off_nl_nosnap = OFFSET_NOT_SET; /* no 802.2 LLC */
break;
case DLT_JUNIPER_ATM1:
cstate->off_linktype.constant_part = 4;
cstate->off_linkpl.constant_part = 6;
cstate->off_nl = 0;
- cstate->off_nl_nosnap = -1; /* no 802.2 LLC */
+ cstate->off_nl_nosnap = OFFSET_NOT_SET; /* no 802.2 LLC */
break;
case DLT_JUNIPER_GGSN:
cstate->off_linktype.constant_part = 6;
cstate->off_linkpl.constant_part = 12;
cstate->off_nl = 0;
- cstate->off_nl_nosnap = -1; /* no 802.2 LLC */
+ cstate->off_nl_nosnap = OFFSET_NOT_SET; /* no 802.2 LLC */
break;
case DLT_JUNIPER_ES:
cstate->off_linktype.constant_part = 6;
cstate->off_linkpl.constant_part = OFFSET_NOT_SET; /* not really a network layer but raw IP addresses */
- cstate->off_nl = -1; /* not really a network layer but raw IP addresses */
- cstate->off_nl_nosnap = -1; /* no 802.2 LLC */
+ cstate->off_nl = OFFSET_NOT_SET; /* not really a network layer but raw IP addresses */
+ cstate->off_nl_nosnap = OFFSET_NOT_SET; /* no 802.2 LLC */
break;
case DLT_JUNIPER_MONITOR:
cstate->off_linktype.constant_part = 12;
cstate->off_linkpl.constant_part = 12;
- cstate->off_nl = 0; /* raw IP/IP6 header */
- cstate->off_nl_nosnap = -1; /* no 802.2 LLC */
+ cstate->off_nl = 0; /* raw IP/IP6 header */
+ cstate->off_nl_nosnap = OFFSET_NOT_SET; /* no 802.2 LLC */
break;
case DLT_BACNET_MS_TP:
cstate->off_linktype.constant_part = OFFSET_NOT_SET;
cstate->off_linkpl.constant_part = OFFSET_NOT_SET;
- cstate->off_nl = -1;
- cstate->off_nl_nosnap = -1;
+ cstate->off_nl = OFFSET_NOT_SET;
+ cstate->off_nl_nosnap = OFFSET_NOT_SET;
break;
case DLT_JUNIPER_SERVICES:
cstate->off_linktype.constant_part = 12;
cstate->off_linkpl.constant_part = OFFSET_NOT_SET; /* L3 proto location dep. on cookie type */
- cstate->off_nl = -1; /* L3 proto location dep. on cookie type */
- cstate->off_nl_nosnap = -1; /* no 802.2 LLC */
+ cstate->off_nl = OFFSET_NOT_SET; /* L3 proto location dep. on cookie type */
+ cstate->off_nl_nosnap = OFFSET_NOT_SET; /* no 802.2 LLC */
break;
case DLT_JUNIPER_VP:
cstate->off_linktype.constant_part = 18;
cstate->off_linkpl.constant_part = OFFSET_NOT_SET;
- cstate->off_nl = -1;
- cstate->off_nl_nosnap = -1;
+ cstate->off_nl = OFFSET_NOT_SET;
+ cstate->off_nl_nosnap = OFFSET_NOT_SET;
break;
case DLT_JUNIPER_ST:
cstate->off_linktype.constant_part = 18;
cstate->off_linkpl.constant_part = OFFSET_NOT_SET;
- cstate->off_nl = -1;
- cstate->off_nl_nosnap = -1;
+ cstate->off_nl = OFFSET_NOT_SET;
+ cstate->off_nl_nosnap = OFFSET_NOT_SET;
break;
case DLT_JUNIPER_ISM:
cstate->off_linktype.constant_part = 8;
cstate->off_linkpl.constant_part = OFFSET_NOT_SET;
- cstate->off_nl = -1;
- cstate->off_nl_nosnap = -1;
+ cstate->off_nl = OFFSET_NOT_SET;
+ cstate->off_nl_nosnap = OFFSET_NOT_SET;
break;
case DLT_JUNIPER_VS:
case DLT_JUNIPER_ATM_CEMIC:
cstate->off_linktype.constant_part = 8;
cstate->off_linkpl.constant_part = OFFSET_NOT_SET;
- cstate->off_nl = -1;
- cstate->off_nl_nosnap = -1;
+ cstate->off_nl = OFFSET_NOT_SET;
+ cstate->off_nl_nosnap = OFFSET_NOT_SET;
break;
case DLT_MTP2:
cstate->off_sls = 7;
cstate->off_linktype.constant_part = OFFSET_NOT_SET;
cstate->off_linkpl.constant_part = OFFSET_NOT_SET;
- cstate->off_nl = -1;
- cstate->off_nl_nosnap = -1;
+ cstate->off_nl = OFFSET_NOT_SET;
+ cstate->off_nl_nosnap = OFFSET_NOT_SET;
break;
case DLT_MTP2_WITH_PHDR:
cstate->off_sls = 11;
cstate->off_linktype.constant_part = OFFSET_NOT_SET;
cstate->off_linkpl.constant_part = OFFSET_NOT_SET;
- cstate->off_nl = -1;
- cstate->off_nl_nosnap = -1;
+ cstate->off_nl = OFFSET_NOT_SET;
+ cstate->off_nl_nosnap = OFFSET_NOT_SET;
break;
case DLT_ERF:
cstate->off_sls = 27;
cstate->off_linktype.constant_part = OFFSET_NOT_SET;
cstate->off_linkpl.constant_part = OFFSET_NOT_SET;
- cstate->off_nl = -1;
- cstate->off_nl_nosnap = -1;
+ cstate->off_nl = OFFSET_NOT_SET;
+ cstate->off_nl_nosnap = OFFSET_NOT_SET;
break;
case DLT_PFSYNC:
*/
cstate->off_linktype.constant_part = OFFSET_NOT_SET; /* variable, min 15, max 71 steps of 7 */
cstate->off_linkpl.constant_part = OFFSET_NOT_SET;
- cstate->off_nl = -1; /* variable, min 16, max 71 steps of 7 */
- cstate->off_nl_nosnap = -1; /* no 802.2 LLC */
+ cstate->off_nl = OFFSET_NOT_SET; /* variable, min 16, max 71 steps of 7 */
+ cstate->off_nl_nosnap = OFFSET_NOT_SET; /* no 802.2 LLC */
break;
case DLT_IPNET:
cstate->off_linktype.constant_part = 1;
cstate->off_linkpl.constant_part = 24; /* ipnet header length */
cstate->off_nl = 0;
- cstate->off_nl_nosnap = -1;
+ cstate->off_nl_nosnap = OFFSET_NOT_SET;
break;
case DLT_NETANALYZER:
cstate->linktype <= DLT_MATCHING_MAX) {
cstate->off_linktype.constant_part = OFFSET_NOT_SET;
cstate->off_linkpl.constant_part = OFFSET_NOT_SET;
- cstate->off_nl = -1;
- cstate->off_nl_nosnap = -1;
+ cstate->off_nl = OFFSET_NOT_SET;
+ cstate->off_nl_nosnap = OFFSET_NOT_SET;
} else {
bpf_error(cstate, "unknown data link type %d", cstate->linktype);
}
default:
abort();
- return NULL;
+ /* NOTREACHED */
}
return s;
}
* Map an Ethernet type to the equivalent PPP type.
*/
static int
-ethertype_to_ppptype(proto)
- int proto;
+ethertype_to_ppptype(int proto)
{
switch (proto) {
*/
#define BSD_AFNUM_INET6_BSD 24 /* NetBSD, OpenBSD, BSD/OS, Npcap */
#define BSD_AFNUM_INET6_FREEBSD 28 /* FreeBSD */
-#define BSD_AFNUM_INET6_DARWIN 30 /* OS X, iOS, other Darwin-based OSes */
+#define BSD_AFNUM_INET6_DARWIN 30 /* macOS, iOS, other Darwin-based OSes */
/*
* Generate code to match a particular packet type by matching the
{
u_char snapblock[8];
- snapblock[0] = LLCSAP_SNAP; /* DSAP = SNAP */
- snapblock[1] = LLCSAP_SNAP; /* SSAP = SNAP */
- snapblock[2] = 0x03; /* control = UI */
- snapblock[3] = (orgcode >> 16); /* upper 8 bits of organization code */
- snapblock[4] = (orgcode >> 8); /* middle 8 bits of organization code */
- snapblock[5] = (orgcode >> 0); /* lower 8 bits of organization code */
- snapblock[6] = (ptype >> 8); /* upper 8 bits of protocol type */
- snapblock[7] = (ptype >> 0); /* lower 8 bits of protocol type */
+ snapblock[0] = LLCSAP_SNAP; /* DSAP = SNAP */
+ snapblock[1] = LLCSAP_SNAP; /* SSAP = SNAP */
+ snapblock[2] = 0x03; /* control = UI */
+ snapblock[3] = (u_char)(orgcode >> 16); /* upper 8 bits of organization code */
+ snapblock[4] = (u_char)(orgcode >> 8); /* middle 8 bits of organization code */
+ snapblock[5] = (u_char)(orgcode >> 0); /* lower 8 bits of organization code */
+ snapblock[6] = (u_char)(ptype >> 8); /* upper 8 bits of protocol type */
+ snapblock[7] = (u_char)(ptype >> 0); /* lower 8 bits of protocol type */
return gen_bcmp(cstate, OR_LLC, 0, 8, snapblock);
}
gen_and(b0, b1);
return b1;
- case Q_OR:
case Q_DEFAULT:
+ case Q_OR:
b0 = gen_hostop(cstate, addr, mask, Q_SRC, proto, src_off, dst_off);
b1 = gen_hostop(cstate, addr, mask, Q_DST, proto, src_off, dst_off);
gen_or(b0, b1);
return b1;
+ case Q_ADDR1:
+ bpf_error(cstate, "'addr1' and 'address1' are not valid qualifiers for addresses other than 802.11 MAC addresses");
+ break;
+
+ case Q_ADDR2:
+ bpf_error(cstate, "'addr2' and 'address2' are not valid qualifiers for addresses other than 802.11 MAC addresses");
+ break;
+
+ case Q_ADDR3:
+ bpf_error(cstate, "'addr3' and 'address3' are not valid qualifiers for addresses other than 802.11 MAC addresses");
+ break;
+
+ case Q_ADDR4:
+ bpf_error(cstate, "'addr4' and 'address4' are not valid qualifiers for addresses other than 802.11 MAC addresses");
+ break;
+
+ case Q_RA:
+ bpf_error(cstate, "'ra' is not a valid qualifier for addresses other than 802.11 MAC addresses");
+ break;
+
+ case Q_TA:
+ bpf_error(cstate, "'ta' is not a valid qualifier for addresses other than 802.11 MAC addresses");
+ break;
+
default:
abort();
}
gen_and(b0, b1);
return b1;
- case Q_OR:
case Q_DEFAULT:
+ case Q_OR:
b0 = gen_hostop6(cstate, addr, mask, Q_SRC, proto, src_off, dst_off);
b1 = gen_hostop6(cstate, addr, mask, Q_DST, proto, src_off, dst_off);
gen_or(b0, b1);
return b1;
+ case Q_ADDR1:
+ bpf_error(cstate, "'addr1' and 'address1' are not valid qualifiers for addresses other than 802.11 MAC addresses");
+ break;
+
+ case Q_ADDR2:
+ bpf_error(cstate, "'addr2' and 'address2' are not valid qualifiers for addresses other than 802.11 MAC addresses");
+ break;
+
+ case Q_ADDR3:
+ bpf_error(cstate, "'addr3' and 'address3' are not valid qualifiers for addresses other than 802.11 MAC addresses");
+ break;
+
+ case Q_ADDR4:
+ bpf_error(cstate, "'addr4' and 'address4' are not valid qualifiers for addresses other than 802.11 MAC addresses");
+ break;
+
+ case Q_RA:
+ bpf_error(cstate, "'ra' is not a valid qualifier for addresses other than 802.11 MAC addresses");
+ break;
+
+ case Q_TA:
+ bpf_error(cstate, "'ta' is not a valid qualifier for addresses other than 802.11 MAC addresses");
+ break;
+
default:
abort();
}
return b1;
case Q_ADDR1:
- bpf_error(cstate, "'addr1' is only supported on 802.11 with 802.11 headers");
+ bpf_error(cstate, "'addr1' and 'address1' are only supported on 802.11 with 802.11 headers");
break;
case Q_ADDR2:
- bpf_error(cstate, "'addr2' is only supported on 802.11 with 802.11 headers");
+ bpf_error(cstate, "'addr2' and 'address2' are only supported on 802.11 with 802.11 headers");
break;
case Q_ADDR3:
- bpf_error(cstate, "'addr3' is only supported on 802.11 with 802.11 headers");
+ bpf_error(cstate, "'addr3' and 'address3' are only supported on 802.11 with 802.11 headers");
break;
case Q_ADDR4:
- bpf_error(cstate, "'addr4' is only supported on 802.11 with 802.11 headers");
+ bpf_error(cstate, "'addr4' and 'address4' are only supported on 802.11 with 802.11 headers");
break;
case Q_RA:
return b1;
case Q_ADDR1:
- bpf_error(cstate, "'addr1' is only supported on 802.11");
+ bpf_error(cstate, "'addr1' and 'address1' are only supported on 802.11");
break;
case Q_ADDR2:
- bpf_error(cstate, "'addr2' is only supported on 802.11");
+ bpf_error(cstate, "'addr2' and 'address2' are only supported on 802.11");
break;
case Q_ADDR3:
- bpf_error(cstate, "'addr3' is only supported on 802.11");
+ bpf_error(cstate, "'addr3' and 'address3' are only supported on 802.11");
break;
case Q_ADDR4:
- bpf_error(cstate, "'addr4' is only supported on 802.11");
+ bpf_error(cstate, "'addr4' and 'address4' are only supported on 802.11");
break;
case Q_RA:
return b1;
case Q_ADDR1:
- bpf_error(cstate, "'addr1' is only supported on 802.11");
+ bpf_error(cstate, "'addr1' and 'address1' are only supported on 802.11");
break;
case Q_ADDR2:
- bpf_error(cstate, "'addr2' is only supported on 802.11");
+ bpf_error(cstate, "'addr2' and 'address2' are only supported on 802.11");
break;
case Q_ADDR3:
- bpf_error(cstate, "'addr3' is only supported on 802.11");
+ bpf_error(cstate, "'addr3' and 'address3' are only supported on 802.11");
break;
case Q_ADDR4:
- bpf_error(cstate, "'addr4' is only supported on 802.11");
+ bpf_error(cstate, "'addr4' and 'address4' are only supported on 802.11");
break;
case Q_RA:
gen_and(b1, b0);
return b0;
+ case Q_AND:
+ b0 = gen_wlanhostop(cstate, eaddr, Q_SRC);
+ b1 = gen_wlanhostop(cstate, eaddr, Q_DST);
+ gen_and(b0, b1);
+ return b1;
+
+ case Q_DEFAULT:
+ case Q_OR:
+ b0 = gen_wlanhostop(cstate, eaddr, Q_SRC);
+ b1 = gen_wlanhostop(cstate, eaddr, Q_DST);
+ gen_or(b0, b1);
+ return b1;
+
+ /*
+ * XXX - add BSSID keyword?
+ */
+ case Q_ADDR1:
+ return (gen_bcmp(cstate, OR_LINKHDR, 4, 6, eaddr));
+
+ case Q_ADDR2:
+ /*
+ * Not present in CTS or ACK control frames.
+ */
+ b0 = gen_mcmp(cstate, OR_LINKHDR, 0, BPF_B, IEEE80211_FC0_TYPE_CTL,
+ IEEE80211_FC0_TYPE_MASK);
+ gen_not(b0);
+ b1 = gen_mcmp(cstate, OR_LINKHDR, 0, BPF_B, IEEE80211_FC0_SUBTYPE_CTS,
+ IEEE80211_FC0_SUBTYPE_MASK);
+ gen_not(b1);
+ b2 = gen_mcmp(cstate, OR_LINKHDR, 0, BPF_B, IEEE80211_FC0_SUBTYPE_ACK,
+ IEEE80211_FC0_SUBTYPE_MASK);
+ gen_not(b2);
+ gen_and(b1, b2);
+ gen_or(b0, b2);
+ b1 = gen_bcmp(cstate, OR_LINKHDR, 10, 6, eaddr);
+ gen_and(b2, b1);
+ return b1;
+
+ case Q_ADDR3:
+ /*
+ * Not present in control frames.
+ */
+ b0 = gen_mcmp(cstate, OR_LINKHDR, 0, BPF_B, IEEE80211_FC0_TYPE_CTL,
+ IEEE80211_FC0_TYPE_MASK);
+ gen_not(b0);
+ b1 = gen_bcmp(cstate, OR_LINKHDR, 16, 6, eaddr);
+ gen_and(b0, b1);
+ return b1;
+
+ case Q_ADDR4:
+ /*
+ * Present only if the direction mask has both "From DS"
+ * and "To DS" set. Neither control frames nor management
+ * frames should have both of those set, so we don't
+ * check the frame type.
+ */
+ b0 = gen_mcmp(cstate, OR_LINKHDR, 1, BPF_B,
+ IEEE80211_FC1_DIR_DSTODS, IEEE80211_FC1_DIR_MASK);
+ b1 = gen_bcmp(cstate, OR_LINKHDR, 24, 6, eaddr);
+ gen_and(b0, b1);
+ return b1;
+
case Q_RA:
/*
* Not present in management frames; addr1 in other
b1 = gen_bcmp(cstate, OR_LINKHDR, 10, 6, eaddr);
gen_and(b2, b1);
return b1;
-
- /*
- * XXX - add BSSID keyword?
- */
- case Q_ADDR1:
- return (gen_bcmp(cstate, OR_LINKHDR, 4, 6, eaddr));
-
- case Q_ADDR2:
- /*
- * Not present in CTS or ACK control frames.
- */
- b0 = gen_mcmp(cstate, OR_LINKHDR, 0, BPF_B, IEEE80211_FC0_TYPE_CTL,
- IEEE80211_FC0_TYPE_MASK);
- gen_not(b0);
- b1 = gen_mcmp(cstate, OR_LINKHDR, 0, BPF_B, IEEE80211_FC0_SUBTYPE_CTS,
- IEEE80211_FC0_SUBTYPE_MASK);
- gen_not(b1);
- b2 = gen_mcmp(cstate, OR_LINKHDR, 0, BPF_B, IEEE80211_FC0_SUBTYPE_ACK,
- IEEE80211_FC0_SUBTYPE_MASK);
- gen_not(b2);
- gen_and(b1, b2);
- gen_or(b0, b2);
- b1 = gen_bcmp(cstate, OR_LINKHDR, 10, 6, eaddr);
- gen_and(b2, b1);
- return b1;
-
- case Q_ADDR3:
- /*
- * Not present in control frames.
- */
- b0 = gen_mcmp(cstate, OR_LINKHDR, 0, BPF_B, IEEE80211_FC0_TYPE_CTL,
- IEEE80211_FC0_TYPE_MASK);
- gen_not(b0);
- b1 = gen_bcmp(cstate, OR_LINKHDR, 16, 6, eaddr);
- gen_and(b0, b1);
- return b1;
-
- case Q_ADDR4:
- /*
- * Present only if the direction mask has both "From DS"
- * and "To DS" set. Neither control frames nor management
- * frames should have both of those set, so we don't
- * check the frame type.
- */
- b0 = gen_mcmp(cstate, OR_LINKHDR, 1, BPF_B,
- IEEE80211_FC1_DIR_DSTODS, IEEE80211_FC1_DIR_MASK);
- b1 = gen_bcmp(cstate, OR_LINKHDR, 24, 6, eaddr);
- gen_and(b0, b1);
- return b1;
-
- case Q_AND:
- b0 = gen_wlanhostop(cstate, eaddr, Q_SRC);
- b1 = gen_wlanhostop(cstate, eaddr, Q_DST);
- gen_and(b0, b1);
- return b1;
-
- case Q_DEFAULT:
- case Q_OR:
- b0 = gen_wlanhostop(cstate, eaddr, Q_SRC);
- b1 = gen_wlanhostop(cstate, eaddr, Q_DST);
- gen_or(b0, b1);
- return b1;
}
abort();
/* NOTREACHED */
return b1;
case Q_ADDR1:
- bpf_error(cstate, "'addr1' is only supported on 802.11");
+ bpf_error(cstate, "'addr1' and 'address1' are only supported on 802.11");
break;
case Q_ADDR2:
- bpf_error(cstate, "'addr2' is only supported on 802.11");
+ bpf_error(cstate, "'addr2' and 'address2' are only supported on 802.11");
break;
case Q_ADDR3:
- bpf_error(cstate, "'addr3' is only supported on 802.11");
+ bpf_error(cstate, "'addr3' and 'address3' are only supported on 802.11");
break;
case Q_ADDR4:
- bpf_error(cstate, "'addr4' is only supported on 802.11");
+ bpf_error(cstate, "'addr4' and 'address4' are only supported on 802.11");
break;
case Q_RA:
gen_and(b0, b1);
return b1;
- case Q_OR:
case Q_DEFAULT:
+ case Q_OR:
/* Inefficient because we do our Calvinball dance twice */
b0 = gen_dnhostop(cstate, addr, Q_SRC);
b1 = gen_dnhostop(cstate, addr, Q_DST);
gen_or(b0, b1);
return b1;
- case Q_ISO:
- bpf_error(cstate, "ISO host filtering not implemented");
+ case Q_ADDR1:
+ bpf_error(cstate, "'addr1' and 'address1' are not valid qualifiers for addresses other than 802.11 MAC addresses");
+ break;
+
+ case Q_ADDR2:
+ bpf_error(cstate, "'addr2' and 'address2' are not valid qualifiers for addresses other than 802.11 MAC addresses");
+ break;
+
+ case Q_ADDR3:
+ bpf_error(cstate, "'addr3' and 'address3' are not valid qualifiers for addresses other than 802.11 MAC addresses");
+ break;
+
+ case Q_ADDR4:
+ bpf_error(cstate, "'addr4' and 'address4' are not valid qualifiers for addresses other than 802.11 MAC addresses");
+ break;
+
+ case Q_RA:
+ bpf_error(cstate, "'ra' is not a valid qualifier for addresses other than 802.11 MAC addresses");
+ break;
+
+ case Q_TA:
+ bpf_error(cstate, "'ta' is not a valid qualifier for addresses other than 802.11 MAC addresses");
+ break;
default:
abort();
case Q_IP:
/* match the bottom-of-stack bit */
- b0 = gen_mcmp(cstate, OR_LINKPL, -2, BPF_B, 0x01, 0x01);
+ b0 = gen_mcmp(cstate, OR_LINKPL, (u_int)-2, BPF_B, 0x01, 0x01);
/* match the IPv4 version number */
b1 = gen_mcmp(cstate, OR_LINKPL, 0, BPF_B, 0x40, 0xf0);
gen_and(b0, b1);
case Q_IPV6:
/* match the bottom-of-stack bit */
- b0 = gen_mcmp(cstate, OR_LINKPL, -2, BPF_B, 0x01, 0x01);
+ b0 = gen_mcmp(cstate, OR_LINKPL, (u_int)-2, BPF_B, 0x01, 0x01);
/* match the IPv4 version number */
b1 = gen_mcmp(cstate, OR_LINKPL, 0, BPF_B, 0x60, 0xf0);
gen_and(b0, b1);
}
return b0;
+ case Q_LINK:
+ bpf_error(cstate, "link-layer modifier applied to %s", typestr);
+
case Q_IP:
return gen_hostop(cstate, addr, mask, dir, ETHERTYPE_IP, 12, 16);
case Q_ARP:
return gen_hostop(cstate, addr, mask, dir, ETHERTYPE_ARP, 14, 24);
- case Q_TCP:
- bpf_error(cstate, "'tcp' modifier applied to %s", typestr);
-
case Q_SCTP:
bpf_error(cstate, "'sctp' modifier applied to %s", typestr);
+ case Q_TCP:
+ bpf_error(cstate, "'tcp' modifier applied to %s", typestr);
+
case Q_UDP:
bpf_error(cstate, "'udp' modifier applied to %s", typestr);
case Q_IGRP:
bpf_error(cstate, "'igrp' modifier applied to %s", typestr);
- case Q_PIM:
- bpf_error(cstate, "'pim' modifier applied to %s", typestr);
-
- case Q_VRRP:
- bpf_error(cstate, "'vrrp' modifier applied to %s", typestr);
-
- case Q_CARP:
- bpf_error(cstate, "'carp' modifier applied to %s", typestr);
-
case Q_ATALK:
- bpf_error(cstate, "ATALK host filtering not implemented");
-
- case Q_AARP:
- bpf_error(cstate, "AARP host filtering not implemented");
+ bpf_error(cstate, "AppleTalk host filtering not implemented");
case Q_DECNET:
return gen_dnhostop(cstate, addr, dir);
- case Q_SCA:
- bpf_error(cstate, "SCA host filtering not implemented");
-
case Q_LAT:
bpf_error(cstate, "LAT host filtering not implemented");
- case Q_MOPDL:
- bpf_error(cstate, "MOPDL host filtering not implemented");
+ case Q_SCA:
+ bpf_error(cstate, "SCA host filtering not implemented");
case Q_MOPRC:
bpf_error(cstate, "MOPRC host filtering not implemented");
+ case Q_MOPDL:
+ bpf_error(cstate, "MOPDL host filtering not implemented");
+
case Q_IPV6:
bpf_error(cstate, "'ip6' modifier applied to ip host");
case Q_ESP:
bpf_error(cstate, "'esp' modifier applied to %s", typestr);
+ case Q_PIM:
+ bpf_error(cstate, "'pim' modifier applied to %s", typestr);
+
+ case Q_VRRP:
+ bpf_error(cstate, "'vrrp' modifier applied to %s", typestr);
+
+ case Q_AARP:
+ bpf_error(cstate, "AARP host filtering not implemented");
+
case Q_ISO:
bpf_error(cstate, "ISO host filtering not implemented");
case Q_NETBEUI:
bpf_error(cstate, "'netbeui' modifier applied to %s", typestr);
+ case Q_ISIS_L1:
+ bpf_error(cstate, "'l1' modifier applied to %s", typestr);
+
+ case Q_ISIS_L2:
+ bpf_error(cstate, "'l2' modifier applied to %s", typestr);
+
+ case Q_ISIS_IIH:
+ bpf_error(cstate, "'iih' modifier applied to %s", typestr);
+
+ case Q_ISIS_SNP:
+ bpf_error(cstate, "'snp' modifier applied to %s", typestr);
+
+ case Q_ISIS_CSNP:
+ bpf_error(cstate, "'csnp' modifier applied to %s", typestr);
+
+ case Q_ISIS_PSNP:
+ bpf_error(cstate, "'psnp' modifier applied to %s", typestr);
+
+ case Q_ISIS_LSP:
+ bpf_error(cstate, "'lsp' modifier applied to %s", typestr);
+
case Q_RADIO:
bpf_error(cstate, "'radio' modifier applied to %s", typestr);
+ case Q_CARP:
+ bpf_error(cstate, "'carp' modifier applied to %s", typestr);
+
default:
abort();
}
bpf_error(cstate, "'arp' modifier applied to ip6 %s", typestr);
case Q_SCTP:
- bpf_error(cstate, "'sctp' modifier applied to %s", typestr);
+ bpf_error(cstate, "'sctp' modifier applied to ip6 %s", typestr);
case Q_TCP:
- bpf_error(cstate, "'tcp' modifier applied to %s", typestr);
+ bpf_error(cstate, "'tcp' modifier applied to ip6 %s", typestr);
case Q_UDP:
- bpf_error(cstate, "'udp' modifier applied to %s", typestr);
+ bpf_error(cstate, "'udp' modifier applied to ip6 %s", typestr);
case Q_ICMP:
- bpf_error(cstate, "'icmp' modifier applied to %s", typestr);
+ bpf_error(cstate, "'icmp' modifier applied to ip6 %s", typestr);
case Q_IGMP:
- bpf_error(cstate, "'igmp' modifier applied to %s", typestr);
+ bpf_error(cstate, "'igmp' modifier applied to ip6 %s", typestr);
case Q_IGRP:
- bpf_error(cstate, "'igrp' modifier applied to %s", typestr);
-
- case Q_PIM:
- bpf_error(cstate, "'pim' modifier applied to %s", typestr);
-
- case Q_VRRP:
- bpf_error(cstate, "'vrrp' modifier applied to %s", typestr);
-
- case Q_CARP:
- bpf_error(cstate, "'carp' modifier applied to %s", typestr);
+ bpf_error(cstate, "'igrp' modifier applied to ip6 %s", typestr);
case Q_ATALK:
- bpf_error(cstate, "ATALK host filtering not implemented");
-
- case Q_AARP:
- bpf_error(cstate, "AARP host filtering not implemented");
+ bpf_error(cstate, "AppleTalk modifier applied to ip6 %s", typestr);
case Q_DECNET:
bpf_error(cstate, "'decnet' modifier applied to ip6 %s", typestr);
- case Q_SCA:
- bpf_error(cstate, "SCA host filtering not implemented");
-
case Q_LAT:
- bpf_error(cstate, "LAT host filtering not implemented");
+ bpf_error(cstate, "'lat' modifier applied to ip6 %s", typestr);
- case Q_MOPDL:
- bpf_error(cstate, "MOPDL host filtering not implemented");
+ case Q_SCA:
+ bpf_error(cstate, "'sca' modifier applied to ip6 %s", typestr);
case Q_MOPRC:
- bpf_error(cstate, "MOPRC host filtering not implemented");
+ bpf_error(cstate, "'moprc' modifier applied to ip6 %s", typestr);
+
+ case Q_MOPDL:
+ bpf_error(cstate, "'mopdl' modifier applied to ip6 %s", typestr);
case Q_IPV6:
return gen_hostop6(cstate, addr, mask, dir, ETHERTYPE_IPV6, 8, 24);
case Q_ICMPV6:
- bpf_error(cstate, "'icmp6' modifier applied to %s", typestr);
+ bpf_error(cstate, "'icmp6' modifier applied to ip6 %s", typestr);
case Q_AH:
- bpf_error(cstate, "'ah' modifier applied to %s", typestr);
+ bpf_error(cstate, "'ah' modifier applied to ip6 %s", typestr);
case Q_ESP:
- bpf_error(cstate, "'esp' modifier applied to %s", typestr);
+ bpf_error(cstate, "'esp' modifier applied to ip6 %s", typestr);
+
+ case Q_PIM:
+ bpf_error(cstate, "'pim' modifier applied to ip6 %s", typestr);
+
+ case Q_VRRP:
+ bpf_error(cstate, "'vrrp' modifier applied to ip6 %s", typestr);
+
+ case Q_AARP:
+ bpf_error(cstate, "'aarp' modifier applied to ip6 %s", typestr);
case Q_ISO:
- bpf_error(cstate, "ISO host filtering not implemented");
+ bpf_error(cstate, "'iso' modifier applied to ip6 %s", typestr);
case Q_ESIS:
- bpf_error(cstate, "'esis' modifier applied to %s", typestr);
+ bpf_error(cstate, "'esis' modifier applied to ip6 %s", typestr);
case Q_ISIS:
- bpf_error(cstate, "'isis' modifier applied to %s", typestr);
+ bpf_error(cstate, "'isis' modifier applied to ip6 %s", typestr);
case Q_CLNP:
- bpf_error(cstate, "'clnp' modifier applied to %s", typestr);
+ bpf_error(cstate, "'clnp' modifier applied to ip6 %s", typestr);
case Q_STP:
- bpf_error(cstate, "'stp' modifier applied to %s", typestr);
+ bpf_error(cstate, "'stp' modifier applied to ip6 %s", typestr);
case Q_IPX:
- bpf_error(cstate, "IPX host filtering not implemented");
+ bpf_error(cstate, "'ipx' modifier applied to ip6 %s", typestr);
case Q_NETBEUI:
- bpf_error(cstate, "'netbeui' modifier applied to %s", typestr);
+ bpf_error(cstate, "'netbeui' modifier applied to ip6 %s", typestr);
+
+ case Q_ISIS_L1:
+ bpf_error(cstate, "'l1' modifier applied to ip6 %s", typestr);
+
+ case Q_ISIS_L2:
+ bpf_error(cstate, "'l2' modifier applied to ip6 %s", typestr);
+
+ case Q_ISIS_IIH:
+ bpf_error(cstate, "'iih' modifier applied to ip6 %s", typestr);
+
+ case Q_ISIS_SNP:
+ bpf_error(cstate, "'snp' modifier applied to ip6 %s", typestr);
+
+ case Q_ISIS_CSNP:
+ bpf_error(cstate, "'csnp' modifier applied to ip6 %s", typestr);
+
+ case Q_ISIS_PSNP:
+ bpf_error(cstate, "'psnp' modifier applied to ip6 %s", typestr);
+
+ case Q_ISIS_LSP:
+ bpf_error(cstate, "'lsp' modifier applied to ip6 %s", typestr);
case Q_RADIO:
- bpf_error(cstate, "'radio' modifier applied to %s", typestr);
+ bpf_error(cstate, "'radio' modifier applied to ip6 %s", typestr);
+
+ case Q_CARP:
+ bpf_error(cstate, "'carp' modifier applied to ip6 %s", typestr);
default:
abort();
#ifndef INET6
static struct block *
-gen_gateway(compiler_state_t *cstate, const u_char *eaddr, bpf_u_int32 **alist,
- int proto, int dir)
+gen_gateway(compiler_state_t *cstate, const u_char *eaddr,
+ struct addrinfo *alist, int proto, int dir)
{
struct block *b0, *b1, *tmp;
+ struct addrinfo *ai;
+ struct sockaddr_in *sin;
if (dir != 0)
bpf_error(cstate, "direction applied to 'gateway'");
bpf_error(cstate,
"'gateway' supported only on ethernet/FDDI/token ring/802.11/ATM LANE/Fibre Channel");
}
- b1 = gen_host(cstate, **alist++, 0xffffffff, proto, Q_OR, Q_HOST);
- while (*alist) {
- tmp = gen_host(cstate, **alist++, 0xffffffff, proto, Q_OR,
- Q_HOST);
- gen_or(b1, tmp);
- b1 = tmp;
+ b1 = NULL;
+ for (ai = alist; ai != NULL; ai = ai->ai_next) {
+ /*
+ * Does it have an address?
+ */
+ if (ai->ai_addr != NULL) {
+ /*
+ * Yes. Is it an IPv4 address?
+ */
+ if (ai->ai_addr->sa_family == AF_INET) {
+ /*
+ * Generate an entry for it.
+ */
+ sin = (struct sockaddr_in *)ai->ai_addr;
+ tmp = gen_host(cstate,
+ ntohl(sin->sin_addr.s_addr),
+ 0xffffffff, proto, Q_OR, Q_HOST);
+ /*
+ * Is it the *first* IPv4 address?
+ */
+ if (b1 == NULL) {
+ /*
+ * Yes, so start with it.
+ */
+ b1 = tmp;
+ } else {
+ /*
+ * No, so OR it into the
+ * existing set of
+ * addresses.
+ */
+ gen_or(b1, tmp);
+ b1 = tmp;
+ }
+ }
+ }
+ }
+ if (b1 == NULL) {
+ /*
+ * No IPv4 addresses found.
+ */
+ return (NULL);
}
gen_not(b1);
gen_and(b0, b1);
b1 = gen_portatom(cstate, 2, (bpf_int32)port);
break;
- case Q_OR:
- case Q_DEFAULT:
+ case Q_AND:
tmp = gen_portatom(cstate, 0, (bpf_int32)port);
b1 = gen_portatom(cstate, 2, (bpf_int32)port);
- gen_or(tmp, b1);
+ gen_and(tmp, b1);
break;
- case Q_AND:
+ case Q_DEFAULT:
+ case Q_OR:
tmp = gen_portatom(cstate, 0, (bpf_int32)port);
b1 = gen_portatom(cstate, 2, (bpf_int32)port);
- gen_and(tmp, b1);
+ gen_or(tmp, b1);
+ break;
+
+ case Q_ADDR1:
+ bpf_error(cstate, "'addr1' and 'address1' are not valid qualifiers for ports");
+ break;
+
+ case Q_ADDR2:
+ bpf_error(cstate, "'addr2' and 'address2' are not valid qualifiers for ports");
+ break;
+
+ case Q_ADDR3:
+ bpf_error(cstate, "'addr3' and 'address3' are not valid qualifiers for ports");
+ break;
+
+ case Q_ADDR4:
+ bpf_error(cstate, "'addr4' and 'address4' are not valid qualifiers for ports");
+ break;
+
+ case Q_RA:
+ bpf_error(cstate, "'ra' is not a valid qualifier for ports");
+ break;
+
+ case Q_TA:
+ bpf_error(cstate, "'ta' is not a valid qualifier for ports");
break;
default:
b1 = gen_portatom6(cstate, 2, (bpf_int32)port);
break;
- case Q_OR:
- case Q_DEFAULT:
+ case Q_AND:
tmp = gen_portatom6(cstate, 0, (bpf_int32)port);
b1 = gen_portatom6(cstate, 2, (bpf_int32)port);
- gen_or(tmp, b1);
+ gen_and(tmp, b1);
break;
- case Q_AND:
+ case Q_DEFAULT:
+ case Q_OR:
tmp = gen_portatom6(cstate, 0, (bpf_int32)port);
b1 = gen_portatom6(cstate, 2, (bpf_int32)port);
- gen_and(tmp, b1);
+ gen_or(tmp, b1);
break;
default:
b1 = gen_portrangeatom(cstate, 2, (bpf_int32)port1, (bpf_int32)port2);
break;
- case Q_OR:
- case Q_DEFAULT:
+ case Q_AND:
tmp = gen_portrangeatom(cstate, 0, (bpf_int32)port1, (bpf_int32)port2);
b1 = gen_portrangeatom(cstate, 2, (bpf_int32)port1, (bpf_int32)port2);
- gen_or(tmp, b1);
+ gen_and(tmp, b1);
break;
- case Q_AND:
+ case Q_DEFAULT:
+ case Q_OR:
tmp = gen_portrangeatom(cstate, 0, (bpf_int32)port1, (bpf_int32)port2);
b1 = gen_portrangeatom(cstate, 2, (bpf_int32)port1, (bpf_int32)port2);
- gen_and(tmp, b1);
+ gen_or(tmp, b1);
+ break;
+
+ case Q_ADDR1:
+ bpf_error(cstate, "'addr1' and 'address1' are not valid qualifiers for port ranges");
+ break;
+
+ case Q_ADDR2:
+ bpf_error(cstate, "'addr2' and 'address2' are not valid qualifiers for port ranges");
+ break;
+
+ case Q_ADDR3:
+ bpf_error(cstate, "'addr3' and 'address3' are not valid qualifiers for port ranges");
+ break;
+
+ case Q_ADDR4:
+ bpf_error(cstate, "'addr4' and 'address4' are not valid qualifiers for port ranges");
+ break;
+
+ case Q_RA:
+ bpf_error(cstate, "'ra' is not a valid qualifier for port ranges");
+ break;
+
+ case Q_TA:
+ bpf_error(cstate, "'ta' is not a valid qualifier for port ranges");
break;
default:
b1 = gen_portrangeatom6(cstate, 2, (bpf_int32)port1, (bpf_int32)port2);
break;
- case Q_OR:
- case Q_DEFAULT:
+ case Q_AND:
tmp = gen_portrangeatom6(cstate, 0, (bpf_int32)port1, (bpf_int32)port2);
b1 = gen_portrangeatom6(cstate, 2, (bpf_int32)port1, (bpf_int32)port2);
- gen_or(tmp, b1);
+ gen_and(tmp, b1);
break;
- case Q_AND:
+ case Q_DEFAULT:
+ case Q_OR:
tmp = gen_portrangeatom6(cstate, 0, (bpf_int32)port1, (bpf_int32)port2);
b1 = gen_portrangeatom6(cstate, 2, (bpf_int32)port1, (bpf_int32)port2);
- gen_and(tmp, b1);
+ gen_or(tmp, b1);
break;
default:
#if 0
struct stmt *
-gen_joinsp(s, n)
- struct stmt **s;
- int n;
+gen_joinsp(struct stmt **s, int n)
{
return NULL;
}
*/
b0 = gen_linktype(cstate, LLCSAP_ISONS<<8 | LLCSAP_ISONS);
/* OSI in C-HDLC is stuffed with a fudge byte */
- b1 = gen_cmp(cstate, OR_LINKPL_NOSNAP, 1, BPF_B, (long)v);
+ b1 = gen_cmp(cstate, OR_LINKPL_NOSNAP, 1, BPF_B, (bpf_int32)v);
gen_and(b0, b1);
return b1;
default:
b0 = gen_linktype(cstate, LLCSAP_ISONS);
- b1 = gen_cmp(cstate, OR_LINKPL_NOSNAP, 0, BPF_B, (long)v);
+ b1 = gen_cmp(cstate, OR_LINKPL_NOSNAP, 0, BPF_B, (bpf_int32)v);
gen_and(b0, b1);
return b1;
}
* 4 is the offset of the PDU type relative to the IS-IS
* header.
*/
- b1 = gen_cmp(cstate, OR_LINKPL_NOSNAP, 4, BPF_B, (long)v);
+ b1 = gen_cmp(cstate, OR_LINKPL_NOSNAP, 4, BPF_B, (bpf_int32)v);
gen_and(b0, b1);
return b1;
int tproto;
u_char *eaddr;
bpf_u_int32 mask, addr;
-#ifndef INET6
- bpf_u_int32 **alist;
-#else
- int tproto6;
+ struct addrinfo *res, *res0;
struct sockaddr_in *sin4;
+#ifdef INET6
+ int tproto6;
struct sockaddr_in6 *sin6;
- struct addrinfo *res, *res0;
struct in6_addr mask128;
#endif /*INET6*/
struct block *b, *tmp;
*/
return (gen_host(cstate, dn_addr, 0, proto, dir, q.addr));
} else {
-#ifndef INET6
- alist = pcap_nametoaddr(name);
- if (alist == NULL || *alist == NULL)
- bpf_error(cstate, "unknown host '%s'", name);
- tproto = proto;
- if (cstate->off_linktype.constant_part == OFFSET_NOT_SET &&
- tproto == Q_DEFAULT)
- tproto = Q_IP;
- b = gen_host(cstate, **alist++, 0xffffffff, tproto, dir, q.addr);
- while (*alist) {
- tmp = gen_host(cstate, **alist++, 0xffffffff,
- tproto, dir, q.addr);
- gen_or(b, tmp);
- b = tmp;
- }
- return b;
-#else
+#ifdef INET6
memset(&mask128, 0xff, sizeof(mask128));
+#endif
res0 = res = pcap_nametoaddrinfo(name);
if (res == NULL)
bpf_error(cstate, "unknown host '%s'", name);
cstate->ai = res;
b = tmp = NULL;
- tproto = tproto6 = proto;
+ tproto = proto;
+#ifdef INET6
+ tproto6 = proto;
+#endif
if (cstate->off_linktype.constant_part == OFFSET_NOT_SET &&
tproto == Q_DEFAULT) {
tproto = Q_IP;
+#ifdef INET6
tproto6 = Q_IPV6;
+#endif
}
for (res = res0; res; res = res->ai_next) {
switch (res->ai_family) {
case AF_INET:
+#ifdef INET6
if (tproto == Q_IPV6)
continue;
+#endif
sin4 = (struct sockaddr_in *)
res->ai_addr;
tmp = gen_host(cstate, ntohl(sin4->sin_addr.s_addr),
0xffffffff, tproto, dir, q.addr);
break;
+#ifdef INET6
case AF_INET6:
if (tproto6 == Q_IP)
continue;
tmp = gen_host6(cstate, &sin6->sin6_addr,
&mask128, tproto6, dir, q.addr);
break;
+#endif
default:
continue;
}
: " for specified address family");
}
return b;
-#endif /*INET6*/
}
case Q_PORT:
if (eaddr == NULL)
bpf_error(cstate, "unknown ether host: %s", name);
- alist = pcap_nametoaddr(name);
- if (alist == NULL || *alist == NULL)
+ res = pcap_nametoaddrinfo(name);
+ cstate->ai = res;
+ if (res == NULL)
+ bpf_error(cstate, "unknown host '%s'", name);
+ b = gen_gateway(cstate, eaddr, res, proto, dir);
+ cstate->ai = NULL;
+ freeaddrinfo(res);
+ if (b == NULL)
bpf_error(cstate, "unknown host '%s'", name);
- b = gen_gateway(cstate, eaddr, alist, proto, dir);
- free(eaddr);
return b;
#else
bpf_error(cstate, "'gateway' not supported in this configuration");
/* NOTREACHED */
}
/* NOTREACHED */
- return NULL;
}
struct block *
bpf_error(cstate, "invalid qualifier against IPv6 address");
/* NOTREACHED */
}
- return NULL;
}
#endif /*INET6*/
struct block *
-gen_ecode(compiler_state_t *cstate, const u_char *eaddr, struct qual q)
+gen_ecode(compiler_state_t *cstate, const char *s, struct qual q)
{
struct block *b, *tmp;
if ((q.addr == Q_HOST || q.addr == Q_DEFAULT) && q.proto == Q_LINK) {
+ cstate->e = pcap_ether_aton(s);
+ if (cstate->e == NULL)
+ bpf_error(cstate, "malloc");
switch (cstate->linktype) {
case DLT_EN10MB:
case DLT_NETANALYZER:
case DLT_NETANALYZER_TRANSPARENT:
tmp = gen_prevlinkhdr_check(cstate);
- b = gen_ehostop(cstate, eaddr, (int)q.dir);
+ b = gen_ehostop(cstate, cstate->e, (int)q.dir);
if (tmp != NULL)
gen_and(tmp, b);
- return b;
+ break;
case DLT_FDDI:
- return gen_fhostop(cstate, eaddr, (int)q.dir);
+ b = gen_fhostop(cstate, cstate->e, (int)q.dir);
+ break;
case DLT_IEEE802:
- return gen_thostop(cstate, eaddr, (int)q.dir);
+ b = gen_thostop(cstate, cstate->e, (int)q.dir);
+ break;
case DLT_IEEE802_11:
case DLT_PRISM_HEADER:
case DLT_IEEE802_11_RADIO_AVS:
case DLT_IEEE802_11_RADIO:
case DLT_PPI:
- return gen_wlanhostop(cstate, eaddr, (int)q.dir);
+ b = gen_wlanhostop(cstate, cstate->e, (int)q.dir);
+ break;
case DLT_IP_OVER_FC:
- return gen_ipfchostop(cstate, eaddr, (int)q.dir);
+ b = gen_ipfchostop(cstate, cstate->e, (int)q.dir);
+ break;
default:
+ free(cstate->e);
+ cstate->e = NULL;
bpf_error(cstate, "ethernet addresses supported only on ethernet/FDDI/token ring/802.11/ATM LANE/Fibre Channel");
+ /* NOTREACHED */
break;
}
+ free(cstate->e);
+ cstate->e = NULL;
+ return (b);
}
bpf_error(cstate, "ethernet address used in non-ether expression");
/* NOTREACHED */
- return NULL;
}
void
-sappend(s0, s1)
- struct slist *s0, *s1;
+sappend(struct slist *s0, struct slist *s1)
{
/*
* This is definitely not the best way to do this, but the
/*
* Disallow division by, or modulus by, zero; we do this here
* so that it gets done even if the optimizer is disabled.
+ *
+ * Also disallow shifts by a value greater than 31; we do this
+ * here, for the same reason.
*/
if (code == BPF_DIV) {
if (a1->s->s.code == (BPF_LD|BPF_IMM) && a1->s->s.k == 0)
} else if (code == BPF_MOD) {
if (a1->s->s.code == (BPF_LD|BPF_IMM) && a1->s->s.k == 0)
bpf_error(cstate, "modulus by zero");
+ } else if (code == BPF_LSH || code == BPF_RSH) {
+ /*
+ * XXX - we need to make up our minds as to what integers
+ * are signed and what integers are unsigned in BPF programs
+ * and in our IR.
+ */
+ if (a1->s->s.code == (BPF_LD|BPF_IMM) &&
+ (a1->s->s.k < 0 || a1->s->s.k > 31))
+ bpf_error(cstate, "shift by more than 31 bits");
}
s0 = xfer_to_x(cstate, a1);
s1 = xfer_to_a(cstate, a0);
}
bpf_error(cstate, "too many registers needed to evaluate expression");
/* NOTREACHED */
- return 0;
}
/*
}
bpf_error(cstate, "only link-layer/IP broadcast filters supported");
/* NOTREACHED */
- return NULL;
}
/*
}
bpf_error(cstate, "link-layer multicast filters supported only on ethernet/FDDI/token ring/ARCNET/802.11/ATM LANE/Fibre Channel");
/* NOTREACHED */
- return NULL;
}
/*
}
break;
+ case DLT_LINUX_SLL2:
+ /* match outgoing packets */
+ b0 = gen_cmp(cstate, OR_LINKHDR, 10, BPF_B, LINUX_SLL_OUTGOING);
+ if (!dir) {
+ /* to filter on inbound traffic, invert the match */
+ gen_not(b0);
+ }
+ break;
+
#ifdef HAVE_NET_PFVAR_H
case DLT_PFLOG:
b0 = gen_cmp(cstate, OR_LINKHDR, offsetof(struct pfloghdr, dir), BPF_B,
default:
/*
* If we have packet meta-data indicating a direction,
- * check it, otherwise give up as this link-layer type
- * has nothing in the packet data.
+ * and that metadata can be checked by BPF code, check
+ * it. Otherwise, give up, as this link-layer type has
+ * nothing in the packet data.
+ *
+ * Currently, the only platform where a BPF filter can
+ * check that metadata is Linux with the in-kernel
+ * BPF interpreter. If other packet capture mechanisms
+ * and BPF filters also supported this, it would be
+ * nice. It would be even better if they made that
+ * metadata available so that we could provide it
+ * with newer capture APIs, allowing it to be saved
+ * in pcapng files.
*/
#if defined(linux) && defined(PF_PACKET) && defined(SO_ATTACH_FILTER)
/*
#else /* defined(linux) && defined(PF_PACKET) && defined(SO_ATTACH_FILTER) */
bpf_error(cstate, "inbound/outbound not supported on linktype %d",
cstate->linktype);
- b0 = NULL;
/* NOTREACHED */
#endif /* defined(linux) && defined(PF_PACKET) && defined(SO_ATTACH_FILTER) */
}
}
#else /* !HAVE_NET_PFVAR_H */
struct block *
-gen_pf_ifname(compiler_state_t *cstate, const char *ifname)
+gen_pf_ifname(compiler_state_t *cstate, const char *ifname _U_)
{
bpf_error(cstate, "libpcap was compiled without pf support");
/* NOTREACHED */
- return (NULL);
}
struct block *
-gen_pf_ruleset(compiler_state_t *cstate, char *ruleset)
+gen_pf_ruleset(compiler_state_t *cstate, char *ruleset _U_)
{
bpf_error(cstate, "libpcap was compiled on a machine without pf support");
/* NOTREACHED */
- return (NULL);
}
struct block *
-gen_pf_rnr(compiler_state_t *cstate, int rnr)
+gen_pf_rnr(compiler_state_t *cstate, int rnr _U_)
{
bpf_error(cstate, "libpcap was compiled on a machine without pf support");
/* NOTREACHED */
- return (NULL);
}
struct block *
-gen_pf_srnr(compiler_state_t *cstate, int srnr)
+gen_pf_srnr(compiler_state_t *cstate, int srnr _U_)
{
bpf_error(cstate, "libpcap was compiled on a machine without pf support");
/* NOTREACHED */
- return (NULL);
}
struct block *
-gen_pf_reason(compiler_state_t *cstate, int reason)
+gen_pf_reason(compiler_state_t *cstate, int reason _U_)
{
bpf_error(cstate, "libpcap was compiled on a machine without pf support");
/* NOTREACHED */
- return (NULL);
}
struct block *
-gen_pf_action(compiler_state_t *cstate, int action)
+gen_pf_action(compiler_state_t *cstate, int action _U_)
{
bpf_error(cstate, "libpcap was compiled on a machine without pf support");
/* NOTREACHED */
- return (NULL);
}
#endif /* HAVE_NET_PFVAR_H */
}
struct block *
-gen_acode(compiler_state_t *cstate, const u_char *eaddr, struct qual q)
+gen_acode(compiler_state_t *cstate, const char *s, struct qual q)
{
+ struct block *b;
+
switch (cstate->linktype) {
case DLT_ARCNET:
case DLT_ARCNET_LINUX:
if ((q.addr == Q_HOST || q.addr == Q_DEFAULT) &&
- q.proto == Q_LINK)
- return (gen_ahostop(cstate, eaddr, (int)q.dir));
- else {
+ q.proto == Q_LINK) {
+ cstate->e = pcap_ether_aton(s);
+ if (cstate->e == NULL)
+ bpf_error(cstate, "malloc");
+ b = gen_ahostop(cstate, cstate->e, (int)q.dir);
+ free(cstate->e);
+ cstate->e = NULL;
+ return (b);
+ } else {
bpf_error(cstate, "ARCnet address used in non-arc expression");
/* NOTREACHED */
}
bpf_error(cstate, "aid supported only on ARCnet");
/* NOTREACHED */
}
- bpf_error(cstate, "ARCnet address used in non-arc expression");
- /* NOTREACHED */
- return NULL;
}
static struct block *
return b1;
case Q_ADDR1:
- bpf_error(cstate, "'addr1' is only supported on 802.11");
+ bpf_error(cstate, "'addr1' and 'address1' are only supported on 802.11");
break;
case Q_ADDR2:
- bpf_error(cstate, "'addr2' is only supported on 802.11");
+ bpf_error(cstate, "'addr2' and 'address2' are only supported on 802.11");
break;
case Q_ADDR3:
- bpf_error(cstate, "'addr3' is only supported on 802.11");
+ bpf_error(cstate, "'addr3' and 'address3' are only supported on 802.11");
break;
case Q_ADDR4:
- bpf_error(cstate, "'addr4' is only supported on 802.11");
+ bpf_error(cstate, "'addr4' and 'address4' are only supported on 802.11");
break;
case Q_RA:
return b0;
}
-#if defined(SKF_AD_VLAN_TAG) && defined(SKF_AD_VLAN_TAG_PRESENT)
+#if defined(SKF_AD_VLAN_TAG_PRESENT)
/* add v to variable part of off */
static void
gen_vlan_vloffset_add(compiler_state_t *cstate, bpf_abs_offset *off, int v, struct slist *s)
sappend(s, s2);
sjeq->s.jt = s2;
- /* jump to the test in b_vid (bypass loading VID from packet data) */
+ /* 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.
+ */
cnt = 0;
for (s2 = b_vid->stmts; s2; s2 = s2->next)
cnt++;
s2 = new_stmt(cstate, JMP(BPF_JA));
- s2->s.k = cnt;
+ s2->s.k = cnt - 1;
sappend(s, s2);
/* insert our statements at the beginning of b_vid */
case DLT_EN10MB:
case DLT_NETANALYZER:
case DLT_NETANALYZER_TRANSPARENT:
-#if defined(SKF_AD_VLAN_TAG) && defined(SKF_AD_VLAN_TAG_PRESENT)
+#if defined(SKF_AD_VLAN_TAG_PRESENT)
/* Verify that this is the outer part of the packet and
* not encapsulated somehow. */
if (cstate->vlan_stack_depth == 0 && !cstate->off_linkhdr.is_variable &&
* support for MPLS
*/
struct block *
-gen_mpls(compiler_state_t *cstate, int label_num)
+gen_mpls(compiler_state_t *cstate, bpf_u_int32 label_num, int has_label_num)
{
struct block *b0, *b1;
default:
bpf_error(cstate, "no MPLS support for data link type %d",
cstate->linktype);
- b0 = NULL;
/*NOTREACHED*/
break;
}
}
/* If a specific MPLS label is requested, check it */
- if (label_num >= 0) {
+ if (has_label_num) {
+ if (label_num > 0xFFFFF) {
+ bpf_error(cstate, "MPLS label %u greater than maximum %u",
+ label_num, 0xFFFFF);
+ }
label_num = label_num << 12; /* label is shifted 12 bits on the wire */
b1 = gen_mcmp(cstate, OR_LINKPL, 0, BPF_W, (bpf_int32)label_num,
0xfffff000); /* only compare the first 20 bits */
case A_VPI:
if (!cstate->is_atm)
bpf_error(cstate, "'vpi' supported only on raw ATM");
- if (cstate->off_vpi == (u_int)-1)
+ if (cstate->off_vpi == OFFSET_NOT_SET)
abort();
b0 = gen_ncmp(cstate, OR_LINKHDR, cstate->off_vpi, BPF_B, 0xffffffff, jtype,
reverse, jvalue);
case A_VCI:
if (!cstate->is_atm)
bpf_error(cstate, "'vci' supported only on raw ATM");
- if (cstate->off_vci == (u_int)-1)
+ if (cstate->off_vci == OFFSET_NOT_SET)
abort();
b0 = gen_ncmp(cstate, OR_LINKHDR, cstate->off_vci, BPF_H, 0xffffffff, jtype,
reverse, jvalue);
break;
case A_PROTOTYPE:
- if (cstate->off_proto == (u_int)-1)
+ if (cstate->off_proto == OFFSET_NOT_SET)
abort(); /* XXX - this isn't on FreeBSD */
b0 = gen_ncmp(cstate, OR_LINKHDR, cstate->off_proto, BPF_B, 0x0f, jtype,
reverse, jvalue);
break;
case A_MSGTYPE:
- if (cstate->off_payload == (u_int)-1)
+ if (cstate->off_payload == OFFSET_NOT_SET)
abort();
b0 = gen_ncmp(cstate, OR_LINKHDR, cstate->off_payload + MSG_TYPE_POS, BPF_B,
0xffffffff, jtype, reverse, jvalue);
case A_CALLREFTYPE:
if (!cstate->is_atm)
bpf_error(cstate, "'callref' supported only on raw ATM");
- if (cstate->off_proto == (u_int)-1)
+ if (cstate->off_proto == OFFSET_NOT_SET)
abort();
b0 = gen_ncmp(cstate, OR_LINKHDR, cstate->off_proto, BPF_B, 0xffffffff,
jtype, reverse, jvalue);
/* FALLTHROUGH */
case M_SIO:
- if (cstate->off_sio == (u_int)-1)
+ if (cstate->off_sio == OFFSET_NOT_SET)
bpf_error(cstate, "'sio' supported only on SS7");
/* sio coded on 1 byte so max value 255 */
if(jvalue > 255)
case MH_OPC:
newoff_opc+=3;
case M_OPC:
- if (cstate->off_opc == (u_int)-1)
+ 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)
/* FALLTHROUGH */
case M_DPC:
- if (cstate->off_dpc == (u_int)-1)
+ 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)
case MH_SLS:
newoff_sls+=3;
case M_SLS:
- if (cstate->off_sls == (u_int)-1)
+ 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)