📄 gencode.c
字号:
case ETHERTYPE_ATALK: case ETHERTYPE_AARP: /* * EtherTalk (AppleTalk protocols on Ethernet link * layer) may use 802.2 encapsulation. */ /* * Check for 802.2 encapsulation (EtherTalk phase 2?); * we check for an Ethernet type field less than * 1500, which means it's an 802.3 length field. */ b0 = gen_cmp_gt(OR_LINK, off_linktype, BPF_H, ETHERMTU); gen_not(b0); /* * 802.2-encapsulated ETHERTYPE_ATALK packets are * SNAP packets with an organization code of * 0x080007 (Apple, for Appletalk) and a protocol * type of ETHERTYPE_ATALK (Appletalk). * * 802.2-encapsulated ETHERTYPE_AARP packets are * SNAP packets with an organization code of * 0x000000 (encapsulated Ethernet) and a protocol * type of ETHERTYPE_AARP (Appletalk ARP). */ if (proto == ETHERTYPE_ATALK) b1 = gen_snap(0x080007, ETHERTYPE_ATALK, 14); else /* proto == ETHERTYPE_AARP */ b1 = gen_snap(0x000000, ETHERTYPE_AARP, 14); gen_and(b0, b1); /* * Check for Ethernet encapsulation (Ethertalk * phase 1?); we just check for the Ethernet * protocol type. */ b0 = gen_cmp(OR_LINK, 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 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(OR_LINK, off_linktype, BPF_H, ETHERMTU); gen_not(b0); b1 = gen_cmp(OR_LINK, 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(OR_LINK, off_linktype, BPF_H, (bpf_int32)proto); } }}/* * Generate code to match a particular packet type. * * "proto" is an Ethernet type value, if > ETHERMTU, or an LLC SAP * value, if <= ETHERMTU. We use that to determine whether to * match the type field or to check the type field for the special * LINUX_SLL_P_802_2 value and then do the appropriate test. */static struct block *gen_linux_sll_linktype(proto) register int proto;{ struct block *b0, *b1; switch (proto) { case LLCSAP_ISONS: case LLCSAP_IP: case LLCSAP_NETBEUI: /* * OSI protocols and NetBEUI always use 802.2 encapsulation, * so we check the DSAP and SSAP. * * LLCSAP_IP checks for IP-over-802.2, rather * than IP-over-Ethernet or IP-over-SNAP. * * 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)? */ b0 = gen_cmp(OR_LINK, off_linktype, BPF_H, LINUX_SLL_P_802_2); b1 = gen_cmp(OR_LINK, off_linktype + 2, BPF_H, (bpf_int32) ((proto << 8) | proto)); 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(OR_LINK, 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(OR_LINK, 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(OR_LINK, 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(OR_LINK, 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(OR_LINK, 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(OR_LINK, 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(OR_LINK, off_linktype, BPF_H, LINUX_SLL_P_802_2); b1 = gen_cmp(OR_LINK, 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(OR_LINK, off_linktype, BPF_H, (bpf_int32)proto); } }}static voidinsert_radiotap_load_llprefixlen(b) struct block *b;{ struct slist *s1, *s2; /* * Prepend to the statements in this block code to load the * length of the radiotap header into the register assigned * to hold that length, if one has been assigned. */ if (reg_ll_size != -1) { /* * The 2 bytes at offsets of 2 and 3 from the beginning * of the radiotap header are the length of the radiotap * header; unfortunately, it's little-endian, so we have * to load it a byte at a time and construct the value. */ /* * Load the high-order byte, at an offset of 3, shift it * left a byte, and put the result in the X register. */ s1 = new_stmt(BPF_LD|BPF_B|BPF_ABS); s1->s.k = 3; s2 = new_stmt(BPF_ALU|BPF_LSH|BPF_K); sappend(s1, s2); s2->s.k = 8; s2 = new_stmt(BPF_MISC|BPF_TAX); sappend(s1, s2); /* * Load the next byte, at an offset of 2, and OR the * value from the X register into it. */ s2 = new_stmt(BPF_LD|BPF_B|BPF_ABS); sappend(s1, s2); s2->s.k = 2; s2 = new_stmt(BPF_ALU|BPF_OR|BPF_X); sappend(s1, s2); /* * Now allocate a register to hold that value and store * it. */ s2 = new_stmt(BPF_ST); s2->s.k = reg_ll_size; sappend(s1, s2); /* * Now move it into the X register. */ s2 = new_stmt(BPF_MISC|BPF_TAX); sappend(s1, s2); /* * Now append all the existing statements in this * block to these statements. */ sappend(s1, b->stmts); b->stmts = s1; }}static voidinsert_load_llprefixlen(b) struct block *b;{ switch (linktype) { case DLT_IEEE802_11_RADIO: insert_radiotap_load_llprefixlen(b); }}static struct slist *gen_radiotap_llprefixlen(void){ struct slist *s; if (reg_ll_size == -1) { /* * We haven't yet assigned a register for the length * of the radiotap header; allocate one. */ reg_ll_size = alloc_reg(); } /* * Load the register containing the radiotap length * into the X register. */ s = new_stmt(BPF_LDX|BPF_MEM); s->s.k = reg_ll_size; return s;}/* * Generate code to compute the link-layer header length, if necessary, * putting it into the X register, and to return either a pointer to a * "struct slist" for the list of statements in that code, or NULL if * no code is necessary. */static struct slist *gen_llprefixlen(void){ switch (linktype) { case DLT_IEEE802_11_RADIO: return gen_radiotap_llprefixlen(); default: return NULL; }}/* * Generate code to match a particular packet type by matching the * link-layer type field or fields in the 802.2 LLC header. * * "proto" is an Ethernet type value, if > ETHERMTU, or an LLC SAP * value, if <= ETHERMTU. */static struct block *gen_linktype(proto) register int proto;{ struct block *b0, *b1, *b2; /* are we checking MPLS-encapsulated packets? */ if (label_stack_depth > 0) { switch (proto) { case ETHERTYPE_IP: case PPP_IP: /* FIXME add other L3 proto IDs */ return gen_mpls_linktype(Q_IP); case ETHERTYPE_IPV6: case PPP_IPV6: /* FIXME add other L3 proto IDs */ return gen_mpls_linktype(Q_IPV6); default: bpf_error("unsupported protocol over mpls"); /* NOTREACHED */ } } switch (linktype) { case DLT_EN10MB: return gen_ether_linktype(proto); /*NOTREACHED*/ break; case DLT_C_HDLC: switch (proto) { case LLCSAP_ISONS: proto = (proto << 8 | LLCSAP_ISONS); /* fall through */ default: return gen_cmp(OR_LINK, off_linktype, BPF_H, (bpf_int32)proto); /*NOTREACHED*/ break; } break; case DLT_FDDI: case DLT_IEEE802: case DLT_IEEE802_11: case DLT_IEEE802_11_RADIO_AVS: case DLT_IEEE802_11_RADIO: case DLT_PRISM_HEADER: case DLT_ATM_RFC1483: case DLT_ATM_CLIP: case DLT_IP_OVER_FC: return gen_llc_linktype(proto); /*NOTREACHED*/ break; case DLT_SUNATM: /* * If "is_lane" is set, check for a LANE-encapsulated * version of this protocol, otherwise check for an * LLC-encapsulated version of this protocol. * * We assume LANE means Ethernet, not Token Ring. */ if (is_lane) { /* * Check that the packet doesn't begin with an * LE Control marker. (We've already generated * a test for LANE.) */ b0 = gen_cmp(OR_LINK, SUNATM_PKT_BEGIN_POS, BPF_H, 0xFF00); gen_not(b0); /* * Now generate an Ethernet test. */ b1 = gen_ether_linktype(proto); gen_and(b0, b1); return b1; } else { /* * Check for LLC encapsulation and then check the * protocol. */ b0 = gen_atmfield_code(A_PROTOTYPE, PT_LLC, BPF_JEQ, 0); b1 = gen_llc_linktype(proto); gen_and(b0, b1); return b1; } /*NOTREACHED*/ break; case DLT_LINUX_SLL: return gen_linux_sll_linktype(proto); /*NOTREACHED*/ break; case DLT_SLIP: 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 */ } /*NOTREACHED*/ break; case DLT_PPP: case DLT_PPP_PPPD: case DLT_PPP_SERIAL: case DLT_PPP_ETHER: /* * We use Ethernet protocol types inside libpcap; * map them to the corresponding PPP protocol types. */ switch (proto) { case ETHERTYPE_IP: proto = PPP_IP; break;#ifdef INET6 case ETHERTYPE_IPV6: proto = PPP_IPV6; break;#endif case ETHERTYPE_DN: proto = PPP_DECNET; break; case ETHERTYPE_ATALK: proto = PPP_APPLE; break; case ETHERTYPE_NS: proto = PPP_NS; break; case LLCSAP_ISONS: proto = PPP_OSI; break; case LLCSAP_8021D: /* * I'm assuming the "Bridging PDU"s that go
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -