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

📄 gencode.c

📁 用来监视网络通信数据的源代码和应用程序,方便网络程序底层开发.
💻 C
📖 第 1 页 / 共 5 页
字号:
		size -= 4;
	}
	while (size >= 2) {
		register const u_char *p = &v[size - 2];
		bpf_int32 w = ((bpf_int32)p[0] << 8) | p[1];

		tmp = gen_cmp(offset + size - 2, BPF_H, w);
		if (b != NULL)
			gen_and(b, tmp);
		b = tmp;
		size -= 2;
	}
	if (size > 0) {
		tmp = gen_cmp(offset, BPF_B, (bpf_int32)v[0]);
		if (b != NULL)
			gen_and(b, tmp);
		b = tmp;
	}
	return b;
}

static struct block *
gen_ncmp(datasize, offset, mask, jtype, jvalue, reverse)
	bpf_u_int32 datasize, offset, mask, jtype, jvalue;
	int reverse;
{
	struct slist *s;
	struct block *b;
 
	s = new_stmt(BPF_LD|datasize|BPF_ABS);
	s->s.k = offset;
 
	if (mask != 0xffffffff) {
		s->next = new_stmt(BPF_ALU|BPF_AND|BPF_K);
		s->next->s.k = mask;
	}
 
	b = new_block(JMP(jtype));
	b->stmts = s;
	b->s.k = jvalue;
	if (reverse && (jtype == BPF_JGT || jtype == BPF_JGE))
		gen_not(b);
	return b;
}

/*
 * Various code constructs need to know the layout of the data link
 * layer.  These variables give the necessary offsets.
 */

/*
 * This is the offset of the beginning of the MAC-layer header.
 * It's usually 0, except for ATM LANE.
 */
static u_int off_mac;

/*
 * "off_linktype" is the offset to information in the link-layer header
 * giving the packet type.
 *
 * For Ethernet, it's the offset of the Ethernet type field.
 *
 * For link-layer types that always use 802.2 headers, it's the
 * offset of the LLC header.
 *
 * For PPP, it's the offset of the PPP type field.
 *
 * For Cisco HDLC, it's the offset of the CHDLC type field.
 *
 * For BSD loopback, it's the offset of the AF_ value.
 *
 * For Linux cooked sockets, it's the offset of the type field.
 *
 * It's set to -1 for no encapsulation, in which case, IP is assumed.
 */
static u_int off_linktype;

/*
 * TRUE if the link layer includes an ATM pseudo-header.
 */
static int is_atm = 0;

/*
 * TRUE if "lane" appeared in the filter; it causes us to generate
 * code that assumes LANE rather than LLC-encapsulated traffic in SunATM.
 */
static int is_lane = 0;

/*
 * These are offsets for the ATM pseudo-header.
 */
static u_int off_vpi;
static u_int off_vci;
static u_int off_proto;

/*
 * This is the offset of the first byte after the ATM pseudo_header,
 * or -1 if there is no ATM pseudo-header.
 */
static u_int off_payload;

/*
 * These are offsets to the beginning of the network-layer header.
 *
 * If the link layer never uses 802.2 LLC:
 *
 *	"off_nl" and "off_nl_nosnap" are the same.
 *
 * If the link layer always uses 802.2 LLC:
 *
 *	"off_nl" is the offset if there's a SNAP header following
 *	the 802.2 header;
 *
 *	"off_nl_nosnap" is the offset if there's no SNAP header.
 *
 * If the link layer is Ethernet:
 *
 *	"off_nl" is the offset if the packet is an Ethernet II packet
 *	(we assume no 802.3+802.2+SNAP);
 *
 *	"off_nl_nosnap" is the offset if the packet is an 802.3 packet
 *	with an 802.2 header following it.
 */
static u_int off_nl;
static u_int off_nl_nosnap;

static int linktype;

