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 19static const char rcsid[] _U_ = 20 "@(#) $Header: /tcpdump/master/libpcap/pcap-dag.c,v 1.21.2.4 2006/04/07 07:08:50 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 42struct mbuf; /* Squelch compiler warnings on some platforms for */ 43struct 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 */ 53struct sunatm_hdr { 54 unsigned char flags; /* destination and traffic type */ 55 unsigned char vpi; /* VPI */ 56 unsigned short vci; /* VCI */ 57}; 58 59typedef struct pcap_dag_node { 60 struct pcap_dag_node *next; 61 pcap_t *p; 62 pid_t pid; 63} pcap_dag_node_t; 64 65static pcap_dag_node_t *pcap_dags = NULL; 66static int atexit_handler_installed = 0; 67static 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 94static int dag_setfilter(pcap_t *p, struct bpf_program *fp); 95static int dag_stats(pcap_t *p, struct pcap_stat *ps); 96static int dag_set_datalink(pcap_t *p, int dlt); 97static int dag_get_datalink(pcap_t *p); 98static int dag_setnonblock(pcap_t *p, int nonblock, char *errbuf); 99 100static void 101delete_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 123static void 124dag_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#ifdef linux 141 free(p->md.device); 142#endif 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 148static void 149atexit_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 160static int 161new_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 */ 188static int 189dag_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_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_COLOR_HDLC_POS 343 case TYPE_COLOR_HDLC_POS: 344#endif 345 case TYPE_HDLC_POS: 346 packet_len = ntohs(header->wlen); 347 packet_len -= (p->md.dag_fcs_bits >> 3); 348 caplen = rlen - dag_record_size; 349 if (caplen > packet_len) { 350 caplen = packet_len; 351 } 352 break; 353#ifdef TYPE_MC_HDLC 354 case TYPE_MC_HDLC: 355 packet_len = ntohs(header->wlen); 356 packet_len -= (p->md.dag_fcs_bits >> 3); 357 caplen = rlen - dag_record_size - 4; 358 if (caplen > packet_len) { 359 caplen = packet_len; 360 } 361 dp += 4; 362 break; 363#endif 364 } 365 366 if (caplen > p->snapshot) 367 caplen = p->snapshot; 368 369 /* Count lost packets. */ 370 switch(header->type) { 371#ifdef TYPE_COLOR_HDLC_POS 372 /* in this type the color value overwrites the lctr */ 373 case TYPE_COLOR_HDLC_POS: 374 break; 375#endif 376#ifdef TYPE_COLOR_ETH 377 /* in this type the color value overwrites the lctr */ 378 case TYPE_COLOR_ETH: 379 break; 380#endif 381 default: 382 if (header->lctr) { 383 if (p->md.stat.ps_drop > (UINT_MAX - ntohs(header->lctr))) { 384 p->md.stat.ps_drop = UINT_MAX; 385 } else { 386 p->md.stat.ps_drop += ntohs(header->lctr); 387 } 388 } 389 } 390 391 /* Run the packet filter if there is one. */ 392 if ((p->fcode.bf_insns == NULL) || bpf_filter(p->fcode.bf_insns, dp, packet_len, caplen)) { 393 394 /* convert between timestamp formats */ 395 register unsigned long long ts; 396 397 if (IS_BIGENDIAN()) { 398 ts = SWAP_TS(header->ts); 399 } else { 400 ts = header->ts; 401 } 402 403 pcap_header.ts.tv_sec = ts >> 32; 404 ts = (ts & 0xffffffffULL) * 1000000; 405 ts += 0x80000000; /* rounding */ 406 pcap_header.ts.tv_usec = ts >> 32; 407 if (pcap_header.ts.tv_usec >= 1000000) { 408 pcap_header.ts.tv_usec -= 1000000; 409 pcap_header.ts.tv_sec++; 410 } 411 412 /* Fill in our own header data */ 413 pcap_header.caplen = caplen; 414 pcap_header.len = packet_len; 415 416 /* Count the packet. */ 417 p->md.stat.ps_recv++; 418 419 /* Call the user supplied callback function */ 420 callback(user, &pcap_header, dp); 421 422 /* Only count packets that pass the filter, for consistency with standard Linux behaviour. */ 423 processed++; 424 if (processed == cnt) 425 { 426 /* Reached the user-specified limit. */ 427 return cnt; 428 } 429 } 430 } 431 432 return processed; 433} 434 435static int 436dag_inject(pcap_t *p, const void *buf _U_, size_t size _U_) 437{ 438 strlcpy(p->errbuf, "Sending packets isn't supported on DAG cards", 439 PCAP_ERRBUF_SIZE); 440 return (-1); 441} 442 443/* 444 * Get a handle for a live capture from the given DAG device. Passing a NULL 445 * device will result in a failure. The promisc flag is ignored because DAG 446 * cards are always promiscuous. The to_ms parameter is also ignored as it is 447 * not supported in hardware. 448 * 449 * See also pcap(3). 450 */ 451pcap_t * 452dag_open_live(const char *device, int snaplen, int promisc, int to_ms, char *ebuf) 453{ 454 char conf[30]; /* dag configure string */ 455 pcap_t *handle; 456 char *s; 457 int n; 458 daginf_t* daginf; 459 char * newDev; 460#ifdef HAVE_DAG_STREAMS_API 461 uint32_t mindata; 462 struct timeval maxwait; 463 struct timeval poll; 464#endif 465 466 if (device == NULL) { 467 snprintf(ebuf, PCAP_ERRBUF_SIZE, "device is NULL: %s", pcap_strerror(errno)); 468 return NULL; 469 } 470 /* Allocate a handle for this session. */ 471 472 handle = malloc(sizeof(*handle)); 473 if (handle == NULL) { 474 snprintf(ebuf, PCAP_ERRBUF_SIZE, "malloc %s: %s", device, pcap_strerror(errno)); 475 return NULL; 476 } 477 478 /* Initialize some components of the pcap structure. */ 479 480 memset(handle, 0, sizeof(*handle)); 481 482 newDev = (char *)malloc(strlen(device) + 16); 483 484#ifdef HAVE_DAG_STREAMS_API 485 486 /* Parse input name to get dag device and stream number if provided */ 487 if (dag_parse_name(device, newDev, strlen(device) + 16, &handle->md.dag_stream) < 0) { 488 snprintf(ebuf, PCAP_ERRBUF_SIZE, "dag_parse_name: %s\n", pcap_strerror(errno)); 489 goto fail; 490 } 491 device = newDev; 492 493 if (handle->md.dag_stream%2) { 494 snprintf(ebuf, PCAP_ERRBUF_SIZE, "dag_parse_name: tx (even numbered) streams not supported for capture\n"); 495 goto fail; 496 } 497#else 498 if (strstr(device, "/dev") == NULL) { 499 newDev[0] = '\0'; 500 strcat(newDev, "/dev/"); 501 strcat(newDev,device); 502 device = newDev; 503 } else { 504 device = strdup(device); 505 } 506 507 if (device == NULL) { 508 snprintf(ebuf, PCAP_ERRBUF_SIZE, "str_dup: %s\n", pcap_strerror(errno)); 509 goto fail; 510 } 511#endif /* HAVE_DAG_STREAMS_API */ 512 513 /* setup device parameters */ 514 if((handle->fd = dag_open((char *)device)) < 0) { 515 snprintf(ebuf, PCAP_ERRBUF_SIZE, "dag_open %s: %s", device, pcap_strerror(errno)); 516 goto fail; 517 } 518 519#ifdef HAVE_DAG_STREAMS_API 520 /* Open requested stream. Can fail if already locked or on error */ 521 if (dag_attach_stream(handle->fd, handle->md.dag_stream, 0, 0) < 0) { 522 snprintf(ebuf, PCAP_ERRBUF_SIZE, "dag_attach_stream: %s\n", pcap_strerror(errno)); 523 goto fail; 524 } 525 526 /* Set up default poll parameters for stream 527 * Can be overridden by pcap_set_nonblock() 528 */ 529 if (dag_get_stream_poll(handle->fd, handle->md.dag_stream, 530 &mindata, &maxwait, &poll) < 0) { 531 snprintf(ebuf, PCAP_ERRBUF_SIZE, "dag_get_stream_poll: %s\n", pcap_strerror(errno)); 532 goto fail; 533 } 534 535 /* Amount of data to collect in Bytes before calling callbacks. 536 * Important for efficiency, but can introduce latency 537 * at low packet rates if to_ms not set! 538 */ 539 mindata = 65536; 540 541 /* Obey to_ms if supplied. This is a good idea! 542 * Recommend 10-100ms. Calls will time out even if no data arrived. 543 */ 544 maxwait.tv_sec = to_ms/1000; 545 maxwait.tv_usec = (to_ms%1000) * 1000; 546 547 if (dag_set_stream_poll(handle->fd, handle->md.dag_stream, 548 mindata, &maxwait, &poll) < 0) { 549 snprintf(ebuf, PCAP_ERRBUF_SIZE, "dag_set_stream_poll: %s\n", pcap_strerror(errno)); 550 goto fail; 551 } 552 553#else 554 if((handle->md.dag_mem_base = dag_mmap(handle->fd)) == MAP_FAILED) { 555 snprintf(ebuf, PCAP_ERRBUF_SIZE,"dag_mmap %s: %s\n", device, pcap_strerror(errno)); 556 goto fail; 557 } 558 559#endif /* HAVE_DAG_STREAMS_API */ 560 561 /* XXX Not calling dag_configure() to set slen; this is unsafe in 562 * multi-stream environments as the gpp config is global. 563 * Once the firmware provides 'per-stream slen' this can be supported 564 * again via the Config API without side-effects */ 565#if 0 566 /* set the card snap length to the specified snaplen parameter */ 567 /* This is a really bad idea, as different cards have different 568 * valid slen ranges. Should fix in Config API. */ 569 if (snaplen == 0 || snaplen > MAX_DAG_SNAPLEN) { 570 snaplen = MAX_DAG_SNAPLEN; 571 } else if (snaplen < MIN_DAG_SNAPLEN) { 572 snaplen = MIN_DAG_SNAPLEN; 573 } 574 /* snap len has to be a multiple of 4 */ 575 snprintf(conf, 30, "varlen slen=%d", (snaplen + 3) & ~3); 576 577 if(dag_configure(handle->fd, conf) < 0) { 578 snprintf(ebuf, PCAP_ERRBUF_SIZE,"dag_configure %s: %s\n", device, pcap_strerror(errno)); 579 goto fail; 580 } 581#endif 582 583#ifdef HAVE_DAG_STREAMS_API 584 if(dag_start_stream(handle->fd, handle->md.dag_stream) < 0) { 585 snprintf(ebuf, PCAP_ERRBUF_SIZE, "dag_start_stream %s: %s\n", device, pcap_strerror(errno)); 586 goto fail; 587 } 588#else 589 if(dag_start(handle->fd) < 0) { 590 snprintf(ebuf, PCAP_ERRBUF_SIZE, "dag_start %s: %s\n", device, pcap_strerror(errno)); 591 goto fail; 592 } 593#endif /* HAVE_DAG_STREAMS_API */ 594 595 /* 596 * Important! You have to ensure bottom is properly 597 * initialized to zero on startup, it won't give you 598 * a compiler warning if you make this mistake! 599 */ 600 handle->md.dag_mem_bottom = 0; 601 handle->md.dag_mem_top = 0; 602 handle->md.dag_fcs_bits = 32; 603 604 /* Query the card first for special cases. */ 605 daginf = dag_info(handle->fd); 606 if ((0x4200 == daginf->device_code) || (0x4230 == daginf->device_code)) 607 { 608 /* DAG 4.2S and 4.23S already strip the FCS. Stripping the final word again truncates the packet. */ 609 handle->md.dag_fcs_bits = 0; 610 } 611 612 /* Then allow an environment variable to override. */ 613 if ((s = getenv("ERF_FCS_BITS")) != NULL) { 614 if ((n = atoi(s)) == 0 || n == 16|| n == 32) { 615 handle->md.dag_fcs_bits = n; 616 } else { 617 snprintf(ebuf, PCAP_ERRBUF_SIZE, 618 "pcap_open_live %s: bad ERF_FCS_BITS value (%d) in environment\n", device, n); 619 goto fail; 620 } 621 } 622 623 handle->snapshot = snaplen; 624 handle->md.dag_timeout = to_ms; 625 626 handle->linktype = -1; 627 if (dag_get_datalink(handle) < 0) { 628 strcpy(ebuf, handle->errbuf); 629 goto fail; 630 } 631 632 handle->bufsize = 0; 633 634 if (new_pcap_dag(handle) < 0) { 635 snprintf(ebuf, PCAP_ERRBUF_SIZE, "new_pcap_dag %s: %s\n", device, pcap_strerror(errno)); 636 goto fail; 637 } 638 639 /* 640 * "select()" and "poll()" don't work on DAG device descriptors. 641 */ 642 handle->selectable_fd = -1; 643 644#ifdef linux 645 handle->md.device = (char *)device; 646 handle->md.timeout = to_ms; 647#else 648 free((char *)device); 649 device = NULL; 650#endif 651 652 handle->read_op = dag_read; 653 handle->inject_op = dag_inject; 654 handle->setfilter_op = dag_setfilter; 655 handle->setdirection_op = NULL; /* Not implemented.*/ 656 handle->set_datalink_op = dag_set_datalink; 657 handle->getnonblock_op = pcap_getnonblock_fd; 658 handle->setnonblock_op = dag_setnonblock; 659 handle->stats_op = dag_stats; 660 handle->close_op = dag_platform_close; 661 662 return handle; 663 664fail: 665 if (newDev != NULL) { 666 free((char *)newDev); 667 } 668 if (handle != NULL) { 669 /* 670 * Get rid of any link-layer type list we allocated. 671 */ 672 if (handle->dlt_list != NULL) { 673 free(handle->dlt_list); 674 } 675 free(handle); 676 } 677 678 return NULL; 679} 680 681static int 682dag_stats(pcap_t *p, struct pcap_stat *ps) { 683 /* This needs to be filled out correctly. Hopefully a dagapi call will 684 provide all necessary information. 685 */ 686 /*p->md.stat.ps_recv = 0;*/ 687 /*p->md.stat.ps_drop = 0;*/ 688 689 *ps = p->md.stat; 690 691 return 0; 692} 693 694/* 695 * Simply submit all possible dag names as candidates. 696 * pcap_add_if() internally tests each candidate with pcap_open_live(), 697 * so any non-existent devices are dropped. 698 * For 2.5 try all rx stream names as well. 699 */ 700int 701dag_platform_finddevs(pcap_if_t **devlistp, char *errbuf) 702{ 703 char name[12]; /* XXX - pick a size */ 704 int ret = 0; 705 int c; 706 707 /* Try all the DAGs 0-9 */ 708 for (c = 0; c < 9; c++) { 709 snprintf(name, 12, "dag%d", c); 710 if (pcap_add_if(devlistp, name, 0, NULL, errbuf) == -1) { 711 /* 712 * Failure. 713 */ 714 ret = -1; 715 } 716#ifdef HAVE_DAG_STREAMS_API 717 { 718 int stream; 719 for(stream=0;stream<16;stream+=2) { 720 snprintf(name, 10, "dag%d:%d", c, stream); 721 if (pcap_add_if(devlistp, name, 0, NULL, errbuf) == -1) { 722 /* 723 * Failure. 724 */ 725 ret = -1; 726 } 727 } 728 } 729#endif /* HAVE_DAG_STREAMS_API */ 730 } 731 return (ret); 732} 733 734/* 735 * Installs the given bpf filter program in the given pcap structure. There is 736 * no attempt to store the filter in kernel memory as that is not supported 737 * with DAG cards. 738 */ 739static int 740dag_setfilter(pcap_t *p, struct bpf_program *fp) 741{ 742 if (!p) 743 return -1; 744 if (!fp) { 745 strncpy(p->errbuf, "setfilter: No filter specified", 746 sizeof(p->errbuf)); 747 return -1; 748 } 749 750 /* Make our private copy of the filter */ 751 752 if (install_bpf_program(p, fp) < 0) 753 return -1; 754 755 p->md.use_bpf = 0; 756 757 return (0); 758} 759 760static int 761dag_set_datalink(pcap_t *p, int dlt) 762{ 763 p->linktype = dlt; 764 765 return (0); 766} 767 768static int 769dag_setnonblock(pcap_t *p, int nonblock, char *errbuf) 770{ 771 /* 772 * Set non-blocking mode on the FD. 773 * XXX - is that necessary? If not, don't bother calling it, 774 * and have a "dag_getnonblock()" function that looks at 775 * "p->md.dag_offset_flags". 776 */ 777 if (pcap_setnonblock_fd(p, nonblock, errbuf) < 0) 778 return (-1); 779#ifdef HAVE_DAG_STREAMS_API 780 { 781 uint32_t mindata; 782 struct timeval maxwait; 783 struct timeval poll; 784 785 if (dag_get_stream_poll(p->fd, p->md.dag_stream, 786 &mindata, &maxwait, &poll) < 0) { 787 snprintf(errbuf, PCAP_ERRBUF_SIZE, "dag_get_stream_poll: %s\n", pcap_strerror(errno)); 788 return -1; 789 } 790 791 /* Amount of data to collect in Bytes before calling callbacks. 792 * Important for efficiency, but can introduce latency 793 * at low packet rates if to_ms not set! 794 */ 795 if(nonblock) 796 mindata = 0; 797 else 798 mindata = 65536; 799 800 if (dag_set_stream_poll(p->fd, p->md.dag_stream, 801 mindata, &maxwait, &poll) < 0) { 802 snprintf(errbuf, PCAP_ERRBUF_SIZE, "dag_set_stream_poll: %s\n", pcap_strerror(errno)); 803 return -1; 804 } 805 } 806#endif /* HAVE_DAG_STREAMS_API */ 807 if (nonblock) { 808 p->md.dag_offset_flags |= DAGF_NONBLOCK; 809 } else { 810 p->md.dag_offset_flags &= ~DAGF_NONBLOCK; 811 } 812 return (0); 813} 814 815static int 816dag_get_datalink(pcap_t *p) 817{ 818 int index=0; 819 uint8_t types[255]; 820 821 memset(types, 0, 255); 822 823 if (p->dlt_list == NULL && (p->dlt_list = malloc(255*sizeof(*(p->dlt_list)))) == NULL) { 824 (void)snprintf(p->errbuf, sizeof(p->errbuf), "malloc: %s", pcap_strerror(errno)); 825 return (-1); 826 } 827 828 p->linktype = 0; 829 830#ifdef HAVE_DAG_GET_ERF_TYPES 831 /* Get list of possible ERF types for this card */ 832 if (dag_get_erf_types(p->fd, types, 255) < 0) { 833 snprintf(p->errbuf, sizeof(p->errbuf), "dag_get_erf_types: %s", pcap_strerror(errno)); 834 return (-1); 835 } 836 837 while (types[index]) { 838#else 839 /* Check the type through a dagapi call. */ 840 types[index] = dag_linktype(p->fd); 841 842 { 843#endif 844 switch(types[index]) { 845 846 case TYPE_HDLC_POS: 847#ifdef TYPE_COLOR_HDLC_POS 848 case TYPE_COLOR_HDLC_POS: 849#endif 850 if (p->dlt_list != NULL) { 851 p->dlt_list[index++] = DLT_CHDLC; 852 p->dlt_list[index++] = DLT_PPP_SERIAL; 853 p->dlt_list[index++] = DLT_FRELAY; 854 } 855 if(!p->linktype) 856 p->linktype = DLT_CHDLC; 857 break; 858 859 case TYPE_ETH: 860#ifdef TYPE_COLOR_ETH 861 case TYPE_COLOR_ETH: 862#endif 863 /* 864 * This is (presumably) a real Ethernet capture; give it a 865 * link-layer-type list with DLT_EN10MB and DLT_DOCSIS, so 866 * that an application can let you choose it, in case you're 867 * capturing DOCSIS traffic that a Cisco Cable Modem 868 * Termination System is putting out onto an Ethernet (it 869 * doesn't put an Ethernet header onto the wire, it puts raw 870 * DOCSIS frames out on the wire inside the low-level 871 * Ethernet framing). 872 */ 873 if (p->dlt_list != NULL) { 874 p->dlt_list[index++] = DLT_EN10MB; 875 p->dlt_list[index++] = DLT_DOCSIS; 876 } 877 if(!p->linktype) 878 p->linktype = DLT_EN10MB; 879 break; 880 881 case TYPE_ATM: 882#ifdef TYPE_AAL5 883 case TYPE_AAL5: 884#endif 885#ifdef TYPE_MC_ATM 886 case TYPE_MC_ATM: 887#endif 888#ifdef TYPE_MC_AAL5 889 case TYPE_MC_AAL5: 890#endif 891 if (p->dlt_list != NULL) { 892 p->dlt_list[index++] = DLT_ATM_RFC1483; 893 p->dlt_list[index++] = DLT_SUNATM; 894 } 895 if(!p->linktype) 896 p->linktype = DLT_ATM_RFC1483; 897 break; 898 899#ifdef TYPE_MC_HDLC 900 case TYPE_MC_HDLC: 901 if (p->dlt_list != NULL) { 902 p->dlt_list[index++] = DLT_CHDLC; 903 p->dlt_list[index++] = DLT_PPP_SERIAL; 904 p->dlt_list[index++] = DLT_FRELAY; 905 p->dlt_list[index++] = DLT_MTP2; 906 } 907 if(!p->linktype) 908 p->linktype = DLT_CHDLC; 909 break; 910#endif 911 912 case TYPE_LEGACY: 913 if(!p->linktype) 914 p->linktype = DLT_NULL; 915 break; 916 917 default: 918 snprintf(p->errbuf, sizeof(p->errbuf), "unknown DAG linktype %d", types[index]); 919 return (-1); 920 921 } /* switch */ 922 } 923 924 p->dlt_count = index; 925 926 return p->linktype; 927} 928