📄 gencode.c
字号:
* over PPP are Spanning Tree Protocol * Bridging PDUs. */ proto = PPP_BRPDU; break; case LLCSAP_IPX: proto = PPP_IPX; break; } break; case DLT_PPP_BSDOS: /* * We use Ethernet protocol types inside libpcap; * map them to the corresponding PPP protocol types. */ switch (proto) { case ETHERTYPE_IP: b0 = gen_cmp(OR_LINK, off_linktype, BPF_H, PPP_IP); b1 = gen_cmp(OR_LINK, off_linktype, BPF_H, PPP_VJC); gen_or(b0, b1); b0 = gen_cmp(OR_LINK, off_linktype, BPF_H, PPP_VJNC); gen_or(b1, b0); return b0;#ifdef INET6 case ETHERTYPE_IPV6: proto = PPP_IPV6; /* more to go? */ break;#endif case ETHERTYPE_DN: proto = PPP_DECNET; break; case ETHERTYPE_ATALK: proto = PPP_APPLE; break; case ETHERTYPE_NS: proto = PPP_NS; break; 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; case DLT_NULL: case DLT_LOOP: case DLT_ENC: /* * For DLT_NULL, the link-layer header is a 32-bit * word containing an AF_ value in *host* byte order, * and for DLT_ENC, the link-layer header begins * with a 32-bit work containing an AF_ value in * host byte order. * * In addition, if we're reading a saved capture file, * the host byte order in the capture may not be the * same as the host byte order on this machine. * * For DLT_LOOP, the link-layer header is a 32-bit * word containing an AF_ value in *network* byte order. * * XXX - AF_ values may, unfortunately, be platform- * dependent; for example, FreeBSD's AF_INET6 is 24 * whilst NetBSD's and OpenBSD's is 26. * * This means that, when reading a capture file, just * checking for our AF_INET6 value won't work if the * capture file came from another OS. */ switch (proto) { case ETHERTYPE_IP: proto = AF_INET; break;#ifdef INET6 case ETHERTYPE_IPV6: proto = AF_INET6; break;#endif default: /* * Not a type on which we support filtering. * XXX - support those that have AF_ values * #defined on this platform, at least? */ return gen_false(); } if (linktype == DLT_NULL || linktype == DLT_ENC) { /* * The AF_ value is in host byte order, but * the BPF interpreter will convert it to * network byte order. * * If this is a save file, and it's from a * machine with the opposite byte order to * ours, we byte-swap the AF_ value. * * Then we run it through "htonl()", and * generate code to compare against the result. */ if (bpf_pcap->sf.rfile != NULL && bpf_pcap->sf.swapped) proto = SWAPLONG(proto); proto = htonl(proto); } return (gen_cmp(OR_LINK, 0, BPF_W, (bpf_int32)proto)); case DLT_PFLOG: /* * af field is host byte order in contrast to the rest of * the packet. */ if (proto == ETHERTYPE_IP) return (gen_cmp(OR_LINK, offsetof(struct pfloghdr, af), BPF_B, (bpf_int32)AF_INET));#ifdef INET6 else if (proto == ETHERTYPE_IPV6) return (gen_cmp(OR_LINK, offsetof(struct pfloghdr, af), BPF_B, (bpf_int32)AF_INET6));#endif /* INET6 */ else return gen_false(); /*NOTREACHED*/ break; case DLT_ARCNET: case DLT_ARCNET_LINUX: /* * 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(OR_LINK, off_linktype, BPF_B, (bpf_int32)ARCTYPE_INET6));#endif /* INET6 */ case ETHERTYPE_IP: b0 = gen_cmp(OR_LINK, off_linktype, BPF_B, (bpf_int32)ARCTYPE_IP); b1 = gen_cmp(OR_LINK, off_linktype, BPF_B, (bpf_int32)ARCTYPE_IP_OLD); gen_or(b0, b1); return (b1); case ETHERTYPE_ARP: b0 = gen_cmp(OR_LINK, off_linktype, BPF_B, (bpf_int32)ARCTYPE_ARP); b1 = gen_cmp(OR_LINK, off_linktype, BPF_B, (bpf_int32)ARCTYPE_ARP_OLD); gen_or(b0, b1); return (b1); case ETHERTYPE_REVARP: return (gen_cmp(OR_LINK, off_linktype, BPF_B, (bpf_int32)ARCTYPE_REVARP)); case ETHERTYPE_ATALK: return (gen_cmp(OR_LINK, off_linktype, BPF_B, (bpf_int32)ARCTYPE_ATALK)); } /*NOTREACHED*/ break; case DLT_LTALK: switch (proto) { case ETHERTYPE_ATALK: return gen_true(); default: return gen_false(); } /*NOTREACHED*/ break; case DLT_FRELAY: /* * XXX - assumes a 2-byte Frame Relay header with * DLCI and flags. What if the address is longer? */ switch (proto) { case ETHERTYPE_IP: /* * Check for the special NLPID for IP. */ return gen_cmp(OR_LINK, 2, BPF_H, (0x03<<8) | 0xcc);#ifdef INET6 case ETHERTYPE_IPV6: /* * Check for the special NLPID for IPv6. */ return gen_cmp(OR_LINK, 2, BPF_H, (0x03<<8) | 0x8e);#endif case LLCSAP_ISONS: /* * Check for several OSI protocols. * * Frame Relay packets typically have an OSI * NLPID at the beginning; we check for each * of them. * * What we check for is the NLPID and a frame * control field of UI, i.e. 0x03 followed * by the NLPID. */ b0 = gen_cmp(OR_LINK, 2, BPF_H, (0x03<<8) | ISO8473_CLNP); b1 = gen_cmp(OR_LINK, 2, BPF_H, (0x03<<8) | ISO9542_ESIS); b2 = gen_cmp(OR_LINK, 2, BPF_H, (0x03<<8) | ISO10589_ISIS); gen_or(b1, b2); gen_or(b0, b2); return b2; default: return gen_false(); } /*NOTREACHED*/ break; case DLT_JUNIPER_MFR: case DLT_JUNIPER_MLFR: case DLT_JUNIPER_MLPPP: case DLT_JUNIPER_ATM1: case DLT_JUNIPER_ATM2: case DLT_JUNIPER_PPPOE: case DLT_JUNIPER_PPPOE_ATM: case DLT_JUNIPER_GGSN: case DLT_JUNIPER_ES: case DLT_JUNIPER_MONITOR: case DLT_JUNIPER_SERVICES: case DLT_JUNIPER_ETHER: case DLT_JUNIPER_PPP: case DLT_JUNIPER_FRELAY: case DLT_JUNIPER_CHDLC: /* 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(OR_LINK, 0, BPF_W, 0x4d474300, 0xffffff00); /* compare the magic number */ case DLT_LINUX_IRDA: bpf_error("IrDA link-layer type filtering not implemented"); case DLT_DOCSIS: bpf_error("DOCSIS link-layer type filtering not implemented"); case DLT_LINUX_LAPD: bpf_error("LAPD link-layer type filtering not implemented"); } /* * 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 == (u_int)-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(OR_LINK, off_linktype, BPF_H, (bpf_int32)proto);}/* * Check for an LLC SNAP packet with a given organization code and * protocol type; we check the entire contents of the 802.2 LLC and * snap headers, checking for DSAP and SSAP of SNAP and a control * field of 0x03 in the LLC header, and for the specified organization * code and protocol type in the SNAP header. */static struct block *gen_snap(orgcode, ptype, offset) bpf_u_int32 orgcode; bpf_u_int32 ptype; u_int offset;{ u_char snapblock[8]; snapblock[0] = 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 */ snapblock[5] = (orgcode >> 0); /* lower 8 bits of organization code */ snapblock[6] = (ptype >> 8); /* upper 8 bits of protocol type */ snapblock[7] = (ptype >> 0); /* lower 8 bits of protocol type */ return gen_bcmp(OR_LINK, offset, 8, snapblock);}/* * Generate code to match a particular packet type, for link-layer types * using 802.2 LLC headers. * * This is *NOT* used for Ethernet; "gen_ether_linktype()" is used * for that - it handles the D/I/X Ethernet vs. 802.3+802.2 issues. * * "proto" is an Ethernet type value, if > ETHERMTU, or an LLC SAP * value, if <= ETHERMTU. We use that to determine whether to * match the DSAP or both DSAP and LSAP or to check the OUI and * protocol ID in a SNAP header. */static struct block *gen_llc_linktype(proto) int proto;{ /* * XXX - handle token-ring variable-length header. */ switch (proto) { case LLCSAP_IP: case LLCSAP_ISONS: case LLCSAP_NETBEUI: /* * XXX - should we check both the DSAP and the * SSAP, like this, or should we check just the * DSAP, as we do for other types <= ETHERMTU * (i.e., other SAP values)? */ return gen_cmp(OR_LINK, off_linktype, BPF_H, (bpf_u_int32) ((proto << 8) | proto)); case LLCSAP_IPX: /* * XXX - are there ever SNAP frames for IPX on * non-Ethernet 802.x networks? */ return gen_cmp(OR_LINK, 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); 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(OR_LINK, 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(OR_LINK, off_linktype+6, BPF_H, (bpf_int32)proto); } }}static struct block *gen_hostop(addr, mask, dir, proto, src_off, dst_off) bpf_u_int32 addr; bpf_u_int32 mask; int dir, proto; u_int src_off, dst_off;{ struct block *b0, *b1; u_int offset; switch (dir) { case Q_SRC: offset = src_off; break; case Q_DST: offset = dst_off; break; case Q_AND: b0 = gen_hostop(addr, mask, Q_SRC, proto, src_off, dst_off); b1 = gen_hostop(addr, mask, Q_DST, proto, src_off, dst_off); gen_and(b0, b1); return b1; case Q_OR: case Q_DEFAULT: b0 = gen_hostop(addr, mask, Q_SRC, proto, src_off, dst_off); b1 = gen_hostop(addr, mask, Q_DST, proto, src_off, dst_off); gen_or(b0, b1); return b1; default: abort(); } b0 = gen_linktype(proto); b1 = gen_mcmp(OR_NET, offset, BPF_W, (bpf_int32)addr, mask); gen_and(b0, b1); return b1;}#ifdef INET6static struct block *gen_hostop6(addr, mask, dir, proto, src_off, dst_off) struct in6_addr *addr; struct in6_addr *mask; int dir, proto; u_int src_off, dst_off;{ struct block *b0, *b1; u_int offset; u_int32_t *a, *m; switch (dir) { case Q_SRC: offset = src_off; break; case Q_DST: offset = dst_off; break; case Q_AND: b0 = gen_hostop6(addr, mask, Q_SRC, proto, src_off, dst_off); b1 = gen_hostop6(addr, mask, Q_DST, proto, src_off, dst_off); gen_and(b0, b1); return b1; case Q_OR: case Q_DEFAULT: b0 = gen_hostop6(addr, mask, Q_SRC, proto, src_off, dst_off); b1 = gen_hostop6(addr, mask, Q_DST, proto, src_off, dst_off); gen_or(b0, b1); return b1; default: abort(); } /* this order is important */ a = (u_int32_t *)addr; m = (u_int32_t *)mask; b1 = gen_mcmp(OR_NET, offset + 12, BPF_W, ntohl(a[3]), ntohl(m[3])); b0 = gen_mcmp(OR_NET, offset + 8, BPF_W, ntohl(a[2]), ntohl(m[2])); gen_and(b0, b1); b0 = gen_mcmp(OR_NET, offset + 4, BPF_W, ntohl(a[1]), ntohl(m[1])); gen_and(b0, b1); b0 = gen_mcmp(OR_NET, offset + 0, BPF_W, ntohl(a[0]), ntohl(m[0])); gen_and(b0, b1); b0 = gen_linktype(proto); gen_and(b0, b1); return b1;}#endif /*INET6*/static struct block *gen_ehostop(ea
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -