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

📄 fprobe.c

📁 模仿cisco路由器
💻 C
📖 第 1 页 / 共 3 页
字号:
/*	Copyright (C) 2002, 2003 Slava Astashonok <sla@0n.ru>	This program is free software; you can redistribute it and/or	modify it under the terms of the GNU General Public License.	$Id: fprobe.c,v 1.10.2.12 2003/10/30 14:38:44 sla Exp $*/#include <common.h>/* stdout, stderr, freopen() */#include <stdio.h>/* atoi(), exit() */#include <stdlib.h>/* getopt(), alarm(), getpid(), sedsid(), chdir() */#include <unistd.h>/* strerror() */#include <string.h>/* sig*() */#include <signal.h>/* pcap_*() */#include <pcap.h>/* inet_*() (Linux, FreeBSD, Solaris), getpid() */#include <sys/types.h>#include <netinet/in_systm.h>#include <sys/socket.h>#include <netinet/in.h>#include <arpa/inet.h>#include <netinet/ip.h>#include <netinet/tcp.h>#include <netinet/udp.h>#include <netinet/ip_icmp.h>/* pthread_*() */#include <pthread.h>/* errno */#include <errno.h>/* gethostbyname(), getservbyname() */#include <netdb.h>/* nanosleep() */#include <time.h>/* gettimeofday() */#include <sys/time.h>/* scheduling */#include <sched.h>/* select() (POSIX)*/#include <sys/select.h>#include <fprobe.h>#include <my_log.h>#include <my_getopt.h>#include <netflow.h>#include <hash.h>#include <mem.h>struct DLT dlt[] = {#ifdef DLT_NULL		{DLT_NULL, 0, 4, 4, "NULL"},#endif#ifdef DLT_EN10MB		{DLT_EN10MB, 12, 14, 17, "EN10MB"},#endif#ifdef DLT_IEEE802	{DLT_IEEE802, 14, 22, 17, "IEEE802"},#endif#ifdef DLT_ARCNET	{DLT_ARCNET, 2 , 6, 6, "ARCNET"},#endif#ifdef DLT_SLIP	{DLT_SLIP, -1, 16, 16, "SLIP"},#endif#ifdef DLT_PPP	{DLT_PPP, 2, 4, 4, "PPP"},#endif#ifdef DLT_FDDI	/*	FIXME	See gencode.c from libpcap	*/	{DLT_FDDI, 13, 21, 16, "FDDI"},#endif#ifdef DLT_ATM_RFC1483	{DLT_ATM_RFC1483, 0, 8, 3, "ATM_RFC1483"},#endif#ifdef DLT_RAW	{DLT_RAW, -1, 0, 0, "RAW"},#endif#ifdef DLT_SLIP_BSDOS	{DLT_SLIP_BSDOS, -1, 24, 24, "SLIP_BSDOS"},#endif#ifdef DLT_PPP_BSDOS	{DLT_PPP_BSDOS, 5, 24, 24, "PPP_BSDOS"},#endif#ifdef DLT_ATM_CLIP	{DLT_ATM_CLIP, 0, 8, 3, "ATM_CLIP"},#endif#ifdef DLT_PPP_SERIAL	{DLT_PPP_SERIAL, 2, 4, 4, "PPP_SERIAL"},#endif#ifdef DLT_PPP_ETHER	{DLT_PPP_ETHER, 6, 8, 8, "PPP_ETHER"},#endif#ifdef DLT_C_HDLC	{DLT_C_HDLC, 2, 4, 4, "C_HDLC"},#endif#ifdef DLT_IEEE802_11	{DLT_IEEE802_11, 24, 32, 27, "IEEE802_11"},#endif#ifdef DLT_LOOP	{DLT_LOOP, 0, 4, 4, "LOOP"},#endif#ifdef DLT_LINUX_SLL	{DLT_LINUX_SLL, 14, 16, 16, "LINUX_SLL"},#endif#ifdef DLT_LTALK	{DLT_LTALK, -1, 0, 0, "LTALK"},#endif#ifdef DLT_PRISM_HEADER	{DLT_PRISM_HEADER, 144+24, 144+30, 144+27, "PRISM_HEADER"},#endif#ifdef DLT_IP_OVER_FC	{DLT_IP_OVER_FC, 16, 24, 19, "IP_OVER_FC"},#endif#ifdef DLT_SUNATM	{DLT_SUNATM, 4, 4+8, 4+3, "SUNATM"},#endif#ifdef DLT_ARCNET_LINUX	{DLT_ARCNET_LINUX, 4, 8, 8, "ARCNET_LINUX"},#endif#ifdef DLT_ENC	{DLT_ENC, 0, 12, 12, "ENC"},#endif#ifdef DLT_FRELAY	{DLT_FRELAY, -1, 0, 0, "FRELAY"},#endif#ifdef DLT_IEEE802_11_RADIO	{DLT_IEEE802_11_RADIO, 64+24, 64+32, 64+27, "IEEE802_11_RADIO"},#endif#ifdef DLT_PFLOG	{DLT_PFLOG, 0, 28, 28, "PFLOG"},#endif	{-1, 0, 0, 0, ""}};enum {	aflag,	bflag,	dflag,	eflag,	fflag,	gflag,	hflag,	iflag,	Kflag,	kflag,	lflag,	mflag,	nflag,	pflag,	qflag,	rflag,	sflag,	tflag,	vflag,	xflag,};static struct getopt_parms parms[] = {	{'a', MY_GETOPT_ARG_REQUIRED, 0, 0},	{'b', MY_GETOPT_ARG_REQUIRED, 0, 0},	{'d', MY_GETOPT_ARG_REQUIRED, 0, 0},	{'e', MY_GETOPT_ARG_REQUIRED, 0, 0},	{'f', MY_GETOPT_ARG_REQUIRED, 0, 0},	{'g', MY_GETOPT_ARG_REQUIRED, 0, 0},	{'h', 0, 0, 0},	{'i', MY_GETOPT_ARG_REQUIRED, 0, 0},	{'K', MY_GETOPT_ARG_REQUIRED, 0, 0},	{'k', 0, 0, 0},	{'l', MY_GETOPT_ARG_REQUIRED, 0, 0},	{'m', MY_GETOPT_ARG_REQUIRED, 0, 0},	{'n', MY_GETOPT_ARG_REQUIRED, 0, 0},	{'p', 0, 0, 0},	{'q', MY_GETOPT_ARG_REQUIRED, 0, 0},	{'r', MY_GETOPT_ARG_REQUIRED, 0, 0},	{'s', MY_GETOPT_ARG_REQUIRED, 0, 0},	{'t', MY_GETOPT_ARG_REQUIRED, 0, 0},	{'v', MY_GETOPT_ARG_REQUIRED, 0, 0},	{'x', MY_GETOPT_ARG_REQUIRED, 0, 0},	{0, 0, 0, 0}};extern char *optarg;extern int optind, opterr, optopt;extern int errno;extern struct NetFlow NetFlow1;extern struct NetFlow NetFlow5;extern struct NetFlow NetFlow7;static unsigned promisc;static char *dev;static char *filter = "";static unsigned scan_interval = 5;static int frag_lifetime = 30;static int inactive_lifetime = 60;static int active_lifetime = 300;#define BULK_QUANTITY_MAX (unsigned)(mem_index_t)(-1)#if (MEM_BITS == 0) || (MEM_BITS == 16)#define BULK_QUANTITY 10000#else#define BULK_QUANTITY 200#endifstatic unsigned bulk_quantity = BULK_QUANTITY;static unsigned pending_queue_length = 100;static struct NetFlow *netflow = &NetFlow5;static unsigned verbosity = 6;static unsigned log_dest = MY_LOG_SYSLOG;static unsigned snmp_input_index;static unsigned snmp_output_index;static int link_layer_size = -1;static int link_layer;static struct Time start_time;static long start_time_offset;static int off_nl = -1;static int off_tl;/* From mem.c */extern unsigned total_elements;extern unsigned free_elements;extern unsigned total_memory;#if ((DEBUG) & DEBUG_I)static unsigned emit_pkts, emit_queue;static uint64_t size_total;static unsigned pkts_total, pkts_total_fragmented;static unsigned pkts_ignored, pkts_lost_capture, pkts_lost_unpending;static unsigned pkts_pending, pkts_pending_done;static unsigned pending_queue_trace, pending_queue_trace_candidate;static unsigned flows_total, flows_fragmented;/*From libpcap's README.linux:...Number of packets that had passed filtering but were notpassed on to pcap due to things like buffer shortage, etc...BTW pcap_stats() freeze on FreeBSD (4.6) with standart libpcapFIXME1. Check for support in other OS2. Compiling option?*/static unsigned pkts_dropped;# ifdef OS_LINUXstatic struct pcap_stat pstat;# endif#endifstatic unsigned emit_count;static uint32_t emit_sequence;static unsigned emit_rate_bytes, emit_rate_delay;static struct Time emit_time;static uint8_t emit_packet[NETFLOW_MAX_PACKET];static pcap_t* pcap_handle;static pthread_t thid;static sigset_t sig_mask;static struct sched_param schedp;static int sched_min, sched_max;static struct sockaddr_in client, server;static int sock;static int sigs;static struct Flow *flows[1 << HASH_BITS];static pthread_mutex_t flows_mutex[1 << HASH_BITS];static pthread_mutex_t unpending_mutex = PTHREAD_MUTEX_INITIALIZER;static pthread_cond_t unpending_cond = PTHREAD_COND_INITIALIZER;static pthread_mutex_t scan_mutex = PTHREAD_MUTEX_INITIALIZER;static pthread_cond_t scan_cond = PTHREAD_COND_INITIALIZER;static struct Flow *pending_head, *pending_tail;static struct Flow *scan_frag_dreg;static pthread_mutex_t emit_mutex = PTHREAD_MUTEX_INITIALIZER;static pthread_cond_t emit_cond = PTHREAD_COND_INITIALIZER;static struct Flow *flows_emit;static char ident[32];static pid_t pid;static int killed;static int emit_timeout = EMIT_TIMEOUT, unpending_timeout = UNPENDING_TIMEOUT;void usage(){	fprintf(stdout,		"fprobe: a NetFlow probe. Version %s\n"		"Usage: fprobe [options] host:port\n"		"\n"		"-h\t\tDisplay this help\n"		"-p\t\tDon't put the interface into promiscuous mode\n"		"-i <interface>\tNetwork interface name\n"		"-f <expression>\tFilter expression (see tcpdump manual for details)\n"		"-s <seconds>\tHow often scan for expired flows [5]\n"		"-g <seconds>\tFragmented flow lifetime [30]\n"		"-d <seconds>\tIdle flow lifetime (inactive timer) [60]\n"		"-e <seconds>\tActive flow lifetime (active timer) [300]\n"		"-n <version>\tNetFlow version for use (1, 5 or 7) [5]\n"		"-a <address>\tUse <address> as source for NetFlow flow\n"		"-x <id>[:<id>]\tWorkaround for SNMP interfaces indexes [0]\n"		"-b <flows>\tMemory bulk size (1..%u) [%u]\n"		"-m <kilobytes>\tMemory limit (0=no limit) [0]\n"		"-q <flows>\tPending queue length [100]\n"		"-r <priority>\tReal-time priority (0=disabled, %d..%d) [0]\n"		"-t <B:N>\tProduce <N> nanosecond delay after each <B> bytes sent [0:0]\n"		"-K <bytes>\tLink layer header size\n"		"-k\t\tDon't exclude link layer header from packet size\n"		"-v <level>\tMaximum log level (0=EMERG, ..., 6=INFO, 7=DEBUG) [6]\n"		"-l <dest>\tLog destination (0=none, 1=syslog, 2=stdout, 3=both) [1]\n"		"host:port\tAddress of the NetFlow collector\n",		VERSION, BULK_QUANTITY_MAX, bulk_quantity, sched_min, sched_max);	exit(0);}#if ((DEBUG) & DEBUG_I)void info_debug(){# ifdef OS_LINUX	pcap_stats(pcap_handle, &pstat);	pkts_dropped += pstat.ps_drop;# endif	my_log(LOG_DEBUG, "I: received:%d/%d (%lld) pending:%d/%d",		pkts_total, pkts_total_fragmented, size_total,		pkts_pending - pkts_pending_done, pending_queue_trace);	my_log(LOG_DEBUG, "I: ignored:%d lost:%d+%d dropped:%d",		pkts_ignored, pkts_lost_capture, pkts_lost_unpending, pkts_dropped);	my_log(LOG_DEBUG, "I: cache:%d/%d emit:%d/%d/%d",		flows_total, flows_fragmented, emit_sequence, emit_pkts, emit_queue);	my_log(LOG_DEBUG, "I: memory:%d/%d (%d)",		total_elements, free_elements, total_memory);}#endifvoid sighandler(int sig){	switch (sig) {		case SIGTERM:			sigs |= SIGTERM_MASK;			break;#if ((DEBUG) & DEBUG_I)		case SIGUSR1:			sigs |= SIGUSR1_MASK;			break;#endif	}}void gettime(struct Time *now){	struct timeval t;	gettimeofday(&t, 0);	now->sec = t.tv_sec;	now->usec = t.tv_usec;}inline time_t cmpmtime(struct Time *t1, struct Time *t2){	return (t1->sec - t2->sec) * 1000 + (t1->usec - t2->usec) / 1000;}/* Uptime in miliseconds */uint32_t getuptime(struct Time *t){	/* Maximum uptime is about 49/2 days */	return cmpmtime(t, &start_time);}hash_t hash_flow(struct Flow *flow){	if (flow->flags & FLOW_FRAG) return hash(flow, sizeof(struct Flow_F));	else return hash(flow, sizeof(struct Flow_TL));}inline void copy_flow(struct Flow *src, struct Flow *dst){	dst->sip = src->sip;	dst->dip = src->dip;	dst->tos = src->tos;	dst->proto = src->proto;	dst->tcp_flags = src->tcp_flags;	dst->id = src->id;	dst->sp = src->sp;	dst->dp = src->dp;	dst->pkts = src->pkts;	dst->size = src->size;	dst->sizeF = src->sizeF;	dst->sizeP = src->sizeP;	dst->ctime = src->ctime;	dst->mtime = src->mtime;	dst->flags = src->flags;}struct Flow *find(struct Flow *where, struct Flow *what, struct Flow ***prev){	struct Flow **flowpp;#ifdef WALL	flowpp = 0;#endif	if (prev) flowpp = *prev;	while (where) {		if (where->sip.s_addr == what->sip.s_addr			&& where->dip.s_addr == what->dip.s_addr			&& where->proto == what->proto) {			switch ((what->flags + where->flags) & FLOW_FRAGMASK) {				case 0:					/* Both unfragmented */					if ((what->sp == where->sp)						&& (what->dp == where->dp)) goto done;					break;				case 2:					/* Both fragmented */					if (where->id == what->id) goto done;					break;			}		}		flowpp = &where->next;		where = where->next;	}done:	if (prev) *prev = flowpp;	return where;}int put_into(struct Flow *flow, int flag#if ((DEBUG) & (DEBUG_S | DEBUG_U))	, char *logbuf#endif){	int ret = 0;	hash_t h;	struct Flow *flown, **flowpp;#if ((DEBUG) & (DEBUG_S | DEBUG_U))	char buf[64];#endif	h = hash_flow(flow);#if ((DEBUG) & (DEBUG_S | DEBUG_U))	sprintf(buf, " %x H:%04x", (unsigned) flow, h);	strcat(logbuf, buf);#endif	pthread_mutex_lock(&flows_mutex[h]);	flowpp = &flows[h];	if (!(flown = find(flows[h], flow, &flowpp))) {		/* No suitable flow found - add */		if (flag == COPY_INTO) {			if ((flown = mem_alloc())) {				copy_flow(flow, flown);				flow = flown;			} else {#if ((DEBUG) & (DEBUG_S | DEBUG_U)) || defined MESSAGES				my_log(LOG_ERR, "%s %s. %s",					"mem_alloc():", strerror(errno), "packet lost");#endif				return -1;			}		}		flow->next = flows[h];		flows[h] = flow;#if ((DEBUG) & DEBUG_I)		flows_total++;		if (flow->flags & FLOW_FRAG) flows_fragmented++;#endif#if ((DEBUG) & (DEBUG_S | DEBUG_U))		if (flown) {			sprintf(buf, " => %x, flags: %x", (unsigned) flown, flown->flags);			strcat(logbuf, buf);		}#endif	} else {		/* Found suitable flow - update */#if ((DEBUG) & (DEBUG_S | DEBUG_U))		sprintf(buf, " +> %x", (unsigned) flown);		strcat(logbuf, buf);#endif		if (cmpmtime(&flow->mtime, &flown->mtime) > 0)			flown->mtime = flow->mtime;

⌨️ 快捷键说明

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