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

📄 pcap-dag.c

📁 Ubuntu packages of security software。 相当不错的源码
💻 C
📖 第 1 页 / 共 2 页
字号:
/* * pcap-dag.c: Packet capture interface for Endace DAG card. * * The functionality of this code attempts to mimic that of pcap-linux as much * as possible.  This code is compiled in several different ways depending on * whether DAG_ONLY and HAVE_DAG_API are defined.  If HAVE_DAG_API is not * defined it should not get compiled in, otherwise if DAG_ONLY is defined then * the 'dag_' function calls are renamed to 'pcap_' equivalents.  If DAG_ONLY * is not defined then nothing is altered - the dag_ functions will be * called as required from their pcap-linux/bpf equivalents. * * Authors: Richard Littin, Sean Irvine ({richard,sean}@reeltwo.com) * Modifications: Jesper Peterson  <support@endace.com> *                Koryn Grant      <support@endace.com> *                Stephen Donnelly <support@endace.com> */#ifndef lintstatic const char rcsid[] _U_ =	"@(#) $Header: /tcpdump/master/libpcap/pcap-dag.c,v 1.21.2.3 2005/07/10 22:09:34 guy Exp $ (LBL)";#endif#ifdef HAVE_CONFIG_H#include "config.h"#endif#include <sys/param.h>			/* optionally get BSD define */#include <stdlib.h>#include <string.h>#include <errno.h>#include "pcap-int.h"#include <ctype.h>#include <netinet/in.h>#include <sys/mman.h>#include <sys/socket.h>#include <sys/types.h>#include <unistd.h>struct mbuf;		/* Squelch compiler warnings on some platforms for */struct rtentry;		/* declarations in <net/if.h> */#include <net/if.h>#include "dagnew.h"#include "dagapi.h"#define MIN_DAG_SNAPLEN		12#define MAX_DAG_SNAPLEN		2040#define ATM_CELL_SIZE		52#define ATM_HDR_SIZE		4/* SunATM pseudo header */struct sunatm_hdr {	unsigned char	flags;		/* destination and traffic type */	unsigned char	vpi;		/* VPI */	unsigned short	vci;		/* VCI */};typedef struct pcap_dag_node {	struct pcap_dag_node *next;	pcap_t *p;	pid_t pid;} pcap_dag_node_t;static pcap_dag_node_t *pcap_dags = NULL;static int atexit_handler_installed = 0;static const unsigned short endian_test_word = 0x0100;#define IS_BIGENDIAN() (*((unsigned char *)&endian_test_word))/* * Swap byte ordering of unsigned long long timestamp on a big endian * machine. */#define SWAP_TS(ull)  ((ull & 0xff00000000000000LL) >> 56) | \                      ((ull & 0x00ff000000000000LL) >> 40) | \                      ((ull & 0x0000ff0000000000LL) >> 24) | \                      ((ull & 0x000000ff00000000LL) >> 8)  | \                      ((ull & 0x00000000ff000000LL) << 8)  | \                      ((ull & 0x0000000000ff0000LL) << 24) | \                      ((ull & 0x000000000000ff00LL) << 40) | \                      ((ull & 0x00000000000000ffLL) << 56)#ifdef DAG_ONLY/* This code is required when compiling for a DAG device only. */#include "pcap-dag.h"/* Replace dag function names with pcap equivalent. */#define dag_open_live pcap_open_live#define dag_platform_finddevs pcap_platform_finddevs#endif /* DAG_ONLY */static int dag_setfilter(pcap_t *p, struct bpf_program *fp);static int dag_stats(pcap_t *p, struct pcap_stat *ps);static int dag_set_datalink(pcap_t *p, int dlt);static int dag_get_datalink(pcap_t *p);static int dag_setnonblock(pcap_t *p, int nonblock, char *errbuf);static voiddelete_pcap_dag(pcap_t *p){	pcap_dag_node_t *curr = NULL, *prev = NULL;	for (prev = NULL, curr = pcap_dags; curr != NULL && curr->p != p; prev = curr, curr = curr->next) {		/* empty */	}	if (curr != NULL && curr->p == p) {		if (prev != NULL) {			prev->next = curr->next;		} else {			pcap_dags = curr->next;		}	}}/* * Performs a graceful shutdown of the DAG card, frees dynamic memory held * in the pcap_t structure, and closes the file descriptor for the DAG card. */static voiddag_platform_close(pcap_t *p){		if (p != NULL) {#ifdef HAVE_DAG_STREAMS_API		if(dag_stop_stream(p->fd, p->md.dag_stream) < 0)			fprintf(stderr,"dag_stop_stream: %s\n", strerror(errno));				if(dag_detach_stream(p->fd, p->md.dag_stream) < 0)			fprintf(stderr,"dag_detach_stream: %s\n", strerror(errno));#else		if(dag_stop(p->fd) < 0)			fprintf(stderr,"dag_stop: %s\n", strerror(errno));#endif /* HAVE_DAG_STREAMS_API */		if(dag_close(p->fd) < 0)			fprintf(stderr,"dag_close: %s\n", strerror(errno));#ifdef linux				free(p->md.device);#endif	}	delete_pcap_dag(p);	/* Note: don't need to call close(p->fd) here as dag_close(p->fd) does this. */}static voidatexit_handler(void){	while (pcap_dags != NULL) {		if (pcap_dags->pid == getpid()) {			dag_platform_close(pcap_dags->p);		} else {			delete_pcap_dag(pcap_dags->p);		}	}}static intnew_pcap_dag(pcap_t *p){	pcap_dag_node_t *node = NULL;	if ((node = malloc(sizeof(pcap_dag_node_t))) == NULL) {		return -1;	}	if (!atexit_handler_installed) {		atexit(atexit_handler);		atexit_handler_installed = 1;	}	node->next = pcap_dags;	node->p = p;	node->pid = getpid();	pcap_dags = node;	return 0;}/* *  Read at most max_packets from the capture stream and call the callback *  for each of them. Returns the number of packets handled, -1 if an *  error occured, or -2 if we were told to break out of the loop. */static intdag_read(pcap_t *p, int cnt, pcap_handler callback, u_char *user){	unsigned int processed = 0;	int flags = p->md.dag_offset_flags;	unsigned int nonblocking = flags & DAGF_NONBLOCK;	/* Get the next bufferful of packets (if necessary). */	while (p->md.dag_mem_top - p->md.dag_mem_bottom < dag_record_size) { 		/*		 * Has "pcap_breakloop()" been called?		 */		if (p->break_loop) {			/*			 * Yes - clear the flag that indicates that			 * it has, and return -2 to indicate that			 * we were told to break out of the loop.			 */			p->break_loop = 0;			return -2;		}#ifdef HAVE_DAG_STREAMS_API		/* dag_advance_stream() will block (unless nonblock is called)		 * until 64kB of data has accumulated.		 * If to_ms is set, it will timeout before 64kB has accumulated.		 * We wait for 64kB because processing a few packets at a time		 * can cause problems at high packet rates (>200kpps) due		 * to inefficiencies.		 * This does mean if to_ms is not specified the capture may 'hang'		 * for long periods if the data rate is extremely slow (<64kB/sec)		 * If non-block is specified it will return immediately. The user		 * is then responsible for efficiency.		 */		p->md.dag_mem_top = dag_advance_stream(p->fd, p->md.dag_stream, (void**)&(p->md.dag_mem_bottom));#else		/* dag_offset does not support timeouts */		p->md.dag_mem_top = dag_offset(p->fd, &(p->md.dag_mem_bottom), flags);#endif /* HAVE_DAG_STREAMS_API */		if (nonblocking && (p->md.dag_mem_top - p->md.dag_mem_bottom < dag_record_size))		{			/* Pcap is configured to process only available packets, and there aren't any, return immediately. */			return 0;		}				if(!nonblocking &&		   p->md.dag_timeout &&		   (p->md.dag_mem_top - p->md.dag_mem_bottom < dag_record_size))		{			/* Blocking mode, but timeout set and no data has arrived, return anyway.*/			return 0;		}	}		/* Process the packets. */	while (p->md.dag_mem_top - p->md.dag_mem_bottom >= dag_record_size) {		unsigned short packet_len = 0;		int caplen = 0;		struct pcap_pkthdr	pcap_header;#ifdef HAVE_DAG_STREAMS_API		dag_record_t *header = (dag_record_t *)(p->md.dag_mem_bottom);#else		dag_record_t *header = (dag_record_t *)(p->md.dag_mem_base + p->md.dag_mem_bottom);#endif /* HAVE_DAG_STREAMS_API */		u_char *dp = ((u_char *)header) + dag_record_size;		unsigned short rlen; 		/*		 * Has "pcap_breakloop()" been called?		 */		if (p->break_loop) {			/*			 * Yes - clear the flag that indicates that			 * it has, and return -2 to indicate that			 * we were told to break out of the loop.			 */			p->break_loop = 0;			return -2;		} 		rlen = ntohs(header->rlen);		if (rlen < dag_record_size)		{			strncpy(p->errbuf, "dag_read: record too small", PCAP_ERRBUF_SIZE);			return -1;		}		p->md.dag_mem_bottom += rlen;		switch(header->type) {		case TYPE_AAL5:		case TYPE_ATM:#ifdef TYPE_MC_ATM		case TYPE_MC_ATM:			if (header->type == TYPE_MC_ATM) {				caplen = packet_len = ATM_CELL_SIZE;				dp+=4;			}#endif#ifdef TYPE_MC_AAL5		case TYPE_MC_AAL5:			if (header->type == TYPE_MC_AAL5) {				packet_len = ntohs(header->wlen);				caplen = rlen - dag_record_size - 4;				dp+=4;			}#endif			if (header->type == TYPE_AAL5) {				packet_len = ntohs(header->wlen);				caplen = rlen - dag_record_size;			} else if(header->type == TYPE_ATM) {				caplen = packet_len = ATM_CELL_SIZE;			}			if (p->linktype == DLT_SUNATM) {				struct sunatm_hdr *sunatm = (struct sunatm_hdr *)dp;				unsigned long rawatm;									rawatm = ntohl(*((unsigned long *)dp));				sunatm->vci = htons((rawatm >>  4) & 0xffff);				sunatm->vpi = (rawatm >> 20) & 0x00ff;				sunatm->flags = ((header->flags.iface & 1) ? 0x80 : 0x00) | 					((sunatm->vpi == 0 && sunatm->vci == htons(5)) ? 6 :					 ((sunatm->vpi == 0 && sunatm->vci == htons(16)) ? 5 : 					  ((dp[ATM_HDR_SIZE] == 0xaa &&					    dp[ATM_HDR_SIZE+1] == 0xaa &&					    dp[ATM_HDR_SIZE+2] == 0x03) ? 2 : 1)));			} else {				packet_len -= ATM_HDR_SIZE;				caplen -= ATM_HDR_SIZE;				dp += ATM_HDR_SIZE;			}			break;#ifdef TYPE_COLOR_ETH		case TYPE_COLOR_ETH:#endif		case TYPE_ETH:			packet_len = ntohs(header->wlen);			packet_len -= (p->md.dag_fcs_bits >> 3);			caplen = rlen - dag_record_size - 2;			if (caplen > packet_len) {				caplen = packet_len;			}			dp += 2;			break;#ifdef TYPE_COLOR_HDLC_POS		case TYPE_COLOR_HDLC_POS:#endif		case TYPE_HDLC_POS:			packet_len = ntohs(header->wlen);			packet_len -= (p->md.dag_fcs_bits >> 3);			caplen = rlen - dag_record_size;			if (caplen > packet_len) {				caplen = packet_len;			}			break;#ifdef TYPE_MC_HDLC		case TYPE_MC_HDLC:			packet_len = ntohs(header->wlen);			packet_len -= (p->md.dag_fcs_bits >> 3);			caplen = rlen - dag_record_size - 4;			if (caplen > packet_len) {				caplen = packet_len;			}			dp += 4;			break;#endif		} 		if (caplen > p->snapshot)			caplen = p->snapshot;		/* Count lost packets. */		switch(header->type) {#ifdef TYPE_COLOR_HDLC_POS			/* in this type the color value overwrites the lctr */		case TYPE_COLOR_HDLC_POS:			break;#endif#ifdef TYPE_COLOR_ETH			/* in this type the color value overwrites the lctr */		case TYPE_COLOR_ETH:			break;#endif		default:			if (header->lctr) {				if (p->md.stat.ps_drop > (UINT_MAX - ntohs(header->lctr))) {					p->md.stat.ps_drop = UINT_MAX;				} else {					p->md.stat.ps_drop += ntohs(header->lctr);				}			}		}		/* Run the packet filter if there is one. */		if ((p->fcode.bf_insns == NULL) || bpf_filter(p->fcode.bf_insns, dp, packet_len, caplen)) {			/* convert between timestamp formats */			register unsigned long long ts;							if (IS_BIGENDIAN()) {				ts = SWAP_TS(header->ts);			} else {				ts = header->ts;			}			pcap_header.ts.tv_sec = ts >> 32;			ts = (ts & 0xffffffffULL) * 1000000;			ts += 0x80000000; /* rounding */			pcap_header.ts.tv_usec = ts >> 32;					if (pcap_header.ts.tv_usec >= 1000000) {				pcap_header.ts.tv_usec -= 1000000;				pcap_header.ts.tv_sec++;			}			/* Fill in our own header data */			pcap_header.caplen = caplen;			pcap_header.len = packet_len;				/* Count the packet. */			p->md.stat.ps_recv++;				/* Call the user supplied callback function */			callback(user, &pcap_header, dp);				/* Only count packets that pass the filter, for consistency with standard Linux behaviour. */			processed++;			if (processed == cnt)			{				/* Reached the user-specified limit. */				return cnt;			}		}	}	return processed;}static intdag_inject(pcap_t *p, const void *buf _U_, size_t size _U_){	strlcpy(p->errbuf, "Sending packets isn't supported on DAG cards",	    PCAP_ERRBUF_SIZE);	return (-1);}/* *  Get a handle for a live capture from the given DAG device.  Passing a NULL *  device will result in a failure.  The promisc flag is ignored because DAG

⌨️ 快捷键说明

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