*/
struct addrinfo *ai;
+ /*
+ * 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.
* These values give the necessary offsets from the beginning
/* NOTREACHED */
}
+/*
+ * For use by the optimizer, which needs to do its *own* cleanup before
+ * delivering a longjmp-based exception.
+ */
+void
+bpf_vset_error(compiler_state_t *cstate, const char *fmt, va_list ap)
+{
+ 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 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 */
}
#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;
}
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();
}
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);
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, "AppleTalk modifier applied to %s", typestr);
-
- 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();
#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 */
/*
* 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);
}
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 */
}
* 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;
}
/* 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 */