From Stephen Donnelly: updates to the DAG support, to support their
updated API if available.
This commit is contained in:
parent
75b14d240d
commit
7f34968ee3
51
README.dag
51
README.dag
|
@ -37,12 +37,57 @@ cards and will not capture from the native OS packet stream.
|
|||
|
||||
----------------------------------------------------------------------
|
||||
|
||||
Libpcap when built for DAG cards against dag-2.5.1 or later releases:
|
||||
|
||||
Timeouts are supported. pcap_dispatch() will return after to_ms milliseconds
|
||||
regardless of how many packets are received. If to_ms is zero pcap_dispatch()
|
||||
will block waiting for data indefinitely.
|
||||
|
||||
pcap_dispatch() will block on and process a minimum of 64kB of data (before
|
||||
filtering) for efficiency. This can introduce high latencies on quiet
|
||||
interfaces unless a timeout value is set. The timeout expiring will override
|
||||
the 64kB minimum causing pcap_dispatch() to process any available data and
|
||||
return.
|
||||
|
||||
pcap_setnonblock is supported. When nonblock is set, pcap_dispatch() will
|
||||
check once for available data, process any data available up to count, then
|
||||
return immediately.
|
||||
|
||||
pcap_findalldevs() is supported, e.g. dag0, dag1...
|
||||
|
||||
Some DAG cards can provide more than one 'stream' of received data.
|
||||
This can be data from different physical ports, or separated by filtering
|
||||
or load balancing mechanisms. Receive streams have even numbers, e.g.
|
||||
dag0:0, dag0:2 etc. Specifying transmit streams for capture is not supported.
|
||||
|
||||
pcap_setfilter() is supported, BPF programs run in userspace.
|
||||
|
||||
pcap_setdirection() is not supported. Only received traffic is captured.
|
||||
DAG cards normally do not have IP or link layer addresses assigned as
|
||||
they are used to passively monitor links.
|
||||
|
||||
pcap_breakloop() is supported.
|
||||
|
||||
pcap_datalink() and pcap_list_datalinks() are supported. The DAG card does
|
||||
not attempt to set the correct datalink type automatically where more than
|
||||
one type is possible.
|
||||
|
||||
pcap_stats() is supported. ps_drop is the number of packets dropped due to
|
||||
RX stream buffer overflow, this count is before filters are applied (it will
|
||||
include packets that would have been dropped by the filter). The RX stream
|
||||
buffer size is user configurable outside libpcap, typically 16-512MB.
|
||||
|
||||
pcap_get_selectable_fd() is not supported, DAG cards do not support
|
||||
poll/select methods.
|
||||
|
||||
pcap_inject() and pcap_sendpacket() are not supported.
|
||||
|
||||
----------------------------------------------------------------------
|
||||
|
||||
Please submit bug reports via <support@endace.com>.
|
||||
|
||||
Please also visit our Web pages at:
|
||||
Please also visit our Web site at:
|
||||
|
||||
http://www.endace.com/
|
||||
http://dag.cs.waikato.ac.nz/
|
||||
|
||||
For more information about Endace DAG cards contact <sales@endace.com>.
|
||||
|
||||
|
|
|
@ -13,6 +13,9 @@
|
|||
/* define if you have the DAG API */
|
||||
#undef HAVE_DAG_API
|
||||
|
||||
/* define if you have streams capable DAG API */
|
||||
#undef HAVE_DAG_STREAMS_API
|
||||
|
||||
/* Define to 1 if you have the declaration of `ether_hostton', and to 0 if you
|
||||
don't. */
|
||||
#undef HAVE_DECL_ETHER_HOSTTON
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
#! /bin/sh
|
||||
# From configure.in Revision: 1.126 .
|
||||
# From configure.in Revision: 1.127 .
|
||||
# Guess values for system-dependent variables and create Makefiles.
|
||||
# Generated by GNU Autoconf 2.57.
|
||||
#
|
||||
|
@ -5791,6 +5791,14 @@ fi
|
|||
|
||||
LDFLAGS=$saved_ldflags
|
||||
|
||||
if test "$dag_version" = 2.5.x; then
|
||||
|
||||
cat >>confdefs.h <<\_ACEOF
|
||||
#define HAVE_DAG_STREAMS_API 1
|
||||
_ACEOF
|
||||
|
||||
fi
|
||||
|
||||
# See if we can find a specific version string.
|
||||
echo "$as_me:$LINENO: checking the DAG API version" >&5
|
||||
echo $ECHO_N "checking the DAG API version... $ECHO_C" >&6
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
dnl @(#) $Header: /tcpdump/master/libpcap/configure.in,v 1.126 2005-06-20 21:36:57 guy Exp $ (LBL)
|
||||
dnl @(#) $Header: /tcpdump/master/libpcap/configure.in,v 1.127 2005-07-07 06:55:19 guy Exp $ (LBL)
|
||||
dnl
|
||||
dnl Copyright (c) 1994, 1995, 1996, 1997
|
||||
dnl The Regents of the University of California. All rights reserved.
|
||||
|
@ -6,7 +6,7 @@ dnl
|
|||
dnl Process this file with autoconf to produce a configure script.
|
||||
dnl
|
||||
|
||||
AC_REVISION($Revision: 1.126 $)
|
||||
AC_REVISION($Revision: 1.127 $)
|
||||
AC_PREREQ(2.50)
|
||||
AC_INIT(pcap.c)
|
||||
|
||||
|
@ -569,6 +569,10 @@ if test $ac_cv_lbl_dag_api = yes; then
|
|||
AC_CHECK_LIB([dag], [dag_attach_stream], [dag_version="2.5.x"], [dag_version="2.4.x"])
|
||||
LDFLAGS=$saved_ldflags
|
||||
|
||||
if test "$dag_version" = 2.5.x; then
|
||||
AC_DEFINE(HAVE_DAG_STREAMS_API, 1, [define if you have streams capable DAG API])
|
||||
fi
|
||||
|
||||
# See if we can find a specific version string.
|
||||
AC_MSG_CHECKING([the DAG API version])
|
||||
if test -r "$dag_root/VERSION"; then
|
||||
|
|
599
pcap-dag.c
599
pcap-dag.c
|
@ -10,12 +10,14 @@
|
|||
* called as required from their pcap-linux/bpf equivalents.
|
||||
*
|
||||
* Authors: Richard Littin, Sean Irvine ({richard,sean}@reeltwo.com)
|
||||
* Modifications: Jesper Peterson, Koryn Grant <support@endace.com>
|
||||
* Modifications: Jesper Peterson <support@endace.com>
|
||||
* Koryn Grant <support@endace.com>
|
||||
* Stephen Donnelly <support@endace.com>
|
||||
*/
|
||||
|
||||
#ifndef lint
|
||||
static const char rcsid[] _U_ =
|
||||
"@(#) $Header: /tcpdump/master/libpcap/pcap-dag.c,v 1.22 2005-05-03 18:53:58 guy Exp $ (LBL)";
|
||||
"@(#) $Header: /tcpdump/master/libpcap/pcap-dag.c,v 1.23 2005-07-07 06:55:20 guy Exp $ (LBL)";
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
|
@ -123,24 +125,24 @@ delete_pcap_dag(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);
|
||||
}
|
||||
#else
|
||||
|
||||
if (p != NULL) {
|
||||
#ifdef HAVE_DAG_STREAMS_API
|
||||
if(dag_stop_stream(p->fd, p->md.dag_stream) < 0)
|
||||
fprintf(stderr,"dag_stop_stream: %s\n", strerror(errno));
|
||||
|
||||
if(dag_detach_stream(p->fd, p->md.dag_stream) < 0)
|
||||
fprintf(stderr,"dag_detach_stream: %s\n", strerror(errno));
|
||||
#else
|
||||
if(dag_stop(p->fd) < 0)
|
||||
fprintf(stderr,"dag_stop: %s\n", strerror(errno));
|
||||
#endif /* HAVE_DAG_STREAMS_API */
|
||||
if(dag_close(p->fd) < 0)
|
||||
fprintf(stderr,"dag_close: %s\n", strerror(errno));
|
||||
}
|
||||
#ifdef linux
|
||||
free(p->md.device);
|
||||
#endif
|
||||
}
|
||||
delete_pcap_dag(p);
|
||||
/* Note: don't need to call close(p->fd) here as dag_close(p->fd) does this. */
|
||||
}
|
||||
|
@ -192,118 +194,190 @@ dag_read(pcap_t *p, int cnt, pcap_handler callback, u_char *user)
|
|||
int flags = p->md.dag_offset_flags;
|
||||
unsigned int nonblocking = flags & DAGF_NONBLOCK;
|
||||
|
||||
for (;;)
|
||||
{
|
||||
/* Get the next bufferful of packets (if necessary). */
|
||||
while (p->md.dag_mem_top - p->md.dag_mem_bottom < dag_record_size) {
|
||||
/* Get the next bufferful of packets (if necessary). */
|
||||
while (p->md.dag_mem_top - p->md.dag_mem_bottom < dag_record_size) {
|
||||
|
||||
/*
|
||||
* Has "pcap_breakloop()" been called?
|
||||
*/
|
||||
if (p->break_loop) {
|
||||
/*
|
||||
* Has "pcap_breakloop()" been called?
|
||||
* Yes - clear the flag that indicates that
|
||||
* it has, and return -2 to indicate that
|
||||
* we were told to break out of the loop.
|
||||
*/
|
||||
if (p->break_loop) {
|
||||
/*
|
||||
* Yes - clear the flag that indicates that
|
||||
* it has, and return -2 to indicate that
|
||||
* we were told to break out of the loop.
|
||||
*/
|
||||
p->break_loop = 0;
|
||||
return -2;
|
||||
}
|
||||
|
||||
p->md.dag_mem_top = dag_offset(p->fd, &(p->md.dag_mem_bottom), flags);
|
||||
if (nonblocking && (p->md.dag_mem_top - p->md.dag_mem_bottom < dag_record_size))
|
||||
{
|
||||
/* Pcap is configured to process only available packets, and there aren't any. */
|
||||
return 0;
|
||||
}
|
||||
p->break_loop = 0;
|
||||
return -2;
|
||||
}
|
||||
|
||||
#ifdef HAVE_DAG_STREAMS_API
|
||||
/* dag_advance_stream() will block (unless nonblock is called)
|
||||
* until 64kB of data has accumulated.
|
||||
* If to_ms is set, it will timeout before 64kB has accumulated.
|
||||
* We wait for 64kB because processing a few packets at a time
|
||||
* can cause problems at high packet rates (>200kpps) due
|
||||
* to inefficiencies.
|
||||
* This does mean if to_ms is not specified the capture may 'hang'
|
||||
* for long periods if the data rate is extremely slow (<64kB/sec)
|
||||
* 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));
|
||||
#else
|
||||
/* dag_offset does not support timeouts */
|
||||
p->md.dag_mem_top = dag_offset(p->fd, &(p->md.dag_mem_bottom), flags);
|
||||
#endif /* HAVE_DAG_STREAMS_API */
|
||||
|
||||
if (nonblocking && (p->md.dag_mem_top - p->md.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))
|
||||
{
|
||||
/* Blocking mode, but timeout set and no data has arrived, return anyway.*/
|
||||
return 0;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/* Process the packets. */
|
||||
while (p->md.dag_mem_top - p->md.dag_mem_bottom >= dag_record_size) {
|
||||
/* Process the packets. */
|
||||
while (p->md.dag_mem_top - p->md.dag_mem_bottom >= dag_record_size) {
|
||||
|
||||
unsigned short packet_len = 0;
|
||||
int caplen = 0;
|
||||
struct pcap_pkthdr pcap_header;
|
||||
unsigned short packet_len = 0;
|
||||
int caplen = 0;
|
||||
struct pcap_pkthdr pcap_header;
|
||||
|
||||
dag_record_t *header = (dag_record_t *)(p->md.dag_mem_base + p->md.dag_mem_bottom);
|
||||
u_char *dp = ((u_char *)header) + dag_record_size;
|
||||
unsigned short rlen;
|
||||
#ifdef HAVE_DAG_STREAMS_API
|
||||
dag_record_t *header = (dag_record_t *)(p->md.dag_mem_bottom);
|
||||
#else
|
||||
dag_record_t *header = (dag_record_t *)(p->md.dag_mem_base + p->md.dag_mem_bottom);
|
||||
#endif /* HAVE_DAG_STREAMS_API */
|
||||
|
||||
u_char *dp = ((u_char *)header) + dag_record_size;
|
||||
unsigned short rlen;
|
||||
|
||||
/*
|
||||
* Has "pcap_breakloop()" been called?
|
||||
*/
|
||||
if (p->break_loop) {
|
||||
/*
|
||||
* Has "pcap_breakloop()" been called?
|
||||
* Yes - clear the flag that indicates that
|
||||
* it has, and return -2 to indicate that
|
||||
* we were told to break out of the loop.
|
||||
*/
|
||||
if (p->break_loop) {
|
||||
/*
|
||||
* Yes - clear the flag that indicates that
|
||||
* it has, and return -2 to indicate that
|
||||
* we were told to break out of the loop.
|
||||
*/
|
||||
p->break_loop = 0;
|
||||
return -2;
|
||||
}
|
||||
p->break_loop = 0;
|
||||
return -2;
|
||||
}
|
||||
|
||||
rlen = ntohs(header->rlen);
|
||||
if (rlen < dag_record_size)
|
||||
{
|
||||
strncpy(p->errbuf, "dag_read: record too small", PCAP_ERRBUF_SIZE);
|
||||
return -1;
|
||||
rlen = ntohs(header->rlen);
|
||||
if (rlen < dag_record_size)
|
||||
{
|
||||
strncpy(p->errbuf, "dag_read: record too small", PCAP_ERRBUF_SIZE);
|
||||
return -1;
|
||||
}
|
||||
p->md.dag_mem_bottom += rlen;
|
||||
|
||||
switch(header->type) {
|
||||
case TYPE_AAL5:
|
||||
case TYPE_ATM:
|
||||
#ifdef TYPE_MC_ATM
|
||||
case TYPE_MC_ATM:
|
||||
if (header->type == TYPE_MC_ATM) {
|
||||
caplen = packet_len = ATM_CELL_SIZE;
|
||||
dp+=4;
|
||||
}
|
||||
p->md.dag_mem_bottom += rlen;
|
||||
|
||||
switch(header->type) {
|
||||
case TYPE_AAL5:
|
||||
case TYPE_ATM:
|
||||
if (header->type == TYPE_AAL5) {
|
||||
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;
|
||||
|
||||
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 == htons(5)) ? 6 :
|
||||
((sunatm->vpi == 0 && sunatm->vci == htons(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:
|
||||
packet_len = ntohs(header->wlen);
|
||||
packet_len -= (p->md.dag_fcs_bits >> 3);
|
||||
caplen = rlen - dag_record_size - 2;
|
||||
if (caplen > packet_len) {
|
||||
caplen = packet_len;
|
||||
}
|
||||
dp += 2;
|
||||
break;
|
||||
|
||||
case TYPE_HDLC_POS:
|
||||
packet_len = ntohs(header->wlen);
|
||||
packet_len -= (p->md.dag_fcs_bits >> 3);
|
||||
#endif
|
||||
#ifdef TYPE_MC_AAL5
|
||||
case TYPE_MC_AAL5:
|
||||
if (header->type == TYPE_MC_AAL5) {
|
||||
packet_len = ntohs(header->wlen);
|
||||
caplen = rlen - dag_record_size - 4;
|
||||
dp+=4;
|
||||
}
|
||||
#endif
|
||||
if (header->type == TYPE_AAL5) {
|
||||
packet_len = ntohs(header->wlen);
|
||||
caplen = rlen - dag_record_size;
|
||||
if (caplen > packet_len) {
|
||||
caplen = packet_len;
|
||||
}
|
||||
break;
|
||||
} else if(header->type == TYPE_ATM) {
|
||||
caplen = packet_len = ATM_CELL_SIZE;
|
||||
}
|
||||
|
||||
if (caplen > p->snapshot)
|
||||
caplen = p->snapshot;
|
||||
if (p->linktype == DLT_SUNATM) {
|
||||
struct sunatm_hdr *sunatm = (struct sunatm_hdr *)dp;
|
||||
unsigned long rawatm;
|
||||
|
||||
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 == htons(5)) ? 6 :
|
||||
((sunatm->vpi == 0 && sunatm->vci == htons(16)) ? 5 :
|
||||
((dp[ATM_HDR_SIZE] == 0xaa &&
|
||||
dp[ATM_HDR_SIZE+1] == 0xaa &&
|
||||
dp[ATM_HDR_SIZE+2] == 0x03) ? 2 : 1)));
|
||||
|
||||
/* Count lost packets. */
|
||||
} else {
|
||||
packet_len -= ATM_HDR_SIZE;
|
||||
caplen -= ATM_HDR_SIZE;
|
||||
dp += ATM_HDR_SIZE;
|
||||
}
|
||||
break;
|
||||
|
||||
#ifdef TYPE_COLOR_ETH
|
||||
case TYPE_COLOR_ETH:
|
||||
#endif
|
||||
case TYPE_ETH:
|
||||
packet_len = ntohs(header->wlen);
|
||||
packet_len -= (p->md.dag_fcs_bits >> 3);
|
||||
caplen = rlen - dag_record_size - 2;
|
||||
if (caplen > packet_len) {
|
||||
caplen = packet_len;
|
||||
}
|
||||
dp += 2;
|
||||
break;
|
||||
#ifdef TYPE_COLOR_HDLC_POS
|
||||
case TYPE_COLOR_HDLC_POS:
|
||||
#endif
|
||||
case TYPE_HDLC_POS:
|
||||
packet_len = ntohs(header->wlen);
|
||||
packet_len -= (p->md.dag_fcs_bits >> 3);
|
||||
caplen = rlen - dag_record_size;
|
||||
if (caplen > packet_len) {
|
||||
caplen = packet_len;
|
||||
}
|
||||
break;
|
||||
#ifdef TYPE_MC_HDLC
|
||||
case TYPE_MC_HDLC:
|
||||
packet_len = ntohs(header->wlen);
|
||||
packet_len -= (p->md.dag_fcs_bits >> 3);
|
||||
caplen = rlen - dag_record_size - 4;
|
||||
if (caplen > packet_len) {
|
||||
caplen = packet_len;
|
||||
}
|
||||
dp += 4;
|
||||
break;
|
||||
#endif
|
||||
}
|
||||
|
||||
if (caplen > p->snapshot)
|
||||
caplen = p->snapshot;
|
||||
|
||||
/* Count lost packets. */
|
||||
switch(header->type) {
|
||||
#ifdef TYPE_COLOR_HDLC_POS
|
||||
/* in this type the color value overwrites the lctr */
|
||||
case TYPE_COLOR_HDLC_POS:
|
||||
break;
|
||||
#endif
|
||||
#ifdef TYPE_COLOR_ETH
|
||||
/* in this type the color value overwrites the lctr */
|
||||
case TYPE_COLOR_ETH:
|
||||
break;
|
||||
#endif
|
||||
default:
|
||||
if (header->lctr) {
|
||||
if (p->md.stat.ps_drop > (UINT_MAX - ntohs(header->lctr))) {
|
||||
p->md.stat.ps_drop = UINT_MAX;
|
||||
|
@ -311,54 +385,49 @@ dag_read(pcap_t *p, int cnt, pcap_handler callback, u_char *user)
|
|||
p->md.stat.ps_drop += ntohs(header->lctr);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Run the packet filter if there is one. */
|
||||
if ((p->fcode.bf_insns == NULL) || bpf_filter(p->fcode.bf_insns, dp, packet_len, caplen)) {
|
||||
/* Run the packet filter if there is one. */
|
||||
if ((p->fcode.bf_insns == NULL) || bpf_filter(p->fcode.bf_insns, dp, packet_len, caplen)) {
|
||||
|
||||
/* convert between timestamp formats */
|
||||
register unsigned long long ts;
|
||||
/* convert between timestamp formats */
|
||||
register unsigned long long ts;
|
||||
|
||||
if (IS_BIGENDIAN()) {
|
||||
ts = SWAP_TS(header->ts);
|
||||
} else {
|
||||
ts = header->ts;
|
||||
}
|
||||
if (IS_BIGENDIAN()) {
|
||||
ts = SWAP_TS(header->ts);
|
||||
} else {
|
||||
ts = header->ts;
|
||||
}
|
||||
|
||||
pcap_header.ts.tv_sec = ts >> 32;
|
||||
ts = (ts & 0xffffffffULL) * 1000000;
|
||||
ts += 0x80000000; /* rounding */
|
||||
pcap_header.ts.tv_usec = ts >> 32;
|
||||
if (pcap_header.ts.tv_usec >= 1000000) {
|
||||
pcap_header.ts.tv_usec -= 1000000;
|
||||
pcap_header.ts.tv_sec++;
|
||||
}
|
||||
pcap_header.ts.tv_sec = ts >> 32;
|
||||
ts = (ts & 0xffffffffULL) * 1000000;
|
||||
ts += 0x80000000; /* rounding */
|
||||
pcap_header.ts.tv_usec = ts >> 32;
|
||||
if (pcap_header.ts.tv_usec >= 1000000) {
|
||||
pcap_header.ts.tv_usec -= 1000000;
|
||||
pcap_header.ts.tv_sec++;
|
||||
}
|
||||
|
||||
/* Fill in our own header data */
|
||||
pcap_header.caplen = caplen;
|
||||
pcap_header.len = packet_len;
|
||||
/* Fill in our own header data */
|
||||
pcap_header.caplen = caplen;
|
||||
pcap_header.len = packet_len;
|
||||
|
||||
/* Count the packet. */
|
||||
p->md.stat.ps_recv++;
|
||||
/* Count the packet. */
|
||||
p->md.stat.ps_recv++;
|
||||
|
||||
/* Call the user supplied callback function */
|
||||
callback(user, &pcap_header, dp);
|
||||
/* 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)
|
||||
{
|
||||
/* Reached the user-specified limit. */
|
||||
return cnt;
|
||||
}
|
||||
/* Only count packets that pass the filter, for consistency with standard Linux behaviour. */
|
||||
processed++;
|
||||
if (processed == cnt)
|
||||
{
|
||||
/* Reached the user-specified limit. */
|
||||
return cnt;
|
||||
}
|
||||
}
|
||||
|
||||
if (nonblocking || processed)
|
||||
{
|
||||
return processed;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
return processed;
|
||||
}
|
||||
|
||||
|
@ -386,7 +455,13 @@ dag_open_live(const char *device, int snaplen, int promisc, int to_ms, char *ebu
|
|||
char *s;
|
||||
int n;
|
||||
daginf_t* daginf;
|
||||
|
||||
char * newDev;
|
||||
#ifdef HAVE_DAG_STREAMS_API
|
||||
uint32_t mindata;
|
||||
struct timeval maxwait;
|
||||
struct timeval poll;
|
||||
#endif
|
||||
|
||||
if (device == NULL) {
|
||||
snprintf(ebuf, PCAP_ERRBUF_SIZE, "device is NULL: %s", pcap_strerror(errno));
|
||||
return NULL;
|
||||
|
@ -403,8 +478,23 @@ dag_open_live(const char *device, int snaplen, int promisc, int to_ms, char *ebu
|
|||
|
||||
memset(handle, 0, sizeof(*handle));
|
||||
|
||||
newDev = (char *)malloc(strlen(device) + 16);
|
||||
|
||||
#ifdef HAVE_DAG_STREAMS_API
|
||||
|
||||
/* 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) {
|
||||
snprintf(ebuf, PCAP_ERRBUF_SIZE, "dag_parse_name: %s\n", pcap_strerror(errno));
|
||||
goto fail;
|
||||
}
|
||||
device = newDev;
|
||||
|
||||
if (handle->md.dag_stream%2) {
|
||||
snprintf(ebuf, PCAP_ERRBUF_SIZE, "dag_parse_name: tx (even numbered) streams not supported for capture\n");
|
||||
goto fail;
|
||||
}
|
||||
#else
|
||||
if (strstr(device, "/dev") == NULL) {
|
||||
char * newDev = (char *)malloc(strlen(device) + 6);
|
||||
newDev[0] = '\0';
|
||||
strcat(newDev, "/dev/");
|
||||
strcat(newDev,device);
|
||||
|
@ -417,6 +507,7 @@ dag_open_live(const char *device, int snaplen, int promisc, int to_ms, char *ebu
|
|||
snprintf(ebuf, PCAP_ERRBUF_SIZE, "str_dup: %s\n", pcap_strerror(errno));
|
||||
goto fail;
|
||||
}
|
||||
#endif /* HAVE_DAG_STREAMS_API */
|
||||
|
||||
/* setup device parameters */
|
||||
if((handle->fd = dag_open((char *)device)) < 0) {
|
||||
|
@ -424,6 +515,48 @@ dag_open_live(const char *device, int snaplen, int promisc, int to_ms, char *ebu
|
|||
goto fail;
|
||||
}
|
||||
|
||||
#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) {
|
||||
snprintf(ebuf, PCAP_ERRBUF_SIZE, "dag_attach_stream: %s\n", pcap_strerror(errno));
|
||||
goto fail;
|
||||
}
|
||||
|
||||
/* 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,
|
||||
&mindata, &maxwait, &poll) < 0) {
|
||||
snprintf(ebuf, PCAP_ERRBUF_SIZE, "dag_get_stream_poll: %s\n", pcap_strerror(errno));
|
||||
goto fail;
|
||||
}
|
||||
|
||||
/* 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 to_ms if supplied. This is a good idea!
|
||||
* Recommend 10-100ms. Calls will time out even if no data arrived.
|
||||
*/
|
||||
maxwait.tv_sec = to_ms/1000;
|
||||
maxwait.tv_usec = (to_ms%1000) * 1000;
|
||||
|
||||
if (dag_set_stream_poll(handle->fd, handle->md.dag_stream,
|
||||
mindata, &maxwait, &poll) < 0) {
|
||||
snprintf(ebuf, PCAP_ERRBUF_SIZE, "dag_set_stream_poll: %s\n", pcap_strerror(errno));
|
||||
goto fail;
|
||||
}
|
||||
|
||||
#else
|
||||
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;
|
||||
}
|
||||
|
||||
#endif /* HAVE_DAG_STREAMS_API */
|
||||
|
||||
/* set the card snap length to the specified snaplen parameter */
|
||||
if (snaplen == 0 || snaplen > MAX_DAG_SNAPLEN) {
|
||||
snaplen = MAX_DAG_SNAPLEN;
|
||||
|
@ -437,16 +570,18 @@ 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;
|
||||
}
|
||||
|
||||
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));
|
||||
|
||||
#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));
|
||||
goto fail;
|
||||
}
|
||||
|
||||
#else
|
||||
if(dag_start(handle->fd) < 0) {
|
||||
snprintf(ebuf, PCAP_ERRBUF_SIZE, "dag_start %s: %s\n", device, pcap_strerror(errno));
|
||||
goto fail;
|
||||
}
|
||||
#endif /* HAVE_DAG_STREAMS_API */
|
||||
|
||||
/*
|
||||
* Important! You have to ensure bottom is properly
|
||||
|
@ -477,7 +612,7 @@ dag_open_live(const char *device, int snaplen, int promisc, int to_ms, char *ebu
|
|||
}
|
||||
|
||||
handle->snapshot = snaplen;
|
||||
/*handle->md.timeout = to_ms; */
|
||||
handle->md.dag_timeout = to_ms;
|
||||
|
||||
handle->linktype = -1;
|
||||
if (dag_get_datalink(handle) < 0) {
|
||||
|
@ -493,12 +628,13 @@ dag_open_live(const char *device, int snaplen, int promisc, int to_ms, char *ebu
|
|||
}
|
||||
|
||||
/*
|
||||
* "select()" and "poll()" don't (yet) work on DAG device descriptors.
|
||||
* "select()" and "poll()" don't work on DAG device descriptors.
|
||||
*/
|
||||
handle->selectable_fd = -1;
|
||||
|
||||
#ifdef linux
|
||||
handle->md.device = (char *)device;
|
||||
handle->md.timeout = to_ms;
|
||||
#else
|
||||
free((char *)device);
|
||||
device = NULL;
|
||||
|
@ -517,8 +653,8 @@ dag_open_live(const char *device, int snaplen, int promisc, int to_ms, char *ebu
|
|||
return handle;
|
||||
|
||||
fail:
|
||||
if (device != NULL) {
|
||||
free((char *)device);
|
||||
if (newDev != NULL) {
|
||||
free((char *)newDev);
|
||||
}
|
||||
if (handle != NULL) {
|
||||
/*
|
||||
|
@ -547,97 +683,42 @@ dag_stats(pcap_t *p, struct pcap_stat *ps) {
|
|||
}
|
||||
|
||||
/*
|
||||
* Get from "/proc/dag" all interfaces listed there; if they're
|
||||
* already in the list of interfaces we have, that won't add another
|
||||
* instance, but if they're not, that'll add them.
|
||||
*
|
||||
* We don't bother getting any addresses for them.
|
||||
*
|
||||
* We also don't fail if we couldn't open "/proc/dag"; we just leave
|
||||
* the list of interfaces as is.
|
||||
* Simply submit all possible dag names as candidates.
|
||||
* pcap_add_if() internally tests each candidate with pcap_open_live(),
|
||||
* so any non-existent devices are dropped.
|
||||
* For 2.5 try all rx stream names as well.
|
||||
*/
|
||||
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;
|
||||
char name[12]; /* XXX - pick a size */
|
||||
int ret = 0;
|
||||
int c;
|
||||
|
||||
/* 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) {
|
||||
/* Try all the DAGs 0-9 */
|
||||
for (c = 0; c < 9; c++) {
|
||||
snprintf(name, 12, "dag%d", c);
|
||||
if (pcap_add_if(devlistp, name, 0, NULL, 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;
|
||||
#ifdef HAVE_DAG_STREAMS_API
|
||||
{
|
||||
int stream;
|
||||
for(stream=0;stream<16;stream+=2) {
|
||||
snprintf(name, 10, "dag%d:%d", c, stream);
|
||||
if (pcap_add_if(devlistp, name, 0, NULL, errbuf) == -1) {
|
||||
/*
|
||||
* Failure.
|
||||
*/
|
||||
ret = -1;
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif /* HAVE_DAG_STREAMS_API */
|
||||
}
|
||||
|
||||
(void)fclose(proc_dag_f);
|
||||
return (ret);
|
||||
}
|
||||
|
||||
|
@ -686,7 +767,34 @@ dag_setnonblock(pcap_t *p, int nonblock, char *errbuf)
|
|||
*/
|
||||
if (pcap_setnonblock_fd(p, nonblock, errbuf) < 0)
|
||||
return (-1);
|
||||
|
||||
#ifdef HAVE_DAG_STREAMS_API
|
||||
{
|
||||
uint32_t mindata;
|
||||
struct timeval maxwait;
|
||||
struct timeval poll;
|
||||
|
||||
if (dag_get_stream_poll(p->fd, p->md.dag_stream,
|
||||
&mindata, &maxwait, &poll) < 0) {
|
||||
snprintf(errbuf, PCAP_ERRBUF_SIZE, "dag_get_stream_poll: %s\n", pcap_strerror(errno));
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* 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!
|
||||
*/
|
||||
if(nonblock)
|
||||
mindata = 0;
|
||||
else
|
||||
mindata = 65536;
|
||||
|
||||
if (dag_set_stream_poll(p->fd, p->md.dag_stream,
|
||||
mindata, &maxwait, &poll) < 0) {
|
||||
snprintf(errbuf, PCAP_ERRBUF_SIZE, "dag_set_stream_poll: %s\n", pcap_strerror(errno));
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
#endif /* HAVE_DAG_STREAMS_API */
|
||||
if (nonblock) {
|
||||
p->md.dag_offset_flags |= DAGF_NONBLOCK;
|
||||
} else {
|
||||
|
@ -711,15 +819,18 @@ dag_get_datalink(pcap_t *p)
|
|||
switch(daglinktype) {
|
||||
|
||||
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_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
|
||||
|
@ -740,6 +851,8 @@ dag_get_datalink(pcap_t *p)
|
|||
|
||||
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;
|
||||
|
@ -748,6 +861,18 @@ dag_get_datalink(pcap_t *p)
|
|||
p->linktype = DLT_ATM_RFC1483;
|
||||
break;
|
||||
|
||||
case TYPE_MC_HDLC:
|
||||
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->dlt_list[3] = DLT_MTP2;
|
||||
p->dlt_list[4] = DLT_MTP3;
|
||||
p->dlt_list[5] = DLT_SCCP;
|
||||
}
|
||||
p->linktype = DLT_CHDLC;
|
||||
break;
|
||||
|
||||
case TYPE_LEGACY:
|
||||
p->linktype = DLT_NULL;
|
||||
|
|
|
@ -7,8 +7,8 @@
|
|||
*
|
||||
* Author: Richard Littin, Sean Irvine ({richard,sean}@reeltwo.com)
|
||||
*
|
||||
* @(#) $Header: /tcpdump/master/libpcap/pcap-dag.h,v 1.3 2003-07-25 05:32:03 guy Exp $ (LBL)
|
||||
* @(#) $Header: /tcpdump/master/libpcap/pcap-dag.h,v 1.4 2005-07-07 06:55:20 guy Exp $ (LBL)
|
||||
*/
|
||||
|
||||
pcap_t *dag_open_live(const char *device, int snaplen, int promisc, int to_ms, char *ebuf);
|
||||
|
||||
int dag_platform_finddevs(pcap_if_t **devlistp, char *errbuf);
|
||||
|
|
17
pcap-int.h
17
pcap-int.h
|
@ -30,7 +30,7 @@
|
|||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* @(#) $Header: /tcpdump/master/libpcap/pcap-int.h,v 1.74 2005-07-07 01:57:01 guy Exp $ (LBL)
|
||||
* @(#) $Header: /tcpdump/master/libpcap/pcap-int.h,v 1.75 2005-07-07 06:55:20 guy Exp $ (LBL)
|
||||
*/
|
||||
|
||||
#ifndef pcap_int_h
|
||||
|
@ -91,12 +91,21 @@ struct pcap_md {
|
|||
#endif
|
||||
|
||||
#ifdef HAVE_DAG_API
|
||||
#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
|
||||
void *dag_mem_base; /* DAG card memory base address */
|
||||
u_int dag_mem_bottom; /* DAG card current memory bottom pointer */
|
||||
u_int dag_mem_top; /* DAG card current memory top pointer */
|
||||
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(). */
|
||||
#endif
|
||||
int dag_stream; /* DAG stream number */
|
||||
int dag_timeout; /* timeout specified to pcap_open_live.
|
||||
* Same as in linux above, introduce
|
||||
* generally? */
|
||||
#endif /* HAVE_DAG_API */
|
||||
};
|
||||
|
||||
/*
|
||||
|
|
Reference in New Issue