From c0653930dad8a2003c8c699a3c21cac01c0d8725 Mon Sep 17 00:00:00 2001 From: Bill Fenner Date: Fri, 21 Jun 2002 01:38:14 +0000 Subject: [PATCH] Merge libpcap 0.7.1 MFC after: 2 weeks --- contrib/libpcap/bpf/net/bpf.h | 72 +++- contrib/libpcap/gencode.c | 762 ++++++++++++++++++++++++++++++++-- contrib/libpcap/gencode.h | 54 ++- contrib/libpcap/grammar.y | 34 +- contrib/libpcap/nametoaddr.c | 5 +- contrib/libpcap/pcap-int.h | 4 +- contrib/libpcap/pcap.3 | 352 +++++++++++++++- contrib/libpcap/pcap.h | 35 +- contrib/libpcap/scanner.l | 58 ++- 9 files changed, 1270 insertions(+), 106 deletions(-) diff --git a/contrib/libpcap/bpf/net/bpf.h b/contrib/libpcap/bpf/net/bpf.h index c2eba554b747..405842eadda9 100644 --- a/contrib/libpcap/bpf/net/bpf.h +++ b/contrib/libpcap/bpf/net/bpf.h @@ -37,8 +37,9 @@ * * @(#)bpf.h 7.1 (Berkeley) 5/7/91 * + * @(#) $Header: /tcpdump/master/libpcap/bpf/net/bpf.h,v 1.51 2001/11/28 05:50:05 guy Exp $ (LBL) + * * $FreeBSD$ - * @(#) $Header: /tcpdump/master/libpcap/bpf/net/bpf.h,v 1.44 2000/12/21 10:29:24 guy Exp $ (LBL) */ #ifndef BPF_MAJOR_VERSION @@ -209,11 +210,18 @@ struct bpf_hdr { #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. + * These values are defined by NetBSD; other platforms should refrain from + * using them for other purposes, so that NetBSD savefiles with link + * types of 50 or 51 can be read as this type on all platforms. */ #define DLT_PPP_SERIAL 50 /* PPP over serial with HDLC encapsulation */ +#define DLT_PPP_ETHER 51 /* PPP over Ethernet */ + +/* + * Values between 100 and 103 are used in capture file headers as + * link-layer types corresponding to DLT_ types that differ + * between platforms; don't use those values for new DLT_ new types. + */ /* * This value was defined by libpcap 0.5; platforms that have defined @@ -232,16 +240,6 @@ struct bpf_hdr { #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 */ /* @@ -257,14 +255,15 @@ struct bpf_hdr { * 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. + * and should not use 108 as a DLT_ value. */ #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. + * between platforms; don't use those values for new DLT_ types + * other than the corresponding DLT_ types. */ /* @@ -272,6 +271,47 @@ struct bpf_hdr { */ #define DLT_LINUX_SLL 113 +/* + * Apple LocalTalk hardware. + */ +#define DLT_LTALK 114 + +/* + * Acorn Econet. + */ +#define DLT_ECONET 115 + +/* + * Reserved for use with OpenBSD ipfilter. + */ +#define DLT_IPFILTER 116 + +/* + * Reserved for use in capture-file headers as a link-layer type + * corresponding to OpenBSD DLT_PFLOG; DLT_PFLOG is 17 in OpenBSD, + * but that's DLT_LANE8023 in SuSE 6.3, so we can't use 17 for it + * in capture-file headers. + */ +#define DLT_PFLOG 117 + +/* + * Registered for Cisco-internal use. + */ +#define DLT_CISCO_IOS 118 + +/* + * Reserved for 802.11 cards using the Prism II chips, with a link-layer + * header including Prism monitor mode information plus an 802.11 + * header. + */ +#define DLT_PRISM_HEADER 119 + +/* + * Reserved for Aironet 802.11 cards, with an Aironet link-layer header + * (see Doug Ambrisko's FreeBSD patches). + */ +#define DLT_AIRONET_HEADER 120 + /* * The instruction encodings. */ diff --git a/contrib/libpcap/gencode.c b/contrib/libpcap/gencode.c index 1b3b55f2a9fc..ea622dec8d44 100644 --- a/contrib/libpcap/gencode.c +++ b/contrib/libpcap/gencode.c @@ -23,7 +23,7 @@ */ #ifndef lint static const char rcsid[] = - "@(#) $Header: /tcpdump/master/libpcap/gencode.c,v 1.140.2.1 2001/01/14 06:48:35 guy Exp $ (LBL)"; + "@(#) $Header: /tcpdump/master/libpcap/gencode.c,v 1.160 2001/11/30 07:25:48 guy Exp $ (LBL)"; #endif #ifdef HAVE_CONFIG_H @@ -53,21 +53,24 @@ struct rtentry; #include "ethertype.h" #include "nlpid.h" +#include "llc.h" #include "gencode.h" #include "ppp.h" #include "sll.h" +#include "arcnet.h" #include #ifdef INET6 #include #include #endif /*INET6*/ -#define LLC_SNAP_LSAP 0xaa -#define LLC_ISO_LSAP 0xfe - #undef ETHERMTU #define ETHERMTU 1500 +#ifndef IPPROTO_SCTP +#define IPPROTO_SCTP 132 +#endif + #ifdef HAVE_OS_PROTO_H #include "os-proto.h" #endif @@ -78,6 +81,9 @@ struct rtentry; static jmp_buf top_ctx; static pcap_t *bpf_pcap; +/* Hack for updating VLAN offsets. */ +static u_int orig_linktype = -1, orig_nl = -1; + /* XXX */ #ifdef PCAP_FDDIPAD int pcap_fddipad = PCAP_FDDIPAD; @@ -146,6 +152,7 @@ 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_thostop(const u_char *, int); @@ -550,8 +557,16 @@ init_linktype(type) { linktype = type; + orig_linktype = -1; + orig_nl = -1; + 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; @@ -580,12 +595,21 @@ init_linktype(type) return; case DLT_PPP: - case DLT_C_HDLC: - case DLT_PPP_SERIAL: + case DLT_C_HDLC: /* BSD/OS Cisco HDLC */ + case DLT_PPP_SERIAL: /* NetBSD sync/async serial PPP */ off_linktype = 2; off_nl = 4; return; + case DLT_PPP_ETHER: + /* + * This does no include the Ethernet header, and + * only covers session state. + */ + off_linktype = 6; + off_nl = 8; + return; + case DLT_PPP_BSDOS: off_linktype = 5; off_nl = 24; @@ -594,12 +618,13 @@ init_linktype(type) case DLT_FDDI: /* * 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. + * We set "off_linktype" to the offset of the LLC header. * + * To check for Ethernet types, 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; + off_linktype = 13; #ifdef PCAP_FDDIPAD off_linktype += pcap_fddipad; #endif @@ -612,9 +637,10 @@ init_linktype(type) 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. + * We set "off_linktype" to the offset of the LLC header. * + * To check for Ethernet types, 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. @@ -632,10 +658,42 @@ init_linktype(type) * the 16-bit value at an offset of 14 (shifted right * 8 - figure out which byte that is). */ - off_linktype = 20; + off_linktype = 14; off_nl = 22; return; + case DLT_IEEE802_11: + /* + * 802.11 doesn't really have a link-level type field. + * We set "off_linktype" to the offset of the LLC header. + * + * To check for Ethernet types, 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. We + * assume a 24-byte link-layer header, as appears in + * data frames in networks with no bridges. + */ + off_linktype = 24; + off_nl = 30; + return; + + case DLT_PRISM_HEADER: + /* + * Same as 802.11, but with an additional header before + * the 802.11 header, containing a bunch of additional + * information including radio-level information. + * + * The header is 144 bytes long. + * + * XXX - same variable-length header problem; at least + * the Prism header is fixed-length. + */ + off_linktype = 144+24; + off_nl = 144+30; + return; + case DLT_ATM_RFC1483: /* * assume routed, non-ISO PDUs @@ -659,6 +717,16 @@ init_linktype(type) off_linktype = 14; off_nl = 16; return; + + case DLT_LTALK: + /* + * LocalTalk does have a 1-byte type field in the LLAP header, + * but really it just indicates whether there is a "short" or + * "long" DDP packet following. + */ + off_linktype = -1; + off_nl = 0; + return; } bpf_error("unknown data link type %d", linktype); /* NOTREACHED */ @@ -705,30 +773,110 @@ gen_linktype(proto) { struct block *b0, *b1; - /* 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: + case LLCSAP_ISONS: /* * OSI protocols always use 802.2 encapsulation. + * XXX - should we check both the DSAP and the + * SSAP, like this, or should we check just the + * DSAP? */ 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)); + ((LLCSAP_ISONS << 8) | LLCSAP_ISONS)); gen_and(b0, b1); return b1; + case LLCSAP_NETBEUI: + /* + * NetBEUI always uses 802.2 encapsulation. + * XXX - should we check both the DSAP and the + * SSAP, like this, or should we check just the + * DSAP? + */ + b0 = gen_cmp_gt(off_linktype, BPF_H, ETHERMTU); + gen_not(b0); + b1 = gen_cmp(off_linktype + 2, BPF_H, (bpf_int32) + ((LLCSAP_NETBEUI << 8) | LLCSAP_NETBEUI)); + gen_and(b0, b1); + return b1; + + case LLCSAP_IPX: + /* + * Check for; + * + * Ethernet_II frames, which are Ethernet + * frames with a frame type of ETHERTYPE_IPX; + * + * Ethernet_802.3 frames, which are 802.3 + * frames (i.e., the type/length field is + * a length field, <= ETHERMTU, rather than + * a type field) with the first two bytes + * after the Ethernet/802.3 header being + * 0xFFFF; + * + * Ethernet_802.2 frames, which are 802.3 + * frames with an 802.2 LLC header and + * with the IPX LSAP as the DSAP in the LLC + * header; + * + * Ethernet_SNAP frames, which are 802.3 + * frames with an LLC header and a SNAP + * header and with an OUI of 0x000000 + * (encapsulated Ethernet) and a protocol + * ID of ETHERTYPE_IPX in the SNAP header. + * + * XXX - should we generate the same code both + * for tests for LLCSAP_IPX and for ETHERTYPE_IPX? + */ + + /* + * This generates code to check both for the + * IPX LSAP (Ethernet_802.2) and for Ethernet_802.3. + */ + b0 = gen_cmp(off_linktype + 2, BPF_B, + (bpf_int32)LLCSAP_IPX); + b1 = gen_cmp(off_linktype + 2, BPF_H, + (bpf_int32)0xFFFF); + gen_or(b0, b1); + + /* + * Now we add code to check for SNAP frames with + * ETHERTYPE_IPX, i.e. Ethernet_SNAP. + */ + b0 = gen_snap(0x000000, ETHERTYPE_IPX, 14); + gen_or(b0, b1); + + /* + * Now we generate code to check for 802.3 + * frames in general. + */ + b0 = gen_cmp_gt(off_linktype, BPF_H, ETHERMTU); + gen_not(b0); + + /* + * Now add the check for 802.3 frames before the + * check for Ethernet_802.2 and Ethernet_802.3, + * as those checks should only be done on 802.3 + * frames, not on Ethernet frames. + */ + gen_and(b0, b1); + + /* + * Now add the check for Ethernet_II frames, and + * do that before checking for the other frame + * types. + */ + b0 = gen_cmp(off_linktype, BPF_H, + (bpf_int32)ETHERTYPE_IPX); + gen_or(b0, b1); + return b1; + case ETHERTYPE_ATALK: case ETHERTYPE_AARP: /* @@ -770,14 +918,301 @@ gen_linktype(proto) gen_or(b0, b1); return b1; + + default: + if (proto <= ETHERMTU) { + /* + * This is an LLC SAP value, so the frames + * that match would be 802.2 frames. + * Check that the frame is an 802.2 frame + * (i.e., that the length/type field is + * a length field, <= ETHERMTU) and + * then check the DSAP. + */ + b0 = gen_cmp_gt(off_linktype, BPF_H, ETHERMTU); + gen_not(b0); + b1 = gen_cmp(off_linktype + 2, BPF_B, + (bpf_int32)proto); + gen_and(b0, b1); + return b1; + } else { + /* + * This is an Ethernet type, so compare + * the length/type field with it (if + * the frame is an 802.2 frame, the length + * field will be <= ETHERMTU, and, as + * "proto" is > ETHERMTU, this test + * will fail and the frame won't match, + * which is what we want). + */ + return gen_cmp(off_linktype, BPF_H, + (bpf_int32)proto); + } + } + break; + + case DLT_IEEE802_11: + case DLT_PRISM_HEADER: + case DLT_FDDI: + case DLT_IEEE802: + case DLT_ATM_RFC1483: + case DLT_ATM_CLIP: + /* + * XXX - handle token-ring variable-length header. + */ + switch (proto) { + + case LLCSAP_ISONS: + return gen_cmp(off_linktype, BPF_H, (long) + ((LLCSAP_ISONS << 8) | LLCSAP_ISONS)); + + case LLCSAP_NETBEUI: + return gen_cmp(off_linktype, BPF_H, (long) + ((LLCSAP_NETBEUI << 8) | LLCSAP_NETBEUI)); + + case LLCSAP_IPX: + /* + * XXX - are there ever SNAP frames for IPX on + * non-Ethernet 802.x networks? + */ + return gen_cmp(off_linktype, BPF_B, + (bpf_int32)LLCSAP_IPX); + + case ETHERTYPE_ATALK: + /* + * 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). + * + * XXX - check for an organization code of + * encapsulated Ethernet as well? + */ + return gen_snap(0x080007, ETHERTYPE_ATALK, + off_linktype); + break; + + default: + /* + * XXX - we don't have to check for IPX 802.3 + * here, but should we check for the IPX Ethertype? + */ + if (proto <= ETHERMTU) { + /* + * This is an LLC SAP value, so check + * the DSAP. + */ + return gen_cmp(off_linktype, BPF_B, + (bpf_int32)proto); + } else { + /* + * This is an Ethernet type; we assume + * that it's unlikely that it'll + * appear in the right place at random, + * and therefore check only the + * location that would hold the Ethernet + * type in a SNAP frame with an organization + * code of 0x000000 (encapsulated Ethernet). + * + * XXX - if we were to check for the SNAP DSAP + * and LSAP, as per XXX, and were also to check + * for an organization code of 0x000000 + * (encapsulated Ethernet), we'd do + * + * return gen_snap(0x000000, proto, + * off_linktype); + * + * here; for now, we don't, as per the above. + * I don't know whether it's worth the + * extra CPU time to do the right check + * or not. + */ + return gen_cmp(off_linktype+6, BPF_H, + (bpf_int32)proto); + } + } + break; + + case DLT_LINUX_SLL: + switch (proto) { + + case LLCSAP_ISONS: + /* + * OSI protocols always use 802.2 encapsulation. + * XXX - should we check both the DSAP and the + * LSAP, like this, or should we check just the + * DSAP? + */ + b0 = gen_cmp(off_linktype, BPF_H, LINUX_SLL_P_802_2); + b1 = gen_cmp(off_linktype + 2, BPF_H, (bpf_int32) + ((LLCSAP_ISONS << 8) | LLCSAP_ISONS)); + gen_and(b0, b1); + return b1; + + case LLCSAP_NETBEUI: + /* + * NetBEUI always uses 802.2 encapsulation. + * XXX - should we check both the DSAP and the + * LSAP, like this, or should we check just the + * DSAP? + */ + b0 = gen_cmp(off_linktype, BPF_H, LINUX_SLL_P_802_2); + b1 = gen_cmp(off_linktype + 2, BPF_H, (bpf_int32) + ((LLCSAP_NETBEUI << 8) | LLCSAP_NETBEUI)); + gen_and(b0, b1); + return b1; + + case LLCSAP_IPX: + /* + * Ethernet_II frames, which are Ethernet + * frames with a frame type of ETHERTYPE_IPX; + * + * Ethernet_802.3 frames, which have a frame + * type of LINUX_SLL_P_802_3; + * + * Ethernet_802.2 frames, which are 802.3 + * frames with an 802.2 LLC header (i.e, have + * a frame type of LINUX_SLL_P_802_2) and + * with the IPX LSAP as the DSAP in the LLC + * header; + * + * Ethernet_SNAP frames, which are 802.3 + * frames with an LLC header and a SNAP + * header and with an OUI of 0x000000 + * (encapsulated Ethernet) and a protocol + * ID of ETHERTYPE_IPX in the SNAP header. + * + * First, do the checks on LINUX_SLL_P_802_2 + * frames; generate the check for either + * Ethernet_802.2 or Ethernet_SNAP frames, and + * then put a check for LINUX_SLL_P_802_2 frames + * before it. + */ + b0 = gen_cmp(off_linktype + 2, BPF_B, + (bpf_int32)LLCSAP_IPX); + b1 = gen_snap(0x000000, ETHERTYPE_IPX, + off_linktype + 2); + gen_or(b0, b1); + b0 = gen_cmp(off_linktype, BPF_H, LINUX_SLL_P_802_2); + gen_and(b0, b1); + + /* + * Now check for 802.3 frames and OR that with + * the previous test. + */ + b0 = gen_cmp(off_linktype, BPF_H, LINUX_SLL_P_802_3); + gen_or(b0, b1); + + /* + * Now add the check for Ethernet_II frames, and + * do that before checking for the other frame + * types. + */ + b0 = gen_cmp(off_linktype, BPF_H, + (bpf_int32)ETHERTYPE_IPX); + gen_or(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 the 802.2 protocol type in the + * "Ethernet type" field. + */ + b0 = gen_cmp(off_linktype, BPF_H, LINUX_SLL_P_802_2); + + /* + * 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, + off_linktype + 2); + else /* proto == ETHERTYPE_AARP */ + b1 = gen_snap(0x000000, ETHERTYPE_AARP, + off_linktype + 2); + 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; + + default: + if (proto <= ETHERMTU) { + /* + * This is an LLC SAP value, so the frames + * that match would be 802.2 frames. + * Check for the 802.2 protocol type + * in the "Ethernet type" field, and + * then check the DSAP. + */ + b0 = gen_cmp(off_linktype, BPF_H, + LINUX_SLL_P_802_2); + b1 = gen_cmp(off_linktype + 2, BPF_B, + (bpf_int32)proto); + gen_and(b0, b1); + return b1; + } else { + /* + * This is an Ethernet type, so compare + * the length/type field with it (if + * the frame is an 802.2 frame, the length + * field will be <= ETHERMTU, and, as + * "proto" is > ETHERMTU, this test + * will fail and the frame won't match, + * which is what we want). + */ + return gen_cmp(off_linktype, BPF_H, + (bpf_int32)proto); + } } break; case DLT_SLIP: - return gen_false(); + case DLT_SLIP_BSDOS: + case DLT_RAW: + /* + * These types don't provide any type field; packets + * are always IP. + * + * XXX - for IPv4, check for a version number of 4, and, + * for IPv6, check for a version number of 6? + */ + switch (proto) { + + case ETHERTYPE_IP: +#ifdef INET6 + case ETHERTYPE_IPV6: +#endif + return gen_true(); /* always true */ + + default: + return gen_false(); /* always false */ + } + break; case DLT_PPP: case DLT_PPP_SERIAL: + case DLT_PPP_ETHER: /* * We use Ethernet protocol types inside libpcap; * map them to the corresponding PPP protocol types. @@ -806,9 +1241,22 @@ gen_linktype(proto) proto = PPP_NS; break; - case LLC_ISO_LSAP: + case LLCSAP_ISONS: proto = PPP_OSI; break; + + case LLCSAP_8021D: + /* + * I'm assuming the "Bridging PDU"s that go + * over PPP are Spanning Tree Protocol + * Bridging PDUs. + */ + proto = PPP_BRPDU; + break; + + case LLCSAP_IPX: + proto = PPP_IPX; + break; } break; @@ -846,9 +1294,22 @@ gen_linktype(proto) proto = PPP_NS; break; - case LLC_ISO_LSAP: + case LLCSAP_ISONS: proto = PPP_OSI; break; + + case LLCSAP_8021D: + /* + * I'm assuming the "Bridging PDU"s that go + * over PPP are Spanning Tree Protocol + * Bridging PDUs. + */ + proto = PPP_BRPDU; + break; + + case LLCSAP_IPX: + proto = PPP_IPX; + break; } break; @@ -913,7 +1374,73 @@ gen_linktype(proto) proto = htonl(proto); } return (gen_cmp(0, BPF_W, (bpf_int32)proto)); + + 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))); + } + break; + + case DLT_LTALK: + switch (proto) { + case ETHERTYPE_ATALK: + return gen_true(); + default: + return gen_false(); + } + break; } + + /* + * All the types that have no encapsulation should either be + * handled as DLT_SLIP, DLT_SLIP_BSDOS, and DLT_RAW are, if + * all packets are IP packets, or should be handled in some + * special case, if none of them are (if some are and some + * aren't, the lack of encapsulation is a problem, as we'd + * have to find some other way of determining the packet type). + * + * Therefore, if "off_linktype" is -1, there's an error. + */ + if (off_linktype == -1) + abort(); + + /* + * Any type not handled above should always have an Ethernet + * type at an offset of "off_linktype". (PPP is partially + * handled above - the protocol type is mapped from the + * Ethernet and LLC types we use internally to the corresponding + * PPP type - but the PPP type is always specified by a value + * at "off_linktype", so we don't have to do the code generation + * above.) + */ return gen_cmp(off_linktype, BPF_H, (bpf_int32)proto); } @@ -932,8 +1459,8 @@ gen_snap(orgcode, ptype, offset) { u_char snapblock[8]; - snapblock[0] = LLC_SNAP_LSAP; /* DSAP = SNAP */ - snapblock[1] = LLC_SNAP_LSAP; /* SSAP = SNAP */ + snapblock[0] = LLCSAP_SNAP; /* DSAP = SNAP */ + snapblock[1] = LLCSAP_SNAP; /* 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 */ @@ -1273,6 +1800,9 @@ gen_host(addr, mask, proto, dir) case Q_TCP: bpf_error("'tcp' modifier applied to host"); + case Q_SCTP: + bpf_error("'sctp' modifier applied to host"); + case Q_UDP: bpf_error("'udp' modifier applied to host"); @@ -1288,6 +1818,9 @@ gen_host(addr, mask, proto, dir) case Q_PIM: bpf_error("'pim' modifier applied to host"); + case Q_VRRP: + bpf_error("'vrrp' modifier applied to host"); + case Q_ATALK: bpf_error("ATALK host filtering not implemented"); @@ -1335,6 +1868,15 @@ gen_host(addr, mask, proto, dir) case Q_CLNP: bpf_error("'clnp' modifier applied to host"); + case Q_STP: + bpf_error("'stp' modifier applied to host"); + + case Q_IPX: + bpf_error("IPX host filtering not implemented"); + + case Q_NETBEUI: + bpf_error("'netbeui' modifier applied to host"); + default: abort(); } @@ -1363,6 +1905,9 @@ gen_host6(addr, mask, proto, dir) case Q_ARP: bpf_error("'arp' modifier applied to ip6 host"); + case Q_SCTP: + bpf_error("'sctp' modifier applied to host"); + case Q_TCP: bpf_error("'tcp' modifier applied to host"); @@ -1381,6 +1926,9 @@ gen_host6(addr, mask, proto, dir) case Q_PIM: bpf_error("'pim' modifier applied to host"); + case Q_VRRP: + bpf_error("'vrrp' modifier applied to host"); + case Q_ATALK: bpf_error("ATALK host filtering not implemented"); @@ -1427,6 +1975,15 @@ gen_host6(addr, mask, proto, dir) case Q_CLNP: bpf_error("'clnp' modifier applied to host"); + case Q_STP: + bpf_error("'stp' modifier applied to host"); + + case Q_IPX: + bpf_error("IPX host filtering not implemented"); + + case Q_NETBEUI: + bpf_error("'netbeui' modifier applied to host"); + default: abort(); } @@ -1488,6 +2045,14 @@ gen_proto_abbrev(proto) switch (proto) { + case Q_SCTP: + b1 = gen_proto(IPPROTO_SCTP, Q_IP, Q_DEFAULT); +#ifdef INET6 + b0 = gen_proto(IPPROTO_SCTP, Q_IPV6, Q_DEFAULT); + gen_or(b0, b1); +#endif + break; + case Q_TCP: b1 = gen_proto(IPPROTO_TCP, Q_IP, Q_DEFAULT); #ifdef INET6 @@ -1535,6 +2100,14 @@ gen_proto_abbrev(proto) #endif break; +#ifndef IPPROTO_VRRP +#define IPPROTO_VRRP 112 +#endif + + case Q_VRRP: + b1 = gen_proto(IPPROTO_VRRP, Q_IP, Q_DEFAULT); + break; + case Q_IP: b1 = gen_linktype(ETHERTYPE_IP); break; @@ -1614,7 +2187,7 @@ gen_proto_abbrev(proto) break; case Q_ISO: - b1 = gen_linktype(LLC_ISO_LSAP); + b1 = gen_linktype(LLCSAP_ISONS); break; case Q_ESIS: @@ -1629,6 +2202,18 @@ gen_proto_abbrev(proto) b1 = gen_proto(ISO8473_CLNP, Q_ISO, Q_DEFAULT); break; + case Q_STP: + b1 = gen_linktype(LLCSAP_8021D); + break; + + case Q_IPX: + b1 = gen_linktype(LLCSAP_IPX); + break; + + case Q_NETBEUI: + b1 = gen_linktype(LLCSAP_NETBEUI); + break; + default: abort(); } @@ -1738,6 +2323,7 @@ gen_port(port, ip_proto, dir) switch (ip_proto) { case IPPROTO_UDP: case IPPROTO_TCP: + case IPPROTO_SCTP: b1 = gen_portop(port, ip_proto, dir); break; @@ -1745,6 +2331,8 @@ gen_port(port, ip_proto, dir) tmp = gen_portop(port, IPPROTO_TCP, dir); b1 = gen_portop(port, IPPROTO_UDP, dir); gen_or(tmp, b1); + tmp = gen_portop(port, IPPROTO_SCTP, dir); + gen_or(tmp, b1); break; default: @@ -1808,6 +2396,7 @@ gen_port6(port, ip_proto, dir) switch (ip_proto) { case IPPROTO_UDP: case IPPROTO_TCP: + case IPPROTO_SCTP: b1 = gen_portop6(port, ip_proto, dir); break; @@ -1815,6 +2404,8 @@ gen_port6(port, ip_proto, dir) tmp = gen_portop6(port, IPPROTO_TCP, dir); b1 = gen_portop6(port, IPPROTO_UDP, dir); gen_or(tmp, b1); + tmp = gen_portop6(port, IPPROTO_SCTP, dir); + gen_or(tmp, b1); break; default: @@ -1836,6 +2427,7 @@ lookup_proto(name, proto) case Q_DEFAULT: case Q_IP: + case Q_IPV6: v = pcap_nametoproto(name); if (v == PROTO_UNDEF) bpf_error("unknown ip proto '%s'", name); @@ -2200,7 +2792,7 @@ gen_proto(v, proto, dir) return b1; case Q_ISO: - b0 = gen_linktype(LLC_ISO_LSAP); + b0 = gen_linktype(LLCSAP_ISONS); b1 = gen_cmp(off_nl + 3, BPF_B, (long)v); gen_and(b0, b1); return b1; @@ -2248,6 +2840,10 @@ gen_proto(v, proto, dir) bpf_error("'tcp proto' is bogus"); /* NOTREACHED */ + case Q_SCTP: + bpf_error("'sctp proto' is bogus"); + /* NOTREACHED */ + case Q_ICMP: bpf_error("'icmp proto' is bogus"); /* NOTREACHED */ @@ -2264,6 +2860,10 @@ gen_proto(v, proto, dir) bpf_error("'pim proto' is bogus"); /* NOTREACHED */ + case Q_VRRP: + bpf_error("'vrrp proto' is bogus"); + /* NOTREACHED */ + #ifdef INET6 case Q_IPV6: b0 = gen_linktype(ETHERTYPE_IPV6); @@ -2285,6 +2885,15 @@ gen_proto(v, proto, dir) case Q_ESP: bpf_error("'ah proto' is bogus"); + case Q_STP: + bpf_error("'stp proto' is bogus"); + + case Q_IPX: + bpf_error("'ipx proto' is bogus"); + + case Q_NETBEUI: + bpf_error("'netbeui proto' is bogus"); + default: abort(); /* NOTREACHED */ @@ -2338,21 +2947,27 @@ gen_scode(name, q) if (eaddr == NULL) bpf_error( "unknown ether host '%s'", name); - return gen_ehostop(eaddr, dir); + b = gen_ehostop(eaddr, dir); + free(eaddr); + return b; case DLT_FDDI: eaddr = pcap_ether_hostton(name); if (eaddr == NULL) bpf_error( "unknown FDDI host '%s'", name); - return gen_fhostop(eaddr, dir); + b = gen_fhostop(eaddr, dir); + free(eaddr); + return b; case DLT_IEEE802: eaddr = pcap_ether_hostton(name); if (eaddr == NULL) bpf_error( "unknown token ring host '%s'", name); - return gen_thostop(eaddr, dir); + b = gen_thostop(eaddr, dir); + free(eaddr); + return b; default: bpf_error( @@ -2413,6 +3028,8 @@ gen_scode(name, q) tmp = gen_host6(&sin6->sin6_addr, &mask128, tproto6, dir); break; + default: + continue; } if (b) gen_or(b, tmp); @@ -2430,13 +3047,16 @@ gen_scode(name, q) } case Q_PORT: - if (proto != Q_DEFAULT && proto != Q_UDP && proto != Q_TCP) + if (proto != Q_DEFAULT && + proto != Q_UDP && proto != Q_TCP && proto != Q_SCTP) bpf_error("illegal qualifier of 'port'"); if (pcap_nametoport(name, &port, &real_proto) == 0) bpf_error("unknown port '%s'", name); if (proto == Q_UDP) { if (real_proto == IPPROTO_TCP) bpf_error("port '%s' is tcp", name); + else if (real_proto == IPPROTO_SCTP) + bpf_error("port '%s' is sctp", name); else /* override PROTO_UNDEF */ real_proto = IPPROTO_UDP; @@ -2444,10 +3064,23 @@ gen_scode(name, q) if (proto == Q_TCP) { if (real_proto == IPPROTO_UDP) bpf_error("port '%s' is udp", name); + + else if (real_proto == IPPROTO_SCTP) + bpf_error("port '%s' is sctp", name); else /* override PROTO_UNDEF */ real_proto = IPPROTO_TCP; } + if (proto == Q_SCTP) { + if (real_proto == IPPROTO_UDP) + bpf_error("port '%s' is udp", name); + + else if (real_proto == IPPROTO_TCP) + bpf_error("port '%s' is tcp", name); + else + /* override PROTO_UNDEF */ + real_proto = IPPROTO_SCTP; + } #ifndef INET6 return gen_port(port, real_proto, dir); #else @@ -2468,7 +3101,9 @@ gen_scode(name, q) alist = pcap_nametoaddr(name); if (alist == NULL || *alist == NULL) bpf_error("unknown host '%s'", name); - return gen_gateway(eaddr, alist, proto, dir); + b = gen_gateway(eaddr, alist, proto, dir); + free(eaddr); + return b; #else bpf_error("'gateway' not supported in this configuration"); #endif /*INET6*/ @@ -2585,6 +3220,8 @@ gen_ncode(s, v, q) proto = IPPROTO_UDP; else if (proto == Q_TCP) proto = IPPROTO_TCP; + else if (proto == Q_SCTP) + proto = IPPROTO_SCTP; else if (proto == Q_DEFAULT) proto = PROTO_UNDEF; else @@ -2647,6 +3284,7 @@ gen_mcode6(s1, s2, masklen, q) if (sizeof(mask) * 8 < masklen) bpf_error("mask length must be <= %u", (unsigned int)(sizeof(mask) * 8)); + memset(&mask, 0, sizeof(mask)); memset(&mask, 0xff, masklen / 8); if (masklen % 8) { mask.s6_addr[masklen / 8] = @@ -2797,12 +3435,14 @@ gen_load(proto, index, size) index->b = b; break; + case Q_SCTP: case Q_TCP: case Q_UDP: case Q_ICMP: case Q_IGMP: case Q_IGRP: case Q_PIM: + case Q_VRRP: s = new_stmt(BPF_LDX|BPF_MSH|BPF_B); s->s.k = off_nl; sappend(s, xfer_to_a(index)); @@ -3077,6 +3717,8 @@ gen_byteop(op, idx, val) return b; } +static u_char abroadcast[] = { 0x0 }; + struct block * gen_broadcast(proto) int proto; @@ -3089,6 +3731,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) @@ -3122,6 +3766,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); @@ -3199,6 +3847,51 @@ gen_inbound(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 */ +} + /* * support IEEE 802.1Q VLAN trunk over ethernet */ @@ -3206,7 +3899,6 @@ struct block * gen_vlan(vlan_num) int vlan_num; { - static u_int orig_linktype = -1, orig_nl = -1; struct block *b0; /* diff --git a/contrib/libpcap/gencode.h b/contrib/libpcap/gencode.h index 21eeecb865b7..c790547f4861 100644 --- a/contrib/libpcap/gencode.h +++ b/contrib/libpcap/gencode.h @@ -18,8 +18,9 @@ * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. * + * @(#) $Header: /tcpdump/master/libpcap/gencode.h,v 1.53 2001/05/10 14:48:02 fenner Exp $ (LBL) + * * $FreeBSD$ - * @(#) $Header: /tcpdump/master/libpcap/gencode.h,v 1.47 2000/11/04 10:09:55 guy Exp $ (LBL) */ /* Address qualifiers. */ @@ -37,34 +38,42 @@ #define Q_IP 2 #define Q_ARP 3 #define Q_RARP 4 -#define Q_TCP 5 -#define Q_UDP 6 -#define Q_ICMP 7 -#define Q_IGMP 8 -#define Q_IGRP 9 +#define Q_SCTP 5 +#define Q_TCP 6 +#define Q_UDP 7 +#define Q_ICMP 8 +#define Q_IGMP 9 +#define Q_IGRP 10 -#define Q_ATALK 10 -#define Q_DECNET 11 -#define Q_LAT 12 -#define Q_SCA 13 -#define Q_MOPRC 14 -#define Q_MOPDL 15 +#define Q_ATALK 11 +#define Q_DECNET 12 +#define Q_LAT 13 +#define Q_SCA 14 +#define Q_MOPRC 15 +#define Q_MOPDL 16 -#define Q_IPV6 16 -#define Q_ICMPV6 17 -#define Q_AH 18 -#define Q_ESP 19 +#define Q_IPV6 17 +#define Q_ICMPV6 18 +#define Q_AH 19 +#define Q_ESP 20 -#define Q_PIM 20 +#define Q_PIM 21 +#define Q_VRRP 22 -#define Q_AARP 21 +#define Q_AARP 23 -#define Q_ISO 22 -#define Q_ESIS 23 -#define Q_ISIS 24 -#define Q_CLNP 25 +#define Q_ISO 24 +#define Q_ESIS 25 +#define Q_ISIS 26 +#define Q_CLNP 27 + +#define Q_STP 28 + +#define Q_IPX 29 + +#define Q_NETBEUI 30 /* Directional qualifiers. */ @@ -167,6 +176,7 @@ 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); diff --git a/contrib/libpcap/grammar.y b/contrib/libpcap/grammar.y index a73208e223eb..ea7501251ae5 100644 --- a/contrib/libpcap/grammar.y +++ b/contrib/libpcap/grammar.y @@ -23,7 +23,7 @@ */ #ifndef lint static const char rcsid[] = - "@(#) $Header: /tcpdump/master/libpcap/grammar.y,v 1.64 2000/10/28 10:18:40 guy Exp $ (LBL)"; + "@(#) $Header: /tcpdump/master/libpcap/grammar.y,v 1.71 2001/07/03 19:15:48 guy Exp $ (LBL)"; #endif #ifdef HAVE_CONFIG_H @@ -107,21 +107,25 @@ 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 ARP RARP IP SCTP TCP UDP ICMP IGMP IGRP PIM VRRP %token ATALK AARP DECNET LAT SCA MOPRC MOPDL %token TK_BROADCAST TK_MULTICAST %token NUM INBOUND OUTBOUND %token LINK %token GEQ LEQ NEQ -%token ID EID HID HID6 +%token ID EID HID HID6 AID %token LSH RSH %token LEN %token IPV6 ICMPV6 AH ESP %token VLAN %token ISO ESIS ISIS CLNP +%token STP +%token IPX +%token NETBEUI %type ID %type EID +%type AID %type HID HID6 %type NUM @@ -185,7 +189,24 @@ nid: ID { $$.b = gen_scode($1, $$.q = $0.q); } "in this configuration"); #endif /*INET6*/ } - | EID { $$.b = gen_ecode($1, $$.q = $0.q); } + | EID { + $$.b = gen_ecode($1, $$.q = $0.q); + /* + * $1 was allocated by "pcap_ether_aton()", + * so we must free it now that we're done + * with it. + */ + free($1); + } + | AID { + $$.b = gen_acode($1, $$.q = $0.q); + /* + * $1 was allocated by "pcap_ether_aton()", + * so we must free it now that we're done + * with it. + */ + free($1); + } | not id { gen_not($2.b); $$ = $2; } ; not: '!' { $$ = $0; } @@ -243,12 +264,14 @@ pname: LINK { $$ = Q_LINK; } | IP { $$ = Q_IP; } | ARP { $$ = Q_ARP; } | RARP { $$ = Q_RARP; } + | SCTP { $$ = Q_SCTP; } | TCP { $$ = Q_TCP; } | UDP { $$ = Q_UDP; } | ICMP { $$ = Q_ICMP; } | IGMP { $$ = Q_IGMP; } | IGRP { $$ = Q_IGRP; } | PIM { $$ = Q_PIM; } + | VRRP { $$ = Q_VRRP; } | ATALK { $$ = Q_ATALK; } | AARP { $$ = Q_AARP; } | DECNET { $$ = Q_DECNET; } @@ -264,6 +287,9 @@ pname: LINK { $$ = Q_LINK; } | ESIS { $$ = Q_ESIS; } | ISIS { $$ = Q_ISIS; } | CLNP { $$ = Q_CLNP; } + | STP { $$ = Q_STP; } + | IPX { $$ = Q_IPX; } + | NETBEUI { $$ = Q_NETBEUI; } ; other: pqual TK_BROADCAST { $$ = gen_broadcast($1); } | pqual TK_MULTICAST { $$ = gen_multicast($1); } diff --git a/contrib/libpcap/nametoaddr.c b/contrib/libpcap/nametoaddr.c index 437caac35659..3043a58cdf12 100644 --- a/contrib/libpcap/nametoaddr.c +++ b/contrib/libpcap/nametoaddr.c @@ -26,7 +26,7 @@ #ifndef lint static const char rcsid[] = - "@(#) $Header: /tcpdump/master/libpcap/nametoaddr.c,v 1.57.2.1 2001/01/17 18:21:56 guy Exp $ (LBL)"; + "@(#) $Header: /tcpdump/master/libpcap/nametoaddr.c,v 1.60 2001/07/28 22:56:35 guy Exp $ (LBL)"; #endif #ifdef HAVE_CONFIG_H @@ -324,7 +324,7 @@ pcap_ether_aton(const char *s) if (*s == ':') s += 1; d = xdtoi(*s++); - if (isxdigit(*s)) { + if (isxdigit((unsigned char)*s)) { d <<= 4; d |= xdtoi(*s++); } @@ -415,5 +415,6 @@ __pcap_nametodnaddr(const char *name) #else bpf_error("decnet name support not included, '%s' cannot be translated\n", name); + return(0); #endif } diff --git a/contrib/libpcap/pcap-int.h b/contrib/libpcap/pcap-int.h index 951cac0feabd..dbac5886ab03 100644 --- a/contrib/libpcap/pcap-int.h +++ b/contrib/libpcap/pcap-int.h @@ -30,8 +30,9 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * + * @(#) $Header: /tcpdump/master/libpcap/pcap-int.h,v 1.33 2001/08/24 07:46:52 guy Exp $ (LBL) + * * $FreeBSD$ - * @(#) $Header: /tcpdump/master/libpcap/pcap-int.h,v 1.32 2000/12/21 10:29:23 guy Exp $ (LBL) */ #ifndef pcap_int_h @@ -66,7 +67,6 @@ struct pcap_md { long OrigMissed; /* missed by i/f before this run */ #ifdef linux 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 */ diff --git a/contrib/libpcap/pcap.3 b/contrib/libpcap/pcap.3 index 7da4eaf65efc..76a8855ec468 100644 --- a/contrib/libpcap/pcap.3 +++ b/contrib/libpcap/pcap.3 @@ -1,4 +1,4 @@ -.\" @(#) $Header: /tcpdump/master/libpcap/pcap.3,v 1.17.2.1 2001/01/18 04:42:11 guy Exp $ +.\" @(#) $Header: /tcpdump/master/libpcap/pcap.3,v 1.31 2001/12/29 21:57:07 guy Exp $ .\" .\" Copyright (c) 1994, 1996, 1997 .\" The Regents of the University of California. All rights reserved. @@ -30,17 +30,28 @@ pcap \- Packet Capture library #include .ft .LP +.nf +.ft B +char errbuf[PCAP_ERRBUF_SIZE]; +.ft +.LP .ft B pcap_t *pcap_open_live(char *device, int snaplen, .ti +8 -int promisc, int to_ms, char *ebuf) +int promisc, int to_ms, char *errbuf) pcap_t *pcap_open_dead(int linktype, int snaplen) -pcap_t *pcap_open_offline(char *fname, char *ebuf) +pcap_t *pcap_open_offline(char *fname, char *errbuf) pcap_dumper_t *pcap_dump_open(pcap_t *p, char *fname) .ft .LP .ft B -char errbuf[PCAP_ERRBUF_SIZE]; +int pcap_setnonblock(pcap_t *p, int nonblock, char *errbuf); +int pcap_getnonblock(pcap_t *p, char *errbuf); +.ft +.LP +.ft B +int pcap_findalldevs(pcap_if_t **alldevsp, char *errbuf) +void pcap_freealldevs(pcap_if_t *) char *pcap_lookupdev(char *errbuf) int pcap_lookupnet(char *device, bpf_u_int32 *netp, .ti +8 @@ -100,9 +111,13 @@ through this mechanism. NOTE: .I errbuf in -.B pcap_open_live(), -.B pcap_open_offline(), -.B pcap_lookupdev(), +.BR pcap_open_live() , +.BR pcap_open_dead() , +.BR pcap_open_offline() , +.BR pcap_setnonblock() , +.BR pcap_getnonblock() , +.BR pcap_findalldevs() , +.BR pcap_lookupdev() , and .B pcap_lookupnet() is assumed to be able to hold at least @@ -136,11 +151,21 @@ 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 +.I errbuf +is used to return error or warning text. It will be set to error text when .B pcap_open_live() fails and returns .BR NULL . +.I errbuf +may also be set to warning text when +.B pcap_open_live() +succeds; to detect this case the caller should store a zero-length string in +.I errbuf +before calling +.B pcap_open_live() +and display the warning to the user if +.I errbuf +is no longer a zero-length string. .PP .B pcap_open_dead() is used for creating a @@ -158,7 +183,7 @@ and .BR tcpslice(1) . The name "-" in a synonym for .BR stdin . -.I ebuf +.I errbuf is used to return error text and is only set when .B pcap_open_offline() fails and returns @@ -185,6 +210,131 @@ is returned, .B pcap_geterr() can be used to get the error text. .PP +.B pcap_setnonblock() +puts a capture descriptor, opened with +.BR pcap_open_live() , +into ``non-blocking'' mode, or takes it out of ``non-blocking'' mode, +depending on whether the +.I nonblock +argument is non-zero or zero. It has no effect on ``savefiles''. +If there is an error, \-1 is returned and +.I errbuf +is filled in with an appropriate error message; otherwise, 0 is +returned. +In +``non-blocking'' mode, an attempt to read from the capture descriptor +with +.B pcap_dispatch() +will, if no packets are currently available to be read, return 0 +immediately rather than blocking waiting for packets to arrive. +.B pcap_loop() +and +.B pcap_next() +will not work in ``non-blocking'' mode. +.PP +.B pcap_getnonblock() +returns the current ``non-blocking'' state of the capture descriptor; it +always returns 0 on ``savefiles''. +If there is an error, \-1 is returned and +.I errbuf +is filled in with an appropriate error message. +.PP +.B pcap_findalldevs() +constructs a list of network devices that can be opened with +.BR pcap_open_live() . +(Note that there may be network devices that cannot be opened with +.BR pcap_open_live() +by the +process calling +.BR pcap_findalldevs() , +because, for example, that process might not have sufficient privileges +to open them for capturing; if so, those devices will not appear on the +list.) +.I alldevsp +is set to point to the first element of the list; each element of the +list is of type +.BR pcap_if_t , +and has the following members: +.RS +.TP +.B next +if not +.BR NULL , +a pointer to the next element in the list; +.B NULL +for the last element of the list +.TP +.B name +a pointer to a string giving a name for the device to pass to +.B pcap_open_live() +.TP +.B description +if not +.BR NULL , +a pointer to a string giving a human-readable description of the device +.TP +.B addresses +a pointer to the first element of a list of addresses for the interface +.TP +.B flags +interface flags: +.RS +.TP +.B PCAP_IF_LOOPBACK +set if the interface is a loopback interface +.RE +.RE +.PP +Each element of the list of addresses is of type +.BR pcap_addr_t , +and has the following members: +.RS +.TP +.B next +if not +.BR NULL , +a pointer to the next element in the list; +.B NULL +for the last element of the list +.TP +.B addr +a pointer to a +.B "struct sockaddr" +containing an address +.TP +.B netmask +if not +.BR NULL , +a pointer to a +.B "struct sockaddr" +that contains the netmask corresponding to the address pointed to by +.B addr +.TP +.B broadaddr +if not +.BR NULL , +a pointer to a +.B "struct sockaddr" +that contains the broadcast address corresponding to the address pointed +to by +.BR addr ; +may be null if the interface doesn't support broadcasts +.TP +.B dstaddr +if not +.BR NULL , +a pointer to a +.B "struct sockaddr" +that contains the destination address corresponding to the address pointed +to by +.BR addr ; +may be null if the interface isn't a point-to-point interface +.RE +.PP +.B pcap_freealldevs() +is used to free a list allocated by +.BR pcap_findalldevs() . +.PP .B pcap_lookupdev() returns a pointer to a network device suitable for use with .B pcap_open_live() @@ -286,9 +436,15 @@ causes to loop forever (or at least until an error occurs). .PP .B pcap_next() -returns a +reads the next packet (by calling +.B pcap_dispatch() +with a +.I cnt +of 1) and returns a .I u_char -pointer to the next packet. +pointer to the data in that packet. (The +.I pcap_pkthdr +struct for that packet is not supplied.) .PP .B pcap_dump() outputs a packet to the ``savefile'' opened with @@ -297,6 +453,12 @@ Note that its calling arguments are suitable for use with .B pcap_dispatch() or .BR pcap_loop() . +If called directly, the +.I user +parameter is of type +.I pcap_dumper_t +as returned by +.BR pcap_dump_open() . .PP .B pcap_compile() is used to compile the string @@ -358,8 +520,150 @@ 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 . +returns the link layer type; link layer types it can return include: +.PP +.RS 5 +.TP 5 +.B DLT_NULL +BSD loopback encapsulation; the link layer header is a 4-byte field, in +.I host +byte order, containing a PF_ value from +.B socket.h +for the network-layer protocol of the packet +.IP +Note that ``host byte order'' is the byte order of the machine on which +the packets are captured, and the PF_ values are for the OS of the +machine on which the packets are captured; if a live capture is being +done, ``host byte order'' is the byte order of the machine capturing the +packets, and the PF_ values are those of the OS of the machine capturing +the packets, but if a ``savefile'' is being read, the byte order and PF_ +values are +.I not +necessarily those of the machine reading the capture file. +.TP 5 +.B DLT_EN10MB +Ethernet (10Mb, 100Mb, 1000Mb, and up) +.TP 5 +.B DLT_IEEE802 +IEEE 802.5 Token Ring +.TP 5 +.B DLT_ARCNET +ARCNET +.TP 5 +.B DLT_SLIP +SLIP; the link layer header contains, in order: +.RS 10 +.LP +a 1-byte flag, which is 0 for packets received by the machine and 1 for +packets sent by the machine; +.LP +a 1-byte field, the upper 4 bits of which indicate the type of packet, +as per RFC 1144: +.RS 5 +.TP 5 +0x40 +an unmodified IP datagram (TYPE_IP); +.TP 5 +0x70 +an uncompressed-TCP IP datagram (UNCOMPRESSED_TCP), with that byte being +the first byte of the raw IP header on the wire, containing the +connection number in the protocol field; +.TP 5 +0x80 +a compressed-TCP IP datagram (COMPRESSED_TCP), with that byte being the +first byte of the compressed TCP/IP datagram header; +.RE +.LP +for UNCOMPRESSED_TCP, the rest of the modified IP header, and for +COMPRESSED_TCP, the compressed TCP/IP datagram header; +.RE +.RS 5 +.LP +for a total of 16 bytes; the uncompressed IP datagram follows the header +.RE +.TP 5 +.B DLT_PPP +PPP; if the first 2 bytes are 0xff and 0x03, it's PPP in HDLC-like +framing, with the PPP header following those two bytes, otherwise it's +PPP without framing, and the packet begins with the PPP header +.TP 5 +.B DLT_FDDI +FDDI +.TP 5 +.B DLT_ATM_RFC1483 +RFC 1483 LLC/SNAP-encapsulated ATM; the packet begins with an IEEE 802.2 +LLC header +.TP 5 +.B DLT_RAW +raw IP; the packet begins with an IP header +.TP 5 +.B DLT_PPP_SERIAL +PPP in HDLC-like framing, as per RFC 1662, or Cisco PPP with HDLC +framing, as per section 4.3.1 of RFC 1547; the first byte will be 0xFF +for PPP in HDLC-like framing, and will be 0x0F or 0x8F for Cisco PPP +with HDLC framing +.TP 5 +.B DLT_PPP_ETHER +PPPoE; the packet begins with a PPPoE header, as per RFC 2516 +.TP 5 +.B DLT_C_HDLC +Cisco PPP with HDLC framing, as per section 4.3.1 of RFC 1547 +.TP 5 +.B DLT_IEEE802_11 +IEEE 802.11 wireless LAN +.TP 5 +.B DLT_LOOP +OpenBSD loopback encapsulation; the link layer header is a 4-byte field, in +.I network +byte order, containing a PF_ value from OpenBSD's +.B socket.h +for the network-layer protocol of the packet +.IP +Note that, if a ``savefile'' is being read, those PF_ values are +.I not +necessarily those of the machine reading the capture file. +.TP 5 +.B DLT_LINUX_SLL +Linux "cooked" capture encapsulation; the link layer header contains, in +order: +.RS 10 +.LP +a 2-byte "packet type", in network byte order, which is one of: +.RS 5 +.TP 5 +0 +packet was sent to us by somebody else +.TP 5 +1 +packet was broadcast by somebody else +.TP 5 +2 +packet was multicast, but not broadcast, by somebody else +.TP 5 +3 +packet was sent by somebody else to somebody else +.TP 5 +4 +packet was sent by us +.RE +.LP +a 2-byte field, in network byte order, containing a Linux ARPHRD_ value +for the link layer device type; +.LP +a 2-byte field, in network byte order, containing the length of the +link layer address of the sender of the packet (which could be 0); +.LP +an 8-byte field containing that number of bytes of the link layer header +(if there are more than 8 bytes, only the first 8 are present); +.LP +a 2-byte field containing an Ethernet protocol type, in network byte +order, or containing 1 for Novell 802.3 frames without an 802.2 LLC +header or 4 for frames beginning with an 802.2 LLC header. +.RE +.TP 5 +.B DLT_LTALK +Apple LocalTalk; the packet begins with an AppleTalk LLAP header +.RE .PP .B pcap_snapshot() returns the snapshot length specified when @@ -379,21 +683,33 @@ returns the minor number of the version of the pcap used to write the savefile. .PP .B pcap_file() -returns the name of the ``savefile.'' +returns the standard I/O stream of the ``savefile,'' if a ``savefile'' +was opened with +.BR pcap_open_offline() , +or NULL, if a network device was opened with +.BR pcap_open_live() . .PP -.B int pcap_stats() +.B pcap_stats() 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 +run to the time of the call. If there is an error or the underlying packet capture doesn't support packet statistics, \-1 is returned and the error text can be obtained with .B pcap_perror() or .BR pcap_geterr() . +.B pcap_stats() +is supported only on live captures, not on ``savefiles''; no statistics +are stored in ``savefiles'', so no statistics are available when reading +from a ``savefile''. .PP .B pcap_fileno() -returns the file descriptor number of the ``savefile.'' +returns the file descriptor number from which captured packets are read, +if a network device was opened with +.BR pcap_open_live() , +or \-1, if a ``savefile'' was opened with +.BR pcap_open_offline() . .PP .B pcap_perror() prints the text of the last pcap library error on diff --git a/contrib/libpcap/pcap.h b/contrib/libpcap/pcap.h index 24cd6f9f8a80..e4ea023ffc24 100644 --- a/contrib/libpcap/pcap.h +++ b/contrib/libpcap/pcap.h @@ -1,3 +1,4 @@ +/* -*- Mode: c; tab-width: 8; indent-tabs-mode: 1; c-basic-offset: 8; -*- */ /* * Copyright (c) 1993, 1994, 1995, 1996, 1997 * The Regents of the University of California. All rights reserved. @@ -30,8 +31,9 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * + * @(#) $Header: /tcpdump/master/libpcap/pcap.h,v 1.34 2001/12/09 05:10:03 guy Exp $ (LBL) + * * $FreeBSD$ - * @(#) $Header: /tcpdump/master/libpcap/pcap.h,v 1.31 2000/10/28 00:01:31 guy Exp $ (LBL) */ #ifndef lib_pcap_h @@ -64,6 +66,8 @@ typedef u_int bpf_u_int32; typedef struct pcap pcap_t; typedef struct pcap_dumper pcap_dumper_t; +typedef struct pcap_if pcap_if_t; +typedef struct pcap_addr pcap_addr_t; /* * The first record in the file contains saved values for some @@ -129,6 +133,30 @@ struct pcap_stat { u_int ps_ifdrop; /* drops by interface XXX not yet supported */ }; +/* + * Item in a list of interfaces. + */ +struct pcap_if { + struct pcap_if *next; + char *name; /* name to hand to "pcap_open_live()" */ + char *description; /* textual description of interface, or NULL */ + struct pcap_addr *addresses; + u_int flags; /* PCAP_IF_ interface flags */ +}; + +#define PCAP_IF_LOOPBACK 0x00000001 /* interface is loopback */ + +/* + * Representation of an interface address. + */ +struct pcap_addr { + struct pcap_addr *next; + struct sockaddr *addr; /* address */ + struct sockaddr *netmask; /* netmask for that address */ + struct sockaddr *broadaddr; /* broadcast address for that address */ + struct sockaddr *dstaddr; /* P2P destination address for that address */ +}; + typedef void (*pcap_handler)(u_char *, const struct pcap_pkthdr *, const u_char *); @@ -144,6 +172,8 @@ const u_char* pcap_next(pcap_t *, struct pcap_pkthdr *); int pcap_stats(pcap_t *, struct pcap_stat *); int pcap_setfilter(pcap_t *, struct bpf_program *); +int pcap_getnonblock(pcap_t *, char *); +int pcap_setnonblock(pcap_t *, int, char *); void pcap_perror(pcap_t *, char *); char *pcap_strerror(int); char *pcap_geterr(pcap_t *); @@ -166,6 +196,9 @@ pcap_dumper_t *pcap_dump_open(pcap_t *, const char *); void pcap_dump_close(pcap_dumper_t *); void pcap_dump(u_char *, const struct pcap_pkthdr *, const u_char *); +int pcap_findalldevs(pcap_if_t **, char *); +void pcap_freealldevs(pcap_if_t *); + /* 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); diff --git a/contrib/libpcap/scanner.l b/contrib/libpcap/scanner.l index 0bf0e26e5b45..15c26733aec0 100644 --- a/contrib/libpcap/scanner.l +++ b/contrib/libpcap/scanner.l @@ -24,7 +24,7 @@ #ifndef lint static const char rcsid[] = - "@(#) $Header: /tcpdump/master/libpcap/scanner.l,v 1.70 2000/10/28 10:18:40 guy Exp $ (LBL)"; + "@(#) $Header: /tcpdump/master/libpcap/scanner.l,v 1.81 2001/09/14 01:40:57 fenner Exp $ (LBL)"; #endif #ifdef HAVE_CONFIG_H @@ -172,15 +172,29 @@ fddi|tr return LINK; arp return ARP; rarp return RARP; ip return IP; +sctp return SCTP; tcp return TCP; udp return UDP; icmp return ICMP; igmp return IGMP; igrp return IGRP; pim return PIM; +vrrp return VRRP; -ip6 return IPV6; -icmp6 return ICMPV6; +ip6 { +#ifdef INET6 + return IPV6; +#else + bpf_error("%s not supported", yytext); +#endif + } +icmp6 { +#ifdef INET6 + return ICMPV6; +#else + bpf_error("%s not supported", yytext); +#endif + } ah return AH; esp return ESP; @@ -199,6 +213,12 @@ isis return ISIS; is-is return ISIS; clnp return CLNP; +stp return STP; + +ipx return IPX; + +netbeui return NETBEUI; + host return HOST; net return NET; mask return MASK; @@ -238,6 +258,8 @@ vlan return VLAN; "==" 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; } @@ -259,11 +281,35 @@ vlan return VLAN; #endif /*INET6*/ } {B}:+({B}:+)+ { bpf_error("bogus ethernet address %s", yytext); } -[A-Za-z0-9][-_.A-Za-z0-9]*[.A-Za-z0-9] { +icmptype { yylval.i = 0; return NUM; } +icmpcode { yylval.i = 1; return NUM; } +icmp-echoreply { yylval.i = 0; return NUM; } +icmp-unreach { yylval.i = 3; return NUM; } +icmp-sourcequench { yylval.i = 4; return NUM; } +icmp-redirect { yylval.i = 5; return NUM; } +icmp-echo { yylval.i = 8; return NUM; } +icmp-routeradvert { yylval.i = 9; return NUM; } +icmp-routersolicit { yylval.i = 10; return NUM; } +icmp-timxceed { yylval.i = 11; return NUM; } +icmp-paramprob { yylval.i = 12; return NUM; } +icmp-tstamp { yylval.i = 13; return NUM; } +icmp-tstampreply { yylval.i = 14; return NUM; } +icmp-ireq { yylval.i = 15; return NUM; } +icmp-ireqreply { yylval.i = 16; return NUM; } +icmp-maskreq { yylval.i = 17; return NUM; } +icmp-maskreply { yylval.i = 18; return NUM; } +tcpflags { yylval.i = 13; return NUM; } +tcp-fin { yylval.i = 0x01; return NUM; } +tcp-syn { yylval.i = 0x02; return NUM; } +tcp-rst { yylval.i = 0x04; return NUM; } +tcp-push { yylval.i = 0x08; return NUM; } +tcp-ack { yylval.i = 0x10; return NUM; } +tcp-urg { yylval.i = 0x20; return NUM; } +[A-Za-z0-9]([-_.A-Za-z0-9]*[.A-Za-z0-9])? { yylval.s = sdup((char *)yytext); return ID; } "\\"[^ !()\n\t]+ { yylval.s = sdup((char *)yytext + 1); return ID; } -[^ \[\]\t\n\-_.A-Za-z0-9!<>()&|=]+i { - bpf_error("illegal token: %s\n", yytext); } +[^ \[\]\t\n\-_.A-Za-z0-9!<>()&|=]+ { + bpf_error("illegal token: %s", yytext); } . { bpf_error("illegal char '%c'", *yytext); } %% void