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

📄 gencode.c

📁 该软件根据网络数据生成NetFlow记录。NetFlow可用于网络规划、负载均衡、安全监控等
💻 C
📖 第 1 页 / 共 3 页
字号:
/* * Copyright (c) 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1997, 1998 *	The Regents of the University of California.  All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that: (1) source code distributions * retain the above copyright notice and this paragraph in its entirety, (2) * distributions including binary code include the above copyright notice and * this paragraph in its entirety in the documentation or other materials * provided with the distribution, and (3) all advertising materials mentioning * features or use of this software display the following acknowledgement: * ``This product includes software developed by the University of California, * Lawrence Berkeley Laboratory and its contributors.'' Neither the name of * the University nor the names of its contributors may be used to endorse * or promote products derived from this software without specific prior * written permission. * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. */#ifndef lintstatic const char rcsid[] =    "@(#) $Header: gencode.c,v 1.94 98/07/12 13:06:49 leres Exp $ (LBL)";#endif#include <sys/types.h>#include <sys/socket.h>#include <sys/time.h>#if __STDC__struct mbuf;struct rtentry;#endif#include <net/if.h>#include <netinet/in.h>#include <netinet/if_ether.h>#include <stdlib.h>#include <memory.h>#include <setjmp.h>#if __STDC__#include <stdarg.h>#else#include <varargs.h>#endif#include "pcap-int.h"#include "ethertype.h"#include "gencode.h"#include "ppp.h"#include <pcap-namedb.h>#include "gnuc.h"#ifdef HAVE_OS_PROTO_H#include "os-proto.h"#endif#ifdef ZFLAG#include "if_nprobe.h"#endif#define JMP(c) ((c)|BPF_JMP|BPF_K)/* Locals */static jmp_buf top_ctx;static pcap_t *bpf_pcap;/* XXX */#ifdef PCAP_FDDIPADint	pcap_fddipad = PCAP_FDDIPAD;#elseint	pcap_fddipad;#endif/* VARARGS */__dead void#if __STDC__bpf_error(const char *fmt, ...)#elsebpf_error(fmt, va_alist)	const char *fmt;	va_dcl#endif{	va_list ap;#if __STDC__	va_start(ap, fmt);#else	va_start(ap);#endif	if (bpf_pcap != NULL)		(void)vsprintf(pcap_geterr(bpf_pcap), fmt, ap);	va_end(ap);	longjmp(top_ctx, 1);	/* NOTREACHED */}static void init_linktype(int);static int alloc_reg(void);static void free_reg(int);static struct block *root;/* * We divy out chunks of memory rather than call malloc each time so * we don't have to worry about leaking memory.  It's probably * not a big deal if all this memory was wasted but it this ever * goes into a library that would probably not be a good idea. */#define NCHUNKS 16#define CHUNK0SIZE 1024struct chunk {	u_int n_left;	void *m;};static struct chunk chunks[NCHUNKS];static int cur_chunk;static void *newchunk(u_int);static void freechunks(void);static inline struct block *new_block(int);static inline struct slist *new_stmt(int);static struct block *gen_retblk(int);static inline void syntax(void);static void backpatch(struct block *, struct block *);static void merge(struct block *, struct block *);static struct block *gen_cmp(u_int, u_int, bpf_int32);static struct block *gen_mcmp(u_int, u_int, bpf_int32, bpf_u_int32);static struct block *gen_bcmp(u_int, u_int, const u_char *);static struct block *gen_uncond(int);static inline struct block *gen_true(void);static inline struct block *gen_false(void);static struct block *gen_linktype(int);static struct block *gen_hostop(bpf_u_int32, bpf_u_int32, int, int, u_int, u_int);static struct block *gen_ehostop(const u_char *, int);static struct block *gen_fhostop(const u_char *, int);static struct block *gen_dnhostop(bpf_u_int32, int, u_int);static struct block *gen_host(bpf_u_int32, bpf_u_int32, int, int);static struct block *gen_gateway(const u_char *, bpf_u_int32 **, int, int);static struct block *gen_ipfrag(void);static struct block *gen_portatom(int, bpf_int32);struct block *gen_portop(int, int, int);static struct block *gen_port(int, int, int);static int lookup_proto(const char *, int);static struct block *gen_proto(int, int, int);static struct slist *xfer_to_x(struct arth *);static struct slist *xfer_to_a(struct arth *);static struct block *gen_len(int, int);static void *newchunk(n)	u_int n;{	struct chunk *cp;	int k, size;	/* XXX Round up to nearest long. */	n = (n + sizeof(long) - 1) & ~(sizeof(long) - 1);	cp = &chunks[cur_chunk];	if (n > cp->n_left) {		++cp, k = ++cur_chunk;		if (k >= NCHUNKS)			bpf_error("out of memory");		size = CHUNK0SIZE << k;		cp->m = (void *)malloc(size);		memset((char *)cp->m, 0, size);		cp->n_left = size;		if (n > size)			bpf_error("out of memory");	}	cp->n_left -= n;	return (void *)((char *)cp->m + cp->n_left);}static voidfreechunks(){	int i;	cur_chunk = 0;	for (i = 0; i < NCHUNKS; ++i)		if (chunks[i].m != NULL) {			free(chunks[i].m);			chunks[i].m = NULL;		}}/* * A strdup whose allocations are freed after code generation is over. */char *sdup(s)	register const char *s;{	int n = strlen(s) + 1;	char *cp = newchunk(n);	strcpy(cp, s);	return (cp);}static inline struct block *new_block(code)	int code;{	struct block *p;	p = (struct block *)newchunk(sizeof(*p));	p->s.code = code;	p->head = p;	return p;}static inline struct slist *new_stmt(code)	int code;{	struct slist *p;	p = (struct slist *)newchunk(sizeof(*p));	p->s.code = code;	return p;}static struct block *gen_retblk(v)	int v;{	struct block *b = new_block(BPF_RET|BPF_K);	b->s.k = v;	return b;}static inline voidsyntax(){	bpf_error("syntax error in filter expression");}static bpf_u_int32 netmask;static int snaplen;intpcap_compile(pcap_t *p, struct bpf_program *program,	     char *buf, int optimize, bpf_u_int32 mask){	extern int n_errors;	int len;	n_errors = 0;	root = NULL;	bpf_pcap = p;	if (setjmp(top_ctx)) {		freechunks();		return (-1);	}	netmask = mask;	snaplen = pcap_snapshot(p);	lex_init(buf ? buf : "");	init_linktype(pcap_datalink(p));	(void)pcap_parse();	if (n_errors)		syntax();	if (root == NULL)		root = gen_retblk(snaplen);	if (optimize) {		bpf_optimize(&root);		if (root == NULL ||		    (root->s.code == (BPF_RET|BPF_K) && root->s.k == 0))			bpf_error("expression rejects all packets");	}	program->bf_insns = icode_to_fcode(root, &len);	program->bf_len = len;	freechunks();	return (0);}/* * Backpatch the blocks in 'list' to 'target'.  The 'sense' field indicates * which of the jt and jf fields has been resolved and which is a pointer * back to another unresolved block (or nil).  At least one of the fields * in each block is already resolved. */static voidbackpatch(list, target)	struct block *list, *target;{	struct block *next;	while (list) {		if (!list->sense) {			next = JT(list);			JT(list) = target;		} else {			next = JF(list);			JF(list) = target;		}		list = next;	}}/* * Merge the lists in b0 and b1, using the 'sense' field to indicate * which of jt and jf is the link. */static voidmerge(b0, b1)	struct block *b0, *b1;{	register struct block **p = &b0;	/* Find end of list. */	while (*p)		p = !((*p)->sense) ? &JT(*p) : &JF(*p);	/* Concatenate the lists. */	*p = b1;}voidfinish_parse(p)	struct block *p;{	backpatch(p, gen_retblk(snaplen));	p->sense = !p->sense;	backpatch(p, gen_retblk(0));	root = p->head;}voidgen_and(b0, b1)	struct block *b0, *b1;{	backpatch(b0, b1->head);	b0->sense = !b0->sense;	b1->sense = !b1->sense;	merge(b1, b0);	b1->sense = !b1->sense;	b1->head = b0->head;}voidgen_or(b0, b1)	struct block *b0, *b1;{	b0->sense = !b0->sense;	backpatch(b0, b1->head);	b0->sense = !b0->sense;	merge(b1, b0);	b1->head = b0->head;}voidgen_not(b)	struct block *b;{	b->sense = !b->sense;}static struct block *gen_cmp(offset, size, v)	u_int offset, size;	bpf_int32 v;{	struct slist *s;	struct block *b;	s = new_stmt(BPF_LD|BPF_ABS|size);	s->s.k = offset;	b = new_block(JMP(BPF_JEQ));	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;}/* * Various code constructs need to know the layout of the data link * layer.  These variables give the necessary offsets.  off_linktype * is set to -1 for no encapsulation, in which case, IP is assumed. */static u_int off_linktype;static u_int off_nl;static int linktype;static voidinit_linktype(type)	int type;{	linktype = type;	switch (type) {#ifdef ZFLAG	case DLT_NPROBE:#endif	case DLT_EN10MB:		off_linktype = 12;		off_nl = 14;		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;		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;		return;	case DLT_NULL:		off_linktype = 0;		off_nl = 4;		return;	case DLT_PPP:		off_linktype = 2;		off_nl = 4;		return;	case DLT_PPP_BSDOS:		off_linktype = 5;		off_nl = 24;		return;	case DLT_FDDI:		/*		 * FDDI doesn't really have a link-level type field.		 * We assume that SSAP = SNAP is being used and pick		 * out the encapsulated Ethernet type.		 */		off_linktype = 19;#ifdef PCAP_FDDIPAD		off_linktype += pcap_fddipad;#endif		off_nl = 21;#ifdef PCAP_FDDIPAD		off_nl += pcap_fddipad;#endif		return;	case DLT_IEEE802:		off_linktype = 20;		off_nl = 22;		return;	case DLT_ATM_RFC1483:		/*		 * assume routed, non-ISO PDUs		 * (i.e., LLC = 0xAA-AA-03, OUT = 0x00-00-00)		 */		off_linktype = 6;		off_nl = 8;		return;	case DLT_RAW:	case DLT_RAW_HIGH:		off_linktype = -1;		off_nl = 0;		return;	case DLT_ATM_CLIP:		off_linktype = 6;		off_nl = 8;		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);}static struct block *gen_linktype(proto)	register int proto;{	struct block *b0, *b1;	/* If we're not using encapsulation and checking for IP, we're done */	if (off_linktype == -1 && proto == ETHERTYPE_IP)		return gen_true();	switch (linktype) {	case DLT_SLIP:		return gen_false();	case DLT_PPP:		if (proto == ETHERTYPE_IP)			proto = PPP_IP;			/* XXX was 0x21 */		break;	case DLT_PPP_BSDOS:		switch (proto) {		case ETHERTYPE_IP:			b0 = gen_cmp(off_linktype, BPF_H, PPP_IP);			b1 = gen_cmp(off_linktype, BPF_H, PPP_VJC);			gen_or(b0, b1);			b0 = gen_cmp(off_linktype, BPF_H, PPP_VJNC);			gen_or(b1, b0);			return b0;		case ETHERTYPE_DN:			proto = PPP_DECNET;			break;		case ETHERTYPE_ATALK:			proto = PPP_APPLE;			break;		case ETHERTYPE_NS:			proto = PPP_NS;			break;		}		break;	case DLT_NULL:		/* XXX */		if (proto == ETHERTYPE_IP)			return (gen_cmp(0, BPF_W, (bpf_int32)htonl(AF_INET)));		else			return gen_false();	}	return gen_cmp(off_linktype, 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:

⌨️ 快捷键说明

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