gencode.c
来自「Ubuntu packages of security software。 相」· C语言 代码 · 共 2,698 行 · 第 1/5 页
C
2,698 行
off_nl_nosnap = 0; /* no 802.2 LLC */ return; case DLT_APPLE_IP_OVER_IEEE1394: off_linktype = 16; off_nl = 18; off_nl_nosnap = 18; /* no 802.2 LLC */ return; case DLT_LINUX_IRDA: /* * Currently, only raw "link[N:M]" filtering is supported. */ off_linktype = -1; off_nl = -1; 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 this from pf.h? */ off_nl = PFLOG_HDRLEN; off_nl_nosnap = PFLOG_HDRLEN; /* no 802.2 LLC */ return; case DLT_JUNIPER_MFR: case DLT_JUNIPER_MLFR: case DLT_JUNIPER_MLPPP: case DLT_JUNIPER_PPP: case DLT_JUNIPER_CHDLC: case DLT_JUNIPER_FRELAY: off_linktype = 4; off_nl = 4; off_nl_nosnap = -1; /* no 802.2 LLC */ 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; /* frames captured on a Juniper PPPoE service PIC * contain raw ethernet frames */ case DLT_JUNIPER_PPPOE: case DLT_JUNIPER_ETHER: off_linktype = 16; off_nl = 18; /* Ethernet II */ off_nl_nosnap = 21; /* 802.3+802.2 */ return; case DLT_JUNIPER_PPPOE_ATM: off_linktype = 4; off_nl = 6; off_nl_nosnap = -1; /* no 802.2 LLC */ return; case DLT_JUNIPER_GGSN: off_linktype = 6; off_nl = 12; off_nl_nosnap = -1; /* no 802.2 LLC */ return; case DLT_JUNIPER_ES: off_linktype = 6; off_nl = -1; /* not really a network layer but raw IP adresses */ off_nl_nosnap = -1; /* no 802.2 LLC */ return; case DLT_JUNIPER_MONITOR: off_linktype = 12; off_nl = 12; /* raw IP/IP6 header */ off_nl_nosnap = -1; /* no 802.2 LLC */ return; case DLT_JUNIPER_SERVICES: off_linktype = 12; off_nl = -1; /* L3 proto location dep. on cookie type */ off_nl_nosnap = -1; /* no 802.2 LLC */ return; case DLT_MTP2: off_sio = 3; off_opc = 4; off_dpc = 4; off_sls = 7; off_linktype = -1; off_nl = -1; off_nl_nosnap = -1; return;#ifdef DLT_PFSYNC case DLT_PFSYNC: off_linktype = -1; off_nl = 4; off_nl_nosnap = 4; return;#endif case DLT_LINUX_LAPD: /* * Currently, only raw "link[N:M]" filtering is supported. */ off_linktype = -1; off_nl = -1; off_nl_nosnap = -1; return; } bpf_error("unknown data link type %d", linktype); /* NOTREACHED */}/* * Load a value relative to the beginning of the link-layer header. * The link-layer header doesn't necessarily begin at the beginning * of the packet data; there might be a variable-length prefix containing * radio information. */static struct slist *gen_load_llrel(offset, size) u_int offset, size;{ struct slist *s, *s2; s = gen_llprefixlen(); /* * If "s" is non-null, it has code to arrange that the X register * contains the length of the prefix preceding the link-layer * header. */ if (s != NULL) { s2 = new_stmt(BPF_LD|BPF_IND|size); s2->s.k = offset; sappend(s, s2); } else { s = new_stmt(BPF_LD|BPF_ABS|size); s->s.k = offset; } return s;}/* * Load a value relative to the beginning of the specified header. */static struct slist *gen_load_a(offrel, offset, size) enum e_offrel offrel; u_int offset, size;{ struct slist *s, *s2; switch (offrel) { case OR_PACKET: s = gen_load_llrel(offset, size); break; case OR_LINK: s = gen_load_llrel(off_ll + offset, size); break; case OR_NET: s = gen_load_llrel(off_nl + offset, size); break; case OR_NET_NOSNAP: s = gen_load_llrel(off_nl_nosnap + offset, size); break; case OR_TRAN_IPV4: /* * Load the X register with the length of the IPv4 header, * in bytes. */ s = gen_loadx_iphdrlen(); /* * Load the item at {length of the link-layer header} + * {length of the IPv4 header} + {specified offset}. */ s2 = new_stmt(BPF_LD|BPF_IND|size); s2->s.k = off_nl + offset; sappend(s, s2); break; case OR_TRAN_IPV6: s = gen_load_llrel(off_nl + 40 + offset, size); break; default: abort(); return NULL; } return s;}/* * Generate code to load into the X register the sum of the length of * the IPv4 header and any variable-length header preceding the link-layer * header. */static struct slist *gen_loadx_iphdrlen(){ struct slist *s, *s2; s = gen_llprefixlen(); if (s != NULL) { /* * There's a variable-length prefix preceding the * link-layer header. "s" points to a list of statements * that put the length of that prefix into the X register. * The 4*([k]&0xf) addressing mode can't be used, as we * don't have a constant offset, so we have to load the * value in question into the A register and add to it * the value from the X register. */ s2 = new_stmt(BPF_LD|BPF_IND|BPF_B); s2->s.k = off_nl; sappend(s, s2); s2 = new_stmt(BPF_ALU|BPF_AND|BPF_K); s2->s.k = 0xf; sappend(s, s2); s2 = new_stmt(BPF_ALU|BPF_LSH|BPF_K); s2->s.k = 2; sappend(s, s2); /* * The A register now contains the length of the * IP header. We need to add to it the length * of the prefix preceding the link-layer * header, which is still in the X register, and * move the result into the X register. */ sappend(s, new_stmt(BPF_ALU|BPF_ADD|BPF_X)); sappend(s, new_stmt(BPF_MISC|BPF_TAX)); } else { /* * There is no variable-length header preceding the * link-layer header; if there's a fixed-length * header preceding it, its length is included in * the off_ variables, so it doesn't need to be added. */ s = new_stmt(BPF_LDX|BPF_MSH|BPF_B); s->s.k = off_nl; } return s;}static struct block *gen_uncond(rsense) int rsense;{ struct block *b; struct slist *s; s = new_stmt(BPF_LD|BPF_IMM); s->s.k = !rsense; b = new_block(JMP(BPF_JEQ)); b->stmts = s; return b;}static inline struct block *gen_true(){ return gen_uncond(1);}static inline struct block *gen_false(){ return gen_uncond(0);}/* * Byte-swap a 32-bit number. * ("htonl()" or "ntohl()" won't work - we want to byte-swap even on * big-endian platforms.) */#define SWAPLONG(y) \((((y)&0xff)<<24) | (((y)&0xff00)<<8) | (((y)&0xff0000)>>8) | (((y)>>24)&0xff))/* * 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/length field or to check the type/length field for * a value <= ETHERMTU to see whether it's a type field and then do * the appropriate test. */static struct block *gen_ether_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_gt(OR_LINK, off_linktype, BPF_H, ETHERMTU); gen_not(b0); b1 = gen_cmp(OR_LINK, off_linktype + 2, BPF_H, (bpf_int32) ((proto << 8) | proto)); gen_and(b0, b1); return b1; case LLCSAP_IPX: /* * Check for; * * Ethernet_II frames, which are Ethernet * frames with a frame type of ETHERTYPE_IPX; * * Ethernet_802.3 frames, which are 802.3 * frames (i.e., the type/length field is * a length field, <= ETHERMTU, rather than * a type field) with the first two bytes * after the Ethernet/802.3 header being * 0xFFFF; * * Ethernet_802.2 frames, which are 802.3 * frames with an 802.2 LLC header and * with the IPX LSAP as the DSAP in the LLC * header; * * Ethernet_SNAP frames, which are 802.3 * frames with an LLC header and a SNAP * header and with an OUI of 0x000000 * (encapsulated Ethernet) and a protocol * ID of ETHERTYPE_IPX in the SNAP header. * * XXX - should we generate the same code both * for tests for LLCSAP_IPX and for ETHERTYPE_IPX? */ /* * This generates code to check both for the * IPX LSAP (Ethernet_802.2) and for Ethernet_802.3. */ b0 = gen_cmp(OR_LINK, off_linktype + 2, BPF_B, (bpf_int32)LLCSAP_IPX); 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;
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?