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