From: guy Date: Mon, 5 Jan 2004 18:18:54 +0000 (+0000) Subject: From Jesper Peterson: X-Git-Tag: libpcap-0.9.1~229 X-Git-Url: https://git.tcpdump.org/libpcap/commitdiff_plain/fab5c982f293d4ccc232c58bba062c43f7bdcd71 From Jesper Peterson: - don't auto-detect HDLC DLT on serial links, use "pcap_set_datalink()" to choose the link-layer header - for ATM, allow selecting SUNATM rather than the default RFC1483 with "pcap_set_datalink()" - reformat and otherwise clean up the code. --- diff --git a/pcap-dag.c b/pcap-dag.c index f245d1af..0aa82d4b 100644 --- a/pcap-dag.c +++ b/pcap-dag.c @@ -9,27 +9,13 @@ * is not defined then nothing is altered - the dag_ functions will be * called as required from their pcap-linux/bpf equivalents. * - * Author: Richard Littin, Sean Irvine ({richard,sean}@reeltwo.com) - * - * Modifications: - * 2003 May - Jesper Peterson - * Code shuffled around to suit fad-xxx.c structure - * Added atexit() handler to stop DAG if application is too lazy - * 2003 September - Koryn Grant - * Added support for nonblocking operation. - * Added support for processing more than a single packet in pcap_dispatch(). - * Fixed bug in loss counter code. - * Improved portability of loss counter code (e.g. use UINT_MAX instead of 0xffff). - * Removed unused local variables. - * Added required headers (ctype.h, limits.h, unistd.h, netinet/in.h). - * 2003 October - Koryn Grant - * Changed semantics to match those of standard pcap on linux. - * - packets rejected by the filter are not counted. + * Authors: Richard Littin, Sean Irvine ({richard,sean}@reeltwo.com) + * Modifications: Jesper Peterson, Koryn Grant */ #ifndef lint static const char rcsid[] _U_ = - "@(#) $Header: /tcpdump/master/libpcap/pcap-dag.c,v 1.15 2003-12-18 23:32:31 guy Exp $ (LBL)"; + "@(#) $Header: /tcpdump/master/libpcap/pcap-dag.c,v 1.16 2004-01-05 18:18:54 guy Exp $ (LBL)"; #endif #ifdef HAVE_CONFIG_H @@ -60,12 +46,20 @@ struct rtentry; /* declarations in */ #define MIN_DAG_SNAPLEN 12 #define MAX_DAG_SNAPLEN 2040 -#define ATM_SNAPLEN 48 +#define ATM_CELL_SIZE 52 +#define ATM_HDR_SIZE 4 + +/* SunATM pseudo header */ +struct sunatm_hdr { + unsigned char flags; /* destination and traffic type */ + unsigned char vpi; /* VPI */ + unsigned short vci; /* VCI */ +}; typedef struct pcap_dag_node { - struct pcap_dag_node *next; - pcap_t *p; - pid_t pid; + struct pcap_dag_node *next; + pcap_t *p; + pid_t pid; } pcap_dag_node_t; static pcap_dag_node_t *pcap_dags = NULL; @@ -103,22 +97,22 @@ static int dag_set_datalink(pcap_t *p, int dlt); static int dag_get_datalink(pcap_t *p); static int dag_setnonblock(pcap_t *p, int nonblock, char *errbuf); -static void delete_pcap_dag(pcap_t *p) { - pcap_dag_node_t *curr = NULL, *prev = NULL; - - for (prev = NULL, curr = pcap_dags; - curr != NULL && curr->p != p; - prev = curr, curr = curr->next) { - /* empty */ - } - - if (curr != NULL && curr->p == p) { - if (prev != NULL) { - prev->next = curr->next; - } else { - pcap_dags = curr->next; - } - } +static void +delete_pcap_dag(pcap_t *p) +{ + pcap_dag_node_t *curr = NULL, *prev = NULL; + + for (prev = NULL, curr = pcap_dags; curr != NULL && curr->p != p; prev = curr, curr = curr->next) { + /* empty */ + } + + if (curr != NULL && curr->p == p) { + if (prev != NULL) { + prev->next = curr->next; + } else { + pcap_dags = curr->next; + } + } } /* @@ -126,58 +120,64 @@ static void delete_pcap_dag(pcap_t *p) { * in the pcap_t structure, and closes the file descriptor for the DAG card. */ -static void dag_platform_close(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)); - - free(p->md.device); - } + 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)); + + free(p->md.device); + } #else - if (p != NULL) { - if(dag_stop(p->fd) < 0) - fprintf(stderr,"dag_stop: %s\n", strerror(errno)); - if(dag_close(p->fd) < 0) - fprintf(stderr,"dag_close: %s\n", strerror(errno)); - } + if (p != NULL) { + if(dag_stop(p->fd) < 0) + fprintf(stderr,"dag_stop: %s\n", strerror(errno)); + if(dag_close(p->fd) < 0) + fprintf(stderr,"dag_close: %s\n", strerror(errno)); + } #endif - delete_pcap_dag(p); - /* Note: don't need to call close(p->fd) here as dag_close(p->fd) does this. */ + delete_pcap_dag(p); + /* Note: don't need to call close(p->fd) here as dag_close(p->fd) does this. */ } -static void atexit_handler(void) { - while (pcap_dags != NULL) { - if (pcap_dags->pid == getpid()) { - dag_platform_close(pcap_dags->p); - } else { - delete_pcap_dag(pcap_dags->p); - } - } +static void +atexit_handler(void) +{ + while (pcap_dags != NULL) { + if (pcap_dags->pid == getpid()) { + dag_platform_close(pcap_dags->p); + } else { + delete_pcap_dag(pcap_dags->p); + } + } } -static int new_pcap_dag(pcap_t *p) { - pcap_dag_node_t *node = NULL; +static int +new_pcap_dag(pcap_t *p) +{ + pcap_dag_node_t *node = NULL; - if ((node = malloc(sizeof(pcap_dag_node_t))) == NULL) { - return -1; - } + if ((node = malloc(sizeof(pcap_dag_node_t))) == NULL) { + return -1; + } - if (!atexit_handler_installed) { - atexit(atexit_handler); - atexit_handler_installed = 1; - } + if (!atexit_handler_installed) { + atexit(atexit_handler); + atexit_handler_installed = 1; + } - node->next = pcap_dags; - node->p = p; - node->pid = getpid(); + node->next = pcap_dags; + node->p = p; + node->pid = getpid(); - pcap_dags = node; + pcap_dags = node; - return 0; + return 0; } /* @@ -185,7 +185,9 @@ static int new_pcap_dag(pcap_t *p) { * for each of them. Returns the number of packets handled, -1 if an * error occured, or -2 if we were told to break out of the loop. */ -static int dag_read(pcap_t *p, int cnt, pcap_handler callback, u_char *user) { +static int +dag_read(pcap_t *p, int cnt, pcap_handler callback, u_char *user) +{ unsigned int processed = 0; int flags = p->md.dag_offset_flags; unsigned int nonblocking = flags & DAGF_NONBLOCK; @@ -215,7 +217,7 @@ static int dag_read(pcap_t *p, int cnt, pcap_handler callback, u_char *user) { return 0; } } - + /* Process the packets. */ while (p->md.dag_mem_top - p->md.dag_mem_bottom >= dag_record_size) { @@ -240,54 +242,74 @@ static int dag_read(pcap_t *p, int cnt, pcap_handler callback, u_char *user) { return -2; } - if (IS_BIGENDIAN()) - { + if (IS_BIGENDIAN()) { rlen = header->rlen; - } - else - { + } else { rlen = ntohs(header->rlen); } p->md.dag_mem_bottom += rlen; switch(header->type) { + case TYPE_AAL5: case TYPE_ATM: - packet_len = ATM_SNAPLEN; - caplen = ATM_SNAPLEN; - dp += 4; + if (header->type == TYPE_AAL5) { + if (IS_BIGENDIAN()) { + packet_len = header->wlen; + } else { + 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; + if (IS_BIGENDIAN()) { + rawatm = *((unsigned long *)dp); + sunatm->vci = (rawatm >> 4) & 0xffff; + } else { + 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 == 5) ? 6 : + ((sunatm->vpi == 0 && sunatm->vci == 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: - if (IS_BIGENDIAN()) - { + if (IS_BIGENDIAN()) { packet_len = header->wlen; - } - else - { + } else { packet_len = ntohs(header->wlen); } packet_len -= (p->md.dag_fcs_bits >> 3); caplen = rlen - dag_record_size - 2; - if (caplen > packet_len) - { + if (caplen > packet_len) { caplen = packet_len; } dp += 2; break; case TYPE_HDLC_POS: - if (IS_BIGENDIAN()) - { + if (IS_BIGENDIAN()) { packet_len = header->wlen; - } - else - { + } else { packet_len = ntohs(header->wlen); } packet_len -= (p->md.dag_fcs_bits >> 3); caplen = rlen - dag_record_size; - if (caplen > packet_len) - { + if (caplen > packet_len) { caplen = packet_len; } break; @@ -311,16 +333,13 @@ static int dag_read(pcap_t *p, int cnt, pcap_handler callback, u_char *user) { /* convert between timestamp formats */ register unsigned long long ts; - if (IS_BIGENDIAN()) - { + if (IS_BIGENDIAN()) { ts = SWAP_TS(header->ts); - } - else - { + } else { ts = header->ts; } - pcap_header.ts.tv_sec = ts >> 32; + pcap_header.ts.tv_sec = ts >> 32; ts = (ts & 0xffffffffULL) * 1000000; ts += 0x80000000; /* rounding */ pcap_header.ts.tv_usec = ts >> 32; @@ -332,13 +351,13 @@ static int dag_read(pcap_t *p, int cnt, pcap_handler callback, u_char *user) { /* Fill in our own header data */ pcap_header.caplen = caplen; pcap_header.len = packet_len; - + /* Count the packet. */ p->md.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) @@ -354,7 +373,7 @@ static int dag_read(pcap_t *p, int cnt, pcap_handler callback, u_char *user) { return processed; } } - + return processed; } @@ -366,157 +385,161 @@ static int dag_read(pcap_t *p, int cnt, pcap_handler callback, u_char *user) { * * See also pcap(3). */ -pcap_t *dag_open_live(const char *device, int snaplen, int promisc, int to_ms, char *ebuf) { - char conf[30]; /* dag configure string */ - pcap_t *handle; - char *s; - int n; - - if (device == NULL) { - snprintf(ebuf, PCAP_ERRBUF_SIZE, "device is NULL: %s", pcap_strerror(errno)); - return NULL; - } - /* Allocate a handle for this session. */ - - handle = malloc(sizeof(*handle)); - if (handle == NULL) { - snprintf(ebuf, PCAP_ERRBUF_SIZE, "malloc %s: %s", device, pcap_strerror(errno)); - return NULL; - } - - /* Initialize some components of the pcap structure. */ - - memset(handle, 0, sizeof(*handle)); - - if (strstr(device, "/dev") == NULL) { - char * newDev = (char *)malloc(strlen(device) + 6); - newDev[0] = '\0'; - strcat(newDev, "/dev/"); - strcat(newDev,device); - device = newDev; - } else { - device = strdup(device); - } - - if (device == NULL) { - snprintf(ebuf, PCAP_ERRBUF_SIZE, "str_dup: %s\n", pcap_strerror(errno)); - goto fail; - } - - /* setup device parameters */ - if((handle->fd = dag_open((char *)device)) < 0) { - snprintf(ebuf, PCAP_ERRBUF_SIZE, "dag_open %s: %s", device, pcap_strerror(errno)); - goto fail; - } - - /* set the card snap length to the specified snaplen parameter */ - if (snaplen == 0 || snaplen > MAX_DAG_SNAPLEN) { - snaplen = MAX_DAG_SNAPLEN; - } else if (snaplen < MIN_DAG_SNAPLEN) { - snaplen = MIN_DAG_SNAPLEN; - } - /* snap len has to be a multiple of 4 */ - snprintf(conf, 30, "varlen slen=%d", (snaplen + 3) & ~3); - - fprintf(stderr, "Configuring DAG with '%s'.\n", conf); - if(dag_configure(handle->fd, conf) < 0) { - 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)); - goto fail; - } - - if(dag_start(handle->fd) < 0) { - snprintf(ebuf, PCAP_ERRBUF_SIZE, "dag_start %s: %s\n", device, pcap_strerror(errno)); - goto fail; - } - - /* - * Important! You have to ensure bottom is properly - * 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; - - /* TODO: query the card */ - handle->md.dag_fcs_bits = 32; - if ((s = getenv("ERF_FCS_BITS")) != NULL) { - if ((n = atoi(s)) == 0 || n == 16|| n == 32) { - handle->md.dag_fcs_bits = n; - } else { - snprintf(ebuf, PCAP_ERRBUF_SIZE, - "pcap_open_live %s: bad ERF_FCS_BITS value (%d) in environment\n", device, n); - goto fail; - } - } - - handle->snapshot = snaplen; - /*handle->md.timeout = to_ms; */ - - if (dag_get_datalink(handle) < 0) { - snprintf(ebuf, PCAP_ERRBUF_SIZE, "dag_get_linktype %s: unknown linktype\n", device); - goto fail; - } - - handle->bufsize = 0; - - if (new_pcap_dag(handle) < 0) { - snprintf(ebuf, PCAP_ERRBUF_SIZE, "new_pcap_dag %s: %s\n", device, pcap_strerror(errno)); - goto fail; - } - - /* - * "select()" and "poll()" don't (yet) work on DAG device descriptors. - */ - handle->selectable_fd = -1; +pcap_t * +dag_open_live(const char *device, int snaplen, int promisc, int to_ms, char *ebuf) +{ + char conf[30]; /* dag configure string */ + pcap_t *handle; + char *s; + int n; + + if (device == NULL) { + snprintf(ebuf, PCAP_ERRBUF_SIZE, "device is NULL: %s", pcap_strerror(errno)); + return NULL; + } + /* Allocate a handle for this session. */ + + handle = malloc(sizeof(*handle)); + if (handle == NULL) { + snprintf(ebuf, PCAP_ERRBUF_SIZE, "malloc %s: %s", device, pcap_strerror(errno)); + return NULL; + } + + /* Initialize some components of the pcap structure. */ + + memset(handle, 0, sizeof(*handle)); + + if (strstr(device, "/dev") == NULL) { + char * newDev = (char *)malloc(strlen(device) + 6); + newDev[0] = '\0'; + strcat(newDev, "/dev/"); + strcat(newDev,device); + device = newDev; + } else { + device = strdup(device); + } + + if (device == NULL) { + snprintf(ebuf, PCAP_ERRBUF_SIZE, "str_dup: %s\n", pcap_strerror(errno)); + goto fail; + } + + /* setup device parameters */ + if((handle->fd = dag_open((char *)device)) < 0) { + snprintf(ebuf, PCAP_ERRBUF_SIZE, "dag_open %s: %s", device, pcap_strerror(errno)); + goto fail; + } + + /* set the card snap length to the specified snaplen parameter */ + if (snaplen == 0 || snaplen > MAX_DAG_SNAPLEN) { + snaplen = MAX_DAG_SNAPLEN; + } else if (snaplen < MIN_DAG_SNAPLEN) { + snaplen = MIN_DAG_SNAPLEN; + } + /* snap len has to be a multiple of 4 */ + snprintf(conf, 30, "varlen slen=%d", (snaplen + 3) & ~3); + + if(dag_configure(handle->fd, conf) < 0) { + 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)); + goto fail; + } + + if(dag_start(handle->fd) < 0) { + snprintf(ebuf, PCAP_ERRBUF_SIZE, "dag_start %s: %s\n", device, pcap_strerror(errno)); + goto fail; + } + + /* + * Important! You have to ensure bottom is properly + * 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; + + /* TODO: query the card */ + handle->md.dag_fcs_bits = 32; + if ((s = getenv("ERF_FCS_BITS")) != NULL) { + if ((n = atoi(s)) == 0 || n == 16|| n == 32) { + handle->md.dag_fcs_bits = n; + } else { + snprintf(ebuf, PCAP_ERRBUF_SIZE, + "pcap_open_live %s: bad ERF_FCS_BITS value (%d) in environment\n", device, n); + goto fail; + } + } + + handle->snapshot = snaplen; + /*handle->md.timeout = to_ms; */ + + handle->linktype = -1; + if (dag_get_datalink(handle) < 0) { + strcpy(ebuf, handle->errbuf); + goto fail; + } + + handle->bufsize = 0; + + if (new_pcap_dag(handle) < 0) { + snprintf(ebuf, PCAP_ERRBUF_SIZE, "new_pcap_dag %s: %s\n", device, pcap_strerror(errno)); + goto fail; + } + + /* + * "select()" and "poll()" don't (yet) work on DAG device descriptors. + */ + handle->selectable_fd = -1; #ifdef linux - handle->md.device = (char *)device; + handle->md.device = (char *)device; #else - free((char *)device); - device = NULL; + free((char *)device); + device = NULL; #endif - handle->read_op = dag_read; - handle->setfilter_op = dag_setfilter; - handle->set_datalink_op = dag_set_datalink; - handle->getnonblock_op = pcap_getnonblock_fd; - handle->setnonblock_op = dag_setnonblock; - handle->stats_op = dag_stats; - handle->close_op = dag_platform_close; + handle->read_op = dag_read; + handle->setfilter_op = dag_setfilter; + handle->set_datalink_op = dag_set_datalink; + handle->getnonblock_op = pcap_getnonblock_fd; + handle->setnonblock_op = dag_setnonblock; + handle->stats_op = dag_stats; + handle->close_op = dag_platform_close; - return handle; + return handle; fail: - if (device != NULL) { - free((char *)device); - } - if (handle != NULL) { - /* - * Get rid of any link-layer type list we allocated. - */ - if (handle->dlt_list != NULL) - free(handle->dlt_list); - free(handle); - } + if (device != NULL) { + free((char *)device); + } + if (handle != NULL) { + /* + * Get rid of any link-layer type list we allocated. + */ + if (handle->dlt_list != NULL) { + free(handle->dlt_list); + } + free(handle); + } - return NULL; + return NULL; } -static int dag_stats(pcap_t *p, struct pcap_stat *ps) { - /* 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;*/ - - *ps = p->md.stat; +static int +dag_stats(pcap_t *p, struct pcap_stat *ps) { + /* 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;*/ + + *ps = p->md.stat; - return 0; + return 0; } /* @@ -532,87 +555,86 @@ static int dag_stats(pcap_t *p, struct pcap_stat *ps) { 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; - int ret = 0; - - /* 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) { - /* - * 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; - } - } - - (void)fclose(proc_dag_f); - return (ret); + FILE *proc_dag_f; + char linebuf[512]; + int linenum; + unsigned char *p; + char name[512]; /* XXX - pick a size */ + char *q; + int ret = 0; + + /* 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) { + /* + * 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; + } + } + + (void)fclose(proc_dag_f); + return (ret); } /* @@ -620,31 +642,35 @@ dag_platform_finddevs(pcap_if_t **devlistp, char *errbuf) * no attempt to store the filter in kernel memory as that is not supported * with DAG cards. */ -static int dag_setfilter(pcap_t *p, struct bpf_program *fp) { - if (!p) - return -1; - if (!fp) { - strncpy(p->errbuf, "setfilter: No filter specified", - sizeof(p->errbuf)); - return -1; - } - - /* Make our private copy of the filter */ - - if (install_bpf_program(p, fp) < 0) { - snprintf(p->errbuf, sizeof(p->errbuf), - "malloc: %s", pcap_strerror(errno)); - return -1; - } - - p->md.use_bpf = 0; - - return (0); +static int +dag_setfilter(pcap_t *p, struct bpf_program *fp) +{ + if (!p) + return -1; + if (!fp) { + strncpy(p->errbuf, "setfilter: No filter specified", + sizeof(p->errbuf)); + return -1; + } + + /* Make our private copy of the filter */ + + if (install_bpf_program(p, fp) < 0) { + snprintf(p->errbuf, sizeof(p->errbuf), + "malloc: %s", pcap_strerror(errno)); + return -1; + } + + p->md.use_bpf = 0; + + return (0); } static int dag_set_datalink(pcap_t *p, int dlt) { + p->linktype = dlt; + return (0); } @@ -671,61 +697,66 @@ dag_setnonblock(pcap_t *p, int nonblock, char *errbuf) static int dag_get_datalink(pcap_t *p) { - /* Check the type through a dagapi call. - */ - switch(dag_linktype(p->fd)) { - case TYPE_HDLC_POS: { - dag_record_t *record; - - /* peek at the first available record to see if it is PPP */ - while ((p->md.dag_mem_top - p->md.dag_mem_bottom) < (dag_record_size + 4)) { - p->md.dag_mem_top = dag_offset(p->fd, &(p->md.dag_mem_bottom), 0); - } - record = (dag_record_t *)(p->md.dag_mem_base + p->md.dag_mem_bottom); - - if ((ntohl(record->rec.pos.hdlc) & 0xffff0000) == 0xff030000) { - p->linktype = DLT_PPP_SERIAL; - fprintf(stderr, "Set DAG linktype to %d (DLT_PPP_SERIAL)\n", linktype); - } else { - p->linktype = DLT_CHDLC; - fprintf(stderr, "Set DAG linktype to %d (DLT_CHDLC)\n", linktype); - } - break; - } - case TYPE_ETH: - p->linktype = DLT_EN10MB; - /* - * This is (presumably) a real Ethernet capture; give it a - * link-layer-type list with DLT_EN10MB and DLT_DOCSIS, so - * that an application can let you choose it, in case you're - * capturing DOCSIS traffic that a Cisco Cable Modem - * Termination System is putting out onto an Ethernet (it - * doesn't put an Ethernet header onto the wire, it puts raw - * DOCSIS frames out on the wire inside the low-level - * Ethernet framing). - */ - p->dlt_list = (u_int *) malloc(sizeof(u_int) * 2); - /* - * If that fails, just leave the list empty. - */ - if (p->dlt_list != NULL) { - p->dlt_list[0] = DLT_EN10MB; - p->dlt_list[1] = DLT_DOCSIS; - p->dlt_count = 2; - } - fprintf(stderr, "Set DAG linktype to %d (DLT_EN10MB)\n", linktype); - break; - case TYPE_ATM: - p->linktype = DLT_ATM_RFC1483; - fprintf(stderr, "Set DAG linktype to %d (DLT_ATM_RFC1483)\n", linktype); - break; - case TYPE_LEGACY: - p->linktype = DLT_NULL; - fprintf(stderr, "Set DAG linktype to %d (DLT_NULL)\n", linktype); - break; - default: - fprintf(stderr, "Unknown DAG linktype %d\n", dag_linktype(p->fd)); - return -1;; - } - return 0; + int daglinktype; + + if (p->dlt_list == NULL && (p->dlt_list = malloc(2*sizeof(*(p->dlt_list)))) == NULL) { + (void)snprintf(p->errbuf, sizeof(p->errbuf), "malloc: %s", pcap_strerror(errno)); + return (-1); + } + + /* Check the type through a dagapi call. */ + daglinktype = dag_linktype(p->fd); + + switch(daglinktype) { + + case TYPE_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->linktype = DLT_CHDLC; + break; + + case TYPE_ETH: + /* + * This is (presumably) a real Ethernet capture; give it a + * link-layer-type list with DLT_EN10MB and DLT_DOCSIS, so + * that an application can let you choose it, in case you're + * capturing DOCSIS traffic that a Cisco Cable Modem + * Termination System is putting out onto an Ethernet (it + * doesn't put an Ethernet header onto the wire, it puts raw + * DOCSIS frames out on the wire inside the low-level + * Ethernet framing). + */ + if (p->dlt_list != NULL) { + p->dlt_count = 2; + p->dlt_list[0] = DLT_EN10MB; + p->dlt_list[1] = DLT_DOCSIS; + } + p->linktype = DLT_EN10MB; + break; + + case TYPE_AAL5: + case TYPE_ATM: + if (p->dlt_list != NULL) { + p->dlt_count = 2; + p->dlt_list[0] = DLT_ATM_RFC1483; + p->dlt_list[1] = DLT_SUNATM; + } + p->linktype = DLT_ATM_RFC1483; + break; + + + case TYPE_LEGACY: + p->linktype = DLT_NULL; + break; + + default: + snprintf(p->errbuf, sizeof(p->errbuf), "unknown DAG linktype %d\n", daglinktype); + return (-1); + + } + + return p->linktype; }