tcpdump mailing list archives

libpcap patch for pcap-dag.c


From: Jesper Peterson <jesper () endace com>
Date: Mon, 05 Jan 2004 19:26:39 +1300


Just an update so my pcap-dag.c sources don't get too far out of sync with CVS:

- Merged funky DOCSIS handling.
- Don't auto-detect HDLC DLT, use pcap_set_datalink() to choose
- Allow selecting SUNATM rather than the default RFC1483
- Slightly beautified the code

BTW, init_linktype() in gencode.c doesn't grok DOCSIS, should it be handled by the EN10MB case?

# tcpdump -yDOCSIS -idag0
tcpdump: data link type DOCSIS
tcpdump: unknown data link type 143

--
Jesper Peterson, Senior Software Developer
http://www.endace.com, +64 7 839 0540
Index: pcap-dag.c
===================================================================
RCS file: /tcpdump/master/libpcap/pcap-dag.c,v
retrieving revision 1.15
diff -u -r1.15 pcap-dag.c
--- pcap-dag.c  18 Dec 2003 23:32:31 -0000      1.15
+++ pcap-dag.c  5 Jan 2004 05:31:02 -0000
@@ -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 <support () endace com>
- *              Code shuffled around to suit fad-xxx.c structure
- *              Added atexit() handler to stop DAG if application is too lazy
- *   2003 September - Koryn Grant <koryn () endace com>
- *              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 <koryn () endace com.>
- *              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 <support () endace com>
  */
 
 #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.15 2003/12/18 23:32:31 guy Exp $ (LBL)";
 #endif
 
 #ifdef HAVE_CONFIG_H
@@ -60,12 +46,20 @@
 
 #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_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;
+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 */
+       }
 
-  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;
-    }
-  }
+       if (curr != NULL && curr->p == p) {
+               if (prev != NULL) {
+                       prev->next = curr->next;
+               } else {
+                       pcap_dags = curr->next;
+               }
+       }
 }
 
 /*
@@ -126,58 +120,64 @@
  * 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 @@
  *  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 @@
                                return 0;
                        }
                }
-  
+       
                /* Process the packets. */
                while (p->md.dag_mem_top - p->md.dag_mem_bottom >= dag_record_size) {
 
@@ -240,54 +242,74 @@
                                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 @@
                                /* 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 @@
                                /* 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 @@
                        return processed;
                }
        }
-  
+       
        return processed;
 }
 
@@ -366,157 +385,161 @@
  *  
  *  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);
-  }
-
-  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;
+       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;
+}
+
+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 @@
 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;
-    }
-  }
+       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);
+       (void)fclose(proc_dag_f);
+       return (ret);
 }
 
 /*
@@ -620,31 +642,35 @@
  * 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;
-  }
+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;
+       p->md.use_bpf = 0;
 
-  return (0);
+       return (0);
 }
 
 static int
 dag_set_datalink(pcap_t *p, int dlt)
 {
+       p->linktype = dlt;
+
        return (0);
 }
 
@@ -671,61 +697,66 @@
 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;
 }

Current thread: