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