diff options
Diffstat (limited to 'contrib/libpcap/pcap-dag.c')
-rw-r--r-- | contrib/libpcap/pcap-dag.c | 197 |
1 files changed, 123 insertions, 74 deletions
diff --git a/contrib/libpcap/pcap-dag.c b/contrib/libpcap/pcap-dag.c index 847a556..aaa3fae 100644 --- a/contrib/libpcap/pcap-dag.c +++ b/contrib/libpcap/pcap-dag.c @@ -15,11 +15,6 @@ * Stephen Donnelly <support@endace.com> */ -#ifndef lint -static const char rcsid[] _U_ = - "@(#) $Header: /tcpdump/master/libpcap/pcap-dag.c,v 1.39 2008-04-14 20:40:58 guy Exp $ (LBL)"; -#endif - #ifdef HAVE_CONFIG_H #include "config.h" #endif @@ -50,9 +45,12 @@ struct rtentry; /* declarations in <net/if.h> */ /* * DAG devices have names beginning with "dag", followed by a number - * from 0 to MAXDAG. + * from 0 to DAG_MAX_BOARDS, then optionally a colon and a stream number + * from 0 to DAG_STREAM_MAX. */ -#define MAXDAG 31 +#ifndef DAG_MAX_BOARDS +#define DAG_MAX_BOARDS 32 +#endif #define ATM_CELL_SIZE 52 #define ATM_HDR_SIZE 4 @@ -76,6 +74,27 @@ struct sunatm_hdr { unsigned short vci; /* VCI */ }; +/* + * Private data for capturing on DAG devices. + */ +struct pcap_dag { + struct pcap_stat stat; +#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 /* HAVE_DAG_STREAMS_API */ + void *dag_mem_base; /* DAG card memory base address */ + 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(). */ + int dag_stream; /* DAG stream number */ + int dag_timeout; /* timeout specified to pcap_open_live. + * Same as in linux above, introduce + * generally? */ +}; + typedef struct pcap_dag_node { struct pcap_dag_node *next; pcap_t *p; @@ -124,13 +143,15 @@ delete_pcap_dag(pcap_t *p) static void dag_platform_cleanup(pcap_t *p) { - + struct pcap_dag *pd; + if (p != NULL) { + pd = p->priv; #ifdef HAVE_DAG_STREAMS_API - if(dag_stop_stream(p->fd, p->md.dag_stream) < 0) + if(dag_stop_stream(p->fd, pd->dag_stream) < 0) fprintf(stderr,"dag_stop_stream: %s\n", strerror(errno)); - if(dag_detach_stream(p->fd, p->md.dag_stream) < 0) + if(dag_detach_stream(p->fd, pd->dag_stream) < 0) fprintf(stderr,"dag_detach_stream: %s\n", strerror(errno)); #else if(dag_stop(p->fd) < 0) @@ -202,7 +223,7 @@ dag_erf_ext_header_count(uint8_t * erf, size_t len) do { /* sanity check we have enough bytes */ - if ( len <= (24 + (hdr_num * 8)) ) + if ( len < (24 + (hdr_num * 8)) ) return hdr_num; /* get the header type */ @@ -222,13 +243,14 @@ dag_erf_ext_header_count(uint8_t * erf, size_t len) static int dag_read(pcap_t *p, int cnt, pcap_handler callback, u_char *user) { + struct pcap_dag *pd = p->priv; unsigned int processed = 0; - int flags = p->md.dag_offset_flags; + int flags = pd->dag_offset_flags; unsigned int nonblocking = flags & DAGF_NONBLOCK; unsigned int num_ext_hdr = 0; /* Get the next bufferful of packets (if necessary). */ - while (p->md.dag_mem_top - p->md.dag_mem_bottom < dag_record_size) { + while (pd->dag_mem_top - pd->dag_mem_bottom < dag_record_size) { /* * Has "pcap_breakloop()" been called? @@ -255,23 +277,23 @@ dag_read(pcap_t *p, int cnt, pcap_handler callback, u_char *user) * If non-block is specified it will return immediately. The user * is then responsible for efficiency. */ - if ( NULL == (p->md.dag_mem_top = dag_advance_stream(p->fd, p->md.dag_stream, &(p->md.dag_mem_bottom))) ) { + if ( NULL == (pd->dag_mem_top = dag_advance_stream(p->fd, pd->dag_stream, &(pd->dag_mem_bottom))) ) { return -1; } #else /* dag_offset does not support timeouts */ - p->md.dag_mem_top = dag_offset(p->fd, &(p->md.dag_mem_bottom), flags); + pd->dag_mem_top = dag_offset(p->fd, &(pd->dag_mem_bottom), flags); #endif /* HAVE_DAG_STREAMS_API */ - if (nonblocking && (p->md.dag_mem_top - p->md.dag_mem_bottom < dag_record_size)) + if (nonblocking && (pd->dag_mem_top - pd->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)) + pd->dag_timeout && + (pd->dag_mem_top - pd->dag_mem_bottom < dag_record_size)) { /* Blocking mode, but timeout set and no data has arrived, return anyway.*/ return 0; @@ -280,16 +302,16 @@ dag_read(pcap_t *p, int cnt, pcap_handler callback, u_char *user) } /* Process the packets. */ - while (p->md.dag_mem_top - p->md.dag_mem_bottom >= dag_record_size) { + while (pd->dag_mem_top - pd->dag_mem_bottom >= dag_record_size) { unsigned short packet_len = 0; int caplen = 0; struct pcap_pkthdr pcap_header; #ifdef HAVE_DAG_STREAMS_API - dag_record_t *header = (dag_record_t *)(p->md.dag_mem_bottom); + dag_record_t *header = (dag_record_t *)(pd->dag_mem_bottom); #else - dag_record_t *header = (dag_record_t *)(p->md.dag_mem_base + p->md.dag_mem_bottom); + dag_record_t *header = (dag_record_t *)(pd->dag_mem_base + pd->dag_mem_bottom); #endif /* HAVE_DAG_STREAMS_API */ u_char *dp = ((u_char *)header); /* + dag_record_size; */ @@ -314,7 +336,7 @@ dag_read(pcap_t *p, int cnt, pcap_handler callback, u_char *user) strncpy(p->errbuf, "dag_read: record too small", PCAP_ERRBUF_SIZE); return -1; } - p->md.dag_mem_bottom += rlen; + pd->dag_mem_bottom += rlen; /* Count lost packets. */ switch((header->type & 0x7f)) { @@ -330,10 +352,10 @@ dag_read(pcap_t *p, int cnt, pcap_handler callback, u_char *user) default: if (header->lctr) { - if (p->md.stat.ps_drop > (UINT_MAX - ntohs(header->lctr))) { - p->md.stat.ps_drop = UINT_MAX; + if (pd->stat.ps_drop > (UINT_MAX - ntohs(header->lctr))) { + pd->stat.ps_drop = UINT_MAX; } else { - p->md.stat.ps_drop += ntohs(header->lctr); + pd->stat.ps_drop += ntohs(header->lctr); } } } @@ -441,7 +463,7 @@ dag_read(pcap_t *p, int cnt, pcap_handler callback, u_char *user) case TYPE_COLOR_ETH: case TYPE_ETH: packet_len = ntohs(header->wlen); - packet_len -= (p->md.dag_fcs_bits >> 3); + packet_len -= (pd->dag_fcs_bits >> 3); caplen = rlen - dag_record_size - 2; if (caplen > packet_len) { caplen = packet_len; @@ -454,7 +476,7 @@ dag_read(pcap_t *p, int cnt, pcap_handler callback, u_char *user) case TYPE_COLOR_HDLC_POS: case TYPE_HDLC_POS: packet_len = ntohs(header->wlen); - packet_len -= (p->md.dag_fcs_bits >> 3); + packet_len -= (pd->dag_fcs_bits >> 3); caplen = rlen - dag_record_size; if (caplen > packet_len) { caplen = packet_len; @@ -464,7 +486,7 @@ dag_read(pcap_t *p, int cnt, pcap_handler callback, u_char *user) case TYPE_COLOR_MC_HDLC_POS: case TYPE_MC_HDLC: packet_len = ntohs(header->wlen); - packet_len -= (p->md.dag_fcs_bits >> 3); + packet_len -= (pd->dag_fcs_bits >> 3); caplen = rlen - dag_record_size - 4; if (caplen > packet_len) { caplen = packet_len; @@ -545,14 +567,14 @@ dag_read(pcap_t *p, int cnt, pcap_handler callback, u_char *user) pcap_header.len = packet_len; /* Count the packet. */ - p->md.stat.ps_recv++; + pd->stat.ps_recv++; /* 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 && cnt > 0) + if (processed == cnt && !PACKET_COUNT_IS_UNLIMITED(cnt)) { /* Reached the user-specified limit. */ return cnt; @@ -584,6 +606,7 @@ dag_inject(pcap_t *p, const void *buf _U_, size_t size _U_) */ static int dag_activate(pcap_t* handle) { + struct pcap_dag *handlep = handle->priv; #if 0 char conf[30]; /* dag configure string */ #endif @@ -613,13 +636,13 @@ static int dag_activate(pcap_t* handle) } /* 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) { + if (dag_parse_name(device, newDev, strlen(device) + 16, &handlep->dag_stream) < 0) { snprintf(handle->errbuf, PCAP_ERRBUF_SIZE, "dag_parse_name: %s\n", pcap_strerror(errno)); goto fail; } device = newDev; - if (handle->md.dag_stream%2) { + if (handlep->dag_stream%2) { snprintf(handle->errbuf, PCAP_ERRBUF_SIZE, "dag_parse_name: tx (even numbered) streams not supported for capture\n"); goto fail; } @@ -644,7 +667,7 @@ static int dag_activate(pcap_t* handle) #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) { + if (dag_attach_stream(handle->fd, handlep->dag_stream, 0, 0) < 0) { snprintf(handle->errbuf, PCAP_ERRBUF_SIZE, "dag_attach_stream: %s\n", pcap_strerror(errno)); goto failclose; } @@ -652,32 +675,39 @@ static int dag_activate(pcap_t* handle) /* 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, + if (dag_get_stream_poll(handle->fd, handlep->dag_stream, &mindata, &maxwait, &poll) < 0) { snprintf(handle->errbuf, PCAP_ERRBUF_SIZE, "dag_get_stream_poll: %s\n", pcap_strerror(errno)); goto faildetach; } - /* 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; + if (handle->opt.immediate) { + /* Call callback immediately. + * XXX - is this the right way to handle this? + */ + mindata = 0; + } else { + /* 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 md.timeout (was to_ms) if supplied. This is a good idea! + /* Obey opt.timeout (was to_ms) if supplied. This is a good idea! * Recommend 10-100ms. Calls will time out even if no data arrived. */ - maxwait.tv_sec = handle->md.timeout/1000; - maxwait.tv_usec = (handle->md.timeout%1000) * 1000; + maxwait.tv_sec = handle->opt.timeout/1000; + maxwait.tv_usec = (handle->opt.timeout%1000) * 1000; - if (dag_set_stream_poll(handle->fd, handle->md.dag_stream, + if (dag_set_stream_poll(handle->fd, handlep->dag_stream, mindata, &maxwait, &poll) < 0) { snprintf(handle->errbuf, PCAP_ERRBUF_SIZE, "dag_set_stream_poll: %s\n", pcap_strerror(errno)); goto faildetach; } #else - if((handle->md.dag_mem_base = dag_mmap(handle->fd)) == MAP_FAILED) { + if((handlep->dag_mem_base = dag_mmap(handle->fd)) == MAP_FAILED) { snprintf(handle->errbuf, PCAP_ERRBUF_SIZE,"dag_mmap %s: %s\n", device, pcap_strerror(errno)); goto failclose; } @@ -707,7 +737,7 @@ static int dag_activate(pcap_t* handle) #endif #ifdef HAVE_DAG_STREAMS_API - if(dag_start_stream(handle->fd, handle->md.dag_stream) < 0) { + if(dag_start_stream(handle->fd, handlep->dag_stream) < 0) { snprintf(handle->errbuf, PCAP_ERRBUF_SIZE, "dag_start_stream %s: %s\n", device, pcap_strerror(errno)); goto faildetach; } @@ -723,8 +753,8 @@ static int dag_activate(pcap_t* handle) * initialized to zero on startup, it won't give you * a compiler warning if you make this mistake! */ - handle->md.dag_mem_bottom = 0; - handle->md.dag_mem_top = 0; + handlep->dag_mem_bottom = 0; + handlep->dag_mem_top = 0; /* * Find out how many FCS bits we should strip. @@ -733,7 +763,7 @@ static int dag_activate(pcap_t* handle) daginf = dag_info(handle->fd); if ((0x4200 == daginf->device_code) || (0x4230 == daginf->device_code)) { /* DAG 4.2S and 4.23S already strip the FCS. Stripping the final word again truncates the packet. */ - handle->md.dag_fcs_bits = 0; + handlep->dag_fcs_bits = 0; /* Note that no FCS will be supplied. */ handle->linktype_ext = LT_FCS_DATALINK_EXT(0); @@ -741,12 +771,12 @@ static int dag_activate(pcap_t* handle) /* * Start out assuming it's 32 bits. */ - handle->md.dag_fcs_bits = 32; + handlep->dag_fcs_bits = 32; /* Allow an environment variable to override. */ if ((s = getenv("ERF_FCS_BITS")) != NULL) { if ((n = atoi(s)) == 0 || n == 16 || n == 32) { - handle->md.dag_fcs_bits = n; + handlep->dag_fcs_bits = n; } else { snprintf(handle->errbuf, PCAP_ERRBUF_SIZE, "pcap_activate %s: bad ERF_FCS_BITS value (%d) in environment\n", device, n); @@ -760,14 +790,14 @@ static int dag_activate(pcap_t* handle) if ((s = getenv("ERF_DONT_STRIP_FCS")) != NULL) { /* Yes. Note the number of bytes that will be supplied. */ - handle->linktype_ext = LT_FCS_DATALINK_EXT(handle->md.dag_fcs_bits/16); + handle->linktype_ext = LT_FCS_DATALINK_EXT(handlep->dag_fcs_bits/16); /* And don't strip them. */ - handle->md.dag_fcs_bits = 0; + handlep->dag_fcs_bits = 0; } } - handle->md.dag_timeout = handle->md.timeout; + handlep->dag_timeout = handle->opt.timeout; handle->linktype = -1; if (dag_get_datalink(handle) < 0) @@ -798,19 +828,19 @@ static int dag_activate(pcap_t* handle) handle->setnonblock_op = dag_setnonblock; handle->stats_op = dag_stats; handle->cleanup_op = dag_platform_cleanup; - handle->md.stat.ps_drop = 0; - handle->md.stat.ps_recv = 0; - handle->md.stat.ps_ifdrop = 0; + handlep->stat.ps_drop = 0; + handlep->stat.ps_recv = 0; + handlep->stat.ps_ifdrop = 0; return 0; #ifdef HAVE_DAG_STREAMS_API failstop: - if (dag_stop_stream(handle->fd, handle->md.dag_stream) < 0) { + if (dag_stop_stream(handle->fd, handlep->dag_stream) < 0) { fprintf(stderr,"dag_stop_stream: %s\n", strerror(errno)); } faildetach: - if (dag_detach_stream(handle->fd, handle->md.dag_stream) < 0) + if (dag_detach_stream(handle->fd, handlep->dag_stream) < 0) fprintf(stderr,"dag_detach_stream: %s\n", strerror(errno)); #else failstop: @@ -838,6 +868,9 @@ pcap_t *dag_create(const char *device, char *ebuf, int *is_ours) char *cpend; long devnum; pcap_t *p; +#ifdef HAVE_DAG_STREAMS_API + long stream = 0; +#endif /* Does this look like a DAG device? */ cp = strrchr(device, '/'); @@ -849,24 +882,37 @@ pcap_t *dag_create(const char *device, char *ebuf, int *is_ours) *is_ours = 0; return NULL; } - /* Yes - is "dag" followed by a number from 0 to MAXDAG? */ + /* Yes - is "dag" followed by a number from 0 to DAG_MAX_BOARDS-1 */ cp += 3; devnum = strtol(cp, &cpend, 10); +#ifdef HAVE_DAG_STREAMS_API + if (*cpend == ':') { + /* Followed by a stream number. */ + stream = strtol(++cpend, &cpend, 10); + } +#endif if (cpend == cp || *cpend != '\0') { /* Not followed by a number. */ *is_ours = 0; return NULL; } - if (devnum < 0 || devnum > MAXDAG) { + if (devnum < 0 || devnum >= DAG_MAX_BOARDS) { /* Followed by a non-valid number. */ *is_ours = 0; return NULL; } +#ifdef HAVE_DAG_STREAMS_API + if (stream <0 || stream >= DAG_STREAM_MAX) { + /* Followed by a non-valid stream number. */ + *is_ours = 0; + return NULL; + } +#endif /* OK, it's probably ours. */ *is_ours = 1; - p = pcap_create_common(device, ebuf); + p = pcap_create_common(device, ebuf, sizeof (struct pcap_dag)); if (p == NULL) return NULL; @@ -876,13 +922,15 @@ pcap_t *dag_create(const char *device, char *ebuf, int *is_ours) static int dag_stats(pcap_t *p, struct pcap_stat *ps) { + struct pcap_dag *pd = p->priv; + /* This needs to be filled out correctly. Hopefully a dagapi call will provide all necessary information. */ - /*p->md.stat.ps_recv = 0;*/ - /*p->md.stat.ps_drop = 0;*/ + /*pd->stat.ps_recv = 0;*/ + /*pd->stat.ps_drop = 0;*/ - *ps = p->md.stat; + *ps = pd->stat; return 0; } @@ -906,8 +954,8 @@ dag_findalldevs(pcap_if_t **devlistp, char *errbuf) int dagstream; int dagfd; - /* Try all the DAGs 0-MAXDAG */ - for (c = 0; c <= MAXDAG; c++) { + /* Try all the DAGs 0-DAG_MAX_BOARDS */ + for (c = 0; c < DAG_MAX_BOARDS; c++) { snprintf(name, 12, "dag%d", c); if (-1 == dag_parse_name(name, dagname, DAGNAME_BUFSIZE, &dagstream)) { @@ -972,8 +1020,6 @@ dag_setfilter(pcap_t *p, struct bpf_program *fp) if (install_bpf_program(p, fp) < 0) return -1; - p->md.use_bpf = 0; - return (0); } @@ -988,11 +1034,13 @@ dag_set_datalink(pcap_t *p, int dlt) static int dag_setnonblock(pcap_t *p, int nonblock, char *errbuf) { + struct pcap_dag *pd = p->priv; + /* * Set non-blocking mode on the FD. * XXX - is that necessary? If not, don't bother calling it, * and have a "dag_getnonblock()" function that looks at - * "p->md.dag_offset_flags". + * "pd->dag_offset_flags". */ if (pcap_setnonblock_fd(p, nonblock, errbuf) < 0) return (-1); @@ -1002,7 +1050,7 @@ dag_setnonblock(pcap_t *p, int nonblock, char *errbuf) struct timeval maxwait; struct timeval poll; - if (dag_get_stream_poll(p->fd, p->md.dag_stream, + if (dag_get_stream_poll(p->fd, pd->dag_stream, &mindata, &maxwait, &poll) < 0) { snprintf(errbuf, PCAP_ERRBUF_SIZE, "dag_get_stream_poll: %s\n", pcap_strerror(errno)); return -1; @@ -1017,7 +1065,7 @@ dag_setnonblock(pcap_t *p, int nonblock, char *errbuf) else mindata = 65536; - if (dag_set_stream_poll(p->fd, p->md.dag_stream, + if (dag_set_stream_poll(p->fd, pd->dag_stream, mindata, &maxwait, &poll) < 0) { snprintf(errbuf, PCAP_ERRBUF_SIZE, "dag_set_stream_poll: %s\n", pcap_strerror(errno)); return -1; @@ -1025,9 +1073,9 @@ dag_setnonblock(pcap_t *p, int nonblock, char *errbuf) } #endif /* HAVE_DAG_STREAMS_API */ if (nonblock) { - p->md.dag_offset_flags |= DAGF_NONBLOCK; + pd->dag_offset_flags |= DAGF_NONBLOCK; } else { - p->md.dag_offset_flags &= ~DAGF_NONBLOCK; + pd->dag_offset_flags &= ~DAGF_NONBLOCK; } return (0); } @@ -1035,6 +1083,7 @@ dag_setnonblock(pcap_t *p, int nonblock, char *errbuf) static int dag_get_datalink(pcap_t *p) { + struct pcap_dag *pd = p->priv; int index=0, dlt_index=0; uint8_t types[255]; @@ -1049,7 +1098,7 @@ dag_get_datalink(pcap_t *p) #ifdef HAVE_DAG_GET_STREAM_ERF_TYPES /* Get list of possible ERF types for this card */ - if (dag_get_stream_erf_types(p->fd, p->md.dag_stream, types, 255) < 0) { + if (dag_get_stream_erf_types(p->fd, pd->dag_stream, types, 255) < 0) { snprintf(p->errbuf, sizeof(p->errbuf), "dag_get_stream_erf_types: %s", pcap_strerror(errno)); return (-1); } |