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

📄 linux.c

📁 Firestorm NIDS是一个性能非常高的网络入侵检测系统 (NIDS)。目前
💻 C
字号:
#include <unistd.h>#include <stdlib.h>#define __USE_XOPEN#include <sys/poll.h>#include <sys/uio.h>#include <sys/socket.h>#include <sys/mman.h>#include <sys/ioctl.h>#include <features.h>		/* for the glibc version number */#if __GLIBC__ >= 2 && __GLIBC_MINOR >= 1#include <netpacket/packet.h>#include <net/ethernet.h>	/* the L2 protocols */#else#include <asm/types.h>#include <linux/if_packet.h>#include <linux/if_ether.h>	/* The L2 protocols */#endif#include <linux/if.h>#include <string.h>#include <netinet/in.h>#include <asm/system.h>#include <firestorm.h>#include <plugin.h>#include <packet.h>#include <cleanup.h>#include <args.h>#include <alert.h>#include <signature.h>#include <decode.h>#include <capture.h>#include <args.h>PLUGIN_STD_DEFS();static int cb_ifname(struct arg *, void *);unsigned int nr_blocks;unsigned int force_mtu;char if_name[IFNAMSIZ];struct arg linux_args[]={	{"blocks",ARGTYPE_PUINT, NULL, {vp_uint:&nr_blocks}},	{"if",ARGTYPE_STRING,cb_ifname},	{"mtu",ARGTYPE_PBYTES, NULL, {vp_uint:&force_mtu}},	{NULL,ARGTYPE_NOP,NULL}};proc_decode_proto decode_proto;proc_serial_number serial_number;proc_args_parse args_parse;struct proto *sllproto=NULL;/* This is our own private data */struct lnx_priv {	int fd;	char *map;	struct tpacket_req req;	struct iovec *ring;	size_t maplen;	int mtu;	int ifindex;};static int cb_ifname(struct arg *a, void *priv){	strncpy(if_name, a->val.v_str, sizeof(if_name));	return 1;}/* Bind us to an interface by index */static int linux_bindif(int fd, int ifindex){	struct sockaddr_ll addr;	/* bind the packet socket */	memset((char *)&addr, 0, sizeof(addr));	addr.sll_family=AF_PACKET;	addr.sll_protocol=__constant_htons(0x03);	addr.sll_ifindex=ifindex;	addr.sll_hatype=0;	addr.sll_pkttype=0;	addr.sll_halen=0;	if ( bind(fd, (struct sockaddr *)&addr, sizeof(addr)) ) {		return 0;	}	return 1;}/* This builds a ring buffer request structure making sure * that we have buffers big enough so that a frame which * is the size of the MTU doesn't get truncated. We also * need to structure things with minimum memory wastage */static void linux_mkreq(struct lnx_priv *p){	unsigned int pg,bs;	unsigned int siz;	unsigned int mult=1;	bs=pg=getpagesize();	siz=p->mtu+TPACKET_HDRLEN;	if ( bs <= siz ) {		while(bs<siz) {			bs+=pg;			mult++;		}		p->req.tp_block_size=bs;		p->req.tp_frame_size=bs/mult;		p->req.tp_block_nr=nr_blocks;		p->req.tp_frame_nr=mult*nr_blocks;	}else{		while( (siz*(mult+1))<=pg ) {			mult++;		}		p->req.tp_block_size=pg;		p->req.tp_frame_size=pg/mult;		p->req.tp_block_nr=nr_blocks;		p->req.tp_frame_nr=mult*nr_blocks;	}}/* Bind the packet socket to a specific interface, * we need to lookup the ifindex from the name * and we also need to determine the MTU */static int linux_iface(struct lnx_priv *p, char *ifn){	struct ifreq ifr;	strncpy(ifr.ifr_name, ifn, sizeof(ifr.ifr_name));	/* Lookup the MTU */	if (ioctl(p->fd, SIOCGIFMTU, &ifr) < 0) {		goto out_err;	}else{		p->mtu=ifr.ifr_ifru.ifru_mtu;	}	/* Lookup the ifindex */	if (ioctl(p->fd, SIOCGIFINDEX, &ifr) < 0) {		goto out_err;	}else{		p->ifindex=ifr.ifr_ifru.ifru_ivalue;	}	/* Actually join up to the interface */	if ( linux_bindif(p->fd, p->ifindex) ) {		return 1;	}else{		mesg(M_ERR,"linux: %s: bind(): %s", ifn, get_err());		return 0;	}out_err:	mesg(M_ERR,"linux: %s: ioctl(): %s", ifn, get_err());	return 0;}/* Initialise a capture process, we open the file and then * return our opaque private data structure to firestorm */static void *lnx_init(char *args){	struct lnx_priv *p=malloc(sizeof(struct lnx_priv));	int i;	if (!p) return NULL;	if ( !sllproto && !(sllproto=decode_proto("linux")) ) {		free(p);		return NULL;	}	/* Open the packet socket */	if ( (p->fd=socket(PF_PACKET, SOCK_DGRAM, 0))<0 ) {		mesg(M_ERR,"linux: socket(): %s", get_err());		free(p);		return NULL;	}	/* Parse args */	if_name[0]=0;	nr_blocks=128;	force_mtu=0;	if ( args ) {		if ( args_parse(linux_args, args, NULL)<=0 ) {			mesg(M_ERR,"linux: parse error: %s", args);			free(p);			return NULL;		}	}	/* Join interfaces */	if ( !if_name || !strcmp(if_name, "any") ) {		p->ifindex=0; /* zero == all */		if ( !linux_bindif(p->fd, p->ifindex) ) {			mesg(M_ERR,"linux: %s: bind(): %s",				if_name, get_err());			close(p->fd);			free(p);			return NULL;		}		/* TODO: enumerate all interfaces for		 * highest possible MTU */		if ( !force_mtu )			p->mtu=2048-TPACKET_HDRLEN;		else			p->mtu=force_mtu;	}else{		if ( force_mtu ) {			mesg(M_WARN,"linux: You are already specifying an interface "				"no need to force MTU!");		}		if ( !linux_iface(p, if_name) ) {			close(p->fd);			free(p);			return NULL;		}	}	/* Setup socket for RX ring buffer */	linux_mkreq(p);	if ( (i=setsockopt(p->fd,SOL_PACKET,PACKET_RX_RING,		(char *)&p->req, sizeof(p->req))) ) {		mesg(M_ERR,"linux: setsockopt(): %s", get_err());		if ( i==-ENOPROTOOPT ) {			mesg(M_ERR, "linux: you need CONFIG_PACKET_MMAP in your kernel");		}		close(p->fd);		free(p);		return NULL;	}	/* mmap() the sucker */	p->maplen=p->req.tp_block_size * p->req.tp_block_nr;	if ( (p->map=mmap(NULL, p->maplen,		PROT_READ|PROT_WRITE|PROT_EXEC,		MAP_SHARED, p->fd, 0))==MAP_FAILED ) {		mesg(M_ERR,"linux: mmap(): %s", get_err());		close(p->fd);		free(p);		return NULL;	}	/* Allocate ring buffer iovecs */	if ( !(p->ring=malloc(p->maplen)) ) {		mesg(M_ERR,"linux: malloc(): %s", get_err());		munmap(p->map, p->maplen);		close(p->fd);		free(p);		return NULL;	}	/* Setup our ring buffer */	for(i=0; i<p->req.tp_frame_nr; i++) {		p->ring[i].iov_base=(void *)(p->map+(i*p->req.tp_frame_size));		p->ring[i].iov_len=p->req.tp_frame_size;	}	/* Print information */	mesg(M_INFO,"linux: %s(%i): mtu=%i blocks=%u buffer=%uKB (%u frames)",		if_name, p->ifindex, p->mtu, nr_blocks,		(p->req.tp_block_size*p->req.tp_block_nr)/1024,		p->req.tp_frame_nr);	return p;}static void lnx_end(void *priv){	struct lnx_priv *p=priv;	struct tpacket_stats st;	int len=sizeof(st);	if ( !p ) return;	/* Print statistics */	if ( !getsockopt(p->fd, SOL_PACKET,		PACKET_STATISTICS, (char *)&st, &len)) {		mesg(M_INFO,"linux: received %u packets, dropped %u",			st.tp_packets, st.tp_drops);	}	munmap(p->map, p->maplen);	close(p->fd);	free(p);}static void lnx_go(void *priv, struct capture *c){	struct lnx_priv *p=priv;	struct tpacket_hdr *h;	struct sockaddr_ll *sll;	struct pollfd pfd;	struct packet pkt;	static int i=0;	memset(&pkt, 0, sizeof(pkt));	pkt.capture=c;	while ( c->state==CAP_STATE_CAPTURE ) {		/* If state gets changed during this while loop		 * we will not see it untill the next poll... It's a		 * corner case really. */		while(*(unsigned long*)p->ring[i].iov_base) {			h=p->ring[i].iov_base;			sll=(void *)h + TPACKET_ALIGN(sizeof(*h));			/* build packet */			pkt.time.tv_sec=h->tp_sec;			pkt.time.tv_usec=h->tp_usec;			pkt.len=h->tp_mac+h->tp_len;			pkt.caplen=h->tp_mac+h->tp_snaplen;			pkt.base=h;			pkt.end=(void *)h+pkt.caplen;			/* Decode */			pkt.layer[0].proto=sllproto;			pkt.layer[0].h.raw=sll;			pkt.layer[0].flags=0;			pkt.layer[0].session=NULL;			pkt.llen=0;			pkt.flags=FP_CLONE|FP_LIVE|FP_PKTTYPE;			switch ( sll->sll_pkttype ) {				case 0:					pkt.flags|=FP_HOST;					break;				case 1:					pkt.flags|=FP_BROADCAST;					break;				case 2:					pkt.flags|=FP_MULTICAST;					break;				case 4:					pkt.flags|=FP_OUTGOING;					break;				case 3:				default:					pkt.flags|=FP_PROMISC;					break;			}			/* Dispatch */			serial_number(&pkt.serial);			sllproto->decode(&pkt);			/* move along */			h->tp_status=0; mb();			i=(i>=p->req.tp_frame_nr-1) ? 0 : i+1;		}		pfd.fd=p->fd;		pfd.events=POLLIN|POLLERR;		pfd.revents=0;		if ( poll(&pfd, 1, -1)<0 ) {			if ( errno==EINTR )				return;			mesg(M_CRIT, "linux: poll(): %s", get_err());			c->state=CAP_STATE_STOP;			return;		}		if ( pfd.revents & (POLLERR|POLLHUP) ) {			mesg(M_CRIT, "linux: %s", get_err());			c->state=CAP_STATE_STOP;			return;		}	}}static struct capdev linux_cap={	.name="linux",	.init=lnx_init,	.end=lnx_end,	.go=lnx_go,};int PLUGIN_CAPDEV (struct capture_api *c){	object_check(c);	serial_number=c->serial_number;	decode_proto=c->decode_proto;	args_parse=c->args_parse;	if ( !c->capdev_add(&linux_cap) )		return PLUGIN_ERR_FAIL;	return PLUGIN_ERR_OK;}int PLUGIN_INIT (struct plugin_in *in, struct plugin_out *out){	/* validate input */	plugin_check(in, out);	PLUGIN_ID("capture.linux", "Linux mmap() packet socket");	PLUGIN_VERSION(1, 0);	PLUGIN_AUTHOR("Gianni Tedesco", "gianni@scaramanga.co.uk");	PLUGIN_LICENSE("GPL");	return PLUGIN_ERR_OK;}int PLUGIN_UNLOAD (int code) {	return PLUGIN_ERR_OK;}

⌨️ 快捷键说明

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