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 + -
显示快捷键?