⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 gencode.c

📁 用来监视网络通信数据的源代码和应用程序,方便网络程序底层开发.
💻 C
📖 第 1 页 / 共 5 页
字号:
		 * 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(2, BPF_H, (0x03<<8) | 0xcc);

#ifdef INET6
		case ETHERTYPE_IPV6:
			/*
			 * Check for the special NLPID for IPv6.
			 */
			return gen_cmp(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(2, BPF_H, (0x03<<8) | ISO8473_CLNP);
			b1 = gen_cmp(2, BPF_H, (0x03<<8) | ISO9542_ESIS);
			b2 = gen_cmp(2, BPF_H, (0x03<<8) | ISO10589_ISIS);
			gen_or(b1, b2);
			gen_or(b0, b2);
			return b2;

		default:
			return gen_false();
		}
		break;
	}

	/*
	 * 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 == -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(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(offset, 8, snapblock);
}

/*
 * Check for a given protocol value assuming an 802.2 LLC header.
 */
static struct block *
gen_llc(proto)
	int proto;
{
	/*
	 * XXX - handle token-ring variable-length header.
	 */
	switch (proto) {

        case LLCSAP_IP:
		return gen_cmp(off_linktype, BPF_H, (long)
			     ((LLCSAP_IP << 8) | LLCSAP_IP));
                
	case LLCSAP_ISONS:
		return gen_cmp(off_linktype, BPF_H, (long)
			     ((LLCSAP_ISONS << 8) | LLCSAP_ISONS));

	case LLCSAP_NETBEUI:
		return gen_cmp(off_linktype, BPF_H, (long)
			     ((LLCSAP_NETBEUI << 8) | LLCSAP_NETBEUI));

	case LLCSAP_IPX:
		/*
		 * XXX - are there ever SNAP frames for IPX on
		 * non-Ethernet 802.x networks?
		 */
		return gen_cmp(off_linktype, BPF_B, (bpf_int32)LLCSAP_IPX);

	case ETHERTYPE_ATALK:
		/*
		 * 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).
		 *
		 * XXX - check for an organization code of
		 * encapsulated Ethernet as well?
		 */
		return gen_snap(0x080007, ETHERTYPE_ATALK, off_linktype);

	default:
		/*
		 * XXX - we don't have to check for IPX 802.3
		 * here, but should we check for the IPX Ethertype?
		 */
		if (proto <= ETHERMTU) {
			/*
			 * This is an LLC SAP value, so check
			 * the DSAP.
			 */
			return gen_cmp(off_linktype, BPF_B, (bpf_int32)proto);
		} else {
			/*
			 * This is an Ethernet type; we assume that it's
			 * unlikely that it'll appear in the right place
			 * at random, and therefore check only the
			 * location that would hold the Ethernet type
			 * in a SNAP frame with an organization code of
			 * 0x000000 (encapsulated Ethernet).
			 *
			 * XXX - if we were to check for the SNAP DSAP and
			 * LSAP, as per XXX, and were also to check for an
			 * organization code of 0x000000 (encapsulated
			 * Ethernet), we'd do
			 *
			 *	return gen_snap(0x000000, proto,
			 *	    off_linktype);
			 *
			 * here; for now, we don't, as per the above.
			 * I don't know whether it's worth the extra CPU
			 * time to do the right check or not.
			 */
			return gen_cmp(off_linktype+6, BPF_H, (bpf_int32)proto);
		}
	}
}

static struct block *
gen_hostop(addr, mask, dir, proto, src_off, dst_off)
	bpf_u_int32 addr;
	bpf_u_int32 mask;
	int dir, proto;
	u_int src_off, dst_off;
{
	struct block *b0, *b1;
	u_int offset;

	switch (dir) {

	case Q_SRC:
		offset = src_off;
		break;

	case Q_DST:
		offset = dst_off;
		break;

	case Q_AND:
		b0 = gen_hostop(addr, mask, Q_SRC, proto, src_off, dst_off);
		b1 = gen_hostop(addr, mask, Q_DST, proto, src_off, dst_off);
		gen_and(b0, b1);
		return b1;

	case Q_OR:
	case Q_DEFAULT:
		b0 = gen_hostop(addr, mask, Q_SRC, proto, src_off, dst_off);
		b1 = gen_hostop(addr, mask, Q_DST, proto, src_off, dst_off);
		gen_or(b0, b1);
		return b1;

	default:
		abort();
	}
	b0 = gen_linktype(proto);
	b1 = gen_mcmp(offset, BPF_W, (bpf_int32)addr, mask);
	gen_and(b0, b1);
	return b1;
}

