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