-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;
-
- 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;
- }
-
- /* setup device parameters */
- if((handle->fd = dag_open((char *)device)) < 0) {
- snprintf(ebuf, PCAP_ERRBUF_SIZE, "dag_open %s: %s", device, pcap_strerror(errno));
- return NULL;
- }
-
- /* set the card snap length as specified by the specified snaplen parameter */
- if (snaplen > MAX_DAG_SNAPLEN) {
- snaplen = MAX_DAG_SNAPLEN;
- }
- snprintf(conf, 30, "varlen slen=%d", (snaplen % 4) ? (snaplen + 3) & ~3 : snaplen); /* snap len has to be a multiple of 4 */
- 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));
- return NULL;
- }
-
- 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));
- return NULL;
- }
-
- if(dag_start(handle->fd) < 0) {
- snprintf(ebuf, PCAP_ERRBUF_SIZE, "dag_start %s: %s\n", device, pcap_strerror(errno));
- return NULL;
- }
-
- /*
- * 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;
- handle->md.is_dag = 1;
-
- handle->snapshot = snaplen;
- /*handle->md.timeout = to_ms; */
-
-#ifdef linux
- if (device) {
- handle->md.device = strdup(device);
- }
-
- if (handle->md.device == NULL) {
- snprintf(ebuf, PCAP_ERRBUF_SIZE, "str_dup %s: %s\n", device, pcap_strerror(errno));
- free(handle);
- return NULL;
- }
-#endif
-
- /* set link type */
-
- /* Check the type through a dagapi call.
- */
- switch(dag_linktype(handle->fd)) {
- case TYPE_HDLC_POS:
- handle->linktype = DLT_CHDLC;
- fprintf(stderr, "Set DAG linktype to %d (DLT_CHDLC)\n", handle->linktype);
- break;
- case TYPE_ETH:
- handle->linktype = DLT_EN10MB;
- fprintf(stderr, "Set DAG linktype to %d (DLT_EN10MB)\n", handle->linktype);
- break;
- case TYPE_ATM:
- handle->linktype = DLT_ATM_RFC1483;
- fprintf(stderr, "Set DAG linktype to %d (DLT_ATM_RFC1483)\n", handle->linktype);
- break;
- case TYPE_LEGACY:
- handle->linktype = DLT_NULL;
- fprintf(stderr, "Set DAG linktype to %d (DLT_NULL)\n", handle->linktype);
- break;
- default:
- snprintf(ebuf, PCAP_ERRBUF_SIZE, "dag_open_live %s: unknown linktype %d\n", device, dag_linktype(handle->fd));
- return NULL;
- }
-
- handle->bufsize = 0;/*handle->snapshot;*/
-
- if (new_pcap_dag(handle) < 0) {
- snprintf(ebuf, PCAP_ERRBUF_SIZE, "new_pcap_dag %s: %s\n", device, pcap_strerror(errno));
- return NULL;
- }
-
- handle->close_op = dag_platform_close;
-
- return handle;
+static int dag_activate(pcap_t* handle)
+{
+ struct pcap_dag *handlep = handle->priv;
+#if 0
+ char conf[30]; /* dag configure string */
+#endif
+ char *s;
+ int n;
+ daginf_t* daginf;
+ char * newDev = NULL;
+ char * device = handle->opt.device;
+#ifdef HAVE_DAG_STREAMS_API
+ uint32_t mindata;
+ struct timeval maxwait;
+ struct timeval poll;
+#endif
+
+ if (device == NULL) {
+ pcap_snprintf(handle->errbuf, PCAP_ERRBUF_SIZE, "device is NULL: %s", pcap_strerror(errno));
+ return -1;
+ }
+
+ /* Initialize some components of the pcap structure. */
+
+#ifdef HAVE_DAG_STREAMS_API
+ newDev = (char *)malloc(strlen(device) + 16);
+ if (newDev == NULL) {
+ pcap_snprintf(handle->errbuf, PCAP_ERRBUF_SIZE, "Can't allocate string for device name: %s", pcap_strerror(errno));
+ goto fail;
+ }
+
+ /* Parse input name to get dag device and stream number if provided */
+ if (dag_parse_name(device, newDev, strlen(device) + 16, &handlep->dag_stream) < 0) {
+ pcap_snprintf(handle->errbuf, PCAP_ERRBUF_SIZE, "dag_parse_name: %s", pcap_strerror(errno));
+ goto fail;
+ }
+ device = newDev;
+
+ if (handlep->dag_stream%2) {
+ pcap_snprintf(handle->errbuf, PCAP_ERRBUF_SIZE, "dag_parse_name: tx (even numbered) streams not supported for capture");
+ goto fail;
+ }
+#else
+ if (strncmp(device, "/dev/", 5) != 0) {
+ newDev = (char *)malloc(strlen(device) + 5);
+ if (newDev == NULL) {
+ pcap_snprintf(handle->errbuf, PCAP_ERRBUF_SIZE, "Can't allocate string for device name: %s", pcap_strerror(errno));
+ goto fail;
+ }
+ strcpy(newDev, "/dev/");
+ strcat(newDev, device);
+ device = newDev;
+ }
+#endif /* HAVE_DAG_STREAMS_API */
+
+ /* setup device parameters */
+ if((handle->fd = dag_open((char *)device)) < 0) {
+ pcap_snprintf(handle->errbuf, PCAP_ERRBUF_SIZE, "dag_open %s: %s", device, pcap_strerror(errno));
+ goto fail;
+ }
+
+#ifdef HAVE_DAG_STREAMS_API
+ /* Open requested stream. Can fail if already locked or on error */
+ if (dag_attach_stream(handle->fd, handlep->dag_stream, 0, 0) < 0) {
+ pcap_snprintf(handle->errbuf, PCAP_ERRBUF_SIZE, "dag_attach_stream: %s", pcap_strerror(errno));
+ goto failclose;
+ }
+
+ /* Set up default poll parameters for stream
+ * Can be overridden by pcap_set_nonblock()
+ */
+ if (dag_get_stream_poll(handle->fd, handlep->dag_stream,
+ &mindata, &maxwait, &poll) < 0) {
+ pcap_snprintf(handle->errbuf, PCAP_ERRBUF_SIZE, "dag_get_stream_poll: %s", pcap_strerror(errno));
+ goto faildetach;
+ }
+
+ 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 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->opt.timeout/1000;
+ maxwait.tv_usec = (handle->opt.timeout%1000) * 1000;
+
+ if (dag_set_stream_poll(handle->fd, handlep->dag_stream,
+ mindata, &maxwait, &poll) < 0) {
+ pcap_snprintf(handle->errbuf, PCAP_ERRBUF_SIZE, "dag_set_stream_poll: %s", pcap_strerror(errno));
+ goto faildetach;
+ }
+
+#else
+ if((handlep->dag_mem_base = dag_mmap(handle->fd)) == MAP_FAILED) {
+ pcap_snprintf(handle->errbuf, PCAP_ERRBUF_SIZE,"dag_mmap %s: %s", device, pcap_strerror(errno));
+ goto failclose;
+ }
+
+#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 (handle->snapshot == 0 || handle->snapshot > MAX_DAG_SNAPLEN) {
+ handle->snapshot = MAX_DAG_SNAPLEN;
+ } else if (snaplen < MIN_DAG_SNAPLEN) {
+ handle->snapshot = MIN_DAG_SNAPLEN;
+ }
+ /* snap len has to be a multiple of 4 */
+ pcap_snprintf(conf, 30, "varlen slen=%d", (snaplen + 3) & ~3);
+
+ if(dag_configure(handle->fd, conf) < 0) {
+ pcap_snprintf(handle->errbuf, PCAP_ERRBUF_SIZE,"dag_configure %s: %s", device, pcap_strerror(errno));
+ goto faildetach;
+ }
+#endif
+
+#ifdef HAVE_DAG_STREAMS_API
+ if(dag_start_stream(handle->fd, handlep->dag_stream) < 0) {
+ pcap_snprintf(handle->errbuf, PCAP_ERRBUF_SIZE, "dag_start_stream %s: %s", device, pcap_strerror(errno));
+ goto faildetach;
+ }
+#else
+ if(dag_start(handle->fd) < 0) {
+ pcap_snprintf(handle->errbuf, PCAP_ERRBUF_SIZE, "dag_start %s: %s", device, pcap_strerror(errno));
+ goto failclose;
+ }
+#endif /* HAVE_DAG_STREAMS_API */
+
+ /*
+ * 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!
+ */
+ handlep->dag_mem_bottom = 0;
+ handlep->dag_mem_top = 0;
+
+ /*
+ * Find out how many FCS bits we should strip.
+ * First, query the card to see if it strips the FCS.
+ */
+ 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. */
+ handlep->dag_fcs_bits = 0;
+
+ /* Note that no FCS will be supplied. */
+ handle->linktype_ext = LT_FCS_DATALINK_EXT(0);
+ } else {
+ /*
+ * Start out assuming it's 32 bits.
+ */
+ 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) {
+ handlep->dag_fcs_bits = n;
+ } else {
+ pcap_snprintf(handle->errbuf, PCAP_ERRBUF_SIZE,
+ "pcap_activate %s: bad ERF_FCS_BITS value (%d) in environment", device, n);
+ goto failstop;
+ }
+ }
+
+ /*
+ * Did the user request that they not be stripped?
+ */
+ 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(handlep->dag_fcs_bits/16);
+
+ /* And don't strip them. */
+ handlep->dag_fcs_bits = 0;
+ }
+ }
+
+ handlep->dag_timeout = handle->opt.timeout;
+
+ handle->linktype = -1;
+ if (dag_get_datalink(handle) < 0)
+ goto failstop;
+
+ handle->bufsize = 0;
+
+ if (new_pcap_dag(handle) < 0) {
+ pcap_snprintf(handle->errbuf, PCAP_ERRBUF_SIZE, "new_pcap_dag %s: %s", device, pcap_strerror(errno));
+ goto failstop;
+ }
+
+ /*
+ * "select()" and "poll()" don't work on DAG device descriptors.
+ */
+ handle->selectable_fd = -1;
+
+ if (newDev != NULL) {
+ free((char *)newDev);
+ }
+
+ handle->read_op = dag_read;
+ handle->inject_op = dag_inject;
+ handle->setfilter_op = dag_setfilter;
+ handle->setdirection_op = NULL; /* Not implemented.*/
+ handle->set_datalink_op = dag_set_datalink;
+ handle->getnonblock_op = pcap_getnonblock_fd;
+ handle->setnonblock_op = dag_setnonblock;
+ handle->stats_op = dag_stats;
+ handle->cleanup_op = dag_platform_cleanup;
+ 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, handlep->dag_stream) < 0) {
+ fprintf(stderr,"dag_stop_stream: %s\n", strerror(errno));
+ }
+
+faildetach:
+ if (dag_detach_stream(handle->fd, handlep->dag_stream) < 0)
+ fprintf(stderr,"dag_detach_stream: %s\n", strerror(errno));
+#else
+failstop:
+ if (dag_stop(handle->fd) < 0)
+ fprintf(stderr,"dag_stop: %s\n", strerror(errno));
+#endif /* HAVE_DAG_STREAMS_API */
+
+failclose:
+ if (dag_close(handle->fd) < 0)
+ fprintf(stderr,"dag_close: %s\n", strerror(errno));
+ delete_pcap_dag(handle);
+
+fail:
+ pcap_cleanup_live_common(handle);
+ if (newDev != NULL) {
+ free((char *)newDev);
+ }
+
+ return PCAP_ERROR;