gencode.c
来自「Ubuntu packages of security software。 相」· C语言 代码 · 共 2,637 行 · 第 1/5 页
C
2,637 行
b1 = gen_cmp(OR_LINK, 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(OR_LINK, 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(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 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; }}/* * At the moment we treat PPI as normal Radiotap encoded * packets. The difference is in the function that generates * the code at the beginning to compute the header length. * Since this code generator of PPI supports bare 802.11 * encapsulation only (i.e. the encapsulated DLT should be * DLT_IEEE802_11) we generate code to check for this too. */static voidinsert_ppi_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 struct block *gen_ppi_dlt_check(void){ struct slist *s_load_dlt; struct block *b; if (linktype == DLT_PPI) { /* Create the statements that check for the DLT */ s_load_dlt = new_stmt(BPF_LD|BPF_W|BPF_ABS); s_load_dlt->s.k = 4; b = new_block(JMP(BPF_JEQ)); b->stmts = s_load_dlt; b->s.k = SWAPLONG(DLT_IEEE802_11); } else { b = NULL; } return b;}static voidinsert_load_llprefixlen(b) struct block *b;{ switch (linktype) { /* * At the moment we treat PPI as normal Radiotap encoded * packets. The difference is in the function that generates * the code at the beginning to compute the header length. * Since this code generator of PPI supports bare 802.11 * encapsulation only (i.e. the encapsulated DLT should be * DLT_IEEE802_11) we generate code to check for this too. */ case DLT_PPI: insert_ppi_load_llprefixlen(b); break; case DLT_IEEE802_11_RADIO: insert_radiotap_load_llprefixlen(b); break; }}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;}/* * At the moment we treat PPI as normal Radiotap encoded * packets. The difference is in the function that generates * the code at the beginning to compute the header length. * Since this code generator of PPI supports bare 802.11 * encapsulation only (i.e. the encapsulated DLT should be * DLT_IEEE802_11) we generate code to check for this too. */static struct slist *gen_ppi_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_PPI: return gen_ppi_llprefixlen();
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?