static void
init_linktype(type)
	int type;
{
	linktype = type;

	/*
	 * Assume it's not raw ATM with a pseudo-header, for now.
	 */
	off_mac = 0;
	is_atm = 0;
	is_lane = 0;
	off_vpi = -1;
	off_vci = -1;
	off_proto = -1;
	off_payload = -1;

	orig_linktype = -1;
	orig_nl = -1;
	orig_nl_nosnap = -1;

	switch (type) {

	case DLT_ARCNET:
		off_linktype = 2;
		off_nl = 6;		/* XXX in reality, variable! */
		off_nl_nosnap = 6;	/* no 802.2 LLC */
		return;

	case DLT_ARCNET_LINUX:
		off_linktype = 4;
		off_nl = 8;		/* XXX in reality, variable! */
		off_nl_nosnap = 8;	/* no 802.2 LLC */
		return;

	case DLT_EN10MB:
		off_linktype = 12;
		off_nl = 14;		/* Ethernet II */
		off_nl_nosnap = 17;	/* 802.3+802.2 */
		return;

	case DLT_SLIP:
		/*
		 * SLIP doesn't have a link level type.  The 16 byte
		 * header is hacked into our SLIP driver.
		 */
		off_linktype = -1;
		off_nl = 16;
		off_nl_nosnap = 16;	/* no 802.2 LLC */
		return;

	case DLT_SLIP_BSDOS:
		/* XXX this may be the same as the DLT_PPP_BSDOS case */
		off_linktype = -1;
		/* XXX end */
		off_nl = 24;
		off_nl_nosnap = 24;	/* no 802.2 LLC */
		return;

	case DLT_NULL:
	case DLT_LOOP:
		off_linktype = 0;
		off_nl = 4;
		off_nl_nosnap = 4;	/* no 802.2 LLC */
		return;

	case DLT_PPP:
	case DLT_C_HDLC:		/* BSD/OS Cisco HDLC */
	case DLT_PPP_SERIAL:		/* NetBSD sync/async serial PPP */
		off_linktype = 2;
		off_nl = 4;
		off_nl_nosnap = 4;	/* no 802.2 LLC */
		return;

	case DLT_PPP_ETHER:
		/*
		 * This does no include the Ethernet header, and
		 * only covers session state.
		 */
		off_linktype = 6;
		off_nl = 8;
		off_nl_nosnap = 8;	/* no 802.2 LLC */
		return;

	case DLT_PPP_BSDOS:
		off_linktype = 5;
		off_nl = 24;
		off_nl_nosnap = 24;	/* no 802.2 LLC */
		return;

	case DLT_FDDI:
		/*
		 * FDDI doesn't really have a link-level type field.
		 * We set "off_linktype" to the offset of the LLC header.
		 *
		 * To check for Ethernet types, we assume that SSAP = SNAP
		 * is being used and pick out the encapsulated Ethernet type.
		 * XXX - should we generate code to check for SNAP?
		 */
		off_linktype = 13;
#ifdef PCAP_FDDIPAD
		off_linktype += pcap_fddipad;
#endif
		off_nl = 21;		/* FDDI+802.2+SNAP */
		off_nl_nosnap = 16;	/* FDDI+802.2 */
#ifdef PCAP_FDDIPAD
		off_nl += pcap_fddipad;
		off_nl_nosnap += pcap_fddipad;
#endif
		return;

	case DLT_IEEE802:
		/*
		 * Token Ring doesn't really have a link-level type field.
		 * We set "off_linktype" to the offset of the LLC header.
		 *
		 * To check for Ethernet types, we assume that SSAP = SNAP
		 * is being used and pick out the encapsulated Ethernet type.
		 * XXX - should we generate code to check for SNAP?
		 *
		 * XXX - the header is actually variable-length.
		 * Some various Linux patched versions gave 38
		 * as "off_linktype" and 40 as "off_nl"; however,
		 * if a token ring packet has *no* routing
		 * information, i.e. is not source-routed, the correct
		 * values are 20 and 22, as they are in the vanilla code.
		 *
		 * A packet is source-routed iff the uppermost bit
		 * of the first byte of the source address, at an
		 * offset of 8, has the uppermost bit set.  If the
		 * packet is source-routed, the total number of bytes
		 * of routing information is 2 plus bits 0x1F00 of
		 * the 16-bit value at an offset of 14 (shifted right
		 * 8 - figure out which byte that is).
		 */
		off_linktype = 14;
		off_nl = 22;		/* Token Ring+802.2+SNAP */
		off_nl_nosnap = 17;	/* Token Ring+802.2 */
		return;

	case DLT_IEEE802_11:
		/*
		 * 802.11 doesn't really have a link-level type field.
		 * We set "off_linktype" to the offset of the LLC header.
		 *
		 * To check for Ethernet types, we assume that SSAP = SNAP
		 * is being used and pick out the encapsulated Ethernet type.
		 * XXX - should we generate code to check for SNAP?
		 *
		 * XXX - the header is actually variable-length.  We
		 * assume a 24-byte link-layer header, as appears in
		 * data frames in networks with no bridges.
		 */
		off_linktype = 24;
		off_nl = 32;		/* 802.11+802.2+SNAP */
		off_nl_nosnap = 27;	/* 802.11+802.2 */
		return;

	case DLT_PRISM_HEADER:
		/*
		 * Same as 802.11, but with an additional header before
		 * the 802.11 header, containing a bunch of additional
		 * information including radio-level information.
		 *
		 * The header is 144 bytes long.
		 *
		 * XXX - same variable-length header problem; at least
		 * the Prism header is fixed-length.
		 */
		off_linktype = 144+24;
		off_nl = 144+32;	/* Prism+802.11+802.2+SNAP */
		off_nl_nosnap = 144+27;	/* Prism+802.11+802.2 */
		return;

	case DLT_IEEE802_11_RADIO:
		/*
		 * Same as 802.11, but with an additional header before
		 * the 802.11 header, containing a bunch of additional
		 * information including radio-level information.
		 *
		 * The header is 64 bytes long.
		 *
		 * XXX - same variable-length header problem, only
		 * more so; this header is also variable-length,
		 * with the length being the 32-bit big-endian
		 * number at an offset of 4 from the beginning
		 * of the radio header.
		 */
		off_linktype = 64+24;
		off_nl = 64+32;		/* Radio+802.11+802.2+SNAP */
		off_nl_nosnap = 64+27;	/* Radio+802.11+802.2 */
		return;

	case DLT_ATM_RFC1483:
		off_linktype = 0;
		off_nl = 4;             /* FIXME SNAP */
		return;

	case DLT_ATM_CLIP:	/* Linux ATM defines this */
		/*
		 * assume routed, non-ISO PDUs
		 * (i.e., LLC = 0xAA-AA-03, OUT = 0x00-00-00)
		 */
		off_linktype = 0;
		off_nl = 8;		/* 802.2+SNAP */
		off_nl_nosnap = 3;	/* 802.2 */
		return;

	case DLT_SUNATM:
		/*
		 * Full Frontal ATM; you get AALn PDUs with an ATM
		 * pseudo-header.
		 */
		is_atm = 1;
		off_vpi = SUNATM_VPI_POS;
		off_vci = SUNATM_VCI_POS;
		off_proto = PROTO_POS;
		off_mac = -1;	/* LLC-encapsulated, so no MAC-layer header */	
		off_payload = SUNATM_PKT_BEGIN_POS;
		off_linktype = off_payload;
		off_nl = off_payload+8;		/* 802.2+SNAP */
		off_nl_nosnap = off_payload+3;	/* 802.2 */
		return;

	case DLT_RAW:
		off_linktype = -1;
		off_nl = 0;
		off_nl_nosnap = 0;	/* no 802.2 LLC */
		return;

	case DLT_LINUX_SLL:	/* fake header for Linux cooked socket */
		off_linktype = 14;
		off_nl = 16;
		off_nl_nosnap = 16;	/* no 802.2 LLC */
		return;

	case DLT_LTALK:
		/*
		 * LocalTalk does have a 1-byte type field in the LLAP header,
		 * but really it just indicates whether there is a "short" or
		 * "long" DDP packet following.
		 */
		off_linktype = -1;
		off_nl = 0;
		off_nl_nosnap = 0;	/* no 802.2 LLC */
		return;

	case DLT_IP_OVER_FC:
		/*
		 * RFC 2625 IP-over-Fibre-Channel doesn't really have a
		 * link-level type field.  We set "off_linktype" to the
		 * offset of the LLC header.
		 *
		 * To check for Ethernet types, we assume that SSAP = SNAP
		 * is being used and pick out the encapsulated Ethernet type.
		 * XXX - should we generate code to check for SNAP? RFC
		 * 2625 says SNAP should be used.
		 */
		off_linktype = 16;
		off_nl = 24;		/* IPFC+802.2+SNAP */
		off_nl_nosnap = 19;	/* IPFC+802.2 */
		return;

	case DLT_FRELAY:
		/*
		 * XXX - we should set this to handle SNAP-encapsulated
		 * frames (NLPID of 0x80).
		 */
		off_linktype = -1;
		off_nl = 0;
		off_nl_nosnap = 0;	/* no 802.2 LLC */
		return;
	}
	bpf_error("unknown data link type %d", linktype);
	/* NOTREACHED */
}

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))

