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 } 887