diff options
Diffstat (limited to 'lib')
| -rw-r--r-- | lib/libpcap/Makefile | 3 | ||||
| -rw-r--r-- | lib/libpcap/gencode.c | 825 | ||||
| -rw-r--r-- | lib/libpcap/gencode.h | 22 | ||||
| -rw-r--r-- | lib/libpcap/grammar.y | 37 | ||||
| -rw-r--r-- | lib/libpcap/nametoaddr.c | 32 | ||||
| -rw-r--r-- | lib/libpcap/optimize.c | 93 | ||||
| -rw-r--r-- | lib/libpcap/pcap-bpf.c | 13 | ||||
| -rw-r--r-- | lib/libpcap/pcap-namedb.h | 5 | ||||
| -rw-r--r-- | lib/libpcap/scanner.l | 33 |
9 files changed, 1019 insertions, 44 deletions
diff --git a/lib/libpcap/Makefile b/lib/libpcap/Makefile index 322165f3fd8..f0712695c92 100644 --- a/lib/libpcap/Makefile +++ b/lib/libpcap/Makefile @@ -1,4 +1,4 @@ -# $NetBSD: Makefile,v 1.17 1998/11/01 03:48:35 lukem Exp $ +# $NetBSD: Makefile,v 1.18 1999/07/02 10:05:22 itojun Exp $ LIB= pcap MAN= pcap.3 @@ -6,6 +6,7 @@ MAN= pcap.3 LEX= flex CPPFLAGS+=-I. -I${.CURDIR} -DYYBISON +CPPFLAGS+=-DINET6 CPPFLAGS+=-DHAVE_MALLOC_H=1 -DHAVE_SYS_IOCCOM_H=1 -DHAVE_SYS_SOCKIO_H=1 CPPFLAGS+=-DHAVE_ETHER_HOSTTON=1 -DHAVE_STRERROR=1 -DHAVE_SOCKADDR_SA_LEN=1 CFPPLAGS+=-DLBL_ALIGN=1 diff --git a/lib/libpcap/gencode.c b/lib/libpcap/gencode.c index 1fc97002c9b..f253299be2e 100644 --- a/lib/libpcap/gencode.c +++ b/lib/libpcap/gencode.c @@ -1,4 +1,4 @@ -/* $NetBSD: gencode.c,v 1.12 1999/05/15 17:39:07 thorpej Exp $ */ +/* $NetBSD: gencode.c,v 1.13 1999/07/02 10:05:22 itojun Exp $ */ /* * Copyright (c) 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1997 @@ -26,7 +26,7 @@ static const char rcsid[] = "@(#) Header: gencode.c,v 1.93 97/06/12 14:22:47 leres Exp (LBL)"; #else -__RCSID("$NetBSD: gencode.c,v 1.12 1999/05/15 17:39:07 thorpej Exp $"); +__RCSID("$NetBSD: gencode.c,v 1.13 1999/07/02 10:05:22 itojun Exp $"); #endif #endif @@ -63,6 +63,10 @@ struct rtentry; #include "gencode.h" #include "ppp.h" #include <pcap-namedb.h> +#ifdef INET6 +#include <netdb.h> +#include <sys/socket.h> +#endif /*INET6*/ #include "gnuc.h" #ifdef HAVE_OS_PROTO_H @@ -147,15 +151,28 @@ static inline struct block *gen_true(void); static inline struct block *gen_false(void); static struct block *gen_linktype(int); static struct block *gen_hostop(bpf_u_int32, bpf_u_int32, int, int, u_int, u_int); +#ifdef INET6 +static struct block *gen_hostop6(struct in6_addr *, struct in6_addr *, int, int, u_int, u_int); +#endif static struct block *gen_ehostop(const u_char *, int); static struct block *gen_fhostop(const u_char *, int); static struct block *gen_dnhostop(bpf_u_int32, int, u_int); static struct block *gen_host(bpf_u_int32, bpf_u_int32, int, int); +#ifdef INET6 +static struct block *gen_host6(struct in6_addr *, struct in6_addr *, int, int); +#endif static struct block *gen_gateway(const u_char *, bpf_u_int32 **, int, int); static struct block *gen_ipfrag(void); static struct block *gen_portatom(int, bpf_int32); +#ifdef INET6 +static struct block *gen_portatom6(int, bpf_int32); +#endif struct block *gen_portop(int, int, int); static struct block *gen_port(int, int, int); +#ifdef INET6 +struct block *gen_portop6(int, int, int); +static struct block *gen_port6(int, int, int); +#endif static int lookup_proto(const char *, int); static struct block *gen_proto(int, int, int); static struct slist *xfer_to_x(struct arth *); @@ -258,6 +275,7 @@ syntax() static bpf_u_int32 netmask; static int snaplen; +int no_optimize; int pcap_compile(pcap_t *p, struct bpf_program *program, @@ -266,6 +284,7 @@ pcap_compile(pcap_t *p, struct bpf_program *program, extern int n_errors; int len; + no_optimize = 0; n_errors = 0; root = NULL; bpf_pcap = p; @@ -287,7 +306,7 @@ pcap_compile(pcap_t *p, struct bpf_program *program, if (root == NULL) root = gen_retblk(snaplen); - if (optimize) { + if (optimize && !no_optimize) { bpf_optimize(&root); if (root == NULL || (root->s.code == (BPF_RET|BPF_K) && root->s.k == 0)) @@ -643,6 +662,10 @@ gen_linktype(proto) /* XXX */ if (proto == ETHERTYPE_IP) return (gen_cmp(0, BPF_W, (bpf_int32)htonl(AF_INET))); +#ifdef INET6 + if (proto == ETHERTYPE_IPV6) + return (gen_cmp(0, BPF_W, (bpf_int32)htonl(AF_INET6))); +#endif /* INET6 */ else return gen_false(); } @@ -691,6 +714,61 @@ gen_hostop(addr, mask, dir, proto, src_off, dst_off) return b1; } +#ifdef INET6 +static struct block * +gen_hostop6(addr, mask, dir, proto, src_off, dst_off) + struct in6_addr *addr; + struct in6_addr *mask; + int dir, proto; + u_int src_off, dst_off; +{ + struct block *b0, *b1; + u_int offset; + + switch (dir) { + + case Q_SRC: + offset = src_off; + break; + + case Q_DST: + offset = dst_off; + break; + + case Q_AND: + b0 = gen_hostop6(addr, mask, Q_SRC, proto, src_off, dst_off); + b1 = gen_hostop6(addr, mask, Q_DST, proto, src_off, dst_off); + gen_and(b0, b1); + return b1; + + case Q_OR: + case Q_DEFAULT: + b0 = gen_hostop6(addr, mask, Q_SRC, proto, src_off, dst_off); + b1 = gen_hostop6(addr, mask, Q_DST, proto, src_off, dst_off); + gen_or(b0, b1); + return b1; + + default: + abort(); + } + /* this order is important */ + b1 = gen_mcmp(offset + 12, BPF_W, ntohl(addr->s6_addr32[3]), + ntohl(mask->s6_addr32[3])); + b0 = gen_mcmp(offset + 8, BPF_W, ntohl(addr->s6_addr32[2]), + ntohl(mask->s6_addr32[2])); + gen_and(b0, b1); + b0 = gen_mcmp(offset + 4, BPF_W, ntohl(addr->s6_addr32[1]), + ntohl(mask->s6_addr32[1])); + gen_and(b0, b1); + b0 = gen_mcmp(offset + 0, BPF_W, ntohl(addr->s6_addr32[0]), + ntohl(mask->s6_addr32[0])); + gen_and(b0, b1); + b0 = gen_linktype(proto); + gen_and(b0, b1); + return b1; +} +#endif /*INET6*/ + static struct block * gen_ehostop(eaddr, dir) register const u_char *eaddr; @@ -898,6 +976,9 @@ gen_host(addr, mask, proto, dir) case Q_IGRP: bpf_error("'igrp' modifier applied to host"); + case Q_PIM: + bpf_error("'pim' modifier applied to host"); + case Q_ATALK: bpf_error("ATALK host filtering not implemented"); @@ -916,11 +997,103 @@ gen_host(addr, mask, proto, dir) case Q_MOPRC: bpf_error("MOPRC host filtering not implemented"); +#ifdef INET6 + case Q_IPV6: + bpf_error("'ip6' modifier applied to ip host"); + + case Q_ICMPV6: + bpf_error("'icmp6' modifier applied to host"); +#endif /* INET6 */ + + case Q_AH: + bpf_error("'ah' modifier applied to host"); + + case Q_ESP: + bpf_error("'esp' modifier applied to host"); + + default: + abort(); + } + /* NOTREACHED */ +} + +#ifdef INET6 +static struct block * +gen_host6(addr, mask, proto, dir) + struct in6_addr *addr; + struct in6_addr *mask; + int proto; + int dir; +{ + switch (proto) { + + case Q_DEFAULT: + return gen_host6(addr, mask, Q_IPV6, dir); + + case Q_IP: + bpf_error("'ip' modifier applied to ip6 host"); + + case Q_RARP: + bpf_error("'rarp' modifier applied to ip6 host"); + + case Q_ARP: + bpf_error("'arp' modifier applied to ip6 host"); + + case Q_TCP: + bpf_error("'tcp' modifier applied to host"); + + case Q_UDP: + bpf_error("'udp' modifier applied to host"); + + case Q_ICMP: + bpf_error("'icmp' modifier applied to host"); + + case Q_IGMP: + bpf_error("'igmp' modifier applied to host"); + + case Q_IGRP: + bpf_error("'igrp' modifier applied to host"); + + case Q_PIM: + bpf_error("'pim' modifier applied to host"); + + case Q_ATALK: + bpf_error("ATALK host filtering not implemented"); + + case Q_DECNET: + bpf_error("'decnet' modifier applied to ip6 host"); + + case Q_SCA: + bpf_error("SCA host filtering not implemented"); + + case Q_LAT: + bpf_error("LAT host filtering not implemented"); + + case Q_MOPDL: + bpf_error("MOPDL host filtering not implemented"); + + case Q_MOPRC: + bpf_error("MOPRC host filtering not implemented"); + + case Q_IPV6: + return gen_hostop6(addr, mask, dir, ETHERTYPE_IPV6, + off_nl + 8, off_nl + 24); + + case Q_ICMPV6: + bpf_error("'icmp6' modifier applied to host"); + + case Q_AH: + bpf_error("'ah' modifier applied to host"); + + case Q_ESP: + bpf_error("'esp' modifier applied to host"); + default: abort(); } /* NOTREACHED */ } +#endif /*INET6*/ static struct block * gen_gateway(eaddr, alist, proto, dir) @@ -970,38 +1143,45 @@ gen_proto_abbrev(proto) switch (proto) { case Q_TCP: - b0 = gen_linktype(ETHERTYPE_IP); - b1 = gen_cmp(off_nl + 9, BPF_B, (bpf_int32)IPPROTO_TCP); - gen_and(b0, b1); + b1 = gen_proto(IPPROTO_TCP, Q_IP, Q_DEFAULT); +#ifdef INET6 + b0 = gen_proto(IPPROTO_TCP, Q_IPV6, Q_DEFAULT); + gen_or(b0, b1); +#endif break; case Q_UDP: - b0 = gen_linktype(ETHERTYPE_IP); - b1 = gen_cmp(off_nl + 9, BPF_B, (bpf_int32)IPPROTO_UDP); - gen_and(b0, b1); + b1 = gen_proto(IPPROTO_UDP, Q_IP, Q_DEFAULT); +#ifdef INET6 + b0 = gen_proto(IPPROTO_UDP, Q_IPV6, Q_DEFAULT); + gen_or(b0, b1); +#endif break; case Q_ICMP: - b0 = gen_linktype(ETHERTYPE_IP); - b1 = gen_cmp(off_nl + 9, BPF_B, (bpf_int32)IPPROTO_ICMP); - gen_and(b0, b1); + b1 = gen_proto(IPPROTO_ICMP, Q_IP, Q_DEFAULT); break; case Q_IGMP: - b0 = gen_linktype(ETHERTYPE_IP); - b1 = gen_cmp(off_nl + 9, BPF_B, (bpf_int32)2); - gen_and(b0, b1); + b1 = gen_proto(2, Q_IP, Q_DEFAULT); break; #ifndef IPPROTO_IGRP #define IPPROTO_IGRP 9 #endif case Q_IGRP: - b0 = gen_linktype(ETHERTYPE_IP); - b1 = gen_cmp(off_nl + 9, BPF_B, (long)IPPROTO_IGRP); + b1 = gen_proto(IPPROTO_IGRP, Q_IP, Q_DEFAULT); gen_and(b0, b1); break; + case Q_PIM: + b1 = gen_proto(IPPROTO_PIM, Q_IP, Q_DEFAULT); +#ifdef INET6 + b0 = gen_proto(IPPROTO_PIM, Q_IPV6, Q_DEFAULT); + gen_or(b0, b1); +#endif + break; + case Q_IP: b1 = gen_linktype(ETHERTYPE_IP); break; @@ -1041,6 +1221,41 @@ gen_proto_abbrev(proto) b1 = gen_linktype(ETHERTYPE_MOPRC); break; +#ifdef INET6 + case Q_IPV6: + b1 = gen_linktype(ETHERTYPE_IPV6); + break; + +#ifndef IPPROTO_ICMPV6 +#define IPPROTO_ICMPV6 58 +#endif + case Q_ICMPV6: + b1 = gen_proto(IPPROTO_ICMPV6, Q_IPV6, Q_DEFAULT); + break; +#endif /* INET6 */ + +#ifndef IPPROTO_AH +#define IPPROTO_AH 51 +#endif + case Q_AH: + b1 = gen_proto(IPPROTO_AH, Q_IP, Q_DEFAULT); +#ifdef INET6 + b0 = gen_proto(IPPROTO_AH, Q_IPV6, Q_DEFAULT); + gen_or(b0, b1); +#endif + break; + +#ifndef IPPROTO_ESP +#define IPPROTO_ESP 50 +#endif + case Q_ESP: + b1 = gen_proto(IPPROTO_ESP, Q_IP, Q_DEFAULT); +#ifdef INET6 + b0 = gen_proto(IPPROTO_ESP, Q_IPV6, Q_DEFAULT); + gen_or(b0, b1); +#endif + break; + default: abort(); } @@ -1085,6 +1300,16 @@ gen_portatom(off, v) return b; } +#ifdef INET6 +static struct block * +gen_portatom6(off, v) + int off; + bpf_int32 v; +{ + return gen_cmp(off_nl + 40 + off, BPF_H, v); +} +#endif/*INET6*/ + struct block * gen_portop(port, proto, dir) int port, proto, dir; @@ -1156,6 +1381,77 @@ gen_port(port, ip_proto, dir) return b1; } +#ifdef INET6 +struct block * +gen_portop6(port, proto, dir) + int port, proto, dir; +{ + struct block *b0, *b1, *tmp; + + /* ip proto 'proto' */ + b0 = gen_cmp(off_nl + 6, BPF_B, (bpf_int32)proto); + + switch (dir) { + case Q_SRC: + b1 = gen_portatom6(0, (bpf_int32)port); + break; + + case Q_DST: + b1 = gen_portatom6(2, (bpf_int32)port); + break; + + case Q_OR: + case Q_DEFAULT: + tmp = gen_portatom6(0, (bpf_int32)port); + b1 = gen_portatom6(2, (bpf_int32)port); + gen_or(tmp, b1); + break; + + case Q_AND: + tmp = gen_portatom6(0, (bpf_int32)port); + b1 = gen_portatom6(2, (bpf_int32)port); + gen_and(tmp, b1); + break; + + default: + abort(); + } + gen_and(b0, b1); + + return b1; +} + +static struct block * +gen_port6(port, ip_proto, dir) + int port; + int ip_proto; + int dir; +{ + struct block *b0, *b1, *tmp; + + /* ether proto ip */ + b0 = gen_linktype(ETHERTYPE_IPV6); + + switch (ip_proto) { + case IPPROTO_UDP: + case IPPROTO_TCP: + b1 = gen_portop6(port, ip_proto, dir); + break; + + case PROTO_UNDEF: + tmp = gen_portop6(port, IPPROTO_TCP, dir); + b1 = gen_portop6(port, IPPROTO_UDP, dir); + gen_or(tmp, b1); + break; + + default: + abort(); + } + gen_and(b0, b1); + return b1; +} +#endif /* INET6 */ + static int lookup_proto(name, proto) register const char *name; @@ -1186,6 +1482,306 @@ lookup_proto(name, proto) return v; } +struct stmt * +gen_joinsp(s, n) + struct stmt **s; + int n; +{ + return NULL; +} + +struct block * +gen_protochain(v, proto, dir) + int v; + int proto; + int dir; +{ + struct block *b0, *b; + struct slist *s[100]; + int fix2, fix3, fix4, fix5; + int ahcheck, again, end; + int i, max; + int reg1 = alloc_reg(); + int reg2 = alloc_reg(); + + memset(s, 0, sizeof(s)); + fix2 = fix3 = fix4 = fix5 = 0; + + switch (proto) { + case Q_IP: + case Q_IPV6: + break; + case Q_DEFAULT: + b0 = gen_protochain(v, Q_IP, dir); + b = gen_protochain(v, Q_IP, dir); + gen_or(b0, b); + return b; + default: + bpf_error("bad protocol applied for 'protochain'"); + /*NOTREACHED*/ + } + + no_optimize = 1; /*this code is not compatible with optimzer yet */ + + /* + * s[0] is a dummy entry to protect other BPF insn from damaged + * by s[fix] = foo with uninitialized variable "fix". It is somewhat + * hard to find interdependency made by jump table fixup. + */ + i = 0; + s[i] = new_stmt(0); /*dummy*/ + i++; + + switch (proto) { + case Q_IP: + b0 = gen_linktype(ETHERTYPE_IP); + + /* A = ip->ip_p */ + s[i] = new_stmt(BPF_LD|BPF_ABS|BPF_B); + s[i]->s.k = off_nl + 9; + i++; + /* X = ip->ip_hl << 2 */ + s[i] = new_stmt(BPF_LDX|BPF_MSH|BPF_B); + s[i]->s.k = off_nl; + i++; + break; + case Q_IPV6: + b0 = gen_linktype(ETHERTYPE_IPV6); + + /* A = ip6->ip_nxt */ + s[i] = new_stmt(BPF_LD|BPF_ABS|BPF_B); + s[i]->s.k = off_nl + 6; + i++; + /* X = sizeof(struct ip6_hdr) */ + s[i] = new_stmt(BPF_LDX|BPF_IMM); + s[i]->s.k = 40; + i++; + break; + default: + bpf_error("unsupported proto to gen_protochain"); + /*NOTREACHED*/ + } + + /* again: if (A == v) goto end; else fall through; */ + again = i; + s[i] = new_stmt(BPF_JMP|BPF_JEQ|BPF_K); + s[i]->s.k = v; + s[i]->s.jt = NULL; /*later*/ + s[i]->s.jf = NULL; /*update in next stmt*/ + fix5 = i; + i++; + + /* if (A == IPPROTO_NONE) goto end */ + s[i] = new_stmt(BPF_JMP|BPF_JEQ|BPF_K); + s[i]->s.jt = NULL; /*later*/ + s[i]->s.jf = NULL; /*update in next stmt*/ + s[i]->s.k = IPPROTO_NONE; + s[fix5]->s.jf = s[i]; + fix2 = i; + i++; + + if (proto == Q_IPV6) { + int v6start, v6end, v6advance, j; + + v6start = i; + /* if (A == IPPROTO_HOPOPTS) goto v6advance */ + s[i] = new_stmt(BPF_JMP|BPF_JEQ|BPF_K); + s[i]->s.jt = NULL; /*later*/ + s[i]->s.jf = NULL; /*update in next stmt*/ + s[i]->s.k = IPPROTO_HOPOPTS; + s[fix2]->s.jf = s[i]; + i++; + /* if (A == IPPROTO_DSTOPTS) goto v6advance */ + s[i - 1]->s.jf = s[i] = new_stmt(BPF_JMP|BPF_JEQ|BPF_K); + s[i]->s.jt = NULL; /*later*/ + s[i]->s.jf = NULL; /*update in next stmt*/ + s[i]->s.k = IPPROTO_DSTOPTS; + i++; + /* if (A == IPPROTO_ROUTING) goto v6advance */ + s[i - 1]->s.jf = s[i] = new_stmt(BPF_JMP|BPF_JEQ|BPF_K); + s[i]->s.jt = NULL; /*later*/ + s[i]->s.jf = NULL; /*update in next stmt*/ + s[i]->s.k = IPPROTO_ROUTING; + i++; + /* if (A == IPPROTO_FRAGMENT) goto v6advance; else goto ahcheck; */ + s[i - 1]->s.jf = s[i] = new_stmt(BPF_JMP|BPF_JEQ|BPF_K); + s[i]->s.jt = NULL; /*later*/ + s[i]->s.jf = NULL; /*later*/ + s[i]->s.k = IPPROTO_FRAGMENT; + fix3 = i; + v6end = i; + i++; + + /* v6advance: */ + v6advance = i; + + /* + * in short, + * A = P[X + 1]; + * X = X + (P[X] + 1) * 8; + */ + /* A = X */ + s[i] = new_stmt(BPF_MISC|BPF_TXA); + i++; + /* MEM[reg1] = A */ + s[i] = new_stmt(BPF_ST); + s[i]->s.k = reg1; + i++; + /* A += 1 */ + s[i] = new_stmt(BPF_ALU|BPF_ADD|BPF_K); + s[i]->s.k = 1; + i++; + /* X = A */ + s[i] = new_stmt(BPF_MISC|BPF_TAX); + i++; + /* A = P[X + packet head]; */ + s[i] = new_stmt(BPF_LD|BPF_IND|BPF_B); + s[i]->s.k = off_nl; + i++; + /* MEM[reg2] = A */ + s[i] = new_stmt(BPF_ST); + s[i]->s.k = reg2; + i++; + /* X = MEM[reg1] */ + s[i] = new_stmt(BPF_LDX|BPF_MEM); + s[i]->s.k = reg1; + i++; + /* A = P[X + packet head] */ + s[i] = new_stmt(BPF_LD|BPF_IND|BPF_B); + s[i]->s.k = off_nl; + i++; + /* A += 1 */ + s[i] = new_stmt(BPF_ALU|BPF_ADD|BPF_K); + s[i]->s.k = 1; + i++; + /* A *= 8 */ + s[i] = new_stmt(BPF_ALU|BPF_MUL|BPF_K); + s[i]->s.k = 8; + i++; + /* X = A; */ + s[i] = new_stmt(BPF_MISC|BPF_TAX); + i++; + /* A = MEM[reg2] */ + s[i] = new_stmt(BPF_LD|BPF_MEM); + s[i]->s.k = reg2; + i++; + + /* goto again; (must use BPF_JA for backward jump) */ + s[i] = new_stmt(BPF_JMP|BPF_JA); + s[i]->s.k = again - i - 1; + s[i - 1]->s.jf = s[i]; + i++; + + /* fixup */ + for (j = v6start; j <= v6end; j++) + s[j]->s.jt = s[v6advance]; + } else { + /* nop */ + s[i] = new_stmt(BPF_ALU|BPF_ADD|BPF_K); + s[i]->s.k = 0; + s[fix2]->s.jf = s[i]; + i++; + } + + /* ahcheck: */ + ahcheck = i; + /* if (A == IPPROTO_AH) then fall through; else goto end; */ + s[i] = new_stmt(BPF_JMP|BPF_JEQ|BPF_K); + s[i]->s.jt = NULL; /*later*/ + s[i]->s.jf = NULL; /*later*/ + s[i]->s.k = IPPROTO_AH; + if (fix3) + s[fix3]->s.jf = s[ahcheck]; + fix4 = i; + i++; + + /* + * in short, + * A = P[X + 1]; + * X = X + (P[X] + 2) * 4; + */ + /* A = X */ + s[i - 1]->s.jt = s[i] = new_stmt(BPF_MISC|BPF_TXA); + i++; + /* MEM[reg1] = A */ + s[i] = new_stmt(BPF_ST); + s[i]->s.k = reg1; + i++; + /* A += 1 */ + s[i] = new_stmt(BPF_ALU|BPF_ADD|BPF_K); + s[i]->s.k = 1; + i++; + /* X = A */ + s[i] = new_stmt(BPF_MISC|BPF_TAX); + i++; + /* A = P[X + packet head]; */ + s[i] = new_stmt(BPF_LD|BPF_IND|BPF_B); + s[i]->s.k = off_nl; + i++; + /* MEM[reg2] = A */ + s[i] = new_stmt(BPF_ST); + s[i]->s.k = reg2; + i++; + /* X = MEM[reg1] */ + s[i] = new_stmt(BPF_LDX|BPF_MEM); + s[i]->s.k = reg1; + i++; + /* A = P[X + packet head] */ + s[i] = new_stmt(BPF_LD|BPF_IND|BPF_B); + s[i]->s.k = off_nl; + i++; + /* A += 2 */ + s[i] = new_stmt(BPF_ALU|BPF_ADD|BPF_K); + s[i]->s.k = 2; + i++; + /* A *= 4 */ + s[i] = new_stmt(BPF_ALU|BPF_MUL|BPF_K); + s[i]->s.k = 4; + i++; + /* X = A; */ + s[i] = new_stmt(BPF_MISC|BPF_TAX); + i++; + /* A = MEM[reg2] */ + s[i] = new_stmt(BPF_LD|BPF_MEM); + s[i]->s.k = reg2; + i++; + + /* goto again; (must use BPF_JA for backward jump) */ + s[i] = new_stmt(BPF_JMP|BPF_JA); + s[i]->s.k = again - i - 1; + i++; + + /* end: nop */ + end = i; + s[i] = new_stmt(BPF_ALU|BPF_ADD|BPF_K); + s[i]->s.k = 0; + s[fix2]->s.jt = s[end]; + s[fix4]->s.jf = s[end]; + s[fix5]->s.jt = s[end]; + i++; + + /* + * make slist chain + */ + max = i; + for (i = 0; i < max - 1; i++) + s[i]->next = s[i + 1]; + s[max - 1]->next = NULL; + + /* + * emit final check + */ + b = new_block(JMP(BPF_JEQ)); + b->stmts = s[1]; /*remember, s[0] is dummy*/ + b->s.k = v; + + free_reg(reg1); + free_reg(reg2); + + gen_and(b0, b); + return b; +} + static struct block * gen_proto(v, proto, dir) int v; @@ -1199,9 +1795,21 @@ gen_proto(v, proto, dir) switch (proto) { case Q_DEFAULT: +#ifdef INET6 + b0 = gen_proto(v, Q_IP, dir); + b1 = gen_proto(v, Q_IPV6, dir); + gen_or(b0, b1); + return b1; +#else + /*FALLTHROUGH*/ +#endif case Q_IP: b0 = gen_linktype(ETHERTYPE_IP); +#ifndef CHASE_CHAIN b1 = gen_cmp(off_nl + 9, BPF_B, (bpf_int32)v); +#else + b1 = gen_protochain(v, Q_IP); +#endif gen_and(b0, b1); return b1; @@ -1260,6 +1868,31 @@ gen_proto(v, proto, dir) bpf_error("'igrp proto' is bogus"); /* NOTREACHED */ + case Q_PIM: + bpf_error("'pim proto' is bogus"); + /* NOTREACHED */ + +#ifdef INET6 + case Q_IPV6: + b0 = gen_linktype(ETHERTYPE_IPV6); +#ifndef CHASE_CHAIN + b1 = gen_cmp(off_nl + 6, BPF_B, (bpf_int32)v); +#else + b1 = gen_protochain(v, Q_IPV6); +#endif + gen_and(b0, b1); + return b1; + + case Q_ICMPV6: + bpf_error("'icmp6 proto' is bogus"); +#endif /* INET6 */ + + case Q_AH: + bpf_error("'ah proto' is bogus"); + + case Q_ESP: + bpf_error("'ah proto' is bogus"); + default: abort(); /* NOTREACHED */ @@ -1276,7 +1909,15 @@ gen_scode(name, q) int dir = q.dir; int tproto; u_char *eaddr; - bpf_u_int32 mask, addr, **alist; + bpf_u_int32 mask, addr; + bpf_u_int32 **alist; +#ifdef INET6 + int tproto6; + struct sockaddr_in *sin; + struct sockaddr_in6 *sin6; + struct addrinfo *res, *res0; + struct in6_addr mask128; +#endif /*INET6*/ struct block *b, *tmp; int port, real_proto; @@ -1326,6 +1967,7 @@ gen_scode(name, q) */ return (gen_host(dn_addr, 0, proto, dir)); } else { +#ifndef INET6 alist = pcap_nametoaddr(name); if (alist == NULL || *alist == NULL) bpf_error("unknown host '%s'", name); @@ -1340,6 +1982,41 @@ gen_scode(name, q) b = tmp; } return b; +#else + memset(&mask128, 0xff, sizeof(mask128)); + res0 = res = pcap_nametoaddrinfo(name); + if (res == NULL) + bpf_error("unknown host '%s'", name); + b = tmp = NULL; + tproto = tproto6 = proto; + if (off_linktype == -1 && tproto == Q_DEFAULT) { + tproto = Q_IP; + tproto6 = Q_IPV6; + } + while (res) { + switch (res->ai_family) { + case AF_INET: + sin = (struct sockaddr_in *) + res->ai_addr; + tmp = gen_host(ntohl(sin->sin_addr.s_addr), + 0xffffffff, tproto, dir); + break; + case AF_INET6: + sin6 = (struct sockaddr_in6 *) + res->ai_addr; + tmp = gen_host6(&sin6->sin6_addr, + &mask128, tproto6, dir); + break; + } + if (b) + gen_or(b, tmp); + b = tmp; + + res = res->ai_next; + } + freeaddrinfo(res0); + return b; +#endif /*INET6*/ } case Q_PORT: @@ -1361,7 +2038,16 @@ gen_scode(name, q) /* override PROTO_UNDEF */ real_proto = IPPROTO_TCP; } +#ifndef INET6 return gen_port(port, real_proto, dir); +#else + { + struct block *b; + b = gen_port(port, real_proto, dir); + gen_or(gen_port6(port, real_proto, dir), b); + return b; + } +#endif /* INET6 */ case Q_GATEWAY: eaddr = pcap_ether_hostton(name); @@ -1380,6 +2066,14 @@ gen_scode(name, q) else bpf_error("unknown protocol: %s", name); + case Q_PROTOCHAIN: + real_proto = lookup_proto(name, proto); + if (real_proto >= 0) + return gen_protochain(real_proto, proto, dir); + else + bpf_error("unknown protocol: %s", name); + + case Q_UNDEF: syntax(); /* NOTREACHED */ @@ -1405,11 +2099,17 @@ gen_mcode(s1, s2, masklen, q) mlen = __pcap_atoin(s2, &m); /* Promote short ipaddr */ m <<= 32 - mlen; + if ((n & ~m) != 0) + bpf_error("non-network bits set in \"%s mask %s\"", + s1, s2); } else { /* Convert mask len to mask */ if (masklen > 32) bpf_error("mask length must be <= 32"); m = 0xffffffff << (32 - masklen); + if ((n & ~m) != 0) + bpf_error("non-network bits set in \"%s/%d\"", + s1, masklen); } switch (q.addr) { @@ -1476,7 +2176,16 @@ gen_ncode(s, v, q) else bpf_error("illegal qualifier of 'port'"); +#ifndef INET6 return gen_port((int)v, proto, dir); +#else + { + struct block *b; + b = gen_port((int)v, proto, dir); + gen_or(gen_port6((int)v, proto, dir), b); + return b; + } +#endif /* INET6 */ case Q_GATEWAY: bpf_error("'gateway' requires a name"); @@ -1485,6 +2194,9 @@ gen_ncode(s, v, q) case Q_PROTO: return gen_proto((int)v, proto, dir); + case Q_PROTOCHAIN: + return gen_protochain((int)v, proto, dir); + case Q_UNDEF: syntax(); /* NOTREACHED */ @@ -1496,6 +2208,63 @@ gen_ncode(s, v, q) /* NOTREACHED */ } +#ifdef INET6 +struct block * +gen_mcode6(s1, s2, masklen, q) + register const char *s1, *s2; + register int masklen; + struct qual q; +{ + struct addrinfo *res; + struct in6_addr *addr; + struct in6_addr mask; + struct block *b; + + if (s2) + bpf_error("no mask %s supported", s2); + + res = pcap_nametoaddrinfo(s1); + if (!res) + bpf_error("invalid ip6 address %s", s1); + if (res->ai_next) + bpf_error("%s resolved to multiple address", s1); + addr = &((struct sockaddr_in6 *)res->ai_addr)->sin6_addr; + + if (sizeof(mask) * 8 < masklen) + bpf_error("mask length must be <= %d", sizeof(mask) * 8); + memset(&mask, 0xff, masklen / 8); + if (masklen % 8) { + mask.s6_addr8[masklen / 8] = + (0xff << (8 - masklen % 8)) & 0xff; + } + + if ((addr->s6_addr32[0] & ~mask.s6_addr32[0]) + || (addr->s6_addr32[1] & ~mask.s6_addr32[1]) + || (addr->s6_addr32[2] & ~mask.s6_addr32[2]) + || (addr->s6_addr32[3] & ~mask.s6_addr32[3])) { + bpf_error("non-network bits set in \"%s/%d\"", s1, masklen); + } + + switch (q.addr) { + + case Q_DEFAULT: + case Q_HOST: + if (masklen != 128) + bpf_error("Mask syntax for networks only"); + /* FALLTHROUGH */ + + case Q_NET: + b = gen_host6(addr, &mask, q.proto, q.dir); + freeaddrinfo(res); + return b; + + default: + bpf_error("invalid qualifier against IPv6 address"); + /* NOTREACHED */ + } +} +#endif /*INET6*/ + struct block * gen_ecode(eaddr, q) register const u_char *eaddr; @@ -1594,6 +2363,9 @@ gen_load(proto, index, size) case Q_LAT: case Q_MOPRC: case Q_MOPDL: +#ifdef INET6 + case Q_IPV6: +#endif /* XXX Note that we assume a fixed link link header here. */ s = xfer_to_x(index); tmp = new_stmt(BPF_LD|BPF_IND|size); @@ -1612,6 +2384,7 @@ gen_load(proto, index, size) case Q_ICMP: case Q_IGMP: case Q_IGRP: + case Q_PIM: s = new_stmt(BPF_LDX|BPF_MSH|BPF_B); s->s.k = off_nl; sappend(s, xfer_to_a(index)); @@ -1624,8 +2397,16 @@ gen_load(proto, index, size) gen_and(gen_proto_abbrev(proto), b = gen_ipfrag()); if (index->b) gen_and(index->b, b); +#ifdef INET6 + gen_and(gen_proto_abbrev(Q_IP), b); +#endif index->b = b; break; +#ifdef INET6 + case Q_ICMPV6: + bpf_error("IPv6 upper-layer protocol is not supported by proto[x]"); + /*NOTREACHED*/ +#endif } index->regno = regno; s = new_stmt(BPF_ST); @@ -1947,6 +2728,14 @@ gen_multicast(proto) b1->s.code = JMP(BPF_JGE); gen_and(b0, b1); return b1; + +#ifdef INET6 + case Q_IPV6: + b0 = gen_linktype(ETHERTYPE_IPV6); + b1 = gen_cmp(off_nl + 24, BPF_B, (bpf_int32)255); + gen_and(b0, b1); + return b1; +#endif /* INET6 */ } bpf_error("only IP multicast filters supported on ethernet/FDDI"); } diff --git a/lib/libpcap/gencode.h b/lib/libpcap/gencode.h index 23487021ca9..dbe45cd908d 100644 --- a/lib/libpcap/gencode.h +++ b/lib/libpcap/gencode.h @@ -1,4 +1,4 @@ -/* $NetBSD: gencode.h,v 1.5 1997/10/03 15:53:06 christos Exp $ */ +/* $NetBSD: gencode.h,v 1.6 1999/07/02 10:05:22 itojun Exp $ */ /* * Copyright (c) 1990, 1991, 1992, 1993, 1994, 1995, 1996 @@ -33,6 +33,7 @@ #define Q_PORT 3 #define Q_GATEWAY 4 #define Q_PROTO 5 +#define Q_PROTOCHAIN 6 /* Protocol qualifiers. */ @@ -54,6 +55,14 @@ #define Q_MOPRC 14 #define Q_MOPDL 15 + +#define Q_IPV6 16 +#define Q_ICMPV6 17 +#define Q_AH 18 +#define Q_ESP 19 + +#define Q_PIM 20 + /* Directional qualifiers. */ #define Q_SRC 1 @@ -64,8 +73,12 @@ #define Q_DEFAULT 0 #define Q_UNDEF 255 +struct slist; + struct stmt { int code; + struct slist *jt; /*only for relative jump in block*/ + struct slist *jf; /*only for relative jump in block*/ bpf_int32 k; }; @@ -149,9 +162,14 @@ void gen_and(struct block *, struct block *); void gen_or(struct block *, struct block *); void gen_not(struct block *); +struct stmt *gen_joinsp __P((struct stmt **, int)); +struct block *gen_protochain __P((int, int, int)); struct block *gen_scode(const char *, struct qual); struct block *gen_ecode(const u_char *, struct qual); struct block *gen_mcode(const char *, const char *, int, struct qual); +#ifdef INET6 +struct block *gen_mcode6(const char *, const char *, int, struct qual); +#endif struct block *gen_ncode(const char *, bpf_u_int32, struct qual); struct block *gen_proto_abbrev(int); struct block *gen_relation(int, struct arth *, struct arth *, int); @@ -179,3 +197,5 @@ void sappend(struct slist *, struct slist *); /* XXX */ #define JT(b) ((b)->et.succ) #define JF(b) ((b)->ef.succ) + +extern int no_optimize; diff --git a/lib/libpcap/grammar.y b/lib/libpcap/grammar.y index 4d0aefe9d74..efc24715186 100644 --- a/lib/libpcap/grammar.y +++ b/lib/libpcap/grammar.y @@ -1,5 +1,5 @@ %{ -/* $NetBSD: grammar.y,v 1.5 1997/10/03 15:53:07 christos Exp $ */ +/* $NetBSD: grammar.y,v 1.6 1999/07/02 10:05:22 itojun Exp $ */ /* * Copyright (c) 1988, 1989, 1990, 1991, 1992, 1993, 1994, 1995, 1996 @@ -28,7 +28,7 @@ static const char rcsid[] = "@(#) Header: grammar.y,v 1.56 96/11/02 21:54:55 leres Exp (LBL)"; #else -__RCSID("$NetBSD: grammar.y,v 1.5 1997/10/03 15:53:07 christos Exp $"); +__RCSID("$NetBSD: grammar.y,v 1.6 1999/07/02 10:05:22 itojun Exp $"); #endif #endif @@ -113,20 +113,21 @@ pcap_parse() %type <rblk> other %token DST SRC HOST GATEWAY -%token NET MASK PORT LESS GREATER PROTO BYTE -%token ARP RARP IP TCP UDP ICMP IGMP IGRP +%token NET MASK PORT LESS GREATER PROTO PROTOCHAIN BYTE +%token ARP RARP IP TCP UDP ICMP IGMP IGRP PIM %token ATALK DECNET LAT SCA MOPRC MOPDL %token TK_BROADCAST TK_MULTICAST %token NUM INBOUND OUTBOUND %token LINK %token GEQ LEQ NEQ -%token ID EID HID +%token ID EID HID HID6 %token LSH RSH %token LEN +%token IPV6 ICMPV6 AH ESP %type <s> ID %type <e> EID -%type <s> HID +%type <s> HID HID6 %type <i> NUM %left OR AND @@ -178,6 +179,24 @@ nid: ID { $$.b = gen_scode($1, $$.q = $<blk>0.q); } break; } } + | HID6 '/' NUM { +#ifdef INET6 + $$.b = gen_mcode6($1, NULL, $3, + $$.q = $<blk>0.q); +#else + bpf_error("'ip6addr/prefixlen' not supported " + "in this configuration"); +#endif /*INET6*/ + } + | HID6 { +#ifdef INET6 + $$.b = gen_mcode6($1, 0, 128, + $$.q = $<blk>0.q); +#else + bpf_error("'ip6addr' not supported " + "in this configuration"); +#endif /*INET6*/ + } | EID { $$.b = gen_ecode($1, $$.q = $<blk>0.q); } | not id { gen_not($2.b); $$ = $2; } ; @@ -200,6 +219,7 @@ head: pqual dqual aqual { QSET($$.q, $1, $2, $3); } | pqual dqual { QSET($$.q, $1, $2, Q_DEFAULT); } | pqual aqual { QSET($$.q, $1, Q_DEFAULT, $2); } | pqual PROTO { QSET($$.q, $1, Q_DEFAULT, Q_PROTO); } + | pqual PROTOCHAIN { QSET($$.q, $1, Q_DEFAULT, Q_PROTOCHAIN); } | pqual ndaqual { QSET($$.q, $1, Q_DEFAULT, $2); } ; rterm: head id { $$ = $2; } @@ -240,12 +260,17 @@ pname: LINK { $$ = Q_LINK; } | ICMP { $$ = Q_ICMP; } | IGMP { $$ = Q_IGMP; } | IGRP { $$ = Q_IGRP; } + | PIM { $$ = Q_PIM; } | ATALK { $$ = Q_ATALK; } | DECNET { $$ = Q_DECNET; } | LAT { $$ = Q_LAT; } | SCA { $$ = Q_SCA; } | MOPDL { $$ = Q_MOPDL; } | MOPRC { $$ = Q_MOPRC; } + | IPV6 { $$ = Q_IPV6; } + | ICMPV6 { $$ = Q_ICMPV6; } + | AH { $$ = Q_AH; } + | ESP { $$ = Q_ESP; } ; other: pqual TK_BROADCAST { $$ = gen_broadcast($1); } | pqual TK_MULTICAST { $$ = gen_multicast($1); } diff --git a/lib/libpcap/nametoaddr.c b/lib/libpcap/nametoaddr.c index 4e799963acd..36e0fc7e984 100644 --- a/lib/libpcap/nametoaddr.c +++ b/lib/libpcap/nametoaddr.c @@ -1,4 +1,4 @@ -/* $NetBSD: nametoaddr.c,v 1.9 1997/11/05 21:37:27 cgd Exp $ */ +/* $NetBSD: nametoaddr.c,v 1.10 1999/07/02 10:05:22 itojun Exp $ */ /* * Copyright (c) 1990, 1991, 1992, 1993, 1994, 1995, 1996 @@ -30,7 +30,7 @@ static const char rcsid[] = "@(#) Header: nametoaddr.c,v 1.47 97/06/13 13:16:19 leres Exp (LBL)"; #else -__RCSID("$NetBSD: nametoaddr.c,v 1.9 1997/11/05 21:37:27 cgd Exp $"); +__RCSID("$NetBSD: nametoaddr.c,v 1.10 1999/07/02 10:05:22 itojun Exp $"); #endif #endif @@ -46,12 +46,12 @@ struct rtentry; #include <net/if.h> #include <netinet/in.h> -#ifdef __NetBSD__ -#include <net/if_ether.h> -#else #include <netinet/if_ether.h> -#endif #include <arpa/inet.h> +#ifdef INET6 +#include <netdb.h> +#include <sys/socket.h> +#endif /*INET6*/ #include <ctype.h> #include <errno.h> @@ -105,6 +105,23 @@ pcap_nametoaddr(const char *name) return 0; } +#ifdef INET6 +struct addrinfo * +pcap_nametoaddrinfo(const char *name) +{ + struct addrinfo hints, *res; + int error; + + memset(&hints, 0, sizeof(hints)); + hints.ai_family = PF_UNSPEC; + error = getaddrinfo(name, NULL, &hints, &res); + if (error) + return NULL; + else + return res; +} +#endif /*INET6*/ + /* * Convert net name to internet address. * Return 0 upon failure. @@ -196,6 +213,9 @@ struct eproto eproto_db[] = { { "pup", ETHERTYPE_PUP }, { "xns", ETHERTYPE_NS }, { "ip", ETHERTYPE_IP }, +#ifdef INET6 + { "ip6", ETHERTYPE_IPV6 }, +#endif { "arp", ETHERTYPE_ARP }, { "rarp", ETHERTYPE_REVARP }, { "sprite", ETHERTYPE_SPRITE }, diff --git a/lib/libpcap/optimize.c b/lib/libpcap/optimize.c index e1274a357d3..7dade84f93d 100644 --- a/lib/libpcap/optimize.c +++ b/lib/libpcap/optimize.c @@ -1,4 +1,4 @@ -/* $NetBSD: optimize.c,v 1.7 1997/10/03 15:53:11 christos Exp $ */ +/* $NetBSD: optimize.c,v 1.8 1999/07/02 10:05:22 itojun Exp $ */ /* * Copyright (c) 1988, 1989, 1990, 1991, 1993, 1994, 1995, 1996 @@ -28,7 +28,7 @@ static const char rcsid[] = "@(#) Header: optimize.c,v 1.60 96/09/26 23:28:14 leres Exp (LBL)"; #else -__RCSID("$NetBSD: optimize.c,v 1.7 1997/10/03 15:53:11 christos Exp $"); +__RCSID("$NetBSD: optimize.c,v 1.8 1999/07/02 10:05:22 itojun Exp $"); #endif #endif @@ -1111,6 +1111,14 @@ opt_blk(b, do_stmts) int i; bpf_int32 aval; +#if 0 + for (s = b->stmts; s && s->next; s = s->next) + if (BPF_CLASS(s->s.code) == BPF_JMP) { + do_stmts = 0; + break; + } +#endif + /* * Initialize the atom values. * If we have no predecessors, everything is undefined. @@ -1480,8 +1488,6 @@ opt_blks(root, do_stmts) init_val(); maxlevel = root->level; - - find_inedges(root); for (i = maxlevel; i >= 0; --i) for (p = levels[i]; p; p = p->link) opt_blk(p, do_stmts); @@ -1499,8 +1505,6 @@ opt_blks(root, do_stmts) opt_j(&p->ef); } } - - find_inedges(root); for (i = 1; i <= maxlevel; ++i) { for (p = levels[i]; p; p = p->link) { or_pullup(p); @@ -1580,6 +1584,7 @@ opt_loop(root, do_stmts) find_levels(root); find_dom(root); find_closure(root); + find_inedges(root); find_ud(root); find_edom(root); opt_blks(root, do_stmts); @@ -1896,6 +1901,7 @@ convert_code_r(p) int slen; u_int off; int extrajmps; /* number of extra jumps inserted */ + struct slist **offset; if (p == 0 || isMarked(p)) return (1); @@ -1912,13 +1918,88 @@ convert_code_r(p) p->offset = dst - fstart; + /* generate offset[] for convenience */ + offset = (struct slist **)calloc(sizeof(struct slist *), slen); + if (!offset) { + bpf_error("not enough core"); + /*NOTREACHED*/ + } + src = p->stmts; + for (off = 0; off < slen && src; off++) { +#if 0 + printf("off=%d src=%x\n", off, src); +#endif + offset[off] = src; + src = src->next; + } + + off = 0; for (src = p->stmts; src; src = src->next) { if (src->s.code == NOP) continue; dst->code = (u_short)src->s.code; dst->k = src->s.k; + + /* fill block-local relative jump */ + if (BPF_CLASS(src->s.code) != BPF_JMP + || src->s.code == (BPF_JMP|BPF_JA)) { +#if 0 + if (src->s.jt || src->s.jf) { + bpf_error("illegal jmp destination"); + /*NOTREACHED*/ + } +#endif + goto filled; + } + if (off == slen - 2) /*???*/ + goto filled; + + { + int i; + int jt, jf; + char *ljerr = "%s for block-local relative jump: off=%d"; + +#if 0 + printf("code=%x off=%d %x %x\n", src->s.code, + off, src->s.jt, src->s.jf); +#endif + + if (!src->s.jt || !src->s.jf) { + bpf_error(ljerr, "no jmp destination", off); + /*NOTREACHED*/ + } + + jt = jf = 0; + for (i = 0; i < slen; i++) { + if (offset[i] == src->s.jt) { + if (jt) { + bpf_error(ljerr, "multiple matches", off); + /*NOTREACHED*/ + } + + dst->jt = i - off - 1; + jt++; + } + if (offset[i] == src->s.jf) { + if (jf) { + bpf_error(ljerr, "multiple matches", off); + /*NOTREACHED*/ + } + dst->jf = i - off - 1; + jf++; + } + } + if (!jt || !jf) { + bpf_error(ljerr, "no destination found", off); + /*NOTREACHED*/ + } + } +filled: ++dst; + ++off; } + free(offset); + #ifdef BDEBUG bids[dst - fstart] = p->id + 1; #endif diff --git a/lib/libpcap/pcap-bpf.c b/lib/libpcap/pcap-bpf.c index a75923decc0..46e23f2ce52 100644 --- a/lib/libpcap/pcap-bpf.c +++ b/lib/libpcap/pcap-bpf.c @@ -1,4 +1,4 @@ -/* $NetBSD: pcap-bpf.c,v 1.6 1997/10/03 15:53:12 christos Exp $ */ +/* $NetBSD: pcap-bpf.c,v 1.7 1999/07/02 10:05:22 itojun Exp $ */ /* * Copyright (c) 1993, 1994, 1995, 1996 @@ -26,7 +26,7 @@ static const char rcsid[] = "@(#) Header: pcap-bpf.c,v 1.29 96/12/31 20:53:40 leres Exp (LBL)"; #else -__RCSID("$NetBSD: pcap-bpf.c,v 1.6 1997/10/03 15:53:12 christos Exp $"); +__RCSID("$NetBSD: pcap-bpf.c,v 1.7 1999/07/02 10:05:22 itojun Exp $"); #endif #endif @@ -54,6 +54,8 @@ __RCSID("$NetBSD: pcap-bpf.c,v 1.6 1997/10/03 15:53:12 christos Exp $"); #include "os-proto.h" #endif +#include "gencode.h" + int pcap_stats(pcap_t *p, struct pcap_stat *ps) { @@ -262,6 +264,13 @@ pcap_open_live(char *device, int snaplen, int promisc, int to_ms, char *ebuf) int pcap_setfilter(pcap_t *p, struct bpf_program *fp) { + /* + * It looks that BPF code generated by gen_protochain() is not + * compatible with some of kernel BPF code (for example BSD/OS 3.1). + * Take a safer side for now. + */ + if (no_optimize) + p->fcode = *fp; if (p->sf.rfile != NULL) p->fcode = *fp; else if (ioctl(p->fd, BIOCSETF, (caddr_t)fp) < 0) { diff --git a/lib/libpcap/pcap-namedb.h b/lib/libpcap/pcap-namedb.h index eb62e4a087d..69d5689015c 100644 --- a/lib/libpcap/pcap-namedb.h +++ b/lib/libpcap/pcap-namedb.h @@ -1,4 +1,4 @@ -/* $NetBSD: pcap-namedb.h,v 1.5 1997/10/03 15:53:14 christos Exp $ */ +/* $NetBSD: pcap-namedb.h,v 1.6 1999/07/02 10:05:22 itojun Exp $ */ /* * Copyright (c) 1994, 1996 @@ -57,6 +57,9 @@ u_char *pcap_ether_hostton(const char*); u_char *pcap_ether_aton(const char *); bpf_u_int32 **pcap_nametoaddr(const char *); +#ifdef INET6 +struct addrinfo *pcap_nametoaddrinfo(const char *); +#endif bpf_u_int32 pcap_nametonetaddr(const char *); int pcap_nametoport(const char *, int *, int *); diff --git a/lib/libpcap/scanner.l b/lib/libpcap/scanner.l index 17066ae4334..74f528e3818 100644 --- a/lib/libpcap/scanner.l +++ b/lib/libpcap/scanner.l @@ -1,5 +1,5 @@ %{ -/* $NetBSD: scanner.l,v 1.6 1999/03/22 09:15:10 ross Exp $ */ +/* $NetBSD: scanner.l,v 1.7 1999/07/02 10:05:22 itojun Exp $ */ /* * Copyright (c) 1988, 1989, 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1997 @@ -28,7 +28,7 @@ static const char rcsid[] = "@(#) Header: scanner.l,v 1.56 97/07/21 13:31:50 leres Exp (LBL)"; #else -__RCSID("$NetBSD: scanner.l,v 1.6 1999/03/22 09:15:10 ross Exp $"); +__RCSID("$NetBSD: scanner.l,v 1.7 1999/07/02 10:05:22 itojun Exp $"); #endif #endif @@ -42,6 +42,10 @@ __RCSID("$NetBSD: scanner.l,v 1.6 1999/03/22 09:15:10 ross Exp $"); #include "gencode.h" #include <pcap-namedb.h> +#ifdef INET6 +#include <netdb.h> +#include <sys/socket.h> +#endif /*INET6*/ #include "grammar.h" #include "gnuc.h" @@ -83,6 +87,7 @@ static char *in_buffer; N ([0-9]+|(0X|0x)[0-9A-Fa-f]+) B ([0-9A-Fa-f][0-9A-Fa-f]?) +W ([0-9A-Fa-f][0-9A-Fa-f]?[0-9A-Fa-f]?[0-9A-Fa-f]?) %a 3000 @@ -100,6 +105,12 @@ udp return UDP; icmp return ICMP; igmp return IGMP; igrp return IGRP; +pim return PIM; + +ip6 return IPV6; +icmp6 return ICMPV6; +ah return AH; +esp return ESP; atalk return ATALK; decnet return DECNET; @@ -113,6 +124,7 @@ net return NET; mask return MASK; port return PORT; proto return PROTO; +protochain return PROTOCHAIN; gateway return GATEWAY; @@ -143,8 +155,23 @@ outbound return OUTBOUND; yylval.s = sdup((char *)yytext); return HID; } {B}:{B}:{B}:{B}:{B}:{B} { yylval.e = pcap_ether_aton((char *)yytext); return EID; } +[0-9a-zA-Z:]*:[0-9a-zA-Z:]*(:{N}\.{N}\.{N}\.{N})? { +#ifdef INET6 + struct addrinfo hints, *res; + memset(&hints, 0, sizeof(hints)); + hints.ai_family = AF_INET6; + hints.ai_flags = AI_NUMERICHOST; + if (getaddrinfo(yytext, NULL, &hints, &res)) + bpf_error("bogus IPv6 address %s", yytext); + else { + yylval.e = sdup((char *)yytext); return HID6; + } +#else + bpf_error("IPv6 address %s not supported", yytext); +#endif /*INET6*/ + } {B}:+({B}:+)+ { bpf_error("bogus ethernet address %s", yytext); } -[A-Za-z0-9][-_.A-Za-z0-9]*[.A-Za-z0-9]|[A-Za-z] { +[A-Za-z0-9][-_.A-Za-z0-9]*[.A-Za-z0-9] { yylval.s = sdup((char *)yytext); return ID; } "\\"[^ !()\n\t]+ { yylval.s = sdup((char *)yytext + 1); return ID; } [^ \[\]\t\n\-_.A-Za-z0-9!<>()&|=]+i { |
