diff --git a/contrib/libpcap/gencode.c b/contrib/libpcap/gencode.c index 41957af5078e..9fa89f23d4fe 100644 --- a/contrib/libpcap/gencode.c +++ b/contrib/libpcap/gencode.c @@ -23,7 +23,7 @@ */ #ifndef lint static const char rcsid[] _U_ = - "@(#) $Header: /tcpdump/master/libpcap/gencode.c,v 1.193.2.8 2004/03/29 20:53:47 guy Exp $ (LBL)"; + "@(#) $Header: /tcpdump/master/libpcap/gencode.c,v 1.221 2005/03/27 22:10:23 guy Exp $ (LBL)"; #endif #ifdef HAVE_CONFIG_H @@ -35,7 +35,6 @@ static const char rcsid[] _U_ = #else /* WIN32 */ #include #include -#include #endif /* WIN32 */ /* @@ -61,6 +60,10 @@ static const char rcsid[] _U_ = #include #include +#ifdef MSDOS +#include "pcap-dos.h" +#endif + #include "pcap-int.h" #include "ethertype.h" @@ -100,14 +103,12 @@ static const char rcsid[] _U_ = static jmp_buf top_ctx; static pcap_t *bpf_pcap; -/* Hack for updating VLAN offsets. */ -static u_int orig_linktype = -1, orig_nl = -1, orig_nl_nosnap = -1; +/* Hack for updating VLAN, MPLS offsets. */ +static u_int orig_linktype = -1U, orig_nl = -1U, orig_nl_nosnap = -1U; /* XXX */ #ifdef PCAP_FDDIPAD -int pcap_fddipad = PCAP_FDDIPAD; -#else -int pcap_fddipad; +static int pcap_fddipad; #endif /* VARARGS */ @@ -126,7 +127,7 @@ bpf_error(const char *fmt, ...) /* NOTREACHED */ } -static void init_linktype(int); +static void init_linktype(pcap_t *); static int alloc_reg(void); static void free_reg(int); @@ -136,8 +137,10 @@ static struct block *root; /* * We divy out chunks of memory rather than call malloc each time so * we don't have to worry about leaking memory. It's probably - * not a big deal if all this memory was wasted but it this ever + * not a big deal if all this memory was wasted but if this ever * goes into a library that would probably not be a good idea. + * + * XXX - this *is* in a library.... */ #define NCHUNKS 16 #define CHUNK0SIZE 1024 @@ -168,6 +171,7 @@ static struct block *gen_uncond(int); static inline struct block *gen_true(void); static inline struct block *gen_false(void); static struct block *gen_ether_linktype(int); +static struct block *gen_linux_sll_linktype(int); static struct block *gen_linktype(int); static struct block *gen_snap(bpf_u_int32, bpf_u_int32, u_int); static struct block *gen_llc(int); @@ -343,7 +347,7 @@ pcap_compile(pcap_t *p, struct bpf_program *program, } lex_init(buf ? buf : ""); - init_linktype(pcap_datalink(p)); + init_linktype(p); (void)pcap_parse(); if (n_errors) @@ -580,15 +584,15 @@ gen_ncmp(datasize, offset, mask, jtype, jvalue, reverse) { struct slist *s; struct block *b; - + s = new_stmt(BPF_LD|datasize|BPF_ABS); s->s.k = offset; - + if (mask != 0xffffffff) { s->next = new_stmt(BPF_ALU|BPF_AND|BPF_K); s->next->s.k = mask; } - + b = new_block(JMP(jtype)); b->stmts = s; b->s.k = jvalue; @@ -681,10 +685,13 @@ static u_int off_nl_nosnap; static int linktype; static void -init_linktype(type) - int type; +init_linktype(p) + pcap_t *p; { - linktype = type; + linktype = pcap_datalink(p); +#ifdef PCAP_FDDIPAD + pcap_fddipad = p->fddipad; +#endif /* * Assume it's not raw ATM with a pseudo-header, for now. @@ -701,7 +708,7 @@ init_linktype(type) orig_nl = -1; orig_nl_nosnap = -1; - switch (type) { + switch (linktype) { case DLT_ARCNET: off_linktype = 2; @@ -753,6 +760,7 @@ init_linktype(type) return; case DLT_PPP: + case DLT_PPP_PPPD: case DLT_C_HDLC: /* BSD/OS Cisco HDLC */ case DLT_PPP_SERIAL: /* NetBSD sync/async serial PPP */ off_linktype = 2; @@ -925,7 +933,7 @@ init_linktype(type) off_vpi = SUNATM_VPI_POS; off_vci = SUNATM_VCI_POS; off_proto = PROTO_POS; - off_mac = -1; /* LLC-encapsulated, so no MAC-layer header */ + off_mac = -1; /* LLC-encapsulated, so no MAC-layer header */ off_payload = SUNATM_PKT_BEGIN_POS; off_linktype = off_payload; off_nl = off_payload+8; /* 802.2+SNAP */ @@ -996,6 +1004,21 @@ init_linktype(type) off_nl_nosnap = -1; return; + case DLT_DOCSIS: + /* + * Currently, only raw "link[N:M]" filtering is supported. + */ + off_linktype = -1; + off_nl = -1; + off_nl_nosnap = -1; + return; + + case DLT_SYMANTEC_FIREWALL: + off_linktype = 6; + off_nl = 44; /* Ethernet II */ + off_nl_nosnap = 44; /* XXX - what does it do with 802.3 packets? */ + return; + case DLT_PFLOG: off_linktype = 0; /* XXX read from header? */ @@ -1003,6 +1026,25 @@ init_linktype(type) off_nl_nosnap = PFLOG_HDRLEN; return; + case DLT_JUNIPER_MLFR: + case DLT_JUNIPER_MLPPP: + off_linktype = 4; + off_nl = 4; + off_nl_nosnap = -1; + return; + + case DLT_JUNIPER_ATM1: + off_linktype = 4; /* in reality variable between 4-8 */ + off_nl = 4; + off_nl_nosnap = 14; + return; + + case DLT_JUNIPER_ATM2: + off_linktype = 8; /* in reality variable between 8-12 */ + off_nl = 8; + off_nl_nosnap = 18; + return; + #ifdef DLT_PFSYNC case DLT_PFSYNC: off_linktype = -1; @@ -1234,6 +1276,172 @@ gen_ether_linktype(proto) } } +static struct block * +gen_linux_sll_linktype(proto) + register int proto; +{ + struct block *b0, *b1; + + switch (proto) { + + case LLCSAP_IP: + b0 = gen_cmp(off_linktype, BPF_H, LINUX_SLL_P_802_2); + b1 = gen_cmp(off_linktype + 2, BPF_H, (bpf_int32) + ((LLCSAP_IP << 8) | LLCSAP_IP)); + gen_and(b0, b1); + return b1; + + 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(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); + } + } +} + static struct block * gen_linktype(proto) register int proto; @@ -1244,6 +1452,7 @@ gen_linktype(proto) case DLT_EN10MB: return gen_ether_linktype(proto); + /*NOTREACHED*/ break; case DLT_C_HDLC: @@ -1255,6 +1464,7 @@ gen_linktype(proto) default: return gen_cmp(off_linktype, BPF_H, (bpf_int32)proto); + /*NOTREACHED*/ break; } break; @@ -1268,6 +1478,7 @@ gen_linktype(proto) case DLT_ATM_CLIP: case DLT_IP_OVER_FC: return gen_llc(proto); + /*NOTREACHED*/ break; case DLT_SUNATM: @@ -1305,164 +1516,8 @@ gen_linktype(proto) } case DLT_LINUX_SLL: - switch (proto) { - - case LLCSAP_IP: - b0 = gen_cmp(off_linktype, BPF_H, LINUX_SLL_P_802_2); - b1 = gen_cmp(off_linktype + 2, BPF_H, (bpf_int32) - ((LLCSAP_IP << 8) | LLCSAP_IP)); - gen_and(b0, b1); - return b1; - - 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); - } - } + return gen_linux_sll_linktype(proto); + /*NOTREACHED*/ break; case DLT_SLIP: @@ -1486,9 +1541,11 @@ gen_linktype(proto) default: return gen_false(); /* always false */ } + /*NOTREACHED*/ break; case DLT_PPP: + case DLT_PPP_PPPD: case DLT_PPP_SERIAL: case DLT_PPP_ETHER: /* @@ -1672,6 +1729,7 @@ gen_linktype(proto) #endif /* INET6 */ else return gen_false(); + /*NOTREACHED*/ break; case DLT_ARCNET: @@ -1692,7 +1750,7 @@ gen_linktype(proto) #endif /* INET6 */ case ETHERTYPE_IP: - b0 = gen_cmp(off_linktype, BPF_B, + b0 = gen_cmp(off_linktype, BPF_B, (bpf_int32)ARCTYPE_IP); b1 = gen_cmp(off_linktype, BPF_B, (bpf_int32)ARCTYPE_IP_OLD); @@ -1702,7 +1760,7 @@ gen_linktype(proto) case ETHERTYPE_ARP: b0 = gen_cmp(off_linktype, BPF_B, (bpf_int32)ARCTYPE_ARP); - b1 = gen_cmp(off_linktype, BPF_B, + b1 = gen_cmp(off_linktype, BPF_B, (bpf_int32)ARCTYPE_ARP_OLD); gen_or(b0, b1); return (b1); @@ -1715,6 +1773,7 @@ gen_linktype(proto) return (gen_cmp(off_linktype, BPF_B, (bpf_int32)ARCTYPE_ATALK)); } + /*NOTREACHED*/ break; case DLT_LTALK: @@ -1724,6 +1783,7 @@ gen_linktype(proto) default: return gen_false(); } + /*NOTREACHED*/ break; case DLT_FRELAY: @@ -1769,10 +1829,27 @@ gen_linktype(proto) default: return gen_false(); } + /*NOTREACHED*/ break; + case DLT_JUNIPER_MLFR: + case DLT_JUNIPER_MLPPP: + case DLT_JUNIPER_ATM1: + case DLT_JUNIPER_ATM2: + /* just lets verify the magic number for now - + * on ATM we may have up to 6 different encapsulations on the wire + * and need a lot of heuristics to figure out that the payload + * might be; + * + * FIXME encapsulation specific BPF_ filters + */ + return gen_mcmp(0, BPF_W, 0x4d474300, 0xffffff00); /* compare the magic number */ + case DLT_LINUX_IRDA: - bpf_error("IrDA link-layer type filtering not implemented"); + bpf_error("IrDA link-layer type filtering not implemented"); + + case DLT_DOCSIS: + bpf_error("DOCSIS link-layer type filtering not implemented"); } /* @@ -2507,7 +2584,7 @@ gen_dnhostop(addr, dir, base_off) return b1; case Q_ISO: - bpf_error("ISO host filtering not implemented"); + bpf_error("ISO host filtering not implemented"); default: abort(); @@ -2981,91 +3058,91 @@ gen_proto_abbrev(proto) break; case Q_ISO: - b1 = gen_linktype(LLCSAP_ISONS); + b1 = gen_linktype(LLCSAP_ISONS); break; case Q_ESIS: - b1 = gen_proto(ISO9542_ESIS, Q_ISO, Q_DEFAULT); + b1 = gen_proto(ISO9542_ESIS, Q_ISO, Q_DEFAULT); break; case Q_ISIS: - b1 = gen_proto(ISO10589_ISIS, Q_ISO, Q_DEFAULT); + b1 = gen_proto(ISO10589_ISIS, Q_ISO, Q_DEFAULT); break; case Q_ISIS_L1: /* all IS-IS Level1 PDU-Types */ - b0 = gen_proto(ISIS_L1_LAN_IIH, Q_ISIS, Q_DEFAULT); - b1 = gen_proto(ISIS_PTP_IIH, Q_ISIS, Q_DEFAULT); /* FIXME extract the circuit-type bits */ + b0 = gen_proto(ISIS_L1_LAN_IIH, Q_ISIS, Q_DEFAULT); + b1 = gen_proto(ISIS_PTP_IIH, Q_ISIS, Q_DEFAULT); /* FIXME extract the circuit-type bits */ gen_or(b0, b1); - b0 = gen_proto(ISIS_L1_LSP, Q_ISIS, Q_DEFAULT); + b0 = gen_proto(ISIS_L1_LSP, Q_ISIS, Q_DEFAULT); gen_or(b0, b1); - b0 = gen_proto(ISIS_L1_CSNP, Q_ISIS, Q_DEFAULT); + b0 = gen_proto(ISIS_L1_CSNP, Q_ISIS, Q_DEFAULT); gen_or(b0, b1); - b0 = gen_proto(ISIS_L1_PSNP, Q_ISIS, Q_DEFAULT); + b0 = gen_proto(ISIS_L1_PSNP, Q_ISIS, Q_DEFAULT); gen_or(b0, b1); break; case Q_ISIS_L2: /* all IS-IS Level2 PDU-Types */ - b0 = gen_proto(ISIS_L2_LAN_IIH, Q_ISIS, Q_DEFAULT); - b1 = gen_proto(ISIS_PTP_IIH, Q_ISIS, Q_DEFAULT); /* FIXME extract the circuit-type bits */ + b0 = gen_proto(ISIS_L2_LAN_IIH, Q_ISIS, Q_DEFAULT); + b1 = gen_proto(ISIS_PTP_IIH, Q_ISIS, Q_DEFAULT); /* FIXME extract the circuit-type bits */ gen_or(b0, b1); - b0 = gen_proto(ISIS_L2_LSP, Q_ISIS, Q_DEFAULT); + b0 = gen_proto(ISIS_L2_LSP, Q_ISIS, Q_DEFAULT); gen_or(b0, b1); - b0 = gen_proto(ISIS_L2_CSNP, Q_ISIS, Q_DEFAULT); + b0 = gen_proto(ISIS_L2_CSNP, Q_ISIS, Q_DEFAULT); gen_or(b0, b1); - b0 = gen_proto(ISIS_L2_PSNP, Q_ISIS, Q_DEFAULT); + b0 = gen_proto(ISIS_L2_PSNP, Q_ISIS, Q_DEFAULT); gen_or(b0, b1); break; case Q_ISIS_IIH: /* all IS-IS Hello PDU-Types */ - b0 = gen_proto(ISIS_L1_LAN_IIH, Q_ISIS, Q_DEFAULT); - b1 = gen_proto(ISIS_L2_LAN_IIH, Q_ISIS, Q_DEFAULT); + b0 = gen_proto(ISIS_L1_LAN_IIH, Q_ISIS, Q_DEFAULT); + b1 = gen_proto(ISIS_L2_LAN_IIH, Q_ISIS, Q_DEFAULT); gen_or(b0, b1); - b0 = gen_proto(ISIS_PTP_IIH, Q_ISIS, Q_DEFAULT); + b0 = gen_proto(ISIS_PTP_IIH, Q_ISIS, Q_DEFAULT); gen_or(b0, b1); break; - case Q_ISIS_LSP: - b0 = gen_proto(ISIS_L1_LSP, Q_ISIS, Q_DEFAULT); - b1 = gen_proto(ISIS_L2_LSP, Q_ISIS, Q_DEFAULT); + case Q_ISIS_LSP: + b0 = gen_proto(ISIS_L1_LSP, Q_ISIS, Q_DEFAULT); + b1 = gen_proto(ISIS_L2_LSP, Q_ISIS, Q_DEFAULT); gen_or(b0, b1); break; case Q_ISIS_SNP: - b0 = gen_proto(ISIS_L1_CSNP, Q_ISIS, Q_DEFAULT); - b1 = gen_proto(ISIS_L2_CSNP, Q_ISIS, Q_DEFAULT); + b0 = gen_proto(ISIS_L1_CSNP, Q_ISIS, Q_DEFAULT); + b1 = gen_proto(ISIS_L2_CSNP, Q_ISIS, Q_DEFAULT); gen_or(b0, b1); - b0 = gen_proto(ISIS_L1_PSNP, Q_ISIS, Q_DEFAULT); + b0 = gen_proto(ISIS_L1_PSNP, Q_ISIS, Q_DEFAULT); gen_or(b0, b1); - b0 = gen_proto(ISIS_L2_PSNP, Q_ISIS, Q_DEFAULT); + b0 = gen_proto(ISIS_L2_PSNP, Q_ISIS, Q_DEFAULT); gen_or(b0, b1); break; case Q_ISIS_CSNP: - b0 = gen_proto(ISIS_L1_CSNP, Q_ISIS, Q_DEFAULT); - b1 = gen_proto(ISIS_L2_CSNP, Q_ISIS, Q_DEFAULT); + b0 = gen_proto(ISIS_L1_CSNP, Q_ISIS, Q_DEFAULT); + b1 = gen_proto(ISIS_L2_CSNP, Q_ISIS, Q_DEFAULT); gen_or(b0, b1); break; case Q_ISIS_PSNP: - b0 = gen_proto(ISIS_L1_PSNP, Q_ISIS, Q_DEFAULT); - b1 = gen_proto(ISIS_L2_PSNP, Q_ISIS, Q_DEFAULT); + b0 = gen_proto(ISIS_L1_PSNP, Q_ISIS, Q_DEFAULT); + b1 = gen_proto(ISIS_L2_PSNP, Q_ISIS, Q_DEFAULT); gen_or(b0, b1); break; case Q_CLNP: - b1 = gen_proto(ISO8473_CLNP, Q_ISO, Q_DEFAULT); + b1 = gen_proto(ISO8473_CLNP, Q_ISO, Q_DEFAULT); break; case Q_STP: - b1 = gen_linktype(LLCSAP_8021D); + b1 = gen_linktype(LLCSAP_8021D); break; case Q_IPX: - b1 = gen_linktype(LLCSAP_IPX); + b1 = gen_linktype(LLCSAP_IPX); break; case Q_NETBEUI: - b1 = gen_linktype(LLCSAP_NETBEUI); + b1 = gen_linktype(LLCSAP_NETBEUI); break; default: @@ -3306,8 +3383,11 @@ lookup_proto(name, proto) case Q_LINK: /* XXX should look up h/w protocol type based on linktype */ v = pcap_nametoeproto(name); - if (v == PROTO_UNDEF) - bpf_error("unknown ether proto '%s'", name); + if (v == PROTO_UNDEF) { + v = pcap_nametollc(name); + if (v == PROTO_UNDEF) + bpf_error("unknown ether proto '%s'", name); + } break; case Q_ISO: @@ -3699,6 +3779,7 @@ gen_proto(v, proto, dir) * XXX - what about SNAP-encapsulated frames? */ return gen_cmp(2, BPF_H, (0x03<<8) | v); + /*NOTREACHED*/ break; case DLT_C_HDLC: @@ -4139,6 +4220,7 @@ gen_mcode(s1, s2, masklen, q) bpf_error("Mask syntax for networks only"); /* NOTREACHED */ } + /* NOTREACHED */ } struct block * @@ -4773,6 +4855,7 @@ gen_broadcast(proto) return b2; } bpf_error("only link-layer/IP broadcast filters supported"); + /* NOTREACHED */ } /* @@ -4989,6 +5072,7 @@ gen_multicast(proto) #endif /* INET6 */ } bpf_error("link-layer multicast filters supported only on ethernet/FDDI/token ring/ARCNET/802.11/ATM LANE/Fibre Channel"); + /* NOTREACHED */ } /* @@ -5039,6 +5123,31 @@ gen_inbound(dir) (bpf_int32)((dir == 0) ? PF_IN : PF_OUT)); break; + case DLT_PPP_PPPD: + if (dir) { + /* match outgoing packets */ + b0 = gen_cmp(0, BPF_B, PPP_PPPD_OUT); + } else { + /* match incoming packets */ + b0 = gen_cmp(0, BPF_B, PPP_PPPD_IN); + } + break; + + case DLT_JUNIPER_MLFR: + case DLT_JUNIPER_MLPPP: + case DLT_JUNIPER_ATM1: + case DLT_JUNIPER_ATM2: + /* juniper flags (including direction) are stored + * the byte after the 3-byte magic number */ + if (dir) { + /* match outgoing packets */ + b0 = gen_mcmp(3, BPF_B, 0, 0x01); + } else { + /* match incoming packets */ + b0 = gen_mcmp(3, BPF_B, 1, 0x01); + } + break; + default: bpf_error("inbound/outbound not supported on linktype %d", linktype); @@ -5067,7 +5176,7 @@ gen_pf_ifname(const char *ifname) len-1); /* NOTREACHED */ } - b0 = gen_bcmp(off, strlen(ifname), ifname); + b0 = gen_bcmp(off, strlen(ifname), (const u_char *)ifname); return (b0); } @@ -5087,7 +5196,7 @@ gen_pf_ruleset(char *ruleset) /* NOTREACHED */ } b0 = gen_bcmp(offsetof(struct pfloghdr, ruleset), - strlen(ruleset), ruleset); + strlen(ruleset), (const u_char *)ruleset); return (b0); } @@ -5243,7 +5352,80 @@ gen_vlan(vlan_num) if (vlan_num >= 0) { struct block *b1; - b1 = gen_cmp(orig_nl, BPF_H, (bpf_int32)vlan_num); + b1 = gen_mcmp(orig_nl, BPF_H, (bpf_int32)vlan_num, 0x0fff); + gen_and(b0, b1); + b0 = b1; + } + + return (b0); +} + +/* + * support for MPLS + */ +struct block * +gen_mpls(label_num) + int label_num; +{ + struct block *b0; + + /* + * Change the offsets to point to the type and data fields within + * the MPLS packet. This is somewhat of a kludge. + */ + if (orig_nl == (u_int)-1) { + orig_linktype = off_linktype; /* save original values */ + orig_nl = off_nl; + orig_nl_nosnap = off_nl_nosnap; + + switch (linktype) { + + case DLT_EN10MB: + off_linktype = 16; + off_nl_nosnap = 18; + off_nl = 18; + + b0 = gen_cmp(orig_linktype, BPF_H, (bpf_int32)ETHERTYPE_MPLS); + break; + + case DLT_PPP: + off_linktype = 6; + off_nl_nosnap = 8; + off_nl = 8; + + b0 = gen_cmp(orig_linktype, BPF_H, (bpf_int32)PPP_MPLS_UCAST); + break; + + case DLT_C_HDLC: + off_linktype = 6; + off_nl_nosnap = 8; + off_nl = 8; + + b0 = gen_cmp(orig_linktype, BPF_H, (bpf_int32)ETHERTYPE_MPLS); + break; + + /* FIXME add other DLT_s ... + * for Frame-Relay/and ATM this may get messy due to SNAP headers + * leave it for now */ + + default: + bpf_error("no MPLS support for data link type %d", + linktype); + b0 = NULL; + /*NOTREACHED*/ + } + } else { + bpf_error("'mpls' can't be combined with 'vlan' or another 'mpls'"); + b0 = NULL; + /*NOTREACHED*/ + } + + /* If a specific MPLS label is requested, check it */ + if (label_num >= 0) { + struct block *b1; + + label_num = label_num << 12; /* label is shifted 12 bits on the wire */ + b1 = gen_mcmp(orig_nl, BPF_W, (bpf_int32)label_num, 0xfffff000); /* only compare the first 20 bits */ gen_and(b0, b1); b0 = b1; } @@ -5428,15 +5610,15 @@ gen_msg_abbrev(type) break; case A_CALLPROCEED: - b1 = gen_atmfield_code(A_MSGTYPE, CALL_PROCEED, BPF_JEQ, 0); + b1 = gen_atmfield_code(A_MSGTYPE, CALL_PROCEED, BPF_JEQ, 0); break; case A_CONNECT: b1 = gen_atmfield_code(A_MSGTYPE, CONNECT, BPF_JEQ, 0); - break; + break; case A_CONNECTACK: - b1 = gen_atmfield_code(A_MSGTYPE, CONNECT_ACK, BPF_JEQ, 0); + b1 = gen_atmfield_code(A_MSGTYPE, CONNECT_ACK, BPF_JEQ, 0); break; case A_RELEASE: @@ -5444,7 +5626,7 @@ gen_msg_abbrev(type) break; case A_RELEASE_DONE: - b1 = gen_atmfield_code(A_MSGTYPE, RELEASE_DONE, BPF_JEQ, 0); + b1 = gen_atmfield_code(A_MSGTYPE, RELEASE_DONE, BPF_JEQ, 0); break; default: @@ -5471,9 +5653,9 @@ gen_atmmulti_abbrev(type) if (!is_atm) bpf_error("'oamf4' supported only on raw ATM"); /* OAM F4 type */ - b0 = gen_atmfield_code(A_VCI, 3, BPF_JEQ, 0); + b0 = gen_atmfield_code(A_VCI, 3, BPF_JEQ, 0); b1 = gen_atmfield_code(A_VCI, 4, BPF_JEQ, 0); - gen_or(b0, b1); + gen_or(b0, b1); b0 = gen_atmfield_code(A_VPI, 0, BPF_JEQ, 0); gen_and(b0, b1); break; diff --git a/contrib/libpcap/gencode.h b/contrib/libpcap/gencode.h index fccdf3c961bf..a7cf9995700e 100644 --- a/contrib/libpcap/gencode.h +++ b/contrib/libpcap/gencode.h @@ -19,7 +19,7 @@ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. * * $FreeBSD$ - * @(#) $Header: /tcpdump/master/libpcap/gencode.h,v 1.58.2.1 2004/03/28 21:45:31 fenner Exp $ (LBL) + * @(#) $Header: /tcpdump/master/libpcap/gencode.h,v 1.60 2004/06/16 08:20:30 hannes Exp $ (LBL) */ /* @@ -274,6 +274,7 @@ struct block *gen_multicast(int); struct block *gen_inbound(int); struct block *gen_vlan(int); +struct block *gen_mpls(int); struct block *gen_atmfield_code(int atmfield, bpf_u_int32 jvalue, bpf_u_int32 jtype, int reverse); struct block *gen_atmtype_abbrev(int type); diff --git a/contrib/libpcap/grammar.y b/contrib/libpcap/grammar.y index 63ca86311242..0d414998580d 100644 --- a/contrib/libpcap/grammar.y +++ b/contrib/libpcap/grammar.y @@ -23,7 +23,7 @@ */ #ifndef lint static const char rcsid[] _U_ = - "@(#) $Header: /tcpdump/master/libpcap/grammar.y,v 1.79.2.3 2004/03/28 21:45:32 fenner Exp $ (LBL)"; + "@(#) $Header: /tcpdump/master/libpcap/grammar.y,v 1.86 2004/12/18 08:49:23 guy Exp $ (LBL)"; #endif #ifdef HAVE_CONFIG_H @@ -34,7 +34,6 @@ static const char rcsid[] _U_ = #include #else /* WIN32 */ #include -#include #include #endif /* WIN32 */ @@ -50,7 +49,6 @@ struct rtentry; #endif /* WIN32 */ #include -#include #include "pcap-int.h" @@ -129,7 +127,7 @@ pcap_parse() %token LSH RSH %token LEN %token IPV6 ICMPV6 AH ESP -%token VLAN +%token VLAN MPLS %token ISO ESIS CLNP ISIS L1 L2 IIH LSP SNP CSNP PSNP %token STP %token IPX @@ -325,6 +323,8 @@ other: pqual TK_BROADCAST { $$ = gen_broadcast($1); } | OUTBOUND { $$ = gen_inbound(1); } | VLAN pnum { $$ = gen_vlan($2); } | VLAN { $$ = gen_vlan(-1); } + | MPLS pnum { $$ = gen_mpls($2); } + | MPLS { $$ = gen_mpls(-1); } | pfvar { $$ = $1; } ; diff --git a/contrib/libpcap/nametoaddr.c b/contrib/libpcap/nametoaddr.c index 678163e31449..d58e794d259d 100644 --- a/contrib/libpcap/nametoaddr.c +++ b/contrib/libpcap/nametoaddr.c @@ -26,7 +26,7 @@ #ifndef lint static const char rcsid[] _U_ = - "@(#) $Header: /tcpdump/master/libpcap/nametoaddr.c,v 1.68.2.3 2003/11/19 18:13:48 guy Exp $ (LBL)"; + "@(#) $Header: /tcpdump/master/libpcap/nametoaddr.c,v 1.77 2005/03/27 22:26:25 guy Exp $ (LBL)"; #endif #ifdef HAVE_CONFIG_H @@ -55,12 +55,19 @@ static const char rcsid[] _U_ = #ifndef WIN32 #ifdef HAVE_ETHER_HOSTTON +/* + * XXX - do we need any of this if doesn't declare + * ether_hostton()? + */ #ifdef HAVE_NETINET_IF_ETHER_H struct mbuf; /* Squelch compiler warnings on some platforms for */ struct rtentry; /* declarations in */ #include /* for "struct ifnet" in "struct arpcom" on Solaris */ #include #endif /* HAVE_NETINET_IF_ETHER_H */ +#ifdef NETINET_ETHER_H_DECLARES_ETHER_HOSTTON +#include +#endif /* NETINET_ETHER_H_DECLARES_ETHER_HOSTTON */ #endif /* HAVE_ETHER_HOSTTON */ #include #include @@ -126,6 +133,7 @@ pcap_nametoaddrinfo(const char *name) memset(&hints, 0, sizeof(hints)); hints.ai_family = PF_UNSPEC; hints.ai_socktype = SOCK_STREAM; /*not really*/ + hints.ai_protocol = IPPROTO_TCP; /*not really*/ error = getaddrinfo(name, NULL, &hints, &res); if (error) return NULL; @@ -278,6 +286,30 @@ pcap_nametoeproto(const char *s) return PROTO_UNDEF; } +#include "llc.h" + +/* Static data base of LLC values. */ +static struct eproto llc_db[] = { + { "iso", LLCSAP_ISONS }, + { "stp", LLCSAP_8021D }, + { "ipx", LLCSAP_IPX }, + { "netbeui", LLCSAP_NETBEUI }, + { (char *)0, 0 } +}; + +int +pcap_nametollc(const char *s) +{ + struct eproto *p = llc_db; + + while (p->s != 0) { + if (strcmp(p->s, s) == 0) + return p->p; + p += 1; + } + return PROTO_UNDEF; +} + /* Hex digit to integer. */ static inline int xdtoi(c) @@ -391,18 +423,8 @@ 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__) && \ - !defined(_UNICOSMP) -extern int ether_hostton(char *, struct ether_addr *); +#if !defined(HAVE_DECL_ETHER_HOSTTON) || !HAVE_DECL_ETHER_HOSTTON +extern int ether_hostton(const char *, struct ether_addr *); #endif /* Use the os supplied routines */ diff --git a/contrib/libpcap/pcap-int.h b/contrib/libpcap/pcap-int.h index 9da493bb89ad..260062b91984 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.55.2.4 2003/12/15 01:42:24 guy Exp $ (LBL) + * @(#) $Header: /tcpdump/master/libpcap/pcap-int.h,v 1.68 2004/12/18 08:52:10 guy Exp $ (LBL) */ #ifndef pcap_int_h @@ -47,6 +47,11 @@ extern "C" { #include #endif /* WIN32 */ +#ifdef MSDOS +#include +#include +#endif + /* * Savefile */ @@ -75,13 +80,14 @@ struct pcap_md { 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 */ + char *device; /* device name */ #ifdef linux int sock_packet; /* using Linux 2.0 compatible interface */ 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 ifindex; /* interface index of device we're bound to */ int lo_ifindex; /* interface index of the loopback device */ - char *device; /* device name */ struct pcap *next; /* list of open promiscuous sock_packet pcaps */ #endif @@ -90,7 +96,7 @@ struct pcap_md { u_int dag_mem_bottom; /* DAG card current memory bottom pointer */ u_int dag_mem_top; /* DAG card current memory top pointer */ int dag_fcs_bits; /* Number of checksum bits from link layer */ - int dag_offset_flags; /* Flags to pass to dag_offset(). */ + int dag_offset_flags; /* Flags to pass to dag_offset(). */ #endif }; @@ -103,6 +109,7 @@ struct pcap { #else int fd; int selectable_fd; + int send_fd; #endif /* WIN32 */ int snapshot; int linktype; @@ -111,6 +118,15 @@ struct pcap { int break_loop; /* flag set to force break from packet-reading loop */ +#ifdef PCAP_FDDIPAD + int fddipad; +#endif + +#ifdef MSDOS + int inter_packet_wait; /* offline: wait between packets */ + void (*wait_proc)(void); /* call proc while waiting */ +#endif + struct pcap_sf sf; struct pcap_md md; @@ -131,6 +147,7 @@ struct pcap { * Methods. */ int (*read_op)(pcap_t *, int cnt, pcap_handler, u_char *); + int (*inject_op)(pcap_t *, const void *, size_t); int (*setfilter_op)(pcap_t *, struct bpf_program *); int (*set_datalink_op)(pcap_t *, int); int (*getnonblock_op)(pcap_t *, char *); @@ -145,7 +162,7 @@ struct pcap { char errbuf[PCAP_ERRBUF_SIZE + 1]; int dlt_count; - int *dlt_list; + u_int *dlt_list; struct pcap_pkthdr pcap_header; /* This is needed for the pcap_next_ex() to work */ }; @@ -236,11 +253,13 @@ int pcap_read(pcap_t *, int cnt, pcap_handler, u_char *); /* * Routines that most pcap implementations can use for non-blocking mode. */ -#ifndef WIN32 +#if !defined(WIN32) && !defined(MSDOS) int pcap_getnonblock_fd(pcap_t *, char *); int pcap_setnonblock_fd(pcap_t *p, int, char *); #endif +void pcap_close_common(pcap_t *); + /* * Internal interfaces for "pcap_findalldevs()". * @@ -251,10 +270,10 @@ int pcap_setnonblock_fd(pcap_t *p, int, char *); * "pcap_add_if()" adds an interface to the list of interfaces. */ int pcap_platform_finddevs(pcap_if_t **, char *); -int add_addr_to_iflist(pcap_if_t **, char *, u_int, struct sockaddr *, +int add_addr_to_iflist(pcap_if_t **, const char *, u_int, struct sockaddr *, size_t, struct sockaddr *, size_t, struct sockaddr *, size_t, struct sockaddr *, size_t, char *); -int pcap_add_if(pcap_if_t **, char *, u_int, const char *, char *); +int pcap_add_if(pcap_if_t **, const char *, u_int, const char *, char *); struct sockaddr *dup_sockaddr(struct sockaddr *, size_t); int add_or_find_if(pcap_if_t **, pcap_if_t **, const char *, u_int, const char *, char *); @@ -263,9 +282,6 @@ int add_or_find_if(pcap_if_t **, pcap_if_t **, const char *, u_int, char *pcap_win32strerror(void); #endif -/* XXX */ -extern int pcap_fddipad; - int install_bpf_program(pcap_t *, struct bpf_program *); int pcap_strcasecmp(const char *, const char *); diff --git a/contrib/libpcap/pcap-namedb.h b/contrib/libpcap/pcap-namedb.h index 43fe1edf55e4..f44c07b6d24d 100644 --- a/contrib/libpcap/pcap-namedb.h +++ b/contrib/libpcap/pcap-namedb.h @@ -31,11 +31,11 @@ * SUCH DAMAGE. * * $FreeBSD$ - * @(#) $Header: /tcpdump/master/libpcap/pcap-namedb.h,v 1.8 2000/07/29 07:36:43 guy Exp $ (LBL) + * @(#) $Header: /tcpdump/master/libpcap/pcap-namedb.h,v 1.10 2005/03/17 07:02:32 guy Exp $ (LBL) */ -#ifndef lib_pcap_ethers_h -#define lib_pcap_ethers_h +#ifndef lib_pcap_namedb_h +#define lib_pcap_namedb_h #ifdef __cplusplus extern "C" { @@ -68,6 +68,7 @@ bpf_u_int32 pcap_nametonetaddr(const char *); int pcap_nametoport(const char *, int *, int *); int pcap_nametoproto(const char *); int pcap_nametoeproto(const char *); +int pcap_nametollc(const char *); /* * If a protocol is unknown, PROTO_UNDEF is returned. * Also, pcap_nametoport() returns the protocol along with the port number. diff --git a/contrib/libpcap/pcap.3 b/contrib/libpcap/pcap.3 index 807d1c790d8e..2af6d8031879 100644 --- a/contrib/libpcap/pcap.3 +++ b/contrib/libpcap/pcap.3 @@ -1,4 +1,4 @@ -.\" @(#) $Header: /tcpdump/master/libpcap/pcap.3,v 1.51.2.9 2004/03/28 21:45:32 fenner Exp $ +.\" @(#) $Header: /tcpdump/master/libpcap/pcap.3,v 1.64 2004/12/17 21:27:54 guy Exp $ .\" .\" Copyright (c) 1994, 1996, 1997 .\" The Regents of the University of California. All rights reserved. @@ -41,7 +41,9 @@ pcap_t *pcap_open_live(const char *device, int snaplen, int promisc, int to_ms, char *errbuf) pcap_t *pcap_open_dead(int linktype, int snaplen) pcap_t *pcap_open_offline(const char *fname, char *errbuf) +pcap_t *pcap_fopen_offline(FILE *fp, char *errbuf) pcap_dumper_t *pcap_dump_open(pcap_t *p, const char *fname) +pcap_dumper_t *pcap_dump_fopen(pcap_t *p, FILE *fp) .ft .LP .ft B @@ -90,6 +92,11 @@ void pcap_breakloop(pcap_t *) .ft .LP .ft B +int pcap_inject(pcap_t *p, const void *buf, size_t size) +int pcap_sendpacket(pcap_t *p, const u_char *buf, int size) +.ft +.LP +.ft B int pcap_datalink(pcap_t *p) int pcap_list_datalinks(pcap_t *p, int **dlt_buf); int pcap_set_datalink(pcap_t *p, int dlt); @@ -103,7 +110,7 @@ int pcap_minor_version(pcap_t *p) int pcap_stats(pcap_t *p, struct pcap_stat *ps) FILE *pcap_file(pcap_t *p) int pcap_fileno(pcap_t *p) -int pcap_get_selectable_fd(pcap_t *p) +int pcap_get_selectable_fd(pcap_t *p); void pcap_perror(pcap_t *p, char *prefix) char *pcap_geterr(pcap_t *p) char *pcap_strerror(int error) @@ -130,6 +137,7 @@ in .BR pcap_open_live() , .BR pcap_open_dead() , .BR pcap_open_offline() , +.BR pcap_fopen_offline() , .BR pcap_setnonblock() , .BR pcap_getnonblock() , .BR pcap_findalldevs() , @@ -208,9 +216,16 @@ and .BR tcpslice(1) . The name "-" in a synonym for .BR stdin . +Alternatively, you may call +.B pcap_fopen_offline() +to read dumped data from an existing open stream +.IR fp . +Note that on Windows, that stream should be opened in binary mode. .I errbuf is used to return error text and is only set when .B pcap_open_offline() +or +.B pcap_fopen_offline() fails and returns .BR NULL . .PP @@ -228,13 +243,18 @@ struct as returned by or .BR pcap_open_live() . .I fname -specifies the name of the file to open. +specifies the name of the file to open. Alternatively, you may call +.B pcap_dump_fopen() +to write data to an existing open stream +.IR fp . +Note that on Windows, that stream should be opened in binary mode. If .B NULL is returned, .B pcap_geterr() can be used to get the error text. .PP +.PP .B pcap_setnonblock() puts a capture descriptor, opened with .BR pcap_open_live() , @@ -356,6 +376,13 @@ to by may be null if the interface isn't a point-to-point interface .RE .PP +Note that not all the addresses in the list of addresses are +necessarily IPv4 or IPv6 addresses - you must check the +.B sa_family +member of the +.B "struct sockaddr" +before interpreting the contents of the address. +.PP .B \-1 is returned on failure, in which case .B errbuf @@ -630,6 +657,45 @@ the flag is cleared, so a subsequent call will resume reading packets. If a positive number is returned, the flag is not cleared, so a subsequent call will return \-2 and clear the flag. .PP +.B pcap_inject() +sends a raw packet through the network interface; +.I buf +points to the data of the packet, including the link-layer header, and +.I size +is the number of bytes in the packet. +It returns the number of bytes written on success. A return of \-1 +indicates an error in which case +.B pcap_perror() +or +.B pcap_geterr() +may be used to display the error text. +Note that, even if you successfully open the network interface, you +might not have permission to send packets on it, or it might not support +sending packets; as +.I pcap_open_live() +doesn't have a flag to indicate whether to open for capturing, sending, +or capturing and sending, you cannot request an open that supports +sending and be notified at open time whether sending will be possible. +Note also that some devices might not support sending packets. +.PP +Note that, on some platforms, the link-layer header of the packet that's +sent might not be the same as the link-layer header of the packet +supplied to +.BR pcap_inject() , +as the source link-layer address, if the header contains such an +address, might be changed to be the address assigned to the interface on +which the packet it sent, if the platform doesn't support sending +completely raw and unchanged packets. +.PP +.B pcap_sendpacket() +is like +.BR pcap_inject() , +but it returns 0 on success and \-1 on failure. +.RB ( pcap_inject() +comes from OpenBSD; +.B pcap_sendpacket() +comes from WinPcap. Both are provided for compatibility.) +.PP .B pcap_dump() outputs a packet to the ``savefile'' opened with .BR pcap_dump_open() . diff --git a/contrib/libpcap/pcap.h b/contrib/libpcap/pcap.h index 34a93d1edfe3..6f5233bc0e0a 100644 --- a/contrib/libpcap/pcap.h +++ b/contrib/libpcap/pcap.h @@ -32,7 +32,7 @@ * SUCH DAMAGE. * * $FreeBSD$ - * @(#) $Header: /tcpdump/master/libpcap/pcap.h,v 1.45.2.4 2004/01/27 22:56:20 guy Exp $ (LBL) + * @(#) $Header: /tcpdump/master/libpcap/pcap.h,v 1.52 2004/12/18 08:52:11 guy Exp $ (LBL) */ #ifndef lib_pcap_h @@ -135,6 +135,39 @@ struct pcap_stat { #endif /* WIN32 */ }; +#ifdef MSDOS +/* + * As returned by the pcap_stats_ex() + */ +struct pcap_stat_ex { + u_long rx_packets; /* total packets received */ + u_long tx_packets; /* total packets transmitted */ + u_long rx_bytes; /* total bytes received */ + u_long tx_bytes; /* total bytes transmitted */ + u_long rx_errors; /* bad packets received */ + u_long tx_errors; /* packet transmit problems */ + u_long rx_dropped; /* no space in Rx buffers */ + u_long tx_dropped; /* no space available for Tx */ + u_long multicast; /* multicast packets received */ + u_long collisions; + + /* detailed rx_errors: */ + u_long rx_length_errors; + u_long rx_over_errors; /* receiver ring buff overflow */ + u_long rx_crc_errors; /* recv'd pkt with crc error */ + u_long rx_frame_errors; /* recv'd frame alignment error */ + u_long rx_fifo_errors; /* recv'r fifo overrun */ + u_long rx_missed_errors; /* recv'r missed packet */ + + /* detailed tx_errors */ + u_long tx_aborted_errors; + u_long tx_carrier_errors; + u_long tx_fifo_errors; + u_long tx_heartbeat_errors; + u_long tx_window_errors; + }; +#endif + /* * Item in a list of interfaces. */ @@ -167,6 +200,7 @@ int pcap_lookupnet(const char *, bpf_u_int32 *, bpf_u_int32 *, char *); pcap_t *pcap_open_live(const char *, int, int, int, char *); pcap_t *pcap_open_dead(int, int); pcap_t *pcap_open_offline(const char *, char *); +pcap_t *pcap_fopen_offline(FILE *, char *); void pcap_close(pcap_t *); int pcap_loop(pcap_t *, int, pcap_handler, u_char *); int pcap_dispatch(pcap_t *, int, pcap_handler, u_char *); @@ -179,6 +213,8 @@ 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 *); +int pcap_inject(pcap_t *, const void *, size_t); +int pcap_sendpacket(pcap_t *, const u_char *, int); char *pcap_strerror(int); char *pcap_geterr(pcap_t *); int pcap_compile(pcap_t *, struct bpf_program *, char *, int, @@ -202,6 +238,7 @@ FILE *pcap_file(pcap_t *); int pcap_fileno(pcap_t *); pcap_dumper_t *pcap_dump_open(pcap_t *, const char *); +pcap_dumper_t *pcap_dump_fopen(pcap_t *, FILE *fp); int pcap_dump_flush(pcap_dumper_t *); void pcap_dump_close(pcap_dumper_t *); void pcap_dump(u_char *, const struct pcap_pkthdr *, const u_char *); @@ -218,33 +255,44 @@ int bpf_validate(struct bpf_insn *f, int len); char *bpf_image(struct bpf_insn *, int); void bpf_dump(struct bpf_program *, int); -#ifdef WIN32 +#if defined(WIN32) + /* * Win32 definitions */ int pcap_setbuff(pcap_t *p, int dim); int pcap_setmode(pcap_t *p, int mode); -int pcap_sendpacket(pcap_t *p, u_char *buf, int size); int pcap_setmintocopy(pcap_t *p, int size); #ifdef WPCAP /* Include file with the wpcap-specific extensions */ #include -#endif +#endif /* WPCAP */ #define MODE_CAPT 0 #define MODE_STAT 1 #define MODE_MON 2 -#else +#elif defined(MSDOS) + +/* + * MS-DOS definitions + */ + +int pcap_stats_ex (pcap_t *, struct pcap_stat_ex *); +void pcap_set_wait (pcap_t *p, void (*yield)(void), int wait); +u_long pcap_mac_packets (void); + +#else /* UN*X */ + /* * UN*X definitions */ int pcap_get_selectable_fd(pcap_t *); -#endif /* WIN32 */ +#endif /* WIN32/MSDOS/UN*X */ #ifdef __cplusplus } diff --git a/contrib/libpcap/scanner.l b/contrib/libpcap/scanner.l index 21e800277ceb..8be0cae7f625 100644 --- a/contrib/libpcap/scanner.l +++ b/contrib/libpcap/scanner.l @@ -24,7 +24,7 @@ #ifndef lint static const char rcsid[] _U_ = - "@(#) $Header: /tcpdump/master/libpcap/scanner.l,v 1.95.2.3 2004/03/28 21:45:33 fenner Exp $ (LBL)"; + "@(#) $Header: /tcpdump/master/libpcap/scanner.l,v 1.99 2004/06/16 08:20:28 hannes Exp $ (LBL)"; #endif #ifdef HAVE_CONFIG_H @@ -261,6 +261,7 @@ inbound return INBOUND; outbound return OUTBOUND; vlan return VLAN; +mpls return MPLS; lane return LANE; llc return LLC; diff --git a/contrib/libpcap/snprintf.c b/contrib/libpcap/snprintf.c deleted file mode 100644 index 111e78ede918..000000000000 --- a/contrib/libpcap/snprintf.c +++ /dev/null @@ -1,632 +0,0 @@ -/* - * Copyright (c) 1995-1999 Kungliga Tekniska Högskolan - * (Royal Institute of Technology, Stockholm, Sweden). - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * 3. Neither the name of the Institute nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - */ - -/* $Id: snprintf.c,v 1.1 2003/12/15 01:35:05 guy Exp $ */ - -#ifdef HAVE_CONFIG_H -#include -#endif - -#ifndef lint -static const char rcsid[] _U_ = - "@(#) $Header: /tcpdump/master/libpcap/snprintf.c,v 1.1 2003/12/15 01:35:05 guy Exp $"; -#endif - -#include -#include -#include -#include -#include -#include - -#include - -enum format_flags { - minus_flag = 1, - plus_flag = 2, - space_flag = 4, - alternate_flag = 8, - zero_flag = 16 -}; - -/* - * Common state - */ - -struct state { - unsigned char *str; - unsigned char *s; - unsigned char *theend; - size_t sz; - size_t max_sz; - int (*append_char)(struct state *, unsigned char); - int (*reserve)(struct state *, size_t); - /* XXX - methods */ -}; - -#ifndef HAVE_VSNPRINTF -static int -sn_reserve (struct state *state, size_t n) -{ - return state->s + n > state->theend; -} - -static int -sn_append_char (struct state *state, unsigned char c) -{ - if (sn_reserve (state, 1)) { - return 1; - } else { - *state->s++ = c; - return 0; - } -} -#endif - -#if 0 -static int -as_reserve (struct state *state, size_t n) -{ - if (state->s + n > state->theend) { - int off = state->s - state->str; - unsigned char *tmp; - - if (state->max_sz && state->sz >= state->max_sz) - return 1; - - state->sz = max(state->sz * 2, state->sz + n); - if (state->max_sz) - state->sz = min(state->sz, state->max_sz); - tmp = realloc (state->str, state->sz); - if (tmp == NULL) - return 1; - state->str = tmp; - state->s = state->str + off; - state->theend = state->str + state->sz - 1; - } - return 0; -} - -static int -as_append_char (struct state *state, unsigned char c) -{ - if(as_reserve (state, 1)) - return 1; - else { - *state->s++ = c; - return 0; - } -} -#endif - -static int -append_number(struct state *state, - unsigned long num, unsigned base, char *rep, - int width, int prec, int flags, int minusp) -{ - int len = 0; - int i; - - /* given precision, ignore zero flag */ - if(prec != -1) - flags &= ~zero_flag; - else - prec = 1; - /* zero value with zero precision -> "" */ - if(prec == 0 && num == 0) - return 0; - do{ - if((*state->append_char)(state, rep[num % base])) - return 1; - len++; - num /= base; - }while(num); - prec -= len; - /* pad with prec zeros */ - while(prec-- > 0){ - if((*state->append_char)(state, '0')) - return 1; - len++; - } - /* add length of alternate prefix (added later) to len */ - if(flags & alternate_flag && (base == 16 || base == 8)) - len += base / 8; - /* pad with zeros */ - if(flags & zero_flag){ - width -= len; - if(minusp || (flags & space_flag) || (flags & plus_flag)) - width--; - while(width-- > 0){ - if((*state->append_char)(state, '0')) - return 1; - len++; - } - } - /* add alternate prefix */ - if(flags & alternate_flag && (base == 16 || base == 8)){ - if(base == 16) - if((*state->append_char)(state, rep[10] + 23)) /* XXX */ - return 1; - if((*state->append_char)(state, '0')) - return 1; - } - /* add sign */ - if(minusp){ - if((*state->append_char)(state, '-')) - return 1; - len++; - } else if(flags & plus_flag) { - if((*state->append_char)(state, '+')) - return 1; - len++; - } else if(flags & space_flag) { - if((*state->append_char)(state, ' ')) - return 1; - len++; - } - if(flags & minus_flag) - /* swap before padding with spaces */ - for(i = 0; i < len / 2; i++){ - char c = state->s[-i-1]; - state->s[-i-1] = state->s[-len+i]; - state->s[-len+i] = c; - } - width -= len; - while(width-- > 0){ - if((*state->append_char)(state, ' ')) - return 1; - len++; - } - if(!(flags & minus_flag)) - /* swap after padding with spaces */ - for(i = 0; i < len / 2; i++){ - char c = state->s[-i-1]; - state->s[-i-1] = state->s[-len+i]; - state->s[-len+i] = c; - } - - return 0; -} - -static int -append_string (struct state *state, - unsigned char *arg, - int width, - int prec, - int flags) -{ - if(prec != -1) - width -= prec; - else - width -= strlen((char *)arg); - if(!(flags & minus_flag)) - while(width-- > 0) - if((*state->append_char) (state, ' ')) - return 1; - if (prec != -1) { - while (*arg && prec--) - if ((*state->append_char) (state, *arg++)) - return 1; - } else { - while (*arg) - if ((*state->append_char) (state, *arg++)) - return 1; - } - if(flags & minus_flag) - while(width-- > 0) - if((*state->append_char) (state, ' ')) - return 1; - return 0; -} - -static int -append_char(struct state *state, - unsigned char arg, - int width, - int flags) -{ - while(!(flags & minus_flag) && --width > 0) - if((*state->append_char) (state, ' ')) - return 1; - - if((*state->append_char) (state, arg)) - return 1; - while((flags & minus_flag) && --width > 0) - if((*state->append_char) (state, ' ')) - return 1; - - return 0; -} - -/* - * This can't be made into a function... - */ - -#define PARSE_INT_FORMAT(res, arg, unsig) \ -if (long_flag) \ - res = (unsig long)va_arg(arg, unsig long); \ -else if (short_flag) \ - res = (unsig short)va_arg(arg, unsig int); \ -else \ - res = (unsig int)va_arg(arg, unsig int) - -/* - * zyxprintf - return 0 or -1 - */ - -static int -xyzprintf (struct state *state, const char *char_format, va_list ap) -{ - const unsigned char *format = (const unsigned char *)char_format; - unsigned char c; - - while((c = *format++)) { - if (c == '%') { - int flags = 0; - int width = 0; - int prec = -1; - int long_flag = 0; - int short_flag = 0; - - /* flags */ - while((c = *format++)){ - if(c == '-') - flags |= minus_flag; - else if(c == '+') - flags |= plus_flag; - else if(c == ' ') - flags |= space_flag; - else if(c == '#') - flags |= alternate_flag; - else if(c == '0') - flags |= zero_flag; - else - break; - } - - if((flags & space_flag) && (flags & plus_flag)) - flags ^= space_flag; - - if((flags & minus_flag) && (flags & zero_flag)) - flags ^= zero_flag; - - /* width */ - if (isdigit(c)) - do { - width = width * 10 + c - '0'; - c = *format++; - } while(isdigit(c)); - else if(c == '*') { - width = va_arg(ap, int); - c = *format++; - } - - /* precision */ - if (c == '.') { - prec = 0; - c = *format++; - if (isdigit(c)) - do { - prec = prec * 10 + c - '0'; - c = *format++; - } while(isdigit(c)); - else if (c == '*') { - prec = va_arg(ap, int); - c = *format++; - } - } - - /* size */ - - if (c == 'h') { - short_flag = 1; - c = *format++; - } else if (c == 'l') { - long_flag = 1; - c = *format++; - } - - switch (c) { - case 'c' : - if(append_char(state, va_arg(ap, int), width, flags)) - return -1; - break; - case 's' : - if (append_string(state, - va_arg(ap, unsigned char*), - width, - prec, - flags)) - return -1; - break; - case 'd' : - case 'i' : { - long arg; - unsigned long num; - int minusp = 0; - - PARSE_INT_FORMAT(arg, ap, signed); - - if (arg < 0) { - minusp = 1; - num = -arg; - } else - num = arg; - - if (append_number (state, num, 10, "0123456789", - width, prec, flags, minusp)) - return -1; - break; - } - case 'u' : { - unsigned long arg; - - PARSE_INT_FORMAT(arg, ap, unsigned); - - if (append_number (state, arg, 10, "0123456789", - width, prec, flags, 0)) - return -1; - break; - } - case 'o' : { - unsigned long arg; - - PARSE_INT_FORMAT(arg, ap, unsigned); - - if (append_number (state, arg, 010, "01234567", - width, prec, flags, 0)) - return -1; - break; - } - case 'x' : { - unsigned long arg; - - PARSE_INT_FORMAT(arg, ap, unsigned); - - if (append_number (state, arg, 0x10, "0123456789abcdef", - width, prec, flags, 0)) - return -1; - break; - } - case 'X' :{ - unsigned long arg; - - PARSE_INT_FORMAT(arg, ap, unsigned); - - if (append_number (state, arg, 0x10, "0123456789ABCDEF", - width, prec, flags, 0)) - return -1; - break; - } - case 'p' : { - unsigned long arg = (unsigned long)va_arg(ap, void*); - - if (append_number (state, arg, 0x10, "0123456789ABCDEF", - width, prec, flags, 0)) - return -1; - break; - } - case 'n' : { - int *arg = va_arg(ap, int*); - *arg = state->s - state->str; - break; - } - case '\0' : - --format; - /* FALLTHROUGH */ - case '%' : - if ((*state->append_char)(state, c)) - return -1; - break; - default : - if ( (*state->append_char)(state, '%') - || (*state->append_char)(state, c)) - return -1; - break; - } - } else - if ((*state->append_char) (state, c)) - return -1; - } - return 0; -} - -#ifndef HAVE_SNPRINTF -int -snprintf (char *str, size_t sz, const char *format, ...) -{ - va_list args; - int ret; - - va_start(args, format); - ret = vsnprintf (str, sz, format, args); - -#ifdef PARANOIA - { - int ret2; - char *tmp; - - tmp = malloc (sz); - if (tmp == NULL) - abort (); - - ret2 = vsprintf (tmp, format, args); - if (ret != ret2 || strcmp(str, tmp)) - abort (); - free (tmp); - } -#endif - - va_end(args); - return ret; -} -#endif - -#if 0 -#ifndef HAVE_ASPRINTF -int -asprintf (char **ret, const char *format, ...) -{ - va_list args; - int val; - - va_start(args, format); - val = vasprintf (ret, format, args); - -#ifdef PARANOIA - { - int ret2; - char *tmp; - tmp = malloc (val + 1); - if (tmp == NULL) - abort (); - - ret2 = vsprintf (tmp, format, args); - if (val != ret2 || strcmp(*ret, tmp)) - abort (); - free (tmp); - } -#endif - - va_end(args); - return val; -} -#endif - -#ifndef HAVE_ASNPRINTF -int -asnprintf (char **ret, size_t max_sz, const char *format, ...) -{ - va_list args; - int val; - - va_start(args, format); - val = vasnprintf (ret, max_sz, format, args); - -#ifdef PARANOIA - { - int ret2; - char *tmp; - tmp = malloc (val + 1); - if (tmp == NULL) - abort (); - - ret2 = vsprintf (tmp, format, args); - if (val != ret2 || strcmp(*ret, tmp)) - abort (); - free (tmp); - } -#endif - - va_end(args); - return val; -} -#endif - -#ifndef HAVE_VASPRINTF -int -vasprintf (char **ret, const char *format, va_list args) -{ - return vasnprintf (ret, 0, format, args); -} -#endif - - -#ifndef HAVE_VASNPRINTF -int -vasnprintf (char **ret, size_t max_sz, const char *format, va_list args) -{ - int st; - size_t len; - struct state state; - - state.max_sz = max_sz; - state.sz = 1; - state.str = malloc(state.sz); - if (state.str == NULL) { - *ret = NULL; - return -1; - } - state.s = state.str; - state.theend = state.s + state.sz - 1; - state.append_char = as_append_char; - state.reserve = as_reserve; - - st = xyzprintf (&state, format, args); - if (st) { - free (state.str); - *ret = NULL; - return -1; - } else { - char *tmp; - - *state.s = '\0'; - len = state.s - state.str; - tmp = realloc (state.str, len+1); - if (tmp == NULL) { - free (state.str); - *ret = NULL; - return -1; - } - *ret = tmp; - return len; - } -} -#endif -#endif - -#ifndef HAVE_VSNPRINTF -int -vsnprintf (char *str, size_t sz, const char *format, va_list args) -{ - struct state state; - int ret; - unsigned char *ustr = (unsigned char *)str; - - state.max_sz = 0; - state.sz = sz; - state.str = ustr; - state.s = ustr; - state.theend = ustr + sz - 1; - state.append_char = sn_append_char; - state.reserve = sn_reserve; - - ret = xyzprintf (&state, format, args); - *state.s = '\0'; - if (ret) - return sz; - else - return state.s - state.str; -} -#endif -