Skip to content

Embed URL

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP
[NMAP] [Patch] Upgrade libpcap to 1.5.3
Index: libpcap/NMAP_MODIFICATIONS/0004-Include-netpacket-packet.h-before-pcap-bpf.h.patch
===================================================================
--- libpcap/NMAP_MODIFICATIONS/0004-Include-netpacket-packet.h-before-pcap-bpf.h.patch (revision 32783)
+++ libpcap/NMAP_MODIFICATIONS/0004-Include-netpacket-packet.h-before-pcap-bpf.h.patch (working copy)
@@ -22,9 +22,8 @@
---
fad-getad.c | 12 ++++++------
1 file changed, 6 insertions(+), 6 deletions(-)
-
diff --git fad-getad.c fad-getad.c
-index 742ae1f..519893a 100644
+index af371d4..2b483f6 100644
--- fad-getad.c
+++ fad-getad.c
@@ -54,12 +54,6 @@ static const char rcsid[] _U_ =
@@ -37,12 +36,12 @@
-#include "os-proto.h"
-#endif
-
- #ifdef AF_PACKET
- # ifdef HAVE_NETPACKET_PACKET_H
- /* Solaris 11 and later, Linux distributions with newer glibc */
-@@ -77,6 +71,12 @@ static const char rcsid[] _U_ =
+ /*
+ * We don't do this on Solaris 11 and later, as it appears there aren't
+ * any AF_PACKET addresses on interfaces, so we don't need this, and
+@@ -83,6 +77,12 @@ static const char rcsid[] _U_ =
# endif /* HAVE_NETPACKET_PACKET_H */
- #endif /* AF_PACKET */
+ #endif /* (defined(linux) || defined(__Lynx__)) && defined(AF_PACKET) */
+#include "pcap-int.h"
+
Index: libpcap/NMAP_MODIFICATIONS/HOWTO-UPGRADE
===================================================================
--- libpcap/NMAP_MODIFICATIONS/HOWTO-UPGRADE (revision 32783)
+++ libpcap/NMAP_MODIFICATIONS/HOWTO-UPGRADE (working copy)
@@ -3,7 +3,7 @@
cd
# Make a copy of this directory.
-cp -r ~/nmap/NMAP_MODIFICATIONS .
+cp -r ~/nmap/libpcap/NMAP_MODIFICATIONS .
tar xzvf libpcap-X.Y.tar.gz
cd nmap
rsync -rv --delete ~/libpcap-X.Y/ ~/nmap/libpcap/
Index: libpcap/NMAP_MODIFICATIONS/0002-Add-the-disable-packet-ring-configure-option.patch
===================================================================
--- libpcap/NMAP_MODIFICATIONS/0002-Add-the-disable-packet-ring-configure-option.patch (revision 32783)
+++ libpcap/NMAP_MODIFICATIONS/0002-Add-the-disable-packet-ring-configure-option.patch (working copy)
@@ -40,28 +40,34 @@
AC_CONFIG_HEADER(config.h)
diff --git pcap-linux.c pcap-linux.c
-index d4f50b7..213558b 100644
+index 17bd0f5..bd2457d 100644
--- pcap-linux.c
+++ pcap-linux.c
-@@ -219,14 +219,16 @@ static const char rcsid[] _U_ =
+@@ -196,17 +196,19 @@ static const char rcsid[] _U_ =
/* check for memory mapped access avaibility. We assume every needed
* struct is defined if the macro TPACKET_HDRLEN is defined, because it
* uses many ring related structs and macros */
-# ifdef TPACKET_HDRLEN
-# define HAVE_PACKET_RING
+-# ifdef TPACKET3_HDRLEN
+-# define HAVE_TPACKET3
+-# endif /* TPACKET3_HDRLEN */
-# ifdef TPACKET2_HDRLEN
-# define HAVE_TPACKET2
--# else
--# define TPACKET_V1 0
+-# else /* TPACKET2_HDRLEN */
+-# define TPACKET_V1 0 /* Old kernel with only V1, so no TPACKET_Vn defined */
-# endif /* TPACKET2_HDRLEN */
-# endif /* TPACKET_HDRLEN */
+# ifdef PCAP_SUPPORT_PACKET_RING
+# ifdef TPACKET_HDRLEN
+# define HAVE_PACKET_RING
++# ifdef TPACKET3_HDRLEN
++# define HAVE_TPACKET3
++# endif /* TPACKET3_HDRLEN */
+# ifdef TPACKET2_HDRLEN
+# define HAVE_TPACKET2
-+# else
-+# define TPACKET_V1 0
++# else /* TPACKET2_HDRLEN */
++# define TPACKET_V1 0 /* Old kernel with only V1, so no TPACKET_Vn defined */
+# endif /* TPACKET2_HDRLEN */
+# endif /* TPACKET_HDRLEN */
+# endif /* PCAP_SUPPORT_PACKET_RING */
Index: todo/nmap.txt
===================================================================
--- todo/nmap.txt (revision 32783)
+++ todo/nmap.txt (working copy)
@@ -1,12 +1,6 @@
TODO $Id: TODO 11866 2009-01-24 23:10:05Z fyodor $ -*-text-*-
-o We should probably update our included libpcap. We currently
- include version 1.2.1 (we upgraded to that in April 2012) while the
- latest version on tcpdump.org is 1.5.2. We make minor changes to
- libpcap that we ship, and instructions for upgrading are in
- libpcap/NMAP_MODIFICATIONS.
-
o Fix a segmentation fault in Ncat when scanned with the SSL NSE
scripts. I was able to reproduce this on 2013-09-27 with latest SVN
by running:
@@ -783,6 +777,12 @@
DONE:
+o We should probably update our included libpcap. We currently
+ include version 1.2.1 (we upgraded to that in April 2012) while the
+ latest version on tcpdump.org is 1.5.3. We make minor changes to
+ libpcap that we ship, and instructions for upgrading are in
+ libpcap/NMAP_MODIFICATIONS.
+
o Web: figure out why autogeneration of nmap.org/nsedoc/ doesn't seem
to be working. I think we had a cron job which was supposed to be
doing it.
Index: libpcap/sf-pcap.c
===================================================================
--- libpcap/sf-pcap.c (revision 32783)
+++ libpcap/sf-pcap.c (working copy)
@@ -123,25 +123,57 @@
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;
+
+typedef enum {
+ PASS_THROUGH,
+ SCALE_UP,
+ SCALE_DOWN
+} tstamp_scale_type_t;
+
+struct pcap_sf {
+ size_t hdrsize;
+ swapped_type_t lengths_swapped;
+ tstamp_scale_type_t scale_type;
+};
+
+/*
* 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, u_int precision, 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
* number for a pcap savefile, or for a byte-swapped pcap
* savefile.
*/
- if (magic != TCPDUMP_MAGIC && magic != KUZNETZOV_TCPDUMP_MAGIC) {
+ if (magic != TCPDUMP_MAGIC && magic != KUZNETZOV_TCPDUMP_MAGIC &&
+ magic != NSEC_TCPDUMP_MAGIC) {
magic = SWAPLONG(magic);
- if (magic != TCPDUMP_MAGIC && magic != KUZNETZOV_TCPDUMP_MAGIC)
- return (0); /* nope */
- p->sf.swapped = 1;
+ if (magic != TCPDUMP_MAGIC && magic != KUZNETZOV_TCPDUMP_MAGIC &&
+ magic != NSEC_TCPDUMP_MAGIC)
+ return (NULL); /* nope */
+ swapped = 1;
}
/*
@@ -162,13 +194,14 @@
(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);
@@ -180,18 +213,83 @@
if (hdr.version_major < PCAP_VERSION_MAJOR) {
snprintf(errbuf, PCAP_ERRBUF_SIZE,
"archaic pcap savefile format");
- return (-1);
+ *err = 1;
+ return (NULL);
}
- p->sf.version_major = hdr.version_major;
- p->sf.version_minor = hdr.version_minor;
+
+ /*
+ * 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->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->priv;
+
+ p->opt.tstamp_precision = precision;
+
/*
+ * Will we need to scale the timestamps to match what the
+ * user wants?
+ */
+ switch (precision) {
+
+ case PCAP_TSTAMP_PRECISION_MICRO:
+ if (magic == NSEC_TCPDUMP_MAGIC) {
+ /*
+ * The file has nanoseconds, the user
+ * wants microseconds; scale the
+ * precision down.
+ */
+ ps->scale_type = SCALE_DOWN;
+ } else {
+ /*
+ * The file has microseconds, the
+ * user wants microseconds; nothing to do.
+ */
+ ps->scale_type = PASS_THROUGH;
+ }
+ break;
+
+ case PCAP_TSTAMP_PRECISION_NANO:
+ if (magic == NSEC_TCPDUMP_MAGIC) {
+ /*
+ * The file has nanoseconds, the
+ * user wants nanoseconds; nothing to do.
+ */
+ ps->scale_type = PASS_THROUGH;
+ } else {
+ /*
+ * The file has microoseconds, the user
+ * wants nanoseconds; scale the
+ * precision up.
+ */
+ ps->scale_type = SCALE_UP;
+ }
+ break;
+
+ default:
+ snprintf(errbuf, PCAP_ERRBUF_SIZE,
+ "unknown time stamp resolution %u", precision);
+ free(p);
+ *err = 1;
+ return (NULL);
+ }
+
+ /*
* We interchanged the caplen and len fields at version 2.3,
* in order to match the bpf header layout. But unfortunately
* some files were written with version 2.3 in their headers
@@ -205,19 +303,19 @@
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;
}
@@ -239,7 +337,7 @@
* 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) {
/*
@@ -265,7 +363,7 @@
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.
@@ -280,10 +378,14 @@
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);
+ p->cleanup_op = sf_cleanup;
+
+ return (p);
}
/*
@@ -294,8 +396,9 @@
static int
pcap_next_packet(pcap_t *p, struct pcap_pkthdr *hdr, u_char **data)
{
+ struct pcap_sf *ps = p->priv;
struct pcap_sf_patched_pkthdr sf_hdr;
- FILE *fp = p->sf.rfile;
+ FILE *fp = p->rfile;
size_t amt_read;
bpf_u_int32 t;
@@ -306,8 +409,8 @@
* 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",
@@ -317,7 +420,7 @@
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);
}
@@ -326,7 +429,7 @@
}
}
- 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);
@@ -338,8 +441,34 @@
hdr->ts.tv_sec = sf_hdr.ts.tv_sec;
hdr->ts.tv_usec = sf_hdr.ts.tv_usec;
}
+
+ switch (ps->scale_type) {
+
+ case PASS_THROUGH:
+ /*
+ * Just pass the time stamp through.
+ */
+ break;
+
+ case SCALE_UP:
+ /*
+ * File has microseconds, user wants nanoseconds; convert
+ * it.
+ */
+ hdr->ts.tv_usec = hdr->ts.tv_usec * 1000;
+ break;
+
+ case SCALE_DOWN:
+ /*
+ * File has nanoseconds, user wants microseconds; convert
+ * it.
+ */
+ hdr->ts.tv_usec = hdr->ts.tv_usec / 1000;
+ break;
+ }
+
/* Swap the caplen and len fields, if necessary. */
- switch (p->sf.lengths_swapped) {
+ switch (ps->lengths_swapped) {
case NOT_SWAPPED:
break;
@@ -430,7 +559,7 @@
}
*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
@@ -452,11 +581,11 @@
}
static int
-sf_write_header(FILE *fp, int linktype, int thiszone, int snaplen)
+sf_write_header(pcap_t *p, FILE *fp, int linktype, int thiszone, int snaplen)
{
struct pcap_file_header hdr;
- hdr.magic = TCPDUMP_MAGIC;
+ hdr.magic = p->opt.tstamp_precision == PCAP_TSTAMP_PRECISION_NANO ? NSEC_TCPDUMP_MAGIC : TCPDUMP_MAGIC;
hdr.version_major = PCAP_VERSION_MAJOR;
hdr.version_minor = PCAP_VERSION_MINOR;
@@ -507,7 +636,7 @@
else
setbuf(f, NULL);
#endif
- if (sf_write_header(f, linktype, p->tzoff, p->snapshot) == -1) {
+ if (sf_write_header(p, f, linktype, p->tzoff, p->snapshot) == -1) {
snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "Can't write to %s: %s",
fname, pcap_strerror(errno));
if (f != stdout)
Index: libpcap/sf-pcap.h
===================================================================
--- libpcap/sf-pcap.h (revision 32783)
+++ libpcap/sf-pcap.h (working copy)
@@ -31,6 +31,7 @@
#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,
+ u_int precision, char *errbuf, int *err);
#endif
Index: libpcap/pcap/bpf.h
===================================================================
--- libpcap/pcap/bpf.h (revision 32783)
+++ libpcap/pcap/bpf.h (working copy)
@@ -177,11 +177,37 @@
#endif
/*
- * 17 is used for DLT_OLD_PFLOG in OpenBSD;
- * OBSOLETE: DLT_PFLOG is 117 in OpenBSD now as well. See below.
- * 18 is used for DLT_PFSYNC in OpenBSD; don't use it for anything else.
+ * 17 was used for DLT_PFLOG in OpenBSD; it no longer is.
+ *
+ * It was DLT_LANE8023 in SuSE 6.3, so we defined LINKTYPE_PFLOG
+ * as 117 so that pflog captures would use a link-layer header type
+ * value that didn't collide with any other values. On all
+ * platforms other than OpenBSD, we defined DLT_PFLOG as 117,
+ * and we mapped between LINKTYPE_PFLOG and DLT_PFLOG.
+ *
+ * OpenBSD eventually switched to using 117 for DLT_PFLOG as well.
+ *
+ * Don't use 17 for anything else.
*/
+/*
+ * 18 is used for DLT_PFSYNC in OpenBSD, NetBSD, DragonFly BSD and
+ * Mac OS X; don't use it for anything else. (FreeBSD uses 121,
+ * which collides with DLT_HHDLC, even though it doesn't use 18
+ * for anything and doesn't appear to have ever used it for anything.)
+ *
+ * We define it as 18 on those platforms; it is, unfortunately, used
+ * for DLT_CIP in Suse 6.3, so we don't define it as DLT_PFSYNC
+ * in general. As the packet format for it, like that for
+ * DLT_PFLOG, is not only OS-dependent but OS-version-dependent,
+ * we don't support printing it in tcpdump except on OSes that
+ * have the relevant header files, so it's not that useful on
+ * other platforms.
+ */
+#if defined(__OpenBSD__) || defined(__NetBSD__) || defined(__DragonFly__) || defined(__APPLE__)
+#define DLT_PFSYNC 18
+#endif
+
#define DLT_ATM_CLIP 19 /* Linux Classical-IP over ATM */
/*
@@ -312,15 +338,8 @@
#define DLT_IPFILTER 116
/*
- * OpenBSD DLT_PFLOG; DLT_PFLOG is 17 in OpenBSD, but that's DLT_LANE8023
- * in SuSE 6.3, so we can't use 17 for it in capture-file headers.
- *
- * XXX: is there a conflict with DLT_PFSYNC 18 as well?
+ * OpenBSD DLT_PFLOG.
*/
-#ifdef __OpenBSD__
-#define DLT_OLD_PFLOG 17
-#define DLT_PFSYNC 18
-#endif
#define DLT_PFLOG 117
/*
@@ -342,9 +361,48 @@
#define DLT_AIRONET_HEADER 120
/*
- * Reserved for Siemens HiPath HDLC.
+ * Sigh.
+ *
+ * This was reserved for Siemens HiPath HDLC on 2002-01-25, as
+ * requested by Tomas Kukosa.
+ *
+ * On 2004-02-25, a FreeBSD checkin to sys/net/bpf.h was made that
+ * assigned 121 as DLT_PFSYNC. Its libpcap does DLT_ <-> LINKTYPE_
+ * mapping, so it probably supports capturing on the pfsync device
+ * but not saving the captured data to a pcap file.
+ *
+ * OpenBSD, from which pf came, however, uses 18 for DLT_PFSYNC;
+ * their libpcap does no DLT_ <-> LINKTYPE_ mapping, so it would
+ * use 18 in pcap files as well.
+ *
+ * NetBSD and DragonFly BSD also use 18 for DLT_PFSYNC; their
+ * libpcaps do DLT_ <-> LINKTYPE_ mapping, and neither has an entry
+ * for DLT_PFSYNC, so it might not be able to write out dump files
+ * with 18 as the link-layer header type. (Earlier versions might
+ * not have done mapping, in which case they'd work the same way
+ * OpenBSD does.)
+ *
+ * Mac OS X defines it as 18, but doesn't appear to use it as of
+ * Mac OS X 10.7.3. Its libpcap does DLT_ <-> LINKTYPE_ mapping.
+ *
+ * We'll define DLT_PFSYNC as 121 on FreeBSD and define it as 18 on
+ * all other platforms. We'll define DLT_HHDLC as 121 on everything
+ * except for FreeBSD; anybody who wants to compile, on FreeBSD, code
+ * that uses DLT_HHDLC is out of luck.
+ *
+ * We'll define LINKTYPE_PFSYNC as 18, *even on FreeBSD*, and map
+ * it, so that savefiles won't use 121 for PFSYNC - they'll all
+ * use 18. Code that uses pcap_datalink() to determine the link-layer
+ * header type of a savefile won't, when built and run on FreeBSD,
+ * be able to distinguish between LINKTYPE_PFSYNC and LINKTYPE_HHDLC
+ * capture files; code that doesn't, such as the code in Wireshark,
+ * will be able to distinguish between them.
*/
+#ifdef __FreeBSD__
+#define DLT_PFSYNC 121
+#else
#define DLT_HHDLC 121
+#endif
/*
* This is for RFC 2625 IP-over-Fibre Channel.
@@ -542,7 +600,7 @@
#define DLT_JUNIPER_MONITOR 164
/*
- * Reserved for BACnet MS/TP.
+ * BACnet MS/TP frames.
*/
#define DLT_BACNET_MS_TP 165
@@ -1075,15 +1133,100 @@
#define DLT_NETANALYZER_TRANSPARENT 241
/*
- * IP-over-Infiniband, as specified by RFC 4391.
+ * IP-over-InfiniBand, as specified by RFC 4391.
*
* Requested by Petr Sumbera <petr.sumbera@oracle.com>.
*/
#define DLT_IPOIB 242
-#define DLT_MATCHING_MAX 242 /* highest value in the "matching" range */
+/*
+ * MPEG-2 transport stream (ISO 13818-1/ITU-T H.222.0).
+ *
+ * Requested by Guy Martin <gmsoft@tuxicoman.be>.
+ */
+#define DLT_MPEG_2_TS 243
/*
+ * ng4T GmbH's UMTS Iub/Iur-over-ATM and Iub/Iur-over-IP format as
+ * used by their ng40 protocol tester.
+ *
+ * Requested by Jens Grimmer <jens.grimmer@ng4t.com>.
+ */
+#define DLT_NG40 244
+
+/*
+ * Pseudo-header giving adapter number and flags, followed by an NFC
+ * (Near-Field Communications) Logical Link Control Protocol (LLCP) PDU,
+ * as specified by NFC Forum Logical Link Control Protocol Technical
+ * Specification LLCP 1.1.
+ *
+ * Requested by Mike Wakerly <mikey@google.com>.
+ */
+#define DLT_NFC_LLCP 245
+
+/*
+ * 245 is used as LINKTYPE_PFSYNC; do not use it for any other purpose.
+ *
+ * DLT_PFSYNC has different values on different platforms, and all of
+ * them collide with something used elsewhere. On platforms that
+ * don't already define it, define it as 245.
+ */
+#if !defined(__FreeBSD__) && !defined(__OpenBSD__) && !defined(__NetBSD__) && !defined(__DragonFly__) && !defined(__APPLE__)
+#define DLT_PFSYNC 246
+#endif
+
+/*
+ * Raw InfiniBand packets, starting with the Local Routing Header.
+ *
+ * Requested by Oren Kladnitsky <orenk@mellanox.com>.
+ */
+#define DLT_INFINIBAND 247
+
+/*
+ * SCTP, with no lower-level protocols (i.e., no IPv4 or IPv6).
+ *
+ * Requested by Michael Tuexen <Michael.Tuexen@lurchi.franken.de>.
+ */
+#define DLT_SCTP 248
+
+/*
+ * USB packets, beginning with a USBPcap header.
+ *
+ * Requested by Tomasz Mon <desowin@gmail.com>
+ */
+#define DLT_USBPCAP 249
+
+/*
+ * Schweitzer Engineering Laboratories "RTAC" product serial-line
+ * packets.
+ *
+ * Requested by Chris Bontje <chris_bontje@selinc.com>.
+ */
+#define DLT_RTAC_SERIAL 250
+
+/*
+ * Bluetooth Low Energy air interface link-layer packets.
+ *
+ * Requested by Mike Kershaw <dragorn@kismetwireless.net>.
+ */
+#define DLT_BLUETOOTH_LE_LL 251
+
+/*
+ * DLT type for upper-protocol layer PDU saves from wireshark.
+ *
+ * the actual contents are determined by two TAGs stored with each
+ * packet:
+ * EXP_PDU_TAG_LINKTYPE the link type (LINKTYPE_ value) of the
+ * original packet.
+ *
+ * EXP_PDU_TAG_PROTO_NAME the name of the wireshark dissector
+ * that can make sense of the data stored.
+ */
+#define DLT_WIRESHARK_UPPER_PDU 252
+
+#define DLT_MATCHING_MAX 252 /* highest value in the "matching" range */
+
+/*
* DLT and savefile link type values are split into a class and
* a member of that class. A class value of 0 indicates a regular
* DLT_/LINKTYPE_ value.
Index: libpcap/pcap/pcap.h
===================================================================
--- libpcap/pcap/pcap.h (revision 32783)
+++ libpcap/pcap/pcap.h (working copy)
@@ -113,12 +113,13 @@
* the old file header as well as files with the new file header
* (using the magic number to determine the header format).
*
- * Then supply the changes as a patch at
+ * Then supply the changes by forking the branch at
*
- * http://sourceforge.net/projects/libpcap/
+ * https://github.com/the-tcpdump-group/libpcap/issues
*
- * so that future versions of libpcap and programs that use it (such as
- * tcpdump) will be able to read your new capture file format.
+ * and issuing a pull request, so that future versions of libpcap and
+ * programs that use it (such as tcpdump) will be able to read your new
+ * capture file format.
*/
struct pcap_file_header {
bpf_u_int32 magic;
@@ -253,6 +254,7 @@
#define PCAP_ERROR_IFACE_NOT_UP -9 /* interface isn't up */
#define PCAP_ERROR_CANTSET_TSTAMP_TYPE -10 /* this device doesn't support setting the time stamp type */
#define PCAP_ERROR_PROMISC_PERM_DENIED -11 /* you don't have permission to capture in promiscuous mode */
+#define PCAP_ERROR_TSTAMP_PRECISION_NOTSUP -12 /* the requested time stamp precision is not supported */
/*
* Warning codes for the pcap API.
@@ -279,7 +281,10 @@
int pcap_set_rfmon(pcap_t *, int);
int pcap_set_timeout(pcap_t *, int);
int pcap_set_tstamp_type(pcap_t *, int);
+int pcap_set_immediate_mode(pcap_t *, int);
int pcap_set_buffer_size(pcap_t *, int);
+int pcap_set_tstamp_precision(pcap_t *, int);
+int pcap_get_tstamp_precision(pcap_t *);
int pcap_activate(pcap_t *);
int pcap_list_tstamp_types(pcap_t *, int **);
@@ -332,18 +337,34 @@
#define PCAP_TSTAMP_ADAPTER 3 /* device-provided, synced with the system clock */
#define PCAP_TSTAMP_ADAPTER_UNSYNCED 4 /* device-provided, not synced with the system clock */
+/*
+ * Time stamp resolution types.
+ * Not all systems and interfaces will necessarily support all of these
+ * resolutions when doing live captures; all of them can be requested
+ * when reading a savefile.
+ */
+#define PCAP_TSTAMP_PRECISION_MICRO 0 /* use timestamps with microsecond precision, default */
+#define PCAP_TSTAMP_PRECISION_NANO 1 /* use timestamps with nanosecond precision */
+
pcap_t *pcap_open_live(const char *, int, int, int, char *);
pcap_t *pcap_open_dead(int, int);
+pcap_t *pcap_open_dead_with_tstamp_precision(int, int, u_int);
+pcap_t *pcap_open_offline_with_tstamp_precision(const char *, u_int, char *);
pcap_t *pcap_open_offline(const char *, char *);
#if defined(WIN32)
+pcap_t *pcap_hopen_offline_with_tstamp_precision(intptr_t, u_int, char *);
pcap_t *pcap_hopen_offline(intptr_t, char *);
#if !defined(LIBPCAP_EXPORTS)
+#define pcap_fopen_offline_with_tstamp_precision(f,p,b) \
+ pcap_hopen_offline_with_tstamp_precision(_get_osfhandle(_fileno(f)), p, b)
#define pcap_fopen_offline(f,b) \
pcap_hopen_offline(_get_osfhandle(_fileno(f)), b)
#else /*LIBPCAP_EXPORTS*/
+static pcap_t *pcap_fopen_offline_with_tstamp_precision(FILE *, u_int, char *);
static pcap_t *pcap_fopen_offline(FILE *, char *);
#endif
#else /*WIN32*/
+pcap_t *pcap_fopen_offline_with_tstamp_precision(FILE *, u_int, char *);
pcap_t *pcap_fopen_offline(FILE *, char *);
#endif /*WIN32*/
@@ -370,8 +391,8 @@
int pcap_compile_nopcap(int, int, struct bpf_program *,
const char *, int, bpf_u_int32);
void pcap_freecode(struct bpf_program *);
-int pcap_offline_filter(struct bpf_program *, const struct pcap_pkthdr *,
- const u_char *);
+int pcap_offline_filter(const struct bpf_program *,
+ const struct pcap_pkthdr *, const u_char *);
int pcap_datalink(pcap_t *);
int pcap_datalink_ext(pcap_t *);
int pcap_list_datalinks(pcap_t *, int **);
@@ -425,6 +446,7 @@
int pcap_setbuff(pcap_t *p, int dim);
int pcap_setmode(pcap_t *p, int mode);
int pcap_setmintocopy(pcap_t *p, int size);
+Adapter *pcap_get_adapter(pcap_t *p);
#ifdef WPCAP
/* Include file with the wpcap-specific extensions */
Index: libpcap/pcap-dos.c
===================================================================
--- libpcap/pcap-dos.c (revision 32783)
+++ libpcap/pcap-dos.c (working copy)
@@ -143,11 +143,19 @@
return handle_to_device [fd-1];
}
-pcap_t *pcap_create (const char *device, char *ebuf)
+/*
+ * 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);
@@ -161,6 +169,8 @@
*/
static int pcap_activate_dos (pcap_t *pcap)
{
+ struct pcap_dos *pcapd = pcap->priv;
+
if (pcap->opt.rfmon) {
/*
* No monitor mode on DOS.
@@ -210,15 +220,16 @@
static int
pcap_read_one (pcap_t *p, pcap_handler callback, u_char *data)
{
+ struct pcap_dos *pd = p->priv;
struct pcap_pkthdr pcap;
- struct timeval now, expiry;
+ 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)
{
@@ -287,10 +298,10 @@
return (1);
}
- /* If not to wait for a packet or pcap_close() called from
+ /* 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);
@@ -308,7 +319,7 @@
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);
@@ -321,9 +332,10 @@
static int
pcap_read_dos (pcap_t *p, int cnt, pcap_handler callback, u_char *data)
{
+ struct pcap_dos *pd = p->priv;
int rc, num = 0;
- while (num <= cnt || (cnt < 0))
+ while (num <= cnt || PACKET_COUNT_IS_UNLIMITED(cnt))
{
if (p->fd <= 0)
return (-1);
@@ -343,6 +355,7 @@
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)
@@ -359,12 +372,13 @@
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->priv;
+ 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);
}
@@ -428,10 +442,13 @@
*/
static void pcap_cleanup_dos (pcap_t *p)
{
+ struct pcap_dos *pd;
+
if (p && !exc_occured)
{
+ pd = p->priv;
if (pcap_stats(p,NULL) < 0)
- p->md.stat.ps_drop = 0;
+ pd->stat.ps_drop = 0;
if (!get_device(p->fd))
return;
@@ -590,10 +607,12 @@
*/
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->priv;
+ pd->wait_proc = yield;
+ p->opt.timeout = wait;
}
}
Index: libpcap/pcap-usb-linux.c
===================================================================
--- libpcap/pcap-usb-linux.c (revision 32783)
+++ libpcap/pcap-usb-linux.c (working copy)
@@ -121,6 +121,16 @@
#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 *);
@@ -148,7 +158,7 @@
}
int
-usb_platform_finddevs(pcap_if_t **alldevsp, char *err_str)
+usb_findalldevs(pcap_if_t **alldevsp, char *err_str)
{
struct dirent* data;
int ret = 0;
@@ -204,14 +214,15 @@
static
int usb_mmap(pcap_t* handle)
{
+ struct pcap_usb_linux *handlep = handle->priv;
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 */
@@ -284,11 +295,41 @@
}
pcap_t *
-usb_create(const char *device, char *ebuf)
+usb_create(const char *device, char *ebuf, int *is_ours)
{
+ const char *cp;
+ char *cpend;
+ long devnum;
pcap_t *p;
- p = pcap_create_common(device, ebuf);
+ /* Does this look like a USB monitoring device? */
+ cp = strrchr(device, '/');
+ if (cp == NULL)
+ cp = device;
+ /* Does it begin with USB_IFACE? */
+ if (strncmp(cp, USB_IFACE, sizeof USB_IFACE - 1) != 0) {
+ /* Nope, doesn't begin with USB_IFACE */
+ *is_ours = 0;
+ return NULL;
+ }
+ /* Yes - is USB_IFACE followed by a number? */
+ cp += sizeof USB_IFACE - 1;
+ devnum = strtol(cp, &cpend, 10);
+ if (cpend == cp || *cpend != '\0') {
+ /* Not followed by a number. */
+ *is_ours = 0;
+ return NULL;
+ }
+ if (devnum < 0) {
+ /* Followed by a non-valid number. */
+ *is_ours = 0;
+ return NULL;
+ }
+
+ /* OK, it's probably ours. */
+ *is_ours = 1;
+
+ p = pcap_create_common(device, ebuf, sizeof (struct pcap_usb_linux));
if (p == NULL)
return (NULL);
@@ -299,6 +340,7 @@
static int
usb_activate(pcap_t* handle)
{
+ struct pcap_usb_linux *handlep = handle->priv;
char full_path[USB_LINE_LEN];
/* Initialize some components of the pcap structure. */
@@ -314,7 +356,7 @@
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);
@@ -322,7 +364,7 @@
}
/*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)
{
@@ -340,7 +382,7 @@
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
@@ -353,11 +395,11 @@
/* 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)
{
@@ -367,7 +409,7 @@
* 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) {
@@ -426,6 +468,7 @@
* /usr/src/linux/Documentation/usb/usbmon.txt
* for message format
*/
+ struct pcap_usb_linux *handlep = handle->priv;
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];
@@ -470,7 +513,7 @@
}
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;
@@ -609,7 +652,7 @@
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;
}
@@ -627,13 +670,14 @@
static int
usb_stats_linux(pcap_t *handle, struct pcap_stat *stats)
{
+ struct pcap_usb_linux *handlep = handle->priv;
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)
{
@@ -643,7 +687,7 @@
* 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) {
@@ -694,7 +738,7 @@
ptr += cnt;
}
- stats->ps_recv = handle->md.packets_read;
+ stats->ps_recv = handlep->packets_read;
stats->ps_ifdrop = 0;
return 0;
}
@@ -710,6 +754,7 @@
static int
usb_stats_linux_bin(pcap_t *handle, struct pcap_stat *stats)
{
+ struct pcap_usb_linux *handlep = handle->priv;
int ret;
struct mon_bin_stats st;
ret = ioctl(handle->fd, MON_IOCG_STATS, &st);
@@ -720,7 +765,7 @@
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;
@@ -733,6 +778,7 @@
static int
usb_read_linux_bin(pcap_t *handle, int max_packets, pcap_handler callback, u_char *user)
{
+ struct pcap_usb_linux *handlep = handle->priv;
struct mon_bin_get info;
int ret;
struct pcap_pkthdr pkth;
@@ -775,7 +821,7 @@
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;
}
@@ -791,6 +837,7 @@
static int
usb_read_linux_mmap(pcap_t *handle, int max_packets, pcap_handler callback, u_char *user)
{
+ struct pcap_usb_linux *handlep = handle->priv;
struct mon_bin_mfetch fetch;
int32_t vec[VEC_SIZE];
struct pcap_pkthdr pkth;
@@ -836,7 +883,7 @@
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;
@@ -855,14 +902,14 @@
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++;
}
}
- /* with max_packets <= 0 we stop afer the first chunk*/
- if ((max_packets <= 0) || (packets == max_packets))
+ /* with max_packets specifying "unlimited" we stop afer the first chunk*/
+ if (PACKET_COUNT_IS_UNLIMITED(max_packets) || (packets == max_packets))
break;
}
@@ -874,10 +921,12 @@
static void
usb_cleanup_linux_mmap(pcap_t* handle)
{
+ struct pcap_usb_linux *handlep = handle->priv;
+
/* 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);
}
Index: libpcap/pcap-dlpi.c
===================================================================
--- libpcap/pcap-dlpi.c (revision 32783)
+++ libpcap/pcap-dlpi.c (working copy)
@@ -245,6 +245,9 @@
static int
pcap_inject_dlpi(pcap_t *p, const void *buf, size_t size)
{
+#ifdef DL_HP_RAWDLS
+ struct pcap_dlpi *pd = p->priv;
+#endif
int ret;
#if defined(DLIOCRAW)
@@ -255,12 +258,12 @@
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));
@@ -321,16 +324,23 @@
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->priv;
+
+ 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->priv;
+#endif
register char *cp;
int ppa;
#ifdef HAVE_SOLARIS
@@ -398,13 +408,13 @@
* 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
/*
@@ -513,8 +523,8 @@
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
@@ -570,13 +580,13 @@
*/
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 */
@@ -669,13 +679,13 @@
** 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
@@ -729,7 +739,7 @@
#endif
/* Push and configure bufmod. */
- if (pcap_conf_bufmod(p, ss, p->md.timeout) != 0)
+ if (pcap_conf_bufmod(p, ss) != 0)
goto bad;
#endif
@@ -1693,15 +1703,21 @@
#endif
pcap_t *
-pcap_create(const char *device, char *ebuf)
+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->priv;
+ pd->send_fd = -1; /* it hasn't been opened yet */
+#endif
p->activate_op = pcap_activate_dlpi;
return (p);
Index: libpcap/pcap_open_dead.3pcap.in
===================================================================
--- libpcap/pcap_open_dead.3pcap.in (revision 32783)
+++ libpcap/pcap_open_dead.3pcap.in (working copy)
@@ -19,10 +19,10 @@
.\" WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
.\" MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
.\"
-.TH PCAP_OPEN_DEAD 3PCAP "5 April 2008"
+.TH PCAP_OPEN_DEAD 3PCAP "1 July 2013"
.SH NAME
-pcap_open_dead \- open a fake pcap_t for compiling filters or opening a
-capture for output
+pcap_open_dead, pcap_open_dead_with_tstamp_precision \- open a fake
+pcap_t for compiling filters or opening a capture for output
.SH SYNOPSIS
.nf
.ft B
@@ -31,15 +31,27 @@
.LP
.ft B
pcap_t *pcap_open_dead(int linktype, int snaplen);
+pcap_t *pcap_open_dead_with_tstamp_precision(int linktype, int snaplen,
+ u_int precision);
.ft
.fi
.SH DESCRIPTION
.PP
.B pcap_open_dead()
-is used for creating a
+and
+.B pcap_open_dead_with_tstamp_precision()
+are used for creating a
.B pcap_t
structure to use when calling the other functions in libpcap. It is
-typically used when just using libpcap for compiling BPF code.
+typically used when just using libpcap for compiling BPF code; it can
+also be used if using
+.BR pcap_dump_open() ,
+.BR pcap_dump() ,
+and
+.B pcap_dump_close()
+to write a savefile if there is no
+.B pcap_t
+that supplies the packets to be written.
.PP
.I linktype
specifies the link-layer type for the
@@ -48,5 +60,22 @@
.I snaplen
specifies the snapshot length for the
.BR pcap_t .
+.PP
+When
+.BR pcap_open_dead_with_tstamp_precision() ,
+is used to create a
+.B pcap_t
+for use with
+.BR pcap_dump_open() ,
+.I precision
+specifies the time stamp precision for packets;
+.B PCAP_TSTAMP_PRECISION_MICRO
+should be specified if the packets to be written have time stamps in
+seconds and microseconds, and
+.B PCAP_TSTAMP_PRECISION_NANO
+should be specified if the packets to be written have time stamps in
+seconds and nanoseconds. Its value does not affect
+.BR pcap_compile() .
.SH SEE ALSO
-pcap(3PCAP), pcap-linktype(@MAN_MISC_INFO@)
+pcap(3PCAP), pcap_compile(3PCAP), pcap_dump_open(3PCAP),
+pcap-linktype(@MAN_MISC_INFO@)
Index: libpcap/pcap-usb-linux.h
===================================================================
--- libpcap/pcap-usb-linux.h (revision 32783)
+++ libpcap/pcap-usb-linux.h (working copy)
@@ -36,5 +36,5 @@
/*
* Prototypes for USB-related functions
*/
-int usb_platform_finddevs(pcap_if_t **alldevsp, char *err_str);
-pcap_t *usb_create(const char *device, char *ebuf);
+int usb_findalldevs(pcap_if_t **alldevsp, char *err_str);
+pcap_t *usb_create(const char *device, char *ebuf, int *is_ours);
Index: libpcap/pcap-win32.c
===================================================================
--- libpcap/pcap-win32.c (revision 32783)
+++ libpcap/pcap-win32.c (working copy)
@@ -72,6 +72,17 @@
#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
*/
@@ -165,6 +176,13 @@
return 0;
}
+/*return the Adapter for a pcap_t*/
+static Adapter *
+pcap_getadapter_win32(pcap_t *p)
+{
+ return p->adapter;
+}
+
static int
pcap_read_win32_npf(pcap_t *p, int cnt, pcap_handler callback, u_char *user)
{
@@ -238,7 +256,7 @@
*/
(*callback)(user, (struct pcap_pkthdr*)bp, bp + hdrlen);
bp += Packet_WORDALIGN(caplen + hdrlen);
- if (++n >= cnt && cnt > 0) {
+ if (++n >= cnt && !PACKET_COUNT_IS_UNLIMITED(cnt)) {
p->bp = bp;
p->cc = ep - bp;
return (n);
@@ -253,6 +271,7 @@
static int
pcap_read_win32_dag(pcap_t *p, int cnt, pcap_handler callback, u_char *user)
{
+ struct pcap_win *pw = p->priv;
u_char *dp = NULL;
int packet_len = 0, caplen = 0;
struct pcap_pkthdr pcap_header;
@@ -295,7 +314,7 @@
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;
@@ -312,7 +331,7 @@
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)
{
@@ -324,7 +343,7 @@
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)
{
@@ -397,7 +416,7 @@
header = (dag_record_t*)((char*)header + erf_record_len);
/* Stop if the number of packets requested by user has been reached*/
- if (++n >= cnt && cnt > 0)
+ if (++n >= cnt && !PACKET_COUNT_IS_UNLIMITED(cnt))
{
p->bp = (char*)header;
p->cc = endofbuf - (char*)header;
@@ -457,6 +476,7 @@
static int
pcap_activate_win32(pcap_t *p)
{
+ struct pcap_win *pw = p->priv;
NetType type;
if (p->opt.rfmon) {
@@ -622,12 +642,24 @@
PacketInitPacket(p->Packet,(BYTE*)p->buffer,p->bufsize);
- /* tell the driver to copy the buffer only if it contains at least 16K */
- if(PacketSetMinToCopy(p->adapter,16000)==FALSE)
+ if (p-opt.immediate)
{
- snprintf(p->errbuf, PCAP_ERRBUF_SIZE,"Error calling PacketSetMinToCopy: %s", pcap_win32strerror());
- goto bad;
+ /* tell the driver to copy the buffer as soon as data arrives */
+ if(PacketSetMinToCopy(p->adapter,0)==FALSE)
+ {
+ snprintf(p->errbuf, PCAP_ERRBUF_SIZE,"Error calling PacketSetMinToCopy: %s", pcap_win32strerror());
+ goto bad;
+ }
}
+ else
+ {
+ /* tell the driver to copy the buffer only if it contains at least 16K */
+ if(PacketSetMinToCopy(p->adapter,16000)==FALSE)
+ {
+ snprintf(p->errbuf, PCAP_ERRBUF_SIZE,"Error calling PacketSetMinToCopy: %s", pcap_win32strerror());
+ goto bad;
+ }
+ }
}
else
#ifdef HAVE_DAG_API
@@ -672,13 +704,13 @@
/* 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)
@@ -706,6 +738,7 @@
p->setbuff_op = pcap_setbuff_win32;
p->setmode_op = pcap_setmode_win32;
p->setmintocopy_op = pcap_setmintocopy_win32;
+ p->getadapter_op = pcap_getadapter_win32;
p->cleanup_op = pcap_cleanup_win32;
return (0);
@@ -715,7 +748,7 @@
}
pcap_t *
-pcap_create(const char *device, char *ebuf)
+pcap_create_interface(const char *device, char *ebuf)
{
pcap_t *p;
@@ -743,12 +776,12 @@
}
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)
@@ -801,25 +834,26 @@
return -1;
}
- p->md.use_bpf = 0;
-
return (0);
}
static int
pcap_getnonblock_win32(pcap_t *p, char *errbuf)
{
+ struct pcap_win *pw = p->priv;
+
/*
* 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->priv;
int newtimeout;
if (nonblock) {
@@ -833,14 +867,14 @@
* (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(p->errbuf, PCAP_ERRBUF_SIZE,
+ snprintf(errbuf, PCAP_ERRBUF_SIZE,
"PacketSetReadTimeout: %s", pcap_win32strerror());
return (-1);
}
- p->nonblock = (newtimeout == -1);
+ pw->nonblock = (newtimeout == -1);
return (0);
}
Index: libpcap/pcap-bpf.c
===================================================================
--- libpcap/pcap-bpf.c (revision 32783)
+++ libpcap/pcap-bpf.c (working copy)
@@ -122,18 +122,60 @@
#include "pcap-int.h"
-#ifdef HAVE_DAG_API
-#include "pcap-dag.h"
-#endif /* HAVE_DAG_API */
-
-#ifdef HAVE_SNF_API
-#include "pcap-snf.h"
-#endif /* HAVE_SNF_API */
-
#ifdef HAVE_OS_PROTO_H
#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;
+ int nonblock; /* true if in nonblocking mode */
+#endif /* HAVE_ZEROCOPY_BPF */
+
+ char *device; /* device name */
+ int filtering_in_kernel; /* using kernel filter */
+ 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
@@ -155,6 +197,10 @@
#endif /* BIOCGDLTLIST */
+#if defined(sun) && defined(LIFNAMSIZ) && defined(lifr_zoneid)
+#include <zone.h>
+#endif
+
/*
* We include the OS's <net/bpf.h>, not our "pcap/bpf.h", so we probably
* don't get DLT_DOCSIS defined.
@@ -188,22 +234,17 @@
/*
* 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-
- * 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.
+ * pb->nonblock so we don't call select(2) if the pcap handle is in non-
+ * blocking mode.
*/
static int
pcap_getnonblock_bpf(pcap_t *p, char *errbuf)
{
#ifdef HAVE_ZEROCOPY_BPF
- if (p->md.zerocopy) {
- /*
- * Use a negative value for the timeout to represent that the
- * pcap handle is in non-blocking mode.
- */
- return (p->md.timeout < 0);
- }
+ struct pcap_bpf *pb = p->priv;
+
+ if (pb->zerocopy)
+ return (pb->nonblock);
#endif
return (pcap_getnonblock_fd(p, errbuf));
}
@@ -212,34 +253,10 @@
pcap_setnonblock_bpf(pcap_t *p, int nonblock, char *errbuf)
{
#ifdef HAVE_ZEROCOPY_BPF
- if (p->md.zerocopy) {
- /*
- * Map each value to the corresponding 2's complement, to
- * preserve the timeout value provided with pcap_set_timeout.
- * (from pcap-linux.c).
- */
- if (nonblock) {
- if (p->md.timeout >= 0) {
- /*
- * Timeout is non-negative, so we're not
- * currently in non-blocking mode; set it
- * to the 2's complement, to make it
- * negative, as an indication that we're
- * in non-blocking mode.
- */
- p->md.timeout = p->md.timeout * -1 - 1;
- }
- } else {
- if (p->md.timeout < 0) {
- /*
- * Timeout is negative, so we're currently
- * in blocking mode; reverse the previous
- * operation, to make the timeout non-negative
- * again.
- */
- p->md.timeout = (p->md.timeout + 1) * -1;
- }
- }
+ struct pcap_bpf *pb = p->priv;
+
+ if (pb->zerocopy) {
+ pb->nonblock = nonblock;
return (0);
}
#endif
@@ -259,25 +276,26 @@
static int
pcap_next_zbuf_shm(pcap_t *p, int *cc)
{
+ struct pcap_bpf *pb = p->priv;
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);
}
@@ -296,6 +314,7 @@
static int
pcap_next_zbuf(pcap_t *p, int *cc)
{
+ struct pcap_bpf *pb = p->priv;
struct bpf_zbuf bz;
struct timeval tv;
struct timespec cur;
@@ -319,15 +338,15 @@
* our timeout is less then or equal to zero, handle it like a
* regular timeout.
*/
- tmout = p->md.timeout;
+ tmout = p->opt.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 && p->opt.timeout) {
+ expire = TSTOMILLI(&pb->firstsel) + p->opt.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);
@@ -344,7 +363,7 @@
* the next timeout. Note that we only call select if the handle
* is in blocking mode.
*/
- if (p->md.timeout >= 0) {
+ if (!pb->nonblock) {
FD_ZERO(&r_set);
FD_SET(p->fd, &r_set);
if (tmout != 0) {
@@ -352,11 +371,11 @@
tv.tv_usec = (tmout * 1000) % 1000000;
}
r = select(p->fd + 1, &r_set, NULL, NULL,
- p->md.timeout != 0 ? &tv : NULL);
+ p->opt.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 && p->opt.timeout) {
+ pb->interrupted = 1;
+ pb->firstsel = cur;
}
return (0);
} else if (r < 0) {
@@ -365,7 +384,7 @@
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"
@@ -393,30 +412,22 @@
static int
pcap_ack_zbuf(pcap_t *p)
{
+ struct pcap_bpf *pb = p->priv;
- 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);
}
#endif /* HAVE_ZEROCOPY_BPF */
pcap_t *
-pcap_create(const char *device, char *ebuf)
+pcap_create_interface(const char *device, char *ebuf)
{
pcap_t *p;
-#ifdef HAVE_DAG_API
- if (strstr(device, "dag"))
- return (dag_create(device, ebuf));
-#endif /* HAVE_DAG_API */
-#ifdef HAVE_SNF_API
- if (strstr(device, "snf"))
- return (snf_create(device, ebuf));
-#endif /* HAVE_SNF_API */
-
- p = pcap_create_common(device, ebuf);
+ p = pcap_create_common(device, ebuf, sizeof (struct pcap_bpf));
if (p == NULL)
return (NULL);
@@ -812,6 +823,7 @@
static int
pcap_read_bpf(pcap_t *p, int cnt, pcap_handler callback, u_char *user)
{
+ struct pcap_bpf *pb = p->priv;
int cc;
int n = 0;
register u_char *bp, *ep;
@@ -847,7 +859,7 @@
* 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);
@@ -995,7 +1007,7 @@
* 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;
@@ -1025,7 +1037,7 @@
#endif
(*callback)(user, &pkthdr, datap);
bp += BPF_WORDALIGN(caplen + hdrlen);
- if (++n >= cnt && cnt > 0) {
+ if (++n >= cnt && !PACKET_COUNT_IS_UNLIMITED(cnt)) {
p->bp = bp;
p->cc = ep - bp;
/*
@@ -1262,19 +1274,20 @@
static void
pcap_cleanup_bpf(pcap_t *p)
{
+ struct pcap_bpf *pb = p->priv;
#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.
@@ -1291,7 +1304,7 @@
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,
@@ -1306,7 +1319,7 @@
*/
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;
@@ -1329,11 +1342,11 @@
* 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
@@ -1341,16 +1354,16 @@
* 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);
}
@@ -1451,15 +1464,25 @@
* Default capture buffer size.
* 32K isn't very much for modern machines with fast networks; we
* pick .5M, as that's the maximum on at least some systems with BPF.
+ *
+ * However, on AIX 3.5, the larger buffer sized caused unrecoverable
+ * read failures under stress, so we leave it as 32K; yet another
+ * place where AIX's BPF is broken.
*/
+#ifdef _AIX
+#define DEFAULT_BUFSIZE 32768
+#else
#define DEFAULT_BUFSIZE 524288
+#endif
static int
pcap_activate_bpf(pcap_t *p)
{
+ struct pcap_bpf *pb = p->priv;
int status = 0;
int fd;
#ifdef LIFNAMSIZ
+ char *zonesep;
struct lifreq ifr;
char *ifrname = ifr.lifr_name;
const size_t ifnamsiz = sizeof(ifr.lifr_name);
@@ -1514,8 +1537,31 @@
goto bad;
}
- p->md.device = strdup(p->opt.source);
- if (p->md.device == NULL) {
+#if defined(LIFNAMSIZ) && defined(ZONENAME_MAX) && defined(lifr_zoneid)
+ /*
+ * Check if the given source network device has a '/' separated
+ * zonename prefix string. The zonename prefixed source device
+ * can be used by libpcap consumers to capture network traffic
+ * in non-global zones from the global zone on Solaris 11 and
+ * above. If the zonename prefix is present then we strip the
+ * prefix and pass the zone ID as part of lifr_zoneid.
+ */
+ if ((zonesep = strchr(p->opt.source, '/')) != NULL) {
+ char zonename[ZONENAME_MAX];
+ int znamelen;
+ char *lnamep;
+
+ znamelen = zonesep - p->opt.source;
+ (void) strlcpy(zonename, p->opt.source, znamelen + 1);
+ lnamep = strdup(zonesep + 1);
+ ifr.lifr_zoneid = getzoneidbyname(zonename);
+ free(p->opt.source);
+ p->opt.source = lnamep;
+ }
+#endif
+
+ pb->device = strdup(p->opt.source);
+ if (pb->device == NULL) {
snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "strdup: %s",
pcap_strerror(errno));
status = PCAP_ERROR;
@@ -1623,7 +1669,7 @@
/*
* We have zerocopy BPF; use it.
*/
- p->md.zerocopy = 1;
+ pb->zerocopy = 1;
/*
* How to pick a buffer size: first, query the maximum buffer
@@ -1653,22 +1699,22 @@
#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;
}
- bzero(&bz, sizeof(bz));
- bz.bz_bufa = p->md.zbuf1;
- bz.bz_bufb = p->md.zbuf2;
- bz.bz_buflen = p->md.zbufsize;
+ memset(&bz, 0, sizeof(bz)); /* bzero() deprecated, replaced with memset() */
+ 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));
@@ -1680,7 +1726,7 @@
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
{
@@ -1992,8 +2038,8 @@
if (v == DLT_FDDI)
p->fddipad = PCAP_FDDIPAD;
else
+#endif
p->fddipad = 0;
-#endif
p->linktype = v;
#if defined(BIOCGHDRCMPLT) && defined(BIOCSHDRCMPLT)
@@ -2015,9 +2061,14 @@
#endif
/* set timeout */
#ifdef HAVE_ZEROCOPY_BPF
- if (p->md.timeout != 0 && !p->md.zerocopy) {
+ /*
+ * In zero-copy mode, we just use the timeout in select().
+ * XXX - what if we're in non-blocking mode and the *application*
+ * is using select() or poll() or kqueues or....?
+ */
+ if (p->opt.timeout && !pb->zerocopy) {
#else
- if (p->md.timeout) {
+ if (p->opt.timeout) {
#endif
/*
* XXX - is this seconds/nanoseconds in AIX?
@@ -2041,8 +2092,8 @@
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 = p->opt.timeout / 1000;
+ bpf_to.tv_usec = (p->opt.timeout * 1000) % 1000000;
if (ioctl(p->fd, BIOCSRTIMEOUT, (caddr_t)&bpf_to) < 0) {
snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
"BIOCSRTIMEOUT: %s", pcap_strerror(errno));
@@ -2051,8 +2102,8 @@
}
} else {
#endif
- to.tv_sec = p->md.timeout / 1000;
- to.tv_usec = (p->md.timeout * 1000) % 1000000;
+ to.tv_sec = p->opt.timeout / 1000;
+ to.tv_usec = (p->opt.timeout * 1000) % 1000000;
if (ioctl(p->fd, BIOCSRTIMEOUT, (caddr_t)&to) < 0) {
snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
"BIOCSRTIMEOUT: %s", pcap_strerror(errno));
@@ -2064,7 +2115,6 @@
#endif
}
-#ifdef _AIX
#ifdef BIOCIMMEDIATE
/*
* Darren Reed notes that
@@ -2076,51 +2126,38 @@
* is reducing things to only a few packets (i.e. one every
* second or so).
*
- * so we turn BIOCIMMEDIATE mode on if this is AIX.
+ * so we always turn BIOCIMMEDIATE mode on if this is AIX.
*
- * We don't turn it on for other platforms, as that means we
- * get woken up for every packet, which may not be what we want;
- * in the Winter 1993 USENIX paper on BPF, they say:
+ * For other platforms, we don't turn immediate mode on by default,
+ * as that would mean we get woken up for every packet, which
+ * probably isn't what you want for a packet sniffer.
*
- * Since a process might want to look at every packet on a
- * network and the time between packets can be only a few
- * microseconds, it is not possible to do a read system call
- * per packet and BPF must collect the data from several
- * packets and return it as a unit when the monitoring
- * application does a read.
- *
- * which I infer is the reason for the timeout - it means we
- * wait that amount of time, in the hopes that more packets
- * will arrive and we'll get them all with one read.
- *
- * Setting BIOCIMMEDIATE mode on FreeBSD (and probably other
- * BSDs) causes the timeout to be ignored.
- *
- * On the other hand, some platforms (e.g., Linux) don't support
- * timeouts, they just hand stuff to you as soon as it arrives;
- * if that doesn't cause a problem on those platforms, it may
- * be OK to have BIOCIMMEDIATE mode on BSD as well.
- *
- * (Note, though, that applications may depend on the read
- * completing, even if no packets have arrived, when the timeout
- * expires, e.g. GUI applications that have to check for input
- * while waiting for packets to arrive; a non-zero timeout
- * prevents "select()" from working right on FreeBSD and
- * possibly other BSDs, as the timer doesn't start until a
- * "read()" is done, so the timer isn't in effect if the
- * application is blocked on a "select()", and the "select()"
- * doesn't get woken up for a BPF device until the buffer
- * fills up.)
+ * We set immediate mode if the caller requested it by calling
+ * pcap_set_immediate() before calling pcap_activate().
*/
- v = 1;
- if (ioctl(p->fd, BIOCIMMEDIATE, &v) < 0) {
- snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "BIOCIMMEDIATE: %s",
- pcap_strerror(errno));
+#ifndef _AIX
+ if (p->opt.immediate) {
+#endif /* _AIX */
+ v = 1;
+ if (ioctl(p->fd, BIOCIMMEDIATE, &v) < 0) {
+ snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
+ "BIOCIMMEDIATE: %s", pcap_strerror(errno));
+ status = PCAP_ERROR;
+ goto bad;
+ }
+#ifndef _AIX
+ }
+#endif /* _AIX */
+#else /* BIOCIMMEDIATE */
+ if (p->opt.immediate) {
+ /*
+ * We don't support immediate mode. Fail.
+ */
+ snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "Immediate mode not supported");
status = PCAP_ERROR;
goto bad;
}
-#endif /* BIOCIMMEDIATE */
-#endif /* _AIX */
+#endif /* BIOCIMMEDIATE */
if (p->opt.promisc) {
/* set promiscuous mode, just warn if it fails */
@@ -2139,7 +2176,7 @@
}
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) {
@@ -2240,22 +2277,13 @@
return (status);
bad:
- pcap_cleanup_bpf(p);
+ pcap_cleanup_bpf(p);
return (status);
}
int
pcap_platform_finddevs(pcap_if_t **alldevsp, char *errbuf)
{
-#ifdef HAVE_DAG_API
- if (dag_platform_finddevs(alldevsp, errbuf) < 0)
- return (-1);
-#endif /* HAVE_DAG_API */
-#ifdef HAVE_SNF_API
- if (snf_platform_finddevs(alldevsp, errbuf) < 0)
- return (-1);
-#endif /* HAVE_SNF_API */
-
return (0);
}
@@ -2263,6 +2291,7 @@
static int
monitor_mode(pcap_t *p, int set)
{
+ struct pcap_bpf *pb = p->priv;
int sock;
struct ifmediareq req;
int *media_list;
@@ -2400,7 +2429,7 @@
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.
@@ -2577,6 +2606,8 @@
static int
pcap_setfilter_bpf(pcap_t *p, struct bpf_program *fp)
{
+ struct pcap_bpf *pb = p->priv;
+
/*
* Free any user-mode filter we might happen to have installed.
*/
@@ -2589,7 +2620,7 @@
/*
* 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
@@ -2629,7 +2660,7 @@
*/
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);
}
Index: libpcap/pcap-null.c
===================================================================
--- libpcap/pcap-null.c (revision 32783)
+++ libpcap/pcap-null.c (working copy)
@@ -40,7 +40,7 @@
static char nosup[] = "live packet capture not supported on this system";
pcap_t *
-pcap_create(const char *device, char *ebuf)
+pcap_create_interface(const char *device, char *ebuf)
{
(void)strlcpy(ebuf, nosup, PCAP_ERRBUF_SIZE);
return (NULL);
Index: libpcap/bpf_image.c
===================================================================
--- libpcap/bpf_image.c (revision 32783)
+++ libpcap/bpf_image.c (working copy)
@@ -292,11 +292,14 @@
break;
}
(void)snprintf(operand, sizeof operand, fmt, v);
- (void)snprintf(image, sizeof image,
- (BPF_CLASS(p->code) == BPF_JMP &&
- BPF_OP(p->code) != BPF_JA) ?
- "(%03d) %-8s %-16s jt %d\tjf %d"
- : "(%03d) %-8s %s",
- n, op, operand, n + 1 + p->jt, n + 1 + p->jf);
+ if (BPF_CLASS(p->code) == BPF_JMP && BPF_OP(p->code) != BPF_JA) {
+ (void)snprintf(image, sizeof image,
+ "(%03d) %-8s %-16s jt %d\tjf %d",
+ n, op, operand, n + 1 + p->jt, n + 1 + p->jf);
+ } else {
+ (void)snprintf(image, sizeof image,
+ "(%03d) %-8s %s",
+ n, op, operand);
+ }
return image;
}
Index: libpcap/README
===================================================================
--- libpcap/README (revision 32783)
+++ libpcap/README (working copy)
@@ -10,15 +10,15 @@
Anonymous Git is available via:
git clone git://bpf.tcpdump.org/libpcap
-Version 1.x.y of LIBPCAP can be retrieved with the CVS tag "libpcap_1_{x}rel{y}":
- cvs -d :pserver:tcpdump@cvs.tcpdump.org:/tcpdump/master checkout -r libpcap_1_{x}rel{y} libpcap
+Please submit patches by forking the branch on GitHub at
-Please submit patches against the master copy to the libpcap project on
-sourceforge.net.
+ http://github.com/the-tcpdump-group/libpcap/tree/master
+and issuing a pull request.
+
formerly from Lawrence Berkeley National Laboratory
Network Research Group <libpcap@ee.lbl.gov>
- ftp://ftp.ee.lbl.gov/libpcap.tar.Z (0.4)
+ ftp://ftp.ee.lbl.gov/old/libpcap-0.4a7.tar.Z
This directory contains source code for libpcap, a system-independent
interface for user-level packet capture. libpcap provides a portable
@@ -91,15 +91,18 @@
Problems, bugs, questions, desirable enhancements, etc. should be sent
to the address "tcpdump-workers@lists.tcpdump.org". Bugs, support
-requests, and feature requests may also be submitted on the SourceForge
-site for libpcap at
+requests, and feature requests may also be submitted on the GitHub issue
+tracker for libpcap at
- http://sourceforge.net/projects/libpcap/
+ https://github.com/the-tcpdump-group/libpcap/issues
Source code contributions, etc. should be sent to the email address
-submitted as patches on the SourceForge site for libpcap.
+above or submitted by forking the branch on GitHub at
-Current versions can be found at www.tcpdump.org, or the SourceForge
-site for libpcap.
+ http://github.com/the-tcpdump-group/libpcap/tree/master
+and issuing a pull request.
+
+Current versions can be found at www.tcpdump.org.
+
- The TCPdump team
Index: libpcap/pcap_datalink.3pcap.in
===================================================================
--- libpcap/pcap_datalink.3pcap.in (revision 32783)
+++ libpcap/pcap_datalink.3pcap.in (working copy)
@@ -37,5 +37,34 @@
returns the link-layer header type for the live capture or ``savefile''
specified by
.IR p .
+.PP
+It must not be called on a pcap descriptor created by
+.B pcap_create()
+that has not yet been activated by
+.BR pcap_activate() .
+.PP
+.I http://www.tcpdump.org/linktypes.html
+lists the values
+.B pcap_datalink()
+can return and describes the packet formats that
+correspond to those values.
+.PP
+Do
+.B NOT
+assume that the packets for a given capture or ``savefile`` will have
+any given link-layer header type, such as
+.B DLT_EN10MB
+for Ethernet. For example, the "any" device on Linux will have a
+link-layer header type of
+.B DLT_LINUX_SLL
+even if all devices on the system at the time the "any" device is opened
+have some other data link type, such as
+.B DLT_EN10MB
+for Ethernet.
+.SH RETURN VALUE
+.B pcap_datalink()
+returns the link-layer header type on success and
+.B PCAP_ERROR_NOT_ACTIVATED
+if called on a capture handle that has been created but not activated.
.SH SEE ALSO
pcap(3PCAP), pcap-linktype(@MAN_MISC_INFO@)
Index: libpcap/CHANGES
===================================================================
--- libpcap/CHANGES (revision 32783)
+++ libpcap/CHANGES (working copy)
@@ -1,3 +1,90 @@
+Wednesday December 18, 2013 guy@alum.mit.edu
+Summary for 1.5.3 libpcap release
+ Don't let packets that don't match the current filter get to the
+ application when TPACKET_V3 is used. (GitHub issue #331)
+ Fix handling of pcap_loop()/pcap_dispatch() with a packet count
+ of 0 on some platforms (including Linux with TPACKET_V3).
+ (GitHub issue #333)
+ Work around TPACKET_V3 deficiency that causes packets to be lost
+ when a timeout of 0 is specified. (GitHub issue #335)
+ Man page formatting fixes.
+
+Wednesday December 4, 2013 guy@alum.mit.edu
+Summary for 1.5.2 libpcap release
+ Fix libpcap to work when compiled with TPACKET_V3 support and
+ running on a kernel without TPACKET_V3 support. (GitHub
+ issue #329)
+
+Wednesday November 20, 2013 guy@alum.mit.edu
+Summary for 1.5.1 libpcap release
+ Report an error, rather than crashing, if an IPv6 address is
+ used for link-layer filtering. (Wireshark bug 9376)
+
+Wednesday October 30, 2013 guy@alum.mit.edu
+Summary for 1.5.0 libpcap release
+ TPACKET_V3 support added for Linux
+ Point users to the the-tcpdump-group repository on GitHub rather
+ than the mcr repository
+ Checks added for malloc()/realloc()/etc. failures
+ Fixed build on Solaris 11
+ Support filtering filtering E1 SS7 traffic on MTP2 layer Annex A
+ Use "ln -s" to link man pages by default
+ Add support for getting nanosecond-resolution time stamps when
+ capturing and reading capture files
+ Many changes to autoconf to deal better with non-GCC compilers
+ added many new DLT types
+
+Saturday April 6, 2013 guy@alum.mit.edu
+Summary for 1.4.0 libpcap release
+ Add netfilter/nfqueue interface.
+ If we don't have support for IPv6 address resolution, support,
+ in filter expressions, what IPv6 stuff we can.
+ Fix pcap-config to include -lpthread if canusb support is
+ present
+ Try to fix "pcap_parse not defined" problems when --without-flex
+ and --without-bison are used when you have Flex and Bison
+ Fix some issues with the pcap_loop man page.
+ Fix pcap_getnonblock() and pcap_setnonblock() to fill in the
+ supplied error message buffer
+ Fix typo that, it appeared, would cause pcap-libdlpi.c not to
+ compile (perhaps systems with libdlpi also have BPF and use
+ that instead)
+ Catch attempts to call pcap_compile() on a non-activated pcap_t
+ Fix crash on Linux with CAN-USB support without usbfs
+ Fix addition of VLAN tags for Linux cooked captures
+ Check for both EOPNOTSUPP and EINVAL after SIOCETHTOOL ioctl, so
+ that the driver can report either one if it doesn't support
+ SIOCETHTOOL
+ Add DLT_INFINIBAND and DLT_SCTP
+ Describe "proto XXX" and "protochain XXX" in the pcap-filter man
+ page
+ Handle either directories, or symlinks to directories, that
+ correspond to interfaces in /sys/class/net
+ Fix handling of VLAN tag insertion to check, on Linux 3.x
+ kernels, for VLAN tag valid flag
+ Clean up some man pages
+ Support libnl3 as well as libnl1 and libnl2 on Linux
+ Fix handling of Bluetooth devices on 3.x Linux kernels
+
+Friday March 30, 2012. mcr@sandelman.ca
+Summary for 1.3.0 libpcap release
+ Handle DLT_PFSYNC in {FreeBSD, other *BSD+Mac OS X, other}.
+ Linux: Don't fail if netfilter isn't enabled in the kernel.
+ Add new link-layer type for NFC Forum LLCP.
+ Put the CANUSB stuff into EXTRA_DIST, so it shows up in the release tarball.
+ Add LINKTYPE_NG40/DLT_NG40.
+ Add DLT_MPEG_2_TS/LINKTYPE_MPEG_2_TS for MPEG-2 transport streams.
+ [PATCH] Fix AIX-3.5 crash with read failure during stress
+ AIX fixes.
+ Introduce --disable-shared configure option.
+ Added initial support for canusb devices.
+ Include the pcap(3PCAP) additions as 1.2.1 changes.
+ many updates to documentation: pcap.3pcap.in
+ Improve 'inbound'/'outbound' capture filters under Linux.
+ Note the cleanup of handling of new DLT_/LINKTYPE_ values.
+ On Lion, don't build for PPC.
+ For mac80211 devices we need to clean up monitor mode on exit.
+
Friday December 9, 2011. guy@alum.mit.edu.
Summary for 1.2.1 libpcap release
Update README file.
Index: libpcap/fad-win32.c
===================================================================
--- libpcap/fad-win32.c (revision 32783)
+++ libpcap/fad-win32.c (working copy)
@@ -216,7 +216,7 @@
* Win32 implementation, based on WinPcap
*/
int
-pcap_findalldevs(pcap_if_t **alldevsp, char *errbuf)
+pcap_findalldevs_interfaces(pcap_if_t **alldevsp, char *errbuf)
{
pcap_if_t *devlist = NULL;
int ret = 0;
@@ -225,6 +225,24 @@
ULONG NameLength;
char *name;
+ /*
+ * Find out how big a buffer we need.
+ *
+ * This call should always return FALSE; if the error is
+ * ERROR_INSUFFICIENT_BUFFER, NameLength will be set to
+ * the size of the buffer we need, otherwise there's a
+ * problem, and NameLength should be set to 0.
+ *
+ * It shouldn't require NameLength to be set, but,
+ * at least as of WinPcap 4.1.3, it checks whether
+ * NameLength is big enough before it checks for a
+ * NULL buffer argument, so, while it'll still do
+ * the right thing if NameLength is uninitialized and
+ * whatever junk happens to be there is big enough
+ * (because the pointer argument will be null), it's
+ * still reading an uninitialized variable.
+ */
+ NameLength = 0;
if (!PacketGetAdapterNames(NULL, &NameLength))
{
DWORD last_error = GetLastError();
Index: libpcap/gencode.c
===================================================================
--- libpcap/gencode.c (revision 32783)
+++ libpcap/gencode.c (working copy)
@@ -84,6 +84,11 @@
#include "pcap/sll.h"
#include "pcap/ipnet.h"
#include "arcnet.h"
+#if defined(linux) && defined(PF_PACKET) && defined(SO_ATTACH_FILTER)
+#include <linux/types.h>
+#include <linux/if_packet.h>
+#include <linux/filter.h>
+#endif
#ifdef HAVE_NET_PFVAR_H
#include <sys/socket.h>
#include <net/if.h>
@@ -102,6 +107,18 @@
#define ETHERMTU 1500
+#ifndef IPPROTO_HOPOPTS
+#define IPPROTO_HOPOPTS 0
+#endif
+#ifndef IPPROTO_ROUTING
+#define IPPROTO_ROUTING 43
+#endif
+#ifndef IPPROTO_FRAGMENT
+#define IPPROTO_FRAGMENT 44
+#endif
+#ifndef IPPROTO_DSTOPTS
+#define IPPROTO_DSTOPTS 60
+#endif
#ifndef IPPROTO_SCTP
#define IPPROTO_SCTP 132
#endif
@@ -124,9 +141,7 @@
#endif
/* XXX */
-#ifdef PCAP_FDDIPAD
static int pcap_fddipad;
-#endif
/* VARARGS */
void
@@ -256,20 +271,16 @@
static struct block *gen_ipfrag(void);
static struct block *gen_portatom(int, bpf_int32);
static struct block *gen_portrangeatom(int, bpf_int32, bpf_int32);
-#ifdef INET6
static struct block *gen_portatom6(int, bpf_int32);
static struct block *gen_portrangeatom6(int, bpf_int32, bpf_int32);
-#endif
struct block *gen_portop(int, int, int);
static struct block *gen_port(int, int, int);
struct block *gen_portrangeop(int, int, int, int);
static struct block *gen_portrange(int, int, int, int);
-#ifdef INET6
struct block *gen_portop6(int, int, int);
static struct block *gen_port6(int, int, int);
struct block *gen_portrangeop6(int, int, int, int);
static struct block *gen_portrange6(int, int, int, int);
-#endif
static int lookup_proto(const char *, int);
static struct block *gen_protochain(int, int, int);
static struct block *gen_proto(int, int, int);
@@ -418,8 +429,17 @@
{
extern int n_errors;
const char * volatile xbuf = buf;
- int len;
+ u_int len;
+ /*
+ * If this pcap_t hasn't been activated, it doesn't have a
+ * link-layer type, so we can't use it.
+ */
+ if (!p->activated) {
+ snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
+ "not-yet-activated pcap_t passed to pcap_compile");
+ return (-1);
+ }
no_optimize = 0;
n_errors = 0;
root = NULL;
@@ -854,6 +874,7 @@
* These are offsets for the MTP2 fields.
*/
static u_int off_li;
+static u_int off_li_hsl;
/*
* These are offsets for the MTP3 fields.
@@ -903,9 +924,7 @@
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.
@@ -927,6 +946,7 @@
* And assume we're not doing SS7.
*/
off_li = -1;
+ off_li_hsl = -1;
off_sio = -1;
off_opc = -1;
off_dpc = -1;
@@ -1042,13 +1062,9 @@
* 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;
@@ -1319,6 +1335,13 @@
off_nl_nosnap = -1; /* no 802.2 LLC */
return;
+ case DLT_BACNET_MS_TP:
+ off_linktype = -1;
+ off_macpl = -1;
+ off_nl = -1;
+ off_nl_nosnap = -1;
+ return;
+
case DLT_JUNIPER_SERVICES:
off_linktype = 12;
off_macpl = -1; /* L3 proto location dep. on cookie type */
@@ -1359,6 +1382,7 @@
case DLT_MTP2:
off_li = 2;
+ off_li_hsl = 4;
off_sio = 3;
off_opc = 4;
off_dpc = 4;
@@ -1371,6 +1395,7 @@
case DLT_MTP2_WITH_PHDR:
off_li = 6;
+ off_li_hsl = 8;
off_sio = 7;
off_opc = 8;
off_dpc = 8;
@@ -1383,6 +1408,7 @@
case DLT_ERF:
off_li = 22;
+ off_li_hsl = 24;
off_sio = 23;
off_opc = 24;
off_dpc = 24;
@@ -1393,14 +1419,12 @@
off_nl_nosnap = -1;
return;
-#ifdef DLT_PFSYNC
case DLT_PFSYNC:
off_linktype = -1;
off_macpl = 4;
off_nl = 0;
off_nl_nosnap = 0;
return;
-#endif
case DLT_AX25_KISS:
/*
@@ -2829,11 +2853,9 @@
proto = PPP_IP;
break;
-#ifdef INET6
case ETHERTYPE_IPV6:
proto = PPP_IPV6;
break;
-#endif
case ETHERTYPE_DN:
proto = PPP_DECNET;
@@ -3041,11 +3063,10 @@
case ETHERTYPE_IP:
/* Check for a version number of 4. */
return gen_mcmp(OR_LINK, 0, BPF_B, 0x40, 0xF0);
-#ifdef INET6
+
case ETHERTYPE_IPV6:
/* Check for a version number of 6. */
return gen_mcmp(OR_LINK, 0, BPF_B, 0x60, 0xF0);
-#endif
default:
return gen_false(); /* always false */
@@ -3069,10 +3090,8 @@
/*
* Raw IPv6, so no type field.
*/
-#ifdef INET6
if (proto == ETHERTYPE_IPV6)
return gen_true(); /* always true */
-#endif
/* Checking for something other than IPv6; always false */
return gen_false();
@@ -3178,8 +3197,7 @@
* 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);
}
@@ -3194,11 +3212,9 @@
if (proto == ETHERTYPE_IP)
return (gen_cmp(OR_LINK, offsetof(struct pfloghdr, af),
BPF_B, (bpf_int32)AF_INET));
-#ifdef INET6
else if (proto == ETHERTYPE_IPV6)
return (gen_cmp(OR_LINK, offsetof(struct pfloghdr, af),
BPF_B, (bpf_int32)AF_INET6));
-#endif /* INET6 */
else
return gen_false();
/*NOTREACHED*/
@@ -3216,11 +3232,9 @@
default:
return gen_false();
-#ifdef INET6
case ETHERTYPE_IPV6:
return (gen_cmp(OR_LINK, off_linktype, BPF_B,
(bpf_int32)ARCTYPE_INET6));
-#endif /* INET6 */
case ETHERTYPE_IP:
b0 = gen_cmp(OR_LINK, off_linktype, BPF_B,
@@ -3272,13 +3286,11 @@
*/
return gen_cmp(OR_LINK, 2, BPF_H, (0x03<<8) | 0xcc);
-#ifdef INET6
case ETHERTYPE_IPV6:
/*
* Check for the special NLPID for IPv6.
*/
return gen_cmp(OR_LINK, 2, BPF_H, (0x03<<8) | 0x8e);
-#endif
case LLCSAP_ISONS:
/*
@@ -3340,6 +3352,9 @@
*/
return gen_mcmp(OR_LINK, 0, BPF_W, 0x4d474300, 0xffffff00); /* compare the magic number */
+ case DLT_BACNET_MS_TP:
+ return gen_mcmp(OR_LINK, 0, BPF_W, 0x55FF0000, 0xffff0000);
+
case DLT_IPNET:
return gen_ipnet_linktype(proto);
@@ -3356,10 +3371,8 @@
case DLT_ERF:
bpf_error("ERF link-layer type filtering not implemented");
-#ifdef DLT_PFSYNC
case DLT_PFSYNC:
bpf_error("PFSYNC link-layer type filtering not implemented");
-#endif
case DLT_LINUX_LAPD:
bpf_error("LAPD link-layer type filtering not implemented");
@@ -3627,7 +3640,7 @@
gen_and(b0, b1);
return b1;
}
-#endif /*INET6*/
+#endif
static struct block *
gen_ehostop(eaddr, dir)
@@ -3696,18 +3709,10 @@
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);
@@ -4505,13 +4510,11 @@
case Q_MOPRC:
bpf_error("MOPRC host filtering not implemented");
-#ifdef INET6
case Q_IPV6:
bpf_error("'ip6' modifier applied to ip host");
case Q_ICMPV6:
bpf_error("'icmp6' modifier applied to %s", typestr);
-#endif /* INET6 */
case Q_AH:
bpf_error("'ah' modifier applied to %s", typestr);
@@ -4570,6 +4573,9 @@
case Q_DEFAULT:
return gen_host6(addr, mask, Q_IPV6, dir, type);
+ case Q_LINK:
+ bpf_error("link-layer modifier applied to ip6 %s", typestr);
+
case Q_IP:
bpf_error("'ip' modifier applied to ip6 %s", typestr);
@@ -4668,7 +4674,7 @@
}
/* NOTREACHED */
}
-#endif /*INET6*/
+#endif
#ifndef INET6
static struct block *
@@ -4760,26 +4766,20 @@
case Q_SCTP:
b1 = gen_proto(IPPROTO_SCTP, Q_IP, Q_DEFAULT);
-#ifdef INET6
b0 = gen_proto(IPPROTO_SCTP, Q_IPV6, Q_DEFAULT);
gen_or(b0, b1);
-#endif
break;
case Q_TCP:
b1 = gen_proto(IPPROTO_TCP, Q_IP, Q_DEFAULT);
-#ifdef INET6
b0 = gen_proto(IPPROTO_TCP, Q_IPV6, Q_DEFAULT);
gen_or(b0, b1);
-#endif
break;
case Q_UDP:
b1 = gen_proto(IPPROTO_UDP, Q_IP, Q_DEFAULT);
-#ifdef INET6
b0 = gen_proto(IPPROTO_UDP, Q_IPV6, Q_DEFAULT);
gen_or(b0, b1);
-#endif
break;
case Q_ICMP:
@@ -4807,10 +4807,8 @@
case Q_PIM:
b1 = gen_proto(IPPROTO_PIM, Q_IP, Q_DEFAULT);
-#ifdef INET6
b0 = gen_proto(IPPROTO_PIM, Q_IPV6, Q_DEFAULT);
gen_or(b0, b1);
-#endif
break;
#ifndef IPPROTO_VRRP
@@ -4872,7 +4870,6 @@
b1 = gen_linktype(ETHERTYPE_MOPRC);
break;
-#ifdef INET6
case Q_IPV6:
b1 = gen_linktype(ETHERTYPE_IPV6);
break;
@@ -4883,17 +4880,14 @@
case Q_ICMPV6:
b1 = gen_proto(IPPROTO_ICMPV6, Q_IPV6, Q_DEFAULT);
break;
-#endif /* INET6 */
#ifndef IPPROTO_AH
#define IPPROTO_AH 51
#endif
case Q_AH:
b1 = gen_proto(IPPROTO_AH, Q_IP, Q_DEFAULT);
-#ifdef INET6
b0 = gen_proto(IPPROTO_AH, Q_IPV6, Q_DEFAULT);
gen_or(b0, b1);
-#endif
break;
#ifndef IPPROTO_ESP
@@ -4901,10 +4895,8 @@
#endif
case Q_ESP:
b1 = gen_proto(IPPROTO_ESP, Q_IP, Q_DEFAULT);
-#ifdef INET6
b0 = gen_proto(IPPROTO_ESP, Q_IPV6, Q_DEFAULT);
gen_or(b0, b1);
-#endif
break;
case Q_ISO:
@@ -5037,7 +5029,6 @@
return gen_cmp(OR_TRAN_IPV4, off, BPF_H, v);
}
-#ifdef INET6
static struct block *
gen_portatom6(off, v)
int off;
@@ -5045,7 +5036,6 @@
{
return gen_cmp(OR_TRAN_IPV6, off, BPF_H, v);
}
-#endif/*INET6*/
struct block *
gen_portop(port, proto, dir)
@@ -5137,7 +5127,6 @@
return b1;
}
-#ifdef INET6
struct block *
gen_portop6(port, proto, dir)
int port, proto, dir;
@@ -5210,7 +5199,6 @@
gen_and(b0, b1);
return b1;
}
-#endif /* INET6 */
/* gen_portrange code */
static struct block *
@@ -5315,7 +5303,6 @@
return b1;
}
-#ifdef INET6
static struct block *
gen_portrangeatom6(off, v1, v2)
int off;
@@ -5416,7 +5403,6 @@
gen_and(b0, b1);
return b1;
}
-#endif /* INET6 */
static int
lookup_proto(name, proto)
@@ -5551,7 +5537,7 @@
s[i]->s.k = off_macpl + off_nl;
i++;
break;
-#ifdef INET6
+
case Q_IPV6:
b0 = gen_linktype(ETHERTYPE_IPV6);
@@ -5564,7 +5550,7 @@
s[i]->s.k = 40;
i++;
break;
-#endif
+
default:
bpf_error("unsupported proto to gen_protochain");
/*NOTREACHED*/
@@ -5591,7 +5577,6 @@
fix2 = i;
i++;
-#ifdef INET6
if (proto == Q_IPV6) {
int v6start, v6end, v6advance, j;
@@ -5673,9 +5658,7 @@
/* fixup */
for (j = v6start; j <= v6end; j++)
s[j]->s.jt = s[v6advance];
- } else
-#endif
- {
+ } else {
/* nop */
s[i] = new_stmt(BPF_ALU|BPF_ADD|BPF_K);
s[i]->s.k = 0;
@@ -5819,20 +5802,20 @@
int dir;
{
struct block *b0, *b1;
+#ifndef CHASE_CHAIN
+ struct block *b2;
+#endif
if (dir != Q_DEFAULT)
bpf_error("direction applied to 'proto'");
switch (proto) {
case Q_DEFAULT:
-#ifdef INET6
b0 = gen_proto(v, Q_IP, dir);
b1 = gen_proto(v, Q_IPV6, dir);
gen_or(b0, b1);
return b1;
-#else
- /*FALLTHROUGH*/
-#endif
+
case Q_IP:
/*
* For FDDI, RFC 1188 says that SNAP encapsulation is used,
@@ -5983,11 +5966,18 @@
bpf_error("'carp proto' is bogus");
/* NOTREACHED */
-#ifdef INET6
case Q_IPV6:
b0 = gen_linktype(ETHERTYPE_IPV6);
#ifndef CHASE_CHAIN
- b1 = gen_cmp(OR_NET, 6, BPF_B, (bpf_int32)v);
+ /*
+ * Also check for a fragment header before the final
+ * header.
+ */
+ b2 = gen_cmp(OR_NET, 6, BPF_B, IPPROTO_FRAGMENT);
+ b1 = gen_cmp(OR_NET, 40, BPF_B, (bpf_int32)v);
+ gen_and(b2, b1);
+ b2 = gen_cmp(OR_NET, 6, BPF_B, (bpf_int32)v);
+ gen_or(b2, b1);
#else
b1 = gen_protochain(v, Q_IPV6);
#endif
@@ -5996,7 +5986,6 @@
case Q_ICMPV6:
bpf_error("'icmp6 proto' is bogus");
-#endif /* INET6 */
case Q_AH:
bpf_error("'ah proto' is bogus");
@@ -6253,13 +6242,9 @@
bpf_error("illegal port number %d < 0", port);
if (port > 65535)
bpf_error("illegal port number %d > 65535", port);
-#ifndef INET6
- return gen_port(port, real_proto, dir);
-#else
b = gen_port(port, real_proto, dir);
gen_or(gen_port6(port, real_proto, dir), b);
return b;
-#endif /* INET6 */
case Q_PORTRANGE:
if (proto != Q_DEFAULT &&
@@ -6303,13 +6288,9 @@
if (port2 > 65535)
bpf_error("illegal port number %d > 65535", port2);
-#ifndef INET6
- return gen_portrange(port1, port2, real_proto, dir);
-#else
b = gen_portrange(port1, port2, real_proto, dir);
gen_or(gen_portrange6(port1, port2, real_proto, dir), b);
return b;
-#endif /* INET6 */
case Q_GATEWAY:
#ifndef INET6
@@ -6457,16 +6438,12 @@
if (v > 65535)
bpf_error("illegal port number %u > 65535", v);
-#ifndef INET6
- return gen_port((int)v, proto, dir);
-#else
{
struct block *b;
b = gen_port((int)v, proto, dir);
gen_or(gen_port6((int)v, proto, dir), b);
return b;
}
-#endif /* INET6 */
case Q_PORTRANGE:
if (proto == Q_UDP)
@@ -6483,16 +6460,12 @@
if (v > 65535)
bpf_error("illegal port number %u > 65535", v);
-#ifndef INET6
- return gen_portrange((int)v, (int)v, proto, dir);
-#else
{
struct block *b;
b = gen_portrange((int)v, (int)v, proto, dir);
gen_or(gen_portrange6((int)v, (int)v, proto, dir), b);
return b;
}
-#endif /* INET6 */
case Q_GATEWAY:
bpf_error("'gateway' requires a name");
@@ -6782,9 +6755,7 @@
case Q_LAT:
case Q_MOPRC:
case Q_MOPDL:
-#ifdef INET6
case Q_IPV6:
-#endif
/*
* The offset is relative to the beginning of
* the network-layer header.
@@ -6893,16 +6864,12 @@
gen_and(gen_proto_abbrev(proto), b = gen_ipfrag());
if (inst->b)
gen_and(inst->b, b);
-#ifdef INET6
gen_and(gen_proto_abbrev(Q_IP), b);
-#endif
inst->b = b;
break;
-#ifdef INET6
case Q_ICMPV6:
bpf_error("IPv6 upper-layer protocol is not supported by proto[x]");
/*NOTREACHED*/
-#endif
}
inst->regno = regno;
s = new_stmt(BPF_ST);
@@ -7454,13 +7421,11 @@
gen_and(b0, b1);
return b1;
-#ifdef INET6
case Q_IPV6:
b0 = gen_linktype(ETHERTYPE_IPV6);
b1 = gen_cmp(OR_NET, 24, BPF_B, (bpf_int32)255);
gen_and(b0, b1);
return b1;
-#endif /* INET6 */
}
bpf_error("link-layer multicast filters supported only on ethernet/FDDI/token ring/ARCNET/802.11/ATM LANE/Fibre Channel");
/* NOTREACHED */
@@ -7468,9 +7433,13 @@
}
/*
- * generate command for inbound/outbound. It's here so we can
- * make it link-type specific. 'dir' = 0 implies "inbound",
- * = 1 implies "outbound".
+ * Filter on inbound (dir == 0) or outbound (dir == 1) traffic.
+ * Outbound traffic is sent by this machine, while inbound traffic is
+ * sent by a remote machine (and may include packets destined for a
+ * unicast or multicast link-layer address we are not subscribing to).
+ * These are the same definitions implemented by pcap_setdirection().
+ * Capturing only unicast traffic destined for this host is probably
+ * better accomplished using a higher-layer filter.
*/
struct block *
gen_inbound(dir)
@@ -7500,23 +7469,11 @@
break;
case DLT_LINUX_SLL:
- if (dir) {
- /*
- * Match packets sent by this machine.
- */
- b0 = gen_cmp(OR_LINK, 0, BPF_H, LINUX_SLL_OUTGOING);
- } else {
- /*
- * Match packets sent to this machine.
- * (No broadcast or multicast packets, or
- * packets sent to some other machine and
- * received promiscuously.)
- *
- * XXX - packets sent to other machines probably
- * shouldn't be matched, but what about broadcast
- * or multicast packets we received?
- */
- b0 = gen_cmp(OR_LINK, 0, BPF_H, LINUX_SLL_HOST);
+ /* match outgoing packets */
+ b0 = gen_cmp(OR_LINK, 0, BPF_H, LINUX_SLL_OUTGOING);
+ if (!dir) {
+ /* to filter on inbound traffic, invert the match */
+ gen_not(b0);
}
break;
@@ -7572,10 +7529,38 @@
break;
default:
+ /*
+ * If we have packet meta-data indicating a direction,
+ * check it, otherwise give up as this link-layer type
+ * has nothing in the packet data.
+ */