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

📄 gencode.c

📁 用来监视网络通信数据的源代码和应用程序,方便网络程序底层开发.
💻 C
📖 第 1 页 / 共 5 页
字号:
	b = new_block(JMP(BPF_JGT));
	b->stmts = s;
	b->s.k = v;

	return b;
}

static struct block *
gen_mcmp(offset, size, v, mask)
	u_int offset, size;
	bpf_int32 v;
	bpf_u_int32 mask;
{
	struct block *b = gen_cmp(offset, size, v);
	struct slist *s;

	if (mask != 0xffffffff) {
		s = new_stmt(BPF_ALU|BPF_AND|BPF_K);
		s->s.k = mask;
		b->stmts->next = s;
	}
	return b;
}

static struct block *
gen_bcmp(offset, size, v)
	register u_int offset, size;
	register const u_char *v;
{
	register struct block *b, *tmp;

	b = NULL;
	while (size >= 4) {
		register const u_char *p = &v[size - 4];
		bpf_int32 w = ((bpf_int32)p[0] << 24) |
		    ((bpf_int32)p[1] << 16) | ((bpf_int32)p[2] << 8) | p[3];

		tmp = gen_cmp(offset + size - 4, BPF_W, w);
		if (b != NULL)
			gen_and(b, tmp);
		b = tmp;
		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_ENC:
		off_linktype = 0;
		off_nl = 12;
		off_nl_nosnap = 12;	/* 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.  If the
		 * fromds and tods 802.11 header bits are both set,
		 * it's actually supposed to be 30 bytes.
		 */
		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_AVS:
		/*
		 * 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, at least in its
		 * current incarnation.
		 *
		 * 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_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.
		 *
		 * XXX - same variable-length header problem, only
		 * even *more* so; this header is also variable-length,
		 * with the length being the 16-bit number at an offset
		 * of 2 from the beginning of the radio header, and it's
		 * device-dependent (different devices might supply
		 * different amounts of information), so we can't even
		 * assume a fixed length for the current version of the
		 * header.
		 *
		 * Therefore, currently, only raw "link[N:M]" filtering is
		 * supported.
		 */
		off_linktype = -1;
		off_nl = -1;
		off_nl_nosnap = -1;
		return;

	case DLT_ATM_RFC1483:
	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;

	case DLT_APPLE_IP_OVER_IEEE1394:
		off_linktype = 16;
		off_nl = 18;
		off_nl_nosnap = 0;	/* 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_PFLOG:
		off_linktype = 0;
		/* XXX read from header? */
		off_nl = PFLOG_HDRLEN;
		off_nl_nosnap = PFLOG_HDRLEN;
		return;

#ifdef DLT_PFSYNC
	case DLT_PFSYNC:
		off_linktype = -1;
		off_nl = 4;
		off_nl_nosnap = 4;
		return;
#endif
	}
	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))

⌨️ 快捷键说明

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