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