From a9b0695f23eb897f3321236f6dd3b42a49f08bdd Mon Sep 17 00:00:00 2001 From: jakob Date: Wed, 26 Apr 2000 21:25:52 +0000 Subject: [PATCH] sync with libpcap v0.5 add support for INET6 (kame) --- lib/libpcap/CHANGES | 10 +- lib/libpcap/Makefile | 5 +- lib/libpcap/README | 22 +- lib/libpcap/VERSION | 2 +- lib/libpcap/bpf_image.c | 8 +- lib/libpcap/ethertype.h | 7 +- lib/libpcap/gencode.c | 1021 ++++++++++++++++++++++++++++++++++++- lib/libpcap/gencode.h | 23 +- lib/libpcap/grammar.y | 39 +- lib/libpcap/inet.c | 59 +-- lib/libpcap/nametoaddr.c | 41 +- lib/libpcap/optimize.c | 90 +++- lib/libpcap/pcap-bpf.c | 15 +- lib/libpcap/pcap-int.h | 25 +- lib/libpcap/pcap-namedb.h | 7 +- lib/libpcap/pcap.3 | 2 +- lib/libpcap/pcap.h | 6 +- lib/libpcap/ppp.h | 6 +- lib/libpcap/scanner.l | 124 ++++- 19 files changed, 1405 insertions(+), 107 deletions(-) diff --git a/lib/libpcap/CHANGES b/lib/libpcap/CHANGES index 6cc6c085882..71bbb7532b0 100644 --- a/lib/libpcap/CHANGES +++ b/lib/libpcap/CHANGES @@ -1,6 +1,12 @@ -$OpenBSD: CHANGES,v 1.5 1999/07/20 04:49:54 deraadt Exp $ +$OpenBSD: CHANGES,v 1.6 2000/04/26 21:25:52 jakob Exp $ $NetBSD: CHANGES,v 1.2 1995/03/06 11:37:58 mycroft Exp $ -@(#) $Header: /home/cvs/src/lib/libpcap/CHANGES,v 1.5 1999/07/20 04:49:54 deraadt Exp $ (LBL) +@(#) $Header: /home/cvs/src/lib/libpcap/CHANGES,v 1.6 2000/04/26 21:25:52 jakob Exp $ (LBL) + +Sun Oct 19 JST 1999 itojun@iijlab.net + * bring in KAME IPv6/IPsec bpf compiler. + +Sometime in 1999 + * tcpdump.org imported LBL 0.4 v0.4 Sat Jul 25 12:40:09 PDT 1998 diff --git a/lib/libpcap/Makefile b/lib/libpcap/Makefile index 8b12773dd95..3780688b51a 100644 --- a/lib/libpcap/Makefile +++ b/lib/libpcap/Makefile @@ -1,4 +1,4 @@ -# $OpenBSD: Makefile,v 1.12 2000/04/13 05:55:19 itojun Exp $ +# $OpenBSD: Makefile,v 1.13 2000/04/26 21:25:52 jakob Exp $ # $NetBSD: Makefile,v 1.3 1996/05/10 21:54:24 cgd Exp $ LIB= pcap @@ -15,7 +15,8 @@ MLINKS= pcap.3 pcap_open_live.3 pcap.3 pcap_open_offline.3 \ pcap.3 pcap_close.3 pcap.3 pcap_dump_close.3 DEFS= -DHAVE_SYS_IOCCOM_H -DHAVE_SYS_SOCKIO_H -DHAVE_ETHER_HOSTTON \ - -DHAVE_STRERROR -DHAVE_SOCKADDR_SA_LEN -DLBL_ALIGN -DHAVE_IFADDRS_H + -DHAVE_STRERROR -DHAVE_SOCKADDR_SA_LEN -DLBL_ALIGN -DHAVE_IFADDRS_H \ + -DINET6 CFLAGS+=-I. -I${.CURDIR} -Dyylval=pcap_yylval ${DEFS} diff --git a/lib/libpcap/README b/lib/libpcap/README index 9b5f897383e..d6f68110140 100644 --- a/lib/libpcap/README +++ b/lib/libpcap/README @@ -1,12 +1,15 @@ -$OpenBSD: README,v 1.5 1999/07/20 04:49:54 deraadt Exp $ +$OpenBSD: README,v 1.6 2000/04/26 21:25:52 jakob Exp $ $NetBSD: README,v 1.2 1995/03/06 11:38:07 mycroft Exp $ -@(#) $Header: /home/cvs/src/lib/libpcap/README,v 1.5 1999/07/20 04:49:54 deraadt Exp $ (LBL) +@(#) $Header: /home/cvs/src/lib/libpcap/README,v 1.6 2000/04/26 21:25:52 jakob Exp $ (LBL) -LIBPCAP 0.4 -Lawrence Berkeley National Laboratory -Network Research Group -libpcap@ee.lbl.gov -ftp://ftp.ee.lbl.gov/libpcap.tar.Z +LIBPCAP 0.5 +Now maintained by "The Tcpdump Group" +Send patches to patches@tcpdump.org +See www.tcpdump.org + +formerly from Lawrence Berkeley National Laboratory + Network Research Group + ftp://ftp.ee.lbl.gov/libpcap.tar.Z (0.4) This directory contains source code for libpcap, a system-independent interface for user-level packet capture. libpcap provides a portable @@ -44,8 +47,5 @@ to Ultrix using the kernel source and/or object patches available in: Problems, bugs, questions, desirable enhancements, source code contributions, etc., should be sent to the email address -"libpcap@ee.lbl.gov". +"patches@tcpdump.org". - - Steve McCanne - Craig Leres - Van Jacobson diff --git a/lib/libpcap/VERSION b/lib/libpcap/VERSION index bd73f47072b..2eb3c4fe4ee 100644 --- a/lib/libpcap/VERSION +++ b/lib/libpcap/VERSION @@ -1 +1 @@ -0.4 +0.5 diff --git a/lib/libpcap/bpf_image.c b/lib/libpcap/bpf_image.c index 125197f2927..e5b75af985a 100644 --- a/lib/libpcap/bpf_image.c +++ b/lib/libpcap/bpf_image.c @@ -1,4 +1,4 @@ -/* $OpenBSD: bpf_image.c,v 1.7 1999/07/20 04:49:54 deraadt Exp $ */ +/* $OpenBSD: bpf_image.c,v 1.8 2000/04/26 21:25:52 jakob Exp $ */ /* * Copyright (c) 1990, 1991, 1992, 1994, 1995, 1996 @@ -23,7 +23,7 @@ #ifndef lint static const char rcsid[] = - "@(#) $Header: /home/cvs/src/lib/libpcap/bpf_image.c,v 1.7 1999/07/20 04:49:54 deraadt Exp $ (LBL)"; + "@(#) $Header: /home/cvs/src/lib/libpcap/bpf_image.c,v 1.8 2000/04/26 21:25:52 jakob Exp $ (LBL)"; #endif #include @@ -245,12 +245,12 @@ bpf_image(p, n) case BPF_ALU|BPF_AND|BPF_K: op = "and"; - fmt = "#%d"; + fmt = "#0x%x"; break; case BPF_ALU|BPF_OR|BPF_K: op = "or"; - fmt = "#%d"; + fmt = "#0x%x"; break; case BPF_ALU|BPF_LSH|BPF_K: diff --git a/lib/libpcap/ethertype.h b/lib/libpcap/ethertype.h index 45cc420c8b6..5f5c70370a3 100644 --- a/lib/libpcap/ethertype.h +++ b/lib/libpcap/ethertype.h @@ -1,4 +1,4 @@ -/* $OpenBSD: ethertype.h,v 1.5 1999/07/20 04:49:54 deraadt Exp $ */ +/* $OpenBSD: ethertype.h,v 1.6 2000/04/26 21:25:52 jakob Exp $ */ /* $NetBSD: ethertype.h,v 1.2 1995/03/06 11:38:17 mycroft Exp $ */ /* @@ -21,7 +21,7 @@ * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. * - * @(#) $Header: /home/cvs/src/lib/libpcap/ethertype.h,v 1.5 1999/07/20 04:49:54 deraadt Exp $ (LBL) + * @(#) $Header: /home/cvs/src/lib/libpcap/ethertype.h,v 1.6 2000/04/26 21:25:52 jakob Exp $ (LBL) */ /* Types missing from some systems */ @@ -74,6 +74,9 @@ #ifndef ETHERTYPE_AARP #define ETHERTYPE_AARP 0x80f3 #endif +#ifndef ETHERTYPE_IPV6 +#define ETHERTYPE_IPV6 0x80f3 +#endif #ifndef ETHERTYPE_LOOPBACK #define ETHERTYPE_LOOPBACK 0x9000 #endif diff --git a/lib/libpcap/gencode.c b/lib/libpcap/gencode.c index c129c977340..827a7105d36 100644 --- a/lib/libpcap/gencode.c +++ b/lib/libpcap/gencode.c @@ -1,4 +1,4 @@ -/* $OpenBSD: gencode.c,v 1.11 1999/07/20 04:49:54 deraadt Exp $ */ +/* $OpenBSD: gencode.c,v 1.12 2000/04/26 21:25:52 jakob Exp $ */ /* * Copyright (c) 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1997, 1998 @@ -22,7 +22,7 @@ */ #ifndef lint static const char rcsid[] = - "@(#) $Header: /home/cvs/src/lib/libpcap/gencode.c,v 1.11 1999/07/20 04:49:54 deraadt Exp $ (LBL)"; + "@(#) $Header: /home/cvs/src/lib/libpcap/gencode.c,v 1.12 2000/04/26 21:25:52 jakob Exp $ (LBL)"; #endif #include @@ -38,6 +38,7 @@ struct rtentry; #include #include +#include #include #include @@ -54,6 +55,10 @@ struct rtentry; #include "gencode.h" #include "ppp.h" #include +#ifdef INET6 +#include +#include +#endif /*INET6*/ #ifdef HAVE_OS_PROTO_H #include "os-proto.h" @@ -137,16 +142,33 @@ 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_ahostop(const u_char *, int); 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 +#ifndef INET6 static struct block *gen_gateway(const u_char *, bpf_u_int32 **, int, int); +#endif 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_protochain(int, int, int); static struct block *gen_proto(int, int, int); static struct slist *xfer_to_x(struct arth *); static struct slist *xfer_to_a(struct arth *); @@ -159,8 +181,8 @@ newchunk(n) struct chunk *cp; int k, size; - /* XXX Round up to nearest long. */ - n = (n + sizeof(long) - 1) & ~(sizeof(long) - 1); + /* XXX Round to structure boundary. */ + n = ALIGN(n); cp = &chunks[cur_chunk]; if (n > cp->n_left) { @@ -248,6 +270,7 @@ syntax() static bpf_u_int32 netmask; static int snaplen; +int no_optimize; int pcap_compile(pcap_t *p, struct bpf_program *program, @@ -256,6 +279,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; @@ -277,6 +301,54 @@ pcap_compile(pcap_t *p, struct bpf_program *program, if (root == NULL) root = gen_retblk(snaplen); + if (optimize && !no_optimize) { + bpf_optimize(&root); + if (root == NULL || + (root->s.code == (BPF_RET|BPF_K) && root->s.k == 0)) + bpf_error("expression rejects all packets"); + } + program->bf_insns = icode_to_fcode(root, &len); + program->bf_len = len; + + freechunks(); + return (0); +} + +/* + * entry point for using the compiler with no pcap open + * pass in all the stuff that is needed explicitly instead. + */ +int +pcap_compile_nopcap(int snaplen_arg, int linktype_arg, + struct bpf_program *program, + char *buf, int optimize, bpf_u_int32 mask) +{ + extern int n_errors; + int len; + + n_errors = 0; + root = NULL; + bpf_pcap = NULL; + if (setjmp(top_ctx)) { + freechunks(); + return (-1); + } + + netmask = mask; + + /* XXX needed? I don't grok the use of globals here. */ + snaplen = snaplen_arg; + + lex_init(buf ? buf : ""); + init_linktype(linktype_arg); + (void)pcap_parse(); + + if (n_errors) + syntax(); + + if (root == NULL) + root = gen_retblk(snaplen_arg); + if (optimize) { bpf_optimize(&root); if (root == NULL || @@ -462,6 +534,11 @@ init_linktype(type) switch (type) { + case DLT_ARCNET: + off_linktype = 2; + off_nl = 6; /* XXX in reality, variable! */ + return; + case DLT_EN10MB: off_linktype = 12; off_nl = 14; @@ -583,6 +660,11 @@ gen_linktype(proto) /* If we're not using encapsulation and checking for IP, we're done */ if (off_linktype == -1 && proto == ETHERTYPE_IP) return gen_true(); +#ifdef INET6 + /* this isn't the right thing to do, but sometimes necessary */ + if (off_linktype == -1 && proto == ETHERTYPE_IPV6) + return gen_true(); +#endif switch (linktype) { @@ -592,6 +674,10 @@ gen_linktype(proto) case DLT_PPP: if (proto == ETHERTYPE_IP) proto = PPP_IP; /* XXX was 0x21 */ +#ifdef INET6 + else if (proto == ETHERTYPE_IPV6) + proto = PPP_IPV6; +#endif break; case DLT_PPP_BSDOS: @@ -605,6 +691,13 @@ gen_linktype(proto) gen_or(b1, b0); return b0; +#ifdef INET6 + case ETHERTYPE_IPV6: + proto = PPP_IPV6; + /* more to go? */ + break; +#endif /* INET6 */ + case ETHERTYPE_DN: proto = PPP_DECNET; break; @@ -625,8 +718,45 @@ gen_linktype(proto) /* XXX */ if (proto == ETHERTYPE_IP) return (gen_cmp(0, BPF_W, (bpf_int32)htonl(AF_INET))); +#ifdef INET6 + else if (proto == ETHERTYPE_IPV6) + return (gen_cmp(0, BPF_W, (bpf_int32)htonl(AF_INET6))); +#endif /* INET6 */ else return gen_false(); + break; + case DLT_ARCNET: + /* + * XXX should we check for first fragment if the protocol + * uses PHDS? + */ + switch(proto) { + default: + return gen_false(); +#ifdef INET6 + case ETHERTYPE_IPV6: + return(gen_cmp(2, BPF_B, + (bpf_int32)htonl(ARCTYPE_INET6))); +#endif /* INET6 */ + case ETHERTYPE_IP: + b0 = gen_cmp(2, BPF_B, (bpf_int32)htonl(ARCTYPE_IP)); + b1 = gen_cmp(2, BPF_B, + (bpf_int32)htonl(ARCTYPE_IP_OLD)); + gen_or(b0, b1); + return(b1); + case ETHERTYPE_ARP: + b0 = gen_cmp(2, BPF_B, (bpf_int32)htonl(ARCTYPE_ARP)); + b1 = gen_cmp(2, BPF_B, + (bpf_int32)htonl(ARCTYPE_ARP_OLD)); + gen_or(b0, b1); + return(b1); + case ETHERTYPE_REVARP: + return(gen_cmp(2, BPF_B, + (bpf_int32)htonl(ARCTYPE_REVARP))); + case ETHERTYPE_ATALK: + return(gen_cmp(2, BPF_B, + (bpf_int32)htonl(ARCTYPE_ATALK))); + } } return gen_cmp(off_linktype, BPF_H, (bpf_int32)proto); } @@ -673,12 +803,66 @@ 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; + u_int32_t *a, *m; + + 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 */ + a = (u_int32_t *)addr; + m = (u_int32_t *)mask; + b1 = gen_mcmp(offset + 12, BPF_W, ntohl(a[3]), ntohl(m[3])); + b0 = gen_mcmp(offset + 8, BPF_W, ntohl(a[2]), ntohl(m[2])); + gen_and(b0, b1); + b0 = gen_mcmp(offset + 4, BPF_W, ntohl(a[1]), ntohl(m[1])); + gen_and(b0, b1); + b0 = gen_mcmp(offset + 0, BPF_W, ntohl(a[0]), ntohl(m[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; register int dir; { - register struct block *b0, *b1; + struct block *b0, *b1; switch (dir) { case Q_SRC: @@ -880,6 +1064,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"); @@ -898,12 +1085,105 @@ 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*/ + +#ifndef INET6 static struct block * gen_gateway(eaddr, alist, proto, dir) const u_char *eaddr; @@ -942,46 +1222,61 @@ gen_gateway(eaddr, alist, proto, dir) bpf_error("illegal modifier of 'gateway'"); /* NOTREACHED */ } +#endif /*INET6*/ struct block * gen_proto_abbrev(proto) int proto; { - struct block *b0, *b1; + struct block *b0 = NULL, *b1; 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; +#ifndef IPPROTO_IGMP +#define IPPROTO_IGMP 2 +#endif + 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(IPPROTO_IGMP, 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); - gen_and(b0, b1); + b1 = gen_proto(IPPROTO_IGRP, Q_IP, Q_DEFAULT); + break; + +#ifndef IPPROTO_PIM +#define IPPROTO_PIM 103 +#endif + + 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: @@ -1023,6 +1318,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(); } @@ -1067,6 +1397,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; @@ -1138,6 +1478,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; @@ -1168,6 +1579,298 @@ lookup_proto(name, proto) return v; } +static 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_IPV6, 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; @@ -1181,9 +1884,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; @@ -1242,6 +1957,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 */ @@ -1258,7 +1998,16 @@ gen_scode(name, q) int dir = q.dir; int tproto; u_char *eaddr; - bpf_u_int32 mask, addr, **alist; + bpf_u_int32 mask, addr; +#ifndef INET6 + bpf_u_int32 **alist; +#else + 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; @@ -1308,6 +2057,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); @@ -1322,6 +2072,51 @@ 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; + } + for (res = res0; res; res = res->ai_next) { + switch (res->ai_family) { + case AF_INET: + if (tproto == Q_IPV6) + continue; + + sin = (struct sockaddr_in *) + res->ai_addr; + tmp = gen_host(ntohl(sin->sin_addr.s_addr), + 0xffffffff, tproto, dir); + break; + case AF_INET6: + if (tproto6 == Q_IP) + continue; + + 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; + } + freeaddrinfo(res0); + if (b == NULL) { + bpf_error("unknown host '%s'%s", name, + (proto == Q_DEFAULT) + ? "" + : " for specified address family"); + } + return b; +#endif /*INET6*/ } case Q_PORT: @@ -1343,9 +2138,19 @@ 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: +#ifndef INET6 eaddr = pcap_ether_hostton(name); if (eaddr == NULL) bpf_error("unknown ether host: %s", name); @@ -1354,6 +2159,9 @@ gen_scode(name, q) if (alist == NULL || *alist == NULL) bpf_error("unknown host '%s'", name); return gen_gateway(eaddr, alist, proto, dir); +#else + bpf_error("'gateway' not supported in this configuration"); +#endif /*INET6*/ case Q_PROTO: real_proto = lookup_proto(name, proto); @@ -1362,6 +2170,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 */ @@ -1464,7 +2280,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"); @@ -1473,6 +2298,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 */ @@ -1484,6 +2312,64 @@ 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; + u_int32_t *a, *m; + + 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 <= %u", (unsigned int)(sizeof(mask) * 8)); + memset(&mask, 0xff, masklen / 8); + if (masklen % 8) { + mask.s6_addr[masklen / 8] = + (0xff << (8 - masklen % 8)) & 0xff; + } + + a = (u_int32_t *)addr; + m = (u_int32_t *)&mask; + if ((a[0] & ~m[0]) || (a[1] & ~m[1]) + || (a[2] & ~m[2]) || (a[3] & ~m[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; @@ -1582,7 +2468,10 @@ gen_load(proto, index, size) case Q_LAT: case Q_MOPRC: case Q_MOPDL: - /* XXX Note that we assume a fixed link link header here. */ +#ifdef INET6 + case Q_IPV6: +#endif + /* XXX Note that we assume a fixed link header here. */ s = xfer_to_x(index); tmp = new_stmt(BPF_LD|BPF_IND|size); tmp->s.k = off_nl; @@ -1600,6 +2489,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)); @@ -1612,8 +2502,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); @@ -1863,6 +2761,8 @@ gen_byteop(op, idx, val) return b; } +static u_char abroadcast[] = { 0x0 }; + struct block * gen_broadcast(proto) int proto; @@ -1875,6 +2775,8 @@ gen_broadcast(proto) case Q_DEFAULT: case Q_LINK: + if (linktype == DLT_ARCNET) + return gen_ahostop(abroadcast, Q_DST); if (linktype == DLT_EN10MB) return gen_ehostop(ebroadcast, Q_DST); if (linktype == DLT_FDDI) @@ -1906,6 +2808,10 @@ gen_multicast(proto) case Q_DEFAULT: case Q_LINK: + if (linktype == DLT_ARCNET) + /* all ARCnet multicasts use the same address */ + return gen_ahostop(abroadcast, Q_DST); + if (linktype == DLT_EN10MB) { /* ether[0] & 1 != 0 */ s = new_stmt(BPF_LD|BPF_B|BPF_ABS); @@ -1935,6 +2841,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"); } @@ -1950,9 +2864,70 @@ gen_inbound(dir) { register struct block *b0; + /* + * Only SLIP and old-style PPP data link types support + * inbound/outbound qualifiers. + */ + switch (linktype) { + case DLT_SLIP: + case DLT_PPP: + /* These are okay. */ + break; + + default: + bpf_error("inbound/outbound not supported on linktype 0x%x\n", + linktype); + /* NOTREACHED */ + } + b0 = gen_relation(BPF_JEQ, gen_load(Q_LINK, gen_loadi(0), 1), gen_loadi(0), dir); return (b0); } + +struct block * +gen_acode(eaddr, q) + register const u_char *eaddr; + struct qual q; +{ + if ((q.addr == Q_HOST || q.addr == Q_DEFAULT) && q.proto == Q_LINK) { + if (linktype == DLT_ARCNET) + return gen_ahostop(eaddr, (int)q.dir); + } + bpf_error("ARCnet address used in non-arc expression"); + /* NOTREACHED */ +} + +static struct block * +gen_ahostop(eaddr, dir) + register const u_char *eaddr; + register int dir; +{ + register struct block *b0, *b1; + + switch (dir) { + /* src comes first, different from Ethernet */ + case Q_SRC: + return gen_bcmp(0, 1, eaddr); + + case Q_DST: + return gen_bcmp(1, 1, eaddr); + + case Q_AND: + b0 = gen_ahostop(eaddr, Q_SRC); + b1 = gen_ahostop(eaddr, Q_DST); + gen_and(b0, b1); + return b1; + + case Q_DEFAULT: + case Q_OR: + b0 = gen_ahostop(eaddr, Q_SRC); + b1 = gen_ahostop(eaddr, Q_DST); + gen_or(b0, b1); + return b1; + } + abort(); + /* NOTREACHED */ +} diff --git a/lib/libpcap/gencode.h b/lib/libpcap/gencode.h index 32bb1af7828..a3479c5d3bb 100644 --- a/lib/libpcap/gencode.h +++ b/lib/libpcap/gencode.h @@ -1,4 +1,4 @@ -/* $OpenBSD: gencode.h,v 1.6 1999/07/20 04:49:54 deraadt Exp $ */ +/* $OpenBSD: gencode.h,v 1.7 2000/04/26 21:25:52 jakob Exp $ */ /* * Copyright (c) 1990, 1991, 1992, 1993, 1994, 1995, 1996 @@ -20,7 +20,7 @@ * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. * - * @(#) $Header: /home/cvs/src/lib/libpcap/gencode.h,v 1.6 1999/07/20 04:49:54 deraadt Exp $ (LBL) + * @(#) $Header: /home/cvs/src/lib/libpcap/gencode.h,v 1.7 2000/04/26 21:25:52 jakob Exp $ (LBL) */ /* Address qualifiers. */ @@ -30,6 +30,7 @@ #define Q_PORT 3 #define Q_GATEWAY 4 #define Q_PROTO 5 +#define Q_PROTOCHAIN 6 /* Protocol qualifiers. */ @@ -51,6 +52,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 @@ -61,8 +70,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; }; @@ -148,7 +161,11 @@ void gen_not(struct block *); struct block *gen_scode(const char *, struct qual); struct block *gen_ecode(const u_char *, struct qual); +struct block *gen_acode(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); @@ -176,3 +193,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 0108ff68711..2c9b57f5c5f 100644 --- a/lib/libpcap/grammar.y +++ b/lib/libpcap/grammar.y @@ -1,5 +1,5 @@ %{ -/* $OpenBSD: grammar.y,v 1.6 1999/07/20 04:49:54 deraadt Exp $ */ +/* $OpenBSD: grammar.y,v 1.7 2000/04/26 21:25:53 jakob Exp $ */ /* * Copyright (c) 1988, 1989, 1990, 1991, 1992, 1993, 1994, 1995, 1996 @@ -24,7 +24,7 @@ */ #ifndef lint static const char rcsid[] = - "@(#) $Header: /home/cvs/src/lib/libpcap/grammar.y,v 1.6 1999/07/20 04:49:54 deraadt Exp $ (LBL)"; + "@(#) $Header: /home/cvs/src/lib/libpcap/grammar.y,v 1.7 2000/04/26 21:25:53 jakob Exp $ (LBL)"; #endif #include @@ -103,20 +103,22 @@ pcap_parse() %type 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 AID %token LSH RSH %token LEN +%token IPV6 ICMPV6 AH ESP %type ID %type EID -%type HID +%type AID +%type HID HID6 %type NUM %left OR AND @@ -168,7 +170,26 @@ nid: ID { $$.b = gen_scode($1, $$.q = $0.q); } break; } } + | HID6 '/' NUM { +#ifdef INET6 + $$.b = gen_mcode6($1, NULL, $3, + $$.q = $0.q); +#else + bpf_error("'ip6addr/prefixlen' not supported " + "in this configuration"); +#endif /*INET6*/ + } + | HID6 { +#ifdef INET6 + $$.b = gen_mcode6($1, 0, 128, + $$.q = $0.q); +#else + bpf_error("'ip6addr' not supported " + "in this configuration"); +#endif /*INET6*/ + } | EID { $$.b = gen_ecode($1, $$.q = $0.q); } + | AID { $$.b = gen_acode($1, $$.q = $0.q); } | not id { gen_not($2.b); $$ = $2; } ; not: '!' { $$ = $0; } @@ -190,6 +211,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; } @@ -230,12 +252,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/inet.c b/lib/libpcap/inet.c index 2f8ef172fa7..f4fa5035fa5 100644 --- a/lib/libpcap/inet.c +++ b/lib/libpcap/inet.c @@ -1,4 +1,4 @@ -/* $OpenBSD: inet.c,v 1.12 2000/04/13 05:55:19 itojun Exp $ */ +/* $OpenBSD: inet.c,v 1.13 2000/04/26 21:25:53 jakob Exp $ */ /* * Copyright (c) 1994, 1995, 1996, 1997, 1998 @@ -35,7 +35,7 @@ #ifndef lint static const char rcsid[] = - "@(#) $Header: /home/cvs/src/lib/libpcap/inet.c,v 1.12 2000/04/13 05:55:19 itojun Exp $ (LBL)"; + "@(#) $Header: /home/cvs/src/lib/libpcap/inet.c,v 1.13 2000/04/26 21:25:53 jakob Exp $ (LBL)"; #endif #include @@ -137,12 +137,11 @@ pcap_lookupdev(errbuf) return (device); #else register int fd, minunit, n; - register char *cp, *ibuf = NULL, *nibuf; + register char *cp; register struct ifreq *ifrp, *ifend, *ifnext, *mp; struct ifconf ifc; - struct ifreq ifr; + struct ifreq ibuf[16], ifr; static char device[sizeof(ifrp->ifr_name) + 1]; - int len = 8192; fd = socket(AF_INET, SOCK_DGRAM, 0); if (fd < 0) { @@ -150,33 +149,24 @@ pcap_lookupdev(errbuf) pcap_strerror(errno)); return (NULL); } - while (1) { - ifc.ifc_len = len; - nibuf = realloc(ibuf, len); - if (nibuf == NULL) { - if (ibuf) - free(ibuf); - close(fd); - return (NULL); - } - ifc.ifc_buf = ibuf = nibuf; - if (ioctl(fd, SIOCGIFCONF, (char *)&ifc) < 0) { - (void)close(fd); - free(ibuf); - return (NULL); - } - if (ifc.ifc_len + sizeof(ifr) < len) - break; - len *= 2; - } + ifc.ifc_len = sizeof ibuf; + ifc.ifc_buf = (caddr_t)ibuf; - ifrp = (struct ifreq *)ibuf; + memset((char *)ibuf, 0, sizeof(ibuf)); + if (ioctl(fd, SIOCGIFCONF, (char *)&ifc) < 0 || + ifc.ifc_len < sizeof(struct ifreq)) { + (void)snprintf(errbuf, PCAP_ERRBUF_SIZE, "SIOCGIFCONF: %s", + pcap_strerror(errno)); + (void)close(fd); + return (NULL); + } + ifrp = ibuf; ifend = (struct ifreq *)((char *)ibuf + ifc.ifc_len); mp = NULL; minunit = 666; for (; ifrp < ifend; ifrp = ifnext) { -#if BSD - 0 >= 199006 +#ifdef HAVE_SOCKADDR_SA_LEN n = ifrp->ifr_addr.sa_len + sizeof(ifrp->ifr_name); if (n < sizeof(*ifrp)) ifnext = ifrp + 1; @@ -202,7 +192,6 @@ pcap_lookupdev(errbuf) (int)sizeof(ifr.ifr_name), ifr.ifr_name, pcap_strerror(errno)); (void)close(fd); - free(ibuf); return (NULL); } @@ -222,13 +211,11 @@ pcap_lookupdev(errbuf) if (mp == NULL) { (void)strlcpy(errbuf, "no suitable device found", PCAP_ERRBUF_SIZE); - free(ibuf); return (NULL); } (void)strncpy(device, mp->ifr_name, sizeof(device) - 1); device[sizeof(device) - 1] = '\0'; - free(ibuf); return (device); #endif } @@ -256,16 +243,22 @@ pcap_lookupnet(device, netp, maskp, errbuf) #endif (void)strncpy(ifr.ifr_name, device, sizeof(ifr.ifr_name)); if (ioctl(fd, SIOCGIFADDR, (char *)&ifr) < 0) { - (void)snprintf(errbuf, PCAP_ERRBUF_SIZE, "SIOCGIFADDR: %s: %s", - device, pcap_strerror(errno)); + if (errno == EADDRNOTAVAIL) { + (void)snprintf(errbuf, PCAP_ERRBUF_SIZE, + "%s: no IPv4 address assigned", device); + } else { + (void)snprintf(errbuf, PCAP_ERRBUF_SIZE, + "SIOCGIFADDR: %s: %s", + device, pcap_strerror(errno)); + } (void)close(fd); return (-1); } sin = (struct sockaddr_in *)&ifr.ifr_addr; *netp = sin->sin_addr.s_addr; if (ioctl(fd, SIOCGIFNETMASK, (char *)&ifr) < 0) { - (void)snprintf(errbuf, PCAP_ERRBUF_SIZE, "SIOCGIFNETMASK: %s: %s", - device, pcap_strerror(errno)); + (void)snprintf(errbuf, PCAP_ERRBUF_SIZE, + "SIOCGIFNETMASK: %s: %s", device, pcap_strerror(errno)); (void)close(fd); return (-1); } diff --git a/lib/libpcap/nametoaddr.c b/lib/libpcap/nametoaddr.c index aae19a44871..ab7162536f5 100644 --- a/lib/libpcap/nametoaddr.c +++ b/lib/libpcap/nametoaddr.c @@ -1,4 +1,4 @@ -/* $OpenBSD: nametoaddr.c,v 1.7 1999/07/20 04:49:55 deraadt Exp $ */ +/* $OpenBSD: nametoaddr.c,v 1.8 2000/04/26 21:25:53 jakob Exp $ */ /* * Copyright (c) 1990, 1991, 1992, 1993, 1994, 1995, 1996 @@ -26,7 +26,7 @@ #ifndef lint static const char rcsid[] = - "@(#) $Header: /home/cvs/src/lib/libpcap/nametoaddr.c,v 1.7 1999/07/20 04:49:55 deraadt Exp $ (LBL)"; + "@(#) $Header: /home/cvs/src/lib/libpcap/nametoaddr.c,v 1.8 2000/04/26 21:25:53 jakob Exp $ (LBL)"; #endif #include @@ -43,6 +43,10 @@ struct rtentry; #include #include #include +#ifdef INET6 +#include +#include +#endif /*INET6*/ #include #include @@ -95,6 +99,24 @@ 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; + hints.ai_socktype = SOCK_STREAM; /*not really*/ + 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. @@ -186,6 +208,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 }, @@ -331,7 +356,7 @@ pcap_ether_hostton(const char *name) } #else -#ifndef sgi +#if !defined(sgi) && !defined(__NetBSD__) extern int ether_hostton(char *, struct ether_addr *); #endif @@ -369,8 +394,16 @@ __pcap_nametodnaddr(const char *name) #else bpf_error("decnet name support not included, '%s' cannot be translated\n", name); + /* NOTREACHED */ #ifdef lint - return 0; + /* + * Arguably, lint should assume that functions which don't return + * (i.e. that contain no return statements and whose ends are + * unreachable) actually return a value, so callers won't get + * warnings for using that value (since they won't actually + * be doing so). However, most lints don't seem to do that... + */ + return (0); #endif #endif } diff --git a/lib/libpcap/optimize.c b/lib/libpcap/optimize.c index a5df40531e7..48947490170 100644 --- a/lib/libpcap/optimize.c +++ b/lib/libpcap/optimize.c @@ -1,4 +1,4 @@ -/* $OpenBSD: optimize.c,v 1.6 1999/07/20 04:49:55 deraadt Exp $ */ +/* $OpenBSD: optimize.c,v 1.7 2000/04/26 21:25:53 jakob Exp $ */ /* * Copyright (c) 1988, 1989, 1990, 1991, 1993, 1994, 1995, 1996 @@ -24,7 +24,7 @@ */ #ifndef lint static const char rcsid[] = - "@(#) $Header: /home/cvs/src/lib/libpcap/optimize.c,v 1.6 1999/07/20 04:49:55 deraadt Exp $ (LBL)"; + "@(#) $Header: /home/cvs/src/lib/libpcap/optimize.c,v 1.7 2000/04/26 21:25:53 jakob Exp $ (LBL)"; #endif #include @@ -1105,6 +1105,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. @@ -1887,6 +1895,7 @@ convert_code_r(p) int slen; u_int off; int extrajmps; /* number of extra jumps inserted */ + struct slist **offset = NULL; if (p == 0 || isMarked(p)) return (1); @@ -1903,13 +1912,90 @@ convert_code_r(p) p->offset = dst - fstart; + /* generate offset[] for convenience */ + if (slen) { + 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; } + if (offset) + 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 ecd1ddb871b..f0b84e7c30f 100644 --- a/lib/libpcap/pcap-bpf.c +++ b/lib/libpcap/pcap-bpf.c @@ -1,4 +1,4 @@ -/* $OpenBSD: pcap-bpf.c,v 1.11 1999/08/17 09:13:13 millert Exp $ */ +/* $OpenBSD: pcap-bpf.c,v 1.12 2000/04/26 21:25:53 jakob Exp $ */ /* * Copyright (c) 1993, 1994, 1995, 1996, 1998 @@ -22,7 +22,7 @@ */ #ifndef lint static const char rcsid[] = - "@(#) $Header: /home/cvs/src/lib/libpcap/pcap-bpf.c,v 1.11 1999/08/17 09:13:13 millert Exp $ (LBL)"; + "@(#) $Header: /home/cvs/src/lib/libpcap/pcap-bpf.c,v 1.12 2000/04/26 21:25:53 jakob Exp $ (LBL)"; #endif #include /* optionally get BSD define */ @@ -48,6 +48,8 @@ static const char rcsid[] = #include "os-proto.h" #endif +#include "gencode.h" + int pcap_stats(pcap_t *p, struct pcap_stat *ps) { @@ -272,7 +274,14 @@ pcap_open_live(char *device, int snaplen, int promisc, int to_ms, char *ebuf) int pcap_setfilter(pcap_t *p, struct bpf_program *fp) { - if (p->sf.rfile != NULL) + /* + * 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; + else if (p->sf.rfile != NULL) p->fcode = *fp; else if (ioctl(p->fd, BIOCSETF, (caddr_t)fp) < 0) { snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "BIOCSETF: %s", diff --git a/lib/libpcap/pcap-int.h b/lib/libpcap/pcap-int.h index 47e20c93af5..d86910de128 100644 --- a/lib/libpcap/pcap-int.h +++ b/lib/libpcap/pcap-int.h @@ -1,4 +1,4 @@ -/* $OpenBSD: pcap-int.h,v 1.7 1999/07/20 04:49:55 deraadt Exp $ */ +/* $OpenBSD: pcap-int.h,v 1.8 2000/04/26 21:25:53 jakob Exp $ */ /* * Copyright (c) 1994, 1995, 1996 @@ -32,7 +32,7 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * @(#) $Header: /home/cvs/src/lib/libpcap/pcap-int.h,v 1.7 1999/07/20 04:49:55 deraadt Exp $ (LBL) + * @(#) $Header: /home/cvs/src/lib/libpcap/pcap-int.h,v 1.8 2000/04/26 21:25:53 jakob Exp $ (LBL) */ #ifndef pcap_int_h @@ -99,6 +99,27 @@ struct pcap { char errbuf[PCAP_ERRBUF_SIZE]; }; +/* + * This is a timeval as stored in disk in a dumpfile. + * It has to use the same types everywhere, independent of the actual + * `struct timeval' + */ + +struct pcap_timeval { + bpf_int32 tv_sec; /* seconds */ + bpf_int32 tv_usec; /* microseconds */ +}; + +/* + * How a `pcap_pkthdr' is actually stored in the dumpfile. + */ + +struct pcap_sf_pkthdr { + struct pcap_timeval ts; /* time stamp */ + bpf_u_int32 caplen; /* length of portion present */ + bpf_u_int32 len; /* length this packet (off wire) */ +}; + int yylex(void); #ifndef min diff --git a/lib/libpcap/pcap-namedb.h b/lib/libpcap/pcap-namedb.h index 12ee067380c..a25f66ac023 100644 --- a/lib/libpcap/pcap-namedb.h +++ b/lib/libpcap/pcap-namedb.h @@ -1,4 +1,4 @@ -/* $OpenBSD: pcap-namedb.h,v 1.5 1999/07/20 04:49:55 deraadt Exp $ */ +/* $OpenBSD: pcap-namedb.h,v 1.6 2000/04/26 21:25:53 jakob Exp $ */ /* * Copyright (c) 1994, 1996 @@ -32,7 +32,7 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * @(#) $Header: /home/cvs/src/lib/libpcap/pcap-namedb.h,v 1.5 1999/07/20 04:49:55 deraadt Exp $ (LBL) + * @(#) $Header: /home/cvs/src/lib/libpcap/pcap-namedb.h,v 1.6 2000/04/26 21:25:53 jakob Exp $ (LBL) */ #ifndef lib_pcap_ethers_h @@ -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/pcap.3 b/lib/libpcap/pcap.3 index fbcaa63be8c..662003d13ec 100644 --- a/lib/libpcap/pcap.3 +++ b/lib/libpcap/pcap.3 @@ -1,4 +1,4 @@ -.\" $NetBSD: pcap.3,v 1.2.6.1 1996/06/05 18:04:43 cgd Exp $ +.\" $OpenBSD: pcap.3,v 1.19 2000/04/26 21:25:53 jakob Exp $ .\" .\" Copyright (c) 1994, 1996, 1997 .\" The Regents of the University of California. All rights reserved. diff --git a/lib/libpcap/pcap.h b/lib/libpcap/pcap.h index 8465f63dde6..1d81843d512 100644 --- a/lib/libpcap/pcap.h +++ b/lib/libpcap/pcap.h @@ -1,4 +1,4 @@ -/* $OpenBSD: pcap.h,v 1.7 1999/07/20 04:49:55 deraadt Exp $ */ +/* $OpenBSD: pcap.h,v 1.8 2000/04/26 21:25:53 jakob Exp $ */ /* * Copyright (c) 1993, 1994, 1995, 1996, 1997 @@ -32,7 +32,7 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * @(#) $Header: /home/cvs/src/lib/libpcap/pcap.h,v 1.7 1999/07/20 04:49:55 deraadt Exp $ (LBL) + * @(#) $Header: /home/cvs/src/lib/libpcap/pcap.h,v 1.8 2000/04/26 21:25:53 jakob Exp $ (LBL) */ #ifndef lib_pcap_h @@ -117,6 +117,8 @@ char *pcap_strerror(int); char *pcap_geterr(pcap_t *); int pcap_compile(pcap_t *, struct bpf_program *, char *, int, bpf_u_int32); +int pcap_compile_nopcap(int, int, struct bpf_program *, + char *, int, bpf_u_int32); /* XXX */ int pcap_freecode(pcap_t *, struct bpf_program *); int pcap_datalink(pcap_t *); diff --git a/lib/libpcap/ppp.h b/lib/libpcap/ppp.h index 1a62ac7e775..bc71c7e6a44 100644 --- a/lib/libpcap/ppp.h +++ b/lib/libpcap/ppp.h @@ -1,6 +1,6 @@ -/* $OpenBSD: ppp.h,v 1.1 1999/07/20 04:49:56 deraadt Exp $ */ +/* $OpenBSD: ppp.h,v 1.2 2000/04/26 21:25:53 jakob Exp $ */ -/* @(#) $Header: /home/cvs/src/lib/libpcap/ppp.h,v 1.1 1999/07/20 04:49:56 deraadt Exp $ (LBL) */ +/* @(#) $Header: /home/cvs/src/lib/libpcap/ppp.h,v 1.2 2000/04/26 21:25:53 jakob Exp $ (LBL) */ /* * Point to Point Protocol (PPP) RFC1331 * @@ -32,6 +32,7 @@ #define PPP_BRPDU 0x0031 /* Bridging PDU */ #define PPP_STII 0x0033 /* Stream Protocol (ST-II) */ #define PPP_VINES 0x0035 /* Banyan Vines */ +#define PPP_IPV6 0x0057 /* Internet Protocol version 6 */ #define PPP_HELLO 0x0201 /* 802.1d Hello Packets */ #define PPP_LUXCOM 0x0231 /* Luxcom */ @@ -45,6 +46,7 @@ #define PPP_IPXCP 0x802b /* Novell IPX Control Protocol */ #define PPP_STIICP 0x8033 /* Strean Protocol Control Protocol */ #define PPP_VINESCP 0x8035 /* Banyan Vines Control Protocol */ +#define PPP_IPV6CP 0x8057 /* IPv6 Control Protocol */ #define PPP_LCP 0xc021 /* Link Control Protocol */ #define PPP_PAP 0xc023 /* Password Authentication Protocol */ diff --git a/lib/libpcap/scanner.l b/lib/libpcap/scanner.l index ef059f18401..bbdbf7bd1f5 100644 --- a/lib/libpcap/scanner.l +++ b/lib/libpcap/scanner.l @@ -1,5 +1,5 @@ %{ -/* $OpenBSD: scanner.l,v 1.8 1999/07/20 04:49:56 deraadt Exp $ */ +/* $OpenBSD: scanner.l,v 1.9 2000/04/26 21:25:53 jakob Exp $ */ /* * Copyright (c) 1988, 1989, 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1997 @@ -24,7 +24,7 @@ #ifndef lint static const char rcsid[] = - "@(#) $Header: /home/cvs/src/lib/libpcap/scanner.l,v 1.8 1999/07/20 04:49:56 deraadt Exp $ (LBL)"; + "@(#) $Header: /home/cvs/src/lib/libpcap/scanner.l,v 1.9 2000/04/26 21:25:53 jakob Exp $ (LBL)"; #endif #include @@ -38,6 +38,11 @@ static const char rcsid[] = #include "gencode.h" #include +#ifdef INET6 +#include +#include +#endif /*INET6*/ + #ifdef HAVE_OS_PROTO_H #include "os-proto.h" #endif @@ -77,8 +82,91 @@ 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 15000 +%o 17000 +%e 6000 +%k 4000 +%p 19000 + +V680 {W}:{W}:{W}:{W}:{W}:{W}:{W}:{W} + +V670 ::{W}:{W}:{W}:{W}:{W}:{W}:{W} +V671 {W}::{W}:{W}:{W}:{W}:{W}:{W} +V672 {W}:{W}::{W}:{W}:{W}:{W}:{W} +V673 {W}:{W}:{W}::{W}:{W}:{W}:{W} +V674 {W}:{W}:{W}:{W}::{W}:{W}:{W} +V675 {W}:{W}:{W}:{W}:{W}::{W}:{W} +V676 {W}:{W}:{W}:{W}:{W}:{W}::{W} +V677 {W}:{W}:{W}:{W}:{W}:{W}:{W}:: + +V660 ::{W}:{W}:{W}:{W}:{W}:{W} +V661 {W}::{W}:{W}:{W}:{W}:{W} +V662 {W}:{W}::{W}:{W}:{W}:{W} +V663 {W}:{W}:{W}::{W}:{W}:{W} +V664 {W}:{W}:{W}:{W}::{W}:{W} +V665 {W}:{W}:{W}:{W}:{W}::{W} +V666 {W}:{W}:{W}:{W}:{W}:{W}:: + +V650 ::{W}:{W}:{W}:{W}:{W} +V651 {W}::{W}:{W}:{W}:{W} +V652 {W}:{W}::{W}:{W}:{W} +V653 {W}:{W}:{W}::{W}:{W} +V654 {W}:{W}:{W}:{W}::{W} +V655 {W}:{W}:{W}:{W}:{W}:: + +V640 ::{W}:{W}:{W}:{W} +V641 {W}::{W}:{W}:{W} +V642 {W}:{W}::{W}:{W} +V643 {W}:{W}:{W}::{W} +V644 {W}:{W}:{W}:{W}:: + +V630 ::{W}:{W}:{W} +V631 {W}::{W}:{W} +V632 {W}:{W}::{W} +V633 {W}:{W}:{W}:: + +V620 ::{W}:{W} +V621 {W}::{W} +V622 {W}:{W}:: + +V610 ::{W} +V611 {W}:: + +V600 :: + +V6604 {W}:{W}:{W}:{W}:{W}:{W}:{N}\.{N}\.{N}\.{N} -%a 3000 +V6504 ::{W}:{W}:{W}:{W}:{W}:{N}\.{N}\.{N}\.{N} +V6514 {W}::{W}:{W}:{W}:{W}:{N}\.{N}\.{N}\.{N} +V6524 {W}:{W}::{W}:{W}:{W}:{N}\.{N}\.{N}\.{N} +V6534 {W}:{W}:{W}::{W}:{W}:{N}\.{N}\.{N}\.{N} +V6544 {W}:{W}:{W}:{W}::{W}:{N}\.{N}\.{N}\.{N} +V6554 {W}:{W}:{W}:{W}:{W}::{N}\.{N}\.{N}\.{N} + +V6404 ::{W}:{W}:{W}:{W}:{N}\.{N}\.{N}\.{N} +V6414 {W}::{W}:{W}:{W}:{N}\.{N}\.{N}\.{N} +V6424 {W}:{W}::{W}:{W}:{N}\.{N}\.{N}\.{N} +V6434 {W}:{W}:{W}::{W}:{N}\.{N}\.{N}\.{N} +V6444 {W}:{W}:{W}:{W}::{N}\.{N}\.{N}\.{N} + +V6304 ::{W}:{W}:{W}:{N}\.{N}\.{N}\.{N} +V6314 {W}::{W}:{W}:{N}\.{N}\.{N}\.{N} +V6324 {W}:{W}::{W}:{N}\.{N}\.{N}\.{N} +V6334 {W}:{W}:{W}::{N}\.{N}\.{N}\.{N} + +V6204 ::{W}:{W}:{N}\.{N}\.{N}\.{N} +V6214 {W}::{W}:{N}\.{N}\.{N}\.{N} +V6224 {W}:{W}::{N}\.{N}\.{N}\.{N} + +V6104 ::{W}:{N}\.{N}\.{N}\.{N} +V6114 {W}::{N}\.{N}\.{N}\.{N} + +V6004 ::{N}\.{N}\.{N}\.{N} + + +V6 ({V680}|{V670}|{V671}|{V672}|{V673}|{V674}|{V675}|{V676}|{V677}|{V660}|{V661}|{V662}|{V663}|{V664}|{V665}|{V666}|{V650}|{V651}|{V652}|{V653}|{V654}|{V655}|{V640}|{V641}|{V642}|{V643}|{V644}|{V630}|{V631}|{V632}|{V633}|{V620}|{V621}|{V622}|{V610}|{V611}|{V600}|{V6604}|{V6504}|{V6514}|{V6524}|{V6534}|{V6544}|{V6554}|{V6404}|{V6414}|{V6424}|{V6434}|{V6444}|{V6304}|{V6314}|{V6324}|{V6334}|{V6204}|{V6214}|{V6224}|{V6104}|{V6114}|{V6004}) %% dst return DST; @@ -94,6 +182,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; @@ -107,6 +201,13 @@ net return NET; mask return MASK; port return PORT; proto return PROTO; +protochain { +#ifdef NO_PROTOCHAIN + bpf_error("%s not supported", yytext); +#else + return PROTOCHAIN; +#endif + } gateway return GATEWAY; @@ -132,11 +233,28 @@ outbound return OUTBOUND; "==" return '='; "<<" return LSH; ">>" return RSH; +:{B} { yylval.e = pcap_ether_aton(((char *)yytext)+1); + return AID; } {N} { yylval.i = stoi((char *)yytext); return NUM; } ({N}\.{N})|({N}\.{N}\.{N})|({N}\.{N}\.{N}\.{N}) { yylval.s = sdup((char *)yytext); return HID; } {B}:{B}:{B}:{B}:{B}:{B} { yylval.e = pcap_ether_aton((char *)yytext); return EID; } +{V6} { +#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] { yylval.s = sdup((char *)yytext); return ID; } -- 2.20.1