diff --git a/contrib/libpcap/bpf/net/bpf.h b/contrib/libpcap/bpf/net/bpf.h index c6910b6d2015..c2eba554b747 100644 --- a/contrib/libpcap/bpf/net/bpf.h +++ b/contrib/libpcap/bpf/net/bpf.h @@ -38,7 +38,7 @@ * @(#)bpf.h 7.1 (Berkeley) 5/7/91 * * $FreeBSD$ - * @(#) $Header: bpf.h,v 1.36 97/06/12 14:29:53 leres Exp $ (LBL) + * @(#) $Header: /tcpdump/master/libpcap/bpf/net/bpf.h,v 1.44 2000/12/21 10:29:24 guy Exp $ (LBL) */ #ifndef BPF_MAJOR_VERSION @@ -151,13 +151,24 @@ struct bpf_hdr { * will insist on inserting padding; hence, sizeof(struct bpf_hdr) won't work. * Only the kernel needs to know about it; applications use bh_hdrlen. */ -#ifdef KERNEL +#if defined(KERNEL) || defined(_KERNEL) #define SIZEOF_BPF_HDR 18 #endif /* * Data-link level type codes. */ + +/* + * These are the types that are the same on all platforms; on other + * platforms, a should be supplied that defines the additional + * DLT_* codes appropriately for that platform (the BSDs, for example, + * should not just pick up this version of "bpf.h"; they should also define + * the additional DLT_* codes used by their kernels, as well as the values + * defined here - and, if the values they use for particular DLT_ types + * differ from those here, they should use their values, not the ones + * here). + */ #define DLT_NULL 0 /* no link-layer encapsulation */ #define DLT_EN10MB 1 /* Ethernet (10Mb) */ #define DLT_EN3MB 2 /* Experimental Ethernet (3Mb) */ @@ -169,13 +180,100 @@ struct bpf_hdr { #define DLT_SLIP 8 /* Serial Line IP */ #define DLT_PPP 9 /* Point-to-point Protocol */ #define DLT_FDDI 10 /* FDDI */ -#define DLT_ATM_RFC1483 11 /* LLC/SNAP encapsulated atm */ -#define DLT_RAW 12 /* raw IP */ -#define DLT_SLIP_BSDOS 13 /* BSD/OS Serial Line IP */ -#define DLT_PPP_BSDOS 14 /* BSD/OS Point-to-point Protocol */ /* - * The instruction encondings. + * These are values from the traditional libpcap "bpf.h". + * Ports of this to particular platforms should replace these definitions + * with the ones appropriate to that platform, if the values are + * different on that platform. + */ +#define DLT_ATM_RFC1483 11 /* LLC/SNAP encapsulated atm */ +#define DLT_RAW 12 /* raw IP */ + +/* + * These are values from BSD/OS's "bpf.h". + * These are not the same as the values from the traditional libpcap + * "bpf.h"; however, these values shouldn't be generated by any + * OS other than BSD/OS, so the correct values to use here are the + * BSD/OS values. + * + * Platforms that have already assigned these values to other + * DLT_ codes, however, should give these codes the values + * from that platform, so that programs that use these codes will + * continue to compile - even though they won't correctly read + * files of these types. + */ +#define DLT_SLIP_BSDOS 15 /* BSD/OS Serial Line IP */ +#define DLT_PPP_BSDOS 16 /* BSD/OS Point-to-point Protocol */ + +#define DLT_ATM_CLIP 19 /* Linux Classical-IP over ATM */ + +/* + * This value is defined by NetBSD; other platforms should refrain from + * using it for other purposes, so that NetBSD savefiles with a link + * type of 50 can be read as this type on all platforms. + */ +#define DLT_PPP_SERIAL 50 /* PPP over serial with HDLC encapsulation */ + +/* + * This value was defined by libpcap 0.5; platforms that have defined + * it with a different value should define it here with that value - + * a link type of 104 in a save file will be mapped to DLT_C_HDLC, + * whatever value that happens to be, so programs will correctly + * handle files with that link type regardless of the value of + * DLT_C_HDLC. + * + * The name DLT_C_HDLC was used by BSD/OS; we use that name for source + * compatibility with programs written for BSD/OS. + * + * libpcap 0.5 defined it as DLT_CHDLC; we define DLT_CHDLC as well, + * for source compatibility with programs written for libpcap 0.5. + */ +#define DLT_C_HDLC 104 /* Cisco HDLC */ +#define DLT_CHDLC DLT_C_HDLC + +/* + * Reserved for future use. + * Do not pick other numerical value for these unless you have also + * picked up the tcpdump.org top-of-CVS-tree version of "savefile.c", + * which will arrange that capture files for these DLT_ types have + * the same "network" value on all platforms, regardless of what + * value is chosen for their DLT_ type (thus allowing captures made + * on one platform to be read on other platforms, even if the two + * platforms don't use the same numerical values for all DLT_ types). + */ +#define DLT_IEEE802_11 105 /* IEEE 802.11 wireless */ + +/* + * Values between 106 and 107 are used in capture file headers as + * link-layer types corresponding to DLT_ types that might differ + * between platforms; don't use those values for new DLT_ new types. + */ + +/* + * OpenBSD DLT_LOOP, for loopback devices; it's like DLT_NULL, except + * that the AF_ type in the link-layer header is in network byte order. + * + * OpenBSD defines it as 12, but that collides with DLT_RAW, so we + * define it as 108 here. If OpenBSD picks up this file, it should + * define DLT_LOOP as 12 in its version, as per the comment above - + * and should not use 108 for any purpose. + */ +#define DLT_LOOP 108 + +/* + * Values between 109 and 112 are used in capture file headers as + * link-layer types corresponding to DLT_ types that might differ + * between platforms; don't use those values for new DLT_ new types. + */ + +/* + * This is for Linux cooked sockets. + */ +#define DLT_LINUX_SLL 113 + +/* + * The instruction encodings. */ /* instruction classes */ #define BPF_CLASS(code) ((code) & 0x07) @@ -246,15 +344,29 @@ struct bpf_insn { #define BPF_STMT(code, k) { (u_short)(code), 0, 0, k } #define BPF_JUMP(code, k, jt, jf) { (u_short)(code), jt, jf, k } -#ifdef KERNEL -extern u_int bpf_filter(); -extern void bpfattach(); +#if defined(BSD) && (defined(KERNEL) || defined(_KERNEL)) +/* + * Systems based on non-BSD kernels don't have ifnet's (or they don't mean + * anything if it is in ) and won't work like this. + */ +# if __STDC__ +extern void bpf_tap(struct ifnet *, u_char *, u_int); +extern void bpf_mtap(struct ifnet *, struct mbuf *); +extern void bpfattach(struct ifnet *, u_int, u_int); +extern void bpfilterattach(int); +# else extern void bpf_tap(); extern void bpf_mtap(); -#else +extern void bpfattach(); +extern void bpfilterattach(); +# endif /* __STDC__ */ +#endif /* BSD && (_KERNEL || KERNEL) */ #if __STDC__ +extern int bpf_validate(struct bpf_insn *, int); extern u_int bpf_filter(struct bpf_insn *, u_char *, u_int, u_int); -#endif +#else +extern int bpf_validate(); +extern u_int bpf_filter(); #endif /* diff --git a/contrib/libpcap/gencode.c b/contrib/libpcap/gencode.c index 4a7c107bbca6..1b3b55f2a9fc 100644 --- a/contrib/libpcap/gencode.c +++ b/contrib/libpcap/gencode.c @@ -23,7 +23,11 @@ */ #ifndef lint static const char rcsid[] = - "@(#) $Header: /tcpdump/master/libpcap/gencode.c,v 1.100.2.1 2000/03/01 14:12:54 itojun Exp $ (LBL)"; + "@(#) $Header: /tcpdump/master/libpcap/gencode.c,v 1.140.2.1 2001/01/14 06:48:35 guy Exp $ (LBL)"; +#endif + +#ifdef HAVE_CONFIG_H +#include "config.h" #endif #include @@ -33,25 +37,17 @@ static const char rcsid[] = #include #endif -#if __STDC__ struct mbuf; struct rtentry; -#endif - #include -#include #include #include +#include #include #include -#include -#if __STDC__ #include -#else -#include -#endif #include "pcap-int.h" @@ -59,13 +55,19 @@ struct rtentry; #include "nlpid.h" #include "gencode.h" #include "ppp.h" +#include "sll.h" #include #ifdef INET6 #include #include #endif /*INET6*/ -#include "gnuc.h" +#define LLC_SNAP_LSAP 0xaa +#define LLC_ISO_LSAP 0xfe + +#undef ETHERMTU +#define ETHERMTU 1500 + #ifdef HAVE_OS_PROTO_H #include "os-proto.h" #endif @@ -84,24 +86,16 @@ int pcap_fddipad; #endif /* VARARGS */ -__dead void -#if __STDC__ +void bpf_error(const char *fmt, ...) -#else -bpf_error(fmt, va_alist) - const char *fmt; - va_dcl -#endif + { va_list ap; -#if __STDC__ va_start(ap, fmt); -#else - va_start(ap); -#endif if (bpf_pcap != NULL) - (void)vsprintf(pcap_geterr(bpf_pcap), fmt, ap); + (void)vsnprintf(pcap_geterr(bpf_pcap), PCAP_ERRBUF_SIZE, + fmt, ap); va_end(ap); longjmp(top_ctx, 1); /* NOTREACHED */ @@ -140,24 +134,29 @@ static inline void syntax(void); static void backpatch(struct block *, struct block *); static void merge(struct block *, struct block *); static struct block *gen_cmp(u_int, u_int, bpf_int32); +static struct block *gen_cmp_gt(u_int, u_int, bpf_int32); static struct block *gen_mcmp(u_int, u_int, bpf_int32, bpf_u_int32); static struct block *gen_bcmp(u_int, u_int, const u_char *); static struct block *gen_uncond(int); static inline struct block *gen_true(void); static inline struct block *gen_false(void); static struct block *gen_linktype(int); +static struct block *gen_snap(bpf_u_int32, bpf_u_int32, u_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_thostop(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 @@ -170,6 +169,7 @@ 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 *); @@ -229,7 +229,7 @@ sdup(s) int n = strlen(s) + 1; char *cp = newchunk(n); - strcpy(cp, s); + strlcpy(cp, s, n); return (cp); } @@ -290,12 +290,19 @@ pcap_compile(pcap_t *p, struct bpf_program *program, root = NULL; bpf_pcap = p; if (setjmp(top_ctx)) { + lex_cleanup(); freechunks(); return (-1); } netmask = mask; + snaplen = pcap_snapshot(p); + if (snaplen == 0) { + snprintf(p->errbuf, PCAP_ERRBUF_SIZE, + "snaplen of 0 rejects all packets"); + return -1; + } lex_init(buf ? buf : ""); init_linktype(pcap_datalink(p)); @@ -316,6 +323,7 @@ pcap_compile(pcap_t *p, struct bpf_program *program, program->bf_insns = icode_to_fcode(root, &len); program->bf_len = len; + lex_cleanup(); freechunks(); return (0); } @@ -329,43 +337,29 @@ 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; + pcap_t *p; + int ret; - n_errors = 0; - root = NULL; - bpf_pcap = NULL; - if (setjmp(top_ctx)) { - freechunks(); + p = pcap_open_dead(linktype_arg, snaplen_arg); + if (p == NULL) return (-1); + ret = pcap_compile(p, program, buf, optimize, mask); + pcap_close(p); + return (ret); +} + +/* + * Clean up a "struct bpf_program" by freeing all the memory allocated + * in it. + */ +void +pcap_freecode(struct bpf_program *program) +{ + program->bf_len = 0; + if (program->bf_insns != NULL) { + free((char *)program->bf_insns); + program->bf_insns = NULL; } - - 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 || - (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); } /* @@ -468,6 +462,24 @@ gen_cmp(offset, size, v) return b; } +static struct block * +gen_cmp_gt(offset, size, v) + u_int offset, size; + bpf_int32 v; +{ + struct slist *s; + struct block *b; + + s = new_stmt(BPF_LD|BPF_ABS|size); + s->s.k = offset; + + b = new_block(JMP(BPF_JGT)); + b->stmts = s; + b->s.k = v; + + return b; +} + static struct block * gen_mcmp(offset, size, v, mask) u_int offset, size; @@ -562,14 +574,14 @@ init_linktype(type) return; case DLT_NULL: + case DLT_LOOP: off_linktype = 0; off_nl = 4; return; case DLT_PPP: -#ifdef DLT_CHDLC - case DLT_CHDLC: -#endif + case DLT_C_HDLC: + case DLT_PPP_SERIAL: off_linktype = 2; off_nl = 4; return; @@ -584,6 +596,8 @@ init_linktype(type) * FDDI doesn't really have a link-level type field. * We assume that SSAP = SNAP is being used and pick * out the encapsulated Ethernet type. + * + * XXX - should we generate code to check for SNAP? */ off_linktype = 19; #ifdef PCAP_FDDIPAD @@ -596,6 +610,28 @@ init_linktype(type) return; case DLT_IEEE802: + /* + * Token Ring doesn't really have a link-level type field. + * We assume that SSAP = SNAP is being used and pick + * out the encapsulated Ethernet type. + * + * XXX - should we generate code to check for SNAP? + * + * XXX - the header is actually variable-length. + * Some various Linux patched versions gave 38 + * as "off_linktype" and 40 as "off_nl"; however, + * if a token ring packet has *no* routing + * information, i.e. is not source-routed, the correct + * values are 20 and 22, as they are in the vanilla code. + * + * A packet is source-routed iff the uppermost bit + * of the first byte of the source address, at an + * offset of 8, has the uppermost bit set. If the + * packet is source-routed, the total number of bytes + * of routing information is 2 plus bits 0x1F00 of + * the 16-bit value at an offset of 14 (shifted right + * 8 - figure out which byte that is). + */ off_linktype = 20; off_nl = 22; return; @@ -613,8 +649,18 @@ init_linktype(type) off_linktype = -1; off_nl = 0; return; + + case DLT_ATM_CLIP: /* Linux ATM defines this */ + off_linktype = 6; + off_nl = 8; + return; + + case DLT_LINUX_SLL: /* fake header for Linux cooked socket */ + off_linktype = 14; + off_nl = 16; + return; } - bpf_error("unknown data link type 0x%x", linktype); + bpf_error("unknown data link type %d", linktype); /* NOTREACHED */ } @@ -645,31 +691,132 @@ gen_false() return gen_uncond(0); } +/* + * Byte-swap a 32-bit number. + * ("htonl()" or "ntohl()" won't work - we want to byte-swap even on + * big-endian platforms.) + */ +#define SWAPLONG(y) \ +((((y)&0xff)<<24) | (((y)&0xff00)<<8) | (((y)&0xff0000)>>8) | (((y)>>24)&0xff)) + static struct block * gen_linktype(proto) register int proto; { struct block *b0, *b1; - /* If we're not using encapsulation and checking for IP, we're done */ - if (off_linktype == -1 && proto == ETHERTYPE_IP) + /* If we're not using encapsulation, we're done */ + if (off_linktype == -1) return gen_true(); switch (linktype) { + case DLT_EN10MB: + /* + * XXX - handle other LLC-encapsulated protocols here + * (IPX, OSI)? + */ + switch (proto) { + + case LLC_ISO_LSAP: + /* + * OSI protocols always use 802.2 encapsulation. + */ + b0 = gen_cmp_gt(off_linktype, BPF_H, ETHERMTU); + gen_not(b0); + b1 = gen_cmp(off_linktype + 2, BPF_H, (bpf_int32) + ((LLC_ISO_LSAP << 8) | LLC_ISO_LSAP)); + gen_and(b0, b1); + return b1; + + case ETHERTYPE_ATALK: + case ETHERTYPE_AARP: + /* + * EtherTalk (AppleTalk protocols on Ethernet link + * layer) may use 802.2 encapsulation. + */ + + /* + * Check for 802.2 encapsulation (EtherTalk phase 2?); + * we check for an Ethernet type field less than + * 1500, which means it's an 802.3 length field. + */ + b0 = gen_cmp_gt(off_linktype, BPF_H, ETHERMTU); + gen_not(b0); + + /* + * 802.2-encapsulated ETHERTYPE_ATALK packets are + * SNAP packets with an organization code of + * 0x080007 (Apple, for Appletalk) and a protocol + * type of ETHERTYPE_ATALK (Appletalk). + * + * 802.2-encapsulated ETHERTYPE_AARP packets are + * SNAP packets with an organization code of + * 0x000000 (encapsulated Ethernet) and a protocol + * type of ETHERTYPE_AARP (Appletalk ARP). + */ + if (proto == ETHERTYPE_ATALK) + b1 = gen_snap(0x080007, ETHERTYPE_ATALK, 14); + else /* proto == ETHERTYPE_AARP */ + b1 = gen_snap(0x000000, ETHERTYPE_AARP, 14); + gen_and(b0, b1); + + /* + * Check for Ethernet encapsulation (Ethertalk + * phase 1?); we just check for the Ethernet + * protocol type. + */ + b0 = gen_cmp(off_linktype, BPF_H, (bpf_int32)proto); + + gen_or(b0, b1); + return b1; + } + break; + case DLT_SLIP: return gen_false(); case DLT_PPP: - if (proto == ETHERTYPE_IP) + case DLT_PPP_SERIAL: + /* + * We use Ethernet protocol types inside libpcap; + * map them to the corresponding PPP protocol types. + */ + switch (proto) { + + case ETHERTYPE_IP: proto = PPP_IP; /* XXX was 0x21 */ + break; + #ifdef INET6 - else if (proto == ETHERTYPE_IPV6) + case ETHERTYPE_IPV6: proto = PPP_IPV6; + break; #endif + + case ETHERTYPE_DN: + proto = PPP_DECNET; + break; + + case ETHERTYPE_ATALK: + proto = PPP_APPLE; + break; + + case ETHERTYPE_NS: + proto = PPP_NS; + break; + + case LLC_ISO_LSAP: + proto = PPP_OSI; + break; + } break; case DLT_PPP_BSDOS: + /* + * We use Ethernet protocol types inside libpcap; + * map them to the corresponding PPP protocol types. + */ switch (proto) { case ETHERTYPE_IP: @@ -698,41 +845,104 @@ gen_linktype(proto) case ETHERTYPE_NS: proto = PPP_NS; break; + + case LLC_ISO_LSAP: + proto = PPP_OSI; + break; } break; case DLT_NULL: - /* 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 - else - return gen_false(); - case DLT_EN10MB: + case DLT_LOOP: /* - * Having to look at SAP's here is quite disgusting, - * but given an internal architecture that _knows_ that - * it's looking at IP on Ethernet... + * For DLT_NULL, the link-layer header is a 32-bit + * word containing an AF_ value in *host* byte order. + * + * In addition, if we're reading a saved capture file, + * the host byte order in the capture may not be the + * same as the host byte order on this machine. + * + * For DLT_LOOP, the link-layer header is a 32-bit + * word containing an AF_ value in *network* byte order. + * + * XXX - AF_ values may, unfortunately, be platform- + * dependent; for example, FreeBSD's AF_INET6 is 24 + * whilst NetBSD's and OpenBSD's is 26. + * + * This means that, when reading a capture file, just + * checking for our AF_INET6 value won't work if the + * capture file came from another OS. */ - if (proto == LLC_ISO_LSAP) { - struct block *b0, *b1; + switch (proto) { - b0 = gen_cmp(off_linktype, BPF_H, (long)ETHERMTU); - b0->s.code = JMP(BPF_JGT); - gen_not(b0); - b1 = gen_cmp(off_linktype + 2, BPF_H, (long) - ((LLC_ISO_LSAP << 8) | LLC_ISO_LSAP)); - gen_and(b0, b1); - return b1; + case ETHERTYPE_IP: + proto = AF_INET; + break; + +#ifdef INET6 + case ETHERTYPE_IPV6: + proto = AF_INET6; + break; +#endif + + default: + /* + * Not a type on which we support filtering. + * XXX - support those that have AF_ values + * #defined on this platform, at least? + */ + return gen_false(); } - break; + + if (linktype == DLT_NULL) { + /* + * The AF_ value is in host byte order, but + * the BPF interpreter will convert it to + * network byte order. + * + * If this is a save file, and it's from a + * machine with the opposite byte order to + * ours, we byte-swap the AF_ value. + * + * Then we run it through "htonl()", and + * generate code to compare against the result. + */ + if (bpf_pcap->sf.rfile != NULL && + bpf_pcap->sf.swapped) + proto = SWAPLONG(proto); + proto = htonl(proto); + } + return (gen_cmp(0, BPF_W, (bpf_int32)proto)); } return gen_cmp(off_linktype, BPF_H, (bpf_int32)proto); } +/* + * Check for an LLC SNAP packet with a given organization code and + * protocol type; we check the entire contents of the 802.2 LLC and + * snap headers, checking for DSAP and SSAP of SNAP and a control + * field of 0x03 in the LLC header, and for the specified organization + * code and protocol type in the SNAP header. + */ +static struct block * +gen_snap(orgcode, ptype, offset) + bpf_u_int32 orgcode; + bpf_u_int32 ptype; + u_int offset; +{ + u_char snapblock[8]; + + snapblock[0] = LLC_SNAP_LSAP; /* DSAP = SNAP */ + snapblock[1] = LLC_SNAP_LSAP; /* SSAP = SNAP */ + snapblock[2] = 0x03; /* control = UI */ + snapblock[3] = (orgcode >> 16); /* upper 8 bits of organization code */ + snapblock[4] = (orgcode >> 8); /* middle 8 bits of organization code */ + snapblock[5] = (orgcode >> 0); /* lower 8 bits of organization code */ + snapblock[6] = (ptype >> 8); /* upper 8 bits of protocol type */ + snapblock[7] = (ptype >> 0); /* lower 8 bits of protocol type */ + return gen_bcmp(offset, 8, snapblock); +} + static struct block * gen_hostop(addr, mask, dir, proto, src_off, dst_off) bpf_u_int32 addr; @@ -902,6 +1112,40 @@ gen_fhostop(eaddr, dir) /* NOTREACHED */ } +/* + * Like gen_ehostop, but for DLT_IEEE802 (Token Ring) + */ +static struct block * +gen_thostop(eaddr, dir) + register const u_char *eaddr; + register int dir; +{ + register struct block *b0, *b1; + + switch (dir) { + case Q_SRC: + return gen_bcmp(8, 6, eaddr); + + case Q_DST: + return gen_bcmp(2, 6, eaddr); + + case Q_AND: + b0 = gen_thostop(eaddr, Q_SRC); + b1 = gen_thostop(eaddr, Q_DST); + gen_and(b0, b1); + return b1; + + case Q_DEFAULT: + case Q_OR: + b0 = gen_thostop(eaddr, Q_SRC); + b1 = gen_thostop(eaddr, Q_DST); + gen_or(b0, b1); + return b1; + } + abort(); + /* NOTREACHED */ +} + /* * This is quite tricky because there may be pad bytes in front of the * DECNET header, and then there are two possible data packet formats that @@ -957,6 +1201,9 @@ gen_dnhostop(addr, dir, base_off) gen_or(b0, b1); return b1; + case Q_ISO: + bpf_error("ISO host filtering not implemented"); + default: abort(); } @@ -1003,10 +1250,12 @@ gen_host(addr, mask, proto, dir) case Q_DEFAULT: b0 = gen_host(addr, mask, Q_IP, dir); - b1 = gen_host(addr, mask, Q_ARP, dir); - gen_or(b0, b1); - b0 = gen_host(addr, mask, Q_RARP, dir); - gen_or(b1, b0); + if (off_linktype != -1) { + b1 = gen_host(addr, mask, Q_ARP, dir); + gen_or(b0, b1); + b0 = gen_host(addr, mask, Q_RARP, dir); + gen_or(b1, b0); + } return b0; case Q_IP: @@ -1042,6 +1291,9 @@ gen_host(addr, mask, proto, dir) case Q_ATALK: bpf_error("ATALK host filtering not implemented"); + case Q_AARP: + bpf_error("AARP host filtering not implemented"); + case Q_DECNET: return gen_dnhostop(addr, dir, off_nl); @@ -1057,9 +1309,6 @@ gen_host(addr, mask, proto, dir) case Q_MOPRC: bpf_error("MOPRC host filtering not implemented"); - case Q_ISO: - bpf_error("ISO host filtering not implemented"); - #ifdef INET6 case Q_IPV6: bpf_error("'ip6' modifier applied to ip host"); @@ -1074,6 +1323,18 @@ gen_host(addr, mask, proto, dir) case Q_ESP: bpf_error("'esp' modifier applied to host"); + case Q_ISO: + bpf_error("ISO host filtering not implemented"); + + case Q_ESIS: + bpf_error("'esis' modifier applied to host"); + + case Q_ISIS: + bpf_error("'isis' modifier applied to host"); + + case Q_CLNP: + bpf_error("'clnp' modifier applied to host"); + default: abort(); } @@ -1088,8 +1349,6 @@ gen_host6(addr, mask, proto, dir) int proto; int dir; { - struct block *b0, *b1; - switch (proto) { case Q_DEFAULT: @@ -1125,6 +1384,9 @@ gen_host6(addr, mask, proto, dir) case Q_ATALK: bpf_error("ATALK host filtering not implemented"); + case Q_AARP: + bpf_error("AARP host filtering not implemented"); + case Q_DECNET: bpf_error("'decnet' modifier applied to ip6 host"); @@ -1153,6 +1415,18 @@ gen_host6(addr, mask, proto, dir) case Q_ESP: bpf_error("'esp' modifier applied to host"); + case Q_ISO: + bpf_error("ISO host filtering not implemented"); + + case Q_ESIS: + bpf_error("'esis' modifier applied to host"); + + case Q_ISIS: + bpf_error("'isis' modifier applied to host"); + + case Q_CLNP: + bpf_error("'clnp' modifier applied to host"); + default: abort(); } @@ -1160,6 +1434,7 @@ gen_host6(addr, mask, proto, dir) } #endif /*INET6*/ +#ifndef INET6 static struct block * gen_gateway(eaddr, alist, proto, dir) const u_char *eaddr; @@ -1181,9 +1456,11 @@ gen_gateway(eaddr, alist, proto, dir) b0 = gen_ehostop(eaddr, Q_OR); else if (linktype == DLT_FDDI) b0 = gen_fhostop(eaddr, Q_OR); + else if (linktype == DLT_IEEE802) + b0 = gen_thostop(eaddr, Q_OR); else bpf_error( - "'gateway' supported only on ethernet or FDDI"); + "'gateway' supported only on ethernet, FDDI or token ring"); b1 = gen_host(**alist++, 0xffffffff, proto, Q_OR); while (*alist) { @@ -1198,12 +1475,16 @@ gen_gateway(eaddr, alist, proto, dir) bpf_error("illegal modifier of 'gateway'"); /* NOTREACHED */ } +#endif struct block * gen_proto_abbrev(proto) int proto; { - struct block *b0, *b1; +#ifdef INET6 + struct block *b0; +#endif + struct block *b1; switch (proto) { @@ -1227,8 +1508,12 @@ gen_proto_abbrev(proto) b1 = gen_proto(IPPROTO_ICMP, Q_IP, Q_DEFAULT); break; +#ifndef IPPROTO_IGMP +#define IPPROTO_IGMP 2 +#endif + case Q_IGMP: - b1 = gen_proto(2, Q_IP, Q_DEFAULT); + b1 = gen_proto(IPPROTO_IGMP, Q_IP, Q_DEFAULT); break; #ifndef IPPROTO_IGRP @@ -1269,6 +1554,10 @@ gen_proto_abbrev(proto) b1 = gen_linktype(ETHERTYPE_ATALK); break; + case Q_AARP: + b1 = gen_linktype(ETHERTYPE_AARP); + break; + case Q_DECNET: b1 = gen_linktype(ETHERTYPE_DN); break; @@ -1336,6 +1625,10 @@ gen_proto_abbrev(proto) b1 = gen_proto(ISO10589_ISIS, Q_ISO, Q_DEFAULT); break; + case Q_CLNP: + b1 = gen_proto(ISO8473_CLNP, Q_ISO, Q_DEFAULT); + break; + default: abort(); } @@ -1555,6 +1848,17 @@ lookup_proto(name, proto) bpf_error("unknown ether proto '%s'", name); break; + case Q_ISO: + if (strcmp(name, "esis") == 0) + v = ISO9542_ESIS; + else if (strcmp(name, "isis") == 0) + v = ISO10589_ISIS; + else if (strcmp(name, "clnp") == 0) + v = ISO8473_CLNP; + else + bpf_error("unknown osi proto '%s'", name); + break; + default: v = PROTO_UNDEF; break; @@ -1562,14 +1866,17 @@ lookup_proto(name, proto) return v; } +#if 0 struct stmt * gen_joinsp(s, n) struct stmt **s; int n; { + return NULL; } +#endif -struct block * +static struct block * gen_protochain(v, proto, dir) int v; int proto; @@ -1579,11 +1886,10 @@ gen_protochain(v, proto, dir) return gen_proto(v, proto, dir); #else struct block *b0, *b; - struct slist *s[100], *sp; + 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)); @@ -1705,15 +2011,22 @@ gen_protochain(v, proto, dir) /* * in short, - * A = P[X + 1]; - * X = X + (P[X] + 1) * 8; + * A = P[X]; + * X = X + (P[X + 1] + 1) * 8; */ /* A = X */ s[i] = new_stmt(BPF_MISC|BPF_TXA); i++; - /* MEM[reg1] = A */ + /* 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 = reg1; + s[i]->s.k = reg2; + i++; + /* A = X */ + s[i] = new_stmt(BPF_MISC|BPF_TXA); i++; /* A += 1 */ s[i] = new_stmt(BPF_ALU|BPF_ADD|BPF_K); @@ -1726,18 +2039,6 @@ gen_protochain(v, proto, dir) 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; @@ -1787,23 +2088,12 @@ gen_protochain(v, proto, dir) /* * in short, - * A = P[X + 1]; - * X = X + (P[X] + 2) * 4; + * A = P[X]; + * X = X + (P[X + 1] + 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; @@ -1812,9 +2102,15 @@ gen_protochain(v, proto, dir) 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; + /* A = X */ + s[i - 1]->s.jt = s[i] = new_stmt(BPF_MISC|BPF_TXA); + 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); @@ -1865,7 +2161,6 @@ gen_protochain(v, proto, dir) b->stmts = s[1]; /*remember, s[0] is dummy*/ b->s.k = v; - free_reg(reg1); free_reg(reg2); gen_and(b0, b); @@ -2006,8 +2301,10 @@ gen_scode(name, q) int dir = q.dir; int tproto; u_char *eaddr; - bpf_u_int32 mask, addr, **alist; -#ifdef INET6 + bpf_u_int32 mask, addr; +#ifndef INET6 + bpf_u_int32 **alist; +#else int tproto6; struct sockaddr_in *sin; struct sockaddr_in6 *sin6; @@ -2050,9 +2347,16 @@ gen_scode(name, q) "unknown FDDI host '%s'", name); return gen_fhostop(eaddr, dir); + case DLT_IEEE802: + eaddr = pcap_ether_hostton(name); + if (eaddr == NULL) + bpf_error( + "unknown token ring host '%s'", name); + return gen_thostop(eaddr, dir); + default: bpf_error( - "only ethernet/FDDI supports link-level host name"); + "only ethernet/FDDI/token ring supports link-level host name"); break; } } else if (proto == Q_DECNET) { @@ -2080,7 +2384,7 @@ gen_scode(name, q) return b; #else memset(&mask128, 0xff, sizeof(mask128)); - res0 = res = pcap_nametoaddr(name); + res0 = res = pcap_nametoaddrinfo(name); if (res == NULL) bpf_error("unknown host '%s'", name); b = tmp = NULL; @@ -2334,7 +2638,7 @@ gen_mcode6(s1, s2, masklen, q) if (s2) bpf_error("no mask %s supported", s2); - res = pcap_nametoaddr(s1); + res = pcap_nametoaddrinfo(s1); if (!res) bpf_error("invalid ip6 address %s", s1); if (res->ai_next) @@ -2386,6 +2690,9 @@ gen_ecode(eaddr, q) return gen_ehostop(eaddr, (int)q.dir); if (linktype == DLT_FDDI) return gen_fhostop(eaddr, (int)q.dir); + if (linktype == DLT_IEEE802) + return gen_thostop(eaddr, (int)q.dir); + bpf_error("ethernet addresses supported only on ethernet, FDDI or token ring"); } bpf_error("ethernet address used in non-ether expression"); /* NOTREACHED */ @@ -2717,7 +3024,6 @@ gen_greater(n) /* * Actually, this is less than or equal. */ - struct block * gen_less(n) int n; @@ -2787,6 +3093,8 @@ gen_broadcast(proto) return gen_ehostop(ebroadcast, Q_DST); if (linktype == DLT_FDDI) return gen_fhostop(ebroadcast, Q_DST); + if (linktype == DLT_IEEE802) + return gen_thostop(ebroadcast, Q_DST); bpf_error("not a broadcast link"); break; @@ -2834,6 +3142,10 @@ gen_multicast(proto) b0->stmts = s; return b0; } + + /* TODO - check how token ring handles multicast */ + /* if (linktype == DLT_IEEE802) ... */ + /* Link not known to support multicasts */ break; @@ -2866,9 +3178,70 @@ gen_inbound(dir) { register struct block *b0; - b0 = gen_relation(BPF_JEQ, + /* + * Only some data link types support inbound/outbound qualifiers. + */ + switch (linktype) { + case DLT_SLIP: + case DLT_PPP: + b0 = gen_relation(BPF_JEQ, gen_load(Q_LINK, gen_loadi(0), 1), gen_loadi(0), dir); + break; + + default: + bpf_error("inbound/outbound not supported on linktype %d\n", + linktype); + b0 = NULL; + /* NOTREACHED */ + } + return (b0); +} + +/* + * support IEEE 802.1Q VLAN trunk over ethernet + */ +struct block * +gen_vlan(vlan_num) + int vlan_num; +{ + static u_int orig_linktype = -1, orig_nl = -1; + struct block *b0; + + /* + * Change the offsets to point to the type and data fields within + * the VLAN packet. This is somewhat of a kludge. + */ + if (orig_nl == (u_int)-1) { + orig_linktype = off_linktype; /* save original values */ + orig_nl = off_nl; + + switch (linktype) { + + case DLT_EN10MB: + off_linktype = 16; + off_nl = 18; + break; + + default: + bpf_error("no VLAN support for data link type %d", + linktype); + /*NOTREACHED*/ + } + } + + /* check for VLAN */ + b0 = gen_cmp(orig_linktype, BPF_H, (bpf_int32)ETHERTYPE_8021Q); + + /* If a specific VLAN is requested, check VLAN id */ + if (vlan_num >= 0) { + struct block *b1; + + b1 = gen_cmp(orig_nl, BPF_H, (bpf_int32)vlan_num); + gen_and(b0, b1); + b0 = b1; + } + return (b0); } diff --git a/contrib/libpcap/gencode.h b/contrib/libpcap/gencode.h index 85fa52623321..21eeecb865b7 100644 --- a/contrib/libpcap/gencode.h +++ b/contrib/libpcap/gencode.h @@ -19,12 +19,9 @@ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. * * $FreeBSD$ - * @(#) $Header: /tcpdump/master/libpcap/gencode.h,v 1.37 1999/10/19 15:18:29 itojun Exp $ (LBL) + * @(#) $Header: /tcpdump/master/libpcap/gencode.h,v 1.47 2000/11/04 10:09:55 guy Exp $ (LBL) */ -/*XXX*/ -#include "gnuc.h" - /* Address qualifiers. */ #define Q_HOST 1 @@ -54,6 +51,7 @@ #define Q_MOPRC 14 #define Q_MOPDL 15 + #define Q_IPV6 16 #define Q_ICMPV6 17 #define Q_AH 18 @@ -61,9 +59,12 @@ #define Q_PIM 20 -#define Q_ISO 21 -#define Q_ESIS 22 -#define Q_ISIS 23 +#define Q_AARP 21 + +#define Q_ISO 22 +#define Q_ESIS 23 +#define Q_ISIS 24 +#define Q_CLNP 25 /* Directional qualifiers. */ @@ -180,11 +181,14 @@ struct block *gen_broadcast(int); struct block *gen_multicast(int); struct block *gen_inbound(int); +struct block *gen_vlan(int); + void bpf_optimize(struct block **); -#if __STDC__ -__dead void bpf_error(const char *, ...) - __attribute__((volatile, format (printf, 1, 2))); +void bpf_error(const char *, ...) +#if HAVE___ATTRIBUTE__ + __attribute__((noreturn, format (printf, 1, 2))) #endif +; void finish_parse(struct block *); char *sdup(const char *); @@ -192,6 +196,7 @@ char *sdup(const char *); struct bpf_insn *icode_to_fcode(struct block *, int *); int pcap_parse(void); void lex_init(char *); +void lex_cleanup(void); void sappend(struct slist *, struct slist *); /* XXX */ diff --git a/contrib/libpcap/grammar.y b/contrib/libpcap/grammar.y index cc4797f93488..a73208e223eb 100644 --- a/contrib/libpcap/grammar.y +++ b/contrib/libpcap/grammar.y @@ -23,12 +23,17 @@ */ #ifndef lint static const char rcsid[] = - "@(#) $Header: /tcpdump/master/libpcap/grammar.y,v 1.57 1999/10/19 15:18:30 itojun Exp $ (LBL)"; + "@(#) $Header: /tcpdump/master/libpcap/grammar.y,v 1.64 2000/10/28 10:18:40 guy Exp $ (LBL)"; +#endif + +#ifdef HAVE_CONFIG_H +#include "config.h" #endif #include #include #include +#include #if __STDC__ struct mbuf; @@ -38,7 +43,6 @@ struct rtentry; #include #include -#include #include @@ -47,7 +51,6 @@ struct rtentry; #include "gencode.h" #include -#include "gnuc.h" #ifdef HAVE_OS_PROTO_H #include "os-proto.h" #endif @@ -105,7 +108,7 @@ pcap_parse() %token DST SRC HOST GATEWAY %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 ATALK AARP DECNET LAT SCA MOPRC MOPDL %token TK_BROADCAST TK_MULTICAST %token NUM INBOUND OUTBOUND %token LINK @@ -113,8 +116,9 @@ pcap_parse() %token ID EID HID HID6 %token LSH RSH %token LEN -%token ISO ESIS ISIS %token IPV6 ICMPV6 AH ESP +%token VLAN +%token ISO ESIS ISIS CLNP %type ID %type EID @@ -161,14 +165,7 @@ nid: ID { $$.b = gen_scode($1, $$.q = $0.q); } | HID { /* Decide how to parse HID based on proto */ $$.q = $0.q; - switch ($$.q.proto) { - case Q_DECNET: - $$.b = gen_ncode($1, 0, $$.q); - break; - default: - $$.b = gen_ncode($1, 0, $$.q); - break; - } + $$.b = gen_ncode($1, 0, $$.q); } | HID6 '/' NUM { #ifdef INET6 @@ -253,6 +250,7 @@ pname: LINK { $$ = Q_LINK; } | IGRP { $$ = Q_IGRP; } | PIM { $$ = Q_PIM; } | ATALK { $$ = Q_ATALK; } + | AARP { $$ = Q_AARP; } | DECNET { $$ = Q_DECNET; } | LAT { $$ = Q_LAT; } | SCA { $$ = Q_SCA; } @@ -265,6 +263,7 @@ pname: LINK { $$ = Q_LINK; } | ISO { $$ = Q_ISO; } | ESIS { $$ = Q_ESIS; } | ISIS { $$ = Q_ISIS; } + | CLNP { $$ = Q_CLNP; } ; other: pqual TK_BROADCAST { $$ = gen_broadcast($1); } | pqual TK_MULTICAST { $$ = gen_multicast($1); } @@ -273,6 +272,8 @@ other: pqual TK_BROADCAST { $$ = gen_broadcast($1); } | BYTE NUM byteop NUM { $$ = gen_byteop($3, $2, $4); } | INBOUND { $$ = gen_inbound(0); } | OUTBOUND { $$ = gen_inbound(1); } + | VLAN pnum { $$ = gen_vlan($2); } + | VLAN { $$ = gen_vlan(-1); } ; relop: '>' { $$ = BPF_JGT; } | GEQ { $$ = BPF_JGE; } diff --git a/contrib/libpcap/nametoaddr.c b/contrib/libpcap/nametoaddr.c index 857aac041da9..437caac35659 100644 --- a/contrib/libpcap/nametoaddr.c +++ b/contrib/libpcap/nametoaddr.c @@ -26,7 +26,11 @@ #ifndef lint static const char rcsid[] = - "@(#) $Header: /tcpdump/master/libpcap/nametoaddr.c,v 1.51 1999/11/25 08:25:35 itojun Exp $ (LBL)"; + "@(#) $Header: /tcpdump/master/libpcap/nametoaddr.c,v 1.57.2.1 2001/01/17 18:21:56 guy Exp $ (LBL)"; +#endif + +#ifdef HAVE_CONFIG_H +#include "config.h" #endif #include @@ -34,14 +38,13 @@ static const char rcsid[] = #include #include -#if __STDC__ struct mbuf; struct rtentry; -#endif - #include -#include #include +#ifdef HAVE_NETINET_IF_ETHER_H +#include +#endif #include #ifdef INET6 #include @@ -60,7 +63,6 @@ struct rtentry; #include "gencode.h" #include -#include "gnuc.h" #ifdef HAVE_OS_PROTO_H #include "os-proto.h" #endif @@ -76,7 +78,6 @@ static inline int xdtoi(int); * Convert host name to internet address. * Return 0 upon failure. */ -#ifndef INET6 bpf_u_int32 ** pcap_nametoaddr(const char *name) { @@ -100,9 +101,10 @@ pcap_nametoaddr(const char *name) else return 0; } -#else + +#ifdef INET6 struct addrinfo * -pcap_nametoaddr(const char *name) +pcap_nametoaddrinfo(const char *name) { struct addrinfo hints, *res; int error; @@ -340,7 +342,7 @@ pcap_ether_hostton(const char *name) register struct pcap_etherent *ep; register u_char *ap; static FILE *fp = NULL; - static init = 0; + static int init = 0; if (!init) { fp = fopen(PCAP_ETHERS_FILE, "r"); @@ -366,6 +368,15 @@ pcap_ether_hostton(const char *name) } #else +/* + * XXX - perhaps this should, instead, be declared in "lbl/os-XXX.h" files, + * for those OS versions that don't declare it, rather than being declared + * here? That way, for example, we could declare it on FreeBSD 2.x (which + * doesn't declare it), but not on FreeBSD 3.x (which declares it like + * this) or FreeBSD 4.x (which declares it with its first argument as + * "const char *", so no matter how we declare it here, it'll fail to + * compile on one of 3.x or 4.x). + */ #if !defined(sgi) && !defined(__NetBSD__) && !defined(__FreeBSD__) extern int ether_hostton(char *, struct ether_addr *); #endif diff --git a/contrib/libpcap/nlpid.h b/contrib/libpcap/nlpid.h index c033da224fd1..907af29aad5e 100644 --- a/contrib/libpcap/nlpid.h +++ b/contrib/libpcap/nlpid.h @@ -15,7 +15,8 @@ * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. * - * @(#) $Header$ (Juniper) + * $FreeBSD$ + * @(#) $Header: /tcpdump/master/libpcap/nlpid.h,v 1.1 2000/10/28 09:30:22 guy Exp $ (Juniper) */ /* Types missing from some systems */ diff --git a/contrib/libpcap/pcap-int.h b/contrib/libpcap/pcap-int.h index fb9f913d0b39..951cac0feabd 100644 --- a/contrib/libpcap/pcap-int.h +++ b/contrib/libpcap/pcap-int.h @@ -31,7 +31,7 @@ * SUCH DAMAGE. * * $FreeBSD$ - * @(#) $Header: /tcpdump/master/libpcap/pcap-int.h,v 1.20 1999/11/21 01:10:20 assar Exp $ (LBL) + * @(#) $Header: /tcpdump/master/libpcap/pcap-int.h,v 1.32 2000/12/21 10:29:23 guy Exp $ (LBL) */ #ifndef pcap_int_h @@ -49,6 +49,7 @@ extern "C" { struct pcap_sf { FILE *rfile; int swapped; + int hdrsize; int version_major; int version_minor; u_char *base; @@ -57,16 +58,21 @@ struct pcap_sf { struct pcap_md { struct pcap_stat stat; /*XXX*/ - int use_bpf; + int use_bpf; /* using kernel filter */ u_long TotPkts; /* can't oflow for 79 hrs on ether */ u_long TotAccepted; /* count accepted by filter */ u_long TotDrops; /* count of dropped packets */ long TotMissed; /* missed by i/f during this run */ long OrigMissed; /* missed by i/f before this run */ #ifdef linux - int pad; - int skip; - char *device; + int sock_packet; /* using Linux 2.0 compatible interface */ + int readlen; /* byte count to hand to "recvmsg()" */ + int timeout; /* timeout specified to pcap_open_live */ + int clear_promisc; /* must clear promiscuous mode when we close */ + int cooked; /* using SOCK_DGRAM rather than SOCK_RAW */ + int lo_ifindex; /* interface index of the loopback device */ + char *device; /* device name */ + struct pcap *next; /* list of open promiscuous sock_packet pcaps */ #endif }; @@ -115,6 +121,28 @@ struct pcap_timeval { /* * How a `pcap_pkthdr' is actually stored in the dumpfile. + * + * Do not change the format of this structure, in any way (this includes + * changes that only affect the length of fields in this structure), + * and do not make the time stamp anything other than seconds and + * microseconds (e.g., seconds and nanoseconds). Instead: + * + * introduce a new structure for the new format; + * + * send mail to "tcpdump-workers@tcpdump.org", requesting a new + * magic number for your new capture file format, and, when + * you get the new magic number, put it in "savefile.c"; + * + * use that magic number for save files with the changed record + * header; + * + * make the code in "savefile.c" capable of reading files with + * the old record header as well as files with the new record header + * (using the magic number to determine the header format). + * + * Then supply the changes to "patches@tcpdump.org", so that future + * versions of libpcap and programs that use it (such as tcpdump) will + * be able to read your new capture file format. */ struct pcap_sf_pkthdr { @@ -123,6 +151,25 @@ struct pcap_sf_pkthdr { bpf_u_int32 len; /* length this packet (off wire) */ }; +/* + * How a `pcap_pkthdr' is actually stored in dumpfiles written + * by some patched versions of libpcap (e.g. the ones in Red + * Hat Linux 6.1 and 6.2). + * + * Do not change the format of this structure, in any way (this includes + * changes that only affect the length of fields in this structure). + * Instead, introduce a new structure, as per the above. + */ + +struct pcap_sf_patched_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 index; + unsigned short protocol; + unsigned char pkt_type; +}; + int yylex(void); #ifndef min @@ -133,14 +180,30 @@ int yylex(void); int pcap_offline_read(pcap_t *, int, pcap_handler, u_char *); int pcap_read(pcap_t *, int cnt, pcap_handler, u_char *); -/* Ultrix pads to make everything line up on a nice boundary */ -#if defined(ultrix) || defined(__alpha) || defined(__NetBSD__) +/* + * Ultrix, DEC OSF/1^H^H^H^H^H^H^H^H^HDigital UNIX^H^H^H^H^H^H^H^H^H^H^H^H + * Tru64 UNIX, and NetBSD pad to make everything line up on a nice boundary. + */ +#if defined(ultrix) || defined(__osf__) || defined(__NetBSD__) #define PCAP_FDDIPAD 3 #endif +#ifndef HAVE_STRLCPY +#define strlcpy(x, y, z) \ + (strncpy((x), (y), (z)), \ + ((z) <= 0 ? 0 : ((x)[(z) - 1] = '\0')), \ + strlen((y))) +#endif + +#ifdef linux +void pcap_close_linux(pcap_t *); +#endif + /* XXX */ extern int pcap_fddipad; +int install_bpf_program(pcap_t *, struct bpf_program *); + #ifdef __cplusplus } #endif diff --git a/contrib/libpcap/pcap-namedb.h b/contrib/libpcap/pcap-namedb.h index 57e759870a33..43fe1edf55e4 100644 --- a/contrib/libpcap/pcap-namedb.h +++ b/contrib/libpcap/pcap-namedb.h @@ -31,7 +31,7 @@ * SUCH DAMAGE. * * $FreeBSD$ - * @(#) $Header: /tcpdump/master/libpcap/pcap-namedb.h,v 1.6 1999/10/19 15:18:31 itojun Exp $ (LBL) + * @(#) $Header: /tcpdump/master/libpcap/pcap-namedb.h,v 1.8 2000/07/29 07:36:43 guy Exp $ (LBL) */ #ifndef lib_pcap_ethers_h @@ -40,7 +40,6 @@ #ifdef __cplusplus extern "C" { #endif - /* * As returned by the pcap_next_etherent() @@ -60,10 +59,9 @@ struct pcap_etherent *pcap_next_etherent(FILE *); u_char *pcap_ether_hostton(const char*); u_char *pcap_ether_aton(const char *); -#ifndef INET6 bpf_u_int32 **pcap_nametoaddr(const char *); -#else -struct addrinfo *pcap_nametoaddr(const char *); +#ifdef INET6 +struct addrinfo *pcap_nametoaddrinfo(const char *); #endif bpf_u_int32 pcap_nametonetaddr(const char *); @@ -86,6 +84,5 @@ u_short __pcap_nametodnaddr(const char *); #ifdef __cplusplus } #endif - #endif diff --git a/contrib/libpcap/pcap.3 b/contrib/libpcap/pcap.3 index 0fb4a82e7b66..7da4eaf65efc 100644 --- a/contrib/libpcap/pcap.3 +++ b/contrib/libpcap/pcap.3 @@ -1,3 +1,5 @@ +.\" @(#) $Header: /tcpdump/master/libpcap/pcap.3,v 1.17.2.1 2001/01/18 04:42:11 guy Exp $ +.\" .\" Copyright (c) 1994, 1996, 1997 .\" The Regents of the University of California. All rights reserved. .\" @@ -18,9 +20,8 @@ .\" MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. .\" .\" $FreeBSD$ -.\" $Id$ .\" -.TH PCAP 3 "24 June 1998" +.TH PCAP 3 "3 January 2001" .SH NAME pcap \- Packet Capture library .SH SYNOPSIS @@ -33,6 +34,7 @@ pcap \- Packet Capture library pcap_t *pcap_open_live(char *device, int snaplen, .ti +8 int promisc, int to_ms, char *ebuf) +pcap_t *pcap_open_dead(int linktype, int snaplen) pcap_t *pcap_open_offline(char *fname, char *ebuf) pcap_dumper_t *pcap_dump_open(pcap_t *p, char *fname) .ft @@ -62,6 +64,7 @@ int pcap_compile(pcap_t *p, struct bpf_program *fp, .ti +8 char *str, int optimize, bpf_u_int32 netmask) int pcap_setfilter(pcap_t *p, struct bpf_program *fp) +void pcap_freecode(struct bpf_program *); .ft .LP .ft B @@ -94,25 +97,57 @@ on the network, even those destined for other hosts, are accessible through this mechanism. .PP .SH ROUTINES +NOTE: +.I errbuf +in +.B pcap_open_live(), +.B pcap_open_offline(), +.B pcap_lookupdev(), +and +.B pcap_lookupnet() +is assumed to be able to hold at least +.B PCAP_ERRBUF_SIZE +chars. +.PP .B pcap_open_live() is used to obtain a packet capture descriptor to look at packets on the network. .I device -is a string that specifies the network device to open. +is a string that specifies the network device to open; on Linux systems +with 2.2 or later kernels, a +.I device +argument of "any" or +.B NULL +can be used to capture packets from all interfaces. .I snaplen specifies the maximum number of bytes to capture. .I promisc specifies if the interface is to be put into promiscuous mode. (Note that even if this parameter is false, the interface -could well be in promiscuous mode for some other reason.) +could well be in promiscuous mode for some other reason.) For now, this +doesn't work on the "any" device; if an argument of "any" or NULL is +supplied, the +.I promisc +flag is ignored. .I to_ms -specifies the read timeout in milliseconds. +specifies the read timeout in milliseconds. The read timeout is used to +arrange that the read not necessarily return immediately when a packet +is seen, but that it wait for some amount of time to allow more packets +to arrive and to read multiple packets from the OS kernel in one +operation. Not all platforms support a read timeout; on platforms that +don't, the read timeout is ignored. .I ebuf is used to return error text and is only set when .B pcap_open_live() fails and returns .BR NULL . .PP +.B pcap_open_dead() +is used for creating a +.B pcap_t +structure to use when calling the other functions in libpcap. It is +typically used when just using libpcap for compiling BPF code. +.PP .B pcap_open_offline() is called to open a ``savefile'' for reading. .I fname @@ -172,21 +207,22 @@ and are .I bpf_u_int32 pointers. -A return of -1 indicates an error in which case +A return of \-1 indicates an error in which case .I errbuf is filled in with an appropriate error message. .PP .B pcap_dispatch() is used to collect and process packets. .I cnt -specifies the maximum number of packets to process before returning. A +specifies the maximum number of packets to process before returning. +This is not a minimum number; when reading a live capture, only one +bufferful of packets is read at a time, so fewer than .I cnt -of -1 processes all the packets received in one buffer. A +packets may be processed. A .I cnt -of 0 processes all packets until an error occurs, -.B EOF -is reached, or the read times out (when doing live reads and a non-zero -read timeout is specified). +of \-1 processes all the packets received in one buffer when reading a +live capture, or all the packets in the file when reading a +``savefile''. .I callback specifies a routine to be called with three arguments: a @@ -198,56 +234,35 @@ a pointer to the struct (which precede the actual network headers and data), and a .I u_char -pointer to the packet data. The number of packets read is returned. -Zero is returned when -.B EOF -is reached in a ``savefile.'' A return of -1 indicates +pointer to the packet data. +.PP +The number of packets read is returned. +0 is returned if no packets were read from a live capture (if, for +example, they were discarded because they didn't pass the packet filter, +or if, on platforms that support a read timeout that starts before any +packets arrive, the timeout expires before any packets arrive, or if the +file descriptor for the capture device is in non-blocking mode and no +packets were available to be read) or if no more packets are available +in a ``savefile.'' A return of \-1 indicates an error in which case .B pcap_perror() or -.BR pcap_geterr() +.B pcap_geterr() may be used to display the error text. .PP -.B pcap_dump() -outputs a packet to the ``savefile'' opened with -.BR pcap_dump_open() . -Note that its calling arguments are suitable for use with -.BR pcap_dispatch() . -.PP -.B pcap_compile() -is used to compile the string -.I str -into a filter program. -.I program -is a pointer to a -.I bpf_program -struct and is filled in by -.BR pcap_compile() . -.I optimize -controls whether optimization on the resulting code is performed. -.I netmask -specifies the netmask of the local net. -.PP -.B pcap_compile_nopcap() -is similar to -.B pcap_compile() -except that instead of passing a pcap structure, one passes the -snaplen and linktype explicitly. It is intended to be used for -compiling filters for direct bpf usage, without necessarily having -called -.BR pcap_open() . -.PP -.B pcap_setfilter() -is used to specify a filter program. -.I fp -is a pointer to an array of -.I bpf_program -struct, usually the result of a call to -.BR pcap_compile() . -.B \-1 -is returned on failure; -.B 0 -is returned on success. +.BR NOTE : +when reading a live capture, +.B pcap_dispatch() +will not necessarily return when the read times out; on some platforms, +the read timeout isn't supported, and, on other platforms, the timer +doesn't start until at least one packet arrives. This means that the +read timeout should +.B NOT +be used in, for example, an interactive application, to allow the packet +capture loop to ``poll'' for user input periodically, as there's no +guarantee that +.B pcap_dispatch() +will return after the timeout expires. .PP .B pcap_loop() is similar to @@ -275,6 +290,73 @@ returns a .I u_char pointer to the next packet. .PP +.B pcap_dump() +outputs a packet to the ``savefile'' opened with +.BR pcap_dump_open() . +Note that its calling arguments are suitable for use with +.B pcap_dispatch() +or +.BR pcap_loop() . +.PP +.B pcap_compile() +is used to compile the string +.I str +into a filter program. +.I program +is a pointer to a +.I bpf_program +struct and is filled in by +.BR pcap_compile() . +.I optimize +controls whether optimization on the resulting code is performed. +.I netmask +specifies the netmask of the local net. +A return of \-1 indicates an error in which case +.BR pcap_geterr() +may be used to display the error text. +.PP +.B pcap_compile_nopcap() +is similar to +.B pcap_compile() +except that instead of passing a pcap structure, one passes the +snaplen and linktype explicitly. It is intended to be used for +compiling filters for direct BPF usage, without necessarily having +called +.BR pcap_open() . +A return of \-1 indicates an error; the error text is unavailable. +.RB ( pcap_compile_nopcap() +is a wrapper around +.BR pcap_open_dead() , +.BR pcap_compile() , +and +.BR pcap_close() ; +the latter three routines can be used directly in order to get the error +text for a compilation error.) +.B +.PP +.B pcap_setfilter() +is used to specify a filter program. +.I fp +is a pointer to a +.I bpf_program +struct, usually the result of a call to +.BR pcap_compile() . +.B \-1 +is returned on failure, in which case +.BR pcap_geterr() +may be used to display the error text; +.B 0 +is returned on success. +.PP +.B pcap_freecode() +is used to free up allocated memory pointed to by a +.I bpf_program +struct generated by +.B pcap_compile() +when that BPF program is no longer needed, for example after it +has been made the filter program for a pcap structure by a call to +.BR pcap_setfilter() . +.PP .B pcap_datalink() returns the link layer type, e.g. .BR DLT_EN10MB . @@ -304,7 +386,7 @@ returns 0 and fills in a .B pcap_stat struct. The values represent packet statistics from the start of the run to the time of the call. If there is an error or the under lying -packet capture doesn't support packet statistics, -1 is returned and +packet capture doesn't support packet statistics, \-1 is returned and the error text can be obtained with .B pcap_perror() or @@ -321,6 +403,13 @@ prefixed by .PP .B pcap_geterr() returns the error text pertaining to the last pcap library error. +.BR NOTE : +the pointer it returns will no longer point to a valid error message +string after the +.B pcap_t +passed to it is closed; you must use or copy the string before closing +the +.BR pcap_t . .PP .B pcap_strerror() is provided in case @@ -338,15 +427,27 @@ closes the ``savefile.'' .SH SEE ALSO tcpdump(1), tcpslice(1) .SH AUTHORS +The original authors are: +.LP Van Jacobson, Craig Leres and Steven McCanne, all of the Lawrence Berkeley National Laboratory, University of California, Berkeley, CA. .LP -The current version is available via anonymous ftp: +The current version is available from "The Tcpdump Group"'s Web site at .LP .RS -.I ftp://ftp.ee.lbl.gov/libpcap.tar.Z +.I http://www.tcpdump.org/ .RE .SH BUGS -Please send bug reports to libpcap@ee.lbl.gov. +Please send problems, bugs, questions, desirable enhancements, etc. to: +.LP +.RS +tcpdump-workers@tcpdump.org +.RE +.LP +Please send source code contributions, etc. to: +.LP +.RS +patches@tcpdump.org +.RE diff --git a/contrib/libpcap/pcap.h b/contrib/libpcap/pcap.h index c21d38c8c611..24cd6f9f8a80 100644 --- a/contrib/libpcap/pcap.h +++ b/contrib/libpcap/pcap.h @@ -31,7 +31,7 @@ * SUCH DAMAGE. * * $FreeBSD$ - * @(#) $Header: /tcpdump/master/libpcap/pcap.h,v 1.22 1999/12/08 19:54:03 mcr Exp $ (LBL) + * @(#) $Header: /tcpdump/master/libpcap/pcap.h,v 1.31 2000/10/28 00:01:31 guy Exp $ (LBL) */ #ifndef lib_pcap_h @@ -47,7 +47,6 @@ #ifdef __cplusplus extern "C" { #endif - #define PCAP_VERSION_MAJOR 2 #define PCAP_VERSION_MINOR 4 @@ -71,6 +70,34 @@ typedef struct pcap_dumper pcap_dumper_t; * of the flags used in the printout phases of tcpdump. * Many fields here are 32 bit ints so compilers won't insert unwanted * padding; these files need to be interchangeable across architectures. + * + * Do not change the layout of this structure, in any way (this includes + * changes that only affect the length of fields in this structure). + * + * Also, do not change the interpretation of any of the members of this + * structure, in any way (this includes using values other than + * LINKTYPE_ values, as defined in "savefile.c", in the "linktype" + * field). + * + * Instead: + * + * introduce a new structure for the new format, if the layout + * of the structure changed; + * + * send mail to "tcpdump-workers@tcpdump.org", requesting a new + * magic number for your new capture file format, and, when + * you get the new magic number, put it in "savefile.c"; + * + * use that magic number for save files with the changed file + * header; + * + * make the code in "savefile.c" capable of reading files with + * the old file header as well as files with the new file header + * (using the magic number to determine the header format). + * + * Then supply the changes to "patches@tcpdump.org", so that future + * versions of libpcap and programs that use it (such as tcpdump) will + * be able to read your new capture file format. */ struct pcap_file_header { bpf_u_int32 magic; @@ -79,7 +106,7 @@ struct pcap_file_header { bpf_int32 thiszone; /* gmt to local correction */ bpf_u_int32 sigfigs; /* accuracy of timestamps */ bpf_u_int32 snaplen; /* max length saved portion of each pkt */ - bpf_u_int32 linktype; /* data link type (DLT_*) */ + bpf_u_int32 linktype; /* data link type (LINKTYPE_*) */ }; /* @@ -108,6 +135,7 @@ typedef void (*pcap_handler)(u_char *, const struct pcap_pkthdr *, char *pcap_lookupdev(char *); int pcap_lookupnet(char *, bpf_u_int32 *, bpf_u_int32 *, char *); pcap_t *pcap_open_live(char *, int, int, int, char *); +pcap_t *pcap_open_dead(int, int); pcap_t *pcap_open_offline(const char *, char *); void pcap_close(pcap_t *); int pcap_loop(pcap_t *, int, pcap_handler, u_char *); @@ -123,8 +151,7 @@ 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 *); +void pcap_freecode(struct bpf_program *); int pcap_datalink(pcap_t *); int pcap_snapshot(pcap_t *); int pcap_is_swapped(pcap_t *); @@ -141,11 +168,12 @@ void pcap_dump(u_char *, const struct pcap_pkthdr *, const u_char *); /* XXX this guy lives in the bpf tree */ u_int bpf_filter(struct bpf_insn *, u_char *, u_int, u_int); +int bpf_validate(struct bpf_insn *f, int len); char *bpf_image(struct bpf_insn *, int); +void bpf_dump(struct bpf_program *, int); #ifdef __cplusplus } #endif - #endif diff --git a/contrib/libpcap/scanner.l b/contrib/libpcap/scanner.l index c90d2a8cbc60..0bf0e26e5b45 100644 --- a/contrib/libpcap/scanner.l +++ b/contrib/libpcap/scanner.l @@ -24,7 +24,11 @@ #ifndef lint static const char rcsid[] = - "@(#) $Header: /tcpdump/master/libpcap/scanner.l,v 1.60 1999/11/17 04:09:58 assar Exp $ (LBL)"; + "@(#) $Header: /tcpdump/master/libpcap/scanner.l,v 1.70 2000/10/28 10:18:40 guy Exp $ (LBL)"; +#endif + +#ifdef HAVE_CONFIG_H +#include "config.h" #endif #include @@ -41,10 +45,13 @@ static const char rcsid[] = #ifdef INET6 #include #include +/* Workaround for AIX 4.3 */ +#if !defined(AI_NUMERICHOST) +#define AI_NUMERICHOST 0x04 +#endif #endif /*INET6*/ #include "tokdefs.h" -#include "gnuc.h" #ifdef HAVE_OS_PROTO_H #include "os-proto.h" #endif @@ -54,22 +61,10 @@ static inline int xdtoi(int); #ifdef FLEX_SCANNER #define YY_NO_UNPUT -#undef YY_INPUT -#define YY_INPUT(buf, result, max)\ - {\ - char *src = in_buffer;\ - int i;\ -\ - if (*src == 0)\ - result = YY_NULL;\ - else {\ - for (i = 0; *src && i < max; ++i)\ - buf[i] = *src++;\ - in_buffer += i;\ - result = i;\ - }\ - } +static YY_BUFFER_STATE in_buffer; #else +static char *in_buffer; + #undef getc #define getc(fp) (*in_buffer == 0 ? EOF : *in_buffer++) #endif @@ -77,8 +72,6 @@ static inline int xdtoi(int); #define yylval pcap_lval extern YYSTYPE yylval; -static char *in_buffer; - %} N ([0-9]+|(0X|0x)[0-9A-Fa-f]+) @@ -90,6 +83,7 @@ W ([0-9A-Fa-f][0-9A-Fa-f]?[0-9A-Fa-f]?[0-9A-Fa-f]?) %e 6000 %k 4000 %p 19000 +%n 2000 V680 {W}:{W}:{W}:{W}:{W}:{W}:{W}:{W} @@ -174,7 +168,7 @@ dst return DST; src return SRC; link|ether|ppp|slip return LINK; -fddi return LINK; +fddi|tr return LINK; arp return ARP; rarp return RARP; ip return IP; @@ -191,6 +185,7 @@ ah return AH; esp return ESP; atalk return ATALK; +aarp return AARP; decnet return DECNET; lat return LAT; sca return SCA; @@ -202,6 +197,7 @@ esis return ESIS; es-is return ESIS; isis return ISIS; is-is return ISIS; +clnp return CLNP; host return HOST; net return NET; @@ -232,6 +228,8 @@ len|length return LEN; inbound return INBOUND; outbound return OUTBOUND; +vlan return VLAN; + [ \n\t] ; [+\-*/:\[\]!<>()&|=] return yytext[0]; ">=" return GEQ; @@ -272,8 +270,24 @@ void lex_init(buf) char *buf; { +#ifdef FLEX_SCANNER + in_buffer = yy_scan_string(buf); +#else in_buffer = buf; - yyrestart(NULL); +#endif +} + +/* + * Do any cleanup necessary after parsing. + */ +void +lex_cleanup() +{ +#ifdef FLEX_SCANNER + if (in_buffer != NULL) + yy_delete_buffer(in_buffer); + in_buffer = NULL; +#endif } /* @@ -325,4 +339,3 @@ stoi(s) return n; } -