#include <stropts.h>
#include <unistd.h>
+#include <libdlpi.h>
+
#include "pcap-int.h"
#include "dlpisubs.h"
int
pcap_stats_dlpi(pcap_t *p, struct pcap_stat *ps)
{
+ struct pcap_dlpi *pd = p->private;
/*
* "ps_recv" counts packets handed to the filter, not packets
* the kernel by libpcap, but they may include packets not
* yet read from libpcap by the application.
*/
- *ps = p->md.stat;
+ *ps = pd->stat;
/*
* Add in the drop count, as per the above comment.
pcap_process_pkts(pcap_t *p, pcap_handler callback, u_char *user,
int count, u_char *bufp, int len)
{
+ struct pcap_dlpi *pd = p->private;
int n, caplen, origlen;
u_char *ep, *pk;
struct pcap_pkthdr pkthdr;
} else
#endif
sbp = (struct sb_hdr *)bufp;
- p->md.stat.ps_drop = sbp->sbh_drops;
+ pd->stat.ps_drop = sbp->sbh_drops;
pk = bufp + sizeof(*sbp);
bufp += sbp->sbh_totlen;
origlen = sbp->sbh_origlen;
pk = bufp;
bufp += caplen;
#endif
- ++p->md.stat.ps_recv;
+ ++pd->stat.ps_recv;
if (bpf_filter(p->fcode.bf_insns, pk, origlen, caplen)) {
#ifdef HAVE_SYS_BUFMOD_H
pkthdr.ts.tv_sec = sbp->sbh_timestamp.tv_sec;
#endif
/*
- * Functions used by dlpisubs.c.
+ * Private data for capturing on DLPI devices.
+ */
+struct pcap_dlpi {
+#ifdef HAVE_LIBDLPI
+ dlpi_handle_t dlpi_hd;
+#endif /* HAVE_LIBDLPI */
+#ifdef DL_HP_RAWDLS
+ int send_fd;
+#endif /* DL_HP_RAWDLS */
+
+ struct pcap_stat stat;
+};
+
+/*
+ * Functions defined by dlpisubs.c.
*/
int pcap_stats_dlpi(pcap_t *, struct pcap_stat *);
int pcap_process_pkts(pcap_t *, pcap_handler, u_char *, int, u_char *, int);
#endif
/* XXX */
-#ifdef PCAP_FDDIPAD
static int pcap_fddipad;
-#endif
/* VARARGS */
void
pcap_t *p;
{
linktype = pcap_datalink(p);
-#ifdef PCAP_FDDIPAD
pcap_fddipad = p->fddipad;
-#endif
/*
* Assume it's not raw ATM with a pseudo-header, for now.
* XXX - should we generate code to check for SNAP?
*/
off_linktype = 13;
-#ifdef PCAP_FDDIPAD
off_linktype += pcap_fddipad;
-#endif
off_macpl = 13; /* FDDI MAC header length */
-#ifdef PCAP_FDDIPAD
off_macpl += pcap_fddipad;
-#endif
off_nl = 8; /* 802.2+SNAP */
off_nl_nosnap = 3; /* 802.2 */
return;
* Then we run it through "htonl()", and
* generate code to compare against the result.
*/
- if (bpf_pcap->sf.rfile != NULL &&
- bpf_pcap->sf.swapped)
+ if (bpf_pcap->rfile != NULL && bpf_pcap->swapped)
proto = SWAPLONG(proto);
proto = htonl(proto);
}
switch (dir) {
case Q_SRC:
-#ifdef PCAP_FDDIPAD
return gen_bcmp(OR_LINK, 6 + 1 + pcap_fddipad, 6, eaddr);
-#else
- return gen_bcmp(OR_LINK, 6 + 1, 6, eaddr);
-#endif
case Q_DST:
-#ifdef PCAP_FDDIPAD
return gen_bcmp(OR_LINK, 0 + 1 + pcap_fddipad, 6, eaddr);
-#else
- return gen_bcmp(OR_LINK, 0 + 1, 6, eaddr);
-#endif
case Q_AND:
b0 = gen_fhostop(eaddr, Q_SRC);
* special meta-data in the filter expression;
* if it's a savefile, we can't.
*/
- if (bpf_pcap->sf.rfile != NULL) {
+ if (bpf_pcap->rfile != NULL) {
/* We have a FILE *, so this is a savefile */
bpf_error("inbound/outbound not supported on linktype %d when reading savefiles",
linktype);
#include "os-proto.h"
#endif
+/*
+ * Later versions of NetBSD stick padding in front of FDDI frames
+ * to align the IP header on a 4-byte boundary.
+ */
+#if defined(__NetBSD__) && __NetBSD_Version__ > 106000000
+#define PCAP_FDDIPAD 3
+#endif
+
+/*
+ * Private data for capturing on BPF devices.
+ */
+struct pcap_bpf {
+#ifdef PCAP_FDDIPAD
+ int fddipad;
+#endif
+
+#ifdef HAVE_ZEROCOPY_BPF
+ /*
+ * Zero-copy read buffer -- for zero-copy BPF. 'buffer' above will
+ * alternative between these two actual mmap'd buffers as required.
+ * As there is a header on the front size of the mmap'd buffer, only
+ * some of the buffer is exposed to libpcap as a whole via bufsize;
+ * zbufsize is the true size. zbuffer tracks the current zbuf
+ * assocated with buffer so that it can be used to decide which the
+ * next buffer to read will be.
+ */
+ u_char *zbuf1, *zbuf2, *zbuffer;
+ u_int zbufsize;
+ u_int zerocopy;
+ u_int interrupted;
+ struct timespec firstsel;
+ /*
+ * If there's currently a buffer being actively processed, then it is
+ * referenced here; 'buffer' is also pointed at it, but offset by the
+ * size of the header.
+ */
+ struct bpf_zbuf_header *bzh;
+#endif /* HAVE_ZEROCOPY_BPF */
+
+ char *device; /* device name */
+ int filtering_in_kernel; /* using kernel filter */
+ int timeout; /* timeout for buffering */
+ int must_do_on_close; /* stuff we must do when we close */
+};
+
+/*
+ * Stuff to do when we close.
+ */
+#define MUST_CLEAR_RFMON 0x00000001 /* clear rfmon (monitor) mode */
+
#ifdef BIOCGDLTLIST
# if (defined(HAVE_NET_IF_MEDIA_H) && defined(IFM_IEEE80211)) && !defined(__APPLE__)
#define HAVE_BSD_IEEE80211
/*
* For zerocopy bpf, the setnonblock/getnonblock routines need to modify
- * p->md.timeout so we don't call select(2) if the pcap handle is in non-
+ * pb->timeout so we don't call select(2) if the pcap handle is in non-
* blocking mode. We preserve the timeout supplied by pcap_open functions
* to make sure it does not get clobbered if the pcap handle moves between
* blocking and non-blocking mode.
pcap_getnonblock_bpf(pcap_t *p, char *errbuf)
{
#ifdef HAVE_ZEROCOPY_BPF
- if (p->md.zerocopy) {
+ struct pcap_bpf *pb = p->private;
+
+ if (pb->zerocopy) {
/*
* Use a negative value for the timeout to represent that the
* pcap handle is in non-blocking mode.
*/
- return (p->md.timeout < 0);
+ return (pb->timeout < 0);
}
#endif
return (pcap_getnonblock_fd(p, errbuf));
pcap_setnonblock_bpf(pcap_t *p, int nonblock, char *errbuf)
{
#ifdef HAVE_ZEROCOPY_BPF
- if (p->md.zerocopy) {
+ struct pcap_bpf *pb = p->private;
+
+ if (pb->zerocopy) {
/*
* Map each value to their corresponding negation to
* preserve the timeout value provided with pcap_set_timeout.
* (from pcap-linux.c).
*/
if (nonblock) {
- if (p->md.timeout >= 0) {
+ if (pb->timeout >= 0) {
/*
* Indicate that we're switching to
* non-blocking mode.
*/
- p->md.timeout = ~p->md.timeout;
+ pb->timeout = ~pb->timeout;
}
} else {
- if (p->md.timeout < 0) {
- p->md.timeout = ~p->md.timeout;
+ if (pb->timeout < 0) {
+ /*
+ * Timeout is negative, so we're currently
+ * in blocking mode; reverse the previous
+ * operation, to make the timeout non-negative
+ * again.
+ */
+ pb->timeout = ~pb->timeout;
}
}
return (0);
static int
pcap_next_zbuf_shm(pcap_t *p, int *cc)
{
+ struct pcap_bpf *pb = p->private;
struct bpf_zbuf_header *bzh;
- if (p->md.zbuffer == p->md.zbuf2 || p->md.zbuffer == NULL) {
- bzh = (struct bpf_zbuf_header *)p->md.zbuf1;
+ if (pb->zbuffer == pb->zbuf2 || pb->zbuffer == NULL) {
+ bzh = (struct bpf_zbuf_header *)pb->zbuf1;
if (bzh->bzh_user_gen !=
atomic_load_acq_int(&bzh->bzh_kernel_gen)) {
- p->md.bzh = bzh;
- p->md.zbuffer = (u_char *)p->md.zbuf1;
- p->buffer = p->md.zbuffer + sizeof(*bzh);
+ pb->bzh = bzh;
+ pb->zbuffer = (u_char *)pb->zbuf1;
+ p->buffer = pb->zbuffer + sizeof(*bzh);
*cc = bzh->bzh_kernel_len;
return (1);
}
- } else if (p->md.zbuffer == p->md.zbuf1) {
- bzh = (struct bpf_zbuf_header *)p->md.zbuf2;
+ } else if (pb->zbuffer == pb->zbuf1) {
+ bzh = (struct bpf_zbuf_header *)pb->zbuf2;
if (bzh->bzh_user_gen !=
atomic_load_acq_int(&bzh->bzh_kernel_gen)) {
- p->md.bzh = bzh;
- p->md.zbuffer = (u_char *)p->md.zbuf2;
- p->buffer = p->md.zbuffer + sizeof(*bzh);
+ pb->bzh = bzh;
+ pb->zbuffer = (u_char *)pb->zbuf2;
+ p->buffer = pb->zbuffer + sizeof(*bzh);
*cc = bzh->bzh_kernel_len;
return (1);
}
static int
pcap_next_zbuf(pcap_t *p, int *cc)
{
+ struct pcap_bpf *pb = p->private;
struct bpf_zbuf bz;
struct timeval tv;
struct timespec cur;
* our timeout is less then or equal to zero, handle it like a
* regular timeout.
*/
- tmout = p->md.timeout;
+ tmout = pb->timeout;
if (tmout)
(void) clock_gettime(CLOCK_MONOTONIC, &cur);
- if (p->md.interrupted && p->md.timeout) {
- expire = TSTOMILLI(&p->md.firstsel) + p->md.timeout;
+ if (pb->interrupted && pb->timeout) {
+ expire = TSTOMILLI(&pb->firstsel) + pb->timeout;
tmout = expire - TSTOMILLI(&cur);
#undef TSTOMILLI
if (tmout <= 0) {
- p->md.interrupted = 0;
+ pb->interrupted = 0;
data = pcap_next_zbuf_shm(p, cc);
if (data)
return (data);
* the next timeout. Note that we only call select if the handle
* is in blocking mode.
*/
- if (p->md.timeout >= 0) {
+ if (pb->timeout >= 0) {
FD_ZERO(&r_set);
FD_SET(p->fd, &r_set);
if (tmout != 0) {
tv.tv_usec = (tmout * 1000) % 1000000;
}
r = select(p->fd + 1, &r_set, NULL, NULL,
- p->md.timeout != 0 ? &tv : NULL);
+ pb->timeout != 0 ? &tv : NULL);
if (r < 0 && errno == EINTR) {
- if (!p->md.interrupted && p->md.timeout) {
- p->md.interrupted = 1;
- p->md.firstsel = cur;
+ if (!pb->interrupted && pb->timeout) {
+ pb->interrupted = 1;
+ pb->firstsel = cur;
}
return (0);
} else if (r < 0) {
return (PCAP_ERROR);
}
}
- p->md.interrupted = 0;
+ pb->interrupted = 0;
/*
* Check again for data, which may exist now that we've either been
* woken up as a result of data or timed out. Try the "there's data"
static int
pcap_ack_zbuf(pcap_t *p)
{
+ struct pcap_bpf *pb = p->private;
- atomic_store_rel_int(&p->md.bzh->bzh_user_gen,
- p->md.bzh->bzh_kernel_gen);
- p->md.bzh = NULL;
+ atomic_store_rel_int(&pb->bzh->bzh_user_gen,
+ pb->bzh->bzh_kernel_gen);
+ pb->bzh = NULL;
p->buffer = NULL;
return (0);
}
{
pcap_t *p;
- p = pcap_create_common(device, ebuf);
+ p = pcap_create_common(device, ebuf, sizeof (struct pcap_bpf));
if (p == NULL)
return (NULL);
static int
pcap_read_bpf(pcap_t *p, int cnt, pcap_handler callback, u_char *user)
{
+ struct pcap_bpf *pb = p->private;
int cc;
int n = 0;
register u_char *bp, *ep;
* buffer.
*/
#ifdef HAVE_ZEROCOPY_BPF
- if (p->md.zerocopy) {
+ if (pb->zerocopy) {
if (p->buffer != NULL)
pcap_ack_zbuf(p);
i = pcap_next_zbuf(p, &cc);
* skipping that padding.
#endif
*/
- if (p->md.use_bpf ||
+ if (pb->filtering_in_kernel ||
bpf_filter(p->fcode.bf_insns, datap, bhp->bh_datalen, caplen)) {
struct pcap_pkthdr pkthdr;
static void
pcap_cleanup_bpf(pcap_t *p)
{
+ struct pcap_bpf *pb = p->private;
#ifdef HAVE_BSD_IEEE80211
int sock;
struct ifmediareq req;
struct ifreq ifr;
#endif
- if (p->md.must_do_on_close != 0) {
+ if (pb->must_do_on_close != 0) {
/*
* There's something we have to do when closing this
* pcap_t.
*/
#ifdef HAVE_BSD_IEEE80211
- if (p->md.must_do_on_close & MUST_CLEAR_RFMON) {
+ if (pb->must_do_on_close & MUST_CLEAR_RFMON) {
/*
* We put the interface into rfmon mode;
* take it out of rfmon mode.
strerror(errno));
} else {
memset(&req, 0, sizeof(req));
- strncpy(req.ifm_name, p->md.device,
+ strncpy(req.ifm_name, pb->device,
sizeof(req.ifm_name));
if (ioctl(sock, SIOCGIFMEDIA, &req) < 0) {
fprintf(stderr,
*/
memset(&ifr, 0, sizeof(ifr));
(void)strncpy(ifr.ifr_name,
- p->md.device,
+ pb->device,
sizeof(ifr.ifr_name));
ifr.ifr_media =
req.ifm_current & ~IFM_IEEE80211_MONITOR;
* have to take the interface out of some mode.
*/
pcap_remove_from_pcaps_to_close(p);
- p->md.must_do_on_close = 0;
+ pb->must_do_on_close = 0;
}
#ifdef HAVE_ZEROCOPY_BPF
- if (p->md.zerocopy) {
+ if (pb->zerocopy) {
/*
* Delete the mappings. Note that p->buffer gets
* initialized to one of the mmapped regions in
* null it out so that pcap_cleanup_live_common()
* doesn't try to free it.
*/
- if (p->md.zbuf1 != MAP_FAILED && p->md.zbuf1 != NULL)
- (void) munmap(p->md.zbuf1, p->md.zbufsize);
- if (p->md.zbuf2 != MAP_FAILED && p->md.zbuf2 != NULL)
- (void) munmap(p->md.zbuf2, p->md.zbufsize);
+ if (pb->zbuf1 != MAP_FAILED && pb->zbuf1 != NULL)
+ (void) munmap(pb->zbuf1, pb->zbufsize);
+ if (pb->zbuf2 != MAP_FAILED && pb->zbuf2 != NULL)
+ (void) munmap(pb->zbuf2, pb->zbufsize);
p->buffer = NULL;
}
#endif
- if (p->md.device != NULL) {
- free(p->md.device);
- p->md.device = NULL;
+ if (pb->device != NULL) {
+ free(pb->device);
+ pb->device = NULL;
}
pcap_cleanup_live_common(p);
}
static int
pcap_activate_bpf(pcap_t *p)
{
+ struct pcap_bpf *pb = p->private;
int status = 0;
int fd;
#ifdef LIFNAMSIZ
}
#endif
- p->md.device = strdup(p->opt.source);
- if (p->md.device == NULL) {
+ pb->device = strdup(p->opt.source);
+ if (pb->device == NULL) {
snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "strdup: %s",
pcap_strerror(errno));
status = PCAP_ERROR;
/*
* We have zerocopy BPF; use it.
*/
- p->md.zerocopy = 1;
+ pb->zerocopy = 1;
/*
* How to pick a buffer size: first, query the maximum buffer
#ifndef roundup
#define roundup(x, y) ((((x)+((y)-1))/(y))*(y)) /* to any y */
#endif
- p->md.zbufsize = roundup(v, getpagesize());
- if (p->md.zbufsize > zbufmax)
- p->md.zbufsize = zbufmax;
- p->md.zbuf1 = mmap(NULL, p->md.zbufsize, PROT_READ | PROT_WRITE,
+ pb->zbufsize = roundup(v, getpagesize());
+ if (pb->zbufsize > zbufmax)
+ pb->zbufsize = zbufmax;
+ pb->zbuf1 = mmap(NULL, pb->zbufsize, PROT_READ | PROT_WRITE,
MAP_ANON, -1, 0);
- p->md.zbuf2 = mmap(NULL, p->md.zbufsize, PROT_READ | PROT_WRITE,
+ pb->zbuf2 = mmap(NULL, pb->zbufsize, PROT_READ | PROT_WRITE,
MAP_ANON, -1, 0);
- if (p->md.zbuf1 == MAP_FAILED || p->md.zbuf2 == MAP_FAILED) {
+ if (pb->zbuf1 == MAP_FAILED || pb->zbuf2 == MAP_FAILED) {
snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "mmap: %s",
pcap_strerror(errno));
goto bad;
}
memset(&bz, 0, sizeof(bz)); /* bzero() deprecated, replaced with memset() */
- bz.bz_bufa = p->md.zbuf1;
- bz.bz_bufb = p->md.zbuf2;
- bz.bz_buflen = p->md.zbufsize;
+ bz.bz_bufa = pb->zbuf1;
+ bz.bz_bufb = pb->zbuf2;
+ bz.bz_buflen = pb->zbufsize;
if (ioctl(fd, BIOCSETZBUF, (caddr_t)&bz) < 0) {
snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "BIOCSETZBUF: %s",
pcap_strerror(errno));
p->opt.source, pcap_strerror(errno));
goto bad;
}
- v = p->md.zbufsize - sizeof(struct bpf_zbuf_header);
+ v = pb->zbufsize - sizeof(struct bpf_zbuf_header);
} else
#endif
{
if (v == DLT_FDDI)
p->fddipad = PCAP_FDDIPAD;
else
- p->fddipad = 0;
#endif
+ p->fddipad = 0;
p->linktype = v;
#if defined(BIOCGHDRCMPLT) && defined(BIOCSHDRCMPLT)
}
#endif
/* set timeout */
+ pb->timeout = p->opt.timeout;
#ifdef HAVE_ZEROCOPY_BPF
- if (p->md.timeout != 0 && !p->md.zerocopy) {
+ if (pb->timeout != 0 && !pb->zerocopy) {
#else
- if (p->md.timeout) {
+ if (pb->timeout) {
#endif
/*
* XXX - is this seconds/nanoseconds in AIX?
struct BPF_TIMEVAL bpf_to;
if (IOCPARM_LEN(BIOCSRTIMEOUT) != sizeof(struct timeval)) {
- bpf_to.tv_sec = p->md.timeout / 1000;
- bpf_to.tv_usec = (p->md.timeout * 1000) % 1000000;
+ bpf_to.tv_sec = pb->timeout / 1000;
+ bpf_to.tv_usec = (pb->timeout * 1000) % 1000000;
if (ioctl(p->fd, BIOCSRTIMEOUT, (caddr_t)&bpf_to) < 0) {
snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
"BIOCSRTIMEOUT: %s", pcap_strerror(errno));
}
} else {
#endif
- to.tv_sec = p->md.timeout / 1000;
- to.tv_usec = (p->md.timeout * 1000) % 1000000;
+ to.tv_sec = pb->timeout / 1000;
+ to.tv_usec = (pb->timeout * 1000) % 1000000;
if (ioctl(p->fd, BIOCSRTIMEOUT, (caddr_t)&to) < 0) {
snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
"BIOCSRTIMEOUT: %s", pcap_strerror(errno));
}
p->bufsize = v;
#ifdef HAVE_ZEROCOPY_BPF
- if (!p->md.zerocopy) {
+ if (!pb->zerocopy) {
#endif
p->buffer = (u_char *)malloc(p->bufsize);
if (p->buffer == NULL) {
static int
monitor_mode(pcap_t *p, int set)
{
+ struct pcap_bpf *pb = p->private;
int sock;
struct ifmediareq req;
int *media_list;
return (PCAP_ERROR);
}
- p->md.must_do_on_close |= MUST_CLEAR_RFMON;
+ pb->must_do_on_close |= MUST_CLEAR_RFMON;
/*
* Add this to the list of pcaps to close when we exit.
static int
pcap_setfilter_bpf(pcap_t *p, struct bpf_program *fp)
{
+ struct pcap_bpf *pb = p->private;
+
/*
* Free any user-mode filter we might happen to have installed.
*/
/*
* It worked.
*/
- p->md.use_bpf = 1; /* filtering in the kernel */
+ pb->filtering_in_kernel = 1; /* filtering in the kernel */
/*
* Discard any previously-received packets, as they might
*/
if (install_bpf_program(p, fp) < 0)
return (-1);
- p->md.use_bpf = 0; /* filtering in userland */
+ pb->filtering_in_kernel = 0; /* filtering in userland */
return (0);
}
static int bt_setdirection_linux(pcap_t *, pcap_direction_t);
static int bt_stats_linux(pcap_t *, struct pcap_stat *);
+/*
+ * Private data for capturing on Linux Bluetooth devices.
+ */
+struct pcap_bt {
+ int dev_id; /* device ID of device we're bound to */
+};
+
int
bt_findalldevs(pcap_if_t **alldevsp, char *err_str)
{
/* OK, it's probably ours. */
*is_ours = 1;
- p = pcap_create_common(device, ebuf);
+ p = pcap_create_common(device, ebuf, sizeof (struct pcap_bt));
if (p == NULL)
return (NULL);
static int
bt_activate(pcap_t* handle)
{
+ struct pcap_bt *handlep = handle->private;
struct sockaddr_hci addr;
int opt;
int dev_id;
handle->getnonblock_op = pcap_getnonblock_fd;
handle->setnonblock_op = pcap_setnonblock_fd;
handle->stats_op = bt_stats_linux;
- handle->md.ifindex = dev_id;
+ handlep->dev_id = dev_id;
/* Create HCI socket */
handle->fd = socket(AF_BLUETOOTH, SOCK_RAW, BTPROTO_HCI);
/* Bind socket to the HCI device */
addr.hci_family = AF_BLUETOOTH;
- addr.hci_dev = handle->md.ifindex;
+ addr.hci_dev = handlep->dev_id;
#ifdef SOCKADDR_HCI_HAS_HCI_CHANNEL
addr.hci_channel = HCI_CHANNEL_RAW;
#endif
if (bind(handle->fd, (struct sockaddr *) &addr, sizeof(addr)) < 0) {
snprintf(handle->errbuf, PCAP_ERRBUF_SIZE,
- "Can't attach to device %d: %s", handle->md.ifindex,
+ "Can't attach to device %d: %s", handlep->dev_id,
strerror(errno));
goto close_fail;
}
static int
bt_stats_linux(pcap_t *handle, struct pcap_stat *stats)
{
+ struct pcap_bt *handlep = handle->private;
int ret;
struct hci_dev_info dev_info;
struct hci_dev_stats * s = &dev_info.stat;
- dev_info.dev_id = handle->md.ifindex;
+ dev_info.dev_id = handlep->dev_id;
/* ignore eintr */
do {
static int can_setdirection_linux(pcap_t *, pcap_direction_t);
static int can_stats_linux(pcap_t *, struct pcap_stat *);
+/*
+ * Private data for capturing on Linux CANbus devices.
+ */
+struct pcap_can {
+ int ifindex; /* interface index of device we're bound to */
+};
+
int
can_findalldevs(pcap_if_t **devlistp, char *errbuf)
{
/* OK, it's probably ours. */
*is_ours = 1;
- p = pcap_create_common(device, ebuf);
+ p = pcap_create_common(device, ebuf, sizeof (struct pcap_can));
if (p == NULL)
return (NULL);
static int
can_activate(pcap_t* handle)
{
+ struct pcap_can *handlep = handle->private;
struct sockaddr_can addr;
struct ifreq ifr;
pcap_cleanup_live_common(handle);
return PCAP_ERROR;
}
- handle->md.ifindex = ifr.ifr_ifindex;
+ handlep->ifindex = ifr.ifr_ifindex;
/* allocate butter */
handle->buffer = malloc(handle->bufsize);
/* Bind to the socket */
addr.can_family = AF_CAN;
- addr.can_ifindex = handle->md.ifindex;
+ addr.can_ifindex = handlep->ifindex;
if( bind( handle->fd, (struct sockaddr*)&addr, sizeof(addr) ) < 0 )
{
snprintf(handle->errbuf, PCAP_ERRBUF_SIZE, "Can't attach to device %d %d:%s",
- handle->md.ifindex, errno, strerror(errno));
+ handlep->ifindex, errno, strerror(errno));
pcap_cleanup_live_common(handle);
return PCAP_ERROR;
}
{
/* Monitor mode doesn't apply to CAN devices. */
pcap_cleanup_live_common(handle);
- return PCAP_ERROR;
+ return PCAP_ERROR_RFMON_NOTSUP;
}
handle->selectable_fd = handle->fd;
#include <unistd.h>
#include <fcntl.h>
#include <string.h>
+#include <pthread.h>
#include "pcap-int.h"
#include "pcap-canusb-linux.h"
uint8_t data[8];
};
-struct canusb_t
-{
+/*
+ * Private data for capturing on Linux CANbus USB devices.
+ */
+struct pcap_canusb {
libusb_context *ctx;
libusb_device_handle *dev;
- char *serial;
pthread_t worker;
int rdpipe, wrpipe;
- volatile int* loop;
+ volatile int loop;
};
-static struct canusb_t canusb;
-static volatile int loop;
-
int canusb_findalldevs(pcap_if_t **alldevsp, char *err_str)
{
libusb_context *fdctx;
libusb_device** devs;
unsigned char sernum[65];
- unsigned char buf[96];
int cnt, i;
if (libusb_init(&fdctx) != 0) {
//It is!
libusb_device_handle *dh = NULL;
- if (ret = libusb_open(devs[i],&dh) == 0)
+ if ((ret = libusb_open(devs[i],&dh)) == 0)
{
char dev_name[30];
char dev_descr[50];
if (pcap_add_if(alldevsp, dev_name, 0, dev_descr, err_str) < 0)
{
libusb_free_device_list(devs,1);
+ libusb_exit(fdctx);
return -1;
}
}
static libusb_device_handle* canusb_opendevice(struct libusb_context *ctx, char* devserial)
{
- libusb_device_handle* dh;
libusb_device** devs;
unsigned char serial[65];
int cnt,i,n;
n = libusb_get_string_descriptor_ascii(dh,desc.iSerialNumber,serial,64);
serial[n] = 0;
- if ((devserial) && (strcmp(serial,devserial) != 0))
+ if ((devserial) && (strcmp((char *)serial,devserial) != 0))
{
libusb_close(dh);
continue;
char *cpend;
long devnum;
pcap_t* p;
-
- libusb_init(&canusb.ctx);
+ struct pcap_canusb *canusb;
/* Does this look like a DAG device? */
cp = strrchr(device, '/');
/* OK, it's probably ours. */
*is_ours = 1;
- p = pcap_create_common(device, ebuf);
+ p = pcap_create_common(device, ebuf, sizeof (struct pcap_canusb));
if (p == NULL)
return (NULL);
- memset(&canusb, 0x00, sizeof(canusb));
+ canusb = p->private;
+ canusb->ctx = NULL;
+ canusb->dev = NULL;
+ canusb->rdpipe = -1;
+ canusb->wrpipe = -1;
p->activate_op = canusb_activate;
}
-static void* canusb_capture_thread(struct canusb_t *canusb)
+static void* canusb_capture_thread(void *arg)
{
- struct libusb_context *ctx;
- libusb_device_handle *dev;
- int i, n;
+ struct pcap_canusb *canusb = arg;
+ int i;
struct
{
uint8_t rxsz, txsz;
} status;
- char *serial;
-
- libusb_init(&ctx);
-
- serial = canusb->serial;
- dev = canusb_opendevice(ctx, serial);
fcntl(canusb->wrpipe, F_SETFL, O_NONBLOCK);
- while(*canusb->loop)
+ while(canusb->loop)
{
- int sz, ret;
+ int sz;
struct CAN_Msg msg;
- libusb_interrupt_transfer(dev, 0x81, (unsigned char*)&status, sizeof(status), &sz, 100);
+ libusb_interrupt_transfer(canusb->dev, 0x81, (unsigned char*)&status, sizeof(status), &sz, 100);
//HACK!!!!! -> drop buffered data, read new one by reading twice.
- ret = libusb_interrupt_transfer(dev, 0x81, (unsigned char*)&status, sizeof(status), &sz, 100);
+ libusb_interrupt_transfer(canusb->dev, 0x81, (unsigned char*)&status, sizeof(status), &sz, 100);
for(i = 0; i<status.rxsz; i++)
{
- libusb_bulk_transfer(dev, 0x85, (unsigned char*)&msg, sizeof(msg), &sz, 100);
- n = write(canusb->wrpipe, &msg, sizeof(msg));
+ libusb_bulk_transfer(canusb->dev, 0x85, (unsigned char*)&msg, sizeof(msg), &sz, 100);
+ write(canusb->wrpipe, &msg, sizeof(msg));
}
}
- libusb_close(dev);
- libusb_exit(ctx);
-
return NULL;
}
-static int canusb_startcapture(struct canusb_t* this)
+static int canusb_startcapture(struct pcap_canusb* this)
{
int pipefd[2];
if (pipe(pipefd) == -1)
return -1;
- canusb.rdpipe = pipefd[0];
- canusb.wrpipe = pipefd[1];
- canusb.loop = &loop;
+ this->rdpipe = pipefd[0];
+ this->wrpipe = pipefd[1];
- loop = 1;
- pthread_create(&this->worker, NULL, canusb_capture_thread, &canusb);
+ this->loop = 1;
+ pthread_create(&this->worker, NULL, canusb_capture_thread, this);
- return canusb.rdpipe;
+ return this->rdpipe;
}
-static void canusb_clearbufs(struct canusb_t* this)
+static void canusb_clearbufs(struct pcap_canusb* this)
{
unsigned char cmd[16];
int al;
static void canusb_close(pcap_t* handle)
{
- loop = 0;
- pthread_join(canusb.worker, NULL);
+ struct pcap_canusb *canusb = handle->private;
+
+ canusb->loop = 0;
+ pthread_join(canusb->worker, NULL);
- if (canusb.dev)
+ if (canusb->dev)
{
- libusb_close(canusb.dev);
- canusb.dev = NULL;
+ libusb_close(canusb->dev);
+ canusb->dev = NULL;
}
+ if (canusb->ctx)
+ {
+ libusb_exit(canusb->ctx);
+ canusb->ctx = NULL;
+ }
}
static int canusb_activate(pcap_t* handle)
{
+ struct pcap_canusb *canusb = handle->private;
char *serial;
+ if (libusb_init(&canusb->ctx) != 0) {
+ /*
+ * XXX - what causes this to fail?
+ */
+ snprintf(handle->errbuf, PCAP_ERRBUF_SIZE, "libusb_init() failed");
+ return PCAP_ERROR;
+ }
+
handle->read_op = canusb_read_linux;
handle->inject_op = canusb_inject_linux;
handle->set_datalink_op = NULL;
serial = handle->opt.source + strlen(CANUSB_IFACE);
- canusb.serial = strdup(serial);
- canusb.dev = canusb_opendevice(canusb.ctx,serial);
- if (!canusb.dev)
+ canusb->dev = canusb_opendevice(canusb->ctx, serial);
+ if (!canusb->dev)
{
- snprintf(handle->errbuf, PCAP_ERRBUF_SIZE, "Can't open USB Device:");
+ libusb_exit(canusb->ctx);
+ snprintf(handle->errbuf, PCAP_ERRBUF_SIZE, "Can't open USB Device");
return PCAP_ERROR;
}
- canusb_clearbufs(&canusb);
+ canusb_clearbufs(canusb);
- handle->fd = canusb_startcapture(&canusb);
+ handle->fd = canusb_startcapture(canusb);
handle->selectable_fd = handle->fd;
return 0;
canusb_read_linux(pcap_t *handle, int max_packets, pcap_handler callback, u_char *user)
{
static struct timeval firstpacket = { -1, -1};
-
- int msgsent = 0;
int i = 0;
struct CAN_Msg msg;
struct pcap_pkthdr pkth;
unsigned short vci; /* VCI */
};
+/*
+ * 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;
static void
dag_platform_cleanup(pcap_t *p)
{
-
+ struct pcap_dag *pd;
+
if (p != NULL) {
+ pd = p->private;
#ifdef HAVE_DAG_STREAMS_API
- if(dag_stop_stream(p->fd, p->md.dag_stream) < 0)
+ if(dag_stop_stream(p->fd, pd->dag_stream) < 0)
fprintf(stderr,"dag_stop_stream: %s\n", strerror(errno));
- if(dag_detach_stream(p->fd, p->md.dag_stream) < 0)
+ if(dag_detach_stream(p->fd, pd->dag_stream) < 0)
fprintf(stderr,"dag_detach_stream: %s\n", strerror(errno));
#else
if(dag_stop(p->fd) < 0)
static int
dag_read(pcap_t *p, int cnt, pcap_handler callback, u_char *user)
{
+ struct pcap_dag *pd = p->private;
unsigned int processed = 0;
- int flags = p->md.dag_offset_flags;
+ int flags = pd->dag_offset_flags;
unsigned int nonblocking = flags & DAGF_NONBLOCK;
unsigned int num_ext_hdr = 0;
/* Get the next bufferful of packets (if necessary). */
- while (p->md.dag_mem_top - p->md.dag_mem_bottom < dag_record_size) {
+ while (pd->dag_mem_top - pd->dag_mem_bottom < dag_record_size) {
/*
* Has "pcap_breakloop()" been called?
* If non-block is specified it will return immediately. The user
* is then responsible for efficiency.
*/
- if ( NULL == (p->md.dag_mem_top = dag_advance_stream(p->fd, p->md.dag_stream, &(p->md.dag_mem_bottom))) ) {
+ if ( NULL == (pd->dag_mem_top = dag_advance_stream(p->fd, pd->dag_stream, &(pd->dag_mem_bottom))) ) {
return -1;
}
#else
/* dag_offset does not support timeouts */
- p->md.dag_mem_top = dag_offset(p->fd, &(p->md.dag_mem_bottom), flags);
+ pd->dag_mem_top = dag_offset(p->fd, &(pd->dag_mem_bottom), flags);
#endif /* HAVE_DAG_STREAMS_API */
- if (nonblocking && (p->md.dag_mem_top - p->md.dag_mem_bottom < dag_record_size))
+ if (nonblocking && (pd->dag_mem_top - pd->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))
+ pd->dag_timeout &&
+ (pd->dag_mem_top - pd->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) {
+ while (pd->dag_mem_top - pd->dag_mem_bottom >= dag_record_size) {
unsigned short packet_len = 0;
int caplen = 0;
struct pcap_pkthdr pcap_header;
#ifdef HAVE_DAG_STREAMS_API
- dag_record_t *header = (dag_record_t *)(p->md.dag_mem_bottom);
+ dag_record_t *header = (dag_record_t *)(pd->dag_mem_bottom);
#else
- dag_record_t *header = (dag_record_t *)(p->md.dag_mem_base + p->md.dag_mem_bottom);
+ dag_record_t *header = (dag_record_t *)(pd->dag_mem_base + pd->dag_mem_bottom);
#endif /* HAVE_DAG_STREAMS_API */
u_char *dp = ((u_char *)header); /* + dag_record_size; */
strncpy(p->errbuf, "dag_read: record too small", PCAP_ERRBUF_SIZE);
return -1;
}
- p->md.dag_mem_bottom += rlen;
+ pd->dag_mem_bottom += rlen;
/* Count lost packets. */
switch((header->type & 0x7f)) {
default:
if (header->lctr) {
- if (p->md.stat.ps_drop > (UINT_MAX - ntohs(header->lctr))) {
- p->md.stat.ps_drop = UINT_MAX;
+ if (pd->stat.ps_drop > (UINT_MAX - ntohs(header->lctr))) {
+ pd->stat.ps_drop = UINT_MAX;
} else {
- p->md.stat.ps_drop += ntohs(header->lctr);
+ pd->stat.ps_drop += ntohs(header->lctr);
}
}
}
case TYPE_COLOR_ETH:
case TYPE_ETH:
packet_len = ntohs(header->wlen);
- packet_len -= (p->md.dag_fcs_bits >> 3);
+ packet_len -= (pd->dag_fcs_bits >> 3);
caplen = rlen - dag_record_size - 2;
if (caplen > packet_len) {
caplen = packet_len;
case TYPE_COLOR_HDLC_POS:
case TYPE_HDLC_POS:
packet_len = ntohs(header->wlen);
- packet_len -= (p->md.dag_fcs_bits >> 3);
+ packet_len -= (pd->dag_fcs_bits >> 3);
caplen = rlen - dag_record_size;
if (caplen > packet_len) {
caplen = packet_len;
case TYPE_COLOR_MC_HDLC_POS:
case TYPE_MC_HDLC:
packet_len = ntohs(header->wlen);
- packet_len -= (p->md.dag_fcs_bits >> 3);
+ packet_len -= (pd->dag_fcs_bits >> 3);
caplen = rlen - dag_record_size - 4;
if (caplen > packet_len) {
caplen = packet_len;
pcap_header.len = packet_len;
/* Count the packet. */
- p->md.stat.ps_recv++;
+ pd->stat.ps_recv++;
/* Call the user supplied callback function */
callback(user, &pcap_header, dp);
*/
static int dag_activate(pcap_t* handle)
{
+ struct pcap_dag *handlep = handle->private;
#if 0
char conf[30]; /* dag configure string */
#endif
}
/* 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) {
+ if (dag_parse_name(device, newDev, strlen(device) + 16, &handlep->dag_stream) < 0) {
snprintf(handle->errbuf, PCAP_ERRBUF_SIZE, "dag_parse_name: %s\n", pcap_strerror(errno));
goto fail;
}
device = newDev;
- if (handle->md.dag_stream%2) {
+ if (handlep->dag_stream%2) {
snprintf(handle->errbuf, PCAP_ERRBUF_SIZE, "dag_parse_name: tx (even numbered) streams not supported for capture\n");
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) {
+ if (dag_attach_stream(handle->fd, handlep->dag_stream, 0, 0) < 0) {
snprintf(handle->errbuf, PCAP_ERRBUF_SIZE, "dag_attach_stream: %s\n", 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, handle->md.dag_stream,
+ if (dag_get_stream_poll(handle->fd, handlep->dag_stream,
&mindata, &maxwait, &poll) < 0) {
snprintf(handle->errbuf, PCAP_ERRBUF_SIZE, "dag_get_stream_poll: %s\n", pcap_strerror(errno));
goto faildetach;
*/
mindata = 65536;
- /* Obey md.timeout (was to_ms) if supplied. This is a good idea!
+ /* 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->md.timeout/1000;
- maxwait.tv_usec = (handle->md.timeout%1000) * 1000;
+ maxwait.tv_sec = handle->opt.timeout/1000;
+ maxwait.tv_usec = (handle->opt.timeout%1000) * 1000;
- if (dag_set_stream_poll(handle->fd, handle->md.dag_stream,
+ if (dag_set_stream_poll(handle->fd, handlep->dag_stream,
mindata, &maxwait, &poll) < 0) {
snprintf(handle->errbuf, PCAP_ERRBUF_SIZE, "dag_set_stream_poll: %s\n", pcap_strerror(errno));
goto faildetach;
}
#else
- if((handle->md.dag_mem_base = dag_mmap(handle->fd)) == MAP_FAILED) {
+ if((handlep->dag_mem_base = dag_mmap(handle->fd)) == MAP_FAILED) {
snprintf(handle->errbuf, PCAP_ERRBUF_SIZE,"dag_mmap %s: %s\n", device, pcap_strerror(errno));
goto failclose;
}
#endif
#ifdef HAVE_DAG_STREAMS_API
- if(dag_start_stream(handle->fd, handle->md.dag_stream) < 0) {
+ if(dag_start_stream(handle->fd, handlep->dag_stream) < 0) {
snprintf(handle->errbuf, PCAP_ERRBUF_SIZE, "dag_start_stream %s: %s\n", device, pcap_strerror(errno));
goto faildetach;
}
* 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;
+ handlep->dag_mem_bottom = 0;
+ handlep->dag_mem_top = 0;
/*
* Find out how many FCS bits we should strip.
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. */
- handle->md.dag_fcs_bits = 0;
+ handlep->dag_fcs_bits = 0;
/* Note that no FCS will be supplied. */
handle->linktype_ext = LT_FCS_DATALINK_EXT(0);
/*
* Start out assuming it's 32 bits.
*/
- handle->md.dag_fcs_bits = 32;
+ 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) {
- handle->md.dag_fcs_bits = n;
+ handlep->dag_fcs_bits = n;
} else {
snprintf(handle->errbuf, PCAP_ERRBUF_SIZE,
"pcap_activate %s: bad ERF_FCS_BITS value (%d) in environment\n", device, n);
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(handle->md.dag_fcs_bits/16);
+ handle->linktype_ext = LT_FCS_DATALINK_EXT(handlep->dag_fcs_bits/16);
/* And don't strip them. */
- handle->md.dag_fcs_bits = 0;
+ handlep->dag_fcs_bits = 0;
}
}
- handle->md.dag_timeout = handle->md.timeout;
+ handlep->dag_timeout = handle->opt.timeout;
handle->linktype = -1;
if (dag_get_datalink(handle) < 0)
handle->setnonblock_op = dag_setnonblock;
handle->stats_op = dag_stats;
handle->cleanup_op = dag_platform_cleanup;
- handle->md.stat.ps_drop = 0;
- handle->md.stat.ps_recv = 0;
- handle->md.stat.ps_ifdrop = 0;
+ 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, handle->md.dag_stream) < 0) {
+ 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, handle->md.dag_stream) < 0)
+ if (dag_detach_stream(handle->fd, handlep->dag_stream) < 0)
fprintf(stderr,"dag_detach_stream: %s\n", strerror(errno));
#else
failstop:
/* OK, it's probably ours. */
*is_ours = 1;
- p = pcap_create_common(device, ebuf);
+ p = pcap_create_common(device, ebuf, sizeof (struct pcap_dag));
if (p == NULL)
return NULL;
static int
dag_stats(pcap_t *p, struct pcap_stat *ps) {
+ struct pcap_dag *pd = p->private;
+
/* This needs to be filled out correctly. Hopefully a dagapi call will
provide all necessary information.
*/
- /*p->md.stat.ps_recv = 0;*/
- /*p->md.stat.ps_drop = 0;*/
+ /*pd->stat.ps_recv = 0;*/
+ /*pd->stat.ps_drop = 0;*/
- *ps = p->md.stat;
+ *ps = pd->stat;
return 0;
}
if (install_bpf_program(p, fp) < 0)
return -1;
- p->md.use_bpf = 0;
-
return (0);
}
static int
dag_setnonblock(pcap_t *p, int nonblock, char *errbuf)
{
+ struct pcap_dag *pd = p->private;
+
/*
* 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
- * "p->md.dag_offset_flags".
+ * "pd->dag_offset_flags".
*/
if (pcap_setnonblock_fd(p, nonblock, errbuf) < 0)
return (-1);
struct timeval maxwait;
struct timeval poll;
- if (dag_get_stream_poll(p->fd, p->md.dag_stream,
+ if (dag_get_stream_poll(p->fd, pd->dag_stream,
&mindata, &maxwait, &poll) < 0) {
snprintf(errbuf, PCAP_ERRBUF_SIZE, "dag_get_stream_poll: %s\n", pcap_strerror(errno));
return -1;
else
mindata = 65536;
- if (dag_set_stream_poll(p->fd, p->md.dag_stream,
+ if (dag_set_stream_poll(p->fd, pd->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;
+ pd->dag_offset_flags |= DAGF_NONBLOCK;
} else {
- p->md.dag_offset_flags &= ~DAGF_NONBLOCK;
+ pd->dag_offset_flags &= ~DAGF_NONBLOCK;
}
return (0);
}
static int
dag_get_datalink(pcap_t *p)
{
+ struct pcap_dag *pd = p->private;
int index=0, dlt_index=0;
uint8_t types[255];
#ifdef HAVE_DAG_GET_STREAM_ERF_TYPES
/* Get list of possible ERF types for this card */
- if (dag_get_stream_erf_types(p->fd, p->md.dag_stream, types, 255) < 0) {
+ if (dag_get_stream_erf_types(p->fd, pd->dag_stream, types, 255) < 0) {
snprintf(p->errbuf, sizeof(p->errbuf), "dag_get_stream_erf_types: %s", pcap_strerror(errno));
return (-1);
}
#include "pcap-int.h"
#include "pcap-dbus.h"
+/*
+ * Private data for capturing on D-Bus.
+ */
+struct pcap_dbus {
+ DBusConnection *conn;
+ u_int packets_read; /* count of packets read */
+};
+
static int
dbus_read(pcap_t *handle, int max_packets, pcap_handler callback, u_char *user)
{
- DBusConnection *conn = handle->md.priv;
+ struct pcap_dbus *handlep = handle->private;
struct pcap_pkthdr pkth;
DBusMessage *message;
int count = 0;
- message = dbus_connection_pop_message(conn);
+ message = dbus_connection_pop_message(handlep->conn);
while (!message) {
- // XXX p->md.timeout = timeout_ms;
- if (!dbus_connection_read_write(conn, 100)) {
+ // XXX handle->opt.timeout = timeout_ms;
+ if (!dbus_connection_read_write(handlep->conn, 100)) {
snprintf(handle->errbuf, PCAP_ERRBUF_SIZE, "Connection closed");
return -1;
}
return -2;
}
- message = dbus_connection_pop_message(conn);
+ message = dbus_connection_pop_message(handlep->conn);
}
if (dbus_message_is_signal(message, DBUS_INTERFACE_LOCAL, "Disconnected")) {
gettimeofday(&pkth.ts, NULL);
if (handle->fcode.bf_insns == NULL ||
bpf_filter(handle->fcode.bf_insns, (u_char *)raw_msg, pkth.len, pkth.caplen)) {
- handle->md.packets_read++;
+ handlep->packets_read++;
callback(user, &pkth, (u_char *)raw_msg);
count++;
}
dbus_write(pcap_t *handle, const void *buf, size_t size)
{
/* XXX, not tested */
- DBusConnection *conn = handle->md.priv;
+ struct pcap_dbus *handlep = handle->private;
DBusError error = DBUS_ERROR_INIT;
DBusMessage *msg;
return -1;
}
- dbus_connection_send(conn, msg, NULL);
- dbus_connection_flush(conn);
+ dbus_connection_send(handlep->conn, msg, NULL);
+ dbus_connection_flush(handlep->conn);
dbus_message_unref(msg);
return 0;
static int
dbus_stats(pcap_t *handle, struct pcap_stat *stats)
{
- stats->ps_recv = handle->md.packets_read;
+ struct pcap_dbus *handlep = handle->private;
+
+ stats->ps_recv = handlep->packets_read;
stats->ps_drop = 0;
stats->ps_ifdrop = 0;
return 0;
static void
dbus_cleanup(pcap_t *handle)
{
- DBusConnection *conn = handle->md.priv;
+ struct pcap_dbus *handlep = handle->private;
- handle->md.priv = NULL;
- dbus_connection_unref(conn);
+ dbus_connection_unref(handlep->conn);
pcap_cleanup_live_common(handle);
}
#define N_RULES sizeof(rules)/sizeof(rules[0])
+ struct pcap_dbus *handlep = handle->private;
const char *dev = handle->opt.source;
DBusError error = DBUS_ERROR_INIT;
- DBusConnection *conn;
int i;
if (strcmp(dev, "dbus-system") == 0) {
- if (!(conn = dbus_bus_get(DBUS_BUS_SYSTEM, &error))) {
+ if (!(handlep->conn = dbus_bus_get(DBUS_BUS_SYSTEM, &error))) {
snprintf(handle->errbuf, PCAP_ERRBUF_SIZE, "Failed to get system bus: %s", error.message);
dbus_error_free(&error);
return PCAP_ERROR;
}
} else if (strcmp(dev, "dbus-session") == 0) {
- if (!(conn = dbus_bus_get(DBUS_BUS_SESSION, &error))) {
+ if (!(handlep->conn = dbus_bus_get(DBUS_BUS_SESSION, &error))) {
snprintf(handle->errbuf, PCAP_ERRBUF_SIZE, "Failed to get session bus: %s", error.message);
dbus_error_free(&error);
return PCAP_ERROR;
} else if (strncmp(dev, "dbus://", 7) == 0) {
const char *addr = dev + 7;
- if (!(conn = dbus_connection_open(addr, &error))) {
+ if (!(handlep->conn = dbus_connection_open(addr, &error))) {
snprintf(handle->errbuf, PCAP_ERRBUF_SIZE, "Failed to open connection to: %s: %s", addr, error.message);
dbus_error_free(&error);
return PCAP_ERROR;
}
- if (!dbus_bus_register(conn, &error)) {
+ if (!dbus_bus_register(handlep->conn, &error)) {
snprintf(handle->errbuf, PCAP_ERRBUF_SIZE, "Failed to register bus %s: %s\n", addr, error.message);
dbus_error_free(&error);
return PCAP_ERROR;
handle->stats_op = dbus_stats;
handle->selectable_fd = handle->fd = -1;
- handle->md.priv = conn;
if (handle->opt.rfmon) {
/*
return PCAP_ERROR_RFMON_NOTSUP;
}
- /* dbus_connection_set_max_message_size(conn, handle->snapshot); */
+ /* dbus_connection_set_max_message_size(handlep->conn, handle->snapshot); */
if (handle->opt.buffer_size != 0)
- dbus_connection_set_max_received_size(conn, handle->opt.buffer_size);
+ dbus_connection_set_max_received_size(handlep->conn, handle->opt.buffer_size);
for (i = 0; i < N_RULES; i++) {
- dbus_bus_add_match(conn, rules[i], &error);
+ dbus_bus_add_match(handlep->conn, rules[i], &error);
if (dbus_error_is_set(&error)) {
dbus_error_free(&error);
/* try without eavesdrop */
- dbus_bus_add_match(conn, rules[i] + strlen(EAVESDROPPING_RULE), &error);
+ dbus_bus_add_match(handlep->conn, rules[i] + strlen(EAVESDROPPING_RULE), &error);
if (dbus_error_is_set(&error)) {
snprintf(handle->errbuf, PCAP_ERRBUF_SIZE, "Failed to add bus match: %s\n", error.message);
dbus_error_free(&error);
}
*is_ours = 1;
- p = pcap_create_common(device, ebuf);
+ p = pcap_create_common(device, ebuf, sizeof (struct pcap_dbus));
if (p == NULL)
return (NULL);
{
pcap_if_t *found_dev = *alldevsp;
- if (pcap_add_if(&found_dev, "dbus-system", 0, "D-BUS system bus", err_str) < 0)
+ if (pcap_add_if(&found_dev, "dbus-system", 0, "D-Bus system bus", err_str) < 0)
return -1;
- if (pcap_add_if(&found_dev, "dbus-session", 0, "D-BUS session bus", err_str) < 0)
+ if (pcap_add_if(&found_dev, "dbus-session", 0, "D-Bus session bus", err_str) < 0)
return -1;
return 0;
}
static int
pcap_inject_dlpi(pcap_t *p, const void *buf, size_t size)
{
+#ifdef DL_HP_RAWDLS
+ struct pcap_dlpi *pd = p->private;
+#endif
int ret;
#if defined(DLIOCRAW)
return (-1);
}
#elif defined(DL_HP_RAWDLS)
- if (p->send_fd < 0) {
+ if (pd->send_fd < 0) {
snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
"send: Output FD couldn't be opened");
return (-1);
}
- ret = dlrawdatareq(p->send_fd, buf, size);
+ ret = dlrawdatareq(pd->send_fd, buf, size);
if (ret == -1) {
snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "send: %s",
pcap_strerror(errno));
static void
pcap_cleanup_dlpi(pcap_t *p)
{
- if (p->send_fd >= 0) {
- close(p->send_fd);
- p->send_fd = -1;
+#ifdef DL_HP_RAWDLS
+ struct pcap_dlpi *pd = p->private;
+
+ if (pd->send_fd >= 0) {
+ close(pd->send_fd);
+ pd->send_fd = -1;
}
+#endif
pcap_cleanup_live_common(p);
}
static int
pcap_activate_dlpi(pcap_t *p)
{
+#ifdef DL_HP_RAWDLS
+ struct pcap_dlpi *pd = p->private;
+#endif
register char *cp;
int ppa;
#ifdef HAVE_SOLARIS
* receiving packets on the same descriptor - you need separate
* descriptors for sending and receiving, bound to different SAPs.
*
- * If the open fails, we just leave -1 in "p->send_fd" and reject
+ * If the open fails, we just leave -1 in "pd->send_fd" and reject
* attempts to send packets, just as if, in pcap-bpf.c, we fail
* to open the BPF device for reading and writing, we just try
* to open it for reading only and, if that succeeds, just let
* the send attempts fail.
*/
- p->send_fd = open(cp, O_RDWR);
+ pd->send_fd = open(cp, O_RDWR);
#endif
/*
if (status < 0)
goto bad;
#ifdef DL_HP_RAWDLS
- if (p->send_fd >= 0) {
- if (dl_doattach(p->send_fd, ppa, p->errbuf) < 0)
+ if (pd->send_fd >= 0) {
+ if (dl_doattach(pd->send_fd, ppa, p->errbuf) < 0)
goto bad;
}
#endif
*/
if (dl_dohpuxbind(p->fd, p->errbuf) < 0)
goto bad;
- if (p->send_fd >= 0) {
+ if (pd->send_fd >= 0) {
/*
** XXX - if this fails, just close send_fd and
** set it to -1, so that you can't send but can
** still receive?
*/
- if (dl_dohpuxbind(p->send_fd, p->errbuf) < 0)
+ if (dl_dohpuxbind(pd->send_fd, p->errbuf) < 0)
goto bad;
}
#else /* neither AIX nor HP-UX */
** binding it anyway, just to keep the HP-UX 9/10.20 or later
** code together.
*/
- if (p->send_fd >= 0) {
+ if (pd->send_fd >= 0) {
/*
** XXX - if this fails, just close send_fd and
** set it to -1, so that you can't send but can
** still receive?
*/
- if (dl_dohpuxbind(p->send_fd, p->errbuf) < 0)
+ if (dl_dohpuxbind(pd->send_fd, p->errbuf) < 0)
goto bad;
}
#endif
#endif
/* Push and configure bufmod. */
- if (pcap_conf_bufmod(p, ss, p->md.timeout) != 0)
+ if (pcap_conf_bufmod(p, ss, p->opt.timeout) != 0)
goto bad;
#endif
pcap_create_interface(const char *device, char *ebuf)
{
pcap_t *p;
+#ifdef DL_HP_RAWDLS
+ struct pcap_dlpi *pd;
+#endif
- p = pcap_create_common(device, ebuf);
+ p = pcap_create_common(device, ebuf, sizeof (struct pcap_dlpi));
if (p == NULL)
return (NULL);
- p->send_fd = -1; /* it hasn't been opened yet */
+#ifdef DL_HP_RAWDLS
+ pd = p->private;
+ pd->send_fd = -1; /* it hasn't been opened yet */
+#endif
p->activate_op = pcap_activate_dlpi;
return (p);
return handle_to_device [fd-1];
}
+/*
+ * Private data for capturing on MS-DOS.
+ */
+struct pcap_dos {
+ void (*wait_proc)(void); /* call proc while waiting */
+ struct pcap_stat stat;
+};
+
pcap_t *pcap_create_interface (const char *device, char *ebuf)
{
pcap_t *p;
- p = pcap_create_common(device, ebuf);
+ p = pcap_create_common(device, ebuf, sizeof (struct pcap_dos));
if (p == NULL)
return (NULL);
*/
static int pcap_activate_dos (pcap_t *pcap)
{
+ struct pcap_dos *pcapd = pcap->private;
+
if (pcap->opt.rfmon) {
/*
* No monitor mode on DOS.
static int
pcap_read_one (pcap_t *p, pcap_handler callback, u_char *data)
{
+ struct pcap_dos *pd = p->private;
struct pcap_pkthdr pcap;
struct timeval now, expiry = { 0,0 };
BYTE *rx_buf;
int rx_len = 0;
- if (p->md.timeout > 0)
+ if (p->opt.timeout > 0)
{
gettimeofday2 (&now, NULL);
- expiry.tv_usec = now.tv_usec + 1000UL * p->md.timeout;
+ expiry.tv_usec = now.tv_usec + 1000UL * p->opt.timeout;
expiry.tv_sec = now.tv_sec;
while (expiry.tv_usec >= 1000000L)
{
/* If not to wait for a packet or pcap_cleanup_dos() called from
* e.g. SIGINT handler, exit loop now.
*/
- if (p->md.timeout <= 0 || (volatile int)p->fd <= 0)
+ if (p->opt.timeout <= 0 || (volatile int)p->fd <= 0)
break;
gettimeofday2 (&now, NULL);
if (rx_len < 0) /* receive error */
{
- p->md.stat.ps_drop++;
+ pd->stat.ps_drop++;
#ifdef USE_32BIT_DRIVERS
if (pcap_pkt_debug > 1)
printk ("pkt-err %s\n", pktInfo.error);
static int
pcap_read_dos (pcap_t *p, int cnt, pcap_handler callback, u_char *data)
{
+ struct pcap_dos *pd = p->private;
int rc, num = 0;
while (num <= cnt || (cnt < 0))
static int pcap_stats_dos (pcap_t *p, struct pcap_stat *ps)
{
struct net_device_stats *stats;
+ struct pcap_dos *pd;
struct device *dev = p ? get_device(p->fd) : NULL;
if (!dev)
FLUSHK();
- p->md.stat.ps_recv = stats->rx_packets;
- p->md.stat.ps_drop += stats->rx_missed_errors;
- p->md.stat.ps_ifdrop = stats->rx_dropped + /* queue full */
+ pd = p->private;
+ pd->stat.ps_recv = stats->rx_packets;
+ pd->stat.ps_drop += stats->rx_missed_errors;
+ pd->stat.ps_ifdrop = stats->rx_dropped + /* queue full */
stats->rx_errors; /* HW errors */
if (ps)
- *ps = p->md.stat;
+ *ps = pd->stat;
return (0);
}
*/
static void pcap_cleanup_dos (pcap_t *p)
{
+ struct pcap_dos *pd;
+
if (p && !exc_occured)
{
+ pd = p->private;
if (pcap_stats(p,NULL) < 0)
- p->md.stat.ps_drop = 0;
+ pd->stat.ps_drop = 0;
if (!get_device(p->fd))
return;
*/
void pcap_set_wait (pcap_t *p, void (*yield)(void), int wait)
{
+ struct pcap_dos *pd;
if (p)
{
- p->wait_proc = yield;
- p->md.timeout = wait;
+ pd = p->private;
+ pd->wait_proc = yield;
+ p->opt.timeout = wait;
}
}
extern "C" {
#endif
-#ifdef HAVE_LIBDLPI
-#include <libdlpi.h>
-#endif
-
#ifdef WIN32
#include <Packet32.h>
extern CRITICAL_SECTION g_PcapCompileCriticalSection;
#include <io.h>
#endif
-#ifdef HAVE_SNF_API
-#include <snf.h>
-#endif
-
#if (defined(_MSC_VER) && (_MSC_VER <= 1200)) /* we are compiling with Visual Studio 6, that doesn't support the LL suffix*/
/*
#endif /* _MSC_VER */
-/*
- * Savefile
- */
-typedef enum {
- NOT_SWAPPED,
- SWAPPED,
- MAYBE_SWAPPED
-} swapped_type_t;
-
-/*
- * Used when reading a savefile.
- */
-struct pcap_sf {
- FILE *rfile;
- int (*next_packet_op)(pcap_t *, struct pcap_pkthdr *, u_char **);
- int swapped;
- size_t hdrsize;
- swapped_type_t lengths_swapped;
- int version_major;
- int version_minor;
- bpf_u_int32 ifcount; /* number of interfaces seen in this capture */
- u_int tsresol; /* time stamp resolution */
- u_int tsscale; /* scaling factor for resolution -> microseconds */
- u_int64_t tsoffset; /* time stamp offset */
-};
-
-/*
- * Used when doing a live capture.
- */
-struct pcap_md {
- struct pcap_stat stat;
- /*XXX*/
- int use_bpf; /* using kernel filter */
- u_long TotPkts; /* can't oflow for 79 hrs on ether */
- u_long TotAccepted; /* count accepted by filter */
- u_long TotDrops; /* count of dropped packets */
- long TotMissed; /* missed by i/f during this run */
- long OrigMissed; /* missed by i/f before this run */
- char *device; /* device name */
- int timeout; /* timeout for buffering */
- int must_do_on_close; /* stuff we must do when we close */
- struct pcap *next; /* list of open pcaps that need stuff cleared on close */
-#if defined(linux) || defined(PCAP_SUPPORT_DBUS)
- u_int packets_read; /* count of packets read with recvfrom() */
-#endif
-#ifdef linux
- int sock_packet; /* using Linux 2.0 compatible interface */
- int cooked; /* using SOCK_DGRAM rather than SOCK_RAW */
- int ifindex; /* interface index of device we're bound to */
- int lo_ifindex; /* interface index of the loopback device */
- bpf_u_int32 oldmode; /* mode to restore when turning monitor mode off */
- char *mondevice; /* mac80211 monitor device we created */
- u_char *mmapbuf; /* memory-mapped region pointer */
- size_t mmapbuflen; /* size of region */
- int vlan_offset; /* offset at which to insert vlan tags; if -1, don't insert */
- u_int tp_version; /* version of tpacket_hdr for mmaped ring */
- u_int tp_hdrlen; /* hdrlen of tpacket_hdr for mmaped ring */
- u_char *oneshot_buffer; /* buffer for copy of packet */
- long proc_dropped; /* packets reported dropped by /proc/net/dev */
-#endif /* linux */
-
-#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 /* 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? */
-#endif /* HAVE_DAG_API */
-#ifdef HAVE_SNF_API
- snf_handle_t snf_handle; /* opaque device handle */
- snf_ring_t snf_ring; /* opaque device ring handle */
- int snf_timeout;
- int snf_boardnum;
-#endif /*HAVE_SNF_API*/
-
-#ifdef HAVE_ZEROCOPY_BPF
- /*
- * Zero-copy read buffer -- for zero-copy BPF. 'buffer' above will
- * alternative between these two actual mmap'd buffers as required.
- * As there is a header on the front size of the mmap'd buffer, only
- * some of the buffer is exposed to libpcap as a whole via bufsize;
- * zbufsize is the true size. zbuffer tracks the current zbuf
- * assocated with buffer so that it can be used to decide which the
- * next buffer to read will be.
- */
- u_char *zbuf1, *zbuf2, *zbuffer;
- u_int zbufsize;
- u_int zerocopy;
- u_int interrupted;
- struct timespec firstsel;
- /*
- * If there's currently a buffer being actively processed, then it is
- * referenced here; 'buffer' is also pointed at it, but offset by the
- * size of the header.
- */
- struct bpf_zbuf_header *bzh;
-#endif /* HAVE_ZEROCOPY_BPF */
-
- void *priv;
-};
-
-/*
- * Stuff to do when we close.
- */
-#define MUST_CLEAR_PROMISC 0x00000001 /* clear promiscuous mode */
-#define MUST_CLEAR_RFMON 0x00000002 /* clear rfmon (monitor) mode */
-#define MUST_DELETE_MONIF 0x00000004 /* delete monitor-mode interface */
-
struct pcap_opt {
+ int timeout; /* timeout for buffering */
int buffer_size;
char *source;
int promisc;
int tstamp_type;
};
-/*
- * Ultrix, DEC OSF/1^H^H^H^H^H^H^H^H^HDigital UNIX^H^H^H^H^H^H^H^H^H^H^H^H
- * Tru64 UNIX, and some versions of NetBSD pad FDDI packets to make everything
- * line up on a nice boundary.
- */
-#ifdef __NetBSD__
-#include <sys/param.h> /* needed to declare __NetBSD_Version__ */
-#endif
-
-#if defined(ultrix) || defined(__osf__) || (defined(__NetBSD__) && __NetBSD_Version__ > 106000000)
-#define PCAP_FDDIPAD 3
-#endif
-
typedef int (*activate_op_t)(pcap_t *);
typedef int (*can_set_rfmon_op_t)(pcap_t *);
typedef int (*read_op_t)(pcap_t *, int cnt, pcap_handler, u_char *);
#endif
typedef void (*cleanup_op_t)(pcap_t *);
+/*
+ * We put all the stuff used in the read code path at the beginning,
+ * to try to keep it together in the same cache line or lines.
+ */
struct pcap {
+ /*
+ * Method to call to read packets on a live capture.
+ */
+ read_op_t read_op;
+
+ /*
+ * Method to call to read to read packets from a savefile.
+ */
+ int (*next_packet_op)(pcap_t *, struct pcap_pkthdr *, u_char **);
+
#ifdef WIN32
ADAPTER *adapter;
LPPACKET Packet;
#else
int fd;
int selectable_fd;
- int send_fd;
#endif /* WIN32 */
-#ifdef HAVE_LIBDLPI
- dlpi_handle_t dlpi_hd;
-#endif
+ /*
+ * Read buffer.
+ */
+ int bufsize;
+ u_char *buffer;
+ u_char *bp;
+ int cc;
+
+ int break_loop; /* flag set to force break from packet-reading loop */
+
+ void *private; /* private data for methods */
+
+ int swapped;
+ FILE *rfile; /* null if live capture, non-null if savefile */
+ int fddipad;
+ struct pcap *next; /* list of open pcaps that need stuff cleared on close */
+
+ /*
+ * File version number; meaningful only for a savefile, but we
+ * keep it here so that apps that (mistakenly) ask for the
+ * version numbers will get the same zero values that they
+ * always did.
+ */
+ int version_major;
+ int version_minor;
+
int snapshot;
int linktype; /* Network linktype */
int linktype_ext; /* Extended information stored in the linktype field of a file */
int activated; /* true if the capture is really started */
int oldstyle; /* if we're opening with pcap_open_live() */
- int break_loop; /* flag set to force break from packet-reading loop */
-
-#ifdef PCAP_FDDIPAD
- int fddipad;
-#endif
-
-#ifdef MSDOS
- void (*wait_proc)(void); /* call proc while waiting */
-#endif
-
- struct pcap_sf sf;
- struct pcap_md md;
struct pcap_opt opt;
- /*
- * Read buffer.
- */
- int bufsize;
- u_char *buffer;
- u_char *bp;
- int cc;
-
/*
* Place holder for pcap_next().
*/
pcap_direction_t direction;
/*
- * Methods.
+ * Placeholder for filter code if bpf not in kernel.
+ */
+ struct bpf_program fcode;
+
+ char errbuf[PCAP_ERRBUF_SIZE + 1];
+ int dlt_count;
+ u_int *dlt_list;
+ int tstamp_type_count;
+ u_int *tstamp_type_list;
+
+ struct pcap_pkthdr pcap_header; /* This is needed for the pcap_next_ex() to work */
+
+ /*
+ * More methods.
*/
activate_op_t activate_op;
can_set_rfmon_op_t can_set_rfmon_op;
- read_op_t read_op;
inject_op_t inject_op;
setfilter_op_t setfilter_op;
setdirection_op_t setdirection_op;
setmintocopy_op_t setmintocopy_op;
#endif
cleanup_op_t cleanup_op;
-
- /*
- * Placeholder for filter code if bpf not in kernel.
- */
- struct bpf_program fcode;
-
- char errbuf[PCAP_ERRBUF_SIZE + 1];
- int dlt_count;
- u_int *dlt_list;
- int tstamp_type_count;
- u_int *tstamp_type_list;
-
- struct pcap_pkthdr pcap_header; /* This is needed for the pcap_next_ex() to work */
};
/*
* by pcap_create routines.
*/
pcap_t *pcap_create_interface(const char *, char *);
-pcap_t *pcap_create_common(const char *, char *);
+pcap_t *pcap_create_common(const char *, char *, size_t);
int pcap_do_addexit(pcap_t *);
void pcap_add_to_pcaps_to_close(pcap_t *);
void pcap_remove_from_pcaps_to_close(pcap_t *);
int add_or_find_if(pcap_if_t **, pcap_if_t **, const char *, u_int,
const char *, char *);
+/*
+ * Internal interfaces for "pcap_open_offline()".
+ *
+ * "pcap_open_offline_common()" allocates and fills in a pcap_t, for use
+ * by pcap_open_offline routines.
+ */
+pcap_t *pcap_open_offline_common(char *ebuf, size_t size);
+
#ifdef WIN32
char *pcap_win32strerror(void);
#endif
static int
pcap_activate_libdlpi(pcap_t *p)
{
+ struct pcap_dlpi *pd = p->private;
int retv;
dlpi_handle_t dh;
dlpi_info_t dlinfo;
p->errbuf);
return (err);
}
- p->dlpi_hd = dh;
+ pd->dlpi_hd = dh;
if (p->opt.rfmon) {
/*
}
/* Bind with DLPI_ANY_SAP. */
- if ((retv = dlpi_bind(p->dlpi_hd, DLPI_ANY_SAP, 0)) != DLPI_SUCCESS) {
+ if ((retv = dlpi_bind(pd->dlpi_hd, DLPI_ANY_SAP, 0)) != DLPI_SUCCESS) {
pcap_libdlpi_err(p->opt.source, "dlpi_bind", retv, p->errbuf);
goto bad;
}
}
/* Determine link type. */
- if ((retv = dlpi_info(p->dlpi_hd, &dlinfo, 0)) != DLPI_SUCCESS) {
+ if ((retv = dlpi_info(pd->dlpi_hd, &dlinfo, 0)) != DLPI_SUCCESS) {
pcap_libdlpi_err(p->opt.source, "dlpi_info", retv, p->errbuf);
goto bad;
}
if (pcap_process_mactype(p, dlinfo.di_mactype) != 0)
goto bad;
- p->fd = dlpi_fd(p->dlpi_hd);
+ p->fd = dlpi_fd(pd->dlpi_hd);
/* Push and configure bufmod. */
- if (pcap_conf_bufmod(p, p->snapshot, p->md.timeout) != 0)
+ if (pcap_conf_bufmod(p, p->snapshot, p->opt.timeout) != 0)
goto bad;
/*
static int
dlpromiscon(pcap_t *p, bpf_u_int32 level)
{
+ struct pcap_dlpi *pd = p->private;
int retv;
int err;
- retv = dlpi_promiscon(p->dlpi_hd, level);
+ retv = dlpi_promiscon(pd->dlpi_hd, level);
if (retv != DLPI_SUCCESS) {
if (retv == DL_SYSERR &&
(errno == EPERM || errno == EACCES))
static int
pcap_read_libdlpi(pcap_t *p, int count, pcap_handler callback, u_char *user)
{
+ struct pcap_dlpi *pd = p->private;
int len;
u_char *bufp;
size_t msglen;
msglen = p->bufsize;
bufp = p->buffer + p->offset;
- retv = dlpi_recv(p->dlpi_hd, NULL, NULL, bufp,
+ retv = dlpi_recv(pd->dlpi_hd, NULL, NULL, bufp,
&msglen, -1, NULL);
if (retv != DLPI_SUCCESS) {
/*
len = 0;
continue;
}
- pcap_libdlpi_err(dlpi_linkname(p->dlpi_hd),
+ pcap_libdlpi_err(dlpi_linkname(pd->dlpi_hd),
"dlpi_recv", retv, p->errbuf);
return (-1);
}
static int
pcap_inject_libdlpi(pcap_t *p, const void *buf, size_t size)
{
+ struct pcap_dlpi *pd = p->private;
int retv;
- retv = dlpi_send(p->dlpi_hd, NULL, 0, buf, size, NULL);
+ retv = dlpi_send(pd->dlpi_hd, NULL, 0, buf, size, NULL);
if (retv != DLPI_SUCCESS) {
- pcap_libdlpi_err(dlpi_linkname(p->dlpi_hd), "dlpi_send", retv,
+ pcap_libdlpi_err(dlpi_linkname(pd->dlpi_hd), "dlpi_send", retv,
p->errbuf);
return (-1);
}
static void
pcap_cleanup_libdlpi(pcap_t *p)
{
- if (p->dlpi_hd != NULL) {
- dlpi_close(p->dlpi_hd);
- p->dlpi_hd = NULL;
+ struct pcap_dlpi *pd = p->private;
+
+ if (pd->dlpi_hd != NULL) {
+ dlpi_close(pd->dlpi_hd);
+ pd->dlpi_hd = NULL;
p->fd = -1;
}
pcap_cleanup_live_common(p);
{
pcap_t *p;
- p = pcap_create_common(device, ebuf);
+ p = pcap_create_common(device, ebuf, sizeof (struct pcap_dlpi));
if (p == NULL)
return (NULL);
*/
#define BIGGER_THAN_ALL_MTUS (64*1024)
+/*
+ * Private data for capturing on Linux SOCK_PACKET or PF_PACKET sockets.
+ */
+struct pcap_linux {
+ u_int packets_read; /* count of packets read with recvfrom() */
+ long proc_dropped; /* packets reported dropped by /proc/net/dev */
+ struct pcap_stat stat;
+
+ char *device; /* device name */
+ int filtering_in_kernel; /* using kernel filter */
+ int must_do_on_close; /* stuff we must do when we close */
+ int timeout; /* timeout for buffering */
+ int sock_packet; /* using Linux 2.0 compatible interface */
+ int cooked; /* using SOCK_DGRAM rather than SOCK_RAW */
+ int ifindex; /* interface index of device we're bound to */
+ int lo_ifindex; /* interface index of the loopback device */
+ bpf_u_int32 oldmode; /* mode to restore when turning monitor mode off */
+ char *mondevice; /* mac80211 monitor device we created */
+ u_char *mmapbuf; /* memory-mapped region pointer */
+ size_t mmapbuflen; /* size of region */
+ int vlan_offset; /* offset at which to insert vlan tags; if -1, don't insert */
+ u_int tp_version; /* version of tpacket_hdr for mmaped ring */
+ u_int tp_hdrlen; /* hdrlen of tpacket_hdr for mmaped ring */
+ u_char *oneshot_buffer; /* buffer for copy of packet */
+};
+
+/*
+ * Stuff to do when we close.
+ */
+#define MUST_CLEAR_PROMISC 0x00000001 /* clear promiscuous mode */
+#define MUST_CLEAR_RFMON 0x00000002 /* clear rfmon (monitor) mode */
+#define MUST_DELETE_MONIF 0x00000004 /* delete monitor-mode interface */
+
/*
* Prototypes for internal functions and methods.
*/
{
pcap_t *handle;
- handle = pcap_create_common(device, ebuf);
+ handle = pcap_create_common(device, ebuf, sizeof (struct pcap_linux));
if (handle == NULL)
return NULL;
static int
enter_rfmon_mode_mac80211(pcap_t *handle, int sock_fd, const char *device)
{
+ struct pcap_linux *handlep = handle->private;
int ret;
char phydev_path[PATH_MAX+1];
struct nl80211_state nlstate;
snprintf(mondevice, sizeof mondevice, "mon%u", n);
ret = add_mon_if(handle, sock_fd, &nlstate, device, mondevice);
if (ret == 1) {
- handle->md.mondevice = strdup(mondevice);
+ handlep->mondevice = strdup(mondevice);
goto added;
}
if (ret < 0) {
* Now configure the monitor interface up.
*/
memset(&ifr, 0, sizeof(ifr));
- strncpy(ifr.ifr_name, handle->md.mondevice, sizeof(ifr.ifr_name));
+ strncpy(ifr.ifr_name, handlep->mondevice, sizeof(ifr.ifr_name));
if (ioctl(sock_fd, SIOCGIFFLAGS, &ifr) == -1) {
snprintf(handle->errbuf, PCAP_ERRBUF_SIZE,
"%s: Can't get flags for %s: %s", device,
- handle->md.mondevice, strerror(errno));
+ handlep->mondevice, strerror(errno));
del_mon_if(handle, sock_fd, &nlstate, device,
- handle->md.mondevice);
+ handlep->mondevice);
nl80211_cleanup(&nlstate);
return PCAP_ERROR;
}
if (ioctl(sock_fd, SIOCSIFFLAGS, &ifr) == -1) {
snprintf(handle->errbuf, PCAP_ERRBUF_SIZE,
"%s: Can't set flags for %s: %s", device,
- handle->md.mondevice, strerror(errno));
+ handlep->mondevice, strerror(errno));
del_mon_if(handle, sock_fd, &nlstate, device,
- handle->md.mondevice);
+ handlep->mondevice);
nl80211_cleanup(&nlstate);
return PCAP_ERROR;
}
* Note that we have to delete the monitor device when we close
* the handle.
*/
- handle->md.must_do_on_close |= MUST_DELETE_MONIF;
+ handlep->must_do_on_close |= MUST_DELETE_MONIF;
/*
* Add this to the list of pcaps to close when we exit.
static void pcap_cleanup_linux( pcap_t *handle )
{
+ struct pcap_linux *handlep = handle->private;
struct ifreq ifr;
#ifdef HAVE_LIBNL
struct nl80211_state nlstate;
struct iwreq ireq;
#endif /* IW_MODE_MONITOR */
- if (handle->md.must_do_on_close != 0) {
+ if (handlep->must_do_on_close != 0) {
/*
* There's something we have to do when closing this
* pcap_t.
*/
- if (handle->md.must_do_on_close & MUST_CLEAR_PROMISC) {
+ if (handlep->must_do_on_close & MUST_CLEAR_PROMISC) {
/*
* We put the interface into promiscuous mode;
* take it out of promiscuous mode.
* in 2.0[.x] kernels.
*/
memset(&ifr, 0, sizeof(ifr));
- strncpy(ifr.ifr_name, handle->md.device,
+ strncpy(ifr.ifr_name, handlep->device,
sizeof(ifr.ifr_name));
if (ioctl(handle->fd, SIOCGIFFLAGS, &ifr) == -1) {
fprintf(stderr,
"Can't restore interface %s flags (SIOCGIFFLAGS failed: %s).\n"
"Please adjust manually.\n"
"Hint: This can't happen with Linux >= 2.2.0.\n",
- handle->md.device, strerror(errno));
+ handlep->device, strerror(errno));
} else {
if (ifr.ifr_flags & IFF_PROMISC) {
/*
"Can't restore interface %s flags (SIOCSIFFLAGS failed: %s).\n"
"Please adjust manually.\n"
"Hint: This can't happen with Linux >= 2.2.0.\n",
- handle->md.device,
+ handlep->device,
strerror(errno));
}
}
}
#ifdef HAVE_LIBNL
- if (handle->md.must_do_on_close & MUST_DELETE_MONIF) {
- ret = nl80211_init(handle, &nlstate, handle->md.device);
+ if (handlep->must_do_on_close & MUST_DELETE_MONIF) {
+ ret = nl80211_init(handle, &nlstate, handlep->device);
if (ret >= 0) {
ret = del_mon_if(handle, handle->fd, &nlstate,
- handle->md.device, handle->md.mondevice);
+ handlep->device, handlep->mondevice);
nl80211_cleanup(&nlstate);
}
if (ret < 0) {
fprintf(stderr,
"Can't delete monitor interface %s (%s).\n"
"Please delete manually.\n",
- handle->md.mondevice, handle->errbuf);
+ handlep->mondevice, handle->errbuf);
}
}
#endif /* HAVE_LIBNL */
#ifdef IW_MODE_MONITOR
- if (handle->md.must_do_on_close & MUST_CLEAR_RFMON) {
+ if (handlep->must_do_on_close & MUST_CLEAR_RFMON) {
/*
* We put the interface into rfmon mode;
* take it out of rfmon mode.
*/
oldflags = 0;
memset(&ifr, 0, sizeof(ifr));
- strncpy(ifr.ifr_name, handle->md.device,
+ strncpy(ifr.ifr_name, handlep->device,
sizeof(ifr.ifr_name));
if (ioctl(handle->fd, SIOCGIFFLAGS, &ifr) != -1) {
if (ifr.ifr_flags & IFF_UP) {
/*
* Now restore the mode.
*/
- strncpy(ireq.ifr_ifrn.ifrn_name, handle->md.device,
+ strncpy(ireq.ifr_ifrn.ifrn_name, handlep->device,
sizeof ireq.ifr_ifrn.ifrn_name);
ireq.ifr_ifrn.ifrn_name[sizeof ireq.ifr_ifrn.ifrn_name - 1]
= 0;
- ireq.u.mode = handle->md.oldmode;
+ ireq.u.mode = handlep->oldmode;
if (ioctl(handle->fd, SIOCSIWMODE, &ireq) == -1) {
/*
* Scientist, you've failed.
fprintf(stderr,
"Can't restore interface %s wireless mode (SIOCSIWMODE failed: %s).\n"
"Please adjust manually.\n",
- handle->md.device, strerror(errno));
+ handlep->device, strerror(errno));
}
/*
fprintf(stderr,
"Can't bring interface %s back up (SIOCSIFFLAGS failed: %s).\n"
"Please adjust manually.\n",
- handle->md.device, strerror(errno));
+ handlep->device, strerror(errno));
}
}
}
pcap_remove_from_pcaps_to_close(handle);
}
- if (handle->md.mondevice != NULL) {
- free(handle->md.mondevice);
- handle->md.mondevice = NULL;
+ if (handlep->mondevice != NULL) {
+ free(handlep->mondevice);
+ handlep->mondevice = NULL;
}
- if (handle->md.device != NULL) {
- free(handle->md.device);
- handle->md.device = NULL;
+ if (handlep->device != NULL) {
+ free(handlep->device);
+ handlep->device = NULL;
}
pcap_cleanup_live_common(handle);
}
static int
pcap_activate_linux(pcap_t *handle)
{
+ struct pcap_linux *handlep = handle->private;
const char *device;
int status = 0;
}
}
- handle->md.device = strdup(device);
- if (handle->md.device == NULL) {
+ handlep->device = strdup(device);
+ if (handlep->device == NULL) {
snprintf(handle->errbuf, PCAP_ERRBUF_SIZE, "strdup: %s",
pcap_strerror(errno) );
return PCAP_ERROR;
}
+ /* copy timeout value */
+ handlep->timeout = handle->opt.timeout;
+
/*
* If we're in promiscuous mode, then we probably want
* to see when the interface drops packets too, so get an
* initial count from /proc/net/dev
*/
if (handle->opt.promisc)
- handle->md.proc_dropped = linux_if_drops(handle->md.device);
+ handlep->proc_dropped = linux_if_drops(handlep->device);
/*
* Current Linux kernels use the protocol family PF_PACKET to
static int
pcap_read_packet(pcap_t *handle, pcap_handler callback, u_char *userdata)
{
+ struct pcap_linux *handlep = handle->private;
u_char *bp;
int offset;
#ifdef HAVE_PF_PACKET_SOCKETS
* If this is a cooked device, leave extra room for a
* fake packet header.
*/
- if (handle->md.cooked)
+ if (handlep->cooked)
offset = SLL_HDR_LEN;
else
offset = 0;
}
#ifdef HAVE_PF_PACKET_SOCKETS
- if (!handle->md.sock_packet) {
+ if (!handlep->sock_packet) {
/*
* Unfortunately, there is a window between socket() and
* bind() where the kernel may queue packets from any
* filter support, and it's a bit more complicated.
* It would save some instructions per packet, however.)
*/
- if (handle->md.ifindex != -1 &&
- from.sll_ifindex != handle->md.ifindex)
+ if (handlep->ifindex != -1 &&
+ from.sll_ifindex != handlep->ifindex)
return 0;
/*
* we'll see the packet as an incoming packet as well,
* and we don't want to see it twice.
*/
- if (from.sll_ifindex == handle->md.lo_ifindex)
+ if (from.sll_ifindex == handlep->lo_ifindex)
return 0;
/*
/*
* If this is a cooked device, fill in the fake packet header.
*/
- if (handle->md.cooked) {
+ if (handlep->cooked) {
/*
* Add the length of the fake header to the length
* of packet data we read.
}
#if defined(HAVE_PACKET_AUXDATA) && defined(HAVE_LINUX_TPACKET_AUXDATA_TP_VLAN_TCI)
- if (handle->md.vlan_offset != -1) {
+ if (handlep->vlan_offset != -1) {
for (cmsg = CMSG_FIRSTHDR(&msg); cmsg; cmsg = CMSG_NXTHDR(&msg, cmsg)) {
struct tpacket_auxdata *aux;
unsigned int len;
continue;
len = packet_len > iov.iov_len ? iov.iov_len : packet_len;
- if (len < (unsigned int) handle->md.vlan_offset)
+ if (len < (unsigned int) handlep->vlan_offset)
break;
bp -= VLAN_TAG_LEN;
- memmove(bp, bp + VLAN_TAG_LEN, handle->md.vlan_offset);
+ memmove(bp, bp + VLAN_TAG_LEN, handlep->vlan_offset);
- tag = (struct vlan_tag *)(bp + handle->md.vlan_offset);
+ tag = (struct vlan_tag *)(bp + handlep->vlan_offset);
tag->vlan_tpid = htons(ETH_P_8021Q);
tag->vlan_tci = htons(aux->tp_vlan_tci);
caplen = handle->snapshot;
/* Run the packet filter if not using kernel filter */
- if (!handle->md.use_bpf && handle->fcode.bf_insns) {
+ if (!handlep->filtering_in_kernel && handle->fcode.bf_insns) {
if (bpf_filter(handle->fcode.bf_insns, bp,
packet_len, caplen) == 0)
{
* the count is more expensive than always testing a flag
* in memory.
*
- * We keep the count in "md.packets_read", and use that for
- * "ps_recv" if we can't get the statistics from the kernel.
+ * We keep the count in "handlep->packets_read", and use that
+ * for "ps_recv" if we can't get the statistics from the kernel.
* We do that because, if we *can* get the statistics from
- * the kernel, we use "md.stat.ps_recv" and "md.stat.ps_drop"
- * as running counts, as reading the statistics from the
- * kernel resets the kernel statistics, and if we directly
- * increment "md.stat.ps_recv" here, that means it will
- * count packets *twice* on systems where we can get kernel
- * statistics - once here, and once in pcap_stats_linux().
+ * the kernel, we use "handlep->stat.ps_recv" and
+ * "handlep->stat.ps_drop" as running counts, as reading the
+ * statistics from the kernel resets the kernel statistics,
+ * and if we directly increment "handlep->stat.ps_recv" here,
+ * that means it will count packets *twice* on systems where
+ * we can get kernel statistics - once here, and once in
+ * pcap_stats_linux().
*/
- handle->md.packets_read++;
+ handlep->packets_read++;
/* Call the user supplied callback function */
callback(userdata, &pcap_header, bp);
static int
pcap_inject_linux(pcap_t *handle, const void *buf, size_t size)
{
+ struct pcap_linux *handlep = handle->private;
int ret;
#ifdef HAVE_PF_PACKET_SOCKETS
- if (!handle->md.sock_packet) {
+ if (!handlep->sock_packet) {
/* PF_PACKET socket */
- if (handle->md.ifindex == -1) {
+ if (handlep->ifindex == -1) {
/*
* We don't support sending on the "any" device.
*/
return (-1);
}
- if (handle->md.cooked) {
+ if (handlep->cooked) {
/*
* We don't support sending on the "any" device.
*
static int
pcap_stats_linux(pcap_t *handle, struct pcap_stat *stats)
{
+ struct pcap_linux *handlep = handle->private;
#ifdef HAVE_TPACKET_STATS
struct tpacket_stats kstats;
socklen_t len = sizeof (struct tpacket_stats);
*/
if (handle->opt.promisc)
{
- if_dropped = handle->md.proc_dropped;
- handle->md.proc_dropped = linux_if_drops(handle->md.device);
- handle->md.stat.ps_ifdrop += (handle->md.proc_dropped - if_dropped);
+ if_dropped = handlep->proc_dropped;
+ handlep->proc_dropped = linux_if_drops(handlep->device);
+ handlep->stat.ps_ifdrop += (handlep->proc_dropped - if_dropped);
}
#ifdef HAVE_TPACKET_STATS
* getsockopt(handle->fd, SOL_PACKET, PACKET_STATISTICS, ....
* resets the counters to zero.
*/
- handle->md.stat.ps_recv += kstats.tp_packets;
- handle->md.stat.ps_drop += kstats.tp_drops;
- *stats = handle->md.stat;
+ handlep->stat.ps_recv += kstats.tp_packets;
+ handlep->stat.ps_drop += kstats.tp_drops;
+ *stats = handlep->stat;
return 0;
}
else
* the kernel by libpcap.
*
* We maintain the count of packets processed by libpcap in
- * "md.packets_read", for reasons described in the comment
+ * "handlep->packets_read", for reasons described in the comment
* at the end of pcap_read_packet(). We have no idea how many
* packets were dropped by the kernel buffers -- but we know
* how many the interface dropped, so we can return that.
*/
- stats->ps_recv = handle->md.packets_read;
+ stats->ps_recv = handlep->packets_read;
stats->ps_drop = 0;
- stats->ps_ifdrop = handle->md.stat.ps_ifdrop;
+ stats->ps_ifdrop = handlep->stat.ps_ifdrop;
return 0;
}
pcap_setfilter_linux_common(pcap_t *handle, struct bpf_program *filter,
int is_mmapped)
{
+ struct pcap_linux *handlep;
#ifdef SO_ATTACH_FILTER
struct sock_fprog fcode;
int can_filter_in_kernel;
return -1;
}
+ handlep = handle->private;
+
/* Make our private copy of the filter */
if (install_bpf_program(handle, filter) < 0)
* Run user level packet filter by default. Will be overriden if
* installing a kernel filter succeeds.
*/
- handle->md.use_bpf = 0;
+ handlep->filtering_in_kernel = 0;
/* Install kernel level filter if possible */
if ((err = set_kernel_filter(handle, &fcode)) == 0)
{
/* Installation succeded - using kernel filter. */
- handle->md.use_bpf = 1;
+ handlep->filtering_in_kernel = 1;
}
else if (err == -1) /* Non-fatal error */
{
* calling "pcap_setfilter()". Otherwise, the kernel filter may
* filter out packets that would pass the new userland filter.
*/
- if (!handle->md.use_bpf)
+ if (!handlep->filtering_in_kernel)
reset_kernel_filter(handle);
/*
pcap_setdirection_linux(pcap_t *handle, pcap_direction_t d)
{
#ifdef HAVE_PF_PACKET_SOCKETS
- if (!handle->md.sock_packet) {
+ struct pcap_linux *handlep = handle->private;
+
+ if (!handlep->sock_packet) {
handle->direction = d;
return 0;
}
handle->linktype = DLT_LINUX_IRDA;
/* We need to save packet direction for IrDA decoding,
* so let's use "Linux-cooked" mode. Jean II */
- //handle->md.cooked = 1;
+ //handlep->cooked = 1;
break;
/* ARPHRD_LAPD is unofficial and randomly allocated, if reallocation
activate_new(pcap_t *handle)
{
#ifdef HAVE_PF_PACKET_SOCKETS
+ struct pcap_linux *handlep = handle->private;
const char *device = handle->opt.source;
int is_any_device = (strcmp(device, "any") == 0);
int sock_fd = -1, arptype;
}
/* It seems the kernel supports the new interface. */
- handle->md.sock_packet = 0;
+ handlep->sock_packet = 0;
/*
* Get the interface index of the loopback device.
* If the attempt fails, don't fail, just set the
- * "md.lo_ifindex" to -1.
+ * "handlep->lo_ifindex" to -1.
*
* XXX - can there be more than one device that loops
* packets back, i.e. devices other than "lo"? If so,
* indices for them, and check all of them in
* "pcap_read_packet()".
*/
- handle->md.lo_ifindex = iface_get_id(sock_fd, "lo", handle->errbuf);
+ handlep->lo_ifindex = iface_get_id(sock_fd, "lo", handle->errbuf);
/*
* Default value for offset to align link-layer payload
*/
if (!is_any_device) {
/* Assume for now we don't need cooked mode. */
- handle->md.cooked = 0;
+ handlep->cooked = 0;
if (handle->opt.rfmon) {
/*
* device to open for monitor mode. If we've
* been given a different device, use it.
*/
- if (handle->md.mondevice != NULL)
- device = handle->md.mondevice;
+ if (handlep->mondevice != NULL)
+ device = handlep->mondevice;
}
arptype = iface_get_arptype(sock_fd, device, handle->errbuf);
if (arptype < 0) {
return PCAP_ERROR;
}
}
- handle->md.cooked = 1;
+ handlep->cooked = 1;
/*
* Get rid of any link-layer type list
handle->linktype = DLT_LINUX_SLL;
}
- handle->md.ifindex = iface_get_id(sock_fd, device,
+ handlep->ifindex = iface_get_id(sock_fd, device,
handle->errbuf);
- if (handle->md.ifindex == -1) {
+ if (handlep->ifindex == -1) {
close(sock_fd);
return PCAP_ERROR;
}
- if ((err = iface_bind(sock_fd, handle->md.ifindex,
+ if ((err = iface_bind(sock_fd, handlep->ifindex,
handle->errbuf)) != 1) {
close(sock_fd);
if (err < 0)
/*
* It uses cooked mode.
*/
- handle->md.cooked = 1;
+ handlep->cooked = 1;
handle->linktype = DLT_LINUX_SLL;
/*
* if we figure out how to transmit in cooked
* mode.
*/
- handle->md.ifindex = -1;
+ handlep->ifindex = -1;
}
/*
if (!is_any_device && handle->opt.promisc) {
memset(&mr, 0, sizeof(mr));
- mr.mr_ifindex = handle->md.ifindex;
+ mr.mr_ifindex = handlep->ifindex;
mr.mr_type = PACKET_MR_PROMISC;
if (setsockopt(sock_fd, SOL_PACKET, PACKET_ADD_MEMBERSHIP,
&mr, sizeof(mr)) == -1) {
* 1 byte of packet data (so we don't pass a byte
* count of 0 to "recvfrom()").
*/
- if (handle->md.cooked) {
+ if (handlep->cooked) {
if (handle->snapshot < SLL_HDR_LEN + 1)
handle->snapshot = SLL_HDR_LEN + 1;
}
switch (handle->linktype) {
case DLT_EN10MB:
- handle->md.vlan_offset = 2 * ETH_ALEN;
+ handlep->vlan_offset = 2 * ETH_ALEN;
break;
case DLT_LINUX_SLL:
- handle->md.vlan_offset = 14;
+ handlep->vlan_offset = 14;
break;
default:
- handle->md.vlan_offset = -1; /* unknown */
+ handlep->vlan_offset = -1; /* unknown */
break;
}
static int
activate_mmap(pcap_t *handle, int *status)
{
+ struct pcap_linux *handlep = handle->private;
int ret;
/*
* Attempt to allocate a buffer to hold the contents of one
* packet, for use by the oneshot callback.
*/
- handle->md.oneshot_buffer = malloc(handle->snapshot);
- if (handle->md.oneshot_buffer == NULL) {
+ handlep->oneshot_buffer = malloc(handle->snapshot);
+ if (handlep->oneshot_buffer == NULL) {
snprintf(handle->errbuf, PCAP_ERRBUF_SIZE,
"can't allocate oneshot buffer: %s",
pcap_strerror(errno));
}
ret = prepare_tpacket_socket(handle);
if (ret == -1) {
- free(handle->md.oneshot_buffer);
+ free(handlep->oneshot_buffer);
*status = PCAP_ERROR;
return ret;
}
* We don't support memory-mapped capture; our caller
* will fall back on reading from the socket.
*/
- free(handle->md.oneshot_buffer);
+ free(handlep->oneshot_buffer);
return 0;
}
if (ret == -1) {
* Error attempting to enable memory-mapped capture;
* fail. create_ring() has set *status.
*/
- free(handle->md.oneshot_buffer);
+ free(handlep->oneshot_buffer);
return -1;
}
static int
prepare_tpacket_socket(pcap_t *handle)
{
+ struct pcap_linux *handlep = handle->private;
#ifdef HAVE_TPACKET2
socklen_t len;
int val;
#endif
- handle->md.tp_version = TPACKET_V1;
- handle->md.tp_hdrlen = sizeof(struct tpacket_hdr);
+ handlep->tp_version = TPACKET_V1;
+ handlep->tp_hdrlen = sizeof(struct tpacket_hdr);
#ifdef HAVE_TPACKET2
/* Probe whether kernel supports TPACKET_V2 */
pcap_strerror(errno));
return -1;
}
- handle->md.tp_hdrlen = val;
+ handlep->tp_hdrlen = val;
val = TPACKET_V2;
if (setsockopt(handle->fd, SOL_PACKET, PACKET_VERSION, &val,
pcap_strerror(errno));
return -1;
}
- handle->md.tp_version = TPACKET_V2;
+ handlep->tp_version = TPACKET_V2;
/* Reserve space for VLAN tag reconstruction */
val = VLAN_TAG_LEN;
static int
create_ring(pcap_t *handle, int *status)
{
+ struct pcap_linux *handlep = handle->private;
unsigned i, j, frames_per_block;
struct tpacket_req req;
socklen_t len;
* let's use it.. maybe is it even large enough to directly
* replace macoff..
*/
- tp_hdrlen = TPACKET_ALIGN(handle->md.tp_hdrlen) + sizeof(struct sockaddr_ll) ;
+ tp_hdrlen = TPACKET_ALIGN(handlep->tp_hdrlen) + sizeof(struct sockaddr_ll) ;
netoff = TPACKET_ALIGN(tp_hdrlen + (maclen < 16 ? 16 : maclen)) + tp_reserve;
/* NOTE: AFAICS tp_reserve may break the TPACKET_ALIGN of
* netoff, which contradicts
}
/* memory map the rx ring */
- handle->md.mmapbuflen = req.tp_block_nr * req.tp_block_size;
- handle->md.mmapbuf = mmap(0, handle->md.mmapbuflen,
+ handlep->mmapbuflen = req.tp_block_nr * req.tp_block_size;
+ handlep->mmapbuf = mmap(0, handlep->mmapbuflen,
PROT_READ|PROT_WRITE, MAP_SHARED, handle->fd, 0);
- if (handle->md.mmapbuf == MAP_FAILED) {
+ if (handlep->mmapbuf == MAP_FAILED) {
snprintf(handle->errbuf, PCAP_ERRBUF_SIZE,
"can't mmap rx ring: %s", pcap_strerror(errno));
/* fill the header ring with proper frame ptr*/
handle->offset = 0;
for (i=0; i<req.tp_block_nr; ++i) {
- void *base = &handle->md.mmapbuf[i*req.tp_block_size];
+ void *base = &handlep->mmapbuf[i*req.tp_block_size];
for (j=0; j<frames_per_block; ++j, ++handle->offset) {
RING_GET_FRAME(handle) = base;
base += req.tp_frame_size;
static void
destroy_ring(pcap_t *handle)
{
+ struct pcap_linux *handlep = handle->private;
+
/* tell the kernel to destroy the ring*/
struct tpacket_req req;
memset(&req, 0, sizeof(req));
(void *) &req, sizeof(req));
/* if ring is mapped, unmap it*/
- if (handle->md.mmapbuf) {
+ if (handlep->mmapbuf) {
/* do not test for mmap failure, as we can't recover from any error */
- munmap(handle->md.mmapbuf, handle->md.mmapbuflen);
- handle->md.mmapbuf = NULL;
+ munmap(handlep->mmapbuf, handlep->mmapbuflen);
+ handlep->mmapbuf = NULL;
}
}
const u_char *bytes)
{
struct oneshot_userdata *sp = (struct oneshot_userdata *)user;
+ pcap_t *handle = sp->pd;
+ struct pcap_linux *handlep = handle->private;
*sp->hdr = *h;
- memcpy(sp->pd->md.oneshot_buffer, bytes, h->caplen);
- *sp->pkt = sp->pd->md.oneshot_buffer;
+ memcpy(handlep->oneshot_buffer, bytes, h->caplen);
+ *sp->pkt = handlep->oneshot_buffer;
}
static void
pcap_cleanup_linux_mmap( pcap_t *handle )
{
+ struct pcap_linux *handlep = handle->private;
+
destroy_ring(handle);
- if (handle->md.oneshot_buffer != NULL) {
- free(handle->md.oneshot_buffer);
- handle->md.oneshot_buffer = NULL;
+ if (handlep->oneshot_buffer != NULL) {
+ free(handlep->oneshot_buffer);
+ handlep->oneshot_buffer = NULL;
}
pcap_cleanup_linux(handle);
}
static int
pcap_getnonblock_mmap(pcap_t *p, char *errbuf)
{
+ struct pcap_linux *handlep = p->private;
+
/* use negative value of timeout to indicate non blocking ops */
- return (p->md.timeout<0);
+ return (handlep->timeout<0);
}
static int
pcap_setnonblock_mmap(pcap_t *p, int nonblock, char *errbuf)
{
+ struct pcap_linux *handlep = p->private;
+
/*
* Map each value to their corresponding negation to
* preserve the timeout value provided with pcap_set_timeout.
*/
if (nonblock) {
- if (p->md.timeout >= 0) {
+ if (handlep->timeout >= 0) {
/*
* Indicate that we're switching to
* non-blocking mode.
*/
- p->md.timeout = ~p->md.timeout;
+ handlep->timeout = ~handlep->timeout;
}
} else {
- if (p->md.timeout < 0) {
- p->md.timeout = ~p->md.timeout;
+ if (handlep->timeout < 0) {
+ handlep->timeout = ~handlep->timeout;
}
}
return 0;
static inline union thdr *
pcap_get_ring_frame(pcap_t *handle, int status)
{
+ struct pcap_linux *handlep = handle->private;
union thdr h;
h.raw = RING_GET_FRAME(handle);
- switch (handle->md.tp_version) {
+ switch (handlep->tp_version) {
case TPACKET_V1:
if (status != (h.h1->tp_status ? TP_STATUS_USER :
TP_STATUS_KERNEL))
pcap_read_linux_mmap(pcap_t *handle, int max_packets, pcap_handler callback,
u_char *user)
{
+ struct pcap_linux *handlep = handle->private;
int timeout;
int pkts = 0;
char c;
pollinfo.fd = handle->fd;
pollinfo.events = POLLIN;
- if (handle->md.timeout == 0)
+ if (handlep->timeout == 0)
timeout = -1; /* block forever */
- else if (handle->md.timeout > 0)
- timeout = handle->md.timeout; /* block for that amount of time */
+ else if (handlep->timeout > 0)
+ timeout = handlep->timeout; /* block for that amount of time */
else
timeout = 0; /* non-blocking mode - poll to pick up errors */
do {
if (!h.raw)
break;
- switch (handle->md.tp_version) {
+ switch (handlep->tp_version) {
case TPACKET_V1:
tp_len = h.h1->tp_len;
tp_mac = h.h1->tp_mac;
default:
snprintf(handle->errbuf, PCAP_ERRBUF_SIZE,
"unsupported tpacket version %d",
- handle->md.tp_version);
+ handlep->tp_version);
return -1;
}
/* perform sanity check on internal offset. */
* If the kernel filtering is enabled we need to run the
* filter until all the frames present into the ring
* at filter creation time are processed.
- * In such case md.use_bpf is used as a counter for the
+ * In such case filtering_in_kernel is used as a counter for the
* packet we need to filter.
* Note: alternatively it could be possible to stop applying
* the filter when the ring became empty, but it can possibly
* happen a lot later... */
bp = (unsigned char*)h.raw + tp_mac;
- run_bpf = (!handle->md.use_bpf) ||
- ((handle->md.use_bpf>1) && handle->md.use_bpf--);
+ run_bpf = (!handlep->filtering_in_kernel) ||
+ ((handlep->filtering_in_kernel>1) && handlep->filtering_in_kernel--);
if (run_bpf && handle->fcode.bf_insns &&
(bpf_filter(handle->fcode.bf_insns, bp,
tp_len, tp_snaplen) == 0))
/*
* Do checks based on packet direction.
*/
- sll = (void *)h.raw + TPACKET_ALIGN(handle->md.tp_hdrlen);
+ sll = (void *)h.raw + TPACKET_ALIGN(handlep->tp_hdrlen);
if (sll->sll_pkttype == PACKET_OUTGOING) {
/*
* Outgoing packet.
* we'll see the packet as an incoming packet as well,
* and we don't want to see it twice.
*/
- if (sll->sll_ifindex == handle->md.lo_ifindex)
+ if (sll->sll_ifindex == handlep->lo_ifindex)
goto skip;
/*
pcaphdr.len = tp_len;
/* if required build in place the sll header*/
- if (handle->md.cooked) {
+ if (handlep->cooked) {
struct sll_header *hdrp;
/*
* the sll header.
*/
if (bp < (u_char *)h.raw +
- TPACKET_ALIGN(handle->md.tp_hdrlen) +
+ TPACKET_ALIGN(handlep->tp_hdrlen) +
sizeof(struct sockaddr_ll)) {
snprintf(handle->errbuf, PCAP_ERRBUF_SIZE,
"cooked-mode frame doesn't have room for sll header");
}
#ifdef HAVE_TPACKET2
- if ((handle->md.tp_version == TPACKET_V2) &&
+ if ((handlep->tp_version == TPACKET_V2) &&
#if defined(TP_STATUS_VLAN_VALID)
(h.h2->tp_vlan_tci || (h.h2->tp_status & TP_STATUS_VLAN_VALID)) &&
#else
h.h2->tp_vlan_tci &&
#endif
- handle->md.vlan_offset != -1 &&
- tp_snaplen >= (unsigned int) handle->md.vlan_offset) {
+ handlep->vlan_offset != -1 &&
+ tp_snaplen >= (unsigned int) handlep->vlan_offset) {
struct vlan_tag *tag;
bp -= VLAN_TAG_LEN;
- memmove(bp, bp + VLAN_TAG_LEN, handle->md.vlan_offset);
+ memmove(bp, bp + VLAN_TAG_LEN, handlep->vlan_offset);
- tag = (struct vlan_tag *)(bp + handle->md.vlan_offset);
+ tag = (struct vlan_tag *)(bp + handlep->vlan_offset);
tag->vlan_tpid = htons(ETH_P_8021Q);
tag->vlan_tci = htons(h.h2->tp_vlan_tci);
/* pass the packet to the user */
pkts++;
callback(user, &pcaphdr, bp);
- handle->md.packets_read++;
+ handlep->packets_read++;
skip:
/* next packet */
- switch (handle->md.tp_version) {
+ switch (handlep->tp_version) {
case TPACKET_V1:
h.h1->tp_status = TP_STATUS_KERNEL;
break;
static int
pcap_setfilter_linux_mmap(pcap_t *handle, struct bpf_program *filter)
{
+ struct pcap_linux *handlep = handle->private;
int n, offset;
int ret;
/* if the kernel filter is enabled, we need to apply the filter on
* all packets present into the ring. Get an upper bound of their number
*/
- if (!handle->md.use_bpf)
+ if (!handlep->filtering_in_kernel)
return ret;
/* walk the ring backward and count the free slot */
handle->offset = offset;
/* store the number of packets currently present in the ring */
- handle->md.use_bpf = 1 + (handle->cc - n);
+ handlep->filtering_in_kernel = 1 + (handle->cc - n);
return ret;
}
* value of -ENFILE. (Return values are negative errnos.) We
* could probably use that to find an unused device.
*/
+ struct pcap_linux *handlep = handle->private;
int err;
struct iwreq ireq;
struct iw_priv_args *priv;
/*
* Save the old mode.
*/
- handle->md.oldmode = ireq.u.mode;
+ handlep->oldmode = ireq.u.mode;
/*
* Put the adapter in rfmon mode. How we do this depends
* Note that we have to put the old mode back
* when we close the device.
*/
- handle->md.must_do_on_close |= MUST_CLEAR_RFMON;
+ handlep->must_do_on_close |= MUST_CLEAR_RFMON;
/*
* Add this to the list of pcaps to close
* Note that we have to put the old mode back when we
* close the device.
*/
- handle->md.must_do_on_close |= MUST_CLEAR_RFMON;
+ handlep->must_do_on_close |= MUST_CLEAR_RFMON;
/*
* Add this to the list of pcaps to close when we exit.
static int
activate_old(pcap_t *handle)
{
+ struct pcap_linux *handlep = handle->private;
int arptype;
struct ifreq ifr;
const char *device = handle->opt.source;
}
/* It worked - we are using the old interface */
- handle->md.sock_packet = 1;
+ handlep->sock_packet = 1;
/* ...which means we get the link-layer header. */
- handle->md.cooked = 0;
+ handlep->cooked = 0;
/* Bind to the given device */
pcap_strerror(errno));
return PCAP_ERROR;
}
- handle->md.must_do_on_close |= MUST_CLEAR_PROMISC;
+ handlep->must_do_on_close |= MUST_CLEAR_PROMISC;
/*
* Add this to the list of pcaps
* SOCK_PACKET sockets don't supply information from
* stripped VLAN tags.
*/
- handle->md.vlan_offset = -1; /* unknown */
+ handlep->vlan_offset = -1; /* unknown */
return 1;
}
static int
fix_program(pcap_t *handle, struct sock_fprog *fcode, int is_mmapped)
{
+ struct pcap_linux *handlep = handle->private;
size_t prog_size;
register int i;
register struct bpf_insn *p;
/*
* Yes; are we in cooked mode?
*/
- if (handle->md.cooked) {
+ if (handlep->cooked) {
/*
* Yes, so we need to fix this
* instruction.
typedef enum { OTHER = -1, NFLOG, NFQUEUE } nftype_t;
+/*
+ * Private data for capturing on Linux netfilter sockets.
+ */
+struct pcap_netfilter {
+ u_int packets_read; /* count of packets read with recvfrom() */
+};
+
static int nfqueue_send_verdict(const pcap_t *handle, u_int16_t group_id, u_int32_t id, u_int32_t verdict);
static int
netfilter_read_linux(pcap_t *handle, int max_packets, pcap_handler callback, u_char *user)
{
+ struct pcap_netfilter *handlep = handle->private;
const unsigned char *buf;
int count = 0;
int len;
if (handle->fcode.bf_insns == NULL ||
bpf_filter(handle->fcode.bf_insns, payload, pkth.len, pkth.caplen))
{
- handle->md.packets_read++;
+ handlep->packets_read++;
callback(user, &pkth, payload);
count++;
}
static int
netfilter_stats_linux(pcap_t *handle, struct pcap_stat *stats)
{
- stats->ps_recv = handle->md.packets_read;
+ struct pcap_netfilter *handlep = handle->private;
+
+ stats->ps_recv = handlep->packets_read;
stats->ps_drop = 0;
stats->ps_ifdrop = 0;
return 0;
handle->inject_op = netfilter_inject_linux;
handle->setfilter_op = install_bpf_program; /* no kernel filtering */
handle->setdirection_op = NULL;
- handle->set_datalink_op = NULL;
handle->set_datalink_op = netfilter_set_datalink;
handle->getnonblock_op = pcap_getnonblock_fd;
handle->setnonblock_op = pcap_setnonblock_fd;
/* OK, it's probably ours. */
*is_ours = 1;
- p = pcap_create_common(device, ebuf);
+ p = pcap_create_common(device, ebuf, sizeof (struct pcap_netfilter));
if (p == NULL)
return (NULL);
/* Forwards */
static int nit_setflags(int, int, int, char *);
+/*
+ * Private data for capturing on NIT devices.
+ */
+struct pcap_nit {
+ struct pcap_stat stat;
+};
+
static int
pcap_stats_nit(pcap_t *p, struct pcap_stat *ps)
{
+ struct pcap_nit *pn = p->private;
/*
* "ps_recv" counts packets handed to the filter, not packets
* kernel by libpcap or packets not yet read from libpcap by the
* application.
*/
- *ps = p->md.stat;
+ *ps = pn->stat;
return (0);
}
static int
pcap_read_nit(pcap_t *p, int cnt, pcap_handler callback, u_char *user)
{
+ struct pcap_nit *pn = p->private;
register int cc, n;
register u_char *bp, *cp, *ep;
register struct nit_hdr *nh;
case NIT_NOMBUF:
case NIT_NOCLUSTER:
case NIT_NOSPACE:
- p->md.stat.ps_drop = nh->nh_dropped;
+ pn->stat.ps_drop = nh->nh_dropped;
continue;
case NIT_SEQNO:
"bad nit state %d", nh->nh_state);
return (-1);
}
- ++p->md.stat.ps_recv;
+ ++pn->stat.ps_recv;
bp += ((sizeof(struct nit_hdr) + nh->nh_datalen +
sizeof(int) - 1) & ~(sizeof(int) - 1));
"bind: %s: %s", snit.snit_ifname, pcap_strerror(errno));
goto bad;
}
- nit_setflags(p->fd, p->opt.promisc, p->md.timeout, p->errbuf);
+ nit_setflags(p->fd, p->opt.promisc, p->opt.timeout, p->errbuf);
/*
* NIT supports only ethernets.
{
pcap_t *p;
- p = pcap_create_common(device, ebuf);
+ p = pcap_create_common(device, ebuf, sizeof (struct pcap_nit));
if (p == NULL)
return (NULL);
#include "os-proto.h"
#endif
+/*
+ * FDDI packets are padded to make everything line up on a nice boundary.
+ */
+#define PCAP_FDDIPAD 3
+
+/*
+ * Private data for capturing on Ultrix and DEC OSF/1^WDigital UNIX^W^W
+ * Tru64 UNIX packetfilter devices.
+ */
+struct pcap_pf {
+ int filtering_in_kernel; /* using kernel filter */
+ u_long TotPkts; /* can't oflow for 79 hrs on ether */
+ u_long TotAccepted; /* count accepted by filter */
+ u_long TotDrops; /* count of dropped packets */
+ long TotMissed; /* missed by i/f during this run */
+ long OrigMissed; /* missed by i/f before this run */
+};
+
static int pcap_setfilter_pf(pcap_t *, struct bpf_program *);
/*
static int
pcap_read_pf(pcap_t *pc, int cnt, pcap_handler callback, u_char *user)
{
+ struct pcap_pf *pf = pc->private;
register u_char *p, *bp;
register int cc, n, buflen, inc;
register struct enstamp *sp;
#ifdef LBL_ALIGN
struct enstamp stamp;
#endif
-#ifdef PCAP_FDDIPAD
register int pad;
-#endif
again:
cc = pc->cc;
* Loop through each packet.
*/
n = 0;
-#ifdef PCAP_FDDIPAD
pad = pc->fddipad;
-#endif
while (cc > 0) {
/*
* Has "pcap_breakloop()" been called?
inc = ENALIGN(buflen + sp->ens_stamplen);
cc -= inc;
bp += inc;
- pc->md.TotPkts++;
- pc->md.TotDrops += sp->ens_dropped;
- pc->md.TotMissed = sp->ens_ifoverflows;
- if (pc->md.OrigMissed < 0)
- pc->md.OrigMissed = pc->md.TotMissed;
+ pf->TotPkts++;
+ pf->TotDrops += sp->ens_dropped;
+ pf->TotMissed = sp->ens_ifoverflows;
+ if (pf->OrigMissed < 0)
+ pf->OrigMissed = pf->TotMissed;
/*
* Short-circuit evaluation: if using BPF filter
* in kernel, no need to do it now - we already know
* the packet passed the filter.
*
-#ifdef PCAP_FDDIPAD
* Note: the filter code was generated assuming
* that pc->fddipad was the amount of padding
* before the header, as that's what's required
* in the kernel, so we run the filter before
* skipping that padding.
-#endif
*/
- if (pc->md.use_bpf ||
+ if (pf->filtering_in_kernel ||
bpf_filter(pc->fcode.bf_insns, p, sp->ens_count, buflen)) {
struct pcap_pkthdr h;
- pc->md.TotAccepted++;
+ pf->TotAccepted++;
h.ts = sp->ens_tstamp;
-#ifdef PCAP_FDDIPAD
h.len = sp->ens_count - pad;
-#else
- h.len = sp->ens_count;
-#endif
-#ifdef PCAP_FDDIPAD
p += pad;
buflen -= pad;
-#endif
h.caplen = buflen;
(*callback)(user, &h, p);
if (++n >= cnt && cnt > 0) {
static int
pcap_stats_pf(pcap_t *p, struct pcap_stat *ps)
{
+ struct pcap_pf *pf = p->private;
/*
* If packet filtering is being done in the kernel:
* the kernel by libpcap, but they may include packets not
* yet read from libpcap by the application.
*/
- ps->ps_recv = p->md.TotAccepted;
- ps->ps_drop = p->md.TotDrops;
- ps->ps_ifdrop = p->md.TotMissed - p->md.OrigMissed;
+ ps->ps_recv = pf->TotAccepted;
+ ps->ps_drop = pf->TotDrops;
+ ps->ps_ifdrop = pf->TotMissed - pf->OrigMissed;
return (0);
}
static int
pcap_activate_pf(pcap_t *p)
{
+ struct pcap_pf *pf = p->private;
short enmode;
int backlog = -1; /* request the most */
struct enfilter Filter;
p->opt.source, pcap_strerror(errno));
goto bad;
}
- p->md.OrigMissed = -1;
+ pf->OrigMissed = -1;
enmode = ENTSTAMP|ENBATCH|ENNONEXCL;
if (p->opt.promisc)
enmode |= ENPROMISC;
goto bad;
}
/* set truncation */
-#ifdef PCAP_FDDIPAD
if (p->linktype == DLT_FDDI) {
p->fddipad = PCAP_FDDIPAD;
p->snapshot += PCAP_FDDIPAD;
} else
p->fddipad = 0;
-#endif
if (ioctl(p->fd, EIOCTRUNCATE, (caddr_t)&p->snapshot) < 0) {
snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "EIOCTRUNCATE: %s",
pcap_strerror(errno));
goto bad;
}
- if (p->md.timeout != 0) {
+ if (p->opt.timeout != 0) {
struct timeval timeout;
- timeout.tv_sec = p->md.timeout / 1000;
- timeout.tv_usec = (p->md.timeout * 1000) % 1000000;
+ timeout.tv_sec = p->opt.timeout / 1000;
+ timeout.tv_usec = (p->opt.timeout * 1000) % 1000000;
if (ioctl(p->fd, EIOCSRTIMEOUT, (caddr_t)&timeout) < 0) {
snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "EIOCSRTIMEOUT: %s",
pcap_strerror(errno));
{
pcap_t *p;
- p = pcap_create_common(device, ebuf);
+ p = pcap_create_common(device, ebuf, sizeof (struct pcap_pf));
if (p == NULL)
return (NULL);
static int
pcap_setfilter_pf(pcap_t *p, struct bpf_program *fp)
{
+ struct pcap_pf *pf = p->private;
struct bpf_version bv;
/*
* a window to annoy the user.
*/
fprintf(stderr, "tcpdump: Using kernel BPF filter\n");
- p->md.use_bpf = 1;
+ pf->filtering_in_kernel = 1;
/*
* Discard any previously-received packets,
* a warning of some sort.
*/
fprintf(stderr, "tcpdump: Filtering in user process\n");
- p->md.use_bpf = 0;
+ pf->filtering_in_kernel = 0;
return (0);
}
static int septel_stats(pcap_t *p, struct pcap_stat *ps);
static int septel_setnonblock(pcap_t *p, int nonblock, char *errbuf);
+/*
+ * Private data for capturing on Septel devices.
+ */
+struct pcap_septel {
+ struct pcap_stat stat;
+}
+
/*
* Read at most max_packets from the capture queue and call the callback
* for each of them. Returns the number of packets handled, -1 if an
*/
static int septel_read(pcap_t *p, int cnt, pcap_handler callback, u_char *user) {
+ struct pcap_septel *ps = p->private;
HDR *h;
MSG *m;
int processed = 0 ;
pcap_header.len = packet_len;
/* Count the packet. */
- p->md.stat.ps_recv++;
+ ps->stat.ps_recv++;
/* Call the user supplied callback function */
callback(user, &pcap_header, dp);
/* OK, it's probably ours. */
*is_ours = 1;
- p = pcap_create_common(device, ebuf);
+ p = pcap_create_common(device, ebuf, sizeof (struct pcap_septel));
if (p == NULL)
return NULL;
}
static int septel_stats(pcap_t *p, struct pcap_stat *ps) {
- /*p->md.stat.ps_recv = 0;*/
- /*p->md.stat.ps_drop = 0;*/
+ struct pcap_septel *handlep = p->private;
+ /*handlep->stat.ps_recv = 0;*/
+ /*handlep->stat.ps_drop = 0;*/
- *ps = p->md.stat;
+ *ps = handlep->stat;
return 0;
}
return -1;
}
- p->md.use_bpf = 0;
-
return (0);
}
static int
septel_setnonblock(pcap_t *p, int nonblock, char *errbuf)
{
- return (0);
+ fprintf(errbuf, PCAP_ERRBUF_SIZE, "Non-blocking mode not supported on Septel devices");
+ return (-1);
}
#define LIVE 1
typedef struct iface {
- struct iface *next; /* a pointer to the next interface */
- char *name; /* this interface's name on Wireshark */
- char *IOPname; /* this interface's name on an IOP */
- uint32_t iftype; /* the type of interface (DLT values) */
+ struct iface *next; /* a pointer to the next interface */
+ char *name; /* this interface's name */
+ char *IOPname; /* this interface's name on an IOP */
+ uint32_t iftype; /* the type of interface (DLT values) */
} iface_t;
typedef struct unit {
- char *ip; /* this unit's IP address (as extracted from /etc/hosts) */
- int fd; /* the connection to this unit (if it exists) */
- int find_fd; /* a big kludge to avoid my programming limitations since I could have this unit open for findalldevs purposes */
- int first_time; /* 0 = just opened via acn_open_live(), ie. the first time, NZ = nth time */
- struct sockaddr_in *serv_addr; /* the address control block for comms to this unit */
- int chassis;
- int geoslot;
- iface_t *iface; /* a pointer to a linked list of interface structures */
- char *imsg; /* a pointer to an inbound message */
- int len; /* the current size of the inbound message */
+ char *ip; /* this unit's IP address (as extracted from /etc/hosts) */
+ int fd; /* the connection to this unit (if it exists) */
+ int find_fd; /* a big kludge to avoid my programming limitations since I could have this unit open for findalldevs purposes */
+ int first_time; /* 0 = just opened via acn_open_live(), ie. the first time, NZ = nth time */
+ struct sockaddr_in *serv_addr; /* the address control block for comms to this unit */
+ int chassis;
+ int geoslot;
+ iface_t *iface; /* a pointer to a linked list of interface structures */
+ char *imsg; /* a pointer to an inbound message */
+ int len; /* the current size of the inbound message */
} unit_t;
-static char *errorString;
static unit_t units[MAX_CHASSIS+1][MAX_GEOSLOT+1]; /* we use indexes of 1 through 8, but we reserve/waste index 0 */
-static fd_set readfds; /* a place to store the file descriptors for the connections to the IOPs */
-static fd_set working_set;
-static int max_fs;
-static char static_buf[32];
+static fd_set readfds; /* a place to store the file descriptors for the connections to the IOPs */
+static int max_fs;
-pcap_if_t *acn_if_list; /* pcap's list of available interfaces */
+pcap_if_t *acn_if_list; /* pcap's list of available interfaces */
static void dump_interface_list(void) {
pcap_if_t *iff;
pcap_addr_t *addr;
- int longest_name_len = 0;
+ int longest_name_len = 0;
char *n, *d, *f;
- int if_number = 0;
+ int if_number = 0;
iff = acn_if_list;
while (iff) {
}
}
-static char *nonUnified_port_num(unit_t *u, int IOPportnum) {
+static void nonUnified_IOP_port_name(char *buf, size_t bufsize, const char *proto, unit_t *u) {
- sprintf(static_buf, "%d_%d", u->chassis, u->geoslot);
- return static_buf;
+ snprintf(buf, bufsize, "%s_%d_%d", proto, u->chassis, u->geoslot);
}
-static char *unified_port_num(unit_t *u, int IOPportnum) {
+static void unified_IOP_port_name(char *buf, size_t bufsize, const char *proto, unit_t *u, int IOPportnum) {
int portnum;
portnum = ((u->chassis - 1) * 64) + ((u->geoslot - 1) * 8) + IOPportnum + 1;
- sprintf(static_buf, "%d", portnum);
- return static_buf;
+ snprintf(buf, bufsize, "%s_%d", proto, portnum);
}
static char *translate_IOP_to_pcap_name(unit_t *u, char *IOPname, bpf_u_int32 iftype) {
if (strncmp(IOPname, "lo", 2) == 0) {
IOPportnum = atoi(&IOPname[2]);
switch (iftype) {
- case DLT_EN10MB: proto = "lo"; port = nonUnified_port_num(u, IOPportnum); break;
- default: proto = "???"; port = unified_port_num(u, IOPportnum); break;
+ case DLT_EN10MB:
+ nonUnified_IOP_port_name(buf, sizeof buf, "lo", u);
+ break;
+ default:
+ unified_IOP_port_name(buf, sizeof buf, "???", u, IOPportnum);
+ break;
}
} else if (strncmp(IOPname, "eth", 3) == 0) {
IOPportnum = atoi(&IOPname[3]);
switch (iftype) {
- case DLT_EN10MB: proto = "eth"; port = nonUnified_port_num(u, IOPportnum); break;
- default: proto = "???"; port = unified_port_num(u, IOPportnum); break;
+ case DLT_EN10MB:
+ nonUnified_IOP_port_name(buf, sizeof buf, "eth", u);
+ break;
+ default:
+ unified_IOP_port_name(buf, sizeof buf, "???", u, IOPportnum);
+ break;
}
} else if (strncmp(IOPname, "wan", 3) == 0) {
IOPportnum = atoi(&IOPname[3]);
switch (iftype) {
- case DLT_SITA: proto = "wan"; port = unified_port_num(u, IOPportnum); break;
- default: proto = "???"; port = unified_port_num(u, IOPportnum); break;
+ case DLT_SITA:
+ unified_IOP_port_name(buf, sizeof buf, "wan", u, IOPportnum);
+ break;
+ default:
+ unified_IOP_port_name(buf, sizeof buf, "???", u, IOPportnum);
+ break;
}
+ } else {
+ fprintf(stderr, "Error... invalid IOP name %s\n", IOPname);
+ return NULL;
}
- sprintf(buf, "%s_%s", proto, port); /* compose the user's name for that IOP port name */
name = malloc(strlen(buf) + 1); /* get memory for that name */
if (name == NULL) { /* oops, we didn't get the memory requested */
fprintf(stderr, "Error...couldn't allocate memory for IOP port name...value of errno is: %d\n", errno);
while (1) {
int flag = 0;
+ fd_set working_set;
+
for (fd = 0; fd <= max_fs; fd++) { /* scan the list of descriptors we may be listening to */
if (FD_ISSET(fd, &readfds)) flag = 1; /* and see if there are any still set */
}
struct pcap_pkthdr pcap_header;
//printf("pcap_read_acn()\n"); // fulko
- acn_start_monitor(handle->fd, handle->snapshot, handle->md.timeout, handle->md.clear_promisc, handle->direction); /* maybe tell him to start monitoring */
+ acn_start_monitor(handle->fd, handle->snapshot, handle->opt.timeout, handle->opt.promisc, handle->direction); /* maybe tell him to start monitoring */
//printf("pcap_read_acn() after start monitor\n"); // fulko
handle->bp = packet_header;
&handle->linktype);
if (fd == -1)
return PCAP_ERROR;
- handle->md.clear_promisc = handle->md.promisc;
handle->fd = fd;
handle->bufsize = handle->snapshot;
pcap_t *pcap_create_interface(const char *device, char *ebuf) {
pcap_t *p;
- p = pcap_create_common(device, ebuf);
+ p = pcap_create_common(device, ebuf, 0);
if (p == NULL)
return (NULL);
#include <sys/types.h>
#include <unistd.h>
+#include <snf.h>
+
#include "pcap-int.h"
#include "pcap-snf.h"
+/*
+ * Private data for capturing on SNF devices.
+ */
+struct pcap_snf {
+ snf_handle_t snf_handle; /* opaque device handle */
+ snf_ring_t snf_ring; /* opaque device ring handle */
+ int snf_timeout;
+ int snf_boardnum;
+};
+
static int
snf_set_datalink(pcap_t *p, int dlt)
{
struct snf_ring_stats stats;
int rc;
- if ((rc = snf_ring_getstats(p->md.snf_ring, &stats))) {
+ if ((rc = snf_ring_getstats(ps->snf_ring, &stats))) {
snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "snf_get_stats: %s",
pcap_strerror(rc));
return -1;
static void
snf_platform_cleanup(pcap_t *p)
{
+ struct pcap_snf *ps = p->private;
+
if (p == NULL)
return;
- snf_ring_close(p->md.snf_ring);
- snf_close(p->md.snf_handle);
+ snf_ring_close(ps->snf_ring);
+ snf_close(ps->snf_handle);
pcap_cleanup_live_common(p);
}
static int
snf_getnonblock(pcap_t *p, char *errbuf)
{
- return (p->md.snf_timeout == 0);
+ struct pcap_snf *ps = p->private;
+
+ return (ps->snf_timeout == 0);
}
static int
snf_setnonblock(pcap_t *p, int nonblock, char *errbuf)
{
+ struct pcap_snf *ps = p->private;
+
if (nonblock)
- p->md.snf_timeout = 0;
+ ps->snf_timeout = 0;
else {
- if (p->md.timeout <= 0)
- p->md.snf_timeout = -1; /* forever */
+ if (p->opt.timeout <= 0)
+ ps->snf_timeout = -1; /* forever */
else
- p->md.snf_timeout = p->md.timeout;
+ ps->snf_timeout = p->opt.timeout;
}
return (0);
}
static int
snf_read(pcap_t *p, int cnt, pcap_handler callback, u_char *user)
{
+ struct pcap_snf *ps = p->private;
struct pcap_pkthdr hdr;
int i, flags, err, caplen, n;
struct snf_recv_req req;
}
}
- err = snf_ring_recv(p->md.snf_ring, p->md.snf_timeout, &req);
+ err = snf_ring_recv(ps->snf_ring, ps->snf_timeout, &req);
if (err) {
if (err == EBUSY || err == EAGAIN)
if (install_bpf_program(p, fp) < 0)
return -1;
- p->md.use_bpf = 0;
-
return (0);
}
static int
snf_activate(pcap_t* p)
{
+ struct pcap_snf *ps = p->private;
char *device = p->opt.source;
const char *nr = NULL;
int err;
else
nr = NULL;
- err = snf_open(p->md.snf_boardnum,
+ err = snf_open(ps->snf_boardnum,
0, /* let SNF API parse SNF_NUM_RINGS, if set */
NULL, /* default RSS, or use SNF_RSS_FLAGS env */
0, /* default to SNF_DATARING_SIZE from env */
flags, /* may want pshared */
- &p->md.snf_handle);
+ &ps->snf_handle);
if (err != 0) {
snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
"snf_open failed: %s", pcap_strerror(err));
return -1;
}
- err = snf_ring_open(p->md.snf_handle, &p->md.snf_ring);
+ err = snf_ring_open(ps->snf_handle, &ps->snf_ring);
if (err != 0) {
snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
"snf_ring_open failed: %s", pcap_strerror(err));
return -1;
}
- if (p->md.timeout <= 0)
- p->md.snf_timeout = -1;
+ if (p->opt.timeout <= 0)
+ ps->snf_timeout = -1;
else
- p->md.snf_timeout = p->md.timeout;
+ ps->snf_timeout = p->opt.timeout;
- err = snf_start(p->md.snf_handle);
+ err = snf_start(ps->snf_handle);
if (err != 0) {
snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
"snf_start failed: %s", pcap_strerror(err));
p->setnonblock_op = snf_setnonblock;
p->stats_op = snf_pcap_stats;
p->cleanup_op = snf_platform_cleanup;
- p->md.stat.ps_recv = 0;
- p->md.stat.ps_drop = 0;
- p->md.stat.ps_ifdrop = 0;
return 0;
}
int boardnum = -1;
struct snf_ifaddrs *ifaddrs, *ifa;
size_t devlen;
+ struct pcap_snf *ps;
if (snf_init(SNF_VERSION_API)) {
/* Can't initialize the API, so no SNF devices */
/* OK, it's probably ours. */
*is_ours = 1;
- p = pcap_create_common(device, ebuf);
+ p = pcap_create_common(device, ebuf, sizeof (struct pcap_snf));
if (p == NULL)
return NULL;
+ ps = p->private;
p->activate_op = snf_activate;
- p->md.snf_boardnum = boardnum;
+ ps->snf_boardnum = boardnum;
return p;
}
/* Forwards */
static int nit_setflags(int, int, int, char *);
+/*
+ * Private data for capturing on STREAMS NIT devices.
+ */
+struct pcap_snit {
+ struct pcap_stat stat;
+};
+
static int
pcap_stats_snit(pcap_t *p, struct pcap_stat *ps)
{
+ struct pcap_snit *psn = p->private;
/*
* "ps_recv" counts packets handed to the filter, not packets
* kernel by libpcap or packets not yet read from libpcap by the
* application.
*/
- *ps = p->md.stat;
+ *ps = psn->stat;
return (0);
}
static int
pcap_read_snit(pcap_t *p, int cnt, pcap_handler callback, u_char *user)
{
+ struct pcap_snit *psn = p->private;
register int cc, n;
register u_char *bp, *cp, *ep;
register struct nit_bufhdr *hdrp;
}
}
- ++p->md.stat.ps_recv;
+ ++psn->stat.ps_recv;
cp = bp;
/* get past NIT buffer */
cp += sizeof(*ntp);
ndp = (struct nit_ifdrops *)cp;
- p->md.stat.ps_drop = ndp->nh_drops;
+ psn->stat.ps_drop = ndp->nh_drops;
cp += sizeof *ndp;
/* get past packet len */
pcap_strerror(errno));
goto bad;
}
- if (nit_setflags(p->fd, p->opt.promisc, p->md.timeout, p->errbuf) < 0)
+ if (nit_setflags(p->fd, p->opt.promisc, p->opt.timeout, p->errbuf) < 0)
goto bad;
(void)ioctl(fd, I_FLUSH, (char *)FLUSHR);
{
pcap_t *p;
- p = pcap_create_common(device, ebuf);
+ p = pcap_create_common(device, ebuf, sizeof (struct pcap_snit));
if (p == NULL)
return (NULL);
#include "os-proto.h"
#endif
+/*
+ * Private data for capturing on snoop devices.
+ */
+struct pcap_snoop {
+ struct pcap_stat stat;
+};
+
static int
pcap_read_snoop(pcap_t *p, int cnt, pcap_handler callback, u_char *user)
{
+ struct pcap_snoop *psn = p->private;
int cc;
register struct snoopheader *sh;
register u_int datalen;
if (p->fcode.bf_insns == NULL ||
bpf_filter(p->fcode.bf_insns, cp, datalen, caplen)) {
struct pcap_pkthdr h;
- ++p->md.stat.ps_recv;
+ ++psn->stat.ps_recv;
h.ts.tv_sec = sh->snoop_timestamp.tv_sec;
h.ts.tv_usec = sh->snoop_timestamp.tv_usec;
h.len = datalen;
static int
pcap_stats_snoop(pcap_t *p, struct pcap_stat *ps)
{
+ struct pcap_snoop *psn = p->private;
register struct rawstats *rs;
struct rawstats rawstats;
* rather than just this socket? If not, why does it have
* both Snoop and Drain statistics?
*/
- p->md.stat.ps_drop =
+ psn->stat.ps_drop =
rs->rs_snoop.ss_ifdrops + rs->rs_snoop.ss_sbdrops +
rs->rs_drain.ds_ifdrops + rs->rs_drain.ds_sbdrops;
* As filtering is done in userland, this does not include
* packets dropped because we ran out of buffer space.
*/
- *ps = p->md.stat;
+ *ps = psn->stat;
return (0);
}
{
pcap_t *p;
- p = pcap_create_common(device, ebuf);
+ p = pcap_create_common(device, ebuf, sizeof (struct pcap_snoop));
if (p == NULL)
return (NULL);
#define MON_BIN_DATA_ZERO 0x4 /* data buffer is not available */
#define MON_BIN_ERROR 0x8
+/*
+ * Private data for capturing on Linux USB.
+ */
+struct pcap_usb_linux {
+ u_char *mmapbuf; /* memory-mapped region pointer */
+ size_t mmapbuflen; /* size of region */
+ int bus_index;
+ u_int packets_read;
+};
+
/* forward declaration */
static int usb_activate(pcap_t *);
static int usb_stats_linux(pcap_t *, struct pcap_stat *);
static
int usb_mmap(pcap_t* handle)
{
+ struct pcap_usb_linux *handlep = handle->private;
int len = ioctl(handle->fd, MON_IOCQ_RING_SIZE);
if (len < 0)
return 0;
- handle->md.mmapbuflen = len;
- handle->md.mmapbuf = mmap(0, handle->md.mmapbuflen, PROT_READ,
+ handlep->mmapbuflen = len;
+ handlep->mmapbuf = mmap(0, handlep->mmapbuflen, PROT_READ,
MAP_SHARED, handle->fd, 0);
- return handle->md.mmapbuf != MAP_FAILED;
+ return handlep->mmapbuf != MAP_FAILED;
}
#define CTRL_TIMEOUT (5*1000) /* milliseconds */
/* OK, it's probably ours. */
*is_ours = 1;
- p = pcap_create_common(device, ebuf);
+ p = pcap_create_common(device, ebuf, sizeof (struct pcap_usb_linux));
if (p == NULL)
return (NULL);
static int
usb_activate(pcap_t* handle)
{
+ struct pcap_usb_linux *handlep = handle->private;
char full_path[USB_LINE_LEN];
/* Initialize some components of the pcap structure. */
handle->setnonblock_op = pcap_setnonblock_fd;
/*get usb bus index from device name */
- if (sscanf(handle->opt.source, USB_IFACE"%d", &handle->md.ifindex) != 1)
+ if (sscanf(handle->opt.source, USB_IFACE"%d", &handlep->bus_index) != 1)
{
snprintf(handle->errbuf, PCAP_ERRBUF_SIZE,
"Can't get USB bus index from %s", handle->opt.source);
}
/*now select the read method: try to open binary interface */
- snprintf(full_path, USB_LINE_LEN, LINUX_USB_MON_DEV"%d", handle->md.ifindex);
+ snprintf(full_path, USB_LINE_LEN, LINUX_USB_MON_DEV"%d", handlep->bus_index);
handle->fd = open(full_path, O_RDONLY, 0);
if (handle->fd >= 0)
{
handle->stats_op = usb_stats_linux_bin;
handle->read_op = usb_read_linux_mmap;
handle->cleanup_op = usb_cleanup_linux_mmap;
- probe_devices(handle->md.ifindex);
+ probe_devices(handlep->bus_index);
/*
* "handle->fd" is a real file, so "select()" and
/* can't mmap, use plain binary interface access */
handle->stats_op = usb_stats_linux_bin;
handle->read_op = usb_read_linux_bin;
- probe_devices(handle->md.ifindex);
+ probe_devices(handlep->bus_index);
}
else {
/*Binary interface not available, try open text interface */
- snprintf(full_path, USB_LINE_LEN, USB_TEXT_DIR"/%dt", handle->md.ifindex);
+ snprintf(full_path, USB_LINE_LEN, USB_TEXT_DIR"/%dt", handlep->bus_index);
handle->fd = open(full_path, O_RDONLY, 0);
if (handle->fd < 0)
{
* Not found at the new location; try
* the old location.
*/
- snprintf(full_path, USB_LINE_LEN, USB_TEXT_DIR_OLD"/%dt", handle->md.ifindex);
+ snprintf(full_path, USB_LINE_LEN, USB_TEXT_DIR_OLD"/%dt", handlep->bus_index);
handle->fd = open(full_path, O_RDONLY, 0);
}
if (handle->fd < 0) {
* /usr/src/linux/Documentation/usb/usbmon.txt
* for message format
*/
+ struct pcap_usb_linux *handlep = handle->private;
unsigned timestamp;
int tag, cnt, ep_num, dev_addr, dummy, ret, urb_len, data_len;
char etype, pipeid1, pipeid2, status[16], urb_tag, line[USB_LINE_LEN];
}
uhdr->id = tag;
uhdr->device_address = dev_addr;
- uhdr->bus_id = handle->md.ifindex;
+ uhdr->bus_id = handlep->bus_index;
uhdr->status = 0;
string += cnt;
if (handle->fcode.bf_insns == NULL ||
bpf_filter(handle->fcode.bf_insns, handle->buffer,
pkth.len, pkth.caplen)) {
- handle->md.packets_read++;
+ handlep->packets_read++;
callback(user, &pkth, handle->buffer);
return 1;
}
static int
usb_stats_linux(pcap_t *handle, struct pcap_stat *stats)
{
+ struct pcap_usb_linux *handlep = handle->private;
int dummy, ret, consumed, cnt;
char string[USB_LINE_LEN];
char token[USB_LINE_LEN];
char * ptr = string;
int fd;
- snprintf(string, USB_LINE_LEN, USB_TEXT_DIR"/%ds", handle->md.ifindex);
+ snprintf(string, USB_LINE_LEN, USB_TEXT_DIR"/%ds", handlep->bus_index);
fd = open(string, O_RDONLY, 0);
if (fd < 0)
{
* Not found at the new location; try the old
* location.
*/
- snprintf(string, USB_LINE_LEN, USB_TEXT_DIR_OLD"/%ds", handle->md.ifindex);
+ snprintf(string, USB_LINE_LEN, USB_TEXT_DIR_OLD"/%ds", handlep->bus_index);
fd = open(string, O_RDONLY, 0);
}
if (fd < 0) {
ptr += cnt;
}
- stats->ps_recv = handle->md.packets_read;
+ stats->ps_recv = handlep->packets_read;
stats->ps_ifdrop = 0;
return 0;
}
static int
usb_stats_linux_bin(pcap_t *handle, struct pcap_stat *stats)
{
+ struct pcap_usb_linux *handlep = handle->private;
int ret;
struct mon_bin_stats st;
ret = ioctl(handle->fd, MON_IOCG_STATS, &st);
return -1;
}
- stats->ps_recv = handle->md.packets_read + st.queued;
+ stats->ps_recv = handlep->packets_read + st.queued;
stats->ps_drop = st.dropped;
stats->ps_ifdrop = 0;
return 0;
static int
usb_read_linux_bin(pcap_t *handle, int max_packets, pcap_handler callback, u_char *user)
{
+ struct pcap_usb_linux *handlep = handle->private;
struct mon_bin_get info;
int ret;
struct pcap_pkthdr pkth;
if (handle->fcode.bf_insns == NULL ||
bpf_filter(handle->fcode.bf_insns, handle->buffer,
pkth.len, pkth.caplen)) {
- handle->md.packets_read++;
+ handlep->packets_read++;
callback(user, &pkth, handle->buffer);
return 1;
}
static int
usb_read_linux_mmap(pcap_t *handle, int max_packets, pcap_handler callback, u_char *user)
{
+ struct pcap_usb_linux *handlep = handle->private;
struct mon_bin_mfetch fetch;
int32_t vec[VEC_SIZE];
struct pcap_pkthdr pkth;
nflush = fetch.nfetch;
for (i=0; i<fetch.nfetch; ++i) {
/* discard filler */
- hdr = (pcap_usb_header*) &handle->md.mmapbuf[vec[i]];
+ hdr = (pcap_usb_header*) &handlep->mmapbuf[vec[i]];
if (hdr->event_type == '@')
continue;
if (handle->fcode.bf_insns == NULL ||
bpf_filter(handle->fcode.bf_insns, (u_char*) hdr,
pkth.len, pkth.caplen)) {
- handle->md.packets_read++;
+ handlep->packets_read++;
callback(user, &pkth, (u_char*) hdr);
packets++;
}
static void
usb_cleanup_linux_mmap(pcap_t* handle)
{
+ struct pcap_usb_linux *handlep = handle->private;
+
/* if we have a memory-mapped buffer, unmap it */
- if (handle->md.mmapbuf != NULL) {
- munmap(handle->md.mmapbuf, handle->md.mmapbuflen);
- handle->md.mmapbuf = NULL;
+ if (handlep->mmapbuf != NULL) {
+ munmap(handlep->mmapbuf, handlep->mmapbuflen);
+ handlep->mmapbuf = NULL;
}
pcap_cleanup_live_common(handle);
}
/* Equivalent to ntohs(), but a lot faster under Windows */
#define SWAPS(_X) ((_X & 0xff) << 8) | (_X >> 8)
+/*
+ * Private data for capturing on WinPcap devices.
+ */
+struct pcap_win {
+ int nonblock;
+
+#ifdef HAVE_DAG_API
+ int dag_fcs_bits; /* Number of checksum bits from link layer */
+#endif
+};
+
/*
* Header that the WinPcap driver associates to the packets.
* Once was in bpf.h
static int
pcap_read_win32_dag(pcap_t *p, int cnt, pcap_handler callback, u_char *user)
{
+ struct pcap_win *pw = p->private;
u_char *dp = NULL;
int packet_len = 0, caplen = 0;
struct pcap_pkthdr pcap_header;
break;
/* Increase the number of captured packets */
- p->md.stat.ps_recv++;
+ pw->stat.ps_recv++;
/* Find the beginning of the packet */
dp = ((u_char *)header) + dag_record_size;
case TYPE_ETH:
swt = SWAPS(header->wlen);
- packet_len = swt - (p->md.dag_fcs_bits);
+ packet_len = swt - (pw->dag_fcs_bits);
caplen = erf_record_len - dag_record_size - 2;
if (caplen > packet_len)
{
case TYPE_HDLC_POS:
swt = SWAPS(header->wlen);
- packet_len = swt - (p->md.dag_fcs_bits);
+ packet_len = swt - (pw->dag_fcs_bits);
caplen = erf_record_len - dag_record_size;
if (caplen > packet_len)
{
static int
pcap_activate_win32(pcap_t *p)
{
+ struct pcap_win *pw = p->private;
NetType type;
if (p->opt.rfmon) {
/* Set the length of the FCS associated to any packet. This value
* will be subtracted to the packet length */
- p->md.dag_fcs_bits = p->adapter->DagFcsLen;
+ pw->dag_fcs_bits = p->adapter->DagFcsLen;
}
#else
goto bad;
#endif /* HAVE_DAG_API */
- PacketSetReadTimeout(p->adapter, p->md.timeout);
+ PacketSetReadTimeout(p->adapter, p->opt.timeout);
#ifdef HAVE_DAG_API
if(p->adapter->Flags & INFO_FLAG_DAG_CARD)
}
snprintf(deviceAscii, length + 1, "%ws", (wchar_t*)device);
- p = pcap_create_common(deviceAscii, ebuf);
+ p = pcap_create_common(deviceAscii, ebuf, sizeof (struct pcap_win));
free(deviceAscii);
}
else
{
- p = pcap_create_common(device, ebuf);
+ p = pcap_create_common(device, ebuf, sizeof (struct pcap_win));
}
if (p == NULL)
return -1;
}
- p->md.use_bpf = 0;
-
return (0);
}
static int
pcap_getnonblock_win32(pcap_t *p, char *errbuf)
{
+ struct pcap_win *pw = p->private;
+
/*
* XXX - if there were a PacketGetReadTimeout() call, we
* would use it, and return 1 if the timeout is -1
* and 0 otherwise.
*/
- return (p->nonblock);
+ return (pw->nonblock);
}
static int
pcap_setnonblock_win32(pcap_t *p, int nonblock, char *errbuf)
{
+ struct pcap_win *pw = p->private;
int newtimeout;
if (nonblock) {
* (Note that this may be -1, in which case we're not
* really leaving non-blocking mode.)
*/
- newtimeout = p->md.timeout;
+ newtimeout = p->opt.timeout;
}
if (!PacketSetReadTimeout(p->adapter, newtimeout)) {
snprintf(errbuf, PCAP_ERRBUF_SIZE,
"PacketSetReadTimeout: %s", pcap_win32strerror());
return (-1);
}
- p->nonblock = (newtimeout == -1);
+ pw->nonblock = (newtimeout == -1);
return (0);
}
/* Saves a pointer to the packet headers */
*pkt_header= &p->pcap_header;
- if (p->sf.rfile != NULL) {
+ if (p->rfile != NULL) {
int status;
/* We are on an offline capture */
p->oneshot_callback = pcap_oneshot;
}
-pcap_t *
-pcap_create_common(const char *source, char *ebuf)
+static pcap_t *
+pcap_alloc_pcap_t(char *ebuf, size_t size)
{
+ char *chunk;
pcap_t *p;
- p = malloc(sizeof(*p));
- if (p == NULL) {
+ /*
+ * Allocate a chunk of memory big enough for a pcap_t
+ * plus a structure following it of size "size". The
+ * structure following it is a private data structure
+ * for the routines that handle this pcap_t.
+ */
+ chunk = malloc(sizeof (pcap_t) + size);
+ if (chunk == NULL) {
snprintf(ebuf, PCAP_ERRBUF_SIZE, "malloc: %s",
pcap_strerror(errno));
return (NULL);
}
- memset(p, 0, sizeof(*p));
+ memset(chunk, 0, sizeof (pcap_t) + size);
+
+ /*
+ * Get a pointer to the pcap_t at the beginning.
+ */
+ p = (pcap_t *)chunk;
+
#ifndef WIN32
p->fd = -1; /* not opened yet */
p->selectable_fd = -1;
- p->send_fd = -1;
#endif
+ if (size == 0) {
+ /* No private data was requested. */
+ p->private = NULL;
+ } else {
+ /*
+ * Set the pointer to the private data; that's the structure
+ * of size "size" following the pcap_t.
+ */
+ p->private = (void *)(chunk + sizeof (pcap_t));
+ }
+
+ return (p);
+}
+
+pcap_t *
+pcap_create_common(const char *source, char *ebuf, size_t size)
+{
+ pcap_t *p;
+
+ p = pcap_alloc_pcap_t(ebuf, size);
+ if (p == NULL)
+ return (NULL);
+
p->opt.source = strdup(source);
if (p->opt.source == NULL) {
snprintf(ebuf, PCAP_ERRBUF_SIZE, "malloc: %s",
{
if (pcap_check_activated(p))
return (PCAP_ERROR_ACTIVATED);
- p->md.timeout = timeout_ms;
+ p->opt.timeout = timeout_ms;
return (0);
}
return (NULL);
}
+pcap_t *
+pcap_open_offline_common(char *ebuf, size_t size)
+{
+ pcap_t *p;
+
+ p = pcap_alloc_pcap_t(ebuf, size);
+ if (p == NULL)
+ return (NULL);
+
+ p->opt.source = strdup("(savefile)");
+ if (p->opt.source == NULL) {
+ snprintf(ebuf, PCAP_ERRBUF_SIZE, "malloc: %s",
+ pcap_strerror(errno));
+ free(p);
+ return (NULL);
+ }
+
+ return (p);
+}
+
int
pcap_dispatch(pcap_t *p, int cnt, pcap_handler callback, u_char *user)
{
register int n;
for (;;) {
- if (p->sf.rfile != NULL) {
+ if (p->rfile != NULL) {
/*
* 0 means EOF, so don't loop if we get 0.
*/
int
pcap_is_swapped(pcap_t *p)
{
- return (p->sf.swapped);
+ return (p->swapped);
}
int
pcap_major_version(pcap_t *p)
{
- return (p->sf.version_major);
+ return (p->version_major);
}
int
pcap_minor_version(pcap_t *p)
{
- return (p->sf.version_minor);
+ return (p->version_minor);
}
FILE *
pcap_file(pcap_t *p)
{
- return (p->sf.rfile);
+ return (p->rfile);
}
int
void
pcap_add_to_pcaps_to_close(pcap_t *p)
{
- p->md.next = pcaps_to_close;
+ p->next = pcaps_to_close;
pcaps_to_close = p;
}
pcap_t *pc, *prevpc;
for (pc = pcaps_to_close, prevpc = NULL; pc != NULL;
- prevpc = pc, pc = pc->md.next) {
+ prevpc = pc, pc = pc->next) {
if (pc == p) {
/*
* Found it. Remove it from the list.
/*
* It was at the head of the list.
*/
- pcaps_to_close = pc->md.next;
+ pcaps_to_close = pc->next;
} else {
/*
* It was in the middle of the list.
*/
- prevpc->md.next = pc->md.next;
+ prevpc->next = pc->next;
}
break;
}
p->fd = -1;
}
p->selectable_fd = -1;
- p->send_fd = -1;
#endif
}
static void
sf_cleanup(pcap_t *p)
{
- if (p->sf.rfile != stdin)
- (void)fclose(p->sf.rfile);
+ if (p->rfile != stdin)
+ (void)fclose(p->rfile);
if (p->buffer != NULL)
free(p->buffer);
pcap_freecode(&p->fcode);
}
#endif
-static int (*check_headers[])(pcap_t *, bpf_u_int32, FILE *, char *) = {
+static pcap_t *(*check_headers[])(bpf_u_int32, FILE *, char *, int *) = {
pcap_check_header,
pcap_ng_check_header
};
bpf_u_int32 magic;
size_t amt_read;
u_int i;
-
- p = pcap_create_common("(savefile)", errbuf);
- if (p == NULL)
- return (NULL);
+ int err;
/*
* Read the first 4 bytes of the file; the network analyzer dump
(unsigned long)sizeof(magic),
(unsigned long)amt_read);
}
- goto bad;
+ return (NULL);
}
/*
* Try all file types.
*/
for (i = 0; i < N_FILE_TYPES; i++) {
- switch ((*check_headers[i])(p, magic, fp, errbuf)) {
-
- case -1:
+ p = (*check_headers[i])(magic, fp, errbuf, &err);
+ if (p != NULL) {
+ /* Yup, that's it. */
+ goto found;
+ }
+ if (err) {
/*
* Error trying to read the header.
*/
- goto bad;
-
- case 1:
- /*
- * Yup, that's it.
- */
- goto found;
+ return (NULL);
}
}
* Well, who knows what this mess is....
*/
snprintf(errbuf, PCAP_ERRBUF_SIZE, "unknown file format");
- goto bad;
+ return (NULL);
found:
- p->sf.rfile = fp;
+ p->rfile = fp;
-#ifdef PCAP_FDDIPAD
/* Padding only needed for live capture fcode */
p->fddipad = 0;
-#endif
#if !defined(WIN32) && !defined(MSDOS)
/*
p->activated = 1;
return (p);
- bad:
- free(p);
- return (NULL);
}
/*
return (n);
}
- status = p->sf.next_packet_op(p, &h, &data);
+ status = p->next_packet_op(p, &h, &data);
if (status) {
if (status == 1)
return (0);
bpf_u_int32 block_type;
};
+struct pcap_ng_sf {
+ bpf_u_int32 ifcount; /* number of interfaces seen in this capture */
+ u_int tsresol; /* time stamp resolution */
+ u_int tsscale; /* scaling factor for resolution -> microseconds */
+ u_int64_t tsoffset; /* time stamp offset */
+};
+
static int pcap_ng_next_packet(pcap_t *p, struct pcap_pkthdr *hdr,
u_char **data);
if (status <= 0)
return (status); /* error or EOF */
- if (p->sf.swapped) {
+ if (p->swapped) {
bhdr.block_type = SWAPLONG(bhdr.block_type);
bhdr.total_length = SWAPLONG(bhdr.total_length);
}
/*
* Byte-swap it if necessary.
*/
- if (p->sf.swapped) {
+ if (p->swapped) {
opthdr->option_code = SWAPSHORT(opthdr->option_code);
opthdr->option_length = SWAPSHORT(opthdr->option_length);
}
}
saw_tsoffset = 1;
memcpy(tsoffset, optvalue, sizeof(*tsoffset));
- if (p->sf.swapped)
+ if (p->swapped)
*tsoffset = SWAPLL(*tsoffset);
break;
* Check whether this is a pcap-ng savefile and, if it is, extract the
* relevant information from the header.
*/
-int
-pcap_ng_check_header(pcap_t *p, bpf_u_int32 magic, FILE *fp, char *errbuf)
+pcap_t *
+pcap_ng_check_header(bpf_u_int32 magic, FILE *fp, char *errbuf, int *err)
{
size_t amt_read;
bpf_u_int32 total_length;
bpf_u_int32 byte_order_magic;
struct block_header *bhdrp;
struct section_header_block *shbp;
+ pcap_t *p;
+ int swapped = 0;
+ struct pcap_ng_sf *ps;
int status;
struct block_cursor cursor;
struct interface_description_block *idbp;
+ /*
+ * Assume no read errors.
+ */
+ *err = 0;
+
/*
* Check whether the first 4 bytes of the file are the block
* type for a pcap-ng savefile.
* this as possibly being a pcap-ng file transferred
* between UN*X and Windows in text file format?
*/
- return (0); /* nope */
+ return (NULL); /* nope */
}
/*
snprintf(errbuf, PCAP_ERRBUF_SIZE,
"error reading dump file: %s",
pcap_strerror(errno));
- return (-1); /* fail */
+ *err = 1;
+ return (NULL); /* fail */
}
/*
* Possibly a weird short text file, so just say
* "not pcap-ng".
*/
- return (0);
+ return (NULL);
}
amt_read = fread(&byte_order_magic, 1, sizeof(byte_order_magic), fp);
if (amt_read < sizeof(byte_order_magic)) {
snprintf(errbuf, PCAP_ERRBUF_SIZE,
"error reading dump file: %s",
pcap_strerror(errno));
- return (-1); /* fail */
+ *err = 1;
+ return (NULL); /* fail */
}
/*
* Possibly a weird short text file, so just say
* "not pcap-ng".
*/
- return (0);
+ return (NULL);
}
if (byte_order_magic != BYTE_ORDER_MAGIC) {
byte_order_magic = SWAPLONG(byte_order_magic);
/*
* Not a pcap-ng file.
*/
- return (0);
+ return (NULL);
}
- p->sf.swapped = 1;
+ swapped = 1;
total_length = SWAPLONG(total_length);
}
"Section Header Block in pcap-ng dump file has a length of %u < %lu",
total_length,
(unsigned long)(sizeof(*bhdrp) + sizeof(*shbp) + sizeof(struct block_trailer)));
- return (-1);
+ *err = 1;
+ return (NULL);
}
+ /*
+ * OK, this is a good pcap-ng file.
+ * Allocate a pcap_t for it.
+ */
+ p = pcap_open_offline_common(errbuf, sizeof (struct pcap_ng_sf));
+ if (p == NULL) {
+ /* Allocation failed. */
+ *err = 1;
+ return (NULL);
+ }
+ p->swapped = swapped;
+ ps = p->private;
+
/*
* Allocate a buffer into which to read blocks. We default to
* the maximum of:
p->buffer = malloc(p->bufsize);
if (p->buffer == NULL) {
snprintf(errbuf, PCAP_ERRBUF_SIZE, "out of memory");
- return (-1);
+ free(p);
+ *err = 1;
+ return (NULL);
}
/*
1, errbuf) == -1)
goto fail;
- if (p->sf.swapped) {
+ if (p->swapped) {
/*
* Byte-swap the fields we've read.
*/
shbp->major_version);
goto fail;
}
- p->sf.version_major = shbp->major_version;
- p->sf.version_minor = shbp->minor_version;
+ p->version_major = shbp->major_version;
+ p->version_minor = shbp->minor_version;
/*
* Set the default time stamp resolution and offset.
*/
- p->sf.tsresol = 1000000; /* microsecond resolution */
- p->sf.tsscale = 1; /* multiply by 1 to scale to microseconds */
- p->sf.tsoffset = 0; /* absolute timestamps */
+ ps->tsresol = 1000000; /* microsecond resolution */
+ ps->tsscale = 1; /* multiply by 1 to scale to microseconds */
+ ps->tsoffset = 0; /* absolute timestamps */
/*
* Now start looking for an Interface Description Block.
/*
* Byte-swap it if necessary.
*/
- if (p->sf.swapped) {
+ if (p->swapped) {
idbp->linktype = SWAPSHORT(idbp->linktype);
idbp->snaplen = SWAPLONG(idbp->snaplen);
}
/*
* Count this interface.
*/
- p->sf.ifcount++;
+ ps->ifcount++;
/*
* Now look for various time stamp options, so
* we know how to interpret the time stamps.
*/
- if (process_idb_options(p, &cursor, &p->sf.tsresol,
- &p->sf.tsoffset, errbuf) == -1)
+ if (process_idb_options(p, &cursor, &ps->tsresol,
+ &ps->tsoffset, errbuf) == -1)
goto fail;
/*
* sub-second part of the time stamp to
* microseconds.
*/
- if (p->sf.tsresol > 1000000) {
+ if (ps->tsresol > 1000000) {
/*
* Higher than microsecond resolution;
* scale down to microseconds.
*/
- p->sf.tsscale = (p->sf.tsresol / 1000000);
+ ps->tsscale = (ps->tsresol / 1000000);
} else {
/*
* Lower than microsecond resolution;
* scale up to microseconds.
*/
- p->sf.tsscale = (1000000 / p->sf.tsresol);
+ ps->tsscale = (1000000 / ps->tsresol);
}
goto done;
p->linktype = linktype_to_dlt(idbp->linktype);
p->linktype_ext = 0;
- p->sf.next_packet_op = pcap_ng_next_packet;
+ p->next_packet_op = pcap_ng_next_packet;
- return (1);
+ return (p);
fail:
free(p->buffer);
- return (-1);
+ free(p);
+ *err = 1;
+ return (NULL);
}
/*
static int
pcap_ng_next_packet(pcap_t *p, struct pcap_pkthdr *hdr, u_char **data)
{
+ struct pcap_ng_sf *ps = p->private;
struct block_cursor cursor;
int status;
struct enhanced_packet_block *epbp;
bpf_u_int32 interface_id = 0xFFFFFFFF;
struct interface_description_block *idbp;
struct section_header_block *shbp;
- FILE *fp = p->sf.rfile;
+ FILE *fp = p->rfile;
u_int tsresol;
u_int64_t tsoffset;
u_int64_t t, sec, frac;
/*
* Byte-swap it if necessary.
*/
- if (p->sf.swapped) {
+ if (p->swapped) {
/* these were written in opposite byte order */
interface_id = SWAPLONG(epbp->interface_id);
hdr->caplen = SWAPLONG(epbp->caplen);
/*
* Byte-swap it if necessary.
*/
- if (p->sf.swapped) {
+ if (p->swapped) {
/* these were written in opposite byte order */
hdr->len = SWAPLONG(spbp->len);
} else
/*
* Byte-swap it if necessary.
*/
- if (p->sf.swapped) {
+ if (p->swapped) {
/* these were written in opposite byte order */
interface_id = SWAPSHORT(pbp->interface_id);
hdr->caplen = SWAPLONG(pbp->caplen);
/*
* Byte-swap it if necessary.
*/
- if (p->sf.swapped) {
+ if (p->swapped) {
idbp->linktype = SWAPSHORT(idbp->linktype);
idbp->snaplen = SWAPLONG(idbp->snaplen);
}
/*
* Count this interface.
*/
- p->sf.ifcount++;
+ ps->ifcount++;
/*
* Set the default time stamp resolution and offset.
if (process_idb_options(p, &cursor, &tsresol, &tsoffset,
p->errbuf) == -1)
return (-1);
- if (tsresol != p->sf.tsresol) {
+ if (tsresol != ps->tsresol) {
snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
"an interface has a time stamp resolution different from the time stamp resolution of the first interface");
return (-1);
}
- if (tsoffset != p->sf.tsoffset) {
+ if (tsoffset != ps->tsoffset) {
snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
"an interface has a time stamp offset different from the time stamp offset of the first interface");
return (-1);
* the same as that of the previous section.
* We'll check for that later.
*/
- if (p->sf.swapped) {
+ if (p->swapped) {
shbp->byte_order_magic =
SWAPLONG(shbp->byte_order_magic);
shbp->major_version =
* any IDBs, we'll fail when we see a packet
* block.)
*/
- p->sf.ifcount = 0;
+ ps->ifcount = 0;
break;
default:
/*
* Is the interface ID an interface we know?
*/
- if (interface_id >= p->sf.ifcount) {
+ if (interface_id >= ps->ifcount) {
/*
* Yes. Fail.
*/
/*
* Convert the time stamp to a struct timeval.
*/
- sec = t / p->sf.tsresol + p->sf.tsoffset;
- frac = t % p->sf.tsresol;
- if (p->sf.tsresol > 1000000) {
+ sec = t / ps->tsresol + ps->tsoffset;
+ frac = t % ps->tsresol;
+ if (ps->tsresol > 1000000) {
/*
* Higher than microsecond resolution; scale down to
* microseconds.
*/
- frac /= p->sf.tsscale;
+ frac /= ps->tsscale;
} else {
/*
* Lower than microsecond resolution; scale up to
* microseconds.
*/
- frac *= p->sf.tsscale;
+ frac *= ps->tsscale;
}
hdr->ts.tv_sec = sec;
hdr->ts.tv_usec = frac;
if (*data == NULL)
return (-1);
- if (p->sf.swapped) {
+ if (p->swapped) {
/*
* Convert pseudo-headers from the byte order of
* the host on which the file was saved to our
#ifndef sf_pcap_ng_h
#define sf_pcap_ng_h
-extern int pcap_ng_check_header(pcap_t *, bpf_u_int32, FILE *, char *);
+extern pcap_t *pcap_ng_check_header(bpf_u_int32 magic, FILE *fp, char *errbuf,
+ int *err);
#endif
static int pcap_next_packet(pcap_t *p, struct pcap_pkthdr *hdr, u_char **datap);
+/*
+ * Private data for reading pcap savefiles.
+ */
+typedef enum {
+ NOT_SWAPPED,
+ SWAPPED,
+ MAYBE_SWAPPED
+} swapped_type_t;
+
+struct pcap_sf {
+ size_t hdrsize;
+ swapped_type_t lengths_swapped;
+};
+
/*
* Check whether this is a pcap savefile and, if it is, extract the
* relevant information from the header.
*/
-int
-pcap_check_header(pcap_t *p, bpf_u_int32 magic, FILE *fp, char *errbuf)
+pcap_t *
+pcap_check_header(bpf_u_int32 magic, FILE *fp, char *errbuf, int *err)
{
struct pcap_file_header hdr;
size_t amt_read;
+ pcap_t *p;
+ int swapped = 0;
+ struct pcap_sf *ps;
+
+ /*
+ * Assume no read errors.
+ */
+ *err = 0;
/*
* Check whether the first 4 bytes of the file are the magic
if (magic != TCPDUMP_MAGIC && magic != KUZNETZOV_TCPDUMP_MAGIC) {
magic = SWAPLONG(magic);
if (magic != TCPDUMP_MAGIC && magic != KUZNETZOV_TCPDUMP_MAGIC)
- return (0); /* nope */
- p->sf.swapped = 1;
+ return (NULL); /* nope */
+ swapped = 1;
}
/*
(unsigned long)sizeof(hdr),
(unsigned long)amt_read);
}
- return (-1);
+ *err = 1;
+ return (NULL);
}
/*
* If it's a byte-swapped capture file, byte-swap the header.
*/
- if (p->sf.swapped) {
+ if (swapped) {
hdr.version_major = SWAPSHORT(hdr.version_major);
hdr.version_minor = SWAPSHORT(hdr.version_minor);
hdr.thiszone = SWAPLONG(hdr.thiszone);
if (hdr.version_major < PCAP_VERSION_MAJOR) {
snprintf(errbuf, PCAP_ERRBUF_SIZE,
"archaic pcap savefile format");
- return (-1);
+ *err = 1;
+ return (NULL);
+ }
+
+ /*
+ * OK, this is a good pcap file.
+ * Allocate a pcap_t for it.
+ */
+ p = pcap_open_offline_common(errbuf, sizeof (struct pcap_sf));
+ if (p == NULL) {
+ /* Allocation failed. */
+ *err = 1;
+ return (NULL);
}
- p->sf.version_major = hdr.version_major;
- p->sf.version_minor = hdr.version_minor;
+ p->swapped = swapped;
+ p->version_major = hdr.version_major;
+ p->version_minor = hdr.version_minor;
p->tzoff = hdr.thiszone;
p->snapshot = hdr.snaplen;
p->linktype = linktype_to_dlt(LT_LINKTYPE(hdr.linktype));
p->linktype_ext = LT_LINKTYPE_EXT(hdr.linktype);
- p->sf.next_packet_op = pcap_next_packet;
+ p->next_packet_op = pcap_next_packet;
+
+ ps = p->private;
/*
* We interchanged the caplen and len fields at version 2.3,
case 2:
if (hdr.version_minor < 3)
- p->sf.lengths_swapped = SWAPPED;
+ ps->lengths_swapped = SWAPPED;
else if (hdr.version_minor == 3)
- p->sf.lengths_swapped = MAYBE_SWAPPED;
+ ps->lengths_swapped = MAYBE_SWAPPED;
else
- p->sf.lengths_swapped = NOT_SWAPPED;
+ ps->lengths_swapped = NOT_SWAPPED;
break;
case 543:
- p->sf.lengths_swapped = SWAPPED;
+ ps->lengths_swapped = SWAPPED;
break;
default:
- p->sf.lengths_swapped = NOT_SWAPPED;
+ ps->lengths_swapped = NOT_SWAPPED;
break;
}
* data ourselves and read from that buffer in order to
* make that work.
*/
- p->sf.hdrsize = sizeof(struct pcap_sf_patched_pkthdr);
+ ps->hdrsize = sizeof(struct pcap_sf_patched_pkthdr);
if (p->linktype == DLT_EN10MB) {
/*
p->snapshot += 14;
}
} else
- p->sf.hdrsize = sizeof(struct pcap_sf_pkthdr);
+ ps->hdrsize = sizeof(struct pcap_sf_pkthdr);
/*
* Allocate a buffer for the packet data.
p->buffer = malloc(p->bufsize);
if (p->buffer == NULL) {
snprintf(errbuf, PCAP_ERRBUF_SIZE, "out of memory");
- return (-1);
+ free(p);
+ *err = 1;
+ return (NULL);
}
- return (1);
+ return (p);
}
/*
static int
pcap_next_packet(pcap_t *p, struct pcap_pkthdr *hdr, u_char **data)
{
+ struct pcap_sf *ps = p->private;
struct pcap_sf_patched_pkthdr sf_hdr;
- FILE *fp = p->sf.rfile;
+ FILE *fp = p->rfile;
size_t amt_read;
bpf_u_int32 t;
* unpatched libpcap we only read as many bytes as the regular
* header has.
*/
- amt_read = fread(&sf_hdr, 1, p->sf.hdrsize, fp);
- if (amt_read != p->sf.hdrsize) {
+ amt_read = fread(&sf_hdr, 1, ps->hdrsize, fp);
+ if (amt_read != ps->hdrsize) {
if (ferror(fp)) {
snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
"error reading dump file: %s",
if (amt_read != 0) {
snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
"truncated dump file; tried to read %lu header bytes, only got %lu",
- (unsigned long)p->sf.hdrsize,
+ (unsigned long)ps->hdrsize,
(unsigned long)amt_read);
return (-1);
}
}
}
- if (p->sf.swapped) {
+ if (p->swapped) {
/* these were written in opposite byte order */
hdr->caplen = SWAPLONG(sf_hdr.caplen);
hdr->len = SWAPLONG(sf_hdr.len);
hdr->ts.tv_usec = sf_hdr.ts.tv_usec;
}
/* Swap the caplen and len fields, if necessary. */
- switch (p->sf.lengths_swapped) {
+ switch (ps->lengths_swapped) {
case NOT_SWAPPED:
break;
}
*data = p->buffer;
- if (p->sf.swapped) {
+ if (p->swapped) {
/*
* Convert pseudo-headers from the byte order of
* the host on which the file was saved to our
#ifndef sf_pcap_h
#define sf_pcap_h
-extern int pcap_check_header(pcap_t *, bpf_u_int32, FILE *, char *);
+extern pcap_t *pcap_check_header(bpf_u_int32 magic, FILE *fp, char *errbuf,
+ int *err);
#endif