From: guy Date: Thu, 7 Jul 2005 06:56:02 +0000 (+0000) Subject: From Stephen Donnelly: updates to the DAG support, to support their X-Git-Tag: libpcap-0.9.2~7 X-Git-Url: https://git.tcpdump.org/libpcap/commitdiff_plain/f6812ab143c0a5219d60bbfdb61492788dee038d From Stephen Donnelly: updates to the DAG support, to support their updated API if available. --- diff --git a/README.dag b/README.dag index eb1471b9..49b3e738 100644 --- a/README.dag +++ b/README.dag @@ -37,12 +37,57 @@ cards and will not capture from the native OS packet stream. ---------------------------------------------------------------------- +Libpcap when built for DAG cards against dag-2.5.1 or later releases: + +Timeouts are supported. pcap_dispatch() will return after to_ms milliseconds +regardless of how many packets are received. If to_ms is zero pcap_dispatch() +will block waiting for data indefinitely. + +pcap_dispatch() will block on and process a minimum of 64kB of data (before +filtering) for efficiency. This can introduce high latencies on quiet +interfaces unless a timeout value is set. The timeout expiring will override +the 64kB minimum causing pcap_dispatch() to process any available data and +return. + +pcap_setnonblock is supported. When nonblock is set, pcap_dispatch() will +check once for available data, process any data available up to count, then +return immediately. + +pcap_findalldevs() is supported, e.g. dag0, dag1... + +Some DAG cards can provide more than one 'stream' of received data. +This can be data from different physical ports, or separated by filtering +or load balancing mechanisms. Receive streams have even numbers, e.g. +dag0:0, dag0:2 etc. Specifying transmit streams for capture is not supported. + +pcap_setfilter() is supported, BPF programs run in userspace. + +pcap_setdirection() is not supported. Only received traffic is captured. +DAG cards normally do not have IP or link layer addresses assigned as +they are used to passively monitor links. + +pcap_breakloop() is supported. + +pcap_datalink() and pcap_list_datalinks() are supported. The DAG card does +not attempt to set the correct datalink type automatically where more than +one type is possible. + +pcap_stats() is supported. ps_drop is the number of packets dropped due to +RX stream buffer overflow, this count is before filters are applied (it will +include packets that would have been dropped by the filter). The RX stream +buffer size is user configurable outside libpcap, typically 16-512MB. + +pcap_get_selectable_fd() is not supported, DAG cards do not support +poll/select methods. + +pcap_inject() and pcap_sendpacket() are not supported. + +---------------------------------------------------------------------- + Please submit bug reports via . -Please also visit our Web pages at: +Please also visit our Web site at: http://www.endace.com/ - http://dag.cs.waikato.ac.nz/ For more information about Endace DAG cards contact . - diff --git a/config.h.in b/config.h.in index 43a6b94c..6943adb5 100644 --- a/config.h.in +++ b/config.h.in @@ -13,6 +13,9 @@ /* define if you have the DAG API */ #undef HAVE_DAG_API +/* define if you have streams capable DAG API */ +#undef HAVE_DAG_STREAMS_API + /* Define to 1 if you have the declaration of `ether_hostton', and to 0 if you don't. */ #undef HAVE_DECL_ETHER_HOSTTON diff --git a/configure b/configure index 42b8153c..bb94054c 100755 --- a/configure +++ b/configure @@ -1,5 +1,5 @@ #! /bin/sh -# From configure.in Revision: 1.120.2.6 . +# From configure.in Revision: 1.120.2.7 . # Guess values for system-dependent variables and create Makefiles. # Generated by GNU Autoconf 2.57. # @@ -5791,6 +5791,14 @@ fi LDFLAGS=$saved_ldflags + if test "$dag_version" = 2.5.x; then + +cat >>confdefs.h <<\_ACEOF +#define HAVE_DAG_STREAMS_API 1 +_ACEOF + + fi + # See if we can find a specific version string. echo "$as_me:$LINENO: checking the DAG API version" >&5 echo $ECHO_N "checking the DAG API version... $ECHO_C" >&6 diff --git a/configure.in b/configure.in index 4df25105..0d3542f6 100644 --- a/configure.in +++ b/configure.in @@ -1,4 +1,4 @@ -dnl @(#) $Header: /tcpdump/master/libpcap/configure.in,v 1.120.2.6 2005-06-20 21:37:43 guy Exp $ (LBL) +dnl @(#) $Header: /tcpdump/master/libpcap/configure.in,v 1.120.2.7 2005-07-07 06:56:03 guy Exp $ (LBL) dnl dnl Copyright (c) 1994, 1995, 1996, 1997 dnl The Regents of the University of California. All rights reserved. @@ -6,7 +6,7 @@ dnl dnl Process this file with autoconf to produce a configure script. dnl -AC_REVISION($Revision: 1.120.2.6 $) +AC_REVISION($Revision: 1.120.2.7 $) AC_PREREQ(2.50) AC_INIT(pcap.c) @@ -569,6 +569,10 @@ if test $ac_cv_lbl_dag_api = yes; then AC_CHECK_LIB([dag], [dag_attach_stream], [dag_version="2.5.x"], [dag_version="2.4.x"]) LDFLAGS=$saved_ldflags + if test "$dag_version" = 2.5.x; then + AC_DEFINE(HAVE_DAG_STREAMS_API, 1, [define if you have streams capable DAG API]) + fi + # See if we can find a specific version string. AC_MSG_CHECKING([the DAG API version]) if test -r "$dag_root/VERSION"; then diff --git a/pcap-dag.c b/pcap-dag.c index f7288e27..3965b839 100644 --- a/pcap-dag.c +++ b/pcap-dag.c @@ -10,12 +10,14 @@ * called as required from their pcap-linux/bpf equivalents. * * Authors: Richard Littin, Sean Irvine ({richard,sean}@reeltwo.com) - * Modifications: Jesper Peterson, Koryn Grant + * Modifications: Jesper Peterson + * Koryn Grant + * Stephen Donnelly */ #ifndef lint static const char rcsid[] _U_ = - "@(#) $Header: /tcpdump/master/libpcap/pcap-dag.c,v 1.21.2.1 2005-05-03 18:54:35 guy Exp $ (LBL)"; + "@(#) $Header: /tcpdump/master/libpcap/pcap-dag.c,v 1.21.2.2 2005-07-07 06:56:03 guy Exp $ (LBL)"; #endif #ifdef HAVE_CONFIG_H @@ -123,24 +125,24 @@ delete_pcap_dag(pcap_t *p) static void dag_platform_close(pcap_t *p) { - -#ifdef linux - if (p != NULL && p->md.device != NULL) { - if(dag_stop(p->fd) < 0) - fprintf(stderr,"dag_stop %s: %s\n", p->md.device, strerror(errno)); - if(dag_close(p->fd) < 0) - fprintf(stderr,"dag_close %s: %s\n", p->md.device, strerror(errno)); + + if (p != NULL) { +#ifdef HAVE_DAG_STREAMS_API + if(dag_stop_stream(p->fd, p->md.dag_stream) < 0) + fprintf(stderr,"dag_stop_stream: %s\n", strerror(errno)); - free(p->md.device); - } + if(dag_detach_stream(p->fd, p->md.dag_stream) < 0) + fprintf(stderr,"dag_detach_stream: %s\n", strerror(errno)); #else - if (p != NULL) { if(dag_stop(p->fd) < 0) fprintf(stderr,"dag_stop: %s\n", strerror(errno)); +#endif /* HAVE_DAG_STREAMS_API */ if(dag_close(p->fd) < 0) fprintf(stderr,"dag_close: %s\n", strerror(errno)); - } +#ifdef linux + free(p->md.device); #endif + } delete_pcap_dag(p); /* Note: don't need to call close(p->fd) here as dag_close(p->fd) does this. */ } @@ -192,118 +194,190 @@ dag_read(pcap_t *p, int cnt, pcap_handler callback, u_char *user) int flags = p->md.dag_offset_flags; unsigned int nonblocking = flags & DAGF_NONBLOCK; - for (;;) - { - /* Get the next bufferful of packets (if necessary). */ - while (p->md.dag_mem_top - p->md.dag_mem_bottom < dag_record_size) { + /* Get the next bufferful of packets (if necessary). */ + while (p->md.dag_mem_top - p->md.dag_mem_bottom < dag_record_size) { + /* + * Has "pcap_breakloop()" been called? + */ + if (p->break_loop) { /* - * Has "pcap_breakloop()" been called? + * Yes - clear the flag that indicates that + * it has, and return -2 to indicate that + * we were told to break out of the loop. */ - if (p->break_loop) { - /* - * Yes - clear the flag that indicates that - * it has, and return -2 to indicate that - * we were told to break out of the loop. - */ - p->break_loop = 0; - return -2; - } + p->break_loop = 0; + return -2; + } - p->md.dag_mem_top = dag_offset(p->fd, &(p->md.dag_mem_bottom), flags); - if (nonblocking && (p->md.dag_mem_top - p->md.dag_mem_bottom < dag_record_size)) - { - /* Pcap is configured to process only available packets, and there aren't any. */ - return 0; - } +#ifdef HAVE_DAG_STREAMS_API + /* dag_advance_stream() will block (unless nonblock is called) + * until 64kB of data has accumulated. + * If to_ms is set, it will timeout before 64kB has accumulated. + * We wait for 64kB because processing a few packets at a time + * can cause problems at high packet rates (>200kpps) due + * to inefficiencies. + * This does mean if to_ms is not specified the capture may 'hang' + * for long periods if the data rate is extremely slow (<64kB/sec) + * If non-block is specified it will return immediately. The user + * is then responsible for efficiency. + */ + p->md.dag_mem_top = dag_advance_stream(p->fd, p->md.dag_stream, (void**)&(p->md.dag_mem_bottom)); +#else + /* dag_offset does not support timeouts */ + p->md.dag_mem_top = dag_offset(p->fd, &(p->md.dag_mem_bottom), flags); +#endif /* HAVE_DAG_STREAMS_API */ + + if (nonblocking && (p->md.dag_mem_top - p->md.dag_mem_bottom < dag_record_size)) + { + /* Pcap is configured to process only available packets, and there aren't any, return immediately. */ + return 0; + } + + if(!nonblocking && + p->md.dag_timeout && + (p->md.dag_mem_top - p->md.dag_mem_bottom < dag_record_size)) + { + /* Blocking mode, but timeout set and no data has arrived, return anyway.*/ + return 0; } + + } - /* Process the packets. */ - while (p->md.dag_mem_top - p->md.dag_mem_bottom >= dag_record_size) { + /* Process the packets. */ + while (p->md.dag_mem_top - p->md.dag_mem_bottom >= dag_record_size) { - unsigned short packet_len = 0; - int caplen = 0; - struct pcap_pkthdr pcap_header; + unsigned short packet_len = 0; + int caplen = 0; + struct pcap_pkthdr pcap_header; - dag_record_t *header = (dag_record_t *)(p->md.dag_mem_base + p->md.dag_mem_bottom); - u_char *dp = ((u_char *)header) + dag_record_size; - unsigned short rlen; +#ifdef HAVE_DAG_STREAMS_API + dag_record_t *header = (dag_record_t *)(p->md.dag_mem_bottom); +#else + dag_record_t *header = (dag_record_t *)(p->md.dag_mem_base + p->md.dag_mem_bottom); +#endif /* HAVE_DAG_STREAMS_API */ + + u_char *dp = ((u_char *)header) + dag_record_size; + unsigned short rlen; + /* + * Has "pcap_breakloop()" been called? + */ + if (p->break_loop) { /* - * Has "pcap_breakloop()" been called? + * Yes - clear the flag that indicates that + * it has, and return -2 to indicate that + * we were told to break out of the loop. */ - if (p->break_loop) { - /* - * Yes - clear the flag that indicates that - * it has, and return -2 to indicate that - * we were told to break out of the loop. - */ - p->break_loop = 0; - return -2; - } + p->break_loop = 0; + return -2; + } - rlen = ntohs(header->rlen); - if (rlen < dag_record_size) - { - strncpy(p->errbuf, "dag_read: record too small", PCAP_ERRBUF_SIZE); - return -1; + rlen = ntohs(header->rlen); + if (rlen < dag_record_size) + { + strncpy(p->errbuf, "dag_read: record too small", PCAP_ERRBUF_SIZE); + return -1; + } + p->md.dag_mem_bottom += rlen; + + switch(header->type) { + case TYPE_AAL5: + case TYPE_ATM: +#ifdef TYPE_MC_ATM + case TYPE_MC_ATM: + if (header->type == TYPE_MC_ATM) { + caplen = packet_len = ATM_CELL_SIZE; + dp+=4; } - p->md.dag_mem_bottom += rlen; - - switch(header->type) { - case TYPE_AAL5: - case TYPE_ATM: - if (header->type == TYPE_AAL5) { - packet_len = ntohs(header->wlen); - caplen = rlen - dag_record_size; - } else { - caplen = packet_len = ATM_CELL_SIZE; - } - if (p->linktype == DLT_SUNATM) { - struct sunatm_hdr *sunatm = (struct sunatm_hdr *)dp; - unsigned long rawatm; +#endif +#ifdef TYPE_MC_AAL5 + case TYPE_MC_AAL5: + if (header->type == TYPE_MC_AAL5) { + packet_len = ntohs(header->wlen); + caplen = rlen - dag_record_size - 4; + dp+=4; + } +#endif + if (header->type == TYPE_AAL5) { + packet_len = ntohs(header->wlen); + caplen = rlen - dag_record_size; + } else if(header->type == TYPE_ATM) { + caplen = packet_len = ATM_CELL_SIZE; + } + if (p->linktype == DLT_SUNATM) { + struct sunatm_hdr *sunatm = (struct sunatm_hdr *)dp; + unsigned long rawatm; - rawatm = ntohl(*((unsigned long *)dp)); - sunatm->vci = htons((rawatm >> 4) & 0xffff); - sunatm->vpi = (rawatm >> 20) & 0x00ff; - sunatm->flags = ((header->flags.iface & 1) ? 0x80 : 0x00) | - ((sunatm->vpi == 0 && sunatm->vci == htons(5)) ? 6 : - ((sunatm->vpi == 0 && sunatm->vci == htons(16)) ? 5 : - ((dp[ATM_HDR_SIZE] == 0xaa && - dp[ATM_HDR_SIZE+1] == 0xaa && - dp[ATM_HDR_SIZE+2] == 0x03) ? 2 : 1))); - - } else { - packet_len -= ATM_HDR_SIZE; - caplen -= ATM_HDR_SIZE; - dp += ATM_HDR_SIZE; - } - break; - - case TYPE_ETH: - packet_len = ntohs(header->wlen); - packet_len -= (p->md.dag_fcs_bits >> 3); - caplen = rlen - dag_record_size - 2; - if (caplen > packet_len) { - caplen = packet_len; - } - dp += 2; - break; + rawatm = ntohl(*((unsigned long *)dp)); + sunatm->vci = htons((rawatm >> 4) & 0xffff); + sunatm->vpi = (rawatm >> 20) & 0x00ff; + sunatm->flags = ((header->flags.iface & 1) ? 0x80 : 0x00) | + ((sunatm->vpi == 0 && sunatm->vci == htons(5)) ? 6 : + ((sunatm->vpi == 0 && sunatm->vci == htons(16)) ? 5 : + ((dp[ATM_HDR_SIZE] == 0xaa && + dp[ATM_HDR_SIZE+1] == 0xaa && + dp[ATM_HDR_SIZE+2] == 0x03) ? 2 : 1))); + + } else { + packet_len -= ATM_HDR_SIZE; + caplen -= ATM_HDR_SIZE; + dp += ATM_HDR_SIZE; + } + break; - case TYPE_HDLC_POS: - packet_len = ntohs(header->wlen); - packet_len -= (p->md.dag_fcs_bits >> 3); - caplen = rlen - dag_record_size; - if (caplen > packet_len) { - caplen = packet_len; - } - break; +#ifdef TYPE_COLOR_ETH + case TYPE_COLOR_ETH: +#endif + case TYPE_ETH: + packet_len = ntohs(header->wlen); + packet_len -= (p->md.dag_fcs_bits >> 3); + caplen = rlen - dag_record_size - 2; + if (caplen > packet_len) { + caplen = packet_len; + } + dp += 2; + break; +#ifdef TYPE_COLOR_HDLC_POS + case TYPE_COLOR_HDLC_POS: +#endif + case TYPE_HDLC_POS: + packet_len = ntohs(header->wlen); + packet_len -= (p->md.dag_fcs_bits >> 3); + caplen = rlen - dag_record_size; + if (caplen > packet_len) { + caplen = packet_len; } + break; +#ifdef TYPE_MC_HDLC + case TYPE_MC_HDLC: + packet_len = ntohs(header->wlen); + packet_len -= (p->md.dag_fcs_bits >> 3); + caplen = rlen - dag_record_size - 4; + if (caplen > packet_len) { + caplen = packet_len; + } + dp += 4; + break; +#endif + } - if (caplen > p->snapshot) - caplen = p->snapshot; - - /* Count lost packets. */ + if (caplen > p->snapshot) + caplen = p->snapshot; + + /* Count lost packets. */ + switch(header->type) { +#ifdef TYPE_COLOR_HDLC_POS + /* in this type the color value overwrites the lctr */ + case TYPE_COLOR_HDLC_POS: + break; +#endif +#ifdef TYPE_COLOR_ETH + /* in this type the color value overwrites the lctr */ + case TYPE_COLOR_ETH: + break; +#endif + default: if (header->lctr) { if (p->md.stat.ps_drop > (UINT_MAX - ntohs(header->lctr))) { p->md.stat.ps_drop = UINT_MAX; @@ -311,54 +385,49 @@ dag_read(pcap_t *p, int cnt, pcap_handler callback, u_char *user) p->md.stat.ps_drop += ntohs(header->lctr); } } + } - /* Run the packet filter if there is one. */ - if ((p->fcode.bf_insns == NULL) || bpf_filter(p->fcode.bf_insns, dp, packet_len, caplen)) { + /* Run the packet filter if there is one. */ + if ((p->fcode.bf_insns == NULL) || bpf_filter(p->fcode.bf_insns, dp, packet_len, caplen)) { - /* convert between timestamp formats */ - register unsigned long long ts; + /* convert between timestamp formats */ + register unsigned long long ts; - if (IS_BIGENDIAN()) { - ts = SWAP_TS(header->ts); - } else { - ts = header->ts; - } + if (IS_BIGENDIAN()) { + ts = SWAP_TS(header->ts); + } else { + ts = header->ts; + } - pcap_header.ts.tv_sec = ts >> 32; - ts = (ts & 0xffffffffULL) * 1000000; - ts += 0x80000000; /* rounding */ - pcap_header.ts.tv_usec = ts >> 32; - if (pcap_header.ts.tv_usec >= 1000000) { - pcap_header.ts.tv_usec -= 1000000; - pcap_header.ts.tv_sec++; - } + pcap_header.ts.tv_sec = ts >> 32; + ts = (ts & 0xffffffffULL) * 1000000; + ts += 0x80000000; /* rounding */ + pcap_header.ts.tv_usec = ts >> 32; + if (pcap_header.ts.tv_usec >= 1000000) { + pcap_header.ts.tv_usec -= 1000000; + pcap_header.ts.tv_sec++; + } - /* Fill in our own header data */ - pcap_header.caplen = caplen; - pcap_header.len = packet_len; + /* Fill in our own header data */ + pcap_header.caplen = caplen; + pcap_header.len = packet_len; - /* Count the packet. */ - p->md.stat.ps_recv++; + /* Count the packet. */ + p->md.stat.ps_recv++; - /* Call the user supplied callback function */ - callback(user, &pcap_header, dp); + /* Call the user supplied callback function */ + callback(user, &pcap_header, dp); - /* Only count packets that pass the filter, for consistency with standard Linux behaviour. */ - processed++; - if (processed == cnt) - { - /* Reached the user-specified limit. */ - return cnt; - } + /* Only count packets that pass the filter, for consistency with standard Linux behaviour. */ + processed++; + if (processed == cnt) + { + /* Reached the user-specified limit. */ + return cnt; } } - - if (nonblocking || processed) - { - return processed; - } } - + return processed; } @@ -386,7 +455,13 @@ dag_open_live(const char *device, int snaplen, int promisc, int to_ms, char *ebu char *s; int n; daginf_t* daginf; - + char * newDev; +#ifdef HAVE_DAG_STREAMS_API + uint32_t mindata; + struct timeval maxwait; + struct timeval poll; +#endif + if (device == NULL) { snprintf(ebuf, PCAP_ERRBUF_SIZE, "device is NULL: %s", pcap_strerror(errno)); return NULL; @@ -403,8 +478,23 @@ dag_open_live(const char *device, int snaplen, int promisc, int to_ms, char *ebu memset(handle, 0, sizeof(*handle)); + newDev = (char *)malloc(strlen(device) + 16); + +#ifdef HAVE_DAG_STREAMS_API + + /* Parse input name to get dag device and stream number if provided */ + if (dag_parse_name(device, newDev, strlen(device) + 16, &handle->md.dag_stream) < 0) { + snprintf(ebuf, PCAP_ERRBUF_SIZE, "dag_parse_name: %s\n", pcap_strerror(errno)); + goto fail; + } + device = newDev; + + if (handle->md.dag_stream%2) { + snprintf(ebuf, PCAP_ERRBUF_SIZE, "dag_parse_name: tx (even numbered) streams not supported for capture\n"); + goto fail; + } +#else if (strstr(device, "/dev") == NULL) { - char * newDev = (char *)malloc(strlen(device) + 6); newDev[0] = '\0'; strcat(newDev, "/dev/"); strcat(newDev,device); @@ -417,6 +507,7 @@ dag_open_live(const char *device, int snaplen, int promisc, int to_ms, char *ebu snprintf(ebuf, PCAP_ERRBUF_SIZE, "str_dup: %s\n", pcap_strerror(errno)); goto fail; } +#endif /* HAVE_DAG_STREAMS_API */ /* setup device parameters */ if((handle->fd = dag_open((char *)device)) < 0) { @@ -424,6 +515,48 @@ dag_open_live(const char *device, int snaplen, int promisc, int to_ms, char *ebu goto fail; } +#ifdef HAVE_DAG_STREAMS_API + /* Open requested stream. Can fail if already locked or on error */ + if (dag_attach_stream(handle->fd, handle->md.dag_stream, 0, 0) < 0) { + snprintf(ebuf, PCAP_ERRBUF_SIZE, "dag_attach_stream: %s\n", pcap_strerror(errno)); + goto fail; + } + + /* Set up default poll parameters for stream + * Can be overridden by pcap_set_nonblock() + */ + if (dag_get_stream_poll(handle->fd, handle->md.dag_stream, + &mindata, &maxwait, &poll) < 0) { + snprintf(ebuf, PCAP_ERRBUF_SIZE, "dag_get_stream_poll: %s\n", pcap_strerror(errno)); + goto fail; + } + + /* Amount of data to collect in Bytes before calling callbacks. + * Important for efficiency, but can introduce latency + * at low packet rates if to_ms not set! + */ + mindata = 65536; + + /* Obey to_ms if supplied. This is a good idea! + * Recommend 10-100ms. Calls will time out even if no data arrived. + */ + maxwait.tv_sec = to_ms/1000; + maxwait.tv_usec = (to_ms%1000) * 1000; + + if (dag_set_stream_poll(handle->fd, handle->md.dag_stream, + mindata, &maxwait, &poll) < 0) { + snprintf(ebuf, PCAP_ERRBUF_SIZE, "dag_set_stream_poll: %s\n", pcap_strerror(errno)); + goto fail; + } + +#else + if((handle->md.dag_mem_base = dag_mmap(handle->fd)) == MAP_FAILED) { + snprintf(ebuf, PCAP_ERRBUF_SIZE,"dag_mmap %s: %s\n", device, pcap_strerror(errno)); + goto fail; + } + +#endif /* HAVE_DAG_STREAMS_API */ + /* set the card snap length to the specified snaplen parameter */ if (snaplen == 0 || snaplen > MAX_DAG_SNAPLEN) { snaplen = MAX_DAG_SNAPLEN; @@ -437,16 +570,18 @@ dag_open_live(const char *device, int snaplen, int promisc, int to_ms, char *ebu snprintf(ebuf, PCAP_ERRBUF_SIZE,"dag_configure %s: %s\n", device, pcap_strerror(errno)); goto fail; } - - if((handle->md.dag_mem_base = dag_mmap(handle->fd)) == MAP_FAILED) { - snprintf(ebuf, PCAP_ERRBUF_SIZE,"dag_mmap %s: %s\n", device, pcap_strerror(errno)); + +#ifdef HAVE_DAG_STREAMS_API + if(dag_start_stream(handle->fd, handle->md.dag_stream) < 0) { + snprintf(ebuf, PCAP_ERRBUF_SIZE, "dag_start_stream %s: %s\n", device, pcap_strerror(errno)); goto fail; } - +#else if(dag_start(handle->fd) < 0) { snprintf(ebuf, PCAP_ERRBUF_SIZE, "dag_start %s: %s\n", device, pcap_strerror(errno)); goto fail; } +#endif /* HAVE_DAG_STREAMS_API */ /* * Important! You have to ensure bottom is properly @@ -477,7 +612,7 @@ dag_open_live(const char *device, int snaplen, int promisc, int to_ms, char *ebu } handle->snapshot = snaplen; - /*handle->md.timeout = to_ms; */ + handle->md.dag_timeout = to_ms; handle->linktype = -1; if (dag_get_datalink(handle) < 0) { @@ -493,12 +628,13 @@ dag_open_live(const char *device, int snaplen, int promisc, int to_ms, char *ebu } /* - * "select()" and "poll()" don't (yet) work on DAG device descriptors. + * "select()" and "poll()" don't work on DAG device descriptors. */ handle->selectable_fd = -1; #ifdef linux handle->md.device = (char *)device; + handle->md.timeout = to_ms; #else free((char *)device); device = NULL; @@ -517,8 +653,8 @@ dag_open_live(const char *device, int snaplen, int promisc, int to_ms, char *ebu return handle; fail: - if (device != NULL) { - free((char *)device); + if (newDev != NULL) { + free((char *)newDev); } if (handle != NULL) { /* @@ -547,97 +683,42 @@ dag_stats(pcap_t *p, struct pcap_stat *ps) { } /* - * Get from "/proc/dag" all interfaces listed there; if they're - * already in the list of interfaces we have, that won't add another - * instance, but if they're not, that'll add them. - * - * We don't bother getting any addresses for them. - * - * We also don't fail if we couldn't open "/proc/dag"; we just leave - * the list of interfaces as is. + * Simply submit all possible dag names as candidates. + * pcap_add_if() internally tests each candidate with pcap_open_live(), + * so any non-existent devices are dropped. + * For 2.5 try all rx stream names as well. */ int dag_platform_finddevs(pcap_if_t **devlistp, char *errbuf) { - FILE *proc_dag_f; - char linebuf[512]; - int linenum; - unsigned char *p; - char name[512]; /* XXX - pick a size */ - char *q; + char name[12]; /* XXX - pick a size */ int ret = 0; + int c; - /* Quick exit if /proc/dag not readable */ - proc_dag_f = fopen("/proc/dag", "r"); - if (proc_dag_f == NULL) - { - int i; - char dev[16] = "dagx"; - - for (i = '0'; ret == 0 && i <= '9'; i++) { - dev[3] = i; - if (pcap_add_if(devlistp, dev, 0, NULL, errbuf) == -1) { - /* - * Failure. - */ - ret = -1; - } - } - - return (ret); - } - - for (linenum = 1; fgets(linebuf, sizeof linebuf, proc_dag_f) != NULL; linenum++) { - - /* - * Skip the first two lines - they're headers. - */ - if (linenum <= 2) - continue; - - p = &linebuf[0]; - - if (*p == '\0' || *p == '\n' || *p != 'D') - continue; /* not a Dag line */ - - /* - * Get the interface name. - */ - q = &name[0]; - while (*p != '\0' && *p != ':') { - if (*p != ' ') - *q++ = tolower(*p++); - else - p++; - } - *q = '\0'; - - /* - * Add an entry for this interface, with no addresses. - */ - p[strlen(p) - 1] = '\0'; /* get rid of \n */ - if (pcap_add_if(devlistp, name, 0, strdup(p + 2), errbuf) == -1) { + /* Try all the DAGs 0-9 */ + for (c = 0; c < 9; c++) { + snprintf(name, 12, "dag%d", c); + if (pcap_add_if(devlistp, name, 0, NULL, errbuf) == -1) { /* * Failure. */ ret = -1; - break; } - } - if (ret != -1) { - /* - * Well, we didn't fail for any other reason; did we - * fail due to an error reading the file? - */ - if (ferror(proc_dag_f)) { - (void)snprintf(errbuf, PCAP_ERRBUF_SIZE, - "Error reading /proc/dag: %s", - pcap_strerror(errno)); - ret = -1; +#ifdef HAVE_DAG_STREAMS_API + { + int stream; + for(stream=0;stream<16;stream+=2) { + snprintf(name, 10, "dag%d:%d", c, stream); + if (pcap_add_if(devlistp, name, 0, NULL, errbuf) == -1) { + /* + * Failure. + */ + ret = -1; + } + } } +#endif /* HAVE_DAG_STREAMS_API */ } - - (void)fclose(proc_dag_f); return (ret); } @@ -686,7 +767,34 @@ dag_setnonblock(pcap_t *p, int nonblock, char *errbuf) */ if (pcap_setnonblock_fd(p, nonblock, errbuf) < 0) return (-1); - +#ifdef HAVE_DAG_STREAMS_API + { + uint32_t mindata; + struct timeval maxwait; + struct timeval poll; + + if (dag_get_stream_poll(p->fd, p->md.dag_stream, + &mindata, &maxwait, &poll) < 0) { + snprintf(errbuf, PCAP_ERRBUF_SIZE, "dag_get_stream_poll: %s\n", pcap_strerror(errno)); + return -1; + } + + /* Amount of data to collect in Bytes before calling callbacks. + * Important for efficiency, but can introduce latency + * at low packet rates if to_ms not set! + */ + if(nonblock) + mindata = 0; + else + mindata = 65536; + + if (dag_set_stream_poll(p->fd, p->md.dag_stream, + mindata, &maxwait, &poll) < 0) { + snprintf(errbuf, PCAP_ERRBUF_SIZE, "dag_set_stream_poll: %s\n", pcap_strerror(errno)); + return -1; + } + } +#endif /* HAVE_DAG_STREAMS_API */ if (nonblock) { p->md.dag_offset_flags |= DAGF_NONBLOCK; } else { @@ -711,15 +819,18 @@ dag_get_datalink(pcap_t *p) switch(daglinktype) { case TYPE_HDLC_POS: + case TYPE_COLOR_HDLC_POS: if (p->dlt_list != NULL) { p->dlt_count = 2; p->dlt_list[0] = DLT_CHDLC; p->dlt_list[1] = DLT_PPP_SERIAL; + p->dlt_list[2] = DLT_FRELAY; } p->linktype = DLT_CHDLC; break; case TYPE_ETH: + case TYPE_COLOR_ETH: /* * This is (presumably) a real Ethernet capture; give it a * link-layer-type list with DLT_EN10MB and DLT_DOCSIS, so @@ -740,6 +851,8 @@ dag_get_datalink(pcap_t *p) case TYPE_AAL5: case TYPE_ATM: + case TYPE_MC_ATM: + case TYPE_MC_AAL5: if (p->dlt_list != NULL) { p->dlt_count = 2; p->dlt_list[0] = DLT_ATM_RFC1483; @@ -748,6 +861,18 @@ dag_get_datalink(pcap_t *p) p->linktype = DLT_ATM_RFC1483; break; + case TYPE_MC_HDLC: + if (p->dlt_list != NULL) { + p->dlt_count = 2; + p->dlt_list[0] = DLT_CHDLC; + p->dlt_list[1] = DLT_PPP_SERIAL; + p->dlt_list[2] = DLT_FRELAY; + p->dlt_list[3] = DLT_MTP2; + p->dlt_list[4] = DLT_MTP3; + p->dlt_list[5] = DLT_SCCP; + } + p->linktype = DLT_CHDLC; + break; case TYPE_LEGACY: p->linktype = DLT_NULL; diff --git a/pcap-dag.h b/pcap-dag.h index 440311cd..e3a90f2c 100644 --- a/pcap-dag.h +++ b/pcap-dag.h @@ -7,8 +7,8 @@ * * Author: Richard Littin, Sean Irvine ({richard,sean}@reeltwo.com) * - * @(#) $Header: /tcpdump/master/libpcap/pcap-dag.h,v 1.3 2003-07-25 05:32:03 guy Exp $ (LBL) + * @(#) $Header: /tcpdump/master/libpcap/pcap-dag.h,v 1.3.4.1 2005-07-07 06:56:04 guy Exp $ (LBL) */ pcap_t *dag_open_live(const char *device, int snaplen, int promisc, int to_ms, char *ebuf); - +int dag_platform_finddevs(pcap_if_t **devlistp, char *errbuf); diff --git a/pcap-int.h b/pcap-int.h index 5cfa7cec..e62d74f1 100644 --- a/pcap-int.h +++ b/pcap-int.h @@ -30,7 +30,7 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * @(#) $Header: /tcpdump/master/libpcap/pcap-int.h,v 1.68.2.5 2005-07-07 02:04:33 guy Exp $ (LBL) + * @(#) $Header: /tcpdump/master/libpcap/pcap-int.h,v 1.68.2.6 2005-07-07 06:56:04 guy Exp $ (LBL) */ #ifndef pcap_int_h @@ -91,12 +91,21 @@ struct pcap_md { #endif #ifdef HAVE_DAG_API +#ifdef HAVE_DAG_STREAMS_API + u_char *dag_mem_bottom; /* DAG card current memory bottom pointer */ + u_char *dag_mem_top; /* DAG card current memory top pointer */ +#else void *dag_mem_base; /* DAG card memory base address */ - u_int dag_mem_bottom; /* DAG card current memory bottom pointer */ - u_int dag_mem_top; /* DAG card current memory top pointer */ + u_int dag_mem_bottom; /* DAG card current memory bottom offset */ + u_int dag_mem_top; /* DAG card current memory top offset */ +#endif /* HAVE_DAG_STREAMS_API */ int dag_fcs_bits; /* Number of checksum bits from link layer */ int dag_offset_flags; /* Flags to pass to dag_offset(). */ -#endif + int dag_stream; /* DAG stream number */ + int dag_timeout; /* timeout specified to pcap_open_live. + * Same as in linux above, introduce + * generally? */ +#endif /* HAVE_DAG_API */ }; /*