summaryrefslogtreecommitdiff
path: root/pcap-dag.c
diff options
context:
space:
mode:
authorguy <guy>2006-04-07 07:07:25 +0000
committerguy <guy>2006-04-07 07:07:25 +0000
commitb64aff479f7c59e1afd9353a247e06821b3cd256 (patch)
treef7b6c81637f0d4b48dddfd6d61f8758f892edf1e /pcap-dag.c
parentcbcd540a75f60872d0252a7161793d9c28f49dc1 (diff)
downloadlibpcap-b64aff479f7c59e1afd9353a247e06821b3cd256.tar.gz
From Stephen Donnelly:
If the DAG API supports asking a card for the set of ERF types it supports, use that capability, to handle cards that support multiple ERF types. This is to support channelised/fractional T1/E1. Don't set the snapshot length - some DAG cards support multiple capture streams, but the snapshot length is global, so it'd affect other captures. Update README.dag.
Diffstat (limited to 'pcap-dag.c')
-rw-r--r--pcap-dag.c185
1 files changed, 113 insertions, 72 deletions
diff --git a/pcap-dag.c b/pcap-dag.c
index 8ec79eb7..7f620957 100644
--- a/pcap-dag.c
+++ b/pcap-dag.c
@@ -17,7 +17,7 @@
#ifndef lint
static const char rcsid[] _U_ =
- "@(#) $Header: /tcpdump/master/libpcap/pcap-dag.c,v 1.24 2005-07-10 22:09:16 guy Exp $ (LBL)";
+ "@(#) $Header: /tcpdump/master/libpcap/pcap-dag.c,v 1.25 2006-04-07 07:07:25 guy Exp $ (LBL)";
#endif
#ifdef HAVE_CONFIG_H
@@ -46,8 +46,6 @@ struct rtentry; /* declarations in <net/if.h> */
#include "dagnew.h"
#include "dagapi.h"
-#define MIN_DAG_SNAPLEN 12
-#define MAX_DAG_SNAPLEN 2040
#define ATM_CELL_SIZE 52
#define ATM_HDR_SIZE 4
@@ -222,7 +220,7 @@ 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.
*/
- p->md.dag_mem_top = dag_advance_stream(p->fd, p->md.dag_stream, (void**)&(p->md.dag_mem_bottom));
+ p->md.dag_mem_top = dag_advance_stream(p->fd, p->md.dag_stream, &(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);
@@ -282,8 +280,14 @@ dag_read(pcap_t *p, int cnt, pcap_handler callback, u_char *user)
p->md.dag_mem_bottom += rlen;
switch(header->type) {
- case TYPE_AAL5:
case TYPE_ATM:
+#ifdef TYPE_AAL5
+ case TYPE_AAL5:
+ if (header->type == TYPE_AAL5) {
+ packet_len = ntohs(header->wlen);
+ caplen = rlen - dag_record_size;
+ }
+#endif
#ifdef TYPE_MC_ATM
case TYPE_MC_ATM:
if (header->type == TYPE_MC_ATM) {
@@ -299,10 +303,7 @@ dag_read(pcap_t *p, int cnt, pcap_handler callback, u_char *user)
dp+=4;
}
#endif
- if (header->type == TYPE_AAL5) {
- packet_len = ntohs(header->wlen);
- caplen = rlen - dag_record_size;
- } else if(header->type == TYPE_ATM) {
+ if (header->type == TYPE_ATM) {
caplen = packet_len = ATM_CELL_SIZE;
}
if (p->linktype == DLT_SUNATM) {
@@ -557,7 +558,14 @@ dag_open_live(const char *device, int snaplen, int promisc, int to_ms, char *ebu
#endif /* HAVE_DAG_STREAMS_API */
+ /* XXX Not calling dag_configure() to set slen; this is unsafe in
+ * multi-stream environments as the gpp config is global.
+ * Once the firmware provides 'per-stream slen' this can be supported
+ * again via the Config API without side-effects */
+#if 0
/* set the card snap length to the specified snaplen parameter */
+ /* This is a really bad idea, as different cards have different
+ * valid slen ranges. Should fix in Config API. */
if (snaplen == 0 || snaplen > MAX_DAG_SNAPLEN) {
snaplen = MAX_DAG_SNAPLEN;
} else if (snaplen < MIN_DAG_SNAPLEN) {
@@ -570,7 +578,8 @@ 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;
}
-
+#endif
+
#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));
@@ -806,81 +815,113 @@ dag_setnonblock(pcap_t *p, int nonblock, char *errbuf)
static int
dag_get_datalink(pcap_t *p)
{
- int daglinktype;
+ int index=0;
+ uint8_t types[255];
- if (p->dlt_list == NULL && (p->dlt_list = malloc(2*sizeof(*(p->dlt_list)))) == NULL) {
+ memset(types, 0, 255);
+
+ if (p->dlt_list == NULL && (p->dlt_list = malloc(255*sizeof(*(p->dlt_list)))) == NULL) {
(void)snprintf(p->errbuf, sizeof(p->errbuf), "malloc: %s", pcap_strerror(errno));
return (-1);
}
+ p->linktype = 0;
+
+#ifdef HAVE_DAG_GET_ERF_TYPES
+ /* Get list of possible ERF types for this card */
+ if (dag_get_erf_types(p->fd, types, 255) < 0) {
+ snprintf(p->errbuf, sizeof(p->errbuf), "dag_get_erf_types: %s", pcap_strerror(errno));
+ return (-1);
+ }
+
+ while (types[index]) {
+#else
/* Check the type through a dagapi call. */
- daglinktype = dag_linktype(p->fd);
+ types[index] = dag_linktype(p->fd);
- switch(daglinktype) {
+ {
+#endif
+ switch(types[index]) {
- 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_HDLC_POS:
+#ifdef TYPE_COLOR_HDLC_POS
+ case TYPE_COLOR_HDLC_POS:
+#endif
+ if (p->dlt_list != NULL) {
+ p->dlt_list[index++] = DLT_CHDLC;
+ p->dlt_list[index++] = DLT_PPP_SERIAL;
+ p->dlt_list[index++] = DLT_FRELAY;
+ }
+ if(!p->linktype)
+ 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
- * 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:
- case TYPE_MC_ATM:
- case TYPE_MC_AAL5:
- 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_MC_HDLC:
- if (p->dlt_list != NULL) {
- p->dlt_count = 4;
- 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->linktype = DLT_CHDLC;
- break;
+ case TYPE_ETH:
+#ifdef TYPE_COLOR_ETH
+ case TYPE_COLOR_ETH:
+#endif
+ /*
+ * 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_list[index++] = DLT_EN10MB;
+ p->dlt_list[index++] = DLT_DOCSIS;
+ }
+ if(!p->linktype)
+ p->linktype = DLT_EN10MB;
+ break;
+
+ case TYPE_ATM:
+#ifdef TYPE_AAL5
+ case TYPE_AAL5:
+#endif
+#ifdef TYPE_MC_ATM
+ case TYPE_MC_ATM:
+#endif
+#ifdef TYPE_MC_AAL5
+ case TYPE_MC_AAL5:
+#endif
+ if (p->dlt_list != NULL) {
+ p->dlt_list[index++] = DLT_ATM_RFC1483;
+ p->dlt_list[index++] = DLT_SUNATM;
+ }
+ if(!p->linktype)
+ p->linktype = DLT_ATM_RFC1483;
+ break;
- case TYPE_LEGACY:
- p->linktype = DLT_NULL;
- break;
+#ifdef TYPE_MC_HDLC
+ case TYPE_MC_HDLC:
+ if (p->dlt_list != NULL) {
+ p->dlt_list[index++] = DLT_CHDLC;
+ p->dlt_list[index++] = DLT_PPP_SERIAL;
+ p->dlt_list[index++] = DLT_FRELAY;
+ p->dlt_list[index++] = DLT_MTP2;
+ }
+ if(!p->linktype)
+ p->linktype = DLT_CHDLC;
+ break;
+#endif
- default:
- snprintf(p->errbuf, sizeof(p->errbuf), "unknown DAG linktype %d\n", daglinktype);
- return (-1);
+ case TYPE_LEGACY:
+ if(!p->linktype)
+ p->linktype = DLT_NULL;
+ break;
+ default:
+ snprintf(p->errbuf, sizeof(p->errbuf), "unknown DAG linktype %d", types[index]);
+ return (-1);
+
+ } /* switch */
}
+ p->dlt_count = index;
+
return p->linktype;
}