#ifdef INET6
static struct block *
gen_hostop6(addr, mask, dir, proto, src_off, dst_off)
	struct in6_addr *addr;
	struct in6_addr *mask;
	int dir, proto;
	u_int src_off, dst_off;
{
	struct block *b0, *b1;
	u_int offset;
	u_int32_t *a, *m;

	switch (dir) {

	case Q_SRC:
		offset = src_off;
		break;

	case Q_DST:
		offset = dst_off;
		break;

	case Q_AND:
		b0 = gen_hostop6(addr, mask, Q_SRC, proto, src_off, dst_off);
		b1 = gen_hostop6(addr, mask, Q_DST, proto, src_off, dst_off);
		gen_and(b0, b1);
		return b1;

	case Q_OR:
	case Q_DEFAULT:
		b0 = gen_hostop6(addr, mask, Q_SRC, proto, src_off, dst_off);
		b1 = gen_hostop6(addr, mask, Q_DST, proto, src_off, dst_off);
		gen_or(b0, b1);
		return b1;

	default:
		abort();
	}
	/* this order is important */
	a = (u_int32_t *)addr;
	m = (u_int32_t *)mask;
	b1 = gen_mcmp(offset + 12, BPF_W, ntohl(a[3]), ntohl(m[3]));
	b0 = gen_mcmp(offset + 8, BPF_W, ntohl(a[2]), ntohl(m[2]));
	gen_and(b0, b1);
	b0 = gen_mcmp(offset + 4, BPF_W, ntohl(a[1]), ntohl(m[1]));
	gen_and(b0, b1);
	b0 = gen_mcmp(offset + 0, BPF_W, ntohl(a[0]), ntohl(m[0]));
	gen_and(b0, b1);
	b0 = gen_linktype(proto);
	gen_and(b0, b1);
	return b1;
}
#endif /*INET6*/

static struct block *
gen_ehostop(eaddr, dir)
	register const u_char *eaddr;
	register int dir;
{
	register struct block *b0, *b1;

	switch (dir) {
	case Q_SRC:
		return gen_bcmp(off_mac + 6, 6, eaddr);

	case Q_DST:
		return gen_bcmp(off_mac + 0, 6, eaddr);

	case Q_AND:
		b0 = gen_ehostop(eaddr, Q_SRC);
		b1 = gen_ehostop(eaddr, Q_DST);
		gen_and(b0, b1);
		return b1;

	case Q_DEFAULT:
	case Q_OR:
		b0 = gen_ehostop(eaddr, Q_SRC);
		b1 = gen_ehostop(eaddr, Q_DST);
		gen_or(b0, b1);
		return b1;
	}
	abort();
	/* NOTREACHED */
}

/*
 * Like gen_ehostop, but for DLT_FDDI
 */
static struct block *
gen_fhostop(eaddr, dir)
	register const u_char *eaddr;
	register int dir;
{
	struct block *b0, *b1;

	switch (dir) {
	case Q_SRC:
#ifdef PCAP_FDDIPAD
		return gen_bcmp(6 + 1 + pcap_fddipad, 6, eaddr);
#else
		return gen_bcmp(6 + 1, 6, eaddr);
#endif

	case Q_DST:
#ifdef PCAP_FDDIPAD
		return gen_bcmp(0 + 1 + pcap_fddipad, 6, eaddr);
#else
		return gen_bcmp(0 + 1, 6, eaddr);
#endif

	case Q_AND:
		b0 = gen_fhostop(eaddr, Q_SRC);
		b1 = gen_fhostop(eaddr, Q_DST);
		gen_and(b0, b1);
		return b1;

	case Q_DEFAULT:
	case Q_OR:
		b0 = gen_fhostop(eaddr, Q_SRC);
		b1 = gen_fhostop(eaddr, Q_DST);
		gen_or(b0, b1);
		return b1;
	}
	abort();
	/* NOTREACHED */
}

/*
 * Like gen_ehostop, but for DLT_IEEE802 (Token Ring)
 */
static struct block *
gen_thostop(eaddr, dir)
	register const u_char *eaddr;
	register int dir;
{
	register struct block *b0, *b1;

	switch (dir) {
	case Q_SRC:
		return gen_bcmp(8, 6, eaddr);

	case Q_DST:
		return gen_bcmp(2, 6, eaddr);

	case Q_AND:
		b0 = gen_thostop(eaddr, Q_SRC);
		b1 = gen_thostop(eaddr, Q_DST);
		gen_and(b0, b1);
		return b1;

	case Q_DEFAULT:
	case Q_OR:
		b0 = gen_thostop(eaddr, Q_SRC);
		b1 = gen_thostop(eaddr, Q_DST);
		gen_or(b0, b1);
		return b1;
	}
	abort();
	/* NOTREACHED */
}

/*
 * Like gen_ehostop, but for DLT_IEEE802_11 (802.11 wireless LAN)
 */
