gencode.c

来自「Ubuntu packages of security software。 相」· C语言 代码 · 共 2,637 行 · 第 1/5 页

C
2,637
字号
		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_PPI:	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 IPv4 or IPv6.		 *		 * 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:			/* Check for a version number of 4. */			return gen_mcmp(OR_LINK, 0, BPF_B, 0x40, 0xF0);#ifdef INET6		case ETHERTYPE_IPV6:			/* Check for a version number of 6. */			return gen_mcmp(OR_LINK, 0, BPF_B, 0x60, 0xF0);#endif		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			 * over PPP are Spanning Tree Protocol			 * Bridging PDUs.			 */			proto = PPP_BRPDU;			break;		case LLCSAP_IPX:			proto = PPP_IPX;			break;		}		break;	case DLT_PPP_BSDOS:		/*		 * We use Ethernet protocol types inside libpcap;		 * map them to the corresponding PPP protocol types.		 */		switch (proto) {		case ETHERTYPE_IP:			b0 = gen_cmp(OR_LINK, off_linktype, BPF_H, PPP_IP);			b1 = gen_cmp(OR_LINK, off_linktype, BPF_H, PPP_VJC);			gen_or(b0, b1);			b0 = gen_cmp(OR_LINK, off_linktype, BPF_H, PPP_VJNC);			gen_or(b1, b0);			return b0;#ifdef INET6		case ETHERTYPE_IPV6:			proto = PPP_IPV6;			/* more to go? */			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			 * over PPP are Spanning Tree Protocol			 * Bridging PDUs.			 */			proto = PPP_BRPDU;			break;		case LLCSAP_IPX:			proto = PPP_IPX;			break;		}		break;	case DLT_NULL:	case DLT_LOOP:	case DLT_ENC:		/*		 * For DLT_NULL, the link-layer header is a 32-bit		 * word containing an AF_ value in *host* byte order,		 * and for DLT_ENC, the link-layer header begins		 * with a 32-bit work containing an AF_ value in		 * host byte order.		 *		 * In addition, if we're reading a saved capture file,		 * the host byte order in the capture may not be the		 * same as the host byte order on this machine.		 *		 * For DLT_LOOP, the link-layer header is a 32-bit		 * word containing an AF_ value in *network* byte order.		 *		 * XXX - AF_ values may, unfortunately, be platform-		 * dependent; for example, FreeBSD's AF_INET6 is 24		 * whilst NetBSD's and OpenBSD's is 26.		 *		 * This means that, when reading a capture file, just		 * checking for our AF_INET6 value won't work if the		 * capture file came from another OS.		 */		switch (proto) {		case ETHERTYPE_IP:			proto = AF_INET;			break;#ifdef INET6		case ETHERTYPE_IPV6:			proto = AF_INET6;			break;#endif		default:			/*			 * Not a type on which we support filtering.			 * XXX - support those that have AF_ values			 * #defined on this platform, at least?			 */			return gen_false();		}		if (linktype == DLT_NULL || linktype == DLT_ENC) {			/*			 * The AF_ value is in host byte order, but			 * the BPF interpreter will convert it to			 * network byte order.			 *			 * If this is a save file, and it's from a			 * machine with the opposite byte order to			 * ours, we byte-swap the AF_ value.			 *			 * Then we run it through "htonl()", and			 * generate code to compare against the result.			 */			if (bpf_pcap->sf.rfile != NULL &&			    bpf_pcap->sf.swapped)				proto = SWAPLONG(proto);			proto = htonl(proto);		}		return (gen_cmp(OR_LINK, 0, BPF_W, (bpf_int32)proto));	case DLT_PFLOG:		/*		 * af field is host byte order in contrast to the rest of		 * the packet.		 */		if (proto == ETHERTYPE_IP)			return (gen_cmp(OR_LINK, offsetof(struct pfloghdr, af),			    BPF_B, (bpf_int32)AF_INET));#ifdef INET6		else if (proto == ETHERTYPE_IPV6)			return (gen_cmp(OR_LINK, offsetof(struct pfloghdr, af),			    BPF_B, (bpf_int32)AF_INET6));#endif /* INET6 */		else			return gen_false();		/*NOTREACHED*/		break;	case DLT_ARCNET:	case DLT_ARCNET_LINUX:		/*		 * XXX should we check for first fragment if the protocol		 * uses PHDS?		 */		switch (proto) {		default:			return gen_false();#ifdef INET6		case ETHERTYPE_IPV6:			return (gen_cmp(OR_LINK, off_linktype, BPF_B,				(bpf_int32)ARCTYPE_INET6));#endif /* INET6 */		case ETHERTYPE_IP:			b0 = gen_cmp(OR_LINK, off_linktype, BPF_B,				     (bpf_int32)ARCTYPE_IP);			b1 = gen_cmp(OR_LINK, off_linktype, BPF_B,				     (bpf_int32)ARCTYPE_IP_OLD);			gen_or(b0, b1);			return (b1);		case ETHERTYPE_ARP:			b0 = gen_cmp(OR_LINK, off_linktype, BPF_B,				     (bpf_int32)ARCTYPE_ARP);			b1 = gen_cmp(OR_LINK, off_linktype, BPF_B,				     (bpf_int32)ARCTYPE_ARP_OLD);			gen_or(b0, b1);			return (b1);		case ETHERTYPE_REVARP:			return (gen_cmp(OR_LINK, off_linktype, BPF_B,					(bpf_int32)ARCTYPE_REVARP));		case ETHERTYPE_ATALK:			return (gen_cmp(OR_LINK, off_linktype, BPF_B,					(bpf_int32)ARCTYPE_ATALK));		}		/*NOTREACHED*/		break;	case DLT_LTALK:		switch (proto) {		case ETHERTYPE_ATALK:			return gen_true();		default:			return gen_false();		}		/*NOTREACHED*/		break;	case DLT_FRELAY:		/*		 * XXX - assumes a 2-byte Frame Relay header with		 * DLCI and flags.  What if the address is longer?		 */		switch (proto) {		case ETHERTYPE_IP:			/*			 * Check for the special NLPID for IP.			 */			return gen_cmp(OR_LINK, 2, BPF_H, (0x03<<8) | 0xcc);#ifdef INET6		case ETHERTYPE_IPV6:			/*			 * Check for the special NLPID for IPv6.			 */			return gen_cmp(OR_LINK, 2, BPF_H, (0x03<<8) | 0x8e);#endif		case LLCSAP_ISONS:			/*			 * Check for several OSI protocols.			 *			 * Frame Relay packets typically have an OSI			 * NLPID at the beginning; we check for each			 * of them.			 *			 * What we check for is the NLPID and a frame			 * control field of UI, i.e. 0x03 followed			 * by the NLPID.			 */			b0 = gen_cmp(OR_LINK, 2, BPF_H, (0x03<<8) | ISO8473_CLNP);			b1 = gen_cmp(OR_LINK, 2, BPF_H, (0x03<<8) | ISO9542_ESIS);			b2 = gen_cmp(OR_LINK, 2, BPF_H, (0x03<<8) | ISO10589_ISIS);			gen_or(b1, b2);			gen_or(b0, b2);			return b2;		default:			return gen_false();		}		/*NOTREACHED*/		break;        case DLT_JUNIPER_MFR:        case DLT_JUNIPER_MLFR:        case DLT_JUNIPER_MLPPP:	case DLT_JUNIPER_ATM1:	case DLT_JUNIPER_ATM2:	case DLT_JUNIPER_PPPOE:	case DLT_JUNIPER_PPPOE_ATM:        case DLT_JUNIPER_GGSN:        case DLT_JUNIPER_ES:        case DLT_JUNIPER_MONITOR:        case DLT_JUNIPER_SERVICES:        case DLT_JUNIPER_ETHER:        case DLT_JUNIPER_PPP:        case DLT_JUNIPER_FRELAY:        case DLT_JUNIPER_CHDLC:        case DLT_JUNIPER_VP:		/* just lets verify the magic number for now -		 * on ATM we may have up to 6 different encapsulations on the wire		 * and need a lot of heuristics to figure out that the payload		 * might be;		 *		 * FIXME encapsulation specific BPF_ filters		 */		return gen_mcmp(OR_LINK, 0, BPF_W, 0x4d474300, 0xffffff00); /* compare the magic number */	case DLT_LINUX_IRDA:		bpf_error("IrDA link-layer type filtering not implemented");	case DLT_DOCSIS:		bpf_error("DOCSIS link-layer type filtering not implemented");	case DLT_LINUX_LAPD:		bpf_error("LAPD link-layer type filtering not implemented");	}	/*	 * All the types that have no encapsulation should either be	 * handled as DLT_SLIP, DLT_SLIP_BSDOS, and DLT_RAW are, if	 * all packets are IP packets, or should be handled in some	 * special case, if none of them are (if some are and some	 * aren't, the lack of encapsulation is a problem, as we'd	 * have to find some other way of determining the packet type).	 *	 * Therefore, if "off_linktype" is -1, there's an error.	 */	if (off_linktype == (u_int)-1)		abort();	/*	 * Any type not handled above should always have an Ethernet	 * type at an offset of "off_linktype".  (PPP is partially	 * handled above - the protocol type is mapped from the	 * Ethernet and LLC types we use internally to the corresponding	 * PPP type - but the PPP type is always specified by a value	 * at "off_linktype", so we don't have to do the code generation	 * above.)	 */	return gen_cmp(OR_LINK, off_linktype, BPF_H, (bpf_int32)proto);}/* * Check for an LLC SNAP packet with a given organization code and * protocol type; we check the entire contents of the 802.2 LLC and * snap headers, checking for DSAP and SSAP of SNAP and a control * field of 0x03 in the LLC header, and for the specified organization * code and protocol type in the SNAP header. */static struct block *gen_snap(orgcode, ptype, offset)	bpf_u_int32 orgcode;	bpf_u_int32 ptype;	u_int offset;{	u_char snapblock[8];	snapblock[0] = LLCSAP_SNAP;	/* DSAP = SNAP */	snapblock[1] = LLCSAP_SNAP;	/* SSAP = SNAP */	snapblock[2] = 0x03;		/* control = UI */	snapblock[3] = (orgcode >> 16);	/* upper 8 bits of organization code */	snapblock[4] = (orgcode >> 8);	/* middle 8 bits of organization code */	snapblock[5] = (orgcode >> 0);	/* lower 8 bits of organization code */	snapblock[6] = (ptype >> 8);	/* upper 8 bits of protocol type */	snapblock[7] = (ptype >> 0);	/* lower 8 bits of protocol type */	return gen_bcmp(OR_LINK, offset, 8, snapblock);}/* * Generate code to match a particular packet type, for link-layer types * using 802.2 LLC headers. * * This is *NOT* used for Ethernet;

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?