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