summaryrefslogtreecommitdiff
path: root/lib
diff options
context:
space:
mode:
authoritojun <itojun@NetBSD.org>1999-07-02 10:05:22 +0000
committeritojun <itojun@NetBSD.org>1999-07-02 10:05:22 +0000
commitc6f88a42f468b45ffa052d50fe70acc86b98a5c4 (patch)
treeb02c54482a4b6d0989d999d980eb279c963419a8 /lib
parent22b07aaafdf84686043596c4264b6d011a67b19d (diff)
support IPv6 address and IPv6 protocols.
"tcp" will match both IPv4 TCP and IPv6 TCP. "ip6" will match IPv6. you can chase header chain by using "protochain" instead of "proto" (but bpf code is not optimizable in this case) commit to tcpdump will follow. I've sent this fix to LBL guys to get no response. I wonder why it was.
Diffstat (limited to 'lib')
-rw-r--r--lib/libpcap/Makefile3
-rw-r--r--lib/libpcap/gencode.c825
-rw-r--r--lib/libpcap/gencode.h22
-rw-r--r--lib/libpcap/grammar.y37
-rw-r--r--lib/libpcap/nametoaddr.c32
-rw-r--r--lib/libpcap/optimize.c93
-rw-r--r--lib/libpcap/pcap-bpf.c13
-rw-r--r--lib/libpcap/pcap-namedb.h5
-rw-r--r--lib/libpcap/scanner.l33
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 {