static struct block *
gen_ether_linktype(proto)
	register int proto;
{
	struct block *b0, *b1;

	switch (proto) {

	case LLCSAP_ISONS:
		/*
		 * OSI protocols always use 802.2 encapsulation.
		 */
		b0 = gen_cmp_gt(off_linktype, BPF_H, ETHERMTU);
		gen_not(b0);
		b1 = gen_cmp(off_linktype + 2, BPF_H, (bpf_int32)
			     ((LLCSAP_ISONS << 8) | LLCSAP_ISONS));
		gen_and(b0, b1);
		return b1;

	case LLCSAP_IP:
		b0 = gen_cmp_gt(off_linktype, BPF_H, ETHERMTU);
		gen_not(b0);
		b1 = gen_cmp(off_linktype + 2, BPF_H, (bpf_int32)
			     ((LLCSAP_IP << 8) | LLCSAP_IP));
		gen_and(b0, b1);
		return b1;

	case LLCSAP_NETBEUI:
		/*
		 * NetBEUI always uses 802.2 encapsulation.
		 */
		b0 = gen_cmp_gt(off_linktype, BPF_H, ETHERMTU);
		gen_not(b0);
		b1 = gen_cmp(off_linktype + 2, BPF_H, (bpf_int32)
			     ((LLCSAP_NETBEUI << 8) | LLCSAP_NETBEUI));
		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(off_linktype + 2, BPF_B, (bpf_int32)LLCSAP_IPX);
		b1 = gen_cmp(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(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(off_linktype, BPF_H, (bpf_int32)ETHERTYPE_IPX);
		gen_or(b0, b1);

⌨️ 快捷键说明

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