static struct block *
gen_wlanhostop(eaddr, dir)
	register const u_char *eaddr;
	register int dir;
{
	register struct block *b0, *b1, *b2;
	register struct slist *s;

	switch (dir) {
	case Q_SRC:
		/*
		 * Oh, yuk.
		 *
		 *	For control frames, there is no SA.
		 *
		 *	For management frames, SA is at an
		 *	offset of 10 from the beginning of
		 *	the packet.
		 *
		 *	For data frames, SA is at an offset
		 *	of 10 from the beginning of the packet
		 *	if From DS is clear, at an offset of
		 *	16 from the beginning of the packet
		 *	if From DS is set and To DS is clear,
		 *	and an offset of 24 from the beginning
		 *	of the packet if From DS is set and To DS
		 *	is set.
		 */

		/*
		 * Generate the tests to be done for data frames
		 * with From DS set.
		 *
		 * First, check for To DS set, i.e. check "link[1] & 0x01".
		 */
		s = new_stmt(BPF_LD|BPF_B|BPF_ABS);
		s->s.k = 1;
		b1 = new_block(JMP(BPF_JSET));
		b1->s.k = 0x01;	/* To DS */
		b1->stmts = s;

		/*
		 * If To DS is set, the SA is at 24.
		 */
		b0 = gen_bcmp(24, 6, eaddr);
		gen_and(b1, b0);

		/*
		 * Now, check for To DS not set, i.e. check
		 * "!(link[1] & 0x01)".
		 */
		s = new_stmt(BPF_LD|BPF_B|BPF_ABS);
		s->s.k = 1;
		b2 = new_block(JMP(BPF_JSET));
		b2->s.k = 0x01;	/* To DS */
		b2->stmts = s;
		gen_not(b2);

		/*
		 * If To DS is not set, the SA is at 16.
		 */
		b1 = gen_bcmp(16, 6, eaddr);
		gen_and(b2, b1);

		/*
		 * Now OR together the last two checks.  That gives
		 * the complete set of checks for data frames with
		 * From DS set.
		 */
		gen_or(b1, b0);

		/*
		 * Now check for From DS being set, and AND that with
		 * the ORed-together checks.
		 */
		s = new_stmt(BPF_LD|BPF_B|BPF_ABS);
		s->s.k = 1;
		b1 = new_block(JMP(BPF_JSET));
		b1->s.k = 0x02;	/* From DS */
		b1->stmts = s;
		gen_and(b1, b0);

		/*
		 * Now check for data frames with From DS not set.
		 */
		s = new_stmt(BPF_LD|BPF_B|BPF_ABS);
		s->s.k = 1;
		b2 = new_block(JMP(BPF_JSET));
		b2->s.k = 0x02;	/* From DS */
		b2->stmts = s;
		gen_not(b2);

		/*
		 * If From DS isn't set, the SA is at 10.
		 */
		b1 = gen_bcmp(10, 6, eaddr);
		gen_and(b2, b1);

		/*
		 * Now OR together the checks for data frames with
		 * From DS not set and for data frames with From DS
		 * set; that gives the checks done for data frames.
		 */
		gen_or(b1, b0);

		/*
		 * Now check for a data frame.
		 * I.e, check "link[0] & 0x08".
		 */
		s = new_stmt(BPF_LD|BPF_B|BPF_ABS);
		s->s.k = 0;
		b1 = new_block(JMP(BPF_JSET));
		b1->s.k = 0x08;
		b1->stmts = s;

		/*
		 * AND that with the checks done for data frames.
		 */
		gen_and(b1, b0);

		/*
		 * If the high-order bit of the type value is 0, this
		 * is a management frame.
		 * I.e, check "!(link[0] & 0x08)".
		 */
		s = new_stmt(BPF_LD|BPF_B|BPF_ABS);
		s->s.k = 0;
		b2 = new_block(JMP(BPF_JSET));
		b2->s.k = 0x08;
		b2->stmts = s;
		gen_not(b2);

		/*
		 * For management frames, the SA is at 10.
		 */
		b1 = gen_bcmp(10, 6, eaddr);
		gen_and(b2, b1);

		/*
		 * OR that with the checks done for data frames.
		 * That gives the checks done for management and
		 * data frames.
		 */
		gen_or(b1, b0);

		/*
		 * If the low-order bit of the type value is 1,
		 * this is either a control frame or a frame
		 * with a reserved type, and thus not a
		 * frame with an SA.
		 *
		 * I.e., check "!(link[0] & 0x04)".
		 */
		s = new_stmt(BPF_LD|BPF_B|BPF_ABS);
		s->s.k = 0;
		b1 = new_block(JMP(BPF_JSET));
		b1->s.k = 0x04;
		b1->stmts = s;
		gen_not(b1);

		/*
		 * AND that with the checks for data and management
		 * frames.

⌨️ 快捷键说明

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