Home | History | Annotate | Download | only in libpcap
      1 /*
      2  * pcap-dag.c: Packet capture interface for Endace DAG card.
      3  *
      4  * The functionality of this code attempts to mimic that of pcap-linux as much
      5  * as possible.  This code is compiled in several different ways depending on
      6  * whether DAG_ONLY and HAVE_DAG_API are defined.  If HAVE_DAG_API is not
      7  * defined it should not get compiled in, otherwise if DAG_ONLY is defined then
      8  * the 'dag_' function calls are renamed to 'pcap_' equivalents.  If DAG_ONLY
      9  * is not defined then nothing is altered - the dag_ functions will be
     10  * called as required from their pcap-linux/bpf equivalents.
     11  *
     12  * Authors: Richard Littin, Sean Irvine ({richard,sean}@reeltwo.com)
     13  * Modifications: Jesper Peterson  <support (at) endace.com>
     14  *                Koryn Grant      <support (at) endace.com>
     15  *                Stephen Donnelly <support (at) endace.com>
     16  */
     17 
     18 #ifndef lint
     19 static const char rcsid[] _U_ =
     20 	"@(#) $Header: /tcpdump/master/libpcap/pcap-dag.c,v 1.21.2.7 2007/06/22 06:43:58 guy Exp $ (LBL)";
     21 #endif
     22 
     23 #ifdef HAVE_CONFIG_H
     24 #include "config.h"
     25 #endif
     26 
     27 #include <sys/param.h>			/* optionally get BSD define */
     28 
     29 #include <stdlib.h>
     30 #include <string.h>
     31 #include <errno.h>
     32 
     33 #include "pcap-int.h"
     34 
     35 #include <ctype.h>
     36 #include <netinet/in.h>
     37 #include <sys/mman.h>
     38 #include <sys/socket.h>
     39 #include <sys/types.h>
     40 #include <unistd.h>
     41 
     42 struct mbuf;		/* Squelch compiler warnings on some platforms for */
     43 struct rtentry;		/* declarations in <net/if.h> */
     44 #include <net/if.h>
     45 
     46 #include "dagnew.h"
     47 #include "dagapi.h"
     48 
     49 #define ATM_CELL_SIZE		52
     50 #define ATM_HDR_SIZE		4
     51 
     52 /*
     53  * A header containing additional MTP information.
     54  */
     55 #define MTP2_SENT_OFFSET		0	/* 1 byte */
     56 #define MTP2_ANNEX_A_USED_OFFSET	1	/* 1 byte */
     57 #define MTP2_LINK_NUMBER_OFFSET		2	/* 2 bytes */
     58 #define MTP2_HDR_LEN			4	/* length of the header */
     59 
     60 #define MTP2_ANNEX_A_NOT_USED      0
     61 #define MTP2_ANNEX_A_USED          1
     62 #define MTP2_ANNEX_A_USED_UNKNOWN  2
     63 
     64 /* SunATM pseudo header */
     65 struct sunatm_hdr {
     66 	unsigned char	flags;		/* destination and traffic type */
     67 	unsigned char	vpi;		/* VPI */
     68 	unsigned short	vci;		/* VCI */
     69 };
     70 
     71 typedef struct pcap_dag_node {
     72 	struct pcap_dag_node *next;
     73 	pcap_t *p;
     74 	pid_t pid;
     75 } pcap_dag_node_t;
     76 
     77 static pcap_dag_node_t *pcap_dags = NULL;
     78 static int atexit_handler_installed = 0;
     79 static const unsigned short endian_test_word = 0x0100;
     80 
     81 #define IS_BIGENDIAN() (*((unsigned char *)&endian_test_word))
     82 
     83 
     84 #ifdef DAG_ONLY
     85 /* This code is required when compiling for a DAG device only. */
     86 #include "pcap-dag.h"
     87 
     88 /* Replace dag function names with pcap equivalent. */
     89 #define dag_open_live pcap_open_live
     90 #define dag_platform_finddevs pcap_platform_finddevs
     91 #endif /* DAG_ONLY */
     92 
     93 #define MAX_DAG_PACKET 65536
     94 
     95 static unsigned char TempPkt[MAX_DAG_PACKET];
     96 
     97 static int dag_setfilter(pcap_t *p, struct bpf_program *fp);
     98 static int dag_stats(pcap_t *p, struct pcap_stat *ps);
     99 static int dag_set_datalink(pcap_t *p, int dlt);
    100 static int dag_get_datalink(pcap_t *p);
    101 static int dag_setnonblock(pcap_t *p, int nonblock, char *errbuf);
    102 
    103 static void
    104 delete_pcap_dag(pcap_t *p)
    105 {
    106 	pcap_dag_node_t *curr = NULL, *prev = NULL;
    107 
    108 	for (prev = NULL, curr = pcap_dags; curr != NULL && curr->p != p; prev = curr, curr = curr->next) {
    109 		/* empty */
    110 	}
    111 
    112 	if (curr != NULL && curr->p == p) {
    113 		if (prev != NULL) {
    114 			prev->next = curr->next;
    115 		} else {
    116 			pcap_dags = curr->next;
    117 		}
    118 	}
    119 }
    120 
    121 /*
    122  * Performs a graceful shutdown of the DAG card, frees dynamic memory held
    123  * in the pcap_t structure, and closes the file descriptor for the DAG card.
    124  */
    125 
    126 static void
    127 dag_platform_close(pcap_t *p)
    128 {
    129 
    130 	if (p != NULL) {
    131 #ifdef HAVE_DAG_STREAMS_API
    132 		if(dag_stop_stream(p->fd, p->md.dag_stream) < 0)
    133 			fprintf(stderr,"dag_stop_stream: %s\n", strerror(errno));
    134 
    135 		if(dag_detach_stream(p->fd, p->md.dag_stream) < 0)
    136 			fprintf(stderr,"dag_detach_stream: %s\n", strerror(errno));
    137 #else
    138 		if(dag_stop(p->fd) < 0)
    139 			fprintf(stderr,"dag_stop: %s\n", strerror(errno));
    140 #endif /* HAVE_DAG_STREAMS_API */
    141 		if(dag_close(p->fd) < 0)
    142 			fprintf(stderr,"dag_close: %s\n", strerror(errno));
    143 	}
    144 	delete_pcap_dag(p);
    145 	/* Note: don't need to call close(p->fd) here as dag_close(p->fd) does this. */
    146 }
    147 
    148 static void
    149 atexit_handler(void)
    150 {
    151 	while (pcap_dags != NULL) {
    152 		if (pcap_dags->pid == getpid()) {
    153 			dag_platform_close(pcap_dags->p);
    154 		} else {
    155 			delete_pcap_dag(pcap_dags->p);
    156 		}
    157 	}
    158 }
    159 
    160 static int
    161 new_pcap_dag(pcap_t *p)
    162 {
    163 	pcap_dag_node_t *node = NULL;
    164 
    165 	if ((node = malloc(sizeof(pcap_dag_node_t))) == NULL) {
    166 		return -1;
    167 	}
    168 
    169 	if (!atexit_handler_installed) {
    170 		atexit(atexit_handler);
    171 		atexit_handler_installed = 1;
    172 	}
    173 
    174 	node->next = pcap_dags;
    175 	node->p = p;
    176 	node->pid = getpid();
    177 
    178 	pcap_dags = node;
    179 
    180 	return 0;
    181 }
    182 
    183 /*
    184  *  Read at most max_packets from the capture stream and call the callback
    185  *  for each of them. Returns the number of packets handled, -1 if an
    186  *  error occured, or -2 if we were told to break out of the loop.
    187  */
    188 static int
    189 dag_read(pcap_t *p, int cnt, pcap_handler callback, u_char *user)
    190 {
    191 	unsigned int processed = 0;
    192 	int flags = p->md.dag_offset_flags;
    193 	unsigned int nonblocking = flags & DAGF_NONBLOCK;
    194 
    195 	/* Get the next bufferful of packets (if necessary). */
    196 	while (p->md.dag_mem_top - p->md.dag_mem_bottom < dag_record_size) {
    197 
    198 		/*
    199 		 * Has "pcap_breakloop()" been called?
    200 		 */
    201 		if (p->break_loop) {
    202 			/*
    203 			 * Yes - clear the flag that indicates that
    204 			 * it has, and return -2 to indicate that
    205 			 * we were told to break out of the loop.
    206 			 */
    207 			p->break_loop = 0;
    208 			return -2;
    209 		}
    210 
    211 #ifdef HAVE_DAG_STREAMS_API
    212 		/* dag_advance_stream() will block (unless nonblock is called)
    213 		 * until 64kB of data has accumulated.
    214 		 * If to_ms is set, it will timeout before 64kB has accumulated.
    215 		 * We wait for 64kB because processing a few packets at a time
    216 		 * can cause problems at high packet rates (>200kpps) due
    217 		 * to inefficiencies.
    218 		 * This does mean if to_ms is not specified the capture may 'hang'
    219 		 * for long periods if the data rate is extremely slow (<64kB/sec)
    220 		 * If non-block is specified it will return immediately. The user
    221 		 * is then responsible for efficiency.
    222 		 */
    223 		p->md.dag_mem_top = dag_advance_stream(p->fd, p->md.dag_stream, &(p->md.dag_mem_bottom));
    224 #else
    225 		/* dag_offset does not support timeouts */
    226 		p->md.dag_mem_top = dag_offset(p->fd, &(p->md.dag_mem_bottom), flags);
    227 #endif /* HAVE_DAG_STREAMS_API */
    228 
    229 		if (nonblocking && (p->md.dag_mem_top - p->md.dag_mem_bottom < dag_record_size))
    230 		{
    231 			/* Pcap is configured to process only available packets, and there aren't any, return immediately. */
    232 			return 0;
    233 		}
    234 
    235 		if(!nonblocking &&
    236 		   p->md.dag_timeout &&
    237 		   (p->md.dag_mem_top - p->md.dag_mem_bottom < dag_record_size))
    238 		{
    239 			/* Blocking mode, but timeout set and no data has arrived, return anyway.*/
    240 			return 0;
    241 		}
    242 
    243 	}
    244 
    245 	/* Process the packets. */
    246 	while (p->md.dag_mem_top - p->md.dag_mem_bottom >= dag_record_size) {
    247 
    248 		unsigned short packet_len = 0;
    249 		int caplen = 0;
    250 		struct pcap_pkthdr	pcap_header;
    251 
    252 #ifdef HAVE_DAG_STREAMS_API
    253 		dag_record_t *header = (dag_record_t *)(p->md.dag_mem_bottom);
    254 #else
    255 		dag_record_t *header = (dag_record_t *)(p->md.dag_mem_base + p->md.dag_mem_bottom);
    256 #endif /* HAVE_DAG_STREAMS_API */
    257 
    258 		u_char *dp = ((u_char *)header) + dag_record_size;
    259 		unsigned short rlen;
    260 
    261 		/*
    262 		 * Has "pcap_breakloop()" been called?
    263 		 */
    264 		if (p->break_loop) {
    265 			/*
    266 			 * Yes - clear the flag that indicates that
    267 			 * it has, and return -2 to indicate that
    268 			 * we were told to break out of the loop.
    269 			 */
    270 			p->break_loop = 0;
    271 			return -2;
    272 		}
    273 
    274 		rlen = ntohs(header->rlen);
    275 		if (rlen < dag_record_size)
    276 		{
    277 			strncpy(p->errbuf, "dag_read: record too small", PCAP_ERRBUF_SIZE);
    278 			return -1;
    279 		}
    280 		p->md.dag_mem_bottom += rlen;
    281 
    282 		switch(header->type) {
    283 		case TYPE_ATM:
    284 #ifdef TYPE_AAL5
    285 		case TYPE_AAL5:
    286 			if (header->type == TYPE_AAL5) {
    287 				packet_len = ntohs(header->wlen);
    288 				caplen = rlen - dag_record_size;
    289 			}
    290 #endif
    291 #ifdef TYPE_MC_ATM
    292 		case TYPE_MC_ATM:
    293 			if (header->type == TYPE_MC_ATM) {
    294 				caplen = packet_len = ATM_CELL_SIZE;
    295 				dp+=4;
    296 			}
    297 #endif
    298 #ifdef TYPE_MC_AAL5
    299 		case TYPE_MC_AAL5:
    300 			if (header->type == TYPE_MC_AAL5) {
    301 				packet_len = ntohs(header->wlen);
    302 				caplen = rlen - dag_record_size - 4;
    303 				dp+=4;
    304 			}
    305 #endif
    306 			if (header->type == TYPE_ATM) {
    307 				caplen = packet_len = ATM_CELL_SIZE;
    308 			}
    309 			if (p->linktype == DLT_SUNATM) {
    310 				struct sunatm_hdr *sunatm = (struct sunatm_hdr *)dp;
    311 				unsigned long rawatm;
    312 
    313 				rawatm = ntohl(*((unsigned long *)dp));
    314 				sunatm->vci = htons((rawatm >>  4) & 0xffff);
    315 				sunatm->vpi = (rawatm >> 20) & 0x00ff;
    316 				sunatm->flags = ((header->flags.iface & 1) ? 0x80 : 0x00) |
    317 					((sunatm->vpi == 0 && sunatm->vci == htons(5)) ? 6 :
    318 					 ((sunatm->vpi == 0 && sunatm->vci == htons(16)) ? 5 :
    319 					  ((dp[ATM_HDR_SIZE] == 0xaa &&
    320 					    dp[ATM_HDR_SIZE+1] == 0xaa &&
    321 					    dp[ATM_HDR_SIZE+2] == 0x03) ? 2 : 1)));
    322 
    323 			} else {
    324 				packet_len -= ATM_HDR_SIZE;
    325 				caplen -= ATM_HDR_SIZE;
    326 				dp += ATM_HDR_SIZE;
    327 			}
    328 			break;
    329 
    330 #ifdef TYPE_DSM_COLOR_ETH
    331 		case TYPE_DSM_COLOR_ETH:
    332 #endif
    333 #ifdef TYPE_COLOR_ETH
    334 		case TYPE_COLOR_ETH:
    335 #endif
    336 		case TYPE_ETH:
    337 			packet_len = ntohs(header->wlen);
    338 			packet_len -= (p->md.dag_fcs_bits >> 3);
    339 			caplen = rlen - dag_record_size - 2;
    340 			if (caplen > packet_len) {
    341 				caplen = packet_len;
    342 			}
    343 			dp += 2;
    344 			break;
    345 #ifdef TYPE_DSM_COLOR_HDLC_POS
    346 		case TYPE_DSM_COLOR_HDLC_POS:
    347 #endif
    348 #ifdef TYPE_COLOR_HDLC_POS
    349 		case TYPE_COLOR_HDLC_POS:
    350 #endif
    351 		case TYPE_HDLC_POS:
    352 			packet_len = ntohs(header->wlen);
    353 			packet_len -= (p->md.dag_fcs_bits >> 3);
    354 			caplen = rlen - dag_record_size;
    355 			if (caplen > packet_len) {
    356 				caplen = packet_len;
    357 			}
    358 			break;
    359 #ifdef TYPE_COLOR_MC_HDLC_POS
    360 		case TYPE_COLOR_MC_HDLC_POS:
    361 #endif
    362 #ifdef TYPE_MC_HDLC
    363 		case TYPE_MC_HDLC:
    364 			packet_len = ntohs(header->wlen);
    365 			packet_len -= (p->md.dag_fcs_bits >> 3);
    366 			caplen = rlen - dag_record_size - 4;
    367 			if (caplen > packet_len) {
    368 				caplen = packet_len;
    369 			}
    370 			/* jump the MC_HDLC_HEADER */
    371 			dp += 4;
    372 			if (p->linktype == DLT_MTP2_WITH_PHDR) {
    373 				/* Add the MTP2 Pseudo Header */
    374 				caplen += MTP2_HDR_LEN;
    375 				packet_len += MTP2_HDR_LEN;
    376 
    377 				TempPkt[MTP2_SENT_OFFSET] = 0;
    378 				TempPkt[MTP2_ANNEX_A_USED_OFFSET] = MTP2_ANNEX_A_USED_UNKNOWN;
    379 				*(TempPkt+MTP2_LINK_NUMBER_OFFSET) = ((header->rec.mc_hdlc.mc_header>>16)&0x01);
    380 				*(TempPkt+MTP2_LINK_NUMBER_OFFSET+1) = ((header->rec.mc_hdlc.mc_header>>24)&0xff);
    381 				memcpy(TempPkt+MTP2_HDR_LEN, dp, caplen);
    382 				dp = TempPkt;
    383 			}
    384 			break;
    385 #endif
    386 		default:
    387 			/* Unhandled ERF type.
    388 			 * Ignore rather than generating error
    389 			 */
    390 			continue;
    391 		}
    392 
    393 		if (caplen > p->snapshot)
    394 			caplen = p->snapshot;
    395 
    396 		/* Count lost packets. */
    397 		switch(header->type) {
    398 #ifdef TYPE_COLOR_HDLC_POS
    399 			/* in this type the color value overwrites the lctr */
    400 		case TYPE_COLOR_HDLC_POS:
    401 			break;
    402 #endif
    403 #ifdef TYPE_COLOR_ETH
    404 			/* in this type the color value overwrites the lctr */
    405 		case TYPE_COLOR_ETH:
    406 			break;
    407 #endif
    408 #ifdef TYPE_DSM_COLOR_HDLC_POS
    409 			/* in this type the color value overwrites the lctr */
    410 		case TYPE_DSM_COLOR_HDLC_POS:
    411 			break;
    412 #endif
    413 #ifdef TYPE_DSM_COLOR_ETH
    414 			/* in this type the color value overwrites the lctr */
    415 		case TYPE_DSM_COLOR_ETH:
    416 			break;
    417 #endif
    418 #ifdef TYPE_COLOR_MC_HDLC_POS
    419 		case TYPE_COLOR_MC_HDLC_POS:
    420 			break;
    421 #endif
    422 
    423 		default:
    424 			if (header->lctr) {
    425 				if (p->md.stat.ps_drop > (UINT_MAX - ntohs(header->lctr))) {
    426 					p->md.stat.ps_drop = UINT_MAX;
    427 				} else {
    428 					p->md.stat.ps_drop += ntohs(header->lctr);
    429 				}
    430 			}
    431 		}
    432 
    433 		/* Run the packet filter if there is one. */
    434 		if ((p->fcode.bf_insns == NULL) || bpf_filter(p->fcode.bf_insns, dp, packet_len, caplen)) {
    435 
    436 			/* convert between timestamp formats */
    437 			register unsigned long long ts;
    438 
    439 			if (IS_BIGENDIAN()) {
    440 				ts = SWAPLL(header->ts);
    441 			} else {
    442 				ts = header->ts;
    443 			}
    444 
    445 			pcap_header.ts.tv_sec = ts >> 32;
    446 			ts = (ts & 0xffffffffULL) * 1000000;
    447 			ts += 0x80000000; /* rounding */
    448 			pcap_header.ts.tv_usec = ts >> 32;
    449 			if (pcap_header.ts.tv_usec >= 1000000) {
    450 				pcap_header.ts.tv_usec -= 1000000;
    451 				pcap_header.ts.tv_sec++;
    452 			}
    453 
    454 			/* Fill in our own header data */
    455 			pcap_header.caplen = caplen;
    456 			pcap_header.len = packet_len;
    457 
    458 			/* Count the packet. */
    459 			p->md.stat.ps_recv++;
    460 
    461 			/* Call the user supplied callback function */
    462 			callback(user, &pcap_header, dp);
    463 
    464 			/* Only count packets that pass the filter, for consistency with standard Linux behaviour. */
    465 			processed++;
    466 			if (processed == cnt)
    467 			{
    468 				/* Reached the user-specified limit. */
    469 				return cnt;
    470 			}
    471 		}
    472 	}
    473 
    474 	return processed;
    475 }
    476 
    477 static int
    478 dag_inject(pcap_t *p, const void *buf _U_, size_t size _U_)
    479 {
    480 	strlcpy(p->errbuf, "Sending packets isn't supported on DAG cards",
    481 	    PCAP_ERRBUF_SIZE);
    482 	return (-1);
    483 }
    484 
    485 /*
    486  *  Get a handle for a live capture from the given DAG device.  Passing a NULL
    487  *  device will result in a failure.  The promisc flag is ignored because DAG
    488  *  cards are always promiscuous.  The to_ms parameter is also ignored as it is
    489  *  not supported in hardware.
    490  *
    491  *  snaplen is now also ignored, until we get per-stream slen support. Set
    492  *  slen with approprite DAG tool BEFORE pcap_open_live().
    493  *
    494  *  See also pcap(3).
    495  */
    496 pcap_t *
    497 dag_open_live(const char *device, int snaplen, int promisc, int to_ms, char *ebuf)
    498 {
    499 	char conf[30]; /* dag configure string */
    500 	pcap_t *handle;
    501 	char *s;
    502 	int n;
    503 	daginf_t* daginf;
    504 	char * newDev = NULL;
    505 #ifdef HAVE_DAG_STREAMS_API
    506 	uint32_t mindata;
    507 	struct timeval maxwait;
    508 	struct timeval poll;
    509 #endif
    510 
    511 	if (device == NULL) {
    512 		snprintf(ebuf, PCAP_ERRBUF_SIZE, "device is NULL: %s", pcap_strerror(errno));
    513 		return NULL;
    514 	}
    515 	/* Allocate a handle for this session. */
    516 
    517 	handle = malloc(sizeof(*handle));
    518 	if (handle == NULL) {
    519 		snprintf(ebuf, PCAP_ERRBUF_SIZE, "malloc %s: %s", device, pcap_strerror(errno));
    520 		return NULL;
    521 	}
    522 
    523 	/* Initialize some components of the pcap structure. */
    524 
    525 	memset(handle, 0, sizeof(*handle));
    526 
    527 #ifdef HAVE_DAG_STREAMS_API
    528 	newDev = (char *)malloc(strlen(device) + 16);
    529 	if (newDev == NULL) {
    530 		snprintf(ebuf, PCAP_ERRBUF_SIZE, "Can't allocate string for device name: %s\n", pcap_strerror(errno));
    531 		goto fail;
    532 	}
    533 
    534 	/* Parse input name to get dag device and stream number if provided */
    535 	if (dag_parse_name(device, newDev, strlen(device) + 16, &handle->md.dag_stream) < 0) {
    536 		snprintf(ebuf, PCAP_ERRBUF_SIZE, "dag_parse_name: %s\n", pcap_strerror(errno));
    537 		goto fail;
    538 	}
    539 	device = newDev;
    540 
    541 	if (handle->md.dag_stream%2) {
    542 		snprintf(ebuf, PCAP_ERRBUF_SIZE, "dag_parse_name: tx (even numbered) streams not supported for capture\n");
    543 		goto fail;
    544 	}
    545 #else
    546 	if (strncmp(device, "/dev/", 5) != 0) {
    547 		newDev = (char *)malloc(strlen(device) + 5);
    548 		if (newDev == NULL) {
    549 			snprintf(ebuf, PCAP_ERRBUF_SIZE, "Can't allocate string for device name: %s\n", pcap_strerror(errno));
    550 			goto fail;
    551 		}
    552 		strcpy(newDev, "/dev/");
    553 		strcat(newDev, device);
    554 		device = newDev;
    555 	}
    556 #endif /* HAVE_DAG_STREAMS_API */
    557 
    558 	/* setup device parameters */
    559 	if((handle->fd = dag_open((char *)device)) < 0) {
    560 		snprintf(ebuf, PCAP_ERRBUF_SIZE, "dag_open %s: %s", device, pcap_strerror(errno));
    561 		goto fail;
    562 	}
    563 
    564 #ifdef HAVE_DAG_STREAMS_API
    565 	/* Open requested stream. Can fail if already locked or on error */
    566 	if (dag_attach_stream(handle->fd, handle->md.dag_stream, 0, 0) < 0) {
    567 		snprintf(ebuf, PCAP_ERRBUF_SIZE, "dag_attach_stream: %s\n", pcap_strerror(errno));
    568 		goto failclose;
    569 	}
    570 
    571 	/* Set up default poll parameters for stream
    572 	 * Can be overridden by pcap_set_nonblock()
    573 	 */
    574 	if (dag_get_stream_poll(handle->fd, handle->md.dag_stream,
    575 				&mindata, &maxwait, &poll) < 0) {
    576 		snprintf(ebuf, PCAP_ERRBUF_SIZE, "dag_get_stream_poll: %s\n", pcap_strerror(errno));
    577 		goto faildetach;
    578 	}
    579 
    580 	/* Amount of data to collect in Bytes before calling callbacks.
    581 	 * Important for efficiency, but can introduce latency
    582 	 * at low packet rates if to_ms not set!
    583 	 */
    584 	mindata = 65536;
    585 
    586 	/* Obey to_ms if supplied. This is a good idea!
    587 	 * Recommend 10-100ms. Calls will time out even if no data arrived.
    588 	 */
    589 	maxwait.tv_sec = to_ms/1000;
    590 	maxwait.tv_usec = (to_ms%1000) * 1000;
    591 
    592 	if (dag_set_stream_poll(handle->fd, handle->md.dag_stream,
    593 				mindata, &maxwait, &poll) < 0) {
    594 		snprintf(ebuf, PCAP_ERRBUF_SIZE, "dag_set_stream_poll: %s\n", pcap_strerror(errno));
    595 		goto faildetach;
    596 	}
    597 
    598 #else
    599 	if((handle->md.dag_mem_base = dag_mmap(handle->fd)) == MAP_FAILED) {
    600 		snprintf(ebuf, PCAP_ERRBUF_SIZE,"dag_mmap %s: %s\n", device, pcap_strerror(errno));
    601 		goto failclose;
    602 	}
    603 
    604 #endif /* HAVE_DAG_STREAMS_API */
    605 
    606         /* XXX Not calling dag_configure() to set slen; this is unsafe in
    607 	 * multi-stream environments as the gpp config is global.
    608          * Once the firmware provides 'per-stream slen' this can be supported
    609 	 * again via the Config API without side-effects */
    610 #if 0
    611 	/* set the card snap length to the specified snaplen parameter */
    612 	/* This is a really bad idea, as different cards have different
    613 	 * valid slen ranges. Should fix in Config API. */
    614 	if (snaplen == 0 || snaplen > MAX_DAG_SNAPLEN) {
    615 		snaplen = MAX_DAG_SNAPLEN;
    616 	} else if (snaplen < MIN_DAG_SNAPLEN) {
    617 		snaplen = MIN_DAG_SNAPLEN;
    618 	}
    619 	/* snap len has to be a multiple of 4 */
    620 	snprintf(conf, 30, "varlen slen=%d", (snaplen + 3) & ~3);
    621 
    622 	if(dag_configure(handle->fd, conf) < 0) {
    623 		snprintf(ebuf, PCAP_ERRBUF_SIZE,"dag_configure %s: %s\n", device, pcap_strerror(errno));
    624 		goto faildetach;
    625 	}
    626 #endif
    627 
    628 #ifdef HAVE_DAG_STREAMS_API
    629 	if(dag_start_stream(handle->fd, handle->md.dag_stream) < 0) {
    630 		snprintf(ebuf, PCAP_ERRBUF_SIZE, "dag_start_stream %s: %s\n", device, pcap_strerror(errno));
    631 		goto faildetach;
    632 	}
    633 #else
    634 	if(dag_start(handle->fd) < 0) {
    635 		snprintf(ebuf, PCAP_ERRBUF_SIZE, "dag_start %s: %s\n", device, pcap_strerror(errno));
    636 		goto failclose;
    637 	}
    638 #endif /* HAVE_DAG_STREAMS_API */
    639 
    640 	/*
    641 	 * Important! You have to ensure bottom is properly
    642 	 * initialized to zero on startup, it won't give you
    643 	 * a compiler warning if you make this mistake!
    644 	 */
    645 	handle->md.dag_mem_bottom = 0;
    646 	handle->md.dag_mem_top = 0;
    647 	handle->md.dag_fcs_bits = 32;
    648 
    649 	/* Query the card first for special cases. */
    650 	daginf = dag_info(handle->fd);
    651 	if ((0x4200 == daginf->device_code) || (0x4230 == daginf->device_code))
    652 	{
    653 		/* DAG 4.2S and 4.23S already strip the FCS.  Stripping the final word again truncates the packet. */
    654 		handle->md.dag_fcs_bits = 0;
    655 	}
    656 
    657 	/* Then allow an environment variable to override. */
    658 	if ((s = getenv("ERF_FCS_BITS")) != NULL) {
    659 		if ((n = atoi(s)) == 0 || n == 16|| n == 32) {
    660 			handle->md.dag_fcs_bits = n;
    661 		} else {
    662 			snprintf(ebuf, PCAP_ERRBUF_SIZE,
    663 				"pcap_open_live %s: bad ERF_FCS_BITS value (%d) in environment\n", device, n);
    664 			goto failstop;
    665 		}
    666 	}
    667 
    668 	handle->snapshot	= snaplen;
    669 	handle->md.dag_timeout	= to_ms;
    670 
    671 	handle->linktype = -1;
    672 	if (dag_get_datalink(handle) < 0) {
    673 		strcpy(ebuf, handle->errbuf);
    674 		goto failstop;
    675 	}
    676 
    677 	handle->bufsize = 0;
    678 
    679 	if (new_pcap_dag(handle) < 0) {
    680 		snprintf(ebuf, PCAP_ERRBUF_SIZE, "new_pcap_dag %s: %s\n", device, pcap_strerror(errno));
    681 		goto failstop;
    682 	}
    683 
    684 	/*
    685 	 * "select()" and "poll()" don't work on DAG device descriptors.
    686 	 */
    687 	handle->selectable_fd = -1;
    688 
    689 	if (newDev != NULL) {
    690 		free((char *)newDev);
    691 	}
    692 
    693 	handle->read_op = dag_read;
    694 	handle->inject_op = dag_inject;
    695 	handle->setfilter_op = dag_setfilter;
    696 	handle->setdirection_op = NULL; /* Not implemented.*/
    697 	handle->set_datalink_op = dag_set_datalink;
    698 	handle->getnonblock_op = pcap_getnonblock_fd;
    699 	handle->setnonblock_op = dag_setnonblock;
    700 	handle->stats_op = dag_stats;
    701 	handle->close_op = dag_platform_close;
    702 	handle->md.stat.ps_drop = 0;
    703 	handle->md.stat.ps_recv = 0;
    704 	return handle;
    705 
    706 #ifdef HAVE_DAG_STREAMS_API
    707 failstop:
    708 	if (handle != NULL) {
    709 		if (dag_stop_stream(handle->fd, handle->md.dag_stream) < 0)
    710 			fprintf(stderr,"dag_stop_stream: %s\n", strerror(errno));
    711 	}
    712 
    713 faildetach:
    714 	if (handle != NULL) {
    715 		if (dag_detach_stream(handle->fd, handle->md.dag_stream) < 0)
    716 			fprintf(stderr,"dag_detach_stream: %s\n", strerror(errno));
    717 	}
    718 #else
    719 failstop:
    720 	if (handle != NULL) {
    721 		if (dag_stop(p->fd) < 0)
    722 			fprintf(stderr,"dag_stop: %s\n", strerror(errno));
    723 	}
    724 #endif /* HAVE_DAG_STREAMS_API */
    725 
    726 failclose:
    727 	if (handle != NULL) {
    728 		if (dag_close(handle->fd) < 0)
    729 			fprintf(stderr,"dag_close: %s\n", strerror(errno));
    730 	}
    731 	if (handle != NULL)
    732 		delete_pcap_dag(handle);
    733 
    734 fail:
    735 	if (newDev != NULL) {
    736 		free((char *)newDev);
    737 	}
    738 	if (handle != NULL) {
    739 		/*
    740 		 * Get rid of any link-layer type list we allocated.
    741 		 */
    742 		if (handle->dlt_list != NULL) {
    743 			free(handle->dlt_list);
    744 		}
    745 		free(handle);
    746 	}
    747 
    748 	return NULL;
    749 }
    750 
    751 static int
    752 dag_stats(pcap_t *p, struct pcap_stat *ps) {
    753 	/* This needs to be filled out correctly.  Hopefully a dagapi call will
    754 		 provide all necessary information.
    755 	*/
    756 	/*p->md.stat.ps_recv = 0;*/
    757 	/*p->md.stat.ps_drop = 0;*/
    758 
    759 	*ps = p->md.stat;
    760 
    761 	return 0;
    762 }
    763 
    764 /*
    765  * Simply submit all possible dag names as candidates.
    766  * pcap_add_if() internally tests each candidate with pcap_open_live(),
    767  * so any non-existent devices are dropped.
    768  * For 2.5 try all rx stream names as well.
    769  */
    770 int
    771 dag_platform_finddevs(pcap_if_t **devlistp, char *errbuf)
    772 {
    773 	char name[12];	/* XXX - pick a size */
    774 	int ret = 0;
    775 	int c;
    776 
    777 	/* Try all the DAGs 0-9 */
    778 	for (c = 0; c < 9; c++) {
    779 		snprintf(name, 12, "dag%d", c);
    780 		if (pcap_add_if(devlistp, name, 0, NULL, errbuf) == -1) {
    781 			/*
    782 			 * Failure.
    783 			 */
    784 			ret = -1;
    785 		}
    786 #ifdef HAVE_DAG_STREAMS_API
    787 		{
    788 			int stream;
    789 			for(stream=0;stream<16;stream+=2) {
    790 				snprintf(name,  10, "dag%d:%d", c, stream);
    791 				if (pcap_add_if(devlistp, name, 0, NULL, errbuf) == -1) {
    792 					/*
    793 					 * Failure.
    794 					 */
    795 					ret = -1;
    796 				}
    797 			}
    798 		}
    799 #endif  /* HAVE_DAG_STREAMS_API */
    800 	}
    801 	return (ret);
    802 }
    803 
    804 /*
    805  * Installs the given bpf filter program in the given pcap structure.  There is
    806  * no attempt to store the filter in kernel memory as that is not supported
    807  * with DAG cards.
    808  */
    809 static int
    810 dag_setfilter(pcap_t *p, struct bpf_program *fp)
    811 {
    812 	if (!p)
    813 		return -1;
    814 	if (!fp) {
    815 		strncpy(p->errbuf, "setfilter: No filter specified",
    816 			sizeof(p->errbuf));
    817 		return -1;
    818 	}
    819 
    820 	/* Make our private copy of the filter */
    821 
    822 	if (install_bpf_program(p, fp) < 0)
    823 		return -1;
    824 
    825 	p->md.use_bpf = 0;
    826 
    827 	return (0);
    828 }
    829 
    830 static int
    831 dag_set_datalink(pcap_t *p, int dlt)
    832 {
    833 	p->linktype = dlt;
    834 
    835 	return (0);
    836 }
    837 
    838 static int
    839 dag_setnonblock(pcap_t *p, int nonblock, char *errbuf)
    840 {
    841 	/*
    842 	 * Set non-blocking mode on the FD.
    843 	 * XXX - is that necessary?  If not, don't bother calling it,
    844 	 * and have a "dag_getnonblock()" function that looks at
    845 	 * "p->md.dag_offset_flags".
    846 	 */
    847 	if (pcap_setnonblock_fd(p, nonblock, errbuf) < 0)
    848 		return (-1);
    849 #ifdef HAVE_DAG_STREAMS_API
    850 	{
    851 		uint32_t mindata;
    852 		struct timeval maxwait;
    853 		struct timeval poll;
    854 
    855 		if (dag_get_stream_poll(p->fd, p->md.dag_stream,
    856 					&mindata, &maxwait, &poll) < 0) {
    857 			snprintf(errbuf, PCAP_ERRBUF_SIZE, "dag_get_stream_poll: %s\n", pcap_strerror(errno));
    858 			return -1;
    859 		}
    860 
    861 		/* Amount of data to collect in Bytes before calling callbacks.
    862 		 * Important for efficiency, but can introduce latency
    863 		 * at low packet rates if to_ms not set!
    864 		 */
    865 		if(nonblock)
    866 			mindata = 0;
    867 		else
    868 			mindata = 65536;
    869 
    870 		if (dag_set_stream_poll(p->fd, p->md.dag_stream,
    871 					mindata, &maxwait, &poll) < 0) {
    872 			snprintf(errbuf, PCAP_ERRBUF_SIZE, "dag_set_stream_poll: %s\n", pcap_strerror(errno));
    873 			return -1;
    874 		}
    875 	}
    876 #endif /* HAVE_DAG_STREAMS_API */
    877 	if (nonblock) {
    878 		p->md.dag_offset_flags |= DAGF_NONBLOCK;
    879 	} else {
    880 		p->md.dag_offset_flags &= ~DAGF_NONBLOCK;
    881 	}
    882 	return (0);
    883 }
    884 
    885 static int
    886 dag_get_datalink(pcap_t *p)
    887 {
    888 	int index=0;
    889 	uint8_t types[255];
    890 
    891 	memset(types, 0, 255);
    892 
    893 	if (p->dlt_list == NULL && (p->dlt_list = malloc(255*sizeof(*(p->dlt_list)))) == NULL) {
    894 		(void)snprintf(p->errbuf, sizeof(p->errbuf), "malloc: %s", pcap_strerror(errno));
    895 		return (-1);
    896 	}
    897 
    898 	p->linktype = 0;
    899 
    900 #ifdef HAVE_DAG_GET_ERF_TYPES
    901 	/* Get list of possible ERF types for this card */
    902 	if (dag_get_erf_types(p->fd, types, 255) < 0) {
    903 		snprintf(p->errbuf, sizeof(p->errbuf), "dag_get_erf_types: %s", pcap_strerror(errno));
    904 		return (-1);
    905 	}
    906 
    907 	while (types[index]) {
    908 #else
    909 	/* Check the type through a dagapi call. */
    910 	types[index] = dag_linktype(p->fd);
    911 
    912 	{
    913 #endif
    914 		switch(types[index]) {
    915 
    916 		case TYPE_HDLC_POS:
    917 #ifdef TYPE_COLOR_HDLC_POS
    918 		case TYPE_COLOR_HDLC_POS:
    919 #endif
    920 #ifdef TYPE_DSM_COLOR_HDLC_POS
    921 		case TYPE_DSM_COLOR_HDLC_POS:
    922 #endif
    923 			if (p->dlt_list != NULL) {
    924 				p->dlt_list[index++] = DLT_CHDLC;
    925 				p->dlt_list[index++] = DLT_PPP_SERIAL;
    926 				p->dlt_list[index++] = DLT_FRELAY;
    927 			}
    928 			if(!p->linktype)
    929 				p->linktype = DLT_CHDLC;
    930 			break;
    931 
    932 		case TYPE_ETH:
    933 #ifdef TYPE_COLOR_ETH
    934 		case TYPE_COLOR_ETH:
    935 #endif
    936 #ifdef TYPE_DSM_COLOR_ETH
    937 		case TYPE_DSM_COLOR_ETH:
    938 #endif
    939 			/*
    940 			 * This is (presumably) a real Ethernet capture; give it a
    941 			 * link-layer-type list with DLT_EN10MB and DLT_DOCSIS, so
    942 			 * that an application can let you choose it, in case you're
    943 			 * capturing DOCSIS traffic that a Cisco Cable Modem
    944 			 * Termination System is putting out onto an Ethernet (it
    945 			 * doesn't put an Ethernet header onto the wire, it puts raw
    946 			 * DOCSIS frames out on the wire inside the low-level
    947 			 * Ethernet framing).
    948 			 */
    949 			if (p->dlt_list != NULL) {
    950 				p->dlt_list[index++] = DLT_EN10MB;
    951 				p->dlt_list[index++] = DLT_DOCSIS;
    952 			}
    953 			if(!p->linktype)
    954 				p->linktype = DLT_EN10MB;
    955 			break;
    956 
    957 		case TYPE_ATM:
    958 #ifdef TYPE_AAL5
    959 		case TYPE_AAL5:
    960 #endif
    961 #ifdef TYPE_MC_ATM
    962 		case TYPE_MC_ATM:
    963 #endif
    964 #ifdef TYPE_MC_AAL5
    965 		case TYPE_MC_AAL5:
    966 #endif
    967 			if (p->dlt_list != NULL) {
    968 				p->dlt_list[index++] = DLT_ATM_RFC1483;
    969 				p->dlt_list[index++] = DLT_SUNATM;
    970 			}
    971 			if(!p->linktype)
    972 				p->linktype = DLT_ATM_RFC1483;
    973 			break;
    974 
    975 #ifdef TYPE_COLOR_MC_HDLC_POS
    976 		case TYPE_COLOR_MC_HDLC_POS:
    977 #endif
    978 #ifdef TYPE_MC_HDLC
    979 		case TYPE_MC_HDLC:
    980 			if (p->dlt_list != NULL) {
    981 				p->dlt_list[index++] = DLT_CHDLC;
    982 				p->dlt_list[index++] = DLT_PPP_SERIAL;
    983 				p->dlt_list[index++] = DLT_FRELAY;
    984 				p->dlt_list[index++] = DLT_MTP2;
    985 				p->dlt_list[index++] = DLT_MTP2_WITH_PHDR;
    986 			}
    987 			if(!p->linktype)
    988 				p->linktype = DLT_CHDLC;
    989 			break;
    990 #endif
    991 
    992 		case TYPE_LEGACY:
    993 			if(!p->linktype)
    994 				p->linktype = DLT_NULL;
    995 			break;
    996 
    997 		default:
    998 			snprintf(p->errbuf, sizeof(p->errbuf), "unknown DAG linktype %d", types[index]);
    999 			return (-1);
   1000 
   1001 		} /* switch */
   1002 	}
   1003 
   1004 	p->dlt_count = index;
   1005 
   1006 	return p->linktype;
   1007 }
   1008