1/*
2 * pcap-dag.c: Packet capture interface for Emulex EndaceDAG cards.
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
14 *                Koryn Grant
15 *                Stephen Donnelly <stephen.donnelly@emulex.com>
16 */
17
18#ifdef HAVE_CONFIG_H
19#include "config.h"
20#endif
21
22#include <sys/param.h>			/* optionally get BSD define */
23
24#include <stdlib.h>
25#include <string.h>
26#include <errno.h>
27
28#include "pcap-int.h"
29
30#include <ctype.h>
31#include <netinet/in.h>
32#include <sys/mman.h>
33#include <sys/socket.h>
34#include <sys/types.h>
35#include <unistd.h>
36
37struct mbuf;		/* Squelch compiler warnings on some platforms for */
38struct rtentry;		/* declarations in <net/if.h> */
39#include <net/if.h>
40
41#include "dagnew.h"
42#include "dagapi.h"
43#include "dagpci.h"
44
45#include "pcap-dag.h"
46
47/*
48 * DAG devices have names beginning with "dag", followed by a number
49 * from 0 to DAG_MAX_BOARDS, then optionally a colon and a stream number
50 * from 0 to DAG_STREAM_MAX.
51 */
52#ifndef DAG_MAX_BOARDS
53#define DAG_MAX_BOARDS 32
54#endif
55
56#define ATM_CELL_SIZE		52
57#define ATM_HDR_SIZE		4
58
59/*
60 * A header containing additional MTP information.
61 */
62#define MTP2_SENT_OFFSET		0	/* 1 byte */
63#define MTP2_ANNEX_A_USED_OFFSET	1	/* 1 byte */
64#define MTP2_LINK_NUMBER_OFFSET		2	/* 2 bytes */
65#define MTP2_HDR_LEN			4	/* length of the header */
66
67#define MTP2_ANNEX_A_NOT_USED      0
68#define MTP2_ANNEX_A_USED          1
69#define MTP2_ANNEX_A_USED_UNKNOWN  2
70
71/* SunATM pseudo header */
72struct sunatm_hdr {
73	unsigned char	flags;		/* destination and traffic type */
74	unsigned char	vpi;		/* VPI */
75	unsigned short	vci;		/* VCI */
76};
77
78/*
79 * Private data for capturing on DAG devices.
80 */
81struct pcap_dag {
82	struct pcap_stat stat;
83#ifdef HAVE_DAG_STREAMS_API
84	u_char	*dag_mem_bottom;	/* DAG card current memory bottom pointer */
85	u_char	*dag_mem_top;	/* DAG card current memory top pointer */
86#else /* HAVE_DAG_STREAMS_API */
87	void	*dag_mem_base;	/* DAG card memory base address */
88	u_int	dag_mem_bottom;	/* DAG card current memory bottom offset */
89	u_int	dag_mem_top;	/* DAG card current memory top offset */
90#endif /* HAVE_DAG_STREAMS_API */
91	int	dag_fcs_bits;	/* Number of checksum bits from link layer */
92	int	dag_offset_flags; /* Flags to pass to dag_offset(). */
93	int	dag_stream;	/* DAG stream number */
94	int	dag_timeout;	/* timeout specified to pcap_open_live.
95				 * Same as in linux above, introduce
96				 * generally? */
97};
98
99typedef struct pcap_dag_node {
100	struct pcap_dag_node *next;
101	pcap_t *p;
102	pid_t pid;
103} pcap_dag_node_t;
104
105static pcap_dag_node_t *pcap_dags = NULL;
106static int atexit_handler_installed = 0;
107static const unsigned short endian_test_word = 0x0100;
108
109#define IS_BIGENDIAN() (*((unsigned char *)&endian_test_word))
110
111#define MAX_DAG_PACKET 65536
112
113static unsigned char TempPkt[MAX_DAG_PACKET];
114
115static int dag_setfilter(pcap_t *p, struct bpf_program *fp);
116static int dag_stats(pcap_t *p, struct pcap_stat *ps);
117static int dag_set_datalink(pcap_t *p, int dlt);
118static int dag_get_datalink(pcap_t *p);
119static int dag_setnonblock(pcap_t *p, int nonblock, char *errbuf);
120
121static void
122delete_pcap_dag(pcap_t *p)
123{
124	pcap_dag_node_t *curr = NULL, *prev = NULL;
125
126	for (prev = NULL, curr = pcap_dags; curr != NULL && curr->p != p; prev = curr, curr = curr->next) {
127		/* empty */
128	}
129
130	if (curr != NULL && curr->p == p) {
131		if (prev != NULL) {
132			prev->next = curr->next;
133		} else {
134			pcap_dags = curr->next;
135		}
136	}
137}
138
139/*
140 * Performs a graceful shutdown of the DAG card, frees dynamic memory held
141 * in the pcap_t structure, and closes the file descriptor for the DAG card.
142 */
143
144static void
145dag_platform_cleanup(pcap_t *p)
146{
147	struct pcap_dag *pd;
148
149	if (p != NULL) {
150		pd = p->priv;
151#ifdef HAVE_DAG_STREAMS_API
152		if(dag_stop_stream(p->fd, pd->dag_stream) < 0)
153			fprintf(stderr,"dag_stop_stream: %s\n", strerror(errno));
154
155		if(dag_detach_stream(p->fd, pd->dag_stream) < 0)
156			fprintf(stderr,"dag_detach_stream: %s\n", strerror(errno));
157#else
158		if(dag_stop(p->fd) < 0)
159			fprintf(stderr,"dag_stop: %s\n", strerror(errno));
160#endif /* HAVE_DAG_STREAMS_API */
161		if(p->fd != -1) {
162			if(dag_close(p->fd) < 0)
163				fprintf(stderr,"dag_close: %s\n", strerror(errno));
164			p->fd = -1;
165		}
166		delete_pcap_dag(p);
167		pcap_cleanup_live_common(p);
168	}
169	/* Note: don't need to call close(p->fd) here as dag_close(p->fd) does this. */
170}
171
172static void
173atexit_handler(void)
174{
175	while (pcap_dags != NULL) {
176		if (pcap_dags->pid == getpid()) {
177			dag_platform_cleanup(pcap_dags->p);
178		} else {
179			delete_pcap_dag(pcap_dags->p);
180		}
181	}
182}
183
184static int
185new_pcap_dag(pcap_t *p)
186{
187	pcap_dag_node_t *node = NULL;
188
189	if ((node = malloc(sizeof(pcap_dag_node_t))) == NULL) {
190		return -1;
191	}
192
193	if (!atexit_handler_installed) {
194		atexit(atexit_handler);
195		atexit_handler_installed = 1;
196	}
197
198	node->next = pcap_dags;
199	node->p = p;
200	node->pid = getpid();
201
202	pcap_dags = node;
203
204	return 0;
205}
206
207static unsigned int
208dag_erf_ext_header_count(uint8_t * erf, size_t len)
209{
210	uint32_t hdr_num = 0;
211	uint8_t  hdr_type;
212
213	/* basic sanity checks */
214	if ( erf == NULL )
215		return 0;
216	if ( len < 16 )
217		return 0;
218
219	/* check if we have any extension headers */
220	if ( (erf[8] & 0x80) == 0x00 )
221		return 0;
222
223	/* loop over the extension headers */
224	do {
225
226		/* sanity check we have enough bytes */
227		if ( len < (24 + (hdr_num * 8)) )
228			return hdr_num;
229
230		/* get the header type */
231		hdr_type = erf[(16 + (hdr_num * 8))];
232		hdr_num++;
233
234	} while ( hdr_type & 0x80 );
235
236	return hdr_num;
237}
238
239/*
240 *  Read at most max_packets from the capture stream and call the callback
241 *  for each of them. Returns the number of packets handled, -1 if an
242 *  error occured, or -2 if we were told to break out of the loop.
243 */
244static int
245dag_read(pcap_t *p, int cnt, pcap_handler callback, u_char *user)
246{
247	struct pcap_dag *pd = p->priv;
248	unsigned int processed = 0;
249	int flags = pd->dag_offset_flags;
250	unsigned int nonblocking = flags & DAGF_NONBLOCK;
251	unsigned int num_ext_hdr = 0;
252	unsigned int ticks_per_second;
253
254	/* Get the next bufferful of packets (if necessary). */
255	while (pd->dag_mem_top - pd->dag_mem_bottom < dag_record_size) {
256
257		/*
258		 * Has "pcap_breakloop()" been called?
259		 */
260		if (p->break_loop) {
261			/*
262			 * Yes - clear the flag that indicates that
263			 * it has, and return -2 to indicate that
264			 * we were told to break out of the loop.
265			 */
266			p->break_loop = 0;
267			return -2;
268		}
269
270#ifdef HAVE_DAG_STREAMS_API
271		/* dag_advance_stream() will block (unless nonblock is called)
272		 * until 64kB of data has accumulated.
273		 * If to_ms is set, it will timeout before 64kB has accumulated.
274		 * We wait for 64kB because processing a few packets at a time
275		 * can cause problems at high packet rates (>200kpps) due
276		 * to inefficiencies.
277		 * This does mean if to_ms is not specified the capture may 'hang'
278		 * for long periods if the data rate is extremely slow (<64kB/sec)
279		 * If non-block is specified it will return immediately. The user
280		 * is then responsible for efficiency.
281		 */
282		if ( NULL == (pd->dag_mem_top = dag_advance_stream(p->fd, pd->dag_stream, &(pd->dag_mem_bottom))) ) {
283		     return -1;
284		}
285#else
286		/* dag_offset does not support timeouts */
287		pd->dag_mem_top = dag_offset(p->fd, &(pd->dag_mem_bottom), flags);
288#endif /* HAVE_DAG_STREAMS_API */
289
290		if (nonblocking && (pd->dag_mem_top - pd->dag_mem_bottom < dag_record_size))
291		{
292			/* Pcap is configured to process only available packets, and there aren't any, return immediately. */
293			return 0;
294		}
295
296		if(!nonblocking &&
297		   pd->dag_timeout &&
298		   (pd->dag_mem_top - pd->dag_mem_bottom < dag_record_size))
299		{
300			/* Blocking mode, but timeout set and no data has arrived, return anyway.*/
301			return 0;
302		}
303
304	}
305
306	/* Process the packets. */
307	while (pd->dag_mem_top - pd->dag_mem_bottom >= dag_record_size) {
308
309		unsigned short packet_len = 0;
310		int caplen = 0;
311		struct pcap_pkthdr	pcap_header;
312
313#ifdef HAVE_DAG_STREAMS_API
314		dag_record_t *header = (dag_record_t *)(pd->dag_mem_bottom);
315#else
316		dag_record_t *header = (dag_record_t *)(pd->dag_mem_base + pd->dag_mem_bottom);
317#endif /* HAVE_DAG_STREAMS_API */
318
319		u_char *dp = ((u_char *)header); /* + dag_record_size; */
320		unsigned short rlen;
321
322		/*
323		 * Has "pcap_breakloop()" been called?
324		 */
325		if (p->break_loop) {
326			/*
327			 * Yes - clear the flag that indicates that
328			 * it has, and return -2 to indicate that
329			 * we were told to break out of the loop.
330			 */
331			p->break_loop = 0;
332			return -2;
333		}
334
335		rlen = ntohs(header->rlen);
336		if (rlen < dag_record_size)
337		{
338			strncpy(p->errbuf, "dag_read: record too small", PCAP_ERRBUF_SIZE);
339			return -1;
340		}
341		pd->dag_mem_bottom += rlen;
342
343		/* Count lost packets. */
344		switch((header->type & 0x7f)) {
345			/* in these types the color value overwrites the lctr */
346		case TYPE_COLOR_HDLC_POS:
347		case TYPE_COLOR_ETH:
348		case TYPE_DSM_COLOR_HDLC_POS:
349		case TYPE_DSM_COLOR_ETH:
350		case TYPE_COLOR_MC_HDLC_POS:
351		case TYPE_COLOR_HASH_ETH:
352		case TYPE_COLOR_HASH_POS:
353			break;
354
355		default:
356			if (header->lctr) {
357				if (pd->stat.ps_drop > (UINT_MAX - ntohs(header->lctr))) {
358					pd->stat.ps_drop = UINT_MAX;
359				} else {
360					pd->stat.ps_drop += ntohs(header->lctr);
361				}
362			}
363		}
364
365		if ((header->type & 0x7f) == TYPE_PAD) {
366			continue;
367		}
368
369		num_ext_hdr = dag_erf_ext_header_count(dp, rlen);
370
371		/* ERF encapsulation */
372		/* The Extensible Record Format is not dropped for this kind of encapsulation,
373		 * and will be handled as a pseudo header by the decoding application.
374		 * The information carried in the ERF header and in the optional subheader (if present)
375		 * could be merged with the libpcap information, to offer a better decoding.
376		 * The packet length is
377		 * o the length of the packet on the link (header->wlen),
378		 * o plus the length of the ERF header (dag_record_size), as the length of the
379		 *   pseudo header will be adjusted during the decoding,
380		 * o plus the length of the optional subheader (if present).
381		 *
382		 * The capture length is header.rlen and the byte stuffing for alignment will be dropped
383		 * if the capture length is greater than the packet length.
384		 */
385		if (p->linktype == DLT_ERF) {
386			packet_len = ntohs(header->wlen) + dag_record_size;
387			caplen = rlen;
388			switch ((header->type & 0x7f)) {
389			case TYPE_MC_AAL5:
390			case TYPE_MC_ATM:
391			case TYPE_MC_HDLC:
392			case TYPE_MC_RAW_CHANNEL:
393			case TYPE_MC_RAW:
394			case TYPE_MC_AAL2:
395			case TYPE_COLOR_MC_HDLC_POS:
396				packet_len += 4; /* MC header */
397				break;
398
399			case TYPE_COLOR_HASH_ETH:
400			case TYPE_DSM_COLOR_ETH:
401			case TYPE_COLOR_ETH:
402			case TYPE_ETH:
403				packet_len += 2; /* ETH header */
404				break;
405			} /* switch type */
406
407			/* Include ERF extension headers */
408			packet_len += (8 * num_ext_hdr);
409
410			if (caplen > packet_len) {
411				caplen = packet_len;
412			}
413		} else {
414			/* Other kind of encapsulation according to the header Type */
415
416			/* Skip over generic ERF header */
417			dp += dag_record_size;
418			/* Skip over extension headers */
419			dp += 8 * num_ext_hdr;
420
421			switch((header->type & 0x7f)) {
422			case TYPE_ATM:
423			case TYPE_AAL5:
424				if (header->type == TYPE_AAL5) {
425					packet_len = ntohs(header->wlen);
426					caplen = rlen - dag_record_size;
427				}
428			case TYPE_MC_ATM:
429				if (header->type == TYPE_MC_ATM) {
430					caplen = packet_len = ATM_CELL_SIZE;
431					dp+=4;
432				}
433			case TYPE_MC_AAL5:
434				if (header->type == TYPE_MC_AAL5) {
435					packet_len = ntohs(header->wlen);
436					caplen = rlen - dag_record_size - 4;
437					dp+=4;
438				}
439				/* Skip over extension headers */
440				caplen -= (8 * num_ext_hdr);
441
442				if (header->type == TYPE_ATM) {
443					caplen = packet_len = ATM_CELL_SIZE;
444				}
445				if (p->linktype == DLT_SUNATM) {
446					struct sunatm_hdr *sunatm = (struct sunatm_hdr *)dp;
447					unsigned long rawatm;
448
449					rawatm = ntohl(*((unsigned long *)dp));
450					sunatm->vci = htons((rawatm >>  4) & 0xffff);
451					sunatm->vpi = (rawatm >> 20) & 0x00ff;
452					sunatm->flags = ((header->flags.iface & 1) ? 0x80 : 0x00) |
453						((sunatm->vpi == 0 && sunatm->vci == htons(5)) ? 6 :
454						 ((sunatm->vpi == 0 && sunatm->vci == htons(16)) ? 5 :
455						  ((dp[ATM_HDR_SIZE] == 0xaa &&
456						    dp[ATM_HDR_SIZE+1] == 0xaa &&
457						    dp[ATM_HDR_SIZE+2] == 0x03) ? 2 : 1)));
458
459				} else {
460					packet_len -= ATM_HDR_SIZE;
461					caplen -= ATM_HDR_SIZE;
462					dp += ATM_HDR_SIZE;
463				}
464				break;
465
466			case TYPE_COLOR_HASH_ETH:
467			case TYPE_DSM_COLOR_ETH:
468			case TYPE_COLOR_ETH:
469			case TYPE_ETH:
470				packet_len = ntohs(header->wlen);
471				packet_len -= (pd->dag_fcs_bits >> 3);
472				caplen = rlen - dag_record_size - 2;
473				/* Skip over extension headers */
474				caplen -= (8 * num_ext_hdr);
475				if (caplen > packet_len) {
476					caplen = packet_len;
477				}
478				dp += 2;
479				break;
480
481			case TYPE_COLOR_HASH_POS:
482			case TYPE_DSM_COLOR_HDLC_POS:
483			case TYPE_COLOR_HDLC_POS:
484			case TYPE_HDLC_POS:
485				packet_len = ntohs(header->wlen);
486				packet_len -= (pd->dag_fcs_bits >> 3);
487				caplen = rlen - dag_record_size;
488				/* Skip over extension headers */
489				caplen -= (8 * num_ext_hdr);
490				if (caplen > packet_len) {
491					caplen = packet_len;
492				}
493				break;
494
495			case TYPE_COLOR_MC_HDLC_POS:
496			case TYPE_MC_HDLC:
497				packet_len = ntohs(header->wlen);
498				packet_len -= (pd->dag_fcs_bits >> 3);
499				caplen = rlen - dag_record_size - 4;
500				/* Skip over extension headers */
501				caplen -= (8 * num_ext_hdr);
502				if (caplen > packet_len) {
503					caplen = packet_len;
504				}
505				/* jump the MC_HDLC_HEADER */
506				dp += 4;
507#ifdef DLT_MTP2_WITH_PHDR
508				if (p->linktype == DLT_MTP2_WITH_PHDR) {
509					/* Add the MTP2 Pseudo Header */
510					caplen += MTP2_HDR_LEN;
511					packet_len += MTP2_HDR_LEN;
512
513					TempPkt[MTP2_SENT_OFFSET] = 0;
514					TempPkt[MTP2_ANNEX_A_USED_OFFSET] = MTP2_ANNEX_A_USED_UNKNOWN;
515					*(TempPkt+MTP2_LINK_NUMBER_OFFSET) = ((header->rec.mc_hdlc.mc_header>>16)&0x01);
516					*(TempPkt+MTP2_LINK_NUMBER_OFFSET+1) = ((header->rec.mc_hdlc.mc_header>>24)&0xff);
517					memcpy(TempPkt+MTP2_HDR_LEN, dp, caplen);
518					dp = TempPkt;
519				}
520#endif
521				break;
522
523			case TYPE_IPV4:
524			case TYPE_IPV6:
525				packet_len = ntohs(header->wlen);
526				caplen = rlen - dag_record_size;
527				/* Skip over extension headers */
528				caplen -= (8 * num_ext_hdr);
529				if (caplen > packet_len) {
530					caplen = packet_len;
531				}
532				break;
533
534			/* These types have no matching 'native' DLT, but can be used with DLT_ERF above */
535			case TYPE_MC_RAW:
536			case TYPE_MC_RAW_CHANNEL:
537			case TYPE_IP_COUNTER:
538			case TYPE_TCP_FLOW_COUNTER:
539			case TYPE_INFINIBAND:
540			case TYPE_RAW_LINK:
541			case TYPE_INFINIBAND_LINK:
542			default:
543				/* Unhandled ERF type.
544				 * Ignore rather than generating error
545				 */
546				continue;
547			} /* switch type */
548
549		} /* ERF encapsulation */
550
551		if (caplen > p->snapshot)
552			caplen = p->snapshot;
553
554		/* Run the packet filter if there is one. */
555		if ((p->fcode.bf_insns == NULL) || bpf_filter(p->fcode.bf_insns, dp, packet_len, caplen)) {
556
557			/* convert between timestamp formats */
558			register unsigned long long ts;
559
560			if (IS_BIGENDIAN()) {
561				ts = SWAPLL(header->ts);
562			} else {
563				ts = header->ts;
564			}
565
566			switch (p->opt.tstamp_precision) {
567			case PCAP_TSTAMP_PRECISION_NANO:
568				ticks_per_second = 1000000000;
569				break;
570			case PCAP_TSTAMP_PRECISION_MICRO:
571			default:
572				ticks_per_second = 1000000;
573				break;
574
575			}
576			pcap_header.ts.tv_sec = ts >> 32;
577			ts = (ts & 0xffffffffULL) * ticks_per_second;
578			ts += 0x80000000; /* rounding */
579			pcap_header.ts.tv_usec = ts >> 32;
580			if (pcap_header.ts.tv_usec >= ticks_per_second) {
581				pcap_header.ts.tv_usec -= ticks_per_second;
582				pcap_header.ts.tv_sec++;
583			}
584
585			/* Fill in our own header data */
586			pcap_header.caplen = caplen;
587			pcap_header.len = packet_len;
588
589			/* Count the packet. */
590			pd->stat.ps_recv++;
591
592			/* Call the user supplied callback function */
593			callback(user, &pcap_header, dp);
594
595			/* Only count packets that pass the filter, for consistency with standard Linux behaviour. */
596			processed++;
597			if (processed == cnt && !PACKET_COUNT_IS_UNLIMITED(cnt))
598			{
599				/* Reached the user-specified limit. */
600				return cnt;
601			}
602		}
603	}
604
605	return processed;
606}
607
608static int
609dag_inject(pcap_t *p, const void *buf _U_, size_t size _U_)
610{
611	strlcpy(p->errbuf, "Sending packets isn't supported on DAG cards",
612	    PCAP_ERRBUF_SIZE);
613	return (-1);
614}
615
616/*
617 *  Get a handle for a live capture from the given DAG device.  Passing a NULL
618 *  device will result in a failure.  The promisc flag is ignored because DAG
619 *  cards are always promiscuous.  The to_ms parameter is used in setting the
620 *  API polling parameters.
621 *
622 *  snaplen is now also ignored, until we get per-stream slen support. Set
623 *  slen with approprite DAG tool BEFORE pcap_activate().
624 *
625 *  See also pcap(3).
626 */
627static int dag_activate(pcap_t* handle)
628{
629	struct pcap_dag *handlep = handle->priv;
630#if 0
631	char conf[30]; /* dag configure string */
632#endif
633	char *s;
634	int n;
635	daginf_t* daginf;
636	char * newDev = NULL;
637	char * device = handle->opt.source;
638#ifdef HAVE_DAG_STREAMS_API
639	uint32_t mindata;
640	struct timeval maxwait;
641	struct timeval poll;
642#endif
643
644	if (device == NULL) {
645		snprintf(handle->errbuf, PCAP_ERRBUF_SIZE, "device is NULL: %s", pcap_strerror(errno));
646		return -1;
647	}
648
649	/* Initialize some components of the pcap structure. */
650
651#ifdef HAVE_DAG_STREAMS_API
652	newDev = (char *)malloc(strlen(device) + 16);
653	if (newDev == NULL) {
654		snprintf(handle->errbuf, PCAP_ERRBUF_SIZE, "Can't allocate string for device name: %s\n", pcap_strerror(errno));
655		goto fail;
656	}
657
658	/* Parse input name to get dag device and stream number if provided */
659	if (dag_parse_name(device, newDev, strlen(device) + 16, &handlep->dag_stream) < 0) {
660		snprintf(handle->errbuf, PCAP_ERRBUF_SIZE, "dag_parse_name: %s\n", pcap_strerror(errno));
661		goto fail;
662	}
663	device = newDev;
664
665	if (handlep->dag_stream%2) {
666		snprintf(handle->errbuf, PCAP_ERRBUF_SIZE, "dag_parse_name: tx (even numbered) streams not supported for capture\n");
667		goto fail;
668	}
669#else
670	if (strncmp(device, "/dev/", 5) != 0) {
671		newDev = (char *)malloc(strlen(device) + 5);
672		if (newDev == NULL) {
673			snprintf(handle->errbuf, PCAP_ERRBUF_SIZE, "Can't allocate string for device name: %s\n", pcap_strerror(errno));
674			goto fail;
675		}
676		strcpy(newDev, "/dev/");
677		strcat(newDev, device);
678		device = newDev;
679	}
680#endif /* HAVE_DAG_STREAMS_API */
681
682	/* setup device parameters */
683	if((handle->fd = dag_open((char *)device)) < 0) {
684		snprintf(handle->errbuf, PCAP_ERRBUF_SIZE, "dag_open %s: %s", device, pcap_strerror(errno));
685		goto fail;
686	}
687
688#ifdef HAVE_DAG_STREAMS_API
689	/* Open requested stream. Can fail if already locked or on error */
690	if (dag_attach_stream(handle->fd, handlep->dag_stream, 0, 0) < 0) {
691		snprintf(handle->errbuf, PCAP_ERRBUF_SIZE, "dag_attach_stream: %s\n", pcap_strerror(errno));
692		goto failclose;
693	}
694
695	/* Set up default poll parameters for stream
696	 * Can be overridden by pcap_set_nonblock()
697	 */
698	if (dag_get_stream_poll(handle->fd, handlep->dag_stream,
699				&mindata, &maxwait, &poll) < 0) {
700		snprintf(handle->errbuf, PCAP_ERRBUF_SIZE, "dag_get_stream_poll: %s\n", pcap_strerror(errno));
701		goto faildetach;
702	}
703
704	if (handle->opt.immediate) {
705		/* Call callback immediately.
706		 * XXX - is this the right way to handle this?
707		 */
708		mindata = 0;
709	} else {
710		/* Amount of data to collect in Bytes before calling callbacks.
711		 * Important for efficiency, but can introduce latency
712		 * at low packet rates if to_ms not set!
713		 */
714		mindata = 65536;
715	}
716
717	/* Obey opt.timeout (was to_ms) if supplied. This is a good idea!
718	 * Recommend 10-100ms. Calls will time out even if no data arrived.
719	 */
720	maxwait.tv_sec = handle->opt.timeout/1000;
721	maxwait.tv_usec = (handle->opt.timeout%1000) * 1000;
722
723	if (dag_set_stream_poll(handle->fd, handlep->dag_stream,
724				mindata, &maxwait, &poll) < 0) {
725		snprintf(handle->errbuf, PCAP_ERRBUF_SIZE, "dag_set_stream_poll: %s\n", pcap_strerror(errno));
726		goto faildetach;
727	}
728
729#else
730	if((handlep->dag_mem_base = dag_mmap(handle->fd)) == MAP_FAILED) {
731		snprintf(handle->errbuf, PCAP_ERRBUF_SIZE,"dag_mmap %s: %s\n", device, pcap_strerror(errno));
732		goto failclose;
733	}
734
735#endif /* HAVE_DAG_STREAMS_API */
736
737        /* XXX Not calling dag_configure() to set slen; this is unsafe in
738	 * multi-stream environments as the gpp config is global.
739         * Once the firmware provides 'per-stream slen' this can be supported
740	 * again via the Config API without side-effects */
741#if 0
742	/* set the card snap length to the specified snaplen parameter */
743	/* This is a really bad idea, as different cards have different
744	 * valid slen ranges. Should fix in Config API. */
745	if (handle->snapshot == 0 || handle->snapshot > MAX_DAG_SNAPLEN) {
746		handle->snapshot = MAX_DAG_SNAPLEN;
747	} else if (snaplen < MIN_DAG_SNAPLEN) {
748		handle->snapshot = MIN_DAG_SNAPLEN;
749	}
750	/* snap len has to be a multiple of 4 */
751	snprintf(conf, 30, "varlen slen=%d", (snaplen + 3) & ~3);
752
753	if(dag_configure(handle->fd, conf) < 0) {
754		snprintf(handle->errbuf, PCAP_ERRBUF_SIZE,"dag_configure %s: %s\n", device, pcap_strerror(errno));
755		goto faildetach;
756	}
757#endif
758
759#ifdef HAVE_DAG_STREAMS_API
760	if(dag_start_stream(handle->fd, handlep->dag_stream) < 0) {
761		snprintf(handle->errbuf, PCAP_ERRBUF_SIZE, "dag_start_stream %s: %s\n", device, pcap_strerror(errno));
762		goto faildetach;
763	}
764#else
765	if(dag_start(handle->fd) < 0) {
766		snprintf(handle->errbuf, PCAP_ERRBUF_SIZE, "dag_start %s: %s\n", device, pcap_strerror(errno));
767		goto failclose;
768	}
769#endif /* HAVE_DAG_STREAMS_API */
770
771	/*
772	 * Important! You have to ensure bottom is properly
773	 * initialized to zero on startup, it won't give you
774	 * a compiler warning if you make this mistake!
775	 */
776	handlep->dag_mem_bottom = 0;
777	handlep->dag_mem_top = 0;
778
779	/*
780	 * Find out how many FCS bits we should strip.
781	 * First, query the card to see if it strips the FCS.
782	 */
783	daginf = dag_info(handle->fd);
784	if ((0x4200 == daginf->device_code) || (0x4230 == daginf->device_code))	{
785		/* DAG 4.2S and 4.23S already strip the FCS.  Stripping the final word again truncates the packet. */
786		handlep->dag_fcs_bits = 0;
787
788		/* Note that no FCS will be supplied. */
789		handle->linktype_ext = LT_FCS_DATALINK_EXT(0);
790	} else {
791		/*
792		 * Start out assuming it's 32 bits.
793		 */
794		handlep->dag_fcs_bits = 32;
795
796		/* Allow an environment variable to override. */
797		if ((s = getenv("ERF_FCS_BITS")) != NULL) {
798			if ((n = atoi(s)) == 0 || n == 16 || n == 32) {
799				handlep->dag_fcs_bits = n;
800			} else {
801				snprintf(handle->errbuf, PCAP_ERRBUF_SIZE,
802					"pcap_activate %s: bad ERF_FCS_BITS value (%d) in environment\n", device, n);
803				goto failstop;
804			}
805		}
806
807		/*
808		 * Did the user request that they not be stripped?
809		 */
810		if ((s = getenv("ERF_DONT_STRIP_FCS")) != NULL) {
811			/* Yes.  Note the number of bytes that will be
812			   supplied. */
813			handle->linktype_ext = LT_FCS_DATALINK_EXT(handlep->dag_fcs_bits/16);
814
815			/* And don't strip them. */
816			handlep->dag_fcs_bits = 0;
817		}
818	}
819
820	handlep->dag_timeout	= handle->opt.timeout;
821
822	handle->linktype = -1;
823	if (dag_get_datalink(handle) < 0)
824		goto failstop;
825
826	handle->bufsize = 0;
827
828	if (new_pcap_dag(handle) < 0) {
829		snprintf(handle->errbuf, PCAP_ERRBUF_SIZE, "new_pcap_dag %s: %s\n", device, pcap_strerror(errno));
830		goto failstop;
831	}
832
833	/*
834	 * "select()" and "poll()" don't work on DAG device descriptors.
835	 */
836	handle->selectable_fd = -1;
837
838	if (newDev != NULL) {
839		free((char *)newDev);
840	}
841
842	handle->read_op = dag_read;
843	handle->inject_op = dag_inject;
844	handle->setfilter_op = dag_setfilter;
845	handle->setdirection_op = NULL; /* Not implemented.*/
846	handle->set_datalink_op = dag_set_datalink;
847	handle->getnonblock_op = pcap_getnonblock_fd;
848	handle->setnonblock_op = dag_setnonblock;
849	handle->stats_op = dag_stats;
850	handle->cleanup_op = dag_platform_cleanup;
851	handlep->stat.ps_drop = 0;
852	handlep->stat.ps_recv = 0;
853	handlep->stat.ps_ifdrop = 0;
854	return 0;
855
856#ifdef HAVE_DAG_STREAMS_API
857failstop:
858	if (dag_stop_stream(handle->fd, handlep->dag_stream) < 0) {
859		fprintf(stderr,"dag_stop_stream: %s\n", strerror(errno));
860	}
861
862faildetach:
863	if (dag_detach_stream(handle->fd, handlep->dag_stream) < 0)
864		fprintf(stderr,"dag_detach_stream: %s\n", strerror(errno));
865#else
866failstop:
867	if (dag_stop(handle->fd) < 0)
868		fprintf(stderr,"dag_stop: %s\n", strerror(errno));
869#endif /* HAVE_DAG_STREAMS_API */
870
871failclose:
872	if (dag_close(handle->fd) < 0)
873		fprintf(stderr,"dag_close: %s\n", strerror(errno));
874	delete_pcap_dag(handle);
875
876fail:
877	pcap_cleanup_live_common(handle);
878	if (newDev != NULL) {
879		free((char *)newDev);
880	}
881
882	return PCAP_ERROR;
883}
884
885pcap_t *dag_create(const char *device, char *ebuf, int *is_ours)
886{
887	const char *cp;
888	char *cpend;
889	long devnum;
890	pcap_t *p;
891#ifdef HAVE_DAG_STREAMS_API
892	long stream = 0;
893#endif
894
895	/* Does this look like a DAG device? */
896	cp = strrchr(device, '/');
897	if (cp == NULL)
898		cp = device;
899	/* Does it begin with "dag"? */
900	if (strncmp(cp, "dag", 3) != 0) {
901		/* Nope, doesn't begin with "dag" */
902		*is_ours = 0;
903		return NULL;
904	}
905	/* Yes - is "dag" followed by a number from 0 to DAG_MAX_BOARDS-1 */
906	cp += 3;
907	devnum = strtol(cp, &cpend, 10);
908#ifdef HAVE_DAG_STREAMS_API
909	if (*cpend == ':') {
910		/* Followed by a stream number. */
911		stream = strtol(++cpend, &cpend, 10);
912	}
913#endif
914	if (cpend == cp || *cpend != '\0') {
915		/* Not followed by a number. */
916		*is_ours = 0;
917		return NULL;
918	}
919	if (devnum < 0 || devnum >= DAG_MAX_BOARDS) {
920		/* Followed by a non-valid number. */
921		*is_ours = 0;
922		return NULL;
923	}
924#ifdef HAVE_DAG_STREAMS_API
925	if (stream <0 || stream >= DAG_STREAM_MAX) {
926		/* Followed by a non-valid stream number. */
927		*is_ours = 0;
928		return NULL;
929	}
930#endif
931
932	/* OK, it's probably ours. */
933	*is_ours = 1;
934
935	p = pcap_create_common(device, ebuf, sizeof (struct pcap_dag));
936	if (p == NULL)
937		return NULL;
938
939	p->activate_op = dag_activate;
940
941	/*
942	 * We claim that we support microsecond and nanosecond time
943	 * stamps.
944	 *
945	 * XXX Our native precision is 2^-32s, but libpcap doesn't support
946	 * power of two precisions yet. We can convert to either MICRO or NANO.
947	 */
948	p->tstamp_precision_count = 2;
949	p->tstamp_precision_list = malloc(2 * sizeof(u_int));
950	if (p->tstamp_precision_list == NULL) {
951		snprintf(ebuf, PCAP_ERRBUF_SIZE, "malloc: %s",
952		    pcap_strerror(errno));
953		if (p->tstamp_type_list != NULL)
954			free(p->tstamp_type_list);
955		free(p);
956		return NULL;
957	}
958	p->tstamp_precision_list[0] = PCAP_TSTAMP_PRECISION_MICRO;
959	p->tstamp_precision_list[1] = PCAP_TSTAMP_PRECISION_NANO;
960	return p;
961}
962
963static int
964dag_stats(pcap_t *p, struct pcap_stat *ps) {
965	struct pcap_dag *pd = p->priv;
966
967	/* This needs to be filled out correctly.  Hopefully a dagapi call will
968		 provide all necessary information.
969	*/
970	/*pd->stat.ps_recv = 0;*/
971	/*pd->stat.ps_drop = 0;*/
972
973	*ps = pd->stat;
974
975	return 0;
976}
977
978/*
979 * Previously we just generated a list of all possible names and let
980 * pcap_add_if() attempt to open each one, but with streams this adds up
981 * to 81 possibilities which is inefficient.
982 *
983 * Since we know more about the devices we can prune the tree here.
984 * pcap_add_if() will still retest each device but the total number of
985 * open attempts will still be much less than the naive approach.
986 */
987int
988dag_findalldevs(pcap_if_t **devlistp, char *errbuf)
989{
990	char name[12];	/* XXX - pick a size */
991	int ret = 0;
992	int c;
993	char dagname[DAGNAME_BUFSIZE];
994	int dagstream;
995	int dagfd;
996	dag_card_inf_t *inf;
997	char *description;
998
999	/* Try all the DAGs 0-DAG_MAX_BOARDS */
1000	for (c = 0; c < DAG_MAX_BOARDS; c++) {
1001		snprintf(name, 12, "dag%d", c);
1002		if (-1 == dag_parse_name(name, dagname, DAGNAME_BUFSIZE, &dagstream))
1003		{
1004			return -1;
1005		}
1006		description = NULL;
1007		if ( (dagfd = dag_open(dagname)) >= 0 ) {
1008			if ((inf = dag_pciinfo(dagfd)))
1009				description = dag_device_name(inf->device_code, 1);
1010			if (pcap_add_if(devlistp, name, 0, description, errbuf) == -1) {
1011				/*
1012				 * Failure.
1013				 */
1014				ret = -1;
1015			}
1016#ifdef HAVE_DAG_STREAMS_API
1017			{
1018				int stream, rxstreams;
1019				rxstreams = dag_rx_get_stream_count(dagfd);
1020				for(stream=0;stream<DAG_STREAM_MAX;stream+=2) {
1021					if (0 == dag_attach_stream(dagfd, stream, 0, 0)) {
1022						dag_detach_stream(dagfd, stream);
1023
1024						snprintf(name,  10, "dag%d:%d", c, stream);
1025						if (pcap_add_if(devlistp, name, 0, description, errbuf) == -1) {
1026							/*
1027							 * Failure.
1028							 */
1029							ret = -1;
1030						}
1031
1032						rxstreams--;
1033						if(rxstreams <= 0) {
1034							break;
1035						}
1036					}
1037				}
1038			}
1039#endif  /* HAVE_DAG_STREAMS_API */
1040			dag_close(dagfd);
1041		}
1042
1043	}
1044	return (ret);
1045}
1046
1047/*
1048 * Installs the given bpf filter program in the given pcap structure.  There is
1049 * no attempt to store the filter in kernel memory as that is not supported
1050 * with DAG cards.
1051 */
1052static int
1053dag_setfilter(pcap_t *p, struct bpf_program *fp)
1054{
1055	if (!p)
1056		return -1;
1057	if (!fp) {
1058		strncpy(p->errbuf, "setfilter: No filter specified",
1059			sizeof(p->errbuf));
1060		return -1;
1061	}
1062
1063	/* Make our private copy of the filter */
1064
1065	if (install_bpf_program(p, fp) < 0)
1066		return -1;
1067
1068	return (0);
1069}
1070
1071static int
1072dag_set_datalink(pcap_t *p, int dlt)
1073{
1074	p->linktype = dlt;
1075
1076	return (0);
1077}
1078
1079static int
1080dag_setnonblock(pcap_t *p, int nonblock, char *errbuf)
1081{
1082	struct pcap_dag *pd = p->priv;
1083
1084	/*
1085	 * Set non-blocking mode on the FD.
1086	 * XXX - is that necessary?  If not, don't bother calling it,
1087	 * and have a "dag_getnonblock()" function that looks at
1088	 * "pd->dag_offset_flags".
1089	 */
1090	if (pcap_setnonblock_fd(p, nonblock, errbuf) < 0)
1091		return (-1);
1092#ifdef HAVE_DAG_STREAMS_API
1093	{
1094		uint32_t mindata;
1095		struct timeval maxwait;
1096		struct timeval poll;
1097
1098		if (dag_get_stream_poll(p->fd, pd->dag_stream,
1099					&mindata, &maxwait, &poll) < 0) {
1100			snprintf(errbuf, PCAP_ERRBUF_SIZE, "dag_get_stream_poll: %s\n", pcap_strerror(errno));
1101			return -1;
1102		}
1103
1104		/* Amount of data to collect in Bytes before calling callbacks.
1105		 * Important for efficiency, but can introduce latency
1106		 * at low packet rates if to_ms not set!
1107		 */
1108		if(nonblock)
1109			mindata = 0;
1110		else
1111			mindata = 65536;
1112
1113		if (dag_set_stream_poll(p->fd, pd->dag_stream,
1114					mindata, &maxwait, &poll) < 0) {
1115			snprintf(errbuf, PCAP_ERRBUF_SIZE, "dag_set_stream_poll: %s\n", pcap_strerror(errno));
1116			return -1;
1117		}
1118	}
1119#endif /* HAVE_DAG_STREAMS_API */
1120	if (nonblock) {
1121		pd->dag_offset_flags |= DAGF_NONBLOCK;
1122	} else {
1123		pd->dag_offset_flags &= ~DAGF_NONBLOCK;
1124	}
1125	return (0);
1126}
1127
1128static int
1129dag_get_datalink(pcap_t *p)
1130{
1131	struct pcap_dag *pd = p->priv;
1132	int index=0, dlt_index=0;
1133	uint8_t types[255];
1134
1135	memset(types, 0, 255);
1136
1137	if (p->dlt_list == NULL && (p->dlt_list = malloc(255*sizeof(*(p->dlt_list)))) == NULL) {
1138		(void)snprintf(p->errbuf, sizeof(p->errbuf), "malloc: %s", pcap_strerror(errno));
1139		return (-1);
1140	}
1141
1142	p->linktype = 0;
1143
1144#ifdef HAVE_DAG_GET_STREAM_ERF_TYPES
1145	/* Get list of possible ERF types for this card */
1146	if (dag_get_stream_erf_types(p->fd, pd->dag_stream, types, 255) < 0) {
1147		snprintf(p->errbuf, sizeof(p->errbuf), "dag_get_stream_erf_types: %s", pcap_strerror(errno));
1148		return (-1);
1149	}
1150
1151	while (types[index]) {
1152
1153#elif defined HAVE_DAG_GET_ERF_TYPES
1154	/* Get list of possible ERF types for this card */
1155	if (dag_get_erf_types(p->fd, types, 255) < 0) {
1156		snprintf(p->errbuf, sizeof(p->errbuf), "dag_get_erf_types: %s", pcap_strerror(errno));
1157		return (-1);
1158	}
1159
1160	while (types[index]) {
1161#else
1162	/* Check the type through a dagapi call. */
1163	types[index] = dag_linktype(p->fd);
1164
1165	{
1166#endif
1167		switch((types[index] & 0x7f)) {
1168
1169		case TYPE_HDLC_POS:
1170		case TYPE_COLOR_HDLC_POS:
1171		case TYPE_DSM_COLOR_HDLC_POS:
1172		case TYPE_COLOR_HASH_POS:
1173
1174			if (p->dlt_list != NULL) {
1175				p->dlt_list[dlt_index++] = DLT_CHDLC;
1176				p->dlt_list[dlt_index++] = DLT_PPP_SERIAL;
1177				p->dlt_list[dlt_index++] = DLT_FRELAY;
1178			}
1179			if(!p->linktype)
1180				p->linktype = DLT_CHDLC;
1181			break;
1182
1183		case TYPE_ETH:
1184		case TYPE_COLOR_ETH:
1185		case TYPE_DSM_COLOR_ETH:
1186		case TYPE_COLOR_HASH_ETH:
1187			/*
1188			 * This is (presumably) a real Ethernet capture; give it a
1189			 * link-layer-type list with DLT_EN10MB and DLT_DOCSIS, so
1190			 * that an application can let you choose it, in case you're
1191			 * capturing DOCSIS traffic that a Cisco Cable Modem
1192			 * Termination System is putting out onto an Ethernet (it
1193			 * doesn't put an Ethernet header onto the wire, it puts raw
1194			 * DOCSIS frames out on the wire inside the low-level
1195			 * Ethernet framing).
1196			 */
1197			if (p->dlt_list != NULL) {
1198				p->dlt_list[dlt_index++] = DLT_EN10MB;
1199				p->dlt_list[dlt_index++] = DLT_DOCSIS;
1200			}
1201			if(!p->linktype)
1202				p->linktype = DLT_EN10MB;
1203			break;
1204
1205		case TYPE_ATM:
1206		case TYPE_AAL5:
1207		case TYPE_MC_ATM:
1208		case TYPE_MC_AAL5:
1209			if (p->dlt_list != NULL) {
1210				p->dlt_list[dlt_index++] = DLT_ATM_RFC1483;
1211				p->dlt_list[dlt_index++] = DLT_SUNATM;
1212			}
1213			if(!p->linktype)
1214				p->linktype = DLT_ATM_RFC1483;
1215			break;
1216
1217		case TYPE_COLOR_MC_HDLC_POS:
1218		case TYPE_MC_HDLC:
1219			if (p->dlt_list != NULL) {
1220				p->dlt_list[dlt_index++] = DLT_CHDLC;
1221				p->dlt_list[dlt_index++] = DLT_PPP_SERIAL;
1222				p->dlt_list[dlt_index++] = DLT_FRELAY;
1223				p->dlt_list[dlt_index++] = DLT_MTP2;
1224				p->dlt_list[dlt_index++] = DLT_MTP2_WITH_PHDR;
1225				p->dlt_list[dlt_index++] = DLT_LAPD;
1226			}
1227			if(!p->linktype)
1228				p->linktype = DLT_CHDLC;
1229			break;
1230
1231		case TYPE_IPV4:
1232		case TYPE_IPV6:
1233			if(!p->linktype)
1234				p->linktype = DLT_RAW;
1235			break;
1236
1237		case TYPE_LEGACY:
1238		case TYPE_MC_RAW:
1239		case TYPE_MC_RAW_CHANNEL:
1240		case TYPE_IP_COUNTER:
1241		case TYPE_TCP_FLOW_COUNTER:
1242		case TYPE_INFINIBAND:
1243		case TYPE_RAW_LINK:
1244		case TYPE_INFINIBAND_LINK:
1245		default:
1246			/* Libpcap cannot deal with these types yet */
1247			/* Add no 'native' DLTs, but still covered by DLT_ERF */
1248			break;
1249
1250		} /* switch */
1251		index++;
1252	}
1253
1254	p->dlt_list[dlt_index++] = DLT_ERF;
1255
1256	p->dlt_count = dlt_index;
1257
1258	if(!p->linktype)
1259		p->linktype = DLT_ERF;
1260
1261	return p->linktype;
1262}
1263