freebsd-nq/contrib/libpcap/pcap-dag.c

1218 lines
32 KiB
C
Raw Normal View History

/*
* pcap-dag.c: Packet capture interface for Endace DAG card.
*
* The functionality of this code attempts to mimic that of pcap-linux as much
* as possible. This code is compiled in several different ways depending on
* whether DAG_ONLY and HAVE_DAG_API are defined. If HAVE_DAG_API is not
* defined it should not get compiled in, otherwise if DAG_ONLY is defined then
* the 'dag_' function calls are renamed to 'pcap_' equivalents. If DAG_ONLY
* is not defined then nothing is altered - the dag_ functions will be
* called as required from their pcap-linux/bpf equivalents.
*
* Authors: Richard Littin, Sean Irvine ({richard,sean}@reeltwo.com)
2006-09-04 19:43:23 +00:00
* Modifications: Jesper Peterson <support@endace.com>
* Koryn Grant <support@endace.com>
* Stephen Donnelly <support@endace.com>
*/
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
#include <sys/param.h> /* optionally get BSD define */
#include <stdlib.h>
#include <string.h>
#include <errno.h>
#include "pcap-int.h"
#include <ctype.h>
#include <netinet/in.h>
#include <sys/mman.h>
#include <sys/socket.h>
#include <sys/types.h>
#include <unistd.h>
struct mbuf; /* Squelch compiler warnings on some platforms for */
struct rtentry; /* declarations in <net/if.h> */
#include <net/if.h>
#include "dagnew.h"
#include "dagapi.h"
2009-03-21 20:43:56 +00:00
#include "pcap-dag.h"
2013-05-30 06:41:26 +00:00
/*
* DAG devices have names beginning with "dag", followed by a number
2015-01-06 18:58:31 +00:00
* from 0 to DAG_MAX_BOARDS, then optionally a colon and a stream number
* from 0 to DAG_STREAM_MAX.
2013-05-30 06:41:26 +00:00
*/
2015-01-06 18:58:31 +00:00
#ifndef DAG_MAX_BOARDS
#define DAG_MAX_BOARDS 32
#endif
2013-05-30 06:41:26 +00:00
#define ATM_CELL_SIZE 52
#define ATM_HDR_SIZE 4
2007-10-16 02:02:02 +00:00
/*
* A header containing additional MTP information.
*/
#define MTP2_SENT_OFFSET 0 /* 1 byte */
#define MTP2_ANNEX_A_USED_OFFSET 1 /* 1 byte */
#define MTP2_LINK_NUMBER_OFFSET 2 /* 2 bytes */
#define MTP2_HDR_LEN 4 /* length of the header */
#define MTP2_ANNEX_A_NOT_USED 0
#define MTP2_ANNEX_A_USED 1
#define MTP2_ANNEX_A_USED_UNKNOWN 2
/* SunATM pseudo header */
struct sunatm_hdr {
unsigned char flags; /* destination and traffic type */
unsigned char vpi; /* VPI */
unsigned short vci; /* VCI */
};
2015-01-06 18:58:31 +00:00
/*
* Private data for capturing on DAG devices.
*/
struct pcap_dag {
struct pcap_stat stat;
#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 /* HAVE_DAG_STREAMS_API */
void *dag_mem_base; /* DAG card memory base address */
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(). */
int dag_stream; /* DAG stream number */
int dag_timeout; /* timeout specified to pcap_open_live.
* Same as in linux above, introduce
* generally? */
};
typedef struct pcap_dag_node {
struct pcap_dag_node *next;
pcap_t *p;
pid_t pid;
} pcap_dag_node_t;
static pcap_dag_node_t *pcap_dags = NULL;
static int atexit_handler_installed = 0;
static const unsigned short endian_test_word = 0x0100;
#define IS_BIGENDIAN() (*((unsigned char *)&endian_test_word))
2007-10-16 02:02:02 +00:00
#define MAX_DAG_PACKET 65536
static unsigned char TempPkt[MAX_DAG_PACKET];
static int dag_setfilter(pcap_t *p, struct bpf_program *fp);
static int dag_stats(pcap_t *p, struct pcap_stat *ps);
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;
}
}
}
/*
* Performs a graceful shutdown of the DAG card, frees dynamic memory held
* in the pcap_t structure, and closes the file descriptor for the DAG card.
*/
static void
2009-03-21 20:43:56 +00:00
dag_platform_cleanup(pcap_t *p)
{
2015-01-06 18:58:31 +00:00
struct pcap_dag *pd;
2006-09-04 19:43:23 +00:00
if (p != NULL) {
2015-01-06 18:58:31 +00:00
pd = p->priv;
2006-09-04 19:43:23 +00:00
#ifdef HAVE_DAG_STREAMS_API
2015-01-06 18:58:31 +00:00
if(dag_stop_stream(p->fd, pd->dag_stream) < 0)
2006-09-04 19:43:23 +00:00
fprintf(stderr,"dag_stop_stream: %s\n", strerror(errno));
2015-01-06 18:58:31 +00:00
if(dag_detach_stream(p->fd, pd->dag_stream) < 0)
2006-09-04 19:43:23 +00:00
fprintf(stderr,"dag_detach_stream: %s\n", strerror(errno));
#else
if(dag_stop(p->fd) < 0)
fprintf(stderr,"dag_stop: %s\n", strerror(errno));
2006-09-04 19:43:23 +00:00
#endif /* HAVE_DAG_STREAMS_API */
2009-03-21 20:43:56 +00:00
if(p->fd != -1) {
if(dag_close(p->fd) < 0)
fprintf(stderr,"dag_close: %s\n", strerror(errno));
p->fd = -1;
}
delete_pcap_dag(p);
pcap_cleanup_live_common(p);
2006-09-04 19:43:23 +00:00
}
/* 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()) {
2009-03-21 20:43:56 +00:00
dag_platform_cleanup(pcap_dags->p);
} else {
delete_pcap_dag(pcap_dags->p);
}
}
}
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 (!atexit_handler_installed) {
atexit(atexit_handler);
atexit_handler_installed = 1;
}
node->next = pcap_dags;
node->p = p;
node->pid = getpid();
pcap_dags = node;
return 0;
}
2009-03-21 20:43:56 +00:00
static unsigned int
dag_erf_ext_header_count(uint8_t * erf, size_t len)
{
uint32_t hdr_num = 0;
uint8_t hdr_type;
/* basic sanity checks */
if ( erf == NULL )
return 0;
if ( len < 16 )
return 0;
/* check if we have any extension headers */
if ( (erf[8] & 0x80) == 0x00 )
return 0;
/* loop over the extension headers */
do {
/* sanity check we have enough bytes */
2015-01-06 18:58:31 +00:00
if ( len < (24 + (hdr_num * 8)) )
2009-03-21 20:43:56 +00:00
return hdr_num;
/* get the header type */
hdr_type = erf[(16 + (hdr_num * 8))];
hdr_num++;
} while ( hdr_type & 0x80 );
return hdr_num;
}
/*
* Read at most max_packets from the capture stream and call the callback
* 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)
{
2015-01-06 18:58:31 +00:00
struct pcap_dag *pd = p->priv;
unsigned int processed = 0;
2015-01-06 18:58:31 +00:00
int flags = pd->dag_offset_flags;
unsigned int nonblocking = flags & DAGF_NONBLOCK;
2009-03-21 20:43:56 +00:00
unsigned int num_ext_hdr = 0;
2006-09-04 19:43:23 +00:00
/* Get the next bufferful of packets (if necessary). */
2015-01-06 18:58:31 +00:00
while (pd->dag_mem_top - pd->dag_mem_bottom < dag_record_size) {
2006-09-04 19:43:23 +00:00
/*
* Has "pcap_breakloop()" been called?
*/
if (p->break_loop) {
/*
2006-09-04 19:43:23 +00:00
* Yes - clear the flag that indicates that
* it has, and return -2 to indicate that
* we were told to break out of the loop.
*/
2006-09-04 19:43:23 +00:00
p->break_loop = 0;
return -2;
}
2006-09-04 19:43:23 +00:00
#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.
*/
2015-01-06 18:58:31 +00:00
if ( NULL == (pd->dag_mem_top = dag_advance_stream(p->fd, pd->dag_stream, &(pd->dag_mem_bottom))) ) {
2009-03-21 20:43:56 +00:00
return -1;
}
2006-09-04 19:43:23 +00:00
#else
/* dag_offset does not support timeouts */
2015-01-06 18:58:31 +00:00
pd->dag_mem_top = dag_offset(p->fd, &(pd->dag_mem_bottom), flags);
2006-09-04 19:43:23 +00:00
#endif /* HAVE_DAG_STREAMS_API */
2015-01-06 18:58:31 +00:00
if (nonblocking && (pd->dag_mem_top - pd->dag_mem_bottom < dag_record_size))
2006-09-04 19:43:23 +00:00
{
/* Pcap is configured to process only available packets, and there aren't any, return immediately. */
return 0;
}
if(!nonblocking &&
2015-01-06 18:58:31 +00:00
pd->dag_timeout &&
(pd->dag_mem_top - pd->dag_mem_bottom < dag_record_size))
2006-09-04 19:43:23 +00:00
{
/* Blocking mode, but timeout set and no data has arrived, return anyway.*/
return 0;
}
2006-09-04 19:43:23 +00:00
}
2006-09-04 19:43:23 +00:00
/* Process the packets. */
2015-01-06 18:58:31 +00:00
while (pd->dag_mem_top - pd->dag_mem_bottom >= dag_record_size) {
2009-03-21 20:43:56 +00:00
2006-09-04 19:43:23 +00:00
unsigned short packet_len = 0;
int caplen = 0;
struct pcap_pkthdr pcap_header;
2009-03-21 20:43:56 +00:00
2006-09-04 19:43:23 +00:00
#ifdef HAVE_DAG_STREAMS_API
2015-01-06 18:58:31 +00:00
dag_record_t *header = (dag_record_t *)(pd->dag_mem_bottom);
2006-09-04 19:43:23 +00:00
#else
2015-01-06 18:58:31 +00:00
dag_record_t *header = (dag_record_t *)(pd->dag_mem_base + pd->dag_mem_bottom);
2006-09-04 19:43:23 +00:00
#endif /* HAVE_DAG_STREAMS_API */
2009-03-21 20:43:56 +00:00
u_char *dp = ((u_char *)header); /* + dag_record_size; */
2006-09-04 19:43:23 +00:00
unsigned short rlen;
2006-09-04 19:43:23 +00:00
/*
* Has "pcap_breakloop()" been called?
*/
if (p->break_loop) {
/*
2006-09-04 19:43:23 +00:00
* Yes - clear the flag that indicates that
* it has, and return -2 to indicate that
* we were told to break out of the loop.
*/
2006-09-04 19:43:23 +00:00
p->break_loop = 0;
return -2;
}
2006-09-04 19:43:23 +00:00
rlen = ntohs(header->rlen);
if (rlen < dag_record_size)
{
strncpy(p->errbuf, "dag_read: record too small", PCAP_ERRBUF_SIZE);
return -1;
}
2015-01-06 18:58:31 +00:00
pd->dag_mem_bottom += rlen;
2006-09-04 19:43:23 +00:00
/* Count lost packets. */
2009-03-21 20:43:56 +00:00
switch((header->type & 0x7f)) {
/* in these types the color value overwrites the lctr */
2006-09-04 19:43:23 +00:00
case TYPE_COLOR_HDLC_POS:
case TYPE_COLOR_ETH:
2007-10-16 02:02:02 +00:00
case TYPE_DSM_COLOR_HDLC_POS:
case TYPE_DSM_COLOR_ETH:
case TYPE_COLOR_MC_HDLC_POS:
2009-03-21 20:43:56 +00:00
case TYPE_COLOR_HASH_ETH:
case TYPE_COLOR_HASH_POS:
2007-10-16 02:02:02 +00:00
break;
2006-09-04 19:43:23 +00:00
default:
if (header->lctr) {
2015-01-06 18:58:31 +00:00
if (pd->stat.ps_drop > (UINT_MAX - ntohs(header->lctr))) {
pd->stat.ps_drop = UINT_MAX;
} else {
2015-01-06 18:58:31 +00:00
pd->stat.ps_drop += ntohs(header->lctr);
}
}
2006-09-04 19:43:23 +00:00
}
2009-03-21 20:43:56 +00:00
if ((header->type & 0x7f) == TYPE_PAD) {
continue;
}
num_ext_hdr = dag_erf_ext_header_count(dp, rlen);
/* ERF encapsulation */
/* The Extensible Record Format is not dropped for this kind of encapsulation,
* and will be handled as a pseudo header by the decoding application.
* The information carried in the ERF header and in the optional subheader (if present)
* could be merged with the libpcap information, to offer a better decoding.
* The packet length is
* o the length of the packet on the link (header->wlen),
* o plus the length of the ERF header (dag_record_size), as the length of the
* pseudo header will be adjusted during the decoding,
* o plus the length of the optional subheader (if present).
*
* The capture length is header.rlen and the byte stuffing for alignment will be dropped
* if the capture length is greater than the packet length.
*/
if (p->linktype == DLT_ERF) {
packet_len = ntohs(header->wlen) + dag_record_size;
caplen = rlen;
switch ((header->type & 0x7f)) {
case TYPE_MC_AAL5:
case TYPE_MC_ATM:
case TYPE_MC_HDLC:
Update libpcap to 1.1.1. Changes: Thu. April 1, 2010. guy@alum.mit.edu. Summary for 1.1.1 libpcap release Update CHANGES to reflect more of the changes in 1.1.0. Fix build on RHEL5. Fix shared library build on AIX. Thu. March 11, 2010. ken@netfunctional.ca/guy@alum.mit.edu. Summary for 1.1.0 libpcap release Add SocketCAN capture support Add Myricom SNF API support Update Endace DAG and ERF support Add support for shared libraries on Solaris, HP-UX, and AIX Build, install, and un-install shared libraries by default; don't build/install shared libraries on platforms we don't support Fix building from a directory other than the source directory Fix compiler warnings and builds on some platforms Update config.guess and config.sub Support monitor mode on mac80211 devices on Linux Fix USB memory-mapped capturing on Linux; it requires a new DLT_ value On Linux, scan /sys/class/net for devices if we have it; scan it, or /proc/net/dev if we don't have /sys/class/net, even if we have getifaddrs(), as it'll find interfaces with no addresses Add limited support for reading pcap-ng files Fix BPF driver-loading error handling on AIX Support getting the full-length interface description on FreeBSD In the lexical analyzer, free up any addrinfo structure we got back from getaddrinfo(). Add support for BPF and libdlpi in OpenSolaris (and SXCE) Hyphenate "link-layer" everywhere Add /sys/kernel/debug/usb/usbmon to the list of usbmon locations In pcap_read_linux_mmap(), if there are no frames available, call poll() even if we're in non-blocking mode, so we pick up errors, and check for the errors in question. Note that poll() works on BPF devices is Snow Leopard If an ENXIO or ENETDOWN is received, it may mean the device has gone away. Deal with it. For BPF, raise the default capture buffer size to from 32k to 512k Support ps_ifdrop on Linux Added a bunch of #ifdef directives to make wpcap.dll (WinPcap) compile under cygwin. Changes to Linux mmapped captures. Fix bug where create_ring would fail for particular snaplen and buffer size combinations Update pcap-config so that it handles libpcap requiring additional libraries Add workaround for threadsafeness on Windows Add missing mapping for DLT_ENC <-> LINKTYPE_ENC DLT: Add DLT_CAN_SOCKETCAN DLT: Add Solaris ipnet Don't check for DLT_IPNET if it's not defined Add link-layer types for Fibre Channel FC-2 Add link-layer types for Wireless HART Add link-layer types for AOS Add link-layer types for DECT Autoconf fixes (AIX, HP-UX, OSF/1, Tru64 cleanups) Install headers unconditionally, and include vlan.h/bluetooth.h if enabled Autoconf fixes+cleanup Support enabling/disabling bluetooth (--{en,dis}able-bluetooth) Support disabling SITA support (--without-sita) Return -1 on failure to create packet ring (if supported but creation failed) Fix handling of 'any' device, so that it can be opened, and no longer attempt to open it in Monitor mode Add support for snapshot length for USB Memory-Mapped Interface Fix configure and build on recent Linux kernels Fix memory-mapped Linux capture to support pcap_next() and pcap_next_ex() Fixes for Linux USB capture DLT: Add DLT_LINUX_EVDEV DLT: Add DLT_GSMTAP_UM DLT: Add DLT_GSMTAP_ABIS
2010-10-28 16:22:13 +00:00
case TYPE_MC_RAW_CHANNEL:
case TYPE_MC_RAW:
case TYPE_MC_AAL2:
case TYPE_COLOR_MC_HDLC_POS:
2009-03-21 20:43:56 +00:00
packet_len += 4; /* MC header */
break;
case TYPE_COLOR_HASH_ETH:
case TYPE_DSM_COLOR_ETH:
case TYPE_COLOR_ETH:
case TYPE_ETH:
packet_len += 2; /* ETH header */
break;
} /* switch type */
/* Include ERF extension headers */
packet_len += (8 * num_ext_hdr);
if (caplen > packet_len) {
caplen = packet_len;
}
} else {
/* Other kind of encapsulation according to the header Type */
/* Skip over generic ERF header */
dp += dag_record_size;
/* Skip over extension headers */
dp += 8 * num_ext_hdr;
switch((header->type & 0x7f)) {
case TYPE_ATM:
case TYPE_AAL5:
if (header->type == TYPE_AAL5) {
packet_len = ntohs(header->wlen);
caplen = rlen - dag_record_size;
}
case TYPE_MC_ATM:
if (header->type == TYPE_MC_ATM) {
caplen = packet_len = ATM_CELL_SIZE;
dp+=4;
}
case TYPE_MC_AAL5:
if (header->type == TYPE_MC_AAL5) {
packet_len = ntohs(header->wlen);
caplen = rlen - dag_record_size - 4;
dp+=4;
}
if (header->type == TYPE_ATM) {
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_COLOR_HASH_ETH:
case TYPE_DSM_COLOR_ETH:
case TYPE_COLOR_ETH:
case TYPE_ETH:
packet_len = ntohs(header->wlen);
2015-01-06 18:58:31 +00:00
packet_len -= (pd->dag_fcs_bits >> 3);
2009-03-21 20:43:56 +00:00
caplen = rlen - dag_record_size - 2;
if (caplen > packet_len) {
caplen = packet_len;
}
dp += 2;
break;
case TYPE_COLOR_HASH_POS:
case TYPE_DSM_COLOR_HDLC_POS:
case TYPE_COLOR_HDLC_POS:
case TYPE_HDLC_POS:
packet_len = ntohs(header->wlen);
2015-01-06 18:58:31 +00:00
packet_len -= (pd->dag_fcs_bits >> 3);
2009-03-21 20:43:56 +00:00
caplen = rlen - dag_record_size;
if (caplen > packet_len) {
caplen = packet_len;
}
break;
case TYPE_COLOR_MC_HDLC_POS:
case TYPE_MC_HDLC:
packet_len = ntohs(header->wlen);
2015-01-06 18:58:31 +00:00
packet_len -= (pd->dag_fcs_bits >> 3);
2009-03-21 20:43:56 +00:00
caplen = rlen - dag_record_size - 4;
if (caplen > packet_len) {
caplen = packet_len;
}
/* jump the MC_HDLC_HEADER */
dp += 4;
#ifdef DLT_MTP2_WITH_PHDR
if (p->linktype == DLT_MTP2_WITH_PHDR) {
/* Add the MTP2 Pseudo Header */
caplen += MTP2_HDR_LEN;
packet_len += MTP2_HDR_LEN;
TempPkt[MTP2_SENT_OFFSET] = 0;
TempPkt[MTP2_ANNEX_A_USED_OFFSET] = MTP2_ANNEX_A_USED_UNKNOWN;
*(TempPkt+MTP2_LINK_NUMBER_OFFSET) = ((header->rec.mc_hdlc.mc_header>>16)&0x01);
*(TempPkt+MTP2_LINK_NUMBER_OFFSET+1) = ((header->rec.mc_hdlc.mc_header>>24)&0xff);
memcpy(TempPkt+MTP2_HDR_LEN, dp, caplen);
dp = TempPkt;
}
#endif
break;
case TYPE_IPV4:
Update libpcap to 1.1.1. Changes: Thu. April 1, 2010. guy@alum.mit.edu. Summary for 1.1.1 libpcap release Update CHANGES to reflect more of the changes in 1.1.0. Fix build on RHEL5. Fix shared library build on AIX. Thu. March 11, 2010. ken@netfunctional.ca/guy@alum.mit.edu. Summary for 1.1.0 libpcap release Add SocketCAN capture support Add Myricom SNF API support Update Endace DAG and ERF support Add support for shared libraries on Solaris, HP-UX, and AIX Build, install, and un-install shared libraries by default; don't build/install shared libraries on platforms we don't support Fix building from a directory other than the source directory Fix compiler warnings and builds on some platforms Update config.guess and config.sub Support monitor mode on mac80211 devices on Linux Fix USB memory-mapped capturing on Linux; it requires a new DLT_ value On Linux, scan /sys/class/net for devices if we have it; scan it, or /proc/net/dev if we don't have /sys/class/net, even if we have getifaddrs(), as it'll find interfaces with no addresses Add limited support for reading pcap-ng files Fix BPF driver-loading error handling on AIX Support getting the full-length interface description on FreeBSD In the lexical analyzer, free up any addrinfo structure we got back from getaddrinfo(). Add support for BPF and libdlpi in OpenSolaris (and SXCE) Hyphenate "link-layer" everywhere Add /sys/kernel/debug/usb/usbmon to the list of usbmon locations In pcap_read_linux_mmap(), if there are no frames available, call poll() even if we're in non-blocking mode, so we pick up errors, and check for the errors in question. Note that poll() works on BPF devices is Snow Leopard If an ENXIO or ENETDOWN is received, it may mean the device has gone away. Deal with it. For BPF, raise the default capture buffer size to from 32k to 512k Support ps_ifdrop on Linux Added a bunch of #ifdef directives to make wpcap.dll (WinPcap) compile under cygwin. Changes to Linux mmapped captures. Fix bug where create_ring would fail for particular snaplen and buffer size combinations Update pcap-config so that it handles libpcap requiring additional libraries Add workaround for threadsafeness on Windows Add missing mapping for DLT_ENC <-> LINKTYPE_ENC DLT: Add DLT_CAN_SOCKETCAN DLT: Add Solaris ipnet Don't check for DLT_IPNET if it's not defined Add link-layer types for Fibre Channel FC-2 Add link-layer types for Wireless HART Add link-layer types for AOS Add link-layer types for DECT Autoconf fixes (AIX, HP-UX, OSF/1, Tru64 cleanups) Install headers unconditionally, and include vlan.h/bluetooth.h if enabled Autoconf fixes+cleanup Support enabling/disabling bluetooth (--{en,dis}able-bluetooth) Support disabling SITA support (--without-sita) Return -1 on failure to create packet ring (if supported but creation failed) Fix handling of 'any' device, so that it can be opened, and no longer attempt to open it in Monitor mode Add support for snapshot length for USB Memory-Mapped Interface Fix configure and build on recent Linux kernels Fix memory-mapped Linux capture to support pcap_next() and pcap_next_ex() Fixes for Linux USB capture DLT: Add DLT_LINUX_EVDEV DLT: Add DLT_GSMTAP_UM DLT: Add DLT_GSMTAP_ABIS
2010-10-28 16:22:13 +00:00
case TYPE_IPV6:
2009-03-21 20:43:56 +00:00
packet_len = ntohs(header->wlen);
caplen = rlen - dag_record_size;
if (caplen > packet_len) {
caplen = packet_len;
}
break;
Update libpcap to 1.1.1. Changes: Thu. April 1, 2010. guy@alum.mit.edu. Summary for 1.1.1 libpcap release Update CHANGES to reflect more of the changes in 1.1.0. Fix build on RHEL5. Fix shared library build on AIX. Thu. March 11, 2010. ken@netfunctional.ca/guy@alum.mit.edu. Summary for 1.1.0 libpcap release Add SocketCAN capture support Add Myricom SNF API support Update Endace DAG and ERF support Add support for shared libraries on Solaris, HP-UX, and AIX Build, install, and un-install shared libraries by default; don't build/install shared libraries on platforms we don't support Fix building from a directory other than the source directory Fix compiler warnings and builds on some platforms Update config.guess and config.sub Support monitor mode on mac80211 devices on Linux Fix USB memory-mapped capturing on Linux; it requires a new DLT_ value On Linux, scan /sys/class/net for devices if we have it; scan it, or /proc/net/dev if we don't have /sys/class/net, even if we have getifaddrs(), as it'll find interfaces with no addresses Add limited support for reading pcap-ng files Fix BPF driver-loading error handling on AIX Support getting the full-length interface description on FreeBSD In the lexical analyzer, free up any addrinfo structure we got back from getaddrinfo(). Add support for BPF and libdlpi in OpenSolaris (and SXCE) Hyphenate "link-layer" everywhere Add /sys/kernel/debug/usb/usbmon to the list of usbmon locations In pcap_read_linux_mmap(), if there are no frames available, call poll() even if we're in non-blocking mode, so we pick up errors, and check for the errors in question. Note that poll() works on BPF devices is Snow Leopard If an ENXIO or ENETDOWN is received, it may mean the device has gone away. Deal with it. For BPF, raise the default capture buffer size to from 32k to 512k Support ps_ifdrop on Linux Added a bunch of #ifdef directives to make wpcap.dll (WinPcap) compile under cygwin. Changes to Linux mmapped captures. Fix bug where create_ring would fail for particular snaplen and buffer size combinations Update pcap-config so that it handles libpcap requiring additional libraries Add workaround for threadsafeness on Windows Add missing mapping for DLT_ENC <-> LINKTYPE_ENC DLT: Add DLT_CAN_SOCKETCAN DLT: Add Solaris ipnet Don't check for DLT_IPNET if it's not defined Add link-layer types for Fibre Channel FC-2 Add link-layer types for Wireless HART Add link-layer types for AOS Add link-layer types for DECT Autoconf fixes (AIX, HP-UX, OSF/1, Tru64 cleanups) Install headers unconditionally, and include vlan.h/bluetooth.h if enabled Autoconf fixes+cleanup Support enabling/disabling bluetooth (--{en,dis}able-bluetooth) Support disabling SITA support (--without-sita) Return -1 on failure to create packet ring (if supported but creation failed) Fix handling of 'any' device, so that it can be opened, and no longer attempt to open it in Monitor mode Add support for snapshot length for USB Memory-Mapped Interface Fix configure and build on recent Linux kernels Fix memory-mapped Linux capture to support pcap_next() and pcap_next_ex() Fixes for Linux USB capture DLT: Add DLT_LINUX_EVDEV DLT: Add DLT_GSMTAP_UM DLT: Add DLT_GSMTAP_ABIS
2010-10-28 16:22:13 +00:00
/* These types have no matching 'native' DLT, but can be used with DLT_ERF above */
case TYPE_MC_RAW:
case TYPE_MC_RAW_CHANNEL:
case TYPE_IP_COUNTER:
case TYPE_TCP_FLOW_COUNTER:
case TYPE_INFINIBAND:
case TYPE_RAW_LINK:
case TYPE_INFINIBAND_LINK:
2009-03-21 20:43:56 +00:00
default:
/* Unhandled ERF type.
* Ignore rather than generating error
*/
continue;
} /* switch type */
/* Skip over extension headers */
caplen -= (8 * num_ext_hdr);
} /* ERF encapsulation */
if (caplen > p->snapshot)
caplen = p->snapshot;
2006-09-04 19:43:23 +00:00
/* Run the packet filter if there is one. */
if ((p->fcode.bf_insns == NULL) || bpf_filter(p->fcode.bf_insns, dp, packet_len, caplen)) {
2009-03-21 20:43:56 +00:00
2006-09-04 19:43:23 +00:00
/* convert between timestamp formats */
register unsigned long long ts;
2006-09-04 19:43:23 +00:00
if (IS_BIGENDIAN()) {
2007-10-16 02:02:02 +00:00
ts = SWAPLL(header->ts);
2006-09-04 19:43:23 +00:00
} else {
ts = header->ts;
}
2006-09-04 19:43:23 +00:00
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++;
}
2006-09-04 19:43:23 +00:00
/* Fill in our own header data */
pcap_header.caplen = caplen;
pcap_header.len = packet_len;
2006-09-04 19:43:23 +00:00
/* Count the packet. */
2015-01-06 18:58:31 +00:00
pd->stat.ps_recv++;
2006-09-04 19:43:23 +00:00
/* Call the user supplied callback function */
callback(user, &pcap_header, dp);
2006-09-04 19:43:23 +00:00
/* Only count packets that pass the filter, for consistency with standard Linux behaviour. */
processed++;
2015-01-06 18:58:31 +00:00
if (processed == cnt && !PACKET_COUNT_IS_UNLIMITED(cnt))
2006-09-04 19:43:23 +00:00
{
/* Reached the user-specified limit. */
return cnt;
}
}
}
2006-09-04 19:43:23 +00:00
return processed;
}
static int
dag_inject(pcap_t *p, const void *buf _U_, size_t size _U_)
{
strlcpy(p->errbuf, "Sending packets isn't supported on DAG cards",
PCAP_ERRBUF_SIZE);
return (-1);
}
/*
* Get a handle for a live capture from the given DAG device. Passing a NULL
* device will result in a failure. The promisc flag is ignored because DAG
2009-03-21 20:43:56 +00:00
* cards are always promiscuous. The to_ms parameter is used in setting the
* API polling parameters.
*
2007-10-16 02:02:02 +00:00
* snaplen is now also ignored, until we get per-stream slen support. Set
2009-03-21 20:43:56 +00:00
* slen with approprite DAG tool BEFORE pcap_activate().
2007-10-16 02:02:02 +00:00
*
* See also pcap(3).
*/
2009-03-21 20:43:56 +00:00
static int dag_activate(pcap_t* handle)
{
2015-01-06 18:58:31 +00:00
struct pcap_dag *handlep = handle->priv;
2009-03-21 20:43:56 +00:00
#if 0
char conf[30]; /* dag configure string */
2009-03-21 20:43:56 +00:00
#endif
char *s;
int n;
daginf_t* daginf;
2007-10-16 02:02:02 +00:00
char * newDev = NULL;
2009-03-21 20:43:56 +00:00
char * device = handle->opt.source;
2006-09-04 19:43:23 +00:00
#ifdef HAVE_DAG_STREAMS_API
uint32_t mindata;
struct timeval maxwait;
struct timeval poll;
#endif
if (device == NULL) {
2009-03-21 20:43:56 +00:00
snprintf(handle->errbuf, PCAP_ERRBUF_SIZE, "device is NULL: %s", pcap_strerror(errno));
return -1;
}
/* Initialize some components of the pcap structure. */
2006-09-04 19:43:23 +00:00
#ifdef HAVE_DAG_STREAMS_API
2007-10-16 02:02:02 +00:00
newDev = (char *)malloc(strlen(device) + 16);
if (newDev == NULL) {
2009-03-21 20:43:56 +00:00
snprintf(handle->errbuf, PCAP_ERRBUF_SIZE, "Can't allocate string for device name: %s\n", pcap_strerror(errno));
2007-10-16 02:02:02 +00:00
goto fail;
}
2006-09-04 19:43:23 +00:00
/* Parse input name to get dag device and stream number if provided */
2015-01-06 18:58:31 +00:00
if (dag_parse_name(device, newDev, strlen(device) + 16, &handlep->dag_stream) < 0) {
2009-03-21 20:43:56 +00:00
snprintf(handle->errbuf, PCAP_ERRBUF_SIZE, "dag_parse_name: %s\n", pcap_strerror(errno));
2006-09-04 19:43:23 +00:00
goto fail;
}
device = newDev;
2015-01-06 18:58:31 +00:00
if (handlep->dag_stream%2) {
2009-03-21 20:43:56 +00:00
snprintf(handle->errbuf, PCAP_ERRBUF_SIZE, "dag_parse_name: tx (even numbered) streams not supported for capture\n");
2006-09-04 19:43:23 +00:00
goto fail;
}
#else
2007-10-16 02:02:02 +00:00
if (strncmp(device, "/dev/", 5) != 0) {
newDev = (char *)malloc(strlen(device) + 5);
if (newDev == NULL) {
2009-03-21 20:43:56 +00:00
snprintf(handle->errbuf, PCAP_ERRBUF_SIZE, "Can't allocate string for device name: %s\n", pcap_strerror(errno));
2007-10-16 02:02:02 +00:00
goto fail;
}
strcpy(newDev, "/dev/");
strcat(newDev, device);
device = newDev;
}
2006-09-04 19:43:23 +00:00
#endif /* HAVE_DAG_STREAMS_API */
/* setup device parameters */
if((handle->fd = dag_open((char *)device)) < 0) {
2009-03-21 20:43:56 +00:00
snprintf(handle->errbuf, PCAP_ERRBUF_SIZE, "dag_open %s: %s", device, pcap_strerror(errno));
goto fail;
}
2006-09-04 19:43:23 +00:00
#ifdef HAVE_DAG_STREAMS_API
/* Open requested stream. Can fail if already locked or on error */
2015-01-06 18:58:31 +00:00
if (dag_attach_stream(handle->fd, handlep->dag_stream, 0, 0) < 0) {
2009-03-21 20:43:56 +00:00
snprintf(handle->errbuf, PCAP_ERRBUF_SIZE, "dag_attach_stream: %s\n", pcap_strerror(errno));
2007-10-16 02:02:02 +00:00
goto failclose;
2006-09-04 19:43:23 +00:00
}
/* Set up default poll parameters for stream
* Can be overridden by pcap_set_nonblock()
*/
2015-01-06 18:58:31 +00:00
if (dag_get_stream_poll(handle->fd, handlep->dag_stream,
2006-09-04 19:43:23 +00:00
&mindata, &maxwait, &poll) < 0) {
2009-03-21 20:43:56 +00:00
snprintf(handle->errbuf, PCAP_ERRBUF_SIZE, "dag_get_stream_poll: %s\n", pcap_strerror(errno));
2007-10-16 02:02:02 +00:00
goto faildetach;
2006-09-04 19:43:23 +00:00
}
2015-01-06 18:58:31 +00:00
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;
}
2006-09-04 19:43:23 +00:00
2015-01-06 18:58:31 +00:00
/* Obey opt.timeout (was to_ms) if supplied. This is a good idea!
2006-09-04 19:43:23 +00:00
* Recommend 10-100ms. Calls will time out even if no data arrived.
*/
2015-01-06 18:58:31 +00:00
maxwait.tv_sec = handle->opt.timeout/1000;
maxwait.tv_usec = (handle->opt.timeout%1000) * 1000;
2006-09-04 19:43:23 +00:00
2015-01-06 18:58:31 +00:00
if (dag_set_stream_poll(handle->fd, handlep->dag_stream,
2006-09-04 19:43:23 +00:00
mindata, &maxwait, &poll) < 0) {
2009-03-21 20:43:56 +00:00
snprintf(handle->errbuf, PCAP_ERRBUF_SIZE, "dag_set_stream_poll: %s\n", pcap_strerror(errno));
2007-10-16 02:02:02 +00:00
goto faildetach;
2006-09-04 19:43:23 +00:00
}
#else
2015-01-06 18:58:31 +00:00
if((handlep->dag_mem_base = dag_mmap(handle->fd)) == MAP_FAILED) {
2009-03-21 20:43:56 +00:00
snprintf(handle->errbuf, PCAP_ERRBUF_SIZE,"dag_mmap %s: %s\n", device, pcap_strerror(errno));
2007-10-16 02:02:02 +00:00
goto failclose;
2006-09-04 19:43:23 +00:00
}
#endif /* HAVE_DAG_STREAMS_API */
2007-10-16 02:02:02 +00:00
/* 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 */
2007-10-16 02:02:02 +00:00
/* This is a really bad idea, as different cards have different
* valid slen ranges. Should fix in Config API. */
2009-03-21 20:43:56 +00:00
if (handle->snapshot == 0 || handle->snapshot > MAX_DAG_SNAPLEN) {
handle->snapshot = MAX_DAG_SNAPLEN;
} else if (snaplen < MIN_DAG_SNAPLEN) {
2009-03-21 20:43:56 +00:00
handle->snapshot = 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) {
2009-03-21 20:43:56 +00:00
snprintf(handle->errbuf, PCAP_ERRBUF_SIZE,"dag_configure %s: %s\n", device, pcap_strerror(errno));
2007-10-16 02:02:02 +00:00
goto faildetach;
}
2007-10-16 02:02:02 +00:00
#endif
2006-09-04 19:43:23 +00:00
#ifdef HAVE_DAG_STREAMS_API
2015-01-06 18:58:31 +00:00
if(dag_start_stream(handle->fd, handlep->dag_stream) < 0) {
2009-03-21 20:43:56 +00:00
snprintf(handle->errbuf, PCAP_ERRBUF_SIZE, "dag_start_stream %s: %s\n", device, pcap_strerror(errno));
2007-10-16 02:02:02 +00:00
goto faildetach;
}
2006-09-04 19:43:23 +00:00
#else
if(dag_start(handle->fd) < 0) {
2009-03-21 20:43:56 +00:00
snprintf(handle->errbuf, PCAP_ERRBUF_SIZE, "dag_start %s: %s\n", device, pcap_strerror(errno));
2007-10-16 02:02:02 +00:00
goto failclose;
}
2006-09-04 19:43:23 +00:00
#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!
*/
2015-01-06 18:58:31 +00:00
handlep->dag_mem_bottom = 0;
handlep->dag_mem_top = 0;
2009-03-21 20:43:56 +00:00
/*
* 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);
2009-03-21 20:43:56 +00:00
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. */
2015-01-06 18:58:31 +00:00
handlep->dag_fcs_bits = 0;
2009-03-21 20:43:56 +00:00
/* Note that no FCS will be supplied. */
handle->linktype_ext = LT_FCS_DATALINK_EXT(0);
} else {
/*
* Start out assuming it's 32 bits.
*/
2015-01-06 18:58:31 +00:00
handlep->dag_fcs_bits = 32;
2009-03-21 20:43:56 +00:00
/* Allow an environment variable to override. */
if ((s = getenv("ERF_FCS_BITS")) != NULL) {
if ((n = atoi(s)) == 0 || n == 16 || n == 32) {
2015-01-06 18:58:31 +00:00
handlep->dag_fcs_bits = n;
2009-03-21 20:43:56 +00:00
} else {
snprintf(handle->errbuf, PCAP_ERRBUF_SIZE,
"pcap_activate %s: bad ERF_FCS_BITS value (%d) in environment\n", 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. */
2015-01-06 18:58:31 +00:00
handle->linktype_ext = LT_FCS_DATALINK_EXT(handlep->dag_fcs_bits/16);
2009-03-21 20:43:56 +00:00
/* And don't strip them. */
2015-01-06 18:58:31 +00:00
handlep->dag_fcs_bits = 0;
}
}
2015-01-06 18:58:31 +00:00
handlep->dag_timeout = handle->opt.timeout;
handle->linktype = -1;
2009-03-21 20:43:56 +00:00
if (dag_get_datalink(handle) < 0)
2007-10-16 02:02:02 +00:00
goto failstop;
handle->bufsize = 0;
if (new_pcap_dag(handle) < 0) {
2009-03-21 20:43:56 +00:00
snprintf(handle->errbuf, PCAP_ERRBUF_SIZE, "new_pcap_dag %s: %s\n", device, pcap_strerror(errno));
2007-10-16 02:02:02 +00:00
goto failstop;
}
/*
2006-09-04 19:43:23 +00:00
* "select()" and "poll()" don't work on DAG device descriptors.
*/
handle->selectable_fd = -1;
2007-10-16 02:02:02 +00:00
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;
2009-03-21 20:43:56 +00:00
handle->cleanup_op = dag_platform_cleanup;
2015-01-06 18:58:31 +00:00
handlep->stat.ps_drop = 0;
handlep->stat.ps_recv = 0;
handlep->stat.ps_ifdrop = 0;
2009-03-21 20:43:56 +00:00
return 0;
2007-10-16 02:02:02 +00:00
#ifdef HAVE_DAG_STREAMS_API
failstop:
2015-01-06 18:58:31 +00:00
if (dag_stop_stream(handle->fd, handlep->dag_stream) < 0) {
2009-03-21 20:43:56 +00:00
fprintf(stderr,"dag_stop_stream: %s\n", strerror(errno));
2007-10-16 02:02:02 +00:00
}
faildetach:
2015-01-06 18:58:31 +00:00
if (dag_detach_stream(handle->fd, handlep->dag_stream) < 0)
2009-03-21 20:43:56 +00:00
fprintf(stderr,"dag_detach_stream: %s\n", strerror(errno));
#else
2007-10-16 02:02:02 +00:00
failstop:
2009-03-21 20:43:56 +00:00
if (dag_stop(handle->fd) < 0)
fprintf(stderr,"dag_stop: %s\n", strerror(errno));
2007-10-16 02:02:02 +00:00
#endif /* HAVE_DAG_STREAMS_API */
failclose:
2009-03-21 20:43:56 +00:00
if (dag_close(handle->fd) < 0)
fprintf(stderr,"dag_close: %s\n", strerror(errno));
delete_pcap_dag(handle);
fail:
2009-03-21 20:43:56 +00:00
pcap_cleanup_live_common(handle);
2006-09-04 19:43:23 +00:00
if (newDev != NULL) {
free((char *)newDev);
}
2009-03-21 20:43:56 +00:00
return PCAP_ERROR;
}
2013-05-30 06:41:26 +00:00
pcap_t *dag_create(const char *device, char *ebuf, int *is_ours)
2009-03-21 20:43:56 +00:00
{
2013-05-30 06:41:26 +00:00
const char *cp;
char *cpend;
long devnum;
2009-03-21 20:43:56 +00:00
pcap_t *p;
2015-01-06 18:58:31 +00:00
#ifdef HAVE_DAG_STREAMS_API
long stream = 0;
#endif
2009-03-21 20:43:56 +00:00
2013-05-30 06:41:26 +00:00
/* Does this look like a DAG device? */
cp = strrchr(device, '/');
if (cp == NULL)
cp = device;
/* Does it begin with "dag"? */
if (strncmp(cp, "dag", 3) != 0) {
/* Nope, doesn't begin with "dag" */
*is_ours = 0;
return NULL;
}
2015-01-06 18:58:31 +00:00
/* Yes - is "dag" followed by a number from 0 to DAG_MAX_BOARDS-1 */
2013-05-30 06:41:26 +00:00
cp += 3;
devnum = strtol(cp, &cpend, 10);
2015-01-06 18:58:31 +00:00
#ifdef HAVE_DAG_STREAMS_API
if (*cpend == ':') {
/* Followed by a stream number. */
stream = strtol(++cpend, &cpend, 10);
}
#endif
2013-05-30 06:41:26 +00:00
if (cpend == cp || *cpend != '\0') {
/* Not followed by a number. */
*is_ours = 0;
return NULL;
}
2015-01-06 18:58:31 +00:00
if (devnum < 0 || devnum >= DAG_MAX_BOARDS) {
2013-05-30 06:41:26 +00:00
/* Followed by a non-valid number. */
*is_ours = 0;
return NULL;
}
2015-01-06 18:58:31 +00:00
#ifdef HAVE_DAG_STREAMS_API
if (stream <0 || stream >= DAG_STREAM_MAX) {
/* Followed by a non-valid stream number. */
*is_ours = 0;
return NULL;
}
#endif
2013-05-30 06:41:26 +00:00
/* OK, it's probably ours. */
*is_ours = 1;
2015-01-06 18:58:31 +00:00
p = pcap_create_common(device, ebuf, sizeof (struct pcap_dag));
2009-03-21 20:43:56 +00:00
if (p == NULL)
return NULL;
p->activate_op = dag_activate;
return p;
}
static int
dag_stats(pcap_t *p, struct pcap_stat *ps) {
2015-01-06 18:58:31 +00:00
struct pcap_dag *pd = p->priv;
/* This needs to be filled out correctly. Hopefully a dagapi call will
provide all necessary information.
*/
2015-01-06 18:58:31 +00:00
/*pd->stat.ps_recv = 0;*/
/*pd->stat.ps_drop = 0;*/
2015-01-06 18:58:31 +00:00
*ps = pd->stat;
return 0;
}
/*
2009-03-21 20:43:56 +00:00
* Previously we just generated a list of all possible names and let
* pcap_add_if() attempt to open each one, but with streams this adds up
* to 81 possibilities which is inefficient.
*
* Since we know more about the devices we can prune the tree here.
* pcap_add_if() will still retest each device but the total number of
* open attempts will still be much less than the naive approach.
*/
int
2013-05-30 06:41:26 +00:00
dag_findalldevs(pcap_if_t **devlistp, char *errbuf)
{
2006-09-04 19:43:23 +00:00
char name[12]; /* XXX - pick a size */
int ret = 0;
2006-09-04 19:43:23 +00:00
int c;
2009-03-21 20:43:56 +00:00
char dagname[DAGNAME_BUFSIZE];
int dagstream;
int dagfd;
2015-01-06 18:58:31 +00:00
/* Try all the DAGs 0-DAG_MAX_BOARDS */
for (c = 0; c < DAG_MAX_BOARDS; c++) {
2006-09-04 19:43:23 +00:00
snprintf(name, 12, "dag%d", c);
2009-03-21 20:43:56 +00:00
if (-1 == dag_parse_name(name, dagname, DAGNAME_BUFSIZE, &dagstream))
2006-09-04 19:43:23 +00:00
{
2009-03-21 20:43:56 +00:00
return -1;
}
2009-03-21 20:43:56 +00:00
if ( (dagfd = dag_open(dagname)) >= 0 ) {
if (pcap_add_if(devlistp, name, 0, NULL, errbuf) == -1) {
/*
* Failure.
*/
ret = -1;
}
#ifdef HAVE_DAG_STREAMS_API
{
int stream, rxstreams;
rxstreams = dag_rx_get_stream_count(dagfd);
for(stream=0;stream<DAG_STREAM_MAX;stream+=2) {
2009-03-21 20:43:56 +00:00
if (0 == dag_attach_stream(dagfd, stream, 0, 0)) {
dag_detach_stream(dagfd, stream);
snprintf(name, 10, "dag%d:%d", c, stream);
if (pcap_add_if(devlistp, name, 0, NULL, errbuf) == -1) {
/*
* Failure.
*/
ret = -1;
}
rxstreams--;
if(rxstreams <= 0) {
break;
}
2009-03-21 20:43:56 +00:00
}
}
}
2006-09-04 19:43:23 +00:00
#endif /* HAVE_DAG_STREAMS_API */
2009-03-21 20:43:56 +00:00
dag_close(dagfd);
}
}
return (ret);
}
/*
* Installs the given bpf filter program in the given pcap structure. There is
* 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)
return -1;
return (0);
}
static int
dag_set_datalink(pcap_t *p, int dlt)
{
p->linktype = dlt;
return (0);
}
static int
dag_setnonblock(pcap_t *p, int nonblock, char *errbuf)
{
2015-01-06 18:58:31 +00:00
struct pcap_dag *pd = p->priv;
/*
* Set non-blocking mode on the FD.
* XXX - is that necessary? If not, don't bother calling it,
* and have a "dag_getnonblock()" function that looks at
2015-01-06 18:58:31 +00:00
* "pd->dag_offset_flags".
*/
if (pcap_setnonblock_fd(p, nonblock, errbuf) < 0)
return (-1);
2006-09-04 19:43:23 +00:00
#ifdef HAVE_DAG_STREAMS_API
{
uint32_t mindata;
struct timeval maxwait;
struct timeval poll;
2015-01-06 18:58:31 +00:00
if (dag_get_stream_poll(p->fd, pd->dag_stream,
2006-09-04 19:43:23 +00:00
&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;
2015-01-06 18:58:31 +00:00
if (dag_set_stream_poll(p->fd, pd->dag_stream,
2006-09-04 19:43:23 +00:00
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) {
2015-01-06 18:58:31 +00:00
pd->dag_offset_flags |= DAGF_NONBLOCK;
} else {
2015-01-06 18:58:31 +00:00
pd->dag_offset_flags &= ~DAGF_NONBLOCK;
}
return (0);
}
static int
dag_get_datalink(pcap_t *p)
{
2015-01-06 18:58:31 +00:00
struct pcap_dag *pd = p->priv;
2009-03-21 20:43:56 +00:00
int index=0, dlt_index=0;
2007-10-16 02:02:02 +00:00
uint8_t types[255];
2007-10-16 02:02:02 +00:00
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);
}
2007-10-16 02:02:02 +00:00
p->linktype = 0;
2009-03-21 20:43:56 +00:00
#ifdef HAVE_DAG_GET_STREAM_ERF_TYPES
/* Get list of possible ERF types for this card */
2015-01-06 18:58:31 +00:00
if (dag_get_stream_erf_types(p->fd, pd->dag_stream, types, 255) < 0) {
2009-03-21 20:43:56 +00:00
snprintf(p->errbuf, sizeof(p->errbuf), "dag_get_stream_erf_types: %s", pcap_strerror(errno));
return (-1);
}
while (types[index]) {
#elif defined HAVE_DAG_GET_ERF_TYPES
2007-10-16 02:02:02 +00:00
/* 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. */
2007-10-16 02:02:02 +00:00
types[index] = dag_linktype(p->fd);
2007-10-16 02:02:02 +00:00
{
#endif
2009-03-21 20:43:56 +00:00
switch((types[index] & 0x7f)) {
2007-10-16 02:02:02 +00:00
case TYPE_HDLC_POS:
case TYPE_COLOR_HDLC_POS:
case TYPE_DSM_COLOR_HDLC_POS:
2009-03-21 20:43:56 +00:00
case TYPE_COLOR_HASH_POS:
2007-10-16 02:02:02 +00:00
if (p->dlt_list != NULL) {
2009-03-21 20:43:56 +00:00
p->dlt_list[dlt_index++] = DLT_CHDLC;
p->dlt_list[dlt_index++] = DLT_PPP_SERIAL;
p->dlt_list[dlt_index++] = DLT_FRELAY;
2007-10-16 02:02:02 +00:00
}
if(!p->linktype)
p->linktype = DLT_CHDLC;
break;
2007-10-16 02:02:02 +00:00
case TYPE_ETH:
case TYPE_COLOR_ETH:
case TYPE_DSM_COLOR_ETH:
2009-03-21 20:43:56 +00:00
case TYPE_COLOR_HASH_ETH:
2007-10-16 02:02:02 +00:00
/*
* 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) {
2009-03-21 20:43:56 +00:00
p->dlt_list[dlt_index++] = DLT_EN10MB;
p->dlt_list[dlt_index++] = DLT_DOCSIS;
2007-10-16 02:02:02 +00:00
}
if(!p->linktype)
p->linktype = DLT_EN10MB;
break;
2007-10-16 02:02:02 +00:00
case TYPE_ATM:
case TYPE_AAL5:
case TYPE_MC_ATM:
case TYPE_MC_AAL5:
if (p->dlt_list != NULL) {
2009-03-21 20:43:56 +00:00
p->dlt_list[dlt_index++] = DLT_ATM_RFC1483;
p->dlt_list[dlt_index++] = DLT_SUNATM;
2007-10-16 02:02:02 +00:00
}
if(!p->linktype)
p->linktype = DLT_ATM_RFC1483;
break;
2007-10-16 02:02:02 +00:00
case TYPE_COLOR_MC_HDLC_POS:
case TYPE_MC_HDLC:
if (p->dlt_list != NULL) {
2009-03-21 20:43:56 +00:00
p->dlt_list[dlt_index++] = DLT_CHDLC;
p->dlt_list[dlt_index++] = DLT_PPP_SERIAL;
p->dlt_list[dlt_index++] = DLT_FRELAY;
p->dlt_list[dlt_index++] = DLT_MTP2;
p->dlt_list[dlt_index++] = DLT_MTP2_WITH_PHDR;
p->dlt_list[dlt_index++] = DLT_LAPD;
2007-10-16 02:02:02 +00:00
}
if(!p->linktype)
p->linktype = DLT_CHDLC;
break;
2009-03-21 20:43:56 +00:00
case TYPE_IPV4:
Update libpcap to 1.1.1. Changes: Thu. April 1, 2010. guy@alum.mit.edu. Summary for 1.1.1 libpcap release Update CHANGES to reflect more of the changes in 1.1.0. Fix build on RHEL5. Fix shared library build on AIX. Thu. March 11, 2010. ken@netfunctional.ca/guy@alum.mit.edu. Summary for 1.1.0 libpcap release Add SocketCAN capture support Add Myricom SNF API support Update Endace DAG and ERF support Add support for shared libraries on Solaris, HP-UX, and AIX Build, install, and un-install shared libraries by default; don't build/install shared libraries on platforms we don't support Fix building from a directory other than the source directory Fix compiler warnings and builds on some platforms Update config.guess and config.sub Support monitor mode on mac80211 devices on Linux Fix USB memory-mapped capturing on Linux; it requires a new DLT_ value On Linux, scan /sys/class/net for devices if we have it; scan it, or /proc/net/dev if we don't have /sys/class/net, even if we have getifaddrs(), as it'll find interfaces with no addresses Add limited support for reading pcap-ng files Fix BPF driver-loading error handling on AIX Support getting the full-length interface description on FreeBSD In the lexical analyzer, free up any addrinfo structure we got back from getaddrinfo(). Add support for BPF and libdlpi in OpenSolaris (and SXCE) Hyphenate "link-layer" everywhere Add /sys/kernel/debug/usb/usbmon to the list of usbmon locations In pcap_read_linux_mmap(), if there are no frames available, call poll() even if we're in non-blocking mode, so we pick up errors, and check for the errors in question. Note that poll() works on BPF devices is Snow Leopard If an ENXIO or ENETDOWN is received, it may mean the device has gone away. Deal with it. For BPF, raise the default capture buffer size to from 32k to 512k Support ps_ifdrop on Linux Added a bunch of #ifdef directives to make wpcap.dll (WinPcap) compile under cygwin. Changes to Linux mmapped captures. Fix bug where create_ring would fail for particular snaplen and buffer size combinations Update pcap-config so that it handles libpcap requiring additional libraries Add workaround for threadsafeness on Windows Add missing mapping for DLT_ENC <-> LINKTYPE_ENC DLT: Add DLT_CAN_SOCKETCAN DLT: Add Solaris ipnet Don't check for DLT_IPNET if it's not defined Add link-layer types for Fibre Channel FC-2 Add link-layer types for Wireless HART Add link-layer types for AOS Add link-layer types for DECT Autoconf fixes (AIX, HP-UX, OSF/1, Tru64 cleanups) Install headers unconditionally, and include vlan.h/bluetooth.h if enabled Autoconf fixes+cleanup Support enabling/disabling bluetooth (--{en,dis}able-bluetooth) Support disabling SITA support (--without-sita) Return -1 on failure to create packet ring (if supported but creation failed) Fix handling of 'any' device, so that it can be opened, and no longer attempt to open it in Monitor mode Add support for snapshot length for USB Memory-Mapped Interface Fix configure and build on recent Linux kernels Fix memory-mapped Linux capture to support pcap_next() and pcap_next_ex() Fixes for Linux USB capture DLT: Add DLT_LINUX_EVDEV DLT: Add DLT_GSMTAP_UM DLT: Add DLT_GSMTAP_ABIS
2010-10-28 16:22:13 +00:00
case TYPE_IPV6:
2007-10-16 02:02:02 +00:00
if(!p->linktype)
2009-03-21 20:43:56 +00:00
p->linktype = DLT_RAW;
2007-10-16 02:02:02 +00:00
break;
2009-03-21 20:43:56 +00:00
case TYPE_LEGACY:
case TYPE_MC_RAW:
case TYPE_MC_RAW_CHANNEL:
case TYPE_IP_COUNTER:
case TYPE_TCP_FLOW_COUNTER:
case TYPE_INFINIBAND:
Update libpcap to 1.1.1. Changes: Thu. April 1, 2010. guy@alum.mit.edu. Summary for 1.1.1 libpcap release Update CHANGES to reflect more of the changes in 1.1.0. Fix build on RHEL5. Fix shared library build on AIX. Thu. March 11, 2010. ken@netfunctional.ca/guy@alum.mit.edu. Summary for 1.1.0 libpcap release Add SocketCAN capture support Add Myricom SNF API support Update Endace DAG and ERF support Add support for shared libraries on Solaris, HP-UX, and AIX Build, install, and un-install shared libraries by default; don't build/install shared libraries on platforms we don't support Fix building from a directory other than the source directory Fix compiler warnings and builds on some platforms Update config.guess and config.sub Support monitor mode on mac80211 devices on Linux Fix USB memory-mapped capturing on Linux; it requires a new DLT_ value On Linux, scan /sys/class/net for devices if we have it; scan it, or /proc/net/dev if we don't have /sys/class/net, even if we have getifaddrs(), as it'll find interfaces with no addresses Add limited support for reading pcap-ng files Fix BPF driver-loading error handling on AIX Support getting the full-length interface description on FreeBSD In the lexical analyzer, free up any addrinfo structure we got back from getaddrinfo(). Add support for BPF and libdlpi in OpenSolaris (and SXCE) Hyphenate "link-layer" everywhere Add /sys/kernel/debug/usb/usbmon to the list of usbmon locations In pcap_read_linux_mmap(), if there are no frames available, call poll() even if we're in non-blocking mode, so we pick up errors, and check for the errors in question. Note that poll() works on BPF devices is Snow Leopard If an ENXIO or ENETDOWN is received, it may mean the device has gone away. Deal with it. For BPF, raise the default capture buffer size to from 32k to 512k Support ps_ifdrop on Linux Added a bunch of #ifdef directives to make wpcap.dll (WinPcap) compile under cygwin. Changes to Linux mmapped captures. Fix bug where create_ring would fail for particular snaplen and buffer size combinations Update pcap-config so that it handles libpcap requiring additional libraries Add workaround for threadsafeness on Windows Add missing mapping for DLT_ENC <-> LINKTYPE_ENC DLT: Add DLT_CAN_SOCKETCAN DLT: Add Solaris ipnet Don't check for DLT_IPNET if it's not defined Add link-layer types for Fibre Channel FC-2 Add link-layer types for Wireless HART Add link-layer types for AOS Add link-layer types for DECT Autoconf fixes (AIX, HP-UX, OSF/1, Tru64 cleanups) Install headers unconditionally, and include vlan.h/bluetooth.h if enabled Autoconf fixes+cleanup Support enabling/disabling bluetooth (--{en,dis}able-bluetooth) Support disabling SITA support (--without-sita) Return -1 on failure to create packet ring (if supported but creation failed) Fix handling of 'any' device, so that it can be opened, and no longer attempt to open it in Monitor mode Add support for snapshot length for USB Memory-Mapped Interface Fix configure and build on recent Linux kernels Fix memory-mapped Linux capture to support pcap_next() and pcap_next_ex() Fixes for Linux USB capture DLT: Add DLT_LINUX_EVDEV DLT: Add DLT_GSMTAP_UM DLT: Add DLT_GSMTAP_ABIS
2010-10-28 16:22:13 +00:00
case TYPE_RAW_LINK:
case TYPE_INFINIBAND_LINK:
2007-10-16 02:02:02 +00:00
default:
2009-03-21 20:43:56 +00:00
/* Libpcap cannot deal with these types yet */
Update libpcap to 1.1.1. Changes: Thu. April 1, 2010. guy@alum.mit.edu. Summary for 1.1.1 libpcap release Update CHANGES to reflect more of the changes in 1.1.0. Fix build on RHEL5. Fix shared library build on AIX. Thu. March 11, 2010. ken@netfunctional.ca/guy@alum.mit.edu. Summary for 1.1.0 libpcap release Add SocketCAN capture support Add Myricom SNF API support Update Endace DAG and ERF support Add support for shared libraries on Solaris, HP-UX, and AIX Build, install, and un-install shared libraries by default; don't build/install shared libraries on platforms we don't support Fix building from a directory other than the source directory Fix compiler warnings and builds on some platforms Update config.guess and config.sub Support monitor mode on mac80211 devices on Linux Fix USB memory-mapped capturing on Linux; it requires a new DLT_ value On Linux, scan /sys/class/net for devices if we have it; scan it, or /proc/net/dev if we don't have /sys/class/net, even if we have getifaddrs(), as it'll find interfaces with no addresses Add limited support for reading pcap-ng files Fix BPF driver-loading error handling on AIX Support getting the full-length interface description on FreeBSD In the lexical analyzer, free up any addrinfo structure we got back from getaddrinfo(). Add support for BPF and libdlpi in OpenSolaris (and SXCE) Hyphenate "link-layer" everywhere Add /sys/kernel/debug/usb/usbmon to the list of usbmon locations In pcap_read_linux_mmap(), if there are no frames available, call poll() even if we're in non-blocking mode, so we pick up errors, and check for the errors in question. Note that poll() works on BPF devices is Snow Leopard If an ENXIO or ENETDOWN is received, it may mean the device has gone away. Deal with it. For BPF, raise the default capture buffer size to from 32k to 512k Support ps_ifdrop on Linux Added a bunch of #ifdef directives to make wpcap.dll (WinPcap) compile under cygwin. Changes to Linux mmapped captures. Fix bug where create_ring would fail for particular snaplen and buffer size combinations Update pcap-config so that it handles libpcap requiring additional libraries Add workaround for threadsafeness on Windows Add missing mapping for DLT_ENC <-> LINKTYPE_ENC DLT: Add DLT_CAN_SOCKETCAN DLT: Add Solaris ipnet Don't check for DLT_IPNET if it's not defined Add link-layer types for Fibre Channel FC-2 Add link-layer types for Wireless HART Add link-layer types for AOS Add link-layer types for DECT Autoconf fixes (AIX, HP-UX, OSF/1, Tru64 cleanups) Install headers unconditionally, and include vlan.h/bluetooth.h if enabled Autoconf fixes+cleanup Support enabling/disabling bluetooth (--{en,dis}able-bluetooth) Support disabling SITA support (--without-sita) Return -1 on failure to create packet ring (if supported but creation failed) Fix handling of 'any' device, so that it can be opened, and no longer attempt to open it in Monitor mode Add support for snapshot length for USB Memory-Mapped Interface Fix configure and build on recent Linux kernels Fix memory-mapped Linux capture to support pcap_next() and pcap_next_ex() Fixes for Linux USB capture DLT: Add DLT_LINUX_EVDEV DLT: Add DLT_GSMTAP_UM DLT: Add DLT_GSMTAP_ABIS
2010-10-28 16:22:13 +00:00
/* Add no 'native' DLTs, but still covered by DLT_ERF */
2009-03-21 20:43:56 +00:00
break;
2007-10-16 02:02:02 +00:00
} /* switch */
2009-03-21 20:43:56 +00:00
index++;
}
2009-03-21 20:43:56 +00:00
p->dlt_list[dlt_index++] = DLT_ERF;
p->dlt_count = dlt_index;
if(!p->linktype)
p->linktype = DLT_ERF;
2007-10-16 02:02:02 +00:00
return p->linktype;
}