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