aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--contrib/libpcap/CHANGES83
-rw-r--r--contrib/libpcap/CREDITS7
-rw-r--r--contrib/libpcap/INSTALL.txt68
-rw-r--r--contrib/libpcap/LICENSE6
-rw-r--r--contrib/libpcap/Makefile-devel-adds4
-rw-r--r--contrib/libpcap/Makefile.in182
-rw-r--r--contrib/libpcap/README10
-rw-r--r--contrib/libpcap/TODO10
-rw-r--r--contrib/libpcap/VERSION2
-rw-r--r--contrib/libpcap/bpf/net/bpf_filter.c120
-rw-r--r--contrib/libpcap/bpf_dump.c5
-rw-r--r--contrib/libpcap/bpf_image.c12
-rwxr-xr-xcontrib/libpcap/config.guess373
-rw-r--r--contrib/libpcap/config.h.in43
-rwxr-xr-xcontrib/libpcap/config.sub128
-rw-r--r--contrib/libpcap/config/have_siocglifconf.c6
-rwxr-xr-xcontrib/libpcap/configure1558
-rw-r--r--contrib/libpcap/configure.ac (renamed from contrib/libpcap/configure.in)849
-rw-r--r--contrib/libpcap/dlpisubs.c31
-rw-r--r--contrib/libpcap/etherent.c6
-rw-r--r--contrib/libpcap/ethertype.h3
-rw-r--r--contrib/libpcap/extract.h221
-rw-r--r--contrib/libpcap/fad-getad.c76
-rw-r--r--contrib/libpcap/fad-gifc.c49
-rw-r--r--contrib/libpcap/fad-glifc.c60
-rw-r--r--contrib/libpcap/fad-helpers.c884
-rw-r--r--contrib/libpcap/fad-sita.c59
-rwxr-xr-xcontrib/libpcap/gen_version_c.sh11
-rwxr-xr-xcontrib/libpcap/gen_version_header.sh19
-rw-r--r--contrib/libpcap/gencode.c5537
-rw-r--r--contrib/libpcap/gencode.h158
-rw-r--r--contrib/libpcap/grammar.y249
-rw-r--r--contrib/libpcap/inet.c883
-rwxr-xr-xcontrib/libpcap/install-sh14
-rw-r--r--contrib/libpcap/lbl/os-aix7.h23
-rw-r--r--contrib/libpcap/lbl/os-osf4.h6
-rw-r--r--contrib/libpcap/lbl/os-osf5.h8
-rw-r--r--contrib/libpcap/lbl/os-solaris2.h2
-rw-r--r--contrib/libpcap/lbl/os-sunos4.h4
-rw-r--r--contrib/libpcap/lbl/os-ultrix4.h1
-rw-r--r--contrib/libpcap/missing/getopt.c126
-rw-r--r--contrib/libpcap/missing/getopt.h7
-rw-r--r--contrib/libpcap/missing/snprintf.c20
-rw-r--r--contrib/libpcap/missing/strtok_r.c87
-rw-r--r--contrib/libpcap/missing/win_snprintf.c31
-rwxr-xr-xcontrib/libpcap/mkdep3
-rw-r--r--contrib/libpcap/nametoaddr.c73
-rw-r--r--contrib/libpcap/nametoaddr.h48
-rw-r--r--contrib/libpcap/optimize.c861
-rw-r--r--contrib/libpcap/pcap-bpf.c582
-rw-r--r--contrib/libpcap/pcap-bpf.h2
-rw-r--r--contrib/libpcap/pcap-bt-linux.c106
-rw-r--r--contrib/libpcap/pcap-bt-linux.h4
-rw-r--r--contrib/libpcap/pcap-bt-monitor-linux.c51
-rw-r--r--contrib/libpcap/pcap-can-linux.c319
-rw-r--r--contrib/libpcap/pcap-can-linux.h36
-rw-r--r--contrib/libpcap/pcap-canusb-linux.c472
-rw-r--r--contrib/libpcap/pcap-common.c192
-rw-r--r--contrib/libpcap/pcap-config.12
-rw-r--r--contrib/libpcap/pcap-dag.c366
-rw-r--r--contrib/libpcap/pcap-dag.h94
-rw-r--r--contrib/libpcap/pcap-dbus.c38
-rw-r--r--contrib/libpcap/pcap-dlpi.c370
-rw-r--r--contrib/libpcap/pcap-dos.c136
-rw-r--r--contrib/libpcap/pcap-dos.h2
-rw-r--r--contrib/libpcap/pcap-filter.manmisc.in31
-rw-r--r--contrib/libpcap/pcap-int.h132
-rw-r--r--contrib/libpcap/pcap-libdlpi.c39
-rw-r--r--contrib/libpcap/pcap-linktype.manmisc.in2
-rw-r--r--contrib/libpcap/pcap-linux.c1571
-rw-r--r--contrib/libpcap/pcap-netfilter-linux.c108
-rw-r--r--contrib/libpcap/pcap-netfilter-linux.h4
-rw-r--r--contrib/libpcap/pcap-new.c1265
-rw-r--r--contrib/libpcap/pcap-nit.c43
-rw-r--r--contrib/libpcap/pcap-null.c6
-rw-r--r--contrib/libpcap/pcap-pf.c59
-rw-r--r--contrib/libpcap/pcap-rpcap.c2127
-rw-r--r--contrib/libpcap/pcap-rpcap.h465
-rw-r--r--contrib/libpcap/pcap-savefile.manfile.in4
-rw-r--r--contrib/libpcap/pcap-septel.c40
-rw-r--r--contrib/libpcap/pcap-sita.c88
-rw-r--r--contrib/libpcap/pcap-snf.c249
-rw-r--r--contrib/libpcap/pcap-snit.c53
-rw-r--r--contrib/libpcap/pcap-snoop.c93
-rw-r--r--contrib/libpcap/pcap-stdinc.h95
-rw-r--r--contrib/libpcap/pcap-tc.c1284
-rw-r--r--contrib/libpcap/pcap-tc.h (renamed from contrib/libpcap/pcap-canusb-linux.h)31
-rw-r--r--contrib/libpcap/pcap-tstamp.manmisc.in51
-rw-r--r--contrib/libpcap/pcap-usb-linux.c194
-rw-r--r--contrib/libpcap/pcap-usb-linux.h4
-rw-r--r--contrib/libpcap/pcap-win32.c1023
-rw-r--r--contrib/libpcap/pcap.3pcap.in44
-rw-r--r--contrib/libpcap/pcap.c977
-rw-r--r--contrib/libpcap/pcap/bluetooth.h10
-rw-r--r--contrib/libpcap/pcap/bpf.h1257
-rw-r--r--contrib/libpcap/pcap/can_socketcan.h54
-rw-r--r--contrib/libpcap/pcap/dlt.h1340
-rw-r--r--contrib/libpcap/pcap/export-defs.h108
-rw-r--r--contrib/libpcap/pcap/namedb.h32
-rw-r--r--contrib/libpcap/pcap/nflog.h4
-rw-r--r--contrib/libpcap/pcap/pcap.h302
-rw-r--r--contrib/libpcap/pcap/sll.h2
-rw-r--r--contrib/libpcap/pcap/usb.h12
-rw-r--r--contrib/libpcap/pcap_activate.3pcap73
-rw-r--r--contrib/libpcap/pcap_breakloop.3pcap4
-rw-r--r--contrib/libpcap/pcap_can_set_rfmon.3pcap34
-rw-r--r--contrib/libpcap/pcap_close.3pcap2
-rw-r--r--contrib/libpcap/pcap_compile.3pcap.in2
-rw-r--r--contrib/libpcap/pcap_create.3pcap2
-rw-r--r--contrib/libpcap/pcap_datalink.3pcap.in2
-rw-r--r--contrib/libpcap/pcap_datalink_name_to_val.3pcap5
-rw-r--r--contrib/libpcap/pcap_datalink_val_to_name.3pcap16
-rw-r--r--contrib/libpcap/pcap_dump.3pcap6
-rw-r--r--contrib/libpcap/pcap_dump_close.3pcap2
-rw-r--r--contrib/libpcap/pcap_dump_file.3pcap2
-rw-r--r--contrib/libpcap/pcap_dump_flush.3pcap2
-rw-r--r--contrib/libpcap/pcap_dump_ftell.3pcap2
-rw-r--r--contrib/libpcap/pcap_dump_open.3pcap.in15
-rw-r--r--contrib/libpcap/pcap_file.3pcap2
-rw-r--r--contrib/libpcap/pcap_fileno.3pcap2
-rw-r--r--contrib/libpcap/pcap_findalldevs.3pcap2
-rw-r--r--contrib/libpcap/pcap_freecode.3pcap2
-rw-r--r--contrib/libpcap/pcap_get_selectable_fd.3pcap14
-rw-r--r--contrib/libpcap/pcap_get_tstamp_precision.3pcap.in2
-rw-r--r--contrib/libpcap/pcap_geterr.3pcap4
-rw-r--r--contrib/libpcap/pcap_inject.3pcap2
-rw-r--r--contrib/libpcap/pcap_is_swapped.3pcap2
-rw-r--r--contrib/libpcap/pcap_lib_version.3pcap2
-rw-r--r--contrib/libpcap/pcap_list_datalinks.3pcap.in4
-rw-r--r--contrib/libpcap/pcap_list_tstamp_types.3pcap.in2
-rw-r--r--contrib/libpcap/pcap_lookupdev.3pcap2
-rw-r--r--contrib/libpcap/pcap_lookupnet.3pcap2
-rw-r--r--contrib/libpcap/pcap_loop.3pcap9
-rw-r--r--contrib/libpcap/pcap_major_version.3pcap2
-rw-r--r--contrib/libpcap/pcap_next_ex.3pcap2
-rw-r--r--contrib/libpcap/pcap_offline_filter.3pcap2
-rw-r--r--contrib/libpcap/pcap_open_dead.3pcap.in2
-rw-r--r--contrib/libpcap/pcap_open_live.3pcap2
-rw-r--r--contrib/libpcap/pcap_open_offline.3pcap.in2
-rw-r--r--contrib/libpcap/pcap_set_buffer_size.3pcap2
-rw-r--r--contrib/libpcap/pcap_set_datalink.3pcap2
-rw-r--r--contrib/libpcap/pcap_set_immediate_mode.3pcap2
-rw-r--r--contrib/libpcap/pcap_set_promisc.3pcap2
-rw-r--r--contrib/libpcap/pcap_set_rfmon.3pcap2
-rw-r--r--contrib/libpcap/pcap_set_snaplen.3pcap2
-rw-r--r--contrib/libpcap/pcap_set_timeout.3pcap9
-rw-r--r--contrib/libpcap/pcap_set_tstamp_precision.3pcap.in4
-rw-r--r--contrib/libpcap/pcap_set_tstamp_type.3pcap.in4
-rw-r--r--contrib/libpcap/pcap_setdirection.3pcap4
-rw-r--r--contrib/libpcap/pcap_setfilter.3pcap2
-rw-r--r--contrib/libpcap/pcap_setnonblock.3pcap10
-rw-r--r--contrib/libpcap/pcap_snapshot.3pcap2
-rw-r--r--contrib/libpcap/pcap_stats.3pcap2
-rw-r--r--contrib/libpcap/pcap_statustostr.3pcap2
-rw-r--r--contrib/libpcap/pcap_strerror.3pcap2
-rw-r--r--contrib/libpcap/pcap_tstamp_type_name_to_val.3pcap4
-rw-r--r--contrib/libpcap/pcap_tstamp_type_val_to_name.3pcap2
-rw-r--r--contrib/libpcap/pcap_version.h.in13
-rw-r--r--contrib/libpcap/portability.h216
-rw-r--r--contrib/libpcap/remote-ext.h467
-rwxr-xr-xcontrib/libpcap/runlex.sh233
-rw-r--r--contrib/libpcap/savefile.c179
-rw-r--r--contrib/libpcap/scanner.l251
-rw-r--r--contrib/libpcap/sf-pcap-ng.c405
-rw-r--r--contrib/libpcap/sf-pcap.c328
-rw-r--r--contrib/libpcap/sockutils.c1230
-rw-r--r--contrib/libpcap/sockutils.h241
-rw-r--r--contrib/libpcap/tests/can_set_rfmon_test.c92
-rw-r--r--contrib/libpcap/tests/capturetest.c67
-rw-r--r--contrib/libpcap/tests/filtertest.c115
-rw-r--r--contrib/libpcap/tests/findalldevstest.c56
-rw-r--r--contrib/libpcap/tests/opentest.c77
-rw-r--r--contrib/libpcap/tests/reactivatetest.c2
-rw-r--r--contrib/libpcap/tests/selpolltest.c73
-rw-r--r--contrib/libpcap/tests/valgrindtest.c90
-rw-r--r--lib/libpcap/Makefile17
-rw-r--r--lib/libpcap/config.h43
-rw-r--r--lib/libpcap/pcap-netmap.c8
-rw-r--r--sbin/pflogd/Makefile1
-rw-r--r--sys/net/bpf.h1052
-rw-r--r--sys/net/dlt.h1342
-rw-r--r--usr.sbin/ipfwpcap/Makefile1
182 files changed, 24279 insertions, 11614 deletions
diff --git a/contrib/libpcap/CHANGES b/contrib/libpcap/CHANGES
index eb73e28d77f0..178409659305 100644
--- a/contrib/libpcap/CHANGES
+++ b/contrib/libpcap/CHANGES
@@ -1,5 +1,80 @@
+Tuesday, Oct. 25, 2016 mcr@sandelman.ca
+ Summary for 1.8.1 libpcap release
+ Add a target in Makefile.in for Exuberant Ctags use: 'extags'.
+ Rename configure.in to configure.ac: autoconf 2.59
+ Clean up the name-to-DLT mapping table.
+ Add some newer DLT_ values: IPMI_HPM_2,ZWAVE_R1_R2,ZWAVE_R3,WATTSTOPPER_DLM,ISO_14443,RDS
+ Clarify what the return values are for both success and failure.
+ Many changes to build on windows
+ Check for the "break the loop" condition in the inner loop for TPACKET_V3.
+ Fix handling of packet count in the TPACKET_V3 inner loop: GitHub issue #493.
+ Filter out duplicate looped back CAN frames.
+ Fix the handling of loopback filters for IPv6 packets.
+ Add a link-layer header type for RDS (IEC 62106) groups.
+ Use different intermediate folders for x86 and x64 builds on Windows.
+ On Linux, handle all CAN captures with pcap-linux.c, in cooked mode.
+ Removes the need for the "host-endian" link-layer header type.
+ Compile with '-Wused-but-marked-unused' in devel mode if supported
+ Have separate DLTs for big-endian and host-endian SocketCAN headers.
+ Reflect version.h being renamed to pcap_version.h.
+ Require that version.h be generated: all build procedures we support generate version.h (autoconf, CMake, MSVC)!
+ Properly check for sock_recv() errors.
+ Re-impose some of Winsock's limitations on sock_recv().
+ Replace sprintf() with pcap_snprintf().
+ Fix signature of pcap_stats_ex_remote().
+ Initial cmake support for remote packet capture.
+ Have rpcap_remoteact_getsock() return a SOCKET and supply an "is active" flag.
+ Clean up {DAG, Septel, Myricom SNF}-only builds.
+ Do UTF-16-to-ASCII conversion into the right place.
+ pcap_create_interface() needs the interface name on Linux.
+ Clean up hardware time stamp support: the "any" device does not support any time stamp types.
+ Add support for capturing on FreeBSD usbusN interfaces.
+ Add a LINKTYPE/DLT_ value for FreeBSD USB.
+ Go back to using PCAP_API on Windows.
+ CMake support
+ Add TurboCap support from WinPcap.
+ Recognize 802.1ad nested VLAN tag in vlan filter.
+
+Thursday Sep. 3, 2015 guy@alum.mit.edu
+ Summary for 1.7.5 libpcap release
+ Man page cleanups.
+ Add some allocation failure checks.
+ Fix a number of Linux/ucLinux configure/build issues.
+ Fix some memory leaks.
+ Recognize 802.1ad nested VLAN tag in vlan filter.
+ Fix building Bluetooth Linux Monitor support with BlueZ 5.1+
+
+Saturday Jun. 27, 2015 mcr@sandelman.ca
+ Summary for 1.7.4 libpcap release
+ Include fix for GitHub issue #424 -- out of tree builds.
+
+Friday Apr. 10, 2015 guy@alum.mit.edu
+ Summary for 1.7.3 libpcap release
+ Work around a Linux bonding driver bug.
+
+Thursday Feb. 12, 2015 guy@alum.mit.edu/mcr@sandelman.ca
+ Summary for 1.7.2 libpcap release
+ Support for filtering Geneve encapsulated packets.
+ Generalize encapsulation handling, fixing some bugs.
+ Don't add null addresses to address lists.
+ Add pcap_dump_open_append() to open for appending.
+ Fix the swapping of isochronous descriptors in Linux USB.
+ Attempt to handle TPACKET_V1 with 32-bit userland and 64-bit kernel.
+
+Wednesday Nov. 12, 2014 guy@alum.mit.edu/mcr@sandelman.ca
+ Summary for 1.7.0 libpcap release
+ Fix handling of zones for BPF on Solaris
+ new DLT for ZWAVE
+ clarifications for read timeouts.
+ Use BPF extensions in compiled filters, fixing VLAN filters
+ some fixes to compilation without stdint.h
+ EBUSY can now be returned by SNFv3 code.
+ Fix the range checks in BPF loads
+ Various DAG fixes.
+ Various Linux fixes.
+
Monday Aug. 12, 2014 guy@alum.mit.edu
- Summary for 1.6.2 tcpdump release
+ Summary for 1.6.2 libpcap release
Don't crash on filters testing a non-existent link-layer type
field.
Fix sending in non-blocking mode on Linux with memory-mapped
@@ -8,12 +83,12 @@ Monday Aug. 12, 2014 guy@alum.mit.edu
machines.
Saturday Jul. 19, 2014 mcr@sandelman.ca
- Summary for 1.6.1 tcpdump release
+ Summary for 1.6.1 libpcap release
some fixes for the any device
- changes for how --enable-XXX works
+ changes for how --enable-XXX (--enable-sniffing, --enable-can) works
Wednesday Jul. 2, 2014 mcr@sandelman.ca
- Summary for 1.6.0 tcpdump release
+ Summary for 1.6.0 libpcap release
Don't support D-Bus sniffing on OS X
fixes for byte order issues with NFLOG captures
Handle using cooked mode for DLT_NETLINK in activate_new().
diff --git a/contrib/libpcap/CREDITS b/contrib/libpcap/CREDITS
index dfc4e411036d..b40152f5e54b 100644
--- a/contrib/libpcap/CREDITS
+++ b/contrib/libpcap/CREDITS
@@ -2,11 +2,12 @@ This file lists people who have contributed to libpcap:
The current maintainers:
Bill Fenner <fenner at research dot att dot com>
- Denis Ovsienko <infrastation at yandex dot ru>
+ Denis Ovsienko <denis at ovsienko dot info>
Fulvio Risso <risso at polito dot it>
Guy Harris <guy at alum dot mit dot edu>
Hannes Gredler <hannes at juniper dot net>
Michael Richardson <mcr at sandelman dot ottawa dot on dot ca>
+ Francois-Xavier Le Bail <fx dot lebail at yahoo dot com>
Additional people who have contributed patches:
@@ -45,7 +46,7 @@ Additional people who have contributed patches:
David Young <dyoung at ojctech dot com>
Dean Gaudet <dean at arctic dot org>
dhruv <rsrivat at sourceforge dot net>
- Don Ebright <Don dot Ebright at compuware dot com>
+ Don Ebright <Don dot Ebright at compuware dot com>
Dug Song <dugsong at monkey dot org>
Dustin Spicuzza <dustin at virtualroadside dot com>
dzejarczech <dzejarczech at sourceforge dot net>
@@ -83,6 +84,7 @@ Additional people who have contributed patches:
Jefferson Ogata <jogata at nodc dot noaa dot gov>
Jesper Dangaard Brouer <hawk at comx dot dk>
Jesper Peterson <jesper at endace dot com>
+ Jesse Gross <jesse at nicira dot com>
Jiri Slaby <jirislaby at gmail dot com>
Joerg Mayer <jmayer at loplof dot de>
John Bankier <jbankier at rainfinity dot com>
@@ -105,6 +107,7 @@ Additional people who have contributed patches:
Mansour Behabadi <mansour at oxplot dot com>
Marcus Felipe Pereira <marcus at task dot com dot br>
Mark C. Brown <mbrown at hp dot com>
+ Mark Johnston <markjdb at gmail dot com>
Mark Pizzolato <List-tcpdump-workers at subscriptions dot pizzolato dot net>
Markus Mayer <markus_mayer at sourceforge dot net>
Martin Husemann <martin at netbsd dot org>
diff --git a/contrib/libpcap/INSTALL.txt b/contrib/libpcap/INSTALL.txt
index 7bbbf0cb8e1c..f305aa2b7929 100644
--- a/contrib/libpcap/INSTALL.txt
+++ b/contrib/libpcap/INSTALL.txt
@@ -16,7 +16,7 @@ does support packet capture but libpcap does not support that
particular type. (If you have HP-UX, see below.) If your system uses a
packet capture not supported by libpcap, please send us patches; don't
forget to include an autoconf fragment suitable for use in
-configure.in.
+configure.ac.
It is possible to override the default packet capture type, although
the circumstance where this works are limited. For example if you have
@@ -31,40 +31,22 @@ You will need an ANSI C compiler to build libpcap. The configure script
will abort if your compiler is not ANSI compliant. If this happens, use
the generally available GNU C compiler (GCC).
-If you use flex, you must use version 2.4.6 or higher. The configure
-script automatically detects the version of flex and will not use it
-unless it is new enough. You can use "flex -V" to see what version you
-have (unless it's really old). The current version of flex is available
-at flex.sourceforge.net and often comes packaged by means of the OS.
-As of this writing, the current version is 2.5.37.
+You will need either Flex 2.5.31 or later, or a version of Lex
+compatible with it (if any exist), to build libpcap. The configure
+script will abort if there isn't any such program. If you have an older
+version of Flex, or don't have a compatible version of Lex, the current
+version of flex is available at flex.sourceforge.net.
-If you use bison, you must use flex (and visa versa). The configure
-script automatically falls back to lex and yacc if both flex and bison
-are not found.
+You will need either Bison, Berkeley YACC, or a version of YACC
+compatible with them (if any exist), to build libpcap. The configure
+script will abort if there isn't any such program. If you don't have
+any such program, the current version of Bison can be found at
+http://ftp.gnu.org/gnu/bison/ and the current version of Berkeley YACC
+can be found at http://invisible-island.net/byacc/.
-Sometimes the stock C compiler does not interact well with flex and
-bison. The list of problems includes undefined references for alloca.
-You can get around this by installing gcc or manually disabling flex
-and bison with:
-
- ./configure --without-flex --without-bison
-
-If your system only has AT&T lex, this is okay unless your libpcap
-program uses other lex/yacc generated code. (Although it's possible to
-map the yy* identifiers with a script, we use flex and bison so we
-don't feel this is necessary.)
-
-Some systems support the Berkeley Packet Filter natively; for example
-out of the box OSF and BSD/OS have bpf. If your system does not support
-bpf, you will need to pick up:
-
- ftp://ftp.ee.lbl.gov/bpf-*.tar.Z
-
-Note well: you MUST have kernel source for your operating system in
-order to install bpf. An exception is SunOS 4; the bpf distribution
-includes replacement kernel objects for some of the standard SunOS 4
-network device drivers. See the bpf INSTALL document for more
-information.
+Sometimes the stock C compiler does not interact well with Flex and
+Bison. The list of problems includes undefined references for alloca.
+You can get around this by installing GCC.
If you use Solaris, there is a bug with bufmod(7) that is fixed in
Solaris 2.3.2 (aka SunOS 5.3.2). Setting a snapshot length with the
@@ -178,14 +160,14 @@ packet timestamps aren't very good. This appears to be due to haphazard
handling of the timestamp in the kernel.
Note well: there is rumoured to be a version of tcpdump floating around
-called 3.0.3 that includes libpcap and is supposed to support Linux.
+called 3.0.3 that includes libpcap and is supposed to support Linux.
You should be advised that neither the Network Research Group at LBNL
-nor the Tcpdump Group ever generated a release with this version number.
+nor the Tcpdump Group ever generated a release with this version number.
The LBNL Network Research Group notes with interest that a standard
cracker trick to get people to install trojans is to distribute bogus
-packages that have a version number higher than the current release.
+packages that have a version number higher than the current release.
They also noted with annoyance that 90% of the Linux related bug reports
-they got are due to changes made to unofficial versions of their page.
+they got are due to changes made to unofficial versions of their page.
If you are having trouble but aren't using a version that came from
tcpdump.org, please try that before submitting a bug report!
@@ -239,11 +221,11 @@ the libpcap 0.6.2 source release, so this release of libpcap might also
build without changes on UnixWare 7.
If linking tcpdump fails with "Undefined: _alloca" when using bison on
-a Sun4, your version of bison is broken. In any case version 1.16 or
+a Sun4, your version of Bison is broken. In any case version 1.16 or
higher is recommended (1.14 is known to cause problems 1.16 is known to
work). Either pick up a current version from:
- ftp://ftp.gnu.org/pub/gnu/bison
+ http://ftp.gnu.org/gnu/bison/
or hack around it by inserting the lines:
@@ -289,6 +271,7 @@ FILES
CHANGES - description of differences between releases
ChmodBPF/* - Mac OS X startup item to set ownership and permissions
on /dev/bpf*
+CMakeLists.txt - CMake file
CREDITS - people that have helped libpcap along
INSTALL.txt - this file
LICENSE - the license under which tcpdump is distributed
@@ -317,7 +300,7 @@ config.guess - autoconf support
config.h.in - autoconf input
config.sub - autoconf support
configure - configure script (run this first)
-configure.in - configure script source
+configure.ac - configure script source
dlpisubs.c - DLPI-related functions for pcap-dlpi.c and pcap-libdlpi.c
dlpisubs.h - DLPI-related function declarations
etherent.c - /etc/ethers support routines
@@ -325,9 +308,6 @@ ethertype.h - Ethernet protocol types and names definitions
fad-getad.c - pcap_findalldevs() for systems with getifaddrs()
fad-gifc.c - pcap_findalldevs() for systems with only SIOCGIFLIST
fad-glifc.c - pcap_findalldevs() for systems with SIOCGLIFCONF
-fad-null.c - pcap_findalldevs() for systems without capture support
-fad-sita.c - pcap_findalldevs() for systems with SITA support
-fad-win32.c - pcap_findalldevs() for WinPcap
filtertest.c - test program for BPF compiler
findalldevstest.c - test program for pcap_findalldevs()
gencode.c - BPF code generation routines
@@ -345,7 +325,6 @@ nametoaddr.c - hostname to address routines
nlpid.h - OSI network layer protocol identifier definitions
net - symlink to bpf/net
optimize.c - BPF optimization routines
-packaging - packaging information for building libpcap RPMs
pcap/bluetooth.h - public definition of DLT_BLUETOOTH_HCI_H4_WITH_PHDR header
pcap/bpf.h - BPF definitions
pcap/namedb.h - public libpcap name database definitions
@@ -389,7 +368,6 @@ pcap_*.3pcap - manual entries for library functions
pcap-filter.4 - manual entry for filter syntax
pcap-linktype.4 - manual entry for link-layer header types
ppp.h - Point to Point Protocol definitions
-runlex.sh - wrapper for Lex/Flex
savefile.c - offline support
scanner.l - filter string scanner
sunatmpos.h - definitions for SunATM capturing
diff --git a/contrib/libpcap/LICENSE b/contrib/libpcap/LICENSE
index dea5f7d54d6b..a10474d54aeb 100644
--- a/contrib/libpcap/LICENSE
+++ b/contrib/libpcap/LICENSE
@@ -1,9 +1,9 @@
License: BSD
-
+
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
are met:
-
+
1. Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright
@@ -13,7 +13,7 @@ are met:
3. The names of the authors may not be used to endorse or promote
products derived from this software without specific prior
written permission.
-
+
THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
diff --git a/contrib/libpcap/Makefile-devel-adds b/contrib/libpcap/Makefile-devel-adds
index 7bf6420c1c82..fea63bbce3a7 100644
--- a/contrib/libpcap/Makefile-devel-adds
+++ b/contrib/libpcap/Makefile-devel-adds
@@ -2,12 +2,12 @@
# Auto-regenerate configure script or Makefile when things change.
# From autoconf.info . Works best with GNU Make.
#
-${srcdir}/configure: configure.in aclocal.m4
+${srcdir}/configure: configure.ac aclocal.m4
cd ${srcdir} && autoconf
# autoheader might not change config.h.in, so touch a stamp file.
${srcdir}/config.h.in: ${srcdir}/stamp-h.in
-${srcdir}/stamp-h.in: configure.in aclocal.m4
+${srcdir}/stamp-h.in: configure.ac aclocal.m4
cd ${srcdir} && autoheader
echo timestamp > ${srcdir}/stamp-h.in
diff --git a/contrib/libpcap/Makefile.in b/contrib/libpcap/Makefile.in
index 1c2d7459943f..e71d973ca448 100644
--- a/contrib/libpcap/Makefile.in
+++ b/contrib/libpcap/Makefile.in
@@ -49,12 +49,13 @@ LN_S = @LN_S@
MKDEP = @MKDEP@
CCOPT = @V_CCOPT@
INCLS = -I. @V_INCLS@
-DEFS = @DEFS@ @V_DEFS@
+DEFS = -DBUILDING_PCAP @DEFS@ @V_DEFS@
ADDLOBJS = @ADDLOBJS@
ADDLARCHIVEOBJS = @ADDLARCHIVEOBJS@
LIBS = @LIBS@
-CFLAGS = @CFLAGS@
-LDFLAGS = @LDFLAGS@
+CROSSFLAGS=
+CFLAGS = @CFLAGS@ ${CROSSFLAGS}
+LDFLAGS = @LDFLAGS@ ${CROSSFLAGS}
DYEXT = @DYEXT@
V_RPATH_OPT = @V_RPATH_OPT@
DEPENDENCY_CFLAG = @DEPENDENCY_CFLAG@
@@ -68,13 +69,8 @@ INSTALL_PROGRAM = @INSTALL_PROGRAM@
INSTALL_DATA = @INSTALL_DATA@
RANLIB = @RANLIB@
-#
-# Flex and bison allow you to specify the prefixes of the global symbols
-# used by the generated parser. This allows programs to use lex/yacc
-# and link against libpcap. If you don't have flex or bison, get them.
-#
-LEX = @V_LEX@
-YACC = @V_YACC@
+LEX = @LEX@
+YACC = @YACC@
# Explicitly define compilation rule since SunOS 4's make doesn't like gcc.
# Also, gcc does not remove the .o before forking 'as', which can be a
@@ -83,11 +79,11 @@ YACC = @V_YACC@
@rm -f $@
$(CC) $(FULL_CFLAGS) -c $(srcdir)/$*.c
-PSRC = pcap-@V_PCAP@.c @USB_SRC@ @BT_SRC@ @BT_MONITOR_SRC@ @CAN_SRC@ @NETFILTER_SRC@ @CANUSB_SRC@ @DBUS_SRC@
-FSRC = fad-@V_FINDALLDEVS@.c
+PSRC = pcap-@V_PCAP@.c @USB_SRC@ @BT_SRC@ @BT_MONITOR_SRC@ @NETFILTER_SRC@ @DBUS_SRC@
+FSRC = @V_FINDALLDEVS@
SSRC = @SSRC@
-CSRC = pcap.c inet.c gencode.c optimize.c nametoaddr.c etherent.c \
- savefile.c sf-pcap.c sf-pcap-ng.c pcap-common.c \
+CSRC = pcap.c inet.c fad-helpers.c gencode.c optimize.c nametoaddr.c \
+ etherent.c savefile.c sf-pcap.c sf-pcap-ng.c pcap-common.c \
bpf_image.c bpf_dump.c
GENSRC = scanner.c grammar.c bpf_filter.c version.c
LIBOBJS = @LIBOBJS@
@@ -103,6 +99,9 @@ PUBHDR = \
pcap-namedb.h \
pcap/bpf.h \
pcap/bluetooth.h \
+ pcap/can_socketcan.h \
+ pcap/dlt.h \
+ pcap/export-defs.h \
pcap/ipnet.h \
pcap/namedb.h \
pcap/nflog.h \
@@ -115,37 +114,43 @@ HDR = $(PUBHDR) \
arcnet.h \
atmuni31.h \
ethertype.h \
+ extract.h \
gencode.h \
ieee80211.h \
llc.h \
+ nametoaddr.h \
nlpid.h \
pcap-common.h \
pcap-int.h \
pcap-stdinc.h \
+ portability.h \
ppp.h \
sf-pcap.h \
sf-pcap-ng.h \
sunatmpos.h
TESTS = \
+ @VALGRINDTEST@ \
capturetest \
+ can_set_rfmon_test \
filtertest \
findalldevstest \
opentest \
- selpolltest \
- valgrindtest
+ reactivatetest \
+ selpolltest
TESTS_SRC = \
+ tests/valgrindtest.c \
tests/capturetest.c \
+ tests/can_set_rfmon_test.c \
tests/filtertest.c \
tests/findalldevstest.c \
tests/opentest.c \
tests/reactivatetest.c \
- tests/selpolltest.c \
- tests/valgrindtest.c
+ tests/selpolltest.c
GENHDR = \
- scanner.h tokdefs.h version.h
+ scanner.h grammar.h pcap_version.h
TAGFILES = \
$(SRC) $(HDR)
@@ -231,6 +236,8 @@ EXTRA_DIST = \
ChmodBPF/ChmodBPF \
ChmodBPF/StartupParameters.plist \
CREDITS \
+ CMakeLists.txt \
+ GenVersion.bat \
INSTALL.txt \
LICENSE \
Makefile.in \
@@ -253,29 +260,37 @@ EXTRA_DIST = \
aclocal.m4 \
bpf/net/bpf_filter.c \
chmod_bpf \
+ cmakeconfig.h.in \
+ cmake/preconfigure.cmake \
+ config/have_siocglifconf.c \
config.guess \
config.h.in \
config.sub \
configure \
- configure.in \
+ configure.ac \
dlpisubs.c \
dlpisubs.h \
fad-getad.c \
fad-gifc.c \
fad-glifc.c \
- fad-null.c \
- fad-sita.c \
- fad-win32.c \
+ fad-helpers.c \
+ gen_version_c.sh \
+ gen_version_header.sh \
grammar.y \
install-sh \
lbl/os-aix4.h \
+ lbl/os-aix7.h \
lbl/os-hpux11.h \
lbl/os-osf4.h \
lbl/os-osf5.h \
lbl/os-solaris2.h \
lbl/os-sunos4.h \
lbl/os-ultrix4.h \
+ missing/getopt.c \
+ missing/getopt.h \
missing/snprintf.c \
+ missing/strtok_r.c \
+ missing/win_snprintf.c \
mkdep \
msdos/bin2c.c \
msdos/common.dj \
@@ -291,16 +306,11 @@ EXTRA_DIST = \
msdos/pktdrvr.h \
msdos/readme.dos \
org.tcpdump.chmod_bpf.plist \
- packaging/pcap.spec.in \
pcap-bpf.c \
pcap-bt-linux.c \
pcap-bt-linux.h \
pcap-bt-monitor-linux.c \
pcap-bt-monitor-linux.h \
- pcap-can-linux.c \
- pcap-can-linux.h \
- pcap-canusb-linux.c \
- pcap-canusb-linux.h \
pcap-config.in \
pcap-dag.c \
pcap-dag.h \
@@ -314,11 +324,14 @@ EXTRA_DIST = \
pcap-libdlpi.c \
pcap-linux.c \
pcap-namedb.h \
+ pcap-new.c \
pcap-netfilter-linux.c \
pcap-netfilter-linux.h \
pcap-nit.c \
pcap-null.c \
pcap-pf.c \
+ pcap-rpcap.c \
+ pcap-rpcap.h \
pcap-septel.c \
pcap-septel.h \
pcap-sita.h \
@@ -328,34 +341,22 @@ EXTRA_DIST = \
pcap-snf.h \
pcap-snit.c \
pcap-snoop.c \
+ pcap-tc.c \
+ pcap-tc.h \
pcap-usb-linux.c \
pcap-usb-linux.h \
pcap-win32.c \
- runlex.sh \
+ remote-ext.h \
+ sockutils.c \
+ sockutils.h \
scanner.l \
+ tests/CMakeLists.txt \
+ pcap_version.h.in \
Win32/Include/Gnuc.h \
- Win32/Include/addrinfo.h \
- Win32/Include/bittypes.h \
- Win32/Include/cdecl_ext.h \
- Win32/Include/inetprivate.h \
- Win32/Include/ip6_misc.h \
- Win32/Include/sockstorage.h \
- Win32/Include/arpa/nameser.h \
Win32/Include/net/if.h \
- Win32/Include/net/netdb.h \
- Win32/Include/net/paths.h \
- Win32/Prj/libpcap.dsp \
- Win32/Prj/libpcap.dsw \
- Win32/Src/ffs.c \
- Win32/Src/gai_strerror.c \
- Win32/Src/getaddrinfo.c \
- Win32/Src/getnetbynm.c \
- Win32/Src/getnetent.c \
- Win32/Src/getopt.c \
- Win32/Src/getservent.c \
- Win32/Src/inet_aton.c \
- Win32/Src/inet_net.c \
- Win32/Src/inet_pton.c
+ Win32/Prj/wpcap.sln \
+ Win32/Prj/wpcap.vcxproj \
+ Win32/Prj/wpcap.vcxproj.filters
all: libpcap.a shared pcap-config
@@ -443,24 +444,33 @@ libpcap.shareda: $(OBJ)
libpcap.none:
scanner.c: $(srcdir)/scanner.l
- @rm -f $@
- $(srcdir)/runlex.sh $(LEX) -o$@ $<
-
-scanner.o: scanner.c tokdefs.h
+ $(LEX) -P pcap_ --header-file=scanner.h --nounput -o scanner.c $<
+scanner.h: scanner.c
+## Recover from the removal of $@
+ @if test -f $@; then :; else \
+ rm -f scanner.c; \
+ $(MAKE) $(MAKEFLAGS) scanner.c; \
+ fi
+
+scanner.o: scanner.c grammar.h
$(CC) $(FULL_CFLAGS) -c scanner.c
-pcap.o: version.h
+pcap.o: pcap_version.h
-tokdefs.h: grammar.c
grammar.c: $(srcdir)/grammar.y
- @rm -f grammar.c tokdefs.h
- $(YACC) -d $<
- mv y.tab.c grammar.c
- mv y.tab.h tokdefs.h
+ $(YACC) -p pcap_ -o grammar.c -d $<
+grammar.h: grammar.c
+## Recover from the removal of $@
+ @if test -f $@; then :; else \
+ rm -f grammar.c; \
+ $(MAKE) $(MAKEFLAGS) grammar.c; \
+ fi
grammar.o: grammar.c
- @rm -f $@
- $(CC) $(FULL_CFLAGS) -Dyylval=pcap_lval -c grammar.c
+ $(CC) $(FULL_CFLAGS) -c grammar.c
+
+gencode.o: $(srcdir)/gencode.c grammar.h scanner.h
+ $(CC) $(FULL_CFLAGS) -c $(srcdir)/gencode.c
version.o: version.c
$(CC) $(FULL_CFLAGS) -c version.c
@@ -468,32 +478,21 @@ version.o: version.c
snprintf.o: $(srcdir)/missing/snprintf.c
$(CC) $(FULL_CFLAGS) -o $@ -c $(srcdir)/missing/snprintf.c
-version.c: $(srcdir)/VERSION
+strtok_r.o: $(srcdir)/missing/strtok_r.c
+ $(CC) $(FULL_CFLAGS) -o $@ -c $(srcdir)/missing/strtok_r.c
+
+version.c: $(srcdir)/VERSION $(srcdir)/gen_version_c.sh
+ #
+ # Older programs import this if they want to show the
+ # libpcap version number, rather than calling
+ # pcap_lib_version(), so we need to export it.
+ #
@rm -f $@
- if grep GIT ${srcdir}/VERSION >/dev/null; then \
- read ver <${srcdir}/VERSION; \
- echo $$ver | tr -d '\012'; \
- date +_%Y_%m_%d; \
- else \
- cat ${srcdir}/VERSION; \
- fi | sed -e 's/.*/char pcap_version[] = "&";/' > $@
+ $(srcdir)/gen_version_c.sh $(srcdir)/VERSION $@
-#
-# NOTE: this really is supposed to be static; importing a string
-# from a shared library does not work very well on many
-# versions of UNIX (Solaris, Linux, and the BSDs, for example),
-# so we make the version string static and return it from
-# a function, which does work.
-#
-version.h: $(srcdir)/VERSION
+pcap_version.h: $(srcdir)/VERSION $(srcdir)/pcap_version.h.in $(srcdir)/gen_version_header.sh
@rm -f $@
- if grep GIT ${srcdir}/VERSION >/dev/null; then \
- read ver <${srcdir}/VERSION; \
- echo $$ver | tr -d '\012'; \
- date +_%Y_%m_%d; \
- else \
- cat ${srcdir}/VERSION; \
- fi | sed -e 's/.*/static const char pcap_version_string[] = "libpcap version &";/' > $@
+ $(srcdir)/gen_version_header.sh $(srcdir)/VERSION $(srcdir)/pcap_version.h.in $@
bpf_filter.c: $(srcdir)/bpf/net/bpf_filter.c
rm -f bpf_filter.c
@@ -530,6 +529,9 @@ tests: $(TESTS)
capturetest: tests/capturetest.c libpcap.a
$(CC) $(FULL_CFLAGS) -I. -L. -o capturetest $(srcdir)/tests/capturetest.c libpcap.a $(LIBS)
+can_set_rfmon_test: tests/can_set_rfmon_test.c libpcap.a
+ $(CC) $(FULL_CFLAGS) -I. -L. -o can_set_rfmon_test $(srcdir)/tests/can_set_rfmon_test.c libpcap.a $(LIBS)
+
filtertest: tests/filtertest.c libpcap.a
$(CC) $(FULL_CFLAGS) -I. -L. -o filtertest $(srcdir)/tests/filtertest.c libpcap.a $(LIBS)
@@ -539,6 +541,9 @@ findalldevstest: tests/findalldevstest.c libpcap.a
opentest: tests/opentest.c libpcap.a
$(CC) $(FULL_CFLAGS) -I. -L. -o opentest $(srcdir)/tests/opentest.c libpcap.a $(LIBS)
+reactivatetest: tests/reactivatetest.c libpcap.a
+ $(CC) $(FULL_CFLAGS) -I. -L. -o reactivatetest $(srcdir)/tests/reactivatetest.c libpcap.a $(LIBS)
+
selpolltest: tests/selpolltest.c libpcap.a
$(CC) $(FULL_CFLAGS) -I. -L. -o selpolltest $(srcdir)/tests/selpolltest.c libpcap.a $(LIBS)
@@ -728,13 +733,12 @@ distclean: clean
rm -f $(MAN3PCAP_EXPAND:.in=) $(MANFILE:.in=) $(MANMISC:.in=)
rm -rf autom4te.cache
+extags: $(TAGFILES)
+ ctags $(TAGFILES)
+
tags: $(TAGFILES)
ctags -wtd $(TAGFILES)
-packaging/pcap.spec: packaging/pcap.spec.in VERSION
- RPMVERSION=`cat VERSION | sed s/-.*//g`; \
- sed -e s/@VERSION@/$$RPMVERSION/ -e s/@NAME@/libpcap-`cat VERSION`/ $< > $@
-
releasetar:
@cwd=`pwd` ; dir=`basename $$cwd` ; name=$(PROG)-`cat VERSION` ; \
mkdir $$name; \
diff --git a/contrib/libpcap/README b/contrib/libpcap/README
index 46fcc5689e70..9f65948d4ef2 100644
--- a/contrib/libpcap/README
+++ b/contrib/libpcap/README
@@ -76,15 +76,15 @@ information on configuring that option.
Note to Linux distributions and *BSD systems that include libpcap:
-There's now a rule to make a shared library, which should work on Linux
+There's now a rule to make a shared library, which should work on Linux
and *BSD, among other platforms.
-It sets the soname of the library to "libpcap.so.1"; this is what it
-should be, *NOT* libpcap.so.1.x or libpcap.so.1.x.y or something such as
+It sets the soname of the library to "libpcap.so.1"; this is what it
+should be, *NOT* libpcap.so.1.x or libpcap.so.1.x.y or something such as
that.
-We've been maintaining binary compatibility between libpcap releases for
-quite a while; there's no reason to tie a binary linked with libpcap to
+We've been maintaining binary compatibility between libpcap releases for
+quite a while; there's no reason to tie a binary linked with libpcap to
a particular release of libpcap.
Problems, bugs, questions, desirable enhancements, etc. should be sent
diff --git a/contrib/libpcap/TODO b/contrib/libpcap/TODO
index 73325e1965dd..aae24c22d251 100644
--- a/contrib/libpcap/TODO
+++ b/contrib/libpcap/TODO
@@ -6,11 +6,11 @@ Important stuff (to be done before the next release)
General
-- configure should not be in Git. Most open source projects have an
- autogen.sh script to run autoconf etc. after checkout. I think we
- should stick to the standard.
+- configure should not be in Git. Most open source projects have an
+ autogen.sh script to run autoconf etc. after checkout. I think we
+ should stick to the standard.
-- The source files should be better documented. There is no official
+- The source files should be better documented. There is no official
design guideline for what is done where. There should be a common coding
style (okay, you can guess that by looking at the code) and a guide for
what needs to be documented.
@@ -18,7 +18,7 @@ General
Less urgent items
-----------------
-- Better documentation and cleanup of the interface. I am seeing a few
+- Better documentation and cleanup of the interface. I am seeing a few
problems at the first glance which needs fixing:
+ pcap_lookupnet makes little to no sense with protocols != IPv4
+ not very well suited for interactive programs (think ethereal). There
diff --git a/contrib/libpcap/VERSION b/contrib/libpcap/VERSION
index fdd3be6df54a..a8fdfda1c782 100644
--- a/contrib/libpcap/VERSION
+++ b/contrib/libpcap/VERSION
@@ -1 +1 @@
-1.6.2
+1.8.1
diff --git a/contrib/libpcap/bpf/net/bpf_filter.c b/contrib/libpcap/bpf/net/bpf_filter.c
index ad689e16a912..01a1b64e7197 100644
--- a/contrib/libpcap/bpf/net/bpf_filter.c
+++ b/contrib/libpcap/bpf/net/bpf_filter.c
@@ -42,11 +42,11 @@
#include "config.h"
#endif
-#ifdef WIN32
+#ifdef _WIN32
#include <pcap-stdinc.h>
-#else /* WIN32 */
+#else /* _WIN32 */
#if HAVE_INTTYPES_H
#include <inttypes.h>
@@ -73,7 +73,7 @@
# define MLEN(m) ((m)->m_len)
#endif /* defined(__hpux) || SOLARIS */
-#endif /* WIN32 */
+#endif /* _WIN32 */
#include <pcap/bpf.h>
@@ -99,7 +99,7 @@
#endif
#ifndef LBL_ALIGN
-#ifndef WIN32
+#ifndef _WIN32
#include <netinet/in.h>
#endif
@@ -195,23 +195,41 @@ m_xhalf(m, k, err)
}
#endif
+#ifdef __linux__
+#include <linux/types.h>
+#include <linux/if_packet.h>
+#include <linux/filter.h>
+#endif
+
+enum {
+ BPF_S_ANC_NONE,
+ BPF_S_ANC_VLAN_TAG,
+ BPF_S_ANC_VLAN_TAG_PRESENT,
+};
+
/*
* Execute the filter program starting at pc on the packet p
* wirelen is the length of the original packet
* buflen is the amount of data present
+ * aux_data is auxiliary data, currently used only when interpreting
+ * filters intended for the Linux kernel in cases where the kernel
+ * rejects the filter; it contains VLAN tag information
* For the kernel, p is assumed to be a pointer to an mbuf if buflen is 0,
* in all other cases, p is a pointer to a buffer and buflen is its size.
+ *
+ * Thanks to Ani Sinha <ani@arista.com> for providing initial implementation
*/
u_int
-bpf_filter(pc, p, wirelen, buflen)
+bpf_filter_with_aux_data(pc, p, wirelen, buflen, aux_data)
register const struct bpf_insn *pc;
register const u_char *p;
u_int wirelen;
register u_int buflen;
+ register const struct bpf_aux_data *aux_data;
{
register u_int32 A, X;
- register int k;
- int32 mem[BPF_MEMWORDS];
+ register bpf_u_int32 k;
+ u_int32 mem[BPF_MEMWORDS];
#if defined(KERNEL) || defined(_KERNEL)
struct mbuf *m, *n;
int merr, len;
@@ -250,7 +268,7 @@ bpf_filter(pc, p, wirelen, buflen)
case BPF_LD|BPF_W|BPF_ABS:
k = pc->k;
- if (k + sizeof(int32) > buflen) {
+ if (k > buflen || sizeof(int32_t) > buflen - k) {
#if defined(KERNEL) || defined(_KERNEL)
if (m == NULL)
return 0;
@@ -267,7 +285,7 @@ bpf_filter(pc, p, wirelen, buflen)
case BPF_LD|BPF_H|BPF_ABS:
k = pc->k;
- if (k + sizeof(short) > buflen) {
+ if (k > buflen || sizeof(int16_t) > buflen - k) {
#if defined(KERNEL) || defined(_KERNEL)
if (m == NULL)
return 0;
@@ -283,22 +301,50 @@ bpf_filter(pc, p, wirelen, buflen)
continue;
case BPF_LD|BPF_B|BPF_ABS:
- k = pc->k;
- if (k >= buflen) {
+ {
+#if defined(SKF_AD_VLAN_TAG) && defined(SKF_AD_VLAN_TAG_PRESENT)
+ int code = BPF_S_ANC_NONE;
+#define ANCILLARY(CODE) case SKF_AD_OFF + SKF_AD_##CODE: \
+ code = BPF_S_ANC_##CODE; \
+ if (!aux_data) \
+ return 0; \
+ break;
+
+ switch (pc->k) {
+ ANCILLARY(VLAN_TAG);
+ ANCILLARY(VLAN_TAG_PRESENT);
+ default :
+#endif
+ k = pc->k;
+ if (k >= buflen) {
#if defined(KERNEL) || defined(_KERNEL)
- if (m == NULL)
- return 0;
- n = m;
- MINDEX(len, n, k);
- A = mtod(n, u_char *)[k];
- continue;
+ if (m == NULL)
+ return 0;
+ n = m;
+ MINDEX(len, n, k);
+ A = mtod(n, u_char *)[k];
+ continue;
#else
- return 0;
+ return 0;
#endif
+ }
+ A = p[k];
+#if defined(SKF_AD_VLAN_TAG) && defined(SKF_AD_VLAN_TAG_PRESENT)
+ }
+ switch (code) {
+ case BPF_S_ANC_VLAN_TAG:
+ if (aux_data)
+ A = aux_data->vlan_tag;
+ break;
+
+ case BPF_S_ANC_VLAN_TAG_PRESENT:
+ if (aux_data)
+ A = aux_data->vlan_tag_present;
+ break;
+ }
+#endif
+ continue;
}
- A = p[k];
- continue;
-
case BPF_LD|BPF_W|BPF_LEN:
A = wirelen;
continue;
@@ -309,7 +355,8 @@ bpf_filter(pc, p, wirelen, buflen)
case BPF_LD|BPF_W|BPF_IND:
k = X + pc->k;
- if (k + sizeof(int32) > buflen) {
+ if (pc->k > buflen || X > buflen - pc->k ||
+ sizeof(int32_t) > buflen - k) {
#if defined(KERNEL) || defined(_KERNEL)
if (m == NULL)
return 0;
@@ -326,7 +373,8 @@ bpf_filter(pc, p, wirelen, buflen)
case BPF_LD|BPF_H|BPF_IND:
k = X + pc->k;
- if (k + sizeof(short) > buflen) {
+ if (X > buflen || pc->k > buflen - X ||
+ sizeof(int16_t) > buflen - k) {
#if defined(KERNEL) || defined(_KERNEL)
if (m == NULL)
return 0;
@@ -343,7 +391,7 @@ bpf_filter(pc, p, wirelen, buflen)
case BPF_LD|BPF_B|BPF_IND:
k = X + pc->k;
- if (k >= buflen) {
+ if (pc->k >= buflen || X >= buflen - pc->k) {
#if defined(KERNEL) || defined(_KERNEL)
if (m == NULL)
return 0;
@@ -531,7 +579,12 @@ bpf_filter(pc, p, wirelen, buflen)
continue;
case BPF_ALU|BPF_NEG:
- A = -A;
+ /*
+ * Most BPF arithmetic is unsigned, but negation
+ * can't be unsigned; throw some casts to
+ * specify what we're trying to do.
+ */
+ A = (u_int32)(-(int32)A);
continue;
case BPF_MISC|BPF_TAX:
@@ -545,6 +598,17 @@ bpf_filter(pc, p, wirelen, buflen)
}
}
+u_int
+bpf_filter(pc, p, wirelen, buflen)
+ register const struct bpf_insn *pc;
+ register const u_char *p;
+ u_int wirelen;
+ register u_int buflen;
+{
+ return bpf_filter_with_aux_data(pc, p, wirelen, buflen, NULL);
+}
+
+
/*
* Return true if the 'fcode' is a valid filter program.
* The constraints are that each jump be forward and to a valid
@@ -574,7 +638,7 @@ bpf_validate(f, len)
return 0;
#endif
- for (i = 0; i < len; ++i) {
+ for (i = 0; i < (u_int)len; ++i) {
p = &f[i];
switch (BPF_CLASS(p->code)) {
/*
@@ -675,7 +739,7 @@ bpf_validate(f, len)
#if defined(KERNEL) || defined(_KERNEL)
if (from + p->k < from || from + p->k >= len)
#else
- if (from + p->k >= len)
+ if (from + p->k >= (u_int)len)
#endif
return 0;
break;
@@ -683,7 +747,7 @@ bpf_validate(f, len)
case BPF_JGT:
case BPF_JGE:
case BPF_JSET:
- if (from + p->jt >= len || from + p->jf >= len)
+ if (from + p->jt >= (u_int)len || from + p->jf >= (u_int)len)
return 0;
break;
default:
diff --git a/contrib/libpcap/bpf_dump.c b/contrib/libpcap/bpf_dump.c
index 5eaadc08aad2..d5ab61e5e8ff 100644
--- a/contrib/libpcap/bpf_dump.c
+++ b/contrib/libpcap/bpf_dump.c
@@ -51,7 +51,10 @@ bpf_dump(const struct bpf_program *p, int option)
for (i = 0; i < n; ++insn, ++i) {
#ifdef BDEBUG
extern int bids[];
- printf(bids[i] > 0 ? "[%02d]" : " -- ", bids[i] - 1);
+ if (bids[i] > 0)
+ printf("[%02d]", bids[i] - 1);
+ else
+ printf(" -- ");
#endif
puts(bpf_image(insn, i));
}
diff --git a/contrib/libpcap/bpf_image.c b/contrib/libpcap/bpf_image.c
index 3e9a23f51b4c..01ec536dfd62 100644
--- a/contrib/libpcap/bpf_image.c
+++ b/contrib/libpcap/bpf_image.c
@@ -23,9 +23,9 @@
#include "config.h"
#endif
-#ifdef WIN32
+#ifdef _WIN32
#include <pcap-stdinc.h>
-#else /* WIN32 */
+#else /* _WIN32 */
#if HAVE_INTTYPES_H
#include <inttypes.h>
#elif HAVE_STDINT_H
@@ -35,7 +35,7 @@
#include <sys/bitypes.h>
#endif
#include <sys/types.h>
-#endif /* WIN32 */
+#endif /* _WIN32 */
#include <stdio.h>
#include <string.h>
@@ -306,13 +306,13 @@ bpf_image(p, n)
fmt = "";
break;
}
- (void)snprintf(operand, sizeof operand, fmt, v);
+ (void)pcap_snprintf(operand, sizeof operand, fmt, v);
if (BPF_CLASS(p->code) == BPF_JMP && BPF_OP(p->code) != BPF_JA) {
- (void)snprintf(image, sizeof image,
+ (void)pcap_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,
+ (void)pcap_snprintf(image, sizeof image,
"(%03d) %-8s %s",
n, op, operand);
}
diff --git a/contrib/libpcap/config.guess b/contrib/libpcap/config.guess
index d622a44e551f..44290b838cd0 100755
--- a/contrib/libpcap/config.guess
+++ b/contrib/libpcap/config.guess
@@ -1,14 +1,12 @@
#! /bin/sh
# Attempt to guess a canonical system name.
-# Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999,
-# 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010,
-# 2011, 2012 Free Software Foundation, Inc.
+# Copyright 1992-2015 Free Software Foundation, Inc.
-timestamp='2012-02-10'
+timestamp='2015-02-23'
# This file is free software; you can redistribute it and/or modify it
# under the terms of the GNU General Public License as published by
-# the Free Software Foundation; either version 2 of the License, or
+# the Free Software Foundation; either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful, but
@@ -22,19 +20,17 @@ timestamp='2012-02-10'
# As a special exception to the GNU General Public License, if you
# distribute this file as part of a program that contains a
# configuration script generated by Autoconf, you may include it under
-# the same distribution terms that you use for the rest of that program.
-
-
-# Originally written by Per Bothner. Please send patches (context
-# diff format) to <config-patches@gnu.org> and include a ChangeLog
-# entry.
+# the same distribution terms that you use for the rest of that
+# program. This Exception is an additional permission under section 7
+# of the GNU General Public License, version 3 ("GPLv3").
#
-# This script attempts to guess a canonical system name similar to
-# config.sub. If it succeeds, it prints the system name on stdout, and
-# exits with 0. Otherwise, it exits with 1.
+# Originally written by Per Bothner; maintained since 2000 by Ben Elliston.
#
# You can get the latest version of this script from:
# http://git.savannah.gnu.org/gitweb/?p=config.git;a=blob_plain;f=config.guess;hb=HEAD
+#
+# Please send patches to <config-patches@gnu.org>.
+
me=`echo "$0" | sed -e 's,.*/,,'`
@@ -54,9 +50,7 @@ version="\
GNU config.guess ($timestamp)
Originally written by Per Bothner.
-Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000,
-2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011, 2012
-Free Software Foundation, Inc.
+Copyright 1992-2015 Free Software Foundation, Inc.
This is free software; see the source for copying conditions. There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE."
@@ -138,6 +132,27 @@ UNAME_RELEASE=`(uname -r) 2>/dev/null` || UNAME_RELEASE=unknown
UNAME_SYSTEM=`(uname -s) 2>/dev/null` || UNAME_SYSTEM=unknown
UNAME_VERSION=`(uname -v) 2>/dev/null` || UNAME_VERSION=unknown
+case "${UNAME_SYSTEM}" in
+Linux|GNU|GNU/*)
+ # If the system lacks a compiler, then just pick glibc.
+ # We could probably try harder.
+ LIBC=gnu
+
+ eval $set_cc_for_build
+ cat <<-EOF > $dummy.c
+ #include <features.h>
+ #if defined(__UCLIBC__)
+ LIBC=uclibc
+ #elif defined(__dietlibc__)
+ LIBC=dietlibc
+ #else
+ LIBC=gnu
+ #endif
+ EOF
+ eval `$CC_FOR_BUILD -E $dummy.c 2>/dev/null | grep '^LIBC' | sed 's, ,,g'`
+ ;;
+esac
+
# Note: order is significant - the case branches are not exclusive.
case "${UNAME_MACHINE}:${UNAME_SYSTEM}:${UNAME_RELEASE}:${UNAME_VERSION}" in
@@ -153,20 +168,27 @@ case "${UNAME_MACHINE}:${UNAME_SYSTEM}:${UNAME_RELEASE}:${UNAME_VERSION}" in
# Note: NetBSD doesn't particularly care about the vendor
# portion of the name. We always set it to "unknown".
sysctl="sysctl -n hw.machine_arch"
- UNAME_MACHINE_ARCH=`(/sbin/$sysctl 2>/dev/null || \
- /usr/sbin/$sysctl 2>/dev/null || echo unknown)`
+ UNAME_MACHINE_ARCH=`(uname -p 2>/dev/null || \
+ /sbin/$sysctl 2>/dev/null || \
+ /usr/sbin/$sysctl 2>/dev/null || \
+ echo unknown)`
case "${UNAME_MACHINE_ARCH}" in
armeb) machine=armeb-unknown ;;
arm*) machine=arm-unknown ;;
sh3el) machine=shl-unknown ;;
sh3eb) machine=sh-unknown ;;
sh5el) machine=sh5le-unknown ;;
+ earmv*)
+ arch=`echo ${UNAME_MACHINE_ARCH} | sed -e 's,^e\(armv[0-9]\).*$,\1,'`
+ endian=`echo ${UNAME_MACHINE_ARCH} | sed -ne 's,^.*\(eb\)$,\1,p'`
+ machine=${arch}${endian}-unknown
+ ;;
*) machine=${UNAME_MACHINE_ARCH}-unknown ;;
esac
# The Operating System including object format, if it has switched
# to ELF recently, or will in the future.
case "${UNAME_MACHINE_ARCH}" in
- arm*|i386|m68k|ns32k|sh3*|sparc|vax)
+ arm*|earm*|i386|m68k|ns32k|sh3*|sparc|vax)
eval $set_cc_for_build
if echo __ELF__ | $CC_FOR_BUILD -E - 2>/dev/null \
| grep -q __ELF__
@@ -182,6 +204,13 @@ case "${UNAME_MACHINE}:${UNAME_SYSTEM}:${UNAME_RELEASE}:${UNAME_VERSION}" in
os=netbsd
;;
esac
+ # Determine ABI tags.
+ case "${UNAME_MACHINE_ARCH}" in
+ earm*)
+ expr='s/^earmv[0-9]/-eabi/;s/eb$//'
+ abi=`echo ${UNAME_MACHINE_ARCH} | sed -e "$expr"`
+ ;;
+ esac
# The OS release
# Debian GNU/NetBSD machines have a different userland, and
# thus, need a distinct triplet. However, they do not need
@@ -198,7 +227,11 @@ case "${UNAME_MACHINE}:${UNAME_SYSTEM}:${UNAME_RELEASE}:${UNAME_VERSION}" in
# Since CPU_TYPE-MANUFACTURER-KERNEL-OPERATING_SYSTEM:
# contains redundant information, the shorter form:
# CPU_TYPE-MANUFACTURER-OPERATING_SYSTEM is used.
- echo "${machine}-${os}${release}"
+ echo "${machine}-${os}${release}${abi}"
+ exit ;;
+ *:Bitrig:*:*)
+ UNAME_MACHINE_ARCH=`arch | sed 's/Bitrig.//'`
+ echo ${UNAME_MACHINE_ARCH}-unknown-bitrig${UNAME_RELEASE}
exit ;;
*:OpenBSD:*:*)
UNAME_MACHINE_ARCH=`arch | sed 's/OpenBSD.//'`
@@ -302,7 +335,7 @@ case "${UNAME_MACHINE}:${UNAME_SYSTEM}:${UNAME_RELEASE}:${UNAME_VERSION}" in
arm:RISC*:1.[012]*:*|arm:riscix:1.[012]*:*)
echo arm-acorn-riscix${UNAME_RELEASE}
exit ;;
- arm:riscos:*:*|arm:RISCOS:*:*)
+ arm*:riscos:*:*|arm*:RISCOS:*:*)
echo arm-unknown-riscos
exit ;;
SR2?01:HI-UX/MPP:*:* | SR8000:HI-UX/MPP:*:*)
@@ -560,8 +593,9 @@ EOF
else
IBM_ARCH=powerpc
fi
- if [ -x /usr/bin/oslevel ] ; then
- IBM_REV=`/usr/bin/oslevel`
+ if [ -x /usr/bin/lslpp ] ; then
+ IBM_REV=`/usr/bin/lslpp -Lqc bos.rte.libc |
+ awk -F: '{ print $3 }' | sed s/[0-9]*$/0/`
else
IBM_REV=${UNAME_VERSION}.${UNAME_RELEASE}
fi
@@ -801,10 +835,13 @@ EOF
i*:CYGWIN*:*)
echo ${UNAME_MACHINE}-pc-cygwin
exit ;;
+ *:MINGW64*:*)
+ echo ${UNAME_MACHINE}-pc-mingw64
+ exit ;;
*:MINGW*:*)
echo ${UNAME_MACHINE}-pc-mingw32
exit ;;
- i*:MSYS*:*)
+ *:MSYS*:*)
echo ${UNAME_MACHINE}-pc-msys
exit ;;
i*:windows32*:*)
@@ -852,21 +889,21 @@ EOF
exit ;;
*:GNU:*:*)
# the GNU system
- echo `echo ${UNAME_MACHINE}|sed -e 's,[-/].*$,,'`-unknown-gnu`echo ${UNAME_RELEASE}|sed -e 's,/.*$,,'`
+ echo `echo ${UNAME_MACHINE}|sed -e 's,[-/].*$,,'`-unknown-${LIBC}`echo ${UNAME_RELEASE}|sed -e 's,/.*$,,'`
exit ;;
*:GNU/*:*:*)
# other systems with GNU libc and userland
- echo ${UNAME_MACHINE}-unknown-`echo ${UNAME_SYSTEM} | sed 's,^[^/]*/,,' | tr '[A-Z]' '[a-z]'``echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'`-gnu
+ echo ${UNAME_MACHINE}-unknown-`echo ${UNAME_SYSTEM} | sed 's,^[^/]*/,,' | tr '[A-Z]' '[a-z]'``echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'`-${LIBC}
exit ;;
i*86:Minix:*:*)
echo ${UNAME_MACHINE}-pc-minix
exit ;;
aarch64:Linux:*:*)
- echo ${UNAME_MACHINE}-unknown-linux-gnu
+ echo ${UNAME_MACHINE}-unknown-linux-${LIBC}
exit ;;
aarch64_be:Linux:*:*)
UNAME_MACHINE=aarch64_be
- echo ${UNAME_MACHINE}-unknown-linux-gnu
+ echo ${UNAME_MACHINE}-unknown-linux-${LIBC}
exit ;;
alpha:Linux:*:*)
case `sed -n '/^cpu model/s/^.*: \(.*\)/\1/p' < /proc/cpuinfo` in
@@ -879,59 +916,54 @@ EOF
EV68*) UNAME_MACHINE=alphaev68 ;;
esac
objdump --private-headers /bin/sh | grep -q ld.so.1
- if test "$?" = 0 ; then LIBC="libc1" ; else LIBC="" ; fi
- echo ${UNAME_MACHINE}-unknown-linux-gnu${LIBC}
+ if test "$?" = 0 ; then LIBC="gnulibc1" ; fi
+ echo ${UNAME_MACHINE}-unknown-linux-${LIBC}
+ exit ;;
+ arc:Linux:*:* | arceb:Linux:*:*)
+ echo ${UNAME_MACHINE}-unknown-linux-${LIBC}
exit ;;
arm*:Linux:*:*)
eval $set_cc_for_build
if echo __ARM_EABI__ | $CC_FOR_BUILD -E - 2>/dev/null \
| grep -q __ARM_EABI__
then
- echo ${UNAME_MACHINE}-unknown-linux-gnu
+ echo ${UNAME_MACHINE}-unknown-linux-${LIBC}
else
if echo __ARM_PCS_VFP | $CC_FOR_BUILD -E - 2>/dev/null \
| grep -q __ARM_PCS_VFP
then
- echo ${UNAME_MACHINE}-unknown-linux-gnueabi
+ echo ${UNAME_MACHINE}-unknown-linux-${LIBC}eabi
else
- echo ${UNAME_MACHINE}-unknown-linux-gnueabihf
+ echo ${UNAME_MACHINE}-unknown-linux-${LIBC}eabihf
fi
fi
exit ;;
avr32*:Linux:*:*)
- echo ${UNAME_MACHINE}-unknown-linux-gnu
+ echo ${UNAME_MACHINE}-unknown-linux-${LIBC}
exit ;;
cris:Linux:*:*)
- echo ${UNAME_MACHINE}-axis-linux-gnu
+ echo ${UNAME_MACHINE}-axis-linux-${LIBC}
exit ;;
crisv32:Linux:*:*)
- echo ${UNAME_MACHINE}-axis-linux-gnu
+ echo ${UNAME_MACHINE}-axis-linux-${LIBC}
exit ;;
frv:Linux:*:*)
- echo ${UNAME_MACHINE}-unknown-linux-gnu
+ echo ${UNAME_MACHINE}-unknown-linux-${LIBC}
exit ;;
hexagon:Linux:*:*)
- echo ${UNAME_MACHINE}-unknown-linux-gnu
+ echo ${UNAME_MACHINE}-unknown-linux-${LIBC}
exit ;;
i*86:Linux:*:*)
- LIBC=gnu
- eval $set_cc_for_build
- sed 's/^ //' << EOF >$dummy.c
- #ifdef __dietlibc__
- LIBC=dietlibc
- #endif
-EOF
- eval `$CC_FOR_BUILD -E $dummy.c 2>/dev/null | grep '^LIBC'`
- echo "${UNAME_MACHINE}-pc-linux-${LIBC}"
+ echo ${UNAME_MACHINE}-pc-linux-${LIBC}
exit ;;
ia64:Linux:*:*)
- echo ${UNAME_MACHINE}-unknown-linux-gnu
+ echo ${UNAME_MACHINE}-unknown-linux-${LIBC}
exit ;;
m32r*:Linux:*:*)
- echo ${UNAME_MACHINE}-unknown-linux-gnu
+ echo ${UNAME_MACHINE}-unknown-linux-${LIBC}
exit ;;
m68*:Linux:*:*)
- echo ${UNAME_MACHINE}-unknown-linux-gnu
+ echo ${UNAME_MACHINE}-unknown-linux-${LIBC}
exit ;;
mips:Linux:*:* | mips64:Linux:*:*)
eval $set_cc_for_build
@@ -950,54 +982,63 @@ EOF
#endif
EOF
eval `$CC_FOR_BUILD -E $dummy.c 2>/dev/null | grep '^CPU'`
- test x"${CPU}" != x && { echo "${CPU}-unknown-linux-gnu"; exit; }
+ test x"${CPU}" != x && { echo "${CPU}-unknown-linux-${LIBC}"; exit; }
;;
- or32:Linux:*:*)
- echo ${UNAME_MACHINE}-unknown-linux-gnu
+ openrisc*:Linux:*:*)
+ echo or1k-unknown-linux-${LIBC}
+ exit ;;
+ or32:Linux:*:* | or1k*:Linux:*:*)
+ echo ${UNAME_MACHINE}-unknown-linux-${LIBC}
exit ;;
padre:Linux:*:*)
- echo sparc-unknown-linux-gnu
+ echo sparc-unknown-linux-${LIBC}
exit ;;
parisc64:Linux:*:* | hppa64:Linux:*:*)
- echo hppa64-unknown-linux-gnu
+ echo hppa64-unknown-linux-${LIBC}
exit ;;
parisc:Linux:*:* | hppa:Linux:*:*)
# Look for CPU level
case `grep '^cpu[^a-z]*:' /proc/cpuinfo 2>/dev/null | cut -d' ' -f2` in
- PA7*) echo hppa1.1-unknown-linux-gnu ;;
- PA8*) echo hppa2.0-unknown-linux-gnu ;;
- *) echo hppa-unknown-linux-gnu ;;
+ PA7*) echo hppa1.1-unknown-linux-${LIBC} ;;
+ PA8*) echo hppa2.0-unknown-linux-${LIBC} ;;
+ *) echo hppa-unknown-linux-${LIBC} ;;
esac
exit ;;
ppc64:Linux:*:*)
- echo powerpc64-unknown-linux-gnu
+ echo powerpc64-unknown-linux-${LIBC}
exit ;;
ppc:Linux:*:*)
- echo powerpc-unknown-linux-gnu
+ echo powerpc-unknown-linux-${LIBC}
+ exit ;;
+ ppc64le:Linux:*:*)
+ echo powerpc64le-unknown-linux-${LIBC}
+ exit ;;
+ ppcle:Linux:*:*)
+ echo powerpcle-unknown-linux-${LIBC}
exit ;;
s390:Linux:*:* | s390x:Linux:*:*)
- echo ${UNAME_MACHINE}-ibm-linux
+ echo ${UNAME_MACHINE}-ibm-linux-${LIBC}
exit ;;
sh64*:Linux:*:*)
- echo ${UNAME_MACHINE}-unknown-linux-gnu
+ echo ${UNAME_MACHINE}-unknown-linux-${LIBC}
exit ;;
sh*:Linux:*:*)
- echo ${UNAME_MACHINE}-unknown-linux-gnu
+ echo ${UNAME_MACHINE}-unknown-linux-${LIBC}
exit ;;
sparc:Linux:*:* | sparc64:Linux:*:*)
- echo ${UNAME_MACHINE}-unknown-linux-gnu
+ echo ${UNAME_MACHINE}-unknown-linux-${LIBC}
exit ;;
tile*:Linux:*:*)
- echo ${UNAME_MACHINE}-unknown-linux-gnu
+ echo ${UNAME_MACHINE}-unknown-linux-${LIBC}
exit ;;
vax:Linux:*:*)
- echo ${UNAME_MACHINE}-dec-linux-gnu
+ echo ${UNAME_MACHINE}-dec-linux-${LIBC}
exit ;;
x86_64:Linux:*:*)
- echo ${UNAME_MACHINE}-unknown-linux-gnu
+ echo ${UNAME_MACHINE}-unknown-linux-${LIBC}
exit ;;
xtensa*:Linux:*:*)
- echo ${UNAME_MACHINE}-unknown-linux-gnu
+ echo ${UNAME_MACHINE}-unknown-linux-${LIBC}
exit ;;
i*86:DYNIX/ptx:4*:*)
# ptx 4.0 does uname -s correctly, with DYNIX/ptx in there.
@@ -1201,6 +1242,9 @@ EOF
BePC:Haiku:*:*) # Haiku running on Intel PC compatible.
echo i586-pc-haiku
exit ;;
+ x86_64:Haiku:*:*)
+ echo x86_64-unknown-haiku
+ exit ;;
SX-4:SUPER-UX:*:*)
echo sx4-nec-superux${UNAME_RELEASE}
exit ;;
@@ -1227,19 +1271,31 @@ EOF
exit ;;
*:Darwin:*:*)
UNAME_PROCESSOR=`uname -p` || UNAME_PROCESSOR=unknown
- case $UNAME_PROCESSOR in
- i386)
- eval $set_cc_for_build
- if [ "$CC_FOR_BUILD" != 'no_compiler_found' ]; then
- if (echo '#ifdef __LP64__'; echo IS_64BIT_ARCH; echo '#endif') | \
- (CCOPTS= $CC_FOR_BUILD -E - 2>/dev/null) | \
- grep IS_64BIT_ARCH >/dev/null
- then
- UNAME_PROCESSOR="x86_64"
- fi
- fi ;;
- unknown) UNAME_PROCESSOR=powerpc ;;
- esac
+ eval $set_cc_for_build
+ if test "$UNAME_PROCESSOR" = unknown ; then
+ UNAME_PROCESSOR=powerpc
+ fi
+ if test `echo "$UNAME_RELEASE" | sed -e 's/\..*//'` -le 10 ; then
+ if [ "$CC_FOR_BUILD" != 'no_compiler_found' ]; then
+ if (echo '#ifdef __LP64__'; echo IS_64BIT_ARCH; echo '#endif') | \
+ (CCOPTS= $CC_FOR_BUILD -E - 2>/dev/null) | \
+ grep IS_64BIT_ARCH >/dev/null
+ then
+ case $UNAME_PROCESSOR in
+ i386) UNAME_PROCESSOR=x86_64 ;;
+ powerpc) UNAME_PROCESSOR=powerpc64 ;;
+ esac
+ fi
+ fi
+ elif test "$UNAME_PROCESSOR" = i386 ; then
+ # Avoid executing cc on OS X 10.9, as it ships with a stub
+ # that puts up a graphical alert prompting to install
+ # developer tools. Any system running Mac OS X 10.7 or
+ # later (Darwin 11 and later) is required to have a 64-bit
+ # processor. This is not true of the ARM version of Darwin
+ # that Apple uses in portable devices.
+ UNAME_PROCESSOR=x86_64
+ fi
echo ${UNAME_PROCESSOR}-apple-darwin${UNAME_RELEASE}
exit ;;
*:procnto*:*:* | *:QNX:[0123456789]*:*)
@@ -1256,7 +1312,7 @@ EOF
NEO-?:NONSTOP_KERNEL:*:*)
echo neo-tandem-nsk${UNAME_RELEASE}
exit ;;
- NSE-?:NONSTOP_KERNEL:*:*)
+ NSE-*:NONSTOP_KERNEL:*:*)
echo nse-tandem-nsk${UNAME_RELEASE}
exit ;;
NSR-?:NONSTOP_KERNEL:*:*)
@@ -1330,157 +1386,6 @@ EOF
exit ;;
esac
-#echo '(No uname command or uname output not recognized.)' 1>&2
-#echo "${UNAME_MACHINE}:${UNAME_SYSTEM}:${UNAME_RELEASE}:${UNAME_VERSION}" 1>&2
-
-eval $set_cc_for_build
-cat >$dummy.c <<EOF
-#ifdef _SEQUENT_
-# include <sys/types.h>
-# include <sys/utsname.h>
-#endif
-main ()
-{
-#if defined (sony)
-#if defined (MIPSEB)
- /* BFD wants "bsd" instead of "newsos". Perhaps BFD should be changed,
- I don't know.... */
- printf ("mips-sony-bsd\n"); exit (0);
-#else
-#include <sys/param.h>
- printf ("m68k-sony-newsos%s\n",
-#ifdef NEWSOS4
- "4"
-#else
- ""
-#endif
- ); exit (0);
-#endif
-#endif
-
-#if defined (__arm) && defined (__acorn) && defined (__unix)
- printf ("arm-acorn-riscix\n"); exit (0);
-#endif
-
-#if defined (hp300) && !defined (hpux)
- printf ("m68k-hp-bsd\n"); exit (0);
-#endif
-
-#if defined (NeXT)
-#if !defined (__ARCHITECTURE__)
-#define __ARCHITECTURE__ "m68k"
-#endif
- int version;
- version=`(hostinfo | sed -n 's/.*NeXT Mach \([0-9]*\).*/\1/p') 2>/dev/null`;
- if (version < 4)
- printf ("%s-next-nextstep%d\n", __ARCHITECTURE__, version);
- else
- printf ("%s-next-openstep%d\n", __ARCHITECTURE__, version);
- exit (0);
-#endif
-
-#if defined (MULTIMAX) || defined (n16)
-#if defined (UMAXV)
- printf ("ns32k-encore-sysv\n"); exit (0);
-#else
-#if defined (CMU)
- printf ("ns32k-encore-mach\n"); exit (0);
-#else
- printf ("ns32k-encore-bsd\n"); exit (0);
-#endif
-#endif
-#endif
-
-#if defined (__386BSD__)
- printf ("i386-pc-bsd\n"); exit (0);
-#endif
-
-#if defined (sequent)
-#if defined (i386)
- printf ("i386-sequent-dynix\n"); exit (0);
-#endif
-#if defined (ns32000)
- printf ("ns32k-sequent-dynix\n"); exit (0);
-#endif
-#endif
-
-#if defined (_SEQUENT_)
- struct utsname un;
-
- uname(&un);
-
- if (strncmp(un.version, "V2", 2) == 0) {
- printf ("i386-sequent-ptx2\n"); exit (0);
- }
- if (strncmp(un.version, "V1", 2) == 0) { /* XXX is V1 correct? */
- printf ("i386-sequent-ptx1\n"); exit (0);
- }
- printf ("i386-sequent-ptx\n"); exit (0);
-
-#endif
-
-#if defined (vax)
-# if !defined (ultrix)
-# include <sys/param.h>
-# if defined (BSD)
-# if BSD == 43
- printf ("vax-dec-bsd4.3\n"); exit (0);
-# else
-# if BSD == 199006
- printf ("vax-dec-bsd4.3reno\n"); exit (0);
-# else
- printf ("vax-dec-bsd\n"); exit (0);
-# endif
-# endif
-# else
- printf ("vax-dec-bsd\n"); exit (0);
-# endif
-# else
- printf ("vax-dec-ultrix\n"); exit (0);
-# endif
-#endif
-
-#if defined (alliant) && defined (i860)
- printf ("i860-alliant-bsd\n"); exit (0);
-#endif
-
- exit (1);
-}
-EOF
-
-$CC_FOR_BUILD -o $dummy $dummy.c 2>/dev/null && SYSTEM_NAME=`$dummy` &&
- { echo "$SYSTEM_NAME"; exit; }
-
-# Apollos put the system type in the environment.
-
-test -d /usr/apollo && { echo ${ISP}-apollo-${SYSTYPE}; exit; }
-
-# Convex versions that predate uname can use getsysinfo(1)
-
-if [ -x /usr/convex/getsysinfo ]
-then
- case `getsysinfo -f cpu_type` in
- c1*)
- echo c1-convex-bsd
- exit ;;
- c2*)
- if getsysinfo -f scalar_acc
- then echo c32-convex-bsd
- else echo c2-convex-bsd
- fi
- exit ;;
- c34*)
- echo c34-convex-bsd
- exit ;;
- c38*)
- echo c38-convex-bsd
- exit ;;
- c4*)
- echo c4-convex-bsd
- exit ;;
- esac
-fi
-
cat >&2 <<EOF
$0: unable to guess system type
diff --git a/contrib/libpcap/config.h.in b/contrib/libpcap/config.h.in
index 4bbb491ec168..e85b2a3f5617 100644
--- a/contrib/libpcap/config.h.in
+++ b/contrib/libpcap/config.h.in
@@ -1,4 +1,4 @@
-/* config.h.in. Generated from configure.in by autoheader. */
+/* config.h.in. Generated from configure.ac by autoheader. */
/* Enable optimizer debugging */
#undef BDEBUG
@@ -76,12 +76,18 @@
/* Define to 1 if you have the <linux/ethtool.h> header file. */
#undef HAVE_LINUX_ETHTOOL_H
+/* Define to 1 if you have the <linux/if_bonding.h> header file. */
+#undef HAVE_LINUX_IF_BONDING_H
+
/* Define to 1 if you have the <linux/if_packet.h> header file. */
#undef HAVE_LINUX_IF_PACKET_H
/* Define to 1 if you have the <linux/net_tstamp.h> header file. */
#undef HAVE_LINUX_NET_TSTAMP_H
+/* Define to 1 if you have the <linux/sockios.h> header file. */
+#undef HAVE_LINUX_SOCKIOS_H
+
/* if tp_vlan_tci exists */
#undef HAVE_LINUX_TPACKET_AUXDATA_TP_VLAN_TCI
@@ -118,16 +124,13 @@
/* if there's an os_proto.h for this platform, to use additional prototypes */
#undef HAVE_OS_PROTO_H
-/* Define to 1 if you have the <paths.h> header file. */
-#undef HAVE_PATHS_H
-
/* define if net/pfvar.h defines PF_NAT through PF_NORDR */
#undef HAVE_PF_NAT_THROUGH_PF_NORDR
-/* define if you have a Septel API */
+/* define if you have the Septel API */
#undef HAVE_SEPTEL_API
-/* define if you have Myricom SNF API */
+/* define if you have the Myricom SNF API */
#undef HAVE_SNF_API
/* Define to 1 if you have the `snprintf' function. */
@@ -163,6 +166,9 @@
/* Define to 1 if you have the `strlcpy' function. */
#undef HAVE_STRLCPY
+/* Define to 1 if you have the `strtok_r' function. */
+#undef HAVE_STRTOK_R
+
/* Define to 1 if the system has the type `struct BPF_TIMEVAL'. */
#undef HAVE_STRUCT_BPF_TIMEVAL
@@ -181,6 +187,9 @@
/* Define to 1 if you have the <sys/ioccom.h> header file. */
#undef HAVE_SYS_IOCCOM_H
+/* Define to 1 if you have the <sys/select.h> header file. */
+#undef HAVE_SYS_SELECT_H
+
/* Define to 1 if you have the <sys/sockio.h> header file. */
#undef HAVE_SYS_SOCKIO_H
@@ -190,6 +199,9 @@
/* Define to 1 if you have the <sys/types.h> header file. */
#undef HAVE_SYS_TYPES_H
+/* define if you have the TurboCap API */
+#undef HAVE_TC_API
+
/* if if_packet.h has tpacket_stats defined */
#undef HAVE_TPACKET_STATS
@@ -199,9 +211,6 @@
/* if struct usbdevfs_ctrltransfer has bRequestType */
#undef HAVE_USBDEVFS_CTRLTRANSFER_BREQUESTTYPE
-/* define if version.h is generated in the build procedure */
-#undef HAVE_VERSION_H
-
/* Define to 1 if you have the `vsnprintf' function. */
#undef HAVE_VSNPRINTF
@@ -220,9 +229,6 @@
/* path for device for USB sniffing */
#undef LINUX_USB_MON_DEV
-/* if we need a pcap_parse wrapper around yyparse */
-#undef NEED_YYPARSE_WRAPPER
-
/* Define to 1 if netinet/ether.h declares `ether_hostton' */
#undef NETINET_ETHER_H_DECLARES_ETHER_HOSTTON
@@ -259,18 +265,15 @@
/* target host supports Bluetooth Monitor */
#undef PCAP_SUPPORT_BT_MONITOR
-/* target host supports CAN sniffing */
-#undef PCAP_SUPPORT_CAN
-
-/* target host supports canusb */
-#undef PCAP_SUPPORT_CANUSB
-
/* support D-Bus sniffing */
#undef PCAP_SUPPORT_DBUS
/* target host supports netfilter sniffing */
#undef PCAP_SUPPORT_NETFILTER
+/* use Linux packet ring capture if available */
+#undef PCAP_SUPPORT_PACKET_RING
+
/* target host supports USB sniffing */
#undef PCAP_SUPPORT_USB
@@ -286,6 +289,10 @@
/* Enable parser debugging */
#undef YYDEBUG
+/* Define to 1 if `lex' declares `yytext' as a `char *' by default, not a
+ `char[]'. */
+#undef YYTEXT_POINTER
+
/* Enable large inode numbers on Mac OS X 10.5. */
#ifndef _DARWIN_USE_64_BIT_INODE
# define _DARWIN_USE_64_BIT_INODE 1
diff --git a/contrib/libpcap/config.sub b/contrib/libpcap/config.sub
index 59bb593f109c..bc855a2a910e 100755
--- a/contrib/libpcap/config.sub
+++ b/contrib/libpcap/config.sub
@@ -1,24 +1,18 @@
#! /bin/sh
# Configuration validation subroutine script.
-# Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999,
-# 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010,
-# 2011, 2012 Free Software Foundation, Inc.
+# Copyright 1992-2015 Free Software Foundation, Inc.
-timestamp='2012-04-18'
+timestamp='2015-02-22'
-# This file is (in principle) common to ALL GNU software.
-# The presence of a machine in this file suggests that SOME GNU software
-# can handle that machine. It does not imply ALL GNU software can.
-#
-# This file is free software; you can redistribute it and/or modify
-# it under the terms of the GNU General Public License as published by
-# the Free Software Foundation; either version 2 of the License, or
+# This file is free software; you can redistribute it and/or modify it
+# under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 3 of the License, or
# (at your option) any later version.
#
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-# GNU General Public License for more details.
+# This program is distributed in the hope that it will be useful, but
+# WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+# General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, see <http://www.gnu.org/licenses/>.
@@ -26,11 +20,12 @@ timestamp='2012-04-18'
# As a special exception to the GNU General Public License, if you
# distribute this file as part of a program that contains a
# configuration script generated by Autoconf, you may include it under
-# the same distribution terms that you use for the rest of that program.
+# the same distribution terms that you use for the rest of that
+# program. This Exception is an additional permission under section 7
+# of the GNU General Public License, version 3 ("GPLv3").
-# Please send patches to <config-patches@gnu.org>. Submit a context
-# diff and a properly formatted GNU ChangeLog entry.
+# Please send patches to <config-patches@gnu.org>.
#
# Configuration subroutine to validate and canonicalize a configuration type.
# Supply the specified configuration type as an argument.
@@ -73,9 +68,7 @@ Report bugs and patches to <config-patches@gnu.org>."
version="\
GNU config.sub ($timestamp)
-Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000,
-2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011, 2012
-Free Software Foundation, Inc.
+Copyright 1992-2015 Free Software Foundation, Inc.
This is free software; see the source for copying conditions. There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE."
@@ -123,8 +116,8 @@ esac
maybe_os=`echo $1 | sed 's/^\(.*\)-\([^-]*-[^-]*\)$/\2/'`
case $maybe_os in
nto-qnx* | linux-gnu* | linux-android* | linux-dietlibc | linux-newlib* | \
- linux-uclibc* | uclinux-uclibc* | uclinux-gnu* | kfreebsd*-gnu* | \
- knetbsd*-gnu* | netbsd*-gnu* | \
+ linux-musl* | linux-uclibc* | uclinux-uclibc* | uclinux-gnu* | kfreebsd*-gnu* | \
+ knetbsd*-gnu* | netbsd*-gnu* | netbsd*-eabi* | \
kopensolaris*-gnu* | \
storm-chaos* | os2-emx* | rtmk-nova*)
os=-$maybe_os
@@ -156,7 +149,7 @@ case $os in
-convergent* | -ncr* | -news | -32* | -3600* | -3100* | -hitachi* |\
-c[123]* | -convex* | -sun | -crds | -omron* | -dg | -ultra | -tti* | \
-harris | -dolphin | -highlevel | -gould | -cbm | -ns | -masscomp | \
- -apple | -axis | -knuth | -cray | -microblaze)
+ -apple | -axis | -knuth | -cray | -microblaze*)
os=
basic_machine=$1
;;
@@ -259,21 +252,24 @@ case $basic_machine in
| alpha | alphaev[4-8] | alphaev56 | alphaev6[78] | alphapca5[67] \
| alpha64 | alpha64ev[4-8] | alpha64ev56 | alpha64ev6[78] | alpha64pca5[67] \
| am33_2.0 \
- | arc | arm | arm[bl]e | arme[lb] | armv[2345] | armv[345][lb] | avr | avr32 \
- | be32 | be64 \
+ | arc | arceb \
+ | arm | arm[bl]e | arme[lb] | armv[2-8] | armv[3-8][lb] | armv7[arm] \
+ | avr | avr32 \
+ | be32 | be64 \
| bfin \
- | c4x | clipper \
+ | c4x | c8051 | clipper \
| d10v | d30v | dlx | dsp16xx \
| epiphany \
- | fido | fr30 | frv \
+ | fido | fr30 | frv | ft32 \
| h8300 | h8500 | hppa | hppa1.[01] | hppa2.0 | hppa2.0[nw] | hppa64 \
| hexagon \
| i370 | i860 | i960 | ia64 \
| ip2k | iq2000 \
+ | k1om \
| le32 | le64 \
| lm32 \
| m32c | m32r | m32rle | m68000 | m68k | m88k \
- | maxq | mb | microblaze | mcore | mep | metag \
+ | maxq | mb | microblaze | microblazeel | mcore | mep | metag \
| mips | mipsbe | mipseb | mipsel | mipsle \
| mips16 \
| mips64 | mips64el \
@@ -287,23 +283,26 @@ case $basic_machine in
| mips64vr5900 | mips64vr5900el \
| mipsisa32 | mipsisa32el \
| mipsisa32r2 | mipsisa32r2el \
+ | mipsisa32r6 | mipsisa32r6el \
| mipsisa64 | mipsisa64el \
| mipsisa64r2 | mipsisa64r2el \
+ | mipsisa64r6 | mipsisa64r6el \
| mipsisa64sb1 | mipsisa64sb1el \
| mipsisa64sr71k | mipsisa64sr71kel \
+ | mipsr5900 | mipsr5900el \
| mipstx39 | mipstx39el \
| mn10200 | mn10300 \
| moxie \
| mt \
| msp430 \
| nds32 | nds32le | nds32be \
- | nios | nios2 \
+ | nios | nios2 | nios2eb | nios2el \
| ns16k | ns32k \
- | open8 \
- | or32 \
+ | open8 | or1k | or1knd | or32 \
| pdp10 | pdp11 | pj | pjl \
| powerpc | powerpc64 | powerpc64le | powerpcle \
| pyramid \
+ | riscv32 | riscv64 \
| rl78 | rx \
| score \
| sh | sh[1234] | sh[24]a | sh[24]aeb | sh[23]e | sh[34]eb | sheb | shbe | shle | sh[1234]le | sh3ele \
@@ -314,6 +313,7 @@ case $basic_machine in
| tahoe | tic4x | tic54x | tic55x | tic6x | tic80 | tron \
| ubicom32 \
| v850 | v850e | v850e1 | v850e2 | v850es | v850e2v3 \
+ | visium \
| we32k \
| x86 | xc16x | xstormy16 | xtensa \
| z8k | z80)
@@ -328,7 +328,10 @@ case $basic_machine in
c6x)
basic_machine=tic6x-unknown
;;
- m6811 | m68hc11 | m6812 | m68hc12 | m68hcs12x | picochip)
+ leon|leon[3-9])
+ basic_machine=sparc-$basic_machine
+ ;;
+ m6811 | m68hc11 | m6812 | m68hc12 | m68hcs12x | nvptx | picochip)
basic_machine=$basic_machine-unknown
os=-none
;;
@@ -370,13 +373,13 @@ case $basic_machine in
| aarch64-* | aarch64_be-* \
| alpha-* | alphaev[4-8]-* | alphaev56-* | alphaev6[78]-* \
| alpha64-* | alpha64ev[4-8]-* | alpha64ev56-* | alpha64ev6[78]-* \
- | alphapca5[67]-* | alpha64pca5[67]-* | arc-* \
+ | alphapca5[67]-* | alpha64pca5[67]-* | arc-* | arceb-* \
| arm-* | armbe-* | armle-* | armeb-* | armv*-* \
| avr-* | avr32-* \
| be32-* | be64-* \
| bfin-* | bs2000-* \
| c[123]* | c30-* | [cjt]90-* | c4x-* \
- | clipper-* | craynv-* | cydra-* \
+ | c8051-* | clipper-* | craynv-* | cydra-* \
| d10v-* | d30v-* | dlx-* \
| elxsi-* \
| f30[01]-* | f700-* | fido-* | fr30-* | frv-* | fx80-* \
@@ -385,11 +388,13 @@ case $basic_machine in
| hexagon-* \
| i*86-* | i860-* | i960-* | ia64-* \
| ip2k-* | iq2000-* \
+ | k1om-* \
| le32-* | le64-* \
| lm32-* \
| m32c-* | m32r-* | m32rle-* \
| m68000-* | m680[012346]0-* | m68360-* | m683?2-* | m68k-* \
- | m88110-* | m88k-* | maxq-* | mcore-* | metag-* | microblaze-* \
+ | m88110-* | m88k-* | maxq-* | mcore-* | metag-* \
+ | microblaze-* | microblazeel-* \
| mips-* | mipsbe-* | mipseb-* | mipsel-* | mipsle-* \
| mips16-* \
| mips64-* | mips64el-* \
@@ -403,18 +408,22 @@ case $basic_machine in
| mips64vr5900-* | mips64vr5900el-* \
| mipsisa32-* | mipsisa32el-* \
| mipsisa32r2-* | mipsisa32r2el-* \
+ | mipsisa32r6-* | mipsisa32r6el-* \
| mipsisa64-* | mipsisa64el-* \
| mipsisa64r2-* | mipsisa64r2el-* \
+ | mipsisa64r6-* | mipsisa64r6el-* \
| mipsisa64sb1-* | mipsisa64sb1el-* \
| mipsisa64sr71k-* | mipsisa64sr71kel-* \
+ | mipsr5900-* | mipsr5900el-* \
| mipstx39-* | mipstx39el-* \
| mmix-* \
| mt-* \
| msp430-* \
| nds32-* | nds32le-* | nds32be-* \
- | nios-* | nios2-* \
+ | nios-* | nios2-* | nios2eb-* | nios2el-* \
| none-* | np1-* | ns16k-* | ns32k-* \
| open8-* \
+ | or1k*-* \
| orion-* \
| pdp10-* | pdp11-* | pj-* | pjl-* | pn-* | power-* \
| powerpc-* | powerpc64-* | powerpc64le-* | powerpcle-* \
@@ -432,6 +441,7 @@ case $basic_machine in
| ubicom32-* \
| v850-* | v850e-* | v850e1-* | v850es-* | v850e2-* | v850e2v3-* \
| vax-* \
+ | visium-* \
| we32k-* \
| x86-* | x86_64-* | xc16x-* | xps100-* \
| xstormy16-* | xtensa*-* \
@@ -769,6 +779,9 @@ case $basic_machine in
basic_machine=m68k-isi
os=-sysv
;;
+ leon-*|leon[3-9]-*)
+ basic_machine=sparc-`echo $basic_machine | sed 's/-.*//'`
+ ;;
m68knommu)
basic_machine=m68k-unknown
os=-linux
@@ -788,11 +801,15 @@ case $basic_machine in
basic_machine=ns32k-utek
os=-sysv
;;
- microblaze)
+ microblaze*)
basic_machine=microblaze-xilinx
;;
+ mingw64)
+ basic_machine=x86_64-pc
+ os=-mingw64
+ ;;
mingw32)
- basic_machine=i386-pc
+ basic_machine=i686-pc
os=-mingw32
;;
mingw32ce)
@@ -820,6 +837,10 @@ case $basic_machine in
basic_machine=powerpc-unknown
os=-morphos
;;
+ moxiebox)
+ basic_machine=moxie-unknown
+ os=-moxiebox
+ ;;
msdos)
basic_machine=i386-pc
os=-msdos
@@ -828,7 +849,7 @@ case $basic_machine in
basic_machine=`echo $basic_machine | sed -e 's/ms1-/mt-/'`
;;
msys)
- basic_machine=i386-pc
+ basic_machine=i686-pc
os=-msys
;;
mvs)
@@ -1019,7 +1040,11 @@ case $basic_machine in
basic_machine=i586-unknown
os=-pw32
;;
- rdos)
+ rdos | rdos64)
+ basic_machine=x86_64-pc
+ os=-rdos
+ ;;
+ rdos32)
basic_machine=i386-pc
os=-rdos
;;
@@ -1346,29 +1371,29 @@ case $os in
-gnu* | -bsd* | -mach* | -minix* | -genix* | -ultrix* | -irix* \
| -*vms* | -sco* | -esix* | -isc* | -aix* | -cnk* | -sunos | -sunos[34]*\
| -hpux* | -unos* | -osf* | -luna* | -dgux* | -auroraux* | -solaris* \
- | -sym* | -kopensolaris* \
+ | -sym* | -kopensolaris* | -plan9* \
| -amigaos* | -amigados* | -msdos* | -newsos* | -unicos* | -aof* \
| -aos* | -aros* \
| -nindy* | -vxsim* | -vxworks* | -ebmon* | -hms* | -mvs* \
| -clix* | -riscos* | -uniplus* | -iris* | -rtu* | -xenix* \
| -hiux* | -386bsd* | -knetbsd* | -mirbsd* | -netbsd* \
- | -openbsd* | -solidbsd* \
+ | -bitrig* | -openbsd* | -solidbsd* \
| -ekkobsd* | -kfreebsd* | -freebsd* | -riscix* | -lynxos* \
| -bosx* | -nextstep* | -cxux* | -aout* | -elf* | -oabi* \
| -ptx* | -coff* | -ecoff* | -winnt* | -domain* | -vsta* \
| -udi* | -eabi* | -lites* | -ieee* | -go32* | -aux* \
| -chorusos* | -chorusrdb* | -cegcc* \
| -cygwin* | -msys* | -pe* | -psos* | -moss* | -proelf* | -rtems* \
- | -mingw32* | -linux-gnu* | -linux-android* \
- | -linux-newlib* | -linux-uclibc* \
- | -uxpv* | -beos* | -mpeix* | -udk* \
+ | -mingw32* | -mingw64* | -linux-gnu* | -linux-android* \
+ | -linux-newlib* | -linux-musl* | -linux-uclibc* \
+ | -uxpv* | -beos* | -mpeix* | -udk* | -moxiebox* \
| -interix* | -uwin* | -mks* | -rhapsody* | -darwin* | -opened* \
| -openstep* | -oskit* | -conix* | -pw32* | -nonstopux* \
| -storm-chaos* | -tops10* | -tenex* | -tops20* | -its* \
| -os2* | -vos* | -palmos* | -uclinux* | -nucleus* \
| -morphos* | -superux* | -rtmk* | -rtmk-nova* | -windiss* \
| -powermax* | -dnix* | -nx6 | -nx7 | -sei* | -dragonfly* \
- | -skyos* | -haiku* | -rdos* | -toppers* | -drops* | -es*)
+ | -skyos* | -haiku* | -rdos* | -toppers* | -drops* | -es* | -tirtos*)
# Remember, each alternative MUST END IN *, to match a version number.
;;
-qnx*)
@@ -1492,9 +1517,6 @@ case $os in
-aros*)
os=-aros
;;
- -kaos*)
- os=-kaos
- ;;
-zvmoe)
os=-zvmoe
;;
@@ -1543,6 +1565,12 @@ case $basic_machine in
c4x-* | tic4x-*)
os=-coff
;;
+ c8051-*)
+ os=-elf
+ ;;
+ hexagon-*)
+ os=-elf
+ ;;
tic54x-*)
os=-coff
;;
diff --git a/contrib/libpcap/config/have_siocglifconf.c b/contrib/libpcap/config/have_siocglifconf.c
new file mode 100644
index 000000000000..5a67abc192c4
--- /dev/null
+++ b/contrib/libpcap/config/have_siocglifconf.c
@@ -0,0 +1,6 @@
+#include <sys/ioctl.h>
+#include <sys/socket.h>
+#include <sys/sockio.h>
+int main() {
+ ioctl(0, SIOCGLIFCONF, (char *)0);
+}
diff --git a/contrib/libpcap/configure b/contrib/libpcap/configure
index e665cb9bbc0c..4c64875e3e69 100755
--- a/contrib/libpcap/configure
+++ b/contrib/libpcap/configure
@@ -623,13 +623,10 @@ ac_subst_vars='LTLIBOBJS
INSTALL_DATA
INSTALL_SCRIPT
INSTALL_PROGRAM
+PCAP_SUPPORT_PACKET_RING
DBUS_SRC
PCAP_SUPPORT_DBUS
PKGCONFIG
-CAN_SRC
-PCAP_SUPPORT_CAN
-CANUSB_SRC
-PCAP_SUPPORT_CANUSB
BT_MONITOR_SRC
BT_SRC
PCAP_SUPPORT_BT
@@ -643,11 +640,13 @@ DYEXT
SSRC
ADDLARCHIVEOBJS
ADDLOBJS
+V_YACC
V_RPATH_OPT
V_SONAME_OPT
V_SHLIB_OPT
V_SHLIB_CMD
V_PCAP
+V_LEX
V_INCLS
V_FINDALLDEVS
V_DEFS
@@ -657,9 +656,13 @@ DEPENDENCY_CFLAG
LN_S
AR
RANLIB
-V_YACC
-V_LEX
+YFLAGS
+YACC
+LEXLIB
+LEX_OUTPUT_ROOT
+LEX
HAVE_LINUX_TPACKET_AUXDATA
+VALGRINDTEST
LIBOBJS
EGREP
GREP
@@ -741,14 +744,13 @@ with_septel
with_snf
with_snf_includes
with_snf_libraries
-with_flex
-with_bison
+with_turbocap
enable_universal
enable_shared
+enable_usb
enable_bluetooth
-enable_canusb
-enable_can
enable_dbus
+enable_packet_ring
'
ac_precious_vars='build_alias
host_alias
@@ -758,7 +760,9 @@ CFLAGS
LDFLAGS
LIBS
CPPFLAGS
-CPP'
+CPP
+YACC
+YFLAGS'
# Initialize some variables set by options.
@@ -1380,14 +1384,13 @@ Optional Features:
--disable-universal don't build universal on OS X
--enable-shared build shared libraries [default=yes, if support
available]
- --enable-bluetooth enable Bluetooth support [default=yes, if support
- available]
- --enable-canusb enable canusb support [default=yes, if support
+ --enable-usb enable nusb support [default=yes, if support
available]
- --enable-can enable CAN support [default=yes, if support
+ --enable-bluetooth enable Bluetooth support [default=yes, if support
available]
--enable-dbus enable D-Bus capture support [default=yes, if
support available]
+ --enable-packet-ring enable Linux packet ring support [default=yes]
Optional Packages:
--with-PACKAGE[=ARG] use PACKAGE [ARG=yes]
@@ -1397,20 +1400,23 @@ Optional Packages:
--with-pcap=TYPE use packet capture TYPE
--without-libnl disable libnl support [default=yes, on Linux, if
present]
- --with-dag[=DIR] include Endace DAG support ["yes", "no" or DIR;
- default="yes" on BSD and Linux if present]
- --with-dag-includes=DIR Endace DAG include directory
- --with-dag-libraries=DIR
- Endace DAG library directory
+ --with-dag[=DIR] include Endace DAG support (located in directory
+ DIR, if supplied). [default=yes, if present]
+ --with-dag-includes=IDIR
+ Endace DAG include directory, if not DIR/include
+ --with-dag-libraries=LDIR
+ Endace DAG library directory, if not DIR/lib
--with-septel[=DIR] include Septel support (located in directory DIR, if
- supplied). [default=yes, on Linux, if present]
- --with-snf[=DIR] include Myricom SNF support ["yes", "no" or DIR;
- default="yes" on BSD and Linux if present]
- --with-snf-includes=DIR Myricom SNF include directory
- --with-snf-libraries=DIR
- Myricom SNF library directory
- --without-flex don't use flex
- --without-bison don't use bison
+ supplied). [default=yes, if present]
+ --with-snf[=DIR] include Myricom SNF support (located in directory
+ DIR, if supplied). [default=yes, if present]
+ --with-snf-includes=IDIR
+ Myricom SNF include directory, if not DIR/include
+ --with-snf-libraries=LDIR
+ Myricom SNF library directory, if not DIR/lib
+ --with-turbocap[=DIR] include Riverbed TurboCap support (located in
+ directory DIR, if supplied). [default=yes, if
+ present]
Some influential environment variables:
CC C compiler command
@@ -1421,6 +1427,12 @@ Some influential environment variables:
CPPFLAGS (Objective) C/C++ preprocessor flags, e.g. -I<include dir> if
you have headers in a nonstandard directory <include dir>
CPP C preprocessor
+ YACC The `Yet Another Compiler Compiler' implementation to use.
+ Defaults to the first program found out of: `bison -y', `byacc',
+ `yacc'.
+ YFLAGS The list of arguments that will be passed by default to $YACC.
+ This script will default YFLAGS to the empty string to avoid a
+ default value of `-d' given by some make applications.
Use these variables to override the choices made by `configure' or to help
it to find libraries and programs with nonstandard names/locations.
@@ -3308,11 +3320,61 @@ ac_compiler_gnu=$ac_cv_c_compiler_gnu
+
if test "$GCC" = yes ; then
#
# -Werror forces warnings to be errors.
#
ac_lbl_cc_force_warning_errors=-Werror
+
+ #
+ # Try to have the compiler default to hiding symbols,
+ # so that only symbols explicitly exported with
+ # PCAP_API will be visible outside (shared) libraries.
+ #
+
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether the compiler supports the -fvisibility=hidden option" >&5
+$as_echo_n "checking whether the compiler supports the -fvisibility=hidden option... " >&6; }
+ save_CFLAGS="$CFLAGS"
+ if expr "x-fvisibility=hidden" : "x-W.*" >/dev/null
+ then
+ CFLAGS="$CFLAGS $ac_lbl_unknown_warning_option_error -fvisibility=hidden"
+ elif expr "x-fvisibility=hidden" : "x-f.*" >/dev/null
+ then
+ CFLAGS="$CFLAGS -Werror -fvisibility=hidden"
+ elif expr "x-fvisibility=hidden" : "x-m.*" >/dev/null
+ then
+ CFLAGS="$CFLAGS -Werror -fvisibility=hidden"
+ else
+ CFLAGS="$CFLAGS -fvisibility=hidden"
+ fi
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+
+int
+main ()
+{
+return 0
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
+$as_echo "yes" >&6; }
+ CFLAGS="$save_CFLAGS"
+ V_CCOPT="$V_CCOPT -fvisibility=hidden"
+
+else
+
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+ CFLAGS="$save_CFLAGS"
+
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+
else
V_INCLS="$V_INCLS -I/usr/local/include"
LDFLAGS="$LDFLAGS -L/usr/local/lib"
@@ -3325,6 +3387,55 @@ ac_compiler_gnu=$ac_cv_c_compiler_gnu
# of which use -Werror to force warnings to be errors.
#
ac_lbl_cc_force_warning_errors=-Werror
+
+ #
+ # Try to have the compiler default to hiding symbols,
+ # so that only symbols explicitly exported with
+ # PCAP_API will be visible outside (shared) libraries.
+ #
+
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether the compiler supports the -fvisibility=hidden option" >&5
+$as_echo_n "checking whether the compiler supports the -fvisibility=hidden option... " >&6; }
+ save_CFLAGS="$CFLAGS"
+ if expr "x-fvisibility=hidden" : "x-W.*" >/dev/null
+ then
+ CFLAGS="$CFLAGS $ac_lbl_unknown_warning_option_error -fvisibility=hidden"
+ elif expr "x-fvisibility=hidden" : "x-f.*" >/dev/null
+ then
+ CFLAGS="$CFLAGS -Werror -fvisibility=hidden"
+ elif expr "x-fvisibility=hidden" : "x-m.*" >/dev/null
+ then
+ CFLAGS="$CFLAGS -Werror -fvisibility=hidden"
+ else
+ CFLAGS="$CFLAGS -fvisibility=hidden"
+ fi
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+
+int
+main ()
+{
+return 0
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
+$as_echo "yes" >&6; }
+ CFLAGS="$save_CFLAGS"
+ V_CCOPT="$V_CCOPT -fvisibility=hidden"
+
+else
+
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+ CFLAGS="$save_CFLAGS"
+
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+
;;
hpux*)
@@ -3399,6 +3510,55 @@ ac_compiler_gnu=$ac_cv_c_compiler_gnu
# warnings to be treated as errors.
#
ac_lbl_cc_force_warning_errors=-errwarn
+
+ #
+ # Try to have the compiler default to hiding symbols,
+ # so that only symbols explicitly exported with
+ # PCAP_API will be visible outside (shared) libraries.
+ #
+
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether the compiler supports the -xldscope=hidden option" >&5
+$as_echo_n "checking whether the compiler supports the -xldscope=hidden option... " >&6; }
+ save_CFLAGS="$CFLAGS"
+ if expr "x-xldscope=hidden" : "x-W.*" >/dev/null
+ then
+ CFLAGS="$CFLAGS $ac_lbl_unknown_warning_option_error -xldscope=hidden"
+ elif expr "x-xldscope=hidden" : "x-f.*" >/dev/null
+ then
+ CFLAGS="$CFLAGS -Werror -xldscope=hidden"
+ elif expr "x-xldscope=hidden" : "x-m.*" >/dev/null
+ then
+ CFLAGS="$CFLAGS -Werror -xldscope=hidden"
+ else
+ CFLAGS="$CFLAGS -xldscope=hidden"
+ fi
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+
+int
+main ()
+{
+return 0
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
+$as_echo "yes" >&6; }
+ CFLAGS="$save_CFLAGS"
+ V_CCOPT="$V_CCOPT -xldscope=hidden"
+
+else
+
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+ CFLAGS="$save_CFLAGS"
+
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+
;;
ultrix*)
@@ -3407,8 +3567,7 @@ $as_echo_n "checking that Ultrix $CC hacks const in prototypes... " >&6; }
if ${ac_cv_lbl_cc_const_proto+:} false; then :
$as_echo_n "(cached) " >&6
else
-
-cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
#include <sys/types.h>
int
@@ -4572,7 +4731,7 @@ $as_echo "#define HAVE_FSEEKO 1" >>confdefs.h
fi
-for ac_header in sys/ioccom.h sys/sockio.h limits.h paths.h
+for ac_header in sys/ioccom.h sys/select.h sys/sockio.h limits.h
do :
as_ac_Header=`$as_echo "ac_cv_header_$ac_header" | $as_tr_sh`
ac_fn_c_check_header_mongrel "$LINENO" "$ac_header" "$as_ac_Header" "$ac_includes_default"
@@ -4704,6 +4863,28 @@ done
fi
+case "$host_os" in
+linux*|uclinux*)
+ for ac_header in linux/sockios.h linux/if_bonding.h
+do :
+ as_ac_Header=`$as_echo "ac_cv_header_$ac_header" | $as_tr_sh`
+ac_fn_c_check_header_compile "$LINENO" "$ac_header" "$as_ac_Header" "
+#include <sys/socket.h>
+#include <linux/if.h>
+
+"
+if eval test \"x\$"$as_ac_Header"\" = x"yes"; then :
+ cat >>confdefs.h <<_ACEOF
+#define `$as_echo "HAVE_$ac_header" | $as_tr_cpp` 1
+_ACEOF
+
+fi
+
+done
+
+ ;;
+esac
+
if test "$GCC" = yes ; then
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for ANSI ioctl definitions" >&5
$as_echo_n "checking for ANSI ioctl definitions... " >&6; }
@@ -4787,6 +4968,29 @@ esac
fi
+needstrtok_r=no
+for ac_func in strtok_r
+do :
+ ac_fn_c_check_func "$LINENO" "strtok_r" "ac_cv_func_strtok_r"
+if test "x$ac_cv_func_strtok_r" = xyes; then :
+ cat >>confdefs.h <<_ACEOF
+#define HAVE_STRTOK_R 1
+_ACEOF
+
+else
+ needstrtok_r=yes
+fi
+done
+
+if test $needstrtok_r = yes; then
+ case " $LIBOBJS " in
+ *" strtok_r.$ac_objext "* ) ;;
+ *) LIBOBJS="$LIBOBJS strtok_r.$ac_objext"
+ ;;
+esac
+
+fi
+
#
# Do this before checking for ether_hostton(), as it's a
# "gethostbyname() -ish function".
@@ -5204,6 +5408,13 @@ fi
$as_echo "${enable_protochain}" >&6; }
#
+# valgrindtest directly uses the native capture mechanism, but
+# only tests with BPF and PF_PACKET sockets; only enable it if
+# we have BPF or PF_PACKET sockets.
+#
+VALGRINDTEST=
+
+#
# SITA support is mutually exclusive with native capture support;
# "--with-sita" selects SITA support.
#
@@ -5218,7 +5429,6 @@ $as_echo "#define SITA 1" >>confdefs.h
{ $as_echo "$as_me:${as_lineno-$LINENO}: Enabling SITA ACN support" >&5
$as_echo "$as_me: Enabling SITA ACN support" >&6;}
V_PCAP=sita
- V_FINDALLDEVS=sita
fi
else
@@ -5244,8 +5454,18 @@ elif test -r /dev/bpf -o -h /dev/bpf ; then
$as_echo "#define HAVE_CLONING_BPF 1" >>confdefs.h
+
+ #
+ # We have BPF, so build valgrindtest with "make test".
+ #
+ VALGRINDTEST=valgrindtest
elif test -r /dev/bpf0 ; then
V_PCAP=bpf
+
+ #
+ # We have BPF, so build valgrindtest with "make test".
+ #
+ VALGRINDTEST=valgrindtest
elif test -r /usr/include/net/pfilt.h ; then
V_PCAP=pf
elif test -r /dev/enet ; then
@@ -5256,6 +5476,12 @@ elif test -r /usr/include/sys/net/nit.h ; then
V_PCAP=nit
elif test -r /usr/include/linux/socket.h ; then
V_PCAP=linux
+
+ #
+ # XXX - this won't work with older kernels that have SOCK_PACKET
+ # sockets but not PF_PACKET sockets.
+ #
+ VALGRINDTEST=valgrindtest
elif test -r /usr/include/net/raw.h ; then
V_PCAP=snoop
elif test -r /usr/include/odmi.h ; then
@@ -5267,6 +5493,11 @@ elif test -r /usr/include/odmi.h ; then
V_PCAP=bpf
elif test -c /dev/bpf0 ; then # check again in case not readable
V_PCAP=bpf
+
+ #
+ # We have BPF, so build valgrindtest with "make test".
+ #
+ VALGRINDTEST=valgrindtest
elif test -r /usr/include/sys/dlpi.h ; then
V_PCAP=dlpi
elif test -c /dev/enet ; then # check again in case not readable
@@ -5279,6 +5510,7 @@ fi
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $V_PCAP" >&5
$as_echo "$V_PCAP" >&6; }
+
#
# Do capture-mechanism-dependent tests.
#
@@ -5512,6 +5744,13 @@ fi
if test x$with_libnl != xno ; then
have_any_nl="no"
+ incdir=-I/usr/include/libnl3
+ libnldir=
+ if test x$withval != x ; then
+ libnldir=-L${withval}/lib/.libs
+ incdir=-I${withval}/include
+ fi
+
#
# Try libnl 3.x first.
#
@@ -5521,7 +5760,7 @@ if ${ac_cv_lib_nl_3_nl_socket_alloc+:} false; then :
$as_echo_n "(cached) " >&6
else
ac_check_lib_save_LIBS=$LIBS
-LIBS="-lnl-3 $LIBS"
+LIBS="-lnl-3 ${incdir} ${libnldir} -lnl-genl-3 -lnl-3 $LIBS"
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
@@ -5556,7 +5795,7 @@ if test "x$ac_cv_lib_nl_3_nl_socket_alloc" = xyes; then :
#
# Yes, we have libnl 3.x.
#
- LIBS="-lnl-genl-3 -lnl-3 $LIBS"
+ LIBS="${libnldir} -lnl-genl-3 -lnl-3 $LIBS"
$as_echo "#define HAVE_LIBNL 1" >>confdefs.h
@@ -5569,7 +5808,7 @@ $as_echo "#define HAVE_LIBNL_NLE 1" >>confdefs.h
$as_echo "#define HAVE_LIBNL_SOCKETS 1" >>confdefs.h
- V_INCLS="$V_INCLS -I/usr/include/libnl3"
+ V_INCLS="$V_INCLS ${incdir}"
have_any_nl="yes"
fi
@@ -5620,7 +5859,7 @@ if test "x$ac_cv_lib_nl_nl_socket_alloc" = xyes; then :
#
# Yes, we have libnl 2.x.
#
- LIBS="-lnl-genl -lnl $LIBS"
+ LIBS="${libnldir} -lnl-genl -lnl $LIBS"
$as_echo "#define HAVE_LIBNL 1" >>confdefs.h
@@ -5684,7 +5923,7 @@ if test "x$ac_cv_lib_nl_nl_handle_alloc" = xyes; then :
#
# Yes.
#
- LIBS="-lnl $LIBS"
+ LIBS="${libnldir} -lnl $LIBS"
$as_echo "#define HAVE_LIBNL 1" >>confdefs.h
@@ -5860,15 +6099,30 @@ fi
;;
dag)
+ #
+ # --with-pcap=dag is the only way to get here, and it means
+ # "DAG support but nothing else"
+ #
V_DEFS="$V_DEFS -DDAG_ONLY"
+ xxx_only=yes
;;
septel)
+ #
+ # --with-pcap=septel is the only way to get here, and it means
+ # "Septel support but nothing else"
+ #
V_DEFS="$V_DEFS -DSEPTEL_ONLY"
+ xxx_only=yes
;;
snf)
+ #
+ # --with-pcap=snf is the only way to get here, and it means
+ # "SNF support but nothing else"
+ #
V_DEFS="$V_DEFS -DSNF_ONLY"
+ xxx_only=yes
;;
null)
@@ -5879,14 +6133,8 @@ $as_echo "$as_me: WARNING: (see the INSTALL doc for more info)" >&2;}
;;
esac
-if test "$V_PCAP" = null
+if test "$V_PCAP" != null
then
- #
- # We can't capture, so we can't open any capture
- # devices, so we won't return any interfaces.
- #
- V_FINDALLDEVS=null
-else
ac_fn_c_check_func "$LINENO" "getifaddrs" "ac_cv_func_getifaddrs"
if test "x$ac_cv_func_getifaddrs" = xyes; then :
@@ -5901,7 +6149,7 @@ if test "x$ac_cv_header_ifaddrs_h" = xyes; then :
# We have the header, so we use "getifaddrs()" to
# get the list of interfaces.
#
- V_FINDALLDEVS=getad
+ V_FINDALLDEVS=fad-getad.c
else
@@ -5969,9 +6217,9 @@ fi
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lbl_have_siocglifconf" >&5
$as_echo "$ac_cv_lbl_have_siocglifconf" >&6; }
if test $ac_cv_lbl_have_siocglifconf = yes ; then
- V_FINDALLDEVS=glifc
+ V_FINDALLDEVS=fad-glifc.c
else
- V_FINDALLDEVS=gifc
+ V_FINDALLDEVS=fad-gifc.c
fi
;;
@@ -5982,7 +6230,7 @@ $as_echo "$ac_cv_lbl_have_siocglifconf" >&6; }
# another mechanism, and we should be using that
# instead.)
#
- V_FINDALLDEVS=gifc
+ V_FINDALLDEVS=fad-gifc.c
;;
esac
fi
@@ -6101,10 +6349,20 @@ if test "${with_dag+set}" = set; then :
else
- #
- # Use DAG API if present, otherwise don't
- #
- want_dag=ifpresent
+ if test "$V_PCAP" = dag; then
+ # User requested DAG-only libpcap, so we'd better have
+ # the DAG API.
+ want_dag=yes
+ elif test "xxx_only" = yes; then
+ # User requested something-else-only pcap, so they don't
+ # want DAG support.
+ want_dag=no
+ else
+ #
+ # Use DAG API if present, otherwise don't
+ #
+ want_dag=ifpresent
+ fi
fi
@@ -6131,28 +6389,6 @@ if test "${with_dag_libraries+set}" = set; then :
fi
-case "$V_PCAP" in
-linux|bpf|dag)
- #
- # We support the DAG API if we're on Linux or BSD, or if we're
- # building a DAG-only libpcap.
- #
- ;;
-*)
- #
- # If the user explicitly requested DAG, tell them it's not
- # supported.
- #
- # If they expressed no preference, don't include it.
- #
- if test $want_dag = yes; then
- as_fn_error $? "DAG support is only available with 'linux' 'bpf' and 'dag' packet capture types" "$LINENO" 5
- elif test $want_dag = yes; then
- want_dag=no
- fi
- ;;
-esac
-
ac_cv_lbl_dag_api=no
if test "$want_dag" != no; then
@@ -6161,7 +6397,7 @@ $as_echo_n "checking whether we have DAG API headers... " >&6; }
# If necessary, set default paths for DAG API headers and libraries.
if test -z "$dag_root"; then
- dag_root=/usr/local
+ dag_root=/usr/local
fi
if test -z "$dag_include_dir"; then
@@ -6169,33 +6405,33 @@ $as_echo_n "checking whether we have DAG API headers... " >&6; }
fi
if test -z "$dag_lib_dir"; then
- dag_lib_dir="$dag_root/lib"
+ dag_lib_dir="$dag_root/lib"
fi
if test -z "$dag_tools_dir"; then
- dag_tools_dir="$dag_root/tools"
+ dag_tools_dir="$dag_root/tools"
fi
if test -r $dag_include_dir/dagapi.h; then
ac_cv_lbl_dag_api=yes
fi
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lbl_dag_api ($dag_include_dir)" >&5
-$as_echo "$ac_cv_lbl_dag_api ($dag_include_dir)" >&6; }
-fi
-if test $ac_cv_lbl_dag_api = yes; then
- V_INCLS="$V_INCLS -I$dag_include_dir"
+ if test "$ac_cv_lbl_dag_api" = yes; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes ($dag_include_dir)" >&5
+$as_echo "yes ($dag_include_dir)" >&6; }
- if test $V_PCAP != dag ; then
- SSRC="pcap-dag.c"
- fi
+ V_INCLS="$V_INCLS -I$dag_include_dir"
- # See if we can find a general version string.
- # Don't need to save and restore LIBS to prevent -ldag being
- # included if there's a found-action (arg 3).
- saved_ldflags=$LDFLAGS
- LDFLAGS="-L$dag_lib_dir"
- { $as_echo "$as_me:${as_lineno-$LINENO}: checking for dag_attach_stream in -ldag" >&5
+ if test $V_PCAP != dag ; then
+ SSRC="$SSRC pcap-dag.c"
+ fi
+
+ # See if we can find a general version string.
+ # Don't need to save and restore LIBS to prevent -ldag being
+ # included if there's a found-action (arg 3).
+ saved_ldflags=$LDFLAGS
+ LDFLAGS="-L$dag_lib_dir"
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking for dag_attach_stream in -ldag" >&5
$as_echo_n "checking for dag_attach_stream in -ldag... " >&6; }
if ${ac_cv_lib_dag_dag_attach_stream+:} false; then :
$as_echo_n "(cached) " >&6
@@ -6237,7 +6473,7 @@ else
dag_streams="0"
fi
- { $as_echo "$as_me:${as_lineno-$LINENO}: checking for dag_get_erf_types in -ldag" >&5
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking for dag_get_erf_types in -ldag" >&5
$as_echo_n "checking for dag_get_erf_types in -ldag... " >&6; }
if ${ac_cv_lib_dag_dag_get_erf_types+:} false; then :
$as_echo_n "(cached) " >&6
@@ -6280,7 +6516,7 @@ $as_echo "#define HAVE_DAG_GET_ERF_TYPES 1" >>confdefs.h
fi
- { $as_echo "$as_me:${as_lineno-$LINENO}: checking for dag_get_stream_erf_types in -ldag" >&5
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking for dag_get_stream_erf_types in -ldag" >&5
$as_echo_n "checking for dag_get_stream_erf_types in -ldag... " >&6; }
if ${ac_cv_lib_dag_dag_get_stream_erf_types+:} false; then :
$as_echo_n "(cached) " >&6
@@ -6324,16 +6560,16 @@ $as_echo "#define HAVE_DAG_GET_STREAM_ERF_TYPES 1" >>confdefs.h
fi
- LDFLAGS=$saved_ldflags
+ LDFLAGS=$saved_ldflags
- if test "$dag_streams" = 1; then
+ if test "$dag_streams" = 1; then
$as_echo "#define HAVE_DAG_STREAMS_API 1" >>confdefs.h
- LIBS="$LIBS -ldag"
- LDFLAGS="$LDFLAGS -L$dag_lib_dir"
+ LIBS="$LIBS -ldag"
+ LDFLAGS="$LDFLAGS -L$dag_lib_dir"
- { $as_echo "$as_me:${as_lineno-$LINENO}: checking for vdag_set_device_info in -lvdag" >&5
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking for vdag_set_device_info in -lvdag" >&5
$as_echo_n "checking for vdag_set_device_info in -lvdag... " >&6; }
if ${ac_cv_lib_vdag_vdag_set_device_info+:} false; then :
$as_echo_n "(cached) " >&6
@@ -6375,38 +6611,32 @@ else
ac_dag_have_vdag="0"
fi
- if test "$ac_dag_have_vdag" = 1; then
+ if test "$ac_dag_have_vdag" = 1; then
$as_echo "#define HAVE_DAG_VDAG 1" >>confdefs.h
- LIBS="$LIBS -lpthread"
+ LIBS="$LIBS -lpthread"
+ fi
fi
- fi
$as_echo "#define HAVE_DAG_API 1" >>confdefs.h
-fi
-
-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether we have the DAG API" >&5
-$as_echo_n "checking whether we have the DAG API... " >&6; }
-
-if test $ac_cv_lbl_dag_api = no; then
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+ else
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
$as_echo "no" >&6; }
- if test "$want_dag" = yes; then
- # User wanted DAG support but we couldn't find it.
- as_fn_error $? "DAG API requested, but not found at $dag_root: use --without-dag" "$LINENO" 5
- fi
- if test "$V_PCAP" = dag; then
- # User requested "dag" capture type but the DAG API wasn't
- # found.
- as_fn_error $? "Specifying the capture type as \"dag\" requires the DAG API to be present; use the --with-dag options to specify the location. (Try \"./configure --help\" for more information.)" "$LINENO" 5
+ if test "$V_PCAP" = dag; then
+ # User requested "dag" capture type but we couldn't
+ # find the DAG API support.
+ as_fn_error $? "DAG support requested with --with-pcap=dag, but the DAG headers weren't found at $dag_include_dir: make sure the DAG support is installed, specify a different path or paths if necessary, or don't request DAG support" "$LINENO" 5
+ fi
+
+ if test "$want_dag" = yes; then
+ # User wanted DAG support but we couldn't find it.
+ as_fn_error $? "DAG support requested with --with-dag, but the DAG headers weren't found at $dag_include_dir: make sure the DAG support is installed, specify a different path or paths if necessary, or don't request DAG support" "$LINENO" 5
+ fi
fi
-else
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
-$as_echo "yes" >&6; }
fi
@@ -6427,41 +6657,31 @@ if test "${with_septel+set}" = set; then :
else
- #
- # Use Septel API if present, otherwise don't
- #
- want_septel=ifpresent
- septel_root=./../septel
+ if test "$V_PCAP" = septel; then
+ # User requested Septel-only libpcap, so we'd better have
+ # the Septel API.
+ want_septel=yes
+ elif test "xxx_only" = yes; then
+ # User requested something-else-only pcap, so they don't
+ # want Septel support.
+ want_septel=no
+ else
+ #
+ # Use Septel API if present, otherwise don't
+ #
+ want_septel=ifpresent
+ fi
fi
-ac_cv_lbl_septel_api=no
-case "$V_PCAP" in
-linux|septel)
- #
- # We support the Septel API if we're on Linux, or if we're building
- # a Septel-only libpcap.
- #
- ;;
-*)
- #
- # If the user explicitly requested Septel, tell them it's not
- # supported.
- #
- # If they expressed no preference, don't include it.
- #
- if test $want_septel = yes; then
- as_fn_error $? "Septel support only available with 'linux' and 'septel' packet capture types" "$LINENO" 5
- elif test $want_septel = yes; then
- want_septel=no
- fi
- ;;
-esac
+ac_cv_lbl_septel_api=no
if test "$with_septel" != no; then
- { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether we have Septel API" >&5
-$as_echo_n "checking whether we have Septel API... " >&6; }
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether we have Septel API headers" >&5
+$as_echo_n "checking whether we have Septel API headers... " >&6; }
+
+ # If necessary, set default paths for Septel API headers and libraries.
if test -z "$septel_root"; then
septel_root=$srcdir/../septel
fi
@@ -6469,33 +6689,40 @@ $as_echo_n "checking whether we have Septel API... " >&6; }
septel_tools_dir="$septel_root"
septel_include_dir="$septel_root/INC"
- ac_cv_lbl_septel_api=no
if test -r "$septel_include_dir/msg.h"; then
+ ac_cv_lbl_septel_api=yes
+ fi
+
+ if test "$ac_cv_lbl_septel_api" = yes; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes ($septel_include_dir)" >&5
+$as_echo "yes ($septel_include_dir)" >&6; }
+
V_INCLS="$V_INCLS -I$septel_include_dir"
ADDLOBJS="$ADDLOBJS $septel_tools_dir/asciibin.o $septel_tools_dir/bit2byte.o $septel_tools_dir/confirm.o $septel_tools_dir/fmtmsg.o $septel_tools_dir/gct_unix.o $septel_tools_dir/hqueue.o $septel_tools_dir/ident.o $septel_tools_dir/mem.o $septel_tools_dir/pack.o $septel_tools_dir/parse.o $septel_tools_dir/pool.o $septel_tools_dir/sdlsig.o $septel_tools_dir/strtonum.o $septel_tools_dir/timer.o $septel_tools_dir/trace.o"
ADDLARCHIVEOBJS="$ADDLARCHIVEOBJS $septel_tools_dir/asciibin.o $septel_tools_dir/bit2byte.o $septel_tools_dir/confirm.o $septel_tools_dir/fmtmsg.o $septel_tools_dir/gct_unix.o $septel_tools_dir/hqueue.o $septel_tools_dir/ident.o $septel_tools_dir/mem.o $septel_tools_dir/pack.o $septel_tools_dir/parse.o $septel_tools_dir/pool.o $septel_tools_dir/sdlsig.o $septel_tools_dir/strtonum.o $septel_tools_dir/timer.o $septel_tools_dir/trace.o"
if test "$V_PCAP" != septel ; then
- SSRC="pcap-septel.c"
+ SSRC="$SSRC pcap-septel.c"
fi
- ac_cv_lbl_septel_api=yes
- fi
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lbl_septel_api" >&5
-$as_echo "$ac_cv_lbl_septel_api" >&6; }
- if test $ac_cv_lbl_septel_api = no; then
- if test "$want_septel" = yes; then
- as_fn_error $? "Septel API not found under directory $septel_root; use --without-septel" "$LINENO" 5
- fi
- else
$as_echo "#define HAVE_SEPTEL_API 1" >>confdefs.h
- fi
-fi
+ else
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
-if test "$V_PCAP" = septel -a "$ac_cv_lbl_septel_api" = no; then
- as_fn_error $? "Specifying the capture type as 'septel' requires the Septel API to be present; use --with-septel=DIR" "$LINENO" 5
+ if test "$V_PCAP" = septel; then
+ # User requested "septel" capture type but
+ # we couldn't find the Septel API support.
+ as_fn_error $? "Septel support requested with --with-pcap=septel, but the Septel headers weren't found at $septel_include_dir: make sure the Septel support is installed, specify a different path or paths if necessary, or don't request Septel support" "$LINENO" 5
+ fi
+
+ if test "$want_septel" = yes; then
+ # User wanted Septel support but we couldn't find it.
+ as_fn_error $? "Septel support requested with --with-septel, but the Septel headers weren't found at $septel_include_dir: make sure the Septel support is installed, specify a different path or paths if necessary, or don't request Septel support" "$LINENO" 5
+ fi
+ fi
fi
# Check for Myricom SNF support.
@@ -6509,7 +6736,7 @@ if test "${with_snf+set}" = set; then :
want_snf=no
elif test "$withval" = yes
then
- # User wants SNF support but hasn't specific a directory.
+ # User wants SNF support but hasn't specified a directory.
want_snf=yes
else
# User wants SNF support with a specified directory.
@@ -6519,10 +6746,20 @@ if test "${with_snf+set}" = set; then :
else
- #
- # Use Sniffer API if present, otherwise don't
- #
- want_snf=ifpresent
+ if test "$V_PCAP" = snf; then
+ # User requested Sniffer-only libpcap, so we'd better have
+ # the Sniffer API.
+ want_snf=yes
+ elif test "xxx_only" = yes; then
+ # User requested something-else-only pcap, so they don't
+ # want SNF support.
+ want_snf=no
+ else
+ #
+ # Use Sniffer API if present, otherwise don't
+ #
+ want_snf=ifpresent
+ fi
fi
@@ -6549,34 +6786,13 @@ if test "${with_snf_libraries+set}" = set; then :
fi
-case "$V_PCAP" in
-bpf|linux|snf)
- #
- # We support the Sniffer API if we're on BSD, Linux, or if we're
- # building a Sniffer-only libpcap.
- #
- ;;
-*)
- #
- # If the user explicitly requested Sniffer, tell them it's not
- # supported.
- #
- # If they expressed no preference, don't include it.
- #
- if test $want_snf = yes; then
- as_fn_error $? "Myricom SNF support only available with 'bpf' 'linux' and 'snf' packet capture types" "$LINENO" 5
- elif test $want_snf = yes; then
- want_snf=no
- fi
- ;;
-esac
-
ac_cv_lbl_snf_api=no
if test "$with_snf" != no; then
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether we have Myricom Sniffer API" >&5
$as_echo_n "checking whether we have Myricom Sniffer API... " >&6; }
+ # If necessary, set default paths for Sniffer headers and libraries.
if test -z "$snf_root"; then
snf_root=/opt/snf
fi
@@ -6590,16 +6806,7 @@ $as_echo_n "checking whether we have Myricom Sniffer API... " >&6; }
fi
if test -f "$snf_include_dir/snf.h"; then
- ac_cv_lbl_snf_api=yes
- fi
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lbl_snf_api ($snf_root)" >&5
-$as_echo "$ac_cv_lbl_snf_api ($snf_root)" >&6; }
-
- if test $ac_cv_lbl_snf_api = no; then
- if test "$want_snf" = yes; then
- as_fn_error $? "SNF API headers not found under $snf_include_dir; use --without-snf" "$LINENO" 5
- fi
- else
+ # We found a header; make sure we can link with the library
saved_ldflags=$LDFLAGS
LDFLAGS="$LDFLAGS -L$snf_lib_dir"
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for snf_init in -lsnf" >&5
@@ -6640,60 +6847,153 @@ fi
$as_echo "$ac_cv_lib_snf_snf_init" >&6; }
if test "x$ac_cv_lib_snf_snf_init" = xyes; then :
ac_cv_lbl_snf_api="yes"
-else
- ac_cv_lbl_snf_api="no"
fi
LDFLAGS="$saved_ldflags"
+ if test "$ac_cv_lbl_snf_api" = no; then
+ as_fn_error $? "SNF API cannot correctly be linked; check config.log" "$LINENO" 5
+ fi
+ fi
+
+ if test "$ac_cv_lbl_snf_api" = yes; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes ($snf_root)" >&5
+$as_echo "yes ($snf_root)" >&6; }
+
+ V_INCLS="$V_INCLS -I$snf_include_dir"
+ LIBS="$LIBS -lsnf"
+ LDFLAGS="$LDFLAGS -L$snf_lib_dir"
+
+ if test "$V_PCAP" != snf ; then
+ SSRC="$SSRC pcap-snf.c"
+ fi
- if test $ac_cv_lbl_snf_api = no; then
- if test "$want_snf" = yes; then
- as_fn_error $? "SNF API cannot correctly be linked check config.log; use --without-snf" "$LINENO" 5
- fi
- else
- V_INCLS="$V_INCLS -I$snf_include_dir"
- LIBS="$LIBS -lsnf"
- LDFLAGS="$LDFLAGS -L$snf_lib_dir"
- if test "$V_PCAP" != snf ; then
- SSRC="pcap-snf.c"
- fi
$as_echo "#define HAVE_SNF_API 1" >>confdefs.h
+ else
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+
+ if test "$want_snf" = yes; then
+ # User requested "snf" capture type but
+ # we couldn't find the Sniffer API support.
+ as_fn_error $? "Myricom Sniffer support requested with --with-pcap=snf, but the Sniffer headers weren't found at $snf_include_dir: make sure the Sniffer support is installed, specify a different path or paths if necessary, or don't request Sniffer support" "$LINENO" 5
+ fi
+
+ if test "$want_snf" = yes; then
+ as_fn_error $? "Myricom Sniffer support requested with --with-snf, but the Sniffer headers weren't found at $snf_include_dir: make sure the Sniffer support is installed, specify a different path or paths if necessary, or don't request Sniffer support" "$LINENO" 5
fi
fi
fi
-if test "$V_PCAP" = snf -a "$ac_cv_lbl_snf_api" = no; then
- as_fn_error $? "Specifying the capture type as 'snf' requires the Myricom Sniffer API to be present; use --with-snf=DIR" "$LINENO" 5
+# Check for Riverbed TurboCap support.
+
+# Check whether --with-turbocap was given.
+if test "${with_turbocap+set}" = set; then :
+ withval=$with_turbocap;
+ if test "$withval" = no
+ then
+ # User explicitly doesn't want TurboCap
+ want_turbocap=no
+ elif test "$withval" = yes
+ then
+ # User wants TurboCap support but hasn't specified a directory.
+ want_turbocap=yes
+ else
+ # User wants TurboCap support with a specified directory.
+ want_turbocap=yes
+ turbocap_root=$withval
+ fi
+
+else
+
+ if test "xxx_only" = yes; then
+ # User requested something-else-only pcap, so they don't
+ # want TurboCap support.
+ want_turbocap=no
+ else
+ #
+ # Use TurboCap API if present, otherwise don't
+ #
+ want_turbocap=ifpresent
+ fi
+
fi
-# Check whether --with-flex was given.
-if test "${with_flex+set}" = set; then :
- withval=$with_flex;
+ac_cv_lbl_turbocap_api=no
+if test "$want_turbocap" != no; then
+
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether TurboCap is supported" >&5
+$as_echo_n "checking whether TurboCap is supported... " >&6; }
+
+ save_CFLAGS="$CFLAGS"
+ save_LIBS="$LIBS"
+ if test ! -z "$turbocap_root"; then
+ TURBOCAP_CFLAGS="-I$turbocap_root/include"
+ TURBOCAP_LIBS="-L$turbocap_root/lib"
+ CFLAGS="$CFLAGS $TURBOCAP_CFLAGS"
+ fi
+
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+
+ #include <TcApi.h>
+
+int
+main ()
+{
+
+ TC_INSTANCE a; TC_PORT b; TC_BOARD c;
+ TC_INSTANCE i;
+ (void)TcInstanceCreateByName("foo", &i);
+
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+ ac_cv_lbl_turbocap_api=yes
fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+
+ CFLAGS="$save_CFLAGS"
+ if test $ac_cv_lbl_turbocap_api = yes; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
+$as_echo "yes" >&6; }
+ SSRC="$SSRC pcap-tc.c"
+ V_INCLS="$V_INCLS $TURBOCAP_CFLAGS"
+ LIBS="$LIBS $TURBOCAP_LIBS -lTcApi -lpthread -lstdc++"
+
+
+$as_echo "#define HAVE_TC_API 1" >>confdefs.h
+
+ else
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
-# Check whether --with-bison was given.
-if test "${with_bison+set}" = set; then :
- withval=$with_bison;
+ if test "$want_turbocap" = yes; then
+ # User wanted Turbo support but we couldn't find it.
+ as_fn_error $? "TurboCap support requested with --with-turbocap, but the TurboCap headers weren't found: make sure the TurboCap support is installed or don't request TurboCap support" "$LINENO" 5
+ fi
+ fi
fi
- if test "$with_flex" = no ; then
- V_LEX=lex
- else
- for ac_prog in flex
+#
+# Look for {f}lex.
+#
+for ac_prog in flex lex
do
# Extract the first word of "$ac_prog", so it can be a program name with args.
set dummy $ac_prog; ac_word=$2
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
$as_echo_n "checking for $ac_word... " >&6; }
-if ${ac_cv_prog_V_LEX+:} false; then :
+if ${ac_cv_prog_LEX+:} false; then :
$as_echo_n "(cached) " >&6
else
- if test -n "$V_LEX"; then
- ac_cv_prog_V_LEX="$V_LEX" # Let the user override the test.
+ if test -n "$LEX"; then
+ ac_cv_prog_LEX="$LEX" # Let the user override the test.
else
as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
for as_dir in $PATH
@@ -6702,7 +7002,7 @@ do
test -z "$as_dir" && as_dir=.
for ac_exec_ext in '' $ac_executable_extensions; do
if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
- ac_cv_prog_V_LEX="$ac_prog"
+ ac_cv_prog_LEX="$ac_prog"
$as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
break 2
fi
@@ -6712,58 +7012,176 @@ IFS=$as_save_IFS
fi
fi
-V_LEX=$ac_cv_prog_V_LEX
-if test -n "$V_LEX"; then
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: $V_LEX" >&5
-$as_echo "$V_LEX" >&6; }
+LEX=$ac_cv_prog_LEX
+if test -n "$LEX"; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: $LEX" >&5
+$as_echo "$LEX" >&6; }
else
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
$as_echo "no" >&6; }
fi
- test -n "$V_LEX" && break
+ test -n "$LEX" && break
done
-test -n "$V_LEX" || V_LEX="lex"
+test -n "$LEX" || LEX=":"
+
+if test "x$LEX" != "x:"; then
+ cat >conftest.l <<_ACEOF
+%%
+a { ECHO; }
+b { REJECT; }
+c { yymore (); }
+d { yyless (1); }
+e { /* IRIX 6.5 flex 2.5.4 underquotes its yyless argument. */
+ yyless ((input () != 0)); }
+f { unput (yytext[0]); }
+. { BEGIN INITIAL; }
+%%
+#ifdef YYTEXT_POINTER
+extern char *yytext;
+#endif
+int
+main (void)
+{
+ return ! yylex () + ! yywrap ();
+}
+_ACEOF
+{ { ac_try="$LEX conftest.l"
+case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\""
+$as_echo "$ac_try_echo"; } >&5
+ (eval "$LEX conftest.l") 2>&5
+ ac_status=$?
+ $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ test $ac_status = 0; }
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking lex output file root" >&5
+$as_echo_n "checking lex output file root... " >&6; }
+if ${ac_cv_prog_lex_root+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
- fi
- if test "$V_LEX" = flex ; then
- # The -V flag was added in 2.4
- { $as_echo "$as_me:${as_lineno-$LINENO}: checking for flex 2.4 or higher" >&5
-$as_echo_n "checking for flex 2.4 or higher... " >&6; }
- if ${ac_cv_lbl_flex_v24+:} false; then :
+if test -f lex.yy.c; then
+ ac_cv_prog_lex_root=lex.yy
+elif test -f lexyy.c; then
+ ac_cv_prog_lex_root=lexyy
+else
+ as_fn_error $? "cannot find output from $LEX; giving up" "$LINENO" 5
+fi
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_prog_lex_root" >&5
+$as_echo "$ac_cv_prog_lex_root" >&6; }
+LEX_OUTPUT_ROOT=$ac_cv_prog_lex_root
+
+if test -z "${LEXLIB+set}"; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking lex library" >&5
+$as_echo_n "checking lex library... " >&6; }
+if ${ac_cv_lib_lex+:} false; then :
$as_echo_n "(cached) " >&6
else
- if flex -V >/dev/null 2>&1; then
- ac_cv_lbl_flex_v24=yes
- else
- ac_cv_lbl_flex_v24=no
- fi
+
+ ac_save_LIBS=$LIBS
+ ac_cv_lib_lex='none needed'
+ for ac_lib in '' -lfl -ll; do
+ LIBS="$ac_lib $ac_save_LIBS"
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+`cat $LEX_OUTPUT_ROOT.c`
+_ACEOF
+if ac_fn_c_try_link "$LINENO"; then :
+ ac_cv_lib_lex=$ac_lib
+fi
+rm -f core conftest.err conftest.$ac_objext \
+ conftest$ac_exeext conftest.$ac_ext
+ test "$ac_cv_lib_lex" != 'none needed' && break
+ done
+ LIBS=$ac_save_LIBS
+
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_lex" >&5
+$as_echo "$ac_cv_lib_lex" >&6; }
+ test "$ac_cv_lib_lex" != 'none needed' && LEXLIB=$ac_cv_lib_lex
fi
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lbl_flex_v24" >&5
-$as_echo "$ac_cv_lbl_flex_v24" >&6; }
- if test $ac_cv_lbl_flex_v24 = no ; then
- s="2.4 or higher required"
- { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: ignoring obsolete flex executable ($s)" >&5
-$as_echo "$as_me: WARNING: ignoring obsolete flex executable ($s)" >&2;}
- V_LEX=lex
- fi
- fi
- if test "$with_bison" = no ; then
- V_YACC=yacc
- else
- for ac_prog in bison
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether yytext is a pointer" >&5
+$as_echo_n "checking whether yytext is a pointer... " >&6; }
+if ${ac_cv_prog_lex_yytext_pointer+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ # POSIX says lex can declare yytext either as a pointer or an array; the
+# default is implementation-dependent. Figure out which it is, since
+# not all implementations provide the %pointer and %array declarations.
+ac_cv_prog_lex_yytext_pointer=no
+ac_save_LIBS=$LIBS
+LIBS="$LEXLIB $ac_save_LIBS"
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+
+ #define YYTEXT_POINTER 1
+`cat $LEX_OUTPUT_ROOT.c`
+_ACEOF
+if ac_fn_c_try_link "$LINENO"; then :
+ ac_cv_prog_lex_yytext_pointer=yes
+fi
+rm -f core conftest.err conftest.$ac_objext \
+ conftest$ac_exeext conftest.$ac_ext
+LIBS=$ac_save_LIBS
+
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_prog_lex_yytext_pointer" >&5
+$as_echo "$ac_cv_prog_lex_yytext_pointer" >&6; }
+if test $ac_cv_prog_lex_yytext_pointer = yes; then
+
+$as_echo "#define YYTEXT_POINTER 1" >>confdefs.h
+
+fi
+rm -f conftest.l $LEX_OUTPUT_ROOT.c
+
+fi
+if test "$LEX" = ":"; then
+ as_fn_error $? "Neither flex nor lex was found." "$LINENO" 5
+fi
+
+#
+# Make sure {f}lex supports the -P, --header-file, and --nounput flags
+# and supports processing our scanner.l.
+#
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for capable lex" >&5
+$as_echo_n "checking for capable lex... " >&6; }
+if ${tcpdump_cv_capable_lex+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ if $LEX -P pcap_ --header-file=/dev/null --nounput -t $srcdir/scanner.l > /dev/null 2>&1; then
+ tcpdump_cv_capable_lex=yes
+ else
+ tcpdump_cv_capable_lex=insufficient
+ fi
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $tcpdump_cv_capable_lex" >&5
+$as_echo "$tcpdump_cv_capable_lex" >&6; }
+if test $tcpdump_cv_capable_lex = insufficient ; then
+ as_fn_error $? "$LEX is insufficient to compile libpcap.
+ libpcap requires Flex 2.5.31 or later, or a compatible version of lex." "$LINENO" 5
+fi
+
+#
+# Look for yacc/bison/byacc.
+#
+for ac_prog in 'bison -y' byacc
do
# Extract the first word of "$ac_prog", so it can be a program name with args.
set dummy $ac_prog; ac_word=$2
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
$as_echo_n "checking for $ac_word... " >&6; }
-if ${ac_cv_prog_V_YACC+:} false; then :
+if ${ac_cv_prog_YACC+:} false; then :
$as_echo_n "(cached) " >&6
else
- if test -n "$V_YACC"; then
- ac_cv_prog_V_YACC="$V_YACC" # Let the user override the test.
+ if test -n "$YACC"; then
+ ac_cv_prog_YACC="$YACC" # Let the user override the test.
else
as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
for as_dir in $PATH
@@ -6772,7 +7190,7 @@ do
test -z "$as_dir" && as_dir=.
for ac_exec_ext in '' $ac_executable_extensions; do
if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
- ac_cv_prog_V_YACC="$ac_prog"
+ ac_cv_prog_YACC="$ac_prog"
$as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
break 2
fi
@@ -6782,61 +7200,42 @@ IFS=$as_save_IFS
fi
fi
-V_YACC=$ac_cv_prog_V_YACC
-if test -n "$V_YACC"; then
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: $V_YACC" >&5
-$as_echo "$V_YACC" >&6; }
+YACC=$ac_cv_prog_YACC
+if test -n "$YACC"; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: $YACC" >&5
+$as_echo "$YACC" >&6; }
else
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
$as_echo "no" >&6; }
fi
- test -n "$V_YACC" && break
+ test -n "$YACC" && break
done
-test -n "$V_YACC" || V_YACC="yacc"
+test -n "$YACC" || YACC="yacc"
- fi
- if test "$V_YACC" = bison ; then
- V_YACC="$V_YACC -y"
- fi
- if test "$V_LEX" != lex -a "$V_YACC" = yacc -o "$V_LEX" = lex -a "$V_YACC" != yacc ; then
- { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: don't have both flex and bison; reverting to lex/yacc" >&5
-$as_echo "$as_me: WARNING: don't have both flex and bison; reverting to lex/yacc" >&2;}
- V_LEX=lex
- V_YACC=yacc
- fi
- if test "$V_LEX" = flex -a -n "pcap_" ; then
- V_LEX="$V_LEX -Ppcap_"
- V_YACC="$V_YACC -p pcap_"
- else
-
-$as_echo "#define NEED_YYPARSE_WRAPPER 1" >>confdefs.h
- fi
-if test "$V_LEX" = lex ; then
-# Some versions of lex can't handle the definitions section of scanner.l .
-# Try lexing it and complain if it can't deal.
- { $as_echo "$as_me:${as_lineno-$LINENO}: checking for capable lex" >&5
-$as_echo_n "checking for capable lex... " >&6; }
-if ${tcpdump_cv_capable_lex+:} false; then :
+#
+# Make sure it supports the -p flag and supports processing our
+# grammar.y.
+#
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for capable yacc/bison" >&5
+$as_echo_n "checking for capable yacc/bison... " >&6; }
+if ${tcpdump_cv_capable_yacc+:} false; then :
$as_echo_n "(cached) " >&6
else
- if lex -t scanner.l > /dev/null 2>&1; then
- tcpdump_cv_capable_lex=yes
- else
- tcpdump_cv_capable_lex=insufficient
- fi
-fi
-{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $tcpdump_cv_capable_lex" >&5
-$as_echo "$tcpdump_cv_capable_lex" >&6; }
- if test $tcpdump_cv_capable_lex = insufficient ; then
- as_fn_error $? "Your operating system's lex is insufficient to compile
- libpcap. flex is a lex replacement that has many advantages, including
- being able to compile libpcap. For more information, see
- http://www.gnu.org/software/flex/flex.html ." "$LINENO" 5
+ if $YACC -p pcap_ -o /dev/null $srcdir/grammar.y >/dev/null 2>&1; then
+ tcpdump_cv_capable_yacc=yes
+ else
+ tcpdump_cv_capable_yacc=insufficient
fi
fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $tcpdump_cv_capable_yacc" >&5
+$as_echo "$tcpdump_cv_capable_yacc" >&6; }
+if test $tcpdump_cv_capable_yacc = insufficient ; then
+ as_fn_error $? "$YACC is insufficient to compile libpcap.
+ libpcap requires Bison, Berkeley YACC, or another YACC compatible with them." "$LINENO" 5
+fi
#
# Assume, by default, no support for shared libraries and V7/BSD convention
@@ -7367,7 +7766,18 @@ rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether the compiler supports the -Wall option" >&5
$as_echo_n "checking whether the compiler supports the -Wall option... " >&6; }
save_CFLAGS="$CFLAGS"
- CFLAGS="$CFLAGS $ac_lbl_unknown_warning_option_error -Wall"
+ if expr "x-Wall" : "x-W.*" >/dev/null
+ then
+ CFLAGS="$CFLAGS $ac_lbl_unknown_warning_option_error -Wall"
+ elif expr "x-Wall" : "x-f.*" >/dev/null
+ then
+ CFLAGS="$CFLAGS -Werror -Wall"
+ elif expr "x-Wall" : "x-m.*" >/dev/null
+ then
+ CFLAGS="$CFLAGS -Werror -Wall"
+ else
+ CFLAGS="$CFLAGS -Wall"
+ fi
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
@@ -7396,10 +7806,64 @@ fi
rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether the compiler supports the -Wsign-compare option" >&5
+$as_echo_n "checking whether the compiler supports the -Wsign-compare option... " >&6; }
+ save_CFLAGS="$CFLAGS"
+ if expr "x-Wsign-compare" : "x-W.*" >/dev/null
+ then
+ CFLAGS="$CFLAGS $ac_lbl_unknown_warning_option_error -Wsign-compare"
+ elif expr "x-Wsign-compare" : "x-f.*" >/dev/null
+ then
+ CFLAGS="$CFLAGS -Werror -Wsign-compare"
+ elif expr "x-Wsign-compare" : "x-m.*" >/dev/null
+ then
+ CFLAGS="$CFLAGS -Werror -Wsign-compare"
+ else
+ CFLAGS="$CFLAGS -Wsign-compare"
+ fi
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+
+int
+main ()
+{
+return 0
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
+$as_echo "yes" >&6; }
+ CFLAGS="$save_CFLAGS"
+ V_CCOPT="$V_CCOPT -Wsign-compare"
+
+else
+
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+ CFLAGS="$save_CFLAGS"
+
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+
+
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether the compiler supports the -Wmissing-prototypes option" >&5
$as_echo_n "checking whether the compiler supports the -Wmissing-prototypes option... " >&6; }
save_CFLAGS="$CFLAGS"
- CFLAGS="$CFLAGS $ac_lbl_unknown_warning_option_error -Wmissing-prototypes"
+ if expr "x-Wmissing-prototypes" : "x-W.*" >/dev/null
+ then
+ CFLAGS="$CFLAGS $ac_lbl_unknown_warning_option_error -Wmissing-prototypes"
+ elif expr "x-Wmissing-prototypes" : "x-f.*" >/dev/null
+ then
+ CFLAGS="$CFLAGS -Werror -Wmissing-prototypes"
+ elif expr "x-Wmissing-prototypes" : "x-m.*" >/dev/null
+ then
+ CFLAGS="$CFLAGS -Werror -Wmissing-prototypes"
+ else
+ CFLAGS="$CFLAGS -Wmissing-prototypes"
+ fi
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
@@ -7431,7 +7895,18 @@ rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether the compiler supports the -Wstrict-prototypes option" >&5
$as_echo_n "checking whether the compiler supports the -Wstrict-prototypes option... " >&6; }
save_CFLAGS="$CFLAGS"
- CFLAGS="$CFLAGS $ac_lbl_unknown_warning_option_error -Wstrict-prototypes"
+ if expr "x-Wstrict-prototypes" : "x-W.*" >/dev/null
+ then
+ CFLAGS="$CFLAGS $ac_lbl_unknown_warning_option_error -Wstrict-prototypes"
+ elif expr "x-Wstrict-prototypes" : "x-f.*" >/dev/null
+ then
+ CFLAGS="$CFLAGS -Werror -Wstrict-prototypes"
+ elif expr "x-Wstrict-prototypes" : "x-m.*" >/dev/null
+ then
+ CFLAGS="$CFLAGS -Werror -Wstrict-prototypes"
+ else
+ CFLAGS="$CFLAGS -Wstrict-prototypes"
+ fi
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
@@ -7459,6 +7934,135 @@ $as_echo "no" >&6; }
fi
rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether the compiler supports the -Wshadow option" >&5
+$as_echo_n "checking whether the compiler supports the -Wshadow option... " >&6; }
+ save_CFLAGS="$CFLAGS"
+ if expr "x-Wshadow" : "x-W.*" >/dev/null
+ then
+ CFLAGS="$CFLAGS $ac_lbl_unknown_warning_option_error -Wshadow"
+ elif expr "x-Wshadow" : "x-f.*" >/dev/null
+ then
+ CFLAGS="$CFLAGS -Werror -Wshadow"
+ elif expr "x-Wshadow" : "x-m.*" >/dev/null
+ then
+ CFLAGS="$CFLAGS -Werror -Wshadow"
+ else
+ CFLAGS="$CFLAGS -Wshadow"
+ fi
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+
+int
+main ()
+{
+return 0
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
+$as_echo "yes" >&6; }
+ CFLAGS="$save_CFLAGS"
+ V_CCOPT="$V_CCOPT -Wshadow"
+
+else
+
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+ CFLAGS="$save_CFLAGS"
+
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+
+
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether the compiler supports the -Wdeclaration-after-statement option" >&5
+$as_echo_n "checking whether the compiler supports the -Wdeclaration-after-statement option... " >&6; }
+ save_CFLAGS="$CFLAGS"
+ if expr "x-Wdeclaration-after-statement" : "x-W.*" >/dev/null
+ then
+ CFLAGS="$CFLAGS $ac_lbl_unknown_warning_option_error -Wdeclaration-after-statement"
+ elif expr "x-Wdeclaration-after-statement" : "x-f.*" >/dev/null
+ then
+ CFLAGS="$CFLAGS -Werror -Wdeclaration-after-statement"
+ elif expr "x-Wdeclaration-after-statement" : "x-m.*" >/dev/null
+ then
+ CFLAGS="$CFLAGS -Werror -Wdeclaration-after-statement"
+ else
+ CFLAGS="$CFLAGS -Wdeclaration-after-statement"
+ fi
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+
+int
+main ()
+{
+return 0
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
+$as_echo "yes" >&6; }
+ CFLAGS="$save_CFLAGS"
+ V_CCOPT="$V_CCOPT -Wdeclaration-after-statement"
+
+else
+
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+ CFLAGS="$save_CFLAGS"
+
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+
+
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether the compiler supports the -Wused-but-marked-unused option" >&5
+$as_echo_n "checking whether the compiler supports the -Wused-but-marked-unused option... " >&6; }
+ save_CFLAGS="$CFLAGS"
+ if expr "x-Wused-but-marked-unused" : "x-W.*" >/dev/null
+ then
+ CFLAGS="$CFLAGS $ac_lbl_unknown_warning_option_error -Wused-but-marked-unused"
+ elif expr "x-Wused-but-marked-unused" : "x-f.*" >/dev/null
+ then
+ CFLAGS="$CFLAGS -Werror -Wused-but-marked-unused"
+ elif expr "x-Wused-but-marked-unused" : "x-m.*" >/dev/null
+ then
+ CFLAGS="$CFLAGS -Werror -Wused-but-marked-unused"
+ else
+ CFLAGS="$CFLAGS -Wused-but-marked-unused"
+ fi
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+
+int
+main ()
+{
+return 0
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
+$as_echo "yes" >&6; }
+ CFLAGS="$save_CFLAGS"
+ V_CCOPT="$V_CCOPT -Wused-but-marked-unused"
+
+else
+
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+ CFLAGS="$save_CFLAGS"
+
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+
fi
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether the compiler supports generating dependencies" >&5
@@ -7778,16 +8382,11 @@ $as_echo "#define LBL_ALIGN 1" >>confdefs.h
fi
-#
-# Makefile.in includes rules to generate version.h, so we assume
-# that it will be generated if autoconf is used.
-#
+rm -f net
+ln -s ${srcdir}/bpf/net net
-$as_echo "#define HAVE_VERSION_H 1" >>confdefs.h
-rm -f net
-ln -s ${srcdir}/bpf/net net
@@ -7804,13 +8403,25 @@ ln -s ${srcdir}/bpf/net net
+# Check whether --enable-usb was given.
+if test "${enable_usb+set}" = set; then :
+ enableval=$enable_usb;
+else
+ enable_usb=yes
+fi
+if test "xxx_only" = yes; then
+ # User requested something-else-only pcap, so they don't
+ # want USB support.
+ enable_usb=no
+fi
-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for USB sniffing support" >&5
+if test "x$enable_usb" != "xno" ; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking for USB sniffing support" >&5
$as_echo_n "checking for USB sniffing support... " >&6; }
-case "$host_os" in
-linux*)
+ case "$host_os" in
+ linux*)
$as_echo "#define PCAP_SUPPORT_USB 1" >>confdefs.h
@@ -7923,31 +8534,42 @@ $as_echo "#define HAVE_USBDEVFS_CTRLTRANSFER_BREQUESTTYPE 1" >>confdefs.h
fi
fi
;;
-*)
+ freebsd*)
+ #
+ # This just uses BPF in FreeBSD 8.4 and later; we don't need
+ # to check for anything special for capturing.
+ #
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes, in FreeBSD 8.4 and later" >&5
+$as_echo "yes, in FreeBSD 8.4 and later" >&6; }
+ ;;
+
+ *)
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
$as_echo "no" >&6; }
;;
esac
+fi
-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether the platform could support netfilter sniffing" >&5
+if test "xxx_only" != yes; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether the platform could support netfilter sniffing" >&5
$as_echo_n "checking whether the platform could support netfilter sniffing... " >&6; }
-case "$host_os" in
-linux*)
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
+ case "$host_os" in
+ linux*)
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
$as_echo "yes" >&6; }
- #
- # Life's too short to deal with trying to get this to compile
- # if you don't get the right types defined with
- # __KERNEL_STRICT_NAMES getting defined by some other include.
- #
- # Check whether the includes Just Work. If not, don't turn on
- # netfilter support.
- #
- { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether we can compile the netfilter support" >&5
+ #
+ # Life's too short to deal with trying to get this to compile
+ # if you don't get the right types defined with
+ # __KERNEL_STRICT_NAMES getting defined by some other include.
+ #
+ # Check whether the includes Just Work. If not, don't turn on
+ # netfilter support.
+ #
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether we can compile the netfilter support" >&5
$as_echo_n "checking whether we can compile the netfilter support... " >&6; }
- if ${ac_cv_netfilter_can_compile+:} false; then :
+ if ${ac_cv_netfilter_can_compile+:} false; then :
$as_echo_n "(cached) " >&6
else
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
@@ -7979,20 +8601,21 @@ fi
rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
fi
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_netfilter_can_compile" >&5
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_netfilter_can_compile" >&5
$as_echo "$ac_cv_netfilter_can_compile" >&6; }
- if test $ac_cv_netfilter_can_compile = yes ; then
+ if test $ac_cv_netfilter_can_compile = yes ; then
$as_echo "#define PCAP_SUPPORT_NETFILTER 1" >>confdefs.h
- NETFILTER_SRC=pcap-netfilter-linux.c
- fi
- ;;
-*)
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+ NETFILTER_SRC=pcap-netfilter-linux.c
+ fi
+ ;;
+ *)
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
$as_echo "no" >&6; }
- ;;
-esac
+ ;;
+ esac
+fi
@@ -8004,6 +8627,12 @@ else
fi
+if test "xxx_only" = yes; then
+ # User requested something-else-only pcap, so they don't
+ # want Bluetooth support.
+ enable_bluetooth=no
+fi
+
if test "x$enable_bluetooth" != "xno" ; then
case "$host_os" in
linux*)
@@ -8125,151 +8754,6 @@ $as_echo "$as_me: no Bluetooth sniffing support implemented for $host_os" >&6;}
fi
-# Check whether --enable-canusb was given.
-if test "${enable_canusb+set}" = set; then :
- enableval=$enable_canusb;
-else
- enable_canusb=ifsupportavailable
-fi
-
-
-if test "x$enable_canusb" != "xno" ; then
- case "$host_os" in
- linux*)
- ac_fn_c_check_header_mongrel "$LINENO" "libusb-1.0/libusb.h" "ac_cv_header_libusb_1_0_libusb_h" "$ac_includes_default"
-if test "x$ac_cv_header_libusb_1_0_libusb_h" = xyes; then :
-
- { $as_echo "$as_me:${as_lineno-$LINENO}: checking for libusb_init in -lusb-1.0" >&5
-$as_echo_n "checking for libusb_init in -lusb-1.0... " >&6; }
-if ${ac_cv_lib_usb_1_0_libusb_init+:} false; then :
- $as_echo_n "(cached) " >&6
-else
- ac_check_lib_save_LIBS=$LIBS
-LIBS="-lusb-1.0 $LIBS"
-cat confdefs.h - <<_ACEOF >conftest.$ac_ext
-/* end confdefs.h. */
-
-/* Override any GCC internal prototype to avoid an error.
- Use char because int might match the return type of a GCC
- builtin and then its argument prototype would still apply. */
-#ifdef __cplusplus
-extern "C"
-#endif
-char libusb_init ();
-int
-main ()
-{
-return libusb_init ();
- ;
- return 0;
-}
-_ACEOF
-if ac_fn_c_try_link "$LINENO"; then :
- ac_cv_lib_usb_1_0_libusb_init=yes
-else
- ac_cv_lib_usb_1_0_libusb_init=no
-fi
-rm -f core conftest.err conftest.$ac_objext \
- conftest$ac_exeext conftest.$ac_ext
-LIBS=$ac_check_lib_save_LIBS
-fi
-{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_usb_1_0_libusb_init" >&5
-$as_echo "$ac_cv_lib_usb_1_0_libusb_init" >&6; }
-if test "x$ac_cv_lib_usb_1_0_libusb_init" = xyes; then :
-
-
-$as_echo "#define PCAP_SUPPORT_CANUSB 1" >>confdefs.h
-
- CANUSB_SRC=pcap-canusb-linux.c
- LIBS="-lusb-1.0 -lpthread $LIBS"
- ac_lbl_has_libusb=yes
-
-else
- ac_lbl_has_libusb=no
-
-fi
-
-
-else
- ac_lbl_has_libusb=no
-
-fi
-
-
- if test "x$ac_lbl_has_libusb" = "xyes" ; then
- { $as_echo "$as_me:${as_lineno-$LINENO}: canusb sniffing is supported" >&5
-$as_echo "$as_me: canusb sniffing is supported" >&6;}
- else
- if test "x$enable_canusb" = "xyes" ; then
- as_fn_error $? "canusb sniffing is not supported; install libusb1.0 lib devel to enable it" "$LINENO" 5
- else
- { $as_echo "$as_me:${as_lineno-$LINENO}: canusb sniffing is not supported; install libusb1.0 lib devel to enable it" >&5
-$as_echo "$as_me: canusb sniffing is not supported; install libusb1.0 lib devel to enable it" >&6;}
- fi
- fi
- ;;
- *)
- if test "x$enable_canusb" = "xyes" ; then
- as_fn_error $? "no canusb support implemented for $host_os" "$LINENO" 5
- else
- { $as_echo "$as_me:${as_lineno-$LINENO}: no canusb support implemented for $host_os" >&5
-$as_echo "$as_me: no canusb support implemented for $host_os" >&6;}
- fi
- ;;
- esac
-
-
-fi
-
-# Check whether --enable-can was given.
-if test "${enable_can+set}" = set; then :
- enableval=$enable_can;
-else
- enable_can=ifsupportavailable
-fi
-
-
-if test "x$enable_can" != "xno" ; then
- case "$host_os" in
- linux*)
- ac_fn_c_check_header_compile "$LINENO" "linux/can.h" "ac_cv_header_linux_can_h" "#include <sys/socket.h>
-
-"
-if test "x$ac_cv_header_linux_can_h" = xyes; then :
-
-
-$as_echo "#define PCAP_SUPPORT_CAN 1" >>confdefs.h
-
- CAN_SRC=pcap-can-linux.c
- { $as_echo "$as_me:${as_lineno-$LINENO}: CAN sniffing is supported" >&5
-$as_echo "$as_me: CAN sniffing is supported" >&6;}
-
-else
-
- if test "x$enable_can" = "xyes" ; then
- as_fn_error $? "CAN sniffing is not supported" "$LINENO" 5
- else
- { $as_echo "$as_me:${as_lineno-$LINENO}: CAN sniffing is not supported" >&5
-$as_echo "$as_me: CAN sniffing is not supported" >&6;}
- fi
-
-fi
-
-
- ;;
- *)
- if test "x$enable_can" = "xyes" ; then
- as_fn_error $? "no CAN sniffing support implemented for $host_os" "$LINENO" 5
- else
- { $as_echo "$as_me:${as_lineno-$LINENO}: no CAN sniffing support implemented for $host_os" >&5
-$as_echo "$as_me: no CAN sniffing support implemented for $host_os" >&6;}
- fi
- ;;
- esac
-
-
-fi
-
# Check whether --enable-dbus was given.
if test "${enable_dbus+set}" = set; then :
enableval=$enable_dbus;
@@ -8278,28 +8762,46 @@ else
fi
+if test "xxx_only" = yes; then
+ # User requested something-else-only pcap, so they don't
+ # want D-Bus support.
+ enable_dbus=no
+fi
+
if test "x$enable_dbus" != "xno"; then
if test "x$enable_dbus" = "xyes"; then
case "$host_os" in
darwin*)
#
+ # We don't support D-Bus sniffing on OS X; see
+ #
# https://bugs.freedesktop.org/show_bug.cgi?id=74029
#
+ # The user requested it, so fail.
+ #
as_fn_error $? "Due to freedesktop.org bug 74029, D-Bus capture support is not available on OS X" "$LINENO" 5
- ;;
esac
else
case "$host_os" in
darwin*)
#
+ # We don't support D-Bus sniffing on OS X; see
+ #
# https://bugs.freedesktop.org/show_bug.cgi?id=74029
#
+ # The user dind't explicitly request it, so just
+ # silently refuse to enable it.
+ #
+ enable_dbus="no"
;;
+ esac
+ fi
+fi
- *)
- # Extract the first word of "pkg-config", so it can be a program name with args.
+if test "x$enable_dbus" != "xno"; then
+ # Extract the first word of "pkg-config", so it can be a program name with args.
set dummy pkg-config; ac_word=$2
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
$as_echo_n "checking for $ac_word... " >&6; }
@@ -8337,28 +8839,28 @@ $as_echo "no" >&6; }
fi
- if test "x$PKGCONFIG" != "xno"; then
- { $as_echo "$as_me:${as_lineno-$LINENO}: checking for D-Bus" >&5
+ if test "x$PKGCONFIG" != "xno"; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking for D-Bus" >&5
$as_echo_n "checking for D-Bus... " >&6; }
- if "$PKGCONFIG" dbus-1; then
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
+ if "$PKGCONFIG" dbus-1; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
$as_echo "yes" >&6; }
- DBUS_CFLAGS=`"$PKGCONFIG" --cflags dbus-1`
- DBUS_LIBS=`"$PKGCONFIG" --libs dbus-1`
- save_CFLAGS="$CFLAGS"
- save_LIBS="$LIBS"
- CFLAGS="$CFLAGS $DBUS_CFLAGS"
- LIBS="$LIBS $DBUS_LIBS"
- { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether the D-Bus library defines dbus_connection_read_write" >&5
+ DBUS_CFLAGS=`"$PKGCONFIG" --cflags dbus-1`
+ DBUS_LIBS=`"$PKGCONFIG" --libs dbus-1`
+ save_CFLAGS="$CFLAGS"
+ save_LIBS="$LIBS"
+ CFLAGS="$CFLAGS $DBUS_CFLAGS"
+ LIBS="$LIBS $DBUS_LIBS"
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether the D-Bus library defines dbus_connection_read_write" >&5
$as_echo_n "checking whether the D-Bus library defines dbus_connection_read_write... " >&6; }
- cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
#include <string.h>
- #include <time.h>
- #include <sys/time.h>
+ #include <time.h>
+ #include <sys/time.h>
- #include <dbus/dbus.h>
+ #include <dbus/dbus.h>
int
main ()
{
@@ -8369,37 +8871,34 @@ return dbus_connection_read_write(NULL, 0);
_ACEOF
if ac_fn_c_try_link "$LINENO"; then :
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
$as_echo "yes" >&6; }
$as_echo "#define PCAP_SUPPORT_DBUS 1" >>confdefs.h
- DBUS_SRC=pcap-dbus.c
- V_INCLS="$V_INCLS $DBUS_CFLAGS"
+ DBUS_SRC=pcap-dbus.c
+ V_INCLS="$V_INCLS $DBUS_CFLAGS"
else
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
$as_echo "no" >&6; }
- if test "x$enable_dbus" = "xyes"; then
- as_fn_error $? "--enable-dbus was given, but the D-Bus library doesn't define dbus_connection_read_write()" "$LINENO" 5
- fi
- LIBS="$save_LIBS"
+ if test "x$enable_dbus" = "xyes"; then
+ as_fn_error $? "--enable-dbus was given, but the D-Bus library doesn't define dbus_connection_read_write()" "$LINENO" 5
+ fi
+ LIBS="$save_LIBS"
fi
rm -f core conftest.err conftest.$ac_objext \
conftest$ac_exeext conftest.$ac_ext
- CFLAGS="$save_CFLAGS"
- else
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+ CFLAGS="$save_CFLAGS"
+ else
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
$as_echo "no" >&6; }
- if test "x$enable_dbus" = "xyes"; then
- as_fn_error $? "--enable-dbus was given, but the dbus-1 package is not installed" "$LINENO" 5
- fi
- fi
+ if test "x$enable_dbus" = "xyes"; then
+ as_fn_error $? "--enable-dbus was given, but the dbus-1 package is not installed" "$LINENO" 5
fi
- ;;
- esac
+ fi
fi
@@ -8426,6 +8925,21 @@ $as_echo "$as_me: no hardware timestamp support implemented for $host_os" >&6;}
;;
esac
+# Check whether --enable-packet-ring was given.
+if test "${enable_packet_ring+set}" = set; then :
+ enableval=$enable_packet_ring;
+else
+ enable_packet_ring=yes
+fi
+
+
+if test "x$enable_packet_ring" != "xno" ; then
+
+$as_echo "#define PCAP_SUPPORT_PACKET_RING 1" >>confdefs.h
+
+
+fi
+
# Find a good install program. We prefer a C program (faster),
# so one script is as good as another. But avoid the broken or
# incompatible versions:
diff --git a/contrib/libpcap/configure.in b/contrib/libpcap/configure.ac
index 4530aed3a7d0..da2f940da963 100644
--- a/contrib/libpcap/configure.in
+++ b/contrib/libpcap/configure.ac
@@ -104,7 +104,7 @@ dnl in "aclocal.m4" uses it, so we would still have to test for it
dnl and set "HAVE_SYS_IOCCOM_H" if we have it, otherwise
dnl "AC_LBL_FIXINCLUDES" wouldn't work on some platforms such as Solaris.
dnl
-AC_CHECK_HEADERS(sys/ioccom.h sys/sockio.h limits.h paths.h)
+AC_CHECK_HEADERS(sys/ioccom.h sys/select.h sys/sockio.h limits.h)
AC_CHECK_HEADERS(linux/types.h)
AC_CHECK_HEADERS(linux/if_packet.h netpacket/packet.h netpacket/if_packet.h)
AC_CHECK_HEADERS(net/pfvar.h, , , [#include <sys/types.h>
@@ -148,6 +148,16 @@ struct rtentry;
#include <net/if.h>])
fi
+case "$host_os" in
+linux*|uclinux*)
+ AC_CHECK_HEADERS(linux/sockios.h linux/if_bonding.h,,,
+ [
+#include <sys/socket.h>
+#include <linux/if.h>
+ ])
+ ;;
+esac
+
AC_LBL_FIXINCLUDES
AC_CHECK_FUNCS(strerror strlcpy)
@@ -159,6 +169,13 @@ if test $needsnprintf = yes; then
AC_LIBOBJ([snprintf])
fi
+needstrtok_r=no
+AC_CHECK_FUNCS(strtok_r,,
+ [needstrtok_r=yes])
+if test $needstrtok_r = yes; then
+ AC_LIBOBJ([strtok_r])
+fi
+
#
# Do this before checking for ether_hostton(), as it's a
# "gethostbyname() -ish function".
@@ -272,6 +289,13 @@ fi
AC_MSG_RESULT(${enable_protochain})
#
+# valgrindtest directly uses the native capture mechanism, but
+# only tests with BPF and PF_PACKET sockets; only enable it if
+# we have BPF or PF_PACKET sockets.
+#
+VALGRINDTEST=
+
+#
# SITA support is mutually exclusive with native capture support;
# "--with-sita" selects SITA support.
#
@@ -282,7 +306,6 @@ AC_HELP_STRING([--with-sita],[include SITA support]),
AC_DEFINE(SITA,1,[include ACN support])
AC_MSG_NOTICE(Enabling SITA ACN support)
V_PCAP=sita
- V_FINDALLDEVS=sita
fi
],
[
@@ -308,8 +331,18 @@ elif test -r /dev/bpf -o -h /dev/bpf ; then
#
V_PCAP=bpf
AC_DEFINE(HAVE_CLONING_BPF,1,[define if you have a cloning BPF device])
+
+ #
+ # We have BPF, so build valgrindtest with "make test".
+ #
+ VALGRINDTEST=valgrindtest
elif test -r /dev/bpf0 ; then
V_PCAP=bpf
+
+ #
+ # We have BPF, so build valgrindtest with "make test".
+ #
+ VALGRINDTEST=valgrindtest
elif test -r /usr/include/net/pfilt.h ; then
V_PCAP=pf
elif test -r /dev/enet ; then
@@ -320,6 +353,12 @@ elif test -r /usr/include/sys/net/nit.h ; then
V_PCAP=nit
elif test -r /usr/include/linux/socket.h ; then
V_PCAP=linux
+
+ #
+ # XXX - this won't work with older kernels that have SOCK_PACKET
+ # sockets but not PF_PACKET sockets.
+ #
+ VALGRINDTEST=valgrindtest
elif test -r /usr/include/net/raw.h ; then
V_PCAP=snoop
elif test -r /usr/include/odmi.h ; then
@@ -331,6 +370,11 @@ elif test -r /usr/include/odmi.h ; then
V_PCAP=bpf
elif test -c /dev/bpf0 ; then # check again in case not readable
V_PCAP=bpf
+
+ #
+ # We have BPF, so build valgrindtest with "make test".
+ #
+ VALGRINDTEST=valgrindtest
elif test -r /usr/include/sys/dlpi.h ; then
V_PCAP=dlpi
elif test -c /dev/enet ; then # check again in case not readable
@@ -341,6 +385,7 @@ else
V_PCAP=null
fi
AC_MSG_RESULT($V_PCAP)
+AC_SUBST(VALGRINDTEST)
#
# Do capture-mechanism-dependent tests.
@@ -360,11 +405,11 @@ dlpi)
#
# Checks to see if Solaris has the public libdlpi(3LIB) library.
# Note: The existence of /usr/include/libdlpi.h does not mean it is the
- # public libdlpi(3LIB) version. Before libdlpi was made public, a
- # private version also existed, which did not have the same APIs.
+ # public libdlpi(3LIB) version. Before libdlpi was made public, a
+ # private version also existed, which did not have the same APIs.
# Due to a gcc bug, the default search path for 32-bit libraries does
# not include /lib, we add it explicitly here.
- # [http://bugs.opensolaris.org/view_bug.do?bug_id=6619485].
+ # [http://bugs.opensolaris.org/view_bug.do?bug_id=6619485].
# Also, due to the bug above applications that link to libpcap with
# libdlpi will have to add "-L/lib" option to "configure".
#
@@ -446,6 +491,13 @@ linux)
if test x$with_libnl != xno ; then
have_any_nl="no"
+ incdir=-I/usr/include/libnl3
+ libnldir=
+ if test x$withval != x ; then
+ libnldir=-L${withval}/lib/.libs
+ incdir=-I${withval}/include
+ fi
+
#
# Try libnl 3.x first.
#
@@ -454,14 +506,14 @@ linux)
#
# Yes, we have libnl 3.x.
#
- LIBS="-lnl-genl-3 -lnl-3 $LIBS"
+ LIBS="${libnldir} -lnl-genl-3 -lnl-3 $LIBS"
AC_DEFINE(HAVE_LIBNL,1,[if libnl exists])
AC_DEFINE(HAVE_LIBNL_3_x,1,[if libnl exists and is version 3.x])
AC_DEFINE(HAVE_LIBNL_NLE,1,[libnl has NLE_FAILURE])
AC_DEFINE(HAVE_LIBNL_SOCKETS,1,[libnl has new-style socket api])
- V_INCLS="$V_INCLS -I/usr/include/libnl3"
+ V_INCLS="$V_INCLS ${incdir}"
have_any_nl="yes"
- ])
+ ],[], ${incdir} ${libnldir} -lnl-genl-3 -lnl-3 )
if test x$have_any_nl = xno ; then
#
@@ -472,7 +524,7 @@ linux)
#
# Yes, we have libnl 2.x.
#
- LIBS="-lnl-genl -lnl $LIBS"
+ LIBS="${libnldir} -lnl-genl -lnl $LIBS"
AC_DEFINE(HAVE_LIBNL,1,[if libnl exists])
AC_DEFINE(HAVE_LIBNL_2_x,1,[if libnl exists and is version 2.x])
AC_DEFINE(HAVE_LIBNL_NLE,1,[libnl has NLE_FAILURE])
@@ -490,7 +542,7 @@ linux)
#
# Yes.
#
- LIBS="-lnl $LIBS"
+ LIBS="${libnldir} -lnl $LIBS"
AC_DEFINE(HAVE_LIBNL,1,[if libnl exists])
have_any_nl="yes"
])
@@ -528,7 +580,7 @@ bpf)
#include <net/if.h>
#include <net/bpf.h>],
[return (BIOCROTZBUF + BPF_BUFMODE_ZBUF);],
- [
+ [
AC_MSG_RESULT(yes)
AC_DEFINE(HAVE_ZEROCOPY_BPF, 1,
[define if the system supports zerocopy BPF])
@@ -550,15 +602,30 @@ bpf)
;;
dag)
+ #
+ # --with-pcap=dag is the only way to get here, and it means
+ # "DAG support but nothing else"
+ #
V_DEFS="$V_DEFS -DDAG_ONLY"
+ xxx_only=yes
;;
septel)
+ #
+ # --with-pcap=septel is the only way to get here, and it means
+ # "Septel support but nothing else"
+ #
V_DEFS="$V_DEFS -DSEPTEL_ONLY"
+ xxx_only=yes
;;
snf)
+ #
+ # --with-pcap=snf is the only way to get here, and it means
+ # "SNF support but nothing else"
+ #
V_DEFS="$V_DEFS -DSNF_ONLY"
+ xxx_only=yes
;;
null)
@@ -572,14 +639,8 @@ dnl Now figure out how we get a list of interfaces and addresses,
dnl if we support capturing. Don't bother if we don't support
dnl capturing.
dnl
-if test "$V_PCAP" = null
+if test "$V_PCAP" != null
then
- #
- # We can't capture, so we can't open any capture
- # devices, so we won't return any interfaces.
- #
- V_FINDALLDEVS=null
-else
AC_CHECK_FUNC(getifaddrs,[
#
# We have "getifaddrs()"; make sure we have <ifaddrs.h>
@@ -590,7 +651,7 @@ else
# We have the header, so we use "getifaddrs()" to
# get the list of interfaces.
#
- V_FINDALLDEVS=getad
+ V_FINDALLDEVS=fad-getad.c
],[
#
# We don't have the header - give up.
@@ -633,9 +694,9 @@ else
ac_cv_lbl_have_siocglifconf=no))
AC_MSG_RESULT($ac_cv_lbl_have_siocglifconf)
if test $ac_cv_lbl_have_siocglifconf = yes ; then
- V_FINDALLDEVS=glifc
+ V_FINDALLDEVS=fad-glifc.c
else
- V_FINDALLDEVS=gifc
+ V_FINDALLDEVS=fad-gifc.c
fi
;;
@@ -646,7 +707,7 @@ else
# another mechanism, and we should be using that
# instead.)
#
- V_FINDALLDEVS=gifc
+ V_FINDALLDEVS=fad-gifc.c
;;
esac])
fi
@@ -699,7 +760,7 @@ AC_MSG_RESULT(${enable_yydebug-no})
# Check for Endace DAG card support.
AC_ARG_WITH([dag],
-AC_HELP_STRING([--with-dag@<:@=DIR@:>@],[include Endace DAG support @<:@"yes", "no" or DIR; default="yes" on BSD and Linux if present@:>@]),
+AC_HELP_STRING([--with-dag@<:@=DIR@:>@],[include Endace DAG support (located in directory DIR, if supplied). @<:@default=yes, if present@:>@]),
[
if test "$withval" = no
then
@@ -715,14 +776,24 @@ AC_HELP_STRING([--with-dag@<:@=DIR@:>@],[include Endace DAG support @<:@"yes", "
dag_root=$withval
fi
],[
- #
- # Use DAG API if present, otherwise don't
- #
- want_dag=ifpresent
+ if test "$V_PCAP" = dag; then
+ # User requested DAG-only libpcap, so we'd better have
+ # the DAG API.
+ want_dag=yes
+ elif test "xxx_only" = yes; then
+ # User requested something-else-only pcap, so they don't
+ # want DAG support.
+ want_dag=no
+ else
+ #
+ # Use DAG API if present, otherwise don't
+ #
+ want_dag=ifpresent
+ fi
])
AC_ARG_WITH([dag-includes],
-AC_HELP_STRING([--with-dag-includes=DIR],[Endace DAG include directory]),
+AC_HELP_STRING([--with-dag-includes=IDIR],[Endace DAG include directory, if not DIR/include]),
[
# User wants DAG support and has specified a header directory, so use the provided value.
want_dag=yes
@@ -730,35 +801,13 @@ AC_HELP_STRING([--with-dag-includes=DIR],[Endace DAG include directory]),
],[])
AC_ARG_WITH([dag-libraries],
-AC_HELP_STRING([--with-dag-libraries=DIR],[Endace DAG library directory]),
+AC_HELP_STRING([--with-dag-libraries=LDIR],[Endace DAG library directory, if not DIR/lib]),
[
# User wants DAG support and has specified a library directory, so use the provided value.
want_dag=yes
dag_lib_dir=$withval
],[])
-case "$V_PCAP" in
-linux|bpf|dag)
- #
- # We support the DAG API if we're on Linux or BSD, or if we're
- # building a DAG-only libpcap.
- #
- ;;
-*)
- #
- # If the user explicitly requested DAG, tell them it's not
- # supported.
- #
- # If they expressed no preference, don't include it.
- #
- if test $want_dag = yes; then
- AC_MSG_ERROR([DAG support is only available with 'linux' 'bpf' and 'dag' packet capture types])
- elif test $want_dag = yes; then
- want_dag=no
- fi
- ;;
-esac
-
ac_cv_lbl_dag_api=no
if test "$want_dag" != no; then
@@ -766,7 +815,7 @@ if test "$want_dag" != no; then
# If necessary, set default paths for DAG API headers and libraries.
if test -z "$dag_root"; then
- dag_root=/usr/local
+ dag_root=/usr/local
fi
if test -z "$dag_include_dir"; then
@@ -774,74 +823,70 @@ if test "$want_dag" != no; then
fi
if test -z "$dag_lib_dir"; then
- dag_lib_dir="$dag_root/lib"
+ dag_lib_dir="$dag_root/lib"
fi
-
+
if test -z "$dag_tools_dir"; then
- dag_tools_dir="$dag_root/tools"
+ dag_tools_dir="$dag_root/tools"
fi
if test -r $dag_include_dir/dagapi.h; then
ac_cv_lbl_dag_api=yes
fi
- AC_MSG_RESULT([$ac_cv_lbl_dag_api ($dag_include_dir)])
-fi
-if test $ac_cv_lbl_dag_api = yes; then
- V_INCLS="$V_INCLS -I$dag_include_dir"
+ if test "$ac_cv_lbl_dag_api" = yes; then
+ AC_MSG_RESULT([yes ($dag_include_dir)])
- if test $V_PCAP != dag ; then
- SSRC="pcap-dag.c"
- fi
-
- # See if we can find a general version string.
- # Don't need to save and restore LIBS to prevent -ldag being
- # included if there's a found-action (arg 3).
- saved_ldflags=$LDFLAGS
- LDFLAGS="-L$dag_lib_dir"
- AC_CHECK_LIB([dag], [dag_attach_stream], [dag_streams="1"], [dag_streams="0"])
- AC_CHECK_LIB([dag],[dag_get_erf_types], [
- AC_DEFINE(HAVE_DAG_GET_ERF_TYPES, 1, [define if you have dag_get_erf_types()])])
- AC_CHECK_LIB([dag],[dag_get_stream_erf_types], [
- AC_DEFINE(HAVE_DAG_GET_STREAM_ERF_TYPES, 1, [define if you have dag_get_stream_erf_types()])])
-
- LDFLAGS=$saved_ldflags
+ V_INCLS="$V_INCLS -I$dag_include_dir"
- if test "$dag_streams" = 1; then
- AC_DEFINE(HAVE_DAG_STREAMS_API, 1, [define if you have streams capable DAG API])
- LIBS="$LIBS -ldag"
- LDFLAGS="$LDFLAGS -L$dag_lib_dir"
-
- AC_CHECK_LIB([vdag],[vdag_set_device_info], [ac_dag_have_vdag="1"], [ac_dag_have_vdag="0"])
- if test "$ac_dag_have_vdag" = 1; then
- AC_DEFINE(HAVE_DAG_VDAG, 1, [define if you have vdag_set_device_info()])
- LIBS="$LIBS -lpthread"
+ if test $V_PCAP != dag ; then
+ SSRC="$SSRC pcap-dag.c"
fi
- fi
- AC_DEFINE(HAVE_DAG_API, 1, [define if you have the DAG API])
-fi
+ # See if we can find a general version string.
+ # Don't need to save and restore LIBS to prevent -ldag being
+ # included if there's a found-action (arg 3).
+ saved_ldflags=$LDFLAGS
+ LDFLAGS="-L$dag_lib_dir"
+ AC_CHECK_LIB([dag], [dag_attach_stream], [dag_streams="1"], [dag_streams="0"])
+ AC_CHECK_LIB([dag],[dag_get_erf_types], [
+ AC_DEFINE(HAVE_DAG_GET_ERF_TYPES, 1, [define if you have dag_get_erf_types()])])
+ AC_CHECK_LIB([dag],[dag_get_stream_erf_types], [
+ AC_DEFINE(HAVE_DAG_GET_STREAM_ERF_TYPES, 1, [define if you have dag_get_stream_erf_types()])])
+
+ LDFLAGS=$saved_ldflags
+
+ if test "$dag_streams" = 1; then
+ AC_DEFINE(HAVE_DAG_STREAMS_API, 1, [define if you have streams capable DAG API])
+ LIBS="$LIBS -ldag"
+ LDFLAGS="$LDFLAGS -L$dag_lib_dir"
+
+ AC_CHECK_LIB([vdag],[vdag_set_device_info], [ac_dag_have_vdag="1"], [ac_dag_have_vdag="0"])
+ if test "$ac_dag_have_vdag" = 1; then
+ AC_DEFINE(HAVE_DAG_VDAG, 1, [define if you have vdag_set_device_info()])
+ LIBS="$LIBS -lpthread"
+ fi
+ fi
-AC_MSG_CHECKING(whether we have the DAG API)
+ AC_DEFINE(HAVE_DAG_API, 1, [define if you have the DAG API])
+ else
+ AC_MSG_RESULT(no)
-if test $ac_cv_lbl_dag_api = no; then
- AC_MSG_RESULT(no)
- if test "$want_dag" = yes; then
- # User wanted DAG support but we couldn't find it.
- AC_MSG_ERROR([DAG API requested, but not found at $dag_root: use --without-dag])
- fi
+ if test "$V_PCAP" = dag; then
+ # User requested "dag" capture type but we couldn't
+ # find the DAG API support.
+ AC_MSG_ERROR([DAG support requested with --with-pcap=dag, but the DAG headers weren't found at $dag_include_dir: make sure the DAG support is installed, specify a different path or paths if necessary, or don't request DAG support])
+ fi
- if test "$V_PCAP" = dag; then
- # User requested "dag" capture type but the DAG API wasn't
- # found.
- AC_MSG_ERROR([Specifying the capture type as "dag" requires the DAG API to be present; use the --with-dag options to specify the location. (Try "./configure --help" for more information.)])
+ if test "$want_dag" = yes; then
+ # User wanted DAG support but we couldn't find it.
+ AC_MSG_ERROR([DAG support requested with --with-dag, but the DAG headers weren't found at $dag_include_dir: make sure the DAG support is installed, specify a different path or paths if necessary, or don't request DAG support])
+ fi
fi
-else
- AC_MSG_RESULT(yes)
fi
AC_ARG_WITH(septel,
-AC_HELP_STRING([--with-septel@<:@=DIR@:>@],[include Septel support (located in directory DIR, if supplied). @<:@default=yes, on Linux, if present@:>@]),
+AC_HELP_STRING([--with-septel@<:@=DIR@:>@],[include Septel support (located in directory DIR, if supplied). @<:@default=yes, if present@:>@]),
[
if test "$withval" = no
then
@@ -855,38 +900,28 @@ AC_HELP_STRING([--with-septel@<:@=DIR@:>@],[include Septel support (located in d
septel_root=$withval
fi
],[
- #
- # Use Septel API if present, otherwise don't
- #
- want_septel=ifpresent
- septel_root=./../septel
-])
-ac_cv_lbl_septel_api=no
-case "$V_PCAP" in
-linux|septel)
- #
- # We support the Septel API if we're on Linux, or if we're building
- # a Septel-only libpcap.
- #
- ;;
-*)
- #
- # If the user explicitly requested Septel, tell them it's not
- # supported.
- #
- # If they expressed no preference, don't include it.
- #
- if test $want_septel = yes; then
- AC_MSG_ERROR(Septel support only available with 'linux' and 'septel' packet capture types)
- elif test $want_septel = yes; then
+ if test "$V_PCAP" = septel; then
+ # User requested Septel-only libpcap, so we'd better have
+ # the Septel API.
+ want_septel=yes
+ elif test "xxx_only" = yes; then
+ # User requested something-else-only pcap, so they don't
+ # want Septel support.
want_septel=no
+ else
+ #
+ # Use Septel API if present, otherwise don't
+ #
+ want_septel=ifpresent
fi
- ;;
-esac
+])
+ac_cv_lbl_septel_api=no
if test "$with_septel" != no; then
- AC_MSG_CHECKING(whether we have Septel API)
+ AC_MSG_CHECKING([whether we have Septel API headers])
+
+ # If necessary, set default paths for Septel API headers and libraries.
if test -z "$septel_root"; then
septel_root=$srcdir/../septel
fi
@@ -894,35 +929,41 @@ if test "$with_septel" != no; then
septel_tools_dir="$septel_root"
septel_include_dir="$septel_root/INC"
- ac_cv_lbl_septel_api=no
if test -r "$septel_include_dir/msg.h"; then
+ ac_cv_lbl_septel_api=yes
+ fi
+
+ if test "$ac_cv_lbl_septel_api" = yes; then
+ AC_MSG_RESULT([yes ($septel_include_dir)])
+
V_INCLS="$V_INCLS -I$septel_include_dir"
ADDLOBJS="$ADDLOBJS $septel_tools_dir/asciibin.o $septel_tools_dir/bit2byte.o $septel_tools_dir/confirm.o $septel_tools_dir/fmtmsg.o $septel_tools_dir/gct_unix.o $septel_tools_dir/hqueue.o $septel_tools_dir/ident.o $septel_tools_dir/mem.o $septel_tools_dir/pack.o $septel_tools_dir/parse.o $septel_tools_dir/pool.o $septel_tools_dir/sdlsig.o $septel_tools_dir/strtonum.o $septel_tools_dir/timer.o $septel_tools_dir/trace.o"
ADDLARCHIVEOBJS="$ADDLARCHIVEOBJS $septel_tools_dir/asciibin.o $septel_tools_dir/bit2byte.o $septel_tools_dir/confirm.o $septel_tools_dir/fmtmsg.o $septel_tools_dir/gct_unix.o $septel_tools_dir/hqueue.o $septel_tools_dir/ident.o $septel_tools_dir/mem.o $septel_tools_dir/pack.o $septel_tools_dir/parse.o $septel_tools_dir/pool.o $septel_tools_dir/sdlsig.o $septel_tools_dir/strtonum.o $septel_tools_dir/timer.o $septel_tools_dir/trace.o"
if test "$V_PCAP" != septel ; then
- SSRC="pcap-septel.c"
+ SSRC="$SSRC pcap-septel.c"
+ fi
+
+ AC_DEFINE(HAVE_SEPTEL_API, 1, [define if you have the Septel API])
+ else
+ AC_MSG_RESULT(no)
+
+ if test "$V_PCAP" = septel; then
+ # User requested "septel" capture type but
+ # we couldn't find the Septel API support.
+ AC_MSG_ERROR([Septel support requested with --with-pcap=septel, but the Septel headers weren't found at $septel_include_dir: make sure the Septel support is installed, specify a different path or paths if necessary, or don't request Septel support])
fi
- ac_cv_lbl_septel_api=yes
- fi
- AC_MSG_RESULT($ac_cv_lbl_septel_api)
- if test $ac_cv_lbl_septel_api = no; then
if test "$want_septel" = yes; then
- AC_MSG_ERROR(Septel API not found under directory $septel_root; use --without-septel)
+ # User wanted Septel support but we couldn't find it.
+ AC_MSG_ERROR([Septel support requested with --with-septel, but the Septel headers weren't found at $septel_include_dir: make sure the Septel support is installed, specify a different path or paths if necessary, or don't request Septel support])
fi
- else
- AC_DEFINE(HAVE_SEPTEL_API, 1, [define if you have a Septel API])
fi
fi
-if test "$V_PCAP" = septel -a "$ac_cv_lbl_septel_api" = no; then
- AC_MSG_ERROR(Specifying the capture type as 'septel' requires the Septel API to be present; use --with-septel=DIR)
-fi
-
# Check for Myricom SNF support.
AC_ARG_WITH([snf],
-AC_HELP_STRING([--with-snf@<:@=DIR@:>@],[include Myricom SNF support @<:@"yes", "no" or DIR; default="yes" on BSD and Linux if present@:>@]),
+AC_HELP_STRING([--with-snf@<:@=DIR@:>@],[include Myricom SNF support (located in directory DIR, if supplied). @<:@default=yes, if present@:>@]),
[
if test "$withval" = no
then
@@ -930,7 +971,7 @@ AC_HELP_STRING([--with-snf@<:@=DIR@:>@],[include Myricom SNF support @<:@"yes",
want_snf=no
elif test "$withval" = yes
then
- # User wants SNF support but hasn't specific a directory.
+ # User wants SNF support but hasn't specified a directory.
want_snf=yes
else
# User wants SNF support with a specified directory.
@@ -938,14 +979,24 @@ AC_HELP_STRING([--with-snf@<:@=DIR@:>@],[include Myricom SNF support @<:@"yes",
snf_root=$withval
fi
],[
- #
- # Use Sniffer API if present, otherwise don't
- #
- want_snf=ifpresent
+ if test "$V_PCAP" = snf; then
+ # User requested Sniffer-only libpcap, so we'd better have
+ # the Sniffer API.
+ want_snf=yes
+ elif test "xxx_only" = yes; then
+ # User requested something-else-only pcap, so they don't
+ # want SNF support.
+ want_snf=no
+ else
+ #
+ # Use Sniffer API if present, otherwise don't
+ #
+ want_snf=ifpresent
+ fi
])
AC_ARG_WITH([snf-includes],
-AC_HELP_STRING([--with-snf-includes=DIR],[Myricom SNF include directory]),
+AC_HELP_STRING([--with-snf-includes=IDIR],[Myricom SNF include directory, if not DIR/include]),
[
# User wants SNF with specific header directory
want_snf=yes
@@ -953,40 +1004,19 @@ AC_HELP_STRING([--with-snf-includes=DIR],[Myricom SNF include directory]),
],[])
AC_ARG_WITH([snf-libraries],
-AC_HELP_STRING([--with-snf-libraries=DIR],[Myricom SNF library directory]),
+AC_HELP_STRING([--with-snf-libraries=LDIR],[Myricom SNF library directory, if not DIR/lib]),
[
# User wants SNF with specific lib directory
want_snf=yes
snf_lib_dir=$withval
],[])
-case "$V_PCAP" in
-bpf|linux|snf)
- #
- # We support the Sniffer API if we're on BSD, Linux, or if we're
- # building a Sniffer-only libpcap.
- #
- ;;
-*)
- #
- # If the user explicitly requested Sniffer, tell them it's not
- # supported.
- #
- # If they expressed no preference, don't include it.
- #
- if test $want_snf = yes; then
- AC_MSG_ERROR(Myricom SNF support only available with 'bpf' 'linux' and 'snf' packet capture types)
- elif test $want_snf = yes; then
- want_snf=no
- fi
- ;;
-esac
-
ac_cv_lbl_snf_api=no
if test "$with_snf" != no; then
AC_MSG_CHECKING(whether we have Myricom Sniffer API)
+ # If necessary, set default paths for Sniffer headers and libraries.
if test -z "$snf_root"; then
snf_root=/opt/snf
fi
@@ -1000,56 +1030,157 @@ if test "$with_snf" != no; then
fi
if test -f "$snf_include_dir/snf.h"; then
- ac_cv_lbl_snf_api=yes
+ # We found a header; make sure we can link with the library
+ saved_ldflags=$LDFLAGS
+ LDFLAGS="$LDFLAGS -L$snf_lib_dir"
+ AC_CHECK_LIB([snf], [snf_init], [ac_cv_lbl_snf_api="yes"])
+ LDFLAGS="$saved_ldflags"
+ if test "$ac_cv_lbl_snf_api" = no; then
+ AC_MSG_ERROR(SNF API cannot correctly be linked; check config.log)
+ fi
fi
- AC_MSG_RESULT([$ac_cv_lbl_snf_api ($snf_root)])
- if test $ac_cv_lbl_snf_api = no; then
+ if test "$ac_cv_lbl_snf_api" = yes; then
+ AC_MSG_RESULT([yes ($snf_root)])
+
+ V_INCLS="$V_INCLS -I$snf_include_dir"
+ LIBS="$LIBS -lsnf"
+ LDFLAGS="$LDFLAGS -L$snf_lib_dir"
+
+ if test "$V_PCAP" != snf ; then
+ SSRC="$SSRC pcap-snf.c"
+ fi
+
+ AC_DEFINE(HAVE_SNF_API, 1, [define if you have the Myricom SNF API])
+ else
+ AC_MSG_RESULT(no)
+
+ if test "$want_snf" = yes; then
+ # User requested "snf" capture type but
+ # we couldn't find the Sniffer API support.
+ AC_MSG_ERROR([Myricom Sniffer support requested with --with-pcap=snf, but the Sniffer headers weren't found at $snf_include_dir: make sure the Sniffer support is installed, specify a different path or paths if necessary, or don't request Sniffer support])
+ fi
+
if test "$want_snf" = yes; then
- AC_MSG_ERROR(SNF API headers not found under $snf_include_dir; use --without-snf)
+ AC_MSG_ERROR([Myricom Sniffer support requested with --with-snf, but the Sniffer headers weren't found at $snf_include_dir: make sure the Sniffer support is installed, specify a different path or paths if necessary, or don't request Sniffer support])
fi
+ fi
+fi
+
+# Check for Riverbed TurboCap support.
+AC_ARG_WITH([turbocap],
+AC_HELP_STRING([--with-turbocap@<:@=DIR@:>@],[include Riverbed TurboCap support (located in directory DIR, if supplied). @<:@default=yes, if present@:>@]),
+[
+ if test "$withval" = no
+ then
+ # User explicitly doesn't want TurboCap
+ want_turbocap=no
+ elif test "$withval" = yes
+ then
+ # User wants TurboCap support but hasn't specified a directory.
+ want_turbocap=yes
else
- saved_ldflags=$LDFLAGS
- LDFLAGS="$LDFLAGS -L$snf_lib_dir"
- AC_CHECK_LIB([snf], [snf_init], [ac_cv_lbl_snf_api="yes"], [ac_cv_lbl_snf_api="no"])
- LDFLAGS="$saved_ldflags"
+ # User wants TurboCap support with a specified directory.
+ want_turbocap=yes
+ turbocap_root=$withval
+ fi
+],[
+ if test "xxx_only" = yes; then
+ # User requested something-else-only pcap, so they don't
+ # want TurboCap support.
+ want_turbocap=no
+ else
+ #
+ # Use TurboCap API if present, otherwise don't
+ #
+ want_turbocap=ifpresent
+ fi
+])
- if test $ac_cv_lbl_snf_api = no; then
- if test "$want_snf" = yes; then
- AC_MSG_ERROR(SNF API cannot correctly be linked check config.log; use --without-snf)
- fi
- else
- V_INCLS="$V_INCLS -I$snf_include_dir"
- LIBS="$LIBS -lsnf"
- LDFLAGS="$LDFLAGS -L$snf_lib_dir"
- if test "$V_PCAP" != snf ; then
- SSRC="pcap-snf.c"
- fi
- AC_DEFINE(HAVE_SNF_API, 1, [define if you have Myricom SNF API])
+ac_cv_lbl_turbocap_api=no
+if test "$want_turbocap" != no; then
+
+ AC_MSG_CHECKING(whether TurboCap is supported)
+
+ save_CFLAGS="$CFLAGS"
+ save_LIBS="$LIBS"
+ if test ! -z "$turbocap_root"; then
+ TURBOCAP_CFLAGS="-I$turbocap_root/include"
+ TURBOCAP_LIBS="-L$turbocap_root/lib"
+ CFLAGS="$CFLAGS $TURBOCAP_CFLAGS"
+ fi
+
+ AC_TRY_COMPILE(
+ [
+ #include <TcApi.h>
+ ],
+ [
+ TC_INSTANCE a; TC_PORT b; TC_BOARD c;
+ TC_INSTANCE i;
+ (void)TcInstanceCreateByName("foo", &i);
+ ],
+ ac_cv_lbl_turbocap_api=yes)
+
+ CFLAGS="$save_CFLAGS"
+ if test $ac_cv_lbl_turbocap_api = yes; then
+ AC_MSG_RESULT(yes)
+
+ SSRC="$SSRC pcap-tc.c"
+ V_INCLS="$V_INCLS $TURBOCAP_CFLAGS"
+ LIBS="$LIBS $TURBOCAP_LIBS -lTcApi -lpthread -lstdc++"
+
+ AC_DEFINE(HAVE_TC_API, 1, [define if you have the TurboCap API])
+ else
+ AC_MSG_RESULT(no)
+
+ if test "$want_turbocap" = yes; then
+ # User wanted Turbo support but we couldn't find it.
+ AC_MSG_ERROR([TurboCap support requested with --with-turbocap, but the TurboCap headers weren't found: make sure the TurboCap support is installed or don't request TurboCap support])
fi
fi
fi
-if test "$V_PCAP" = snf -a "$ac_cv_lbl_snf_api" = no; then
- AC_MSG_ERROR(Specifying the capture type as 'snf' requires the Myricom Sniffer API to be present; use --with-snf=DIR)
+#
+# Look for {f}lex.
+#
+AC_PROG_LEX
+if test "$LEX" = ":"; then
+ AC_MSG_ERROR([Neither flex nor lex was found.])
fi
-AC_LBL_LEX_AND_YACC(V_LEX, V_YACC, pcap_)
-if test "$V_LEX" = lex ; then
-# Some versions of lex can't handle the definitions section of scanner.l .
-# Try lexing it and complain if it can't deal.
- AC_CACHE_CHECK([for capable lex], tcpdump_cv_capable_lex,
- if lex -t scanner.l > /dev/null 2>&1; then
- tcpdump_cv_capable_lex=yes
- else
- tcpdump_cv_capable_lex=insufficient
- fi)
- if test $tcpdump_cv_capable_lex = insufficient ; then
- AC_MSG_ERROR([Your operating system's lex is insufficient to compile
- libpcap. flex is a lex replacement that has many advantages, including
- being able to compile libpcap. For more information, see
- http://www.gnu.org/software/flex/flex.html .])
- fi
+#
+# Make sure {f}lex supports the -P, --header-file, and --nounput flags
+# and supports processing our scanner.l.
+#
+AC_CACHE_CHECK([for capable lex], tcpdump_cv_capable_lex,
+ if $LEX -P pcap_ --header-file=/dev/null --nounput -t $srcdir/scanner.l > /dev/null 2>&1; then
+ tcpdump_cv_capable_lex=yes
+ else
+ tcpdump_cv_capable_lex=insufficient
+ fi)
+if test $tcpdump_cv_capable_lex = insufficient ; then
+ AC_MSG_ERROR([$LEX is insufficient to compile libpcap.
+ libpcap requires Flex 2.5.31 or later, or a compatible version of lex.])
+fi
+
+#
+# Look for yacc/bison/byacc.
+#
+AC_PROG_YACC
+
+#
+# Make sure it supports the -p flag and supports processing our
+# grammar.y.
+#
+AC_CACHE_CHECK([for capable yacc/bison], tcpdump_cv_capable_yacc,
+ if $YACC -p pcap_ -o /dev/null $srcdir/grammar.y >/dev/null 2>&1; then
+ tcpdump_cv_capable_yacc=yes
+ else
+ tcpdump_cv_capable_yacc=insufficient
+ fi)
+if test $tcpdump_cv_capable_yacc = insufficient ; then
+ AC_MSG_ERROR([$YACC is insufficient to compile libpcap.
+ libpcap requires Bison, Berkeley YACC, or another YACC compatible with them.])
fi
#
@@ -1321,12 +1452,6 @@ AC_LBL_HP_PPA_INFO_T_DL_MODULE_ID_1
AC_LBL_UNALIGNED_ACCESS
-#
-# Makefile.in includes rules to generate version.h, so we assume
-# that it will be generated if autoconf is used.
-#
-AC_DEFINE(HAVE_VERSION_H, 1, [define if version.h is generated in the build procedure])
-
rm -f net
ln -s ${srcdir}/bpf/net net
@@ -1348,10 +1473,22 @@ AC_SUBST(DYEXT)
AC_SUBST(MAN_FILE_FORMATS)
AC_SUBST(MAN_MISC_INFO)
-dnl check for USB sniffing support
-AC_MSG_CHECKING(for USB sniffing support)
-case "$host_os" in
-linux*)
+AC_ARG_ENABLE([usb],
+[AC_HELP_STRING([--enable-usb],[enable nusb support @<:@default=yes, if support available@:>@])],
+ [],
+ [enable_usb=yes])
+
+if test "xxx_only" = yes; then
+ # User requested something-else-only pcap, so they don't
+ # want USB support.
+ enable_usb=no
+fi
+
+if test "x$enable_usb" != "xno" ; then
+ dnl check for USB sniffing support
+ AC_MSG_CHECKING(for USB sniffing support)
+ case "$host_os" in
+ linux*)
AC_DEFINE(PCAP_SUPPORT_USB, 1, [target host supports USB sniffing])
USB_SRC=pcap-usb-linux.c
AC_MSG_RESULT(yes)
@@ -1402,29 +1539,39 @@ AC_INCLUDES_DEFAULT
fi
fi
;;
-*)
+ freebsd*)
+ #
+ # This just uses BPF in FreeBSD 8.4 and later; we don't need
+ # to check for anything special for capturing.
+ #
+ AC_MSG_RESULT([yes, in FreeBSD 8.4 and later])
+ ;;
+
+ *)
AC_MSG_RESULT(no)
;;
esac
+fi
AC_SUBST(PCAP_SUPPORT_USB)
AC_SUBST(USB_SRC)
dnl check for netfilter sniffing support
-AC_MSG_CHECKING(whether the platform could support netfilter sniffing)
-case "$host_os" in
-linux*)
- AC_MSG_RESULT(yes)
- #
- # Life's too short to deal with trying to get this to compile
- # if you don't get the right types defined with
- # __KERNEL_STRICT_NAMES getting defined by some other include.
- #
- # Check whether the includes Just Work. If not, don't turn on
- # netfilter support.
- #
- AC_MSG_CHECKING(whether we can compile the netfilter support)
- AC_CACHE_VAL(ac_cv_netfilter_can_compile,
- AC_TRY_COMPILE([
+if test "xxx_only" != yes; then
+ AC_MSG_CHECKING(whether the platform could support netfilter sniffing)
+ case "$host_os" in
+ linux*)
+ AC_MSG_RESULT(yes)
+ #
+ # Life's too short to deal with trying to get this to compile
+ # if you don't get the right types defined with
+ # __KERNEL_STRICT_NAMES getting defined by some other include.
+ #
+ # Check whether the includes Just Work. If not, don't turn on
+ # netfilter support.
+ #
+ AC_MSG_CHECKING(whether we can compile the netfilter support)
+ AC_CACHE_VAL(ac_cv_netfilter_can_compile,
+ AC_TRY_COMPILE([
AC_INCLUDES_DEFAULT
#include <sys/socket.h>
#include <netinet/in.h>
@@ -1438,17 +1585,18 @@ AC_INCLUDES_DEFAULT
[],
ac_cv_netfilter_can_compile=yes,
ac_cv_netfilter_can_compile=no))
- AC_MSG_RESULT($ac_cv_netfilter_can_compile)
- if test $ac_cv_netfilter_can_compile = yes ; then
- AC_DEFINE(PCAP_SUPPORT_NETFILTER, 1,
- [target host supports netfilter sniffing])
- NETFILTER_SRC=pcap-netfilter-linux.c
- fi
- ;;
-*)
- AC_MSG_RESULT(no)
- ;;
-esac
+ AC_MSG_RESULT($ac_cv_netfilter_can_compile)
+ if test $ac_cv_netfilter_can_compile = yes ; then
+ AC_DEFINE(PCAP_SUPPORT_NETFILTER, 1,
+ [target host supports netfilter sniffing])
+ NETFILTER_SRC=pcap-netfilter-linux.c
+ fi
+ ;;
+ *)
+ AC_MSG_RESULT(no)
+ ;;
+ esac
+fi
AC_SUBST(PCAP_SUPPORT_NETFILTER)
AC_SUBST(NETFILTER_SRC)
@@ -1457,6 +1605,12 @@ AC_ARG_ENABLE([bluetooth],
[],
[enable_bluetooth=ifsupportavailable])
+if test "xxx_only" = yes; then
+ # User requested something-else-only pcap, so they don't
+ # want Bluetooth support.
+ enable_bluetooth=no
+fi
+
if test "x$enable_bluetooth" != "xno" ; then
dnl check for Bluetooth sniffing support
case "$host_os" in
@@ -1531,157 +1685,90 @@ if test "x$enable_bluetooth" != "xno" ; then
AC_SUBST(BT_MONITOR_SRC)
fi
-AC_ARG_ENABLE([canusb],
-[AC_HELP_STRING([--enable-canusb],[enable canusb support @<:@default=yes, if support available@:>@])],
- [],
- [enable_canusb=ifsupportavailable])
-
-if test "x$enable_canusb" != "xno" ; then
- dnl check for canusb support
- case "$host_os" in
- linux*)
- AC_CHECK_HEADER(libusb-1.0/libusb.h,
- [
- AC_CHECK_LIB(usb-1.0, libusb_init,
- [
- AC_DEFINE(PCAP_SUPPORT_CANUSB, 1, [target host supports canusb])
- CANUSB_SRC=pcap-canusb-linux.c
- LIBS="-lusb-1.0 -lpthread $LIBS"
- ac_lbl_has_libusb=yes
- ],
- ac_lbl_has_libusb=no
- )
- ],
- ac_lbl_has_libusb=no
- )
- if test "x$ac_lbl_has_libusb" = "xyes" ; then
- AC_MSG_NOTICE(canusb sniffing is supported)
- else
- if test "x$enable_canusb" = "xyes" ; then
- AC_MSG_ERROR(canusb sniffing is not supported; install libusb1.0 lib devel to enable it)
- else
- AC_MSG_NOTICE(canusb sniffing is not supported; install libusb1.0 lib devel to enable it)
- fi
- fi
- ;;
- *)
- if test "x$enable_canusb" = "xyes" ; then
- AC_MSG_ERROR(no canusb support implemented for $host_os)
- else
- AC_MSG_NOTICE(no canusb support implemented for $host_os)
- fi
- ;;
- esac
- AC_SUBST(PCAP_SUPPORT_CANUSB)
- AC_SUBST(CANUSB_SRC)
-fi
-
-AC_ARG_ENABLE([can],
-[AC_HELP_STRING([--enable-can],[enable CAN support @<:@default=yes, if support available@:>@])],
- [],
- [enable_can=ifsupportavailable])
-
-if test "x$enable_can" != "xno" ; then
- dnl check for CAN sniffing support
- case "$host_os" in
- linux*)
- AC_CHECK_HEADER(linux/can.h,
- [
- AC_DEFINE(PCAP_SUPPORT_CAN, 1, [target host supports CAN sniffing])
- CAN_SRC=pcap-can-linux.c
- AC_MSG_NOTICE(CAN sniffing is supported)
- ],
- [
- if test "x$enable_can" = "xyes" ; then
- AC_MSG_ERROR(CAN sniffing is not supported)
- else
- AC_MSG_NOTICE(CAN sniffing is not supported)
- fi
- ],
- [#include <sys/socket.h>]
- )
- ;;
- *)
- if test "x$enable_can" = "xyes" ; then
- AC_MSG_ERROR(no CAN sniffing support implemented for $host_os)
- else
- AC_MSG_NOTICE(no CAN sniffing support implemented for $host_os)
- fi
- ;;
- esac
- AC_SUBST(PCAP_SUPPORT_CAN)
- AC_SUBST(CAN_SRC)
-fi
-
AC_ARG_ENABLE([dbus],
[AC_HELP_STRING([--enable-dbus],[enable D-Bus capture support @<:@default=yes, if support available@:>@])],
[],
[enable_dbus=ifavailable])
+if test "xxx_only" = yes; then
+ # User requested something-else-only pcap, so they don't
+ # want D-Bus support.
+ enable_dbus=no
+fi
+
if test "x$enable_dbus" != "xno"; then
if test "x$enable_dbus" = "xyes"; then
case "$host_os" in
darwin*)
#
+ # We don't support D-Bus sniffing on OS X; see
+ #
# https://bugs.freedesktop.org/show_bug.cgi?id=74029
#
+ # The user requested it, so fail.
+ #
AC_MSG_ERROR([Due to freedesktop.org bug 74029, D-Bus capture support is not available on OS X])
- ;;
esac
- else
+ else
case "$host_os" in
darwin*)
#
+ # We don't support D-Bus sniffing on OS X; see
+ #
# https://bugs.freedesktop.org/show_bug.cgi?id=74029
#
+ # The user dind't explicitly request it, so just
+ # silently refuse to enable it.
+ #
+ enable_dbus="no"
;;
+ esac
+ fi
+fi
- *)
- AC_CHECK_PROG([PKGCONFIG], [pkg-config], [pkg-config], [no])
- if test "x$PKGCONFIG" != "xno"; then
- AC_MSG_CHECKING([for D-Bus])
- if "$PKGCONFIG" dbus-1; then
- AC_MSG_RESULT([yes])
- DBUS_CFLAGS=`"$PKGCONFIG" --cflags dbus-1`
- DBUS_LIBS=`"$PKGCONFIG" --libs dbus-1`
- save_CFLAGS="$CFLAGS"
- save_LIBS="$LIBS"
- CFLAGS="$CFLAGS $DBUS_CFLAGS"
- LIBS="$LIBS $DBUS_LIBS"
- AC_MSG_CHECKING(whether the D-Bus library defines dbus_connection_read_write)
- AC_TRY_LINK(
- [#include <string.h>
-
- #include <time.h>
- #include <sys/time.h>
-
- #include <dbus/dbus.h>],
- [return dbus_connection_read_write(NULL, 0);],
- [
- AC_MSG_RESULT([yes])
- AC_DEFINE(PCAP_SUPPORT_DBUS, 1, [support D-Bus sniffing])
- DBUS_SRC=pcap-dbus.c
- V_INCLS="$V_INCLS $DBUS_CFLAGS"
- ],
- [
- AC_MSG_RESULT([no])
- if test "x$enable_dbus" = "xyes"; then
- AC_MSG_ERROR([--enable-dbus was given, but the D-Bus library doesn't define dbus_connection_read_write()])
- fi
- LIBS="$save_LIBS"
- ])
- CFLAGS="$save_CFLAGS"
- else
- AC_MSG_RESULT([no])
- if test "x$enable_dbus" = "xyes"; then
- AC_MSG_ERROR([--enable-dbus was given, but the dbus-1 package is not installed])
- fi
+if test "x$enable_dbus" != "xno"; then
+ AC_CHECK_PROG([PKGCONFIG], [pkg-config], [pkg-config], [no])
+ if test "x$PKGCONFIG" != "xno"; then
+ AC_MSG_CHECKING([for D-Bus])
+ if "$PKGCONFIG" dbus-1; then
+ AC_MSG_RESULT([yes])
+ DBUS_CFLAGS=`"$PKGCONFIG" --cflags dbus-1`
+ DBUS_LIBS=`"$PKGCONFIG" --libs dbus-1`
+ save_CFLAGS="$CFLAGS"
+ save_LIBS="$LIBS"
+ CFLAGS="$CFLAGS $DBUS_CFLAGS"
+ LIBS="$LIBS $DBUS_LIBS"
+ AC_MSG_CHECKING(whether the D-Bus library defines dbus_connection_read_write)
+ AC_TRY_LINK(
+ [#include <string.h>
+
+ #include <time.h>
+ #include <sys/time.h>
+
+ #include <dbus/dbus.h>],
+ [return dbus_connection_read_write(NULL, 0);],
+ [
+ AC_MSG_RESULT([yes])
+ AC_DEFINE(PCAP_SUPPORT_DBUS, 1, [support D-Bus sniffing])
+ DBUS_SRC=pcap-dbus.c
+ V_INCLS="$V_INCLS $DBUS_CFLAGS"
+ ],
+ [
+ AC_MSG_RESULT([no])
+ if test "x$enable_dbus" = "xyes"; then
+ AC_MSG_ERROR([--enable-dbus was given, but the D-Bus library doesn't define dbus_connection_read_write()])
fi
+ LIBS="$save_LIBS"
+ ])
+ CFLAGS="$save_CFLAGS"
+ else
+ AC_MSG_RESULT([no])
+ if test "x$enable_dbus" = "xyes"; then
+ AC_MSG_ERROR([--enable-dbus was given, but the dbus-1 package is not installed])
fi
- ;;
- esac
+ fi
fi
AC_SUBST(PCAP_SUPPORT_DBUS)
AC_SUBST(DBUS_SRC)
@@ -1697,6 +1784,24 @@ linux*)
;;
esac
+dnl The packet ring capture facility of Linux, described in
+dnl Documentation/networking/packet_mmap.txt, is not 32/64-bit compatible before
+dnl version 2.6.27. A 32-bit kernel requires a 32-bit userland, and likewise for
+dnl 64-bit. The effect of this is that a 32-bit libpcap binary will not run
+dnl correctly on a 64-bit kernel (the binary will use the wrong offsets into a
+dnl kernel struct). This problem was solved in Linux 2.6.27. Use
+dnl --disable-packet-ring whenever a 32-bit application must run on a 64-bit
+dnl target host, and either the build host or the target host run Linux 2.6.26
+dnl or earlier.
+AC_ARG_ENABLE([packet-ring],
+[AC_HELP_STRING([--enable-packet-ring],[enable Linux packet ring support @<:@default=yes@:>@])],
+,enable_packet_ring=yes)
+
+if test "x$enable_packet_ring" != "xno" ; then
+ AC_DEFINE(PCAP_SUPPORT_PACKET_RING, 1, [use Linux packet ring capture if available])
+ AC_SUBST(PCAP_SUPPORT_PACKET_RING)
+fi
+
AC_PROG_INSTALL
AC_CONFIG_HEADER(config.h)
diff --git a/contrib/libpcap/dlpisubs.c b/contrib/libpcap/dlpisubs.c
index 131fa279d843..fb94a6057675 100644
--- a/contrib/libpcap/dlpisubs.c
+++ b/contrib/libpcap/dlpisubs.c
@@ -186,8 +186,8 @@ pcap_process_pkts(pcap_t *p, pcap_handler callback, u_char *user,
pkthdr.len = origlen;
pkthdr.caplen = caplen;
/* Insure caplen does not exceed snapshot */
- if (pkthdr.caplen > p->snapshot)
- pkthdr.caplen = p->snapshot;
+ if (pkthdr.caplen > (bpf_u_int32)p->snapshot)
+ pkthdr.caplen = (bpf_u_int32)p->snapshot;
(*callback)(user, &pkthdr, pk);
if (++n >= count && !PACKET_COUNT_IS_UNLIMITED(count)) {
p->cc = ep - bufp;
@@ -255,8 +255,29 @@ pcap_process_mactype(pcap_t *p, u_int mactype)
break;
#endif
+#ifdef DL_IPV4
+ case DL_IPV4:
+ p->linktype = DLT_IPV4;
+ p->offset = 0;
+ break;
+#endif
+
+#ifdef DL_IPV6
+ case DL_IPV6:
+ p->linktype = DLT_IPV6;
+ p->offset = 0;
+ break;
+#endif
+
+#ifdef DL_IPNET
+ case DL_IPNET:
+ p->linktype = DLT_IPNET;
+ p->offset = 0;
+ break;
+#endif
+
default:
- snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "unknown mactype %u",
+ pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "unknown mactype 0x%x",
mactype);
retv = -1;
}
@@ -326,7 +347,7 @@ int
pcap_alloc_databuf(pcap_t *p)
{
p->bufsize = PKTBUFSIZE;
- p->buffer = (u_char *)malloc(p->bufsize + p->offset);
+ p->buffer = malloc(p->bufsize + p->offset);
if (p->buffer == NULL) {
strlcpy(p->errbuf, pcap_strerror(errno), PCAP_ERRBUF_SIZE);
return (-1);
@@ -362,6 +383,6 @@ strioctl(int fd, int cmd, int len, char *dp)
static void
pcap_stream_err(const char *func, int err, char *errbuf)
{
- snprintf(errbuf, PCAP_ERRBUF_SIZE, "%s: %s", func, pcap_strerror(err));
+ pcap_snprintf(errbuf, PCAP_ERRBUF_SIZE, "%s: %s", func, pcap_strerror(err));
}
#endif
diff --git a/contrib/libpcap/etherent.c b/contrib/libpcap/etherent.c
index 707fd9d148b7..5cfd1b4c3bbb 100644
--- a/contrib/libpcap/etherent.c
+++ b/contrib/libpcap/etherent.c
@@ -23,9 +23,9 @@
#include "config.h"
#endif
-#ifdef WIN32
+#ifdef _WIN32
#include <pcap-stdinc.h>
-#else /* WIN32 */
+#else /* _WIN32 */
#if HAVE_INTTYPES_H
#include <inttypes.h>
#elif HAVE_STDINT_H
@@ -35,7 +35,7 @@
#include <sys/bitypes.h>
#endif
#include <sys/types.h>
-#endif /* WIN32 */
+#endif /* _WIN32 */
#include <ctype.h>
#include <memory.h>
diff --git a/contrib/libpcap/ethertype.h b/contrib/libpcap/ethertype.h
index 8bab881634d6..51f63083f8b8 100644
--- a/contrib/libpcap/ethertype.h
+++ b/contrib/libpcap/ethertype.h
@@ -112,6 +112,9 @@
#ifndef ETHERTYPE_PPPOES
#define ETHERTYPE_PPPOES 0x8864
#endif
+#ifndef ETHERTYPE_8021AD
+#define ETHERTYPE_8021AD 0x88a8
+#endif
#ifndef ETHERTYPE_LOOPBACK
#define ETHERTYPE_LOOPBACK 0x9000
#endif
diff --git a/contrib/libpcap/extract.h b/contrib/libpcap/extract.h
new file mode 100644
index 000000000000..face5b7e94cd
--- /dev/null
+++ b/contrib/libpcap/extract.h
@@ -0,0 +1,221 @@
+/*
+ * Copyright (c) 1992, 1993, 1994, 1995, 1996
+ * The Regents of the University of California. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that: (1) source code distributions
+ * retain the above copyright notice and this paragraph in its entirety, (2)
+ * distributions including binary code include the above copyright notice and
+ * this paragraph in its entirety in the documentation or other materials
+ * provided with the distribution, and (3) all advertising materials mentioning
+ * features or use of this software display the following acknowledgement:
+ * ``This product includes software developed by the University of California,
+ * Lawrence Berkeley Laboratory and its contributors.'' Neither the name of
+ * the University nor the names of its contributors may be used to endorse
+ * or promote products derived from this software without specific prior
+ * written permission.
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+ */
+
+#ifndef _WIN32
+#include <arpa/inet.h>
+#endif
+
+/*
+ * Macros to extract possibly-unaligned big-endian integral values.
+ */
+#ifdef LBL_ALIGN
+/*
+ * The processor doesn't natively handle unaligned loads.
+ */
+#if defined(__GNUC__) && defined(HAVE___ATTRIBUTE__) && \
+ (defined(__alpha) || defined(__alpha__) || \
+ defined(__mips) || defined(__mips__))
+
+/*
+ * This is a GCC-compatible compiler and we have __attribute__, which
+ * we assume that mean we have __attribute__((packed)), and this is
+ * MIPS or Alpha, which has instructions that can help when doing
+ * unaligned loads.
+ *
+ * Declare packed structures containing a uint16_t and a uint32_t,
+ * cast the pointer to point to one of those, and fetch through it;
+ * the GCC manual doesn't appear to explicitly say that
+ * __attribute__((packed)) causes the compiler to generate unaligned-safe
+ * code, but it apppears to do so.
+ *
+ * We do this in case the compiler can generate code using those
+ * instructions to do an unaligned load and pass stuff to "ntohs()" or
+ * "ntohl()", which might be better than than the code to fetch the
+ * bytes one at a time and assemble them. (That might not be the
+ * case on a little-endian platform, such as DEC's MIPS machines and
+ * Alpha machines, where "ntohs()" and "ntohl()" might not be done
+ * inline.)
+ *
+ * We do this only for specific architectures because, for example,
+ * at least some versions of GCC, when compiling for 64-bit SPARC,
+ * generate code that assumes alignment if we do this.
+ *
+ * XXX - add other architectures and compilers as possible and
+ * appropriate.
+ *
+ * HP's C compiler, indicated by __HP_cc being defined, supports
+ * "#pragma unaligned N" in version A.05.50 and later, where "N"
+ * specifies a number of bytes at which the typedef on the next
+ * line is aligned, e.g.
+ *
+ * #pragma unalign 1
+ * typedef uint16_t unaligned_uint16_t;
+ *
+ * to define unaligned_uint16_t as a 16-bit unaligned data type.
+ * This could be presumably used, in sufficiently recent versions of
+ * the compiler, with macros similar to those below. This would be
+ * useful only if that compiler could generate better code for PA-RISC
+ * or Itanium than would be generated by a bunch of shifts-and-ORs.
+ *
+ * DEC C, indicated by __DECC being defined, has, at least on Alpha,
+ * an __unaligned qualifier that can be applied to pointers to get the
+ * compiler to generate code that does unaligned loads and stores when
+ * dereferencing the pointer in question.
+ *
+ * XXX - what if the native C compiler doesn't support
+ * __attribute__((packed))? How can we get it to generate unaligned
+ * accesses for *specific* items?
+ */
+typedef struct {
+ uint16_t val;
+} __attribute__((packed)) unaligned_uint16_t;
+
+typedef struct {
+ uint32_t val;
+} __attribute__((packed)) unaligned_uint32_t;
+
+static inline uint16_t
+EXTRACT_16BITS(const void *p)
+{
+ return ((uint16_t)ntohs(((const unaligned_uint16_t *)(p))->val));
+}
+
+static inline uint32_t
+EXTRACT_32BITS(const void *p)
+{
+ return ((uint32_t)ntohl(((const unaligned_uint32_t *)(p))->val));
+}
+
+static inline uint64_t
+EXTRACT_64BITS(const void *p)
+{
+ return ((uint64_t)(((uint64_t)ntohl(((const unaligned_uint32_t *)(p) + 0)->val)) << 32 | \
+ ((uint64_t)ntohl(((const unaligned_uint32_t *)(p) + 1)->val)) << 0));
+}
+
+#else /* have to do it a byte at a time */
+/*
+ * This isn't a GCC-compatible compiler, we don't have __attribute__,
+ * or we do but we don't know of any better way with this instruction
+ * set to do unaligned loads, so do unaligned loads of big-endian
+ * quantities the hard way - fetch the bytes one at a time and
+ * assemble them.
+ */
+#define EXTRACT_16BITS(p) \
+ ((uint16_t)(((uint16_t)(*((const uint8_t *)(p) + 0)) << 8) | \
+ ((uint16_t)(*((const uint8_t *)(p) + 1)) << 0)))
+#define EXTRACT_32BITS(p) \
+ ((uint32_t)(((uint32_t)(*((const uint8_t *)(p) + 0)) << 24) | \
+ ((uint32_t)(*((const uint8_t *)(p) + 1)) << 16) | \
+ ((uint32_t)(*((const uint8_t *)(p) + 2)) << 8) | \
+ ((uint32_t)(*((const uint8_t *)(p) + 3)) << 0)))
+#define EXTRACT_64BITS(p) \
+ ((uint64_t)(((uint64_t)(*((const uint8_t *)(p) + 0)) << 56) | \
+ ((uint64_t)(*((const uint8_t *)(p) + 1)) << 48) | \
+ ((uint64_t)(*((const uint8_t *)(p) + 2)) << 40) | \
+ ((uint64_t)(*((const uint8_t *)(p) + 3)) << 32) | \
+ ((uint64_t)(*((const uint8_t *)(p) + 4)) << 24) | \
+ ((uint64_t)(*((const uint8_t *)(p) + 5)) << 16) | \
+ ((uint64_t)(*((const uint8_t *)(p) + 6)) << 8) | \
+ ((uint64_t)(*((const uint8_t *)(p) + 7)) << 0)))
+#endif /* must special-case unaligned accesses */
+#else /* LBL_ALIGN */
+/*
+ * The processor natively handles unaligned loads, so we can just
+ * cast the pointer and fetch through it.
+ */
+static inline uint16_t
+EXTRACT_16BITS(const void *p)
+{
+ return ((uint16_t)ntohs(*(const uint16_t *)(p)));
+}
+
+static inline uint32_t
+EXTRACT_32BITS(const void *p)
+{
+ return ((uint32_t)ntohl(*(const uint32_t *)(p)));
+}
+
+static inline uint64_t
+EXTRACT_64BITS(const void *p)
+{
+ return ((uint64_t)(((uint64_t)ntohl(*((const uint32_t *)(p) + 0))) << 32 | \
+ ((uint64_t)ntohl(*((const uint32_t *)(p) + 1))) << 0));
+
+}
+
+#endif /* LBL_ALIGN */
+
+#define EXTRACT_24BITS(p) \
+ ((uint32_t)(((uint32_t)(*((const uint8_t *)(p) + 0)) << 16) | \
+ ((uint32_t)(*((const uint8_t *)(p) + 1)) << 8) | \
+ ((uint32_t)(*((const uint8_t *)(p) + 2)) << 0)))
+
+#define EXTRACT_40BITS(p) \
+ ((uint64_t)(((uint64_t)(*((const uint8_t *)(p) + 0)) << 32) | \
+ ((uint64_t)(*((const uint8_t *)(p) + 1)) << 24) | \
+ ((uint64_t)(*((const uint8_t *)(p) + 2)) << 16) | \
+ ((uint64_t)(*((const uint8_t *)(p) + 3)) << 8) | \
+ ((uint64_t)(*((const uint8_t *)(p) + 4)) << 0)))
+
+#define EXTRACT_48BITS(p) \
+ ((uint64_t)(((uint64_t)(*((const uint8_t *)(p) + 0)) << 40) | \
+ ((uint64_t)(*((const uint8_t *)(p) + 1)) << 32) | \
+ ((uint64_t)(*((const uint8_t *)(p) + 2)) << 24) | \
+ ((uint64_t)(*((const uint8_t *)(p) + 3)) << 16) | \
+ ((uint64_t)(*((const uint8_t *)(p) + 4)) << 8) | \
+ ((uint64_t)(*((const uint8_t *)(p) + 5)) << 0)))
+
+#define EXTRACT_56BITS(p) \
+ ((uint64_t)(((uint64_t)(*((const uint8_t *)(p) + 0)) << 48) | \
+ ((uint64_t)(*((const uint8_t *)(p) + 1)) << 40) | \
+ ((uint64_t)(*((const uint8_t *)(p) + 2)) << 32) | \
+ ((uint64_t)(*((const uint8_t *)(p) + 3)) << 24) | \
+ ((uint64_t)(*((const uint8_t *)(p) + 4)) << 16) | \
+ ((uint64_t)(*((const uint8_t *)(p) + 5)) << 8) | \
+ ((uint64_t)(*((const uint8_t *)(p) + 6)) << 0)))
+
+/*
+ * Macros to extract possibly-unaligned little-endian integral values.
+ * XXX - do loads on little-endian machines that support unaligned loads?
+ */
+#define EXTRACT_LE_8BITS(p) (*(p))
+#define EXTRACT_LE_16BITS(p) \
+ ((uint16_t)(((uint16_t)(*((const uint8_t *)(p) + 1)) << 8) | \
+ ((uint16_t)(*((const uint8_t *)(p) + 0)) << 0)))
+#define EXTRACT_LE_32BITS(p) \
+ ((uint32_t)(((uint32_t)(*((const uint8_t *)(p) + 3)) << 24) | \
+ ((uint32_t)(*((const uint8_t *)(p) + 2)) << 16) | \
+ ((uint32_t)(*((const uint8_t *)(p) + 1)) << 8) | \
+ ((uint32_t)(*((const uint8_t *)(p) + 0)) << 0)))
+#define EXTRACT_LE_24BITS(p) \
+ ((uint32_t)(((uint32_t)(*((const uint8_t *)(p) + 2)) << 16) | \
+ ((uint32_t)(*((const uint8_t *)(p) + 1)) << 8) | \
+ ((uint32_t)(*((const uint8_t *)(p) + 0)) << 0)))
+#define EXTRACT_LE_64BITS(p) \
+ ((uint64_t)(((uint64_t)(*((const uint8_t *)(p) + 7)) << 56) | \
+ ((uint64_t)(*((const uint8_t *)(p) + 6)) << 48) | \
+ ((uint64_t)(*((const uint8_t *)(p) + 5)) << 40) | \
+ ((uint64_t)(*((const uint8_t *)(p) + 4)) << 32) | \
+ ((uint64_t)(*((const uint8_t *)(p) + 3)) << 24) | \
+ ((uint64_t)(*((const uint8_t *)(p) + 2)) << 16) | \
+ ((uint64_t)(*((const uint8_t *)(p) + 1)) << 8) | \
+ ((uint64_t)(*((const uint8_t *)(p) + 0)) << 0)))
diff --git a/contrib/libpcap/fad-getad.c b/contrib/libpcap/fad-getad.c
index 6fd3360f788f..b67b5cdcd46a 100644
--- a/contrib/libpcap/fad-getad.c
+++ b/contrib/libpcap/fad-getad.c
@@ -144,7 +144,8 @@ get_sa_len(struct sockaddr *addr)
* could be opened.
*/
int
-pcap_findalldevs_interfaces(pcap_if_t **alldevsp, char *errbuf)
+pcap_findalldevs_interfaces(pcap_if_t **alldevsp, char *errbuf,
+ int (*check_usable)(const char *))
{
pcap_if_t *devlist = NULL;
struct ifaddrs *ifap, *ifa;
@@ -168,12 +169,51 @@ pcap_findalldevs_interfaces(pcap_if_t **alldevsp, char *errbuf)
* those.
*/
if (getifaddrs(&ifap) != 0) {
- (void)snprintf(errbuf, PCAP_ERRBUF_SIZE,
+ (void)pcap_snprintf(errbuf, PCAP_ERRBUF_SIZE,
"getifaddrs: %s", pcap_strerror(errno));
return (-1);
}
for (ifa = ifap; ifa != NULL; ifa = ifa->ifa_next) {
/*
+ * If this entry has a colon followed by a number at
+ * the end, we assume it's a logical interface. Those
+ * are just the way you assign multiple IP addresses to
+ * a real interface on Linux, so an entry for a logical
+ * interface should be treated like the entry for the
+ * real interface; we do that by stripping off the ":"
+ * and the number.
+ *
+ * XXX - should we do this only on Linux?
+ */
+ p = strchr(ifa->ifa_name, ':');
+ if (p != NULL) {
+ /*
+ * We have a ":"; is it followed by a number?
+ */
+ q = p + 1;
+ while (isdigit((unsigned char)*q))
+ q++;
+ if (*q == '\0') {
+ /*
+ * All digits after the ":" until the end.
+ * Strip off the ":" and everything after
+ * it.
+ */
+ *p = '\0';
+ }
+ }
+
+ /*
+ * Can we capture on this device?
+ */
+ if (!(*check_usable)(ifa->ifa_name)) {
+ /*
+ * No.
+ */
+ continue;
+ }
+
+ /*
* "ifa_addr" was apparently null on at least one
* interface on some system. Therefore, we supply
* the address and netmask only if "ifa_addr" is
@@ -223,39 +263,11 @@ pcap_findalldevs_interfaces(pcap_if_t **alldevsp, char *errbuf)
}
/*
- * If this entry has a colon followed by a number at
- * the end, we assume it's a logical interface. Those
- * are just the way you assign multiple IP addresses to
- * a real interface on Linux, so an entry for a logical
- * interface should be treated like the entry for the
- * real interface; we do that by stripping off the ":"
- * and the number.
- *
- * XXX - should we do this only on Linux?
- */
- p = strchr(ifa->ifa_name, ':');
- if (p != NULL) {
- /*
- * We have a ":"; is it followed by a number?
- */
- q = p + 1;
- while (isdigit((unsigned char)*q))
- q++;
- if (*q == '\0') {
- /*
- * All digits after the ":" until the end.
- * Strip off the ":" and everything after
- * it.
- */
- *p = '\0';
- }
- }
-
- /*
* Add information for this address to the list.
*/
if (add_addr_to_iflist(&devlist, ifa->ifa_name,
- ifa->ifa_flags, addr, addr_size, netmask, addr_size,
+ if_flags_to_pcap_flags(ifa->ifa_name, ifa->ifa_flags),
+ addr, addr_size, netmask, addr_size,
broadaddr, broadaddr_size, dstaddr, dstaddr_size,
errbuf) < 0) {
ret = -1;
diff --git a/contrib/libpcap/fad-gifc.c b/contrib/libpcap/fad-gifc.c
index 5c3357c7cea0..1b24af292985 100644
--- a/contrib/libpcap/fad-gifc.c
+++ b/contrib/libpcap/fad-gifc.c
@@ -132,12 +132,13 @@ struct rtentry; /* declarations in <net/if.h> */
* we already have that.
*/
int
-pcap_findalldevs_interfaces(pcap_if_t **alldevsp, char *errbuf)
+pcap_findalldevs_interfaces(pcap_if_t **alldevsp, char *errbuf,
+ int (*check_usable)(const char *))
{
pcap_if_t *devlist = NULL;
register int fd;
register struct ifreq *ifrp, *ifend, *ifnext;
- int n;
+ size_t n;
struct ifconf ifc;
char *buf = NULL;
unsigned buf_size;
@@ -154,7 +155,7 @@ pcap_findalldevs_interfaces(pcap_if_t **alldevsp, char *errbuf)
*/
fd = socket(AF_INET, SOCK_DGRAM, 0);
if (fd < 0) {
- (void)snprintf(errbuf, PCAP_ERRBUF_SIZE,
+ (void)pcap_snprintf(errbuf, PCAP_ERRBUF_SIZE,
"socket: %s", pcap_strerror(errno));
return (-1);
}
@@ -170,7 +171,7 @@ pcap_findalldevs_interfaces(pcap_if_t **alldevsp, char *errbuf)
for (;;) {
buf = malloc(buf_size);
if (buf == NULL) {
- (void)snprintf(errbuf, PCAP_ERRBUF_SIZE,
+ (void)pcap_snprintf(errbuf, PCAP_ERRBUF_SIZE,
"malloc: %s", pcap_strerror(errno));
(void)close(fd);
return (-1);
@@ -181,7 +182,7 @@ pcap_findalldevs_interfaces(pcap_if_t **alldevsp, char *errbuf)
memset(buf, 0, buf_size);
if (ioctl(fd, SIOCGIFCONF, (char *)&ifc) < 0
&& errno != EINVAL) {
- (void)snprintf(errbuf, PCAP_ERRBUF_SIZE,
+ (void)pcap_snprintf(errbuf, PCAP_ERRBUF_SIZE,
"SIOCGIFCONF: %s", pcap_strerror(errno));
(void)close(fd);
free(buf);
@@ -217,12 +218,12 @@ pcap_findalldevs_interfaces(pcap_if_t **alldevsp, char *errbuf)
/*
* XXX - The 32-bit compatibility layer for Linux on IA-64
* is slightly broken. It correctly converts the structures
- * to and from kernel land from 64 bit to 32 bit but
- * doesn't update ifc.ifc_len, leaving it larger than the
- * amount really used. This means we read off the end
- * of the buffer and encounter an interface with an
- * "empty" name. Since this is highly unlikely to ever
- * occur in a valid case we can just finish looking for
+ * to and from kernel land from 64 bit to 32 bit but
+ * doesn't update ifc.ifc_len, leaving it larger than the
+ * amount really used. This means we read off the end
+ * of the buffer and encounter an interface with an
+ * "empty" name. Since this is highly unlikely to ever
+ * occur in a valid case we can just finish looking for
* interfaces if we see an empty name.
*/
if (!(*ifrp->ifr_name))
@@ -237,6 +238,16 @@ pcap_findalldevs_interfaces(pcap_if_t **alldevsp, char *errbuf)
continue;
/*
+ * Can we capture on this device?
+ */
+ if (!(*check_usable)(ifrp->ifr_name)) {
+ /*
+ * No.
+ */
+ continue;
+ }
+
+ /*
* Get the flags for this interface.
*/
strncpy(ifrflags.ifr_name, ifrp->ifr_name,
@@ -244,7 +255,7 @@ pcap_findalldevs_interfaces(pcap_if_t **alldevsp, char *errbuf)
if (ioctl(fd, SIOCGIFFLAGS, (char *)&ifrflags) < 0) {
if (errno == ENXIO)
continue;
- (void)snprintf(errbuf, PCAP_ERRBUF_SIZE,
+ (void)pcap_snprintf(errbuf, PCAP_ERRBUF_SIZE,
"SIOCGIFFLAGS: %.*s: %s",
(int)sizeof(ifrflags.ifr_name),
ifrflags.ifr_name,
@@ -268,7 +279,7 @@ pcap_findalldevs_interfaces(pcap_if_t **alldevsp, char *errbuf)
netmask = NULL;
netmask_size = 0;
} else {
- (void)snprintf(errbuf, PCAP_ERRBUF_SIZE,
+ (void)pcap_snprintf(errbuf, PCAP_ERRBUF_SIZE,
"SIOCGIFNETMASK: %.*s: %s",
(int)sizeof(ifrnetmask.ifr_name),
ifrnetmask.ifr_name,
@@ -299,7 +310,7 @@ pcap_findalldevs_interfaces(pcap_if_t **alldevsp, char *errbuf)
broadaddr = NULL;
broadaddr_size = 0;
} else {
- (void)snprintf(errbuf, PCAP_ERRBUF_SIZE,
+ (void)pcap_snprintf(errbuf, PCAP_ERRBUF_SIZE,
"SIOCGIFBRDADDR: %.*s: %s",
(int)sizeof(ifrbroadaddr.ifr_name),
ifrbroadaddr.ifr_name,
@@ -338,7 +349,7 @@ pcap_findalldevs_interfaces(pcap_if_t **alldevsp, char *errbuf)
dstaddr = NULL;
dstaddr_size = 0;
} else {
- (void)snprintf(errbuf, PCAP_ERRBUF_SIZE,
+ (void)pcap_snprintf(errbuf, PCAP_ERRBUF_SIZE,
"SIOCGIFDSTADDR: %.*s: %s",
(int)sizeof(ifrdstaddr.ifr_name),
ifrdstaddr.ifr_name,
@@ -391,10 +402,10 @@ pcap_findalldevs_interfaces(pcap_if_t **alldevsp, char *errbuf)
* Add information for this address to the list.
*/
if (add_addr_to_iflist(&devlist, ifrp->ifr_name,
- ifrflags.ifr_flags, &ifrp->ifr_addr,
- SA_LEN(&ifrp->ifr_addr), netmask, netmask_size,
- broadaddr, broadaddr_size, dstaddr, dstaddr_size,
- errbuf) < 0) {
+ if_flags_to_pcap_flags(ifrp->ifr_name, ifrflags.ifr_flags),
+ &ifrp->ifr_addr, SA_LEN(&ifrp->ifr_addr),
+ netmask, netmask_size, broadaddr, broadaddr_size,
+ dstaddr, dstaddr_size, errbuf) < 0) {
ret = -1;
break;
}
diff --git a/contrib/libpcap/fad-glifc.c b/contrib/libpcap/fad-glifc.c
index 1a820ad90c61..511481cf9636 100644
--- a/contrib/libpcap/fad-glifc.c
+++ b/contrib/libpcap/fad-glifc.c
@@ -75,7 +75,8 @@ struct rtentry; /* declarations in <net/if.h> */
* SIOCGLIFCONF rather than SIOCGIFCONF in order to get IPv6 addresses.)
*/
int
-pcap_findalldevs_interfaces(pcap_if_t **alldevsp, char *errbuf)
+pcap_findalldevs_interfaces(pcap_if_t **alldevsp, char *errbuf,
+ int (*check_usable)(const char *))
{
pcap_if_t *devlist = NULL;
register int fd4, fd6, fd;
@@ -97,7 +98,7 @@ pcap_findalldevs_interfaces(pcap_if_t **alldevsp, char *errbuf)
*/
fd4 = socket(AF_INET, SOCK_DGRAM, 0);
if (fd4 < 0) {
- (void)snprintf(errbuf, PCAP_ERRBUF_SIZE,
+ (void)pcap_snprintf(errbuf, PCAP_ERRBUF_SIZE,
"socket: %s", pcap_strerror(errno));
return (-1);
}
@@ -107,7 +108,7 @@ pcap_findalldevs_interfaces(pcap_if_t **alldevsp, char *errbuf)
*/
fd6 = socket(AF_INET6, SOCK_DGRAM, 0);
if (fd6 < 0) {
- (void)snprintf(errbuf, PCAP_ERRBUF_SIZE,
+ (void)pcap_snprintf(errbuf, PCAP_ERRBUF_SIZE,
"socket: %s", pcap_strerror(errno));
(void)close(fd4);
return (-1);
@@ -120,7 +121,7 @@ pcap_findalldevs_interfaces(pcap_if_t **alldevsp, char *errbuf)
ifn.lifn_flags = 0;
ifn.lifn_count = 0;
if (ioctl(fd4, SIOCGLIFNUM, (char *)&ifn) < 0) {
- (void)snprintf(errbuf, PCAP_ERRBUF_SIZE,
+ (void)pcap_snprintf(errbuf, PCAP_ERRBUF_SIZE,
"SIOCGLIFNUM: %s", pcap_strerror(errno));
(void)close(fd6);
(void)close(fd4);
@@ -133,7 +134,7 @@ pcap_findalldevs_interfaces(pcap_if_t **alldevsp, char *errbuf)
buf_size = ifn.lifn_count * sizeof (struct lifreq);
buf = malloc(buf_size);
if (buf == NULL) {
- (void)snprintf(errbuf, PCAP_ERRBUF_SIZE,
+ (void)pcap_snprintf(errbuf, PCAP_ERRBUF_SIZE,
"malloc: %s", pcap_strerror(errno));
(void)close(fd6);
(void)close(fd4);
@@ -149,7 +150,7 @@ pcap_findalldevs_interfaces(pcap_if_t **alldevsp, char *errbuf)
ifc.lifc_flags = 0;
memset(buf, 0, buf_size);
if (ioctl(fd4, SIOCGLIFCONF, (char *)&ifc) < 0) {
- (void)snprintf(errbuf, PCAP_ERRBUF_SIZE,
+ (void)pcap_snprintf(errbuf, PCAP_ERRBUF_SIZE,
"SIOCGLIFCONF: %s", pcap_strerror(errno));
(void)close(fd6);
(void)close(fd4);
@@ -165,14 +166,6 @@ pcap_findalldevs_interfaces(pcap_if_t **alldevsp, char *errbuf)
for (; ifrp < ifend; ifrp++) {
/*
- * IPv6 or not?
- */
- if (((struct sockaddr *)&ifrp->lifr_addr)->sa_family == AF_INET6)
- fd = fd6;
- else
- fd = fd4;
-
- /*
* Skip entries that begin with "dummy".
* XXX - what are these? Is this Linux-specific?
* Are there platforms on which we shouldn't do this?
@@ -180,27 +173,23 @@ pcap_findalldevs_interfaces(pcap_if_t **alldevsp, char *errbuf)
if (strncmp(ifrp->lifr_name, "dummy", 5) == 0)
continue;
-#ifdef HAVE_SOLARIS
/*
- * Skip entries that have a ":" followed by a number
- * at the end - those are Solaris virtual interfaces
- * on which you can't capture.
+ * Can we capture on this device?
*/
- p = strchr(ifrp->lifr_name, ':');
- if (p != NULL) {
+ if (!(*check_usable)(ifrp->lifr_name)) {
/*
- * We have a ":"; is it followed by a number?
+ * No.
*/
- while (isdigit((unsigned char)*p))
- p++;
- if (*p == '\0') {
- /*
- * All digits after the ":" until the end.
- */
- continue;
- }
+ continue;
}
-#endif
+
+ /*
+ * IPv6 or not?
+ */
+ if (((struct sockaddr *)&ifrp->lifr_addr)->sa_family == AF_INET6)
+ fd = fd6;
+ else
+ fd = fd4;
/*
* Get the flags for this interface.
@@ -210,7 +199,7 @@ pcap_findalldevs_interfaces(pcap_if_t **alldevsp, char *errbuf)
if (ioctl(fd, SIOCGLIFFLAGS, (char *)&ifrflags) < 0) {
if (errno == ENXIO)
continue;
- (void)snprintf(errbuf, PCAP_ERRBUF_SIZE,
+ (void)pcap_snprintf(errbuf, PCAP_ERRBUF_SIZE,
"SIOCGLIFFLAGS: %.*s: %s",
(int)sizeof(ifrflags.lifr_name),
ifrflags.lifr_name,
@@ -233,7 +222,7 @@ pcap_findalldevs_interfaces(pcap_if_t **alldevsp, char *errbuf)
*/
netmask = NULL;
} else {
- (void)snprintf(errbuf, PCAP_ERRBUF_SIZE,
+ (void)pcap_snprintf(errbuf, PCAP_ERRBUF_SIZE,
"SIOCGLIFNETMASK: %.*s: %s",
(int)sizeof(ifrnetmask.lifr_name),
ifrnetmask.lifr_name,
@@ -261,7 +250,7 @@ pcap_findalldevs_interfaces(pcap_if_t **alldevsp, char *errbuf)
*/
broadaddr = NULL;
} else {
- (void)snprintf(errbuf, PCAP_ERRBUF_SIZE,
+ (void)pcap_snprintf(errbuf, PCAP_ERRBUF_SIZE,
"SIOCGLIFBRDADDR: %.*s: %s",
(int)sizeof(ifrbroadaddr.lifr_name),
ifrbroadaddr.lifr_name,
@@ -296,7 +285,7 @@ pcap_findalldevs_interfaces(pcap_if_t **alldevsp, char *errbuf)
*/
dstaddr = NULL;
} else {
- (void)snprintf(errbuf, PCAP_ERRBUF_SIZE,
+ (void)pcap_snprintf(errbuf, PCAP_ERRBUF_SIZE,
"SIOCGLIFDSTADDR: %.*s: %s",
(int)sizeof(ifrdstaddr.lifr_name),
ifrdstaddr.lifr_name,
@@ -341,7 +330,8 @@ pcap_findalldevs_interfaces(pcap_if_t **alldevsp, char *errbuf)
* Add information for this address to the list.
*/
if (add_addr_to_iflist(&devlist, ifrp->lifr_name,
- ifrflags.lifr_flags, (struct sockaddr *)&ifrp->lifr_addr,
+ if_flags_to_pcap_flags(ifrp->lifr_name, ifrflags.lifr_flags),
+ (struct sockaddr *)&ifrp->lifr_addr,
sizeof (struct sockaddr_storage),
netmask, sizeof (struct sockaddr_storage),
broadaddr, sizeof (struct sockaddr_storage),
diff --git a/contrib/libpcap/fad-helpers.c b/contrib/libpcap/fad-helpers.c
new file mode 100644
index 000000000000..4860bc55ca80
--- /dev/null
+++ b/contrib/libpcap/fad-helpers.c
@@ -0,0 +1,884 @@
+/* -*- Mode: c; tab-width: 8; indent-tabs-mode: 1; c-basic-offset: 8; -*- */
+/*
+ * Copyright (c) 1994, 1995, 1996, 1997, 1998
+ * The Regents of the University of California. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the Computer Systems
+ * Engineering Group at Lawrence Berkeley Laboratory.
+ * 4. Neither the name of the University nor of the Laboratory may be used
+ * to endorse or promote products derived from this software without
+ * specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#ifdef _WIN32
+#include <pcap-stdinc.h>
+#else /* _WIN32 */
+
+#include <sys/param.h>
+#ifndef MSDOS
+#include <sys/file.h>
+#endif
+#include <sys/ioctl.h>
+#include <sys/socket.h>
+#ifdef HAVE_SYS_SOCKIO_H
+#include <sys/sockio.h>
+#endif
+
+struct mbuf; /* Squelch compiler warnings on some platforms for */
+struct rtentry; /* declarations in <net/if.h> */
+#include <net/if.h>
+#include <netinet/in.h>
+#endif /* _WIN32 */
+
+#include <ctype.h>
+#include <errno.h>
+#include <memory.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#if !defined(_WIN32) && !defined(__BORLANDC__)
+#include <unistd.h>
+#endif /* !_WIN32 && !__BORLANDC__ */
+#ifdef HAVE_LIMITS_H
+#include <limits.h>
+#else
+#define INT_MAX 2147483647
+#endif
+
+#include "pcap-int.h"
+
+#ifdef HAVE_OS_PROTO_H
+#include "os-proto.h"
+#endif
+
+#ifndef _WIN32
+/* Not all systems have IFF_LOOPBACK */
+#ifdef IFF_LOOPBACK
+#define ISLOOPBACK(name, flags) ((flags) & IFF_LOOPBACK)
+#else
+#define ISLOOPBACK(name, flags) ((name)[0] == 'l' && (name)[1] == 'o' && \
+ (isdigit((unsigned char)((name)[2])) || (name)[2] == '\0'))
+#endif
+
+#ifdef IFF_UP
+#define ISUP(flags) ((flags) & IFF_UP)
+#else
+#define ISUP(flags) 0
+#endif
+
+#ifdef IFF_RUNNING
+#define ISRUNNING(flags) ((flags) & IFF_RUNNING)
+#else
+#define ISRUNNING(flags) 0
+#endif
+
+/*
+ * Map UN*X-style interface flags to libpcap flags.
+ */
+bpf_u_int32
+if_flags_to_pcap_flags(const char *name _U_, u_int if_flags)
+{
+ bpf_u_int32 pcap_flags;
+
+ pcap_flags = 0;
+ if (ISLOOPBACK(name, if_flags))
+ pcap_flags |= PCAP_IF_LOOPBACK;
+ if (ISUP(if_flags))
+ pcap_flags |= PCAP_IF_UP;
+ if (ISRUNNING(if_flags))
+ pcap_flags |= PCAP_IF_RUNNING;
+ return (pcap_flags);
+}
+#endif
+
+static struct sockaddr *
+dup_sockaddr(struct sockaddr *sa, size_t sa_length)
+{
+ struct sockaddr *newsa;
+
+ if ((newsa = malloc(sa_length)) == NULL)
+ return (NULL);
+ return (memcpy(newsa, sa, sa_length));
+}
+
+/*
+ * Construct a "figure of merit" for an interface, for use when sorting
+ * the list of interfaces, in which interfaces that are up are superior
+ * to interfaces that aren't up, interfaces that are up and running are
+ * superior to interfaces that are up but not running, and non-loopback
+ * interfaces that are up and running are superior to loopback interfaces,
+ * and interfaces with the same flags have a figure of merit that's higher
+ * the lower the instance number.
+ *
+ * The goal is to try to put the interfaces most likely to be useful for
+ * capture at the beginning of the list.
+ *
+ * The figure of merit, which is lower the "better" the interface is,
+ * has the uppermost bit set if the interface isn't running, the bit
+ * below that set if the interface isn't up, the bit below that set
+ * if the interface is a loopback interface, and the interface index
+ * in the 29 bits below that. (Yes, we assume u_int is 32 bits.)
+ */
+static u_int
+get_figure_of_merit(pcap_if_t *dev)
+{
+ const char *cp;
+ u_int n;
+
+ if (strcmp(dev->name, "any") == 0) {
+ /*
+ * Give the "any" device an artificially high instance
+ * number, so it shows up after all other non-loopback
+ * interfaces.
+ */
+ n = 0x1FFFFFFF; /* 29 all-1 bits */
+ } else {
+ /*
+ * A number at the end of the device name string is
+ * assumed to be a unit number.
+ */
+ cp = dev->name + strlen(dev->name) - 1;
+ while (cp-1 >= dev->name && *(cp-1) >= '0' && *(cp-1) <= '9')
+ cp--;
+ if (*cp >= '0' && *cp <= '9')
+ n = atoi(cp);
+ else
+ n = 0;
+ }
+ if (!(dev->flags & PCAP_IF_RUNNING))
+ n |= 0x80000000;
+ if (!(dev->flags & PCAP_IF_UP))
+ n |= 0x40000000;
+ if (dev->flags & PCAP_IF_LOOPBACK)
+ n |= 0x20000000;
+ return (n);
+}
+
+/*
+ * Try to get a description for a given device.
+ * Returns a mallocated description if it could and NULL if it couldn't.
+ *
+ * XXX - on FreeBSDs that support it, should it get the sysctl named
+ * "dev.{adapter family name}.{adapter unit}.%desc" to get a description
+ * of the adapter? Note that "dev.an.0.%desc" is "Aironet PC4500/PC4800"
+ * with my Cisco 350 card, so the name isn't entirely descriptive. The
+ * "dev.an.0.%pnpinfo" has a better description, although one might argue
+ * that the problem is really a driver bug - if it can find out that it's
+ * a Cisco 340 or 350, rather than an old Aironet card, it should use
+ * that in the description.
+ *
+ * Do NetBSD, DragonflyBSD, or OpenBSD support this as well? FreeBSD
+ * and OpenBSD let you get a description, but it's not generated by the OS,
+ * it's set with another ioctl that ifconfig supports; we use that to get
+ * a description in FreeBSD and OpenBSD, but if there is no such
+ * description available, it still might be nice to get some description
+ * string based on the device type or something such as that.
+ *
+ * In OS X, the System Configuration framework can apparently return
+ * names in 10.4 and later.
+ *
+ * It also appears that freedesktop.org's HAL offers an "info.product"
+ * string, but the HAL specification says it "should not be used in any
+ * UI" and "subsystem/capability specific properties" should be used
+ * instead and, in any case, I think HAL is being deprecated in
+ * favor of other stuff such as DeviceKit. DeviceKit doesn't appear
+ * to have any obvious product information for devices, but maybe
+ * I haven't looked hard enough.
+ *
+ * Using the System Configuration framework, or HAL, or DeviceKit, or
+ * whatever, would require that libpcap applications be linked with
+ * the frameworks/libraries in question. That shouldn't be a problem
+ * for programs linking with the shared version of libpcap (unless
+ * you're running on AIX - which I think is the only UN*X that doesn't
+ * support linking a shared library with other libraries on which it
+ * depends, and having an executable linked only with the first shared
+ * library automatically pick up the other libraries when started -
+ * and using HAL or whatever). Programs linked with the static
+ * version of libpcap would have to use pcap-config with the --static
+ * flag in order to get the right linker flags in order to pick up
+ * the additional libraries/frameworks; those programs need that anyway
+ * for libpcap 1.1 and beyond on Linux, as, by default, it requires
+ * -lnl.
+ *
+ * Do any other UN*Xes, or desktop environments support getting a
+ * description?
+ */
+static char *
+get_if_description(const char *name)
+{
+#ifdef SIOCGIFDESCR
+ char *description = NULL;
+ int s;
+ struct ifreq ifrdesc;
+#ifndef IFDESCRSIZE
+ size_t descrlen = 64;
+#else
+ size_t descrlen = IFDESCRSIZE;
+#endif /* IFDESCRSIZE */
+
+ /*
+ * Get the description for the interface.
+ */
+ memset(&ifrdesc, 0, sizeof ifrdesc);
+ strlcpy(ifrdesc.ifr_name, name, sizeof ifrdesc.ifr_name);
+ s = socket(AF_INET, SOCK_DGRAM, 0);
+ if (s >= 0) {
+#ifdef __FreeBSD__
+ /*
+ * On FreeBSD, if the buffer isn't big enough for the
+ * description, the ioctl succeeds, but the description
+ * isn't copied, ifr_buffer.length is set to the description
+ * length, and ifr_buffer.buffer is set to NULL.
+ */
+ for (;;) {
+ free(description);
+ if ((description = malloc(descrlen)) != NULL) {
+ ifrdesc.ifr_buffer.buffer = description;
+ ifrdesc.ifr_buffer.length = descrlen;
+ if (ioctl(s, SIOCGIFDESCR, &ifrdesc) == 0) {
+ if (ifrdesc.ifr_buffer.buffer ==
+ description)
+ break;
+ else
+ descrlen = ifrdesc.ifr_buffer.length;
+ } else {
+ /*
+ * Failed to get interface description.
+ */
+ free(description);
+ description = NULL;
+ break;
+ }
+ } else
+ break;
+ }
+#else /* __FreeBSD__ */
+ /*
+ * The only other OS that currently supports
+ * SIOCGIFDESCR is OpenBSD, and it has no way
+ * to get the description length - it's clamped
+ * to a maximum of IFDESCRSIZE.
+ */
+ if ((description = malloc(descrlen)) != NULL) {
+ ifrdesc.ifr_data = (caddr_t)description;
+ if (ioctl(s, SIOCGIFDESCR, &ifrdesc) != 0) {
+ /*
+ * Failed to get interface description.
+ */
+ free(description);
+ description = NULL;
+ }
+ }
+#endif /* __FreeBSD__ */
+ close(s);
+ if (description != NULL && strlen(description) == 0) {
+ /*
+ * Description is empty, so discard it.
+ */
+ free(description);
+ description = NULL;
+ }
+ }
+
+#ifdef __FreeBSD__
+ /*
+ * For FreeBSD, if we didn't get a description, and this is
+ * a device with a name of the form usbusN, label it as a USB
+ * bus.
+ */
+ if (description == NULL) {
+ if (strncmp(name, "usbus", 5) == 0) {
+ /*
+ * OK, it begins with "usbus".
+ */
+ long busnum;
+ char *p;
+
+ errno = 0;
+ busnum = strtol(name + 5, &p, 10);
+ if (errno == 0 && p != name + 5 && *p == '\0' &&
+ busnum >= 0 && busnum <= INT_MAX) {
+ /*
+ * OK, it's a valid number that's not
+ * bigger than INT_MAX. Construct
+ * a description from it.
+ */
+ static const char descr_prefix[] = "USB bus number ";
+ size_t descr_size;
+
+ /*
+ * Allow enough room for a 32-bit bus number.
+ * sizeof (descr_prefix) includes the
+ * terminating NUL.
+ */
+ descr_size = sizeof (descr_prefix) + 10;
+ description = malloc(descr_size);
+ if (description != NULL) {
+ pcap_snprintf(description, descr_size,
+ "%s%ld", descr_prefix, busnum);
+ }
+ }
+ }
+ }
+#endif
+ return (description);
+#else /* SIOCGIFDESCR */
+ return (NULL);
+#endif /* SIOCGIFDESCR */
+}
+
+/*
+ * Look for a given device in the specified list of devices.
+ *
+ * If we find it, return 0 and set *curdev_ret to point to it.
+ *
+ * If we don't find it, check whether we can open it:
+ *
+ * If that fails with PCAP_ERROR_NO_SUCH_DEVICE or
+ * PCAP_ERROR_IFACE_NOT_UP, don't attempt to add an entry for
+ * it, as that probably means it exists but doesn't support
+ * packet capture.
+ *
+ * Otherwise, attempt to add an entry for it, with the specified
+ * ifnet flags and description, and, if that succeeds, return 0
+ * and set *curdev_ret to point to the new entry, otherwise
+ * return PCAP_ERROR and set errbuf to an error message. If we
+ * weren't given a description, try to get one.
+ */
+int
+add_or_find_if(pcap_if_t **curdev_ret, pcap_if_t **alldevs, const char *name,
+ bpf_u_int32 flags, const char *description, char *errbuf)
+{
+ pcap_t *p;
+ pcap_if_t *curdev, *prevdev, *nextdev;
+ u_int this_figure_of_merit, nextdev_figure_of_merit;
+ char open_errbuf[PCAP_ERRBUF_SIZE];
+ int ret;
+
+ /*
+ * Is there already an entry in the list for this interface?
+ */
+ for (curdev = *alldevs; curdev != NULL; curdev = curdev->next) {
+ if (strcmp(name, curdev->name) == 0)
+ break; /* yes, we found it */
+ }
+
+ if (curdev == NULL) {
+ /*
+ * No, we didn't find it.
+ *
+ * Can we open this interface for live capture?
+ *
+ * We do this check so that interfaces that are
+ * supplied by the interface enumeration mechanism
+ * we're using but that don't support packet capture
+ * aren't included in the list. Loopback interfaces
+ * on Solaris are an example of this; we don't just
+ * omit loopback interfaces on all platforms because
+ * you *can* capture on loopback interfaces on some
+ * OSes.
+ *
+ * On OS X, we don't do this check if the device
+ * name begins with "wlt"; at least some versions
+ * of OS X offer monitor mode capturing by having
+ * a separate "monitor mode" device for each wireless
+ * adapter, rather than by implementing the ioctls
+ * that {Free,Net,Open,DragonFly}BSD provide.
+ * Opening that device puts the adapter into monitor
+ * mode, which, at least for some adapters, causes
+ * them to deassociate from the network with which
+ * they're associated.
+ *
+ * Instead, we try to open the corresponding "en"
+ * device (so that we don't end up with, for users
+ * without sufficient privilege to open capture
+ * devices, a list of adapters that only includes
+ * the wlt devices).
+ */
+#ifdef __APPLE__
+ if (strncmp(name, "wlt", 3) == 0) {
+ char *en_name;
+ size_t en_name_len;
+
+ /*
+ * Try to allocate a buffer for the "en"
+ * device's name.
+ */
+ en_name_len = strlen(name) - 1;
+ en_name = malloc(en_name_len + 1);
+ if (en_name == NULL) {
+ (void)pcap_snprintf(errbuf, PCAP_ERRBUF_SIZE,
+ "malloc: %s", pcap_strerror(errno));
+ return (-1);
+ }
+ strcpy(en_name, "en");
+ strcat(en_name, name + 3);
+ p = pcap_create(en_name, open_errbuf);
+ free(en_name);
+ } else
+#endif /* __APPLE */
+ p = pcap_create(name, open_errbuf);
+ if (p == NULL) {
+ /*
+ * The attempt to create the pcap_t failed;
+ * that's probably an indication that we're
+ * out of memory.
+ *
+ * Don't bother including this interface,
+ * but don't treat it as an error.
+ */
+ *curdev_ret = NULL;
+ return (0);
+ }
+ /* Small snaplen, so we don't try to allocate much memory. */
+ pcap_set_snaplen(p, 68);
+ ret = pcap_activate(p);
+ pcap_close(p);
+ switch (ret) {
+
+ case PCAP_ERROR_NO_SUCH_DEVICE:
+ case PCAP_ERROR_IFACE_NOT_UP:
+ /*
+ * We expect these two errors - they're the
+ * reason we try to open the device.
+ *
+ * PCAP_ERROR_NO_SUCH_DEVICE typically means
+ * "there's no such device *known to the
+ * OS's capture mechanism*", so, even though
+ * it might be a valid network interface, you
+ * can't capture on it (e.g., the loopback
+ * device in Solaris up to Solaris 10, or
+ * the vmnet devices in OS X with VMware
+ * Fusion). We don't include those devices
+ * in our list of devices, as there's no
+ * point in doing so - they're not available
+ * for capture.
+ *
+ * PCAP_ERROR_IFACE_NOT_UP means that the
+ * OS's capture mechanism doesn't work on
+ * interfaces not marked as up; some capture
+ * mechanisms *do* support that, so we no
+ * longer reject those interfaces out of hand,
+ * but we *do* want to reject them if they
+ * can't be opened for capture.
+ */
+ *curdev_ret = NULL;
+ return (0);
+ }
+
+ /*
+ * Yes, we can open it, or we can't, for some other
+ * reason.
+ *
+ * If we can open it, we want to offer it for
+ * capture, as you can capture on it. If we can't,
+ * we want to offer it for capture, so that, if
+ * the user tries to capture on it, they'll get
+ * an error and they'll know why they can't
+ * capture on it (e.g., insufficient permissions)
+ * or they'll report it as a problem (and then
+ * have the error message to provide as information).
+ *
+ * Allocate a new entry.
+ */
+ curdev = malloc(sizeof(pcap_if_t));
+ if (curdev == NULL) {
+ (void)pcap_snprintf(errbuf, PCAP_ERRBUF_SIZE,
+ "malloc: %s", pcap_strerror(errno));
+ return (-1);
+ }
+
+ /*
+ * Fill in the entry.
+ */
+ curdev->next = NULL;
+ curdev->name = strdup(name);
+ if (curdev->name == NULL) {
+ (void)pcap_snprintf(errbuf, PCAP_ERRBUF_SIZE,
+ "malloc: %s", pcap_strerror(errno));
+ free(curdev);
+ return (-1);
+ }
+ if (description == NULL) {
+ /*
+ * We weren't handed a description for the
+ * interface, so see if we can generate one
+ * ourselves.
+ */
+ curdev->description = get_if_description(name);
+ } else {
+ /*
+ * We were handed a description; make a copy.
+ */
+ curdev->description = strdup(description);
+ if (curdev->description == NULL) {
+ (void)pcap_snprintf(errbuf, PCAP_ERRBUF_SIZE,
+ "malloc: %s", pcap_strerror(errno));
+ free(curdev->name);
+ free(curdev);
+ return (-1);
+ }
+ }
+ curdev->addresses = NULL; /* list starts out as empty */
+ curdev->flags = flags;
+
+ /*
+ * Add it to the list, in the appropriate location.
+ * First, get the "figure of merit" for this
+ * interface.
+ */
+ this_figure_of_merit = get_figure_of_merit(curdev);
+
+ /*
+ * Now look for the last interface with an figure of merit
+ * less than or equal to the new interface's figure of
+ * merit.
+ *
+ * We start with "prevdev" being NULL, meaning we're before
+ * the first element in the list.
+ */
+ prevdev = NULL;
+ for (;;) {
+ /*
+ * Get the interface after this one.
+ */
+ if (prevdev == NULL) {
+ /*
+ * The next element is the first element.
+ */
+ nextdev = *alldevs;
+ } else
+ nextdev = prevdev->next;
+
+ /*
+ * Are we at the end of the list?
+ */
+ if (nextdev == NULL) {
+ /*
+ * Yes - we have to put the new entry
+ * after "prevdev".
+ */
+ break;
+ }
+
+ /*
+ * Is the new interface's figure of merit less
+ * than the next interface's figure of merit,
+ * meaning that the new interface is better
+ * than the next interface?
+ */
+ nextdev_figure_of_merit = get_figure_of_merit(nextdev);
+ if (this_figure_of_merit < nextdev_figure_of_merit) {
+ /*
+ * Yes - we should put the new entry
+ * before "nextdev", i.e. after "prevdev".
+ */
+ break;
+ }
+
+ prevdev = nextdev;
+ }
+
+ /*
+ * Insert before "nextdev".
+ */
+ curdev->next = nextdev;
+
+ /*
+ * Insert after "prevdev" - unless "prevdev" is null,
+ * in which case this is the first interface.
+ */
+ if (prevdev == NULL) {
+ /*
+ * This is the first interface. Pass back a
+ * pointer to it, and put "curdev" before
+ * "nextdev".
+ */
+ *alldevs = curdev;
+ } else
+ prevdev->next = curdev;
+ }
+
+ *curdev_ret = curdev;
+ return (0);
+}
+
+/*
+ * Try to get a description for a given device, and then look for that
+ * device in the specified list of devices.
+ *
+ * If we find it, then, if the specified address isn't null, add it to
+ * the list of addresses for the device and return 0.
+ *
+ * If we don't find it, check whether we can open it:
+ *
+ * If that fails with PCAP_ERROR_NO_SUCH_DEVICE or
+ * PCAP_ERROR_IFACE_NOT_UP, don't attempt to add an entry for
+ * it, as that probably means it exists but doesn't support
+ * packet capture.
+ *
+ * Otherwise, attempt to add an entry for it, with the specified
+ * ifnet flags, and, if that succeeds, add the specified address
+ * to its list of addresses if that address is non-null, set
+ * *curdev_ret to point to the new entry, and return 0, otherwise
+ * return PCAP_ERROR and set errbuf to an error message.
+ *
+ * (We can get called with a null address because we might get a list
+ * of interface name/address combinations from the underlying OS, with
+ * the address being absent in some cases, rather than a list of
+ * interfaces with each interface having a list of addresses, so this
+ * call may be the only call made to add to the list, and we want to
+ * add interfaces even if they have no addresses.)
+ */
+int
+add_addr_to_iflist(pcap_if_t **alldevs, const char *name, bpf_u_int32 flags,
+ struct sockaddr *addr, size_t addr_size,
+ struct sockaddr *netmask, size_t netmask_size,
+ struct sockaddr *broadaddr, size_t broadaddr_size,
+ struct sockaddr *dstaddr, size_t dstaddr_size,
+ char *errbuf)
+{
+ pcap_if_t *curdev;
+
+ if (add_or_find_if(&curdev, alldevs, name, flags, NULL, errbuf) == -1) {
+ /*
+ * Error - give up.
+ */
+ return (-1);
+ }
+ if (curdev == NULL) {
+ /*
+ * Device wasn't added because it can't be opened.
+ * Not a fatal error.
+ */
+ return (0);
+ }
+
+ if (addr == NULL) {
+ /*
+ * There's no address to add; this entry just meant
+ * "here's a new interface".
+ */
+ return (0);
+ }
+
+ /*
+ * "curdev" is an entry for this interface, and we have an
+ * address for it; add an entry for that address to the
+ * interface's list of addresses.
+ *
+ * Allocate the new entry and fill it in.
+ */
+ return (add_addr_to_dev(curdev, addr, addr_size, netmask,
+ netmask_size, broadaddr, broadaddr_size, dstaddr,
+ dstaddr_size, errbuf));
+}
+
+/*
+ * Add an entry to the list of addresses for an interface.
+ * "curdev" is the entry for that interface.
+ * If this is the first IP address added to the interface, move it
+ * in the list as appropriate.
+ */
+int
+add_addr_to_dev(pcap_if_t *curdev,
+ struct sockaddr *addr, size_t addr_size,
+ struct sockaddr *netmask, size_t netmask_size,
+ struct sockaddr *broadaddr, size_t broadaddr_size,
+ struct sockaddr *dstaddr, size_t dstaddr_size,
+ char *errbuf)
+{
+ pcap_addr_t *curaddr, *prevaddr, *nextaddr;
+
+ curaddr = malloc(sizeof(pcap_addr_t));
+ if (curaddr == NULL) {
+ (void)pcap_snprintf(errbuf, PCAP_ERRBUF_SIZE,
+ "malloc: %s", pcap_strerror(errno));
+ return (-1);
+ }
+
+ curaddr->next = NULL;
+ if (addr != NULL) {
+ curaddr->addr = dup_sockaddr(addr, addr_size);
+ if (curaddr->addr == NULL) {
+ (void)pcap_snprintf(errbuf, PCAP_ERRBUF_SIZE,
+ "malloc: %s", pcap_strerror(errno));
+ free(curaddr);
+ return (-1);
+ }
+ } else
+ curaddr->addr = NULL;
+
+ if (netmask != NULL) {
+ curaddr->netmask = dup_sockaddr(netmask, netmask_size);
+ if (curaddr->netmask == NULL) {
+ (void)pcap_snprintf(errbuf, PCAP_ERRBUF_SIZE,
+ "malloc: %s", pcap_strerror(errno));
+ if (curaddr->addr != NULL)
+ free(curaddr->addr);
+ free(curaddr);
+ return (-1);
+ }
+ } else
+ curaddr->netmask = NULL;
+
+ if (broadaddr != NULL) {
+ curaddr->broadaddr = dup_sockaddr(broadaddr, broadaddr_size);
+ if (curaddr->broadaddr == NULL) {
+ (void)pcap_snprintf(errbuf, PCAP_ERRBUF_SIZE,
+ "malloc: %s", pcap_strerror(errno));
+ if (curaddr->netmask != NULL)
+ free(curaddr->netmask);
+ if (curaddr->addr != NULL)
+ free(curaddr->addr);
+ free(curaddr);
+ return (-1);
+ }
+ } else
+ curaddr->broadaddr = NULL;
+
+ if (dstaddr != NULL) {
+ curaddr->dstaddr = dup_sockaddr(dstaddr, dstaddr_size);
+ if (curaddr->dstaddr == NULL) {
+ (void)pcap_snprintf(errbuf, PCAP_ERRBUF_SIZE,
+ "malloc: %s", pcap_strerror(errno));
+ if (curaddr->broadaddr != NULL)
+ free(curaddr->broadaddr);
+ if (curaddr->netmask != NULL)
+ free(curaddr->netmask);
+ if (curaddr->addr != NULL)
+ free(curaddr->addr);
+ free(curaddr);
+ return (-1);
+ }
+ } else
+ curaddr->dstaddr = NULL;
+
+ /*
+ * Find the end of the list of addresses.
+ */
+ for (prevaddr = curdev->addresses; prevaddr != NULL; prevaddr = nextaddr) {
+ nextaddr = prevaddr->next;
+ if (nextaddr == NULL) {
+ /*
+ * This is the end of the list.
+ */
+ break;
+ }
+ }
+
+ if (prevaddr == NULL) {
+ /*
+ * The list was empty; this is the first member.
+ */
+ curdev->addresses = curaddr;
+ } else {
+ /*
+ * "prevaddr" is the last member of the list; append
+ * this member to it.
+ */
+ prevaddr->next = curaddr;
+ }
+
+ return (0);
+}
+
+/*
+ * Look for a given device in the specified list of devices.
+ *
+ * If we find it, return 0.
+ *
+ * If we don't find it, check whether we can open it:
+ *
+ * If that fails with PCAP_ERROR_NO_SUCH_DEVICE or
+ * PCAP_ERROR_IFACE_NOT_UP, don't attempt to add an entry for
+ * it, as that probably means it exists but doesn't support
+ * packet capture.
+ *
+ * Otherwise, attempt to add an entry for it, with the specified
+ * ifnet flags and description, and, if that succeeds, return 0
+ * and set *curdev_ret to point to the new entry, otherwise
+ * return PCAP_ERROR and set errbuf to an error message.
+ */
+int
+pcap_add_if(pcap_if_t **devlist, const char *name, u_int flags,
+ const char *description, char *errbuf)
+{
+ pcap_if_t *curdev;
+
+ return (add_or_find_if(&curdev, devlist, name, flags, description,
+ errbuf));
+}
+
+
+/*
+ * Free a list of interfaces.
+ */
+void
+pcap_freealldevs(pcap_if_t *alldevs)
+{
+ pcap_if_t *curdev, *nextdev;
+ pcap_addr_t *curaddr, *nextaddr;
+
+ for (curdev = alldevs; curdev != NULL; curdev = nextdev) {
+ nextdev = curdev->next;
+
+ /*
+ * Free all addresses.
+ */
+ for (curaddr = curdev->addresses; curaddr != NULL; curaddr = nextaddr) {
+ nextaddr = curaddr->next;
+ if (curaddr->addr)
+ free(curaddr->addr);
+ if (curaddr->netmask)
+ free(curaddr->netmask);
+ if (curaddr->broadaddr)
+ free(curaddr->broadaddr);
+ if (curaddr->dstaddr)
+ free(curaddr->dstaddr);
+ free(curaddr);
+ }
+
+ /*
+ * Free the name string.
+ */
+ free(curdev->name);
+
+ /*
+ * Free the description string, if any.
+ */
+ if (curdev->description != NULL)
+ free(curdev->description);
+
+ /*
+ * Free the interface.
+ */
+ free(curdev);
+ }
+}
diff --git a/contrib/libpcap/fad-sita.c b/contrib/libpcap/fad-sita.c
deleted file mode 100644
index 34ddf1d85186..000000000000
--- a/contrib/libpcap/fad-sita.c
+++ /dev/null
@@ -1,59 +0,0 @@
-/*
- * fad-sita.c: Packet capture interface additions for SITA ACN devices
- *
- * Copyright (c) 2007 Fulko Hew, SITA INC Canada, Inc <fulko.hew@sita.aero>
- *
- * License: BSD
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in
- * the documentation and/or other materials provided with the
- * distribution.
- * 3. The names of the authors may not be used to endorse or promote
- * products derived from this software without specific prior
- * written permission.
- *
- * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
- * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
- * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
- */
-
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-
-#include <string.h>
-#include "pcap-int.h"
-
-#include "pcap-sita.h"
-
-extern pcap_if_t *acn_if_list; /* pcap's list of available interfaces */
-
-int pcap_findalldevs_interfaces(pcap_if_t **alldevsp, char *errbuf) {
-
- //printf("pcap_findalldevs()\n"); // fulko
-
- *alldevsp = 0; /* initialize the returned variables before we do anything */
- strcpy(errbuf, "");
- if (acn_parse_hosts_file(errbuf)) /* scan the hosts file for potential IOPs */
- {
- //printf("pcap_findalldevs() returning BAD after parsehosts\n"); // fulko
- return -1;
- }
- //printf("pcap_findalldevs() got hostlist now finding devs\n"); // fulko
- if (acn_findalldevs(errbuf)) /* then ask the IOPs for their monitorable devices */
- {
- //printf("pcap_findalldevs() returning BAD after findalldevs\n"); // fulko
- return -1;
- }
- *alldevsp = acn_if_list;
- acn_if_list = 0; /* then forget our list head, because someone will call pcap_freealldevs() to empty the malloc'ed stuff */
- //printf("pcap_findalldevs() returning ZERO OK\n"); // fulko
- return 0;
-}
diff --git a/contrib/libpcap/gen_version_c.sh b/contrib/libpcap/gen_version_c.sh
new file mode 100755
index 000000000000..d5a5e75bfec8
--- /dev/null
+++ b/contrib/libpcap/gen_version_c.sh
@@ -0,0 +1,11 @@
+#! /bin/sh
+echo '#include <pcap/export-defs.h>' > "$2"
+echo 'PCAP_API_DEF' >> "$2"
+if grep GIT "$1" >/dev/null; then
+ read ver <"$1"
+ echo $ver | tr -d '\012'
+ date +_%Y_%m_%d
+else
+ cat "$1"
+fi | sed -e 's/.*/char pcap_version[] = "&";/' >> "$2"
+
diff --git a/contrib/libpcap/gen_version_header.sh b/contrib/libpcap/gen_version_header.sh
new file mode 100755
index 000000000000..6b4b82da1af7
--- /dev/null
+++ b/contrib/libpcap/gen_version_header.sh
@@ -0,0 +1,19 @@
+#! /bin/sh
+print_version_string()
+{
+ if grep GIT "$1" >/dev/null
+ then
+ read ver <"$1"
+ echo $ver | tr -d '\012'
+ date +_%Y_%m_%d
+ else
+ cat "$1"
+ fi
+}
+if test $# != 3
+then
+ echo "Usage: gen_version_header.sh <version file> <template> <output file>" 1>&2
+ exit 1
+fi
+version_string=`print_version_string "$1"`
+sed "s/%%LIBPCAP_VERSION%%/$version_string/" "$2" >"$3"
diff --git a/contrib/libpcap/gencode.c b/contrib/libpcap/gencode.c
index 1ed1e7b8fb2e..d4ddc24df21a 100644
--- a/contrib/libpcap/gencode.c
+++ b/contrib/libpcap/gencode.c
@@ -26,9 +26,9 @@
#include "config.h"
#endif
-#ifdef WIN32
+#ifdef _WIN32
#include <pcap-stdinc.h>
-#else /* WIN32 */
+#else /* _WIN32 */
#if HAVE_INTTYPES_H
#include <inttypes.h>
#elif HAVE_STDINT_H
@@ -39,16 +39,9 @@
#endif
#include <sys/types.h>
#include <sys/socket.h>
-#endif /* WIN32 */
+#endif /* _WIN32 */
-/*
- * XXX - why was this included even on UNIX?
- */
-#ifdef __MINGW32__
-#include "ip6_misc.h"
-#endif
-
-#ifndef WIN32
+#ifndef _WIN32
#ifdef __NetBSD__
#include <sys/param.h>
@@ -57,7 +50,7 @@
#include <netinet/in.h>
#include <arpa/inet.h>
-#endif /* WIN32 */
+#endif /* _WIN32 */
#include <stdlib.h>
#include <string.h>
@@ -82,29 +75,86 @@
#include "pcap/sll.h"
#include "pcap/ipnet.h"
#include "arcnet.h"
+
+#include "grammar.h"
+#include "scanner.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>
#include <net/pfvar.h>
#include <net/if_pflog.h>
#endif
+
#ifndef offsetof
#define offsetof(s, e) ((size_t)&((s *)0)->e)
#endif
+
#ifdef INET6
-#ifndef WIN32
+#ifdef _WIN32
+#if defined(__MINGW32__) && defined(DEFINE_ADDITIONAL_IPV6_STUFF)
+/* IPv6 address */
+struct in6_addr
+ {
+ union
+ {
+ u_int8_t u6_addr8[16];
+ u_int16_t u6_addr16[8];
+ u_int32_t u6_addr32[4];
+ } in6_u;
+#define s6_addr in6_u.u6_addr8
+#define s6_addr16 in6_u.u6_addr16
+#define s6_addr32 in6_u.u6_addr32
+#define s6_addr64 in6_u.u6_addr64
+ };
+
+typedef unsigned short sa_family_t;
+
+#define __SOCKADDR_COMMON(sa_prefix) \
+ sa_family_t sa_prefix##family
+
+/* Ditto, for IPv6. */
+struct sockaddr_in6
+ {
+ __SOCKADDR_COMMON (sin6_);
+ u_int16_t sin6_port; /* Transport layer port # */
+ u_int32_t sin6_flowinfo; /* IPv6 flow information */
+ struct in6_addr sin6_addr; /* IPv6 address */
+ };
+
+#ifndef EAI_ADDRFAMILY
+struct addrinfo {
+ int ai_flags; /* AI_PASSIVE, AI_CANONNAME */
+ int ai_family; /* PF_xxx */
+ int ai_socktype; /* SOCK_xxx */
+ int ai_protocol; /* 0 or IPPROTO_xxx for IPv4 and IPv6 */
+ size_t ai_addrlen; /* length of ai_addr */
+ char *ai_canonname; /* canonical name for hostname */
+ struct sockaddr *ai_addr; /* binary address */
+ struct addrinfo *ai_next; /* next structure in linked list */
+};
+#endif /* EAI_ADDRFAMILY */
+#endif /* defined(__MINGW32__) && defined(DEFINE_ADDITIONAL_IPV6_STUFF) */
+#else /* _WIN32 */
#include <netdb.h> /* for "struct addrinfo" */
-#endif /* WIN32 */
-#endif /*INET6*/
+#endif /* _WIN32 */
+#endif /* INET6 */
#include <pcap/namedb.h>
+#include "nametoaddr.h"
+
#define ETHERMTU 1500
+#ifndef ETHERTYPE_TEB
+#define ETHERTYPE_TEB 0x6558
+#endif
+
#ifndef IPPROTO_HOPOPTS
#define IPPROTO_HOPOPTS 0
#endif
@@ -121,74 +171,75 @@
#define IPPROTO_SCTP 132
#endif
+#define GENEVE_PORT 6081
+
#ifdef HAVE_OS_PROTO_H
#include "os-proto.h"
#endif
#define JMP(c) ((c)|BPF_JMP|BPF_K)
-/* Locals */
-static jmp_buf top_ctx;
-static pcap_t *bpf_pcap;
-
-/* Hack for updating VLAN, MPLS, and PPPoE offsets. */
-#ifdef WIN32
-static u_int orig_linktype = (u_int)-1, orig_nl = (u_int)-1, label_stack_depth = (u_int)-1;
-#else
-static u_int orig_linktype = -1U, orig_nl = -1U, label_stack_depth = -1U;
-#endif
-
-/* XXX */
-static int pcap_fddipad;
-
-/* VARARGS */
-void
-bpf_error(const char *fmt, ...)
-{
- va_list ap;
-
- va_start(ap, fmt);
- if (bpf_pcap != NULL)
- (void)vsnprintf(pcap_geterr(bpf_pcap), PCAP_ERRBUF_SIZE,
- fmt, ap);
- va_end(ap);
- longjmp(top_ctx, 1);
- /* NOTREACHED */
+/*
+ * "Push" the current value of the link-layer header type and link-layer
+ * header offset onto a "stack", and set a new value. (It's not a
+ * full-blown stack; we keep only the top two items.)
+ */
+#define PUSH_LINKHDR(cs, new_linktype, new_is_variable, new_constant_part, new_reg) \
+{ \
+ (cs)->prevlinktype = (cs)->linktype; \
+ (cs)->off_prevlinkhdr = (cs)->off_linkhdr; \
+ (cs)->linktype = (new_linktype); \
+ (cs)->off_linkhdr.is_variable = (new_is_variable); \
+ (cs)->off_linkhdr.constant_part = (new_constant_part); \
+ (cs)->off_linkhdr.reg = (new_reg); \
+ (cs)->is_geneve = 0; \
}
-static void init_linktype(pcap_t *);
-
-static void init_regs(void);
-static int alloc_reg(void);
-static void free_reg(int);
+/*
+ * Offset "not set" value.
+ */
+#define OFFSET_NOT_SET 0xffffffffU
-static struct block *root;
+/*
+ * Absolute offsets, which are offsets from the beginning of the raw
+ * packet data, are, in the general case, the sum of a variable value
+ * and a constant value; the variable value may be absent, in which
+ * case the offset is only the constant value, and the constant value
+ * may be zero, in which case the offset is only the variable value.
+ *
+ * bpf_abs_offset is a structure containing all that information:
+ *
+ * is_variable is 1 if there's a variable part.
+ *
+ * constant_part is the constant part of the value, possibly zero;
+ *
+ * if is_variable is 1, reg is the register number for a register
+ * containing the variable value if the register has been assigned,
+ * and -1 otherwise.
+ */
+typedef struct {
+ int is_variable;
+ u_int constant_part;
+ int reg;
+} bpf_abs_offset;
/*
* Value passed to gen_load_a() to indicate what the offset argument
- * is relative to.
+ * is relative to the beginning of.
*/
enum e_offrel {
- OR_PACKET, /* relative to the beginning of the packet */
- OR_LINK, /* relative to the beginning of the link-layer header */
- OR_MACPL, /* relative to the end of the MAC-layer header */
- OR_NET, /* relative to the network-layer header */
- OR_NET_NOSNAP, /* relative to the network-layer header, with no SNAP header at the link layer */
- OR_TRAN_IPV4, /* relative to the transport-layer header, with IPv4 network layer */
- OR_TRAN_IPV6 /* relative to the transport-layer header, with IPv6 network layer */
+ OR_PACKET, /* full packet data */
+ OR_LINKHDR, /* link-layer header */
+ OR_PREVLINKHDR, /* previous link-layer header */
+ OR_LLC, /* 802.2 LLC header */
+ OR_PREVMPLSHDR, /* previous MPLS header */
+ OR_LINKTYPE, /* link-layer type */
+ OR_LINKPL, /* link-layer payload */
+ OR_LINKPL_NOSNAP, /* link-layer payload, with no SNAP header at the link layer */
+ OR_TRAN_IPV4, /* transport-layer header, with IPv4 network layer */
+ OR_TRAN_IPV6 /* transport-layer header, with IPv6 network layer */
};
-#ifdef INET6
-/*
- * As errors are handled by a longjmp, anything allocated must be freed
- * in the longjmp handler, so it must be reachable from that handler.
- * One thing that's allocated is the result of pcap_nametoaddrinfo();
- * it must be freed with freeaddrinfo(). This variable points to any
- * addrinfo structure that would need to be freed.
- */
-static struct addrinfo *ai;
-#endif
-
/*
* We divy out chunks of memory rather than call malloc each time so
* we don't have to worry about leaking memory. It's probably
@@ -200,100 +251,324 @@ static struct addrinfo *ai;
#define NCHUNKS 16
#define CHUNK0SIZE 1024
struct chunk {
- u_int n_left;
+ size_t n_left;
void *m;
};
-static struct chunk chunks[NCHUNKS];
-static int cur_chunk;
+/* Code generator state */
+
+struct _compiler_state {
+ jmp_buf top_ctx;
+ pcap_t *bpf_pcap;
+
+ struct icode ic;
+
+ int snaplen;
+
+ int linktype;
+ int prevlinktype;
+ int outermostlinktype;
+
+ bpf_u_int32 netmask;
+ int no_optimize;
+
+ /* Hack for handling VLAN and MPLS stacks. */
+ u_int label_stack_depth;
+ u_int vlan_stack_depth;
+
+ /* XXX */
+ u_int pcap_fddipad;
+
+#ifdef INET6
+ /*
+ * As errors are handled by a longjmp, anything allocated must
+ * be freed in the longjmp handler, so it must be reachable
+ * from that handler.
+ *
+ * One thing that's allocated is the result of pcap_nametoaddrinfo();
+ * it must be freed with freeaddrinfo(). This variable points to
+ * any addrinfo structure that would need to be freed.
+ */
+ struct addrinfo *ai;
+#endif
+
+ /*
+ * Various code constructs need to know the layout of the packet.
+ * These values give the necessary offsets from the beginning
+ * of the packet data.
+ */
+
+ /*
+ * Absolute offset of the beginning of the link-layer header.
+ */
+ bpf_abs_offset off_linkhdr;
+
+ /*
+ * If we're checking a link-layer header for a packet encapsulated
+ * in another protocol layer, this is the equivalent information
+ * for the previous layers' link-layer header from the beginning
+ * of the raw packet data.
+ */
+ bpf_abs_offset off_prevlinkhdr;
+
+ /*
+ * This is the equivalent information for the outermost layers'
+ * link-layer header.
+ */
+ bpf_abs_offset off_outermostlinkhdr;
+
+ /*
+ * Absolute offset of the beginning of the link-layer payload.
+ */
+ bpf_abs_offset off_linkpl;
+
+ /*
+ * "off_linktype" is the offset to information in the link-layer
+ * header giving the packet type. This is an absolute offset
+ * from the beginning of the packet.
+ *
+ * For Ethernet, it's the offset of the Ethernet type field; this
+ * means that it must have a value that skips VLAN tags.
+ *
+ * For link-layer types that always use 802.2 headers, it's the
+ * offset of the LLC header; this means that it must have a value
+ * that skips VLAN tags.
+ *
+ * For PPP, it's the offset of the PPP type field.
+ *
+ * For Cisco HDLC, it's the offset of the CHDLC type field.
+ *
+ * For BSD loopback, it's the offset of the AF_ value.
+ *
+ * For Linux cooked sockets, it's the offset of the type field.
+ *
+ * off_linktype.constant_part is set to OFFSET_NOT_SET for no
+ * encapsulation, in which case, IP is assumed.
+ */
+ bpf_abs_offset off_linktype;
+
+ /*
+ * TRUE if the link layer includes an ATM pseudo-header.
+ */
+ int is_atm;
+
+ /*
+ * TRUE if "geneve" appeared in the filter; it causes us to
+ * generate code that checks for a Geneve header and assume
+ * that later filters apply to the encapsulated payload.
+ */
+ int is_geneve;
+
+ /*
+ * These are offsets for the ATM pseudo-header.
+ */
+ u_int off_vpi;
+ u_int off_vci;
+ u_int off_proto;
+
+ /*
+ * These are offsets for the MTP2 fields.
+ */
+ u_int off_li;
+ u_int off_li_hsl;
+
+ /*
+ * These are offsets for the MTP3 fields.
+ */
+ u_int off_sio;
+ u_int off_opc;
+ u_int off_dpc;
+ u_int off_sls;
+
+ /*
+ * This is the offset of the first byte after the ATM pseudo_header,
+ * or -1 if there is no ATM pseudo-header.
+ */
+ u_int off_payload;
+
+ /*
+ * These are offsets to the beginning of the network-layer header.
+ * They are relative to the beginning of the link-layer payload
+ * (i.e., they don't include off_linkhdr.constant_part or
+ * off_linkpl.constant_part).
+ *
+ * If the link layer never uses 802.2 LLC:
+ *
+ * "off_nl" and "off_nl_nosnap" are the same.
+ *
+ * If the link layer always uses 802.2 LLC:
+ *
+ * "off_nl" is the offset if there's a SNAP header following
+ * the 802.2 header;
+ *
+ * "off_nl_nosnap" is the offset if there's no SNAP header.
+ *
+ * If the link layer is Ethernet:
+ *
+ * "off_nl" is the offset if the packet is an Ethernet II packet
+ * (we assume no 802.3+802.2+SNAP);
+ *
+ * "off_nl_nosnap" is the offset if the packet is an 802.3 packet
+ * with an 802.2 header following it.
+ */
+ u_int off_nl;
+ u_int off_nl_nosnap;
+
+ /*
+ * Here we handle simple allocation of the scratch registers.
+ * If too many registers are alloc'd, the allocator punts.
+ */
+ int regused[BPF_MEMWORDS];
+ int curreg;
+
+ /*
+ * Memory chunks.
+ */
+ struct chunk chunks[NCHUNKS];
+ int cur_chunk;
+};
+
+void
+bpf_syntax_error(compiler_state_t *cstate, const char *msg)
+{
+ bpf_error(cstate, "syntax error in filter expression: %s", msg);
+ /* NOTREACHED */
+}
-static void *newchunk(u_int);
-static void freechunks(void);
-static inline struct block *new_block(int);
-static inline struct slist *new_stmt(int);
-static struct block *gen_retblk(int);
-static inline void syntax(void);
+/* VARARGS */
+void
+bpf_error(compiler_state_t *cstate, const char *fmt, ...)
+{
+ va_list ap;
+
+ va_start(ap, fmt);
+ if (cstate->bpf_pcap != NULL)
+ (void)pcap_vsnprintf(pcap_geterr(cstate->bpf_pcap),
+ PCAP_ERRBUF_SIZE, fmt, ap);
+ va_end(ap);
+ longjmp(cstate->top_ctx, 1);
+ /* NOTREACHED */
+}
+
+static void init_linktype(compiler_state_t *, pcap_t *);
+
+static void init_regs(compiler_state_t *);
+static int alloc_reg(compiler_state_t *);
+static void free_reg(compiler_state_t *, int);
+
+static void initchunks(compiler_state_t *cstate);
+static void *newchunk(compiler_state_t *cstate, size_t);
+static void freechunks(compiler_state_t *cstate);
+static inline struct block *new_block(compiler_state_t *cstate, int);
+static inline struct slist *new_stmt(compiler_state_t *cstate, int);
+static struct block *gen_retblk(compiler_state_t *cstate, int);
+static inline void syntax(compiler_state_t *cstate);
static void backpatch(struct block *, struct block *);
static void merge(struct block *, struct block *);
-static struct block *gen_cmp(enum e_offrel, u_int, u_int, bpf_int32);
-static struct block *gen_cmp_gt(enum e_offrel, u_int, u_int, bpf_int32);
-static struct block *gen_cmp_ge(enum e_offrel, u_int, u_int, bpf_int32);
-static struct block *gen_cmp_lt(enum e_offrel, u_int, u_int, bpf_int32);
-static struct block *gen_cmp_le(enum e_offrel, u_int, u_int, bpf_int32);
-static struct block *gen_mcmp(enum e_offrel, u_int, u_int, bpf_int32,
- bpf_u_int32);
-static struct block *gen_bcmp(enum e_offrel, u_int, u_int, const u_char *);
-static struct block *gen_ncmp(enum e_offrel, bpf_u_int32, bpf_u_int32,
- bpf_u_int32, bpf_u_int32, int, bpf_int32);
-static struct slist *gen_load_llrel(u_int, u_int);
-static struct slist *gen_load_macplrel(u_int, u_int);
-static struct slist *gen_load_a(enum e_offrel, u_int, u_int);
-static struct slist *gen_loadx_iphdrlen(void);
-static struct block *gen_uncond(int);
-static inline struct block *gen_true(void);
-static inline struct block *gen_false(void);
-static struct block *gen_ether_linktype(int);
-static struct block *gen_ipnet_linktype(int);
-static struct block *gen_linux_sll_linktype(int);
-static struct slist *gen_load_prism_llprefixlen(void);
-static struct slist *gen_load_avs_llprefixlen(void);
-static struct slist *gen_load_radiotap_llprefixlen(void);
-static struct slist *gen_load_ppi_llprefixlen(void);
-static void insert_compute_vloffsets(struct block *);
-static struct slist *gen_llprefixlen(void);
-static struct slist *gen_off_macpl(void);
+static struct block *gen_cmp(compiler_state_t *, enum e_offrel, u_int,
+ u_int, bpf_int32);
+static struct block *gen_cmp_gt(compiler_state_t *, enum e_offrel, u_int,
+ u_int, bpf_int32);
+static struct block *gen_cmp_ge(compiler_state_t *, enum e_offrel, u_int,
+ u_int, bpf_int32);
+static struct block *gen_cmp_lt(compiler_state_t *, enum e_offrel, u_int,
+ u_int, bpf_int32);
+static struct block *gen_cmp_le(compiler_state_t *, enum e_offrel, u_int,
+ u_int, bpf_int32);
+static struct block *gen_mcmp(compiler_state_t *, enum e_offrel, u_int,
+ u_int, bpf_int32, bpf_u_int32);
+static struct block *gen_bcmp(compiler_state_t *, enum e_offrel, u_int,
+ u_int, const u_char *);
+static struct block *gen_ncmp(compiler_state_t *, enum e_offrel, bpf_u_int32,
+ bpf_u_int32, bpf_u_int32, bpf_u_int32, int, bpf_int32);
+static struct slist *gen_load_absoffsetrel(compiler_state_t *, bpf_abs_offset *,
+ u_int, u_int);
+static struct slist *gen_load_a(compiler_state_t *, enum e_offrel, u_int,
+ u_int);
+static struct slist *gen_loadx_iphdrlen(compiler_state_t *);
+static struct block *gen_uncond(compiler_state_t *, int);
+static inline struct block *gen_true(compiler_state_t *);
+static inline struct block *gen_false(compiler_state_t *);
+static struct block *gen_ether_linktype(compiler_state_t *, int);
+static struct block *gen_ipnet_linktype(compiler_state_t *, int);
+static struct block *gen_linux_sll_linktype(compiler_state_t *, int);
+static struct slist *gen_load_prism_llprefixlen(compiler_state_t *);
+static struct slist *gen_load_avs_llprefixlen(compiler_state_t *);
+static struct slist *gen_load_radiotap_llprefixlen(compiler_state_t *);
+static struct slist *gen_load_ppi_llprefixlen(compiler_state_t *);
+static void insert_compute_vloffsets(compiler_state_t *, struct block *);
+static struct slist *gen_abs_offset_varpart(compiler_state_t *,
+ bpf_abs_offset *);
static int ethertype_to_ppptype(int);
-static struct block *gen_linktype(int);
-static struct block *gen_snap(bpf_u_int32, bpf_u_int32);
-static struct block *gen_llc_linktype(int);
-static struct block *gen_hostop(bpf_u_int32, bpf_u_int32, int, int, u_int, u_int);
+static struct block *gen_linktype(compiler_state_t *, int);
+static struct block *gen_snap(compiler_state_t *, bpf_u_int32, bpf_u_int32);
+static struct block *gen_llc_linktype(compiler_state_t *, int);
+static struct block *gen_hostop(compiler_state_t *, bpf_u_int32, bpf_u_int32,
+ int, int, u_int, u_int);
#ifdef INET6
-static struct block *gen_hostop6(struct in6_addr *, struct in6_addr *, int, int, u_int, u_int);
+static struct block *gen_hostop6(compiler_state_t *, struct in6_addr *,
+ struct in6_addr *, int, int, u_int, u_int);
#endif
-static struct block *gen_ahostop(const u_char *, int);
-static struct block *gen_ehostop(const u_char *, int);
-static struct block *gen_fhostop(const u_char *, int);
-static struct block *gen_thostop(const u_char *, int);
-static struct block *gen_wlanhostop(const u_char *, int);
-static struct block *gen_ipfchostop(const u_char *, int);
-static struct block *gen_dnhostop(bpf_u_int32, int);
-static struct block *gen_mpls_linktype(int);
-static struct block *gen_host(bpf_u_int32, bpf_u_int32, int, int, int);
+static struct block *gen_ahostop(compiler_state_t *, const u_char *, int);
+static struct block *gen_ehostop(compiler_state_t *, const u_char *, int);
+static struct block *gen_fhostop(compiler_state_t *, const u_char *, int);
+static struct block *gen_thostop(compiler_state_t *, const u_char *, int);
+static struct block *gen_wlanhostop(compiler_state_t *, const u_char *, int);
+static struct block *gen_ipfchostop(compiler_state_t *, const u_char *, int);
+static struct block *gen_dnhostop(compiler_state_t *, bpf_u_int32, int);
+static struct block *gen_mpls_linktype(compiler_state_t *, int);
+static struct block *gen_host(compiler_state_t *, bpf_u_int32, bpf_u_int32,
+ int, int, int);
#ifdef INET6
-static struct block *gen_host6(struct in6_addr *, struct in6_addr *, int, int, int);
+static struct block *gen_host6(compiler_state_t *, struct in6_addr *,
+ struct in6_addr *, int, int, int);
#endif
#ifndef INET6
static struct block *gen_gateway(const u_char *, bpf_u_int32 **, int, int);
#endif
-static struct block *gen_ipfrag(void);
-static struct block *gen_portatom(int, bpf_int32);
-static struct block *gen_portrangeatom(int, bpf_int32, bpf_int32);
-static struct block *gen_portatom6(int, bpf_int32);
-static struct block *gen_portrangeatom6(int, bpf_int32, bpf_int32);
-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);
-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);
-static int lookup_proto(const char *, int);
-static struct block *gen_protochain(int, int, int);
-static struct block *gen_proto(int, int, int);
-static struct slist *xfer_to_x(struct arth *);
-static struct slist *xfer_to_a(struct arth *);
-static struct block *gen_mac_multicast(int);
-static struct block *gen_len(int, int);
-static struct block *gen_check_802_11_data_frame(void);
-
-static struct block *gen_ppi_dlt_check(void);
-static struct block *gen_msg_abbrev(int type);
+static struct block *gen_ipfrag(compiler_state_t *);
+static struct block *gen_portatom(compiler_state_t *, int, bpf_int32);
+static struct block *gen_portrangeatom(compiler_state_t *, int, bpf_int32,
+ bpf_int32);
+static struct block *gen_portatom6(compiler_state_t *, int, bpf_int32);
+static struct block *gen_portrangeatom6(compiler_state_t *, int, bpf_int32,
+ bpf_int32);
+struct block *gen_portop(compiler_state_t *, int, int, int);
+static struct block *gen_port(compiler_state_t *, int, int, int);
+struct block *gen_portrangeop(compiler_state_t *, int, int, int, int);
+static struct block *gen_portrange(compiler_state_t *, int, int, int, int);
+struct block *gen_portop6(compiler_state_t *, int, int, int);
+static struct block *gen_port6(compiler_state_t *, int, int, int);
+struct block *gen_portrangeop6(compiler_state_t *, int, int, int, int);
+static struct block *gen_portrange6(compiler_state_t *, int, int, int, int);
+static int lookup_proto(compiler_state_t *, const char *, int);
+static struct block *gen_protochain(compiler_state_t *, int, int, int);
+static struct block *gen_proto(compiler_state_t *, int, int, int);
+static struct slist *xfer_to_x(compiler_state_t *, struct arth *);
+static struct slist *xfer_to_a(compiler_state_t *, struct arth *);
+static struct block *gen_mac_multicast(compiler_state_t *, int);
+static struct block *gen_len(compiler_state_t *, int, int);
+static struct block *gen_check_802_11_data_frame(compiler_state_t *);
+static struct block *gen_geneve_ll_check(compiler_state_t *cstate);
+
+static struct block *gen_ppi_dlt_check(compiler_state_t *);
+static struct block *gen_msg_abbrev(compiler_state_t *, int type);
+
+static void
+initchunks(compiler_state_t *cstate)
+{
+ int i;
+
+ for (i = 0; i < NCHUNKS; i++) {
+ cstate->chunks[i].n_left = 0;
+ cstate->chunks[i].m = NULL;
+ }
+ cstate->cur_chunk = 0;
+}
static void *
-newchunk(n)
- u_int n;
+newchunk(compiler_state_t *cstate, size_t n)
{
struct chunk *cp;
int k;
@@ -307,58 +582,53 @@ newchunk(n)
n = ALIGN(n);
#endif
- cp = &chunks[cur_chunk];
+ cp = &cstate->chunks[cstate->cur_chunk];
if (n > cp->n_left) {
- ++cp, k = ++cur_chunk;
+ ++cp, k = ++cstate->cur_chunk;
if (k >= NCHUNKS)
- bpf_error("out of memory");
+ bpf_error(cstate, "out of memory");
size = CHUNK0SIZE << k;
cp->m = (void *)malloc(size);
if (cp->m == NULL)
- bpf_error("out of memory");
+ bpf_error(cstate, "out of memory");
memset((char *)cp->m, 0, size);
cp->n_left = size;
if (n > size)
- bpf_error("out of memory");
+ bpf_error(cstate, "out of memory");
}
cp->n_left -= n;
return (void *)((char *)cp->m + cp->n_left);
}
static void
-freechunks()
+freechunks(compiler_state_t *cstate)
{
int i;
- cur_chunk = 0;
for (i = 0; i < NCHUNKS; ++i)
- if (chunks[i].m != NULL) {
- free(chunks[i].m);
- chunks[i].m = NULL;
- }
+ if (cstate->chunks[i].m != NULL)
+ free(cstate->chunks[i].m);
}
/*
* A strdup whose allocations are freed after code generation is over.
*/
char *
-sdup(s)
- register const char *s;
+sdup(compiler_state_t *cstate, const char *s)
{
- int n = strlen(s) + 1;
- char *cp = newchunk(n);
+ size_t n = strlen(s) + 1;
+ char *cp = newchunk(cstate, n);
strlcpy(cp, s, n);
return (cp);
}
static inline struct block *
-new_block(code)
- int code;
+new_block(compiler_state_t *cstate, int code)
{
struct block *p;
- p = (struct block *)newchunk(sizeof(*p));
+ p = (struct block *)newchunk(cstate, sizeof(*p));
p->s.code = code;
p->head = p;
@@ -366,59 +636,48 @@ new_block(code)
}
static inline struct slist *
-new_stmt(code)
- int code;
+new_stmt(compiler_state_t *cstate, int code)
{
struct slist *p;
- p = (struct slist *)newchunk(sizeof(*p));
+ p = (struct slist *)newchunk(cstate, sizeof(*p));
p->s.code = code;
return p;
}
static struct block *
-gen_retblk(v)
- int v;
+gen_retblk(compiler_state_t *cstate, int v)
{
- struct block *b = new_block(BPF_RET|BPF_K);
+ struct block *b = new_block(cstate, BPF_RET|BPF_K);
b->s.k = v;
return b;
}
static inline void
-syntax()
+syntax(compiler_state_t *cstate)
{
- bpf_error("syntax error in filter expression");
+ bpf_error(cstate, "syntax error in filter expression");
}
-static bpf_u_int32 netmask;
-static int snaplen;
-int no_optimize;
-
int
pcap_compile(pcap_t *p, struct bpf_program *program,
const char *buf, int optimize, bpf_u_int32 mask)
{
- extern int n_errors;
+ compiler_state_t cstate;
const char * volatile xbuf = buf;
+ yyscan_t scanner = NULL;
+ YY_BUFFER_STATE in_buffer = NULL;
u_int len;
int rc;
- /*
- * XXX - single-thread this code path with pthread calls on
- * UN*X, if the platform supports pthreads? If that requires
- * a separate -lpthread, we might not want to do that.
- */
-#ifdef WIN32
- extern int wsockinit (void);
+#ifdef _WIN32
static int done = 0;
if (!done)
- wsockinit();
+ pcap_wsockinit();
done = 1;
- EnterCriticalSection(&g_PcapCompileCriticalSection);
#endif
/*
@@ -426,69 +685,78 @@ pcap_compile(pcap_t *p, struct bpf_program *program,
* link-layer type, so we can't use it.
*/
if (!p->activated) {
- snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
+ pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
"not-yet-activated pcap_t passed to pcap_compile");
rc = -1;
goto quit;
}
- no_optimize = 0;
- n_errors = 0;
- root = NULL;
- bpf_pcap = p;
- init_regs();
-
- if (setjmp(top_ctx)) {
+ initchunks(&cstate);
+ cstate.no_optimize = 0;
+ cstate.ai = NULL;
+ cstate.ic.root = NULL;
+ cstate.ic.cur_mark = 0;
+ cstate.bpf_pcap = p;
+ init_regs(&cstate);
+
+ if (setjmp(cstate.top_ctx)) {
#ifdef INET6
- if (ai != NULL) {
- freeaddrinfo(ai);
- ai = NULL;
- }
+ if (cstate.ai != NULL)
+ freeaddrinfo(cstate.ai);
#endif
- lex_cleanup();
- freechunks();
rc = -1;
goto quit;
}
- netmask = mask;
+ cstate.netmask = mask;
- snaplen = pcap_snapshot(p);
- if (snaplen == 0) {
- snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
+ cstate.snaplen = pcap_snapshot(p);
+ if (cstate.snaplen == 0) {
+ pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
"snaplen of 0 rejects all packets");
rc = -1;
goto quit;
}
- lex_init(xbuf ? xbuf : "");
- init_linktype(p);
- (void)pcap_parse();
+ if (pcap_lex_init(&scanner) != 0)
+ bpf_error(&cstate, "can't initialize scanner: %s", pcap_strerror(errno));
+ in_buffer = pcap__scan_string(xbuf ? xbuf : "", scanner);
+
+ /*
+ * Associate the compiler state with the lexical analyzer
+ * state.
+ */
+ pcap_set_extra(&cstate, scanner);
- if (n_errors)
- syntax();
+ init_linktype(&cstate, p);
+ (void)pcap_parse(scanner, &cstate);
- if (root == NULL)
- root = gen_retblk(snaplen);
+ if (cstate.ic.root == NULL)
+ cstate.ic.root = gen_retblk(&cstate, cstate.snaplen);
- if (optimize && !no_optimize) {
- bpf_optimize(&root);
- if (root == NULL ||
- (root->s.code == (BPF_RET|BPF_K) && root->s.k == 0))
- bpf_error("expression rejects all packets");
+ if (optimize && !cstate.no_optimize) {
+ bpf_optimize(&cstate, &cstate.ic);
+ if (cstate.ic.root == NULL ||
+ (cstate.ic.root->s.code == (BPF_RET|BPF_K) && cstate.ic.root->s.k == 0))
+ bpf_error(&cstate, "expression rejects all packets");
}
- program->bf_insns = icode_to_fcode(root, &len);
+ program->bf_insns = icode_to_fcode(&cstate, &cstate.ic, cstate.ic.root, &len);
program->bf_len = len;
- lex_cleanup();
- freechunks();
-
rc = 0; /* We're all okay */
quit:
+ /*
+ * Clean up everything for the lexical analyzer.
+ */
+ if (in_buffer != NULL)
+ pcap__delete_buffer(in_buffer, scanner);
+ if (scanner != NULL)
+ pcap_lex_destroy(scanner);
-#ifdef WIN32
- LeaveCriticalSection(&g_PcapCompileCriticalSection);
-#endif
+ /*
+ * Clean up our own allocated memory.
+ */
+ freechunks(&cstate);
return (rc);
}
@@ -570,8 +838,7 @@ merge(b0, b1)
}
void
-finish_parse(p)
- struct block *p;
+finish_parse(compiler_state_t *cstate, struct block *p)
{
struct block *ppi_dlt_check;
@@ -594,20 +861,29 @@ finish_parse(p)
* for tests that fail early, and it's not clear that's
* worth the effort.
*/
- insert_compute_vloffsets(p->head);
+ insert_compute_vloffsets(cstate, p->head);
/*
* For DLT_PPI captures, generate a check of the per-packet
* DLT value to make sure it's DLT_IEEE802_11.
+ *
+ * XXX - TurboCap cards use DLT_PPI for Ethernet.
+ * Can we just define some DLT_ETHERNET_WITH_PHDR pseudo-header
+ * with appropriate Ethernet information and use that rather
+ * than using something such as DLT_PPI where you don't know
+ * the link-layer header type until runtime, which, in the
+ * general case, would force us to generate both Ethernet *and*
+ * 802.11 code (*and* anything else for which PPI is used)
+ * and choose between them early in the BPF program?
*/
- ppi_dlt_check = gen_ppi_dlt_check();
+ ppi_dlt_check = gen_ppi_dlt_check(cstate);
if (ppi_dlt_check != NULL)
gen_and(ppi_dlt_check, p);
- backpatch(p, gen_retblk(snaplen));
+ backpatch(p, gen_retblk(cstate, cstate->snaplen));
p->sense = !p->sense;
- backpatch(p, gen_retblk(0));
- root = p->head;
+ backpatch(p, gen_retblk(cstate, 0));
+ cstate->ic.root = p->head;
}
void
@@ -641,65 +917,50 @@ gen_not(b)
}
static struct block *
-gen_cmp(offrel, offset, size, v)
- enum e_offrel offrel;
- u_int offset, size;
- bpf_int32 v;
+gen_cmp(compiler_state_t *cstate, enum e_offrel offrel, u_int offset,
+ u_int size, bpf_int32 v)
{
- return gen_ncmp(offrel, offset, size, 0xffffffff, BPF_JEQ, 0, v);
+ return gen_ncmp(cstate, offrel, offset, size, 0xffffffff, BPF_JEQ, 0, v);
}
static struct block *
-gen_cmp_gt(offrel, offset, size, v)
- enum e_offrel offrel;
- u_int offset, size;
- bpf_int32 v;
+gen_cmp_gt(compiler_state_t *cstate, enum e_offrel offrel, u_int offset,
+ u_int size, bpf_int32 v)
{
- return gen_ncmp(offrel, offset, size, 0xffffffff, BPF_JGT, 0, v);
+ return gen_ncmp(cstate, offrel, offset, size, 0xffffffff, BPF_JGT, 0, v);
}
static struct block *
-gen_cmp_ge(offrel, offset, size, v)
- enum e_offrel offrel;
- u_int offset, size;
- bpf_int32 v;
+gen_cmp_ge(compiler_state_t *cstate, enum e_offrel offrel, u_int offset,
+ u_int size, bpf_int32 v)
{
- return gen_ncmp(offrel, offset, size, 0xffffffff, BPF_JGE, 0, v);
+ return gen_ncmp(cstate, offrel, offset, size, 0xffffffff, BPF_JGE, 0, v);
}
static struct block *
-gen_cmp_lt(offrel, offset, size, v)
- enum e_offrel offrel;
- u_int offset, size;
- bpf_int32 v;
+gen_cmp_lt(compiler_state_t *cstate, enum e_offrel offrel, u_int offset,
+ u_int size, bpf_int32 v)
{
- return gen_ncmp(offrel, offset, size, 0xffffffff, BPF_JGE, 1, v);
+ return gen_ncmp(cstate, offrel, offset, size, 0xffffffff, BPF_JGE, 1, v);
}
static struct block *
-gen_cmp_le(offrel, offset, size, v)
- enum e_offrel offrel;
- u_int offset, size;
- bpf_int32 v;
+gen_cmp_le(compiler_state_t *cstate, enum e_offrel offrel, u_int offset,
+ u_int size, bpf_int32 v)
{
- return gen_ncmp(offrel, offset, size, 0xffffffff, BPF_JGT, 1, v);
+ return gen_ncmp(cstate, offrel, offset, size, 0xffffffff, BPF_JGT, 1, v);
}
static struct block *
-gen_mcmp(offrel, offset, size, v, mask)
- enum e_offrel offrel;
- u_int offset, size;
- bpf_int32 v;
- bpf_u_int32 mask;
+gen_mcmp(compiler_state_t *cstate, enum e_offrel offrel, u_int offset,
+ u_int size, bpf_int32 v, bpf_u_int32 mask)
{
- return gen_ncmp(offrel, offset, size, mask, BPF_JEQ, 0, v);
+ return gen_ncmp(cstate, offrel, offset, size, mask, BPF_JEQ, 0, v);
}
static struct block *
-gen_bcmp(offrel, offset, size, v)
- enum e_offrel offrel;
- register u_int offset, size;
- register const u_char *v;
+gen_bcmp(compiler_state_t *cstate, enum e_offrel offrel, u_int offset,
+ u_int size, const u_char *v)
{
register struct block *b, *tmp;
@@ -709,7 +970,7 @@ gen_bcmp(offrel, offset, size, v)
bpf_int32 w = ((bpf_int32)p[0] << 24) |
((bpf_int32)p[1] << 16) | ((bpf_int32)p[2] << 8) | p[3];
- tmp = gen_cmp(offrel, offset + size - 4, BPF_W, w);
+ tmp = gen_cmp(cstate, offrel, offset + size - 4, BPF_W, w);
if (b != NULL)
gen_and(b, tmp);
b = tmp;
@@ -719,14 +980,14 @@ gen_bcmp(offrel, offset, size, v)
register const u_char *p = &v[size - 2];
bpf_int32 w = ((bpf_int32)p[0] << 8) | p[1];
- tmp = gen_cmp(offrel, offset + size - 2, BPF_H, w);
+ tmp = gen_cmp(cstate, offrel, offset + size - 2, BPF_H, w);
if (b != NULL)
gen_and(b, tmp);
b = tmp;
size -= 2;
}
if (size > 0) {
- tmp = gen_cmp(offrel, offset, BPF_B, (bpf_int32)v[0]);
+ tmp = gen_cmp(cstate, offrel, offset, BPF_B, (bpf_int32)v[0]);
if (b != NULL)
gen_and(b, tmp);
b = tmp;
@@ -741,24 +1002,22 @@ gen_bcmp(offrel, offset, size, v)
* should test the opposite of "jtype".
*/
static struct block *
-gen_ncmp(offrel, offset, size, mask, jtype, reverse, v)
- enum e_offrel offrel;
- bpf_int32 v;
- bpf_u_int32 offset, size, mask, jtype;
- int reverse;
+gen_ncmp(compiler_state_t *cstate, enum e_offrel offrel, bpf_u_int32 offset,
+ bpf_u_int32 size, bpf_u_int32 mask, bpf_u_int32 jtype, int reverse,
+ bpf_int32 v)
{
struct slist *s, *s2;
struct block *b;
- s = gen_load_a(offrel, offset, size);
+ s = gen_load_a(cstate, offrel, offset, size);
if (mask != 0xffffffff) {
- s2 = new_stmt(BPF_ALU|BPF_AND|BPF_K);
+ s2 = new_stmt(cstate, BPF_ALU|BPF_AND|BPF_K);
s2->s.k = mask;
sappend(s, s2);
}
- b = new_block(JMP(jtype));
+ b = new_block(cstate, JMP(jtype));
b->stmts = s;
b->s.k = v;
if (reverse && (jtype == BPF_JGT || jtype == BPF_JGE))
@@ -766,294 +1025,152 @@ gen_ncmp(offrel, offset, size, mask, jtype, reverse, v)
return b;
}
-/*
- * Various code constructs need to know the layout of the data link
- * layer. These variables give the necessary offsets from the beginning
- * of the packet data.
- */
-
-/*
- * This is the offset of the beginning of the link-layer header from
- * the beginning of the raw packet data.
- *
- * It's usually 0, except for 802.11 with a fixed-length radio header.
- * (For 802.11 with a variable-length radio header, we have to generate
- * code to compute that offset; off_ll is 0 in that case.)
- */
-static u_int off_ll;
-
-/*
- * If there's a variable-length header preceding the link-layer header,
- * "reg_off_ll" is the register number for a register containing the
- * length of that header, and therefore the offset of the link-layer
- * header from the beginning of the raw packet data. Otherwise,
- * "reg_off_ll" is -1.
- */
-static int reg_off_ll;
-
-/*
- * This is the offset of the beginning of the MAC-layer header from
- * the beginning of the link-layer header.
- * It's usually 0, except for ATM LANE, where it's the offset, relative
- * to the beginning of the raw packet data, of the Ethernet header, and
- * for Ethernet with various additional information.
- */
-static u_int off_mac;
-
-/*
- * This is the offset of the beginning of the MAC-layer payload,
- * from the beginning of the raw packet data.
- *
- * I.e., it's the sum of the length of the link-layer header (without,
- * for example, any 802.2 LLC header, so it's the MAC-layer
- * portion of that header), plus any prefix preceding the
- * link-layer header.
- */
-static u_int off_macpl;
-
-/*
- * This is 1 if the offset of the beginning of the MAC-layer payload
- * from the beginning of the link-layer header is variable-length.
- */
-static int off_macpl_is_variable;
-
-/*
- * If the link layer has variable_length headers, "reg_off_macpl"
- * is the register number for a register containing the length of the
- * link-layer header plus the length of any variable-length header
- * preceding the link-layer header. Otherwise, "reg_off_macpl"
- * is -1.
- */
-static int reg_off_macpl;
-
-/*
- * "off_linktype" is the offset to information in the link-layer header
- * giving the packet type. This offset is relative to the beginning
- * of the link-layer header (i.e., it doesn't include off_ll).
- *
- * For Ethernet, it's the offset of the Ethernet type field.
- *
- * For link-layer types that always use 802.2 headers, it's the
- * offset of the LLC header.
- *
- * For PPP, it's the offset of the PPP type field.
- *
- * For Cisco HDLC, it's the offset of the CHDLC type field.
- *
- * For BSD loopback, it's the offset of the AF_ value.
- *
- * For Linux cooked sockets, it's the offset of the type field.
- *
- * It's set to -1 for no encapsulation, in which case, IP is assumed.
- */
-static u_int off_linktype;
-
-/*
- * TRUE if "pppoes" appeared in the filter; it causes link-layer type
- * checks to check the PPP header, assumed to follow a LAN-style link-
- * layer header and a PPPoE session header.
- */
-static int is_pppoes = 0;
-
-/*
- * TRUE if the link layer includes an ATM pseudo-header.
- */
-static int is_atm = 0;
-
-/*
- * TRUE if "lane" appeared in the filter; it causes us to generate
- * code that assumes LANE rather than LLC-encapsulated traffic in SunATM.
- */
-static int is_lane = 0;
-
-/*
- * These are offsets for the ATM pseudo-header.
- */
-static u_int off_vpi;
-static u_int off_vci;
-static u_int off_proto;
+static void
+init_linktype(compiler_state_t *cstate, pcap_t *p)
+{
+ cstate->pcap_fddipad = p->fddipad;
-/*
- * These are offsets for the MTP2 fields.
- */
-static u_int off_li;
-static u_int off_li_hsl;
+ /*
+ * We start out with only one link-layer header.
+ */
+ cstate->outermostlinktype = pcap_datalink(p);
+ cstate->off_outermostlinkhdr.constant_part = 0;
+ cstate->off_outermostlinkhdr.is_variable = 0;
+ cstate->off_outermostlinkhdr.reg = -1;
-/*
- * These are offsets for the MTP3 fields.
- */
-static u_int off_sio;
-static u_int off_opc;
-static u_int off_dpc;
-static u_int off_sls;
+ cstate->prevlinktype = cstate->outermostlinktype;
+ cstate->off_prevlinkhdr.constant_part = 0;
+ cstate->off_prevlinkhdr.is_variable = 0;
+ cstate->off_prevlinkhdr.reg = -1;
-/*
- * This is the offset of the first byte after the ATM pseudo_header,
- * or -1 if there is no ATM pseudo-header.
- */
-static u_int off_payload;
+ cstate->linktype = cstate->outermostlinktype;
+ cstate->off_linkhdr.constant_part = 0;
+ cstate->off_linkhdr.is_variable = 0;
+ cstate->off_linkhdr.reg = -1;
-/*
- * These are offsets to the beginning of the network-layer header.
- * They are relative to the beginning of the MAC-layer payload (i.e.,
- * they don't include off_ll or off_macpl).
- *
- * If the link layer never uses 802.2 LLC:
- *
- * "off_nl" and "off_nl_nosnap" are the same.
- *
- * If the link layer always uses 802.2 LLC:
- *
- * "off_nl" is the offset if there's a SNAP header following
- * the 802.2 header;
- *
- * "off_nl_nosnap" is the offset if there's no SNAP header.
- *
- * If the link layer is Ethernet:
- *
- * "off_nl" is the offset if the packet is an Ethernet II packet
- * (we assume no 802.3+802.2+SNAP);
- *
- * "off_nl_nosnap" is the offset if the packet is an 802.3 packet
- * with an 802.2 header following it.
- */
-static u_int off_nl;
-static u_int off_nl_nosnap;
-
-static int linktype;
+ /*
+ * XXX
+ */
+ cstate->off_linkpl.constant_part = 0;
+ cstate->off_linkpl.is_variable = 0;
+ cstate->off_linkpl.reg = -1;
-static void
-init_linktype(p)
- pcap_t *p;
-{
- linktype = pcap_datalink(p);
- pcap_fddipad = p->fddipad;
+ cstate->off_linktype.constant_part = 0;
+ cstate->off_linktype.is_variable = 0;
+ cstate->off_linktype.reg = -1;
/*
* Assume it's not raw ATM with a pseudo-header, for now.
*/
- off_mac = 0;
- is_atm = 0;
- is_lane = 0;
- off_vpi = -1;
- off_vci = -1;
- off_proto = -1;
- off_payload = -1;
+ cstate->is_atm = 0;
+ cstate->off_vpi = -1;
+ cstate->off_vci = -1;
+ cstate->off_proto = -1;
+ cstate->off_payload = -1;
/*
- * And that we're not doing PPPoE.
+ * And not Geneve.
*/
- is_pppoes = 0;
+ cstate->is_geneve = 0;
/*
* And assume we're not doing SS7.
*/
- off_li = -1;
- off_li_hsl = -1;
- off_sio = -1;
- off_opc = -1;
- off_dpc = -1;
- off_sls = -1;
-
- /*
- * Also assume it's not 802.11.
- */
- off_ll = 0;
- off_macpl = 0;
- off_macpl_is_variable = 0;
-
- orig_linktype = -1;
- orig_nl = -1;
- label_stack_depth = 0;
+ cstate->off_li = -1;
+ cstate->off_li_hsl = -1;
+ cstate->off_sio = -1;
+ cstate->off_opc = -1;
+ cstate->off_dpc = -1;
+ cstate->off_sls = -1;
- reg_off_ll = -1;
- reg_off_macpl = -1;
+ cstate->label_stack_depth = 0;
+ cstate->vlan_stack_depth = 0;
- switch (linktype) {
+ switch (cstate->linktype) {
case DLT_ARCNET:
- off_linktype = 2;
- off_macpl = 6;
- off_nl = 0; /* XXX in reality, variable! */
- off_nl_nosnap = 0; /* no 802.2 LLC */
- return;
+ cstate->off_linktype.constant_part = 2;
+ cstate->off_linkpl.constant_part = 6;
+ cstate->off_nl = 0; /* XXX in reality, variable! */
+ cstate->off_nl_nosnap = 0; /* no 802.2 LLC */
+ break;
case DLT_ARCNET_LINUX:
- off_linktype = 4;
- off_macpl = 8;
- off_nl = 0; /* XXX in reality, variable! */
- off_nl_nosnap = 0; /* no 802.2 LLC */
- return;
+ cstate->off_linktype.constant_part = 4;
+ cstate->off_linkpl.constant_part = 8;
+ cstate->off_nl = 0; /* XXX in reality, variable! */
+ cstate->off_nl_nosnap = 0; /* no 802.2 LLC */
+ break;
case DLT_EN10MB:
- off_linktype = 12;
- off_macpl = 14; /* Ethernet header length */
- off_nl = 0; /* Ethernet II */
- off_nl_nosnap = 3; /* 802.3+802.2 */
- return;
+ cstate->off_linktype.constant_part = 12;
+ cstate->off_linkpl.constant_part = 14; /* Ethernet header length */
+ cstate->off_nl = 0; /* Ethernet II */
+ cstate->off_nl_nosnap = 3; /* 802.3+802.2 */
+ break;
case DLT_SLIP:
/*
* SLIP doesn't have a link level type. The 16 byte
* header is hacked into our SLIP driver.
*/
- off_linktype = -1;
- off_macpl = 16;
- off_nl = 0;
- off_nl_nosnap = 0; /* no 802.2 LLC */
- return;
+ cstate->off_linktype.constant_part = OFFSET_NOT_SET;
+ cstate->off_linkpl.constant_part = 16;
+ cstate->off_nl = 0;
+ cstate->off_nl_nosnap = 0; /* no 802.2 LLC */
+ break;
case DLT_SLIP_BSDOS:
/* XXX this may be the same as the DLT_PPP_BSDOS case */
- off_linktype = -1;
+ cstate->off_linktype.constant_part = OFFSET_NOT_SET;
/* XXX end */
- off_macpl = 24;
- off_nl = 0;
- off_nl_nosnap = 0; /* no 802.2 LLC */
- return;
+ cstate->off_linkpl.constant_part = 24;
+ cstate->off_nl = 0;
+ cstate->off_nl_nosnap = 0; /* no 802.2 LLC */
+ break;
case DLT_NULL:
case DLT_LOOP:
- off_linktype = 0;
- off_macpl = 4;
- off_nl = 0;
- off_nl_nosnap = 0; /* no 802.2 LLC */
- return;
+ cstate->off_linktype.constant_part = 0;
+ cstate->off_linkpl.constant_part = 4;
+ cstate->off_nl = 0;
+ cstate->off_nl_nosnap = 0; /* no 802.2 LLC */
+ break;
case DLT_ENC:
- off_linktype = 0;
- off_macpl = 12;
- off_nl = 0;
- off_nl_nosnap = 0; /* no 802.2 LLC */
- return;
+ cstate->off_linktype.constant_part = 0;
+ cstate->off_linkpl.constant_part = 12;
+ cstate->off_nl = 0;
+ cstate->off_nl_nosnap = 0; /* no 802.2 LLC */
+ break;
case DLT_PPP:
case DLT_PPP_PPPD:
case DLT_C_HDLC: /* BSD/OS Cisco HDLC */
case DLT_PPP_SERIAL: /* NetBSD sync/async serial PPP */
- off_linktype = 2;
- off_macpl = 4;
- off_nl = 0;
- off_nl_nosnap = 0; /* no 802.2 LLC */
- return;
+ cstate->off_linktype.constant_part = 2; /* skip HDLC-like framing */
+ cstate->off_linkpl.constant_part = 4; /* skip HDLC-like framing and protocol field */
+ cstate->off_nl = 0;
+ cstate->off_nl_nosnap = 0; /* no 802.2 LLC */
+ break;
case DLT_PPP_ETHER:
/*
* This does no include the Ethernet header, and
* only covers session state.
*/
- off_linktype = 6;
- off_macpl = 8;
- off_nl = 0;
- off_nl_nosnap = 0; /* no 802.2 LLC */
- return;
+ cstate->off_linktype.constant_part = 6;
+ cstate->off_linkpl.constant_part = 8;
+ cstate->off_nl = 0;
+ cstate->off_nl_nosnap = 0; /* no 802.2 LLC */
+ break;
case DLT_PPP_BSDOS:
- off_linktype = 5;
- off_macpl = 24;
- off_nl = 0;
- off_nl_nosnap = 0; /* no 802.2 LLC */
- return;
+ cstate->off_linktype.constant_part = 5;
+ cstate->off_linkpl.constant_part = 24;
+ cstate->off_nl = 0;
+ cstate->off_nl_nosnap = 0; /* no 802.2 LLC */
+ break;
case DLT_FDDI:
/*
@@ -1064,13 +1181,13 @@ init_linktype(p)
* is being used and pick out the encapsulated Ethernet type.
* XXX - should we generate code to check for SNAP?
*/
- off_linktype = 13;
- off_linktype += pcap_fddipad;
- off_macpl = 13; /* FDDI MAC header length */
- off_macpl += pcap_fddipad;
- off_nl = 8; /* 802.2+SNAP */
- off_nl_nosnap = 3; /* 802.2 */
- return;
+ cstate->off_linktype.constant_part = 13;
+ cstate->off_linktype.constant_part += cstate->pcap_fddipad;
+ cstate->off_linkpl.constant_part = 13; /* FDDI MAC header length */
+ cstate->off_linkpl.constant_part += cstate->pcap_fddipad;
+ cstate->off_nl = 8; /* 802.2+SNAP */
+ cstate->off_nl_nosnap = 3; /* 802.2 */
+ break;
case DLT_IEEE802:
/*
@@ -1096,19 +1213,24 @@ init_linktype(p)
* the 16-bit value at an offset of 14 (shifted right
* 8 - figure out which byte that is).
*/
- off_linktype = 14;
- off_macpl = 14; /* Token Ring MAC header length */
- off_nl = 8; /* 802.2+SNAP */
- off_nl_nosnap = 3; /* 802.2 */
- return;
+ cstate->off_linktype.constant_part = 14;
+ cstate->off_linkpl.constant_part = 14; /* Token Ring MAC header length */
+ cstate->off_nl = 8; /* 802.2+SNAP */
+ cstate->off_nl_nosnap = 3; /* 802.2 */
+ break;
- case DLT_IEEE802_11:
case DLT_PRISM_HEADER:
case DLT_IEEE802_11_RADIO_AVS:
case DLT_IEEE802_11_RADIO:
+ cstate->off_linkhdr.is_variable = 1;
+ /* Fall through, 802.11 doesn't have a variable link
+ * prefix but is otherwise the same. */
+
+ case DLT_IEEE802_11:
/*
* 802.11 doesn't really have a link-level type field.
- * We set "off_linktype" to the offset of the LLC header.
+ * We set "off_linktype.constant_part" to the offset of
+ * the LLC header.
*
* To check for Ethernet types, we assume that SSAP = SNAP
* is being used and pick out the encapsulated Ethernet type.
@@ -1123,12 +1245,12 @@ init_linktype(p)
* header or an AVS header, so, in practice, it's
* variable-length.
*/
- off_linktype = 24;
- off_macpl = 0; /* link-layer header is variable-length */
- off_macpl_is_variable = 1;
- off_nl = 8; /* 802.2+SNAP */
- off_nl_nosnap = 3; /* 802.2 */
- return;
+ cstate->off_linktype.constant_part = 24;
+ cstate->off_linkpl.constant_part = 0; /* link-layer header is variable-length */
+ cstate->off_linkpl.is_variable = 1;
+ cstate->off_nl = 8; /* 802.2+SNAP */
+ cstate->off_nl_nosnap = 3; /* 802.2 */
+ break;
case DLT_PPI:
/*
@@ -1140,12 +1262,13 @@ init_linktype(p)
* the encapsulated DLT should be DLT_IEEE802_11) we
* generate code to check for this too.
*/
- off_linktype = 24;
- off_macpl = 0; /* link-layer header is variable-length */
- off_macpl_is_variable = 1;
- off_nl = 8; /* 802.2+SNAP */
- off_nl_nosnap = 3; /* 802.2 */
- return;
+ cstate->off_linktype.constant_part = 24;
+ cstate->off_linkpl.constant_part = 0; /* link-layer header is variable-length */
+ cstate->off_linkpl.is_variable = 1;
+ cstate->off_linkhdr.is_variable = 1;
+ cstate->off_nl = 8; /* 802.2+SNAP */
+ cstate->off_nl_nosnap = 3; /* 802.2 */
+ break;
case DLT_ATM_RFC1483:
case DLT_ATM_CLIP: /* Linux ATM defines this */
@@ -1160,44 +1283,43 @@ init_linktype(p)
* or "pppoa and tcp port 80" and have it check for
* PPPo{A,E} and a PPP protocol of IP and....
*/
- off_linktype = 0;
- off_macpl = 0; /* packet begins with LLC header */
- off_nl = 8; /* 802.2+SNAP */
- off_nl_nosnap = 3; /* 802.2 */
- return;
+ cstate->off_linktype.constant_part = 0;
+ cstate->off_linkpl.constant_part = 0; /* packet begins with LLC header */
+ cstate->off_nl = 8; /* 802.2+SNAP */
+ cstate->off_nl_nosnap = 3; /* 802.2 */
+ break;
case DLT_SUNATM:
/*
* Full Frontal ATM; you get AALn PDUs with an ATM
* pseudo-header.
*/
- is_atm = 1;
- off_vpi = SUNATM_VPI_POS;
- off_vci = SUNATM_VCI_POS;
- off_proto = PROTO_POS;
- off_mac = -1; /* assume LLC-encapsulated, so no MAC-layer header */
- off_payload = SUNATM_PKT_BEGIN_POS;
- off_linktype = off_payload;
- off_macpl = off_payload; /* if LLC-encapsulated */
- off_nl = 8; /* 802.2+SNAP */
- off_nl_nosnap = 3; /* 802.2 */
- return;
+ cstate->is_atm = 1;
+ cstate->off_vpi = SUNATM_VPI_POS;
+ cstate->off_vci = SUNATM_VCI_POS;
+ cstate->off_proto = PROTO_POS;
+ cstate->off_payload = SUNATM_PKT_BEGIN_POS;
+ cstate->off_linktype.constant_part = cstate->off_payload;
+ cstate->off_linkpl.constant_part = cstate->off_payload; /* if LLC-encapsulated */
+ cstate->off_nl = 8; /* 802.2+SNAP */
+ cstate->off_nl_nosnap = 3; /* 802.2 */
+ break;
case DLT_RAW:
case DLT_IPV4:
case DLT_IPV6:
- off_linktype = -1;
- off_macpl = 0;
- off_nl = 0;
- off_nl_nosnap = 0; /* no 802.2 LLC */
- return;
+ cstate->off_linktype.constant_part = OFFSET_NOT_SET;
+ cstate->off_linkpl.constant_part = 0;
+ cstate->off_nl = 0;
+ cstate->off_nl_nosnap = 0; /* no 802.2 LLC */
+ break;
case DLT_LINUX_SLL: /* fake header for Linux cooked socket */
- off_linktype = 14;
- off_macpl = 16;
- off_nl = 0;
- off_nl_nosnap = 0; /* no 802.2 LLC */
- return;
+ cstate->off_linktype.constant_part = 14;
+ cstate->off_linkpl.constant_part = 16;
+ cstate->off_nl = 0;
+ cstate->off_nl_nosnap = 0; /* no 802.2 LLC */
+ break;
case DLT_LTALK:
/*
@@ -1205,11 +1327,11 @@ init_linktype(p)
* but really it just indicates whether there is a "short" or
* "long" DDP packet following.
*/
- off_linktype = -1;
- off_macpl = 0;
- off_nl = 0;
- off_nl_nosnap = 0; /* no 802.2 LLC */
- return;
+ cstate->off_linktype.constant_part = OFFSET_NOT_SET;
+ cstate->off_linkpl.constant_part = 0;
+ cstate->off_nl = 0;
+ cstate->off_nl_nosnap = 0; /* no 802.2 LLC */
+ break;
case DLT_IP_OVER_FC:
/*
@@ -1222,22 +1344,22 @@ init_linktype(p)
* XXX - should we generate code to check for SNAP? RFC
* 2625 says SNAP should be used.
*/
- off_linktype = 16;
- off_macpl = 16;
- off_nl = 8; /* 802.2+SNAP */
- off_nl_nosnap = 3; /* 802.2 */
- return;
+ cstate->off_linktype.constant_part = 16;
+ cstate->off_linkpl.constant_part = 16;
+ cstate->off_nl = 8; /* 802.2+SNAP */
+ cstate->off_nl_nosnap = 3; /* 802.2 */
+ break;
case DLT_FRELAY:
/*
* XXX - we should set this to handle SNAP-encapsulated
* frames (NLPID of 0x80).
*/
- off_linktype = -1;
- off_macpl = 0;
- off_nl = 0;
- off_nl_nosnap = 0; /* no 802.2 LLC */
- return;
+ cstate->off_linktype.constant_part = OFFSET_NOT_SET;
+ cstate->off_linkpl.constant_part = 0;
+ cstate->off_nl = 0;
+ cstate->off_nl_nosnap = 0; /* no 802.2 LLC */
+ break;
/*
* the only BPF-interesting FRF.16 frames are non-control frames;
@@ -1245,33 +1367,33 @@ init_linktype(p)
* so lets start with offset 4 for now and increments later on (FIXME);
*/
case DLT_MFR:
- off_linktype = -1;
- off_macpl = 0;
- off_nl = 4;
- off_nl_nosnap = 0; /* XXX - for now -> no 802.2 LLC */
- return;
+ cstate->off_linktype.constant_part = OFFSET_NOT_SET;
+ cstate->off_linkpl.constant_part = 0;
+ cstate->off_nl = 4;
+ cstate->off_nl_nosnap = 0; /* XXX - for now -> no 802.2 LLC */
+ break;
case DLT_APPLE_IP_OVER_IEEE1394:
- off_linktype = 16;
- off_macpl = 18;
- off_nl = 0;
- off_nl_nosnap = 0; /* no 802.2 LLC */
- return;
+ cstate->off_linktype.constant_part = 16;
+ cstate->off_linkpl.constant_part = 18;
+ cstate->off_nl = 0;
+ cstate->off_nl_nosnap = 0; /* no 802.2 LLC */
+ break;
case DLT_SYMANTEC_FIREWALL:
- off_linktype = 6;
- off_macpl = 44;
- off_nl = 0; /* Ethernet II */
- off_nl_nosnap = 0; /* XXX - what does it do with 802.3 packets? */
- return;
+ cstate->off_linktype.constant_part = 6;
+ cstate->off_linkpl.constant_part = 44;
+ cstate->off_nl = 0; /* Ethernet II */
+ cstate->off_nl_nosnap = 0; /* XXX - what does it do with 802.3 packets? */
+ break;
#ifdef HAVE_NET_PFVAR_H
case DLT_PFLOG:
- off_linktype = 0;
- off_macpl = PFLOG_HDRLEN;
- off_nl = 0;
- off_nl_nosnap = 0; /* no 802.2 LLC */
- return;
+ cstate->off_linktype.constant_part = 0;
+ cstate->off_linkpl.constant_part = PFLOG_HDRLEN;
+ cstate->off_nl = 0;
+ cstate->off_nl_nosnap = 0; /* no 802.2 LLC */
+ break;
#endif
case DLT_JUNIPER_MFR:
@@ -1280,289 +1402,244 @@ init_linktype(p)
case DLT_JUNIPER_PPP:
case DLT_JUNIPER_CHDLC:
case DLT_JUNIPER_FRELAY:
- off_linktype = 4;
- off_macpl = 4;
- off_nl = 0;
- off_nl_nosnap = -1; /* no 802.2 LLC */
- return;
+ cstate->off_linktype.constant_part = 4;
+ cstate->off_linkpl.constant_part = 4;
+ cstate->off_nl = 0;
+ cstate->off_nl_nosnap = -1; /* no 802.2 LLC */
+ break;
case DLT_JUNIPER_ATM1:
- off_linktype = 4; /* in reality variable between 4-8 */
- off_macpl = 4; /* in reality variable between 4-8 */
- off_nl = 0;
- off_nl_nosnap = 10;
- return;
+ cstate->off_linktype.constant_part = 4; /* in reality variable between 4-8 */
+ cstate->off_linkpl.constant_part = 4; /* in reality variable between 4-8 */
+ cstate->off_nl = 0;
+ cstate->off_nl_nosnap = 10;
+ break;
case DLT_JUNIPER_ATM2:
- off_linktype = 8; /* in reality variable between 8-12 */
- off_macpl = 8; /* in reality variable between 8-12 */
- off_nl = 0;
- off_nl_nosnap = 10;
- return;
+ cstate->off_linktype.constant_part = 8; /* in reality variable between 8-12 */
+ cstate->off_linkpl.constant_part = 8; /* in reality variable between 8-12 */
+ cstate->off_nl = 0;
+ cstate->off_nl_nosnap = 10;
+ break;
/* frames captured on a Juniper PPPoE service PIC
* contain raw ethernet frames */
case DLT_JUNIPER_PPPOE:
case DLT_JUNIPER_ETHER:
- off_macpl = 14;
- off_linktype = 16;
- off_nl = 18; /* Ethernet II */
- off_nl_nosnap = 21; /* 802.3+802.2 */
- return;
+ cstate->off_linkpl.constant_part = 14;
+ cstate->off_linktype.constant_part = 16;
+ cstate->off_nl = 18; /* Ethernet II */
+ cstate->off_nl_nosnap = 21; /* 802.3+802.2 */
+ break;
case DLT_JUNIPER_PPPOE_ATM:
- off_linktype = 4;
- off_macpl = 6;
- off_nl = 0;
- off_nl_nosnap = -1; /* no 802.2 LLC */
- return;
+ cstate->off_linktype.constant_part = 4;
+ cstate->off_linkpl.constant_part = 6;
+ cstate->off_nl = 0;
+ cstate->off_nl_nosnap = -1; /* no 802.2 LLC */
+ break;
case DLT_JUNIPER_GGSN:
- off_linktype = 6;
- off_macpl = 12;
- off_nl = 0;
- off_nl_nosnap = -1; /* no 802.2 LLC */
- return;
+ cstate->off_linktype.constant_part = 6;
+ cstate->off_linkpl.constant_part = 12;
+ cstate->off_nl = 0;
+ cstate->off_nl_nosnap = -1; /* no 802.2 LLC */
+ break;
case DLT_JUNIPER_ES:
- off_linktype = 6;
- off_macpl = -1; /* not really a network layer but raw IP addresses */
- off_nl = -1; /* not really a network layer but raw IP addresses */
- off_nl_nosnap = -1; /* no 802.2 LLC */
- return;
+ cstate->off_linktype.constant_part = 6;
+ cstate->off_linkpl.constant_part = OFFSET_NOT_SET; /* not really a network layer but raw IP addresses */
+ cstate->off_nl = -1; /* not really a network layer but raw IP addresses */
+ cstate->off_nl_nosnap = -1; /* no 802.2 LLC */
+ break;
case DLT_JUNIPER_MONITOR:
- off_linktype = 12;
- off_macpl = 12;
- off_nl = 0; /* raw IP/IP6 header */
- off_nl_nosnap = -1; /* no 802.2 LLC */
- return;
+ cstate->off_linktype.constant_part = 12;
+ cstate->off_linkpl.constant_part = 12;
+ cstate->off_nl = 0; /* raw IP/IP6 header */
+ cstate->off_nl_nosnap = -1; /* no 802.2 LLC */
+ break;
case DLT_BACNET_MS_TP:
- off_linktype = -1;
- off_macpl = -1;
- off_nl = -1;
- off_nl_nosnap = -1;
- return;
+ cstate->off_linktype.constant_part = OFFSET_NOT_SET;
+ cstate->off_linkpl.constant_part = OFFSET_NOT_SET;
+ cstate->off_nl = -1;
+ cstate->off_nl_nosnap = -1;
+ break;
case DLT_JUNIPER_SERVICES:
- off_linktype = 12;
- off_macpl = -1; /* L3 proto location dep. on cookie type */
- off_nl = -1; /* L3 proto location dep. on cookie type */
- off_nl_nosnap = -1; /* no 802.2 LLC */
- return;
+ cstate->off_linktype.constant_part = 12;
+ cstate->off_linkpl.constant_part = OFFSET_NOT_SET; /* L3 proto location dep. on cookie type */
+ cstate->off_nl = -1; /* L3 proto location dep. on cookie type */
+ cstate->off_nl_nosnap = -1; /* no 802.2 LLC */
+ break;
case DLT_JUNIPER_VP:
- off_linktype = 18;
- off_macpl = -1;
- off_nl = -1;
- off_nl_nosnap = -1;
- return;
+ cstate->off_linktype.constant_part = 18;
+ cstate->off_linkpl.constant_part = OFFSET_NOT_SET;
+ cstate->off_nl = -1;
+ cstate->off_nl_nosnap = -1;
+ break;
case DLT_JUNIPER_ST:
- off_linktype = 18;
- off_macpl = -1;
- off_nl = -1;
- off_nl_nosnap = -1;
- return;
+ cstate->off_linktype.constant_part = 18;
+ cstate->off_linkpl.constant_part = OFFSET_NOT_SET;
+ cstate->off_nl = -1;
+ cstate->off_nl_nosnap = -1;
+ break;
case DLT_JUNIPER_ISM:
- off_linktype = 8;
- off_macpl = -1;
- off_nl = -1;
- off_nl_nosnap = -1;
- return;
+ cstate->off_linktype.constant_part = 8;
+ cstate->off_linkpl.constant_part = OFFSET_NOT_SET;
+ cstate->off_nl = -1;
+ cstate->off_nl_nosnap = -1;
+ break;
case DLT_JUNIPER_VS:
case DLT_JUNIPER_SRX_E2E:
case DLT_JUNIPER_FIBRECHANNEL:
case DLT_JUNIPER_ATM_CEMIC:
- off_linktype = 8;
- off_macpl = -1;
- off_nl = -1;
- off_nl_nosnap = -1;
- return;
+ cstate->off_linktype.constant_part = 8;
+ cstate->off_linkpl.constant_part = OFFSET_NOT_SET;
+ cstate->off_nl = -1;
+ cstate->off_nl_nosnap = -1;
+ break;
case DLT_MTP2:
- off_li = 2;
- off_li_hsl = 4;
- off_sio = 3;
- off_opc = 4;
- off_dpc = 4;
- off_sls = 7;
- off_linktype = -1;
- off_macpl = -1;
- off_nl = -1;
- off_nl_nosnap = -1;
- return;
+ cstate->off_li = 2;
+ cstate->off_li_hsl = 4;
+ cstate->off_sio = 3;
+ cstate->off_opc = 4;
+ cstate->off_dpc = 4;
+ cstate->off_sls = 7;
+ cstate->off_linktype.constant_part = OFFSET_NOT_SET;
+ cstate->off_linkpl.constant_part = OFFSET_NOT_SET;
+ cstate->off_nl = -1;
+ cstate->off_nl_nosnap = -1;
+ break;
case DLT_MTP2_WITH_PHDR:
- off_li = 6;
- off_li_hsl = 8;
- off_sio = 7;
- off_opc = 8;
- off_dpc = 8;
- off_sls = 11;
- off_linktype = -1;
- off_macpl = -1;
- off_nl = -1;
- off_nl_nosnap = -1;
- return;
+ cstate->off_li = 6;
+ cstate->off_li_hsl = 8;
+ cstate->off_sio = 7;
+ cstate->off_opc = 8;
+ cstate->off_dpc = 8;
+ cstate->off_sls = 11;
+ cstate->off_linktype.constant_part = OFFSET_NOT_SET;
+ cstate->off_linkpl.constant_part = OFFSET_NOT_SET;
+ cstate->off_nl = -1;
+ cstate->off_nl_nosnap = -1;
+ break;
case DLT_ERF:
- off_li = 22;
- off_li_hsl = 24;
- off_sio = 23;
- off_opc = 24;
- off_dpc = 24;
- off_sls = 27;
- off_linktype = -1;
- off_macpl = -1;
- off_nl = -1;
- off_nl_nosnap = -1;
- return;
+ cstate->off_li = 22;
+ cstate->off_li_hsl = 24;
+ cstate->off_sio = 23;
+ cstate->off_opc = 24;
+ cstate->off_dpc = 24;
+ cstate->off_sls = 27;
+ cstate->off_linktype.constant_part = OFFSET_NOT_SET;
+ cstate->off_linkpl.constant_part = OFFSET_NOT_SET;
+ cstate->off_nl = -1;
+ cstate->off_nl_nosnap = -1;
+ break;
case DLT_PFSYNC:
- off_linktype = -1;
- off_macpl = 4;
- off_nl = 0;
- off_nl_nosnap = 0;
- return;
+ cstate->off_linktype.constant_part = OFFSET_NOT_SET;
+ cstate->off_linkpl.constant_part = 4;
+ cstate->off_nl = 0;
+ cstate->off_nl_nosnap = 0;
+ break;
case DLT_AX25_KISS:
/*
* Currently, only raw "link[N:M]" filtering is supported.
*/
- off_linktype = -1; /* variable, min 15, max 71 steps of 7 */
- off_macpl = -1;
- off_nl = -1; /* variable, min 16, max 71 steps of 7 */
- off_nl_nosnap = -1; /* no 802.2 LLC */
- off_mac = 1; /* step over the kiss length byte */
- return;
+ cstate->off_linktype.constant_part = OFFSET_NOT_SET; /* variable, min 15, max 71 steps of 7 */
+ cstate->off_linkpl.constant_part = OFFSET_NOT_SET;
+ cstate->off_nl = -1; /* variable, min 16, max 71 steps of 7 */
+ cstate->off_nl_nosnap = -1; /* no 802.2 LLC */
+ break;
case DLT_IPNET:
- off_linktype = 1;
- off_macpl = 24; /* ipnet header length */
- off_nl = 0;
- off_nl_nosnap = -1;
- return;
+ cstate->off_linktype.constant_part = 1;
+ cstate->off_linkpl.constant_part = 24; /* ipnet header length */
+ cstate->off_nl = 0;
+ cstate->off_nl_nosnap = -1;
+ break;
case DLT_NETANALYZER:
- off_mac = 4; /* MAC header is past 4-byte pseudo-header */
- off_linktype = 16; /* includes 4-byte pseudo-header */
- off_macpl = 18; /* pseudo-header+Ethernet header length */
- off_nl = 0; /* Ethernet II */
- off_nl_nosnap = 3; /* 802.3+802.2 */
- return;
+ cstate->off_linkhdr.constant_part = 4; /* Ethernet header is past 4-byte pseudo-header */
+ cstate->off_linktype.constant_part = cstate->off_linkhdr.constant_part + 12;
+ cstate->off_linkpl.constant_part = cstate->off_linkhdr.constant_part + 14; /* pseudo-header+Ethernet header length */
+ cstate->off_nl = 0; /* Ethernet II */
+ cstate->off_nl_nosnap = 3; /* 802.3+802.2 */
+ break;
case DLT_NETANALYZER_TRANSPARENT:
- off_mac = 12; /* MAC header is past 4-byte pseudo-header, preamble, and SFD */
- off_linktype = 24; /* includes 4-byte pseudo-header+preamble+SFD */
- off_macpl = 26; /* pseudo-header+preamble+SFD+Ethernet header length */
- off_nl = 0; /* Ethernet II */
- off_nl_nosnap = 3; /* 802.3+802.2 */
- return;
+ cstate->off_linkhdr.constant_part = 12; /* MAC header is past 4-byte pseudo-header, preamble, and SFD */
+ cstate->off_linktype.constant_part = cstate->off_linkhdr.constant_part + 12;
+ cstate->off_linkpl.constant_part = cstate->off_linkhdr.constant_part + 14; /* pseudo-header+preamble+SFD+Ethernet header length */
+ cstate->off_nl = 0; /* Ethernet II */
+ cstate->off_nl_nosnap = 3; /* 802.3+802.2 */
+ break;
default:
/*
* For values in the range in which we've assigned new
* DLT_ values, only raw "link[N:M]" filtering is supported.
*/
- if (linktype >= DLT_MATCHING_MIN &&
- linktype <= DLT_MATCHING_MAX) {
- off_linktype = -1;
- off_macpl = -1;
- off_nl = -1;
- off_nl_nosnap = -1;
- return;
+ if (cstate->linktype >= DLT_MATCHING_MIN &&
+ cstate->linktype <= DLT_MATCHING_MAX) {
+ cstate->off_linktype.constant_part = OFFSET_NOT_SET;
+ cstate->off_linkpl.constant_part = OFFSET_NOT_SET;
+ cstate->off_nl = -1;
+ cstate->off_nl_nosnap = -1;
+ } else {
+ bpf_error(cstate, "unknown data link type %d", cstate->linktype);
}
-
+ break;
}
- bpf_error("unknown data link type %d", linktype);
- /* NOTREACHED */
-}
-
-/*
- * Load a value relative to the beginning of the link-layer header.
- * The link-layer header doesn't necessarily begin at the beginning
- * of the packet data; there might be a variable-length prefix containing
- * radio information.
- */
-static struct slist *
-gen_load_llrel(offset, size)
- u_int offset, size;
-{
- struct slist *s, *s2;
-
- s = gen_llprefixlen();
- /*
- * If "s" is non-null, it has code to arrange that the X register
- * contains the length of the prefix preceding the link-layer
- * header.
- *
- * Otherwise, the length of the prefix preceding the link-layer
- * header is "off_ll".
- */
- if (s != NULL) {
- /*
- * There's a variable-length prefix preceding the
- * link-layer header. "s" points to a list of statements
- * that put the length of that prefix into the X register.
- * do an indirect load, to use the X register as an offset.
- */
- s2 = new_stmt(BPF_LD|BPF_IND|size);
- s2->s.k = offset;
- sappend(s, s2);
- } else {
- /*
- * There is no variable-length header preceding the
- * link-layer header; add in off_ll, which, if there's
- * a fixed-length header preceding the link-layer header,
- * is the length of that header.
- */
- s = new_stmt(BPF_LD|BPF_ABS|size);
- s->s.k = offset + off_ll;
- }
- return s;
+ cstate->off_outermostlinkhdr = cstate->off_prevlinkhdr = cstate->off_linkhdr;
}
/*
- * Load a value relative to the beginning of the MAC-layer payload.
+ * Load a value relative to the specified absolute offset.
*/
static struct slist *
-gen_load_macplrel(offset, size)
- u_int offset, size;
+gen_load_absoffsetrel(compiler_state_t *cstate, bpf_abs_offset *abs_offset,
+ u_int offset, u_int size)
{
struct slist *s, *s2;
- s = gen_off_macpl();
+ s = gen_abs_offset_varpart(cstate, abs_offset);
/*
- * If s is non-null, the offset of the MAC-layer payload is
- * variable, and s points to a list of instructions that
- * arrange that the X register contains that offset.
+ * If "s" is non-null, it has code to arrange that the X register
+ * contains the variable part of the absolute offset, so we
+ * generate a load relative to that, with an offset of
+ * abs_offset->constant_part + offset.
*
- * Otherwise, the offset of the MAC-layer payload is constant,
- * and is in off_macpl.
+ * Otherwise, we can do an absolute load with an offset of
+ * abs_offset->constant_part + offset.
*/
if (s != NULL) {
/*
- * The offset of the MAC-layer payload is in the X
- * register. Do an indirect load, to use the X register
- * as an offset.
+ * "s" points to a list of statements that puts the
+ * variable part of the absolute offset into the X register.
+ * Do an indirect load, to use the X register as an offset.
*/
- s2 = new_stmt(BPF_LD|BPF_IND|size);
- s2->s.k = offset;
+ s2 = new_stmt(cstate, BPF_LD|BPF_IND|size);
+ s2->s.k = abs_offset->constant_part + offset;
sappend(s, s2);
} else {
/*
- * The offset of the MAC-layer payload is constant,
- * and is in off_macpl; load the value at that offset
- * plus the specified offset.
+ * There is no variable part of the absolute offset, so
+ * just do an absolute load.
*/
- s = new_stmt(BPF_LD|BPF_ABS|size);
- s->s.k = off_macpl + offset;
+ s = new_stmt(cstate, BPF_LD|BPF_ABS|size);
+ s->s.k = abs_offset->constant_part + offset;
}
return s;
}
@@ -1571,33 +1648,44 @@ gen_load_macplrel(offset, size)
* Load a value relative to the beginning of the specified header.
*/
static struct slist *
-gen_load_a(offrel, offset, size)
- enum e_offrel offrel;
- u_int offset, size;
+gen_load_a(compiler_state_t *cstate, enum e_offrel offrel, u_int offset,
+ u_int size)
{
struct slist *s, *s2;
switch (offrel) {
case OR_PACKET:
- s = new_stmt(BPF_LD|BPF_ABS|size);
+ s = new_stmt(cstate, BPF_LD|BPF_ABS|size);
s->s.k = offset;
break;
- case OR_LINK:
- s = gen_load_llrel(offset, size);
+ case OR_LINKHDR:
+ s = gen_load_absoffsetrel(cstate, &cstate->off_linkhdr, offset, size);
break;
- case OR_MACPL:
- s = gen_load_macplrel(offset, size);
+ case OR_PREVLINKHDR:
+ s = gen_load_absoffsetrel(cstate, &cstate->off_prevlinkhdr, offset, size);
break;
- case OR_NET:
- s = gen_load_macplrel(off_nl + offset, size);
+ case OR_LLC:
+ s = gen_load_absoffsetrel(cstate, &cstate->off_linkpl, offset, size);
break;
- case OR_NET_NOSNAP:
- s = gen_load_macplrel(off_nl_nosnap + offset, size);
+ case OR_PREVMPLSHDR:
+ s = gen_load_absoffsetrel(cstate, &cstate->off_linkpl, cstate->off_nl - 4 + offset, size);
+ break;
+
+ case OR_LINKPL:
+ s = gen_load_absoffsetrel(cstate, &cstate->off_linkpl, cstate->off_nl + offset, size);
+ break;
+
+ case OR_LINKPL_NOSNAP:
+ s = gen_load_absoffsetrel(cstate, &cstate->off_linkpl, cstate->off_nl_nosnap + offset, size);
+ break;
+
+ case OR_LINKTYPE:
+ s = gen_load_absoffsetrel(cstate, &cstate->off_linktype, offset, size);
break;
case OR_TRAN_IPV4:
@@ -1607,25 +1695,26 @@ gen_load_a(offrel, offset, size)
* preceded by a variable-length header such as a radio
* header), in bytes.
*/
- s = gen_loadx_iphdrlen();
+ s = gen_loadx_iphdrlen(cstate);
/*
- * Load the item at {offset of the MAC-layer payload} +
- * {offset, relative to the start of the MAC-layer
+ * Load the item at {offset of the link-layer payload} +
+ * {offset, relative to the start of the link-layer
* paylod, of the IPv4 header} + {length of the IPv4 header} +
* {specified offset}.
*
- * (If the offset of the MAC-layer payload is variable,
- * it's included in the value in the X register, and
- * off_macpl is 0.)
+ * If the offset of the link-layer payload is variable,
+ * the variable part of that offset is included in the
+ * value in the X register, and we include the constant
+ * part in the offset of the load.
*/
- s2 = new_stmt(BPF_LD|BPF_IND|size);
- s2->s.k = off_macpl + off_nl + offset;
+ s2 = new_stmt(cstate, BPF_LD|BPF_IND|size);
+ s2->s.k = cstate->off_linkpl.constant_part + cstate->off_nl + offset;
sappend(s, s2);
break;
case OR_TRAN_IPV6:
- s = gen_load_macplrel(off_nl + 40 + offset, size);
+ s = gen_load_absoffsetrel(cstate, &cstate->off_linkpl, cstate->off_nl + 40 + offset, size);
break;
default:
@@ -1637,87 +1726,87 @@ gen_load_a(offrel, offset, size)
/*
* Generate code to load into the X register the sum of the length of
- * the IPv4 header and any variable-length header preceding the link-layer
- * header.
+ * the IPv4 header and the variable part of the offset of the link-layer
+ * payload.
*/
static struct slist *
-gen_loadx_iphdrlen()
+gen_loadx_iphdrlen(compiler_state_t *cstate)
{
struct slist *s, *s2;
- s = gen_off_macpl();
+ s = gen_abs_offset_varpart(cstate, &cstate->off_linkpl);
if (s != NULL) {
/*
- * There's a variable-length prefix preceding the
- * link-layer header, or the link-layer header is itself
- * variable-length. "s" points to a list of statements
- * that put the offset of the MAC-layer payload into
- * the X register.
+ * The offset of the link-layer payload has a variable
+ * part. "s" points to a list of statements that put
+ * the variable part of that offset into the X register.
*
* The 4*([k]&0xf) addressing mode can't be used, as we
* don't have a constant offset, so we have to load the
* value in question into the A register and add to it
* the value from the X register.
*/
- s2 = new_stmt(BPF_LD|BPF_IND|BPF_B);
- s2->s.k = off_nl;
+ s2 = new_stmt(cstate, BPF_LD|BPF_IND|BPF_B);
+ s2->s.k = cstate->off_linkpl.constant_part + cstate->off_nl;
sappend(s, s2);
- s2 = new_stmt(BPF_ALU|BPF_AND|BPF_K);
+ s2 = new_stmt(cstate, BPF_ALU|BPF_AND|BPF_K);
s2->s.k = 0xf;
sappend(s, s2);
- s2 = new_stmt(BPF_ALU|BPF_LSH|BPF_K);
+ s2 = new_stmt(cstate, BPF_ALU|BPF_LSH|BPF_K);
s2->s.k = 2;
sappend(s, s2);
/*
- * The A register now contains the length of the
- * IP header. We need to add to it the offset of
- * the MAC-layer payload, which is still in the X
+ * The A register now contains the length of the IP header.
+ * We need to add to it the variable part of the offset of
+ * the link-layer payload, which is still in the X
* register, and move the result into the X register.
*/
- sappend(s, new_stmt(BPF_ALU|BPF_ADD|BPF_X));
- sappend(s, new_stmt(BPF_MISC|BPF_TAX));
+ sappend(s, new_stmt(cstate, BPF_ALU|BPF_ADD|BPF_X));
+ sappend(s, new_stmt(cstate, BPF_MISC|BPF_TAX));
} else {
/*
- * There is no variable-length header preceding the
- * link-layer header, and the link-layer header is
- * fixed-length; load the length of the IPv4 header,
- * which is at an offset of off_nl from the beginning
- * of the MAC-layer payload, and thus at an offset
- * of off_mac_pl + off_nl from the beginning of the
- * raw packet data.
- */
- s = new_stmt(BPF_LDX|BPF_MSH|BPF_B);
- s->s.k = off_macpl + off_nl;
+ * The offset of the link-layer payload is a constant,
+ * so no code was generated to load the (non-existent)
+ * variable part of that offset.
+ *
+ * This means we can use the 4*([k]&0xf) addressing
+ * mode. Load the length of the IPv4 header, which
+ * is at an offset of cstate->off_nl from the beginning of
+ * the link-layer payload, and thus at an offset of
+ * cstate->off_linkpl.constant_part + cstate->off_nl from the beginning
+ * of the raw packet data, using that addressing mode.
+ */
+ s = new_stmt(cstate, BPF_LDX|BPF_MSH|BPF_B);
+ s->s.k = cstate->off_linkpl.constant_part + cstate->off_nl;
}
return s;
}
static struct block *
-gen_uncond(rsense)
- int rsense;
+gen_uncond(compiler_state_t *cstate, int rsense)
{
struct block *b;
struct slist *s;
- s = new_stmt(BPF_LD|BPF_IMM);
+ s = new_stmt(cstate, BPF_LD|BPF_IMM);
s->s.k = !rsense;
- b = new_block(JMP(BPF_JEQ));
+ b = new_block(cstate, JMP(BPF_JEQ));
b->stmts = s;
return b;
}
static inline struct block *
-gen_true()
+gen_true(compiler_state_t *cstate)
{
- return gen_uncond(1);
+ return gen_uncond(cstate, 1);
}
static inline struct block *
-gen_false()
+gen_false(compiler_state_t *cstate)
{
- return gen_uncond(0);
+ return gen_uncond(cstate, 0);
}
/*
@@ -1738,8 +1827,7 @@ gen_false()
* the appropriate test.
*/
static struct block *
-gen_ether_linktype(proto)
- register int proto;
+gen_ether_linktype(compiler_state_t *cstate, int proto)
{
struct block *b0, *b1;
@@ -1760,9 +1848,9 @@ gen_ether_linktype(proto)
* DSAP, as we do for other types <= ETHERMTU
* (i.e., other SAP values)?
*/
- b0 = gen_cmp_gt(OR_LINK, off_linktype, BPF_H, ETHERMTU);
+ b0 = gen_cmp_gt(cstate, OR_LINKTYPE, 0, BPF_H, ETHERMTU);
gen_not(b0);
- b1 = gen_cmp(OR_MACPL, 0, BPF_H, (bpf_int32)
+ b1 = gen_cmp(cstate, OR_LLC, 0, BPF_H, (bpf_int32)
((proto << 8) | proto));
gen_and(b0, b1);
return b1;
@@ -1800,22 +1888,22 @@ gen_ether_linktype(proto)
* This generates code to check both for the
* IPX LSAP (Ethernet_802.2) and for Ethernet_802.3.
*/
- b0 = gen_cmp(OR_MACPL, 0, BPF_B, (bpf_int32)LLCSAP_IPX);
- b1 = gen_cmp(OR_MACPL, 0, BPF_H, (bpf_int32)0xFFFF);
+ b0 = gen_cmp(cstate, OR_LLC, 0, BPF_B, (bpf_int32)LLCSAP_IPX);
+ b1 = gen_cmp(cstate, OR_LLC, 0, BPF_H, (bpf_int32)0xFFFF);
gen_or(b0, b1);
/*
* Now we add code to check for SNAP frames with
* ETHERTYPE_IPX, i.e. Ethernet_SNAP.
*/
- b0 = gen_snap(0x000000, ETHERTYPE_IPX);
+ b0 = gen_snap(cstate, 0x000000, ETHERTYPE_IPX);
gen_or(b0, b1);
/*
* Now we generate code to check for 802.3
* frames in general.
*/
- b0 = gen_cmp_gt(OR_LINK, off_linktype, BPF_H, ETHERMTU);
+ b0 = gen_cmp_gt(cstate, OR_LINKTYPE, 0, BPF_H, ETHERMTU);
gen_not(b0);
/*
@@ -1831,8 +1919,7 @@ gen_ether_linktype(proto)
* do that before checking for the other frame
* types.
*/
- b0 = gen_cmp(OR_LINK, off_linktype, BPF_H,
- (bpf_int32)ETHERTYPE_IPX);
+ b0 = gen_cmp(cstate, OR_LINKTYPE, 0, BPF_H, (bpf_int32)ETHERTYPE_IPX);
gen_or(b0, b1);
return b1;
@@ -1848,7 +1935,7 @@ gen_ether_linktype(proto)
* we check for an Ethernet type field less than
* 1500, which means it's an 802.3 length field.
*/
- b0 = gen_cmp_gt(OR_LINK, off_linktype, BPF_H, ETHERMTU);
+ b0 = gen_cmp_gt(cstate, OR_LINKTYPE, 0, BPF_H, ETHERMTU);
gen_not(b0);
/*
@@ -1863,9 +1950,9 @@ gen_ether_linktype(proto)
* type of ETHERTYPE_AARP (Appletalk ARP).
*/
if (proto == ETHERTYPE_ATALK)
- b1 = gen_snap(0x080007, ETHERTYPE_ATALK);
+ b1 = gen_snap(cstate, 0x080007, ETHERTYPE_ATALK);
else /* proto == ETHERTYPE_AARP */
- b1 = gen_snap(0x000000, ETHERTYPE_AARP);
+ b1 = gen_snap(cstate, 0x000000, ETHERTYPE_AARP);
gen_and(b0, b1);
/*
@@ -1873,7 +1960,7 @@ gen_ether_linktype(proto)
* phase 1?); we just check for the Ethernet
* protocol type.
*/
- b0 = gen_cmp(OR_LINK, off_linktype, BPF_H, (bpf_int32)proto);
+ b0 = gen_cmp(cstate, OR_LINKTYPE, 0, BPF_H, (bpf_int32)proto);
gen_or(b0, b1);
return b1;
@@ -1888,10 +1975,9 @@ gen_ether_linktype(proto)
* a length field, <= ETHERMTU) and
* then check the DSAP.
*/
- b0 = gen_cmp_gt(OR_LINK, off_linktype, BPF_H, ETHERMTU);
+ b0 = gen_cmp_gt(cstate, OR_LINKTYPE, 0, BPF_H, ETHERMTU);
gen_not(b0);
- b1 = gen_cmp(OR_LINK, off_linktype + 2, BPF_B,
- (bpf_int32)proto);
+ b1 = gen_cmp(cstate, OR_LINKTYPE, 2, BPF_B, (bpf_int32)proto);
gen_and(b0, b1);
return b1;
} else {
@@ -1904,29 +1990,62 @@ gen_ether_linktype(proto)
* will fail and the frame won't match,
* which is what we want).
*/
- return gen_cmp(OR_LINK, off_linktype, BPF_H,
+ return gen_cmp(cstate, OR_LINKTYPE, 0, BPF_H,
(bpf_int32)proto);
}
}
}
+static struct block *
+gen_loopback_linktype(compiler_state_t *cstate, int proto)
+{
+ /*
+ * For DLT_NULL, the link-layer header is a 32-bit word
+ * containing an AF_ value in *host* byte order, and for
+ * DLT_ENC, the link-layer header begins with a 32-bit
+ * word containing an AF_ value in host byte order.
+ *
+ * In addition, if we're reading a saved capture file,
+ * the host byte order in the capture may not be the
+ * same as the host byte order on this machine.
+ *
+ * For DLT_LOOP, the link-layer header is a 32-bit
+ * word containing an AF_ value in *network* byte order.
+ */
+ if (cstate->linktype == DLT_NULL || cstate->linktype == DLT_ENC) {
+ /*
+ * The AF_ value is in host byte order, but the BPF
+ * interpreter will convert it to network byte order.
+ *
+ * If this is a save file, and it's from a machine
+ * with the opposite byte order to ours, we byte-swap
+ * the AF_ value.
+ *
+ * Then we run it through "htonl()", and generate
+ * code to compare against the result.
+ */
+ if (cstate->bpf_pcap->rfile != NULL && cstate->bpf_pcap->swapped)
+ proto = SWAPLONG(proto);
+ proto = htonl(proto);
+ }
+ return (gen_cmp(cstate, OR_LINKHDR, 0, BPF_W, (bpf_int32)proto));
+}
+
/*
* "proto" is an Ethernet type value and for IPNET, if it is not IPv4
* or IPv6 then we have an error.
*/
static struct block *
-gen_ipnet_linktype(proto)
- register int proto;
+gen_ipnet_linktype(compiler_state_t *cstate, int proto)
{
switch (proto) {
case ETHERTYPE_IP:
- return gen_cmp(OR_LINK, off_linktype, BPF_B,
- (bpf_int32)IPH_AF_INET);
+ return gen_cmp(cstate, OR_LINKTYPE, 0, BPF_B, (bpf_int32)IPH_AF_INET);
/* NOTREACHED */
case ETHERTYPE_IPV6:
- return gen_cmp(OR_LINK, off_linktype, BPF_B,
+ return gen_cmp(cstate, OR_LINKTYPE, 0, BPF_B,
(bpf_int32)IPH_AF_INET6);
/* NOTREACHED */
@@ -1934,7 +2053,7 @@ gen_ipnet_linktype(proto)
break;
}
- return gen_false();
+ return gen_false(cstate);
}
/*
@@ -1946,8 +2065,7 @@ gen_ipnet_linktype(proto)
* LINUX_SLL_P_802_2 value and then do the appropriate test.
*/
static struct block *
-gen_linux_sll_linktype(proto)
- register int proto;
+gen_linux_sll_linktype(compiler_state_t *cstate, int proto)
{
struct block *b0, *b1;
@@ -1968,8 +2086,8 @@ gen_linux_sll_linktype(proto)
* DSAP, as we do for other types <= ETHERMTU
* (i.e., other SAP values)?
*/
- b0 = gen_cmp(OR_LINK, off_linktype, BPF_H, LINUX_SLL_P_802_2);
- b1 = gen_cmp(OR_MACPL, 0, BPF_H, (bpf_int32)
+ b0 = gen_cmp(cstate, OR_LINKTYPE, 0, BPF_H, LINUX_SLL_P_802_2);
+ b1 = gen_cmp(cstate, OR_LLC, 0, BPF_H, (bpf_int32)
((proto << 8) | proto));
gen_and(b0, b1);
return b1;
@@ -2000,17 +2118,17 @@ gen_linux_sll_linktype(proto)
* then put a check for LINUX_SLL_P_802_2 frames
* before it.
*/
- b0 = gen_cmp(OR_MACPL, 0, BPF_B, (bpf_int32)LLCSAP_IPX);
- b1 = gen_snap(0x000000, ETHERTYPE_IPX);
+ b0 = gen_cmp(cstate, OR_LLC, 0, BPF_B, (bpf_int32)LLCSAP_IPX);
+ b1 = gen_snap(cstate, 0x000000, ETHERTYPE_IPX);
gen_or(b0, b1);
- b0 = gen_cmp(OR_LINK, off_linktype, BPF_H, LINUX_SLL_P_802_2);
+ b0 = gen_cmp(cstate, OR_LINKTYPE, 0, BPF_H, LINUX_SLL_P_802_2);
gen_and(b0, b1);
/*
* Now check for 802.3 frames and OR that with
* the previous test.
*/
- b0 = gen_cmp(OR_LINK, off_linktype, BPF_H, LINUX_SLL_P_802_3);
+ b0 = gen_cmp(cstate, OR_LINKTYPE, 0, BPF_H, LINUX_SLL_P_802_3);
gen_or(b0, b1);
/*
@@ -2018,8 +2136,7 @@ gen_linux_sll_linktype(proto)
* do that before checking for the other frame
* types.
*/
- b0 = gen_cmp(OR_LINK, off_linktype, BPF_H,
- (bpf_int32)ETHERTYPE_IPX);
+ b0 = gen_cmp(cstate, OR_LINKTYPE, 0, BPF_H, (bpf_int32)ETHERTYPE_IPX);
gen_or(b0, b1);
return b1;
@@ -2035,7 +2152,7 @@ gen_linux_sll_linktype(proto)
* we check for the 802.2 protocol type in the
* "Ethernet type" field.
*/
- b0 = gen_cmp(OR_LINK, off_linktype, BPF_H, LINUX_SLL_P_802_2);
+ b0 = gen_cmp(cstate, OR_LINKTYPE, 0, BPF_H, LINUX_SLL_P_802_2);
/*
* 802.2-encapsulated ETHERTYPE_ATALK packets are
@@ -2049,9 +2166,9 @@ gen_linux_sll_linktype(proto)
* type of ETHERTYPE_AARP (Appletalk ARP).
*/
if (proto == ETHERTYPE_ATALK)
- b1 = gen_snap(0x080007, ETHERTYPE_ATALK);
+ b1 = gen_snap(cstate, 0x080007, ETHERTYPE_ATALK);
else /* proto == ETHERTYPE_AARP */
- b1 = gen_snap(0x000000, ETHERTYPE_AARP);
+ b1 = gen_snap(cstate, 0x000000, ETHERTYPE_AARP);
gen_and(b0, b1);
/*
@@ -2059,7 +2176,7 @@ gen_linux_sll_linktype(proto)
* phase 1?); we just check for the Ethernet
* protocol type.
*/
- b0 = gen_cmp(OR_LINK, off_linktype, BPF_H, (bpf_int32)proto);
+ b0 = gen_cmp(cstate, OR_LINKTYPE, 0, BPF_H, (bpf_int32)proto);
gen_or(b0, b1);
return b1;
@@ -2073,9 +2190,8 @@ gen_linux_sll_linktype(proto)
* in the "Ethernet type" field, and
* then check the DSAP.
*/
- b0 = gen_cmp(OR_LINK, off_linktype, BPF_H,
- LINUX_SLL_P_802_2);
- b1 = gen_cmp(OR_LINK, off_macpl, BPF_B,
+ b0 = gen_cmp(cstate, OR_LINKTYPE, 0, BPF_H, LINUX_SLL_P_802_2);
+ b1 = gen_cmp(cstate, OR_LINKHDR, cstate->off_linkpl.constant_part, BPF_B,
(bpf_int32)proto);
gen_and(b0, b1);
return b1;
@@ -2089,14 +2205,13 @@ gen_linux_sll_linktype(proto)
* will fail and the frame won't match,
* which is what we want).
*/
- return gen_cmp(OR_LINK, off_linktype, BPF_H,
- (bpf_int32)proto);
+ return gen_cmp(cstate, OR_LINKTYPE, 0, BPF_H, (bpf_int32)proto);
}
}
}
static struct slist *
-gen_load_prism_llprefixlen()
+gen_load_prism_llprefixlen(compiler_state_t *cstate)
{
struct slist *s1, *s2;
struct slist *sjeq_avs_cookie;
@@ -2107,7 +2222,7 @@ gen_load_prism_llprefixlen()
* we are generating jmp instructions within a normal
* slist of instructions
*/
- no_optimize = 1;
+ cstate->no_optimize = 1;
/*
* Generate code to load the length of the radio header into
@@ -2128,24 +2243,24 @@ gen_load_prism_llprefixlen()
* but no known software generates headers that aren't 144
* bytes long.
*/
- if (reg_off_ll != -1) {
+ if (cstate->off_linkhdr.reg != -1) {
/*
* Load the cookie.
*/
- s1 = new_stmt(BPF_LD|BPF_W|BPF_ABS);
+ s1 = new_stmt(cstate, BPF_LD|BPF_W|BPF_ABS);
s1->s.k = 0;
/*
* AND it with 0xFFFFF000.
*/
- s2 = new_stmt(BPF_ALU|BPF_AND|BPF_K);
+ s2 = new_stmt(cstate, BPF_ALU|BPF_AND|BPF_K);
s2->s.k = 0xFFFFF000;
sappend(s1, s2);
/*
* Compare with 0x80211000.
*/
- sjeq_avs_cookie = new_stmt(JMP(BPF_JEQ));
+ sjeq_avs_cookie = new_stmt(cstate, JMP(BPF_JEQ));
sjeq_avs_cookie->s.k = 0x80211000;
sappend(s1, sjeq_avs_cookie);
@@ -2156,7 +2271,7 @@ gen_load_prism_llprefixlen()
* the AVS header are the length of the AVS header.
* That field is big-endian.
*/
- s2 = new_stmt(BPF_LD|BPF_W|BPF_ABS);
+ s2 = new_stmt(cstate, BPF_LD|BPF_W|BPF_ABS);
s2->s.k = 4;
sappend(s1, s2);
sjeq_avs_cookie->s.jt = s2;
@@ -2169,7 +2284,7 @@ gen_load_prism_llprefixlen()
* it's added to the PC, so, as we're jumping
* over a single instruction, it should be 1.)
*/
- sjcommon = new_stmt(JMP(BPF_JA));
+ sjcommon = new_stmt(cstate, JMP(BPF_JA));
sjcommon->s.k = 1;
sappend(s1, sjcommon);
@@ -2179,7 +2294,7 @@ gen_load_prism_llprefixlen()
* into the A register. Have the test for an AVS
* header branch here if we don't have an AVS header.
*/
- s2 = new_stmt(BPF_LD|BPF_W|BPF_IMM);
+ s2 = new_stmt(cstate, BPF_LD|BPF_W|BPF_IMM);
s2->s.k = 144;
sappend(s1, s2);
sjeq_avs_cookie->s.jf = s2;
@@ -2189,15 +2304,15 @@ gen_load_prism_llprefixlen()
* it. The code for the AVS header will jump here after
* loading the length of the AVS header.
*/
- s2 = new_stmt(BPF_ST);
- s2->s.k = reg_off_ll;
+ s2 = new_stmt(cstate, BPF_ST);
+ s2->s.k = cstate->off_linkhdr.reg;
sappend(s1, s2);
sjcommon->s.jf = s2;
/*
* Now move it into the X register.
*/
- s2 = new_stmt(BPF_MISC|BPF_TAX);
+ s2 = new_stmt(cstate, BPF_MISC|BPF_TAX);
sappend(s1, s2);
return (s1);
@@ -2206,7 +2321,7 @@ gen_load_prism_llprefixlen()
}
static struct slist *
-gen_load_avs_llprefixlen()
+gen_load_avs_llprefixlen(compiler_state_t *cstate)
{
struct slist *s1, *s2;
@@ -2217,27 +2332,27 @@ gen_load_avs_llprefixlen()
* generated uses that prefix, so we don't need to generate any
* code to load it.)
*/
- if (reg_off_ll != -1) {
+ if (cstate->off_linkhdr.reg != -1) {
/*
* The 4 bytes at an offset of 4 from the beginning of
* the AVS header are the length of the AVS header.
* That field is big-endian.
*/
- s1 = new_stmt(BPF_LD|BPF_W|BPF_ABS);
+ s1 = new_stmt(cstate, BPF_LD|BPF_W|BPF_ABS);
s1->s.k = 4;
/*
* Now allocate a register to hold that value and store
* it.
*/
- s2 = new_stmt(BPF_ST);
- s2->s.k = reg_off_ll;
+ s2 = new_stmt(cstate, BPF_ST);
+ s2->s.k = cstate->off_linkhdr.reg;
sappend(s1, s2);
/*
* Now move it into the X register.
*/
- s2 = new_stmt(BPF_MISC|BPF_TAX);
+ s2 = new_stmt(cstate, BPF_MISC|BPF_TAX);
sappend(s1, s2);
return (s1);
@@ -2246,7 +2361,7 @@ gen_load_avs_llprefixlen()
}
static struct slist *
-gen_load_radiotap_llprefixlen()
+gen_load_radiotap_llprefixlen(compiler_state_t *cstate)
{
struct slist *s1, *s2;
@@ -2257,7 +2372,7 @@ gen_load_radiotap_llprefixlen()
* generated uses that prefix, so we don't need to generate any
* code to load it.)
*/
- if (reg_off_ll != -1) {
+ if (cstate->off_linkhdr.reg != -1) {
/*
* The 2 bytes at offsets of 2 and 3 from the beginning
* of the radiotap header are the length of the radiotap
@@ -2269,36 +2384,36 @@ gen_load_radiotap_llprefixlen()
* Load the high-order byte, at an offset of 3, shift it
* left a byte, and put the result in the X register.
*/
- s1 = new_stmt(BPF_LD|BPF_B|BPF_ABS);
+ s1 = new_stmt(cstate, BPF_LD|BPF_B|BPF_ABS);
s1->s.k = 3;
- s2 = new_stmt(BPF_ALU|BPF_LSH|BPF_K);
+ s2 = new_stmt(cstate, BPF_ALU|BPF_LSH|BPF_K);
sappend(s1, s2);
s2->s.k = 8;
- s2 = new_stmt(BPF_MISC|BPF_TAX);
+ s2 = new_stmt(cstate, BPF_MISC|BPF_TAX);
sappend(s1, s2);
/*
* Load the next byte, at an offset of 2, and OR the
* value from the X register into it.
*/
- s2 = new_stmt(BPF_LD|BPF_B|BPF_ABS);
+ s2 = new_stmt(cstate, BPF_LD|BPF_B|BPF_ABS);
sappend(s1, s2);
s2->s.k = 2;
- s2 = new_stmt(BPF_ALU|BPF_OR|BPF_X);
+ s2 = new_stmt(cstate, BPF_ALU|BPF_OR|BPF_X);
sappend(s1, s2);
/*
* Now allocate a register to hold that value and store
* it.
*/
- s2 = new_stmt(BPF_ST);
- s2->s.k = reg_off_ll;
+ s2 = new_stmt(cstate, BPF_ST);
+ s2->s.k = cstate->off_linkhdr.reg;
sappend(s1, s2);
/*
* Now move it into the X register.
*/
- s2 = new_stmt(BPF_MISC|BPF_TAX);
+ s2 = new_stmt(cstate, BPF_MISC|BPF_TAX);
sappend(s1, s2);
return (s1);
@@ -2316,7 +2431,7 @@ gen_load_radiotap_llprefixlen()
* that's done in finish_parse().
*/
static struct slist *
-gen_load_ppi_llprefixlen()
+gen_load_ppi_llprefixlen(compiler_state_t *cstate)
{
struct slist *s1, *s2;
@@ -2325,7 +2440,7 @@ gen_load_ppi_llprefixlen()
* into the register assigned to hold that length, if one has
* been assigned.
*/
- if (reg_off_ll != -1) {
+ if (cstate->off_linkhdr.reg != -1) {
/*
* The 2 bytes at offsets of 2 and 3 from the beginning
* of the radiotap header are the length of the radiotap
@@ -2337,36 +2452,36 @@ gen_load_ppi_llprefixlen()
* Load the high-order byte, at an offset of 3, shift it
* left a byte, and put the result in the X register.
*/
- s1 = new_stmt(BPF_LD|BPF_B|BPF_ABS);
+ s1 = new_stmt(cstate, BPF_LD|BPF_B|BPF_ABS);
s1->s.k = 3;
- s2 = new_stmt(BPF_ALU|BPF_LSH|BPF_K);
+ s2 = new_stmt(cstate, BPF_ALU|BPF_LSH|BPF_K);
sappend(s1, s2);
s2->s.k = 8;
- s2 = new_stmt(BPF_MISC|BPF_TAX);
+ s2 = new_stmt(cstate, BPF_MISC|BPF_TAX);
sappend(s1, s2);
/*
* Load the next byte, at an offset of 2, and OR the
* value from the X register into it.
*/
- s2 = new_stmt(BPF_LD|BPF_B|BPF_ABS);
+ s2 = new_stmt(cstate, BPF_LD|BPF_B|BPF_ABS);
sappend(s1, s2);
s2->s.k = 2;
- s2 = new_stmt(BPF_ALU|BPF_OR|BPF_X);
+ s2 = new_stmt(cstate, BPF_ALU|BPF_OR|BPF_X);
sappend(s1, s2);
/*
* Now allocate a register to hold that value and store
* it.
*/
- s2 = new_stmt(BPF_ST);
- s2->s.k = reg_off_ll;
+ s2 = new_stmt(cstate, BPF_ST);
+ s2->s.k = cstate->off_linkhdr.reg;
sappend(s1, s2);
/*
* Now move it into the X register.
*/
- s2 = new_stmt(BPF_MISC|BPF_TAX);
+ s2 = new_stmt(cstate, BPF_MISC|BPF_TAX);
sappend(s1, s2);
return (s1);
@@ -2382,21 +2497,22 @@ gen_load_ppi_llprefixlen()
* radio information.
*/
static struct slist *
-gen_load_802_11_header_len(struct slist *s, struct slist *snext)
+gen_load_802_11_header_len(compiler_state_t *cstate, struct slist *s, struct slist *snext)
{
struct slist *s2;
struct slist *sjset_data_frame_1;
struct slist *sjset_data_frame_2;
struct slist *sjset_qos;
- struct slist *sjset_radiotap_flags;
- struct slist *sjset_radiotap_tsft;
+ struct slist *sjset_radiotap_flags_present;
+ struct slist *sjset_radiotap_ext_present;
+ struct slist *sjset_radiotap_tsft_present;
struct slist *sjset_tsft_datapad, *sjset_notsft_datapad;
struct slist *s_roundup;
- if (reg_off_macpl == -1) {
+ if (cstate->off_linkpl.reg == -1) {
/*
* No register has been assigned to the offset of
- * the MAC-layer payload, which means nobody needs
+ * the link-layer payload, which means nobody needs
* it; don't bother computing it - just return
* what we already have.
*/
@@ -2408,7 +2524,7 @@ gen_load_802_11_header_len(struct slist *s, struct slist *snext)
* we are generating jmp instructions within a normal
* slist of instructions
*/
- no_optimize = 1;
+ cstate->no_optimize = 1;
/*
* If "s" is non-null, it has code to arrange that the X register
@@ -2416,7 +2532,7 @@ gen_load_802_11_header_len(struct slist *s, struct slist *snext)
* header.
*
* Otherwise, the length of the prefix preceding the link-layer
- * header is "off_ll".
+ * header is "off_outermostlinkhdr.constant_part".
*/
if (s == NULL) {
/*
@@ -2425,30 +2541,30 @@ gen_load_802_11_header_len(struct slist *s, struct slist *snext)
*
* Load the length of the fixed-length prefix preceding
* the link-layer header (if any) into the X register,
- * and store it in the reg_off_macpl register.
- * That length is off_ll.
+ * and store it in the cstate->off_linkpl.reg register.
+ * That length is off_outermostlinkhdr.constant_part.
*/
- s = new_stmt(BPF_LDX|BPF_IMM);
- s->s.k = off_ll;
+ s = new_stmt(cstate, BPF_LDX|BPF_IMM);
+ s->s.k = cstate->off_outermostlinkhdr.constant_part;
}
/*
* The X register contains the offset of the beginning of the
* link-layer header; add 24, which is the minimum length
* of the MAC header for a data frame, to that, and store it
- * in reg_off_macpl, and then load the Frame Control field,
+ * in cstate->off_linkpl.reg, and then load the Frame Control field,
* which is at the offset in the X register, with an indexed load.
*/
- s2 = new_stmt(BPF_MISC|BPF_TXA);
+ s2 = new_stmt(cstate, BPF_MISC|BPF_TXA);
sappend(s, s2);
- s2 = new_stmt(BPF_ALU|BPF_ADD|BPF_K);
+ s2 = new_stmt(cstate, BPF_ALU|BPF_ADD|BPF_K);
s2->s.k = 24;
sappend(s, s2);
- s2 = new_stmt(BPF_ST);
- s2->s.k = reg_off_macpl;
+ s2 = new_stmt(cstate, BPF_ST);
+ s2->s.k = cstate->off_linkpl.reg;
sappend(s, s2);
- s2 = new_stmt(BPF_LD|BPF_IND|BPF_B);
+ s2 = new_stmt(cstate, BPF_LD|BPF_IND|BPF_B);
s2->s.k = 0;
sappend(s, s2);
@@ -2457,7 +2573,7 @@ gen_load_802_11_header_len(struct slist *s, struct slist *snext)
* a data frame has the 0x08 bit (b3) in that field set and the
* 0x04 bit (b2) clear.
*/
- sjset_data_frame_1 = new_stmt(JMP(BPF_JSET));
+ sjset_data_frame_1 = new_stmt(cstate, JMP(BPF_JSET));
sjset_data_frame_1->s.k = 0x08;
sappend(s, sjset_data_frame_1);
@@ -2465,7 +2581,7 @@ gen_load_802_11_header_len(struct slist *s, struct slist *snext)
* If b3 is set, test b2, otherwise go to the first statement of
* the rest of the program.
*/
- sjset_data_frame_1->s.jt = sjset_data_frame_2 = new_stmt(JMP(BPF_JSET));
+ sjset_data_frame_1->s.jt = sjset_data_frame_2 = new_stmt(cstate, JMP(BPF_JSET));
sjset_data_frame_2->s.k = 0x04;
sappend(s, sjset_data_frame_2);
sjset_data_frame_1->s.jf = snext;
@@ -2476,24 +2592,24 @@ gen_load_802_11_header_len(struct slist *s, struct slist *snext)
* program.
*/
sjset_data_frame_2->s.jt = snext;
- sjset_data_frame_2->s.jf = sjset_qos = new_stmt(JMP(BPF_JSET));
+ sjset_data_frame_2->s.jf = sjset_qos = new_stmt(cstate, JMP(BPF_JSET));
sjset_qos->s.k = 0x80; /* QoS bit */
sappend(s, sjset_qos);
/*
- * If it's set, add 2 to reg_off_macpl, to skip the QoS
+ * If it's set, add 2 to cstate->off_linkpl.reg, to skip the QoS
* field.
* Otherwise, go to the first statement of the rest of the
* program.
*/
- sjset_qos->s.jt = s2 = new_stmt(BPF_LD|BPF_MEM);
- s2->s.k = reg_off_macpl;
+ sjset_qos->s.jt = s2 = new_stmt(cstate, BPF_LD|BPF_MEM);
+ s2->s.k = cstate->off_linkpl.reg;
sappend(s, s2);
- s2 = new_stmt(BPF_ALU|BPF_ADD|BPF_IMM);
+ s2 = new_stmt(cstate, BPF_ALU|BPF_ADD|BPF_IMM);
s2->s.k = 2;
sappend(s, s2);
- s2 = new_stmt(BPF_ST);
- s2->s.k = reg_off_macpl;
+ s2 = new_stmt(cstate, BPF_ST);
+ s2->s.k = cstate->off_linkpl.reg;
sappend(s, s2);
/*
@@ -2505,32 +2621,54 @@ gen_load_802_11_header_len(struct slist *s, struct slist *snext)
* little-endian, so we byte-swap all of the values
* we test against, as they will be loaded as big-endian
* values.
+ *
+ * XXX - in the general case, we would have to scan through
+ * *all* the presence bits, if there's more than one word of
+ * presence bits. That would require a loop, meaning that
+ * we wouldn't be able to run the filter in the kernel.
+ *
+ * We assume here that the Atheros adapters that insert the
+ * annoying padding don't have multiple antennae and therefore
+ * do not generate radiotap headers with multiple presence words.
*/
- if (linktype == DLT_IEEE802_11_RADIO) {
+ if (cstate->linktype == DLT_IEEE802_11_RADIO) {
/*
* Is the IEEE80211_RADIOTAP_FLAGS bit (0x0000002) set
- * in the presence flag?
+ * in the first presence flag word?
*/
- sjset_qos->s.jf = s2 = new_stmt(BPF_LD|BPF_ABS|BPF_W);
+ sjset_qos->s.jf = s2 = new_stmt(cstate, BPF_LD|BPF_ABS|BPF_W);
s2->s.k = 4;
sappend(s, s2);
- sjset_radiotap_flags = new_stmt(JMP(BPF_JSET));
- sjset_radiotap_flags->s.k = SWAPLONG(0x00000002);
- sappend(s, sjset_radiotap_flags);
+ sjset_radiotap_flags_present = new_stmt(cstate, JMP(BPF_JSET));
+ sjset_radiotap_flags_present->s.k = SWAPLONG(0x00000002);
+ sappend(s, sjset_radiotap_flags_present);
/*
* If not, skip all of this.
*/
- sjset_radiotap_flags->s.jf = snext;
+ sjset_radiotap_flags_present->s.jf = snext;
+
+ /*
+ * Otherwise, is the "extension" bit set in that word?
+ */
+ sjset_radiotap_ext_present = new_stmt(cstate, JMP(BPF_JSET));
+ sjset_radiotap_ext_present->s.k = SWAPLONG(0x80000000);
+ sappend(s, sjset_radiotap_ext_present);
+ sjset_radiotap_flags_present->s.jt = sjset_radiotap_ext_present;
+
+ /*
+ * If so, skip all of this.
+ */
+ sjset_radiotap_ext_present->s.jt = snext;
/*
* Otherwise, is the IEEE80211_RADIOTAP_TSFT bit set?
*/
- sjset_radiotap_tsft = sjset_radiotap_flags->s.jt =
- new_stmt(JMP(BPF_JSET));
- sjset_radiotap_tsft->s.k = SWAPLONG(0x00000001);
- sappend(s, sjset_radiotap_tsft);
+ sjset_radiotap_tsft_present = new_stmt(cstate, JMP(BPF_JSET));
+ sjset_radiotap_tsft_present->s.k = SWAPLONG(0x00000001);
+ sappend(s, sjset_radiotap_tsft_present);
+ sjset_radiotap_ext_present->s.jf = sjset_radiotap_tsft_present;
/*
* If IEEE80211_RADIOTAP_TSFT is set, the flags field is
@@ -2541,11 +2679,12 @@ gen_load_802_11_header_len(struct slist *s, struct slist *snext)
* Test whether the IEEE80211_RADIOTAP_F_DATAPAD bit (0x20)
* is set.
*/
- sjset_radiotap_tsft->s.jt = s2 = new_stmt(BPF_LD|BPF_ABS|BPF_B);
+ s2 = new_stmt(cstate, BPF_LD|BPF_ABS|BPF_B);
s2->s.k = 16;
sappend(s, s2);
+ sjset_radiotap_tsft_present->s.jt = s2;
- sjset_tsft_datapad = new_stmt(JMP(BPF_JSET));
+ sjset_tsft_datapad = new_stmt(cstate, JMP(BPF_JSET));
sjset_tsft_datapad->s.k = 0x20;
sappend(s, sjset_tsft_datapad);
@@ -2557,11 +2696,12 @@ gen_load_802_11_header_len(struct slist *s, struct slist *snext)
* Test whether the IEEE80211_RADIOTAP_F_DATAPAD bit (0x20)
* is set.
*/
- sjset_radiotap_tsft->s.jf = s2 = new_stmt(BPF_LD|BPF_ABS|BPF_B);
+ s2 = new_stmt(cstate, BPF_LD|BPF_ABS|BPF_B);
s2->s.k = 8;
sappend(s, s2);
+ sjset_radiotap_tsft_present->s.jf = s2;
- sjset_notsft_datapad = new_stmt(JMP(BPF_JSET));
+ sjset_notsft_datapad = new_stmt(cstate, JMP(BPF_JSET));
sjset_notsft_datapad->s.k = 0x20;
sappend(s, sjset_notsft_datapad);
@@ -2572,17 +2712,17 @@ gen_load_802_11_header_len(struct slist *s, struct slist *snext)
* dividing by and multiplying by 4, which we do by
* ANDing with ~3.
*/
- s_roundup = new_stmt(BPF_LD|BPF_MEM);
- s_roundup->s.k = reg_off_macpl;
+ s_roundup = new_stmt(cstate, BPF_LD|BPF_MEM);
+ s_roundup->s.k = cstate->off_linkpl.reg;
sappend(s, s_roundup);
- s2 = new_stmt(BPF_ALU|BPF_ADD|BPF_IMM);
+ s2 = new_stmt(cstate, BPF_ALU|BPF_ADD|BPF_IMM);
s2->s.k = 3;
sappend(s, s2);
- s2 = new_stmt(BPF_ALU|BPF_AND|BPF_IMM);
+ s2 = new_stmt(cstate, BPF_ALU|BPF_AND|BPF_IMM);
s2->s.k = ~3;
sappend(s, s2);
- s2 = new_stmt(BPF_ST);
- s2->s.k = reg_off_macpl;
+ s2 = new_stmt(cstate, BPF_ST);
+ s2->s.k = cstate->off_linkpl.reg;
sappend(s, s2);
sjset_tsft_datapad->s.jt = s_roundup;
@@ -2596,33 +2736,46 @@ gen_load_802_11_header_len(struct slist *s, struct slist *snext)
}
static void
-insert_compute_vloffsets(b)
- struct block *b;
+insert_compute_vloffsets(compiler_state_t *cstate, struct block *b)
{
struct slist *s;
+ /* There is an implicit dependency between the link
+ * payload and link header since the payload computation
+ * includes the variable part of the header. Therefore,
+ * if nobody else has allocated a register for the link
+ * header and we need it, do it now. */
+ if (cstate->off_linkpl.reg != -1 && cstate->off_linkhdr.is_variable &&
+ cstate->off_linkhdr.reg == -1)
+ cstate->off_linkhdr.reg = alloc_reg(cstate);
+
/*
* For link-layer types that have a variable-length header
* preceding the link-layer header, generate code to load
* the offset of the link-layer header into the register
* assigned to that offset, if any.
+ *
+ * XXX - this, and the next switch statement, won't handle
+ * encapsulation of 802.11 or 802.11+radio information in
+ * some other protocol stack. That's significantly more
+ * complicated.
*/
- switch (linktype) {
+ switch (cstate->outermostlinktype) {
case DLT_PRISM_HEADER:
- s = gen_load_prism_llprefixlen();
+ s = gen_load_prism_llprefixlen(cstate);
break;
case DLT_IEEE802_11_RADIO_AVS:
- s = gen_load_avs_llprefixlen();
+ s = gen_load_avs_llprefixlen(cstate);
break;
case DLT_IEEE802_11_RADIO:
- s = gen_load_radiotap_llprefixlen();
+ s = gen_load_radiotap_llprefixlen(cstate);
break;
case DLT_PPI:
- s = gen_load_ppi_llprefixlen();
+ s = gen_load_ppi_llprefixlen(cstate);
break;
default:
@@ -2632,17 +2785,17 @@ insert_compute_vloffsets(b)
/*
* For link-layer types that have a variable-length link-layer
- * header, generate code to load the offset of the MAC-layer
+ * header, generate code to load the offset of the link-layer
* payload into the register assigned to that offset, if any.
*/
- switch (linktype) {
+ switch (cstate->outermostlinktype) {
case DLT_IEEE802_11:
case DLT_PRISM_HEADER:
case DLT_IEEE802_11_RADIO_AVS:
case DLT_IEEE802_11_RADIO:
case DLT_PPI:
- s = gen_load_802_11_header_len(s, b->stmts);
+ s = gen_load_802_11_header_len(cstate, s, b->stmts);
break;
}
@@ -2659,19 +2812,19 @@ insert_compute_vloffsets(b)
}
static struct block *
-gen_ppi_dlt_check(void)
+gen_ppi_dlt_check(compiler_state_t *cstate)
{
struct slist *s_load_dlt;
struct block *b;
- if (linktype == DLT_PPI)
+ if (cstate->linktype == DLT_PPI)
{
/* Create the statements that check for the DLT
*/
- s_load_dlt = new_stmt(BPF_LD|BPF_W|BPF_ABS);
+ s_load_dlt = new_stmt(cstate, BPF_LD|BPF_W|BPF_ABS);
s_load_dlt->s.k = 4;
- b = new_block(JMP(BPF_JEQ));
+ b = new_block(cstate, JMP(BPF_JEQ));
b->stmts = s_load_dlt;
b->s.k = SWAPLONG(DLT_IEEE802_11);
@@ -2684,160 +2837,45 @@ gen_ppi_dlt_check(void)
return b;
}
-static struct slist *
-gen_prism_llprefixlen(void)
-{
- struct slist *s;
-
- if (reg_off_ll == -1) {
- /*
- * We haven't yet assigned a register for the length
- * of the radio header; allocate one.
- */
- reg_off_ll = alloc_reg();
- }
-
- /*
- * Load the register containing the radio length
- * into the X register.
- */
- s = new_stmt(BPF_LDX|BPF_MEM);
- s->s.k = reg_off_ll;
- return s;
-}
-
-static struct slist *
-gen_avs_llprefixlen(void)
-{
- struct slist *s;
-
- if (reg_off_ll == -1) {
- /*
- * We haven't yet assigned a register for the length
- * of the AVS header; allocate one.
- */
- reg_off_ll = alloc_reg();
- }
-
- /*
- * Load the register containing the AVS length
- * into the X register.
- */
- s = new_stmt(BPF_LDX|BPF_MEM);
- s->s.k = reg_off_ll;
- return s;
-}
-
-static struct slist *
-gen_radiotap_llprefixlen(void)
-{
- struct slist *s;
-
- if (reg_off_ll == -1) {
- /*
- * We haven't yet assigned a register for the length
- * of the radiotap header; allocate one.
- */
- reg_off_ll = alloc_reg();
- }
-
- /*
- * Load the register containing the radiotap length
- * into the X register.
- */
- s = new_stmt(BPF_LDX|BPF_MEM);
- s->s.k = reg_off_ll;
- return s;
-}
-
-/*
- * At the moment we treat PPI as normal Radiotap encoded
- * packets. The difference is in the function that generates
- * the code at the beginning to compute the header length.
- * Since this code generator of PPI supports bare 802.11
- * encapsulation only (i.e. the encapsulated DLT should be
- * DLT_IEEE802_11) we generate code to check for this too.
- */
-static struct slist *
-gen_ppi_llprefixlen(void)
-{
- struct slist *s;
-
- if (reg_off_ll == -1) {
- /*
- * We haven't yet assigned a register for the length
- * of the radiotap header; allocate one.
- */
- reg_off_ll = alloc_reg();
- }
-
- /*
- * Load the register containing the PPI length
- * into the X register.
- */
- s = new_stmt(BPF_LDX|BPF_MEM);
- s->s.k = reg_off_ll;
- return s;
-}
-
/*
- * Generate code to compute the link-layer header length, if necessary,
- * putting it into the X register, and to return either a pointer to a
- * "struct slist" for the list of statements in that code, or NULL if
- * no code is necessary.
- */
-static struct slist *
-gen_llprefixlen(void)
-{
- switch (linktype) {
-
- case DLT_PRISM_HEADER:
- return gen_prism_llprefixlen();
-
- case DLT_IEEE802_11_RADIO_AVS:
- return gen_avs_llprefixlen();
-
- case DLT_IEEE802_11_RADIO:
- return gen_radiotap_llprefixlen();
-
- case DLT_PPI:
- return gen_ppi_llprefixlen();
-
- default:
- return NULL;
- }
-}
-
-/*
- * Generate code to load the register containing the offset of the
- * MAC-layer payload into the X register; if no register for that offset
- * has been allocated, allocate it first.
+ * Take an absolute offset, and:
+ *
+ * if it has no variable part, return NULL;
+ *
+ * if it has a variable part, generate code to load the register
+ * containing that variable part into the X register, returning
+ * a pointer to that code - if no register for that offset has
+ * been allocated, allocate it first.
+ *
+ * (The code to set that register will be generated later, but will
+ * be placed earlier in the code sequence.)
*/
static struct slist *
-gen_off_macpl(void)
+gen_abs_offset_varpart(compiler_state_t *cstate, bpf_abs_offset *off)
{
struct slist *s;
- if (off_macpl_is_variable) {
- if (reg_off_macpl == -1) {
+ if (off->is_variable) {
+ if (off->reg == -1) {
/*
- * We haven't yet assigned a register for the offset
- * of the MAC-layer payload; allocate one.
+ * We haven't yet assigned a register for the
+ * variable part of the offset of the link-layer
+ * header; allocate one.
*/
- reg_off_macpl = alloc_reg();
+ off->reg = alloc_reg(cstate);
}
/*
- * Load the register containing the offset of the MAC-layer
- * payload into the X register.
+ * Load the register containing the variable part of the
+ * offset of the link-layer header into the X register.
*/
- s = new_stmt(BPF_LDX|BPF_MEM);
- s->s.k = reg_off_macpl;
+ s = new_stmt(cstate, BPF_LDX|BPF_MEM);
+ s->s.k = off->reg;
return s;
} else {
/*
- * That offset isn't variable, so we don't need to
- * generate any code.
+ * That offset isn't variable, there's no variable part,
+ * so we don't need to generate any code.
*/
return NULL;
}
@@ -2893,6 +2931,51 @@ ethertype_to_ppptype(proto)
}
/*
+ * Generate any tests that, for encapsulation of a link-layer packet
+ * inside another protocol stack, need to be done to check for those
+ * link-layer packets (and that haven't already been done by a check
+ * for that encapsulation).
+ */
+static struct block *
+gen_prevlinkhdr_check(compiler_state_t *cstate)
+{
+ struct block *b0;
+
+ if (cstate->is_geneve)
+ return gen_geneve_ll_check(cstate);
+
+ switch (cstate->prevlinktype) {
+
+ case DLT_SUNATM:
+ /*
+ * This is LANE-encapsulated Ethernet; check that the LANE
+ * packet doesn't begin with an LE Control marker, i.e.
+ * that it's data, not a control message.
+ *
+ * (We've already generated a test for LANE.)
+ */
+ b0 = gen_cmp(cstate, OR_PREVLINKHDR, SUNATM_PKT_BEGIN_POS, BPF_H, 0xFF00);
+ gen_not(b0);
+ return b0;
+
+ default:
+ /*
+ * No such tests are necessary.
+ */
+ return NULL;
+ }
+ /*NOTREACHED*/
+}
+
+/*
+ * The three different values we should check for when checking for an
+ * IPv6 packet with DLT_NULL.
+ */
+#define BSD_AFNUM_INET6_BSD 24 /* NetBSD, OpenBSD, BSD/OS, Npcap */
+#define BSD_AFNUM_INET6_FREEBSD 28 /* FreeBSD */
+#define BSD_AFNUM_INET6_DARWIN 30 /* OS X, iOS, other Darwin-based OSes */
+
+/*
* Generate code to match a particular packet type by matching the
* link-layer type field or fields in the 802.2 LLC header.
*
@@ -2900,56 +2983,46 @@ ethertype_to_ppptype(proto)
* value, if <= ETHERMTU.
*/
static struct block *
-gen_linktype(proto)
- register int proto;
+gen_linktype(compiler_state_t *cstate, int proto)
{
struct block *b0, *b1, *b2;
const char *description;
/* are we checking MPLS-encapsulated packets? */
- if (label_stack_depth > 0) {
+ if (cstate->label_stack_depth > 0) {
switch (proto) {
case ETHERTYPE_IP:
case PPP_IP:
/* FIXME add other L3 proto IDs */
- return gen_mpls_linktype(Q_IP);
+ return gen_mpls_linktype(cstate, Q_IP);
case ETHERTYPE_IPV6:
case PPP_IPV6:
/* FIXME add other L3 proto IDs */
- return gen_mpls_linktype(Q_IPV6);
+ return gen_mpls_linktype(cstate, Q_IPV6);
default:
- bpf_error("unsupported protocol over mpls");
+ bpf_error(cstate, "unsupported protocol over mpls");
/* NOTREACHED */
}
}
- /*
- * Are we testing PPPoE packets?
- */
- if (is_pppoes) {
- /*
- * The PPPoE session header is part of the
- * MAC-layer payload, so all references
- * should be relative to the beginning of
- * that payload.
- */
-
- /*
- * We use Ethernet protocol types inside libpcap;
- * map them to the corresponding PPP protocol types.
- */
- proto = ethertype_to_ppptype(proto);
- return gen_cmp(OR_MACPL, off_linktype, BPF_H, (bpf_int32)proto);
- }
-
- switch (linktype) {
+ switch (cstate->linktype) {
case DLT_EN10MB:
case DLT_NETANALYZER:
case DLT_NETANALYZER_TRANSPARENT:
- return gen_ether_linktype(proto);
+ /* Geneve has an EtherType regardless of whether there is an
+ * L2 header. */
+ if (!cstate->is_geneve)
+ b0 = gen_prevlinkhdr_check(cstate);
+ else
+ b0 = NULL;
+
+ b1 = gen_ether_linktype(cstate, proto);
+ if (b0 != NULL)
+ gen_and(b0, b1);
+ return b1;
/*NOTREACHED*/
break;
@@ -2961,8 +3034,7 @@ gen_linktype(proto)
/* fall through */
default:
- return gen_cmp(OR_LINK, off_linktype, BPF_H,
- (bpf_int32)proto);
+ return gen_cmp(cstate, OR_LINKTYPE, 0, BPF_H, (bpf_int32)proto);
/*NOTREACHED*/
break;
}
@@ -2976,12 +3048,12 @@ gen_linktype(proto)
/*
* Check that we have a data frame.
*/
- b0 = gen_check_802_11_data_frame();
+ b0 = gen_check_802_11_data_frame(cstate);
/*
* Now check for the specified link-layer type.
*/
- b1 = gen_llc_linktype(proto);
+ b1 = gen_llc_linktype(cstate, proto);
gen_and(b0, b1);
return b1;
/*NOTREACHED*/
@@ -2991,7 +3063,7 @@ gen_linktype(proto)
/*
* XXX - check for LLC frames.
*/
- return gen_llc_linktype(proto);
+ return gen_llc_linktype(cstate, proto);
/*NOTREACHED*/
break;
@@ -2999,56 +3071,34 @@ gen_linktype(proto)
/*
* XXX - check for LLC PDUs, as per IEEE 802.5.
*/
- return gen_llc_linktype(proto);
+ return gen_llc_linktype(cstate, proto);
/*NOTREACHED*/
break;
case DLT_ATM_RFC1483:
case DLT_ATM_CLIP:
case DLT_IP_OVER_FC:
- return gen_llc_linktype(proto);
+ return gen_llc_linktype(cstate, proto);
/*NOTREACHED*/
break;
case DLT_SUNATM:
/*
- * If "is_lane" is set, check for a LANE-encapsulated
- * version of this protocol, otherwise check for an
- * LLC-encapsulated version of this protocol.
+ * Check for an LLC-encapsulated version of this protocol;
+ * if we were checking for LANE, linktype would no longer
+ * be DLT_SUNATM.
*
- * We assume LANE means Ethernet, not Token Ring.
+ * Check for LLC encapsulation and then check the protocol.
*/
- if (is_lane) {
- /*
- * Check that the packet doesn't begin with an
- * LE Control marker. (We've already generated
- * a test for LANE.)
- */
- b0 = gen_cmp(OR_LINK, SUNATM_PKT_BEGIN_POS, BPF_H,
- 0xFF00);
- gen_not(b0);
-
- /*
- * Now generate an Ethernet test.
- */
- b1 = gen_ether_linktype(proto);
- gen_and(b0, b1);
- return b1;
- } else {
- /*
- * Check for LLC encapsulation and then check the
- * protocol.
- */
- b0 = gen_atmfield_code(A_PROTOTYPE, PT_LLC, BPF_JEQ, 0);
- b1 = gen_llc_linktype(proto);
- gen_and(b0, b1);
- return b1;
- }
+ b0 = gen_atmfield_code(cstate, A_PROTOTYPE, PT_LLC, BPF_JEQ, 0);
+ b1 = gen_llc_linktype(cstate, proto);
+ gen_and(b0, b1);
+ return b1;
/*NOTREACHED*/
break;
case DLT_LINUX_SLL:
- return gen_linux_sll_linktype(proto);
+ return gen_linux_sll_linktype(cstate, proto);
/*NOTREACHED*/
break;
@@ -3066,14 +3116,14 @@ gen_linktype(proto)
case ETHERTYPE_IP:
/* Check for a version number of 4. */
- return gen_mcmp(OR_LINK, 0, BPF_B, 0x40, 0xF0);
+ return gen_mcmp(cstate, OR_LINKHDR, 0, BPF_B, 0x40, 0xF0);
case ETHERTYPE_IPV6:
/* Check for a version number of 6. */
- return gen_mcmp(OR_LINK, 0, BPF_B, 0x60, 0xF0);
+ return gen_mcmp(cstate, OR_LINKHDR, 0, BPF_B, 0x60, 0xF0);
default:
- return gen_false(); /* always false */
+ return gen_false(cstate); /* always false */
}
/*NOTREACHED*/
break;
@@ -3083,10 +3133,10 @@ gen_linktype(proto)
* Raw IPv4, so no type field.
*/
if (proto == ETHERTYPE_IP)
- return gen_true(); /* always true */
+ return gen_true(cstate); /* always true */
/* Checking for something other than IPv4; always false */
- return gen_false();
+ return gen_false(cstate);
/*NOTREACHED*/
break;
@@ -3095,10 +3145,10 @@ gen_linktype(proto)
* Raw IPv6, so no type field.
*/
if (proto == ETHERTYPE_IPV6)
- return gen_true(); /* always true */
+ return gen_true(cstate); /* always true */
/* Checking for something other than IPv6; always false */
- return gen_false();
+ return gen_false(cstate);
/*NOTREACHED*/
break;
@@ -3111,7 +3161,7 @@ gen_linktype(proto)
* map them to the corresponding PPP protocol types.
*/
proto = ethertype_to_ppptype(proto);
- return gen_cmp(OR_LINK, off_linktype, BPF_H, (bpf_int32)proto);
+ return gen_cmp(cstate, OR_LINKTYPE, 0, BPF_H, (bpf_int32)proto);
/*NOTREACHED*/
break;
@@ -3127,16 +3177,16 @@ gen_linktype(proto)
* Also check for Van Jacobson-compressed IP.
* XXX - do this for other forms of PPP?
*/
- b0 = gen_cmp(OR_LINK, off_linktype, BPF_H, PPP_IP);
- b1 = gen_cmp(OR_LINK, off_linktype, BPF_H, PPP_VJC);
+ b0 = gen_cmp(cstate, OR_LINKTYPE, 0, BPF_H, PPP_IP);
+ b1 = gen_cmp(cstate, OR_LINKTYPE, 0, BPF_H, PPP_VJC);
gen_or(b0, b1);
- b0 = gen_cmp(OR_LINK, off_linktype, BPF_H, PPP_VJNC);
+ b0 = gen_cmp(cstate, OR_LINKTYPE, 0, BPF_H, PPP_VJNC);
gen_or(b1, b0);
return b0;
default:
proto = ethertype_to_ppptype(proto);
- return gen_cmp(OR_LINK, off_linktype, BPF_H,
+ return gen_cmp(cstate, OR_LINKTYPE, 0, BPF_H,
(bpf_int32)proto);
}
/*NOTREACHED*/
@@ -3145,39 +3195,71 @@ gen_linktype(proto)
case DLT_NULL:
case DLT_LOOP:
case DLT_ENC:
- /*
- * For DLT_NULL, the link-layer header is a 32-bit
- * word containing an AF_ value in *host* byte order,
- * and for DLT_ENC, the link-layer header begins
- * with a 32-bit work containing an AF_ value in
- * host byte order.
- *
- * In addition, if we're reading a saved capture file,
- * the host byte order in the capture may not be the
- * same as the host byte order on this machine.
- *
- * For DLT_LOOP, the link-layer header is a 32-bit
- * word containing an AF_ value in *network* byte order.
- *
- * XXX - AF_ values may, unfortunately, be platform-
- * dependent; for example, FreeBSD's AF_INET6 is 24
- * whilst NetBSD's and OpenBSD's is 26.
- *
- * This means that, when reading a capture file, just
- * checking for our AF_INET6 value won't work if the
- * capture file came from another OS.
- */
switch (proto) {
case ETHERTYPE_IP:
- proto = AF_INET;
- break;
+ return (gen_loopback_linktype(cstate, AF_INET));
-#ifdef INET6
case ETHERTYPE_IPV6:
- proto = AF_INET6;
- break;
-#endif
+ /*
+ * AF_ values may, unfortunately, be platform-
+ * dependent; AF_INET isn't, because everybody
+ * used 4.2BSD's value, but AF_INET6 is, because
+ * 4.2BSD didn't have a value for it (given that
+ * IPv6 didn't exist back in the early 1980's),
+ * and they all picked their own values.
+ *
+ * This means that, if we're reading from a
+ * savefile, we need to check for all the
+ * possible values.
+ *
+ * If we're doing a live capture, we only need
+ * to check for this platform's value; however,
+ * Npcap uses 24, which isn't Windows's AF_INET6
+ * value. (Given the multiple different values,
+ * programs that read pcap files shouldn't be
+ * checking for their platform's AF_INET6 value
+ * anyway, they should check for all of the
+ * possible values. and they might as well do
+ * that even for live captures.)
+ */
+ if (cstate->bpf_pcap->rfile != NULL) {
+ /*
+ * Savefile - check for all three
+ * possible IPv6 values.
+ */
+ b0 = gen_loopback_linktype(cstate, BSD_AFNUM_INET6_BSD);
+ b1 = gen_loopback_linktype(cstate, BSD_AFNUM_INET6_FREEBSD);
+ gen_or(b0, b1);
+ b0 = gen_loopback_linktype(cstate, BSD_AFNUM_INET6_DARWIN);
+ gen_or(b0, b1);
+ return (b1);
+ } else {
+ /*
+ * Live capture, so we only need to
+ * check for the value used on this
+ * platform.
+ */
+#ifdef _WIN32
+ /*
+ * Npcap doesn't use Windows's AF_INET6,
+ * as that collides with AF_IPX on
+ * some BSDs (both have the value 23).
+ * Instead, it uses 24.
+ */
+ return (gen_loopback_linktype(cstate, 24));
+#else /* _WIN32 */
+#ifdef AF_INET6
+ return (gen_loopback_linktype(cstate, AF_INET6));
+#else /* AF_INET6 */
+ /*
+ * I guess this platform doesn't support
+ * IPv6, so we just reject all packets.
+ */
+ return gen_false(cstate);
+#endif /* AF_INET6 */
+#endif /* _WIN32 */
+ }
default:
/*
@@ -3185,27 +3267,8 @@ gen_linktype(proto)
* XXX - support those that have AF_ values
* #defined on this platform, at least?
*/
- return gen_false();
- }
-
- if (linktype == DLT_NULL || linktype == DLT_ENC) {
- /*
- * The AF_ value is in host byte order, but
- * the BPF interpreter will convert it to
- * network byte order.
- *
- * If this is a save file, and it's from a
- * machine with the opposite byte order to
- * ours, we byte-swap the AF_ value.
- *
- * Then we run it through "htonl()", and
- * generate code to compare against the result.
- */
- if (bpf_pcap->rfile != NULL && bpf_pcap->swapped)
- proto = SWAPLONG(proto);
- proto = htonl(proto);
+ return gen_false(cstate);
}
- return (gen_cmp(OR_LINK, 0, BPF_W, (bpf_int32)proto));
#ifdef HAVE_NET_PFVAR_H
case DLT_PFLOG:
@@ -3214,13 +3277,13 @@ gen_linktype(proto)
* the packet.
*/
if (proto == ETHERTYPE_IP)
- return (gen_cmp(OR_LINK, offsetof(struct pfloghdr, af),
+ return (gen_cmp(cstate, OR_LINKHDR, offsetof(struct pfloghdr, af),
BPF_B, (bpf_int32)AF_INET));
else if (proto == ETHERTYPE_IPV6)
- return (gen_cmp(OR_LINK, offsetof(struct pfloghdr, af),
+ return (gen_cmp(cstate, OR_LINKHDR, offsetof(struct pfloghdr, af),
BPF_B, (bpf_int32)AF_INET6));
else
- return gen_false();
+ return gen_false(cstate);
/*NOTREACHED*/
break;
#endif /* HAVE_NET_PFVAR_H */
@@ -3234,34 +3297,34 @@ gen_linktype(proto)
switch (proto) {
default:
- return gen_false();
+ return gen_false(cstate);
case ETHERTYPE_IPV6:
- return (gen_cmp(OR_LINK, off_linktype, BPF_B,
+ return (gen_cmp(cstate, OR_LINKTYPE, 0, BPF_B,
(bpf_int32)ARCTYPE_INET6));
case ETHERTYPE_IP:
- b0 = gen_cmp(OR_LINK, off_linktype, BPF_B,
+ b0 = gen_cmp(cstate, OR_LINKTYPE, 0, BPF_B,
(bpf_int32)ARCTYPE_IP);
- b1 = gen_cmp(OR_LINK, off_linktype, BPF_B,
+ b1 = gen_cmp(cstate, OR_LINKTYPE, 0, BPF_B,
(bpf_int32)ARCTYPE_IP_OLD);
gen_or(b0, b1);
return (b1);
case ETHERTYPE_ARP:
- b0 = gen_cmp(OR_LINK, off_linktype, BPF_B,
+ b0 = gen_cmp(cstate, OR_LINKTYPE, 0, BPF_B,
(bpf_int32)ARCTYPE_ARP);
- b1 = gen_cmp(OR_LINK, off_linktype, BPF_B,
+ b1 = gen_cmp(cstate, OR_LINKTYPE, 0, BPF_B,
(bpf_int32)ARCTYPE_ARP_OLD);
gen_or(b0, b1);
return (b1);
case ETHERTYPE_REVARP:
- return (gen_cmp(OR_LINK, off_linktype, BPF_B,
+ return (gen_cmp(cstate, OR_LINKTYPE, 0, BPF_B,
(bpf_int32)ARCTYPE_REVARP));
case ETHERTYPE_ATALK:
- return (gen_cmp(OR_LINK, off_linktype, BPF_B,
+ return (gen_cmp(cstate, OR_LINKTYPE, 0, BPF_B,
(bpf_int32)ARCTYPE_ATALK));
}
/*NOTREACHED*/
@@ -3270,9 +3333,9 @@ gen_linktype(proto)
case DLT_LTALK:
switch (proto) {
case ETHERTYPE_ATALK:
- return gen_true();
+ return gen_true(cstate);
default:
- return gen_false();
+ return gen_false(cstate);
}
/*NOTREACHED*/
break;
@@ -3288,13 +3351,13 @@ gen_linktype(proto)
/*
* Check for the special NLPID for IP.
*/
- return gen_cmp(OR_LINK, 2, BPF_H, (0x03<<8) | 0xcc);
+ return gen_cmp(cstate, OR_LINKHDR, 2, BPF_H, (0x03<<8) | 0xcc);
case ETHERTYPE_IPV6:
/*
* Check for the special NLPID for IPv6.
*/
- return gen_cmp(OR_LINK, 2, BPF_H, (0x03<<8) | 0x8e);
+ return gen_cmp(cstate, OR_LINKHDR, 2, BPF_H, (0x03<<8) | 0x8e);
case LLCSAP_ISONS:
/*
@@ -3308,21 +3371,21 @@ gen_linktype(proto)
* control field of UI, i.e. 0x03 followed
* by the NLPID.
*/
- b0 = gen_cmp(OR_LINK, 2, BPF_H, (0x03<<8) | ISO8473_CLNP);
- b1 = gen_cmp(OR_LINK, 2, BPF_H, (0x03<<8) | ISO9542_ESIS);
- b2 = gen_cmp(OR_LINK, 2, BPF_H, (0x03<<8) | ISO10589_ISIS);
+ b0 = gen_cmp(cstate, OR_LINKHDR, 2, BPF_H, (0x03<<8) | ISO8473_CLNP);
+ b1 = gen_cmp(cstate, OR_LINKHDR, 2, BPF_H, (0x03<<8) | ISO9542_ESIS);
+ b2 = gen_cmp(cstate, OR_LINKHDR, 2, BPF_H, (0x03<<8) | ISO10589_ISIS);
gen_or(b1, b2);
gen_or(b0, b2);
return b2;
default:
- return gen_false();
+ return gen_false(cstate);
}
/*NOTREACHED*/
break;
case DLT_MFR:
- bpf_error("Multi-link Frame Relay link-layer type filtering not implemented");
+ bpf_error(cstate, "Multi-link Frame Relay link-layer type filtering not implemented");
case DLT_JUNIPER_MFR:
case DLT_JUNIPER_MLFR:
@@ -3354,99 +3417,100 @@ gen_linktype(proto)
*
* FIXME encapsulation specific BPF_ filters
*/
- return gen_mcmp(OR_LINK, 0, BPF_W, 0x4d474300, 0xffffff00); /* compare the magic number */
+ return gen_mcmp(cstate, OR_LINKHDR, 0, BPF_W, 0x4d474300, 0xffffff00); /* compare the magic number */
case DLT_BACNET_MS_TP:
- return gen_mcmp(OR_LINK, 0, BPF_W, 0x55FF0000, 0xffff0000);
+ return gen_mcmp(cstate, OR_LINKHDR, 0, BPF_W, 0x55FF0000, 0xffff0000);
case DLT_IPNET:
- return gen_ipnet_linktype(proto);
+ return gen_ipnet_linktype(cstate, proto);
case DLT_LINUX_IRDA:
- bpf_error("IrDA link-layer type filtering not implemented");
+ bpf_error(cstate, "IrDA link-layer type filtering not implemented");
case DLT_DOCSIS:
- bpf_error("DOCSIS link-layer type filtering not implemented");
+ bpf_error(cstate, "DOCSIS link-layer type filtering not implemented");
case DLT_MTP2:
case DLT_MTP2_WITH_PHDR:
- bpf_error("MTP2 link-layer type filtering not implemented");
+ bpf_error(cstate, "MTP2 link-layer type filtering not implemented");
case DLT_ERF:
- bpf_error("ERF link-layer type filtering not implemented");
+ bpf_error(cstate, "ERF link-layer type filtering not implemented");
case DLT_PFSYNC:
- bpf_error("PFSYNC link-layer type filtering not implemented");
+ bpf_error(cstate, "PFSYNC link-layer type filtering not implemented");
case DLT_LINUX_LAPD:
- bpf_error("LAPD link-layer type filtering not implemented");
+ bpf_error(cstate, "LAPD link-layer type filtering not implemented");
- case DLT_USB:
+ case DLT_USB_FREEBSD:
case DLT_USB_LINUX:
case DLT_USB_LINUX_MMAPPED:
- bpf_error("USB link-layer type filtering not implemented");
+ case DLT_USBPCAP:
+ bpf_error(cstate, "USB link-layer type filtering not implemented");
case DLT_BLUETOOTH_HCI_H4:
case DLT_BLUETOOTH_HCI_H4_WITH_PHDR:
- bpf_error("Bluetooth link-layer type filtering not implemented");
+ bpf_error(cstate, "Bluetooth link-layer type filtering not implemented");
case DLT_CAN20B:
case DLT_CAN_SOCKETCAN:
- bpf_error("CAN link-layer type filtering not implemented");
+ bpf_error(cstate, "CAN link-layer type filtering not implemented");
case DLT_IEEE802_15_4:
case DLT_IEEE802_15_4_LINUX:
case DLT_IEEE802_15_4_NONASK_PHY:
case DLT_IEEE802_15_4_NOFCS:
- bpf_error("IEEE 802.15.4 link-layer type filtering not implemented");
+ bpf_error(cstate, "IEEE 802.15.4 link-layer type filtering not implemented");
case DLT_IEEE802_16_MAC_CPS_RADIO:
- bpf_error("IEEE 802.16 link-layer type filtering not implemented");
+ bpf_error(cstate, "IEEE 802.16 link-layer type filtering not implemented");
case DLT_SITA:
- bpf_error("SITA link-layer type filtering not implemented");
+ bpf_error(cstate, "SITA link-layer type filtering not implemented");
case DLT_RAIF1:
- bpf_error("RAIF1 link-layer type filtering not implemented");
+ bpf_error(cstate, "RAIF1 link-layer type filtering not implemented");
case DLT_IPMB:
- bpf_error("IPMB link-layer type filtering not implemented");
+ bpf_error(cstate, "IPMB link-layer type filtering not implemented");
case DLT_AX25_KISS:
- bpf_error("AX.25 link-layer type filtering not implemented");
+ bpf_error(cstate, "AX.25 link-layer type filtering not implemented");
case DLT_NFLOG:
/* Using the fixed-size NFLOG header it is possible to tell only
* the address family of the packet, other meaningful data is
* either missing or behind TLVs.
*/
- bpf_error("NFLOG link-layer type filtering not implemented");
+ bpf_error(cstate, "NFLOG link-layer type filtering not implemented");
default:
/*
* Does this link-layer header type have a field
* indicating the type of the next protocol? If
- * so, off_linktype will be the offset of that
- * field in the packet; if not, it will be -1.
+ * so, off_linktype.constant_part will be the offset of that
+ * field in the packet; if not, it will be OFFSET_NOT_SET.
*/
- if (off_linktype != (u_int)-1) {
+ if (cstate->off_linktype.constant_part != OFFSET_NOT_SET) {
/*
* Yes; assume it's an Ethernet type. (If
* it's not, it needs to be handled specially
* above.)
*/
- return gen_cmp(OR_LINK, off_linktype, BPF_H, (bpf_int32)proto);
+ return gen_cmp(cstate, OR_LINKTYPE, 0, BPF_H, (bpf_int32)proto);
} else {
/*
* No; report an error.
*/
- description = pcap_datalink_val_to_description(linktype);
+ description = pcap_datalink_val_to_description(cstate->linktype);
if (description != NULL) {
- bpf_error("%s link-layer type filtering not implemented",
+ bpf_error(cstate, "%s link-layer type filtering not implemented",
description);
} else {
- bpf_error("DLT %u link-layer type filtering not implemented",
- linktype);
+ bpf_error(cstate, "DLT %u link-layer type filtering not implemented",
+ cstate->linktype);
}
}
break;
@@ -3461,9 +3525,7 @@ gen_linktype(proto)
* code and protocol type in the SNAP header.
*/
static struct block *
-gen_snap(orgcode, ptype)
- bpf_u_int32 orgcode;
- bpf_u_int32 ptype;
+gen_snap(compiler_state_t *cstate, bpf_u_int32 orgcode, bpf_u_int32 ptype)
{
u_char snapblock[8];
@@ -3475,32 +3537,32 @@ gen_snap(orgcode, ptype)
snapblock[5] = (orgcode >> 0); /* lower 8 bits of organization code */
snapblock[6] = (ptype >> 8); /* upper 8 bits of protocol type */
snapblock[7] = (ptype >> 0); /* lower 8 bits of protocol type */
- return gen_bcmp(OR_MACPL, 0, 8, snapblock);
+ return gen_bcmp(cstate, OR_LLC, 0, 8, snapblock);
}
/*
* Generate code to match frames with an LLC header.
*/
struct block *
-gen_llc(void)
+gen_llc(compiler_state_t *cstate)
{
struct block *b0, *b1;
- switch (linktype) {
+ switch (cstate->linktype) {
case DLT_EN10MB:
/*
* We check for an Ethernet type field less than
* 1500, which means it's an 802.3 length field.
*/
- b0 = gen_cmp_gt(OR_LINK, off_linktype, BPF_H, ETHERMTU);
+ b0 = gen_cmp_gt(cstate, OR_LINKTYPE, 0, BPF_H, ETHERMTU);
gen_not(b0);
/*
* Now check for the purported DSAP and SSAP not being
* 0xFF, to rule out NetWare-over-802.3.
*/
- b1 = gen_cmp(OR_MACPL, 0, BPF_H, (bpf_int32)0xFFFF);
+ b1 = gen_cmp(cstate, OR_LLC, 0, BPF_H, (bpf_int32)0xFFFF);
gen_not(b1);
gen_and(b0, b1);
return b1;
@@ -3509,20 +3571,20 @@ gen_llc(void)
/*
* We check for LLC traffic.
*/
- b0 = gen_atmtype_abbrev(A_LLC);
+ b0 = gen_atmtype_abbrev(cstate, A_LLC);
return b0;
case DLT_IEEE802: /* Token Ring */
/*
* XXX - check for LLC frames.
*/
- return gen_true();
+ return gen_true(cstate);
case DLT_FDDI:
/*
* XXX - check for LLC frames.
*/
- return gen_true();
+ return gen_true(cstate);
case DLT_ATM_RFC1483:
/*
@@ -3533,7 +3595,7 @@ gen_llc(void)
* way to check for that; the protocol used on the VC
* is negotiated out of band.
*/
- return gen_true();
+ return gen_true(cstate);
case DLT_IEEE802_11:
case DLT_PRISM_HEADER:
@@ -3543,17 +3605,17 @@ gen_llc(void)
/*
* Check that we have a data frame.
*/
- b0 = gen_check_802_11_data_frame();
+ b0 = gen_check_802_11_data_frame(cstate);
return b0;
default:
- bpf_error("'llc' not supported for linktype %d", linktype);
+ bpf_error(cstate, "'llc' not supported for linktype %d", cstate->linktype);
/* NOTREACHED */
}
}
struct block *
-gen_llc_i(void)
+gen_llc_i(compiler_state_t *cstate)
{
struct block *b0, *b1;
struct slist *s;
@@ -3561,14 +3623,14 @@ gen_llc_i(void)
/*
* Check whether this is an LLC frame.
*/
- b0 = gen_llc();
+ b0 = gen_llc(cstate);
/*
* Load the control byte and test the low-order bit; it must
* be clear for I frames.
*/
- s = gen_load_a(OR_MACPL, 2, BPF_B);
- b1 = new_block(JMP(BPF_JSET));
+ s = gen_load_a(cstate, OR_LLC, 2, BPF_B);
+ b1 = new_block(cstate, JMP(BPF_JSET));
b1->s.k = 0x01;
b1->stmts = s;
gen_not(b1);
@@ -3577,75 +3639,75 @@ gen_llc_i(void)
}
struct block *
-gen_llc_s(void)
+gen_llc_s(compiler_state_t *cstate)
{
struct block *b0, *b1;
/*
* Check whether this is an LLC frame.
*/
- b0 = gen_llc();
+ b0 = gen_llc(cstate);
/*
* Now compare the low-order 2 bit of the control byte against
* the appropriate value for S frames.
*/
- b1 = gen_mcmp(OR_MACPL, 2, BPF_B, LLC_S_FMT, 0x03);
+ b1 = gen_mcmp(cstate, OR_LLC, 2, BPF_B, LLC_S_FMT, 0x03);
gen_and(b0, b1);
return b1;
}
struct block *
-gen_llc_u(void)
+gen_llc_u(compiler_state_t *cstate)
{
struct block *b0, *b1;
/*
* Check whether this is an LLC frame.
*/
- b0 = gen_llc();
+ b0 = gen_llc(cstate);
/*
* Now compare the low-order 2 bit of the control byte against
* the appropriate value for U frames.
*/
- b1 = gen_mcmp(OR_MACPL, 2, BPF_B, LLC_U_FMT, 0x03);
+ b1 = gen_mcmp(cstate, OR_LLC, 2, BPF_B, LLC_U_FMT, 0x03);
gen_and(b0, b1);
return b1;
}
struct block *
-gen_llc_s_subtype(bpf_u_int32 subtype)
+gen_llc_s_subtype(compiler_state_t *cstate, bpf_u_int32 subtype)
{
struct block *b0, *b1;
/*
* Check whether this is an LLC frame.
*/
- b0 = gen_llc();
+ b0 = gen_llc(cstate);
/*
* Now check for an S frame with the appropriate type.
*/
- b1 = gen_mcmp(OR_MACPL, 2, BPF_B, subtype, LLC_S_CMD_MASK);
+ b1 = gen_mcmp(cstate, OR_LLC, 2, BPF_B, subtype, LLC_S_CMD_MASK);
gen_and(b0, b1);
return b1;
}
struct block *
-gen_llc_u_subtype(bpf_u_int32 subtype)
+gen_llc_u_subtype(compiler_state_t *cstate, bpf_u_int32 subtype)
{
struct block *b0, *b1;
/*
* Check whether this is an LLC frame.
*/
- b0 = gen_llc();
+ b0 = gen_llc(cstate);
/*
* Now check for a U frame with the appropriate type.
*/
- b1 = gen_mcmp(OR_MACPL, 2, BPF_B, subtype, LLC_U_CMD_MASK);
+ b1 = gen_mcmp(cstate, OR_LLC, 2, BPF_B, subtype, LLC_U_CMD_MASK);
gen_and(b0, b1);
return b1;
}
@@ -3663,8 +3725,7 @@ gen_llc_u_subtype(bpf_u_int32 subtype)
* protocol ID in a SNAP header.
*/
static struct block *
-gen_llc_linktype(proto)
- int proto;
+gen_llc_linktype(compiler_state_t *cstate, int proto)
{
/*
* XXX - handle token-ring variable-length header.
@@ -3677,10 +3738,9 @@ gen_llc_linktype(proto)
/*
* XXX - should we check both the DSAP and the
* SSAP, like this, or should we check just the
- * DSAP, as we do for other types <= ETHERMTU
- * (i.e., other SAP values)?
+ * DSAP, as we do for other SAP values?
*/
- return gen_cmp(OR_MACPL, 0, BPF_H, (bpf_u_int32)
+ return gen_cmp(cstate, OR_LLC, 0, BPF_H, (bpf_u_int32)
((proto << 8) | proto));
case LLCSAP_IPX:
@@ -3688,7 +3748,7 @@ gen_llc_linktype(proto)
* XXX - are there ever SNAP frames for IPX on
* non-Ethernet 802.x networks?
*/
- return gen_cmp(OR_MACPL, 0, BPF_B,
+ return gen_cmp(cstate, OR_LLC, 0, BPF_B,
(bpf_int32)LLCSAP_IPX);
case ETHERTYPE_ATALK:
@@ -3701,7 +3761,7 @@ gen_llc_linktype(proto)
* XXX - check for an organization code of
* encapsulated Ethernet as well?
*/
- return gen_snap(0x080007, ETHERTYPE_ATALK);
+ return gen_snap(cstate, 0x080007, ETHERTYPE_ATALK);
default:
/*
@@ -3713,7 +3773,7 @@ gen_llc_linktype(proto)
* This is an LLC SAP value, so check
* the DSAP.
*/
- return gen_cmp(OR_MACPL, 0, BPF_B, (bpf_int32)proto);
+ return gen_cmp(cstate, OR_LLC, 0, BPF_B, (bpf_int32)proto);
} else {
/*
* This is an Ethernet type; we assume that it's
@@ -3728,23 +3788,20 @@ gen_llc_linktype(proto)
* organization code of 0x000000 (encapsulated
* Ethernet), we'd do
*
- * return gen_snap(0x000000, proto);
+ * return gen_snap(cstate, 0x000000, proto);
*
* here; for now, we don't, as per the above.
* I don't know whether it's worth the extra CPU
* time to do the right check or not.
*/
- return gen_cmp(OR_MACPL, 6, BPF_H, (bpf_int32)proto);
+ return gen_cmp(cstate, OR_LLC, 6, BPF_H, (bpf_int32)proto);
}
}
}
static struct block *
-gen_hostop(addr, mask, dir, proto, src_off, dst_off)
- bpf_u_int32 addr;
- bpf_u_int32 mask;
- int dir, proto;
- u_int src_off, dst_off;
+gen_hostop(compiler_state_t *cstate, bpf_u_int32 addr, bpf_u_int32 mask,
+ int dir, int proto, u_int src_off, u_int dst_off)
{
struct block *b0, *b1;
u_int offset;
@@ -3760,34 +3817,31 @@ gen_hostop(addr, mask, dir, proto, src_off, dst_off)
break;
case Q_AND:
- b0 = gen_hostop(addr, mask, Q_SRC, proto, src_off, dst_off);
- b1 = gen_hostop(addr, mask, Q_DST, proto, src_off, dst_off);
+ b0 = gen_hostop(cstate, addr, mask, Q_SRC, proto, src_off, dst_off);
+ b1 = gen_hostop(cstate, addr, mask, Q_DST, proto, src_off, dst_off);
gen_and(b0, b1);
return b1;
case Q_OR:
case Q_DEFAULT:
- b0 = gen_hostop(addr, mask, Q_SRC, proto, src_off, dst_off);
- b1 = gen_hostop(addr, mask, Q_DST, proto, src_off, dst_off);
+ b0 = gen_hostop(cstate, addr, mask, Q_SRC, proto, src_off, dst_off);
+ b1 = gen_hostop(cstate, addr, mask, Q_DST, proto, src_off, dst_off);
gen_or(b0, b1);
return b1;
default:
abort();
}
- b0 = gen_linktype(proto);
- b1 = gen_mcmp(OR_NET, offset, BPF_W, (bpf_int32)addr, mask);
+ b0 = gen_linktype(cstate, proto);
+ b1 = gen_mcmp(cstate, OR_LINKPL, offset, BPF_W, (bpf_int32)addr, mask);
gen_and(b0, b1);
return b1;
}
#ifdef INET6
static struct block *
-gen_hostop6(addr, mask, dir, proto, src_off, dst_off)
- struct in6_addr *addr;
- struct in6_addr *mask;
- int dir, proto;
- u_int src_off, dst_off;
+gen_hostop6(compiler_state_t *cstate, struct in6_addr *addr,
+ struct in6_addr *mask, int dir, int proto, u_int src_off, u_int dst_off)
{
struct block *b0, *b1;
u_int offset;
@@ -3804,15 +3858,15 @@ gen_hostop6(addr, mask, dir, proto, src_off, dst_off)
break;
case Q_AND:
- b0 = gen_hostop6(addr, mask, Q_SRC, proto, src_off, dst_off);
- b1 = gen_hostop6(addr, mask, Q_DST, proto, src_off, dst_off);
+ b0 = gen_hostop6(cstate, addr, mask, Q_SRC, proto, src_off, dst_off);
+ b1 = gen_hostop6(cstate, addr, mask, Q_DST, proto, src_off, dst_off);
gen_and(b0, b1);
return b1;
case Q_OR:
case Q_DEFAULT:
- b0 = gen_hostop6(addr, mask, Q_SRC, proto, src_off, dst_off);
- b1 = gen_hostop6(addr, mask, Q_DST, proto, src_off, dst_off);
+ b0 = gen_hostop6(cstate, addr, mask, Q_SRC, proto, src_off, dst_off);
+ b1 = gen_hostop6(cstate, addr, mask, Q_DST, proto, src_off, dst_off);
gen_or(b0, b1);
return b1;
@@ -3822,68 +3876,66 @@ gen_hostop6(addr, mask, dir, proto, src_off, dst_off)
/* this order is important */
a = (u_int32_t *)addr;
m = (u_int32_t *)mask;
- b1 = gen_mcmp(OR_NET, offset + 12, BPF_W, ntohl(a[3]), ntohl(m[3]));
- b0 = gen_mcmp(OR_NET, offset + 8, BPF_W, ntohl(a[2]), ntohl(m[2]));
+ b1 = gen_mcmp(cstate, OR_LINKPL, offset + 12, BPF_W, ntohl(a[3]), ntohl(m[3]));
+ b0 = gen_mcmp(cstate, OR_LINKPL, offset + 8, BPF_W, ntohl(a[2]), ntohl(m[2]));
gen_and(b0, b1);
- b0 = gen_mcmp(OR_NET, offset + 4, BPF_W, ntohl(a[1]), ntohl(m[1]));
+ b0 = gen_mcmp(cstate, OR_LINKPL, offset + 4, BPF_W, ntohl(a[1]), ntohl(m[1]));
gen_and(b0, b1);
- b0 = gen_mcmp(OR_NET, offset + 0, BPF_W, ntohl(a[0]), ntohl(m[0]));
+ b0 = gen_mcmp(cstate, OR_LINKPL, offset + 0, BPF_W, ntohl(a[0]), ntohl(m[0]));
gen_and(b0, b1);
- b0 = gen_linktype(proto);
+ b0 = gen_linktype(cstate, proto);
gen_and(b0, b1);
return b1;
}
#endif
static struct block *
-gen_ehostop(eaddr, dir)
- register const u_char *eaddr;
- register int dir;
+gen_ehostop(compiler_state_t *cstate, const u_char *eaddr, int dir)
{
register struct block *b0, *b1;
switch (dir) {
case Q_SRC:
- return gen_bcmp(OR_LINK, off_mac + 6, 6, eaddr);
+ return gen_bcmp(cstate, OR_LINKHDR, 6, 6, eaddr);
case Q_DST:
- return gen_bcmp(OR_LINK, off_mac + 0, 6, eaddr);
+ return gen_bcmp(cstate, OR_LINKHDR, 0, 6, eaddr);
case Q_AND:
- b0 = gen_ehostop(eaddr, Q_SRC);
- b1 = gen_ehostop(eaddr, Q_DST);
+ b0 = gen_ehostop(cstate, eaddr, Q_SRC);
+ b1 = gen_ehostop(cstate, eaddr, Q_DST);
gen_and(b0, b1);
return b1;
case Q_DEFAULT:
case Q_OR:
- b0 = gen_ehostop(eaddr, Q_SRC);
- b1 = gen_ehostop(eaddr, Q_DST);
+ b0 = gen_ehostop(cstate, eaddr, Q_SRC);
+ b1 = gen_ehostop(cstate, eaddr, Q_DST);
gen_or(b0, b1);
return b1;
case Q_ADDR1:
- bpf_error("'addr1' is only supported on 802.11 with 802.11 headers");
+ bpf_error(cstate, "'addr1' is only supported on 802.11 with 802.11 headers");
break;
case Q_ADDR2:
- bpf_error("'addr2' is only supported on 802.11 with 802.11 headers");
+ bpf_error(cstate, "'addr2' is only supported on 802.11 with 802.11 headers");
break;
case Q_ADDR3:
- bpf_error("'addr3' is only supported on 802.11 with 802.11 headers");
+ bpf_error(cstate, "'addr3' is only supported on 802.11 with 802.11 headers");
break;
case Q_ADDR4:
- bpf_error("'addr4' is only supported on 802.11 with 802.11 headers");
+ bpf_error(cstate, "'addr4' is only supported on 802.11 with 802.11 headers");
break;
case Q_RA:
- bpf_error("'ra' is only supported on 802.11 with 802.11 headers");
+ bpf_error(cstate, "'ra' is only supported on 802.11 with 802.11 headers");
break;
case Q_TA:
- bpf_error("'ta' is only supported on 802.11 with 802.11 headers");
+ bpf_error(cstate, "'ta' is only supported on 802.11 with 802.11 headers");
break;
}
abort();
@@ -3894,54 +3946,52 @@ gen_ehostop(eaddr, dir)
* Like gen_ehostop, but for DLT_FDDI
*/
static struct block *
-gen_fhostop(eaddr, dir)
- register const u_char *eaddr;
- register int dir;
+gen_fhostop(compiler_state_t *cstate, const u_char *eaddr, int dir)
{
struct block *b0, *b1;
switch (dir) {
case Q_SRC:
- return gen_bcmp(OR_LINK, 6 + 1 + pcap_fddipad, 6, eaddr);
+ return gen_bcmp(cstate, OR_LINKHDR, 6 + 1 + cstate->pcap_fddipad, 6, eaddr);
case Q_DST:
- return gen_bcmp(OR_LINK, 0 + 1 + pcap_fddipad, 6, eaddr);
+ return gen_bcmp(cstate, OR_LINKHDR, 0 + 1 + cstate->pcap_fddipad, 6, eaddr);
case Q_AND:
- b0 = gen_fhostop(eaddr, Q_SRC);
- b1 = gen_fhostop(eaddr, Q_DST);
+ b0 = gen_fhostop(cstate, eaddr, Q_SRC);
+ b1 = gen_fhostop(cstate, eaddr, Q_DST);
gen_and(b0, b1);
return b1;
case Q_DEFAULT:
case Q_OR:
- b0 = gen_fhostop(eaddr, Q_SRC);
- b1 = gen_fhostop(eaddr, Q_DST);
+ b0 = gen_fhostop(cstate, eaddr, Q_SRC);
+ b1 = gen_fhostop(cstate, eaddr, Q_DST);
gen_or(b0, b1);
return b1;
case Q_ADDR1:
- bpf_error("'addr1' is only supported on 802.11");
+ bpf_error(cstate, "'addr1' is only supported on 802.11");
break;
case Q_ADDR2:
- bpf_error("'addr2' is only supported on 802.11");
+ bpf_error(cstate, "'addr2' is only supported on 802.11");
break;
case Q_ADDR3:
- bpf_error("'addr3' is only supported on 802.11");
+ bpf_error(cstate, "'addr3' is only supported on 802.11");
break;
case Q_ADDR4:
- bpf_error("'addr4' is only supported on 802.11");
+ bpf_error(cstate, "'addr4' is only supported on 802.11");
break;
case Q_RA:
- bpf_error("'ra' is only supported on 802.11");
+ bpf_error(cstate, "'ra' is only supported on 802.11");
break;
case Q_TA:
- bpf_error("'ta' is only supported on 802.11");
+ bpf_error(cstate, "'ta' is only supported on 802.11");
break;
}
abort();
@@ -3952,54 +4002,52 @@ gen_fhostop(eaddr, dir)
* Like gen_ehostop, but for DLT_IEEE802 (Token Ring)
*/
static struct block *
-gen_thostop(eaddr, dir)
- register const u_char *eaddr;
- register int dir;
+gen_thostop(compiler_state_t *cstate, const u_char *eaddr, int dir)
{
register struct block *b0, *b1;
switch (dir) {
case Q_SRC:
- return gen_bcmp(OR_LINK, 8, 6, eaddr);
+ return gen_bcmp(cstate, OR_LINKHDR, 8, 6, eaddr);
case Q_DST:
- return gen_bcmp(OR_LINK, 2, 6, eaddr);
+ return gen_bcmp(cstate, OR_LINKHDR, 2, 6, eaddr);
case Q_AND:
- b0 = gen_thostop(eaddr, Q_SRC);
- b1 = gen_thostop(eaddr, Q_DST);
+ b0 = gen_thostop(cstate, eaddr, Q_SRC);
+ b1 = gen_thostop(cstate, eaddr, Q_DST);
gen_and(b0, b1);
return b1;
case Q_DEFAULT:
case Q_OR:
- b0 = gen_thostop(eaddr, Q_SRC);
- b1 = gen_thostop(eaddr, Q_DST);
+ b0 = gen_thostop(cstate, eaddr, Q_SRC);
+ b1 = gen_thostop(cstate, eaddr, Q_DST);
gen_or(b0, b1);
return b1;
case Q_ADDR1:
- bpf_error("'addr1' is only supported on 802.11");
+ bpf_error(cstate, "'addr1' is only supported on 802.11");
break;
case Q_ADDR2:
- bpf_error("'addr2' is only supported on 802.11");
+ bpf_error(cstate, "'addr2' is only supported on 802.11");
break;
case Q_ADDR3:
- bpf_error("'addr3' is only supported on 802.11");
+ bpf_error(cstate, "'addr3' is only supported on 802.11");
break;
case Q_ADDR4:
- bpf_error("'addr4' is only supported on 802.11");
+ bpf_error(cstate, "'addr4' is only supported on 802.11");
break;
case Q_RA:
- bpf_error("'ra' is only supported on 802.11");
+ bpf_error(cstate, "'ra' is only supported on 802.11");
break;
case Q_TA:
- bpf_error("'ta' is only supported on 802.11");
+ bpf_error(cstate, "'ta' is only supported on 802.11");
break;
}
abort();
@@ -4011,9 +4059,7 @@ gen_thostop(eaddr, dir)
* various 802.11 + radio headers.
*/
static struct block *
-gen_wlanhostop(eaddr, dir)
- register const u_char *eaddr;
- register int dir;
+gen_wlanhostop(compiler_state_t *cstate, const u_char *eaddr, int dir)
{
register struct block *b0, *b1, *b2;
register struct slist *s;
@@ -4025,7 +4071,7 @@ gen_wlanhostop(eaddr, dir)
* and wipes out some LD instructions generated by the below
* code to validate the Frame Control bits
*/
- no_optimize = 1;
+ cstate->no_optimize = 1;
#endif /* ENABLE_WLAN_FILTERING_PATCH */
switch (dir) {
@@ -4055,23 +4101,23 @@ gen_wlanhostop(eaddr, dir)
*
* First, check for To DS set, i.e. check "link[1] & 0x01".
*/
- s = gen_load_a(OR_LINK, 1, BPF_B);
- b1 = new_block(JMP(BPF_JSET));
+ s = gen_load_a(cstate, OR_LINKHDR, 1, BPF_B);
+ b1 = new_block(cstate, JMP(BPF_JSET));
b1->s.k = 0x01; /* To DS */
b1->stmts = s;
/*
* If To DS is set, the SA is at 24.
*/
- b0 = gen_bcmp(OR_LINK, 24, 6, eaddr);
+ b0 = gen_bcmp(cstate, OR_LINKHDR, 24, 6, eaddr);
gen_and(b1, b0);
/*
* Now, check for To DS not set, i.e. check
* "!(link[1] & 0x01)".
*/
- s = gen_load_a(OR_LINK, 1, BPF_B);
- b2 = new_block(JMP(BPF_JSET));
+ s = gen_load_a(cstate, OR_LINKHDR, 1, BPF_B);
+ b2 = new_block(cstate, JMP(BPF_JSET));
b2->s.k = 0x01; /* To DS */
b2->stmts = s;
gen_not(b2);
@@ -4079,7 +4125,7 @@ gen_wlanhostop(eaddr, dir)
/*
* If To DS is not set, the SA is at 16.
*/
- b1 = gen_bcmp(OR_LINK, 16, 6, eaddr);
+ b1 = gen_bcmp(cstate, OR_LINKHDR, 16, 6, eaddr);
gen_and(b2, b1);
/*
@@ -4093,8 +4139,8 @@ gen_wlanhostop(eaddr, dir)
* Now check for From DS being set, and AND that with
* the ORed-together checks.
*/
- s = gen_load_a(OR_LINK, 1, BPF_B);
- b1 = new_block(JMP(BPF_JSET));
+ s = gen_load_a(cstate, OR_LINKHDR, 1, BPF_B);
+ b1 = new_block(cstate, JMP(BPF_JSET));
b1->s.k = 0x02; /* From DS */
b1->stmts = s;
gen_and(b1, b0);
@@ -4102,8 +4148,8 @@ gen_wlanhostop(eaddr, dir)
/*
* Now check for data frames with From DS not set.
*/
- s = gen_load_a(OR_LINK, 1, BPF_B);
- b2 = new_block(JMP(BPF_JSET));
+ s = gen_load_a(cstate, OR_LINKHDR, 1, BPF_B);
+ b2 = new_block(cstate, JMP(BPF_JSET));
b2->s.k = 0x02; /* From DS */
b2->stmts = s;
gen_not(b2);
@@ -4111,7 +4157,7 @@ gen_wlanhostop(eaddr, dir)
/*
* If From DS isn't set, the SA is at 10.
*/
- b1 = gen_bcmp(OR_LINK, 10, 6, eaddr);
+ b1 = gen_bcmp(cstate, OR_LINKHDR, 10, 6, eaddr);
gen_and(b2, b1);
/*
@@ -4125,8 +4171,8 @@ gen_wlanhostop(eaddr, dir)
* Now check for a data frame.
* I.e, check "link[0] & 0x08".
*/
- s = gen_load_a(OR_LINK, 0, BPF_B);
- b1 = new_block(JMP(BPF_JSET));
+ s = gen_load_a(cstate, OR_LINKHDR, 0, BPF_B);
+ b1 = new_block(cstate, JMP(BPF_JSET));
b1->s.k = 0x08;
b1->stmts = s;
@@ -4140,8 +4186,8 @@ gen_wlanhostop(eaddr, dir)
* is a management frame.
* I.e, check "!(link[0] & 0x08)".
*/
- s = gen_load_a(OR_LINK, 0, BPF_B);
- b2 = new_block(JMP(BPF_JSET));
+ s = gen_load_a(cstate, OR_LINKHDR, 0, BPF_B);
+ b2 = new_block(cstate, JMP(BPF_JSET));
b2->s.k = 0x08;
b2->stmts = s;
gen_not(b2);
@@ -4149,7 +4195,7 @@ gen_wlanhostop(eaddr, dir)
/*
* For management frames, the SA is at 10.
*/
- b1 = gen_bcmp(OR_LINK, 10, 6, eaddr);
+ b1 = gen_bcmp(cstate, OR_LINKHDR, 10, 6, eaddr);
gen_and(b2, b1);
/*
@@ -4167,8 +4213,8 @@ gen_wlanhostop(eaddr, dir)
*
* I.e., check "!(link[0] & 0x04)".
*/
- s = gen_load_a(OR_LINK, 0, BPF_B);
- b1 = new_block(JMP(BPF_JSET));
+ s = gen_load_a(cstate, OR_LINKHDR, 0, BPF_B);
+ b1 = new_block(cstate, JMP(BPF_JSET));
b1->s.k = 0x04;
b1->stmts = s;
gen_not(b1);
@@ -4202,23 +4248,23 @@ gen_wlanhostop(eaddr, dir)
*
* First, check for To DS set, i.e. "link[1] & 0x01".
*/
- s = gen_load_a(OR_LINK, 1, BPF_B);
- b1 = new_block(JMP(BPF_JSET));
+ s = gen_load_a(cstate, OR_LINKHDR, 1, BPF_B);
+ b1 = new_block(cstate, JMP(BPF_JSET));
b1->s.k = 0x01; /* To DS */
b1->stmts = s;
/*
* If To DS is set, the DA is at 16.
*/
- b0 = gen_bcmp(OR_LINK, 16, 6, eaddr);
+ b0 = gen_bcmp(cstate, OR_LINKHDR, 16, 6, eaddr);
gen_and(b1, b0);
/*
* Now, check for To DS not set, i.e. check
* "!(link[1] & 0x01)".
*/
- s = gen_load_a(OR_LINK, 1, BPF_B);
- b2 = new_block(JMP(BPF_JSET));
+ s = gen_load_a(cstate, OR_LINKHDR, 1, BPF_B);
+ b2 = new_block(cstate, JMP(BPF_JSET));
b2->s.k = 0x01; /* To DS */
b2->stmts = s;
gen_not(b2);
@@ -4226,7 +4272,7 @@ gen_wlanhostop(eaddr, dir)
/*
* If To DS is not set, the DA is at 4.
*/
- b1 = gen_bcmp(OR_LINK, 4, 6, eaddr);
+ b1 = gen_bcmp(cstate, OR_LINKHDR, 4, 6, eaddr);
gen_and(b2, b1);
/*
@@ -4239,8 +4285,8 @@ gen_wlanhostop(eaddr, dir)
* Now check for a data frame.
* I.e, check "link[0] & 0x08".
*/
- s = gen_load_a(OR_LINK, 0, BPF_B);
- b1 = new_block(JMP(BPF_JSET));
+ s = gen_load_a(cstate, OR_LINKHDR, 0, BPF_B);
+ b1 = new_block(cstate, JMP(BPF_JSET));
b1->s.k = 0x08;
b1->stmts = s;
@@ -4254,8 +4300,8 @@ gen_wlanhostop(eaddr, dir)
* is a management frame.
* I.e, check "!(link[0] & 0x08)".
*/
- s = gen_load_a(OR_LINK, 0, BPF_B);
- b2 = new_block(JMP(BPF_JSET));
+ s = gen_load_a(cstate, OR_LINKHDR, 0, BPF_B);
+ b2 = new_block(cstate, JMP(BPF_JSET));
b2->s.k = 0x08;
b2->stmts = s;
gen_not(b2);
@@ -4263,7 +4309,7 @@ gen_wlanhostop(eaddr, dir)
/*
* For management frames, the DA is at 4.
*/
- b1 = gen_bcmp(OR_LINK, 4, 6, eaddr);
+ b1 = gen_bcmp(cstate, OR_LINKHDR, 4, 6, eaddr);
gen_and(b2, b1);
/*
@@ -4281,8 +4327,8 @@ gen_wlanhostop(eaddr, dir)
*
* I.e., check "!(link[0] & 0x04)".
*/
- s = gen_load_a(OR_LINK, 0, BPF_B);
- b1 = new_block(JMP(BPF_JSET));
+ s = gen_load_a(cstate, OR_LINKHDR, 0, BPF_B);
+ b1 = new_block(cstate, JMP(BPF_JSET));
b1->s.k = 0x04;
b1->stmts = s;
gen_not(b1);
@@ -4305,15 +4351,15 @@ gen_wlanhostop(eaddr, dir)
* is a management frame.
* I.e, check "(link[0] & 0x08)".
*/
- s = gen_load_a(OR_LINK, 0, BPF_B);
- b1 = new_block(JMP(BPF_JSET));
+ s = gen_load_a(cstate, OR_LINKHDR, 0, BPF_B);
+ b1 = new_block(cstate, JMP(BPF_JSET));
b1->s.k = 0x08;
b1->stmts = s;
/*
* Check addr1.
*/
- b0 = gen_bcmp(OR_LINK, 4, 6, eaddr);
+ b0 = gen_bcmp(cstate, OR_LINKHDR, 4, 6, eaddr);
/*
* AND that with the check of addr1.
@@ -4330,13 +4376,13 @@ gen_wlanhostop(eaddr, dir)
/*
* Not present in CTS or ACK control frames.
*/
- b0 = gen_mcmp(OR_LINK, 0, BPF_B, IEEE80211_FC0_TYPE_CTL,
+ b0 = gen_mcmp(cstate, OR_LINKHDR, 0, BPF_B, IEEE80211_FC0_TYPE_CTL,
IEEE80211_FC0_TYPE_MASK);
gen_not(b0);
- b1 = gen_mcmp(OR_LINK, 0, BPF_B, IEEE80211_FC0_SUBTYPE_CTS,
+ b1 = gen_mcmp(cstate, OR_LINKHDR, 0, BPF_B, IEEE80211_FC0_SUBTYPE_CTS,
IEEE80211_FC0_SUBTYPE_MASK);
gen_not(b1);
- b2 = gen_mcmp(OR_LINK, 0, BPF_B, IEEE80211_FC0_SUBTYPE_ACK,
+ b2 = gen_mcmp(cstate, OR_LINKHDR, 0, BPF_B, IEEE80211_FC0_SUBTYPE_ACK,
IEEE80211_FC0_SUBTYPE_MASK);
gen_not(b2);
gen_and(b1, b2);
@@ -4347,8 +4393,8 @@ gen_wlanhostop(eaddr, dir)
* is a management frame.
* I.e, check "(link[0] & 0x08)".
*/
- s = gen_load_a(OR_LINK, 0, BPF_B);
- b1 = new_block(JMP(BPF_JSET));
+ s = gen_load_a(cstate, OR_LINKHDR, 0, BPF_B);
+ b1 = new_block(cstate, JMP(BPF_JSET));
b1->s.k = 0x08;
b1->stmts = s;
@@ -4361,7 +4407,7 @@ gen_wlanhostop(eaddr, dir)
/*
* Check addr2.
*/
- b1 = gen_bcmp(OR_LINK, 10, 6, eaddr);
+ b1 = gen_bcmp(cstate, OR_LINKHDR, 10, 6, eaddr);
gen_and(b2, b1);
return b1;
@@ -4369,24 +4415,24 @@ gen_wlanhostop(eaddr, dir)
* XXX - add BSSID keyword?
*/
case Q_ADDR1:
- return (gen_bcmp(OR_LINK, 4, 6, eaddr));
+ return (gen_bcmp(cstate, OR_LINKHDR, 4, 6, eaddr));
case Q_ADDR2:
/*
* Not present in CTS or ACK control frames.
*/
- b0 = gen_mcmp(OR_LINK, 0, BPF_B, IEEE80211_FC0_TYPE_CTL,
+ b0 = gen_mcmp(cstate, OR_LINKHDR, 0, BPF_B, IEEE80211_FC0_TYPE_CTL,
IEEE80211_FC0_TYPE_MASK);
gen_not(b0);
- b1 = gen_mcmp(OR_LINK, 0, BPF_B, IEEE80211_FC0_SUBTYPE_CTS,
+ b1 = gen_mcmp(cstate, OR_LINKHDR, 0, BPF_B, IEEE80211_FC0_SUBTYPE_CTS,
IEEE80211_FC0_SUBTYPE_MASK);
gen_not(b1);
- b2 = gen_mcmp(OR_LINK, 0, BPF_B, IEEE80211_FC0_SUBTYPE_ACK,
+ b2 = gen_mcmp(cstate, OR_LINKHDR, 0, BPF_B, IEEE80211_FC0_SUBTYPE_ACK,
IEEE80211_FC0_SUBTYPE_MASK);
gen_not(b2);
gen_and(b1, b2);
gen_or(b0, b2);
- b1 = gen_bcmp(OR_LINK, 10, 6, eaddr);
+ b1 = gen_bcmp(cstate, OR_LINKHDR, 10, 6, eaddr);
gen_and(b2, b1);
return b1;
@@ -4394,10 +4440,10 @@ gen_wlanhostop(eaddr, dir)
/*
* Not present in control frames.
*/
- b0 = gen_mcmp(OR_LINK, 0, BPF_B, IEEE80211_FC0_TYPE_CTL,
+ b0 = gen_mcmp(cstate, OR_LINKHDR, 0, BPF_B, IEEE80211_FC0_TYPE_CTL,
IEEE80211_FC0_TYPE_MASK);
gen_not(b0);
- b1 = gen_bcmp(OR_LINK, 16, 6, eaddr);
+ b1 = gen_bcmp(cstate, OR_LINKHDR, 16, 6, eaddr);
gen_and(b0, b1);
return b1;
@@ -4408,22 +4454,22 @@ gen_wlanhostop(eaddr, dir)
* frames should have both of those set, so we don't
* check the frame type.
*/
- b0 = gen_mcmp(OR_LINK, 1, BPF_B,
+ b0 = gen_mcmp(cstate, OR_LINKHDR, 1, BPF_B,
IEEE80211_FC1_DIR_DSTODS, IEEE80211_FC1_DIR_MASK);
- b1 = gen_bcmp(OR_LINK, 24, 6, eaddr);
+ b1 = gen_bcmp(cstate, OR_LINKHDR, 24, 6, eaddr);
gen_and(b0, b1);
return b1;
case Q_AND:
- b0 = gen_wlanhostop(eaddr, Q_SRC);
- b1 = gen_wlanhostop(eaddr, Q_DST);
+ b0 = gen_wlanhostop(cstate, eaddr, Q_SRC);
+ b1 = gen_wlanhostop(cstate, eaddr, Q_DST);
gen_and(b0, b1);
return b1;
case Q_DEFAULT:
case Q_OR:
- b0 = gen_wlanhostop(eaddr, Q_SRC);
- b1 = gen_wlanhostop(eaddr, Q_DST);
+ b0 = gen_wlanhostop(cstate, eaddr, Q_SRC);
+ b1 = gen_wlanhostop(cstate, eaddr, Q_DST);
gen_or(b0, b1);
return b1;
}
@@ -4437,54 +4483,52 @@ gen_wlanhostop(eaddr, dir)
* as the RFC states.)
*/
static struct block *
-gen_ipfchostop(eaddr, dir)
- register const u_char *eaddr;
- register int dir;
+gen_ipfchostop(compiler_state_t *cstate, const u_char *eaddr, int dir)
{
register struct block *b0, *b1;
switch (dir) {
case Q_SRC:
- return gen_bcmp(OR_LINK, 10, 6, eaddr);
+ return gen_bcmp(cstate, OR_LINKHDR, 10, 6, eaddr);
case Q_DST:
- return gen_bcmp(OR_LINK, 2, 6, eaddr);
+ return gen_bcmp(cstate, OR_LINKHDR, 2, 6, eaddr);
case Q_AND:
- b0 = gen_ipfchostop(eaddr, Q_SRC);
- b1 = gen_ipfchostop(eaddr, Q_DST);
+ b0 = gen_ipfchostop(cstate, eaddr, Q_SRC);
+ b1 = gen_ipfchostop(cstate, eaddr, Q_DST);
gen_and(b0, b1);
return b1;
case Q_DEFAULT:
case Q_OR:
- b0 = gen_ipfchostop(eaddr, Q_SRC);
- b1 = gen_ipfchostop(eaddr, Q_DST);
+ b0 = gen_ipfchostop(cstate, eaddr, Q_SRC);
+ b1 = gen_ipfchostop(cstate, eaddr, Q_DST);
gen_or(b0, b1);
return b1;
case Q_ADDR1:
- bpf_error("'addr1' is only supported on 802.11");
+ bpf_error(cstate, "'addr1' is only supported on 802.11");
break;
case Q_ADDR2:
- bpf_error("'addr2' is only supported on 802.11");
+ bpf_error(cstate, "'addr2' is only supported on 802.11");
break;
case Q_ADDR3:
- bpf_error("'addr3' is only supported on 802.11");
+ bpf_error(cstate, "'addr3' is only supported on 802.11");
break;
case Q_ADDR4:
- bpf_error("'addr4' is only supported on 802.11");
+ bpf_error(cstate, "'addr4' is only supported on 802.11");
break;
case Q_RA:
- bpf_error("'ra' is only supported on 802.11");
+ bpf_error(cstate, "'ra' is only supported on 802.11");
break;
case Q_TA:
- bpf_error("'ta' is only supported on 802.11");
+ bpf_error(cstate, "'ta' is only supported on 802.11");
break;
}
abort();
@@ -4510,9 +4554,7 @@ gen_ipfchostop(eaddr, dir)
* and not generate masking instructions if the mask is 0xFFFF.
*/
static struct block *
-gen_dnhostop(addr, dir)
- bpf_u_int32 addr;
- int dir;
+gen_dnhostop(compiler_state_t *cstate, bpf_u_int32 addr, int dir)
{
struct block *b0, *b1, *b2, *tmp;
u_int offset_lh; /* offset if long header is received */
@@ -4532,50 +4574,50 @@ gen_dnhostop(addr, dir)
case Q_AND:
/* Inefficient because we do our Calvinball dance twice */
- b0 = gen_dnhostop(addr, Q_SRC);
- b1 = gen_dnhostop(addr, Q_DST);
+ b0 = gen_dnhostop(cstate, addr, Q_SRC);
+ b1 = gen_dnhostop(cstate, addr, Q_DST);
gen_and(b0, b1);
return b1;
case Q_OR:
case Q_DEFAULT:
/* Inefficient because we do our Calvinball dance twice */
- b0 = gen_dnhostop(addr, Q_SRC);
- b1 = gen_dnhostop(addr, Q_DST);
+ b0 = gen_dnhostop(cstate, addr, Q_SRC);
+ b1 = gen_dnhostop(cstate, addr, Q_DST);
gen_or(b0, b1);
return b1;
case Q_ISO:
- bpf_error("ISO host filtering not implemented");
+ bpf_error(cstate, "ISO host filtering not implemented");
default:
abort();
}
- b0 = gen_linktype(ETHERTYPE_DN);
+ b0 = gen_linktype(cstate, ETHERTYPE_DN);
/* Check for pad = 1, long header case */
- tmp = gen_mcmp(OR_NET, 2, BPF_H,
+ tmp = gen_mcmp(cstate, OR_LINKPL, 2, BPF_H,
(bpf_int32)ntohs(0x0681), (bpf_int32)ntohs(0x07FF));
- b1 = gen_cmp(OR_NET, 2 + 1 + offset_lh,
+ b1 = gen_cmp(cstate, OR_LINKPL, 2 + 1 + offset_lh,
BPF_H, (bpf_int32)ntohs((u_short)addr));
gen_and(tmp, b1);
/* Check for pad = 0, long header case */
- tmp = gen_mcmp(OR_NET, 2, BPF_B, (bpf_int32)0x06, (bpf_int32)0x7);
- b2 = gen_cmp(OR_NET, 2 + offset_lh, BPF_H, (bpf_int32)ntohs((u_short)addr));
+ tmp = gen_mcmp(cstate, OR_LINKPL, 2, BPF_B, (bpf_int32)0x06, (bpf_int32)0x7);
+ b2 = gen_cmp(cstate, OR_LINKPL, 2 + offset_lh, BPF_H, (bpf_int32)ntohs((u_short)addr));
gen_and(tmp, b2);
gen_or(b2, b1);
/* Check for pad = 1, short header case */
- tmp = gen_mcmp(OR_NET, 2, BPF_H,
+ tmp = gen_mcmp(cstate, OR_LINKPL, 2, BPF_H,
(bpf_int32)ntohs(0x0281), (bpf_int32)ntohs(0x07FF));
- b2 = gen_cmp(OR_NET, 2 + 1 + offset_sh, BPF_H, (bpf_int32)ntohs((u_short)addr));
+ b2 = gen_cmp(cstate, OR_LINKPL, 2 + 1 + offset_sh, BPF_H, (bpf_int32)ntohs((u_short)addr));
gen_and(tmp, b2);
gen_or(b2, b1);
/* Check for pad = 0, short header case */
- tmp = gen_mcmp(OR_NET, 2, BPF_B, (bpf_int32)0x02, (bpf_int32)0x7);
- b2 = gen_cmp(OR_NET, 2 + offset_sh, BPF_H, (bpf_int32)ntohs((u_short)addr));
+ tmp = gen_mcmp(cstate, OR_LINKPL, 2, BPF_B, (bpf_int32)0x02, (bpf_int32)0x7);
+ b2 = gen_cmp(cstate, OR_LINKPL, 2 + offset_sh, BPF_H, (bpf_int32)ntohs((u_short)addr));
gen_and(tmp, b2);
gen_or(b2, b1);
- /* Combine with test for linktype */
+ /* Combine with test for cstate->linktype */
gen_and(b0, b1);
return b1;
}
@@ -4586,8 +4628,7 @@ gen_dnhostop(addr, dir)
* field in the IP header.
*/
static struct block *
-gen_mpls_linktype(proto)
- int proto;
+gen_mpls_linktype(compiler_state_t *cstate, int proto)
{
struct block *b0, *b1;
@@ -4595,17 +4636,17 @@ gen_mpls_linktype(proto)
case Q_IP:
/* match the bottom-of-stack bit */
- b0 = gen_mcmp(OR_NET, -2, BPF_B, 0x01, 0x01);
+ b0 = gen_mcmp(cstate, OR_LINKPL, -2, BPF_B, 0x01, 0x01);
/* match the IPv4 version number */
- b1 = gen_mcmp(OR_NET, 0, BPF_B, 0x40, 0xf0);
+ b1 = gen_mcmp(cstate, OR_LINKPL, 0, BPF_B, 0x40, 0xf0);
gen_and(b0, b1);
return b1;
case Q_IPV6:
/* match the bottom-of-stack bit */
- b0 = gen_mcmp(OR_NET, -2, BPF_B, 0x01, 0x01);
+ b0 = gen_mcmp(cstate, OR_LINKPL, -2, BPF_B, 0x01, 0x01);
/* match the IPv4 version number */
- b1 = gen_mcmp(OR_NET, 0, BPF_B, 0x60, 0xf0);
+ b1 = gen_mcmp(cstate, OR_LINKPL, 0, BPF_B, 0x60, 0xf0);
gen_and(b0, b1);
return b1;
@@ -4615,12 +4656,8 @@ gen_mpls_linktype(proto)
}
static struct block *
-gen_host(addr, mask, proto, dir, type)
- bpf_u_int32 addr;
- bpf_u_int32 mask;
- int proto;
- int dir;
- int type;
+gen_host(compiler_state_t *cstate, bpf_u_int32 addr, bpf_u_int32 mask,
+ int proto, int dir, int type)
{
struct block *b0, *b1;
const char *typestr;
@@ -4633,111 +4670,111 @@ gen_host(addr, mask, proto, dir, type)
switch (proto) {
case Q_DEFAULT:
- b0 = gen_host(addr, mask, Q_IP, dir, type);
+ b0 = gen_host(cstate, addr, mask, Q_IP, dir, type);
/*
* Only check for non-IPv4 addresses if we're not
* checking MPLS-encapsulated packets.
*/
- if (label_stack_depth == 0) {
- b1 = gen_host(addr, mask, Q_ARP, dir, type);
+ if (cstate->label_stack_depth == 0) {
+ b1 = gen_host(cstate, addr, mask, Q_ARP, dir, type);
gen_or(b0, b1);
- b0 = gen_host(addr, mask, Q_RARP, dir, type);
+ b0 = gen_host(cstate, addr, mask, Q_RARP, dir, type);
gen_or(b1, b0);
}
return b0;
case Q_IP:
- return gen_hostop(addr, mask, dir, ETHERTYPE_IP, 12, 16);
+ return gen_hostop(cstate, addr, mask, dir, ETHERTYPE_IP, 12, 16);
case Q_RARP:
- return gen_hostop(addr, mask, dir, ETHERTYPE_REVARP, 14, 24);
+ return gen_hostop(cstate, addr, mask, dir, ETHERTYPE_REVARP, 14, 24);
case Q_ARP:
- return gen_hostop(addr, mask, dir, ETHERTYPE_ARP, 14, 24);
+ return gen_hostop(cstate, addr, mask, dir, ETHERTYPE_ARP, 14, 24);
case Q_TCP:
- bpf_error("'tcp' modifier applied to %s", typestr);
+ bpf_error(cstate, "'tcp' modifier applied to %s", typestr);
case Q_SCTP:
- bpf_error("'sctp' modifier applied to %s", typestr);
+ bpf_error(cstate, "'sctp' modifier applied to %s", typestr);
case Q_UDP:
- bpf_error("'udp' modifier applied to %s", typestr);
+ bpf_error(cstate, "'udp' modifier applied to %s", typestr);
case Q_ICMP:
- bpf_error("'icmp' modifier applied to %s", typestr);
+ bpf_error(cstate, "'icmp' modifier applied to %s", typestr);
case Q_IGMP:
- bpf_error("'igmp' modifier applied to %s", typestr);
+ bpf_error(cstate, "'igmp' modifier applied to %s", typestr);
case Q_IGRP:
- bpf_error("'igrp' modifier applied to %s", typestr);
+ bpf_error(cstate, "'igrp' modifier applied to %s", typestr);
case Q_PIM:
- bpf_error("'pim' modifier applied to %s", typestr);
+ bpf_error(cstate, "'pim' modifier applied to %s", typestr);
case Q_VRRP:
- bpf_error("'vrrp' modifier applied to %s", typestr);
+ bpf_error(cstate, "'vrrp' modifier applied to %s", typestr);
case Q_CARP:
- bpf_error("'carp' modifier applied to %s", typestr);
+ bpf_error(cstate, "'carp' modifier applied to %s", typestr);
case Q_ATALK:
- bpf_error("ATALK host filtering not implemented");
+ bpf_error(cstate, "ATALK host filtering not implemented");
case Q_AARP:
- bpf_error("AARP host filtering not implemented");
+ bpf_error(cstate, "AARP host filtering not implemented");
case Q_DECNET:
- return gen_dnhostop(addr, dir);
+ return gen_dnhostop(cstate, addr, dir);
case Q_SCA:
- bpf_error("SCA host filtering not implemented");
+ bpf_error(cstate, "SCA host filtering not implemented");
case Q_LAT:
- bpf_error("LAT host filtering not implemented");
+ bpf_error(cstate, "LAT host filtering not implemented");
case Q_MOPDL:
- bpf_error("MOPDL host filtering not implemented");
+ bpf_error(cstate, "MOPDL host filtering not implemented");
case Q_MOPRC:
- bpf_error("MOPRC host filtering not implemented");
+ bpf_error(cstate, "MOPRC host filtering not implemented");
case Q_IPV6:
- bpf_error("'ip6' modifier applied to ip host");
+ bpf_error(cstate, "'ip6' modifier applied to ip host");
case Q_ICMPV6:
- bpf_error("'icmp6' modifier applied to %s", typestr);
+ bpf_error(cstate, "'icmp6' modifier applied to %s", typestr);
case Q_AH:
- bpf_error("'ah' modifier applied to %s", typestr);
+ bpf_error(cstate, "'ah' modifier applied to %s", typestr);
case Q_ESP:
- bpf_error("'esp' modifier applied to %s", typestr);
+ bpf_error(cstate, "'esp' modifier applied to %s", typestr);
case Q_ISO:
- bpf_error("ISO host filtering not implemented");
+ bpf_error(cstate, "ISO host filtering not implemented");
case Q_ESIS:
- bpf_error("'esis' modifier applied to %s", typestr);
+ bpf_error(cstate, "'esis' modifier applied to %s", typestr);
case Q_ISIS:
- bpf_error("'isis' modifier applied to %s", typestr);
+ bpf_error(cstate, "'isis' modifier applied to %s", typestr);
case Q_CLNP:
- bpf_error("'clnp' modifier applied to %s", typestr);
+ bpf_error(cstate, "'clnp' modifier applied to %s", typestr);
case Q_STP:
- bpf_error("'stp' modifier applied to %s", typestr);
+ bpf_error(cstate, "'stp' modifier applied to %s", typestr);
case Q_IPX:
- bpf_error("IPX host filtering not implemented");
+ bpf_error(cstate, "IPX host filtering not implemented");
case Q_NETBEUI:
- bpf_error("'netbeui' modifier applied to %s", typestr);
+ bpf_error(cstate, "'netbeui' modifier applied to %s", typestr);
case Q_RADIO:
- bpf_error("'radio' modifier applied to %s", typestr);
+ bpf_error(cstate, "'radio' modifier applied to %s", typestr);
default:
abort();
@@ -4747,12 +4784,8 @@ gen_host(addr, mask, proto, dir, type)
#ifdef INET6
static struct block *
-gen_host6(addr, mask, proto, dir, type)
- struct in6_addr *addr;
- struct in6_addr *mask;
- int proto;
- int dir;
- int type;
+gen_host6(compiler_state_t *cstate, struct in6_addr *addr,
+ struct in6_addr *mask, int proto, int dir, int type)
{
const char *typestr;
@@ -4764,103 +4797,103 @@ gen_host6(addr, mask, proto, dir, type)
switch (proto) {
case Q_DEFAULT:
- return gen_host6(addr, mask, Q_IPV6, dir, type);
+ return gen_host6(cstate, addr, mask, Q_IPV6, dir, type);
case Q_LINK:
- bpf_error("link-layer modifier applied to ip6 %s", typestr);
+ bpf_error(cstate, "link-layer modifier applied to ip6 %s", typestr);
case Q_IP:
- bpf_error("'ip' modifier applied to ip6 %s", typestr);
+ bpf_error(cstate, "'ip' modifier applied to ip6 %s", typestr);
case Q_RARP:
- bpf_error("'rarp' modifier applied to ip6 %s", typestr);
+ bpf_error(cstate, "'rarp' modifier applied to ip6 %s", typestr);
case Q_ARP:
- bpf_error("'arp' modifier applied to ip6 %s", typestr);
+ bpf_error(cstate, "'arp' modifier applied to ip6 %s", typestr);
case Q_SCTP:
- bpf_error("'sctp' modifier applied to %s", typestr);
+ bpf_error(cstate, "'sctp' modifier applied to %s", typestr);
case Q_TCP:
- bpf_error("'tcp' modifier applied to %s", typestr);
+ bpf_error(cstate, "'tcp' modifier applied to %s", typestr);
case Q_UDP:
- bpf_error("'udp' modifier applied to %s", typestr);
+ bpf_error(cstate, "'udp' modifier applied to %s", typestr);
case Q_ICMP:
- bpf_error("'icmp' modifier applied to %s", typestr);
+ bpf_error(cstate, "'icmp' modifier applied to %s", typestr);
case Q_IGMP:
- bpf_error("'igmp' modifier applied to %s", typestr);
+ bpf_error(cstate, "'igmp' modifier applied to %s", typestr);
case Q_IGRP:
- bpf_error("'igrp' modifier applied to %s", typestr);
+ bpf_error(cstate, "'igrp' modifier applied to %s", typestr);
case Q_PIM:
- bpf_error("'pim' modifier applied to %s", typestr);
+ bpf_error(cstate, "'pim' modifier applied to %s", typestr);
case Q_VRRP:
- bpf_error("'vrrp' modifier applied to %s", typestr);
+ bpf_error(cstate, "'vrrp' modifier applied to %s", typestr);
case Q_CARP:
- bpf_error("'carp' modifier applied to %s", typestr);
+ bpf_error(cstate, "'carp' modifier applied to %s", typestr);
case Q_ATALK:
- bpf_error("ATALK host filtering not implemented");
+ bpf_error(cstate, "ATALK host filtering not implemented");
case Q_AARP:
- bpf_error("AARP host filtering not implemented");
+ bpf_error(cstate, "AARP host filtering not implemented");
case Q_DECNET:
- bpf_error("'decnet' modifier applied to ip6 %s", typestr);
+ bpf_error(cstate, "'decnet' modifier applied to ip6 %s", typestr);
case Q_SCA:
- bpf_error("SCA host filtering not implemented");
+ bpf_error(cstate, "SCA host filtering not implemented");
case Q_LAT:
- bpf_error("LAT host filtering not implemented");
+ bpf_error(cstate, "LAT host filtering not implemented");
case Q_MOPDL:
- bpf_error("MOPDL host filtering not implemented");
+ bpf_error(cstate, "MOPDL host filtering not implemented");
case Q_MOPRC:
- bpf_error("MOPRC host filtering not implemented");
+ bpf_error(cstate, "MOPRC host filtering not implemented");
case Q_IPV6:
- return gen_hostop6(addr, mask, dir, ETHERTYPE_IPV6, 8, 24);
+ return gen_hostop6(cstate, addr, mask, dir, ETHERTYPE_IPV6, 8, 24);
case Q_ICMPV6:
- bpf_error("'icmp6' modifier applied to %s", typestr);
+ bpf_error(cstate, "'icmp6' modifier applied to %s", typestr);
case Q_AH:
- bpf_error("'ah' modifier applied to %s", typestr);
+ bpf_error(cstate, "'ah' modifier applied to %s", typestr);
case Q_ESP:
- bpf_error("'esp' modifier applied to %s", typestr);
+ bpf_error(cstate, "'esp' modifier applied to %s", typestr);
case Q_ISO:
- bpf_error("ISO host filtering not implemented");
+ bpf_error(cstate, "ISO host filtering not implemented");
case Q_ESIS:
- bpf_error("'esis' modifier applied to %s", typestr);
+ bpf_error(cstate, "'esis' modifier applied to %s", typestr);
case Q_ISIS:
- bpf_error("'isis' modifier applied to %s", typestr);
+ bpf_error(cstate, "'isis' modifier applied to %s", typestr);
case Q_CLNP:
- bpf_error("'clnp' modifier applied to %s", typestr);
+ bpf_error(cstate, "'clnp' modifier applied to %s", typestr);
case Q_STP:
- bpf_error("'stp' modifier applied to %s", typestr);
+ bpf_error(cstate, "'stp' modifier applied to %s", typestr);
case Q_IPX:
- bpf_error("IPX host filtering not implemented");
+ bpf_error(cstate, "IPX host filtering not implemented");
case Q_NETBEUI:
- bpf_error("'netbeui' modifier applied to %s", typestr);
+ bpf_error(cstate, "'netbeui' modifier applied to %s", typestr);
case Q_RADIO:
- bpf_error("'radio' modifier applied to %s", typestr);
+ bpf_error(cstate, "'radio' modifier applied to %s", typestr);
default:
abort();
@@ -4880,61 +4913,54 @@ gen_gateway(eaddr, alist, proto, dir)
struct block *b0, *b1, *tmp;
if (dir != 0)
- bpf_error("direction applied to 'gateway'");
+ bpf_error(cstate, "direction applied to 'gateway'");
switch (proto) {
case Q_DEFAULT:
case Q_IP:
case Q_ARP:
case Q_RARP:
- switch (linktype) {
+ switch (cstate->linktype) {
case DLT_EN10MB:
case DLT_NETANALYZER:
case DLT_NETANALYZER_TRANSPARENT:
- b0 = gen_ehostop(eaddr, Q_OR);
+ b1 = gen_prevlinkhdr_check(cstate);
+ b0 = gen_ehostop(cstate, eaddr, Q_OR);
+ if (b1 != NULL)
+ gen_and(b1, b0);
break;
case DLT_FDDI:
- b0 = gen_fhostop(eaddr, Q_OR);
+ b0 = gen_fhostop(cstate, eaddr, Q_OR);
break;
case DLT_IEEE802:
- b0 = gen_thostop(eaddr, Q_OR);
+ b0 = gen_thostop(cstate, eaddr, Q_OR);
break;
case DLT_IEEE802_11:
case DLT_PRISM_HEADER:
case DLT_IEEE802_11_RADIO_AVS:
case DLT_IEEE802_11_RADIO:
case DLT_PPI:
- b0 = gen_wlanhostop(eaddr, Q_OR);
+ b0 = gen_wlanhostop(cstate, eaddr, Q_OR);
break;
case DLT_SUNATM:
- if (!is_lane)
- bpf_error(
- "'gateway' supported only on ethernet/FDDI/token ring/802.11/ATM LANE/Fibre Channel");
- /*
- * Check that the packet doesn't begin with an
- * LE Control marker. (We've already generated
- * a test for LANE.)
- */
- b1 = gen_cmp(OR_LINK, SUNATM_PKT_BEGIN_POS,
- BPF_H, 0xFF00);
- gen_not(b1);
-
/*
- * Now check the MAC address.
+ * This is LLC-multiplexed traffic; if it were
+ * LANE, cstate->linktype would have been set to
+ * DLT_EN10MB.
*/
- b0 = gen_ehostop(eaddr, Q_OR);
- gen_and(b1, b0);
+ bpf_error(cstate,
+ "'gateway' supported only on ethernet/FDDI/token ring/802.11/ATM LANE/Fibre Channel");
break;
case DLT_IP_OVER_FC:
- b0 = gen_ipfchostop(eaddr, Q_OR);
+ b0 = gen_ipfchostop(cstate, eaddr, Q_OR);
break;
default:
- bpf_error(
+ bpf_error(cstate,
"'gateway' supported only on ethernet/FDDI/token ring/802.11/ATM LANE/Fibre Channel");
}
- b1 = gen_host(**alist++, 0xffffffff, proto, Q_OR, Q_HOST);
+ b1 = gen_host(cstate, **alist++, 0xffffffff, proto, Q_OR, Q_HOST);
while (*alist) {
- tmp = gen_host(**alist++, 0xffffffff, proto, Q_OR,
+ tmp = gen_host(cstate, **alist++, 0xffffffff, proto, Q_OR,
Q_HOST);
gen_or(b1, tmp);
b1 = tmp;
@@ -4943,14 +4969,13 @@ gen_gateway(eaddr, alist, proto, dir)
gen_and(b0, b1);
return b1;
}
- bpf_error("illegal modifier of 'gateway'");
+ bpf_error(cstate, "illegal modifier of 'gateway'");
/* NOTREACHED */
}
#endif
struct block *
-gen_proto_abbrev(proto)
- int proto;
+gen_proto_abbrev(compiler_state_t *cstate, int proto)
{
struct block *b0;
struct block *b1;
@@ -4958,25 +4983,25 @@ gen_proto_abbrev(proto)
switch (proto) {
case Q_SCTP:
- b1 = gen_proto(IPPROTO_SCTP, Q_IP, Q_DEFAULT);
- b0 = gen_proto(IPPROTO_SCTP, Q_IPV6, Q_DEFAULT);
+ b1 = gen_proto(cstate, IPPROTO_SCTP, Q_IP, Q_DEFAULT);
+ b0 = gen_proto(cstate, IPPROTO_SCTP, Q_IPV6, Q_DEFAULT);
gen_or(b0, b1);
break;
case Q_TCP:
- b1 = gen_proto(IPPROTO_TCP, Q_IP, Q_DEFAULT);
- b0 = gen_proto(IPPROTO_TCP, Q_IPV6, Q_DEFAULT);
+ b1 = gen_proto(cstate, IPPROTO_TCP, Q_IP, Q_DEFAULT);
+ b0 = gen_proto(cstate, IPPROTO_TCP, Q_IPV6, Q_DEFAULT);
gen_or(b0, b1);
break;
case Q_UDP:
- b1 = gen_proto(IPPROTO_UDP, Q_IP, Q_DEFAULT);
- b0 = gen_proto(IPPROTO_UDP, Q_IPV6, Q_DEFAULT);
+ b1 = gen_proto(cstate, IPPROTO_UDP, Q_IP, Q_DEFAULT);
+ b0 = gen_proto(cstate, IPPROTO_UDP, Q_IPV6, Q_DEFAULT);
gen_or(b0, b1);
break;
case Q_ICMP:
- b1 = gen_proto(IPPROTO_ICMP, Q_IP, Q_DEFAULT);
+ b1 = gen_proto(cstate, IPPROTO_ICMP, Q_IP, Q_DEFAULT);
break;
#ifndef IPPROTO_IGMP
@@ -4984,14 +5009,14 @@ gen_proto_abbrev(proto)
#endif
case Q_IGMP:
- b1 = gen_proto(IPPROTO_IGMP, Q_IP, Q_DEFAULT);
+ b1 = gen_proto(cstate, IPPROTO_IGMP, Q_IP, Q_DEFAULT);
break;
#ifndef IPPROTO_IGRP
#define IPPROTO_IGRP 9
#endif
case Q_IGRP:
- b1 = gen_proto(IPPROTO_IGRP, Q_IP, Q_DEFAULT);
+ b1 = gen_proto(cstate, IPPROTO_IGRP, Q_IP, Q_DEFAULT);
break;
#ifndef IPPROTO_PIM
@@ -4999,8 +5024,8 @@ gen_proto_abbrev(proto)
#endif
case Q_PIM:
- b1 = gen_proto(IPPROTO_PIM, Q_IP, Q_DEFAULT);
- b0 = gen_proto(IPPROTO_PIM, Q_IPV6, Q_DEFAULT);
+ b1 = gen_proto(cstate, IPPROTO_PIM, Q_IP, Q_DEFAULT);
+ b0 = gen_proto(cstate, IPPROTO_PIM, Q_IPV6, Q_DEFAULT);
gen_or(b0, b1);
break;
@@ -5009,7 +5034,7 @@ gen_proto_abbrev(proto)
#endif
case Q_VRRP:
- b1 = gen_proto(IPPROTO_VRRP, Q_IP, Q_DEFAULT);
+ b1 = gen_proto(cstate, IPPROTO_VRRP, Q_IP, Q_DEFAULT);
break;
#ifndef IPPROTO_CARP
@@ -5017,69 +5042,69 @@ gen_proto_abbrev(proto)
#endif
case Q_CARP:
- b1 = gen_proto(IPPROTO_CARP, Q_IP, Q_DEFAULT);
+ b1 = gen_proto(cstate, IPPROTO_CARP, Q_IP, Q_DEFAULT);
break;
case Q_IP:
- b1 = gen_linktype(ETHERTYPE_IP);
+ b1 = gen_linktype(cstate, ETHERTYPE_IP);
break;
case Q_ARP:
- b1 = gen_linktype(ETHERTYPE_ARP);
+ b1 = gen_linktype(cstate, ETHERTYPE_ARP);
break;
case Q_RARP:
- b1 = gen_linktype(ETHERTYPE_REVARP);
+ b1 = gen_linktype(cstate, ETHERTYPE_REVARP);
break;
case Q_LINK:
- bpf_error("link layer applied in wrong context");
+ bpf_error(cstate, "link layer applied in wrong context");
case Q_ATALK:
- b1 = gen_linktype(ETHERTYPE_ATALK);
+ b1 = gen_linktype(cstate, ETHERTYPE_ATALK);
break;
case Q_AARP:
- b1 = gen_linktype(ETHERTYPE_AARP);
+ b1 = gen_linktype(cstate, ETHERTYPE_AARP);
break;
case Q_DECNET:
- b1 = gen_linktype(ETHERTYPE_DN);
+ b1 = gen_linktype(cstate, ETHERTYPE_DN);
break;
case Q_SCA:
- b1 = gen_linktype(ETHERTYPE_SCA);
+ b1 = gen_linktype(cstate, ETHERTYPE_SCA);
break;
case Q_LAT:
- b1 = gen_linktype(ETHERTYPE_LAT);
+ b1 = gen_linktype(cstate, ETHERTYPE_LAT);
break;
case Q_MOPDL:
- b1 = gen_linktype(ETHERTYPE_MOPDL);
+ b1 = gen_linktype(cstate, ETHERTYPE_MOPDL);
break;
case Q_MOPRC:
- b1 = gen_linktype(ETHERTYPE_MOPRC);
+ b1 = gen_linktype(cstate, ETHERTYPE_MOPRC);
break;
case Q_IPV6:
- b1 = gen_linktype(ETHERTYPE_IPV6);
+ b1 = gen_linktype(cstate, ETHERTYPE_IPV6);
break;
#ifndef IPPROTO_ICMPV6
#define IPPROTO_ICMPV6 58
#endif
case Q_ICMPV6:
- b1 = gen_proto(IPPROTO_ICMPV6, Q_IPV6, Q_DEFAULT);
+ b1 = gen_proto(cstate, IPPROTO_ICMPV6, Q_IPV6, Q_DEFAULT);
break;
#ifndef IPPROTO_AH
#define IPPROTO_AH 51
#endif
case Q_AH:
- b1 = gen_proto(IPPROTO_AH, Q_IP, Q_DEFAULT);
- b0 = gen_proto(IPPROTO_AH, Q_IPV6, Q_DEFAULT);
+ b1 = gen_proto(cstate, IPPROTO_AH, Q_IP, Q_DEFAULT);
+ b0 = gen_proto(cstate, IPPROTO_AH, Q_IPV6, Q_DEFAULT);
gen_or(b0, b1);
break;
@@ -5087,101 +5112,101 @@ gen_proto_abbrev(proto)
#define IPPROTO_ESP 50
#endif
case Q_ESP:
- b1 = gen_proto(IPPROTO_ESP, Q_IP, Q_DEFAULT);
- b0 = gen_proto(IPPROTO_ESP, Q_IPV6, Q_DEFAULT);
+ b1 = gen_proto(cstate, IPPROTO_ESP, Q_IP, Q_DEFAULT);
+ b0 = gen_proto(cstate, IPPROTO_ESP, Q_IPV6, Q_DEFAULT);
gen_or(b0, b1);
break;
case Q_ISO:
- b1 = gen_linktype(LLCSAP_ISONS);
+ b1 = gen_linktype(cstate, LLCSAP_ISONS);
break;
case Q_ESIS:
- b1 = gen_proto(ISO9542_ESIS, Q_ISO, Q_DEFAULT);
+ b1 = gen_proto(cstate, ISO9542_ESIS, Q_ISO, Q_DEFAULT);
break;
case Q_ISIS:
- b1 = gen_proto(ISO10589_ISIS, Q_ISO, Q_DEFAULT);
+ b1 = gen_proto(cstate, ISO10589_ISIS, Q_ISO, Q_DEFAULT);
break;
case Q_ISIS_L1: /* all IS-IS Level1 PDU-Types */
- b0 = gen_proto(ISIS_L1_LAN_IIH, Q_ISIS, Q_DEFAULT);
- b1 = gen_proto(ISIS_PTP_IIH, Q_ISIS, Q_DEFAULT); /* FIXME extract the circuit-type bits */
+ b0 = gen_proto(cstate, ISIS_L1_LAN_IIH, Q_ISIS, Q_DEFAULT);
+ b1 = gen_proto(cstate, ISIS_PTP_IIH, Q_ISIS, Q_DEFAULT); /* FIXME extract the circuit-type bits */
gen_or(b0, b1);
- b0 = gen_proto(ISIS_L1_LSP, Q_ISIS, Q_DEFAULT);
+ b0 = gen_proto(cstate, ISIS_L1_LSP, Q_ISIS, Q_DEFAULT);
gen_or(b0, b1);
- b0 = gen_proto(ISIS_L1_CSNP, Q_ISIS, Q_DEFAULT);
+ b0 = gen_proto(cstate, ISIS_L1_CSNP, Q_ISIS, Q_DEFAULT);
gen_or(b0, b1);
- b0 = gen_proto(ISIS_L1_PSNP, Q_ISIS, Q_DEFAULT);
+ b0 = gen_proto(cstate, ISIS_L1_PSNP, Q_ISIS, Q_DEFAULT);
gen_or(b0, b1);
break;
case Q_ISIS_L2: /* all IS-IS Level2 PDU-Types */
- b0 = gen_proto(ISIS_L2_LAN_IIH, Q_ISIS, Q_DEFAULT);
- b1 = gen_proto(ISIS_PTP_IIH, Q_ISIS, Q_DEFAULT); /* FIXME extract the circuit-type bits */
+ b0 = gen_proto(cstate, ISIS_L2_LAN_IIH, Q_ISIS, Q_DEFAULT);
+ b1 = gen_proto(cstate, ISIS_PTP_IIH, Q_ISIS, Q_DEFAULT); /* FIXME extract the circuit-type bits */
gen_or(b0, b1);
- b0 = gen_proto(ISIS_L2_LSP, Q_ISIS, Q_DEFAULT);
+ b0 = gen_proto(cstate, ISIS_L2_LSP, Q_ISIS, Q_DEFAULT);
gen_or(b0, b1);
- b0 = gen_proto(ISIS_L2_CSNP, Q_ISIS, Q_DEFAULT);
+ b0 = gen_proto(cstate, ISIS_L2_CSNP, Q_ISIS, Q_DEFAULT);
gen_or(b0, b1);
- b0 = gen_proto(ISIS_L2_PSNP, Q_ISIS, Q_DEFAULT);
+ b0 = gen_proto(cstate, ISIS_L2_PSNP, Q_ISIS, Q_DEFAULT);
gen_or(b0, b1);
break;
case Q_ISIS_IIH: /* all IS-IS Hello PDU-Types */
- b0 = gen_proto(ISIS_L1_LAN_IIH, Q_ISIS, Q_DEFAULT);
- b1 = gen_proto(ISIS_L2_LAN_IIH, Q_ISIS, Q_DEFAULT);
+ b0 = gen_proto(cstate, ISIS_L1_LAN_IIH, Q_ISIS, Q_DEFAULT);
+ b1 = gen_proto(cstate, ISIS_L2_LAN_IIH, Q_ISIS, Q_DEFAULT);
gen_or(b0, b1);
- b0 = gen_proto(ISIS_PTP_IIH, Q_ISIS, Q_DEFAULT);
+ b0 = gen_proto(cstate, ISIS_PTP_IIH, Q_ISIS, Q_DEFAULT);
gen_or(b0, b1);
break;
case Q_ISIS_LSP:
- b0 = gen_proto(ISIS_L1_LSP, Q_ISIS, Q_DEFAULT);
- b1 = gen_proto(ISIS_L2_LSP, Q_ISIS, Q_DEFAULT);
+ b0 = gen_proto(cstate, ISIS_L1_LSP, Q_ISIS, Q_DEFAULT);
+ b1 = gen_proto(cstate, ISIS_L2_LSP, Q_ISIS, Q_DEFAULT);
gen_or(b0, b1);
break;
case Q_ISIS_SNP:
- b0 = gen_proto(ISIS_L1_CSNP, Q_ISIS, Q_DEFAULT);
- b1 = gen_proto(ISIS_L2_CSNP, Q_ISIS, Q_DEFAULT);
+ b0 = gen_proto(cstate, ISIS_L1_CSNP, Q_ISIS, Q_DEFAULT);
+ b1 = gen_proto(cstate, ISIS_L2_CSNP, Q_ISIS, Q_DEFAULT);
gen_or(b0, b1);
- b0 = gen_proto(ISIS_L1_PSNP, Q_ISIS, Q_DEFAULT);
+ b0 = gen_proto(cstate, ISIS_L1_PSNP, Q_ISIS, Q_DEFAULT);
gen_or(b0, b1);
- b0 = gen_proto(ISIS_L2_PSNP, Q_ISIS, Q_DEFAULT);
+ b0 = gen_proto(cstate, ISIS_L2_PSNP, Q_ISIS, Q_DEFAULT);
gen_or(b0, b1);
break;
case Q_ISIS_CSNP:
- b0 = gen_proto(ISIS_L1_CSNP, Q_ISIS, Q_DEFAULT);
- b1 = gen_proto(ISIS_L2_CSNP, Q_ISIS, Q_DEFAULT);
+ b0 = gen_proto(cstate, ISIS_L1_CSNP, Q_ISIS, Q_DEFAULT);
+ b1 = gen_proto(cstate, ISIS_L2_CSNP, Q_ISIS, Q_DEFAULT);
gen_or(b0, b1);
break;
case Q_ISIS_PSNP:
- b0 = gen_proto(ISIS_L1_PSNP, Q_ISIS, Q_DEFAULT);
- b1 = gen_proto(ISIS_L2_PSNP, Q_ISIS, Q_DEFAULT);
+ b0 = gen_proto(cstate, ISIS_L1_PSNP, Q_ISIS, Q_DEFAULT);
+ b1 = gen_proto(cstate, ISIS_L2_PSNP, Q_ISIS, Q_DEFAULT);
gen_or(b0, b1);
break;
case Q_CLNP:
- b1 = gen_proto(ISO8473_CLNP, Q_ISO, Q_DEFAULT);
+ b1 = gen_proto(cstate, ISO8473_CLNP, Q_ISO, Q_DEFAULT);
break;
case Q_STP:
- b1 = gen_linktype(LLCSAP_8021D);
+ b1 = gen_linktype(cstate, LLCSAP_8021D);
break;
case Q_IPX:
- b1 = gen_linktype(LLCSAP_IPX);
+ b1 = gen_linktype(cstate, LLCSAP_IPX);
break;
case Q_NETBEUI:
- b1 = gen_linktype(LLCSAP_NETBEUI);
+ b1 = gen_linktype(cstate, LLCSAP_NETBEUI);
break;
case Q_RADIO:
- bpf_error("'radio' is not a valid protocol type");
+ bpf_error(cstate, "'radio' is not a valid protocol type");
default:
abort();
@@ -5190,14 +5215,14 @@ gen_proto_abbrev(proto)
}
static struct block *
-gen_ipfrag()
+gen_ipfrag(compiler_state_t *cstate)
{
struct slist *s;
struct block *b;
/* not IPv4 frag other than the first frag */
- s = gen_load_a(OR_NET, 6, BPF_H);
- b = new_block(JMP(BPF_JSET));
+ s = gen_load_a(cstate, OR_LINKPL, 6, BPF_H);
+ b = new_block(cstate, JMP(BPF_JSET));
b->s.k = 0x1fff;
b->stmts = s;
gen_not(b);
@@ -5215,51 +5240,46 @@ gen_ipfrag()
* headers).
*/
static struct block *
-gen_portatom(off, v)
- int off;
- bpf_int32 v;
+gen_portatom(compiler_state_t *cstate, int off, bpf_int32 v)
{
- return gen_cmp(OR_TRAN_IPV4, off, BPF_H, v);
+ return gen_cmp(cstate, OR_TRAN_IPV4, off, BPF_H, v);
}
static struct block *
-gen_portatom6(off, v)
- int off;
- bpf_int32 v;
+gen_portatom6(compiler_state_t *cstate, int off, bpf_int32 v)
{
- return gen_cmp(OR_TRAN_IPV6, off, BPF_H, v);
+ return gen_cmp(cstate, OR_TRAN_IPV6, off, BPF_H, v);
}
struct block *
-gen_portop(port, proto, dir)
- int port, proto, dir;
+gen_portop(compiler_state_t *cstate, int port, int proto, int dir)
{
struct block *b0, *b1, *tmp;
/* ip proto 'proto' and not a fragment other than the first fragment */
- tmp = gen_cmp(OR_NET, 9, BPF_B, (bpf_int32)proto);
- b0 = gen_ipfrag();
+ tmp = gen_cmp(cstate, OR_LINKPL, 9, BPF_B, (bpf_int32)proto);
+ b0 = gen_ipfrag(cstate);
gen_and(tmp, b0);
switch (dir) {
case Q_SRC:
- b1 = gen_portatom(0, (bpf_int32)port);
+ b1 = gen_portatom(cstate, 0, (bpf_int32)port);
break;
case Q_DST:
- b1 = gen_portatom(2, (bpf_int32)port);
+ b1 = gen_portatom(cstate, 2, (bpf_int32)port);
break;
case Q_OR:
case Q_DEFAULT:
- tmp = gen_portatom(0, (bpf_int32)port);
- b1 = gen_portatom(2, (bpf_int32)port);
+ tmp = gen_portatom(cstate, 0, (bpf_int32)port);
+ b1 = gen_portatom(cstate, 2, (bpf_int32)port);
gen_or(tmp, b1);
break;
case Q_AND:
- tmp = gen_portatom(0, (bpf_int32)port);
- b1 = gen_portatom(2, (bpf_int32)port);
+ tmp = gen_portatom(cstate, 0, (bpf_int32)port);
+ b1 = gen_portatom(cstate, 2, (bpf_int32)port);
gen_and(tmp, b1);
break;
@@ -5272,10 +5292,7 @@ gen_portop(port, proto, dir)
}
static struct block *
-gen_port(port, ip_proto, dir)
- int port;
- int ip_proto;
- int dir;
+gen_port(compiler_state_t *cstate, int port, int ip_proto, int dir)
{
struct block *b0, *b1, *tmp;
@@ -5296,20 +5313,20 @@ gen_port(port, ip_proto, dir)
*
* So we always check for ETHERTYPE_IP.
*/
- b0 = gen_linktype(ETHERTYPE_IP);
+ b0 = gen_linktype(cstate, ETHERTYPE_IP);
switch (ip_proto) {
case IPPROTO_UDP:
case IPPROTO_TCP:
case IPPROTO_SCTP:
- b1 = gen_portop(port, ip_proto, dir);
+ b1 = gen_portop(cstate, port, ip_proto, dir);
break;
case PROTO_UNDEF:
- tmp = gen_portop(port, IPPROTO_TCP, dir);
- b1 = gen_portop(port, IPPROTO_UDP, dir);
+ tmp = gen_portop(cstate, port, IPPROTO_TCP, dir);
+ b1 = gen_portop(cstate, port, IPPROTO_UDP, dir);
gen_or(tmp, b1);
- tmp = gen_portop(port, IPPROTO_SCTP, dir);
+ tmp = gen_portop(cstate, port, IPPROTO_SCTP, dir);
gen_or(tmp, b1);
break;
@@ -5321,34 +5338,33 @@ gen_port(port, ip_proto, dir)
}
struct block *
-gen_portop6(port, proto, dir)
- int port, proto, dir;
+gen_portop6(compiler_state_t *cstate, int port, int proto, int dir)
{
struct block *b0, *b1, *tmp;
/* ip6 proto 'proto' */
/* XXX - catch the first fragment of a fragmented packet? */
- b0 = gen_cmp(OR_NET, 6, BPF_B, (bpf_int32)proto);
+ b0 = gen_cmp(cstate, OR_LINKPL, 6, BPF_B, (bpf_int32)proto);
switch (dir) {
case Q_SRC:
- b1 = gen_portatom6(0, (bpf_int32)port);
+ b1 = gen_portatom6(cstate, 0, (bpf_int32)port);
break;
case Q_DST:
- b1 = gen_portatom6(2, (bpf_int32)port);
+ b1 = gen_portatom6(cstate, 2, (bpf_int32)port);
break;
case Q_OR:
case Q_DEFAULT:
- tmp = gen_portatom6(0, (bpf_int32)port);
- b1 = gen_portatom6(2, (bpf_int32)port);
+ tmp = gen_portatom6(cstate, 0, (bpf_int32)port);
+ b1 = gen_portatom6(cstate, 2, (bpf_int32)port);
gen_or(tmp, b1);
break;
case Q_AND:
- tmp = gen_portatom6(0, (bpf_int32)port);
- b1 = gen_portatom6(2, (bpf_int32)port);
+ tmp = gen_portatom6(cstate, 0, (bpf_int32)port);
+ b1 = gen_portatom6(cstate, 2, (bpf_int32)port);
gen_and(tmp, b1);
break;
@@ -5361,28 +5377,25 @@ gen_portop6(port, proto, dir)
}
static struct block *
-gen_port6(port, ip_proto, dir)
- int port;
- int ip_proto;
- int dir;
+gen_port6(compiler_state_t *cstate, int port, int ip_proto, int dir)
{
struct block *b0, *b1, *tmp;
/* link proto ip6 */
- b0 = gen_linktype(ETHERTYPE_IPV6);
+ b0 = gen_linktype(cstate, ETHERTYPE_IPV6);
switch (ip_proto) {
case IPPROTO_UDP:
case IPPROTO_TCP:
case IPPROTO_SCTP:
- b1 = gen_portop6(port, ip_proto, dir);
+ b1 = gen_portop6(cstate, port, ip_proto, dir);
break;
case PROTO_UNDEF:
- tmp = gen_portop6(port, IPPROTO_TCP, dir);
- b1 = gen_portop6(port, IPPROTO_UDP, dir);
+ tmp = gen_portop6(cstate, port, IPPROTO_TCP, dir);
+ b1 = gen_portop6(cstate, port, IPPROTO_UDP, dir);
gen_or(tmp, b1);
- tmp = gen_portop6(port, IPPROTO_SCTP, dir);
+ tmp = gen_portop6(cstate, port, IPPROTO_SCTP, dir);
gen_or(tmp, b1);
break;
@@ -5395,9 +5408,8 @@ gen_port6(port, ip_proto, dir)
/* gen_portrange code */
static struct block *
-gen_portrangeatom(off, v1, v2)
- int off;
- bpf_int32 v1, v2;
+gen_portrangeatom(compiler_state_t *cstate, int off, bpf_int32 v1,
+ bpf_int32 v2)
{
struct block *b1, *b2;
@@ -5412,8 +5424,8 @@ gen_portrangeatom(off, v1, v2)
v2 = vtemp;
}
- b1 = gen_cmp_ge(OR_TRAN_IPV4, off, BPF_H, v1);
- b2 = gen_cmp_le(OR_TRAN_IPV4, off, BPF_H, v2);
+ b1 = gen_cmp_ge(cstate, OR_TRAN_IPV4, off, BPF_H, v1);
+ b2 = gen_cmp_le(cstate, OR_TRAN_IPV4, off, BPF_H, v2);
gen_and(b1, b2);
@@ -5421,37 +5433,35 @@ gen_portrangeatom(off, v1, v2)
}
struct block *
-gen_portrangeop(port1, port2, proto, dir)
- int port1, port2;
- int proto;
- int dir;
+gen_portrangeop(compiler_state_t *cstate, int port1, int port2, int proto,
+ int dir)
{
struct block *b0, *b1, *tmp;
/* ip proto 'proto' and not a fragment other than the first fragment */
- tmp = gen_cmp(OR_NET, 9, BPF_B, (bpf_int32)proto);
- b0 = gen_ipfrag();
+ tmp = gen_cmp(cstate, OR_LINKPL, 9, BPF_B, (bpf_int32)proto);
+ b0 = gen_ipfrag(cstate);
gen_and(tmp, b0);
switch (dir) {
case Q_SRC:
- b1 = gen_portrangeatom(0, (bpf_int32)port1, (bpf_int32)port2);
+ b1 = gen_portrangeatom(cstate, 0, (bpf_int32)port1, (bpf_int32)port2);
break;
case Q_DST:
- b1 = gen_portrangeatom(2, (bpf_int32)port1, (bpf_int32)port2);
+ b1 = gen_portrangeatom(cstate, 2, (bpf_int32)port1, (bpf_int32)port2);
break;
case Q_OR:
case Q_DEFAULT:
- tmp = gen_portrangeatom(0, (bpf_int32)port1, (bpf_int32)port2);
- b1 = gen_portrangeatom(2, (bpf_int32)port1, (bpf_int32)port2);
+ tmp = gen_portrangeatom(cstate, 0, (bpf_int32)port1, (bpf_int32)port2);
+ b1 = gen_portrangeatom(cstate, 2, (bpf_int32)port1, (bpf_int32)port2);
gen_or(tmp, b1);
break;
case Q_AND:
- tmp = gen_portrangeatom(0, (bpf_int32)port1, (bpf_int32)port2);
- b1 = gen_portrangeatom(2, (bpf_int32)port1, (bpf_int32)port2);
+ tmp = gen_portrangeatom(cstate, 0, (bpf_int32)port1, (bpf_int32)port2);
+ b1 = gen_portrangeatom(cstate, 2, (bpf_int32)port1, (bpf_int32)port2);
gen_and(tmp, b1);
break;
@@ -5464,28 +5474,26 @@ gen_portrangeop(port1, port2, proto, dir)
}
static struct block *
-gen_portrange(port1, port2, ip_proto, dir)
- int port1, port2;
- int ip_proto;
- int dir;
+gen_portrange(compiler_state_t *cstate, int port1, int port2, int ip_proto,
+ int dir)
{
struct block *b0, *b1, *tmp;
/* link proto ip */
- b0 = gen_linktype(ETHERTYPE_IP);
+ b0 = gen_linktype(cstate, ETHERTYPE_IP);
switch (ip_proto) {
case IPPROTO_UDP:
case IPPROTO_TCP:
case IPPROTO_SCTP:
- b1 = gen_portrangeop(port1, port2, ip_proto, dir);
+ b1 = gen_portrangeop(cstate, port1, port2, ip_proto, dir);
break;
case PROTO_UNDEF:
- tmp = gen_portrangeop(port1, port2, IPPROTO_TCP, dir);
- b1 = gen_portrangeop(port1, port2, IPPROTO_UDP, dir);
+ tmp = gen_portrangeop(cstate, port1, port2, IPPROTO_TCP, dir);
+ b1 = gen_portrangeop(cstate, port1, port2, IPPROTO_UDP, dir);
gen_or(tmp, b1);
- tmp = gen_portrangeop(port1, port2, IPPROTO_SCTP, dir);
+ tmp = gen_portrangeop(cstate, port1, port2, IPPROTO_SCTP, dir);
gen_or(tmp, b1);
break;
@@ -5497,9 +5505,8 @@ gen_portrange(port1, port2, ip_proto, dir)
}
static struct block *
-gen_portrangeatom6(off, v1, v2)
- int off;
- bpf_int32 v1, v2;
+gen_portrangeatom6(compiler_state_t *cstate, int off, bpf_int32 v1,
+ bpf_int32 v2)
{
struct block *b1, *b2;
@@ -5514,8 +5521,8 @@ gen_portrangeatom6(off, v1, v2)
v2 = vtemp;
}
- b1 = gen_cmp_ge(OR_TRAN_IPV6, off, BPF_H, v1);
- b2 = gen_cmp_le(OR_TRAN_IPV6, off, BPF_H, v2);
+ b1 = gen_cmp_ge(cstate, OR_TRAN_IPV6, off, BPF_H, v1);
+ b2 = gen_cmp_le(cstate, OR_TRAN_IPV6, off, BPF_H, v2);
gen_and(b1, b2);
@@ -5523,36 +5530,34 @@ gen_portrangeatom6(off, v1, v2)
}
struct block *
-gen_portrangeop6(port1, port2, proto, dir)
- int port1, port2;
- int proto;
- int dir;
+gen_portrangeop6(compiler_state_t *cstate, int port1, int port2, int proto,
+ int dir)
{
struct block *b0, *b1, *tmp;
/* ip6 proto 'proto' */
/* XXX - catch the first fragment of a fragmented packet? */
- b0 = gen_cmp(OR_NET, 6, BPF_B, (bpf_int32)proto);
+ b0 = gen_cmp(cstate, OR_LINKPL, 6, BPF_B, (bpf_int32)proto);
switch (dir) {
case Q_SRC:
- b1 = gen_portrangeatom6(0, (bpf_int32)port1, (bpf_int32)port2);
+ b1 = gen_portrangeatom6(cstate, 0, (bpf_int32)port1, (bpf_int32)port2);
break;
case Q_DST:
- b1 = gen_portrangeatom6(2, (bpf_int32)port1, (bpf_int32)port2);
+ b1 = gen_portrangeatom6(cstate, 2, (bpf_int32)port1, (bpf_int32)port2);
break;
case Q_OR:
case Q_DEFAULT:
- tmp = gen_portrangeatom6(0, (bpf_int32)port1, (bpf_int32)port2);
- b1 = gen_portrangeatom6(2, (bpf_int32)port1, (bpf_int32)port2);
+ tmp = gen_portrangeatom6(cstate, 0, (bpf_int32)port1, (bpf_int32)port2);
+ b1 = gen_portrangeatom6(cstate, 2, (bpf_int32)port1, (bpf_int32)port2);
gen_or(tmp, b1);
break;
case Q_AND:
- tmp = gen_portrangeatom6(0, (bpf_int32)port1, (bpf_int32)port2);
- b1 = gen_portrangeatom6(2, (bpf_int32)port1, (bpf_int32)port2);
+ tmp = gen_portrangeatom6(cstate, 0, (bpf_int32)port1, (bpf_int32)port2);
+ b1 = gen_portrangeatom6(cstate, 2, (bpf_int32)port1, (bpf_int32)port2);
gen_and(tmp, b1);
break;
@@ -5565,28 +5570,26 @@ gen_portrangeop6(port1, port2, proto, dir)
}
static struct block *
-gen_portrange6(port1, port2, ip_proto, dir)
- int port1, port2;
- int ip_proto;
- int dir;
+gen_portrange6(compiler_state_t *cstate, int port1, int port2, int ip_proto,
+ int dir)
{
struct block *b0, *b1, *tmp;
/* link proto ip6 */
- b0 = gen_linktype(ETHERTYPE_IPV6);
+ b0 = gen_linktype(cstate, ETHERTYPE_IPV6);
switch (ip_proto) {
case IPPROTO_UDP:
case IPPROTO_TCP:
case IPPROTO_SCTP:
- b1 = gen_portrangeop6(port1, port2, ip_proto, dir);
+ b1 = gen_portrangeop6(cstate, port1, port2, ip_proto, dir);
break;
case PROTO_UNDEF:
- tmp = gen_portrangeop6(port1, port2, IPPROTO_TCP, dir);
- b1 = gen_portrangeop6(port1, port2, IPPROTO_UDP, dir);
+ tmp = gen_portrangeop6(cstate, port1, port2, IPPROTO_TCP, dir);
+ b1 = gen_portrangeop6(cstate, port1, port2, IPPROTO_UDP, dir);
gen_or(tmp, b1);
- tmp = gen_portrangeop6(port1, port2, IPPROTO_SCTP, dir);
+ tmp = gen_portrangeop6(cstate, port1, port2, IPPROTO_SCTP, dir);
gen_or(tmp, b1);
break;
@@ -5598,9 +5601,7 @@ gen_portrange6(port1, port2, ip_proto, dir)
}
static int
-lookup_proto(name, proto)
- register const char *name;
- register int proto;
+lookup_proto(compiler_state_t *cstate, const char *name, int proto)
{
register int v;
@@ -5611,16 +5612,16 @@ lookup_proto(name, proto)
case Q_IPV6:
v = pcap_nametoproto(name);
if (v == PROTO_UNDEF)
- bpf_error("unknown ip proto '%s'", name);
+ bpf_error(cstate, "unknown ip proto '%s'", name);
break;
case Q_LINK:
- /* XXX should look up h/w protocol type based on linktype */
+ /* XXX should look up h/w protocol type based on cstate->linktype */
v = pcap_nametoeproto(name);
if (v == PROTO_UNDEF) {
v = pcap_nametollc(name);
if (v == PROTO_UNDEF)
- bpf_error("unknown ether proto '%s'", name);
+ bpf_error(cstate, "unknown ether proto '%s'", name);
}
break;
@@ -5632,7 +5633,7 @@ lookup_proto(name, proto)
else if (strcmp(name, "clnp") == 0)
v = ISO8473_CLNP;
else
- bpf_error("unknown osi proto '%s'", name);
+ bpf_error(cstate, "unknown osi proto '%s'", name);
break;
default:
@@ -5653,35 +5654,32 @@ gen_joinsp(s, n)
#endif
static struct block *
-gen_protochain(v, proto, dir)
- int v;
- int proto;
- int dir;
+gen_protochain(compiler_state_t *cstate, int v, int proto, int dir)
{
#ifdef NO_PROTOCHAIN
- return gen_proto(v, proto, dir);
+ return gen_proto(cstate, v, proto, dir);
#else
struct block *b0, *b;
struct slist *s[100];
int fix2, fix3, fix4, fix5;
int ahcheck, again, end;
int i, max;
- int reg2 = alloc_reg();
+ int reg2 = alloc_reg(cstate);
memset(s, 0, sizeof(s));
- fix2 = fix3 = fix4 = fix5 = 0;
+ fix3 = fix4 = fix5 = 0;
switch (proto) {
case Q_IP:
case Q_IPV6:
break;
case Q_DEFAULT:
- b0 = gen_protochain(v, Q_IP, dir);
- b = gen_protochain(v, Q_IPV6, dir);
+ b0 = gen_protochain(cstate, v, Q_IP, dir);
+ b = gen_protochain(cstate, v, Q_IPV6, dir);
gen_or(b0, b);
return b;
default:
- bpf_error("bad protocol applied for 'protochain'");
+ bpf_error(cstate, "bad protocol applied for 'protochain'");
/*NOTREACHED*/
}
@@ -5696,17 +5694,10 @@ gen_protochain(v, proto, dir)
* branches, and backward branch support is unlikely to appear
* in kernel BPF engines.)
*/
- switch (linktype) {
-
- case DLT_IEEE802_11:
- case DLT_PRISM_HEADER:
- case DLT_IEEE802_11_RADIO_AVS:
- case DLT_IEEE802_11_RADIO:
- case DLT_PPI:
- bpf_error("'protochain' not supported with 802.11");
- }
+ if (cstate->off_linkpl.is_variable)
+ bpf_error(cstate, "'protochain' not supported with variable length headers");
- no_optimize = 1; /*this code is not compatible with optimzer yet */
+ cstate->no_optimize = 1; /*this code is not compatible with optimzer yet */
/*
* s[0] is a dummy entry to protect other BPF insn from damage
@@ -5714,44 +5705,44 @@ gen_protochain(v, proto, dir)
* hard to find interdependency made by jump table fixup.
*/
i = 0;
- s[i] = new_stmt(0); /*dummy*/
+ s[i] = new_stmt(cstate, 0); /*dummy*/
i++;
switch (proto) {
case Q_IP:
- b0 = gen_linktype(ETHERTYPE_IP);
+ b0 = gen_linktype(cstate, ETHERTYPE_IP);
/* A = ip->ip_p */
- s[i] = new_stmt(BPF_LD|BPF_ABS|BPF_B);
- s[i]->s.k = off_macpl + off_nl + 9;
+ s[i] = new_stmt(cstate, BPF_LD|BPF_ABS|BPF_B);
+ s[i]->s.k = cstate->off_linkpl.constant_part + cstate->off_nl + 9;
i++;
/* X = ip->ip_hl << 2 */
- s[i] = new_stmt(BPF_LDX|BPF_MSH|BPF_B);
- s[i]->s.k = off_macpl + off_nl;
+ s[i] = new_stmt(cstate, BPF_LDX|BPF_MSH|BPF_B);
+ s[i]->s.k = cstate->off_linkpl.constant_part + cstate->off_nl;
i++;
break;
case Q_IPV6:
- b0 = gen_linktype(ETHERTYPE_IPV6);
+ b0 = gen_linktype(cstate, ETHERTYPE_IPV6);
/* A = ip6->ip_nxt */
- s[i] = new_stmt(BPF_LD|BPF_ABS|BPF_B);
- s[i]->s.k = off_macpl + off_nl + 6;
+ s[i] = new_stmt(cstate, BPF_LD|BPF_ABS|BPF_B);
+ s[i]->s.k = cstate->off_linkpl.constant_part + cstate->off_nl + 6;
i++;
/* X = sizeof(struct ip6_hdr) */
- s[i] = new_stmt(BPF_LDX|BPF_IMM);
+ s[i] = new_stmt(cstate, BPF_LDX|BPF_IMM);
s[i]->s.k = 40;
i++;
break;
default:
- bpf_error("unsupported proto to gen_protochain");
+ bpf_error(cstate, "unsupported proto to gen_protochain");
/*NOTREACHED*/
}
/* again: if (A == v) goto end; else fall through; */
again = i;
- s[i] = new_stmt(BPF_JMP|BPF_JEQ|BPF_K);
+ s[i] = new_stmt(cstate, BPF_JMP|BPF_JEQ|BPF_K);
s[i]->s.k = v;
s[i]->s.jt = NULL; /*later*/
s[i]->s.jf = NULL; /*update in next stmt*/
@@ -5762,7 +5753,7 @@ gen_protochain(v, proto, dir)
#define IPPROTO_NONE 59
#endif
/* if (A == IPPROTO_NONE) goto end */
- s[i] = new_stmt(BPF_JMP|BPF_JEQ|BPF_K);
+ s[i] = new_stmt(cstate, BPF_JMP|BPF_JEQ|BPF_K);
s[i]->s.jt = NULL; /*later*/
s[i]->s.jf = NULL; /*update in next stmt*/
s[i]->s.k = IPPROTO_NONE;
@@ -5775,26 +5766,26 @@ gen_protochain(v, proto, dir)
v6start = i;
/* if (A == IPPROTO_HOPOPTS) goto v6advance */
- s[i] = new_stmt(BPF_JMP|BPF_JEQ|BPF_K);
+ s[i] = new_stmt(cstate, BPF_JMP|BPF_JEQ|BPF_K);
s[i]->s.jt = NULL; /*later*/
s[i]->s.jf = NULL; /*update in next stmt*/
s[i]->s.k = IPPROTO_HOPOPTS;
s[fix2]->s.jf = s[i];
i++;
/* if (A == IPPROTO_DSTOPTS) goto v6advance */
- s[i - 1]->s.jf = s[i] = new_stmt(BPF_JMP|BPF_JEQ|BPF_K);
+ s[i - 1]->s.jf = s[i] = new_stmt(cstate, BPF_JMP|BPF_JEQ|BPF_K);
s[i]->s.jt = NULL; /*later*/
s[i]->s.jf = NULL; /*update in next stmt*/
s[i]->s.k = IPPROTO_DSTOPTS;
i++;
/* if (A == IPPROTO_ROUTING) goto v6advance */
- s[i - 1]->s.jf = s[i] = new_stmt(BPF_JMP|BPF_JEQ|BPF_K);
+ s[i - 1]->s.jf = s[i] = new_stmt(cstate, BPF_JMP|BPF_JEQ|BPF_K);
s[i]->s.jt = NULL; /*later*/
s[i]->s.jf = NULL; /*update in next stmt*/
s[i]->s.k = IPPROTO_ROUTING;
i++;
/* if (A == IPPROTO_FRAGMENT) goto v6advance; else goto ahcheck; */
- s[i - 1]->s.jf = s[i] = new_stmt(BPF_JMP|BPF_JEQ|BPF_K);
+ s[i - 1]->s.jf = s[i] = new_stmt(cstate, BPF_JMP|BPF_JEQ|BPF_K);
s[i]->s.jt = NULL; /*later*/
s[i]->s.jf = NULL; /*later*/
s[i]->s.k = IPPROTO_FRAGMENT;
@@ -5811,39 +5802,39 @@ gen_protochain(v, proto, dir)
* X = X + (P[X + packet head + 1] + 1) * 8;
*/
/* A = P[X + packet head] */
- s[i] = new_stmt(BPF_LD|BPF_IND|BPF_B);
- s[i]->s.k = off_macpl + off_nl;
+ s[i] = new_stmt(cstate, BPF_LD|BPF_IND|BPF_B);
+ s[i]->s.k = cstate->off_linkpl.constant_part + cstate->off_nl;
i++;
/* MEM[reg2] = A */
- s[i] = new_stmt(BPF_ST);
+ s[i] = new_stmt(cstate, BPF_ST);
s[i]->s.k = reg2;
i++;
/* A = P[X + packet head + 1]; */
- s[i] = new_stmt(BPF_LD|BPF_IND|BPF_B);
- s[i]->s.k = off_macpl + off_nl + 1;
+ s[i] = new_stmt(cstate, BPF_LD|BPF_IND|BPF_B);
+ s[i]->s.k = cstate->off_linkpl.constant_part + cstate->off_nl + 1;
i++;
/* A += 1 */
- s[i] = new_stmt(BPF_ALU|BPF_ADD|BPF_K);
+ s[i] = new_stmt(cstate, BPF_ALU|BPF_ADD|BPF_K);
s[i]->s.k = 1;
i++;
/* A *= 8 */
- s[i] = new_stmt(BPF_ALU|BPF_MUL|BPF_K);
+ s[i] = new_stmt(cstate, BPF_ALU|BPF_MUL|BPF_K);
s[i]->s.k = 8;
i++;
/* A += X */
- s[i] = new_stmt(BPF_ALU|BPF_ADD|BPF_X);
+ s[i] = new_stmt(cstate, BPF_ALU|BPF_ADD|BPF_X);
s[i]->s.k = 0;
i++;
/* X = A; */
- s[i] = new_stmt(BPF_MISC|BPF_TAX);
+ s[i] = new_stmt(cstate, BPF_MISC|BPF_TAX);
i++;
/* A = MEM[reg2] */
- s[i] = new_stmt(BPF_LD|BPF_MEM);
+ s[i] = new_stmt(cstate, BPF_LD|BPF_MEM);
s[i]->s.k = reg2;
i++;
/* goto again; (must use BPF_JA for backward jump) */
- s[i] = new_stmt(BPF_JMP|BPF_JA);
+ s[i] = new_stmt(cstate, BPF_JMP|BPF_JA);
s[i]->s.k = again - i - 1;
s[i - 1]->s.jf = s[i];
i++;
@@ -5853,7 +5844,7 @@ gen_protochain(v, proto, dir)
s[j]->s.jt = s[v6advance];
} else {
/* nop */
- s[i] = new_stmt(BPF_ALU|BPF_ADD|BPF_K);
+ s[i] = new_stmt(cstate, BPF_ALU|BPF_ADD|BPF_K);
s[i]->s.k = 0;
s[fix2]->s.jf = s[i];
i++;
@@ -5862,7 +5853,7 @@ gen_protochain(v, proto, dir)
/* ahcheck: */
ahcheck = i;
/* if (A == IPPROTO_AH) then fall through; else goto end; */
- s[i] = new_stmt(BPF_JMP|BPF_JEQ|BPF_K);
+ s[i] = new_stmt(cstate, BPF_JMP|BPF_JEQ|BPF_K);
s[i]->s.jt = NULL; /*later*/
s[i]->s.jf = NULL; /*later*/
s[i]->s.k = IPPROTO_AH;
@@ -5877,54 +5868,54 @@ gen_protochain(v, proto, dir)
* X = X + (P[X + 1] + 2) * 4;
*/
/* A = X */
- s[i - 1]->s.jt = s[i] = new_stmt(BPF_MISC|BPF_TXA);
+ s[i - 1]->s.jt = s[i] = new_stmt(cstate, BPF_MISC|BPF_TXA);
i++;
/* A = P[X + packet head]; */
- s[i] = new_stmt(BPF_LD|BPF_IND|BPF_B);
- s[i]->s.k = off_macpl + off_nl;
+ s[i] = new_stmt(cstate, BPF_LD|BPF_IND|BPF_B);
+ s[i]->s.k = cstate->off_linkpl.constant_part + cstate->off_nl;
i++;
/* MEM[reg2] = A */
- s[i] = new_stmt(BPF_ST);
+ s[i] = new_stmt(cstate, BPF_ST);
s[i]->s.k = reg2;
i++;
/* A = X */
- s[i - 1]->s.jt = s[i] = new_stmt(BPF_MISC|BPF_TXA);
+ s[i - 1]->s.jt = s[i] = new_stmt(cstate, BPF_MISC|BPF_TXA);
i++;
/* A += 1 */
- s[i] = new_stmt(BPF_ALU|BPF_ADD|BPF_K);
+ s[i] = new_stmt(cstate, BPF_ALU|BPF_ADD|BPF_K);
s[i]->s.k = 1;
i++;
/* X = A */
- s[i] = new_stmt(BPF_MISC|BPF_TAX);
+ s[i] = new_stmt(cstate, BPF_MISC|BPF_TAX);
i++;
/* A = P[X + packet head] */
- s[i] = new_stmt(BPF_LD|BPF_IND|BPF_B);
- s[i]->s.k = off_macpl + off_nl;
+ s[i] = new_stmt(cstate, BPF_LD|BPF_IND|BPF_B);
+ s[i]->s.k = cstate->off_linkpl.constant_part + cstate->off_nl;
i++;
/* A += 2 */
- s[i] = new_stmt(BPF_ALU|BPF_ADD|BPF_K);
+ s[i] = new_stmt(cstate, BPF_ALU|BPF_ADD|BPF_K);
s[i]->s.k = 2;
i++;
/* A *= 4 */
- s[i] = new_stmt(BPF_ALU|BPF_MUL|BPF_K);
+ s[i] = new_stmt(cstate, BPF_ALU|BPF_MUL|BPF_K);
s[i]->s.k = 4;
i++;
/* X = A; */
- s[i] = new_stmt(BPF_MISC|BPF_TAX);
+ s[i] = new_stmt(cstate, BPF_MISC|BPF_TAX);
i++;
/* A = MEM[reg2] */
- s[i] = new_stmt(BPF_LD|BPF_MEM);
+ s[i] = new_stmt(cstate, BPF_LD|BPF_MEM);
s[i]->s.k = reg2;
i++;
/* goto again; (must use BPF_JA for backward jump) */
- s[i] = new_stmt(BPF_JMP|BPF_JA);
+ s[i] = new_stmt(cstate, BPF_JMP|BPF_JA);
s[i]->s.k = again - i - 1;
i++;
/* end: nop */
end = i;
- s[i] = new_stmt(BPF_ALU|BPF_ADD|BPF_K);
+ s[i] = new_stmt(cstate, BPF_ALU|BPF_ADD|BPF_K);
s[i]->s.k = 0;
s[fix2]->s.jt = s[end];
s[fix4]->s.jf = s[end];
@@ -5942,11 +5933,11 @@ gen_protochain(v, proto, dir)
/*
* emit final check
*/
- b = new_block(JMP(BPF_JEQ));
+ b = new_block(cstate, JMP(BPF_JEQ));
b->stmts = s[1]; /*remember, s[0] is dummy*/
b->s.k = v;
- free_reg(reg2);
+ free_reg(cstate, reg2);
gen_and(b0, b);
return b;
@@ -5954,7 +5945,7 @@ gen_protochain(v, proto, dir)
}
static struct block *
-gen_check_802_11_data_frame()
+gen_check_802_11_data_frame(compiler_state_t *cstate)
{
struct slist *s;
struct block *b0, *b1;
@@ -5963,13 +5954,13 @@ gen_check_802_11_data_frame()
* A data frame has the 0x08 bit (b3) in the frame control field set
* and the 0x04 bit (b2) clear.
*/
- s = gen_load_a(OR_LINK, 0, BPF_B);
- b0 = new_block(JMP(BPF_JSET));
+ s = gen_load_a(cstate, OR_LINKHDR, 0, BPF_B);
+ b0 = new_block(cstate, JMP(BPF_JSET));
b0->s.k = 0x08;
b0->stmts = s;
- s = gen_load_a(OR_LINK, 0, BPF_B);
- b1 = new_block(JMP(BPF_JSET));
+ s = gen_load_a(cstate, OR_LINKHDR, 0, BPF_B);
+ b1 = new_block(cstate, JMP(BPF_JSET));
b1->s.k = 0x04;
b1->stmts = s;
gen_not(b1);
@@ -5989,10 +5980,7 @@ gen_check_802_11_data_frame()
* against Q_IP and Q_IPV6.
*/
static struct block *
-gen_proto(v, proto, dir)
- int v;
- int proto;
- int dir;
+gen_proto(compiler_state_t *cstate, int v, int proto, int dir)
{
struct block *b0, *b1;
#ifndef CHASE_CHAIN
@@ -6000,12 +5988,12 @@ gen_proto(v, proto, dir)
#endif
if (dir != Q_DEFAULT)
- bpf_error("direction applied to 'proto'");
+ bpf_error(cstate, "direction applied to 'proto'");
switch (proto) {
case Q_DEFAULT:
- b0 = gen_proto(v, Q_IP, dir);
- b1 = gen_proto(v, Q_IPV6, dir);
+ b0 = gen_proto(cstate, v, Q_IP, dir);
+ b1 = gen_proto(cstate, v, Q_IPV6, dir);
gen_or(b0, b1);
return b1;
@@ -6025,22 +6013,22 @@ gen_proto(v, proto, dir)
*
* So we always check for ETHERTYPE_IP.
*/
- b0 = gen_linktype(ETHERTYPE_IP);
+ b0 = gen_linktype(cstate, ETHERTYPE_IP);
#ifndef CHASE_CHAIN
- b1 = gen_cmp(OR_NET, 9, BPF_B, (bpf_int32)v);
+ b1 = gen_cmp(cstate, OR_LINKPL, 9, BPF_B, (bpf_int32)v);
#else
- b1 = gen_protochain(v, Q_IP);
+ b1 = gen_protochain(cstate, v, Q_IP);
#endif
gen_and(b0, b1);
return b1;
case Q_ISO:
- switch (linktype) {
+ switch (cstate->linktype) {
case DLT_FRELAY:
/*
* Frame Relay packets typically have an OSI
- * NLPID at the beginning; "gen_linktype(LLCSAP_ISONS)"
+ * NLPID at the beginning; "gen_linktype(cstate, LLCSAP_ISONS)"
* generates code to check for all the OSI
* NLPIDs, so calling it and then adding a check
* for the particular NLPID for which we're
@@ -6056,7 +6044,7 @@ gen_proto(v, proto, dir)
*
* XXX - what about SNAP-encapsulated frames?
*/
- return gen_cmp(OR_LINK, 2, BPF_H, (0x03<<8) | v);
+ return gen_cmp(cstate, OR_LINKHDR, 2, BPF_H, (0x03<<8) | v);
/*NOTREACHED*/
break;
@@ -6065,138 +6053,138 @@ gen_proto(v, proto, dir)
* Cisco uses an Ethertype lookalike - for OSI,
* it's 0xfefe.
*/
- b0 = gen_linktype(LLCSAP_ISONS<<8 | LLCSAP_ISONS);
+ b0 = gen_linktype(cstate, LLCSAP_ISONS<<8 | LLCSAP_ISONS);
/* OSI in C-HDLC is stuffed with a fudge byte */
- b1 = gen_cmp(OR_NET_NOSNAP, 1, BPF_B, (long)v);
+ b1 = gen_cmp(cstate, OR_LINKPL_NOSNAP, 1, BPF_B, (long)v);
gen_and(b0, b1);
return b1;
default:
- b0 = gen_linktype(LLCSAP_ISONS);
- b1 = gen_cmp(OR_NET_NOSNAP, 0, BPF_B, (long)v);
+ b0 = gen_linktype(cstate, LLCSAP_ISONS);
+ b1 = gen_cmp(cstate, OR_LINKPL_NOSNAP, 0, BPF_B, (long)v);
gen_and(b0, b1);
return b1;
}
case Q_ISIS:
- b0 = gen_proto(ISO10589_ISIS, Q_ISO, Q_DEFAULT);
+ b0 = gen_proto(cstate, ISO10589_ISIS, Q_ISO, Q_DEFAULT);
/*
* 4 is the offset of the PDU type relative to the IS-IS
* header.
*/
- b1 = gen_cmp(OR_NET_NOSNAP, 4, BPF_B, (long)v);
+ b1 = gen_cmp(cstate, OR_LINKPL_NOSNAP, 4, BPF_B, (long)v);
gen_and(b0, b1);
return b1;
case Q_ARP:
- bpf_error("arp does not encapsulate another protocol");
+ bpf_error(cstate, "arp does not encapsulate another protocol");
/* NOTREACHED */
case Q_RARP:
- bpf_error("rarp does not encapsulate another protocol");
+ bpf_error(cstate, "rarp does not encapsulate another protocol");
/* NOTREACHED */
case Q_ATALK:
- bpf_error("atalk encapsulation is not specifiable");
+ bpf_error(cstate, "atalk encapsulation is not specifiable");
/* NOTREACHED */
case Q_DECNET:
- bpf_error("decnet encapsulation is not specifiable");
+ bpf_error(cstate, "decnet encapsulation is not specifiable");
/* NOTREACHED */
case Q_SCA:
- bpf_error("sca does not encapsulate another protocol");
+ bpf_error(cstate, "sca does not encapsulate another protocol");
/* NOTREACHED */
case Q_LAT:
- bpf_error("lat does not encapsulate another protocol");
+ bpf_error(cstate, "lat does not encapsulate another protocol");
/* NOTREACHED */
case Q_MOPRC:
- bpf_error("moprc does not encapsulate another protocol");
+ bpf_error(cstate, "moprc does not encapsulate another protocol");
/* NOTREACHED */
case Q_MOPDL:
- bpf_error("mopdl does not encapsulate another protocol");
+ bpf_error(cstate, "mopdl does not encapsulate another protocol");
/* NOTREACHED */
case Q_LINK:
- return gen_linktype(v);
+ return gen_linktype(cstate, v);
case Q_UDP:
- bpf_error("'udp proto' is bogus");
+ bpf_error(cstate, "'udp proto' is bogus");
/* NOTREACHED */
case Q_TCP:
- bpf_error("'tcp proto' is bogus");
+ bpf_error(cstate, "'tcp proto' is bogus");
/* NOTREACHED */
case Q_SCTP:
- bpf_error("'sctp proto' is bogus");
+ bpf_error(cstate, "'sctp proto' is bogus");
/* NOTREACHED */
case Q_ICMP:
- bpf_error("'icmp proto' is bogus");
+ bpf_error(cstate, "'icmp proto' is bogus");
/* NOTREACHED */
case Q_IGMP:
- bpf_error("'igmp proto' is bogus");
+ bpf_error(cstate, "'igmp proto' is bogus");
/* NOTREACHED */
case Q_IGRP:
- bpf_error("'igrp proto' is bogus");
+ bpf_error(cstate, "'igrp proto' is bogus");
/* NOTREACHED */
case Q_PIM:
- bpf_error("'pim proto' is bogus");
+ bpf_error(cstate, "'pim proto' is bogus");
/* NOTREACHED */
case Q_VRRP:
- bpf_error("'vrrp proto' is bogus");
+ bpf_error(cstate, "'vrrp proto' is bogus");
/* NOTREACHED */
case Q_CARP:
- bpf_error("'carp proto' is bogus");
+ bpf_error(cstate, "'carp proto' is bogus");
/* NOTREACHED */
case Q_IPV6:
- b0 = gen_linktype(ETHERTYPE_IPV6);
+ b0 = gen_linktype(cstate, ETHERTYPE_IPV6);
#ifndef CHASE_CHAIN
/*
* 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);
+ b2 = gen_cmp(cstate, OR_LINKPL, 6, BPF_B, IPPROTO_FRAGMENT);
+ b1 = gen_cmp(cstate, OR_LINKPL, 40, BPF_B, (bpf_int32)v);
gen_and(b2, b1);
- b2 = gen_cmp(OR_NET, 6, BPF_B, (bpf_int32)v);
+ b2 = gen_cmp(cstate, OR_LINKPL, 6, BPF_B, (bpf_int32)v);
gen_or(b2, b1);
#else
- b1 = gen_protochain(v, Q_IPV6);
+ b1 = gen_protochain(cstate, v, Q_IPV6);
#endif
gen_and(b0, b1);
return b1;
case Q_ICMPV6:
- bpf_error("'icmp6 proto' is bogus");
+ bpf_error(cstate, "'icmp6 proto' is bogus");
case Q_AH:
- bpf_error("'ah proto' is bogus");
+ bpf_error(cstate, "'ah proto' is bogus");
case Q_ESP:
- bpf_error("'ah proto' is bogus");
+ bpf_error(cstate, "'ah proto' is bogus");
case Q_STP:
- bpf_error("'stp proto' is bogus");
+ bpf_error(cstate, "'stp proto' is bogus");
case Q_IPX:
- bpf_error("'ipx proto' is bogus");
+ bpf_error(cstate, "'ipx proto' is bogus");
case Q_NETBEUI:
- bpf_error("'netbeui proto' is bogus");
+ bpf_error(cstate, "'netbeui proto' is bogus");
case Q_RADIO:
- bpf_error("'radio proto' is bogus");
+ bpf_error(cstate, "'radio proto' is bogus");
default:
abort();
@@ -6206,9 +6194,7 @@ gen_proto(v, proto, dir)
}
struct block *
-gen_scode(name, q)
- register const char *name;
- struct qual q;
+gen_scode(compiler_state_t *cstate, const char *name, struct qual q)
{
int proto = q.proto;
int dir = q.dir;
@@ -6233,46 +6219,49 @@ gen_scode(name, q)
case Q_NET:
addr = pcap_nametonetaddr(name);
if (addr == 0)
- bpf_error("unknown network '%s'", name);
+ bpf_error(cstate, "unknown network '%s'", name);
/* Left justify network addr and calculate its network mask */
mask = 0xffffffff;
while (addr && (addr & 0xff000000) == 0) {
addr <<= 8;
mask <<= 8;
}
- return gen_host(addr, mask, proto, dir, q.addr);
+ return gen_host(cstate, addr, mask, proto, dir, q.addr);
case Q_DEFAULT:
case Q_HOST:
if (proto == Q_LINK) {
- switch (linktype) {
+ switch (cstate->linktype) {
case DLT_EN10MB:
case DLT_NETANALYZER:
case DLT_NETANALYZER_TRANSPARENT:
eaddr = pcap_ether_hostton(name);
if (eaddr == NULL)
- bpf_error(
+ bpf_error(cstate,
"unknown ether host '%s'", name);
- b = gen_ehostop(eaddr, dir);
+ tmp = gen_prevlinkhdr_check(cstate);
+ b = gen_ehostop(cstate, eaddr, dir);
+ if (tmp != NULL)
+ gen_and(tmp, b);
free(eaddr);
return b;
case DLT_FDDI:
eaddr = pcap_ether_hostton(name);
if (eaddr == NULL)
- bpf_error(
+ bpf_error(cstate,
"unknown FDDI host '%s'", name);
- b = gen_fhostop(eaddr, dir);
+ b = gen_fhostop(cstate, eaddr, dir);
free(eaddr);
return b;
case DLT_IEEE802:
eaddr = pcap_ether_hostton(name);
if (eaddr == NULL)
- bpf_error(
+ bpf_error(cstate,
"unknown token ring host '%s'", name);
- b = gen_thostop(eaddr, dir);
+ b = gen_thostop(cstate, eaddr, dir);
free(eaddr);
return b;
@@ -6283,63 +6272,51 @@ gen_scode(name, q)
case DLT_PPI:
eaddr = pcap_ether_hostton(name);
if (eaddr == NULL)
- bpf_error(
+ bpf_error(cstate,
"unknown 802.11 host '%s'", name);
- b = gen_wlanhostop(eaddr, dir);
+ b = gen_wlanhostop(cstate, eaddr, dir);
free(eaddr);
return b;
case DLT_IP_OVER_FC:
eaddr = pcap_ether_hostton(name);
if (eaddr == NULL)
- bpf_error(
+ bpf_error(cstate,
"unknown Fibre Channel host '%s'", name);
- b = gen_ipfchostop(eaddr, dir);
- free(eaddr);
- return b;
-
- case DLT_SUNATM:
- if (!is_lane)
- break;
-
- /*
- * Check that the packet doesn't begin
- * with an LE Control marker. (We've
- * already generated a test for LANE.)
- */
- tmp = gen_cmp(OR_LINK, SUNATM_PKT_BEGIN_POS,
- BPF_H, 0xFF00);
- gen_not(tmp);
-
- eaddr = pcap_ether_hostton(name);
- if (eaddr == NULL)
- bpf_error(
- "unknown ether host '%s'", name);
- b = gen_ehostop(eaddr, dir);
- gen_and(tmp, b);
+ b = gen_ipfchostop(cstate, eaddr, dir);
free(eaddr);
return b;
}
- bpf_error("only ethernet/FDDI/token ring/802.11/ATM LANE/Fibre Channel supports link-level host name");
+ bpf_error(cstate, "only ethernet/FDDI/token ring/802.11/ATM LANE/Fibre Channel supports link-level host name");
} else if (proto == Q_DECNET) {
- unsigned short dn_addr = __pcap_nametodnaddr(name);
+ unsigned short dn_addr;
+
+ if (!__pcap_nametodnaddr(name, &dn_addr)) {
+#ifdef DECNETLIB
+ bpf_error(cstate, "unknown decnet host name '%s'\n", name);
+#else
+ bpf_error(cstate, "decnet name support not included, '%s' cannot be translated\n",
+ name);
+#endif
+ }
/*
* I don't think DECNET hosts can be multihomed, so
* there is no need to build up a list of addresses
*/
- return (gen_host(dn_addr, 0, proto, dir, q.addr));
+ return (gen_host(cstate, dn_addr, 0, proto, dir, q.addr));
} else {
#ifndef INET6
alist = pcap_nametoaddr(name);
if (alist == NULL || *alist == NULL)
- bpf_error("unknown host '%s'", name);
+ bpf_error(cstate, "unknown host '%s'", name);
tproto = proto;
- if (off_linktype == (u_int)-1 && tproto == Q_DEFAULT)
+ if (cstate->off_linktype.constant_part == OFFSET_NOT_SET &&
+ tproto == Q_DEFAULT)
tproto = Q_IP;
- b = gen_host(**alist++, 0xffffffff, tproto, dir, q.addr);
+ b = gen_host(cstate, **alist++, 0xffffffff, tproto, dir, q.addr);
while (*alist) {
- tmp = gen_host(**alist++, 0xffffffff,
+ tmp = gen_host(cstate, **alist++, 0xffffffff,
tproto, dir, q.addr);
gen_or(b, tmp);
b = tmp;
@@ -6349,11 +6326,12 @@ gen_scode(name, q)
memset(&mask128, 0xff, sizeof(mask128));
res0 = res = pcap_nametoaddrinfo(name);
if (res == NULL)
- bpf_error("unknown host '%s'", name);
- ai = res;
+ bpf_error(cstate, "unknown host '%s'", name);
+ cstate->ai = res;
b = tmp = NULL;
tproto = tproto6 = proto;
- if (off_linktype == -1 && tproto == Q_DEFAULT) {
+ if (cstate->off_linktype.constant_part == OFFSET_NOT_SET &&
+ tproto == Q_DEFAULT) {
tproto = Q_IP;
tproto6 = Q_IPV6;
}
@@ -6365,7 +6343,7 @@ gen_scode(name, q)
sin4 = (struct sockaddr_in *)
res->ai_addr;
- tmp = gen_host(ntohl(sin4->sin_addr.s_addr),
+ tmp = gen_host(cstate, ntohl(sin4->sin_addr.s_addr),
0xffffffff, tproto, dir, q.addr);
break;
case AF_INET6:
@@ -6374,7 +6352,7 @@ gen_scode(name, q)
sin6 = (struct sockaddr_in6 *)
res->ai_addr;
- tmp = gen_host6(&sin6->sin6_addr,
+ tmp = gen_host6(cstate, &sin6->sin6_addr,
&mask128, tproto6, dir, q.addr);
break;
default:
@@ -6384,10 +6362,10 @@ gen_scode(name, q)
gen_or(b, tmp);
b = tmp;
}
- ai = NULL;
+ cstate->ai = NULL;
freeaddrinfo(res0);
if (b == NULL) {
- bpf_error("unknown host '%s'%s", name,
+ bpf_error(cstate, "unknown host '%s'%s", name,
(proto == Q_DEFAULT)
? ""
: " for specified address family");
@@ -6399,124 +6377,124 @@ gen_scode(name, q)
case Q_PORT:
if (proto != Q_DEFAULT &&
proto != Q_UDP && proto != Q_TCP && proto != Q_SCTP)
- bpf_error("illegal qualifier of 'port'");
+ bpf_error(cstate, "illegal qualifier of 'port'");
if (pcap_nametoport(name, &port, &real_proto) == 0)
- bpf_error("unknown port '%s'", name);
+ bpf_error(cstate, "unknown port '%s'", name);
if (proto == Q_UDP) {
if (real_proto == IPPROTO_TCP)
- bpf_error("port '%s' is tcp", name);
+ bpf_error(cstate, "port '%s' is tcp", name);
else if (real_proto == IPPROTO_SCTP)
- bpf_error("port '%s' is sctp", name);
+ bpf_error(cstate, "port '%s' is sctp", name);
else
/* override PROTO_UNDEF */
real_proto = IPPROTO_UDP;
}
if (proto == Q_TCP) {
if (real_proto == IPPROTO_UDP)
- bpf_error("port '%s' is udp", name);
+ bpf_error(cstate, "port '%s' is udp", name);
else if (real_proto == IPPROTO_SCTP)
- bpf_error("port '%s' is sctp", name);
+ bpf_error(cstate, "port '%s' is sctp", name);
else
/* override PROTO_UNDEF */
real_proto = IPPROTO_TCP;
}
if (proto == Q_SCTP) {
if (real_proto == IPPROTO_UDP)
- bpf_error("port '%s' is udp", name);
+ bpf_error(cstate, "port '%s' is udp", name);
else if (real_proto == IPPROTO_TCP)
- bpf_error("port '%s' is tcp", name);
+ bpf_error(cstate, "port '%s' is tcp", name);
else
/* override PROTO_UNDEF */
real_proto = IPPROTO_SCTP;
}
if (port < 0)
- bpf_error("illegal port number %d < 0", port);
+ bpf_error(cstate, "illegal port number %d < 0", port);
if (port > 65535)
- bpf_error("illegal port number %d > 65535", port);
- b = gen_port(port, real_proto, dir);
- gen_or(gen_port6(port, real_proto, dir), b);
+ bpf_error(cstate, "illegal port number %d > 65535", port);
+ b = gen_port(cstate, port, real_proto, dir);
+ gen_or(gen_port6(cstate, port, real_proto, dir), b);
return b;
case Q_PORTRANGE:
if (proto != Q_DEFAULT &&
proto != Q_UDP && proto != Q_TCP && proto != Q_SCTP)
- bpf_error("illegal qualifier of 'portrange'");
+ bpf_error(cstate, "illegal qualifier of 'portrange'");
if (pcap_nametoportrange(name, &port1, &port2, &real_proto) == 0)
- bpf_error("unknown port in range '%s'", name);
+ bpf_error(cstate, "unknown port in range '%s'", name);
if (proto == Q_UDP) {
if (real_proto == IPPROTO_TCP)
- bpf_error("port in range '%s' is tcp", name);
+ bpf_error(cstate, "port in range '%s' is tcp", name);
else if (real_proto == IPPROTO_SCTP)
- bpf_error("port in range '%s' is sctp", name);
+ bpf_error(cstate, "port in range '%s' is sctp", name);
else
/* override PROTO_UNDEF */
real_proto = IPPROTO_UDP;
}
if (proto == Q_TCP) {
if (real_proto == IPPROTO_UDP)
- bpf_error("port in range '%s' is udp", name);
+ bpf_error(cstate, "port in range '%s' is udp", name);
else if (real_proto == IPPROTO_SCTP)
- bpf_error("port in range '%s' is sctp", name);
+ bpf_error(cstate, "port in range '%s' is sctp", name);
else
/* override PROTO_UNDEF */
real_proto = IPPROTO_TCP;
}
if (proto == Q_SCTP) {
if (real_proto == IPPROTO_UDP)
- bpf_error("port in range '%s' is udp", name);
+ bpf_error(cstate, "port in range '%s' is udp", name);
else if (real_proto == IPPROTO_TCP)
- bpf_error("port in range '%s' is tcp", name);
+ bpf_error(cstate, "port in range '%s' is tcp", name);
else
/* override PROTO_UNDEF */
real_proto = IPPROTO_SCTP;
}
if (port1 < 0)
- bpf_error("illegal port number %d < 0", port1);
+ bpf_error(cstate, "illegal port number %d < 0", port1);
if (port1 > 65535)
- bpf_error("illegal port number %d > 65535", port1);
+ bpf_error(cstate, "illegal port number %d > 65535", port1);
if (port2 < 0)
- bpf_error("illegal port number %d < 0", port2);
+ bpf_error(cstate, "illegal port number %d < 0", port2);
if (port2 > 65535)
- bpf_error("illegal port number %d > 65535", port2);
+ bpf_error(cstate, "illegal port number %d > 65535", port2);
- b = gen_portrange(port1, port2, real_proto, dir);
- gen_or(gen_portrange6(port1, port2, real_proto, dir), b);
+ b = gen_portrange(cstate, port1, port2, real_proto, dir);
+ gen_or(gen_portrange6(cstate, port1, port2, real_proto, dir), b);
return b;
case Q_GATEWAY:
#ifndef INET6
eaddr = pcap_ether_hostton(name);
if (eaddr == NULL)
- bpf_error("unknown ether host: %s", name);
+ bpf_error(cstate, "unknown ether host: %s", name);
alist = pcap_nametoaddr(name);
if (alist == NULL || *alist == NULL)
- bpf_error("unknown host '%s'", name);
+ bpf_error(cstate, "unknown host '%s'", name);
b = gen_gateway(eaddr, alist, proto, dir);
free(eaddr);
return b;
#else
- bpf_error("'gateway' not supported in this configuration");
+ bpf_error(cstate, "'gateway' not supported in this configuration");
#endif /*INET6*/
case Q_PROTO:
- real_proto = lookup_proto(name, proto);
+ real_proto = lookup_proto(cstate, name, proto);
if (real_proto >= 0)
- return gen_proto(real_proto, proto, dir);
+ return gen_proto(cstate, real_proto, proto, dir);
else
- bpf_error("unknown protocol: %s", name);
+ bpf_error(cstate, "unknown protocol: %s", name);
case Q_PROTOCHAIN:
- real_proto = lookup_proto(name, proto);
+ real_proto = lookup_proto(cstate, name, proto);
if (real_proto >= 0)
- return gen_protochain(real_proto, proto, dir);
+ return gen_protochain(cstate, real_proto, proto, dir);
else
- bpf_error("unknown protocol: %s", name);
+ bpf_error(cstate, "unknown protocol: %s", name);
case Q_UNDEF:
- syntax();
+ syntax(cstate);
/* NOTREACHED */
}
abort();
@@ -6524,10 +6502,8 @@ gen_scode(name, q)
}
struct block *
-gen_mcode(s1, s2, masklen, q)
- register const char *s1, *s2;
- register int masklen;
- struct qual q;
+gen_mcode(compiler_state_t *cstate, const char *s1, const char *s2,
+ unsigned int masklen, struct qual q)
{
register int nlen, mlen;
bpf_u_int32 n, m;
@@ -6541,12 +6517,12 @@ gen_mcode(s1, s2, masklen, q)
/* Promote short ipaddr */
m <<= 32 - mlen;
if ((n & ~m) != 0)
- bpf_error("non-network bits set in \"%s mask %s\"",
+ bpf_error(cstate, "non-network bits set in \"%s mask %s\"",
s1, s2);
} else {
/* Convert mask len to mask */
if (masklen > 32)
- bpf_error("mask length must be <= 32");
+ bpf_error(cstate, "mask length must be <= 32");
if (masklen == 0) {
/*
* X << 32 is not guaranteed by C to be 0; it's
@@ -6556,17 +6532,17 @@ gen_mcode(s1, s2, masklen, q)
} else
m = 0xffffffff << (32 - masklen);
if ((n & ~m) != 0)
- bpf_error("non-network bits set in \"%s/%d\"",
+ bpf_error(cstate, "non-network bits set in \"%s/%d\"",
s1, masklen);
}
switch (q.addr) {
case Q_NET:
- return gen_host(n, m, q.proto, q.dir, q.addr);
+ return gen_host(cstate, n, m, q.proto, q.dir, q.addr);
default:
- bpf_error("Mask syntax for networks only");
+ bpf_error(cstate, "Mask syntax for networks only");
/* NOTREACHED */
}
/* NOTREACHED */
@@ -6574,10 +6550,7 @@ gen_mcode(s1, s2, masklen, q)
}
struct block *
-gen_ncode(s, v, q)
- register const char *s;
- bpf_u_int32 v;
- struct qual q;
+gen_ncode(compiler_state_t *cstate, const char *s, bpf_u_int32 v, struct qual q)
{
bpf_u_int32 mask;
int proto = q.proto;
@@ -6586,9 +6559,11 @@ gen_ncode(s, v, q)
if (s == NULL)
vlen = 32;
- else if (q.proto == Q_DECNET)
+ else if (q.proto == Q_DECNET) {
vlen = __pcap_atodn(s, &v);
- else
+ if (vlen == 0)
+ bpf_error(cstate, "malformed decnet address '%s'", s);
+ } else
vlen = __pcap_atoin(s, &v);
switch (q.addr) {
@@ -6597,9 +6572,9 @@ gen_ncode(s, v, q)
case Q_HOST:
case Q_NET:
if (proto == Q_DECNET)
- return gen_host(v, 0, proto, dir, q.addr);
+ return gen_host(cstate, v, 0, proto, dir, q.addr);
else if (proto == Q_LINK) {
- bpf_error("illegal link layer address");
+ bpf_error(cstate, "illegal link layer address");
} else {
mask = 0xffffffff;
if (s == NULL && q.addr == Q_NET) {
@@ -6611,9 +6586,9 @@ gen_ncode(s, v, q)
} else {
/* Promote short ipaddr */
v <<= 32 - vlen;
- mask <<= 32 - vlen;
+ mask <<= 32 - vlen ;
}
- return gen_host(v, mask, proto, dir, q.addr);
+ return gen_host(cstate, v, mask, proto, dir, q.addr);
}
case Q_PORT:
@@ -6626,15 +6601,15 @@ gen_ncode(s, v, q)
else if (proto == Q_DEFAULT)
proto = PROTO_UNDEF;
else
- bpf_error("illegal qualifier of 'port'");
+ bpf_error(cstate, "illegal qualifier of 'port'");
if (v > 65535)
- bpf_error("illegal port number %u > 65535", v);
+ bpf_error(cstate, "illegal port number %u > 65535", v);
{
struct block *b;
- b = gen_port((int)v, proto, dir);
- gen_or(gen_port6((int)v, proto, dir), b);
+ b = gen_port(cstate, (int)v, proto, dir);
+ gen_or(gen_port6(cstate, (int)v, proto, dir), b);
return b;
}
@@ -6648,30 +6623,30 @@ gen_ncode(s, v, q)
else if (proto == Q_DEFAULT)
proto = PROTO_UNDEF;
else
- bpf_error("illegal qualifier of 'portrange'");
+ bpf_error(cstate, "illegal qualifier of 'portrange'");
if (v > 65535)
- bpf_error("illegal port number %u > 65535", v);
+ bpf_error(cstate, "illegal port number %u > 65535", v);
{
struct block *b;
- b = gen_portrange((int)v, (int)v, proto, dir);
- gen_or(gen_portrange6((int)v, (int)v, proto, dir), b);
+ b = gen_portrange(cstate, (int)v, (int)v, proto, dir);
+ gen_or(gen_portrange6(cstate, (int)v, (int)v, proto, dir), b);
return b;
}
case Q_GATEWAY:
- bpf_error("'gateway' requires a name");
+ bpf_error(cstate, "'gateway' requires a name");
/* NOTREACHED */
case Q_PROTO:
- return gen_proto((int)v, proto, dir);
+ return gen_proto(cstate, (int)v, proto, dir);
case Q_PROTOCHAIN:
- return gen_protochain((int)v, proto, dir);
+ return gen_protochain(cstate, (int)v, proto, dir);
case Q_UNDEF:
- syntax();
+ syntax(cstate);
/* NOTREACHED */
default:
@@ -6683,10 +6658,8 @@ gen_ncode(s, v, q)
#ifdef INET6
struct block *
-gen_mcode6(s1, s2, masklen, q)
- register const char *s1, *s2;
- register int masklen;
- struct qual q;
+gen_mcode6(compiler_state_t *cstate, const char *s1, const char *s2,
+ unsigned int masklen, struct qual q)
{
struct addrinfo *res;
struct in6_addr *addr;
@@ -6695,18 +6668,18 @@ gen_mcode6(s1, s2, masklen, q)
u_int32_t *a, *m;
if (s2)
- bpf_error("no mask %s supported", s2);
+ bpf_error(cstate, "no mask %s supported", s2);
res = pcap_nametoaddrinfo(s1);
if (!res)
- bpf_error("invalid ip6 address %s", s1);
- ai = res;
+ bpf_error(cstate, "invalid ip6 address %s", s1);
+ cstate->ai = res;
if (res->ai_next)
- bpf_error("%s resolved to multiple address", s1);
+ bpf_error(cstate, "%s resolved to multiple address", s1);
addr = &((struct sockaddr_in6 *)res->ai_addr)->sin6_addr;
if (sizeof(mask) * 8 < masklen)
- bpf_error("mask length must be <= %u", (unsigned int)(sizeof(mask) * 8));
+ bpf_error(cstate, "mask length must be <= %u", (unsigned int)(sizeof(mask) * 8));
memset(&mask, 0, sizeof(mask));
memset(&mask, 0xff, masklen / 8);
if (masklen % 8) {
@@ -6718,7 +6691,7 @@ gen_mcode6(s1, s2, masklen, q)
m = (u_int32_t *)&mask;
if ((a[0] & ~m[0]) || (a[1] & ~m[1])
|| (a[2] & ~m[2]) || (a[3] & ~m[3])) {
- bpf_error("non-network bits set in \"%s/%d\"", s1, masklen);
+ bpf_error(cstate, "non-network bits set in \"%s/%d\"", s1, masklen);
}
switch (q.addr) {
@@ -6726,17 +6699,17 @@ gen_mcode6(s1, s2, masklen, q)
case Q_DEFAULT:
case Q_HOST:
if (masklen != 128)
- bpf_error("Mask syntax for networks only");
+ bpf_error(cstate, "Mask syntax for networks only");
/* FALLTHROUGH */
case Q_NET:
- b = gen_host6(addr, &mask, q.proto, q.dir, q.addr);
- ai = NULL;
+ b = gen_host6(cstate, addr, &mask, q.proto, q.dir, q.addr);
+ cstate->ai = NULL;
freeaddrinfo(res);
return b;
default:
- bpf_error("invalid qualifier against IPv6 address");
+ bpf_error(cstate, "invalid qualifier against IPv6 address");
/* NOTREACHED */
}
return NULL;
@@ -6744,55 +6717,38 @@ gen_mcode6(s1, s2, masklen, q)
#endif /*INET6*/
struct block *
-gen_ecode(eaddr, q)
- register const u_char *eaddr;
- struct qual q;
+gen_ecode(compiler_state_t *cstate, const u_char *eaddr, struct qual q)
{
struct block *b, *tmp;
if ((q.addr == Q_HOST || q.addr == Q_DEFAULT) && q.proto == Q_LINK) {
- switch (linktype) {
+ switch (cstate->linktype) {
case DLT_EN10MB:
case DLT_NETANALYZER:
case DLT_NETANALYZER_TRANSPARENT:
- return gen_ehostop(eaddr, (int)q.dir);
+ tmp = gen_prevlinkhdr_check(cstate);
+ b = gen_ehostop(cstate, eaddr, (int)q.dir);
+ if (tmp != NULL)
+ gen_and(tmp, b);
+ return b;
case DLT_FDDI:
- return gen_fhostop(eaddr, (int)q.dir);
+ return gen_fhostop(cstate, eaddr, (int)q.dir);
case DLT_IEEE802:
- return gen_thostop(eaddr, (int)q.dir);
+ return gen_thostop(cstate, eaddr, (int)q.dir);
case DLT_IEEE802_11:
case DLT_PRISM_HEADER:
case DLT_IEEE802_11_RADIO_AVS:
case DLT_IEEE802_11_RADIO:
case DLT_PPI:
- return gen_wlanhostop(eaddr, (int)q.dir);
- case DLT_SUNATM:
- if (is_lane) {
- /*
- * Check that the packet doesn't begin with an
- * LE Control marker. (We've already generated
- * a test for LANE.)
- */
- tmp = gen_cmp(OR_LINK, SUNATM_PKT_BEGIN_POS, BPF_H,
- 0xFF00);
- gen_not(tmp);
-
- /*
- * Now check the MAC address.
- */
- b = gen_ehostop(eaddr, (int)q.dir);
- gen_and(tmp, b);
- return b;
- }
- break;
+ return gen_wlanhostop(cstate, eaddr, (int)q.dir);
case DLT_IP_OVER_FC:
- return gen_ipfchostop(eaddr, (int)q.dir);
+ return gen_ipfchostop(cstate, eaddr, (int)q.dir);
default:
- bpf_error("ethernet addresses supported only on ethernet/FDDI/token ring/802.11/ATM LANE/Fibre Channel");
+ bpf_error(cstate, "ethernet addresses supported only on ethernet/FDDI/token ring/802.11/ATM LANE/Fibre Channel");
break;
}
}
- bpf_error("ethernet address used in non-ether expression");
+ bpf_error(cstate, "ethernet address used in non-ether expression");
/* NOTREACHED */
return NULL;
}
@@ -6811,23 +6767,21 @@ sappend(s0, s1)
}
static struct slist *
-xfer_to_x(a)
- struct arth *a;
+xfer_to_x(compiler_state_t *cstate, struct arth *a)
{
struct slist *s;
- s = new_stmt(BPF_LDX|BPF_MEM);
+ s = new_stmt(cstate, BPF_LDX|BPF_MEM);
s->s.k = a->regno;
return s;
}
static struct slist *
-xfer_to_a(a)
- struct arth *a;
+xfer_to_a(compiler_state_t *cstate, struct arth *a)
{
struct slist *s;
- s = new_stmt(BPF_LD|BPF_MEM);
+ s = new_stmt(cstate, BPF_LD|BPF_MEM);
s->s.k = a->regno;
return s;
}
@@ -6840,20 +6794,17 @@ xfer_to_a(a)
* for "index".
*/
struct arth *
-gen_load(proto, inst, size)
- int proto;
- struct arth *inst;
- int size;
+gen_load(compiler_state_t *cstate, int proto, struct arth *inst, int size)
{
struct slist *s, *tmp;
struct block *b;
- int regno = alloc_reg();
+ int regno = alloc_reg(cstate);
- free_reg(inst->regno);
+ free_reg(cstate, inst->regno);
switch (size) {
default:
- bpf_error("data size must be 1, 2, or 4");
+ bpf_error(cstate, "data size must be 1, 2, or 4");
case 1:
size = BPF_B;
@@ -6869,7 +6820,7 @@ gen_load(proto, inst, size)
}
switch (proto) {
default:
- bpf_error("unsupported index operation");
+ bpf_error(cstate, "unsupported index operation");
case Q_RADIO:
/*
@@ -6877,21 +6828,21 @@ gen_load(proto, inst, size)
* data, if we have a radio header. (If we don't, this
* is an error.)
*/
- if (linktype != DLT_IEEE802_11_RADIO_AVS &&
- linktype != DLT_IEEE802_11_RADIO &&
- linktype != DLT_PRISM_HEADER)
- bpf_error("radio information not present in capture");
+ if (cstate->linktype != DLT_IEEE802_11_RADIO_AVS &&
+ cstate->linktype != DLT_IEEE802_11_RADIO &&
+ cstate->linktype != DLT_PRISM_HEADER)
+ bpf_error(cstate, "radio information not present in capture");
/*
* Load into the X register the offset computed into the
* register specified by "index".
*/
- s = xfer_to_x(inst);
+ s = xfer_to_x(cstate, inst);
/*
* Load the item at that offset.
*/
- tmp = new_stmt(BPF_LD|BPF_IND|size);
+ tmp = new_stmt(cstate, BPF_LD|BPF_IND|size);
sappend(s, tmp);
sappend(inst->s, s);
break;
@@ -6908,7 +6859,7 @@ gen_load(proto, inst, size)
* frame, so that 0 refers, for Ethernet LANE, to
* the beginning of the destination address?
*/
- s = gen_llprefixlen();
+ s = gen_abs_offset_varpart(cstate, &cstate->off_linkhdr);
/*
* If "s" is non-null, it has code to arrange that the
@@ -6920,11 +6871,11 @@ gen_load(proto, inst, size)
* by "index".
*/
if (s != NULL) {
- sappend(s, xfer_to_a(inst));
- sappend(s, new_stmt(BPF_ALU|BPF_ADD|BPF_X));
- sappend(s, new_stmt(BPF_MISC|BPF_TAX));
+ sappend(s, xfer_to_a(cstate, inst));
+ sappend(s, new_stmt(cstate, BPF_ALU|BPF_ADD|BPF_X));
+ sappend(s, new_stmt(cstate, BPF_MISC|BPF_TAX));
} else
- s = xfer_to_x(inst);
+ s = xfer_to_x(cstate, inst);
/*
* Load the item at the sum of the offset we've put in the
@@ -6933,8 +6884,8 @@ gen_load(proto, inst, size)
* variable-length; that header length is what we put
* into the X register and then added to the index).
*/
- tmp = new_stmt(BPF_LD|BPF_IND|size);
- tmp->s.k = off_ll;
+ tmp = new_stmt(cstate, BPF_LD|BPF_IND|size);
+ tmp->s.k = cstate->off_linkhdr.constant_part;
sappend(s, tmp);
sappend(inst->s, s);
break;
@@ -6953,40 +6904,35 @@ gen_load(proto, inst, size)
* The offset is relative to the beginning of
* the network-layer header.
* XXX - are there any cases where we want
- * off_nl_nosnap?
+ * cstate->off_nl_nosnap?
*/
- s = gen_off_macpl();
+ s = gen_abs_offset_varpart(cstate, &cstate->off_linkpl);
/*
* If "s" is non-null, it has code to arrange that the
- * X register contains the offset of the MAC-layer
- * payload. Add to it the offset computed into the
- * register specified by "index", and move that into
- * the X register. Otherwise, just load into the X
- * register the offset computed into the register specified
- * by "index".
+ * X register contains the variable part of the offset
+ * of the link-layer payload. Add to it the offset
+ * computed into the register specified by "index",
+ * and move that into the X register. Otherwise, just
+ * load into the X register the offset computed into
+ * the register specified by "index".
*/
if (s != NULL) {
- sappend(s, xfer_to_a(inst));
- sappend(s, new_stmt(BPF_ALU|BPF_ADD|BPF_X));
- sappend(s, new_stmt(BPF_MISC|BPF_TAX));
+ sappend(s, xfer_to_a(cstate, inst));
+ sappend(s, new_stmt(cstate, BPF_ALU|BPF_ADD|BPF_X));
+ sappend(s, new_stmt(cstate, BPF_MISC|BPF_TAX));
} else
- s = xfer_to_x(inst);
+ s = xfer_to_x(cstate, inst);
/*
* Load the item at the sum of the offset we've put in the
* X register, the offset of the start of the network
- * layer header from the beginning of the MAC-layer
- * payload, and the purported offset of the start of the
- * MAC-layer payload (which might be 0 if there's a
- * variable-length prefix before the link-layer header
- * or the link-layer header itself is variable-length;
- * the variable-length offset of the start of the
- * MAC-layer payload is what we put into the X register
- * and then added to the index).
- */
- tmp = new_stmt(BPF_LD|BPF_IND|size);
- tmp->s.k = off_macpl + off_nl;
+ * layer header from the beginning of the link-layer
+ * payload, and the constant part of the offset of the
+ * start of the link-layer payload.
+ */
+ tmp = new_stmt(cstate, BPF_LD|BPF_IND|size);
+ tmp->s.k = cstate->off_linkpl.constant_part + cstate->off_nl;
sappend(s, tmp);
sappend(inst->s, s);
@@ -6994,7 +6940,7 @@ gen_load(proto, inst, size)
* Do the computation only if the packet contains
* the protocol in question.
*/
- b = gen_proto_abbrev(proto);
+ b = gen_proto_abbrev(cstate, proto);
if (inst->b)
gen_and(inst->b, b);
inst->b = b;
@@ -7018,34 +6964,32 @@ gen_load(proto, inst, size)
* a variable-length header), in bytes.
*
* XXX - are there any cases where we want
- * off_nl_nosnap?
+ * cstate->off_nl_nosnap?
* XXX - we should, if we're built with
* IPv6 support, generate code to load either
* IPv4, IPv6, or both, as appropriate.
*/
- s = gen_loadx_iphdrlen();
+ s = gen_loadx_iphdrlen(cstate);
/*
- * The X register now contains the sum of the length
- * of any variable-length header preceding the link-layer
- * header, any variable-length link-layer header, and the
+ * The X register now contains the sum of the variable
+ * part of the offset of the link-layer payload and the
* length of the network-layer header.
*
* Load into the A register the offset relative to
* the beginning of the transport layer header,
* add the X register to that, move that to the
* X register, and load with an offset from the
- * X register equal to the offset of the network
- * layer header relative to the beginning of
- * the MAC-layer payload plus the fixed-length
- * portion of the offset of the MAC-layer payload
- * from the beginning of the raw packet data.
- */
- sappend(s, xfer_to_a(inst));
- sappend(s, new_stmt(BPF_ALU|BPF_ADD|BPF_X));
- sappend(s, new_stmt(BPF_MISC|BPF_TAX));
- sappend(s, tmp = new_stmt(BPF_LD|BPF_IND|size));
- tmp->s.k = off_macpl + off_nl;
+ * X register equal to the sum of the constant part of
+ * the offset of the link-layer payload and the offset,
+ * relative to the beginning of the link-layer payload,
+ * of the network-layer header.
+ */
+ sappend(s, xfer_to_a(cstate, inst));
+ sappend(s, new_stmt(cstate, BPF_ALU|BPF_ADD|BPF_X));
+ sappend(s, new_stmt(cstate, BPF_MISC|BPF_TAX));
+ sappend(s, tmp = new_stmt(cstate, BPF_LD|BPF_IND|size));
+ tmp->s.k = cstate->off_linkpl.constant_part + cstate->off_nl;
sappend(inst->s, s);
/*
@@ -7054,18 +6998,18 @@ gen_load(proto, inst, size)
* if this is an IP datagram and is the first or
* only fragment of that datagram.
*/
- gen_and(gen_proto_abbrev(proto), b = gen_ipfrag());
+ gen_and(gen_proto_abbrev(cstate, proto), b = gen_ipfrag(cstate));
if (inst->b)
gen_and(inst->b, b);
- gen_and(gen_proto_abbrev(Q_IP), b);
+ gen_and(gen_proto_abbrev(cstate, Q_IP), b);
inst->b = b;
break;
case Q_ICMPV6:
- bpf_error("IPv6 upper-layer protocol is not supported by proto[x]");
+ bpf_error(cstate, "IPv6 upper-layer protocol is not supported by proto[x]");
/*NOTREACHED*/
}
inst->regno = regno;
- s = new_stmt(BPF_ST);
+ s = new_stmt(cstate, BPF_ST);
s->s.k = regno;
sappend(inst->s, s);
@@ -7073,23 +7017,21 @@ gen_load(proto, inst, size)
}
struct block *
-gen_relation(code, a0, a1, reversed)
- int code;
- struct arth *a0, *a1;
- int reversed;
+gen_relation(compiler_state_t *cstate, int code, struct arth *a0,
+ struct arth *a1, int reversed)
{
struct slist *s0, *s1, *s2;
struct block *b, *tmp;
- s0 = xfer_to_x(a1);
- s1 = xfer_to_a(a0);
+ s0 = xfer_to_x(cstate, a1);
+ s1 = xfer_to_a(cstate, a0);
if (code == BPF_JEQ) {
- s2 = new_stmt(BPF_ALU|BPF_SUB|BPF_X);
- b = new_block(JMP(code));
+ s2 = new_stmt(cstate, BPF_ALU|BPF_SUB|BPF_X);
+ b = new_block(cstate, JMP(code));
sappend(s1, s2);
}
else
- b = new_block(BPF_JMP|code|BPF_X);
+ b = new_block(cstate, BPF_JMP|code|BPF_X);
if (reversed)
gen_not(b);
@@ -7099,8 +7041,8 @@ gen_relation(code, a0, a1, reversed)
b->stmts = a0->s;
- free_reg(a0->regno);
- free_reg(a1->regno);
+ free_reg(cstate, a0->regno);
+ free_reg(cstate, a1->regno);
/* 'and' together protocol checks */
if (a0->b) {
@@ -7119,14 +7061,14 @@ gen_relation(code, a0, a1, reversed)
}
struct arth *
-gen_loadlen()
+gen_loadlen(compiler_state_t *cstate)
{
- int regno = alloc_reg();
- struct arth *a = (struct arth *)newchunk(sizeof(*a));
+ int regno = alloc_reg(cstate);
+ struct arth *a = (struct arth *)newchunk(cstate, sizeof(*a));
struct slist *s;
- s = new_stmt(BPF_LD|BPF_LEN);
- s->next = new_stmt(BPF_ST);
+ s = new_stmt(cstate, BPF_LD|BPF_LEN);
+ s->next = new_stmt(cstate, BPF_ST);
s->next->s.k = regno;
a->s = s;
a->regno = regno;
@@ -7135,20 +7077,19 @@ gen_loadlen()
}
struct arth *
-gen_loadi(val)
- int val;
+gen_loadi(compiler_state_t *cstate, int val)
{
struct arth *a;
struct slist *s;
int reg;
- a = (struct arth *)newchunk(sizeof(*a));
+ a = (struct arth *)newchunk(cstate, sizeof(*a));
- reg = alloc_reg();
+ reg = alloc_reg(cstate);
- s = new_stmt(BPF_LD|BPF_IMM);
+ s = new_stmt(cstate, BPF_LD|BPF_IMM);
s->s.k = val;
- s->next = new_stmt(BPF_ST);
+ s->next = new_stmt(cstate, BPF_ST);
s->next->s.k = reg;
a->s = s;
a->regno = reg;
@@ -7157,17 +7098,16 @@ gen_loadi(val)
}
struct arth *
-gen_neg(a)
- struct arth *a;
+gen_neg(compiler_state_t *cstate, struct arth *a)
{
struct slist *s;
- s = xfer_to_a(a);
+ s = xfer_to_a(cstate, a);
sappend(a->s, s);
- s = new_stmt(BPF_ALU|BPF_NEG);
+ s = new_stmt(cstate, BPF_ALU|BPF_NEG);
s->s.k = 0;
sappend(a->s, s);
- s = new_stmt(BPF_ST);
+ s = new_stmt(cstate, BPF_ST);
s->s.k = a->regno;
sappend(a->s, s);
@@ -7175,65 +7115,68 @@ gen_neg(a)
}
struct arth *
-gen_arth(code, a0, a1)
- int code;
- struct arth *a0, *a1;
+gen_arth(compiler_state_t *cstate, int code, struct arth *a0,
+ struct arth *a1)
{
struct slist *s0, *s1, *s2;
- s0 = xfer_to_x(a1);
- s1 = xfer_to_a(a0);
- s2 = new_stmt(BPF_ALU|BPF_X|code);
+ /*
+ * Disallow division by, or modulus by, zero; we do this here
+ * so that it gets done even if the optimizer is disabled.
+ */
+ if (code == BPF_DIV) {
+ if (a1->s->s.code == (BPF_LD|BPF_IMM) && a1->s->s.k == 0)
+ bpf_error(cstate, "division by zero");
+ } else if (code == BPF_MOD) {
+ if (a1->s->s.code == (BPF_LD|BPF_IMM) && a1->s->s.k == 0)
+ bpf_error(cstate, "modulus by zero");
+ }
+ s0 = xfer_to_x(cstate, a1);
+ s1 = xfer_to_a(cstate, a0);
+ s2 = new_stmt(cstate, BPF_ALU|BPF_X|code);
sappend(s1, s2);
sappend(s0, s1);
sappend(a1->s, s0);
sappend(a0->s, a1->s);
- free_reg(a0->regno);
- free_reg(a1->regno);
+ free_reg(cstate, a0->regno);
+ free_reg(cstate, a1->regno);
- s0 = new_stmt(BPF_ST);
- a0->regno = s0->s.k = alloc_reg();
+ s0 = new_stmt(cstate, BPF_ST);
+ a0->regno = s0->s.k = alloc_reg(cstate);
sappend(a0->s, s0);
return a0;
}
/*
- * Here we handle simple allocation of the scratch registers.
- * If too many registers are alloc'd, the allocator punts.
- */
-static int regused[BPF_MEMWORDS];
-static int curreg;
-
-/*
* Initialize the table of used registers and the current register.
*/
static void
-init_regs()
+init_regs(compiler_state_t *cstate)
{
- curreg = 0;
- memset(regused, 0, sizeof regused);
+ cstate->curreg = 0;
+ memset(cstate->regused, 0, sizeof cstate->regused);
}
/*
* Return the next free register.
*/
static int
-alloc_reg()
+alloc_reg(compiler_state_t *cstate)
{
int n = BPF_MEMWORDS;
while (--n >= 0) {
- if (regused[curreg])
- curreg = (curreg + 1) % BPF_MEMWORDS;
+ if (cstate->regused[cstate->curreg])
+ cstate->curreg = (cstate->curreg + 1) % BPF_MEMWORDS;
else {
- regused[curreg] = 1;
- return curreg;
+ cstate->regused[cstate->curreg] = 1;
+ return cstate->curreg;
}
}
- bpf_error("too many registers needed to evaluate expression");
+ bpf_error(cstate, "too many registers needed to evaluate expression");
/* NOTREACHED */
return 0;
}
@@ -7243,21 +7186,19 @@ alloc_reg()
* be used later.
*/
static void
-free_reg(n)
- int n;
+free_reg(compiler_state_t *cstate, int n)
{
- regused[n] = 0;
+ cstate->regused[n] = 0;
}
static struct block *
-gen_len(jmp, n)
- int jmp, n;
+gen_len(compiler_state_t *cstate, int jmp, int n)
{
struct slist *s;
struct block *b;
- s = new_stmt(BPF_LD|BPF_LEN);
- b = new_block(JMP(jmp));
+ s = new_stmt(cstate, BPF_LD|BPF_LEN);
+ b = new_block(cstate, JMP(jmp));
b->stmts = s;
b->s.k = n;
@@ -7265,22 +7206,20 @@ gen_len(jmp, n)
}
struct block *
-gen_greater(n)
- int n;
+gen_greater(compiler_state_t *cstate, int n)
{
- return gen_len(BPF_JGE, n);
+ return gen_len(cstate, BPF_JGE, n);
}
/*
* Actually, this is less than or equal.
*/
struct block *
-gen_less(n)
- int n;
+gen_less(compiler_state_t *cstate, int n)
{
struct block *b;
- b = gen_len(BPF_JGT, n);
+ b = gen_len(cstate, BPF_JGT, n);
gen_not(b);
return b;
@@ -7297,8 +7236,7 @@ gen_less(n)
* would generate code appropriate to the radio header in question.
*/
struct block *
-gen_byteop(op, idx, val)
- int op, idx, val;
+gen_byteop(compiler_state_t *cstate, int op, int idx, int val)
{
struct block *b;
struct slist *s;
@@ -7308,87 +7246,71 @@ gen_byteop(op, idx, val)
abort();
case '=':
- return gen_cmp(OR_LINK, (u_int)idx, BPF_B, (bpf_int32)val);
+ return gen_cmp(cstate, OR_LINKHDR, (u_int)idx, BPF_B, (bpf_int32)val);
case '<':
- b = gen_cmp_lt(OR_LINK, (u_int)idx, BPF_B, (bpf_int32)val);
+ b = gen_cmp_lt(cstate, OR_LINKHDR, (u_int)idx, BPF_B, (bpf_int32)val);
return b;
case '>':
- b = gen_cmp_gt(OR_LINK, (u_int)idx, BPF_B, (bpf_int32)val);
+ b = gen_cmp_gt(cstate, OR_LINKHDR, (u_int)idx, BPF_B, (bpf_int32)val);
return b;
case '|':
- s = new_stmt(BPF_ALU|BPF_OR|BPF_K);
+ s = new_stmt(cstate, BPF_ALU|BPF_OR|BPF_K);
break;
case '&':
- s = new_stmt(BPF_ALU|BPF_AND|BPF_K);
+ s = new_stmt(cstate, BPF_ALU|BPF_AND|BPF_K);
break;
}
s->s.k = val;
- b = new_block(JMP(BPF_JEQ));
+ b = new_block(cstate, JMP(BPF_JEQ));
b->stmts = s;
gen_not(b);
return b;
}
-static u_char abroadcast[] = { 0x0 };
+static const u_char abroadcast[] = { 0x0 };
struct block *
-gen_broadcast(proto)
- int proto;
+gen_broadcast(compiler_state_t *cstate, int proto)
{
bpf_u_int32 hostmask;
struct block *b0, *b1, *b2;
- static u_char ebroadcast[] = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff };
+ static const u_char ebroadcast[] = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff };
switch (proto) {
case Q_DEFAULT:
case Q_LINK:
- switch (linktype) {
+ switch (cstate->linktype) {
case DLT_ARCNET:
case DLT_ARCNET_LINUX:
- return gen_ahostop(abroadcast, Q_DST);
+ return gen_ahostop(cstate, abroadcast, Q_DST);
case DLT_EN10MB:
case DLT_NETANALYZER:
case DLT_NETANALYZER_TRANSPARENT:
- return gen_ehostop(ebroadcast, Q_DST);
+ b1 = gen_prevlinkhdr_check(cstate);
+ b0 = gen_ehostop(cstate, ebroadcast, Q_DST);
+ if (b1 != NULL)
+ gen_and(b1, b0);
+ return b0;
case DLT_FDDI:
- return gen_fhostop(ebroadcast, Q_DST);
+ return gen_fhostop(cstate, ebroadcast, Q_DST);
case DLT_IEEE802:
- return gen_thostop(ebroadcast, Q_DST);
+ return gen_thostop(cstate, ebroadcast, Q_DST);
case DLT_IEEE802_11:
case DLT_PRISM_HEADER:
case DLT_IEEE802_11_RADIO_AVS:
case DLT_IEEE802_11_RADIO:
case DLT_PPI:
- return gen_wlanhostop(ebroadcast, Q_DST);
+ return gen_wlanhostop(cstate, ebroadcast, Q_DST);
case DLT_IP_OVER_FC:
- return gen_ipfchostop(ebroadcast, Q_DST);
- case DLT_SUNATM:
- if (is_lane) {
- /*
- * Check that the packet doesn't begin with an
- * LE Control marker. (We've already generated
- * a test for LANE.)
- */
- b1 = gen_cmp(OR_LINK, SUNATM_PKT_BEGIN_POS,
- BPF_H, 0xFF00);
- gen_not(b1);
-
- /*
- * Now check the MAC address.
- */
- b0 = gen_ehostop(ebroadcast, Q_DST);
- gen_and(b1, b0);
- return b0;
- }
- break;
+ return gen_ipfchostop(cstate, ebroadcast, Q_DST);
default:
- bpf_error("not a broadcast link");
+ bpf_error(cstate, "not a broadcast link");
}
break;
@@ -7398,18 +7320,18 @@ gen_broadcast(proto)
* as an indication that we don't know the netmask, and fail
* in that case.
*/
- if (netmask == PCAP_NETMASK_UNKNOWN)
- bpf_error("netmask not known, so 'ip broadcast' not supported");
- b0 = gen_linktype(ETHERTYPE_IP);
- hostmask = ~netmask;
- b1 = gen_mcmp(OR_NET, 16, BPF_W, (bpf_int32)0, hostmask);
- b2 = gen_mcmp(OR_NET, 16, BPF_W,
+ if (cstate->netmask == PCAP_NETMASK_UNKNOWN)
+ bpf_error(cstate, "netmask not known, so 'ip broadcast' not supported");
+ b0 = gen_linktype(cstate, ETHERTYPE_IP);
+ hostmask = ~cstate->netmask;
+ b1 = gen_mcmp(cstate, OR_LINKPL, 16, BPF_W, (bpf_int32)0, hostmask);
+ b2 = gen_mcmp(cstate, OR_LINKPL, 16, BPF_W,
(bpf_int32)(~0 & hostmask), hostmask);
gen_or(b1, b2);
gen_and(b0, b2);
return b2;
}
- bpf_error("only link-layer/IP broadcast filters supported");
+ bpf_error(cstate, "only link-layer/IP broadcast filters supported");
/* NOTREACHED */
return NULL;
}
@@ -7419,23 +7341,21 @@ gen_broadcast(proto)
* the bottom bit of the *first* byte).
*/
static struct block *
-gen_mac_multicast(offset)
- int offset;
+gen_mac_multicast(compiler_state_t *cstate, int offset)
{
register struct block *b0;
register struct slist *s;
/* link[offset] & 1 != 0 */
- s = gen_load_a(OR_LINK, offset, BPF_B);
- b0 = new_block(JMP(BPF_JSET));
+ s = gen_load_a(cstate, OR_LINKHDR, offset, BPF_B);
+ b0 = new_block(cstate, JMP(BPF_JSET));
b0->s.k = 1;
b0->stmts = s;
return b0;
}
struct block *
-gen_multicast(proto)
- int proto;
+gen_multicast(compiler_state_t *cstate, int proto)
{
register struct block *b0, *b1, *b2;
register struct slist *s;
@@ -7444,16 +7364,20 @@ gen_multicast(proto)
case Q_DEFAULT:
case Q_LINK:
- switch (linktype) {
+ switch (cstate->linktype) {
case DLT_ARCNET:
case DLT_ARCNET_LINUX:
/* all ARCnet multicasts use the same address */
- return gen_ahostop(abroadcast, Q_DST);
+ return gen_ahostop(cstate, abroadcast, Q_DST);
case DLT_EN10MB:
case DLT_NETANALYZER:
case DLT_NETANALYZER_TRANSPARENT:
+ b1 = gen_prevlinkhdr_check(cstate);
/* ether[0] & 1 != 0 */
- return gen_mac_multicast(0);
+ b0 = gen_mac_multicast(cstate, 0);
+ if (b1 != NULL)
+ gen_and(b1, b0);
+ return b0;
case DLT_FDDI:
/*
* XXX TEST THIS: MIGHT NOT PORT PROPERLY XXX
@@ -7461,10 +7385,10 @@ gen_multicast(proto)
* XXX - was that referring to bit-order issues?
*/
/* fddi[1] & 1 != 0 */
- return gen_mac_multicast(1);
+ return gen_mac_multicast(cstate, 1);
case DLT_IEEE802:
/* tr[2] & 1 != 0 */
- return gen_mac_multicast(2);
+ return gen_mac_multicast(cstate, 2);
case DLT_IEEE802_11:
case DLT_PRISM_HEADER:
case DLT_IEEE802_11_RADIO_AVS:
@@ -7491,23 +7415,23 @@ gen_multicast(proto)
*
* First, check for To DS set, i.e. "link[1] & 0x01".
*/
- s = gen_load_a(OR_LINK, 1, BPF_B);
- b1 = new_block(JMP(BPF_JSET));
+ s = gen_load_a(cstate, OR_LINKHDR, 1, BPF_B);
+ b1 = new_block(cstate, JMP(BPF_JSET));
b1->s.k = 0x01; /* To DS */
b1->stmts = s;
/*
* If To DS is set, the DA is at 16.
*/
- b0 = gen_mac_multicast(16);
+ b0 = gen_mac_multicast(cstate, 16);
gen_and(b1, b0);
/*
* Now, check for To DS not set, i.e. check
* "!(link[1] & 0x01)".
*/
- s = gen_load_a(OR_LINK, 1, BPF_B);
- b2 = new_block(JMP(BPF_JSET));
+ s = gen_load_a(cstate, OR_LINKHDR, 1, BPF_B);
+ b2 = new_block(cstate, JMP(BPF_JSET));
b2->s.k = 0x01; /* To DS */
b2->stmts = s;
gen_not(b2);
@@ -7515,7 +7439,7 @@ gen_multicast(proto)
/*
* If To DS is not set, the DA is at 4.
*/
- b1 = gen_mac_multicast(4);
+ b1 = gen_mac_multicast(cstate, 4);
gen_and(b2, b1);
/*
@@ -7528,8 +7452,8 @@ gen_multicast(proto)
* Now check for a data frame.
* I.e, check "link[0] & 0x08".
*/
- s = gen_load_a(OR_LINK, 0, BPF_B);
- b1 = new_block(JMP(BPF_JSET));
+ s = gen_load_a(cstate, OR_LINKHDR, 0, BPF_B);
+ b1 = new_block(cstate, JMP(BPF_JSET));
b1->s.k = 0x08;
b1->stmts = s;
@@ -7543,8 +7467,8 @@ gen_multicast(proto)
* is a management frame.
* I.e, check "!(link[0] & 0x08)".
*/
- s = gen_load_a(OR_LINK, 0, BPF_B);
- b2 = new_block(JMP(BPF_JSET));
+ s = gen_load_a(cstate, OR_LINKHDR, 0, BPF_B);
+ b2 = new_block(cstate, JMP(BPF_JSET));
b2->s.k = 0x08;
b2->stmts = s;
gen_not(b2);
@@ -7552,7 +7476,7 @@ gen_multicast(proto)
/*
* For management frames, the DA is at 4.
*/
- b1 = gen_mac_multicast(4);
+ b1 = gen_mac_multicast(cstate, 4);
gen_and(b2, b1);
/*
@@ -7570,8 +7494,8 @@ gen_multicast(proto)
*
* I.e., check "!(link[0] & 0x04)".
*/
- s = gen_load_a(OR_LINK, 0, BPF_B);
- b1 = new_block(JMP(BPF_JSET));
+ s = gen_load_a(cstate, OR_LINKHDR, 0, BPF_B);
+ b1 = new_block(cstate, JMP(BPF_JSET));
b1->s.k = 0x04;
b1->stmts = s;
gen_not(b1);
@@ -7583,25 +7507,8 @@ gen_multicast(proto)
gen_and(b1, b0);
return b0;
case DLT_IP_OVER_FC:
- b0 = gen_mac_multicast(2);
+ b0 = gen_mac_multicast(cstate, 2);
return b0;
- case DLT_SUNATM:
- if (is_lane) {
- /*
- * Check that the packet doesn't begin with an
- * LE Control marker. (We've already generated
- * a test for LANE.)
- */
- b1 = gen_cmp(OR_LINK, SUNATM_PKT_BEGIN_POS,
- BPF_H, 0xFF00);
- gen_not(b1);
-
- /* ether[off_mac] & 1 != 0 */
- b0 = gen_mac_multicast(off_mac);
- gen_and(b1, b0);
- return b0;
- }
- break;
default:
break;
}
@@ -7609,18 +7516,18 @@ gen_multicast(proto)
break;
case Q_IP:
- b0 = gen_linktype(ETHERTYPE_IP);
- b1 = gen_cmp_ge(OR_NET, 16, BPF_B, (bpf_int32)224);
+ b0 = gen_linktype(cstate, ETHERTYPE_IP);
+ b1 = gen_cmp_ge(cstate, OR_LINKPL, 16, BPF_B, (bpf_int32)224);
gen_and(b0, b1);
return b1;
case Q_IPV6:
- b0 = gen_linktype(ETHERTYPE_IPV6);
- b1 = gen_cmp(OR_NET, 24, BPF_B, (bpf_int32)255);
+ b0 = gen_linktype(cstate, ETHERTYPE_IPV6);
+ b1 = gen_cmp(cstate, OR_LINKPL, 24, BPF_B, (bpf_int32)255);
gen_and(b0, b1);
return b1;
}
- bpf_error("link-layer multicast filters supported only on ethernet/FDDI/token ring/ARCNET/802.11/ATM LANE/Fibre Channel");
+ bpf_error(cstate, "link-layer multicast filters supported only on ethernet/FDDI/token ring/ARCNET/802.11/ATM LANE/Fibre Channel");
/* NOTREACHED */
return NULL;
}
@@ -7635,35 +7542,34 @@ gen_multicast(proto)
* better accomplished using a higher-layer filter.
*/
struct block *
-gen_inbound(dir)
- int dir;
+gen_inbound(compiler_state_t *cstate, int dir)
{
register struct block *b0;
/*
* Only some data link types support inbound/outbound qualifiers.
*/
- switch (linktype) {
+ switch (cstate->linktype) {
case DLT_SLIP:
- b0 = gen_relation(BPF_JEQ,
- gen_load(Q_LINK, gen_loadi(0), 1),
- gen_loadi(0),
+ b0 = gen_relation(cstate, BPF_JEQ,
+ gen_load(cstate, Q_LINK, gen_loadi(cstate, 0), 1),
+ gen_loadi(cstate, 0),
dir);
break;
case DLT_IPNET:
if (dir) {
/* match outgoing packets */
- b0 = gen_cmp(OR_LINK, 2, BPF_H, IPNET_OUTBOUND);
+ b0 = gen_cmp(cstate, OR_LINKHDR, 2, BPF_H, IPNET_OUTBOUND);
} else {
/* match incoming packets */
- b0 = gen_cmp(OR_LINK, 2, BPF_H, IPNET_INBOUND);
+ b0 = gen_cmp(cstate, OR_LINKHDR, 2, BPF_H, IPNET_INBOUND);
}
break;
case DLT_LINUX_SLL:
/* match outgoing packets */
- b0 = gen_cmp(OR_LINK, 0, BPF_H, LINUX_SLL_OUTGOING);
+ b0 = gen_cmp(cstate, OR_LINKHDR, 0, BPF_H, LINUX_SLL_OUTGOING);
if (!dir) {
/* to filter on inbound traffic, invert the match */
gen_not(b0);
@@ -7672,7 +7578,7 @@ gen_inbound(dir)
#ifdef HAVE_NET_PFVAR_H
case DLT_PFLOG:
- b0 = gen_cmp(OR_LINK, offsetof(struct pfloghdr, dir), BPF_B,
+ b0 = gen_cmp(cstate, OR_LINKHDR, offsetof(struct pfloghdr, dir), BPF_B,
(bpf_int32)((dir == 0) ? PF_IN : PF_OUT));
break;
#endif
@@ -7680,10 +7586,10 @@ gen_inbound(dir)
case DLT_PPP_PPPD:
if (dir) {
/* match outgoing packets */
- b0 = gen_cmp(OR_LINK, 0, BPF_B, PPP_PPPD_OUT);
+ b0 = gen_cmp(cstate, OR_LINKHDR, 0, BPF_B, PPP_PPPD_OUT);
} else {
/* match incoming packets */
- b0 = gen_cmp(OR_LINK, 0, BPF_B, PPP_PPPD_IN);
+ b0 = gen_cmp(cstate, OR_LINKHDR, 0, BPF_B, PPP_PPPD_IN);
}
break;
@@ -7714,10 +7620,10 @@ gen_inbound(dir)
* the byte after the 3-byte magic number */
if (dir) {
/* match outgoing packets */
- b0 = gen_mcmp(OR_LINK, 3, BPF_B, 0, 0x01);
+ b0 = gen_mcmp(cstate, OR_LINKHDR, 3, BPF_B, 0, 0x01);
} else {
/* match incoming packets */
- b0 = gen_mcmp(OR_LINK, 3, BPF_B, 1, 0x01);
+ b0 = gen_mcmp(cstate, OR_LINKHDR, 3, BPF_B, 1, 0x01);
}
break;
@@ -7734,23 +7640,23 @@ gen_inbound(dir)
* special meta-data in the filter expression;
* if it's a savefile, we can't.
*/
- if (bpf_pcap->rfile != NULL) {
+ if (cstate->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);
+ bpf_error(cstate, "inbound/outbound not supported on linktype %d when reading savefiles",
+ cstate->linktype);
b0 = NULL;
/* NOTREACHED */
}
/* match outgoing packets */
- b0 = gen_cmp(OR_LINK, SKF_AD_OFF + SKF_AD_PKTTYPE, BPF_H,
+ b0 = gen_cmp(cstate, OR_LINKHDR, SKF_AD_OFF + SKF_AD_PKTTYPE, BPF_H,
PACKET_OUTGOING);
if (!dir) {
/* to filter on inbound traffic, invert the match */
gen_not(b0);
}
#else /* defined(linux) && defined(PF_PACKET) && defined(SO_ATTACH_FILTER) */
- bpf_error("inbound/outbound not supported on linktype %d",
- linktype);
+ bpf_error(cstate, "inbound/outbound not supported on linktype %d",
+ cstate->linktype);
b0 = NULL;
/* NOTREACHED */
#endif /* defined(linux) && defined(PF_PACKET) && defined(SO_ATTACH_FILTER) */
@@ -7761,156 +7667,156 @@ gen_inbound(dir)
#ifdef HAVE_NET_PFVAR_H
/* PF firewall log matched interface */
struct block *
-gen_pf_ifname(const char *ifname)
+gen_pf_ifname(compiler_state_t *cstate, const char *ifname)
{
struct block *b0;
u_int len, off;
- if (linktype != DLT_PFLOG) {
- bpf_error("ifname supported only on PF linktype");
+ if (cstate->linktype != DLT_PFLOG) {
+ bpf_error(cstate, "ifname supported only on PF linktype");
/* NOTREACHED */
}
len = sizeof(((struct pfloghdr *)0)->ifname);
off = offsetof(struct pfloghdr, ifname);
if (strlen(ifname) >= len) {
- bpf_error("ifname interface names can only be %d characters",
+ bpf_error(cstate, "ifname interface names can only be %d characters",
len-1);
/* NOTREACHED */
}
- b0 = gen_bcmp(OR_LINK, off, strlen(ifname), (const u_char *)ifname);
+ b0 = gen_bcmp(cstate, OR_LINKHDR, off, strlen(ifname), (const u_char *)ifname);
return (b0);
}
/* PF firewall log ruleset name */
struct block *
-gen_pf_ruleset(char *ruleset)
+gen_pf_ruleset(compiler_state_t *cstate, char *ruleset)
{
struct block *b0;
- if (linktype != DLT_PFLOG) {
- bpf_error("ruleset supported only on PF linktype");
+ if (cstate->linktype != DLT_PFLOG) {
+ bpf_error(cstate, "ruleset supported only on PF linktype");
/* NOTREACHED */
}
if (strlen(ruleset) >= sizeof(((struct pfloghdr *)0)->ruleset)) {
- bpf_error("ruleset names can only be %ld characters",
+ bpf_error(cstate, "ruleset names can only be %ld characters",
(long)(sizeof(((struct pfloghdr *)0)->ruleset) - 1));
/* NOTREACHED */
}
- b0 = gen_bcmp(OR_LINK, offsetof(struct pfloghdr, ruleset),
+ b0 = gen_bcmp(cstate, OR_LINKHDR, offsetof(struct pfloghdr, ruleset),
strlen(ruleset), (const u_char *)ruleset);
return (b0);
}
/* PF firewall log rule number */
struct block *
-gen_pf_rnr(int rnr)
+gen_pf_rnr(compiler_state_t *cstate, int rnr)
{
struct block *b0;
- if (linktype != DLT_PFLOG) {
- bpf_error("rnr supported only on PF linktype");
+ if (cstate->linktype != DLT_PFLOG) {
+ bpf_error(cstate, "rnr supported only on PF linktype");
/* NOTREACHED */
}
- b0 = gen_cmp(OR_LINK, offsetof(struct pfloghdr, rulenr), BPF_W,
+ b0 = gen_cmp(cstate, OR_LINKHDR, offsetof(struct pfloghdr, rulenr), BPF_W,
(bpf_int32)rnr);
return (b0);
}
/* PF firewall log sub-rule number */
struct block *
-gen_pf_srnr(int srnr)
+gen_pf_srnr(compiler_state_t *cstate, int srnr)
{
struct block *b0;
- if (linktype != DLT_PFLOG) {
- bpf_error("srnr supported only on PF linktype");
+ if (cstate->linktype != DLT_PFLOG) {
+ bpf_error(cstate, "srnr supported only on PF linktype");
/* NOTREACHED */
}
- b0 = gen_cmp(OR_LINK, offsetof(struct pfloghdr, subrulenr), BPF_W,
+ b0 = gen_cmp(cstate, OR_LINKHDR, offsetof(struct pfloghdr, subrulenr), BPF_W,
(bpf_int32)srnr);
return (b0);
}
/* PF firewall log reason code */
struct block *
-gen_pf_reason(int reason)
+gen_pf_reason(compiler_state_t *cstate, int reason)
{
struct block *b0;
- if (linktype != DLT_PFLOG) {
- bpf_error("reason supported only on PF linktype");
+ if (cstate->linktype != DLT_PFLOG) {
+ bpf_error(cstate, "reason supported only on PF linktype");
/* NOTREACHED */
}
- b0 = gen_cmp(OR_LINK, offsetof(struct pfloghdr, reason), BPF_B,
+ b0 = gen_cmp(cstate, OR_LINKHDR, offsetof(struct pfloghdr, reason), BPF_B,
(bpf_int32)reason);
return (b0);
}
/* PF firewall log action */
struct block *
-gen_pf_action(int action)
+gen_pf_action(compiler_state_t *cstate, int action)
{
struct block *b0;
- if (linktype != DLT_PFLOG) {
- bpf_error("action supported only on PF linktype");
+ if (cstate->linktype != DLT_PFLOG) {
+ bpf_error(cstate, "action supported only on PF linktype");
/* NOTREACHED */
}
- b0 = gen_cmp(OR_LINK, offsetof(struct pfloghdr, action), BPF_B,
+ b0 = gen_cmp(cstate, OR_LINKHDR, offsetof(struct pfloghdr, action), BPF_B,
(bpf_int32)action);
return (b0);
}
#else /* !HAVE_NET_PFVAR_H */
struct block *
-gen_pf_ifname(const char *ifname)
+gen_pf_ifname(compiler_state_t *cstate, const char *ifname)
{
- bpf_error("libpcap was compiled without pf support");
+ bpf_error(cstate, "libpcap was compiled without pf support");
/* NOTREACHED */
return (NULL);
}
struct block *
-gen_pf_ruleset(char *ruleset)
+gen_pf_ruleset(compiler_state_t *cstate, char *ruleset)
{
- bpf_error("libpcap was compiled on a machine without pf support");
+ bpf_error(cstate, "libpcap was compiled on a machine without pf support");
/* NOTREACHED */
return (NULL);
}
struct block *
-gen_pf_rnr(int rnr)
+gen_pf_rnr(compiler_state_t *cstate, int rnr)
{
- bpf_error("libpcap was compiled on a machine without pf support");
+ bpf_error(cstate, "libpcap was compiled on a machine without pf support");
/* NOTREACHED */
return (NULL);
}
struct block *
-gen_pf_srnr(int srnr)
+gen_pf_srnr(compiler_state_t *cstate, int srnr)
{
- bpf_error("libpcap was compiled on a machine without pf support");
+ bpf_error(cstate, "libpcap was compiled on a machine without pf support");
/* NOTREACHED */
return (NULL);
}
struct block *
-gen_pf_reason(int reason)
+gen_pf_reason(compiler_state_t *cstate, int reason)
{
- bpf_error("libpcap was compiled on a machine without pf support");
+ bpf_error(cstate, "libpcap was compiled on a machine without pf support");
/* NOTREACHED */
return (NULL);
}
struct block *
-gen_pf_action(int action)
+gen_pf_action(compiler_state_t *cstate, int action)
{
- bpf_error("libpcap was compiled on a machine without pf support");
+ bpf_error(cstate, "libpcap was compiled on a machine without pf support");
/* NOTREACHED */
return (NULL);
}
@@ -7918,22 +7824,22 @@ gen_pf_action(int action)
/* IEEE 802.11 wireless header */
struct block *
-gen_p80211_type(int type, int mask)
+gen_p80211_type(compiler_state_t *cstate, int type, int mask)
{
struct block *b0;
- switch (linktype) {
+ switch (cstate->linktype) {
case DLT_IEEE802_11:
case DLT_PRISM_HEADER:
case DLT_IEEE802_11_RADIO_AVS:
case DLT_IEEE802_11_RADIO:
- b0 = gen_mcmp(OR_LINK, 0, BPF_B, (bpf_int32)type,
+ b0 = gen_mcmp(cstate, OR_LINKHDR, 0, BPF_B, (bpf_int32)type,
(bpf_int32)mask);
break;
default:
- bpf_error("802.11 link-layer types supported only on 802.11");
+ bpf_error(cstate, "802.11 link-layer types supported only on 802.11");
/* NOTREACHED */
}
@@ -7941,11 +7847,11 @@ gen_p80211_type(int type, int mask)
}
struct block *
-gen_p80211_fcdir(int fcdir)
+gen_p80211_fcdir(compiler_state_t *cstate, int fcdir)
{
struct block *b0;
- switch (linktype) {
+ switch (cstate->linktype) {
case DLT_IEEE802_11:
case DLT_PRISM_HEADER:
@@ -7954,111 +7860,175 @@ gen_p80211_fcdir(int fcdir)
break;
default:
- bpf_error("frame direction supported only with 802.11 headers");
+ bpf_error(cstate, "frame direction supported only with 802.11 headers");
/* NOTREACHED */
}
- b0 = gen_mcmp(OR_LINK, 1, BPF_B, (bpf_int32)fcdir,
+ b0 = gen_mcmp(cstate, OR_LINKHDR, 1, BPF_B, (bpf_int32)fcdir,
(bpf_u_int32)IEEE80211_FC1_DIR_MASK);
return (b0);
}
struct block *
-gen_acode(eaddr, q)
- register const u_char *eaddr;
- struct qual q;
+gen_acode(compiler_state_t *cstate, const u_char *eaddr, struct qual q)
{
- switch (linktype) {
+ switch (cstate->linktype) {
case DLT_ARCNET:
case DLT_ARCNET_LINUX:
if ((q.addr == Q_HOST || q.addr == Q_DEFAULT) &&
q.proto == Q_LINK)
- return (gen_ahostop(eaddr, (int)q.dir));
+ return (gen_ahostop(cstate, eaddr, (int)q.dir));
else {
- bpf_error("ARCnet address used in non-arc expression");
+ bpf_error(cstate, "ARCnet address used in non-arc expression");
/* NOTREACHED */
}
break;
default:
- bpf_error("aid supported only on ARCnet");
+ bpf_error(cstate, "aid supported only on ARCnet");
/* NOTREACHED */
}
- bpf_error("ARCnet address used in non-arc expression");
+ bpf_error(cstate, "ARCnet address used in non-arc expression");
/* NOTREACHED */
return NULL;
}
static struct block *
-gen_ahostop(eaddr, dir)
- register const u_char *eaddr;
- register int dir;
+gen_ahostop(compiler_state_t *cstate, const u_char *eaddr, int dir)
{
register struct block *b0, *b1;
switch (dir) {
/* src comes first, different from Ethernet */
case Q_SRC:
- return gen_bcmp(OR_LINK, 0, 1, eaddr);
+ return gen_bcmp(cstate, OR_LINKHDR, 0, 1, eaddr);
case Q_DST:
- return gen_bcmp(OR_LINK, 1, 1, eaddr);
+ return gen_bcmp(cstate, OR_LINKHDR, 1, 1, eaddr);
case Q_AND:
- b0 = gen_ahostop(eaddr, Q_SRC);
- b1 = gen_ahostop(eaddr, Q_DST);
+ b0 = gen_ahostop(cstate, eaddr, Q_SRC);
+ b1 = gen_ahostop(cstate, eaddr, Q_DST);
gen_and(b0, b1);
return b1;
case Q_DEFAULT:
case Q_OR:
- b0 = gen_ahostop(eaddr, Q_SRC);
- b1 = gen_ahostop(eaddr, Q_DST);
+ b0 = gen_ahostop(cstate, eaddr, Q_SRC);
+ b1 = gen_ahostop(cstate, eaddr, Q_DST);
gen_or(b0, b1);
return b1;
case Q_ADDR1:
- bpf_error("'addr1' is only supported on 802.11");
+ bpf_error(cstate, "'addr1' is only supported on 802.11");
break;
case Q_ADDR2:
- bpf_error("'addr2' is only supported on 802.11");
+ bpf_error(cstate, "'addr2' is only supported on 802.11");
break;
case Q_ADDR3:
- bpf_error("'addr3' is only supported on 802.11");
+ bpf_error(cstate, "'addr3' is only supported on 802.11");
break;
case Q_ADDR4:
- bpf_error("'addr4' is only supported on 802.11");
+ bpf_error(cstate, "'addr4' is only supported on 802.11");
break;
case Q_RA:
- bpf_error("'ra' is only supported on 802.11");
+ bpf_error(cstate, "'ra' is only supported on 802.11");
break;
case Q_TA:
- bpf_error("'ta' is only supported on 802.11");
+ bpf_error(cstate, "'ta' is only supported on 802.11");
break;
}
abort();
/* NOTREACHED */
}
+#if defined(SKF_AD_VLAN_TAG) && defined(SKF_AD_VLAN_TAG_PRESENT)
+static struct block *
+gen_vlan_bpf_extensions(compiler_state_t *cstate, int vlan_num)
+{
+ struct block *b0, *b1;
+ struct slist *s;
+
+ /* generate new filter code based on extracting packet
+ * metadata */
+ s = new_stmt(cstate, BPF_LD|BPF_B|BPF_ABS);
+ s->s.k = SKF_AD_OFF + SKF_AD_VLAN_TAG_PRESENT;
+
+ b0 = new_block(cstate, JMP(BPF_JEQ));
+ b0->stmts = s;
+ b0->s.k = 1;
+
+ if (vlan_num >= 0) {
+ s = new_stmt(cstate, BPF_LD|BPF_B|BPF_ABS);
+ s->s.k = SKF_AD_OFF + SKF_AD_VLAN_TAG;
+
+ b1 = new_block(cstate, JMP(BPF_JEQ));
+ b1->stmts = s;
+ b1->s.k = (bpf_int32) vlan_num;
+
+ gen_and(b0,b1);
+ b0 = b1;
+ }
+
+ return b0;
+}
+#endif
+
+static struct block *
+gen_vlan_no_bpf_extensions(compiler_state_t *cstate, int vlan_num)
+{
+ struct block *b0, *b1;
+
+ /* check for VLAN, including QinQ */
+ b0 = gen_linktype(cstate, ETHERTYPE_8021Q);
+ b1 = gen_linktype(cstate, ETHERTYPE_8021AD);
+ gen_or(b0,b1);
+ b0 = b1;
+ b1 = gen_linktype(cstate, ETHERTYPE_8021QINQ);
+ gen_or(b0,b1);
+ b0 = b1;
+
+ /* If a specific VLAN is requested, check VLAN id */
+ if (vlan_num >= 0) {
+ b1 = gen_mcmp(cstate, OR_LINKPL, 0, BPF_H,
+ (bpf_int32)vlan_num, 0x0fff);
+ gen_and(b0, b1);
+ b0 = b1;
+ }
+
+ /*
+ * The payload follows the full header, including the
+ * VLAN tags, so skip past this VLAN tag.
+ */
+ cstate->off_linkpl.constant_part += 4;
+
+ /*
+ * The link-layer type information follows the VLAN tags, so
+ * skip past this VLAN tag.
+ */
+ cstate->off_linktype.constant_part += 4;
+
+ return b0;
+}
+
/*
* support IEEE 802.1Q VLAN trunk over ethernet
*/
struct block *
-gen_vlan(vlan_num)
- int vlan_num;
+gen_vlan(compiler_state_t *cstate, int vlan_num)
{
- struct block *b0, *b1;
+ struct block *b0;
/* can't check for VLAN-encapsulated packets inside MPLS */
- if (label_stack_depth > 0)
- bpf_error("no VLAN match after MPLS");
+ if (cstate->label_stack_depth > 0)
+ bpf_error(cstate, "no VLAN match after MPLS");
/*
* Check for a VLAN packet, and then change the offsets to point
@@ -8091,43 +8061,44 @@ gen_vlan(vlan_num)
* be done assuming a VLAN, even though the "or" could be viewed
* as meaning "or, if this isn't a VLAN packet...".
*/
- orig_nl = off_nl;
-
- switch (linktype) {
+ switch (cstate->linktype) {
case DLT_EN10MB:
case DLT_NETANALYZER:
case DLT_NETANALYZER_TRANSPARENT:
- /* check for VLAN, including QinQ */
- b0 = gen_cmp(OR_LINK, off_linktype, BPF_H,
- (bpf_int32)ETHERTYPE_8021Q);
- b1 = gen_cmp(OR_LINK, off_linktype, BPF_H,
- (bpf_int32)ETHERTYPE_8021QINQ);
- gen_or(b0,b1);
- b0 = b1;
-
- /* If a specific VLAN is requested, check VLAN id */
- if (vlan_num >= 0) {
- b1 = gen_mcmp(OR_MACPL, 0, BPF_H,
- (bpf_int32)vlan_num, 0x0fff);
- gen_and(b0, b1);
- b0 = b1;
- }
-
- off_macpl += 4;
- off_linktype += 4;
-#if 0
- off_nl_nosnap += 4;
- off_nl += 4;
+#if defined(SKF_AD_VLAN_TAG) && defined(SKF_AD_VLAN_TAG_PRESENT)
+ /* Verify that this is the outer part of the packet and
+ * not encapsulated somehow. */
+ if (cstate->vlan_stack_depth == 0 && !cstate->off_linkhdr.is_variable &&
+ cstate->off_linkhdr.constant_part ==
+ cstate->off_outermostlinkhdr.constant_part) {
+ /*
+ * Do we need special VLAN handling?
+ */
+ if (cstate->bpf_pcap->bpf_codegen_flags & BPF_SPECIAL_VLAN_HANDLING)
+ b0 = gen_vlan_bpf_extensions(cstate, vlan_num);
+ else
+ b0 = gen_vlan_no_bpf_extensions(cstate, vlan_num);
+ } else
#endif
+ b0 = gen_vlan_no_bpf_extensions(cstate, vlan_num);
+ break;
+
+ case DLT_IEEE802_11:
+ case DLT_PRISM_HEADER:
+ case DLT_IEEE802_11_RADIO_AVS:
+ case DLT_IEEE802_11_RADIO:
+ b0 = gen_vlan_no_bpf_extensions(cstate, vlan_num);
break;
default:
- bpf_error("no VLAN support for data link type %d",
- linktype);
+ bpf_error(cstate, "no VLAN support for data link type %d",
+ cstate->linktype);
/*NOTREACHED*/
}
+ cstate->vlan_stack_depth++;
+
return (b0);
}
@@ -8135,43 +8106,29 @@ gen_vlan(vlan_num)
* support for MPLS
*/
struct block *
-gen_mpls(label_num)
- int label_num;
+gen_mpls(compiler_state_t *cstate, int label_num)
{
- struct block *b0,*b1;
-
- /*
- * Change the offsets to point to the type and data fields within
- * the MPLS packet. Just increment the offsets, so that we
- * can support a hierarchy, e.g. "mpls 100000 && mpls 1024" to
- * capture packets with an outer label of 100000 and an inner
- * label of 1024.
- *
- * XXX - this is a bit of a kludge. See comments in gen_vlan().
- */
- orig_nl = off_nl;
+ struct block *b0, *b1;
- if (label_stack_depth > 0) {
+ if (cstate->label_stack_depth > 0) {
/* just match the bottom-of-stack bit clear */
- b0 = gen_mcmp(OR_MACPL, orig_nl-2, BPF_B, 0, 0x01);
+ b0 = gen_mcmp(cstate, OR_PREVMPLSHDR, 2, BPF_B, 0, 0x01);
} else {
/*
- * Indicate that we're checking MPLS-encapsulated headers,
- * to make sure higher level code generators don't try to
- * match against IP-related protocols such as Q_ARP, Q_RARP
- * etc.
+ * We're not in an MPLS stack yet, so check the link-layer
+ * type against MPLS.
*/
- switch (linktype) {
+ switch (cstate->linktype) {
case DLT_C_HDLC: /* fall through */
case DLT_EN10MB:
case DLT_NETANALYZER:
case DLT_NETANALYZER_TRANSPARENT:
- b0 = gen_linktype(ETHERTYPE_MPLS);
+ b0 = gen_linktype(cstate, ETHERTYPE_MPLS);
break;
case DLT_PPP:
- b0 = gen_linktype(PPP_MPLS_UCAST);
+ b0 = gen_linktype(cstate, PPP_MPLS_UCAST);
break;
/* FIXME add other DLT_s ...
@@ -8179,8 +8136,8 @@ gen_mpls(label_num)
* leave it for now */
default:
- bpf_error("no MPLS support for data link type %d",
- linktype);
+ bpf_error(cstate, "no MPLS support for data link type %d",
+ cstate->linktype);
b0 = NULL;
/*NOTREACHED*/
break;
@@ -8190,15 +8147,29 @@ gen_mpls(label_num)
/* If a specific MPLS label is requested, check it */
if (label_num >= 0) {
label_num = label_num << 12; /* label is shifted 12 bits on the wire */
- b1 = gen_mcmp(OR_MACPL, orig_nl, BPF_W, (bpf_int32)label_num,
+ b1 = gen_mcmp(cstate, OR_LINKPL, 0, BPF_W, (bpf_int32)label_num,
0xfffff000); /* only compare the first 20 bits */
gen_and(b0, b1);
b0 = b1;
}
- off_nl_nosnap += 4;
- off_nl += 4;
- label_stack_depth++;
+ /*
+ * Change the offsets to point to the type and data fields within
+ * the MPLS packet. Just increment the offsets, so that we
+ * can support a hierarchy, e.g. "mpls 100000 && mpls 1024" to
+ * capture packets with an outer label of 100000 and an inner
+ * label of 1024.
+ *
+ * Increment the MPLS stack depth as well; this indicates that
+ * we're checking MPLS-encapsulated headers, to make sure higher
+ * level code generators don't try to match against IP-related
+ * protocols such as Q_ARP, Q_RARP etc.
+ *
+ * XXX - this is a bit of a kludge. See comments in gen_vlan().
+ */
+ cstate->off_nl_nosnap += 4;
+ cstate->off_nl += 4;
+ cstate->label_stack_depth++;
return (b0);
}
@@ -8206,22 +8177,29 @@ gen_mpls(label_num)
* Support PPPOE discovery and session.
*/
struct block *
-gen_pppoed()
+gen_pppoed(compiler_state_t *cstate)
{
/* check for PPPoE discovery */
- return gen_linktype((bpf_int32)ETHERTYPE_PPPOED);
+ return gen_linktype(cstate, (bpf_int32)ETHERTYPE_PPPOED);
}
struct block *
-gen_pppoes(sess_num)
- int sess_num;
+gen_pppoes(compiler_state_t *cstate, int sess_num)
{
struct block *b0, *b1;
/*
* Test against the PPPoE session link-layer type.
*/
- b0 = gen_linktype((bpf_int32)ETHERTYPE_PPPOES);
+ b0 = gen_linktype(cstate, (bpf_int32)ETHERTYPE_PPPOES);
+
+ /* If a specific session is requested, check PPPoE session id */
+ if (sess_num >= 0) {
+ b1 = gen_mcmp(cstate, OR_LINKPL, 0, BPF_W,
+ (bpf_int32)sess_num, 0x0000ffff);
+ gen_and(b0, b1);
+ b0 = b1;
+ }
/*
* Change the offsets to point to the type and data fields within
@@ -8251,20 +8229,7 @@ gen_pppoes(sess_num)
* as all the "or ..." tests would be done assuming PPPoE, even
* though the "or" could be viewed as meaning "or, if this isn't
* a PPPoE packet...".
- */
- orig_linktype = off_linktype; /* save original values */
- orig_nl = off_nl;
- is_pppoes = 1;
-
- /* If a specific session is requested, check PPPoE session id */
- if (sess_num >= 0) {
- b1 = gen_mcmp(OR_MACPL, orig_nl, BPF_W,
- (bpf_int32)sess_num, 0x0000ffff);
- gen_and(b0, b1);
- b0 = b1;
- }
-
- /*
+ *
* The "network-layer" protocol is PPPoE, which has a 6-byte
* PPPoE header, followed by a PPP packet.
*
@@ -8273,70 +8238,362 @@ gen_pppoes(sess_num)
* starts at the first byte of the PPP packet. For PPPoE,
* that offset is relative to the beginning of the total
* link-layer payload, including any 802.2 LLC header, so
- * it's 6 bytes past off_nl.
+ * it's 6 bytes past cstate->off_nl.
*/
- off_linktype = off_nl + 6;
+ PUSH_LINKHDR(cstate, DLT_PPP, cstate->off_linkpl.is_variable,
+ cstate->off_linkpl.constant_part + cstate->off_nl + 6, /* 6 bytes past the PPPoE header */
+ cstate->off_linkpl.reg);
- /*
- * The network-layer offsets are relative to the beginning
- * of the MAC-layer payload; that's past the 6-byte
- * PPPoE header and the 2-byte PPP header.
- */
- off_nl = 6+2;
- off_nl_nosnap = 6+2;
+ cstate->off_linktype = cstate->off_linkhdr;
+ cstate->off_linkpl.constant_part = cstate->off_linkhdr.constant_part + 2;
+
+ cstate->off_nl = 0;
+ cstate->off_nl_nosnap = 0; /* no 802.2 LLC */
+
+ return b0;
+}
+
+/* Check that this is Geneve and the VNI is correct if
+ * specified. Parameterized to handle both IPv4 and IPv6. */
+static struct block *
+gen_geneve_check(compiler_state_t *cstate,
+ struct block *(*gen_portfn)(compiler_state_t *, int, int, int),
+ enum e_offrel offrel, int vni)
+{
+ struct block *b0, *b1;
+
+ b0 = gen_portfn(cstate, GENEVE_PORT, IPPROTO_UDP, Q_DST);
+
+ /* Check that we are operating on version 0. Otherwise, we
+ * can't decode the rest of the fields. The version is 2 bits
+ * in the first byte of the Geneve header. */
+ b1 = gen_mcmp(cstate, offrel, 8, BPF_B, (bpf_int32)0, 0xc0);
+ gen_and(b0, b1);
+ b0 = b1;
+
+ if (vni >= 0) {
+ vni <<= 8; /* VNI is in the upper 3 bytes */
+ b1 = gen_mcmp(cstate, offrel, 12, BPF_W, (bpf_int32)vni,
+ 0xffffff00);
+ gen_and(b0, b1);
+ b0 = b1;
+ }
+
+ return b0;
+}
+
+/* The IPv4 and IPv6 Geneve checks need to do two things:
+ * - Verify that this actually is Geneve with the right VNI.
+ * - Place the IP header length (plus variable link prefix if
+ * needed) into register A to be used later to compute
+ * the inner packet offsets. */
+static struct block *
+gen_geneve4(compiler_state_t *cstate, int vni)
+{
+ struct block *b0, *b1;
+ struct slist *s, *s1;
+
+ b0 = gen_geneve_check(cstate, gen_port, OR_TRAN_IPV4, vni);
+
+ /* Load the IP header length into A. */
+ s = gen_loadx_iphdrlen(cstate);
+
+ s1 = new_stmt(cstate, BPF_MISC|BPF_TXA);
+ sappend(s, s1);
+
+ /* Forcibly append these statements to the true condition
+ * of the protocol check by creating a new block that is
+ * always true and ANDing them. */
+ b1 = new_block(cstate, BPF_JMP|BPF_JEQ|BPF_X);
+ b1->stmts = s;
+ b1->s.k = 0;
+
+ gen_and(b0, b1);
+
+ return b1;
+}
+
+static struct block *
+gen_geneve6(compiler_state_t *cstate, int vni)
+{
+ struct block *b0, *b1;
+ struct slist *s, *s1;
+
+ b0 = gen_geneve_check(cstate, gen_port6, OR_TRAN_IPV6, vni);
+
+ /* Load the IP header length. We need to account for a
+ * variable length link prefix if there is one. */
+ s = gen_abs_offset_varpart(cstate, &cstate->off_linkpl);
+ if (s) {
+ s1 = new_stmt(cstate, BPF_LD|BPF_IMM);
+ s1->s.k = 40;
+ sappend(s, s1);
+
+ s1 = new_stmt(cstate, BPF_ALU|BPF_ADD|BPF_X);
+ s1->s.k = 0;
+ sappend(s, s1);
+ } else {
+ s = new_stmt(cstate, BPF_LD|BPF_IMM);
+ s->s.k = 40;
+ }
+
+ /* Forcibly append these statements to the true condition
+ * of the protocol check by creating a new block that is
+ * always true and ANDing them. */
+ s1 = new_stmt(cstate, BPF_MISC|BPF_TAX);
+ sappend(s, s1);
+
+ b1 = new_block(cstate, BPF_JMP|BPF_JEQ|BPF_X);
+ b1->stmts = s;
+ b1->s.k = 0;
+
+ gen_and(b0, b1);
+
+ return b1;
+}
+
+/* We need to store three values based on the Geneve header::
+ * - The offset of the linktype.
+ * - The offset of the end of the Geneve header.
+ * - The offset of the end of the encapsulated MAC header. */
+static struct slist *
+gen_geneve_offsets(compiler_state_t *cstate)
+{
+ struct slist *s, *s1, *s_proto;
+
+ /* First we need to calculate the offset of the Geneve header
+ * itself. This is composed of the IP header previously calculated
+ * (include any variable link prefix) and stored in A plus the
+ * fixed sized headers (fixed link prefix, MAC length, and UDP
+ * header). */
+ s = new_stmt(cstate, BPF_ALU|BPF_ADD|BPF_K);
+ s->s.k = cstate->off_linkpl.constant_part + cstate->off_nl + 8;
+
+ /* Stash this in X since we'll need it later. */
+ s1 = new_stmt(cstate, BPF_MISC|BPF_TAX);
+ sappend(s, s1);
+
+ /* The EtherType in Geneve is 2 bytes in. Calculate this and
+ * store it. */
+ s1 = new_stmt(cstate, BPF_ALU|BPF_ADD|BPF_K);
+ s1->s.k = 2;
+ sappend(s, s1);
+
+ cstate->off_linktype.reg = alloc_reg(cstate);
+ cstate->off_linktype.is_variable = 1;
+ cstate->off_linktype.constant_part = 0;
+
+ s1 = new_stmt(cstate, BPF_ST);
+ s1->s.k = cstate->off_linktype.reg;
+ sappend(s, s1);
+
+ /* Load the Geneve option length and mask and shift to get the
+ * number of bytes. It is stored in the first byte of the Geneve
+ * header. */
+ s1 = new_stmt(cstate, BPF_LD|BPF_IND|BPF_B);
+ s1->s.k = 0;
+ sappend(s, s1);
+
+ s1 = new_stmt(cstate, BPF_ALU|BPF_AND|BPF_K);
+ s1->s.k = 0x3f;
+ sappend(s, s1);
+
+ s1 = new_stmt(cstate, BPF_ALU|BPF_MUL|BPF_K);
+ s1->s.k = 4;
+ sappend(s, s1);
+
+ /* Add in the rest of the Geneve base header. */
+ s1 = new_stmt(cstate, BPF_ALU|BPF_ADD|BPF_K);
+ s1->s.k = 8;
+ sappend(s, s1);
+
+ /* Add the Geneve header length to its offset and store. */
+ s1 = new_stmt(cstate, BPF_ALU|BPF_ADD|BPF_X);
+ s1->s.k = 0;
+ sappend(s, s1);
+
+ /* Set the encapsulated type as Ethernet. Even though we may
+ * not actually have Ethernet inside there are two reasons this
+ * is useful:
+ * - The linktype field is always in EtherType format regardless
+ * of whether it is in Geneve or an inner Ethernet frame.
+ * - The only link layer that we have specific support for is
+ * Ethernet. We will confirm that the packet actually is
+ * Ethernet at runtime before executing these checks. */
+ PUSH_LINKHDR(cstate, DLT_EN10MB, 1, 0, alloc_reg(cstate));
+
+ s1 = new_stmt(cstate, BPF_ST);
+ s1->s.k = cstate->off_linkhdr.reg;
+ sappend(s, s1);
+
+ /* Calculate whether we have an Ethernet header or just raw IP/
+ * MPLS/etc. If we have Ethernet, advance the end of the MAC offset
+ * and linktype by 14 bytes so that the network header can be found
+ * seamlessly. Otherwise, keep what we've calculated already. */
+
+ /* We have a bare jmp so we can't use the optimizer. */
+ cstate->no_optimize = 1;
+
+ /* Load the EtherType in the Geneve header, 2 bytes in. */
+ s1 = new_stmt(cstate, BPF_LD|BPF_IND|BPF_H);
+ s1->s.k = 2;
+ sappend(s, s1);
+
+ /* Load X with the end of the Geneve header. */
+ s1 = new_stmt(cstate, BPF_LDX|BPF_MEM);
+ s1->s.k = cstate->off_linkhdr.reg;
+ sappend(s, s1);
+
+ /* Check if the EtherType is Transparent Ethernet Bridging. At the
+ * end of this check, we should have the total length in X. In
+ * the non-Ethernet case, it's already there. */
+ s_proto = new_stmt(cstate, JMP(BPF_JEQ));
+ s_proto->s.k = ETHERTYPE_TEB;
+ sappend(s, s_proto);
+
+ s1 = new_stmt(cstate, BPF_MISC|BPF_TXA);
+ sappend(s, s1);
+ s_proto->s.jt = s1;
+
+ /* Since this is Ethernet, use the EtherType of the payload
+ * directly as the linktype. Overwrite what we already have. */
+ s1 = new_stmt(cstate, BPF_ALU|BPF_ADD|BPF_K);
+ s1->s.k = 12;
+ sappend(s, s1);
+
+ s1 = new_stmt(cstate, BPF_ST);
+ s1->s.k = cstate->off_linktype.reg;
+ sappend(s, s1);
+
+ /* Advance two bytes further to get the end of the Ethernet
+ * header. */
+ s1 = new_stmt(cstate, BPF_ALU|BPF_ADD|BPF_K);
+ s1->s.k = 2;
+ sappend(s, s1);
+
+ /* Move the result to X. */
+ s1 = new_stmt(cstate, BPF_MISC|BPF_TAX);
+ sappend(s, s1);
+
+ /* Store the final result of our linkpl calculation. */
+ cstate->off_linkpl.reg = alloc_reg(cstate);
+ cstate->off_linkpl.is_variable = 1;
+ cstate->off_linkpl.constant_part = 0;
+
+ s1 = new_stmt(cstate, BPF_STX);
+ s1->s.k = cstate->off_linkpl.reg;
+ sappend(s, s1);
+ s_proto->s.jf = s1;
+
+ cstate->off_nl = 0;
+
+ return s;
+}
+
+/* Check to see if this is a Geneve packet. */
+struct block *
+gen_geneve(compiler_state_t *cstate, int vni)
+{
+ struct block *b0, *b1;
+ struct slist *s;
+
+ b0 = gen_geneve4(cstate, vni);
+ b1 = gen_geneve6(cstate, vni);
+
+ gen_or(b0, b1);
+ b0 = b1;
+
+ /* Later filters should act on the payload of the Geneve frame,
+ * update all of the header pointers. Attach this code so that
+ * it gets executed in the event that the Geneve filter matches. */
+ s = gen_geneve_offsets(cstate);
+
+ b1 = gen_true(cstate);
+ sappend(s, b1->stmts);
+ b1->stmts = s;
+
+ gen_and(b0, b1);
+
+ cstate->is_geneve = 1;
+
+ return b1;
+}
+
+/* Check that the encapsulated frame has a link layer header
+ * for Ethernet filters. */
+static struct block *
+gen_geneve_ll_check(compiler_state_t *cstate)
+{
+ struct block *b0;
+ struct slist *s, *s1;
+
+ /* The easiest way to see if there is a link layer present
+ * is to check if the link layer header and payload are not
+ * the same. */
+
+ /* Geneve always generates pure variable offsets so we can
+ * compare only the registers. */
+ s = new_stmt(cstate, BPF_LD|BPF_MEM);
+ s->s.k = cstate->off_linkhdr.reg;
+
+ s1 = new_stmt(cstate, BPF_LDX|BPF_MEM);
+ s1->s.k = cstate->off_linkpl.reg;
+ sappend(s, s1);
+
+ b0 = new_block(cstate, BPF_JMP|BPF_JEQ|BPF_X);
+ b0->stmts = s;
+ b0->s.k = 0;
+ gen_not(b0);
return b0;
}
struct block *
-gen_atmfield_code(atmfield, jvalue, jtype, reverse)
- int atmfield;
- bpf_int32 jvalue;
- bpf_u_int32 jtype;
- int reverse;
+gen_atmfield_code(compiler_state_t *cstate, int atmfield, bpf_int32 jvalue,
+ bpf_u_int32 jtype, int reverse)
{
struct block *b0;
switch (atmfield) {
case A_VPI:
- if (!is_atm)
- bpf_error("'vpi' supported only on raw ATM");
- if (off_vpi == (u_int)-1)
+ if (!cstate->is_atm)
+ bpf_error(cstate, "'vpi' supported only on raw ATM");
+ if (cstate->off_vpi == (u_int)-1)
abort();
- b0 = gen_ncmp(OR_LINK, off_vpi, BPF_B, 0xffffffff, jtype,
+ b0 = gen_ncmp(cstate, OR_LINKHDR, cstate->off_vpi, BPF_B, 0xffffffff, jtype,
reverse, jvalue);
break;
case A_VCI:
- if (!is_atm)
- bpf_error("'vci' supported only on raw ATM");
- if (off_vci == (u_int)-1)
+ if (!cstate->is_atm)
+ bpf_error(cstate, "'vci' supported only on raw ATM");
+ if (cstate->off_vci == (u_int)-1)
abort();
- b0 = gen_ncmp(OR_LINK, off_vci, BPF_H, 0xffffffff, jtype,
+ b0 = gen_ncmp(cstate, OR_LINKHDR, cstate->off_vci, BPF_H, 0xffffffff, jtype,
reverse, jvalue);
break;
case A_PROTOTYPE:
- if (off_proto == (u_int)-1)
+ if (cstate->off_proto == (u_int)-1)
abort(); /* XXX - this isn't on FreeBSD */
- b0 = gen_ncmp(OR_LINK, off_proto, BPF_B, 0x0f, jtype,
+ b0 = gen_ncmp(cstate, OR_LINKHDR, cstate->off_proto, BPF_B, 0x0f, jtype,
reverse, jvalue);
break;
case A_MSGTYPE:
- if (off_payload == (u_int)-1)
+ if (cstate->off_payload == (u_int)-1)
abort();
- b0 = gen_ncmp(OR_LINK, off_payload + MSG_TYPE_POS, BPF_B,
+ b0 = gen_ncmp(cstate, OR_LINKHDR, cstate->off_payload + MSG_TYPE_POS, BPF_B,
0xffffffff, jtype, reverse, jvalue);
break;
case A_CALLREFTYPE:
- if (!is_atm)
- bpf_error("'callref' supported only on raw ATM");
- if (off_proto == (u_int)-1)
+ if (!cstate->is_atm)
+ bpf_error(cstate, "'callref' supported only on raw ATM");
+ if (cstate->off_proto == (u_int)-1)
abort();
- b0 = gen_ncmp(OR_LINK, off_proto, BPF_B, 0xffffffff,
+ b0 = gen_ncmp(cstate, OR_LINKHDR, cstate->off_proto, BPF_B, 0xffffffff,
jtype, reverse, jvalue);
break;
@@ -8347,8 +8604,7 @@ gen_atmfield_code(atmfield, jvalue, jtype, reverse)
}
struct block *
-gen_atmtype_abbrev(type)
- int type;
+gen_atmtype_abbrev(compiler_state_t *cstate, int type)
{
struct block *b0, *b1;
@@ -8356,63 +8612,63 @@ gen_atmtype_abbrev(type)
case A_METAC:
/* Get all packets in Meta signalling Circuit */
- if (!is_atm)
- bpf_error("'metac' supported only on raw ATM");
- b0 = gen_atmfield_code(A_VPI, 0, BPF_JEQ, 0);
- b1 = gen_atmfield_code(A_VCI, 1, BPF_JEQ, 0);
+ if (!cstate->is_atm)
+ bpf_error(cstate, "'metac' supported only on raw ATM");
+ b0 = gen_atmfield_code(cstate, A_VPI, 0, BPF_JEQ, 0);
+ b1 = gen_atmfield_code(cstate, A_VCI, 1, BPF_JEQ, 0);
gen_and(b0, b1);
break;
case A_BCC:
/* Get all packets in Broadcast Circuit*/
- if (!is_atm)
- bpf_error("'bcc' supported only on raw ATM");
- b0 = gen_atmfield_code(A_VPI, 0, BPF_JEQ, 0);
- b1 = gen_atmfield_code(A_VCI, 2, BPF_JEQ, 0);
+ if (!cstate->is_atm)
+ bpf_error(cstate, "'bcc' supported only on raw ATM");
+ b0 = gen_atmfield_code(cstate, A_VPI, 0, BPF_JEQ, 0);
+ b1 = gen_atmfield_code(cstate, A_VCI, 2, BPF_JEQ, 0);
gen_and(b0, b1);
break;
case A_OAMF4SC:
/* Get all cells in Segment OAM F4 circuit*/
- if (!is_atm)
- bpf_error("'oam4sc' supported only on raw ATM");
- b0 = gen_atmfield_code(A_VPI, 0, BPF_JEQ, 0);
- b1 = gen_atmfield_code(A_VCI, 3, BPF_JEQ, 0);
+ if (!cstate->is_atm)
+ bpf_error(cstate, "'oam4sc' supported only on raw ATM");
+ b0 = gen_atmfield_code(cstate, A_VPI, 0, BPF_JEQ, 0);
+ b1 = gen_atmfield_code(cstate, A_VCI, 3, BPF_JEQ, 0);
gen_and(b0, b1);
break;
case A_OAMF4EC:
/* Get all cells in End-to-End OAM F4 Circuit*/
- if (!is_atm)
- bpf_error("'oam4ec' supported only on raw ATM");
- b0 = gen_atmfield_code(A_VPI, 0, BPF_JEQ, 0);
- b1 = gen_atmfield_code(A_VCI, 4, BPF_JEQ, 0);
+ if (!cstate->is_atm)
+ bpf_error(cstate, "'oam4ec' supported only on raw ATM");
+ b0 = gen_atmfield_code(cstate, A_VPI, 0, BPF_JEQ, 0);
+ b1 = gen_atmfield_code(cstate, A_VCI, 4, BPF_JEQ, 0);
gen_and(b0, b1);
break;
case A_SC:
/* Get all packets in connection Signalling Circuit */
- if (!is_atm)
- bpf_error("'sc' supported only on raw ATM");
- b0 = gen_atmfield_code(A_VPI, 0, BPF_JEQ, 0);
- b1 = gen_atmfield_code(A_VCI, 5, BPF_JEQ, 0);
+ if (!cstate->is_atm)
+ bpf_error(cstate, "'sc' supported only on raw ATM");
+ b0 = gen_atmfield_code(cstate, A_VPI, 0, BPF_JEQ, 0);
+ b1 = gen_atmfield_code(cstate, A_VCI, 5, BPF_JEQ, 0);
gen_and(b0, b1);
break;
case A_ILMIC:
/* Get all packets in ILMI Circuit */
- if (!is_atm)
- bpf_error("'ilmic' supported only on raw ATM");
- b0 = gen_atmfield_code(A_VPI, 0, BPF_JEQ, 0);
- b1 = gen_atmfield_code(A_VCI, 16, BPF_JEQ, 0);
+ if (!cstate->is_atm)
+ bpf_error(cstate, "'ilmic' supported only on raw ATM");
+ b0 = gen_atmfield_code(cstate, A_VPI, 0, BPF_JEQ, 0);
+ b1 = gen_atmfield_code(cstate, A_VCI, 16, BPF_JEQ, 0);
gen_and(b0, b1);
break;
case A_LANE:
/* Get all LANE packets */
- if (!is_atm)
- bpf_error("'lane' supported only on raw ATM");
- b1 = gen_atmfield_code(A_PROTOTYPE, PT_LANE, BPF_JEQ, 0);
+ if (!cstate->is_atm)
+ bpf_error(cstate, "'lane' supported only on raw ATM");
+ b1 = gen_atmfield_code(cstate, A_PROTOTYPE, PT_LANE, BPF_JEQ, 0);
/*
* Arrange that all subsequent tests assume LANE
@@ -8420,26 +8676,23 @@ gen_atmtype_abbrev(type)
* the offsets appropriately for LANE-encapsulated
* Ethernet.
*
- * "off_mac" is the offset of the Ethernet header,
- * which is 2 bytes past the ATM pseudo-header
- * (skipping the pseudo-header and 2-byte LE Client
- * field). The other offsets are Ethernet offsets
- * relative to "off_mac".
+ * We assume LANE means Ethernet, not Token Ring.
*/
- is_lane = 1;
- off_mac = off_payload + 2; /* MAC header */
- off_linktype = off_mac + 12;
- off_macpl = off_mac + 14; /* Ethernet */
- off_nl = 0; /* Ethernet II */
- off_nl_nosnap = 3; /* 802.3+802.2 */
+ PUSH_LINKHDR(cstate, DLT_EN10MB, 0,
+ cstate->off_payload + 2, /* Ethernet header */
+ -1);
+ cstate->off_linktype.constant_part = cstate->off_linkhdr.constant_part + 12;
+ cstate->off_linkpl.constant_part = cstate->off_linkhdr.constant_part + 14; /* Ethernet */
+ cstate->off_nl = 0; /* Ethernet II */
+ cstate->off_nl_nosnap = 3; /* 802.3+802.2 */
break;
case A_LLC:
/* Get all LLC-encapsulated packets */
- if (!is_atm)
- bpf_error("'llc' supported only on raw ATM");
- b1 = gen_atmfield_code(A_PROTOTYPE, PT_LLC, BPF_JEQ, 0);
- is_lane = 0;
+ if (!cstate->is_atm)
+ bpf_error(cstate, "'llc' supported only on raw ATM");
+ b1 = gen_atmfield_code(cstate, A_PROTOTYPE, PT_LLC, BPF_JEQ, 0);
+ cstate->linktype = cstate->prevlinktype;
break;
default:
@@ -8456,65 +8709,64 @@ gen_atmtype_abbrev(type)
* For MTP2_HSL, sequences are on 2 bytes, and length on 9 bits
*/
struct block *
-gen_mtp2type_abbrev(type)
- int type;
+gen_mtp2type_abbrev(compiler_state_t *cstate, int type)
{
struct block *b0, *b1;
switch (type) {
case M_FISU:
- if ( (linktype != DLT_MTP2) &&
- (linktype != DLT_ERF) &&
- (linktype != DLT_MTP2_WITH_PHDR) )
- bpf_error("'fisu' supported only on MTP2");
- /* gen_ncmp(offrel, offset, size, mask, jtype, reverse, value) */
- b0 = gen_ncmp(OR_PACKET, off_li, BPF_B, 0x3f, BPF_JEQ, 0, 0);
+ if ( (cstate->linktype != DLT_MTP2) &&
+ (cstate->linktype != DLT_ERF) &&
+ (cstate->linktype != DLT_MTP2_WITH_PHDR) )
+ bpf_error(cstate, "'fisu' supported only on MTP2");
+ /* gen_ncmp(cstate, offrel, offset, size, mask, jtype, reverse, value) */
+ b0 = gen_ncmp(cstate, OR_PACKET, cstate->off_li, BPF_B, 0x3f, BPF_JEQ, 0, 0);
break;
case M_LSSU:
- if ( (linktype != DLT_MTP2) &&
- (linktype != DLT_ERF) &&
- (linktype != DLT_MTP2_WITH_PHDR) )
- bpf_error("'lssu' supported only on MTP2");
- b0 = gen_ncmp(OR_PACKET, off_li, BPF_B, 0x3f, BPF_JGT, 1, 2);
- b1 = gen_ncmp(OR_PACKET, off_li, BPF_B, 0x3f, BPF_JGT, 0, 0);
+ if ( (cstate->linktype != DLT_MTP2) &&
+ (cstate->linktype != DLT_ERF) &&
+ (cstate->linktype != DLT_MTP2_WITH_PHDR) )
+ bpf_error(cstate, "'lssu' supported only on MTP2");
+ b0 = gen_ncmp(cstate, OR_PACKET, cstate->off_li, BPF_B, 0x3f, BPF_JGT, 1, 2);
+ b1 = gen_ncmp(cstate, OR_PACKET, cstate->off_li, BPF_B, 0x3f, BPF_JGT, 0, 0);
gen_and(b1, b0);
break;
case M_MSU:
- if ( (linktype != DLT_MTP2) &&
- (linktype != DLT_ERF) &&
- (linktype != DLT_MTP2_WITH_PHDR) )
- bpf_error("'msu' supported only on MTP2");
- b0 = gen_ncmp(OR_PACKET, off_li, BPF_B, 0x3f, BPF_JGT, 0, 2);
+ if ( (cstate->linktype != DLT_MTP2) &&
+ (cstate->linktype != DLT_ERF) &&
+ (cstate->linktype != DLT_MTP2_WITH_PHDR) )
+ bpf_error(cstate, "'msu' supported only on MTP2");
+ b0 = gen_ncmp(cstate, OR_PACKET, cstate->off_li, BPF_B, 0x3f, BPF_JGT, 0, 2);
break;
case MH_FISU:
- if ( (linktype != DLT_MTP2) &&
- (linktype != DLT_ERF) &&
- (linktype != DLT_MTP2_WITH_PHDR) )
- bpf_error("'hfisu' supported only on MTP2_HSL");
- /* gen_ncmp(offrel, offset, size, mask, jtype, reverse, value) */
- b0 = gen_ncmp(OR_PACKET, off_li_hsl, BPF_H, 0xff80, BPF_JEQ, 0, 0);
+ if ( (cstate->linktype != DLT_MTP2) &&
+ (cstate->linktype != DLT_ERF) &&
+ (cstate->linktype != DLT_MTP2_WITH_PHDR) )
+ bpf_error(cstate, "'hfisu' supported only on MTP2_HSL");
+ /* gen_ncmp(cstate, offrel, offset, size, mask, jtype, reverse, value) */
+ b0 = gen_ncmp(cstate, OR_PACKET, cstate->off_li_hsl, BPF_H, 0xff80, BPF_JEQ, 0, 0);
break;
case MH_LSSU:
- if ( (linktype != DLT_MTP2) &&
- (linktype != DLT_ERF) &&
- (linktype != DLT_MTP2_WITH_PHDR) )
- bpf_error("'hlssu' supported only on MTP2_HSL");
- b0 = gen_ncmp(OR_PACKET, off_li_hsl, BPF_H, 0xff80, BPF_JGT, 1, 0x0100);
- b1 = gen_ncmp(OR_PACKET, off_li_hsl, BPF_H, 0xff80, BPF_JGT, 0, 0);
+ if ( (cstate->linktype != DLT_MTP2) &&
+ (cstate->linktype != DLT_ERF) &&
+ (cstate->linktype != DLT_MTP2_WITH_PHDR) )
+ bpf_error(cstate, "'hlssu' supported only on MTP2_HSL");
+ b0 = gen_ncmp(cstate, OR_PACKET, cstate->off_li_hsl, BPF_H, 0xff80, BPF_JGT, 1, 0x0100);
+ b1 = gen_ncmp(cstate, OR_PACKET, cstate->off_li_hsl, BPF_H, 0xff80, BPF_JGT, 0, 0);
gen_and(b1, b0);
break;
case MH_MSU:
- if ( (linktype != DLT_MTP2) &&
- (linktype != DLT_ERF) &&
- (linktype != DLT_MTP2_WITH_PHDR) )
- bpf_error("'hmsu' supported only on MTP2_HSL");
- b0 = gen_ncmp(OR_PACKET, off_li_hsl, BPF_H, 0xff80, BPF_JGT, 0, 0x0100);
+ if ( (cstate->linktype != DLT_MTP2) &&
+ (cstate->linktype != DLT_ERF) &&
+ (cstate->linktype != DLT_MTP2_WITH_PHDR) )
+ bpf_error(cstate, "'hmsu' supported only on MTP2_HSL");
+ b0 = gen_ncmp(cstate, OR_PACKET, cstate->off_li_hsl, BPF_H, 0xff80, BPF_JGT, 0, 0x0100);
break;
default:
@@ -8524,18 +8776,15 @@ gen_mtp2type_abbrev(type)
}
struct block *
-gen_mtp3field_code(mtp3field, jvalue, jtype, reverse)
- int mtp3field;
- bpf_u_int32 jvalue;
- bpf_u_int32 jtype;
- int reverse;
+gen_mtp3field_code(compiler_state_t *cstate, int mtp3field, bpf_u_int32 jvalue,
+ bpf_u_int32 jtype, int reverse)
{
struct block *b0;
bpf_u_int32 val1 , val2 , val3;
- u_int newoff_sio=off_sio;
- u_int newoff_opc=off_opc;
- u_int newoff_dpc=off_dpc;
- u_int newoff_sls=off_sls;
+ u_int newoff_sio = cstate->off_sio;
+ u_int newoff_opc = cstate->off_opc;
+ u_int newoff_dpc = cstate->off_dpc;
+ u_int newoff_sls = cstate->off_sls;
switch (mtp3field) {
@@ -8544,24 +8793,24 @@ gen_mtp3field_code(mtp3field, jvalue, jtype, reverse)
/* FALLTHROUGH */
case M_SIO:
- if (off_sio == (u_int)-1)
- bpf_error("'sio' supported only on SS7");
+ if (cstate->off_sio == (u_int)-1)
+ bpf_error(cstate, "'sio' supported only on SS7");
/* sio coded on 1 byte so max value 255 */
if(jvalue > 255)
- bpf_error("sio value %u too big; max value = 255",
+ bpf_error(cstate, "sio value %u too big; max value = 255",
jvalue);
- b0 = gen_ncmp(OR_PACKET, newoff_sio, BPF_B, 0xffffffff,
+ b0 = gen_ncmp(cstate, OR_PACKET, newoff_sio, BPF_B, 0xffffffff,
(u_int)jtype, reverse, (u_int)jvalue);
break;
case MH_OPC:
newoff_opc+=3;
case M_OPC:
- if (off_opc == (u_int)-1)
- bpf_error("'opc' supported only on SS7");
+ if (cstate->off_opc == (u_int)-1)
+ bpf_error(cstate, "'opc' supported only on SS7");
/* opc coded on 14 bits so max value 16383 */
if (jvalue > 16383)
- bpf_error("opc value %u too big; max value = 16383",
+ bpf_error(cstate, "opc value %u too big; max value = 16383",
jvalue);
/* the following instructions are made to convert jvalue
* to the form used to write opc in an ss7 message*/
@@ -8572,7 +8821,7 @@ gen_mtp3field_code(mtp3field, jvalue, jtype, reverse)
val3 = jvalue & 0x00000003;
val3 = val3 <<22;
jvalue = val1 + val2 + val3;
- b0 = gen_ncmp(OR_PACKET, newoff_opc, BPF_W, 0x00c0ff0f,
+ b0 = gen_ncmp(cstate, OR_PACKET, newoff_opc, BPF_W, 0x00c0ff0f,
(u_int)jtype, reverse, (u_int)jvalue);
break;
@@ -8581,11 +8830,11 @@ gen_mtp3field_code(mtp3field, jvalue, jtype, reverse)
/* FALLTHROUGH */
case M_DPC:
- if (off_dpc == (u_int)-1)
- bpf_error("'dpc' supported only on SS7");
+ if (cstate->off_dpc == (u_int)-1)
+ bpf_error(cstate, "'dpc' supported only on SS7");
/* dpc coded on 14 bits so max value 16383 */
if (jvalue > 16383)
- bpf_error("dpc value %u too big; max value = 16383",
+ bpf_error(cstate, "dpc value %u too big; max value = 16383",
jvalue);
/* the following instructions are made to convert jvalue
* to the forme used to write dpc in an ss7 message*/
@@ -8594,23 +8843,23 @@ gen_mtp3field_code(mtp3field, jvalue, jtype, reverse)
val2 = jvalue & 0x00003f00;
val2 = val2 << 8;
jvalue = val1 + val2;
- b0 = gen_ncmp(OR_PACKET, newoff_dpc, BPF_W, 0xff3f0000,
+ b0 = gen_ncmp(cstate, OR_PACKET, newoff_dpc, BPF_W, 0xff3f0000,
(u_int)jtype, reverse, (u_int)jvalue);
break;
case MH_SLS:
newoff_sls+=3;
case M_SLS:
- if (off_sls == (u_int)-1)
- bpf_error("'sls' supported only on SS7");
+ if (cstate->off_sls == (u_int)-1)
+ bpf_error(cstate, "'sls' supported only on SS7");
/* sls coded on 4 bits so max value 15 */
if (jvalue > 15)
- bpf_error("sls value %u too big; max value = 15",
+ bpf_error(cstate, "sls value %u too big; max value = 15",
jvalue);
/* the following instruction is made to convert jvalue
* to the forme used to write sls in an ss7 message*/
jvalue = jvalue << 4;
- b0 = gen_ncmp(OR_PACKET, newoff_sls, BPF_B, 0xf0,
+ b0 = gen_ncmp(cstate, OR_PACKET, newoff_sls, BPF_B, 0xf0,
(u_int)jtype,reverse, (u_int)jvalue);
break;
@@ -8621,8 +8870,7 @@ gen_mtp3field_code(mtp3field, jvalue, jtype, reverse)
}
static struct block *
-gen_msg_abbrev(type)
- int type;
+gen_msg_abbrev(compiler_state_t *cstate, int type)
{
struct block *b1;
@@ -8633,27 +8881,27 @@ gen_msg_abbrev(type)
switch (type) {
case A_SETUP:
- b1 = gen_atmfield_code(A_MSGTYPE, SETUP, BPF_JEQ, 0);
+ b1 = gen_atmfield_code(cstate, A_MSGTYPE, SETUP, BPF_JEQ, 0);
break;
case A_CALLPROCEED:
- b1 = gen_atmfield_code(A_MSGTYPE, CALL_PROCEED, BPF_JEQ, 0);
+ b1 = gen_atmfield_code(cstate, A_MSGTYPE, CALL_PROCEED, BPF_JEQ, 0);
break;
case A_CONNECT:
- b1 = gen_atmfield_code(A_MSGTYPE, CONNECT, BPF_JEQ, 0);
+ b1 = gen_atmfield_code(cstate, A_MSGTYPE, CONNECT, BPF_JEQ, 0);
break;
case A_CONNECTACK:
- b1 = gen_atmfield_code(A_MSGTYPE, CONNECT_ACK, BPF_JEQ, 0);
+ b1 = gen_atmfield_code(cstate, A_MSGTYPE, CONNECT_ACK, BPF_JEQ, 0);
break;
case A_RELEASE:
- b1 = gen_atmfield_code(A_MSGTYPE, RELEASE, BPF_JEQ, 0);
+ b1 = gen_atmfield_code(cstate, A_MSGTYPE, RELEASE, BPF_JEQ, 0);
break;
case A_RELEASE_DONE:
- b1 = gen_atmfield_code(A_MSGTYPE, RELEASE_DONE, BPF_JEQ, 0);
+ b1 = gen_atmfield_code(cstate, A_MSGTYPE, RELEASE_DONE, BPF_JEQ, 0);
break;
default:
@@ -8663,27 +8911,26 @@ gen_msg_abbrev(type)
}
struct block *
-gen_atmmulti_abbrev(type)
- int type;
+gen_atmmulti_abbrev(compiler_state_t *cstate, int type)
{
struct block *b0, *b1;
switch (type) {
case A_OAM:
- if (!is_atm)
- bpf_error("'oam' supported only on raw ATM");
- b1 = gen_atmmulti_abbrev(A_OAMF4);
+ if (!cstate->is_atm)
+ bpf_error(cstate, "'oam' supported only on raw ATM");
+ b1 = gen_atmmulti_abbrev(cstate, A_OAMF4);
break;
case A_OAMF4:
- if (!is_atm)
- bpf_error("'oamf4' supported only on raw ATM");
+ if (!cstate->is_atm)
+ bpf_error(cstate, "'oamf4' supported only on raw ATM");
/* OAM F4 type */
- b0 = gen_atmfield_code(A_VCI, 3, BPF_JEQ, 0);
- b1 = gen_atmfield_code(A_VCI, 4, BPF_JEQ, 0);
+ b0 = gen_atmfield_code(cstate, A_VCI, 3, BPF_JEQ, 0);
+ b1 = gen_atmfield_code(cstate, A_VCI, 4, BPF_JEQ, 0);
gen_or(b0, b1);
- b0 = gen_atmfield_code(A_VPI, 0, BPF_JEQ, 0);
+ b0 = gen_atmfield_code(cstate, A_VPI, 0, BPF_JEQ, 0);
gen_and(b0, b1);
break;
@@ -8692,36 +8939,36 @@ gen_atmmulti_abbrev(type)
* Get Q.2931 signalling messages for switched
* virtual connection
*/
- if (!is_atm)
- bpf_error("'connectmsg' supported only on raw ATM");
- b0 = gen_msg_abbrev(A_SETUP);
- b1 = gen_msg_abbrev(A_CALLPROCEED);
+ if (!cstate->is_atm)
+ bpf_error(cstate, "'connectmsg' supported only on raw ATM");
+ b0 = gen_msg_abbrev(cstate, A_SETUP);
+ b1 = gen_msg_abbrev(cstate, A_CALLPROCEED);
gen_or(b0, b1);
- b0 = gen_msg_abbrev(A_CONNECT);
+ b0 = gen_msg_abbrev(cstate, A_CONNECT);
gen_or(b0, b1);
- b0 = gen_msg_abbrev(A_CONNECTACK);
+ b0 = gen_msg_abbrev(cstate, A_CONNECTACK);
gen_or(b0, b1);
- b0 = gen_msg_abbrev(A_RELEASE);
+ b0 = gen_msg_abbrev(cstate, A_RELEASE);
gen_or(b0, b1);
- b0 = gen_msg_abbrev(A_RELEASE_DONE);
+ b0 = gen_msg_abbrev(cstate, A_RELEASE_DONE);
gen_or(b0, b1);
- b0 = gen_atmtype_abbrev(A_SC);
+ b0 = gen_atmtype_abbrev(cstate, A_SC);
gen_and(b0, b1);
break;
case A_METACONNECT:
- if (!is_atm)
- bpf_error("'metaconnect' supported only on raw ATM");
- b0 = gen_msg_abbrev(A_SETUP);
- b1 = gen_msg_abbrev(A_CALLPROCEED);
+ if (!cstate->is_atm)
+ bpf_error(cstate, "'metaconnect' supported only on raw ATM");
+ b0 = gen_msg_abbrev(cstate, A_SETUP);
+ b1 = gen_msg_abbrev(cstate, A_CALLPROCEED);
gen_or(b0, b1);
- b0 = gen_msg_abbrev(A_CONNECT);
+ b0 = gen_msg_abbrev(cstate, A_CONNECT);
gen_or(b0, b1);
- b0 = gen_msg_abbrev(A_RELEASE);
+ b0 = gen_msg_abbrev(cstate, A_RELEASE);
gen_or(b0, b1);
- b0 = gen_msg_abbrev(A_RELEASE_DONE);
+ b0 = gen_msg_abbrev(cstate, A_RELEASE_DONE);
gen_or(b0, b1);
- b0 = gen_atmtype_abbrev(A_METAC);
+ b0 = gen_atmtype_abbrev(cstate, A_METAC);
gen_and(b0, b1);
break;
diff --git a/contrib/libpcap/gencode.h b/contrib/libpcap/gencode.h
index e6b3a71ea0db..2b089d21d561 100644
--- a/contrib/libpcap/gencode.h
+++ b/contrib/libpcap/gencode.h
@@ -161,7 +161,7 @@
#define A_CONNECTACK 44 /* Connect Ack message */
#define A_RELEASE 45 /* Release message */
#define A_RELEASE_DONE 46 /* Release message */
-
+
/* ATM field types */
#define A_VPI 51
#define A_VCI 52
@@ -281,83 +281,115 @@ struct qual {
unsigned char pad;
};
-struct arth *gen_loadi(int);
-struct arth *gen_load(int, struct arth *, int);
-struct arth *gen_loadlen(void);
-struct arth *gen_neg(struct arth *);
-struct arth *gen_arth(int, struct arth *, struct arth *);
+struct _compiler_state;
+
+typedef struct _compiler_state compiler_state_t;
+
+struct arth *gen_loadi(compiler_state_t *, int);
+struct arth *gen_load(compiler_state_t *, int, struct arth *, int);
+struct arth *gen_loadlen(compiler_state_t *);
+struct arth *gen_neg(compiler_state_t *, struct arth *);
+struct arth *gen_arth(compiler_state_t *, int, struct arth *, struct arth *);
void gen_and(struct block *, struct block *);
void gen_or(struct block *, struct block *);
void gen_not(struct block *);
-struct block *gen_scode(const char *, struct qual);
-struct block *gen_ecode(const u_char *, struct qual);
-struct block *gen_acode(const u_char *, struct qual);
-struct block *gen_mcode(const char *, const char *, int, struct qual);
+struct block *gen_scode(compiler_state_t *, const char *, struct qual);
+struct block *gen_ecode(compiler_state_t *, const u_char *, struct qual);
+struct block *gen_acode(compiler_state_t *, const u_char *, struct qual);
+struct block *gen_mcode(compiler_state_t *, const char *, const char *,
+ unsigned int, struct qual);
#ifdef INET6
-struct block *gen_mcode6(const char *, const char *, int, struct qual);
+struct block *gen_mcode6(compiler_state_t *, const char *, const char *,
+ unsigned int, struct qual);
#endif
-struct block *gen_ncode(const char *, bpf_u_int32, struct qual);
-struct block *gen_proto_abbrev(int);
-struct block *gen_relation(int, struct arth *, struct arth *, int);
-struct block *gen_less(int);
-struct block *gen_greater(int);
-struct block *gen_byteop(int, int, int);
-struct block *gen_broadcast(int);
-struct block *gen_multicast(int);
-struct block *gen_inbound(int);
-
-struct block *gen_llc(void);
-struct block *gen_llc_i(void);
-struct block *gen_llc_s(void);
-struct block *gen_llc_u(void);
-struct block *gen_llc_s_subtype(bpf_u_int32);
-struct block *gen_llc_u_subtype(bpf_u_int32);
-
-struct block *gen_vlan(int);
-struct block *gen_mpls(int);
-
-struct block *gen_pppoed(void);
-struct block *gen_pppoes(int);
-
-struct block *gen_atmfield_code(int atmfield, bpf_int32 jvalue, bpf_u_int32 jtype, int reverse);
-struct block *gen_atmtype_abbrev(int type);
-struct block *gen_atmmulti_abbrev(int type);
-
-struct block *gen_mtp2type_abbrev(int type);
-struct block *gen_mtp3field_code(int mtp3field, bpf_u_int32 jvalue, bpf_u_int32 jtype, int reverse);
-
-struct block *gen_pf_ifname(const char *);
-struct block *gen_pf_rnr(int);
-struct block *gen_pf_srnr(int);
-struct block *gen_pf_ruleset(char *);
-struct block *gen_pf_reason(int);
-struct block *gen_pf_action(int);
-struct block *gen_pf_dir(int);
-
-struct block *gen_p80211_type(int, int);
-struct block *gen_p80211_fcdir(int);
-
-void bpf_optimize(struct block **);
-void bpf_error(const char *, ...)
+struct block *gen_ncode(compiler_state_t *, const char *, bpf_u_int32,
+ struct qual);
+struct block *gen_proto_abbrev(compiler_state_t *, int);
+struct block *gen_relation(compiler_state_t *, int, struct arth *,
+ struct arth *, int);
+struct block *gen_less(compiler_state_t *, int);
+struct block *gen_greater(compiler_state_t *, int);
+struct block *gen_byteop(compiler_state_t *, int, int, int);
+struct block *gen_broadcast(compiler_state_t *, int);
+struct block *gen_multicast(compiler_state_t *, int);
+struct block *gen_inbound(compiler_state_t *, int);
+
+struct block *gen_llc(compiler_state_t *);
+struct block *gen_llc_i(compiler_state_t *);
+struct block *gen_llc_s(compiler_state_t *);
+struct block *gen_llc_u(compiler_state_t *);
+struct block *gen_llc_s_subtype(compiler_state_t *, bpf_u_int32);
+struct block *gen_llc_u_subtype(compiler_state_t *, bpf_u_int32);
+
+struct block *gen_vlan(compiler_state_t *, int);
+struct block *gen_mpls(compiler_state_t *, int);
+
+struct block *gen_pppoed(compiler_state_t *);
+struct block *gen_pppoes(compiler_state_t *, int);
+
+struct block *gen_geneve(compiler_state_t *, int);
+
+struct block *gen_atmfield_code(compiler_state_t *, int, bpf_int32,
+ bpf_u_int32, int);
+struct block *gen_atmtype_abbrev(compiler_state_t *, int type);
+struct block *gen_atmmulti_abbrev(compiler_state_t *, int type);
+
+struct block *gen_mtp2type_abbrev(compiler_state_t *, int type);
+struct block *gen_mtp3field_code(compiler_state_t *, int, bpf_u_int32,
+ bpf_u_int32, int);
+
+struct block *gen_pf_ifname(compiler_state_t *, const char *);
+struct block *gen_pf_rnr(compiler_state_t *, int);
+struct block *gen_pf_srnr(compiler_state_t *, int);
+struct block *gen_pf_ruleset(compiler_state_t *, char *);
+struct block *gen_pf_reason(compiler_state_t *, int);
+struct block *gen_pf_action(compiler_state_t *, int);
+
+struct block *gen_p80211_type(compiler_state_t *, int, int);
+struct block *gen_p80211_fcdir(compiler_state_t *, int);
+
+/*
+ * Representation of a program as a tree of blocks, plus current mark.
+ * A block is marked if only if its mark equals the current mark.
+ * Rather than traverse the code array, marking each item, 'cur_mark'
+ * is incremented. This automatically makes each element unmarked.
+ */
+#define isMarked(icp, p) ((p)->mark == (icp)->cur_mark)
+#define unMarkAll(icp) (icp)->cur_mark += 1
+#define Mark(icp, p) ((p)->mark = (icp)->cur_mark)
+
+struct icode {
+ struct block *root;
+ int cur_mark;
+};
+
+void bpf_optimize(compiler_state_t *, struct icode *ic);
+void bpf_syntax_error(compiler_state_t *, const char *);
+void bpf_error(compiler_state_t *, const char *, ...)
__attribute__((noreturn))
#ifdef __ATTRIBUTE___FORMAT_OK
- __attribute__((format (printf, 1, 2)))
+ __attribute__((format (printf, 2, 3)))
#endif /* __ATTRIBUTE___FORMAT_OK */
;
-void finish_parse(struct block *);
-char *sdup(const char *);
+void finish_parse(compiler_state_t *, struct block *);
+char *sdup(compiler_state_t *, const char *);
-struct bpf_insn *icode_to_fcode(struct block *, u_int *);
-int pcap_parse(void);
-void lex_init(const char *);
-void lex_cleanup(void);
+struct _opt_state;
+typedef struct _opt_state opt_state_t;
+
+struct bpf_insn *icode_to_fcode(compiler_state_t *, struct icode *,
+ struct block *, u_int *);
void sappend(struct slist *, struct slist *);
+/*
+ * Older versions of Bison don't put this declaration in
+ * grammar.h.
+ */
+int pcap_parse(void *, compiler_state_t *);
+
/* XXX */
#define JT(b) ((b)->et.succ)
#define JF(b) ((b)->ef.succ)
-
-extern int no_optimize;
diff --git a/contrib/libpcap/grammar.y b/contrib/libpcap/grammar.y
index fd8b64d19488..ef6a7abbb0b9 100644
--- a/contrib/libpcap/grammar.y
+++ b/contrib/libpcap/grammar.y
@@ -1,3 +1,28 @@
+/*
+ * We want a reentrant parser.
+ */
+%pure-parser
+
+/*
+ * We also want a reentrant scanner, so we have to pass the
+ * handle for the reentrant scanner to the parser, and the
+ * parser has to pass it to the lexical analyzer.
+ *
+ * We use void * rather than yyscan_t because, at least with some
+ * versions of Flex and Bison, if you use yyscan_t in %parse-param and
+ * %lex-param, you have to include scanner.h before grammar.h to get
+ * yyscan_t declared, and you have to include grammar.h before scanner.h
+ * to get YYSTYPE declared. Using void * breaks the cycle; the Flex
+ * documentation says yyscan_t is just a void *.
+ */
+%parse-param {void *yyscanner}
+%lex-param {void *yyscanner}
+
+/*
+ * And we need to pass the compiler state to the scanner.
+ */
+%parse-param {compiler_state_t *cstate}
+
%{
/*
* Copyright (c) 1988, 1989, 1990, 1991, 1992, 1993, 1994, 1995, 1996
@@ -26,16 +51,16 @@
#include "config.h"
#endif
-#ifdef WIN32
+#ifdef _WIN32
#include <pcap-stdinc.h>
-#else /* WIN32 */
+#else /* _WIN32 */
#include <sys/types.h>
#include <sys/socket.h>
-#endif /* WIN32 */
+#endif /* _WIN32 */
#include <stdlib.h>
-#ifndef WIN32
+#ifndef _WIN32
#if __STDC__
struct mbuf;
struct rtentry;
@@ -43,13 +68,16 @@ struct rtentry;
#include <netinet/in.h>
#include <arpa/inet.h>
-#endif /* WIN32 */
+#endif /* _WIN32 */
#include <stdio.h>
#include "pcap-int.h"
#include "gencode.h"
+#include "grammar.h"
+#include "scanner.h"
+
#ifdef HAVE_NET_PFVAR_H
#include <net/if.h>
#include <netpfil/pf/pf.h>
@@ -170,31 +198,18 @@ str2tok(const char *str, const struct tok *toks)
return (-1);
}
-int n_errors = 0;
-
static struct qual qerr = { Q_UNDEF, Q_UNDEF, Q_UNDEF, Q_UNDEF };
static void
-yyerror(const char *msg)
+yyerror(void *yyscanner, compiler_state_t *cstate, const char *msg)
{
- ++n_errors;
- bpf_error("%s", msg);
+ bpf_syntax_error(cstate, msg);
/* NOTREACHED */
}
-#ifdef NEED_YYPARSE_WRAPPER
-int yyparse(void);
-
-int
-pcap_parse()
-{
- return (yyparse());
-}
-#endif
-
#ifdef HAVE_NET_PFVAR_H
static int
-pfreason_to_num(const char *reason)
+pfreason_to_num(compiler_state_t *cstate, const char *reason)
{
const char *reasons[] = PFRES_NAMES;
int i;
@@ -203,12 +218,12 @@ pfreason_to_num(const char *reason)
if (pcap_strcasecmp(reason, reasons[i]) == 0)
return (i);
}
- bpf_error("unknown PF reason");
+ bpf_error(cstate, "unknown PF reason");
/*NOTREACHED*/
}
static int
-pfaction_to_num(const char *action)
+pfaction_to_num(compiler_state_t *cstate, const char *action)
{
if (pcap_strcasecmp(action, "pass") == 0 ||
pcap_strcasecmp(action, "accept") == 0)
@@ -227,15 +242,15 @@ pfaction_to_num(const char *action)
return (PF_NORDR);
#endif
else {
- bpf_error("unknown PF action");
+ bpf_error(cstate, "unknown PF action");
/*NOTREACHED*/
}
}
#else /* !HAVE_NET_PFVAR_H */
static int
-pfreason_to_num(const char *reason)
+pfreason_to_num(compiler_state_t *cstate, const char *reason)
{
- bpf_error("libpcap was compiled on a machine without pf support");
+ bpf_error(cstate, "libpcap was compiled on a machine without pf support");
/*NOTREACHED*/
/* this is to make the VC compiler happy */
@@ -243,9 +258,9 @@ pfreason_to_num(const char *reason)
}
static int
-pfaction_to_num(const char *action)
+pfaction_to_num(compiler_state_t *cstate, const char *action)
{
- bpf_error("libpcap was compiled on a machine without pf support");
+ bpf_error(cstate, "libpcap was compiled on a machine without pf support");
/*NOTREACHED*/
/* this is to make the VC compiler happy */
@@ -300,8 +315,8 @@ pfaction_to_num(const char *action)
%token LEN
%token IPV6 ICMPV6 AH ESP
%token VLAN MPLS
-%token PPPOED PPPOES
-%token ISO ESIS CLNP ISIS L1 L2 IIH LSP SNP CSNP PSNP
+%token PPPOED PPPOES GENEVE
+%token ISO ESIS CLNP ISIS L1 L2 IIH LSP SNP CSNP PSNP
%token STP
%token IPX
%token NETBEUI
@@ -311,7 +326,7 @@ pfaction_to_num(const char *action)
%token RADIO
%token FISU LSSU MSU HFISU HLSSU HMSU
%token SIO OPC DPC SLS HSIO HOPC HDPC HSLS
-
+
%type <s> ID
%type <e> EID
@@ -330,7 +345,7 @@ pfaction_to_num(const char *action)
%%
prog: null expr
{
- finish_parse($2.b);
+ finish_parse(cstate, $2.b);
}
| null
;
@@ -347,48 +362,48 @@ and: AND { $$ = $<blk>0; }
or: OR { $$ = $<blk>0; }
;
id: nid
- | pnum { $$.b = gen_ncode(NULL, (bpf_u_int32)$1,
+ | pnum { $$.b = gen_ncode(cstate, NULL, (bpf_u_int32)$1,
$$.q = $<blk>0.q); }
| paren pid ')' { $$ = $2; }
;
-nid: ID { $$.b = gen_scode($1, $$.q = $<blk>0.q); }
- | HID '/' NUM { $$.b = gen_mcode($1, NULL, $3,
+nid: ID { $$.b = gen_scode(cstate, $1, $$.q = $<blk>0.q); }
+ | HID '/' NUM { $$.b = gen_mcode(cstate, $1, NULL, $3,
$$.q = $<blk>0.q); }
- | HID NETMASK HID { $$.b = gen_mcode($1, $3, 0,
+ | HID NETMASK HID { $$.b = gen_mcode(cstate, $1, $3, 0,
$$.q = $<blk>0.q); }
| HID {
/* Decide how to parse HID based on proto */
$$.q = $<blk>0.q;
if ($$.q.addr == Q_PORT)
- bpf_error("'port' modifier applied to ip host");
+ bpf_error(cstate, "'port' modifier applied to ip host");
else if ($$.q.addr == Q_PORTRANGE)
- bpf_error("'portrange' modifier applied to ip host");
+ bpf_error(cstate, "'portrange' modifier applied to ip host");
else if ($$.q.addr == Q_PROTO)
- bpf_error("'proto' modifier applied to ip host");
+ bpf_error(cstate, "'proto' modifier applied to ip host");
else if ($$.q.addr == Q_PROTOCHAIN)
- bpf_error("'protochain' modifier applied to ip host");
- $$.b = gen_ncode($1, 0, $$.q);
+ bpf_error(cstate, "'protochain' modifier applied to ip host");
+ $$.b = gen_ncode(cstate, $1, 0, $$.q);
}
| HID6 '/' NUM {
#ifdef INET6
- $$.b = gen_mcode6($1, NULL, $3,
+ $$.b = gen_mcode6(cstate, $1, NULL, $3,
$$.q = $<blk>0.q);
#else
- bpf_error("'ip6addr/prefixlen' not supported "
+ bpf_error(cstate, "'ip6addr/prefixlen' not supported "
"in this configuration");
#endif /*INET6*/
}
| HID6 {
#ifdef INET6
- $$.b = gen_mcode6($1, 0, 128,
+ $$.b = gen_mcode6(cstate, $1, 0, 128,
$$.q = $<blk>0.q);
#else
- bpf_error("'ip6addr' not supported "
+ bpf_error(cstate, "'ip6addr' not supported "
"in this configuration");
#endif /*INET6*/
}
- | EID {
- $$.b = gen_ecode($1, $$.q = $<blk>0.q);
+ | EID {
+ $$.b = gen_ecode(cstate, $1, $$.q = $<blk>0.q);
/*
* $1 was allocated by "pcap_ether_aton()",
* so we must free it now that we're done
@@ -397,7 +412,7 @@ nid: ID { $$.b = gen_scode($1, $$.q = $<blk>0.q); }
free($1);
}
| AID {
- $$.b = gen_acode($1, $$.q = $<blk>0.q);
+ $$.b = gen_acode(cstate, $1, $$.q = $<blk>0.q);
/*
* $1 was allocated by "pcap_ether_aton()",
* so we must free it now that we're done
@@ -415,7 +430,7 @@ pid: nid
| qid and id { gen_and($1.b, $3.b); $$ = $3; }
| qid or id { gen_or($1.b, $3.b); $$ = $3; }
;
-qid: pnum { $$.b = gen_ncode(NULL, (bpf_u_int32)$1,
+qid: pnum { $$.b = gen_ncode(cstate, NULL, (bpf_u_int32)$1,
$$.q = $<blk>0.q); }
| pid
;
@@ -431,16 +446,16 @@ head: pqual dqual aqual { QSET($$.q, $1, $2, $3); }
;
rterm: head id { $$ = $2; }
| paren expr ')' { $$.b = $2.b; $$.q = $1.q; }
- | pname { $$.b = gen_proto_abbrev($1); $$.q = qerr; }
- | arth relop arth { $$.b = gen_relation($2, $1, $3, 0);
+ | pname { $$.b = gen_proto_abbrev(cstate, $1); $$.q = qerr; }
+ | arth relop arth { $$.b = gen_relation(cstate, $2, $1, $3, 0);
$$.q = qerr; }
- | arth irelop arth { $$.b = gen_relation($2, $1, $3, 1);
+ | arth irelop arth { $$.b = gen_relation(cstate, $2, $1, $3, 1);
$$.q = qerr; }
| other { $$.b = $1; $$.q = qerr; }
- | atmtype { $$.b = gen_atmtype_abbrev($1); $$.q = qerr; }
- | atmmultitype { $$.b = gen_atmmulti_abbrev($1); $$.q = qerr; }
+ | atmtype { $$.b = gen_atmtype_abbrev(cstate, $1); $$.q = qerr; }
+ | atmmultitype { $$.b = gen_atmmulti_abbrev(cstate, $1); $$.q = qerr; }
| atmfield atmvalue { $$.b = $2.b; $$.q = qerr; }
- | mtp2type { $$.b = gen_mtp2type_abbrev($1); $$.q = qerr; }
+ | mtp2type { $$.b = gen_mtp2type_abbrev(cstate, $1); $$.q = qerr; }
| mtp3field mtp3value { $$.b = $2.b; $$.q = qerr; }
;
/* protocol level qualifiers */
@@ -510,52 +525,54 @@ pname: LINK { $$ = Q_LINK; }
| NETBEUI { $$ = Q_NETBEUI; }
| RADIO { $$ = Q_RADIO; }
;
-other: pqual TK_BROADCAST { $$ = gen_broadcast($1); }
- | pqual TK_MULTICAST { $$ = gen_multicast($1); }
- | LESS NUM { $$ = gen_less($2); }
- | GREATER NUM { $$ = gen_greater($2); }
- | CBYTE NUM byteop NUM { $$ = gen_byteop($3, $2, $4); }
- | INBOUND { $$ = gen_inbound(0); }
- | OUTBOUND { $$ = gen_inbound(1); }
- | VLAN pnum { $$ = gen_vlan($2); }
- | VLAN { $$ = gen_vlan(-1); }
- | MPLS pnum { $$ = gen_mpls($2); }
- | MPLS { $$ = gen_mpls(-1); }
- | PPPOED { $$ = gen_pppoed(); }
- | PPPOES pnum { $$ = gen_pppoes($2); }
- | PPPOES { $$ = gen_pppoes(-1); }
+other: pqual TK_BROADCAST { $$ = gen_broadcast(cstate, $1); }
+ | pqual TK_MULTICAST { $$ = gen_multicast(cstate, $1); }
+ | LESS NUM { $$ = gen_less(cstate, $2); }
+ | GREATER NUM { $$ = gen_greater(cstate, $2); }
+ | CBYTE NUM byteop NUM { $$ = gen_byteop(cstate, $3, $2, $4); }
+ | INBOUND { $$ = gen_inbound(cstate, 0); }
+ | OUTBOUND { $$ = gen_inbound(cstate, 1); }
+ | VLAN pnum { $$ = gen_vlan(cstate, $2); }
+ | VLAN { $$ = gen_vlan(cstate, -1); }
+ | MPLS pnum { $$ = gen_mpls(cstate, $2); }
+ | MPLS { $$ = gen_mpls(cstate, -1); }
+ | PPPOED { $$ = gen_pppoed(cstate); }
+ | PPPOES pnum { $$ = gen_pppoes(cstate, $2); }
+ | PPPOES { $$ = gen_pppoes(cstate, -1); }
+ | GENEVE pnum { $$ = gen_geneve(cstate, $2); }
+ | GENEVE { $$ = gen_geneve(cstate, -1); }
| pfvar { $$ = $1; }
| pqual p80211 { $$ = $2; }
| pllc { $$ = $1; }
;
-pfvar: PF_IFNAME ID { $$ = gen_pf_ifname($2); }
- | PF_RSET ID { $$ = gen_pf_ruleset($2); }
- | PF_RNR NUM { $$ = gen_pf_rnr($2); }
- | PF_SRNR NUM { $$ = gen_pf_srnr($2); }
- | PF_REASON reason { $$ = gen_pf_reason($2); }
- | PF_ACTION action { $$ = gen_pf_action($2); }
+pfvar: PF_IFNAME ID { $$ = gen_pf_ifname(cstate, $2); }
+ | PF_RSET ID { $$ = gen_pf_ruleset(cstate, $2); }
+ | PF_RNR NUM { $$ = gen_pf_rnr(cstate, $2); }
+ | PF_SRNR NUM { $$ = gen_pf_srnr(cstate, $2); }
+ | PF_REASON reason { $$ = gen_pf_reason(cstate, $2); }
+ | PF_ACTION action { $$ = gen_pf_action(cstate, $2); }
;
p80211: TYPE type SUBTYPE subtype
- { $$ = gen_p80211_type($2 | $4,
+ { $$ = gen_p80211_type(cstate, $2 | $4,
IEEE80211_FC0_TYPE_MASK |
IEEE80211_FC0_SUBTYPE_MASK);
}
- | TYPE type { $$ = gen_p80211_type($2,
+ | TYPE type { $$ = gen_p80211_type(cstate, $2,
IEEE80211_FC0_TYPE_MASK);
}
- | SUBTYPE type_subtype { $$ = gen_p80211_type($2,
+ | SUBTYPE type_subtype { $$ = gen_p80211_type(cstate, $2,
IEEE80211_FC0_TYPE_MASK |
IEEE80211_FC0_SUBTYPE_MASK);
}
- | DIR dir { $$ = gen_p80211_fcdir($2); }
+ | DIR dir { $$ = gen_p80211_fcdir(cstate, $2); }
;
type: NUM
| ID { $$ = str2tok($1, ieee80211_types);
if ($$ == -1)
- bpf_error("unknown 802.11 type name");
+ bpf_error(cstate, "unknown 802.11 type name");
}
;
@@ -565,7 +582,7 @@ subtype: NUM
for (i = 0;; i++) {
if (ieee80211_type_subtypes[i].tok == NULL) {
/* Ran out of types */
- bpf_error("unknown 802.11 type");
+ bpf_error(cstate, "unknown 802.11 type");
break;
}
if ($<i>-1 == ieee80211_type_subtypes[i].type) {
@@ -576,7 +593,7 @@ subtype: NUM
$$ = str2tok($1, types);
if ($$ == -1)
- bpf_error("unknown 802.11 subtype name");
+ bpf_error(cstate, "unknown 802.11 subtype name");
}
;
@@ -584,7 +601,7 @@ type_subtype: ID { int i;
for (i = 0;; i++) {
if (ieee80211_type_subtypes[i].tok == NULL) {
/* Ran out of types */
- bpf_error("unknown 802.11 type name");
+ bpf_error(cstate, "unknown 802.11 type name");
break;
}
$$ = str2tok($1, ieee80211_type_subtypes[i].tok);
@@ -596,29 +613,29 @@ type_subtype: ID { int i;
}
;
-pllc: LLC { $$ = gen_llc(); }
+pllc: LLC { $$ = gen_llc(cstate); }
| LLC ID { if (pcap_strcasecmp($2, "i") == 0)
- $$ = gen_llc_i();
+ $$ = gen_llc_i(cstate);
else if (pcap_strcasecmp($2, "s") == 0)
- $$ = gen_llc_s();
+ $$ = gen_llc_s(cstate);
else if (pcap_strcasecmp($2, "u") == 0)
- $$ = gen_llc_u();
+ $$ = gen_llc_u(cstate);
else {
- u_int subtype;
+ int subtype;
subtype = str2tok($2, llc_s_subtypes);
if (subtype != -1)
- $$ = gen_llc_s_subtype(subtype);
+ $$ = gen_llc_s_subtype(cstate, subtype);
else {
subtype = str2tok($2, llc_u_subtypes);
if (subtype == -1)
- bpf_error("unknown LLC type name \"%s\"", $2);
- $$ = gen_llc_u_subtype(subtype);
+ bpf_error(cstate, "unknown LLC type name \"%s\"", $2);
+ $$ = gen_llc_u_subtype(cstate, subtype);
}
}
}
/* sigh, "rnr" is already a keyword for PF */
- | LLC PF_RNR { $$ = gen_llc_s_subtype(LLC_RNR); }
+ | LLC PF_RNR { $$ = gen_llc_s_subtype(cstate, LLC_RNR); }
;
dir: NUM
@@ -631,15 +648,15 @@ dir: NUM
else if (pcap_strcasecmp($1, "dstods") == 0)
$$ = IEEE80211_FC1_DIR_DSTODS;
else
- bpf_error("unknown 802.11 direction");
+ bpf_error(cstate, "unknown 802.11 direction");
}
;
reason: NUM { $$ = $1; }
- | ID { $$ = pfreason_to_num($1); }
+ | ID { $$ = pfreason_to_num(cstate, $1); }
;
-action: ID { $$ = pfaction_to_num($1); }
+action: ID { $$ = pfaction_to_num(cstate, $1); }
;
relop: '>' { $$ = BPF_JGT; }
@@ -650,24 +667,24 @@ irelop: LEQ { $$ = BPF_JGT; }
| '<' { $$ = BPF_JGE; }
| NEQ { $$ = BPF_JEQ; }
;
-arth: pnum { $$ = gen_loadi($1); }
+arth: pnum { $$ = gen_loadi(cstate, $1); }
| narth
;
-narth: pname '[' arth ']' { $$ = gen_load($1, $3, 1); }
- | pname '[' arth ':' NUM ']' { $$ = gen_load($1, $3, $5); }
- | arth '+' arth { $$ = gen_arth(BPF_ADD, $1, $3); }
- | arth '-' arth { $$ = gen_arth(BPF_SUB, $1, $3); }
- | arth '*' arth { $$ = gen_arth(BPF_MUL, $1, $3); }
- | arth '/' arth { $$ = gen_arth(BPF_DIV, $1, $3); }
- | arth '%' arth { $$ = gen_arth(BPF_MOD, $1, $3); }
- | arth '&' arth { $$ = gen_arth(BPF_AND, $1, $3); }
- | arth '|' arth { $$ = gen_arth(BPF_OR, $1, $3); }
- | arth '^' arth { $$ = gen_arth(BPF_XOR, $1, $3); }
- | arth LSH arth { $$ = gen_arth(BPF_LSH, $1, $3); }
- | arth RSH arth { $$ = gen_arth(BPF_RSH, $1, $3); }
- | '-' arth %prec UMINUS { $$ = gen_neg($2); }
+narth: pname '[' arth ']' { $$ = gen_load(cstate, $1, $3, 1); }
+ | pname '[' arth ':' NUM ']' { $$ = gen_load(cstate, $1, $3, $5); }
+ | arth '+' arth { $$ = gen_arth(cstate, BPF_ADD, $1, $3); }
+ | arth '-' arth { $$ = gen_arth(cstate, BPF_SUB, $1, $3); }
+ | arth '*' arth { $$ = gen_arth(cstate, BPF_MUL, $1, $3); }
+ | arth '/' arth { $$ = gen_arth(cstate, BPF_DIV, $1, $3); }
+ | arth '%' arth { $$ = gen_arth(cstate, BPF_MOD, $1, $3); }
+ | arth '&' arth { $$ = gen_arth(cstate, BPF_AND, $1, $3); }
+ | arth '|' arth { $$ = gen_arth(cstate, BPF_OR, $1, $3); }
+ | arth '^' arth { $$ = gen_arth(cstate, BPF_XOR, $1, $3); }
+ | arth LSH arth { $$ = gen_arth(cstate, BPF_LSH, $1, $3); }
+ | arth RSH arth { $$ = gen_arth(cstate, BPF_RSH, $1, $3); }
+ | '-' arth %prec UMINUS { $$ = gen_neg(cstate, $2); }
| paren narth ')' { $$ = $2; }
- | LEN { $$ = gen_loadlen(); }
+ | LEN { $$ = gen_loadlen(cstate); }
;
byteop: '&' { $$ = '&'; }
| '|' { $$ = '|'; }
@@ -696,15 +713,15 @@ atmfield: VPI { $$.atmfieldtype = A_VPI; }
| VCI { $$.atmfieldtype = A_VCI; }
;
atmvalue: atmfieldvalue
- | relop NUM { $$.b = gen_atmfield_code($<blk>0.atmfieldtype, (bpf_int32)$2, (bpf_u_int32)$1, 0); }
- | irelop NUM { $$.b = gen_atmfield_code($<blk>0.atmfieldtype, (bpf_int32)$2, (bpf_u_int32)$1, 1); }
+ | relop NUM { $$.b = gen_atmfield_code(cstate, $<blk>0.atmfieldtype, (bpf_int32)$2, (bpf_u_int32)$1, 0); }
+ | irelop NUM { $$.b = gen_atmfield_code(cstate, $<blk>0.atmfieldtype, (bpf_int32)$2, (bpf_u_int32)$1, 1); }
| paren atmlistvalue ')' { $$.b = $2.b; $$.q = qerr; }
;
atmfieldvalue: NUM {
$$.atmfieldtype = $<blk>0.atmfieldtype;
if ($$.atmfieldtype == A_VPI ||
$$.atmfieldtype == A_VCI)
- $$.b = gen_atmfield_code($$.atmfieldtype, (bpf_int32) $1, BPF_JEQ, 0);
+ $$.b = gen_atmfield_code(cstate, $$.atmfieldtype, (bpf_int32) $1, BPF_JEQ, 0);
}
;
atmlistvalue: atmfieldvalue
@@ -729,8 +746,8 @@ mtp3field: SIO { $$.mtp3fieldtype = M_SIO; }
| HSLS { $$.mtp3fieldtype = MH_SLS; }
;
mtp3value: mtp3fieldvalue
- | relop NUM { $$.b = gen_mtp3field_code($<blk>0.mtp3fieldtype, (u_int)$2, (u_int)$1, 0); }
- | irelop NUM { $$.b = gen_mtp3field_code($<blk>0.mtp3fieldtype, (u_int)$2, (u_int)$1, 1); }
+ | relop NUM { $$.b = gen_mtp3field_code(cstate, $<blk>0.mtp3fieldtype, (u_int)$2, (u_int)$1, 0); }
+ | irelop NUM { $$.b = gen_mtp3field_code(cstate, $<blk>0.mtp3fieldtype, (u_int)$2, (u_int)$1, 1); }
| paren mtp3listvalue ')' { $$.b = $2.b; $$.q = qerr; }
;
mtp3fieldvalue: NUM {
@@ -743,7 +760,7 @@ mtp3fieldvalue: NUM {
$$.mtp3fieldtype == MH_OPC ||
$$.mtp3fieldtype == MH_DPC ||
$$.mtp3fieldtype == MH_SLS)
- $$.b = gen_mtp3field_code($$.mtp3fieldtype, (u_int) $1, BPF_JEQ, 0);
+ $$.b = gen_mtp3field_code(cstate, $$.mtp3fieldtype, (u_int) $1, BPF_JEQ, 0);
}
;
mtp3listvalue: mtp3fieldvalue
diff --git a/contrib/libpcap/inet.c b/contrib/libpcap/inet.c
index 7e1a896fb0e7..a5d0f87bf879 100644
--- a/contrib/libpcap/inet.c
+++ b/contrib/libpcap/inet.c
@@ -36,9 +36,9 @@
#include "config.h"
#endif
-#ifdef WIN32
+#ifdef _WIN32
#include <pcap-stdinc.h>
-#else /* WIN32 */
+#else /* _WIN32 */
#include <sys/param.h>
#ifndef MSDOS
@@ -54,22 +54,16 @@ struct mbuf; /* Squelch compiler warnings on some platforms for */
struct rtentry; /* declarations in <net/if.h> */
#include <net/if.h>
#include <netinet/in.h>
-#endif /* WIN32 */
+#endif /* _WIN32 */
-#include <ctype.h>
#include <errno.h>
#include <memory.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
-#if !defined(WIN32) && !defined(__BORLANDC__)
+#if !defined(_WIN32) && !defined(__BORLANDC__)
#include <unistd.h>
-#endif /* !WIN32 && !__BORLANDC__ */
-#ifdef HAVE_LIMITS_H
-#include <limits.h>
-#else
-#define INT_MAX 2147483647
-#endif
+#endif /* !_WIN32 && !__BORLANDC__ */
#include "pcap-int.h"
@@ -77,739 +71,7 @@ struct rtentry; /* declarations in <net/if.h> */
#include "os-proto.h"
#endif
-/* Not all systems have IFF_LOOPBACK */
-#ifdef IFF_LOOPBACK
-#define ISLOOPBACK(name, flags) ((flags) & IFF_LOOPBACK)
-#else
-#define ISLOOPBACK(name, flags) ((name)[0] == 'l' && (name)[1] == 'o' && \
- (isdigit((unsigned char)((name)[2])) || (name)[2] == '\0'))
-#endif
-
-#ifdef IFF_UP
-#define ISUP(flags) ((flags) & IFF_UP)
-#else
-#define ISUP(flags) 0
-#endif
-
-#ifdef IFF_RUNNING
-#define ISRUNNING(flags) ((flags) & IFF_RUNNING)
-#else
-#define ISRUNNING(flags) 0
-#endif
-
-struct sockaddr *
-dup_sockaddr(struct sockaddr *sa, size_t sa_length)
-{
- struct sockaddr *newsa;
-
- if ((newsa = malloc(sa_length)) == NULL)
- return (NULL);
- return (memcpy(newsa, sa, sa_length));
-}
-
-/*
- * Construct a "figure of merit" for an interface, for use when sorting
- * the list of interfaces, in which interfaces that are up are superior
- * to interfaces that aren't up, interfaces that are up and running are
- * superior to interfaces that are up but not running, and non-loopback
- * interfaces that are up and running are superior to loopback interfaces,
- * and interfaces with the same flags have a figure of merit that's higher
- * the lower the instance number.
- *
- * The goal is to try to put the interfaces most likely to be useful for
- * capture at the beginning of the list.
- *
- * The figure of merit, which is lower the "better" the interface is,
- * has the uppermost bit set if the interface isn't running, the bit
- * below that set if the interface isn't up, the bit below that set
- * if the interface is a loopback interface, and the interface index
- * in the 29 bits below that. (Yes, we assume u_int is 32 bits.)
- */
-static u_int
-get_figure_of_merit(pcap_if_t *dev)
-{
- const char *cp;
- u_int n;
-
- if (strcmp(dev->name, "any") == 0) {
- /*
- * Give the "any" device an artificially high instance
- * number, so it shows up after all other non-loopback
- * interfaces.
- */
- n = 0x1FFFFFFF; /* 29 all-1 bits */
- } else {
- /*
- * A number at the end of the device name string is
- * assumed to be a unit number.
- */
- cp = dev->name + strlen(dev->name) - 1;
- while (cp-1 >= dev->name && *(cp-1) >= '0' && *(cp-1) <= '9')
- cp--;
- if (*cp >= '0' && *cp <= '9')
- n = atoi(cp);
- else
- n = 0;
- }
- if (!(dev->flags & PCAP_IF_RUNNING))
- n |= 0x80000000;
- if (!(dev->flags & PCAP_IF_UP))
- n |= 0x40000000;
- if (dev->flags & PCAP_IF_LOOPBACK)
- n |= 0x20000000;
- return (n);
-}
-
-/*
- * Look for a given device in the specified list of devices.
- *
- * If we find it, return 0 and set *curdev_ret to point to it.
- *
- * If we don't find it, check whether we can open it:
- *
- * If that fails with PCAP_ERROR_NO_SUCH_DEVICE or
- * PCAP_ERROR_IFACE_NOT_UP, don't attempt to add an entry for
- * it, as that probably means it exists but doesn't support
- * packet capture.
- *
- * Otherwise, attempt to add an entry for it, with the specified
- * ifnet flags and description, and, if that succeeds, return 0
- * and set *curdev_ret to point to the new entry, otherwise
- * return PCAP_ERROR and set errbuf to an error message.
- */
-int
-add_or_find_if(pcap_if_t **curdev_ret, pcap_if_t **alldevs, const char *name,
- u_int flags, const char *description, char *errbuf)
-{
- pcap_t *p;
- pcap_if_t *curdev, *prevdev, *nextdev;
- u_int this_figure_of_merit, nextdev_figure_of_merit;
- char open_errbuf[PCAP_ERRBUF_SIZE];
- int ret;
-
- /*
- * Is there already an entry in the list for this interface?
- */
- for (curdev = *alldevs; curdev != NULL; curdev = curdev->next) {
- if (strcmp(name, curdev->name) == 0)
- break; /* yes, we found it */
- }
-
- if (curdev == NULL) {
- /*
- * No, we didn't find it.
- *
- * Can we open this interface for live capture?
- *
- * We do this check so that interfaces that are
- * supplied by the interface enumeration mechanism
- * we're using but that don't support packet capture
- * aren't included in the list. Loopback interfaces
- * on Solaris are an example of this; we don't just
- * omit loopback interfaces on all platforms because
- * you *can* capture on loopback interfaces on some
- * OSes.
- *
- * On OS X, we don't do this check if the device
- * name begins with "wlt"; at least some versions
- * of OS X offer monitor mode capturing by having
- * a separate "monitor mode" device for each wireless
- * adapter, rather than by implementing the ioctls
- * that {Free,Net,Open,DragonFly}BSD provide.
- * Opening that device puts the adapter into monitor
- * mode, which, at least for some adapters, causes
- * them to deassociate from the network with which
- * they're associated.
- *
- * Instead, we try to open the corresponding "en"
- * device (so that we don't end up with, for users
- * without sufficient privilege to open capture
- * devices, a list of adapters that only includes
- * the wlt devices).
- */
-#ifdef __APPLE__
- if (strncmp(name, "wlt", 3) == 0) {
- char *en_name;
- size_t en_name_len;
-
- /*
- * Try to allocate a buffer for the "en"
- * device's name.
- */
- en_name_len = strlen(name) - 1;
- en_name = malloc(en_name_len + 1);
- if (en_name == NULL) {
- (void)snprintf(errbuf, PCAP_ERRBUF_SIZE,
- "malloc: %s", pcap_strerror(errno));
- return (-1);
- }
- strcpy(en_name, "en");
- strcat(en_name, name + 3);
- p = pcap_create(en_name, open_errbuf);
- free(en_name);
- } else
-#endif /* __APPLE */
- p = pcap_create(name, open_errbuf);
- if (p == NULL) {
- /*
- * The attempt to create the pcap_t failed;
- * that's probably an indication that we're
- * out of memory.
- *
- * Don't bother including this interface,
- * but don't treat it as an error.
- */
- *curdev_ret = NULL;
- return (0);
- }
- /* Small snaplen, so we don't try to allocate much memory. */
- pcap_set_snaplen(p, 68);
- ret = pcap_activate(p);
- pcap_close(p);
- switch (ret) {
-
- case PCAP_ERROR_NO_SUCH_DEVICE:
- case PCAP_ERROR_IFACE_NOT_UP:
- /*
- * We expect these two errors - they're the
- * reason we try to open the device.
- *
- * PCAP_ERROR_NO_SUCH_DEVICE typically means
- * "there's no such device *known to the
- * OS's capture mechanism*", so, even though
- * it might be a valid network interface, you
- * can't capture on it (e.g., the loopback
- * device in Solaris up to Solaris 10, or
- * the vmnet devices in OS X with VMware
- * Fusion). We don't include those devices
- * in our list of devices, as there's no
- * point in doing so - they're not available
- * for capture.
- *
- * PCAP_ERROR_IFACE_NOT_UP means that the
- * OS's capture mechanism doesn't work on
- * interfaces not marked as up; some capture
- * mechanisms *do* support that, so we no
- * longer reject those interfaces out of hand,
- * but we *do* want to reject them if they
- * can't be opened for capture.
- */
- *curdev_ret = NULL;
- return (0);
- }
-
- /*
- * Yes, we can open it, or we can't, for some other
- * reason.
- *
- * If we can open it, we want to offer it for
- * capture, as you can capture on it. If we can't,
- * we want to offer it for capture, so that, if
- * the user tries to capture on it, they'll get
- * an error and they'll know why they can't
- * capture on it (e.g., insufficient permissions)
- * or they'll report it as a problem (and then
- * have the error message to provide as information).
- *
- * Allocate a new entry.
- */
- curdev = malloc(sizeof(pcap_if_t));
- if (curdev == NULL) {
- (void)snprintf(errbuf, PCAP_ERRBUF_SIZE,
- "malloc: %s", pcap_strerror(errno));
- return (-1);
- }
-
- /*
- * Fill in the entry.
- */
- curdev->next = NULL;
- curdev->name = strdup(name);
- if (curdev->name == NULL) {
- (void)snprintf(errbuf, PCAP_ERRBUF_SIZE,
- "malloc: %s", pcap_strerror(errno));
- free(curdev);
- return (-1);
- }
- if (description != NULL) {
- /*
- * We have a description for this interface.
- */
- curdev->description = strdup(description);
- if (curdev->description == NULL) {
- (void)snprintf(errbuf, PCAP_ERRBUF_SIZE,
- "malloc: %s", pcap_strerror(errno));
- free(curdev->name);
- free(curdev);
- return (-1);
- }
- } else {
- /*
- * We don't.
- */
- curdev->description = NULL;
- }
- curdev->addresses = NULL; /* list starts out as empty */
- curdev->flags = 0;
- if (ISLOOPBACK(name, flags))
- curdev->flags |= PCAP_IF_LOOPBACK;
- if (ISUP(flags))
- curdev->flags |= PCAP_IF_UP;
- if (ISRUNNING(flags))
- curdev->flags |= PCAP_IF_RUNNING;
-
- /*
- * Add it to the list, in the appropriate location.
- * First, get the "figure of merit" for this
- * interface.
- */
- this_figure_of_merit = get_figure_of_merit(curdev);
-
- /*
- * Now look for the last interface with an figure of merit
- * less than or equal to the new interface's figure of
- * merit.
- *
- * We start with "prevdev" being NULL, meaning we're before
- * the first element in the list.
- */
- prevdev = NULL;
- for (;;) {
- /*
- * Get the interface after this one.
- */
- if (prevdev == NULL) {
- /*
- * The next element is the first element.
- */
- nextdev = *alldevs;
- } else
- nextdev = prevdev->next;
-
- /*
- * Are we at the end of the list?
- */
- if (nextdev == NULL) {
- /*
- * Yes - we have to put the new entry
- * after "prevdev".
- */
- break;
- }
-
- /*
- * Is the new interface's figure of merit less
- * than the next interface's figure of merit,
- * meaning that the new interface is better
- * than the next interface?
- */
- nextdev_figure_of_merit = get_figure_of_merit(nextdev);
- if (this_figure_of_merit < nextdev_figure_of_merit) {
- /*
- * Yes - we should put the new entry
- * before "nextdev", i.e. after "prevdev".
- */
- break;
- }
-
- prevdev = nextdev;
- }
-
- /*
- * Insert before "nextdev".
- */
- curdev->next = nextdev;
-
- /*
- * Insert after "prevdev" - unless "prevdev" is null,
- * in which case this is the first interface.
- */
- if (prevdev == NULL) {
- /*
- * This is the first interface. Pass back a
- * pointer to it, and put "curdev" before
- * "nextdev".
- */
- *alldevs = curdev;
- } else
- prevdev->next = curdev;
- }
-
- *curdev_ret = curdev;
- return (0);
-}
-
-/*
- * Try to get a description for a given device.
- * Returns a mallocated description if it could and NULL if it couldn't.
- *
- * XXX - on FreeBSDs that support it, should it get the sysctl named
- * "dev.{adapter family name}.{adapter unit}.%desc" to get a description
- * of the adapter? Note that "dev.an.0.%desc" is "Aironet PC4500/PC4800"
- * with my Cisco 350 card, so the name isn't entirely descriptive. The
- * "dev.an.0.%pnpinfo" has a better description, although one might argue
- * that the problem is really a driver bug - if it can find out that it's
- * a Cisco 340 or 350, rather than an old Aironet card, it should use
- * that in the description.
- *
- * Do NetBSD, DragonflyBSD, or OpenBSD support this as well? FreeBSD
- * and OpenBSD let you get a description, but it's not generated by the OS,
- * it's set with another ioctl that ifconfig supports; we use that to get
- * a description in FreeBSD and OpenBSD, but if there is no such
- * description available, it still might be nice to get some description
- * string based on the device type or something such as that.
- *
- * In OS X, the System Configuration framework can apparently return
- * names in 10.4 and later.
- *
- * It also appears that freedesktop.org's HAL offers an "info.product"
- * string, but the HAL specification says it "should not be used in any
- * UI" and "subsystem/capability specific properties" should be used
- * instead and, in any case, I think HAL is being deprecated in
- * favor of other stuff such as DeviceKit. DeviceKit doesn't appear
- * to have any obvious product information for devices, but maybe
- * I haven't looked hard enough.
- *
- * Using the System Configuration framework, or HAL, or DeviceKit, or
- * whatever, would require that libpcap applications be linked with
- * the frameworks/libraries in question. That shouldn't be a problem
- * for programs linking with the shared version of libpcap (unless
- * you're running on AIX - which I think is the only UN*X that doesn't
- * support linking a shared library with other libraries on which it
- * depends, and having an executable linked only with the first shared
- * library automatically pick up the other libraries when started -
- * and using HAL or whatever). Programs linked with the static
- * version of libpcap would have to use pcap-config with the --static
- * flag in order to get the right linker flags in order to pick up
- * the additional libraries/frameworks; those programs need that anyway
- * for libpcap 1.1 and beyond on Linux, as, by default, it requires
- * -lnl.
- *
- * Do any other UN*Xes, or desktop environments support getting a
- * description?
- */
-static char *
-get_if_description(const char *name)
-{
-#ifdef SIOCGIFDESCR
- char *description = NULL;
- int s;
- struct ifreq ifrdesc;
-#ifndef IFDESCRSIZE
- size_t descrlen = 64;
-#else
- size_t descrlen = IFDESCRSIZE;
-#endif /* IFDESCRSIZE */
-
- /*
- * Get the description for the interface.
- */
- memset(&ifrdesc, 0, sizeof ifrdesc);
- strlcpy(ifrdesc.ifr_name, name, sizeof ifrdesc.ifr_name);
- s = socket(AF_INET, SOCK_DGRAM, 0);
- if (s >= 0) {
-#ifdef __FreeBSD__
- /*
- * On FreeBSD, if the buffer isn't big enough for the
- * description, the ioctl succeeds, but the description
- * isn't copied, ifr_buffer.length is set to the description
- * length, and ifr_buffer.buffer is set to NULL.
- */
- for (;;) {
- free(description);
- if ((description = malloc(descrlen)) != NULL) {
- ifrdesc.ifr_buffer.buffer = description;
- ifrdesc.ifr_buffer.length = descrlen;
- if (ioctl(s, SIOCGIFDESCR, &ifrdesc) == 0) {
- if (ifrdesc.ifr_buffer.buffer ==
- description)
- break;
- else
- descrlen = ifrdesc.ifr_buffer.length;
- } else {
- /*
- * Failed to get interface description.
- */
- free(description);
- description = NULL;
- break;
- }
- } else
- break;
- }
-#else /* __FreeBSD__ */
- /*
- * The only other OS that currently supports
- * SIOCGIFDESCR is OpenBSD, and it has no way
- * to get the description length - it's clamped
- * to a maximum of IFDESCRSIZE.
- */
- if ((description = malloc(descrlen)) != NULL) {
- ifrdesc.ifr_data = (caddr_t)description;
- if (ioctl(s, SIOCGIFDESCR, &ifrdesc) != 0) {
- /*
- * Failed to get interface description.
- */
- free(description);
- description = NULL;
- }
- }
-#endif /* __FreeBSD__ */
- close(s);
- if (description != NULL && strlen(description) == 0) {
- free(description);
- description = NULL;
- }
- }
-
- return (description);
-#else /* SIOCGIFDESCR */
- return (NULL);
-#endif /* SIOCGIFDESCR */
-}
-
-/*
- * Try to get a description for a given device, and then look for that
- * device in the specified list of devices.
- *
- * If we find it, add the specified address to it and return 0.
- *
- * If we don't find it, check whether we can open it:
- *
- * If that fails with PCAP_ERROR_NO_SUCH_DEVICE or
- * PCAP_ERROR_IFACE_NOT_UP, don't attempt to add an entry for
- * it, as that probably means it exists but doesn't support
- * packet capture.
- *
- * Otherwise, attempt to add an entry for it, with the specified
- * ifnet flags and description, and, if that succeeds, add the
- * specified address to it, set *curdev_ret to point to the new
- * entry, and return 0, otherwise return PCAP_ERROR and set errbuf
- * to an error message.
- */
-int
-add_addr_to_iflist(pcap_if_t **alldevs, const char *name, u_int flags,
- struct sockaddr *addr, size_t addr_size,
- struct sockaddr *netmask, size_t netmask_size,
- struct sockaddr *broadaddr, size_t broadaddr_size,
- struct sockaddr *dstaddr, size_t dstaddr_size,
- char *errbuf)
-{
- char *description;
- pcap_if_t *curdev;
-
- description = get_if_description(name);
- if (add_or_find_if(&curdev, alldevs, name, flags, description,
- errbuf) == -1) {
- free(description);
- /*
- * Error - give up.
- */
- return (-1);
- }
- free(description);
- if (curdev == NULL) {
- /*
- * Device wasn't added because it can't be opened.
- * Not a fatal error.
- */
- return (0);
- }
-
- /*
- * "curdev" is an entry for this interface; add an entry for this
- * address to its list of addresses.
- *
- * Allocate the new entry and fill it in.
- */
- return (add_addr_to_dev(curdev, addr, addr_size, netmask, netmask_size,
- broadaddr, broadaddr_size, dstaddr, dstaddr_size, errbuf));
-}
-
-/*
- * Add an entry to the list of addresses for an interface.
- * "curdev" is the entry for that interface.
- * If this is the first IP address added to the interface, move it
- * in the list as appropriate.
- */
-int
-add_addr_to_dev(pcap_if_t *curdev,
- struct sockaddr *addr, size_t addr_size,
- struct sockaddr *netmask, size_t netmask_size,
- struct sockaddr *broadaddr, size_t broadaddr_size,
- struct sockaddr *dstaddr, size_t dstaddr_size,
- char *errbuf)
-{
- pcap_addr_t *curaddr, *prevaddr, *nextaddr;
-
- curaddr = malloc(sizeof(pcap_addr_t));
- if (curaddr == NULL) {
- (void)snprintf(errbuf, PCAP_ERRBUF_SIZE,
- "malloc: %s", pcap_strerror(errno));
- return (-1);
- }
-
- curaddr->next = NULL;
- if (addr != NULL) {
- curaddr->addr = dup_sockaddr(addr, addr_size);
- if (curaddr->addr == NULL) {
- (void)snprintf(errbuf, PCAP_ERRBUF_SIZE,
- "malloc: %s", pcap_strerror(errno));
- free(curaddr);
- return (-1);
- }
- } else
- curaddr->addr = NULL;
-
- if (netmask != NULL) {
- curaddr->netmask = dup_sockaddr(netmask, netmask_size);
- if (curaddr->netmask == NULL) {
- (void)snprintf(errbuf, PCAP_ERRBUF_SIZE,
- "malloc: %s", pcap_strerror(errno));
- if (curaddr->addr != NULL)
- free(curaddr->addr);
- free(curaddr);
- return (-1);
- }
- } else
- curaddr->netmask = NULL;
-
- if (broadaddr != NULL) {
- curaddr->broadaddr = dup_sockaddr(broadaddr, broadaddr_size);
- if (curaddr->broadaddr == NULL) {
- (void)snprintf(errbuf, PCAP_ERRBUF_SIZE,
- "malloc: %s", pcap_strerror(errno));
- if (curaddr->netmask != NULL)
- free(curaddr->netmask);
- if (curaddr->addr != NULL)
- free(curaddr->addr);
- free(curaddr);
- return (-1);
- }
- } else
- curaddr->broadaddr = NULL;
-
- if (dstaddr != NULL) {
- curaddr->dstaddr = dup_sockaddr(dstaddr, dstaddr_size);
- if (curaddr->dstaddr == NULL) {
- (void)snprintf(errbuf, PCAP_ERRBUF_SIZE,
- "malloc: %s", pcap_strerror(errno));
- if (curaddr->broadaddr != NULL)
- free(curaddr->broadaddr);
- if (curaddr->netmask != NULL)
- free(curaddr->netmask);
- if (curaddr->addr != NULL)
- free(curaddr->addr);
- free(curaddr);
- return (-1);
- }
- } else
- curaddr->dstaddr = NULL;
-
- /*
- * Find the end of the list of addresses.
- */
- for (prevaddr = curdev->addresses; prevaddr != NULL; prevaddr = nextaddr) {
- nextaddr = prevaddr->next;
- if (nextaddr == NULL) {
- /*
- * This is the end of the list.
- */
- break;
- }
- }
-
- if (prevaddr == NULL) {
- /*
- * The list was empty; this is the first member.
- */
- curdev->addresses = curaddr;
- } else {
- /*
- * "prevaddr" is the last member of the list; append
- * this member to it.
- */
- prevaddr->next = curaddr;
- }
-
- return (0);
-}
-
-/*
- * Look for a given device in the specified list of devices.
- *
- * If we find it, return 0.
- *
- * If we don't find it, check whether we can open it:
- *
- * If that fails with PCAP_ERROR_NO_SUCH_DEVICE or
- * PCAP_ERROR_IFACE_NOT_UP, don't attempt to add an entry for
- * it, as that probably means it exists but doesn't support
- * packet capture.
- *
- * Otherwise, attempt to add an entry for it, with the specified
- * ifnet flags and description, and, if that succeeds, return 0
- * and set *curdev_ret to point to the new entry, otherwise
- * return PCAP_ERROR and set errbuf to an error message.
- */
-int
-pcap_add_if(pcap_if_t **devlist, const char *name, u_int flags,
- const char *description, char *errbuf)
-{
- pcap_if_t *curdev;
-
- return (add_or_find_if(&curdev, devlist, name, flags, description,
- errbuf));
-}
-
-
-/*
- * Free a list of interfaces.
- */
-void
-pcap_freealldevs(pcap_if_t *alldevs)
-{
- pcap_if_t *curdev, *nextdev;
- pcap_addr_t *curaddr, *nextaddr;
-
- for (curdev = alldevs; curdev != NULL; curdev = nextdev) {
- nextdev = curdev->next;
-
- /*
- * Free all addresses.
- */
- for (curaddr = curdev->addresses; curaddr != NULL; curaddr = nextaddr) {
- nextaddr = curaddr->next;
- if (curaddr->addr)
- free(curaddr->addr);
- if (curaddr->netmask)
- free(curaddr->netmask);
- if (curaddr->broadaddr)
- free(curaddr->broadaddr);
- if (curaddr->dstaddr)
- free(curaddr->dstaddr);
- free(curaddr);
- }
-
- /*
- * Free the name string.
- */
- free(curdev->name);
-
- /*
- * Free the description string, if any.
- */
- if (curdev->description != NULL)
- free(curdev->description);
-
- /*
- * Free the interface.
- */
- free(curdev);
- }
-}
-
-#if !defined(WIN32) && !defined(MSDOS)
+#if !defined(_WIN32) && !defined(MSDOS)
/*
* Return the name of a network interface attached to the system, or NULL
@@ -900,7 +162,7 @@ pcap_lookupnet(device, netp, maskp, errbuf)
fd = socket(AF_INET, SOCK_DGRAM, 0);
if (fd < 0) {
- (void)snprintf(errbuf, PCAP_ERRBUF_SIZE, "socket: %s",
+ (void)pcap_snprintf(errbuf, PCAP_ERRBUF_SIZE, "socket: %s",
pcap_strerror(errno));
return (-1);
}
@@ -909,13 +171,13 @@ pcap_lookupnet(device, netp, maskp, errbuf)
/* XXX Work around Linux kernel bug */
ifr.ifr_addr.sa_family = AF_INET;
#endif
- (void)strncpy(ifr.ifr_name, device, sizeof(ifr.ifr_name));
+ (void)strlcpy(ifr.ifr_name, device, sizeof(ifr.ifr_name));
if (ioctl(fd, SIOCGIFADDR, (char *)&ifr) < 0) {
if (errno == EADDRNOTAVAIL) {
- (void)snprintf(errbuf, PCAP_ERRBUF_SIZE,
+ (void)pcap_snprintf(errbuf, PCAP_ERRBUF_SIZE,
"%s: no IPv4 address assigned", device);
} else {
- (void)snprintf(errbuf, PCAP_ERRBUF_SIZE,
+ (void)pcap_snprintf(errbuf, PCAP_ERRBUF_SIZE,
"SIOCGIFADDR: %s: %s",
device, pcap_strerror(errno));
}
@@ -929,9 +191,9 @@ pcap_lookupnet(device, netp, maskp, errbuf)
/* XXX Work around Linux kernel bug */
ifr.ifr_addr.sa_family = AF_INET;
#endif
- (void)strncpy(ifr.ifr_name, device, sizeof(ifr.ifr_name));
+ (void)strlcpy(ifr.ifr_name, device, sizeof(ifr.ifr_name));
if (ioctl(fd, SIOCGIFNETMASK, (char *)&ifr) < 0) {
- (void)snprintf(errbuf, PCAP_ERRBUF_SIZE,
+ (void)pcap_snprintf(errbuf, PCAP_ERRBUF_SIZE,
"SIOCGIFNETMASK: %s: %s", device, pcap_strerror(errno));
(void)close(fd);
return (-1);
@@ -946,7 +208,7 @@ pcap_lookupnet(device, netp, maskp, errbuf)
else if (IN_CLASSC(*netp))
*maskp = IN_CLASSC_NET;
else {
- (void)snprintf(errbuf, PCAP_ERRBUF_SIZE,
+ (void)pcap_snprintf(errbuf, PCAP_ERRBUF_SIZE,
"inet class for 0x%x unknown", *netp);
return (-1);
}
@@ -955,28 +217,38 @@ pcap_lookupnet(device, netp, maskp, errbuf)
return (0);
}
-#elif defined(WIN32)
+#elif defined(_WIN32)
/*
* Return the name of a network interface attached to the system, or NULL
* if none can be found. The interface must be configured up; the
* lowest unit number is preferred; loopback is ignored.
+ *
+ * In the best of all possible worlds, this would be the same as on
+ * UN*X, but there may be software that expects this to return a
+ * full list of devices after the first device.
*/
+#define ADAPTERSNAME_LEN 8192
char *
pcap_lookupdev(errbuf)
register char *errbuf;
{
DWORD dwVersion;
DWORD dwWindowsMajorVersion;
+ char our_errbuf[PCAP_ERRBUF_SIZE+1];
+
+#pragma warning (push)
+#pragma warning (disable: 4996) /* disable MSVC's GetVersion() deprecated warning here */
dwVersion = GetVersion(); /* get the OS version */
+#pragma warning (pop)
dwWindowsMajorVersion = (DWORD)(LOBYTE(LOWORD(dwVersion)));
if (dwVersion >= 0x80000000 && dwWindowsMajorVersion >= 4) {
/*
* Windows 95, 98, ME.
*/
- ULONG NameLength = 8192;
- static char AdaptersName[8192];
+ ULONG NameLength = ADAPTERSNAME_LEN;
+ static char AdaptersName[ADAPTERSNAME_LEN];
if (PacketGetAdapterNames(AdaptersName,&NameLength) )
return (AdaptersName);
@@ -984,60 +256,109 @@ pcap_lookupdev(errbuf)
return NULL;
} else {
/*
- * Windows NT (NT 4.0, W2K, WXP). Convert the names to UNICODE for backward compatibility
+ * Windows NT (NT 4.0 and later).
+ * Convert the names to Unicode for backward compatibility.
*/
- ULONG NameLength = 8192;
- static WCHAR AdaptersName[8192];
+ ULONG NameLength = ADAPTERSNAME_LEN;
+ static WCHAR AdaptersName[ADAPTERSNAME_LEN];
+ size_t BufferSpaceLeft;
char *tAstr;
- WCHAR *tUstr;
- WCHAR *TAdaptersName = (WCHAR*)malloc(8192 * sizeof(WCHAR));
+ WCHAR *Unameptr;
+ char *Adescptr;
+ size_t namelen, i;
+ WCHAR *TAdaptersName = (WCHAR*)malloc(ADAPTERSNAME_LEN * sizeof(WCHAR));
int NAdapts = 0;
if(TAdaptersName == NULL)
{
- (void)snprintf(errbuf, PCAP_ERRBUF_SIZE, "memory allocation failure");
+ (void)pcap_snprintf(errbuf, PCAP_ERRBUF_SIZE, "memory allocation failure");
return NULL;
}
if ( !PacketGetAdapterNames((PTSTR)TAdaptersName,&NameLength) )
{
- (void)snprintf(errbuf, PCAP_ERRBUF_SIZE,
- "PacketGetAdapterNames: %s",
- pcap_win32strerror());
+ pcap_win32_err_to_str(GetLastError(), our_errbuf);
+ (void)pcap_snprintf(errbuf, PCAP_ERRBUF_SIZE,
+ "PacketGetAdapterNames: %s", our_errbuf);
free(TAdaptersName);
return NULL;
}
+ BufferSpaceLeft = ADAPTERSNAME_LEN * sizeof(WCHAR);
tAstr = (char*)TAdaptersName;
- tUstr = (WCHAR*)AdaptersName;
+ Unameptr = AdaptersName;
/*
- * Convert and copy the device names
+ * Convert the device names to Unicode into AdapterName.
*/
- while(sscanf(tAstr, "%S", tUstr) > 0)
- {
- tAstr += strlen(tAstr) + 1;
- tUstr += wcslen(tUstr) + 1;
- NAdapts ++;
- }
+ do {
+ /*
+ * Length of the name, including the terminating
+ * NUL.
+ */
+ namelen = strlen(tAstr) + 1;
+
+ /*
+ * Do we have room for the name in the Unicode
+ * buffer?
+ */
+ if (BufferSpaceLeft < namelen * sizeof(WCHAR)) {
+ /*
+ * No.
+ */
+ goto quit;
+ }
+ BufferSpaceLeft -= namelen * sizeof(WCHAR);
+
+ /*
+ * Copy the name, converting ASCII to Unicode.
+ * namelen includes the NUL, so we copy it as
+ * well.
+ */
+ for (i = 0; i < namelen; i++)
+ *Unameptr++ = *tAstr++;
- tAstr++;
- *tUstr = 0;
- tUstr++;
+ /*
+ * Count this adapter.
+ */
+ NAdapts++;
+ } while (namelen != 1);
/*
- * Copy the descriptions
+ * Copy the descriptions, but don't convert them from
+ * ASCII to Unicode.
*/
+ Adescptr = (char *)Unameptr;
while(NAdapts--)
{
- char* tmp = (char*)tUstr;
- strcpy(tmp, tAstr);
- tmp += strlen(tAstr) + 1;
- tUstr = (WCHAR*)tmp;
- tAstr += strlen(tAstr) + 1;
+ size_t desclen;
+
+ desclen = strlen(tAstr) + 1;
+
+ /*
+ * Do we have room for the name in the Unicode
+ * buffer?
+ */
+ if (BufferSpaceLeft < desclen) {
+ /*
+ * No.
+ */
+ goto quit;
+ }
+
+ /*
+ * Just copy the ASCII string.
+ * namelen includes the NUL, so we copy it as
+ * well.
+ */
+ memcpy(Adescptr, tAstr, desclen);
+ Adescptr += desclen;
+ tAstr += desclen;
+ BufferSpaceLeft -= desclen;
}
+ quit:
free(TAdaptersName);
return (char *)(AdaptersName);
}
@@ -1083,4 +404,4 @@ pcap_lookupnet(device, netp, maskp, errbuf)
return (0);
}
-#endif /* !WIN32 && !MSDOS */
+#endif /* !_WIN32 && !MSDOS */
diff --git a/contrib/libpcap/install-sh b/contrib/libpcap/install-sh
index ebc66913e940..b44de0989d2f 100755
--- a/contrib/libpcap/install-sh
+++ b/contrib/libpcap/install-sh
@@ -115,7 +115,7 @@ fi
if [ x"$dir_arg" != x ]; then
dst=$src
src=""
-
+
if [ -d $dst ]; then
instcmd=:
else
@@ -124,7 +124,7 @@ if [ x"$dir_arg" != x ]; then
else
# Waiting for this to be detected by the "$instcmd $src $dsttmp" command
-# might cause directories to be created, which would be especially bad
+# might cause directories to be created, which would be especially bad
# if $src (and thus $dsttmp) contains '*'.
if [ -f $src -o -d $src ]
@@ -134,7 +134,7 @@ else
echo "install: $src does not exist"
exit 1
fi
-
+
if [ x"$dst" = x ]
then
echo "install: no destination specified"
@@ -201,17 +201,17 @@ else
# If we're going to rename the final executable, determine the name now.
- if [ x"$transformarg" = x ]
+ if [ x"$transformarg" = x ]
then
dstfile=`basename $dst`
else
- dstfile=`basename $dst $transformbasename |
+ dstfile=`basename $dst $transformbasename |
sed $transformarg`$transformbasename
fi
# don't allow the sed command to completely eliminate the filename
- if [ x"$dstfile" = x ]
+ if [ x"$dstfile" = x ]
then
dstfile=`basename $dst`
else
@@ -242,7 +242,7 @@ else
# Now rename the file to the real destination.
$doit $rmcmd -f $dstdir/$dstfile &&
- $doit $mvcmd $dsttmp $dstdir/$dstfile
+ $doit $mvcmd $dsttmp $dstdir/$dstfile
fi &&
diff --git a/contrib/libpcap/lbl/os-aix7.h b/contrib/libpcap/lbl/os-aix7.h
new file mode 100644
index 000000000000..93b12f2d267e
--- /dev/null
+++ b/contrib/libpcap/lbl/os-aix7.h
@@ -0,0 +1,23 @@
+/*
+ * Copyright (c) 1993, 1994, 1995, 1996, 1997
+ * The Regents of the University of California. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that: (1) source code distributions
+ * retain the above copyright notice and this paragraph in its entirety, (2)
+ * distributions including binary code include the above copyright notice and
+ * this paragraph in its entirety in the documentation or other materials
+ * provided with the distribution, and (3) all advertising materials mentioning
+ * features or use of this software display the following acknowledgement:
+ * ``This product includes software developed by the University of California,
+ * Lawrence Berkeley Laboratory and its contributors.'' Neither the name of
+ * the University nor the names of its contributors may be used to endorse
+ * or promote products derived from this software without specific prior
+ * written permission.
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+ */
+
+/* Prototypes missing in AIX 7.x */
+int ffs(int i);
diff --git a/contrib/libpcap/lbl/os-osf4.h b/contrib/libpcap/lbl/os-osf4.h
index 6b87bc055c29..055eb80ac623 100644
--- a/contrib/libpcap/lbl/os-osf4.h
+++ b/contrib/libpcap/lbl/os-osf4.h
@@ -20,7 +20,7 @@
*/
/* Prototypes missing in Digital UNIX 4.x */
-int snprintf(char *, size_t, const char *, ...);
-int vsnprintf(char *, size_t, const char *, va_list);
+int pcap_snprintf(char *, size_t, const char *, ...);
+int pcap_vsnprintf(char *, size_t, const char *, va_list);
int pfopen(char *, int);
-
+
diff --git a/contrib/libpcap/lbl/os-osf5.h b/contrib/libpcap/lbl/os-osf5.h
index 4c73c69f4a71..5422f18f18a1 100644
--- a/contrib/libpcap/lbl/os-osf5.h
+++ b/contrib/libpcap/lbl/os-osf5.h
@@ -21,10 +21,10 @@
/*
* Prototypes missing in Tru64 UNIX 5.x
- * XXX - "snprintf()" and "vsnprintf()" aren't missing, but you have to
+ * XXX - "pcap_snprintf()" and "pcap_vsnprintf()" aren't missing, but you have to
* #define the right value to get them defined by <stdio.h>.
*/
-int snprintf(char *, size_t, const char *, ...);
-int vsnprintf(char *, size_t, const char *, va_list);
+int pcap_snprintf(char *, size_t, const char *, ...);
+int pcap_vsnprintf(char *, size_t, const char *, va_list);
int pfopen(char *, int);
-
+
diff --git a/contrib/libpcap/lbl/os-solaris2.h b/contrib/libpcap/lbl/os-solaris2.h
index 22948b4a2695..a555f5ed3147 100644
--- a/contrib/libpcap/lbl/os-solaris2.h
+++ b/contrib/libpcap/lbl/os-solaris2.h
@@ -21,4 +21,4 @@
/* Prototypes missing in SunOS 5 */
char *strerror(int);
-int snprintf(char *, size_t, const char *, ...);
+int pcap_snprintf(char *, size_t, const char *, ...);
diff --git a/contrib/libpcap/lbl/os-sunos4.h b/contrib/libpcap/lbl/os-sunos4.h
index b73585706cd5..6353fb09cf6e 100644
--- a/contrib/libpcap/lbl/os-sunos4.h
+++ b/contrib/libpcap/lbl/os-sunos4.h
@@ -65,7 +65,6 @@ int fchmod(int, int);
int fchown(int, int, int);
void endgrent(void);
void endpwent(void);
-void endservent(void);
#ifdef __STDC__
struct ether_addr;
#endif
@@ -146,7 +145,6 @@ int select(int, fd_set *, fd_set *, fd_set *, struct timeval *);
int setpgrp(int, int);
void setpwent(void);
int setrlimit(int, struct rlimit *);
-void setservent(int);
int setsockopt(int, int, int, char *, int);
int shutdown(int, int);
int sigblock(int);
@@ -157,7 +155,7 @@ int sigsetmask(int);
struct sigvec;
#endif
int sigvec(int, struct sigvec *, struct sigvec*);
-int snprintf(char *, size_t, const char *, ...);
+int pcap_snprintf(char *, size_t, const char *, ...);
int socket(int, int, int);
int socketpair(int, int, int, int *);
int symlink(const char *, const char *);
diff --git a/contrib/libpcap/lbl/os-ultrix4.h b/contrib/libpcap/lbl/os-ultrix4.h
index fa1f770f8d44..21e570234bef 100644
--- a/contrib/libpcap/lbl/os-ultrix4.h
+++ b/contrib/libpcap/lbl/os-ultrix4.h
@@ -23,7 +23,6 @@
int bcmp(const char *, const char *, u_int);
void bcopy(const void *, void *, u_int);
void bzero(void *, u_int);
-void endservent(void);
int getopt(int, char * const *, const char *);
#ifdef __STDC__
struct timeval;
diff --git a/contrib/libpcap/missing/getopt.c b/contrib/libpcap/missing/getopt.c
new file mode 100644
index 000000000000..cc798e1de84d
--- /dev/null
+++ b/contrib/libpcap/missing/getopt.c
@@ -0,0 +1,126 @@
+/*
+ * Copyright (c) 1987, 1993, 1994
+ * The Regents of the University of California. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the University of
+ * California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#if defined(LIBC_SCCS) && !defined(lint)
+static char sccsid[] = "@(#)getopt.c 8.3 (Berkeley) 4/27/95";
+#endif /* LIBC_SCCS and not lint */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "getopt.h"
+
+int opterr = 1, /* if error message should be printed */
+ optind = 1, /* index into parent argv vector */
+ optopt, /* character checked for validity */
+ optreset; /* reset getopt */
+char *optarg; /* argument associated with option */
+
+#define BADCH (int)'?'
+#define BADARG (int)':'
+#define EMSG ""
+
+/*
+ * getopt --
+ * Parse argc/argv argument vector.
+ */
+int
+getopt(nargc, nargv, ostr)
+ int nargc;
+ char * const *nargv;
+ const char *ostr;
+{
+ char *cp;
+ static char *__progname;
+ static char *place = EMSG; /* option letter processing */
+ char *oli; /* option letter list index */
+
+ if (__progname == NULL) {
+ if ((cp = strrchr(nargv[0], '/')) != NULL)
+ __progname = cp + 1;
+ else
+ __progname = nargv[0];
+ }
+ if (optreset || !*place) { /* update scanning pointer */
+ optreset = 0;
+ if (optind >= nargc || *(place = nargv[optind]) != '-') {
+ place = EMSG;
+ return (-1);
+ }
+ if (place[1] && *++place == '-') { /* found "--" */
+ ++optind;
+ place = EMSG;
+ return (-1);
+ }
+ } /* option letter okay? */
+ if ((optopt = (int)*place++) == (int)':' ||
+ !(oli = strchr(ostr, optopt))) {
+ /*
+ * if the user didn't specify '-' as an option,
+ * assume it means -1.
+ */
+ if (optopt == (int)'-')
+ return (-1);
+ if (!*place)
+ ++optind;
+ if (opterr && *ostr != ':')
+ (void)fprintf(stderr,
+ "%s: illegal option -- %c\n", __progname, optopt);
+ return (BADCH);
+ }
+ if (*++oli != ':') { /* don't need argument */
+ optarg = NULL;
+ if (!*place)
+ ++optind;
+ }
+ else { /* need an argument */
+ if (*place) /* no white space */
+ optarg = place;
+ else if (nargc <= ++optind) { /* no arg */
+ place = EMSG;
+ if (*ostr == ':')
+ return (BADARG);
+ if (opterr)
+ (void)fprintf(stderr,
+ "%s: option requires an argument -- %c\n",
+ __progname, optopt);
+ return (BADCH);
+ }
+ else /* white space */
+ optarg = nargv[optind];
+ place = EMSG;
+ ++optind;
+ }
+ return (optopt); /* dump back option letter */
+}
diff --git a/contrib/libpcap/missing/getopt.h b/contrib/libpcap/missing/getopt.h
new file mode 100644
index 000000000000..d176345ae20b
--- /dev/null
+++ b/contrib/libpcap/missing/getopt.h
@@ -0,0 +1,7 @@
+/*
+ * Header for the getopt() we supply if the platform doesn't supply it.
+ */
+extern char *optarg; /* getopt(3) external variables */
+extern int optind, opterr, optopt;
+
+extern int getopt(int nargc, char * const *nargv, const char *ostr);
diff --git a/contrib/libpcap/missing/snprintf.c b/contrib/libpcap/missing/snprintf.c
index 9b63f8b1dcd0..99f0bdfc2a93 100644
--- a/contrib/libpcap/missing/snprintf.c
+++ b/contrib/libpcap/missing/snprintf.c
@@ -456,13 +456,13 @@ xyzprintf (struct state *state, const char *char_format, va_list ap)
#ifndef HAVE_SNPRINTF
int
-snprintf (char *str, size_t sz, const char *format, ...)
+pcap_snprintf (char *str, size_t sz, const char *format, ...)
{
va_list args;
int ret;
va_start(args, format);
- ret = vsnprintf (str, sz, format, args);
+ ret = pcap_vsnprintf (str, sz, format, args);
#ifdef PARANOIA
{
@@ -473,7 +473,7 @@ snprintf (char *str, size_t sz, const char *format, ...)
if (tmp == NULL)
abort ();
- ret2 = vsprintf (tmp, format, args);
+ ret2 = pcap_vsprintf (tmp, format, args);
if (ret != ret2 || strcmp(str, tmp))
abort ();
free (tmp);
@@ -518,13 +518,13 @@ asprintf (char **ret, const char *format, ...)
#ifndef HAVE_ASNPRINTF
int
-asnprintf (char **ret, size_t max_sz, const char *format, ...)
+pcap_asnprintf (char **ret, size_t max_sz, const char *format, ...)
{
va_list args;
int val;
va_start(args, format);
- val = vasnprintf (ret, max_sz, format, args);
+ val = pcap_vasnprintf (ret, max_sz, format, args);
#ifdef PARANOIA
{
@@ -534,7 +534,7 @@ asnprintf (char **ret, size_t max_sz, const char *format, ...)
if (tmp == NULL)
abort ();
- ret2 = vsprintf (tmp, format, args);
+ ret2 = pcap_vsprintf (tmp, format, args);
if (val != ret2 || strcmp(*ret, tmp))
abort ();
free (tmp);
@@ -548,16 +548,16 @@ asnprintf (char **ret, size_t max_sz, const char *format, ...)
#ifndef HAVE_VASPRINTF
int
-vasprintf (char **ret, const char *format, va_list args)
+pcap_vasprintf (char **ret, const char *format, va_list args)
{
- return vasnprintf (ret, 0, format, args);
+ return pcap_vasnprintf (ret, 0, format, args);
}
#endif
#ifndef HAVE_VASNPRINTF
int
-vasnprintf (char **ret, size_t max_sz, const char *format, va_list args)
+pcap_vasnprintf (char **ret, size_t max_sz, const char *format, va_list args)
{
int st;
size_t len;
@@ -600,7 +600,7 @@ vasnprintf (char **ret, size_t max_sz, const char *format, va_list args)
#ifndef HAVE_VSNPRINTF
int
-vsnprintf (char *str, size_t sz, const char *format, va_list args)
+pcap_vsnprintf (char *str, size_t sz, const char *format, va_list args)
{
struct state state;
int ret;
diff --git a/contrib/libpcap/missing/strtok_r.c b/contrib/libpcap/missing/strtok_r.c
new file mode 100644
index 000000000000..c9c94b95d832
--- /dev/null
+++ b/contrib/libpcap/missing/strtok_r.c
@@ -0,0 +1,87 @@
+/*-
+ * Copyright (c) 1998 Softweyr LLC. All rights reserved.
+ *
+ * strtok_r, from Berkeley strtok
+ * Oct 13, 1998 by Wes Peters <wes@softweyr.com>
+ *
+ * Copyright (c) 1988, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notices, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notices, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY SOFTWEYR LLC, THE REGENTS AND CONTRIBUTORS
+ * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
+ * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL SOFTWEYR LLC, THE
+ * REGENTS, OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+ * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+ * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * From: @(#)strtok.c 8.1 (Berkeley) 6/4/93
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include "portability.h"
+
+char *
+pcap_strtok_r(char *s, const char *delim, char **last)
+{
+ char *spanp, *tok;
+ int c, sc;
+
+ if (s == NULL && (s = *last) == NULL)
+ return (NULL);
+
+ /*
+ * Skip (span) leading delimiters (s += strspn(s, delim), sort of).
+ */
+cont:
+ c = *s++;
+ for (spanp = (char *)delim; (sc = *spanp++) != 0;) {
+ if (c == sc)
+ goto cont;
+ }
+
+ if (c == 0) { /* no non-delimiter characters */
+ *last = NULL;
+ return (NULL);
+ }
+ tok = s - 1;
+
+ /*
+ * Scan token (scan for delimiters: s += strcspn(s, delim), sort of).
+ * Note that delim must have one NUL; we stop if we see that, too.
+ */
+ for (;;) {
+ c = *s++;
+ spanp = (char *)delim;
+ do {
+ if ((sc = *spanp++) == c) {
+ if (c == 0)
+ s = NULL;
+ else
+ s[-1] = '\0';
+ *last = s;
+ return (tok);
+ }
+ } while (sc != 0);
+ }
+ /* NOTREACHED */
+}
diff --git a/contrib/libpcap/missing/win_snprintf.c b/contrib/libpcap/missing/win_snprintf.c
new file mode 100644
index 000000000000..65a8ea1a5cd9
--- /dev/null
+++ b/contrib/libpcap/missing/win_snprintf.c
@@ -0,0 +1,31 @@
+#include <stdio.h>
+#include <stdarg.h>
+
+int
+pcap_vsnprintf(char *str, size_t str_size, const char *format, va_list args)
+{
+ int ret;
+
+ ret = _vsnprintf_s(str, str_size, _TRUNCATE, format, args);
+
+ /*
+ * XXX - _vsnprintf() and _snprintf() do *not* guarantee
+ * that str is null-terminated, but C99's vsnprintf()
+ * and snprintf() do, and we want to offer C99 behavior,
+ * so forcibly null-terminate the string.
+ */
+ str[str_size - 1] = '\0';
+ return (ret);
+}
+
+int
+pcap_snprintf(char *str, size_t str_size, const char *format, ...)
+{
+ va_list args;
+ int ret;
+
+ va_start(args, format);
+ ret = pcap_vsnprintf(str, str_size, format, args);
+ va_end(args);
+ return (ret);
+}
diff --git a/contrib/libpcap/mkdep b/contrib/libpcap/mkdep
index bfe4a2614a4f..1486b185aa43 100755
--- a/contrib/libpcap/mkdep
+++ b/contrib/libpcap/mkdep
@@ -13,9 +13,6 @@
# @(#)mkdep.sh 5.11 (Berkeley) 5/5/88
#
-PATH=/bin:/usr/bin:/usr/ucb:/usr/local:/usr/local/bin:/usr/sfw/bin
-export PATH
-
MAKE=Makefile # default makefile name is "Makefile"
CC=cc # default C compiler is "cc"
DEPENDENCY_CFLAG=-M # default dependency-generation flag is -M
diff --git a/contrib/libpcap/nametoaddr.c b/contrib/libpcap/nametoaddr.c
index b91869384dc3..49d23d85521e 100644
--- a/contrib/libpcap/nametoaddr.c
+++ b/contrib/libpcap/nametoaddr.c
@@ -33,10 +33,36 @@
#include <netdnet/dnetdb.h>
#endif
-#ifdef WIN32
+#ifdef _WIN32
#include <pcap-stdinc.h>
-#else /* WIN32 */
+#ifdef INET6
+/*
+ * To quote the MSDN page for getaddrinfo() at
+ *
+ * https://msdn.microsoft.com/en-us/library/windows/desktop/ms738520(v=vs.85).aspx
+ *
+ * "Support for getaddrinfo on Windows 2000 and older versions
+ * The getaddrinfo function was added to the Ws2_32.dll on Windows XP and
+ * later. To execute an application that uses this function on earlier
+ * versions of Windows, then you need to include the Ws2tcpip.h and
+ * Wspiapi.h files. When the Wspiapi.h include file is added, the
+ * getaddrinfo function is defined to the WspiapiGetAddrInfo inline
+ * function in the Wspiapi.h file. At runtime, the WspiapiGetAddrInfo
+ * function is implemented in such a way that if the Ws2_32.dll or the
+ * Wship6.dll (the file containing getaddrinfo in the IPv6 Technology
+ * Preview for Windows 2000) does not include getaddrinfo, then a
+ * version of getaddrinfo is implemented inline based on code in the
+ * Wspiapi.h header file. This inline code will be used on older Windows
+ * platforms that do not natively support the getaddrinfo function."
+ *
+ * We use getaddrinfo(), so we include Wspiapi.h here. pcap-stdinc.h
+ * includes Ws2tcpip.h, so we don't need to include it ourselves.
+ */
+#include <Wspiapi.h>
+#endif
+
+#else /* _WIN32 */
#include <sys/param.h>
#include <sys/types.h> /* concession to AIX */
@@ -44,9 +70,9 @@
#include <sys/time.h>
#include <netinet/in.h>
-#endif /* WIN32 */
+#endif /* _WIN32 */
-#ifndef WIN32
+#ifndef _WIN32
#ifdef HAVE_ETHER_HOSTTON
/*
* XXX - do we need any of this if <netinet/if_ether.h> doesn't declare
@@ -64,7 +90,7 @@ struct rtentry; /* declarations in <net/if.h> */
#endif /* HAVE_ETHER_HOSTTON */
#include <arpa/inet.h>
#include <netdb.h>
-#endif /* WIN32 */
+#endif /* _WIN32 */
#include <ctype.h>
#include <errno.h>
@@ -76,6 +102,7 @@ struct rtentry; /* declarations in <net/if.h> */
#include "gencode.h"
#include <pcap/namedb.h>
+#include "nametoaddr.h"
#ifdef HAVE_OS_PROTO_H
#include "os-proto.h"
@@ -142,7 +169,7 @@ pcap_nametoaddrinfo(const char *name)
bpf_u_int32
pcap_nametonetaddr(const char *name)
{
-#ifndef WIN32
+#ifndef _WIN32
struct netent *np;
if ((np = getnetbyname(name)) != NULL)
@@ -152,6 +179,15 @@ pcap_nametonetaddr(const char *name)
#else
/*
* There's no "getnetbyname()" on Windows.
+ *
+ * XXX - I guess we could use the BSD code to read
+ * C:\Windows\System32\drivers\etc/networks, assuming
+ * that's its home on all the versions of Windows
+ * we use, but that file probably just has the loopback
+ * network on 127/24 on 99 44/100% of Windows machines.
+ *
+ * (Heck, these days it probably just has that on 99 44/100%
+ * of *UN*X* machines.)
*/
return 0;
#endif
@@ -276,8 +312,14 @@ struct eproto {
u_short p;
};
-/* Static data base of ether protocol types. */
-struct eproto eproto_db[] = {
+/*
+ * Static data base of ether protocol types.
+ * tcpdump used to import this, and it's declared as an export on
+ * Debian, at least, so make it a public symbol, even though we
+ * don't officially export it by declaring it in a header file.
+ * (Programs *should* do this themselves, as tcpdump now does.)
+ */
+PCAP_API_DEF struct eproto eproto_db[] = {
#if 0
/* The FreeBSD elf linker generates a request to copy this array
* (including its size) when you link with -lpcap. In order to
@@ -394,7 +436,7 @@ __pcap_atodn(const char *s, bpf_u_int32 *addr)
u_int node, area;
if (sscanf(s, "%d.%d", &area, &node) != 2)
- bpf_error("malformed decnet address '%s'", s);
+ return(0);
*addr = (area << AREASHIFT) & AREAMASK;
*addr |= (node & NODEMASK);
@@ -498,23 +540,20 @@ pcap_ether_hostton(const char *name)
}
#endif
-u_short
-__pcap_nametodnaddr(const char *name)
+int
+__pcap_nametodnaddr(const char *name, u_short *res)
{
#ifdef DECNETLIB
struct nodeent *getnodebyname();
struct nodeent *nep;
- unsigned short res;
nep = getnodebyname(name);
if (nep == ((struct nodeent *)0))
- bpf_error("unknown decnet host name '%s'\n", name);
+ return(0);
- memcpy((char *)&res, (char *)nep->n_addr, sizeof(unsigned short));
- return(res);
+ memcpy((char *)res, (char *)nep->n_addr, sizeof(unsigned short));
+ return(1);
#else
- bpf_error("decnet name support not included, '%s' cannot be translated\n",
- name);
return(0);
#endif
}
diff --git a/contrib/libpcap/nametoaddr.h b/contrib/libpcap/nametoaddr.h
new file mode 100644
index 000000000000..fd6b7e101640
--- /dev/null
+++ b/contrib/libpcap/nametoaddr.h
@@ -0,0 +1,48 @@
+/*
+ * Copyright (c) 1994, 1996
+ * The Regents of the University of California. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the Computer Systems
+ * Engineering Group at Lawrence Berkeley Laboratory.
+ * 4. Neither the name of the University nor of the Laboratory may be used
+ * to endorse or promote products derived from this software without
+ * specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/*
+ * Routines used for name-or-address-string-to-address resolution
+ * that are *not* exported to code using libpcap.
+ */
+int __pcap_atodn(const char *, bpf_u_int32 *);
+int __pcap_atoin(const char *, bpf_u_int32 *);
+int __pcap_nametodnaddr(const char *, u_short *);
+
+#ifdef __cplusplus
+}
+#endif
diff --git a/contrib/libpcap/optimize.c b/contrib/libpcap/optimize.c
index feaf2017213a..19980dc81d9f 100644
--- a/contrib/libpcap/optimize.c
+++ b/contrib/libpcap/optimize.c
@@ -25,9 +25,9 @@
#include "config.h"
#endif
-#ifdef WIN32
+#ifdef _WIN32
#include <pcap-stdinc.h>
-#else /* WIN32 */
+#else /* _WIN32 */
#if HAVE_INTTYPES_H
#include <inttypes.h>
#elif HAVE_STDINT_H
@@ -37,7 +37,7 @@
#include <sys/bitypes.h>
#endif
#include <sys/types.h>
-#endif /* WIN32 */
+#endif /* _WIN32 */
#include <stdio.h>
#include <stdlib.h>
@@ -55,7 +55,7 @@
#endif
#ifdef BDEBUG
-extern int dflag;
+int pcap_optimizer_debug;
#endif
#if defined(MSDOS) && !defined(__DJGPP__)
@@ -63,8 +63,26 @@ extern int _w32_ffs (int mask);
#define ffs _w32_ffs
#endif
-#if defined(WIN32) && defined (_MSC_VER)
-int ffs(int mask);
+/*
+ * So is the check for _MSC_VER done because MinGW has this?
+ */
+#if defined(_WIN32) && defined (_MSC_VER)
+/*
+ * ffs -- vax ffs instruction
+ *
+ * XXX - with versions of VS that have it, use _BitScanForward()?
+ */
+static int
+ffs(int mask)
+{
+ int bit;
+
+ if (mask == 0)
+ return(0);
+ for (bit = 1; !(mask & 1); bit++)
+ mask >>= 1;
+ return(bit);
+}
#endif
/*
@@ -89,45 +107,48 @@ int ffs(int mask);
#define AX_ATOM N_ATOMS
/*
- * A flag to indicate that further optimization is needed.
- * Iterative passes are continued until a given pass yields no
- * branch movement.
+ * These data structures are used in a Cocke and Shwarz style
+ * value numbering scheme. Since the flowgraph is acyclic,
+ * exit values can be propagated from a node's predecessors
+ * provided it is uniquely defined.
*/
-static int done;
+struct valnode {
+ int code;
+ int v0, v1;
+ int val;
+ struct valnode *next;
+};
-/*
- * A block is marked if only if its mark equals the current mark.
- * Rather than traverse the code array, marking each item, 'cur_mark' is
- * incremented. This automatically makes each element unmarked.
- */
-static int cur_mark;
-#define isMarked(p) ((p)->mark == cur_mark)
-#define unMarkAll() cur_mark += 1
-#define Mark(p) ((p)->mark = cur_mark)
+/* Integer constants mapped with the load immediate opcode. */
+#define K(i) F(opt_state, BPF_LD|BPF_IMM|BPF_W, i, 0L)
-static void opt_init(struct block *);
-static void opt_cleanup(void);
+struct vmapinfo {
+ int is_const;
+ bpf_int32 const_val;
+};
-static void intern_blocks(struct block *);
+struct _opt_state {
+ /*
+ * A flag to indicate that further optimization is needed.
+ * Iterative passes are continued until a given pass yields no
+ * branch movement.
+ */
+ int done;
-static void find_inedges(struct block *);
-#ifdef BDEBUG
-static void opt_dump(struct block *);
-#endif
+ int n_blocks;
+ struct block **blocks;
+ int n_edges;
+ struct edge **edges;
-static int n_blocks;
-struct block **blocks;
-static int n_edges;
-struct edge **edges;
+ /*
+ * A bit vector set representation of the dominators.
+ * We round up the set size to the next power of two.
+ */
+ int nodewords;
+ int edgewords;
+ struct block **levels;
+ bpf_u_int32 *space;
-/*
- * A bit vector set representation of the dominators.
- * We round up the set size to the next power of two.
- */
-static int nodewords;
-static int edgewords;
-struct block **levels;
-bpf_u_int32 *space;
#define BITS_PER_WORD (8*sizeof(bpf_u_int32))
/*
* True if a is in uset {p}
@@ -177,48 +198,79 @@ bpf_u_int32 *space;
while (--_n >= 0) *_x++ |= *_y++;\
}
-static uset all_dom_sets;
-static uset all_closure_sets;
-static uset all_edge_sets;
+ uset all_dom_sets;
+ uset all_closure_sets;
+ uset all_edge_sets;
+
+#define MODULUS 213
+ struct valnode *hashtbl[MODULUS];
+ int curval;
+ int maxval;
+
+ struct vmapinfo *vmap;
+ struct valnode *vnode_base;
+ struct valnode *next_vnode;
+};
+
+typedef struct {
+ /*
+ * Some pointers used to convert the basic block form of the code,
+ * into the array form that BPF requires. 'fstart' will point to
+ * the malloc'd array while 'ftail' is used during the recursive
+ * traversal.
+ */
+ struct bpf_insn *fstart;
+ struct bpf_insn *ftail;
+} conv_state_t;
+
+static void opt_init(compiler_state_t *, opt_state_t *, struct icode *);
+static void opt_cleanup(opt_state_t *);
+
+static void intern_blocks(opt_state_t *, struct icode *);
+
+static void find_inedges(opt_state_t *, struct block *);
+#ifdef BDEBUG
+static void opt_dump(compiler_state_t *, struct icode *);
+#endif
#ifndef MAX
#define MAX(a,b) ((a)>(b)?(a):(b))
#endif
static void
-find_levels_r(struct block *b)
+find_levels_r(opt_state_t *opt_state, struct icode *ic, struct block *b)
{
int level;
- if (isMarked(b))
+ if (isMarked(ic, b))
return;
- Mark(b);
+ Mark(ic, b);
b->link = 0;
if (JT(b)) {
- find_levels_r(JT(b));
- find_levels_r(JF(b));
+ find_levels_r(opt_state, ic, JT(b));
+ find_levels_r(opt_state, ic, JF(b));
level = MAX(JT(b)->level, JF(b)->level) + 1;
} else
level = 0;
b->level = level;
- b->link = levels[level];
- levels[level] = b;
+ b->link = opt_state->levels[level];
+ opt_state->levels[level] = b;
}
/*
* Level graph. The levels go from 0 at the leaves to
- * N_LEVELS at the root. The levels[] array points to the
+ * N_LEVELS at the root. The opt_state->levels[] array points to the
* first node of the level list, whose elements are linked
* with the 'link' field of the struct block.
*/
static void
-find_levels(struct block *root)
+find_levels(opt_state_t *opt_state, struct icode *ic)
{
- memset((char *)levels, 0, n_blocks * sizeof(*levels));
- unMarkAll();
- find_levels_r(root);
+ memset((char *)opt_state->levels, 0, opt_state->n_blocks * sizeof(*opt_state->levels));
+ unMarkAll(ic);
+ find_levels_r(opt_state, ic, ic->root);
}
/*
@@ -226,7 +278,7 @@ find_levels(struct block *root)
* Assumes graph has been leveled.
*/
static void
-find_dom(struct block *root)
+find_dom(opt_state_t *opt_state, struct block *root)
{
int i;
struct block *b;
@@ -235,33 +287,33 @@ find_dom(struct block *root)
/*
* Initialize sets to contain all nodes.
*/
- x = all_dom_sets;
- i = n_blocks * nodewords;
+ x = opt_state->all_dom_sets;
+ i = opt_state->n_blocks * opt_state->nodewords;
while (--i >= 0)
*x++ = ~0;
/* Root starts off empty. */
- for (i = nodewords; --i >= 0;)
+ for (i = opt_state->nodewords; --i >= 0;)
root->dom[i] = 0;
/* root->level is the highest level no found. */
for (i = root->level; i >= 0; --i) {
- for (b = levels[i]; b; b = b->link) {
+ for (b = opt_state->levels[i]; b; b = b->link) {
SET_INSERT(b->dom, b->id);
if (JT(b) == 0)
continue;
- SET_INTERSECT(JT(b)->dom, b->dom, nodewords);
- SET_INTERSECT(JF(b)->dom, b->dom, nodewords);
+ SET_INTERSECT(JT(b)->dom, b->dom, opt_state->nodewords);
+ SET_INTERSECT(JF(b)->dom, b->dom, opt_state->nodewords);
}
}
}
static void
-propedom(struct edge *ep)
+propedom(opt_state_t *opt_state, struct edge *ep)
{
SET_INSERT(ep->edom, ep->id);
if (ep->succ) {
- SET_INTERSECT(ep->succ->et.edom, ep->edom, edgewords);
- SET_INTERSECT(ep->succ->ef.edom, ep->edom, edgewords);
+ SET_INTERSECT(ep->succ->et.edom, ep->edom, opt_state->edgewords);
+ SET_INTERSECT(ep->succ->ef.edom, ep->edom, opt_state->edgewords);
}
}
@@ -270,23 +322,23 @@ propedom(struct edge *ep)
* Assumes graph has been leveled and predecessors established.
*/
static void
-find_edom(struct block *root)
+find_edom(opt_state_t *opt_state, struct block *root)
{
int i;
uset x;
struct block *b;
- x = all_edge_sets;
- for (i = n_edges * edgewords; --i >= 0; )
+ x = opt_state->all_edge_sets;
+ for (i = opt_state->n_edges * opt_state->edgewords; --i >= 0; )
x[i] = ~0;
/* root->level is the highest level no found. */
- memset(root->et.edom, 0, edgewords * sizeof(*(uset)0));
- memset(root->ef.edom, 0, edgewords * sizeof(*(uset)0));
+ memset(root->et.edom, 0, opt_state->edgewords * sizeof(*(uset)0));
+ memset(root->ef.edom, 0, opt_state->edgewords * sizeof(*(uset)0));
for (i = root->level; i >= 0; --i) {
- for (b = levels[i]; b != 0; b = b->link) {
- propedom(&b->et);
- propedom(&b->ef);
+ for (b = opt_state->levels[i]; b != 0; b = b->link) {
+ propedom(opt_state, &b->et);
+ propedom(opt_state, &b->ef);
}
}
}
@@ -299,7 +351,7 @@ find_edom(struct block *root)
* Assumes graph has been leveled.
*/
static void
-find_closure(struct block *root)
+find_closure(opt_state_t *opt_state, struct block *root)
{
int i;
struct block *b;
@@ -307,17 +359,17 @@ find_closure(struct block *root)
/*
* Initialize sets to contain no nodes.
*/
- memset((char *)all_closure_sets, 0,
- n_blocks * nodewords * sizeof(*all_closure_sets));
+ memset((char *)opt_state->all_closure_sets, 0,
+ opt_state->n_blocks * opt_state->nodewords * sizeof(*opt_state->all_closure_sets));
/* root->level is the highest level no found. */
for (i = root->level; i >= 0; --i) {
- for (b = levels[i]; b; b = b->link) {
+ for (b = opt_state->levels[i]; b; b = b->link) {
SET_INSERT(b->closure, b->id);
if (JT(b) == 0)
continue;
- SET_UNION(JT(b)->closure, b->closure, nodewords);
- SET_UNION(JF(b)->closure, b->closure, nodewords);
+ SET_UNION(JT(b)->closure, b->closure, opt_state->nodewords);
+ SET_UNION(JF(b)->closure, b->closure, opt_state->nodewords);
}
}
}
@@ -413,7 +465,7 @@ static void
compute_local_ud(struct block *b)
{
struct slist *s;
- atomset def = 0, use = 0, kill = 0;
+ atomset def = 0, use = 0, killed = 0;
int atom;
for (s = b->stmts; s; s = s->next) {
@@ -437,7 +489,7 @@ compute_local_ud(struct block *b)
atom = atomdef(&s->s);
if (atom >= 0) {
if (!ATOMELEM(use, atom))
- kill |= ATOMMASK(atom);
+ killed |= ATOMMASK(atom);
def |= ATOMMASK(atom);
}
}
@@ -463,7 +515,7 @@ compute_local_ud(struct block *b)
}
b->def = def;
- b->kill = kill;
+ b->kill = killed;
b->in_use = use;
}
@@ -471,7 +523,7 @@ compute_local_ud(struct block *b)
* Assume graph is already leveled.
*/
static void
-find_ud(struct block *root)
+find_ud(opt_state_t *opt_state, struct block *root)
{
int i, maxlevel;
struct block *p;
@@ -482,61 +534,30 @@ find_ud(struct block *root)
*/
maxlevel = root->level;
for (i = maxlevel; i >= 0; --i)
- for (p = levels[i]; p; p = p->link) {
+ for (p = opt_state->levels[i]; p; p = p->link) {
compute_local_ud(p);
p->out_use = 0;
}
for (i = 1; i <= maxlevel; ++i) {
- for (p = levels[i]; p; p = p->link) {
+ for (p = opt_state->levels[i]; p; p = p->link) {
p->out_use |= JT(p)->in_use | JF(p)->in_use;
p->in_use |= p->out_use &~ p->kill;
}
}
}
-
-/*
- * These data structures are used in a Cocke and Shwarz style
- * value numbering scheme. Since the flowgraph is acyclic,
- * exit values can be propagated from a node's predecessors
- * provided it is uniquely defined.
- */
-struct valnode {
- int code;
- int v0, v1;
- int val;
- struct valnode *next;
-};
-
-#define MODULUS 213
-static struct valnode *hashtbl[MODULUS];
-static int curval;
-static int maxval;
-
-/* Integer constants mapped with the load immediate opcode. */
-#define K(i) F(BPF_LD|BPF_IMM|BPF_W, i, 0L)
-
-struct vmapinfo {
- int is_const;
- bpf_int32 const_val;
-};
-
-struct vmapinfo *vmap;
-struct valnode *vnode_base;
-struct valnode *next_vnode;
-
static void
-init_val(void)
+init_val(opt_state_t *opt_state)
{
- curval = 0;
- next_vnode = vnode_base;
- memset((char *)vmap, 0, maxval * sizeof(*vmap));
- memset((char *)hashtbl, 0, sizeof hashtbl);
+ opt_state->curval = 0;
+ opt_state->next_vnode = opt_state->vnode_base;
+ memset((char *)opt_state->vmap, 0, opt_state->maxval * sizeof(*opt_state->vmap));
+ memset((char *)opt_state->hashtbl, 0, sizeof opt_state->hashtbl);
}
/* Because we really don't have an IR, this stuff is a little messy. */
static int
-F(int code, int v0, int v1)
+F(opt_state_t *opt_state, int code, int v0, int v1)
{
u_int hash;
int val;
@@ -545,23 +566,23 @@ F(int code, int v0, int v1)
hash = (u_int)code ^ (v0 << 4) ^ (v1 << 8);
hash %= MODULUS;
- for (p = hashtbl[hash]; p; p = p->next)
+ for (p = opt_state->hashtbl[hash]; p; p = p->next)
if (p->code == code && p->v0 == v0 && p->v1 == v1)
return p->val;
- val = ++curval;
+ val = ++opt_state->curval;
if (BPF_MODE(code) == BPF_IMM &&
(BPF_CLASS(code) == BPF_LD || BPF_CLASS(code) == BPF_LDX)) {
- vmap[val].const_val = v0;
- vmap[val].is_const = 1;
+ opt_state->vmap[val].const_val = v0;
+ opt_state->vmap[val].is_const = 1;
}
- p = next_vnode++;
+ p = opt_state->next_vnode++;
p->val = val;
p->code = code;
p->v0 = v0;
p->v1 = v1;
- p->next = hashtbl[hash];
- hashtbl[hash] = p;
+ p->next = opt_state->hashtbl[hash];
+ opt_state->hashtbl[hash] = p;
return val;
}
@@ -580,12 +601,13 @@ vstore(struct stmt *s, int *valp, int newval, int alter)
* (Unary operators are handled elsewhere.)
*/
static void
-fold_op(struct stmt *s, int v0, int v1)
+fold_op(compiler_state_t *cstate, struct icode *ic, opt_state_t *opt_state,
+ struct stmt *s, int v0, int v1)
{
bpf_u_int32 a, b;
- a = vmap[v0].const_val;
- b = vmap[v1].const_val;
+ a = opt_state->vmap[v0].const_val;
+ b = opt_state->vmap[v1].const_val;
switch (BPF_OP(s->code)) {
case BPF_ADD:
@@ -602,13 +624,13 @@ fold_op(struct stmt *s, int v0, int v1)
case BPF_DIV:
if (b == 0)
- bpf_error("division by zero");
+ bpf_error(cstate, "division by zero");
a /= b;
break;
case BPF_MOD:
if (b == 0)
- bpf_error("modulus by zero");
+ bpf_error(cstate, "modulus by zero");
a %= b;
break;
@@ -637,7 +659,7 @@ fold_op(struct stmt *s, int v0, int v1)
}
s->k = a;
s->code = BPF_LD|BPF_IMM;
- done = 0;
+ opt_state->done = 0;
}
static inline struct slist *
@@ -658,7 +680,7 @@ opt_not(struct block *b)
}
static void
-opt_peep(struct block *b)
+opt_peep(opt_state_t *opt_state, struct block *b)
{
struct slist *s;
struct slist *next, *last;
@@ -693,7 +715,7 @@ opt_peep(struct block *b)
if (s->s.code == BPF_ST &&
next->s.code == (BPF_LDX|BPF_MEM) &&
s->s.k == next->s.k) {
- done = 0;
+ opt_state->done = 0;
next->s.code = BPF_MISC|BPF_TAX;
}
/*
@@ -704,7 +726,7 @@ opt_peep(struct block *b)
next->s.code == (BPF_MISC|BPF_TAX)) {
s->s.code = BPF_LDX|BPF_IMM;
next->s.code = BPF_MISC|BPF_TXA;
- done = 0;
+ opt_state->done = 0;
}
/*
* This is an ugly special case, but it happens
@@ -783,7 +805,7 @@ opt_peep(struct block *b)
s->s.code = NOP;
add->s.code = NOP;
tax->s.code = NOP;
- done = 0;
+ opt_state->done = 0;
}
}
/*
@@ -801,7 +823,7 @@ opt_peep(struct block *b)
*/
if (last->s.code == (BPF_ALU|BPF_SUB|BPF_X)) {
val = b->val[X_ATOM];
- if (vmap[val].is_const) {
+ if (opt_state->vmap[val].is_const) {
/*
* If we have a subtract to do a comparison,
* and the X register is a known constant,
@@ -811,9 +833,9 @@ opt_peep(struct block *b)
* sub x -> nop
* jeq #y jeq #(x+y)
*/
- b->s.k += vmap[val].const_val;
+ b->s.k += opt_state->vmap[val].const_val;
last->s.code = NOP;
- done = 0;
+ opt_state->done = 0;
} else if (b->s.k == 0) {
/*
* If the X register isn't a constant,
@@ -826,7 +848,7 @@ opt_peep(struct block *b)
*/
last->s.code = NOP;
b->s.code = BPF_JMP|BPF_JEQ|BPF_X;
- done = 0;
+ opt_state->done = 0;
}
}
/*
@@ -838,7 +860,7 @@ opt_peep(struct block *b)
else if (last->s.code == (BPF_ALU|BPF_SUB|BPF_K)) {
last->s.code = NOP;
b->s.k += last->s.k;
- done = 0;
+ opt_state->done = 0;
}
/*
* And, similarly, a constant AND can be simplified
@@ -852,7 +874,7 @@ opt_peep(struct block *b)
b->s.k = last->s.k;
b->s.code = BPF_JMP|BPF_K|BPF_JSET;
last->s.code = NOP;
- done = 0;
+ opt_state->done = 0;
opt_not(b);
}
}
@@ -863,7 +885,7 @@ opt_peep(struct block *b)
if (b->s.code == (BPF_JMP|BPF_K|BPF_JSET)) {
if (b->s.k == 0)
JT(b) = JF(b);
- if (b->s.k == 0xffffffff)
+ if ((u_int)b->s.k == 0xffffffffU)
JF(b) = JT(b);
}
/*
@@ -872,8 +894,8 @@ opt_peep(struct block *b)
* constant.
*/
val = b->val[X_ATOM];
- if (vmap[val].is_const && BPF_SRC(b->s.code) == BPF_X) {
- bpf_int32 v = vmap[val].const_val;
+ if (opt_state->vmap[val].is_const && BPF_SRC(b->s.code) == BPF_X) {
+ bpf_int32 v = opt_state->vmap[val].const_val;
b->s.code &= ~BPF_X;
b->s.k = v;
}
@@ -882,8 +904,8 @@ opt_peep(struct block *b)
* comparison result.
*/
val = b->val[A_ATOM];
- if (vmap[val].is_const && BPF_SRC(b->s.code) == BPF_K) {
- bpf_int32 v = vmap[val].const_val;
+ if (opt_state->vmap[val].is_const && BPF_SRC(b->s.code) == BPF_K) {
+ bpf_int32 v = opt_state->vmap[val].const_val;
switch (BPF_OP(b->s.code)) {
case BPF_JEQ:
@@ -891,11 +913,11 @@ opt_peep(struct block *b)
break;
case BPF_JGT:
- v = (unsigned)v > b->s.k;
+ v = (unsigned)v > (unsigned)b->s.k;
break;
case BPF_JGE:
- v = (unsigned)v >= b->s.k;
+ v = (unsigned)v >= (unsigned)b->s.k;
break;
case BPF_JSET:
@@ -906,7 +928,7 @@ opt_peep(struct block *b)
abort();
}
if (JF(b) != JT(b))
- done = 0;
+ opt_state->done = 0;
if (v)
JF(b) = JT(b);
else
@@ -921,7 +943,8 @@ opt_peep(struct block *b)
* evaluation and code transformations weren't folded together.
*/
static void
-opt_stmt(struct stmt *s, int val[], int alter)
+opt_stmt(compiler_state_t *cstate, struct icode *ic, opt_state_t *opt_state,
+ struct stmt *s, int val[], int alter)
{
int op;
int v;
@@ -931,7 +954,7 @@ opt_stmt(struct stmt *s, int val[], int alter)
case BPF_LD|BPF_ABS|BPF_W:
case BPF_LD|BPF_ABS|BPF_H:
case BPF_LD|BPF_ABS|BPF_B:
- v = F(s->code, s->k, 0L);
+ v = F(opt_state, s->code, s->k, 0L);
vstore(s, &val[A_ATOM], v, alter);
break;
@@ -939,19 +962,19 @@ opt_stmt(struct stmt *s, int val[], int alter)
case BPF_LD|BPF_IND|BPF_H:
case BPF_LD|BPF_IND|BPF_B:
v = val[X_ATOM];
- if (alter && vmap[v].is_const) {
+ if (alter && opt_state->vmap[v].is_const) {
s->code = BPF_LD|BPF_ABS|BPF_SIZE(s->code);
- s->k += vmap[v].const_val;
- v = F(s->code, s->k, 0L);
- done = 0;
+ s->k += opt_state->vmap[v].const_val;
+ v = F(opt_state, s->code, s->k, 0L);
+ opt_state->done = 0;
}
else
- v = F(s->code, s->k, v);
+ v = F(opt_state, s->code, s->k, v);
vstore(s, &val[A_ATOM], v, alter);
break;
case BPF_LD|BPF_LEN:
- v = F(s->code, 0L, 0L);
+ v = F(opt_state, s->code, 0L, 0L);
vstore(s, &val[A_ATOM], v, alter);
break;
@@ -966,18 +989,18 @@ opt_stmt(struct stmt *s, int val[], int alter)
break;
case BPF_LDX|BPF_MSH|BPF_B:
- v = F(s->code, s->k, 0L);
+ v = F(opt_state, s->code, s->k, 0L);
vstore(s, &val[X_ATOM], v, alter);
break;
case BPF_ALU|BPF_NEG:
- if (alter && vmap[val[A_ATOM]].is_const) {
+ if (alter && opt_state->vmap[val[A_ATOM]].is_const) {
s->code = BPF_LD|BPF_IMM;
- s->k = -vmap[val[A_ATOM]].const_val;
+ s->k = -opt_state->vmap[val[A_ATOM]].const_val;
val[A_ATOM] = K(s->k);
}
else
- val[A_ATOM] = F(s->code, val[A_ATOM], 0L);
+ val[A_ATOM] = F(opt_state, s->code, val[A_ATOM], 0L);
break;
case BPF_ALU|BPF_ADD|BPF_K:
@@ -1008,13 +1031,13 @@ opt_stmt(struct stmt *s, int val[], int alter)
break;
}
}
- if (vmap[val[A_ATOM]].is_const) {
- fold_op(s, val[A_ATOM], K(s->k));
+ if (opt_state->vmap[val[A_ATOM]].is_const) {
+ fold_op(cstate, ic, opt_state, s, val[A_ATOM], K(s->k));
val[A_ATOM] = K(s->k);
break;
}
}
- val[A_ATOM] = F(s->code, val[A_ATOM], K(s->k));
+ val[A_ATOM] = F(opt_state, s->code, val[A_ATOM], K(s->k));
break;
case BPF_ALU|BPF_ADD|BPF_X:
@@ -1028,17 +1051,17 @@ opt_stmt(struct stmt *s, int val[], int alter)
case BPF_ALU|BPF_LSH|BPF_X:
case BPF_ALU|BPF_RSH|BPF_X:
op = BPF_OP(s->code);
- if (alter && vmap[val[X_ATOM]].is_const) {
- if (vmap[val[A_ATOM]].is_const) {
- fold_op(s, val[A_ATOM], val[X_ATOM]);
+ if (alter && opt_state->vmap[val[X_ATOM]].is_const) {
+ if (opt_state->vmap[val[A_ATOM]].is_const) {
+ fold_op(cstate, ic, opt_state, s, val[A_ATOM], val[X_ATOM]);
val[A_ATOM] = K(s->k);
}
else {
s->code = BPF_ALU|BPF_K|op;
- s->k = vmap[val[X_ATOM]].const_val;
- done = 0;
+ s->k = opt_state->vmap[val[X_ATOM]].const_val;
+ opt_state->done = 0;
val[A_ATOM] =
- F(s->code, val[A_ATOM], K(s->k));
+ F(opt_state, s->code, val[A_ATOM], K(s->k));
}
break;
}
@@ -1049,8 +1072,8 @@ opt_stmt(struct stmt *s, int val[], int alter)
* optimizations.
* XXX We could also check for mul by 1, etc.
*/
- if (alter && vmap[val[A_ATOM]].is_const
- && vmap[val[A_ATOM]].const_val == 0) {
+ if (alter && opt_state->vmap[val[A_ATOM]].is_const
+ && opt_state->vmap[val[A_ATOM]].const_val == 0) {
if (op == BPF_ADD || op == BPF_OR || op == BPF_XOR) {
s->code = BPF_MISC|BPF_TXA;
vstore(s, &val[A_ATOM], val[X_ATOM], alter);
@@ -1068,7 +1091,7 @@ opt_stmt(struct stmt *s, int val[], int alter)
break;
}
}
- val[A_ATOM] = F(s->code, val[A_ATOM], val[X_ATOM]);
+ val[A_ATOM] = F(opt_state, s->code, val[A_ATOM], val[X_ATOM]);
break;
case BPF_MISC|BPF_TXA:
@@ -1077,10 +1100,10 @@ opt_stmt(struct stmt *s, int val[], int alter)
case BPF_LD|BPF_MEM:
v = val[s->k];
- if (alter && vmap[v].is_const) {
+ if (alter && opt_state->vmap[v].is_const) {
s->code = BPF_LD|BPF_IMM;
- s->k = vmap[v].const_val;
- done = 0;
+ s->k = opt_state->vmap[v].const_val;
+ opt_state->done = 0;
}
vstore(s, &val[A_ATOM], v, alter);
break;
@@ -1091,10 +1114,10 @@ opt_stmt(struct stmt *s, int val[], int alter)
case BPF_LDX|BPF_MEM:
v = val[s->k];
- if (alter && vmap[v].is_const) {
+ if (alter && opt_state->vmap[v].is_const) {
s->code = BPF_LDX|BPF_IMM;
- s->k = vmap[v].const_val;
- done = 0;
+ s->k = opt_state->vmap[v].const_val;
+ opt_state->done = 0;
}
vstore(s, &val[X_ATOM], v, alter);
break;
@@ -1110,7 +1133,7 @@ opt_stmt(struct stmt *s, int val[], int alter)
}
static void
-deadstmt(register struct stmt *s, register struct stmt *last[])
+deadstmt(opt_state_t *opt_state, register struct stmt *s, register struct stmt *last[])
{
register int atom;
@@ -1126,7 +1149,7 @@ deadstmt(register struct stmt *s, register struct stmt *last[])
atom = atomdef(s);
if (atom >= 0) {
if (last[atom]) {
- done = 0;
+ opt_state->done = 0;
last[atom]->code = NOP;
}
last[atom] = s;
@@ -1134,7 +1157,7 @@ deadstmt(register struct stmt *s, register struct stmt *last[])
}
static void
-opt_deadstores(register struct block *b)
+opt_deadstores(opt_state_t *opt_state, register struct block *b)
{
register struct slist *s;
register int atom;
@@ -1143,18 +1166,19 @@ opt_deadstores(register struct block *b)
memset((char *)last, 0, sizeof last);
for (s = b->stmts; s != 0; s = s->next)
- deadstmt(&s->s, last);
- deadstmt(&b->s, last);
+ deadstmt(opt_state, &s->s, last);
+ deadstmt(opt_state, &b->s, last);
for (atom = 0; atom < N_ATOMS; ++atom)
if (last[atom] && !ATOMELEM(b->out_use, atom)) {
last[atom]->code = NOP;
- done = 0;
+ opt_state->done = 0;
}
}
static void
-opt_blk(struct block *b, int do_stmts)
+opt_blk(compiler_state_t *cstate, struct icode *ic, opt_state_t *opt_state,
+ struct block *b, int do_stmts)
{
struct slist *s;
struct edge *p;
@@ -1204,7 +1228,7 @@ opt_blk(struct block *b, int do_stmts)
aval = b->val[A_ATOM];
xval = b->val[X_ATOM];
for (s = b->stmts; s; s = s->next)
- opt_stmt(&s->s, b->val, do_stmts);
+ opt_stmt(cstate, ic, opt_state, &s->s, b->val, do_stmts);
/*
* This is a special case: if we don't use anything from this
@@ -1235,11 +1259,11 @@ opt_blk(struct block *b, int do_stmts)
BPF_CLASS(b->s.code) == BPF_RET)) {
if (b->stmts != 0) {
b->stmts = 0;
- done = 0;
+ opt_state->done = 0;
}
} else {
- opt_peep(b);
- opt_deadstores(b);
+ opt_peep(opt_state, b);
+ opt_deadstores(opt_state, b);
}
/*
* Set up values for branch optimizer.
@@ -1326,7 +1350,7 @@ fold_edge(struct block *child, struct edge *ep)
}
static void
-opt_j(struct edge *ep)
+opt_j(opt_state_t *opt_state, struct edge *ep)
{
register int i, k;
register struct block *target;
@@ -1340,7 +1364,7 @@ opt_j(struct edge *ep)
* there is no data dependency.
*/
if (!use_conflict(ep->pred, ep->succ->et.succ)) {
- done = 0;
+ opt_state->done = 0;
ep->succ = JT(ep->succ);
}
}
@@ -1352,7 +1376,7 @@ opt_j(struct edge *ep)
* efficient loop.
*/
top:
- for (i = 0; i < edgewords; ++i) {
+ for (i = 0; i < opt_state->edgewords; ++i) {
register bpf_u_int32 x = ep->edom[i];
while (x != 0) {
@@ -1360,13 +1384,13 @@ opt_j(struct edge *ep)
x &=~ (1 << k);
k += i * BITS_PER_WORD;
- target = fold_edge(ep->succ, edges[k]);
+ target = fold_edge(ep->succ, opt_state->edges[k]);
/*
* Check that there is no data dependency between
* nodes that will be violated if we move the edge.
*/
if (target != 0 && !use_conflict(ep->pred, target)) {
- done = 0;
+ opt_state->done = 0;
ep->succ = target;
if (JT(target) != 0)
/*
@@ -1381,7 +1405,7 @@ opt_j(struct edge *ep)
static void
-or_pullup(struct block *b)
+or_pullup(opt_state_t *opt_state, struct block *b)
{
int val, at_top;
struct block *pull;
@@ -1469,11 +1493,11 @@ or_pullup(struct block *b)
else
*diffp = pull;
- done = 0;
+ opt_state->done = 0;
}
static void
-and_pullup(struct block *b)
+and_pullup(opt_state_t *opt_state, struct block *b)
{
int val, at_top;
struct block *pull;
@@ -1560,22 +1584,23 @@ and_pullup(struct block *b)
else
*diffp = pull;
- done = 0;
+ opt_state->done = 0;
}
static void
-opt_blks(struct block *root, int do_stmts)
+opt_blks(compiler_state_t *cstate, opt_state_t *opt_state, struct icode *ic,
+ int do_stmts)
{
int i, maxlevel;
struct block *p;
- init_val();
- maxlevel = root->level;
+ init_val(opt_state);
+ maxlevel = ic->root->level;
- find_inedges(root);
+ find_inedges(opt_state, ic->root);
for (i = maxlevel; i >= 0; --i)
- for (p = levels[i]; p; p = p->link)
- opt_blk(p, do_stmts);
+ for (p = opt_state->levels[i]; p; p = p->link)
+ opt_blk(cstate, ic, opt_state, p, do_stmts);
if (do_stmts)
/*
@@ -1585,17 +1610,17 @@ opt_blks(struct block *root, int do_stmts)
return;
for (i = 1; i <= maxlevel; ++i) {
- for (p = levels[i]; p; p = p->link) {
- opt_j(&p->et);
- opt_j(&p->ef);
+ for (p = opt_state->levels[i]; p; p = p->link) {
+ opt_j(opt_state, &p->et);
+ opt_j(opt_state, &p->ef);
}
}
- find_inedges(root);
+ find_inedges(opt_state, ic->root);
for (i = 1; i <= maxlevel; ++i) {
- for (p = levels[i]; p; p = p->link) {
- or_pullup(p);
- and_pullup(p);
+ for (p = opt_state->levels[i]; p; p = p->link) {
+ or_pullup(opt_state, p);
+ and_pullup(opt_state, p);
}
}
}
@@ -1608,20 +1633,20 @@ link_inedge(struct edge *parent, struct block *child)
}
static void
-find_inedges(struct block *root)
+find_inedges(opt_state_t *opt_state, struct block *root)
{
int i;
struct block *b;
- for (i = 0; i < n_blocks; ++i)
- blocks[i]->in_edges = 0;
+ for (i = 0; i < opt_state->n_blocks; ++i)
+ opt_state->blocks[i]->in_edges = 0;
/*
* Traverse the graph, adding each edge to the predecessor
* list of its successors. Skip the leaves (i.e. level 0).
*/
for (i = root->level; i > 0; --i) {
- for (b = levels[i]; b != 0; b = b->link) {
+ for (b = opt_state->levels[i]; b != 0; b = b->link) {
link_inedge(&b->et, JT(b));
link_inedge(&b->ef, JF(b));
}
@@ -1653,83 +1678,82 @@ opt_root(struct block **b)
}
static void
-opt_loop(struct block *root, int do_stmts)
+opt_loop(compiler_state_t *cstate, opt_state_t *opt_state, struct icode *ic,
+ int do_stmts)
{
#ifdef BDEBUG
- if (dflag > 1) {
+ if (pcap_optimizer_debug > 1) {
printf("opt_loop(root, %d) begin\n", do_stmts);
- opt_dump(root);
+ opt_dump(cstate, ic);
}
#endif
do {
- done = 1;
- find_levels(root);
- find_dom(root);
- find_closure(root);
- find_ud(root);
- find_edom(root);
- opt_blks(root, do_stmts);
+ opt_state->done = 1;
+ find_levels(opt_state, ic);
+ find_dom(opt_state, ic->root);
+ find_closure(opt_state, ic->root);
+ find_ud(opt_state, ic->root);
+ find_edom(opt_state, ic->root);
+ opt_blks(cstate, opt_state, ic, do_stmts);
#ifdef BDEBUG
- if (dflag > 1) {
- printf("opt_loop(root, %d) bottom, done=%d\n", do_stmts, done);
- opt_dump(root);
+ if (pcap_optimizer_debug > 1) {
+ printf("opt_loop(root, %d) bottom, done=%d\n", do_stmts, opt_state->done);
+ opt_dump(cstate, ic);
}
#endif
- } while (!done);
+ } while (!opt_state->done);
}
/*
* Optimize the filter code in its dag representation.
*/
void
-bpf_optimize(struct block **rootp)
+bpf_optimize(compiler_state_t *cstate, struct icode *ic)
{
- struct block *root;
+ opt_state_t opt_state;
- root = *rootp;
-
- opt_init(root);
- opt_loop(root, 0);
- opt_loop(root, 1);
- intern_blocks(root);
+ opt_init(cstate, &opt_state, ic);
+ opt_loop(cstate, &opt_state, ic, 0);
+ opt_loop(cstate, &opt_state, ic, 1);
+ intern_blocks(&opt_state, ic);
#ifdef BDEBUG
- if (dflag > 1) {
+ if (pcap_optimizer_debug > 1) {
printf("after intern_blocks()\n");
- opt_dump(root);
+ opt_dump(cstate, ic);
}
#endif
- opt_root(rootp);
+ opt_root(&ic->root);
#ifdef BDEBUG
- if (dflag > 1) {
+ if (pcap_optimizer_debug > 1) {
printf("after opt_root()\n");
- opt_dump(root);
+ opt_dump(cstate, ic);
}
#endif
- opt_cleanup();
+ opt_cleanup(&opt_state);
}
static void
-make_marks(struct block *p)
+make_marks(struct icode *ic, struct block *p)
{
- if (!isMarked(p)) {
- Mark(p);
+ if (!isMarked(ic, p)) {
+ Mark(ic, p);
if (BPF_CLASS(p->s.code) != BPF_RET) {
- make_marks(JT(p));
- make_marks(JF(p));
+ make_marks(ic, JT(p));
+ make_marks(ic, JF(p));
}
}
}
/*
- * Mark code array such that isMarked(i) is true
+ * Mark code array such that isMarked(ic->cur_mark, i) is true
* only for nodes that are alive.
*/
static void
-mark_code(struct block *p)
+mark_code(struct icode *ic)
{
- cur_mark += 1;
- make_marks(p);
+ ic->cur_mark += 1;
+ make_marks(ic, ic->root);
}
/*
@@ -1767,33 +1791,33 @@ eq_blk(struct block *b0, struct block *b1)
}
static void
-intern_blocks(struct block *root)
+intern_blocks(opt_state_t *opt_state, struct icode *ic)
{
struct block *p;
int i, j;
int done1; /* don't shadow global */
top:
done1 = 1;
- for (i = 0; i < n_blocks; ++i)
- blocks[i]->link = 0;
+ for (i = 0; i < opt_state->n_blocks; ++i)
+ opt_state->blocks[i]->link = 0;
- mark_code(root);
+ mark_code(ic);
- for (i = n_blocks - 1; --i >= 0; ) {
- if (!isMarked(blocks[i]))
+ for (i = opt_state->n_blocks - 1; --i >= 0; ) {
+ if (!isMarked(ic, opt_state->blocks[i]))
continue;
- for (j = i + 1; j < n_blocks; ++j) {
- if (!isMarked(blocks[j]))
+ for (j = i + 1; j < opt_state->n_blocks; ++j) {
+ if (!isMarked(ic, opt_state->blocks[j]))
continue;
- if (eq_blk(blocks[i], blocks[j])) {
- blocks[i]->link = blocks[j]->link ?
- blocks[j]->link : blocks[j];
+ if (eq_blk(opt_state->blocks[i], opt_state->blocks[j])) {
+ opt_state->blocks[i]->link = opt_state->blocks[j]->link ?
+ opt_state->blocks[j]->link : opt_state->blocks[j];
break;
}
}
}
- for (i = 0; i < n_blocks; ++i) {
- p = blocks[i];
+ for (i = 0; i < opt_state->n_blocks; ++i) {
+ p = opt_state->blocks[i];
if (JT(p) == 0)
continue;
if (JT(p)->link) {
@@ -1810,14 +1834,14 @@ intern_blocks(struct block *root)
}
static void
-opt_cleanup(void)
+opt_cleanup(opt_state_t *opt_state)
{
- free((void *)vnode_base);
- free((void *)vmap);
- free((void *)edges);
- free((void *)space);
- free((void *)levels);
- free((void *)blocks);
+ free((void *)opt_state->vnode_base);
+ free((void *)opt_state->vmap);
+ free((void *)opt_state->edges);
+ free((void *)opt_state->space);
+ free((void *)opt_state->levels);
+ free((void *)opt_state->blocks);
}
/*
@@ -1839,12 +1863,12 @@ slength(struct slist *s)
* All nodes should be initially unmarked.
*/
static int
-count_blocks(struct block *p)
+count_blocks(struct icode *ic, struct block *p)
{
- if (p == 0 || isMarked(p))
+ if (p == 0 || isMarked(ic, p))
return 0;
- Mark(p);
- return count_blocks(JT(p)) + count_blocks(JF(p)) + 1;
+ Mark(ic, p);
+ return count_blocks(ic, JT(p)) + count_blocks(ic, JF(p)) + 1;
}
/*
@@ -1852,20 +1876,20 @@ count_blocks(struct block *p)
* the basic blocks, and entering them into the 'blocks' array.`
*/
static void
-number_blks_r(struct block *p)
+number_blks_r(opt_state_t *opt_state, struct icode *ic, struct block *p)
{
int n;
- if (p == 0 || isMarked(p))
+ if (p == 0 || isMarked(ic, p))
return;
- Mark(p);
- n = n_blocks++;
+ Mark(ic, p);
+ n = opt_state->n_blocks++;
p->id = n;
- blocks[n] = p;
+ opt_state->blocks[n] = p;
- number_blks_r(JT(p));
- number_blks_r(JF(p));
+ number_blks_r(opt_state, ic, JT(p));
+ number_blks_r(opt_state, ic, JF(p));
}
/*
@@ -1887,14 +1911,14 @@ number_blks_r(struct block *p)
* an extra long jump if the false branch requires it (p->longjf).
*/
static u_int
-count_stmts(struct block *p)
+count_stmts(struct icode *ic, struct block *p)
{
u_int n;
- if (p == 0 || isMarked(p))
+ if (p == 0 || isMarked(ic, p))
return 0;
- Mark(p);
- n = count_stmts(JT(p)) + count_stmts(JF(p));
+ Mark(ic, p);
+ n = count_stmts(ic, JT(p)) + count_stmts(ic, JF(p));
return slength(p->stmts) + n + 1 + p->longjt + p->longjf;
}
@@ -1904,7 +1928,7 @@ count_stmts(struct block *p)
* from the total number of blocks and/or statements.
*/
static void
-opt_init(struct block *root)
+opt_init(compiler_state_t *cstate, opt_state_t *opt_state, struct icode *ic)
{
bpf_u_int32 *p;
int i, n, max_stmts;
@@ -1913,84 +1937,81 @@ opt_init(struct block *root)
* First, count the blocks, so we can malloc an array to map
* block number to block. Then, put the blocks into the array.
*/
- unMarkAll();
- n = count_blocks(root);
- blocks = (struct block **)calloc(n, sizeof(*blocks));
- if (blocks == NULL)
- bpf_error("malloc");
- unMarkAll();
- n_blocks = 0;
- number_blks_r(root);
-
- n_edges = 2 * n_blocks;
- edges = (struct edge **)calloc(n_edges, sizeof(*edges));
- if (edges == NULL)
- bpf_error("malloc");
+ unMarkAll(ic);
+ n = count_blocks(ic, ic->root);
+ opt_state->blocks = (struct block **)calloc(n, sizeof(*opt_state->blocks));
+ if (opt_state->blocks == NULL)
+ bpf_error(cstate, "malloc");
+ unMarkAll(ic);
+ opt_state->n_blocks = 0;
+ number_blks_r(opt_state, ic, ic->root);
+
+ opt_state->n_edges = 2 * opt_state->n_blocks;
+ opt_state->edges = (struct edge **)calloc(opt_state->n_edges, sizeof(*opt_state->edges));
+ if (opt_state->edges == NULL)
+ bpf_error(cstate, "malloc");
/*
* The number of levels is bounded by the number of nodes.
*/
- levels = (struct block **)calloc(n_blocks, sizeof(*levels));
- if (levels == NULL)
- bpf_error("malloc");
+ opt_state->levels = (struct block **)calloc(opt_state->n_blocks, sizeof(*opt_state->levels));
+ if (opt_state->levels == NULL)
+ bpf_error(cstate, "malloc");
- edgewords = n_edges / (8 * sizeof(bpf_u_int32)) + 1;
- nodewords = n_blocks / (8 * sizeof(bpf_u_int32)) + 1;
+ opt_state->edgewords = opt_state->n_edges / (8 * sizeof(bpf_u_int32)) + 1;
+ opt_state->nodewords = opt_state->n_blocks / (8 * sizeof(bpf_u_int32)) + 1;
/* XXX */
- space = (bpf_u_int32 *)malloc(2 * n_blocks * nodewords * sizeof(*space)
- + n_edges * edgewords * sizeof(*space));
- if (space == NULL)
- bpf_error("malloc");
- p = space;
- all_dom_sets = p;
+ opt_state->space = (bpf_u_int32 *)malloc(2 * opt_state->n_blocks * opt_state->nodewords * sizeof(*opt_state->space)
+ + opt_state->n_edges * opt_state->edgewords * sizeof(*opt_state->space));
+ if (opt_state->space == NULL)
+ bpf_error(cstate, "malloc");
+ p = opt_state->space;
+ opt_state->all_dom_sets = p;
for (i = 0; i < n; ++i) {
- blocks[i]->dom = p;
- p += nodewords;
+ opt_state->blocks[i]->dom = p;
+ p += opt_state->nodewords;
}
- all_closure_sets = p;
+ opt_state->all_closure_sets = p;
for (i = 0; i < n; ++i) {
- blocks[i]->closure = p;
- p += nodewords;
+ opt_state->blocks[i]->closure = p;
+ p += opt_state->nodewords;
}
- all_edge_sets = p;
+ opt_state->all_edge_sets = p;
for (i = 0; i < n; ++i) {
- register struct block *b = blocks[i];
+ register struct block *b = opt_state->blocks[i];
b->et.edom = p;
- p += edgewords;
+ p += opt_state->edgewords;
b->ef.edom = p;
- p += edgewords;
+ p += opt_state->edgewords;
b->et.id = i;
- edges[i] = &b->et;
- b->ef.id = n_blocks + i;
- edges[n_blocks + i] = &b->ef;
+ opt_state->edges[i] = &b->et;
+ b->ef.id = opt_state->n_blocks + i;
+ opt_state->edges[opt_state->n_blocks + i] = &b->ef;
b->et.pred = b;
b->ef.pred = b;
}
max_stmts = 0;
for (i = 0; i < n; ++i)
- max_stmts += slength(blocks[i]->stmts) + 1;
+ max_stmts += slength(opt_state->blocks[i]->stmts) + 1;
/*
* We allocate at most 3 value numbers per statement,
* so this is an upper bound on the number of valnodes
* we'll need.
*/
- maxval = 3 * max_stmts;
- vmap = (struct vmapinfo *)calloc(maxval, sizeof(*vmap));
- vnode_base = (struct valnode *)calloc(maxval, sizeof(*vnode_base));
- if (vmap == NULL || vnode_base == NULL)
- bpf_error("malloc");
+ opt_state->maxval = 3 * max_stmts;
+ opt_state->vmap = (struct vmapinfo *)calloc(opt_state->maxval, sizeof(*opt_state->vmap));
+ opt_state->vnode_base = (struct valnode *)calloc(opt_state->maxval, sizeof(*opt_state->vnode_base));
+ if (opt_state->vmap == NULL || opt_state->vnode_base == NULL)
+ bpf_error(cstate, "malloc");
}
/*
- * Some pointers used to convert the basic block form of the code,
- * into the array form that BPF requires. 'fstart' will point to
- * the malloc'd array while 'ftail' is used during the recursive traversal.
+ * This is only used when supporting optimizer debugging. It is
+ * global state, so do *not* do more than one compile in parallel
+ * and expect it to provide meaningful information.
*/
-static struct bpf_insn *fstart;
-static struct bpf_insn *ftail;
-
#ifdef BDEBUG
int bids[1000];
#endif
@@ -2002,35 +2023,36 @@ int bids[1000];
* properly.
*/
static int
-convert_code_r(struct block *p)
+convert_code_r(compiler_state_t *cstate, conv_state_t *conv_state,
+ struct icode *ic, struct block *p)
{
struct bpf_insn *dst;
struct slist *src;
- int slen;
+ u_int slen;
u_int off;
int extrajmps; /* number of extra jumps inserted */
struct slist **offset = NULL;
- if (p == 0 || isMarked(p))
+ if (p == 0 || isMarked(ic, p))
return (1);
- Mark(p);
+ Mark(ic, p);
- if (convert_code_r(JF(p)) == 0)
+ if (convert_code_r(cstate, conv_state, ic, JF(p)) == 0)
return (0);
- if (convert_code_r(JT(p)) == 0)
+ if (convert_code_r(cstate, conv_state, ic, JT(p)) == 0)
return (0);
slen = slength(p->stmts);
- dst = ftail -= (slen + 1 + p->longjt + p->longjf);
+ dst = conv_state->ftail -= (slen + 1 + p->longjt + p->longjf);
/* inflate length by any extra jumps */
- p->offset = dst - fstart;
+ p->offset = (int)(dst - conv_state->fstart);
/* generate offset[] for convenience */
if (slen) {
offset = (struct slist **)calloc(slen, sizeof(struct slist *));
if (!offset) {
- bpf_error("not enough core");
+ bpf_error(cstate, "not enough core");
/*NOTREACHED*/
}
}
@@ -2054,7 +2076,7 @@ convert_code_r(struct block *p)
if (BPF_CLASS(src->s.code) != BPF_JMP || src->s.code == (BPF_JMP|BPF_JA)) {
#if 0
if (src->s.jt || src->s.jf) {
- bpf_error("illegal jmp destination");
+ bpf_error(cstate, "illegal jmp destination");
/*NOTREACHED*/
}
#endif
@@ -2064,7 +2086,7 @@ convert_code_r(struct block *p)
goto filled;
{
- int i;
+ u_int i;
int jt, jf;
const char *ljerr = "%s for block-local relative jump: off=%d";
@@ -2074,7 +2096,7 @@ convert_code_r(struct block *p)
#endif
if (!src->s.jt || !src->s.jf) {
- bpf_error(ljerr, "no jmp destination", off);
+ bpf_error(cstate, ljerr, "no jmp destination", off);
/*NOTREACHED*/
}
@@ -2082,7 +2104,7 @@ convert_code_r(struct block *p)
for (i = 0; i < slen; i++) {
if (offset[i] == src->s.jt) {
if (jt) {
- bpf_error(ljerr, "multiple matches", off);
+ bpf_error(cstate, ljerr, "multiple matches", off);
/*NOTREACHED*/
}
@@ -2091,7 +2113,7 @@ convert_code_r(struct block *p)
}
if (offset[i] == src->s.jf) {
if (jf) {
- bpf_error(ljerr, "multiple matches", off);
+ bpf_error(cstate, ljerr, "multiple matches", off);
/*NOTREACHED*/
}
dst->jf = i - off - 1;
@@ -2099,7 +2121,7 @@ convert_code_r(struct block *p)
}
}
if (!jt || !jf) {
- bpf_error(ljerr, "no destination found", off);
+ bpf_error(cstate, ljerr, "no destination found", off);
/*NOTREACHED*/
}
}
@@ -2111,7 +2133,7 @@ filled:
free(offset);
#ifdef BDEBUG
- bids[dst - fstart] = p->id + 1;
+ bids[dst - conv_state->fstart] = p->id + 1;
#endif
dst->code = (u_short)p->s.code;
dst->k = p->s.k;
@@ -2174,28 +2196,30 @@ filled:
* done with the filter program. See the pcap man page.
*/
struct bpf_insn *
-icode_to_fcode(struct block *root, u_int *lenp)
+icode_to_fcode(compiler_state_t *cstate, struct icode *ic,
+ struct block *root, u_int *lenp)
{
u_int n;
struct bpf_insn *fp;
+ conv_state_t conv_state;
/*
* Loop doing convert_code_r() until no branches remain
* with too-large offsets.
*/
while (1) {
- unMarkAll();
- n = *lenp = count_stmts(root);
+ unMarkAll(ic);
+ n = *lenp = count_stmts(ic, root);
fp = (struct bpf_insn *)malloc(sizeof(*fp) * n);
if (fp == NULL)
- bpf_error("malloc");
+ bpf_error(cstate, "malloc");
memset((char *)fp, 0, sizeof(*fp) * n);
- fstart = fp;
- ftail = fp + n;
+ conv_state.fstart = fp;
+ conv_state.ftail = fp + n;
- unMarkAll();
- if (convert_code_r(root))
+ unMarkAll(ic);
+ if (convert_code_r(cstate, &conv_state, ic, root))
break;
free(fp);
}
@@ -2220,7 +2244,7 @@ install_bpf_program(pcap_t *p, struct bpf_program *fp)
* Validate the program.
*/
if (!bpf_validate(fp->bf_insns, fp->bf_len)) {
- snprintf(p->errbuf, sizeof(p->errbuf),
+ pcap_snprintf(p->errbuf, sizeof(p->errbuf),
"BPF program is not valid");
return (-1);
}
@@ -2234,7 +2258,7 @@ install_bpf_program(pcap_t *p, struct bpf_program *fp)
p->fcode.bf_len = fp->bf_len;
p->fcode.bf_insns = (struct bpf_insn *)malloc(prog_size);
if (p->fcode.bf_insns == NULL) {
- snprintf(p->errbuf, sizeof(p->errbuf),
+ pcap_snprintf(p->errbuf, sizeof(p->errbuf),
"malloc: %s", pcap_strerror(errno));
return (-1);
}
@@ -2244,14 +2268,117 @@ install_bpf_program(pcap_t *p, struct bpf_program *fp)
#ifdef BDEBUG
static void
-opt_dump(struct block *root)
+dot_dump_node(struct icode *ic, struct block *block, struct bpf_program *prog,
+ FILE *out)
+{
+ int icount, noffset;
+ int i;
+
+ if (block == NULL || isMarked(ic, block))
+ return;
+ Mark(ic, block);
+
+ icount = slength(block->stmts) + 1 + block->longjt + block->longjf;
+ noffset = min(block->offset + icount, (int)prog->bf_len);
+
+ fprintf(out, "\tblock%d [shape=ellipse, id=\"block-%d\" label=\"BLOCK%d\\n", block->id, block->id, block->id);
+ for (i = block->offset; i < noffset; i++) {
+ fprintf(out, "\\n%s", bpf_image(prog->bf_insns + i, i));
+ }
+ fprintf(out, "\" tooltip=\"");
+ for (i = 0; i < BPF_MEMWORDS; i++)
+ if (block->val[i] != 0)
+ fprintf(out, "val[%d]=%d ", i, block->val[i]);
+ fprintf(out, "val[A]=%d ", block->val[A_ATOM]);
+ fprintf(out, "val[X]=%d", block->val[X_ATOM]);
+ fprintf(out, "\"");
+ if (JT(block) == NULL)
+ fprintf(out, ", peripheries=2");
+ fprintf(out, "];\n");
+
+ dot_dump_node(ic, JT(block), prog, out);
+ dot_dump_node(ic, JF(block), prog, out);
+}
+
+static void
+dot_dump_edge(struct icode *ic, struct block *block, FILE *out)
+{
+ if (block == NULL || isMarked(ic, block))
+ return;
+ Mark(ic, block);
+
+ if (JT(block)) {
+ fprintf(out, "\t\"block%d\":se -> \"block%d\":n [label=\"T\"]; \n",
+ block->id, JT(block)->id);
+ fprintf(out, "\t\"block%d\":sw -> \"block%d\":n [label=\"F\"]; \n",
+ block->id, JF(block)->id);
+ }
+ dot_dump_edge(ic, JT(block), out);
+ dot_dump_edge(ic, JF(block), out);
+}
+
+/* Output the block CFG using graphviz/DOT language
+ * In the CFG, block's code, value index for each registers at EXIT,
+ * and the jump relationship is show.
+ *
+ * example DOT for BPF `ip src host 1.1.1.1' is:
+ digraph BPF {
+ block0 [shape=ellipse, id="block-0" label="BLOCK0\n\n(000) ldh [12]\n(001) jeq #0x800 jt 2 jf 5" tooltip="val[A]=0 val[X]=0"];
+ block1 [shape=ellipse, id="block-1" label="BLOCK1\n\n(002) ld [26]\n(003) jeq #0x1010101 jt 4 jf 5" tooltip="val[A]=0 val[X]=0"];
+ block2 [shape=ellipse, id="block-2" label="BLOCK2\n\n(004) ret #68" tooltip="val[A]=0 val[X]=0", peripheries=2];
+ block3 [shape=ellipse, id="block-3" label="BLOCK3\n\n(005) ret #0" tooltip="val[A]=0 val[X]=0", peripheries=2];
+ "block0":se -> "block1":n [label="T"];
+ "block0":sw -> "block3":n [label="F"];
+ "block1":se -> "block2":n [label="T"];
+ "block1":sw -> "block3":n [label="F"];
+ }
+ *
+ * After install graphviz on http://www.graphviz.org/, save it as bpf.dot
+ * and run `dot -Tpng -O bpf.dot' to draw the graph.
+ */
+static void
+dot_dump(compiler_state_t *cstate, struct icode *ic)
{
struct bpf_program f;
+ FILE *out = stdout;
memset(bids, 0, sizeof bids);
- f.bf_insns = icode_to_fcode(root, &f.bf_len);
+ f.bf_insns = icode_to_fcode(cstate, ic, ic->root, &f.bf_len);
+
+ fprintf(out, "digraph BPF {\n");
+ ic->cur_mark = 0;
+ unMarkAll(ic);
+ dot_dump_node(ic, ic->root, &f, out);
+ ic->cur_mark = 0;
+ unMarkAll(ic);
+ dot_dump_edge(ic, ic->root, out);
+ fprintf(out, "}\n");
+
+ free((char *)f.bf_insns);
+}
+
+static void
+plain_dump(compiler_state_t *cstate, struct icode *ic)
+{
+ struct bpf_program f;
+
+ memset(bids, 0, sizeof bids);
+ f.bf_insns = icode_to_fcode(cstate, ic, ic->root, &f.bf_len);
bpf_dump(&f, 1);
putchar('\n');
free((char *)f.bf_insns);
}
+
+static void
+opt_dump(compiler_state_t *cstate, struct icode *ic)
+{
+ /* if optimizer debugging is enabled, output DOT graph
+ * `pcap_optimizer_debug=4' is equivalent to -dddd to follow -d/-dd/-ddd
+ * convention in tcpdump command line
+ */
+ if (pcap_optimizer_debug > 3)
+ dot_dump(cstate, ic);
+ else
+ plain_dump(cstate, ic);
+}
#endif
diff --git a/contrib/libpcap/pcap-bpf.c b/contrib/libpcap/pcap-bpf.c
index 2f801bc1c3a7..eb9d100d117f 100644
--- a/contrib/libpcap/pcap-bpf.c
+++ b/contrib/libpcap/pcap-bpf.c
@@ -50,6 +50,15 @@
#endif
#include <sys/utsname.h>
+#if defined(__FreeBSD__) && defined(SIOCIFCREATE2)
+/*
+ * Add support for capturing on FreeBSD usbusN interfaces.
+ */
+static const char usbus_prefix[] = "usbus";
+#define USBUS_PREFIX_LEN (sizeof(usbus_prefix) - 1)
+#include <dirent.h>
+#endif
+
#ifdef HAVE_ZEROCOPY_BPF
#include <machine/atomic.h>
#endif
@@ -136,10 +145,6 @@ static int bpf_load(char *errbuf);
* 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
@@ -173,10 +178,23 @@ struct pcap_bpf {
* Stuff to do when we close.
*/
#define MUST_CLEAR_RFMON 0x00000001 /* clear rfmon (monitor) mode */
+#define MUST_DESTROY_USBUS 0x00000002 /* destroy usbusN interface */
#ifdef BIOCGDLTLIST
# if (defined(HAVE_NET_IF_MEDIA_H) && defined(IFM_IEEE80211)) && !defined(__APPLE__)
#define HAVE_BSD_IEEE80211
+
+/*
+ * The ifm_ulist member of a struct ifmediareq is an int * on most systems,
+ * but it's a uint64_t on newer versions of OpenBSD.
+ *
+ * We check this by checking whether IFM_GMASK is defined and > 2^32-1.
+ */
+# if defined(IFM_GMASK) && IFM_GMASK > 0xFFFFFFFF
+# define IFM_ULIST_TYPE uint64_t
+# else
+# define IFM_ULIST_TYPE int
+# endif
# endif
# if defined(__APPLE__) || defined(HAVE_BSD_IEEE80211)
@@ -237,7 +255,7 @@ static int pcap_set_datalink_bpf(pcap_t *p, int dlt);
*/
static int
pcap_getnonblock_bpf(pcap_t *p, char *errbuf)
-{
+{
#ifdef HAVE_ZEROCOPY_BPF
struct pcap_bpf *pb = p->priv;
@@ -249,7 +267,7 @@ pcap_getnonblock_bpf(pcap_t *p, char *errbuf)
static int
pcap_setnonblock_bpf(pcap_t *p, int nonblock, char *errbuf)
-{
+{
#ifdef HAVE_ZEROCOPY_BPF
struct pcap_bpf *pb = p->priv;
@@ -349,7 +367,7 @@ pcap_next_zbuf(pcap_t *p, int *cc)
if (data)
return (data);
if (ioctl(p->fd, BIOCROTZBUF, &bz) < 0) {
- (void) snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
+ (void) pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
"BIOCROTZBUF: %s", strerror(errno));
return (PCAP_ERROR);
}
@@ -377,7 +395,7 @@ pcap_next_zbuf(pcap_t *p, int *cc)
}
return (0);
} else if (r < 0) {
- (void) snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
+ (void) pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
"select: %s", strerror(errno));
return (PCAP_ERROR);
}
@@ -396,7 +414,7 @@ pcap_next_zbuf(pcap_t *p, int *cc)
* data.
*/
if (ioctl(p->fd, BIOCROTZBUF, &bz) < 0) {
- (void) snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
+ (void) pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
"BIOCROTZBUF: %s", strerror(errno));
return (PCAP_ERROR);
}
@@ -421,11 +439,11 @@ pcap_ack_zbuf(pcap_t *p)
#endif /* HAVE_ZEROCOPY_BPF */
pcap_t *
-pcap_create_interface(const char *device, char *ebuf)
+pcap_create_interface(const char *device _U_, char *ebuf)
{
pcap_t *p;
- p = pcap_create_common(device, ebuf, sizeof (struct pcap_bpf));
+ p = pcap_create_common(ebuf, sizeof (struct pcap_bpf));
if (p == NULL)
return (NULL);
@@ -455,7 +473,7 @@ pcap_create_interface(const char *device, char *ebuf)
* On failure, returns a PCAP_ERROR_ value, and sets p->errbuf.
*/
static int
-bpf_open(pcap_t *p)
+bpf_open(char *errbuf)
{
int fd;
#ifdef HAVE_CLONING_BPF
@@ -471,7 +489,7 @@ bpf_open(pcap_t *p)
* and create the BPF device entries, if they don't
* already exist.
*/
- if (bpf_load(p->errbuf) == PCAP_ERROR)
+ if (bpf_load(errbuf) == PCAP_ERROR)
return (PCAP_ERROR);
#endif
@@ -482,7 +500,7 @@ bpf_open(pcap_t *p)
fd = PCAP_ERROR_PERM_DENIED;
else
fd = PCAP_ERROR;
- snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
+ pcap_snprintf(errbuf, PCAP_ERRBUF_SIZE,
"(cannot open device) %s: %s", device, pcap_strerror(errno));
}
#else
@@ -490,7 +508,7 @@ bpf_open(pcap_t *p)
* Go through all the minors and find one that isn't in use.
*/
do {
- (void)snprintf(device, sizeof(device), "/dev/bpf%d", n++);
+ (void)pcap_snprintf(device, sizeof(device), "/dev/bpf%d", n++);
/*
* Initially try a read/write open (to allow the inject
* method to work). If that fails due to permission
@@ -524,7 +542,7 @@ bpf_open(pcap_t *p)
* means we probably have no BPF
* devices.
*/
- snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
+ pcap_snprintf(errbuf, PCAP_ERRBUF_SIZE,
"(there are no BPF devices)");
} else {
/*
@@ -533,7 +551,7 @@ bpf_open(pcap_t *p)
* devices, but all the ones
* that exist are busy.
*/
- snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
+ pcap_snprintf(errbuf, PCAP_ERRBUF_SIZE,
"(all BPF devices are busy)");
}
break;
@@ -545,7 +563,7 @@ bpf_open(pcap_t *p)
* if any.
*/
fd = PCAP_ERROR_PERM_DENIED;
- snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
+ pcap_snprintf(errbuf, PCAP_ERRBUF_SIZE,
"(cannot open BPF device) %s: %s", device,
pcap_strerror(errno));
break;
@@ -555,7 +573,7 @@ bpf_open(pcap_t *p)
* Some other problem.
*/
fd = PCAP_ERROR;
- snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
+ pcap_snprintf(errbuf, PCAP_ERRBUF_SIZE,
"(cannot open BPF device) %s: %s", device,
pcap_strerror(errno));
break;
@@ -566,6 +584,66 @@ bpf_open(pcap_t *p)
return (fd);
}
+/*
+ * Open and bind to a device; used if we're not actually going to use
+ * the device, but are just testing whether it can be opened, or opening
+ * it to get information about it.
+ *
+ * Returns an error code on failure (always negative), and an FD for
+ * the now-bound BPF device on success (always non-negative).
+ */
+static int
+bpf_open_and_bind(const char *name, char *errbuf)
+{
+ int fd;
+ struct ifreq ifr;
+
+ /*
+ * First, open a BPF device.
+ */
+ fd = bpf_open(errbuf);
+ if (fd < 0)
+ return (fd); /* fd is the appropriate error code */
+
+ /*
+ * Now bind to the device.
+ */
+ (void)strncpy(ifr.ifr_name, name, sizeof(ifr.ifr_name));
+ if (ioctl(fd, BIOCSETIF, (caddr_t)&ifr) < 0) {
+ switch (errno) {
+
+ case ENXIO:
+ /*
+ * There's no such device.
+ */
+ close(fd);
+ return (PCAP_ERROR_NO_SUCH_DEVICE);
+
+ case ENETDOWN:
+ /*
+ * Return a "network down" indication, so that
+ * the application can report that rather than
+ * saying we had a mysterious failure and
+ * suggest that they report a problem to the
+ * libpcap developers.
+ */
+ close(fd);
+ return (PCAP_ERROR_IFACE_NOT_UP);
+
+ default:
+ pcap_snprintf(errbuf, PCAP_ERRBUF_SIZE,
+ "BIOCSETIF: %s: %s", name, pcap_strerror(errno));
+ close(fd);
+ return (PCAP_ERROR);
+ }
+ }
+
+ /*
+ * Success.
+ */
+ return (fd);
+}
+
#ifdef BIOCGDLTLIST
static int
get_dlt_list(int fd, int v, struct bpf_dltlist *bdlp, char *ebuf)
@@ -577,13 +655,13 @@ get_dlt_list(int fd, int v, struct bpf_dltlist *bdlp, char *ebuf)
bdlp->bfl_list = (u_int *) malloc(sizeof(u_int) * (bdlp->bfl_len + 1));
if (bdlp->bfl_list == NULL) {
- (void)snprintf(ebuf, PCAP_ERRBUF_SIZE, "malloc: %s",
+ (void)pcap_snprintf(ebuf, PCAP_ERRBUF_SIZE, "malloc: %s",
pcap_strerror(errno));
return (PCAP_ERROR);
}
if (ioctl(fd, BIOCGDLTLIST, (caddr_t)bdlp) < 0) {
- (void)snprintf(ebuf, PCAP_ERRBUF_SIZE,
+ (void)pcap_snprintf(ebuf, PCAP_ERRBUF_SIZE,
"BIOCGDLTLIST: %s", pcap_strerror(errno));
free(bdlp->bfl_list);
return (PCAP_ERROR);
@@ -638,7 +716,7 @@ get_dlt_list(int fd, int v, struct bpf_dltlist *bdlp, char *ebuf)
* this device"; don't treat it as an error.
*/
if (errno != EINVAL) {
- (void)snprintf(ebuf, PCAP_ERRBUF_SIZE,
+ (void)pcap_snprintf(ebuf, PCAP_ERRBUF_SIZE,
"BIOCGDLTLIST: %s", pcap_strerror(errno));
return (PCAP_ERROR);
}
@@ -697,7 +775,7 @@ pcap_can_set_rfmon_bpf(pcap_t *p)
* 10.4 (Darwin 8.x). s/en/wlt/, and check
* whether the device exists.
*/
- if (strncmp(p->opt.source, "en", 2) != 0) {
+ if (strncmp(p->opt.device, "en", 2) != 0) {
/*
* Not an enN device; no monitor mode.
*/
@@ -705,12 +783,12 @@ pcap_can_set_rfmon_bpf(pcap_t *p)
}
fd = socket(AF_INET, SOCK_DGRAM, 0);
if (fd == -1) {
- (void)snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
+ (void)pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
"socket: %s", pcap_strerror(errno));
return (PCAP_ERROR);
}
strlcpy(ifr.ifr_name, "wlt", sizeof(ifr.ifr_name));
- strlcat(ifr.ifr_name, p->opt.source + 2, sizeof(ifr.ifr_name));
+ strlcat(ifr.ifr_name, p->opt.device + 2, sizeof(ifr.ifr_name));
if (ioctl(fd, SIOCGIFFLAGS, (char *)&ifr) < 0) {
/*
* No such device?
@@ -730,14 +808,14 @@ pcap_can_set_rfmon_bpf(pcap_t *p)
*
* First, open a BPF device.
*/
- fd = bpf_open(p);
+ fd = bpf_open(p->errbuf);
if (fd < 0)
return (fd); /* fd is the appropriate error code */
/*
* Now bind to the device.
*/
- (void)strncpy(ifr.ifr_name, p->opt.source, sizeof(ifr.ifr_name));
+ (void)strncpy(ifr.ifr_name, p->opt.device, sizeof(ifr.ifr_name));
if (ioctl(fd, BIOCSETIF, (caddr_t)&ifr) < 0) {
switch (errno) {
@@ -760,9 +838,9 @@ pcap_can_set_rfmon_bpf(pcap_t *p)
return (PCAP_ERROR_IFACE_NOT_UP);
default:
- snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
+ pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
"BIOCSETIF: %s: %s",
- p->opt.source, pcap_strerror(errno));
+ p->opt.device, pcap_strerror(errno));
close(fd);
return (PCAP_ERROR);
}
@@ -788,6 +866,7 @@ pcap_can_set_rfmon_bpf(pcap_t *p)
return (1);
}
free(bdl.bfl_list);
+ close(fd);
#endif /* BIOCGDLTLIST */
return (0);
#elif defined(HAVE_BSD_IEEE80211)
@@ -823,7 +902,7 @@ pcap_stats_bpf(pcap_t *p, struct pcap_stat *ps)
* by libpcap, and thus not yet seen by the application.
*/
if (ioctl(p->fd, BIOCGSTATS, (caddr_t)&s) < 0) {
- snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "BIOCGSTATS: %s",
+ pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "BIOCGSTATS: %s",
pcap_strerror(errno));
return (PCAP_ERROR);
}
@@ -843,7 +922,7 @@ pcap_read_bpf(pcap_t *p, int cnt, pcap_handler callback, u_char *user)
register u_char *bp, *ep;
u_char *datap;
#ifdef PCAP_FDDIPAD
- register int pad;
+ register u_int pad;
#endif
#ifdef HAVE_ZEROCOPY_BPF
int i;
@@ -884,7 +963,7 @@ pcap_read_bpf(pcap_t *p, int cnt, pcap_handler callback, u_char *user)
} else
#endif
{
- cc = read(p->fd, (char *)p->buffer, p->bufsize);
+ cc = read(p->fd, p->buffer, p->bufsize);
}
if (cc < 0) {
/* Don't choke when we get ptraced */
@@ -932,7 +1011,7 @@ pcap_read_bpf(pcap_t *p, int cnt, pcap_handler callback, u_char *user)
* pcap_dispatch() etc. aren't
* defined to retur that.
*/
- snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
+ pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
"The interface went down");
return (PCAP_ERROR);
@@ -951,11 +1030,11 @@ pcap_read_bpf(pcap_t *p, int cnt, pcap_handler callback, u_char *user)
/* fall through */
#endif
}
- snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "read: %s",
+ pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "read: %s",
pcap_strerror(errno));
return (PCAP_ERROR);
}
- bp = p->buffer;
+ bp = (u_char *)p->buffer;
} else
bp = p->bp;
@@ -972,7 +1051,7 @@ pcap_read_bpf(pcap_t *p, int cnt, pcap_handler callback, u_char *user)
pad = p->fddipad;
#endif
while (bp < ep) {
- register int caplen, hdrlen;
+ register u_int caplen, hdrlen;
/*
* Has "pcap_breakloop()" been called?
@@ -1125,7 +1204,7 @@ pcap_inject_bpf(pcap_t *p, const void *buf, size_t size)
u_int spoof_eth_src = 0;
if (ioctl(p->fd, BIOCSHDRCMPLT, &spoof_eth_src) == -1) {
- (void)snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
+ (void)pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
"send: can't turn off BIOCSHDRCMPLT: %s",
pcap_strerror(errno));
return (PCAP_ERROR);
@@ -1138,7 +1217,7 @@ pcap_inject_bpf(pcap_t *p, const void *buf, size_t size)
}
#endif /* __APPLE__ */
if (ret == -1) {
- snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "send: %s",
+ pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "send: %s",
pcap_strerror(errno));
return (PCAP_ERROR);
}
@@ -1154,7 +1233,7 @@ bpf_odminit(char *errbuf)
if (odm_initialize() == -1) {
if (odm_err_msg(odmerrno, &errstr) == -1)
errstr = "Unknown error";
- snprintf(errbuf, PCAP_ERRBUF_SIZE,
+ pcap_snprintf(errbuf, PCAP_ERRBUF_SIZE,
"bpf_load: odm_initialize failed: %s",
errstr);
return (PCAP_ERROR);
@@ -1163,7 +1242,7 @@ bpf_odminit(char *errbuf)
if ((odmlockid = odm_lock("/etc/objrepos/config_lock", ODM_WAIT)) == -1) {
if (odm_err_msg(odmerrno, &errstr) == -1)
errstr = "Unknown error";
- snprintf(errbuf, PCAP_ERRBUF_SIZE,
+ pcap_snprintf(errbuf, PCAP_ERRBUF_SIZE,
"bpf_load: odm_lock of /etc/objrepos/config_lock failed: %s",
errstr);
(void)odm_terminate();
@@ -1182,7 +1261,7 @@ bpf_odmcleanup(char *errbuf)
if (errbuf != NULL) {
if (odm_err_msg(odmerrno, &errstr) == -1)
errstr = "Unknown error";
- snprintf(errbuf, PCAP_ERRBUF_SIZE,
+ pcap_snprintf(errbuf, PCAP_ERRBUF_SIZE,
"bpf_load: odm_unlock failed: %s",
errstr);
}
@@ -1193,7 +1272,7 @@ bpf_odmcleanup(char *errbuf)
if (errbuf != NULL) {
if (odm_err_msg(odmerrno, &errstr) == -1)
errstr = "Unknown error";
- snprintf(errbuf, PCAP_ERRBUF_SIZE,
+ pcap_snprintf(errbuf, PCAP_ERRBUF_SIZE,
"bpf_load: odm_terminate failed: %s",
errstr);
}
@@ -1227,7 +1306,7 @@ bpf_load(char *errbuf)
major = genmajor(BPF_NAME);
if (major == -1) {
- snprintf(errbuf, PCAP_ERRBUF_SIZE,
+ pcap_snprintf(errbuf, PCAP_ERRBUF_SIZE,
"bpf_load: genmajor failed: %s", pcap_strerror(errno));
(void)bpf_odmcleanup(NULL);
return (PCAP_ERROR);
@@ -1237,7 +1316,7 @@ bpf_load(char *errbuf)
if (!minors) {
minors = genminor("bpf", major, 0, BPF_MINORS, 1, 1);
if (!minors) {
- snprintf(errbuf, PCAP_ERRBUF_SIZE,
+ pcap_snprintf(errbuf, PCAP_ERRBUF_SIZE,
"bpf_load: genminor failed: %s",
pcap_strerror(errno));
(void)bpf_odmcleanup(NULL);
@@ -1250,7 +1329,7 @@ bpf_load(char *errbuf)
rc = stat(BPF_NODE "0", &sbuf);
if (rc == -1 && errno != ENOENT) {
- snprintf(errbuf, PCAP_ERRBUF_SIZE,
+ pcap_snprintf(errbuf, PCAP_ERRBUF_SIZE,
"bpf_load: can't stat %s: %s",
BPF_NODE "0", pcap_strerror(errno));
return (PCAP_ERROR);
@@ -1261,7 +1340,7 @@ bpf_load(char *errbuf)
sprintf(buf, "%s%d", BPF_NODE, i);
unlink(buf);
if (mknod(buf, S_IRUSR | S_IFCHR, domakedev(major, i)) == -1) {
- snprintf(errbuf, PCAP_ERRBUF_SIZE,
+ pcap_snprintf(errbuf, PCAP_ERRBUF_SIZE,
"bpf_load: can't mknod %s: %s",
buf, pcap_strerror(errno));
return (PCAP_ERROR);
@@ -1277,7 +1356,7 @@ bpf_load(char *errbuf)
(cfg_ld.kmid == 0)) {
/* Driver isn't loaded, load it now */
if (sysconfig(SYS_SINGLELOAD, (void *)&cfg_ld, sizeof(cfg_ld)) == -1) {
- snprintf(errbuf, PCAP_ERRBUF_SIZE,
+ pcap_snprintf(errbuf, PCAP_ERRBUF_SIZE,
"bpf_load: could not load driver: %s",
strerror(errno));
return (PCAP_ERROR);
@@ -1292,7 +1371,7 @@ bpf_load(char *errbuf)
for (i = 0; i < BPF_MINORS; i++) {
cfg_bpf.devno = domakedev(major, i);
if (sysconfig(SYS_CFGKMOD, (void *)&cfg_km, sizeof(cfg_km)) == -1) {
- snprintf(errbuf, PCAP_ERRBUF_SIZE,
+ pcap_snprintf(errbuf, PCAP_ERRBUF_SIZE,
"bpf_load: could not configure driver: %s",
strerror(errno));
return (PCAP_ERROR);
@@ -1306,7 +1385,7 @@ bpf_load(char *errbuf)
#endif
/*
- * Turn off rfmon mode if necessary.
+ * Undo any operations done when opening the device when necessary.
*/
static void
pcap_cleanup_bpf(pcap_t *p)
@@ -1374,6 +1453,24 @@ pcap_cleanup_bpf(pcap_t *p)
}
#endif /* HAVE_BSD_IEEE80211 */
+#if defined(__FreeBSD__) && defined(SIOCIFCREATE2)
+ /*
+ * Attempt to destroy the usbusN interface that we created.
+ */
+ if (pb->must_do_on_close & MUST_DESTROY_USBUS) {
+ if (if_nametoindex(pb->device) > 0) {
+ int s;
+
+ s = socket(AF_LOCAL, SOCK_DGRAM, 0);
+ if (s >= 0) {
+ strlcpy(ifr.ifr_name, pb->device,
+ sizeof(ifr.ifr_name));
+ ioctl(s, SIOCIFDESTROY, &ifr);
+ close(s);
+ }
+ }
+ }
+#endif /* defined(__FreeBSD__) && defined(SIOCIFCREATE2) */
/*
* Take this pcap out of the list of pcaps for which we
* have to take the interface out of some mode.
@@ -1420,7 +1517,7 @@ check_setif_failure(pcap_t *p, int error)
* No such device exists.
*/
#ifdef __APPLE__
- if (p->opt.rfmon && strncmp(p->opt.source, "wlt", 3) == 0) {
+ if (p->opt.rfmon && strncmp(p->opt.device, "wlt", 3) == 0) {
/*
* Monitor mode was requested, and we're trying
* to open a "wltN" device. Assume that this
@@ -1432,7 +1529,7 @@ check_setif_failure(pcap_t *p, int error)
if (fd != -1) {
strlcpy(ifr.ifr_name, "en",
sizeof(ifr.ifr_name));
- strlcat(ifr.ifr_name, p->opt.source + 3,
+ strlcat(ifr.ifr_name, p->opt.device + 3,
sizeof(ifr.ifr_name));
if (ioctl(fd, SIOCGIFFLAGS, (char *)&ifr) < 0) {
/*
@@ -1441,7 +1538,7 @@ check_setif_failure(pcap_t *p, int error)
* exist.
*/
err = PCAP_ERROR_NO_SUCH_DEVICE;
- snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
+ pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
"SIOCGIFFLAGS on %s failed: %s",
ifr.ifr_name, pcap_strerror(errno));
} else {
@@ -1465,7 +1562,7 @@ check_setif_failure(pcap_t *p, int error)
* just report "no such device".
*/
err = PCAP_ERROR_NO_SUCH_DEVICE;
- snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
+ pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
"socket() failed: %s",
pcap_strerror(errno));
}
@@ -1475,7 +1572,7 @@ check_setif_failure(pcap_t *p, int error)
/*
* No such device.
*/
- snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "BIOCSETIF failed: %s",
+ pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "BIOCSETIF failed: %s",
pcap_strerror(errno));
return (PCAP_ERROR_NO_SUCH_DEVICE);
} else if (errno == ENETDOWN) {
@@ -1492,8 +1589,8 @@ check_setif_failure(pcap_t *p, int error)
* Some other error; fill in the error string, and
* return PCAP_ERROR.
*/
- snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "BIOCSETIF: %s: %s",
- p->opt.source, pcap_strerror(errno));
+ pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "BIOCSETIF: %s: %s",
+ p->opt.device, pcap_strerror(errno));
return (PCAP_ERROR);
}
}
@@ -1565,7 +1662,7 @@ pcap_activate_bpf(pcap_t *p)
u_int bufmode, zbufmax;
#endif
- fd = bpf_open(p);
+ fd = bpf_open(p->errbuf);
if (fd < 0) {
status = fd;
goto bad;
@@ -1574,14 +1671,14 @@ pcap_activate_bpf(pcap_t *p)
p->fd = fd;
if (ioctl(fd, BIOCVERSION, (caddr_t)&bv) < 0) {
- snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "BIOCVERSION: %s",
+ pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "BIOCVERSION: %s",
pcap_strerror(errno));
status = PCAP_ERROR;
goto bad;
}
if (bv.bv_major != BPF_MAJOR_VERSION ||
bv.bv_minor < BPF_MINOR_VERSION) {
- snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
+ pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
"kernel bpf filter out of date");
status = PCAP_ERROR;
goto bad;
@@ -1589,30 +1686,57 @@ pcap_activate_bpf(pcap_t *p)
#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.
+ * Retrieve the zoneid of the zone we are currently executing in.
*/
- if ((zonesep = strchr(p->opt.source, '/')) != NULL) {
- char zonename[ZONENAME_MAX];
+ if ((ifr.lifr_zoneid = getzoneid()) == -1) {
+ pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "getzoneid(): %s",
+ pcap_strerror(errno));
+ status = PCAP_ERROR;
+ goto bad;
+ }
+ /*
+ * Check if the given source datalink name has a '/' separated
+ * zonename prefix string. The zonename prefixed source datalink can
+ * be used by pcap consumers in the Solaris global zone to capture
+ * traffic on datalinks in non-global zones. Non-global zones
+ * do not have access to datalinks outside of their own namespace.
+ */
+ if ((zonesep = strchr(p->opt.device, '/')) != NULL) {
+ char path_zname[ZONENAME_MAX];
int znamelen;
char *lnamep;
- znamelen = zonesep - p->opt.source;
- (void) strlcpy(zonename, p->opt.source, znamelen + 1);
+ if (ifr.lifr_zoneid != GLOBAL_ZONEID) {
+ pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
+ "zonename/linkname only valid in global zone.");
+ status = PCAP_ERROR;
+ goto bad;
+ }
+ znamelen = zonesep - p->opt.device;
+ (void) strlcpy(path_zname, p->opt.device, znamelen + 1);
+ ifr.lifr_zoneid = getzoneidbyname(path_zname);
+ if (ifr.lifr_zoneid == -1) {
+ pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
+ "getzoneidbyname(%s): %s", path_zname,
+ pcap_strerror(errno));
+ status = PCAP_ERROR;
+ goto bad;
+ }
lnamep = strdup(zonesep + 1);
- ifr.lifr_zoneid = getzoneidbyname(zonename);
- free(p->opt.source);
- p->opt.source = lnamep;
+ if (lnamep == NULL) {
+ pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "strdup: %s",
+ pcap_strerror(errno));
+ status = PCAP_ERROR;
+ goto bad;
+ }
+ free(p->opt.device);
+ p->opt.device = lnamep;
}
#endif
- pb->device = strdup(p->opt.source);
+ pb->device = strdup(p->opt.device);
if (pb->device == NULL) {
- snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "strdup: %s",
+ pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "strdup: %s",
pcap_strerror(errno));
status = PCAP_ERROR;
goto bad;
@@ -1655,7 +1779,7 @@ pcap_activate_bpf(pcap_t *p)
/*
* 10.4 (Darwin 8.x). s/en/wlt/
*/
- if (strncmp(p->opt.source, "en", 2) != 0) {
+ if (strncmp(p->opt.device, "en", 2) != 0) {
/*
* Not an enN device; check
* whether the device even exists.
@@ -1663,7 +1787,7 @@ pcap_activate_bpf(pcap_t *p)
sockfd = socket(AF_INET, SOCK_DGRAM, 0);
if (sockfd != -1) {
strlcpy(ifrname,
- p->opt.source, ifnamsiz);
+ p->opt.device, ifnamsiz);
if (ioctl(sockfd, SIOCGIFFLAGS,
(char *)&ifr) < 0) {
/*
@@ -1674,7 +1798,7 @@ pcap_activate_bpf(pcap_t *p)
* exist.
*/
status = PCAP_ERROR_NO_SUCH_DEVICE;
- snprintf(p->errbuf,
+ pcap_snprintf(p->errbuf,
PCAP_ERRBUF_SIZE,
"SIOCGIFFLAGS failed: %s",
pcap_strerror(errno));
@@ -1688,25 +1812,25 @@ pcap_activate_bpf(pcap_t *p)
* report "no such device".
*/
status = PCAP_ERROR_NO_SUCH_DEVICE;
- snprintf(p->errbuf,
+ pcap_snprintf(p->errbuf,
PCAP_ERRBUF_SIZE,
"socket() failed: %s",
pcap_strerror(errno));
}
goto bad;
}
- wltdev = malloc(strlen(p->opt.source) + 2);
+ wltdev = malloc(strlen(p->opt.device) + 2);
if (wltdev == NULL) {
- (void)snprintf(p->errbuf,
+ (void)pcap_snprintf(p->errbuf,
PCAP_ERRBUF_SIZE, "malloc: %s",
pcap_strerror(errno));
status = PCAP_ERROR;
goto bad;
}
strcpy(wltdev, "wlt");
- strcat(wltdev, p->opt.source + 2);
- free(p->opt.source);
- p->opt.source = wltdev;
+ strcat(wltdev, p->opt.device + 2);
+ free(p->opt.device);
+ p->opt.device = wltdev;
}
/*
* Everything else is 10.5 or later; for those,
@@ -1715,6 +1839,85 @@ pcap_activate_bpf(pcap_t *p)
}
}
#endif /* __APPLE__ */
+
+ /*
+ * If this is FreeBSD, and the device name begins with "usbus",
+ * try to create the interface if it's not available.
+ */
+#if defined(__FreeBSD__) && defined(SIOCIFCREATE2)
+ if (strncmp(p->opt.device, usbus_prefix, USBUS_PREFIX_LEN) == 0) {
+ /*
+ * Do we already have an interface with that name?
+ */
+ if (if_nametoindex(p->opt.device) == 0) {
+ /*
+ * No. We need to create it, and, if we
+ * succeed, remember that we should destroy
+ * it when the pcap_t is closed.
+ */
+ int s;
+
+ /*
+ * Open a socket to use for ioctls to
+ * create the interface.
+ */
+ s = socket(AF_LOCAL, SOCK_DGRAM, 0);
+ if (s < 0) {
+ pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
+ "Can't open socket: %s",
+ pcap_strerror(errno));
+ status = PCAP_ERROR;
+ goto bad;
+ }
+
+ /*
+ * If we haven't already done so, arrange to have
+ * "pcap_close_all()" called when we exit.
+ */
+ if (!pcap_do_addexit(p)) {
+ /*
+ * "atexit()" failed; don't create the
+ * interface, just give up.
+ */
+ pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
+ "atexit failed");
+ close(s);
+ status = PCAP_ERROR;
+ goto bad;
+ }
+
+ /*
+ * Create the interface.
+ */
+ strlcpy(ifr.ifr_name, p->opt.device, sizeof(ifr.ifr_name));
+ if (ioctl(s, SIOCIFCREATE2, &ifr) < 0) {
+ if (errno == EINVAL) {
+ pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
+ "Invalid USB bus interface %s",
+ p->opt.device);
+ } else {
+ pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
+ "Can't create interface for %s: %s",
+ p->opt.device, pcap_strerror(errno));
+ }
+ close(s);
+ status = PCAP_ERROR;
+ goto bad;
+ }
+
+ /*
+ * Make sure we clean this up when we close.
+ */
+ pb->must_do_on_close |= MUST_DESTROY_USBUS;
+
+ /*
+ * Add this to the list of pcaps to close when we exit.
+ */
+ pcap_add_to_pcaps_to_close(p);
+ }
+ }
+#endif /* defined(__FreeBSD__) && defined(SIOCIFCREATE2) */
+
#ifdef HAVE_ZEROCOPY_BPF
/*
* If the BPF extension to set buffer mode is present, try setting
@@ -1738,7 +1941,7 @@ pcap_activate_bpf(pcap_t *p)
* size.
*/
if (ioctl(fd, BIOCGETZMAX, (caddr_t)&zbufmax) < 0) {
- snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "BIOCGETZMAX: %s",
+ pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "BIOCGETZMAX: %s",
pcap_strerror(errno));
status = PCAP_ERROR;
goto bad;
@@ -1765,7 +1968,7 @@ pcap_activate_bpf(pcap_t *p)
pb->zbuf2 = mmap(NULL, pb->zbufsize, PROT_READ | PROT_WRITE,
MAP_ANON, -1, 0);
if (pb->zbuf1 == MAP_FAILED || pb->zbuf2 == MAP_FAILED) {
- snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "mmap: %s",
+ pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "mmap: %s",
pcap_strerror(errno));
status = PCAP_ERROR;
goto bad;
@@ -1775,15 +1978,15 @@ pcap_activate_bpf(pcap_t *p)
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_snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "BIOCSETZBUF: %s",
pcap_strerror(errno));
status = PCAP_ERROR;
goto bad;
}
- (void)strncpy(ifrname, p->opt.source, ifnamsiz);
+ (void)strncpy(ifrname, p->opt.device, ifnamsiz);
if (ioctl(fd, BIOCSETIF, (caddr_t)&ifr) < 0) {
- snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "BIOCSETIF: %s: %s",
- p->opt.source, pcap_strerror(errno));
+ pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "BIOCSETIF: %s: %s",
+ p->opt.device, pcap_strerror(errno));
status = PCAP_ERROR;
goto bad;
}
@@ -1801,8 +2004,8 @@ pcap_activate_bpf(pcap_t *p)
*/
if (ioctl(fd, BIOCSBLEN,
(caddr_t)&p->opt.buffer_size) < 0) {
- snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
- "BIOCSBLEN: %s: %s", p->opt.source,
+ pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
+ "BIOCSBLEN: %s: %s", p->opt.device,
pcap_strerror(errno));
status = PCAP_ERROR;
goto bad;
@@ -1811,7 +2014,7 @@ pcap_activate_bpf(pcap_t *p)
/*
* Now bind to the device.
*/
- (void)strncpy(ifrname, p->opt.source, ifnamsiz);
+ (void)strncpy(ifrname, p->opt.device, ifnamsiz);
#ifdef BIOCSETLIF
if (ioctl(fd, BIOCSETLIF, (caddr_t)&ifr) < 0)
#else
@@ -1844,7 +2047,7 @@ pcap_activate_bpf(pcap_t *p)
*/
(void) ioctl(fd, BIOCSBLEN, (caddr_t)&v);
- (void)strncpy(ifrname, p->opt.source, ifnamsiz);
+ (void)strncpy(ifrname, p->opt.device, ifnamsiz);
#ifdef BIOCSETLIF
if (ioctl(fd, BIOCSETLIF, (caddr_t)&ifr) >= 0)
#else
@@ -1859,9 +2062,9 @@ pcap_activate_bpf(pcap_t *p)
}
if (v == 0) {
- snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
+ pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
"BIOCSBLEN: %s: No buffer size worked",
- p->opt.source);
+ p->opt.device);
status = PCAP_ERROR;
goto bad;
}
@@ -1871,7 +2074,7 @@ pcap_activate_bpf(pcap_t *p)
/* Get the data link layer type. */
if (ioctl(fd, BIOCGDLT, (caddr_t)&v) < 0) {
- snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "BIOCGDLT: %s",
+ pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "BIOCGDLT: %s",
pcap_strerror(errno));
status = PCAP_ERROR;
goto bad;
@@ -1904,7 +2107,7 @@ pcap_activate_bpf(pcap_t *p)
/*
* We don't know what to map this to yet.
*/
- snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "unknown interface type %u",
+ pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "unknown interface type %u",
v);
status = PCAP_ERROR;
goto bad;
@@ -1992,7 +2195,7 @@ pcap_activate_bpf(pcap_t *p)
* the default mode, attempt to
* select the new mode.
*/
- if (new_dlt != v) {
+ if ((u_int)new_dlt != v) {
if (ioctl(p->fd, BIOCSDLT,
&new_dlt) != -1) {
/*
@@ -2064,7 +2267,7 @@ pcap_activate_bpf(pcap_t *p)
* If the new mode we want isn't the default mode,
* attempt to select the new mode.
*/
- if (new_dlt != v) {
+ if ((u_int)new_dlt != v) {
if (ioctl(p->fd, BIOCSDLT, &new_dlt) != -1) {
/*
* We succeeded; make this the
@@ -2116,7 +2319,7 @@ pcap_activate_bpf(pcap_t *p)
* BSDs - check CVS log for "bpf.c"?
*/
if (ioctl(fd, BIOCSHDRCMPLT, &spoof_eth_src) == -1) {
- (void)snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
+ (void)pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
"BIOCSHDRCMPLT: %s", pcap_strerror(errno));
status = PCAP_ERROR;
goto bad;
@@ -2158,7 +2361,7 @@ pcap_activate_bpf(pcap_t *p)
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,
+ pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
"BIOCSRTIMEOUT: %s", pcap_strerror(errno));
status = PCAP_ERROR;
goto bad;
@@ -2168,7 +2371,7 @@ pcap_activate_bpf(pcap_t *p)
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,
+ pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
"BIOCSRTIMEOUT: %s", pcap_strerror(errno));
status = PCAP_ERROR;
goto bad;
@@ -2203,7 +2406,7 @@ pcap_activate_bpf(pcap_t *p)
#endif /* _AIX */
v = 1;
if (ioctl(p->fd, BIOCIMMEDIATE, &v) < 0) {
- snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
+ pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
"BIOCIMMEDIATE: %s", pcap_strerror(errno));
status = PCAP_ERROR;
goto bad;
@@ -2216,7 +2419,7 @@ pcap_activate_bpf(pcap_t *p)
/*
* We don't support immediate mode. Fail.
*/
- snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "Immediate mode not supported");
+ pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "Immediate mode not supported");
status = PCAP_ERROR;
goto bad;
}
@@ -2225,7 +2428,7 @@ pcap_activate_bpf(pcap_t *p)
if (p->opt.promisc) {
/* set promiscuous mode, just warn if it fails */
if (ioctl(p->fd, BIOCPROMISC, NULL) < 0) {
- snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "BIOCPROMISC: %s",
+ pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "BIOCPROMISC: %s",
pcap_strerror(errno));
status = PCAP_WARNING_PROMISC_NOTSUP;
}
@@ -2242,7 +2445,7 @@ pcap_activate_bpf(pcap_t *p)
#endif /* BIOCSTSTAMP */
if (ioctl(fd, BIOCGBLEN, (caddr_t)&v) < 0) {
- snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "BIOCGBLEN: %s",
+ pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "BIOCGBLEN: %s",
pcap_strerror(errno));
status = PCAP_ERROR;
goto bad;
@@ -2251,9 +2454,9 @@ pcap_activate_bpf(pcap_t *p)
#ifdef HAVE_ZEROCOPY_BPF
if (!pb->zerocopy) {
#endif
- p->buffer = (u_char *)malloc(p->bufsize);
+ p->buffer = malloc(p->bufsize);
if (p->buffer == NULL) {
- snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "malloc: %s",
+ pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "malloc: %s",
pcap_strerror(errno));
status = PCAP_ERROR;
goto bad;
@@ -2284,7 +2487,7 @@ pcap_activate_bpf(pcap_t *p)
total_prog.bf_len = 1;
total_prog.bf_insns = &total_insn;
if (ioctl(p->fd, BIOCSETF, (caddr_t)&total_prog) < 0) {
- snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "BIOCSETF: %s",
+ pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "BIOCSETF: %s",
pcap_strerror(errno));
status = PCAP_ERROR;
goto bad;
@@ -2354,9 +2557,136 @@ pcap_activate_bpf(pcap_t *p)
return (status);
}
+/*
+ * Not all interfaces can be bound to by BPF, so try to bind to
+ * the specified interface; return 0 if we fail with
+ * PCAP_ERROR_NO_SUCH_DEVICE (which means we got an ENXIO when we tried
+ * to bind, which means this interface isn't in the list of interfaces
+ * attached to BPF) and 1 otherwise.
+ */
+static int
+check_bpf_bindable(const char *name)
+{
+ int fd;
+ char errbuf[PCAP_ERRBUF_SIZE];
+
+ fd = bpf_open_and_bind(name, errbuf);
+ if (fd < 0) {
+ /*
+ * Error - was it PCAP_ERROR_NO_SUCH_DEVICE?
+ */
+ if (fd == PCAP_ERROR_NO_SUCH_DEVICE) {
+ /*
+ * Yes, so we can't bind to this because it's
+ * not something supported by BPF.
+ */
+ return (0);
+ }
+ /*
+ * No, so we don't know whether it's supported or not;
+ * say it is, so that the user can at least try to
+ * open it and report the error (which is probably
+ * "you don't have permission to open BPF devices";
+ * reporting those interfaces means users will ask
+ * "why am I getting a permissions error when I try
+ * to capture" rather than "why am I not seeing any
+ * interfaces", making the underlying problem clearer).
+ */
+ return (1);
+ }
+
+ /*
+ * Success.
+ */
+ close(fd);
+ return (1);
+}
+
+#if defined(__FreeBSD__) && defined(SIOCIFCREATE2)
+static int
+finddevs_usb(pcap_if_t **alldevsp, char *errbuf)
+{
+ DIR *usbdir;
+ struct dirent *usbitem;
+ size_t name_max;
+ char *name;
+
+ /*
+ * We might have USB sniffing support, so try looking for USB
+ * interfaces.
+ *
+ * We want to report a usbusN device for each USB bus, but
+ * usbusN interfaces might, or might not, exist for them -
+ * we create one if there isn't already one.
+ *
+ * So, instead, we look in /dev/usb for all buses and create
+ * a "usbusN" device for each one.
+ */
+ usbdir = opendir("/dev/usb");
+ if (usbdir == NULL) {
+ /*
+ * Just punt.
+ */
+ return (0);
+ }
+
+ /*
+ * Leave enough room for a 32-bit (10-digit) bus number.
+ * Yes, that's overkill, but we won't be using
+ * the buffer very long.
+ */
+ name_max = USBUS_PREFIX_LEN + 10 + 1;
+ name = malloc(name_max);
+ if (name == NULL) {
+ closedir(usbdir);
+ return (0);
+ }
+ while ((usbitem = readdir(usbdir)) != NULL) {
+ char *p;
+ size_t busnumlen;
+ int err;
+
+ if (strcmp(usbitem->d_name, ".") == 0 ||
+ strcmp(usbitem->d_name, "..") == 0) {
+ /*
+ * Ignore these.
+ */
+ continue;
+ }
+ p = strchr(usbitem->d_name, '.');
+ if (p == NULL)
+ continue;
+ busnumlen = p - usbitem->d_name;
+ memcpy(name, usbus_prefix, USBUS_PREFIX_LEN);
+ memcpy(name + USBUS_PREFIX_LEN, usbitem->d_name, busnumlen);
+ *(name + USBUS_PREFIX_LEN + busnumlen) = '\0';
+ err = pcap_add_if(alldevsp, name, PCAP_IF_UP, NULL, errbuf);
+ if (err != 0) {
+ free(name);
+ closedir(usbdir);
+ return (err);
+ }
+ }
+ free(name);
+ closedir(usbdir);
+ return (0);
+}
+#endif
+
int
pcap_platform_finddevs(pcap_if_t **alldevsp, char *errbuf)
{
+ /*
+ * Get the list of regular interfaces first.
+ */
+ if (pcap_findalldevs_interfaces(alldevsp, errbuf, check_bpf_bindable) == -1)
+ return (-1); /* failure */
+
+#if defined(__FreeBSD__) && defined(SIOCIFCREATE2)
+ if (finddevs_usb(alldevsp, errbuf) == -1)
+ return (-1);
+#endif
+
return (0);
}
@@ -2367,20 +2697,20 @@ monitor_mode(pcap_t *p, int set)
struct pcap_bpf *pb = p->priv;
int sock;
struct ifmediareq req;
- int *media_list;
+ IFM_ULIST_TYPE *media_list;
int i;
int can_do;
struct ifreq ifr;
sock = socket(AF_INET, SOCK_DGRAM, 0);
if (sock == -1) {
- snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "can't open socket: %s",
+ pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "can't open socket: %s",
pcap_strerror(errno));
return (PCAP_ERROR);
}
memset(&req, 0, sizeof req);
- strncpy(req.ifm_name, p->opt.source, sizeof req.ifm_name);
+ strncpy(req.ifm_name, p->opt.device, sizeof req.ifm_name);
/*
* Find out how many media types we have.
@@ -2406,7 +2736,7 @@ monitor_mode(pcap_t *p, int set)
return (PCAP_ERROR_RFMON_NOTSUP);
default:
- snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
+ pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
"SIOCGIFMEDIA 1: %s", pcap_strerror(errno));
close(sock);
return (PCAP_ERROR);
@@ -2424,16 +2754,16 @@ monitor_mode(pcap_t *p, int set)
* Allocate a buffer to hold all the media types, and
* get the media types.
*/
- media_list = malloc(req.ifm_count * sizeof(int));
+ media_list = malloc(req.ifm_count * sizeof(*media_list));
if (media_list == NULL) {
- snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "malloc: %s",
+ pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "malloc: %s",
pcap_strerror(errno));
close(sock);
return (PCAP_ERROR);
}
req.ifm_ulist = media_list;
if (ioctl(sock, SIOCGIFMEDIA, &req) < 0) {
- snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "SIOCGIFMEDIA: %s",
+ pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "SIOCGIFMEDIA: %s",
pcap_strerror(errno));
free(media_list);
close(sock);
@@ -2486,17 +2816,15 @@ monitor_mode(pcap_t *p, int set)
* "atexit()" failed; don't put the interface
* in monitor mode, just give up.
*/
- snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
- "atexit failed");
close(sock);
return (PCAP_ERROR);
}
memset(&ifr, 0, sizeof(ifr));
- (void)strncpy(ifr.ifr_name, p->opt.source,
+ (void)strncpy(ifr.ifr_name, p->opt.device,
sizeof(ifr.ifr_name));
ifr.ifr_media = req.ifm_current | IFM_IEEE80211_MONITOR;
if (ioctl(sock, SIOCSIFMEDIA, &ifr) == -1) {
- snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
+ pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
"SIOCSIFMEDIA: %s", pcap_strerror(errno));
close(sock);
return (PCAP_ERROR);
@@ -2529,7 +2857,7 @@ static int
find_802_11(struct bpf_dltlist *bdlp)
{
int new_dlt;
- int i;
+ u_int i;
/*
* Scan the list of DLT_ values, looking for 802.11 values,
@@ -2721,7 +3049,7 @@ pcap_setfilter_bpf(pcap_t *p, struct bpf_program *fp)
* some kernels.
*/
if (errno != EINVAL) {
- snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "BIOCSETF: %s",
+ pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "BIOCSETF: %s",
pcap_strerror(errno));
return (-1);
}
@@ -2750,7 +3078,7 @@ pcap_setdirection_bpf(pcap_t *p, pcap_direction_t d)
direction = (d == PCAP_D_IN) ? BPF_D_IN :
((d == PCAP_D_OUT) ? BPF_D_OUT : BPF_D_INOUT);
if (ioctl(p->fd, BIOCSDIRECTION, &direction) == -1) {
- (void) snprintf(p->errbuf, sizeof(p->errbuf),
+ (void) pcap_snprintf(p->errbuf, sizeof(p->errbuf),
"Cannot set direction to %s: %s",
(d == PCAP_D_IN) ? "PCAP_D_IN" :
((d == PCAP_D_OUT) ? "PCAP_D_OUT" : "PCAP_D_INOUT"),
@@ -2765,14 +3093,14 @@ pcap_setdirection_bpf(pcap_t *p, pcap_direction_t d)
* We don't support PCAP_D_OUT.
*/
if (d == PCAP_D_OUT) {
- snprintf(p->errbuf, sizeof(p->errbuf),
+ pcap_snprintf(p->errbuf, sizeof(p->errbuf),
"Setting direction to PCAP_D_OUT is not supported on BPF");
return -1;
}
seesent = (d == PCAP_D_INOUT);
if (ioctl(p->fd, BIOCSSEESENT, &seesent) == -1) {
- (void) snprintf(p->errbuf, sizeof(p->errbuf),
+ (void) pcap_snprintf(p->errbuf, sizeof(p->errbuf),
"Cannot set direction to %s: %s",
(d == PCAP_D_INOUT) ? "PCAP_D_INOUT" : "PCAP_D_IN",
strerror(errno));
@@ -2780,7 +3108,7 @@ pcap_setdirection_bpf(pcap_t *p, pcap_direction_t d)
}
return (0);
#else
- (void) snprintf(p->errbuf, sizeof(p->errbuf),
+ (void) pcap_snprintf(p->errbuf, sizeof(p->errbuf),
"This system doesn't support BIOCSSEESENT, so the direction can't be set");
return (-1);
#endif
@@ -2791,7 +3119,7 @@ pcap_set_datalink_bpf(pcap_t *p, int dlt)
{
#ifdef BIOCSDLT
if (ioctl(p->fd, BIOCSDLT, &dlt) == -1) {
- (void) snprintf(p->errbuf, sizeof(p->errbuf),
+ (void) pcap_snprintf(p->errbuf, sizeof(p->errbuf),
"Cannot set DLT %d: %s", dlt, strerror(errno));
return (-1);
}
diff --git a/contrib/libpcap/pcap-bpf.h b/contrib/libpcap/pcap-bpf.h
index 937452293362..ebb64c3f96fa 100644
--- a/contrib/libpcap/pcap-bpf.h
+++ b/contrib/libpcap/pcap-bpf.h
@@ -4,7 +4,7 @@
*
* This code is derived from the Stanford/CMU enet packet filter,
* (net/enet.c) distributed as part of 4.3BSD, and code contributed
- * to Berkeley by Steven McCanne and Van Jacobson both of Lawrence
+ * to Berkeley by Steven McCanne and Van Jacobson both of Lawrence
* Berkeley Laboratory.
*
* Redistribution and use in source and binary forms, with or without
diff --git a/contrib/libpcap/pcap-bt-linux.c b/contrib/libpcap/pcap-bt-linux.c
index a32691d348c3..4452fe44e379 100644
--- a/contrib/libpcap/pcap-bt-linux.c
+++ b/contrib/libpcap/pcap-bt-linux.c
@@ -11,8 +11,8 @@
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
- * 3. The name of the author may not be used to endorse or promote
- * products derived from this software without specific prior written
+ * 3. The name of the author may not be used to endorse or promote
+ * products derived from this software without specific prior written
* permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
@@ -31,7 +31,7 @@
* By Paolo Abeni <paolo.abeni@email.it>
*
*/
-
+
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
@@ -73,7 +73,7 @@ struct pcap_bt {
int dev_id; /* device ID of device we're bound to */
};
-int
+int
bt_findalldevs(pcap_if_t **alldevsp, char *err_str)
{
struct hci_dev_list_req *dev_list;
@@ -84,18 +84,18 @@ bt_findalldevs(pcap_if_t **alldevsp, char *err_str)
sock = socket(AF_BLUETOOTH, SOCK_RAW, BTPROTO_HCI);
if (sock < 0)
{
- /* if bluetooth is not supported this this is not fatal*/
+ /* if bluetooth is not supported this this is not fatal*/
if (errno == EAFNOSUPPORT)
return 0;
- snprintf(err_str, PCAP_ERRBUF_SIZE,
+ pcap_snprintf(err_str, PCAP_ERRBUF_SIZE,
"Can't open raw Bluetooth socket: %s", strerror(errno));
return -1;
}
dev_list = malloc(HCI_MAX_DEV * sizeof(*dev_req) + sizeof(*dev_list));
- if (!dev_list)
+ if (!dev_list)
{
- snprintf(err_str, PCAP_ERRBUF_SIZE, "Can't allocate %zu bytes for Bluetooth device list",
+ pcap_snprintf(err_str, PCAP_ERRBUF_SIZE, "Can't allocate %zu bytes for Bluetooth device list",
HCI_MAX_DEV * sizeof(*dev_req) + sizeof(*dev_list));
ret = -1;
goto done;
@@ -103,9 +103,9 @@ bt_findalldevs(pcap_if_t **alldevsp, char *err_str)
dev_list->dev_num = HCI_MAX_DEV;
- if (ioctl(sock, HCIGETDEVLIST, (void *) dev_list) < 0)
+ if (ioctl(sock, HCIGETDEVLIST, (void *) dev_list) < 0)
{
- snprintf(err_str, PCAP_ERRBUF_SIZE,
+ pcap_snprintf(err_str, PCAP_ERRBUF_SIZE,
"Can't get Bluetooth device list via ioctl: %s",
strerror(errno));
ret = -1;
@@ -115,11 +115,11 @@ bt_findalldevs(pcap_if_t **alldevsp, char *err_str)
dev_req = dev_list->dev_req;
for (i = 0; i < dev_list->dev_num; i++, dev_req++) {
char dev_name[20], dev_descr[30];
-
- snprintf(dev_name, 20, BT_IFACE"%d", dev_req->dev_id);
- snprintf(dev_descr, 30, "Bluetooth adapter number %d", i);
-
- if (pcap_add_if(alldevsp, dev_name, 0,
+
+ pcap_snprintf(dev_name, 20, BT_IFACE"%d", dev_req->dev_id);
+ pcap_snprintf(dev_descr, 30, "Bluetooth adapter number %d", i);
+
+ if (pcap_add_if(alldevsp, dev_name, 0,
dev_descr, err_str) < 0)
{
ret = -1;
@@ -171,7 +171,7 @@ bt_create(const char *device, char *ebuf, int *is_ours)
/* OK, it's probably ours. */
*is_ours = 1;
- p = pcap_create_common(device, ebuf, sizeof (struct pcap_bt));
+ p = pcap_create_common(ebuf, sizeof (struct pcap_bt));
if (p == NULL)
return (NULL);
@@ -190,17 +190,16 @@ bt_activate(pcap_t* handle)
int err = PCAP_ERROR;
/* get bt interface id */
- if (sscanf(handle->opt.source, BT_IFACE"%d", &dev_id) != 1)
+ if (sscanf(handle->opt.device, BT_IFACE"%d", &dev_id) != 1)
{
- snprintf(handle->errbuf, PCAP_ERRBUF_SIZE,
- "Can't get Bluetooth device index from %s",
- handle->opt.source);
+ pcap_snprintf(handle->errbuf, PCAP_ERRBUF_SIZE,
+ "Can't get Bluetooth device index from %s",
+ handle->opt.device);
return PCAP_ERROR;
}
/* Initialize some components of the pcap structure. */
- handle->bufsize = handle->snapshot+BT_CTRL_SIZE+sizeof(pcap_bluetooth_h4_header);
- handle->offset = BT_CTRL_SIZE;
+ handle->bufsize = BT_CTRL_SIZE+sizeof(pcap_bluetooth_h4_header)+handle->snapshot;
handle->linktype = DLT_BLUETOOTH_HCI_H4_WITH_PHDR;
handle->read_op = bt_read_linux;
@@ -212,43 +211,43 @@ bt_activate(pcap_t* handle)
handle->setnonblock_op = pcap_setnonblock_fd;
handle->stats_op = bt_stats_linux;
handlep->dev_id = dev_id;
-
+
/* Create HCI socket */
handle->fd = socket(AF_BLUETOOTH, SOCK_RAW, BTPROTO_HCI);
if (handle->fd < 0) {
- snprintf(handle->errbuf, PCAP_ERRBUF_SIZE,
+ pcap_snprintf(handle->errbuf, PCAP_ERRBUF_SIZE,
"Can't create raw socket: %s", strerror(errno));
return PCAP_ERROR;
}
handle->buffer = malloc(handle->bufsize);
if (!handle->buffer) {
- snprintf(handle->errbuf, PCAP_ERRBUF_SIZE, "Can't allocate dump buffer: %s",
+ pcap_snprintf(handle->errbuf, PCAP_ERRBUF_SIZE, "Can't allocate dump buffer: %s",
pcap_strerror(errno));
goto close_fail;
}
opt = 1;
if (setsockopt(handle->fd, SOL_HCI, HCI_DATA_DIR, &opt, sizeof(opt)) < 0) {
- snprintf(handle->errbuf, PCAP_ERRBUF_SIZE,
+ pcap_snprintf(handle->errbuf, PCAP_ERRBUF_SIZE,
"Can't enable data direction info: %s", strerror(errno));
goto close_fail;
}
opt = 1;
if (setsockopt(handle->fd, SOL_HCI, HCI_TIME_STAMP, &opt, sizeof(opt)) < 0) {
- snprintf(handle->errbuf, PCAP_ERRBUF_SIZE,
+ pcap_snprintf(handle->errbuf, PCAP_ERRBUF_SIZE,
"Can't enable time stamp: %s", strerror(errno));
goto close_fail;
}
- /* Setup filter, do not call hci function to avoid dependence on
+ /* Setup filter, do not call hci function to avoid dependence on
* external libs */
memset(&flt, 0, sizeof(flt));
- memset((void *) &flt.type_mask, 0xff, sizeof(flt.type_mask));
+ memset((void *) &flt.type_mask, 0xff, sizeof(flt.type_mask));
memset((void *) &flt.event_mask, 0xff, sizeof(flt.event_mask));
if (setsockopt(handle->fd, SOL_HCI, HCI_FILTER, &flt, sizeof(flt)) < 0) {
- snprintf(handle->errbuf, PCAP_ERRBUF_SIZE,
+ pcap_snprintf(handle->errbuf, PCAP_ERRBUF_SIZE,
"Can't set filter: %s", strerror(errno));
goto close_fail;
}
@@ -261,7 +260,7 @@ bt_activate(pcap_t* handle)
addr.hci_channel = HCI_CHANNEL_RAW;
#endif
if (bind(handle->fd, (struct sockaddr *) &addr, sizeof(addr)) < 0) {
- snprintf(handle->errbuf, PCAP_ERRBUF_SIZE,
+ pcap_snprintf(handle->errbuf, PCAP_ERRBUF_SIZE,
"Can't attach to device %d: %s", handlep->dev_id,
strerror(errno));
goto close_fail;
@@ -282,7 +281,7 @@ bt_activate(pcap_t* handle)
if (setsockopt(handle->fd, SOL_SOCKET, SO_RCVBUF,
&handle->opt.buffer_size,
sizeof(handle->opt.buffer_size)) == -1) {
- snprintf(handle->errbuf, PCAP_ERRBUF_SIZE,
+ pcap_snprintf(handle->errbuf, PCAP_ERRBUF_SIZE,
"SO_RCVBUF: %s", pcap_strerror(errno));
goto close_fail;
}
@@ -305,16 +304,19 @@ bt_read_linux(pcap_t *handle, int max_packets, pcap_handler callback, u_char *us
ssize_t ret;
struct pcap_pkthdr pkth;
pcap_bluetooth_h4_header* bthdr;
+ u_char *pktd;
+ int in = 0;
- bthdr = (pcap_bluetooth_h4_header*) &handle->buffer[handle->offset];
- iv.iov_base = &handle->buffer[handle->offset+sizeof(pcap_bluetooth_h4_header)];
+ pktd = (u_char *)handle->buffer + BT_CTRL_SIZE;
+ bthdr = (pcap_bluetooth_h4_header*)(void *)pktd;
+ iv.iov_base = pktd + sizeof(pcap_bluetooth_h4_header);
iv.iov_len = handle->snapshot;
-
+
memset(&msg, 0, sizeof(msg));
msg.msg_iov = &iv;
msg.msg_iovlen = 1;
msg.msg_control = handle->buffer;
- msg.msg_controllen = handle->offset;
+ msg.msg_controllen = BT_CTRL_SIZE;
/* ignore interrupt system call error */
do {
@@ -327,16 +329,15 @@ bt_read_linux(pcap_t *handle, int max_packets, pcap_handler callback, u_char *us
} while ((ret == -1) && (errno == EINTR));
if (ret < 0) {
- snprintf(handle->errbuf, PCAP_ERRBUF_SIZE,
+ pcap_snprintf(handle->errbuf, PCAP_ERRBUF_SIZE,
"Can't receive packet: %s", strerror(errno));
return -1;
}
pkth.caplen = ret;
- /* get direction and timestamp*/
+ /* get direction and timestamp*/
cmsg = CMSG_FIRSTHDR(&msg);
- int in=0;
while (cmsg) {
switch (cmsg->cmsg_type) {
case HCI_CMSG_DIR:
@@ -349,7 +350,7 @@ bt_read_linux(pcap_t *handle, int max_packets, pcap_handler callback, u_char *us
}
cmsg = CMSG_NXTHDR(&msg, cmsg);
}
- if ((in && (handle->direction == PCAP_D_OUT)) ||
+ if ((in && (handle->direction == PCAP_D_OUT)) ||
((!in) && (handle->direction == PCAP_D_IN)))
return 0;
@@ -357,9 +358,8 @@ bt_read_linux(pcap_t *handle, int max_packets, pcap_handler callback, u_char *us
pkth.caplen+=sizeof(pcap_bluetooth_h4_header);
pkth.len = pkth.caplen;
if (handle->fcode.bf_insns == NULL ||
- bpf_filter(handle->fcode.bf_insns, &handle->buffer[handle->offset],
- pkth.len, pkth.caplen)) {
- callback(user, &pkth, &handle->buffer[handle->offset]);
+ bpf_filter(handle->fcode.bf_insns, pktd, pkth.len, pkth.caplen)) {
+ callback(user, &pkth, pktd);
return 1;
}
return 0; /* didn't pass filter */
@@ -368,13 +368,13 @@ bt_read_linux(pcap_t *handle, int max_packets, pcap_handler callback, u_char *us
static int
bt_inject_linux(pcap_t *handle, const void *buf, size_t size)
{
- snprintf(handle->errbuf, PCAP_ERRBUF_SIZE, "inject not supported on "
+ pcap_snprintf(handle->errbuf, PCAP_ERRBUF_SIZE, "inject not supported on "
"bluetooth devices");
return (-1);
-}
+}
-static int
+static int
bt_stats_linux(pcap_t *handle, struct pcap_stat *stats)
{
struct pcap_bt *handlep = handle->priv;
@@ -382,28 +382,28 @@ bt_stats_linux(pcap_t *handle, struct pcap_stat *stats)
struct hci_dev_info dev_info;
struct hci_dev_stats * s = &dev_info.stat;
dev_info.dev_id = handlep->dev_id;
-
+
/* ignore eintr */
do {
ret = ioctl(handle->fd, HCIGETDEVINFO, (void *)&dev_info);
} while ((ret == -1) && (errno == EINTR));
-
+
if (ret < 0) {
- snprintf(handle->errbuf, PCAP_ERRBUF_SIZE,
+ pcap_snprintf(handle->errbuf, PCAP_ERRBUF_SIZE,
"Can't get stats via ioctl: %s", strerror(errno));
return (-1);
-
+
}
- /* we receive both rx and tx frames, so comulate all stats */
- stats->ps_recv = s->evt_rx + s->acl_rx + s->sco_rx + s->cmd_tx +
+ /* we receive both rx and tx frames, so comulate all stats */
+ stats->ps_recv = s->evt_rx + s->acl_rx + s->sco_rx + s->cmd_tx +
s->acl_tx +s->sco_tx;
stats->ps_drop = s->err_rx + s->err_tx;
stats->ps_ifdrop = 0;
return 0;
}
-static int
+static int
bt_setdirection_linux(pcap_t *p, pcap_direction_t d)
{
p->direction = d;
diff --git a/contrib/libpcap/pcap-bt-linux.h b/contrib/libpcap/pcap-bt-linux.h
index cacbd2f10dbd..e098654dcbc8 100644
--- a/contrib/libpcap/pcap-bt-linux.h
+++ b/contrib/libpcap/pcap-bt-linux.h
@@ -11,8 +11,8 @@
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
- * 3. The name of the author may not be used to endorse or promote
- * products derived from this software without specific prior written
+ * 3. The name of the author may not be used to endorse or promote
+ * products derived from this software without specific prior written
* permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
diff --git a/contrib/libpcap/pcap-bt-monitor-linux.c b/contrib/libpcap/pcap-bt-monitor-linux.c
index 76c9ee34a4e1..521d6d500d05 100644
--- a/contrib/libpcap/pcap-bt-monitor-linux.c
+++ b/contrib/libpcap/pcap-bt-monitor-linux.c
@@ -34,19 +34,31 @@
#endif
#include <errno.h>
+#include <stdint.h>
#include <stdlib.h>
#include <string.h>
#include <bluetooth/bluetooth.h>
#include <bluetooth/hci.h>
-#include <bluetooth/mgmt.h>
#include "pcap/bluetooth.h"
#include "pcap-int.h"
+#include "pcap-bt-monitor-linux.h"
+
#define BT_CONTROL_SIZE 32
#define INTERFACE_NAME "bluetooth-monitor"
+/*
+ * Fields and alignment must match the declaration in the Linux kernel 3.4+.
+ * See struct hci_mon_hdr in include/net/bluetooth/hci_mon.h.
+ */
+struct hci_mon_hdr {
+ uint16_t opcode;
+ uint16_t index;
+ uint16_t len;
+} __attribute__((packed));
+
int
bt_monitor_findalldevs(pcap_if_t **alldevsp, char *err_str)
{
@@ -70,14 +82,15 @@ bt_monitor_read(pcap_t *handle, int max_packets _U_, pcap_handler callback, u_ch
ssize_t ret;
struct pcap_pkthdr pkth;
pcap_bluetooth_linux_monitor_header *bthdr;
- struct mgmt_hdr hdr;
- int in = 0;
+ u_char *pktd;
+ struct hci_mon_hdr hdr;
- bthdr = (pcap_bluetooth_linux_monitor_header*) &handle->buffer[handle->offset];
+ pktd = (u_char *)handle->buffer + BT_CONTROL_SIZE;
+ bthdr = (pcap_bluetooth_linux_monitor_header*)(void *)pktd;
iv[0].iov_base = &hdr;
- iv[0].iov_len = MGMT_HDR_SIZE;
- iv[1].iov_base = &handle->buffer[handle->offset + sizeof(pcap_bluetooth_linux_monitor_header)];
+ iv[0].iov_len = sizeof(hdr);
+ iv[1].iov_base = pktd + sizeof(pcap_bluetooth_linux_monitor_header);
iv[1].iov_len = handle->snapshot;
memset(&pkth.ts, 0, sizeof(pkth.ts));
@@ -85,7 +98,7 @@ bt_monitor_read(pcap_t *handle, int max_packets _U_, pcap_handler callback, u_ch
msg.msg_iov = iv;
msg.msg_iovlen = 2;
msg.msg_control = handle->buffer;
- msg.msg_controllen = handle->offset;
+ msg.msg_controllen = BT_CONTROL_SIZE;
do {
ret = recvmsg(handle->fd, &msg, 0);
@@ -97,12 +110,12 @@ bt_monitor_read(pcap_t *handle, int max_packets _U_, pcap_handler callback, u_ch
} while ((ret == -1) && (errno == EINTR));
if (ret < 0) {
- snprintf(handle->errbuf, PCAP_ERRBUF_SIZE,
+ pcap_snprintf(handle->errbuf, PCAP_ERRBUF_SIZE,
"Can't receive packet: %s", strerror(errno));
return -1;
}
- pkth.caplen = ret - MGMT_HDR_SIZE + sizeof(pcap_bluetooth_linux_monitor_header);
+ pkth.caplen = ret - sizeof(hdr) + sizeof(pcap_bluetooth_linux_monitor_header);
pkth.len = pkth.caplen;
for (cmsg = CMSG_FIRSTHDR(&msg); cmsg != NULL; cmsg = CMSG_NXTHDR(&msg, cmsg)) {
@@ -117,9 +130,8 @@ bt_monitor_read(pcap_t *handle, int max_packets _U_, pcap_handler callback, u_ch
bthdr->opcode = htons(hdr.opcode);
if (handle->fcode.bf_insns == NULL ||
- bpf_filter(handle->fcode.bf_insns, &handle->buffer[handle->offset],
- pkth.len, pkth.caplen)) {
- callback(user, &pkth, &handle->buffer[handle->offset]);
+ bpf_filter(handle->fcode.bf_insns, pktd, pkth.len, pkth.caplen)) {
+ callback(user, &pkth, pktd);
return 1;
}
return 0; /* didn't pass filter */
@@ -128,7 +140,7 @@ bt_monitor_read(pcap_t *handle, int max_packets _U_, pcap_handler callback, u_ch
static int
bt_monitor_inject(pcap_t *handle, const void *buf _U_, size_t size _U_)
{
- snprintf(handle->errbuf, PCAP_ERRBUF_SIZE, "inject not supported yet");
+ pcap_snprintf(handle->errbuf, PCAP_ERRBUF_SIZE, "inject not supported yet");
return -1;
}
@@ -161,8 +173,7 @@ bt_monitor_activate(pcap_t* handle)
return PCAP_ERROR_RFMON_NOTSUP;
}
- handle->bufsize = handle->snapshot + BT_CONTROL_SIZE + sizeof(pcap_bluetooth_linux_monitor_header);
- handle->offset = BT_CONTROL_SIZE;
+ handle->bufsize = BT_CONTROL_SIZE + sizeof(pcap_bluetooth_linux_monitor_header) + handle->snapshot;
handle->linktype = DLT_BLUETOOTH_LINUX_MONITOR;
handle->read_op = bt_monitor_read;
@@ -176,14 +187,14 @@ bt_monitor_activate(pcap_t* handle)
handle->fd = socket(AF_BLUETOOTH, SOCK_RAW, BTPROTO_HCI);
if (handle->fd < 0) {
- snprintf(handle->errbuf, PCAP_ERRBUF_SIZE,
+ pcap_snprintf(handle->errbuf, PCAP_ERRBUF_SIZE,
"Can't create raw socket: %s", strerror(errno));
return PCAP_ERROR;
}
handle->buffer = malloc(handle->bufsize);
if (!handle->buffer) {
- snprintf(handle->errbuf, PCAP_ERRBUF_SIZE, "Can't allocate dump buffer: %s",
+ pcap_snprintf(handle->errbuf, PCAP_ERRBUF_SIZE, "Can't allocate dump buffer: %s",
pcap_strerror(errno));
goto close_fail;
}
@@ -194,14 +205,14 @@ bt_monitor_activate(pcap_t* handle)
addr.hci_channel = HCI_CHANNEL_MONITOR;
if (bind(handle->fd, (struct sockaddr *) &addr, sizeof(addr)) < 0) {
- snprintf(handle->errbuf, PCAP_ERRBUF_SIZE,
+ pcap_snprintf(handle->errbuf, PCAP_ERRBUF_SIZE,
"Can't attach to interface: %s", strerror(errno));
goto close_fail;
}
opt = 1;
if (setsockopt(handle->fd, SOL_SOCKET, SO_TIMESTAMP, &opt, sizeof(opt)) < 0) {
- snprintf(handle->errbuf, PCAP_ERRBUF_SIZE,
+ pcap_snprintf(handle->errbuf, PCAP_ERRBUF_SIZE,
"Can't enable time stamp: %s", strerror(errno));
goto close_fail;
}
@@ -231,7 +242,7 @@ bt_monitor_create(const char *device, char *ebuf, int *is_ours)
}
*is_ours = 1;
- p = pcap_create_common(device, ebuf, 0);
+ p = pcap_create_common(ebuf, 0);
if (p == NULL)
return NULL;
diff --git a/contrib/libpcap/pcap-can-linux.c b/contrib/libpcap/pcap-can-linux.c
deleted file mode 100644
index 3a9e8cbeef21..000000000000
--- a/contrib/libpcap/pcap-can-linux.c
+++ /dev/null
@@ -1,319 +0,0 @@
-/*
- * Copyright (c) 2009 Felix Obenhuber
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- * 3. The name of the author may not be used to endorse or promote
- * products derived from this software without specific prior written
- * permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
- * SocketCan sniffing API implementation for Linux platform
- * By Felix Obenhuber <felix@obenhuber.de>
- *
- */
-
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-
-#include "pcap-int.h"
-#include "pcap-can-linux.h"
-
-#ifdef NEED_STRERROR_H
-#include "strerror.h"
-#endif
-
-#include <errno.h>
-#include <stdlib.h>
-#include <unistd.h>
-#include <fcntl.h>
-#include <string.h>
-#include <sys/ioctl.h>
-#include <sys/socket.h>
-#include <net/if.h>
-#include <arpa/inet.h>
-
-#include <linux/can.h>
-#include <linux/can/raw.h>
-
-/* not yet defined anywhere */
-#ifndef PF_CAN
-#define PF_CAN 29
-#endif
-#ifndef AF_CAN
-#define AF_CAN PF_CAN
-#endif
-
-/* forward declaration */
-static int can_activate(pcap_t *);
-static int can_read_linux(pcap_t *, int , pcap_handler , u_char *);
-static int can_inject_linux(pcap_t *, const void *, size_t);
-static int can_setfilter_linux(pcap_t *, struct bpf_program *);
-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)
-{
- /*
- * There are no platform-specific devices since each device
- * exists as a regular network interface.
- *
- * XXX - true?
- */
- return 0;
-}
-
-pcap_t *
-can_create(const char *device, char *ebuf, int *is_ours)
-{
- const char *cp;
- char *cpend;
- long devnum;
- pcap_t* p;
-
- /* Does this look like a CANbus device? */
- cp = strrchr(device, '/');
- if (cp == NULL)
- cp = device;
- /* Does it begin with "can" or "vcan"? */
- if (strncmp(cp, "can", 3) == 0) {
- /* Begins with "can" */
- cp += 3; /* skip past "can" */
- } else if (strncmp(cp, "vcan", 4) == 0) {
- /* Begins with "vcan" */
- cp += 4;
- } else {
- /* Nope, doesn't begin with "can" or "vcan" */
- *is_ours = 0;
- return NULL;
- }
- /* Yes - is "can" or "vcan" followed by a number from 0? */
- 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_can));
- if (p == NULL)
- return (NULL);
-
- p->activate_op = can_activate;
- return (p);
-}
-
-
-static int
-can_activate(pcap_t* handle)
-{
- struct pcap_can *handlep = handle->priv;
- struct sockaddr_can addr;
- struct ifreq ifr;
-
- /* Initialize some components of the pcap structure. */
- handle->bufsize = 24;
- handle->offset = 8;
- handle->linktype = DLT_CAN_SOCKETCAN;
- handle->read_op = can_read_linux;
- handle->inject_op = can_inject_linux;
- handle->setfilter_op = can_setfilter_linux;
- handle->setdirection_op = can_setdirection_linux;
- handle->set_datalink_op = NULL;
- handle->getnonblock_op = pcap_getnonblock_fd;
- handle->setnonblock_op = pcap_setnonblock_fd;
- handle->stats_op = can_stats_linux;
-
- /* Create socket */
- handle->fd = socket(PF_CAN, SOCK_RAW, CAN_RAW);
- if (handle->fd < 0)
- {
- snprintf(handle->errbuf, PCAP_ERRBUF_SIZE, "Can't create raw socket %d:%s",
- errno, strerror(errno));
- return PCAP_ERROR;
- }
-
- /* get interface index */
- memset(&ifr, 0, sizeof(ifr));
- strncpy(ifr.ifr_name, handle->opt.source, sizeof(ifr.ifr_name));
- if (ioctl(handle->fd, SIOCGIFINDEX, &ifr) < 0)
- {
- snprintf(handle->errbuf, PCAP_ERRBUF_SIZE,
- "Unable to get interface index: %s",
- pcap_strerror(errno));
- pcap_cleanup_live_common(handle);
- return PCAP_ERROR;
- }
- handlep->ifindex = ifr.ifr_ifindex;
-
- /* allocate butter */
- handle->buffer = malloc(handle->bufsize);
- if (!handle->buffer)
- {
- snprintf(handle->errbuf, PCAP_ERRBUF_SIZE, "Can't allocate dump buffer: %s",
- pcap_strerror(errno));
- pcap_cleanup_live_common(handle);
- return PCAP_ERROR;
- }
-
- /* Bind to the socket */
- addr.can_family = AF_CAN;
- 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",
- handlep->ifindex, errno, strerror(errno));
- pcap_cleanup_live_common(handle);
- return PCAP_ERROR;
- }
-
- if (handle->opt.rfmon)
- {
- /* Monitor mode doesn't apply to CAN devices. */
- pcap_cleanup_live_common(handle);
- return PCAP_ERROR_RFMON_NOTSUP;
- }
-
- handle->selectable_fd = handle->fd;
- return 0;
-
-}
-
-
-static int
-can_read_linux(pcap_t *handle, int max_packets, pcap_handler callback, u_char *user)
-{
- struct msghdr msg;
- struct pcap_pkthdr pkth;
- struct iovec iv;
- struct can_frame* cf;
-
- iv.iov_base = &handle->buffer[handle->offset];
- iv.iov_len = handle->snapshot;
-
- memset(&msg, 0, sizeof(msg));
- msg.msg_iov = &iv;
- msg.msg_iovlen = 1;
- msg.msg_control = handle->buffer;
- msg.msg_controllen = handle->offset;
-
- do
- {
- pkth.caplen = recvmsg(handle->fd, &msg, 0);
- if (handle->break_loop)
- {
- handle->break_loop = 0;
- return -2;
- }
- } while ((pkth.caplen == -1) && (errno == EINTR));
-
- if (pkth.caplen == -1)
- {
- snprintf(handle->errbuf, PCAP_ERRBUF_SIZE, "Can't receive packet %d:%s",
- errno, strerror(errno));
- return -1;
- }
-
- /* adjust capture len according to frame len */
- cf = (struct can_frame*)&handle->buffer[8];
- pkth.caplen -= 8 - cf->can_dlc;
- pkth.len = pkth.caplen;
-
- cf->can_id = htonl( cf->can_id );
-
- if( -1 == gettimeofday(&pkth.ts, NULL) )
- {
- snprintf(handle->errbuf, PCAP_ERRBUF_SIZE, "Can't get time of day %d:%s",
- errno, strerror(errno));
- return -1;
- }
-
- callback(user, &pkth, &handle->buffer[8]);
-
- return 1;
-}
-
-
-static int
-can_inject_linux(pcap_t *handle, const void *buf, size_t size)
-{
- /* not yet implemented */
- snprintf(handle->errbuf, PCAP_ERRBUF_SIZE, "inject not supported on "
- "can devices");
- return (-1);
-}
-
-
-static int
-can_stats_linux(pcap_t *handle, struct pcap_stat *stats)
-{
- /* not yet implemented */
- stats->ps_recv = 0; /* number of packets received */
- stats->ps_drop = 0; /* number of packets dropped */
- stats->ps_ifdrop = 0; /* drops by interface -- only supported on some platforms */
- return 0;
-}
-
-
-static int
-can_setfilter_linux(pcap_t *p, struct bpf_program *fp)
-{
- /* not yet implemented */
- return 0;
-}
-
-
-static int
-can_setdirection_linux(pcap_t *p, pcap_direction_t d)
-{
- /* no support for PCAP_D_OUT */
- if (d == PCAP_D_OUT)
- {
- snprintf(p->errbuf, sizeof(p->errbuf),
- "Setting direction to PCAP_D_OUT is not supported on can");
- return -1;
- }
-
- p->direction = d;
-
- return 0;
-}
-
-
-/* eof */
diff --git a/contrib/libpcap/pcap-can-linux.h b/contrib/libpcap/pcap-can-linux.h
deleted file mode 100644
index fe806ff93578..000000000000
--- a/contrib/libpcap/pcap-can-linux.h
+++ /dev/null
@@ -1,36 +0,0 @@
-/*
- * Copyright (c) 2009 Felix Obenhuber
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- * 3. The name of the author may not be used to endorse or promote
- * products derived from this software without specific prior written
- * permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
- */
-
-/*
- * Prototypes for SocketCAN related functions
- */
-pcap_t* can_create(const char *device, char *ebuf, int *is_ours);
-int can_findalldevs(pcap_if_t **devlistp, char *errbuf);
diff --git a/contrib/libpcap/pcap-canusb-linux.c b/contrib/libpcap/pcap-canusb-linux.c
deleted file mode 100644
index a72f4697fa4d..000000000000
--- a/contrib/libpcap/pcap-canusb-linux.c
+++ /dev/null
@@ -1,472 +0,0 @@
-/*
- * Copyright (c) 2009 Felix Obenhuber
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- * 3. The name of the author may not be used to endorse or promote
- * products derived from this software without specific prior written
- * permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
- * Sockettrace sniffing API implementation for Linux platform
- * By Felix Obenhuber <felix@obenhuber.de>
- *
- */
-
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-
-#include <libusb-1.0/libusb.h>
-
-#include <stdlib.h>
-#include <unistd.h>
-#include <fcntl.h>
-#include <string.h>
-#include <pthread.h>
-
-#include "pcap-int.h"
-#include "pcap-canusb-linux.h"
-
-#define CANUSB_IFACE "canusb"
-
-#define CANUSB_VID 0x0403
-#define CANUSB_PID 0x8990
-
-#define USE_THREAD 1
-
-#if USE_THREAD == 0
-#include <signal.h>
-#endif
-
-
-/* forward declaration */
-static int canusb_activate(pcap_t *);
-static int canusb_read_linux(pcap_t *, int , pcap_handler , u_char *);
-static int canusb_inject_linux(pcap_t *, const void *, size_t);
-static int canusb_setfilter_linux(pcap_t *, struct bpf_program *);
-static int canusb_setdirection_linux(pcap_t *, pcap_direction_t);
-static int canusb_stats_linux(pcap_t *, struct pcap_stat *);
-
-struct CAN_Msg
-{
- uint32_t timestamp;
- uint32_t id;
- uint32_t length;
- uint8_t data[8];
-};
-
-/*
- * Private data for capturing on Linux CANbus USB devices.
- */
-struct pcap_canusb {
- libusb_context *ctx;
- libusb_device_handle *dev;
- pthread_t worker;
- int rdpipe, wrpipe;
- volatile int loop;
-};
-
-int canusb_findalldevs(pcap_if_t **alldevsp, char *err_str)
-{
- libusb_context *fdctx;
- libusb_device** devs;
- unsigned char sernum[65];
- int cnt, i;
-
- if (libusb_init(&fdctx) != 0) {
- /*
- * XXX - if this doesn't just mean "no USB file system mounted",
- * perhaps we should report a real error rather than just
- * saying "no CANUSB devices".
- */
- return 0;
- }
-
- cnt = libusb_get_device_list(fdctx,&devs);
-
- for(i=0;i<cnt;i++)
- {
- int ret;
- // Check if this device is interesting.
- struct libusb_device_descriptor desc;
- libusb_get_device_descriptor(devs[i],&desc);
-
- if ((desc.idVendor != CANUSB_VID) || (desc.idProduct != CANUSB_PID))
- continue; //It is not, check next device
-
- //It is!
- libusb_device_handle *dh = NULL;
-
- if ((ret = libusb_open(devs[i],&dh)) == 0)
- {
- char dev_name[30];
- char dev_descr[50];
- int n = libusb_get_string_descriptor_ascii(dh,desc.iSerialNumber,sernum,64);
- sernum[n] = 0;
-
- snprintf(dev_name, 30, CANUSB_IFACE"%s", sernum);
- snprintf(dev_descr, 50, "CanUSB [%s]", sernum);
-
- libusb_close(dh);
-
- if (pcap_add_if(alldevsp, dev_name, 0, dev_descr, err_str) < 0)
- {
- libusb_free_device_list(devs,1);
- libusb_exit(fdctx);
- return -1;
- }
- }
- }
-
- libusb_free_device_list(devs,1);
- libusb_exit(fdctx);
- return 0;
-}
-
-static libusb_device_handle* canusb_opendevice(struct libusb_context *ctx, char* devserial)
-{
- libusb_device** devs;
- unsigned char serial[65];
- int cnt,i,n;
-
- cnt = libusb_get_device_list(ctx,&devs);
-
- for(i=0;i<cnt;i++)
- {
- // Check if this device is interesting.
- struct libusb_device_descriptor desc;
- libusb_get_device_descriptor(devs[i],&desc);
-
- if ((desc.idVendor != CANUSB_VID) || (desc.idProduct != CANUSB_PID))
- continue;
-
- //Found one!
- libusb_device_handle *dh = NULL;
-
- if (libusb_open(devs[i],&dh) != 0) continue;
-
- n = libusb_get_string_descriptor_ascii(dh,desc.iSerialNumber,serial,64);
- serial[n] = 0;
-
- if ((devserial) && (strcmp((char *)serial,devserial) != 0))
- {
- libusb_close(dh);
- continue;
- }
-
- if ((libusb_kernel_driver_active(dh,0)) && (libusb_detach_kernel_driver(dh,0) != 0))
- {
- libusb_close(dh);
- continue;
- }
-
- if (libusb_set_configuration(dh,1) != 0)
- {
- libusb_close(dh);
- continue;
- }
-
- if (libusb_claim_interface(dh,0) != 0)
- {
- libusb_close(dh);
- continue;
- }
-
- //Fount it!
- libusb_free_device_list(devs,1);
- return dh;
- }
-
- libusb_free_device_list(devs,1);
- return NULL;
-}
-
-
-pcap_t *
-canusb_create(const char *device, char *ebuf, int *is_ours)
-{
- const char *cp;
- char *cpend;
- long devnum;
- pcap_t* p;
- struct pcap_canusb *canusb;
-
- /* Does this look like a DAG device? */
- cp = strrchr(device, '/');
- if (cp == NULL)
- cp = device;
- /* Does it begin with "canusb"? */
- if (strncmp(cp, "canusb", 6) != 0) {
- /* Nope, doesn't begin with "canusb" */
- *is_ours = 0;
- return NULL;
- }
- /* Yes - is "canusb" followed by a number? */
- cp += 6;
- 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_canusb));
- if (p == NULL)
- return (NULL);
-
- canusb = p->priv;
- canusb->ctx = NULL;
- canusb->dev = NULL;
- canusb->rdpipe = -1;
- canusb->wrpipe = -1;
-
- p->activate_op = canusb_activate;
-
- return (p);
-}
-
-
-static void* canusb_capture_thread(void *arg)
-{
- struct pcap_canusb *canusb = arg;
- int i;
- struct
- {
- uint8_t rxsz, txsz;
- } status;
-
- fcntl(canusb->wrpipe, F_SETFL, O_NONBLOCK);
-
- while(canusb->loop)
- {
- int sz;
- struct CAN_Msg msg;
-
- libusb_interrupt_transfer(canusb->dev, 0x81, (unsigned char*)&status, sizeof(status), &sz, 100);
- //HACK!!!!! -> drop buffered data, read new one by reading twice.
- libusb_interrupt_transfer(canusb->dev, 0x81, (unsigned char*)&status, sizeof(status), &sz, 100);
-
- for(i = 0; i<status.rxsz; i++)
- {
- libusb_bulk_transfer(canusb->dev, 0x85, (unsigned char*)&msg, sizeof(msg), &sz, 100);
- write(canusb->wrpipe, &msg, sizeof(msg));
- }
-
- }
-
- return NULL;
-}
-
-static int canusb_startcapture(struct pcap_canusb* this)
-{
- int pipefd[2];
-
- if (pipe(pipefd) == -1)
- return -1;
-
- this->rdpipe = pipefd[0];
- this->wrpipe = pipefd[1];
-
- this->loop = 1;
- pthread_create(&this->worker, NULL, canusb_capture_thread, this);
-
- return this->rdpipe;
-}
-
-static void canusb_clearbufs(struct pcap_canusb* this)
-{
- unsigned char cmd[16];
- int al;
-
- cmd[0] = 1; //Empty incoming buffer
- cmd[1] = 1; //Empty outgoing buffer
- cmd[3] = 0; //Not a write to serial number
- memset(&cmd[4],0,16-4);
-
- libusb_interrupt_transfer(this->dev, 0x1,cmd,16,&al,100);
-}
-
-
-static void canusb_close(pcap_t* handle)
-{
- struct pcap_canusb *canusb = handle->priv;
-
- canusb->loop = 0;
- pthread_join(canusb->worker, NULL);
-
- if (canusb->dev)
- {
- 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->priv;
- 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->setfilter_op = canusb_setfilter_linux;
- handle->setdirection_op = canusb_setdirection_linux;
- handle->getnonblock_op = pcap_getnonblock_fd;
- handle->setnonblock_op = pcap_setnonblock_fd;
- handle->stats_op = canusb_stats_linux;
- handle->cleanup_op = canusb_close;
-
- /* Initialize some components of the pcap structure. */
- handle->bufsize = 32;
- handle->offset = 8;
- handle->linktype = DLT_CAN_SOCKETCAN;
- handle->set_datalink_op = NULL;
-
- serial = handle->opt.source + strlen(CANUSB_IFACE);
-
- canusb->dev = canusb_opendevice(canusb->ctx, serial);
- if (!canusb->dev)
- {
- libusb_exit(canusb->ctx);
- snprintf(handle->errbuf, PCAP_ERRBUF_SIZE, "Can't open USB Device");
- return PCAP_ERROR;
- }
-
- canusb_clearbufs(canusb);
-
- handle->fd = canusb_startcapture(canusb);
- handle->selectable_fd = handle->fd;
-
- return 0;
-}
-
-
-
-
-static int
-canusb_read_linux(pcap_t *handle, int max_packets, pcap_handler callback, u_char *user)
-{
- static struct timeval firstpacket = { -1, -1};
- int i = 0;
- struct CAN_Msg msg;
- struct pcap_pkthdr pkth;
-
- while(i < max_packets)
- {
- int n;
- usleep(10 * 1000);
- n = read(handle->fd, &msg, sizeof(msg));
- if (n <= 0)
- break;
- pkth.caplen = pkth.len = n;
- pkth.caplen -= 4;
- pkth.caplen -= 8 - msg.length;
-
- if ((firstpacket.tv_sec == -1) && (firstpacket.tv_usec == -1))
- gettimeofday(&firstpacket, NULL);
-
- pkth.ts.tv_usec = firstpacket.tv_usec + (msg.timestamp % 100) * 10000;
- pkth.ts.tv_sec = firstpacket.tv_usec + (msg.timestamp / 100);
- if (pkth.ts.tv_usec > 1000000)
- {
- pkth.ts.tv_usec -= 1000000;
- pkth.ts.tv_sec++;
- }
-
- callback(user, &pkth, (void*)&msg.id);
- i++;
- }
-
- return i;
-}
-
-
-static int
-canusb_inject_linux(pcap_t *handle, const void *buf, size_t size)
-{
- /* not yet implemented */
- snprintf(handle->errbuf, PCAP_ERRBUF_SIZE, "inject not supported on canusb devices");
- return (-1);
-}
-
-
-static int
-canusb_stats_linux(pcap_t *handle, struct pcap_stat *stats)
-{
- /* not yet implemented */
- stats->ps_recv = 0; /* number of packets received */
- stats->ps_drop = 0; /* number of packets dropped */
- stats->ps_ifdrop = 0; /* drops by interface -- only supported on some platforms */
- return 0;
-}
-
-
-static int
-canusb_setfilter_linux(pcap_t *p, struct bpf_program *fp)
-{
- /* not yet implemented */
- return 0;
-}
-
-
-static int
-canusb_setdirection_linux(pcap_t *p, pcap_direction_t d)
-{
- /* no support for PCAP_D_OUT */
- if (d == PCAP_D_OUT)
- {
- snprintf(p->errbuf, sizeof(p->errbuf),
- "Setting direction to PCAP_D_OUT is not supported on this interface");
- return -1;
- }
-
- p->direction = d;
-
- return 0;
-}
-
-
-/* eof */
diff --git a/contrib/libpcap/pcap-common.c b/contrib/libpcap/pcap-common.c
index a68e03221528..84368f6cefa6 100644
--- a/contrib/libpcap/pcap-common.c
+++ b/contrib/libpcap/pcap-common.c
@@ -25,9 +25,9 @@
#include "config.h"
#endif
-#ifdef WIN32
+#ifdef _WIN32
#include <pcap-stdinc.h>
-#else /* WIN32 */
+#else /* _WIN32 */
#if HAVE_INTTYPES_H
#include <inttypes.h>
#elif HAVE_STDINT_H
@@ -37,11 +37,14 @@
#include <sys/bitypes.h>
#endif
#include <sys/types.h>
-#endif /* WIN32 */
+#endif /* _WIN32 */
#include "pcap-int.h"
+#include "extract.h"
+#include "pcap/sll.h"
#include "pcap/usb.h"
#include "pcap/nflog.h"
+#include "pcap/can_socketcan.h"
#include "pcap-common.h"
@@ -351,7 +354,7 @@
#define LINKTYPE_GPRS_LLC 169 /* GPRS LLC */
#define LINKTYPE_GPF_T 170 /* GPF-T (ITU-T G.7041/Y.1303) */
-#define LINKTYPE_GPF_F 171 /* GPF-T (ITU-T G.7041/Y.1303) */
+#define LINKTYPE_GPF_F 171 /* GPF-F (ITU-T G.7041/Y.1303) */
/*
* Requested by Oolan Zimmer <oz@gcom.com> for use in Gcom's T1/E1 line
@@ -386,7 +389,7 @@
/*
* Juniper-private data link type, as per request from
- * Hannes Gredler <hannes@juniper.net>.
+ * Hannes Gredler <hannes@juniper.net>.
* The Link Types are used for prepending meta-information
* like interface index, interface name
* before standard Ethernet, PPP, Frelay & C-HDLC Frames
@@ -403,7 +406,7 @@
/*
* Juniper-private data link type, as per request from
- * Hannes Gredler <hannes@juniper.net>.
+ * Hannes Gredler <hannes@juniper.net>.
* The DLT_ is used for internal communication with a
* voice Adapter Card (PIC)
*/
@@ -426,10 +429,17 @@
#define LINKTYPE_A653_ICM 185
/*
- * USB packets, beginning with a USB setup header; requested by
- * Paolo Abeni <paolo.abeni@email.it>.
+ * This used to be "USB packets, beginning with a USB setup header;
+ * requested by Paolo Abeni <paolo.abeni@email.it>."
+ *
+ * However, that header didn't work all that well - it left out some
+ * useful information - and was abandoned in favor of the DLT_USB_LINUX
+ * header.
+ *
+ * This is now used by FreeBSD for its BPF taps for USB; that has its
+ * own headers. So it is written, so it is done.
*/
-#define LINKTYPE_USB 186
+#define LINKTYPE_USB_FREEBSD 186
/*
* Bluetooth HCI UART transport layer (part H:4); requested by
@@ -478,7 +488,7 @@
/*
* Juniper-private data link type, as per request from
- * Hannes Gredler <hannes@juniper.net>.
+ * Hannes Gredler <hannes@juniper.net>.
* The DLT_ is used for internal communication with a
* integrated service module (ISM).
*/
@@ -519,7 +529,7 @@
/*
* Juniper-private data link type, as per request from
- * Hannes Gredler <hannes@juniper.net>.
+ * Hannes Gredler <hannes@juniper.net>.
* The DLT_ is used for capturing data on a secure tunnel interface.
*/
#define LINKTYPE_JUNIPER_ST 200
@@ -611,11 +621,11 @@
*/
#define LINKTYPE_IEEE802_15_4_NONASK_PHY 215
-/*
+/*
* David Gibson <david@gibson.dropbear.id.au> requested this for
* captures from the Linux kernel /dev/input/eventN devices. This
* is used to communicate keystrokes and mouse movements from the
- * Linux kernel to display systems, such as Xorg.
+ * Linux kernel to display systems, such as Xorg.
*/
#define LINKTYPE_LINUX_EVDEV 216
@@ -736,8 +746,10 @@
/*
* CAN (Controller Area Network) frames, with a pseudo-header as supplied
- * by Linux SocketCAN. See Documentation/networking/can.txt in the Linux
- * source.
+ * by Linux SocketCAN, and with multi-byte numerical fields in that header
+ * in big-endian byte order.
+ *
+ * See Documentation/networking/can.txt in the Linux source.
*
* Requested by Felix Obenhuber <felix@obenhuber.de>.
*/
@@ -777,7 +789,7 @@
/*
* Juniper-private data link type, as per request from
- * Hannes Gredler <hannes@juniper.net>.
+ * Hannes Gredler <hannes@juniper.net>.
*/
#define LINKTYPE_JUNIPER_VS 232
#define LINKTYPE_JUNIPER_SRX_E2E 233
@@ -809,12 +821,12 @@
/*
* Juniper-private data link type, as per request from
- * Hannes Gredler <hannes@juniper.net>.
+ * Hannes Gredler <hannes@juniper.net>.
*/
#define LINKTYPE_JUNIPER_ATM_CEMIC 238
/*
- * NetFilter LOG messages
+ * NetFilter LOG messages
* (payload of netlink NFNL_SUBSYS_ULOG/NFULNL_MSG_PACKET packets)
*
* Requested by Jakub Zawadzki <darkjames-ws@darkjames.pl>
@@ -922,7 +934,7 @@
/*
* Link-layer header 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
@@ -959,7 +971,6 @@
*/
#define LINKTYPE_PROFIBUS_DL 257
-
/*
* Apple's DLT_PKTAP headers.
*
@@ -994,7 +1005,30 @@
*/
#define LINKTYPE_IPMI_HPM_2 260
-#define LINKTYPE_MATCHING_MAX 260 /* highest value in the "matching" range */
+/*
+ * per Joshua Wright <jwright@hasborg.com>, formats for Zwave captures.
+ */
+#define LINKTYPE_ZWAVE_R1_R2 261
+#define LINKTYPE_ZWAVE_R3 262
+
+/*
+ * per Steve Karg <skarg@users.sourceforge.net>, formats for Wattstopper
+ * Digital Lighting Management room bus serial protocol captures.
+ */
+#define LINKTYPE_WATTSTOPPER_DLM 263
+
+/*
+ * ISO 14443 contactless smart card messages.
+ */
+#define LINKTYPE_ISO_14443 264
+
+/*
+ * Radio data system (RDS) groups. IEC 62106.
+ * Per Jonathan Brucker <jonathan.brucke@gmail.com>.
+ */
+#define LINKTYPE_RDS 265
+
+#define LINKTYPE_MATCHING_MAX 265 /* highest value in the "matching" range */
static struct linktype_map {
int dlt;
@@ -1141,6 +1175,48 @@ linktype_to_dlt(int linktype)
return linktype;
}
+#define EXTRACT_
+
+/*
+ * DLT_LINUX_SLL packets with a protocol type of LINUX_SLL_P_CAN or
+ * LINUX_SLL_P_CANFD have SocketCAN headers in front of the payload,
+ * with the CAN ID being in host byte order.
+ *
+ * When reading a DLT_LINUX_SLL capture file, we need to check for those
+ * packets and convert the CAN ID from the byte order of the host that
+ * wrote the file to this host's byte order.
+ */
+static void
+swap_linux_sll_header(const struct pcap_pkthdr *hdr, u_char *buf)
+{
+ u_int caplen = hdr->caplen;
+ u_int length = hdr->len;
+ struct sll_header *shdr = (struct sll_header *)buf;
+ u_int16_t protocol;
+ pcap_can_socketcan_hdr *chdr;
+
+ if (caplen < (u_int) sizeof(struct sll_header) ||
+ length < (u_int) sizeof(struct sll_header)) {
+ /* Not enough data to have the protocol field */
+ return;
+ }
+
+ protocol = EXTRACT_16BITS(&shdr->sll_protocol);
+ if (protocol != LINUX_SLL_P_CAN && protocol != LINUX_SLL_P_CANFD)
+ return;
+
+ /*
+ * SocketCAN packet; fix up the packet's header.
+ */
+ chdr = (pcap_can_socketcan_hdr *)(buf + sizeof(struct sll_header));
+ if (caplen < (u_int) sizeof(struct sll_header) + sizeof(chdr->can_id) ||
+ length < (u_int) sizeof(struct sll_header) + sizeof(chdr->can_id)) {
+ /* Not enough data to have the CAN ID */
+ return;
+ }
+ chdr->can_id = SWAPLONG(chdr->can_id);
+}
+
/*
* The DLT_USB_LINUX and DLT_USB_LINUX_MMAPPED headers are in host
* byte order when capturing (it's supplied directly from a
@@ -1156,8 +1232,6 @@ swap_linux_usb_header(const struct pcap_pkthdr *hdr, u_char *buf,
{
pcap_usb_header_mmapped *uhdr = (pcap_usb_header_mmapped *)buf;
bpf_u_int32 offset = 0;
- usb_isodesc *pisodesc;
- int32_t numdesc, i;
/*
* "offset" is the offset *past* the field we're swapping;
@@ -1166,7 +1240,7 @@ swap_linux_usb_header(const struct pcap_pkthdr *hdr, u_char *buf,
*/
/*
- * The URB id is a totally opaque value; do we really need to
+ * The URB id is a totally opaque value; do we really need to
* convert it to the reading host's byte order???
*/
offset += 8; /* skip past id */
@@ -1221,6 +1295,17 @@ swap_linux_usb_header(const struct pcap_pkthdr *hdr, u_char *buf,
} else
offset += 8; /* skip USB setup header */
+ /*
+ * With the old header, there are no isochronous descriptors
+ * after the header.
+ *
+ * With the new header, the actual number of descriptors in
+ * the header is not s.iso.numdesc, it's ndesc - only the
+ * first N descriptors, for some value of N, are put into
+ * the header, and ndesc is set to the actual number copied.
+ * In addition, if s.iso.numdesc is negative, no descriptors
+ * are captured, and ndesc is set to 0.
+ */
if (header_len_64_bytes) {
/*
* This is either the "version 1" header, with
@@ -1249,31 +1334,33 @@ swap_linux_usb_header(const struct pcap_pkthdr *hdr, u_char *buf,
if (hdr->caplen < offset)
return;
uhdr->ndesc = SWAPLONG(uhdr->ndesc);
- }
- if (uhdr->transfer_type == URB_ISOCHRONOUS) {
- /* swap the values in struct linux_usb_isodesc */
- pisodesc = (usb_isodesc *)(void *)(buf+offset);
- numdesc = uhdr->s.iso.numdesc;
- for (i = 0; i < numdesc; i++) {
- offset += 4; /* skip past status */
- if (hdr->caplen < offset)
- return;
- pisodesc->status = SWAPLONG(pisodesc->status);
-
- offset += 4; /* skip past offset */
- if (hdr->caplen < offset)
- return;
- pisodesc->offset = SWAPLONG(pisodesc->offset);
-
- offset += 4; /* skip past len */
- if (hdr->caplen < offset)
- return;
- pisodesc->len = SWAPLONG(pisodesc->len);
-
- offset += 4; /* skip past padding */
-
- pisodesc++;
+ if (uhdr->transfer_type == URB_ISOCHRONOUS) {
+ /* swap the values in struct linux_usb_isodesc */
+ usb_isodesc *pisodesc;
+ u_int32_t i;
+
+ pisodesc = (usb_isodesc *)(void *)(buf+offset);
+ for (i = 0; i < uhdr->ndesc; i++) {
+ offset += 4; /* skip past status */
+ if (hdr->caplen < offset)
+ return;
+ pisodesc->status = SWAPLONG(pisodesc->status);
+
+ offset += 4; /* skip past offset */
+ if (hdr->caplen < offset)
+ return;
+ pisodesc->offset = SWAPLONG(pisodesc->offset);
+
+ offset += 4; /* skip past len */
+ if (hdr->caplen < offset)
+ return;
+ pisodesc->len = SWAPLONG(pisodesc->len);
+
+ offset += 4; /* skip past padding */
+
+ pisodesc++;
+ }
}
}
}
@@ -1299,12 +1386,13 @@ swap_nflog_header(const struct pcap_pkthdr *hdr, u_char *buf)
u_int length = hdr->len;
u_int16_t size;
- if (caplen < (int) sizeof(nflog_hdr_t) || length < (int) sizeof(nflog_hdr_t)) {
+ if (caplen < (u_int) sizeof(nflog_hdr_t) ||
+ length < (u_int) sizeof(nflog_hdr_t)) {
/* Not enough data to have any TLVs. */
return;
}
- if (!(nfhdr->nflog_version) == 0) {
+ if (nfhdr->nflog_version != 0) {
/* Unknown NFLOG version */
return;
}
@@ -1354,6 +1442,10 @@ swap_pseudo_headers(int linktype, struct pcap_pkthdr *hdr, u_char *data)
*/
switch (linktype) {
+ case DLT_LINUX_SLL:
+ swap_linux_sll_header(hdr, data);
+ break;
+
case DLT_USB_LINUX:
swap_linux_usb_header(hdr, data, 0);
break;
diff --git a/contrib/libpcap/pcap-config.1 b/contrib/libpcap/pcap-config.1
index 2a2272b38f1d..0388d0f17dd4 100644
--- a/contrib/libpcap/pcap-config.1
+++ b/contrib/libpcap/pcap-config.1
@@ -18,7 +18,7 @@
.\" WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
.\" MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
.\"
-.TH PCAP-CONFIG 1 "22 May 2009"
+.TH PCAP-CONFIG 1 "15 February 2015"
.SH NAME
pcap-config \- write libpcap compiler and linker flags to standard output
.SH SYNOPSIS
diff --git a/contrib/libpcap/pcap-dag.c b/contrib/libpcap/pcap-dag.c
index aaa3fae3dd3c..201696cca296 100644
--- a/contrib/libpcap/pcap-dag.c
+++ b/contrib/libpcap/pcap-dag.c
@@ -1,5 +1,5 @@
/*
- * pcap-dag.c: Packet capture interface for Endace DAG card.
+ * pcap-dag.c: Packet capture interface for Emulex EndaceDAG cards.
*
* The functionality of this code attempts to mimic that of pcap-linux as much
* as possible. This code is compiled in several different ways depending on
@@ -10,9 +10,9 @@
* called as required from their pcap-linux/bpf equivalents.
*
* Authors: Richard Littin, Sean Irvine ({richard,sean}@reeltwo.com)
- * Modifications: Jesper Peterson <support@endace.com>
- * Koryn Grant <support@endace.com>
- * Stephen Donnelly <support@endace.com>
+ * Modifications: Jesper Peterson
+ * Koryn Grant
+ * Stephen Donnelly <stephen.donnelly@emulex.com>
*/
#ifdef HAVE_CONFIG_H
@@ -40,6 +40,7 @@ struct rtentry; /* declarations in <net/if.h> */
#include "dagnew.h"
#include "dagapi.h"
+#include "dagpci.h"
#include "pcap-dag.h"
@@ -52,6 +53,99 @@ struct rtentry; /* declarations in <net/if.h> */
#define DAG_MAX_BOARDS 32
#endif
+
+#ifndef TYPE_AAL5
+#define TYPE_AAL5 4
+#endif
+
+#ifndef TYPE_MC_HDLC
+#define TYPE_MC_HDLC 5
+#endif
+
+#ifndef TYPE_MC_RAW
+#define TYPE_MC_RAW 6
+#endif
+
+#ifndef TYPE_MC_ATM
+#define TYPE_MC_ATM 7
+#endif
+
+#ifndef TYPE_MC_RAW_CHANNEL
+#define TYPE_MC_RAW_CHANNEL 8
+#endif
+
+#ifndef TYPE_MC_AAL5
+#define TYPE_MC_AAL5 9
+#endif
+
+#ifndef TYPE_COLOR_HDLC_POS
+#define TYPE_COLOR_HDLC_POS 10
+#endif
+
+#ifndef TYPE_COLOR_ETH
+#define TYPE_COLOR_ETH 11
+#endif
+
+#ifndef TYPE_MC_AAL2
+#define TYPE_MC_AAL2 12
+#endif
+
+#ifndef TYPE_IP_COUNTER
+#define TYPE_IP_COUNTER 13
+#endif
+
+#ifndef TYPE_TCP_FLOW_COUNTER
+#define TYPE_TCP_FLOW_COUNTER 14
+#endif
+
+#ifndef TYPE_DSM_COLOR_HDLC_POS
+#define TYPE_DSM_COLOR_HDLC_POS 15
+#endif
+
+#ifndef TYPE_DSM_COLOR_ETH
+#define TYPE_DSM_COLOR_ETH 16
+#endif
+
+#ifndef TYPE_COLOR_MC_HDLC_POS
+#define TYPE_COLOR_MC_HDLC_POS 17
+#endif
+
+#ifndef TYPE_AAL2
+#define TYPE_AAL2 18
+#endif
+
+#ifndef TYPE_COLOR_HASH_POS
+#define TYPE_COLOR_HASH_POS 19
+#endif
+
+#ifndef TYPE_COLOR_HASH_ETH
+#define TYPE_COLOR_HASH_ETH 20
+#endif
+
+#ifndef TYPE_INFINIBAND
+#define TYPE_INFINIBAND 21
+#endif
+
+#ifndef TYPE_IPV4
+#define TYPE_IPV4 22
+#endif
+
+#ifndef TYPE_IPV6
+#define TYPE_IPV6 23
+#endif
+
+#ifndef TYPE_RAW_LINK
+#define TYPE_RAW_LINK 24
+#endif
+
+#ifndef TYPE_INFINIBAND_LINK
+#define TYPE_INFINIBAND_LINK 25
+#endif
+
+#ifndef TYPE_PAD
+#define TYPE_PAD 48
+#endif
+
#define ATM_CELL_SIZE 52
#define ATM_HDR_SIZE 4
@@ -143,28 +237,25 @@ delete_pcap_dag(pcap_t *p)
static void
dag_platform_cleanup(pcap_t *p)
{
- struct pcap_dag *pd;
+ struct pcap_dag *pd = p->pr;
- if (p != NULL) {
- pd = p->priv;
#ifdef HAVE_DAG_STREAMS_API
- 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, pd->dag_stream) < 0)
- fprintf(stderr,"dag_detach_stream: %s\n", strerror(errno));
+ 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, pd->dag_stream) < 0)
+ fprintf(stderr,"dag_detach_stream: %s\n", strerror(errno));
#else
- if(dag_stop(p->fd) < 0)
- fprintf(stderr,"dag_stop: %s\n", strerror(errno));
+ if(dag_stop(p->fd) < 0)
+ fprintf(stderr,"dag_stop: %s\n", strerror(errno));
#endif /* HAVE_DAG_STREAMS_API */
- if(p->fd != -1) {
- if(dag_close(p->fd) < 0)
- fprintf(stderr,"dag_close: %s\n", strerror(errno));
- p->fd = -1;
- }
- delete_pcap_dag(p);
- pcap_cleanup_live_common(p);
+ if(p->fd != -1) {
+ if(dag_close(p->fd) < 0)
+ fprintf(stderr,"dag_close: %s\n", strerror(errno));
+ p->fd = -1;
}
+ delete_pcap_dag(p);
+ pcap_cleanup_live_common(p);
/* Note: don't need to call close(p->fd) here as dag_close(p->fd) does this. */
}
@@ -173,7 +264,8 @@ atexit_handler(void)
{
while (pcap_dags != NULL) {
if (pcap_dags->pid == getpid()) {
- dag_platform_cleanup(pcap_dags->p);
+ if (pcap_dags->p != NULL)
+ dag_platform_cleanup(pcap_dags->p);
} else {
delete_pcap_dag(pcap_dags->p);
}
@@ -221,7 +313,7 @@ dag_erf_ext_header_count(uint8_t * erf, size_t len)
/* loop over the extension headers */
do {
-
+
/* sanity check we have enough bytes */
if ( len < (24 + (hdr_num * 8)) )
return hdr_num;
@@ -248,10 +340,11 @@ dag_read(pcap_t *p, int cnt, pcap_handler callback, u_char *user)
int flags = pd->dag_offset_flags;
unsigned int nonblocking = flags & DAGF_NONBLOCK;
unsigned int num_ext_hdr = 0;
+ unsigned int ticks_per_second;
/* Get the next bufferful of packets (if necessary). */
while (pd->dag_mem_top - pd->dag_mem_bottom < dag_record_size) {
-
+
/*
* Has "pcap_breakloop()" been called?
*/
@@ -290,7 +383,7 @@ dag_read(pcap_t *p, int cnt, pcap_handler callback, u_char *user)
/* Pcap is configured to process only available packets, and there aren't any, return immediately. */
return 0;
}
-
+
if(!nonblocking &&
pd->dag_timeout &&
(pd->dag_mem_top - pd->dag_mem_bottom < dag_record_size))
@@ -300,14 +393,14 @@ dag_read(pcap_t *p, int cnt, pcap_handler callback, u_char *user)
}
}
-
+
/* Process the packets. */
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 *)(pd->dag_mem_bottom);
#else
@@ -316,7 +409,7 @@ dag_read(pcap_t *p, int cnt, pcap_handler callback, u_char *user)
u_char *dp = ((u_char *)header); /* + dag_record_size; */
unsigned short rlen;
-
+
/*
* Has "pcap_breakloop()" been called?
*/
@@ -329,7 +422,7 @@ dag_read(pcap_t *p, int cnt, pcap_handler callback, u_char *user)
p->break_loop = 0;
return -2;
}
-
+
rlen = ntohs(header->rlen);
if (rlen < dag_record_size)
{
@@ -359,7 +452,7 @@ dag_read(pcap_t *p, int cnt, pcap_handler callback, u_char *user)
}
}
}
-
+
if ((header->type & 0x7f) == TYPE_PAD) {
continue;
}
@@ -367,13 +460,13 @@ dag_read(pcap_t *p, int cnt, pcap_handler callback, u_char *user)
num_ext_hdr = dag_erf_ext_header_count(dp, rlen);
/* ERF encapsulation */
- /* The Extensible Record Format is not dropped for this kind of encapsulation,
+ /* The Extensible Record Format is not dropped for this kind of encapsulation,
* and will be handled as a pseudo header by the decoding application.
* The information carried in the ERF header and in the optional subheader (if present)
* could be merged with the libpcap information, to offer a better decoding.
* The packet length is
* o the length of the packet on the link (header->wlen),
- * o plus the length of the ERF header (dag_record_size), as the length of the
+ * o plus the length of the ERF header (dag_record_size), as the length of the
* pseudo header will be adjusted during the decoding,
* o plus the length of the optional subheader (if present).
*
@@ -415,7 +508,7 @@ dag_read(pcap_t *p, int cnt, pcap_handler callback, u_char *user)
dp += dag_record_size;
/* Skip over extension headers */
dp += 8 * num_ext_hdr;
-
+
switch((header->type & 0x7f)) {
case TYPE_ATM:
case TYPE_AAL5:
@@ -434,19 +527,22 @@ dag_read(pcap_t *p, int cnt, pcap_handler callback, u_char *user)
caplen = rlen - dag_record_size - 4;
dp+=4;
}
+ /* Skip over extension headers */
+ caplen -= (8 * num_ext_hdr);
+
if (header->type == TYPE_ATM) {
caplen = packet_len = ATM_CELL_SIZE;
}
if (p->linktype == DLT_SUNATM) {
struct sunatm_hdr *sunatm = (struct sunatm_hdr *)dp;
unsigned long rawatm;
-
+
rawatm = ntohl(*((unsigned long *)dp));
sunatm->vci = htons((rawatm >> 4) & 0xffff);
sunatm->vpi = (rawatm >> 20) & 0x00ff;
- sunatm->flags = ((header->flags.iface & 1) ? 0x80 : 0x00) |
+ sunatm->flags = ((header->flags.iface & 1) ? 0x80 : 0x00) |
((sunatm->vpi == 0 && sunatm->vci == htons(5)) ? 6 :
- ((sunatm->vpi == 0 && sunatm->vci == htons(16)) ? 5 :
+ ((sunatm->vpi == 0 && sunatm->vci == htons(16)) ? 5 :
((dp[ATM_HDR_SIZE] == 0xaa &&
dp[ATM_HDR_SIZE+1] == 0xaa &&
dp[ATM_HDR_SIZE+2] == 0x03) ? 2 : 1)));
@@ -465,6 +561,8 @@ dag_read(pcap_t *p, int cnt, pcap_handler callback, u_char *user)
packet_len = ntohs(header->wlen);
packet_len -= (pd->dag_fcs_bits >> 3);
caplen = rlen - dag_record_size - 2;
+ /* Skip over extension headers */
+ caplen -= (8 * num_ext_hdr);
if (caplen > packet_len) {
caplen = packet_len;
}
@@ -478,6 +576,8 @@ dag_read(pcap_t *p, int cnt, pcap_handler callback, u_char *user)
packet_len = ntohs(header->wlen);
packet_len -= (pd->dag_fcs_bits >> 3);
caplen = rlen - dag_record_size;
+ /* Skip over extension headers */
+ caplen -= (8 * num_ext_hdr);
if (caplen > packet_len) {
caplen = packet_len;
}
@@ -488,6 +588,8 @@ dag_read(pcap_t *p, int cnt, pcap_handler callback, u_char *user)
packet_len = ntohs(header->wlen);
packet_len -= (pd->dag_fcs_bits >> 3);
caplen = rlen - dag_record_size - 4;
+ /* Skip over extension headers */
+ caplen -= (8 * num_ext_hdr);
if (caplen > packet_len) {
caplen = packet_len;
}
@@ -498,7 +600,7 @@ dag_read(pcap_t *p, int cnt, pcap_handler callback, u_char *user)
/* Add the MTP2 Pseudo Header */
caplen += MTP2_HDR_LEN;
packet_len += MTP2_HDR_LEN;
-
+
TempPkt[MTP2_SENT_OFFSET] = 0;
TempPkt[MTP2_ANNEX_A_USED_OFFSET] = MTP2_ANNEX_A_USED_UNKNOWN;
*(TempPkt+MTP2_LINK_NUMBER_OFFSET) = ((header->rec.mc_hdlc.mc_header>>16)&0x01);
@@ -513,6 +615,8 @@ dag_read(pcap_t *p, int cnt, pcap_handler callback, u_char *user)
case TYPE_IPV6:
packet_len = ntohs(header->wlen);
caplen = rlen - dag_record_size;
+ /* Skip over extension headers */
+ caplen -= (8 * num_ext_hdr);
if (caplen > packet_len) {
caplen = packet_len;
}
@@ -533,45 +637,52 @@ dag_read(pcap_t *p, int cnt, pcap_handler callback, u_char *user)
continue;
} /* switch type */
- /* Skip over extension headers */
- caplen -= (8 * num_ext_hdr);
-
} /* ERF encapsulation */
-
+
if (caplen > p->snapshot)
caplen = p->snapshot;
/* Run the packet filter if there is one. */
if ((p->fcode.bf_insns == NULL) || bpf_filter(p->fcode.bf_insns, dp, packet_len, caplen)) {
-
+
/* convert between timestamp formats */
register unsigned long long ts;
-
+
if (IS_BIGENDIAN()) {
ts = SWAPLL(header->ts);
} else {
ts = header->ts;
}
+ switch (p->opt.tstamp_precision) {
+ case PCAP_TSTAMP_PRECISION_NANO:
+ ticks_per_second = 1000000000;
+ break;
+ case PCAP_TSTAMP_PRECISION_MICRO:
+ default:
+ ticks_per_second = 1000000;
+ break;
+
+ }
pcap_header.ts.tv_sec = ts >> 32;
- ts = (ts & 0xffffffffULL) * 1000000;
+ ts = (ts & 0xffffffffULL) * ticks_per_second;
ts += 0x80000000; /* rounding */
- pcap_header.ts.tv_usec = ts >> 32;
- if (pcap_header.ts.tv_usec >= 1000000) {
- pcap_header.ts.tv_usec -= 1000000;
+ pcap_header.ts.tv_usec = ts >> 32;
+ if (pcap_header.ts.tv_usec >= ticks_per_second) {
+ pcap_header.ts.tv_usec -= ticks_per_second;
pcap_header.ts.tv_sec++;
}
/* Fill in our own header data */
pcap_header.caplen = caplen;
pcap_header.len = packet_len;
-
+
/* Count the packet. */
pd->stat.ps_recv++;
-
+
/* Call the user supplied callback function */
callback(user, &pcap_header, dp);
-
+
/* Only count packets that pass the filter, for consistency with standard Linux behaviour. */
processed++;
if (processed == cnt && !PACKET_COUNT_IS_UNLIMITED(cnt))
@@ -598,7 +709,7 @@ dag_inject(pcap_t *p, const void *buf _U_, size_t size _U_)
* device will result in a failure. The promisc flag is ignored because DAG
* cards are always promiscuous. The to_ms parameter is used in setting the
* API polling parameters.
- *
+ *
* snaplen is now also ignored, until we get per-stream slen support. Set
* slen with approprite DAG tool BEFORE pcap_activate().
*
@@ -614,7 +725,7 @@ static int dag_activate(pcap_t* handle)
int n;
daginf_t* daginf;
char * newDev = NULL;
- char * device = handle->opt.source;
+ char * device = handle->opt.device;
#ifdef HAVE_DAG_STREAMS_API
uint32_t mindata;
struct timeval maxwait;
@@ -622,7 +733,7 @@ static int dag_activate(pcap_t* handle)
#endif
if (device == NULL) {
- snprintf(handle->errbuf, PCAP_ERRBUF_SIZE, "device is NULL: %s", pcap_strerror(errno));
+ pcap_snprintf(handle->errbuf, PCAP_ERRBUF_SIZE, "device is NULL: %s", pcap_strerror(errno));
return -1;
}
@@ -631,26 +742,26 @@ static int dag_activate(pcap_t* handle)
#ifdef HAVE_DAG_STREAMS_API
newDev = (char *)malloc(strlen(device) + 16);
if (newDev == NULL) {
- snprintf(handle->errbuf, PCAP_ERRBUF_SIZE, "Can't allocate string for device name: %s\n", pcap_strerror(errno));
+ pcap_snprintf(handle->errbuf, PCAP_ERRBUF_SIZE, "Can't allocate string for device name: %s", pcap_strerror(errno));
goto fail;
}
-
+
/* Parse input name to get dag device and stream number if provided */
if (dag_parse_name(device, newDev, strlen(device) + 16, &handlep->dag_stream) < 0) {
- snprintf(handle->errbuf, PCAP_ERRBUF_SIZE, "dag_parse_name: %s\n", pcap_strerror(errno));
+ pcap_snprintf(handle->errbuf, PCAP_ERRBUF_SIZE, "dag_parse_name: %s", pcap_strerror(errno));
goto fail;
}
device = newDev;
if (handlep->dag_stream%2) {
- snprintf(handle->errbuf, PCAP_ERRBUF_SIZE, "dag_parse_name: tx (even numbered) streams not supported for capture\n");
+ pcap_snprintf(handle->errbuf, PCAP_ERRBUF_SIZE, "dag_parse_name: tx (even numbered) streams not supported for capture");
goto fail;
}
#else
if (strncmp(device, "/dev/", 5) != 0) {
newDev = (char *)malloc(strlen(device) + 5);
if (newDev == NULL) {
- snprintf(handle->errbuf, PCAP_ERRBUF_SIZE, "Can't allocate string for device name: %s\n", pcap_strerror(errno));
+ pcap_snprintf(handle->errbuf, PCAP_ERRBUF_SIZE, "Can't allocate string for device name: %s", pcap_strerror(errno));
goto fail;
}
strcpy(newDev, "/dev/");
@@ -661,14 +772,14 @@ static int dag_activate(pcap_t* handle)
/* setup device parameters */
if((handle->fd = dag_open((char *)device)) < 0) {
- snprintf(handle->errbuf, PCAP_ERRBUF_SIZE, "dag_open %s: %s", device, pcap_strerror(errno));
+ pcap_snprintf(handle->errbuf, PCAP_ERRBUF_SIZE, "dag_open %s: %s", device, pcap_strerror(errno));
goto fail;
}
#ifdef HAVE_DAG_STREAMS_API
/* Open requested stream. Can fail if already locked or on error */
if (dag_attach_stream(handle->fd, handlep->dag_stream, 0, 0) < 0) {
- snprintf(handle->errbuf, PCAP_ERRBUF_SIZE, "dag_attach_stream: %s\n", pcap_strerror(errno));
+ pcap_snprintf(handle->errbuf, PCAP_ERRBUF_SIZE, "dag_attach_stream: %s", pcap_strerror(errno));
goto failclose;
}
@@ -677,10 +788,10 @@ static int dag_activate(pcap_t* handle)
*/
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));
+ pcap_snprintf(handle->errbuf, PCAP_ERRBUF_SIZE, "dag_get_stream_poll: %s", pcap_strerror(errno));
goto faildetach;
}
-
+
if (handle->opt.immediate) {
/* Call callback immediately.
* XXX - is this the right way to handle this?
@@ -702,13 +813,13 @@ static int dag_activate(pcap_t* handle)
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));
+ pcap_snprintf(handle->errbuf, PCAP_ERRBUF_SIZE, "dag_set_stream_poll: %s", pcap_strerror(errno));
goto faildetach;
}
-
+
#else
if((handlep->dag_mem_base = dag_mmap(handle->fd)) == MAP_FAILED) {
- snprintf(handle->errbuf, PCAP_ERRBUF_SIZE,"dag_mmap %s: %s\n", device, pcap_strerror(errno));
+ pcap_snprintf(handle->errbuf, PCAP_ERRBUF_SIZE,"dag_mmap %s: %s", device, pcap_strerror(errno));
goto failclose;
}
@@ -728,22 +839,22 @@ static int dag_activate(pcap_t* handle)
handle->snapshot = MIN_DAG_SNAPLEN;
}
/* snap len has to be a multiple of 4 */
- snprintf(conf, 30, "varlen slen=%d", (snaplen + 3) & ~3);
+ pcap_snprintf(conf, 30, "varlen slen=%d", (snaplen + 3) & ~3);
if(dag_configure(handle->fd, conf) < 0) {
- snprintf(handle->errbuf, PCAP_ERRBUF_SIZE,"dag_configure %s: %s\n", device, pcap_strerror(errno));
+ pcap_snprintf(handle->errbuf, PCAP_ERRBUF_SIZE,"dag_configure %s: %s", device, pcap_strerror(errno));
goto faildetach;
}
-#endif
-
+#endif
+
#ifdef HAVE_DAG_STREAMS_API
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));
+ pcap_snprintf(handle->errbuf, PCAP_ERRBUF_SIZE, "dag_start_stream %s: %s", device, pcap_strerror(errno));
goto faildetach;
}
#else
if(dag_start(handle->fd) < 0) {
- snprintf(handle->errbuf, PCAP_ERRBUF_SIZE, "dag_start %s: %s\n", device, pcap_strerror(errno));
+ pcap_snprintf(handle->errbuf, PCAP_ERRBUF_SIZE, "dag_start %s: %s", device, pcap_strerror(errno));
goto failclose;
}
#endif /* HAVE_DAG_STREAMS_API */
@@ -778,8 +889,8 @@ static int dag_activate(pcap_t* handle)
if ((n = atoi(s)) == 0 || n == 16 || n == 32) {
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);
+ pcap_snprintf(handle->errbuf, PCAP_ERRBUF_SIZE,
+ "pcap_activate %s: bad ERF_FCS_BITS value (%d) in environment", device, n);
goto failstop;
}
}
@@ -802,11 +913,11 @@ static int dag_activate(pcap_t* handle)
handle->linktype = -1;
if (dag_get_datalink(handle) < 0)
goto failstop;
-
+
handle->bufsize = 0;
if (new_pcap_dag(handle) < 0) {
- snprintf(handle->errbuf, PCAP_ERRBUF_SIZE, "new_pcap_dag %s: %s\n", device, pcap_strerror(errno));
+ pcap_snprintf(handle->errbuf, PCAP_ERRBUF_SIZE, "new_pcap_dag %s: %s", device, pcap_strerror(errno));
goto failstop;
}
@@ -833,12 +944,12 @@ static int dag_activate(pcap_t* handle)
handlep->stat.ps_ifdrop = 0;
return 0;
-#ifdef HAVE_DAG_STREAMS_API
+#ifdef HAVE_DAG_STREAMS_API
failstop:
if (dag_stop_stream(handle->fd, handlep->dag_stream) < 0) {
fprintf(stderr,"dag_stop_stream: %s\n", strerror(errno));
}
-
+
faildetach:
if (dag_detach_stream(handle->fd, handlep->dag_stream) < 0)
fprintf(stderr,"dag_detach_stream: %s\n", strerror(errno));
@@ -847,7 +958,7 @@ failstop:
if (dag_stop(handle->fd) < 0)
fprintf(stderr,"dag_stop: %s\n", strerror(errno));
#endif /* HAVE_DAG_STREAMS_API */
-
+
failclose:
if (dag_close(handle->fd) < 0)
fprintf(stderr,"dag_close: %s\n", strerror(errno));
@@ -912,11 +1023,29 @@ pcap_t *dag_create(const char *device, char *ebuf, int *is_ours)
/* OK, it's probably ours. */
*is_ours = 1;
- p = pcap_create_common(device, ebuf, sizeof (struct pcap_dag));
+ p = pcap_create_common(ebuf, sizeof (struct pcap_dag));
if (p == NULL)
return NULL;
p->activate_op = dag_activate;
+
+ /*
+ * We claim that we support microsecond and nanosecond time
+ * stamps.
+ *
+ * XXX Our native precision is 2^-32s, but libpcap doesn't support
+ * power of two precisions yet. We can convert to either MICRO or NANO.
+ */
+ p->tstamp_precision_count = 2;
+ p->tstamp_precision_list = malloc(2 * sizeof(u_int));
+ if (p->tstamp_precision_list == NULL) {
+ pcap_snprintf(ebuf, PCAP_ERRBUF_SIZE, "malloc: %s",
+ pcap_strerror(errno));
+ pcap_close(p);
+ return NULL;
+ }
+ p->tstamp_precision_list[0] = PCAP_TSTAMP_PRECISION_MICRO;
+ p->tstamp_precision_list[1] = PCAP_TSTAMP_PRECISION_NANO;
return p;
}
@@ -929,9 +1058,9 @@ dag_stats(pcap_t *p, struct pcap_stat *ps) {
*/
/*pd->stat.ps_recv = 0;*/
/*pd->stat.ps_drop = 0;*/
-
+
*ps = pd->stat;
-
+
return 0;
}
@@ -953,16 +1082,21 @@ dag_findalldevs(pcap_if_t **devlistp, char *errbuf)
char dagname[DAGNAME_BUFSIZE];
int dagstream;
int dagfd;
+ dag_card_inf_t *inf;
+ char *description;
/* Try all the DAGs 0-DAG_MAX_BOARDS */
for (c = 0; c < DAG_MAX_BOARDS; c++) {
- snprintf(name, 12, "dag%d", c);
+ pcap_snprintf(name, 12, "dag%d", c);
if (-1 == dag_parse_name(name, dagname, DAGNAME_BUFSIZE, &dagstream))
{
return -1;
}
+ description = NULL;
if ( (dagfd = dag_open(dagname)) >= 0 ) {
- if (pcap_add_if(devlistp, name, 0, NULL, errbuf) == -1) {
+ if ((inf = dag_pciinfo(dagfd)))
+ description = dag_device_name(inf->device_code, 1);
+ if (pcap_add_if(devlistp, name, 0, description, errbuf) == -1) {
/*
* Failure.
*/
@@ -976,20 +1110,20 @@ dag_findalldevs(pcap_if_t **devlistp, char *errbuf)
if (0 == dag_attach_stream(dagfd, stream, 0, 0)) {
dag_detach_stream(dagfd, stream);
- snprintf(name, 10, "dag%d:%d", c, stream);
- if (pcap_add_if(devlistp, name, 0, NULL, errbuf) == -1) {
+ pcap_snprintf(name, 10, "dag%d:%d", c, stream);
+ if (pcap_add_if(devlistp, name, 0, description, errbuf) == -1) {
/*
* Failure.
*/
ret = -1;
}
-
+
rxstreams--;
if(rxstreams <= 0) {
break;
}
}
- }
+ }
}
#endif /* HAVE_DAG_STREAMS_API */
dag_close(dagfd);
@@ -1049,13 +1183,13 @@ dag_setnonblock(pcap_t *p, int nonblock, char *errbuf)
uint32_t mindata;
struct timeval maxwait;
struct timeval poll;
-
+
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));
+ pcap_snprintf(errbuf, PCAP_ERRBUF_SIZE, "dag_get_stream_poll: %s", pcap_strerror(errno));
return -1;
}
-
+
/* Amount of data to collect in Bytes before calling callbacks.
* Important for efficiency, but can introduce latency
* at low packet rates if to_ms not set!
@@ -1064,10 +1198,10 @@ dag_setnonblock(pcap_t *p, int nonblock, char *errbuf)
mindata = 0;
else
mindata = 65536;
-
+
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));
+ pcap_snprintf(errbuf, PCAP_ERRBUF_SIZE, "dag_set_stream_poll: %s", pcap_strerror(errno));
return -1;
}
}
@@ -1079,7 +1213,7 @@ dag_setnonblock(pcap_t *p, int nonblock, char *errbuf)
}
return (0);
}
-
+
static int
dag_get_datalink(pcap_t *p)
{
@@ -1090,7 +1224,7 @@ dag_get_datalink(pcap_t *p)
memset(types, 0, 255);
if (p->dlt_list == NULL && (p->dlt_list = malloc(255*sizeof(*(p->dlt_list)))) == NULL) {
- (void)snprintf(p->errbuf, sizeof(p->errbuf), "malloc: %s", pcap_strerror(errno));
+ (void)pcap_snprintf(p->errbuf, sizeof(p->errbuf), "malloc: %s", pcap_strerror(errno));
return (-1);
}
@@ -1099,19 +1233,19 @@ dag_get_datalink(pcap_t *p)
#ifdef HAVE_DAG_GET_STREAM_ERF_TYPES
/* Get list of possible ERF types for this card */
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);
+ pcap_snprintf(p->errbuf, sizeof(p->errbuf), "dag_get_stream_erf_types: %s", pcap_strerror(errno));
+ return (-1);
}
-
+
while (types[index]) {
#elif defined HAVE_DAG_GET_ERF_TYPES
/* Get list of possible ERF types for this card */
if (dag_get_erf_types(p->fd, types, 255) < 0) {
- snprintf(p->errbuf, sizeof(p->errbuf), "dag_get_erf_types: %s", pcap_strerror(errno));
- return (-1);
+ pcap_snprintf(p->errbuf, sizeof(p->errbuf), "dag_get_erf_types: %s", pcap_strerror(errno));
+ return (-1);
}
-
+
while (types[index]) {
#else
/* Check the type through a dagapi call. */
@@ -1157,7 +1291,7 @@ dag_get_datalink(pcap_t *p)
p->linktype = DLT_EN10MB;
break;
- case TYPE_ATM:
+ case TYPE_ATM:
case TYPE_AAL5:
case TYPE_MC_ATM:
case TYPE_MC_AAL5:
@@ -1215,3 +1349,31 @@ dag_get_datalink(pcap_t *p)
return p->linktype;
}
+
+#ifdef DAG_ONLY
+/*
+ * This libpcap build supports only DAG cards, not regular network
+ * interfaces.
+ */
+
+/*
+ * There are no regular interfaces, just DAG interfaces.
+ */
+int
+pcap_platform_finddevs(pcap_if_t **alldevsp, char *errbuf)
+{
+ *alldevsp = NULL;
+ return (0);
+}
+
+/*
+ * Attempts to open a regular interface fail.
+ */
+pcap_t *
+pcap_create_interface(const char *device, char *errbuf)
+{
+ pcap_snprintf(errbuf, PCAP_ERRBUF_SIZE,
+ "This version of libpcap only supports DAG cards");
+ return NULL;
+}
+#endif
diff --git a/contrib/libpcap/pcap-dag.h b/contrib/libpcap/pcap-dag.h
index 68520dc8214d..dfeccd8b7116 100644
--- a/contrib/libpcap/pcap-dag.h
+++ b/contrib/libpcap/pcap-dag.h
@@ -10,97 +10,3 @@
pcap_t *dag_create(const char *, char *, int *);
int dag_findalldevs(pcap_if_t **devlistp, char *errbuf);
-
-#ifndef TYPE_AAL5
-#define TYPE_AAL5 4
-#endif
-
-#ifndef TYPE_MC_HDLC
-#define TYPE_MC_HDLC 5
-#endif
-
-#ifndef TYPE_MC_RAW
-#define TYPE_MC_RAW 6
-#endif
-
-#ifndef TYPE_MC_ATM
-#define TYPE_MC_ATM 7
-#endif
-
-#ifndef TYPE_MC_RAW_CHANNEL
-#define TYPE_MC_RAW_CHANNEL 8
-#endif
-
-#ifndef TYPE_MC_AAL5
-#define TYPE_MC_AAL5 9
-#endif
-
-#ifndef TYPE_COLOR_HDLC_POS
-#define TYPE_COLOR_HDLC_POS 10
-#endif
-
-#ifndef TYPE_COLOR_ETH
-#define TYPE_COLOR_ETH 11
-#endif
-
-#ifndef TYPE_MC_AAL2
-#define TYPE_MC_AAL2 12
-#endif
-
-#ifndef TYPE_IP_COUNTER
-#define TYPE_IP_COUNTER 13
-#endif
-
-#ifndef TYPE_TCP_FLOW_COUNTER
-#define TYPE_TCP_FLOW_COUNTER 14
-#endif
-
-#ifndef TYPE_DSM_COLOR_HDLC_POS
-#define TYPE_DSM_COLOR_HDLC_POS 15
-#endif
-
-#ifndef TYPE_DSM_COLOR_ETH
-#define TYPE_DSM_COLOR_ETH 16
-#endif
-
-#ifndef TYPE_COLOR_MC_HDLC_POS
-#define TYPE_COLOR_MC_HDLC_POS 17
-#endif
-
-#ifndef TYPE_AAL2
-#define TYPE_AAL2 18
-#endif
-
-#ifndef TYPE_COLOR_HASH_POS
-#define TYPE_COLOR_HASH_POS 19
-#endif
-
-#ifndef TYPE_COLOR_HASH_ETH
-#define TYPE_COLOR_HASH_ETH 20
-#endif
-
-#ifndef TYPE_INFINIBAND
-#define TYPE_INFINIBAND 21
-#endif
-
-#ifndef TYPE_IPV4
-#define TYPE_IPV4 22
-#endif
-
-#ifndef TYPE_IPV6
-#define TYPE_IPV6 23
-#endif
-
-#ifndef TYPE_RAW_LINK
-#define TYPE_RAW_LINK 24
-#endif
-
-#ifndef TYPE_INFINIBAND_LINK
-#define TYPE_INFINIBAND_LINK 25
-#endif
-
-
-
-#ifndef TYPE_PAD
-#define TYPE_PAD 48
-#endif
diff --git a/contrib/libpcap/pcap-dbus.c b/contrib/libpcap/pcap-dbus.c
index c878353b9f4b..8e92093da110 100644
--- a/contrib/libpcap/pcap-dbus.c
+++ b/contrib/libpcap/pcap-dbus.c
@@ -11,8 +11,8 @@
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
- * 3. The name of the author may not be used to endorse or promote
- * products derived from this software without specific prior written
+ * 3. The name of the author may not be used to endorse or promote
+ * products derived from this software without specific prior written
* permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
@@ -66,9 +66,9 @@ dbus_read(pcap_t *handle, int max_packets, pcap_handler callback, u_char *user)
message = dbus_connection_pop_message(handlep->conn);
while (!message) {
- // XXX handle->opt.timeout = timeout_ms;
+ /* XXX handle->opt.timeout = timeout_ms; */
if (!dbus_connection_read_write(handlep->conn, 100)) {
- snprintf(handle->errbuf, PCAP_ERRBUF_SIZE, "Connection closed");
+ pcap_snprintf(handle->errbuf, PCAP_ERRBUF_SIZE, "Connection closed");
return -1;
}
@@ -81,7 +81,7 @@ dbus_read(pcap_t *handle, int max_packets, pcap_handler callback, u_char *user)
}
if (dbus_message_is_signal(message, DBUS_INTERFACE_LOCAL, "Disconnected")) {
- snprintf(handle->errbuf, PCAP_ERRBUF_SIZE, "Disconnected");
+ pcap_snprintf(handle->errbuf, PCAP_ERRBUF_SIZE, "Disconnected");
return -1;
}
@@ -112,7 +112,7 @@ dbus_write(pcap_t *handle, const void *buf, size_t size)
DBusMessage *msg;
if (!(msg = dbus_message_demarshal(buf, size, &error))) {
- snprintf(handle->errbuf, PCAP_ERRBUF_SIZE, "dbus_message_demarshal() failed: %s", error.message);
+ pcap_snprintf(handle->errbuf, PCAP_ERRBUF_SIZE, "dbus_message_demarshal() failed: %s", error.message);
dbus_error_free(&error);
return -1;
}
@@ -122,7 +122,7 @@ dbus_write(pcap_t *handle, const void *buf, size_t size)
dbus_message_unref(msg);
return 0;
-}
+}
static int
dbus_stats(pcap_t *handle, struct pcap_stat *stats)
@@ -160,21 +160,21 @@ dbus_activate(pcap_t *handle)
#define N_RULES sizeof(rules)/sizeof(rules[0])
struct pcap_dbus *handlep = handle->priv;
- const char *dev = handle->opt.source;
+ const char *dev = handle->opt.device;
DBusError error = DBUS_ERROR_INIT;
- int i;
+ u_int i;
if (strcmp(dev, "dbus-system") == 0) {
if (!(handlep->conn = dbus_bus_get(DBUS_BUS_SYSTEM, &error))) {
- snprintf(handle->errbuf, PCAP_ERRBUF_SIZE, "Failed to get system bus: %s", error.message);
+ pcap_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 (!(handlep->conn = dbus_bus_get(DBUS_BUS_SESSION, &error))) {
- snprintf(handle->errbuf, PCAP_ERRBUF_SIZE, "Failed to get session bus: %s", error.message);
+ pcap_snprintf(handle->errbuf, PCAP_ERRBUF_SIZE, "Failed to get session bus: %s", error.message);
dbus_error_free(&error);
return PCAP_ERROR;
}
@@ -183,19 +183,19 @@ dbus_activate(pcap_t *handle)
const char *addr = dev + 7;
if (!(handlep->conn = dbus_connection_open(addr, &error))) {
- snprintf(handle->errbuf, PCAP_ERRBUF_SIZE, "Failed to open connection to: %s: %s", addr, error.message);
+ pcap_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(handlep->conn, &error)) {
- snprintf(handle->errbuf, PCAP_ERRBUF_SIZE, "Failed to register bus %s: %s\n", addr, error.message);
+ pcap_snprintf(handle->errbuf, PCAP_ERRBUF_SIZE, "Failed to register bus %s: %s\n", addr, error.message);
dbus_error_free(&error);
return PCAP_ERROR;
}
} else {
- snprintf(handle->errbuf, PCAP_ERRBUF_SIZE, "Can't get bus address from %s", handle->opt.source);
+ pcap_snprintf(handle->errbuf, PCAP_ERRBUF_SIZE, "Can't get bus address from %s", handle->opt.device);
return PCAP_ERROR;
}
@@ -234,7 +234,7 @@ dbus_activate(pcap_t *handle)
/* try without eavesdrop */
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);
+ pcap_snprintf(handle->errbuf, PCAP_ERRBUF_SIZE, "Failed to add bus match: %s\n", error.message);
dbus_error_free(&error);
dbus_cleanup(handle);
return PCAP_ERROR;
@@ -250,8 +250,8 @@ dbus_create(const char *device, char *ebuf, int *is_ours)
{
pcap_t *p;
- if (strcmp(device, "dbus-system") &&
- strcmp(device, "dbus-session") &&
+ if (strcmp(device, "dbus-system") &&
+ strcmp(device, "dbus-session") &&
strncmp(device, "dbus://", 7))
{
*is_ours = 0;
@@ -259,7 +259,7 @@ dbus_create(const char *device, char *ebuf, int *is_ours)
}
*is_ours = 1;
- p = pcap_create_common(device, ebuf, sizeof (struct pcap_dbus));
+ p = pcap_create_common(ebuf, sizeof (struct pcap_dbus));
if (p == NULL)
return (NULL);
@@ -267,7 +267,7 @@ dbus_create(const char *device, char *ebuf, int *is_ours)
return (p);
}
-int
+int
dbus_findalldevs(pcap_if_t **alldevsp, char *err_str)
{
if (pcap_add_if(alldevsp, "dbus-system", 0, "D-Bus system bus", err_str) < 0)
diff --git a/contrib/libpcap/pcap-dlpi.c b/contrib/libpcap/pcap-dlpi.c
index 459860066eb6..a431e7c1a3fa 100644
--- a/contrib/libpcap/pcap-dlpi.c
+++ b/contrib/libpcap/pcap-dlpi.c
@@ -153,10 +153,12 @@ static void dlpassive(int, char *);
static int dlrawdatareq(int, const u_char *, int);
#endif
static int recv_ack(int, int, const char *, char *, char *, int *);
-static char *dlstrerror(bpf_u_int32);
-static char *dlprim(bpf_u_int32);
+static char *dlstrerror(char *, size_t, bpf_u_int32);
+static char *dlprim(char *, size_t, bpf_u_int32);
#if defined(HAVE_SOLARIS) && defined(HAVE_SYS_BUFMOD_H)
-static char *get_release(bpf_u_int32 *, bpf_u_int32 *, bpf_u_int32 *);
+#define GET_RELEASE_BUFSIZE 32
+static void get_release(char *, size_t, bpf_u_int32 *, bpf_u_int32 *,
+ bpf_u_int32 *);
#endif
static int send_request(int, char *, int, char *, char *);
#ifdef HAVE_HPUX9
@@ -166,14 +168,6 @@ static int dlpi_kread(int, off_t, void *, u_int, char *);
static int get_dlpi_ppa(int, const char *, int, char *);
#endif
-/* XXX Needed by HP-UX (at least) */
-static bpf_u_int32 ctlbuf[MAXDLBUF];
-static struct strbuf ctl = {
- MAXDLBUF,
- 0,
- (char *)ctlbuf
-};
-
/*
* Cast a buffer to "union DL_primitives" without provoking warnings
* from the compiler.
@@ -186,6 +180,12 @@ pcap_read_dlpi(pcap_t *p, int cnt, pcap_handler callback, u_char *user)
int cc;
u_char *bp;
int flags;
+ bpf_u_int32 ctlbuf[MAXDLBUF];
+ struct strbuf ctl = {
+ MAXDLBUF,
+ 0,
+ (char *)ctlbuf
+ };
struct strbuf data;
flags = 0;
@@ -213,6 +213,9 @@ pcap_read_dlpi(pcap_t *p, int cnt, pcap_handler callback, u_char *user)
* would be DL_HP_RAWDATA_IND on HP-UX
* if we're in raw mode?
*/
+ ctl.buf = (char *)ctlbuf;
+ ctl.maxlen = MAXDLBUF;
+ ctl.len = 0;
if (getmsg(p->fd, &ctl, &data, &flags) < 0) {
/* Don't choke when we get ptraced */
switch (errno) {
@@ -230,7 +233,7 @@ pcap_read_dlpi(pcap_t *p, int cnt, pcap_handler callback, u_char *user)
}
cc = data.len;
} while (cc == 0);
- bp = p->buffer + p->offset;
+ bp = (u_char *)p->buffer + p->offset;
} else
bp = p->bp;
@@ -248,19 +251,19 @@ pcap_inject_dlpi(pcap_t *p, const void *buf, size_t size)
#if defined(DLIOCRAW)
ret = write(p->fd, buf, size);
if (ret == -1) {
- snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "send: %s",
+ pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "send: %s",
pcap_strerror(errno));
return (-1);
}
#elif defined(DL_HP_RAWDLS)
if (pd->send_fd < 0) {
- snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
+ pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
"send: Output FD couldn't be opened");
return (-1);
}
ret = dlrawdatareq(pd->send_fd, buf, size);
if (ret == -1) {
- snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "send: %s",
+ pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "send: %s",
pcap_strerror(errno));
return (-1);
}
@@ -298,7 +301,7 @@ pcap_inject_dlpi(pcap_t *p, const void *buf, size_t size)
ret = -1;
#endif /* raw mode */
return (ret);
-}
+}
#ifndef DL_IPATM
#define DL_IPATM 0x12 /* ATM Classical IP interface */
@@ -331,28 +334,12 @@ pcap_cleanup_dlpi(pcap_t *p)
}
static int
-pcap_activate_dlpi(pcap_t *p)
+open_dlpi_device(const char *name, int *ppa, char *errbuf)
{
-#ifdef DL_HP_RAWDLS
- struct pcap_dlpi *pd = p->priv;
-#endif
- int status = 0;
- int retv;
- register char *cp;
- int ppa;
-#ifdef HAVE_SOLARIS
- int isatm = 0;
-#endif
- register dl_info_ack_t *infop;
-#ifdef HAVE_SYS_BUFMOD_H
- bpf_u_int32 ss;
-#ifdef HAVE_SOLARIS
- register char *release;
- bpf_u_int32 osmajor, osminor, osmicro;
-#endif
-#endif
- bpf_u_int32 buf[MAXDLBUF];
+ int status;
char dname[100];
+ char *cp;
+ int fd;
#ifndef HAVE_DEV_DLPI
char dname2[100];
#endif
@@ -361,9 +348,9 @@ pcap_activate_dlpi(pcap_t *p)
/*
** Remove any "/dev/" on the front of the device.
*/
- cp = strrchr(p->opt.source, '/');
+ cp = strrchr(name, '/');
if (cp == NULL)
- strlcpy(dname, p->opt.source, sizeof(dname));
+ strlcpy(dname, name, sizeof(dname));
else
strlcpy(dname, cp + 1, sizeof(dname));
@@ -371,11 +358,9 @@ pcap_activate_dlpi(pcap_t *p)
* Split the device name into a device type name and a unit number;
* chop off the unit number, so "dname" is just a device type name.
*/
- cp = split_dname(dname, &ppa, p->errbuf);
- if (cp == NULL) {
- status = PCAP_ERROR_NO_SUCH_DEVICE;
- goto bad;
- }
+ cp = split_dname(dname, ppa, errbuf);
+ if (cp == NULL)
+ return (PCAP_ERROR_NO_SUCH_DEVICE);
*cp = '\0';
/*
@@ -390,39 +375,24 @@ pcap_activate_dlpi(pcap_t *p)
* device number, rather than hardwiring "/dev/dlpi".
*/
cp = "/dev/dlpi";
- if ((p->fd = open(cp, O_RDWR)) < 0) {
+ if ((fd = open(cp, O_RDWR)) < 0) {
if (errno == EPERM || errno == EACCES)
status = PCAP_ERROR_PERM_DENIED;
else
status = PCAP_ERROR;
- snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
+ pcap_snprintf(errbuf, PCAP_ERRBUF_SIZE,
"%s: %s", cp, pcap_strerror(errno));
- goto bad;
+ return (status);
}
-#ifdef DL_HP_RAWDLS
- /*
- * XXX - HP-UX 10.20 and 11.xx don't appear to support sending and
- * 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 "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.
- */
- pd->send_fd = open(cp, O_RDWR);
-#endif
-
/*
* Get a table of all PPAs for that device, and search that
* table for the specified device type name and unit number.
*/
- ppa = get_dlpi_ppa(p->fd, dname, ppa, p->errbuf);
- if (ppa < 0) {
- status = ppa;
- goto bad;
+ *ppa = get_dlpi_ppa(fd, dname, *ppa, errbuf);
+ if (*ppa < 0) {
+ close(fd);
+ return (*ppa);
}
#else
/*
@@ -431,21 +401,19 @@ pcap_activate_dlpi(pcap_t *p)
* otherwise, concatenate the device directory name and the
* device name.
*/
- if (*p->opt.source == '/')
- strlcpy(dname, p->opt.source, sizeof(dname));
+ if (*name == '/')
+ strlcpy(dname, name, sizeof(dname));
else
- snprintf(dname, sizeof(dname), "%s/%s", PCAP_DEV_PREFIX,
- p->opt.source);
+ pcap_snprintf(dname, sizeof(dname), "%s/%s", PCAP_DEV_PREFIX,
+ name);
/*
* Get the unit number, and a pointer to the end of the device
* type name.
*/
- cp = split_dname(dname, &ppa, p->errbuf);
- if (cp == NULL) {
- status = PCAP_ERROR_NO_SUCH_DEVICE;
- goto bad;
- }
+ cp = split_dname(dname, ppa, errbuf);
+ if (cp == NULL)
+ return (PCAP_ERROR_NO_SUCH_DEVICE);
/*
* Make a copy of the device pathname, and then remove the unit
@@ -455,19 +423,19 @@ pcap_activate_dlpi(pcap_t *p)
*cp = '\0';
/* Try device without unit number */
- if ((p->fd = open(dname, O_RDWR)) < 0) {
+ if ((fd = open(dname, O_RDWR)) < 0) {
if (errno != ENOENT) {
if (errno == EPERM || errno == EACCES)
status = PCAP_ERROR_PERM_DENIED;
else
status = PCAP_ERROR;
- snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "%s: %s", dname,
+ pcap_snprintf(errbuf, PCAP_ERRBUF_SIZE, "%s: %s", dname,
pcap_strerror(errno));
- goto bad;
+ return (status);
}
/* Try again with unit number */
- if ((p->fd = open(dname2, O_RDWR)) < 0) {
+ if ((fd = open(dname2, O_RDWR)) < 0) {
if (errno == ENOENT) {
status = PCAP_ERROR_NO_SUCH_DEVICE;
@@ -482,32 +450,79 @@ pcap_activate_dlpi(pcap_t *p)
* found" with the device name, so people
* don't get confused and think, for example,
* that if they can't capture on "lo0"
- * on Solaris the fix is to change libpcap
- * (or the application that uses it) to
- * look for something other than "/dev/lo0",
- * as the fix is to look for an operating
- * system other than Solaris - you just
- * *can't* capture on a loopback interface
- * on Solaris, the lack of a DLPI device
- * for the loopback interface is just a
- * symptom of that inability.
+ * on Solaris prior to Solaris 11 the fix
+ * is to change libpcap (or the application
+ * that uses it) to look for something other
+ * than "/dev/lo0", as the fix is to use
+ * Solaris 11 or some operating system
+ * other than Solaris - you just *can't*
+ * capture on a loopback interface
+ * on Solaris prior to Solaris 11, the lack
+ * of a DLPI device for the loopback
+ * interface is just a symptom of that
+ * inability.
*/
- snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
- "%s: No DLPI device found", p->opt.source);
+ pcap_snprintf(errbuf, PCAP_ERRBUF_SIZE,
+ "%s: No DLPI device found", name);
} else {
if (errno == EPERM || errno == EACCES)
status = PCAP_ERROR_PERM_DENIED;
else
status = PCAP_ERROR;
- snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "%s: %s",
+ pcap_snprintf(errbuf, PCAP_ERRBUF_SIZE, "%s: %s",
dname2, pcap_strerror(errno));
}
- goto bad;
+ return (status);
}
/* XXX Assume unit zero */
- ppa = 0;
+ *ppa = 0;
}
#endif
+ return (fd);
+}
+
+static int
+pcap_activate_dlpi(pcap_t *p)
+{
+#ifdef DL_HP_RAWDLS
+ struct pcap_dlpi *pd = p->priv;
+#endif
+ int status = 0;
+ int retv;
+ int ppa;
+#ifdef HAVE_SOLARIS
+ int isatm = 0;
+#endif
+ register dl_info_ack_t *infop;
+#ifdef HAVE_SYS_BUFMOD_H
+ bpf_u_int32 ss;
+#ifdef HAVE_SOLARIS
+ char release[GET_RELEASE_BUFSIZE];
+ bpf_u_int32 osmajor, osminor, osmicro;
+#endif
+#endif
+ bpf_u_int32 buf[MAXDLBUF];
+
+ p->fd = open_dlpi_device(p->opt.device, &ppa, p->errbuf);
+ if (p->fd < 0) {
+ status = p->fd;
+ goto bad;
+ }
+
+#ifdef DL_HP_RAWDLS
+ /*
+ * XXX - HP-UX 10.20 and 11.xx don't appear to support sending and
+ * 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 "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.
+ */
+ pd->send_fd = open("/dev/dlpi", O_RDWR);
+#endif
/*
** Attach if "style 2" provider
@@ -627,7 +642,7 @@ pcap_activate_dlpi(pcap_t *p)
*/
if (strioctl(p->fd, A_PROMISCON_REQ, 0, NULL) < 0) {
status = PCAP_ERROR;
- snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
+ pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
"A_PROMISCON_REQ: %s", pcap_strerror(errno));
goto bad;
}
@@ -745,7 +760,7 @@ pcap_activate_dlpi(pcap_t *p)
*/
if (strioctl(p->fd, DLIOCRAW, 0, NULL) < 0) {
status = PCAP_ERROR;
- snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "DLIOCRAW: %s",
+ pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "DLIOCRAW: %s",
pcap_strerror(errno));
goto bad;
}
@@ -763,10 +778,10 @@ pcap_activate_dlpi(pcap_t *p)
** Ask for bugid 1149065.
*/
#ifdef HAVE_SOLARIS
- release = get_release(&osmajor, &osminor, &osmicro);
+ get_release(release, sizeof (release), &osmajor, &osminor, &osmicro);
if (osmajor == 5 && (osminor <= 2 || (osminor == 3 && osmicro < 2)) &&
getenv("BUFMOD_FIXED") == NULL) {
- snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
+ pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
"WARNING: bufmod is broken in SunOS %s; ignoring snaplen.",
release);
ss = 0;
@@ -786,7 +801,7 @@ pcap_activate_dlpi(pcap_t *p)
*/
if (ioctl(p->fd, I_FLUSH, FLUSHR) != 0) {
status = PCAP_ERROR;
- snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "FLUSHR: %s",
+ pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "FLUSHR: %s",
pcap_strerror(errno));
goto bad;
}
@@ -841,7 +856,7 @@ split_dname(char *device, int *unitp, char *ebuf)
*/
cp = device + strlen(device) - 1;
if (*cp < '0' || *cp > '9') {
- snprintf(ebuf, PCAP_ERRBUF_SIZE, "%s missing unit number",
+ pcap_snprintf(ebuf, PCAP_ERRBUF_SIZE, "%s missing unit number",
device);
return (NULL);
}
@@ -853,16 +868,16 @@ split_dname(char *device, int *unitp, char *ebuf)
errno = 0;
unit = strtol(cp, &eos, 10);
if (*eos != '\0') {
- snprintf(ebuf, PCAP_ERRBUF_SIZE, "%s bad unit number", device);
+ pcap_snprintf(ebuf, PCAP_ERRBUF_SIZE, "%s bad unit number", device);
return (NULL);
}
if (errno == ERANGE || unit > INT_MAX) {
- snprintf(ebuf, PCAP_ERRBUF_SIZE, "%s unit number too large",
+ pcap_snprintf(ebuf, PCAP_ERRBUF_SIZE, "%s unit number too large",
device);
return (NULL);
}
if (unit < 0) {
- snprintf(ebuf, PCAP_ERRBUF_SIZE, "%s unit number is negative",
+ pcap_snprintf(ebuf, PCAP_ERRBUF_SIZE, "%s unit number is negative",
device);
return (NULL);
}
@@ -960,6 +975,56 @@ dlpromiscon(pcap_t *p, bpf_u_int32 level)
return (0);
}
+/*
+ * Not all interfaces are DLPI interfaces, and thus not all interfaces
+ * can be opened with DLPI (for example, the loopback interface is not
+ * a DLPI interface on Solaris prior to Solaris 11), so try to open
+ * the specified interface; return 0 if we fail with PCAP_ERROR_NO_SUCH_DEVICE
+ * and 1 otherwise.
+ */
+static int
+is_dlpi_interface(const char *name)
+{
+ int fd;
+ int ppa;
+ char errbuf[PCAP_ERRBUF_SIZE];
+
+ fd = open_dlpi_device(name, &ppa, errbuf);
+ if (fd < 0) {
+ /*
+ * Error - was it PCAP_ERROR_NO_SUCH_DEVICE?
+ */
+ if (fd == PCAP_ERROR_NO_SUCH_DEVICE) {
+ /*
+ * Yes, so we can't open this because it's
+ * not a DLPI interface.
+ */
+ return (0);
+ }
+ /*
+ * No, so, in the case where there's a single DLPI
+ * device for all interfaces of this type ("style
+ * 2" providers?), we don't know whether it's a DLPI
+ * interface or not, as we didn't try an attach.
+ * Say it is a DLPI device, so that the user can at
+ * least try to open it and report the error (which
+ * is probably "you don't have permission to open that
+ * DLPI device"; reporting those interfaces means
+ * users will ask "why am I getting a permissions error
+ * when I try to capture" rather than "why am I not
+ * seeing any interfaces", making the underlying problem
+ * clearer).
+ */
+ return (1);
+ }
+
+ /*
+ * Success.
+ */
+ close(fd);
+ return (1);
+}
+
int
pcap_platform_finddevs(pcap_if_t **alldevsp, char *errbuf)
{
@@ -972,7 +1037,15 @@ pcap_platform_finddevs(pcap_if_t **alldevsp, char *errbuf)
} buf;
char baname[2+1+1];
u_int i;
+#endif
+
+ /*
+ * Get the list of regular interfaces first.
+ */
+ if (pcap_findalldevs_interfaces(alldevsp, errbuf, is_dlpi_interface) == -1)
+ return (-1); /* failure */
+#ifdef HAVE_SOLARIS
/*
* We may have to do special magic to get ATM devices.
*/
@@ -989,12 +1062,12 @@ pcap_platform_finddevs(pcap_if_t **alldevsp, char *errbuf)
}
if (strioctl(fd, A_GET_UNITS, sizeof(buf), (char *)&buf) < 0) {
- snprintf(errbuf, PCAP_ERRBUF_SIZE, "A_GET_UNITS: %s",
+ pcap_snprintf(errbuf, PCAP_ERRBUF_SIZE, "A_GET_UNITS: %s",
pcap_strerror(errno));
return (-1);
}
for (i = 0; i < buf.nunits; i++) {
- snprintf(baname, sizeof baname, "ba%u", i);
+ pcap_snprintf(baname, sizeof baname, "ba%u", i);
if (pcap_add_if(alldevsp, baname, 0, NULL, errbuf) < 0)
return (-1);
}
@@ -1015,7 +1088,7 @@ send_request(int fd, char *ptr, int len, char *what, char *ebuf)
flags = 0;
if (putmsg(fd, &ctl, (struct strbuf *) NULL, flags) < 0) {
- snprintf(ebuf, PCAP_ERRBUF_SIZE,
+ pcap_snprintf(ebuf, PCAP_ERRBUF_SIZE,
"send_request: putmsg \"%s\": %s",
what, pcap_strerror(errno));
return (-1);
@@ -1029,6 +1102,8 @@ recv_ack(int fd, int size, const char *what, char *bufp, char *ebuf, int *uerror
union DL_primitives *dlp;
struct strbuf ctl;
int flags;
+ char errmsgbuf[PCAP_ERRBUF_SIZE];
+ char dlprimbuf[64];
/*
* Clear out "*uerror", so it's only set for DL_ERROR_ACK/DL_SYSERR,
@@ -1043,7 +1118,7 @@ recv_ack(int fd, int size, const char *what, char *bufp, char *ebuf, int *uerror
flags = 0;
if (getmsg(fd, &ctl, (struct strbuf*)NULL, &flags) < 0) {
- snprintf(ebuf, PCAP_ERRBUF_SIZE, "recv_ack: %s getmsg: %s",
+ pcap_snprintf(ebuf, PCAP_ERRBUF_SIZE, "recv_ack: %s getmsg: %s",
what, pcap_strerror(errno));
return (PCAP_ERROR);
}
@@ -1066,7 +1141,7 @@ recv_ack(int fd, int size, const char *what, char *bufp, char *ebuf, int *uerror
case DL_SYSERR:
if (uerror != NULL)
*uerror = dlp->error_ack.dl_unix_errno;
- snprintf(ebuf, PCAP_ERRBUF_SIZE,
+ pcap_snprintf(ebuf, PCAP_ERRBUF_SIZE,
"recv_ack: %s: UNIX error - %s",
what, pcap_strerror(dlp->error_ack.dl_unix_errno));
if (dlp->error_ack.dl_unix_errno == EPERM ||
@@ -1075,8 +1150,9 @@ recv_ack(int fd, int size, const char *what, char *bufp, char *ebuf, int *uerror
break;
default:
- snprintf(ebuf, PCAP_ERRBUF_SIZE, "recv_ack: %s: %s",
- what, dlstrerror(dlp->error_ack.dl_errno));
+ pcap_snprintf(ebuf, PCAP_ERRBUF_SIZE,
+ "recv_ack: %s: %s", what,
+ dlstrerror(errmsgbuf, sizeof (errmsgbuf), dlp->error_ack.dl_errno));
if (dlp->error_ack.dl_errno == DL_BADPPA)
return (PCAP_ERROR_NO_SUCH_DEVICE);
else if (dlp->error_ack.dl_errno == DL_ACCESS)
@@ -1086,14 +1162,14 @@ recv_ack(int fd, int size, const char *what, char *bufp, char *ebuf, int *uerror
return (PCAP_ERROR);
default:
- snprintf(ebuf, PCAP_ERRBUF_SIZE,
+ pcap_snprintf(ebuf, PCAP_ERRBUF_SIZE,
"recv_ack: %s: Unexpected primitive ack %s",
- what, dlprim(dlp->dl_primitive));
+ what, dlprim(dlprimbuf, sizeof (dlprimbuf), dlp->dl_primitive));
return (PCAP_ERROR);
}
if (ctl.len < size) {
- snprintf(ebuf, PCAP_ERRBUF_SIZE,
+ pcap_snprintf(ebuf, PCAP_ERRBUF_SIZE,
"recv_ack: %s: Ack too small (%d < %d)",
what, ctl.len, size);
return (PCAP_ERROR);
@@ -1102,10 +1178,8 @@ recv_ack(int fd, int size, const char *what, char *bufp, char *ebuf, int *uerror
}
static char *
-dlstrerror(bpf_u_int32 dl_errno)
+dlstrerror(char *errbuf, size_t errbufsize, bpf_u_int32 dl_errno)
{
- static char errstring[6+2+8+1];
-
switch (dl_errno) {
case DL_ACCESS:
@@ -1206,16 +1280,14 @@ dlstrerror(bpf_u_int32 dl_errno)
return ("Pending outstanding connect indications");
default:
- sprintf(errstring, "Error %02x", dl_errno);
- return (errstring);
+ pcap_snprintf(errbuf, errbufsize, "Error %02x", dl_errno);
+ return (errbuf);
}
}
static char *
-dlprim(bpf_u_int32 prim)
+dlprim(char *primbuf, size_t primbufsize, bpf_u_int32 prim)
{
- static char primbuf[80];
-
switch (prim) {
case DL_INFO_REQ:
@@ -1300,7 +1372,8 @@ dlprim(bpf_u_int32 prim)
return ("DL_RESET_CON");
default:
- (void) sprintf(primbuf, "unknown primitive 0x%x", prim);
+ pcap_snprintf(primbuf, primbufsize, "unknown primitive 0x%x",
+ prim);
return (primbuf);
}
}
@@ -1412,28 +1485,29 @@ dlrawdatareq(int fd, const u_char *datap, int datalen)
#endif /* DL_HP_RAWDLS */
#if defined(HAVE_SOLARIS) && defined(HAVE_SYS_BUFMOD_H)
-static char *
-get_release(bpf_u_int32 *majorp, bpf_u_int32 *minorp, bpf_u_int32 *microp)
+static void
+get_release(char *buf, size_t bufsize, bpf_u_int32 *majorp,
+ bpf_u_int32 *minorp, bpf_u_int32 *microp)
{
char *cp;
- static char buf[32];
*majorp = 0;
*minorp = 0;
*microp = 0;
- if (sysinfo(SI_RELEASE, buf, sizeof(buf)) < 0)
- return ("?");
+ if (sysinfo(SI_RELEASE, buf, bufsize) < 0) {
+ strlcpy(buf, "?", bufsize);
+ return;
+ }
cp = buf;
if (!isdigit((unsigned char)*cp))
- return (buf);
+ return;
*majorp = strtol(cp, &cp, 10);
if (*cp++ != '.')
- return (buf);
+ return;
*minorp = strtol(cp, &cp, 10);
if (*cp++ != '.')
- return (buf);
+ return;
*microp = strtol(cp, &cp, 10);
- return (buf);
}
#endif
@@ -1521,21 +1595,21 @@ get_dlpi_ppa(register int fd, register const char *device, register int unit,
*/
/* get the head first */
if (getmsg(fd, &ctl, (struct strbuf *)NULL, &flags) < 0) {
- snprintf(ebuf, PCAP_ERRBUF_SIZE,
+ pcap_snprintf(ebuf, PCAP_ERRBUF_SIZE,
"get_dlpi_ppa: hpppa getmsg: %s", pcap_strerror(errno));
return (PCAP_ERROR);
}
dlp = (dl_hp_ppa_ack_t *)ctl.buf;
if (dlp->dl_primitive != DL_HP_PPA_ACK) {
- snprintf(ebuf, PCAP_ERRBUF_SIZE,
+ pcap_snprintf(ebuf, PCAP_ERRBUF_SIZE,
"get_dlpi_ppa: hpppa unexpected primitive ack 0x%x",
(bpf_u_int32)dlp->dl_primitive);
return (PCAP_ERROR);
}
if (ctl.len < DL_HP_PPA_ACK_SIZE) {
- snprintf(ebuf, PCAP_ERRBUF_SIZE,
+ pcap_snprintf(ebuf, PCAP_ERRBUF_SIZE,
"get_dlpi_ppa: hpppa ack too small (%d < %lu)",
ctl.len, (unsigned long)DL_HP_PPA_ACK_SIZE);
return (PCAP_ERROR);
@@ -1543,7 +1617,7 @@ get_dlpi_ppa(register int fd, register const char *device, register int unit,
/* allocate buffer */
if ((ppa_data_buf = (char *)malloc(dlp->dl_length)) == NULL) {
- snprintf(ebuf, PCAP_ERRBUF_SIZE,
+ pcap_snprintf(ebuf, PCAP_ERRBUF_SIZE,
"get_dlpi_ppa: hpppa malloc: %s", pcap_strerror(errno));
return (PCAP_ERROR);
}
@@ -1552,13 +1626,13 @@ get_dlpi_ppa(register int fd, register const char *device, register int unit,
ctl.buf = (char *)ppa_data_buf;
/* get the data */
if (getmsg(fd, &ctl, (struct strbuf *)NULL, &flags) < 0) {
- snprintf(ebuf, PCAP_ERRBUF_SIZE,
+ pcap_snprintf(ebuf, PCAP_ERRBUF_SIZE,
"get_dlpi_ppa: hpppa getmsg: %s", pcap_strerror(errno));
free(ppa_data_buf);
return (PCAP_ERROR);
}
if (ctl.len < dlp->dl_length) {
- snprintf(ebuf, PCAP_ERRBUF_SIZE,
+ pcap_snprintf(ebuf, PCAP_ERRBUF_SIZE,
"get_dlpi_ppa: hpppa ack too small (%d < %lu)",
ctl.len, (unsigned long)dlp->dl_length);
free(ppa_data_buf);
@@ -1615,9 +1689,9 @@ get_dlpi_ppa(register int fd, register const char *device, register int unit,
* device number of a device with the name "/dev/<dev><unit>",
* if such a device exists, as the old code did.
*/
- snprintf(dname, sizeof(dname), "/dev/%s%d", device, unit);
+ pcap_snprintf(dname, sizeof(dname), "/dev/%s%d", device, unit);
if (stat(dname, &statbuf) < 0) {
- snprintf(ebuf, PCAP_ERRBUF_SIZE, "stat: %s: %s",
+ pcap_snprintf(ebuf, PCAP_ERRBUF_SIZE, "stat: %s: %s",
dname, pcap_strerror(errno));
return (PCAP_ERROR);
}
@@ -1634,12 +1708,12 @@ get_dlpi_ppa(register int fd, register const char *device, register int unit,
}
}
if (i == ap->dl_count) {
- snprintf(ebuf, PCAP_ERRBUF_SIZE,
+ pcap_snprintf(ebuf, PCAP_ERRBUF_SIZE,
"can't find /dev/dlpi PPA for %s%d", device, unit);
return (PCAP_ERROR_NO_SUCH_DEVICE);
}
if (ip->dl_hdw_state == HDW_DEAD) {
- snprintf(ebuf, PCAP_ERRBUF_SIZE,
+ pcap_snprintf(ebuf, PCAP_ERRBUF_SIZE,
"%s%d: hardware state: DOWN\n", device, unit);
free(ppa_data_buf);
return (PCAP_ERROR);
@@ -1678,19 +1752,19 @@ get_dlpi_ppa(register int fd, register const char *ifname, register int unit,
if (cp != NULL)
ifname = cp + 1;
if (nlist(path_vmunix, &nl) < 0) {
- snprintf(ebuf, PCAP_ERRBUF_SIZE, "nlist %s failed",
+ pcap_snprintf(ebuf, PCAP_ERRBUF_SIZE, "nlist %s failed",
path_vmunix);
return (-1);
}
if (nl[NL_IFNET].n_value == 0) {
- snprintf(ebuf, PCAP_ERRBUF_SIZE,
+ pcap_snprintf(ebuf, PCAP_ERRBUF_SIZE,
"could't find %s kernel symbol",
nl[NL_IFNET].n_name);
return (-1);
}
kd = open("/dev/kmem", O_RDONLY);
if (kd < 0) {
- snprintf(ebuf, PCAP_ERRBUF_SIZE, "kmem open: %s",
+ pcap_snprintf(ebuf, PCAP_ERRBUF_SIZE, "kmem open: %s",
pcap_strerror(errno));
return (-1);
}
@@ -1712,7 +1786,7 @@ get_dlpi_ppa(register int fd, register const char *ifname, register int unit,
return (ifnet.if_index);
}
- snprintf(ebuf, PCAP_ERRBUF_SIZE, "Can't find %s", ifname);
+ pcap_snprintf(ebuf, PCAP_ERRBUF_SIZE, "Can't find %s", ifname);
return (-1);
}
@@ -1723,17 +1797,17 @@ dlpi_kread(register int fd, register off_t addr,
register int cc;
if (lseek(fd, addr, SEEK_SET) < 0) {
- snprintf(ebuf, PCAP_ERRBUF_SIZE, "lseek: %s",
+ pcap_snprintf(ebuf, PCAP_ERRBUF_SIZE, "lseek: %s",
pcap_strerror(errno));
return (-1);
}
cc = read(fd, buf, len);
if (cc < 0) {
- snprintf(ebuf, PCAP_ERRBUF_SIZE, "read: %s",
+ pcap_snprintf(ebuf, PCAP_ERRBUF_SIZE, "read: %s",
pcap_strerror(errno));
return (-1);
} else if (cc != len) {
- snprintf(ebuf, PCAP_ERRBUF_SIZE, "short read (%d != %d)", cc,
+ pcap_snprintf(ebuf, PCAP_ERRBUF_SIZE, "short read (%d != %d)", cc,
len);
return (-1);
}
@@ -1742,14 +1816,14 @@ dlpi_kread(register int fd, register off_t addr,
#endif
pcap_t *
-pcap_create_interface(const char *device, char *ebuf)
+pcap_create_interface(const char *device _U_, char *ebuf)
{
pcap_t *p;
#ifdef DL_HP_RAWDLS
struct pcap_dlpi *pd;
#endif
- p = pcap_create_common(device, ebuf, sizeof (struct pcap_dlpi));
+ p = pcap_create_common(ebuf, sizeof (struct pcap_dlpi));
if (p == NULL)
return (NULL);
diff --git a/contrib/libpcap/pcap-dos.c b/contrib/libpcap/pcap-dos.c
index 43f50c7f13b2..ea6b225a23ef 100644
--- a/contrib/libpcap/pcap-dos.c
+++ b/contrib/libpcap/pcap-dos.c
@@ -1,6 +1,6 @@
/*
* This file is part of DOS-libpcap
- * Ported to DOS/DOSX by G. Vanem <gvanem@broadpark.no>
+ * Ported to DOS/DOSX by G. Vanem <gvanem@yahoo.no>
*
* pcap-dos.c: Interface to PKTDRVR, NDIS2 and 32-bit pmode
* network drivers.
@@ -145,15 +145,15 @@ static struct device *get_device (int fd)
* Private data for capturing on MS-DOS.
*/
struct pcap_dos {
- void (*wait_proc)(void); /* call proc while waiting */
+ void (*wait_proc)(void); /* call proc while waiting */
struct pcap_stat stat;
};
-pcap_t *pcap_create_interface (const char *device, char *ebuf)
+pcap_t *pcap_create_interface (const char *device _U_, char *ebuf)
{
pcap_t *p;
- p = pcap_create_common(device, ebuf, sizeof (struct pcap_dos));
+ p = pcap_create_common(ebuf, sizeof (struct pcap_dos));
if (p == NULL)
return (NULL);
@@ -166,9 +166,7 @@ pcap_t *pcap_create_interface (const char *device, char *ebuf)
* network packets.
*/
static int pcap_activate_dos (pcap_t *pcap)
-{
- struct pcap_dos *pcapd = pcap->priv;
-
+{
if (pcap->opt.rfmon) {
/*
* No monitor mode on DOS.
@@ -188,23 +186,26 @@ static int pcap_activate_dos (pcap_t *pcap)
pcap->stats_op = pcap_stats_dos;
pcap->inject_op = pcap_sendpacket_dos;
pcap->setfilter_op = pcap_setfilter_dos;
- pcap->setdirection_op = NULL; /* Not implemented.*/
+ pcap->setdirection_op = NULL; /* Not implemented.*/
pcap->fd = ++ref_count;
+ pcap->bufsize = ETH_MAX+100; /* add some margin */
+ pcap->buffer = calloc (pcap->bufsize, 1);
+
if (pcap->fd == 1) /* first time we're called */
{
- if (!init_watt32(pcap, pcap->opt.source, pcap->errbuf) ||
- !first_init(pcap->opt.source, pcap->errbuf, pcap->opt.promisc))
+ if (!init_watt32(pcap, pcap->opt.device, pcap->errbuf) ||
+ !first_init(pcap->opt.device, pcap->errbuf, pcap->opt.promisc))
{
return (PCAP_ERROR);
- }
+ }
atexit (close_driver);
}
- else if (stricmp(active_dev->name,pcap->opt.source))
+ else if (stricmp(active_dev->name,pcap->opt.device))
{
- snprintf (pcap->errbuf, PCAP_ERRBUF_SIZE,
- "Cannot use different devices simultaneously "
- "(`%s' vs. `%s')", active_dev->name, pcap->opt.source);
+ pcap_snprintf (pcap->errbuf, PCAP_ERRBUF_SIZE,
+ "Cannot use different devices simultaneously "
+ "(`%s' vs. `%s')", active_dev->name, pcap->opt.device);
return (PCAP_ERROR);
}
handle_to_device [pcap->fd-1] = active_dev;
@@ -221,7 +222,6 @@ 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 = { 0,0 };
- BYTE *rx_buf;
int rx_len = 0;
if (p->opt.timeout > 0)
@@ -253,13 +253,11 @@ pcap_read_one (pcap_t *p, pcap_handler callback, u_char *data)
if (dev->peek_rx_buf)
{
PCAP_ASSERT (dev->release_rx_buf);
- rx_len = (*dev->peek_rx_buf) (&rx_buf);
+ rx_len = (*dev->peek_rx_buf) (&p->buffer);
}
else
{
- BYTE buf [ETH_MAX+100]; /* add some margin */
- rx_len = (*dev->copy_rx_buf) (buf, p->snapshot);
- rx_buf = buf;
+ rx_len = (*dev->copy_rx_buf) (p->buffer, p->snapshot);
}
if (rx_len > 0) /* got a packet */
@@ -272,7 +270,7 @@ pcap_read_one (pcap_t *p, pcap_handler callback, u_char *data)
pcap.len = rx_len;
if (callback &&
- (!p->fcode.bf_insns || bpf_filter(p->fcode.bf_insns, rx_buf, pcap.len, pcap.caplen)))
+ (!p->fcode.bf_insns || bpf_filter(p->fcode.bf_insns, p->buffer, pcap.len, pcap.caplen)))
{
filter_count++;
@@ -280,11 +278,11 @@ pcap_read_one (pcap_t *p, pcap_handler callback, u_char *data)
* capture.
*/
gettimeofday2 (&pcap.ts, NULL);
- (*callback) (data, &pcap, rx_buf);
+ (*callback) (data, &pcap, p->buffer);
}
if (dev->release_rx_buf)
- (*dev->release_rx_buf) (rx_buf);
+ (*dev->release_rx_buf) (p->buffer);
if (pcap_pkt_debug > 0)
{
@@ -296,6 +294,18 @@ pcap_read_one (pcap_t *p, pcap_handler callback, u_char *data)
return (1);
}
+ /* Has "pcap_breakloop()" been called?
+ */
+ if (p->break_loop) {
+ /*
+ * Yes - clear the flag that indicates that it
+ * has, and return -2 to indicate that we were
+ * told to break out of the loop.
+ */
+ p->break_loop = 0;
+ return (-2);
+ }
+
/* If not to wait for a packet or pcap_cleanup_dos() called from
* e.g. SIGINT handler, exit loop now.
*/
@@ -311,8 +321,8 @@ pcap_read_one (pcap_t *p, pcap_handler callback, u_char *data)
kbhit(); /* a real CPU hog */
#endif
- if (p->wait_proc)
- (*p->wait_proc)(); /* call yield func */
+ if (pd->wait_proc)
+ (*pd->wait_proc)(); /* call yield func */
}
if (rx_len < 0) /* receive error */
@@ -330,7 +340,6 @@ pcap_read_one (pcap_t *p, pcap_handler callback, u_char *data)
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 || PACKET_COUNT_IS_UNLIMITED(cnt))
@@ -401,7 +410,7 @@ int pcap_stats_ex (pcap_t *p, struct pcap_stat_ex *se)
strlcpy (p->errbuf, "pktdrvr doesn't have detailed statistics",
PCAP_ERRBUF_SIZE);
return (-1);
- }
+ }
memcpy (se, (*dev->get_stats)(dev), sizeof(*se));
return (0);
}
@@ -442,7 +451,7 @@ static void pcap_cleanup_dos (pcap_t *p)
{
struct pcap_dos *pd;
- if (p && !exc_occured)
+ if (!exc_occured)
{
pd = p->priv;
if (pcap_stats(p,NULL) < 0)
@@ -495,6 +504,8 @@ char *pcap_lookupdev (char *ebuf)
int pcap_lookupnet (const char *device, bpf_u_int32 *localnet,
bpf_u_int32 *netmask, char *errbuf)
{
+ DWORD mask, net;
+
if (!_watt_is_init)
{
strcpy (errbuf, "pcap_open_offline() or pcap_activate() must be "
@@ -502,40 +513,43 @@ int pcap_lookupnet (const char *device, bpf_u_int32 *localnet,
return (-1);
}
- *netmask = _w32_sin_mask;
- *localnet = my_ip_addr & *netmask;
- if (*localnet == 0)
+ mask = _w32_sin_mask;
+ net = my_ip_addr & mask;
+ if (net == 0)
{
if (IN_CLASSA(*netmask))
- *localnet = IN_CLASSA_NET;
+ net = IN_CLASSA_NET;
else if (IN_CLASSB(*netmask))
- *localnet = IN_CLASSB_NET;
+ net = IN_CLASSB_NET;
else if (IN_CLASSC(*netmask))
- *localnet = IN_CLASSC_NET;
+ net = IN_CLASSC_NET;
else
{
- sprintf (errbuf, "inet class for 0x%lx unknown", *netmask);
+ pcap_snprintf (errbuf, PCAP_ERRBUF_SIZE, "inet class for 0x%lx unknown", mask);
return (-1);
}
}
+ *localnet = htonl (net);
+ *netmask = htonl (mask);
+
ARGSUSED (device);
return (0);
-}
+}
/*
* Get a list of all interfaces that are present and that we probe okay.
* Returns -1 on error, 0 otherwise.
- * The list, as returned through "alldevsp", may be null if no interfaces
+ * The list, as returned through "alldevsp", may be NULL if no interfaces
* were up and could be opened.
*/
-int pcap_findalldevs (pcap_if_t **alldevsp, char *errbuf)
+int pcap_platform_finddevs (pcap_if_t **alldevsp, char *errbuf)
{
struct device *dev;
- struct sockaddr_ll sa_ll_1, sa_ll_2;
+ struct sockaddr_in sa_ll_1, sa_ll_2;
struct sockaddr *addr, *netmask, *broadaddr, *dstaddr;
pcap_if_t *devlist = NULL;
int ret = 0;
- size_t addr_size = sizeof(struct sockaddr_ll);
+ size_t addr_size = sizeof(*addr);
for (dev = (struct device*)dev_base; dev; dev = dev->next)
{
@@ -550,14 +564,14 @@ int pcap_findalldevs (pcap_if_t **alldevsp, char *errbuf)
memset (&sa_ll_1, 0, sizeof(sa_ll_1));
memset (&sa_ll_2, 0, sizeof(sa_ll_2));
- sa_ll_1.sll_family = AF_PACKET;
- sa_ll_2.sll_family = AF_PACKET;
+ sa_ll_1.sin_family = AF_INET;
+ sa_ll_2.sin_family = AF_INET;
addr = (struct sockaddr*) &sa_ll_1;
netmask = (struct sockaddr*) &sa_ll_1;
dstaddr = (struct sockaddr*) &sa_ll_1;
broadaddr = (struct sockaddr*) &sa_ll_2;
- memset (&sa_ll_2.sll_addr, 0xFF, sizeof(sa_ll_2.sll_addr));
+ memset (&sa_ll_2.sin_addr, 0xFF, sizeof(sa_ll_2.sin_addr));
if (pcap_add_if(&devlist, dev->name, dev->flags,
dev->long_name, errbuf) < 0)
@@ -565,13 +579,15 @@ int pcap_findalldevs (pcap_if_t **alldevsp, char *errbuf)
ret = -1;
break;
}
- if (add_addr_to_iflist(&devlist,dev->name, dev->flags, addr, addr_size,
+#if 0 /* Pkt drivers should have no addresses */
+ if (add_addr_to_iflist(&devlist, dev->name, dev->flags, addr, addr_size,
netmask, addr_size, broadaddr, addr_size,
dstaddr, addr_size, errbuf) < 0)
{
ret = -1;
break;
}
+#endif
}
if (devlist && ret < 0)
@@ -605,12 +621,12 @@ void pcap_assert (const char *what, const char *file, unsigned line)
*/
void pcap_set_wait (pcap_t *p, void (*yield)(void), int wait)
{
- struct pcap_dos *pd;
if (p)
{
- pd = p->priv;
- pd->wait_proc = yield;
- p->opt.timeout = wait;
+ struct pcap_dos *pd = p->priv;
+
+ pd->wait_proc = yield;
+ p->opt.timeout = wait;
}
}
@@ -635,7 +651,7 @@ open_driver (const char *dev_name, char *ebuf, int promisc)
if (!(*dev->probe)(dev)) /* call the xx_probe() function */
{
- sprintf (ebuf, "failed to detect device `%s'", dev_name);
+ pcap_snprintf (ebuf, PCAP_ERRBUF_SIZE, "failed to detect device `%s'", dev_name);
return (NULL);
}
probed_dev = dev; /* device is probed okay and may be used */
@@ -657,7 +673,7 @@ open_driver (const char *dev_name, char *ebuf, int promisc)
if (!(*dev->open)(dev))
{
- sprintf (ebuf, "failed to activate device `%s'", dev_name);
+ pcap_snprintf (ebuf, PCAP_ERRBUF_SIZE, "failed to activate device `%s'", dev_name);
if (pktInfo.error && !strncmp(dev->name,"pkt",3))
{
strcat (ebuf, ": ");
@@ -679,14 +695,14 @@ open_driver (const char *dev_name, char *ebuf, int promisc)
*/
if (!dev)
{
- sprintf (ebuf, "device `%s' not supported", dev_name);
+ pcap_snprintf (ebuf, PCAP_ERRBUF_SIZE, "device `%s' not supported", dev_name);
return (NULL);
}
not_probed:
if (!probed_dev)
{
- sprintf (ebuf, "device `%s' not probed", dev_name);
+ pcap_snprintf (ebuf, PCAP_ERRBUF_SIZE, "device `%s' not probed", dev_name);
return (NULL);
}
return (dev);
@@ -756,7 +772,7 @@ static void exc_handler (int sig)
fprintf (stderr, "Catching signal %d.\n", sig);
}
exc_occured = 1;
- pcap_cleanup_dos (NULL);
+ close_driver();
}
#endif /* __DJGPP__ */
@@ -933,7 +949,7 @@ static int init_watt32 (struct pcap *pcap, const char *dev_name, char *err_buf)
if (_watt_is_init)
sock_exit();
- env = getenv ("PCAP_DEBUG");
+ env = getenv ("PCAP_TRACE");
if (env && atoi(env) > 0 &&
pcap_pkt_debug < 0) /* if not already set */
{
@@ -960,7 +976,7 @@ static int init_watt32 (struct pcap *pcap, const char *dev_name, char *err_buf)
* have default values. Should be taken from another
* ini-file/environment in any case (ref. tcpdump.ini)
*/
- _watt_is_init = 1;
+ _watt_is_init = 1;
if (!using_pktdrv || !has_ip_addr) /* for now .... */
{
@@ -973,7 +989,7 @@ static int init_watt32 (struct pcap *pcap, const char *dev_name, char *err_buf)
}
else if (rc && using_pktdrv)
{
- sprintf (err_buf, "sock_init() failed, code %d", rc);
+ pcap_snprintf (err_buf, PCAP_ERRBUF_SIZE, "sock_init() failed, code %d", rc);
return (0);
}
@@ -1053,9 +1069,9 @@ static const struct config_table debug_tab[] = {
* pcap_config_hook() is an extension to application's config
* handling. Uses Watt-32's config-table function.
*/
-int pcap_config_hook (const char *name, const char *value)
+int pcap_config_hook (const char *keyword, const char *value)
{
- return parse_config_table (debug_tab, NULL, name, value);
+ return parse_config_table (debug_tab, NULL, keyword, value);
}
/*
@@ -1092,7 +1108,7 @@ static int pkt_open (struct device *dev)
if (!PktInitDriver(mode))
return (0);
-
+
PktResetStatistics (pktInfo.handle);
PktQueueBusy (FALSE);
return (1);
@@ -1290,7 +1306,7 @@ struct device rtl8139_dev LOCKED_VAR = {
0,0,0,0,0,0,
&cs89_dev,
rtl8139_probe /* dev->probe routine */
- };
+ };
/*
* Dequeue routine is called by polling.
diff --git a/contrib/libpcap/pcap-dos.h b/contrib/libpcap/pcap-dos.h
index 8f92252ba268..bf47fb511ece 100644
--- a/contrib/libpcap/pcap-dos.h
+++ b/contrib/libpcap/pcap-dos.h
@@ -214,7 +214,7 @@ extern void _w32_os_yield (void); /* Watt-32's misc.c */
#define PCAP_ASSERT(x) ((void)0)
#else
- void pcap_assert (const char *what, const char *file, unsigned line);
+ void pcap_assert (const char *what, const char *file, unsigned line);
#define PCAP_ASSERT(x) do { \
if (!(x)) \
diff --git a/contrib/libpcap/pcap-filter.manmisc.in b/contrib/libpcap/pcap-filter.manmisc.in
index 9197d29b1605..a23bba1babe7 100644
--- a/contrib/libpcap/pcap-filter.manmisc.in
+++ b/contrib/libpcap/pcap-filter.manmisc.in
@@ -18,7 +18,7 @@
.\" WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
.\" MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
.\"
-.TH PCAP-FILTER @MAN_MISC_INFO@ "17 May 2013"
+.TH PCAP-FILTER @MAN_MISC_INFO@ "3 August 2015"
.SH NAME
pcap-filter \- packet filter syntax
.br
@@ -298,7 +298,7 @@ of protocol type \fIprotocol\fP.
\fBicmp\fP, \fBicmp6\fP, \fBigmp\fP, \fBigrp\fP, \fBpim\fP, \fBah\fP,
\fBesp\fP, \fBvrrp\fP, \fBudp\fP, or \fBtcp\fP.
Note that the identifiers \fBtcp\fP, \fBudp\fP, and \fBicmp\fP are also
-keywords and must be escaped via backslash (\\), which is \\\\ in the C-shell.
+keywords and must be escaped via backslash (\\).
Note that this primitive does not chase the protocol header chain.
.IP "\fBip6 proto \fIprotocol\fR"
True if the packet is an IPv6 packet of protocol type \fIprotocol\fP.
@@ -372,9 +372,9 @@ True if the packet is of ether type \fIprotocol\fR.
Note these identifiers are also keywords
and must be escaped via backslash (\\).
.IP
-[In the case of FDDI (e.g., `\fBfddi protocol arp\fR'), Token Ring
-(e.g., `\fBtr protocol arp\fR'), and IEEE 802.11 wireless LANS (e.g.,
-`\fBwlan protocol arp\fR'), for most of those protocols, the
+[In the case of FDDI (e.g., `\fBfddi proto arp\fR'), Token Ring
+(e.g., `\fBtr proto arp\fR'), and IEEE 802.11 wireless LANS (e.g.,
+`\fBwlan proto arp\fR'), for most of those protocols, the
protocol identification comes from the 802.2 Logical Link Control (LLC)
header, which is usually layered on top of the FDDI, Token Ring, or
802.11 header.
@@ -697,7 +697,7 @@ changes the decoding offsets for the remainder of \fIexpression\fR on
the assumption that the packet is a MPLS-encapsulated IP packet. The
\fBmpls \fI[label_num]\fR expression may be used more than once, to
filter on MPLS hierarchies. Each use of that expression increments the
-filter offsets by 4.
+filter offsets by 4.
.IP
For example:
.in +.5i
@@ -733,6 +733,22 @@ For example:
.fi
.in -.5i
filters IPv4 protocols encapsulated in PPPoE session id 0x27.
+.IP "\fBgeneve \fI[vni]\fR"
+True if the packet is a Geneve packet (UDP port 6081). If \fI[vni]\fR
+is specified, only true if the packet has the specified \fIvni\fR.
+Note that when the \fBgeneve\fR keyword is encountered in
+\fIexpression\fR, it changes the decoding offsets for the remainder of
+\fIexpression\fR on the assumption that the packet is a Geneve packet.
+.IP
+For example:
+.in +.5i
+.nf
+\fBgeneve 0xb && ip\fR
+.fi
+.in -.5i
+filters IPv4 protocols encapsulated in Geneve with VNI 0xb. This will
+match both IP directly encapsulated in Geneve as well as IP contained
+inside an Ethernet frame.
.IP "\fBiso proto \fIprotocol\fR"
True if the packet is an OSI packet of protocol type \fIprotocol\fP.
\fIProtocol\fP can be a number or one of the names
@@ -864,8 +880,7 @@ The following TCP flags field values are available: \fBtcp-fin\fP,
.LP
Primitives may be combined using:
.IP
-A parenthesized group of primitives and operators
-(parentheses are special to the Shell and must be escaped).
+A parenthesized group of primitives and operators.
.IP
Negation (`\fB!\fP' or `\fBnot\fP').
.IP
diff --git a/contrib/libpcap/pcap-int.h b/contrib/libpcap/pcap-int.h
index 5a20444617a9..7db7ff5e688d 100644
--- a/contrib/libpcap/pcap-int.h
+++ b/contrib/libpcap/pcap-int.h
@@ -40,14 +40,16 @@
extern "C" {
#endif
-#ifdef WIN32
-#include <Packet32.h>
-extern CRITICAL_SECTION g_PcapCompileCriticalSection;
-#endif /* WIN32 */
-
-#ifdef MSDOS
-#include <fcntl.h>
-#include <io.h>
+#if defined(_WIN32)
+ /*
+ * Make sure Packet32.h doesn't define BPF structures that we've
+ * probably already defined as a result of including <pcap/pcap.h>.
+ */
+ #define BPF_MAJOR_VERSION
+ #include <Packet32.h>
+#elif defined(MSDOS)
+ #include <fcntl.h>
+ #include <io.h>
#endif
#if (defined(_MSC_VER) && (_MSC_VER <= 1200)) /* we are compiling with Visual Studio 6, that doesn't support the LL suffix*/
@@ -106,9 +108,9 @@ extern CRITICAL_SECTION g_PcapCompileCriticalSection;
#define MAXIMUM_SNAPLEN 262144
struct pcap_opt {
- char *source;
+ char *device;
int timeout; /* timeout for buffering */
- int buffer_size;
+ u_int buffer_size;
int promisc;
int rfmon; /* monitor mode */
int immediate; /* immediate mode - deliver packets as soon as they arrive */
@@ -126,11 +128,19 @@ typedef int (*set_datalink_op_t)(pcap_t *, int);
typedef int (*getnonblock_op_t)(pcap_t *, char *);
typedef int (*setnonblock_op_t)(pcap_t *, int, char *);
typedef int (*stats_op_t)(pcap_t *, struct pcap_stat *);
-#ifdef WIN32
+#ifdef _WIN32
+typedef struct pcap_stat *(*stats_ex_op_t)(pcap_t *, int *);
typedef int (*setbuff_op_t)(pcap_t *, int);
typedef int (*setmode_op_t)(pcap_t *, int);
typedef int (*setmintocopy_op_t)(pcap_t *, int);
-typedef Adapter *(*getadapter_op_t)(pcap_t *);
+typedef HANDLE (*getevent_op_t)(pcap_t *);
+typedef int (*oid_get_request_op_t)(pcap_t *, bpf_u_int32, void *, size_t *);
+typedef int (*oid_set_request_op_t)(pcap_t *, bpf_u_int32, const void *, size_t *);
+typedef u_int (*sendqueue_transmit_op_t)(pcap_t *, pcap_send_queue *, int);
+typedef int (*setuserbuffer_op_t)(pcap_t *, int);
+typedef int (*live_dump_op_t)(pcap_t *, char *, int, int);
+typedef int (*live_dump_ended_op_t)(pcap_t *, int);
+typedef PAirpcapHandle (*get_airpcap_handle_op_t)(pcap_t *);
#endif
typedef void (*cleanup_op_t)(pcap_t *);
@@ -145,24 +155,22 @@ struct pcap {
read_op_t read_op;
/*
- * Method to call to read to read packets from a savefile.
+ * Method to call to read packets from a savefile.
*/
int (*next_packet_op)(pcap_t *, struct pcap_pkthdr *, u_char **);
-#ifdef WIN32
+#ifdef _WIN32
ADAPTER *adapter;
- LPPACKET Packet;
- int nonblock;
#else
int fd;
int selectable_fd;
-#endif /* WIN32 */
+#endif /* _WIN32 */
/*
* Read buffer.
*/
- int bufsize;
- u_char *buffer;
+ u_int bufsize;
+ void *buffer;
u_char *bp;
int cc;
@@ -172,7 +180,7 @@ struct pcap {
int swapped;
FILE *rfile; /* null if live capture, non-null if savefile */
- int fddipad;
+ u_int fddipad;
struct pcap *next; /* list of open pcaps that need stuff cleared on close */
/*
@@ -199,10 +207,19 @@ struct pcap {
*/
u_char *pkt;
+#ifdef _WIN32
+ struct pcap_stat stat; /* used for pcap_stats_ex() */
+#endif
+
/* We're accepting only packets in this direction/these directions. */
pcap_direction_t direction;
/*
+ * Flags to affect BPF code generation.
+ */
+ int bpf_codegen_flags;
+
+ /*
* Placeholder for filter code if bpf not in kernel.
*/
struct bpf_program fcode;
@@ -235,20 +252,33 @@ struct pcap {
*/
pcap_handler oneshot_callback;
-#ifdef WIN32
+#ifdef _WIN32
/*
* These are, at least currently, specific to the Win32 NPF
* driver.
*/
+ stats_ex_op_t stats_ex_op;
setbuff_op_t setbuff_op;
setmode_op_t setmode_op;
setmintocopy_op_t setmintocopy_op;
- getadapter_op_t getadapter_op;
+ getevent_op_t getevent_op;
+ oid_get_request_op_t oid_get_request_op;
+ oid_set_request_op_t oid_set_request_op;
+ sendqueue_transmit_op_t sendqueue_transmit_op;
+ setuserbuffer_op_t setuserbuffer_op;
+ live_dump_op_t live_dump_op;
+ live_dump_ended_op_t live_dump_ended_op;
+ get_airpcap_handle_op_t get_airpcap_handle_op;
#endif
cleanup_op_t cleanup_op;
};
/*
+ * BPF code generation flags.
+ */
+#define BPF_SPECIAL_VLAN_HANDLING 0x00000001 /* special VLAN handling for Linux */
+
+/*
* This is a timeval as stored in a savefile.
* It has to use the same types everywhere, independent of the actual
* `struct timeval'; `struct timeval' has 32-bit tv_sec values on some
@@ -328,34 +358,15 @@ struct oneshot_userdata {
pcap_t *pd;
};
-int yylex(void);
-
#ifndef min
#define min(a, b) ((a) > (b) ? (b) : (a))
#endif
-/* XXX should these be in pcap.h? */
int pcap_offline_read(pcap_t *, int, pcap_handler, u_char *);
-int pcap_read(pcap_t *, int cnt, pcap_handler, u_char *);
-
-#ifndef HAVE_STRLCPY
-#define strlcpy(x, y, z) \
- (strncpy((x), (y), (z)), \
- ((z) <= 0 ? 0 : ((x)[(z) - 1] = '\0')), \
- strlen((y)))
-#endif
#include <stdarg.h>
-#if !defined(HAVE_SNPRINTF)
-#define snprintf pcap_snprintf
-extern int snprintf (char *, size_t, const char *, ...);
-#endif
-
-#if !defined(HAVE_VSNPRINTF)
-#define vsnprintf pcap_vsnprintf
-extern int vsnprintf (char *, size_t, const char *, va_list ap);
-#endif
+#include "portability.h"
/*
* Does the packet count argument to a module's read routine say
@@ -366,7 +377,7 @@ extern int vsnprintf (char *, size_t, const char *, va_list ap);
/*
* Routines that most pcap implementations can use for non-blocking mode.
*/
-#if !defined(WIN32) && !defined(MSDOS)
+#if !defined(_WIN32) && !defined(MSDOS)
int pcap_getnonblock_fd(pcap_t *, char *);
int pcap_setnonblock_fd(pcap_t *p, int, char *);
#endif
@@ -383,38 +394,43 @@ int pcap_setnonblock_fd(pcap_t *p, int, char *);
* by pcap_create routines.
*/
pcap_t *pcap_create_interface(const char *, char *);
-pcap_t *pcap_create_common(const char *, char *, size_t);
+pcap_t *pcap_create_common(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 *);
void pcap_cleanup_live_common(pcap_t *);
-int pcap_not_initialized(pcap_t *);
int pcap_check_activated(pcap_t *);
/*
* Internal interfaces for "pcap_findalldevs()".
*
- * "pcap_findalldevs_interfaces()" finds interfaces using the
- * "standard" mechanisms (SIOCGIFCONF, "getifaddrs()", etc.).
- *
* "pcap_platform_finddevs()" is a platform-dependent routine to
- * add devices not found by the "standard" mechanisms.
+ * find local network interfaces.
+ *
+ * "pcap_findalldevs_interfaces()" is a helper to find those interfaces
+ * using the "standard" mechanisms (SIOCGIFCONF, "getifaddrs()", etc.).
*
* "pcap_add_if()" adds an interface to the list of interfaces, for
* use by various "find interfaces" routines.
*/
-int pcap_findalldevs_interfaces(pcap_if_t **, char *);
int pcap_platform_finddevs(pcap_if_t **, char *);
-int add_addr_to_iflist(pcap_if_t **, const char *, u_int, struct sockaddr *,
- size_t, struct sockaddr *, size_t, struct sockaddr *, size_t,
- struct sockaddr *, size_t, char *);
+#if !defined(_WIN32) && !defined(MSDOS)
+int pcap_findalldevs_interfaces(pcap_if_t **, char *,
+ int (*)(const char *));
+#endif
+int add_addr_to_iflist(pcap_if_t **, const char *, bpf_u_int32,
+ struct sockaddr *, size_t, struct sockaddr *, size_t,
+ struct sockaddr *, size_t, struct sockaddr *, size_t, char *);
int add_addr_to_dev(pcap_if_t *, struct sockaddr *, size_t,
struct sockaddr *, size_t, struct sockaddr *, size_t,
struct sockaddr *dstaddr, size_t, char *errbuf);
-int pcap_add_if(pcap_if_t **, const char *, u_int, const char *, char *);
-struct sockaddr *dup_sockaddr(struct sockaddr *, size_t);
-int add_or_find_if(pcap_if_t **, pcap_if_t **, const char *, u_int,
+int pcap_add_if(pcap_if_t **, const char *, bpf_u_int32, const char *,
+ char *);
+int add_or_find_if(pcap_if_t **, pcap_if_t **, const char *, bpf_u_int32,
const char *, char *);
+#ifndef _WIN32
+bpf_u_int32 if_flags_to_pcap_flags(const char *, u_int);
+#endif
/*
* Internal interfaces for "pcap_open_offline()".
@@ -438,8 +454,8 @@ void sf_cleanup(pcap_t *p);
*/
void pcap_oneshot(u_char *, const struct pcap_pkthdr *, const u_char *);
-#ifdef WIN32
-char *pcap_win32strerror(void);
+#ifdef _WIN32
+void pcap_win32_err_to_str(DWORD, char *);
#endif
int install_bpf_program(pcap_t *, struct bpf_program *);
diff --git a/contrib/libpcap/pcap-libdlpi.c b/contrib/libpcap/pcap-libdlpi.c
index 333e532b765a..625f1e0a31ed 100644
--- a/contrib/libpcap/pcap-libdlpi.c
+++ b/contrib/libpcap/pcap-libdlpi.c
@@ -106,7 +106,7 @@ pcap_activate_libdlpi(pcap_t *p)
* dlpi_open() will not fail if the underlying link does not support
* passive mode. See dlpi(7P) for details.
*/
- retv = dlpi_open(p->opt.source, &dh, DLPI_RAW|DLPI_PASSIVE);
+ retv = dlpi_open(p->opt.device, &dh, DLPI_RAW|DLPI_PASSIVE);
if (retv != DLPI_SUCCESS) {
if (retv == DLPI_ELINKNAMEINVAL || retv == DLPI_ENOLINK)
status = PCAP_ERROR_NO_SUCH_DEVICE;
@@ -115,7 +115,7 @@ pcap_activate_libdlpi(pcap_t *p)
status = PCAP_ERROR_PERM_DENIED;
else
status = PCAP_ERROR;
- pcap_libdlpi_err(p->opt.source, "dlpi_open", retv,
+ pcap_libdlpi_err(p->opt.device, "dlpi_open", retv,
p->errbuf);
return (status);
}
@@ -133,7 +133,7 @@ pcap_activate_libdlpi(pcap_t *p)
/* Bind with DLPI_ANY_SAP. */
if ((retv = dlpi_bind(pd->dlpi_hd, DLPI_ANY_SAP, 0)) != DLPI_SUCCESS) {
status = PCAP_ERROR;
- pcap_libdlpi_err(p->opt.source, "dlpi_bind", retv, p->errbuf);
+ pcap_libdlpi_err(p->opt.device, "dlpi_bind", retv, p->errbuf);
goto bad;
}
@@ -187,7 +187,7 @@ pcap_activate_libdlpi(pcap_t *p)
/* Determine link type. */
if ((retv = dlpi_info(pd->dlpi_hd, &dlinfo, 0)) != DLPI_SUCCESS) {
status = PCAP_ERROR;
- pcap_libdlpi_err(p->opt.source, "dlpi_info", retv, p->errbuf);
+ pcap_libdlpi_err(p->opt.device, "dlpi_info", retv, p->errbuf);
goto bad;
}
@@ -209,7 +209,7 @@ pcap_activate_libdlpi(pcap_t *p)
*/
if (ioctl(p->fd, I_FLUSH, FLUSHR) != 0) {
status = PCAP_ERROR;
- snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "FLUSHR: %s",
+ pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "FLUSHR: %s",
pcap_strerror(errno));
goto bad;
}
@@ -258,7 +258,7 @@ dlpromiscon(pcap_t *p, bpf_u_int32 level)
err = PCAP_ERROR_PERM_DENIED;
else
err = PCAP_ERROR;
- pcap_libdlpi_err(p->opt.source, "dlpi_promiscon" STRINGIFY(level),
+ pcap_libdlpi_err(p->opt.device, "dlpi_promiscon" STRINGIFY(level),
retv, p->errbuf);
return (err);
}
@@ -266,6 +266,17 @@ dlpromiscon(pcap_t *p, bpf_u_int32 level)
}
/*
+ * Presumably everything returned by dlpi_walk() is a DLPI device,
+ * so there's no work to be done here to check whether name refers
+ * to a DLPI device.
+ */
+static int
+is_dlpi_interface(const char *name _U_)
+{
+ return (1);
+}
+
+/*
* In Solaris, the "standard" mechanism" i.e SIOCGLIFCONF will only find
* network links that are plumbed and are up. dlpi_walk(3DLPI) will find
* additional network links present in the system.
@@ -279,12 +290,18 @@ pcap_platform_finddevs(pcap_if_t **alldevsp, char *errbuf)
linkwalk_t lw = {NULL, 0};
int save_errno;
+ /*
+ * Get the list of regular interfaces first.
+ */
+ if (pcap_findalldevs_interfaces(alldevsp, errbuf, is_dlpi_interface) == -1)
+ return (-1); /* failure */
+
/* dlpi_walk() for loopback will be added here. */
dlpi_walk(list_interfaces, &lw, 0);
if (lw.lw_err != 0) {
- snprintf(errbuf, PCAP_ERRBUF_SIZE,
+ pcap_snprintf(errbuf, PCAP_ERRBUF_SIZE,
"dlpi_walk: %s", pcap_strerror(lw.lw_err));
retv = -1;
goto done;
@@ -337,7 +354,7 @@ pcap_read_libdlpi(pcap_t *p, int count, pcap_handler callback, u_char *user)
}
msglen = p->bufsize;
- bufp = p->buffer + p->offset;
+ bufp = (u_char *)p->buffer + p->offset;
retv = dlpi_recv(pd->dlpi_hd, NULL, NULL, bufp,
&msglen, -1, NULL);
@@ -404,16 +421,16 @@ pcap_cleanup_libdlpi(pcap_t *p)
static void
pcap_libdlpi_err(const char *linkname, const char *func, int err, char *errbuf)
{
- snprintf(errbuf, PCAP_ERRBUF_SIZE, "libpcap: %s failed on %s: %s",
+ pcap_snprintf(errbuf, PCAP_ERRBUF_SIZE, "libpcap: %s failed on %s: %s",
func, linkname, dlpi_strerror(err));
}
pcap_t *
-pcap_create_interface(const char *device, char *ebuf)
+pcap_create_interface(const char *device _U_, char *ebuf)
{
pcap_t *p;
- p = pcap_create_common(device, ebuf, sizeof (struct pcap_dlpi));
+ p = pcap_create_common(ebuf, sizeof (struct pcap_dlpi));
if (p == NULL)
return (NULL);
diff --git a/contrib/libpcap/pcap-linktype.manmisc.in b/contrib/libpcap/pcap-linktype.manmisc.in
index e42c5b367f3b..7634a96290f7 100644
--- a/contrib/libpcap/pcap-linktype.manmisc.in
+++ b/contrib/libpcap/pcap-linktype.manmisc.in
@@ -18,7 +18,7 @@
.\" WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
.\" MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
.\"
-.TH PCAP-LINKTYPE @MAN_MISC_INFO@ "12 March 2011"
+.TH PCAP-LINKTYPE @MAN_MISC_INFO@ "7 April 2014"
.SH NAME
pcap-linktype \- link-layer header types supported by libpcap
.SH DESCRIPTION
diff --git a/contrib/libpcap/pcap-linux.c b/contrib/libpcap/pcap-linux.c
index 900ebbc0dd56..924df42af061 100644
--- a/contrib/libpcap/pcap-linux.c
+++ b/contrib/libpcap/pcap-linux.c
@@ -25,10 +25,10 @@
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
*
* Modifications: Added PACKET_MMAP support
- * Paolo Abeni <paolo.abeni@email.it>
+ * Paolo Abeni <paolo.abeni@email.it>
* Added TPACKET_V3 support
* Gabor Tatarka <gabor.tatarka@ericsson.com>
- *
+ *
* based on previous works of:
* Simon Patarin <patarin@cs.unibo.it>
* Phil Wood <cpw@lanl.gov>
@@ -47,7 +47,7 @@
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
+ * notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
@@ -56,12 +56,12 @@
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
- * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
@@ -188,9 +188,10 @@
# endif /* PACKET_HOST */
- /* check for memory mapped access avaibility. We assume every needed
+ /* 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 PCAP_SUPPORT_PACKET_RING
# ifdef TPACKET_HDRLEN
# define HAVE_PACKET_RING
# ifdef TPACKET3_HDRLEN
@@ -202,6 +203,7 @@
# 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 */
#endif /* PF_PACKET */
#ifdef SO_ATTACH_FILTER
@@ -213,6 +215,23 @@
#include <linux/net_tstamp.h>
#endif
+#ifdef HAVE_LINUX_SOCKIOS_H
+#include <linux/sockios.h>
+#endif
+
+#ifdef HAVE_LINUX_IF_BONDING_H
+#include <linux/if_bonding.h>
+
+/*
+ * The ioctl code to use to check whether a device is a bonding device.
+ */
+#if defined(SIOCBONDINFOQUERY)
+ #define BOND_INFO_QUERY_IOCTL SIOCBONDINFOQUERY
+#elif defined(BOND_INFO_QUERY_OLD)
+ #define BOND_INFO_QUERY_IOCTL BOND_INFO_QUERY_OLD
+#endif
+#endif /* HAVE_LINUX_IF_BONDING_H */
+
/*
* Got Wireless Extensions?
*/
@@ -300,6 +319,7 @@ struct pcap_linux {
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 */
+ int poll_timeout; /* timeout to use in poll() */
#ifdef HAVE_TPACKET3
unsigned char *current_packet; /* Current packet within the TPACKET_V3 block. Move to next block if NULL. */
int packets_left; /* Unhandled packets left within the block from previous call to pcap_read_linux_mmap_v3 in case of TPACKET_V3. */
@@ -316,7 +336,7 @@ struct pcap_linux {
/*
* Prototypes for internal functions and methods.
*/
-static void map_arphrd_to_dlt(pcap_t *, int, const char *, int);
+static void map_arphrd_to_dlt(pcap_t *, int, int, const char *, int);
#ifdef HAVE_PF_PACKET_SOCKETS
static short int map_packet_type_to_sll_type(short int);
#endif
@@ -334,8 +354,30 @@ static int pcap_setdirection_linux(pcap_t *, pcap_direction_t);
static int pcap_set_datalink_linux(pcap_t *, int);
static void pcap_cleanup_linux(pcap_t *);
+/*
+ * This is what the header structure looks like in a 64-bit kernel;
+ * we use this, rather than struct tpacket_hdr, if we're using
+ * TPACKET_V1 in 32-bit code running on a 64-bit kernel.
+ */
+struct tpacket_hdr_64 {
+ uint64_t tp_status;
+ unsigned int tp_len;
+ unsigned int tp_snaplen;
+ unsigned short tp_mac;
+ unsigned short tp_net;
+ unsigned int tp_sec;
+ unsigned int tp_usec;
+};
+
+/*
+ * We use this internally as the tpacket version for TPACKET_V1 in
+ * 32-bit code on a 64-bit kernel.
+ */
+#define TPACKET_V1_64 99
+
union thdr {
struct tpacket_hdr *h1;
+ struct tpacket_hdr_64 *h1_64;
#ifdef HAVE_TPACKET2
struct tpacket2_hdr *h2;
#endif
@@ -346,13 +388,15 @@ union thdr {
};
#ifdef HAVE_PACKET_RING
-#define RING_GET_FRAME(h) (((union thdr **)h->buffer)[h->offset])
+#define RING_GET_FRAME_AT(h, offset) (((union thdr **)h->buffer)[(offset)])
+#define RING_GET_CURRENT_FRAME(h) RING_GET_FRAME_AT(h, h->offset)
static void destroy_ring(pcap_t *handle);
static int create_ring(pcap_t *handle, int *status);
static int prepare_tpacket_socket(pcap_t *handle);
static void pcap_cleanup_linux_mmap(pcap_t *);
static int pcap_read_linux_mmap_v1(pcap_t *, int, pcap_handler , u_char *);
+static int pcap_read_linux_mmap_v1_64(pcap_t *, int, pcap_handler , u_char *);
#ifdef HAVE_TPACKET2
static int pcap_read_linux_mmap_v2(pcap_t *, int, pcap_handler , u_char *);
#endif
@@ -366,6 +410,12 @@ static void pcap_oneshot_mmap(u_char *user, const struct pcap_pkthdr *h,
const u_char *bytes);
#endif
+#ifdef TP_STATUS_VLAN_TPID_VALID
+# define VLAN_TPID(hdr, hv) (((hv)->tp_vlan_tpid || ((hdr)->tp_status & TP_STATUS_VLAN_TPID_VALID)) ? (hv)->tp_vlan_tpid : ETH_P_8021Q)
+#else
+# define VLAN_TPID(hdr, hv) ETH_P_8021Q
+#endif
+
/*
* Wrap some ioctl calls
*/
@@ -382,7 +432,13 @@ static int has_wext(int sock_fd, const char *device, char *ebuf);
static int enter_rfmon_mode(pcap_t *handle, int sock_fd,
const char *device);
#endif /* HAVE_PF_PACKET_SOCKETS */
+#if defined(HAVE_LINUX_NET_TSTAMP_H) && defined(PACKET_TIMESTAMP)
+static int iface_ethtool_get_ts_info(const char *device, pcap_t *handle,
+ char *ebuf);
+#endif
+#ifdef HAVE_PACKET_RING
static int iface_get_offload(pcap_t *handle);
+#endif
static int iface_bind_old(int fd, const char *device, char *ebuf);
#ifdef SO_ATTACH_FILTER
@@ -403,34 +459,21 @@ pcap_create_interface(const char *device, char *ebuf)
{
pcap_t *handle;
- handle = pcap_create_common(device, ebuf, sizeof (struct pcap_linux));
+ handle = pcap_create_common(ebuf, sizeof (struct pcap_linux));
if (handle == NULL)
return NULL;
handle->activate_op = pcap_activate_linux;
handle->can_set_rfmon_op = pcap_can_set_rfmon_linux;
+
#if defined(HAVE_LINUX_NET_TSTAMP_H) && defined(PACKET_TIMESTAMP)
/*
- * We claim that we support:
- *
- * software time stamps, with no details about their precision;
- * hardware time stamps, synced to the host time;
- * hardware time stamps, not synced to the host time.
- *
- * XXX - we can't ask a device whether it supports
- * hardware time stamps, so we just claim all devices do.
+ * See what time stamp types we support.
*/
- handle->tstamp_type_count = 3;
- handle->tstamp_type_list = malloc(3 * sizeof(u_int));
- if (handle->tstamp_type_list == NULL) {
- snprintf(ebuf, PCAP_ERRBUF_SIZE, "malloc: %s",
- pcap_strerror(errno));
- free(handle);
+ if (iface_ethtool_get_ts_info(device, handle, ebuf) == -1) {
+ pcap_close(handle);
return NULL;
}
- handle->tstamp_type_list[0] = PCAP_TSTAMP_HOST;
- handle->tstamp_type_list[1] = PCAP_TSTAMP_ADAPTER;
- handle->tstamp_type_list[2] = PCAP_TSTAMP_ADAPTER_UNSYNCED;
#endif
#if defined(SIOCGSTAMPNS) && defined(SO_TIMESTAMPNS)
@@ -445,11 +488,9 @@ pcap_create_interface(const char *device, char *ebuf)
handle->tstamp_precision_count = 2;
handle->tstamp_precision_list = malloc(2 * sizeof(u_int));
if (handle->tstamp_precision_list == NULL) {
- snprintf(ebuf, PCAP_ERRBUF_SIZE, "malloc: %s",
+ pcap_snprintf(ebuf, PCAP_ERRBUF_SIZE, "malloc: %s",
pcap_strerror(errno));
- if (handle->tstamp_type_list != NULL)
- free(handle->tstamp_type_list);
- free(handle);
+ pcap_close(handle);
return NULL;
}
handle->tstamp_precision_list[0] = PCAP_TSTAMP_PRECISION_MICRO;
@@ -501,7 +542,7 @@ pcap_create_interface(const char *device, char *ebuf)
*
* Yes, you can have multiple monitor devices for a given
* physical device.
-*/
+ */
/*
* Is this a mac80211 device? If so, fill in the physical device path and
@@ -519,7 +560,7 @@ get_mac80211_phydev(pcap_t *handle, const char *device, char *phydev_path,
* Generate the path string for the symlink to the physical device.
*/
if (asprintf(&pathstr, "/sys/class/net/%s/phy80211", device) == -1) {
- snprintf(handle->errbuf, PCAP_ERRBUF_SIZE,
+ pcap_snprintf(handle->errbuf, PCAP_ERRBUF_SIZE,
"%s: Can't generate path name string for /sys/class/net device",
device);
return PCAP_ERROR;
@@ -534,7 +575,7 @@ get_mac80211_phydev(pcap_t *handle, const char *device, char *phydev_path,
free(pathstr);
return 0;
}
- snprintf(handle->errbuf, PCAP_ERRBUF_SIZE,
+ pcap_snprintf(handle->errbuf, PCAP_ERRBUF_SIZE,
"%s: Can't readlink %s: %s", device, pathstr,
strerror(errno));
free(pathstr);
@@ -591,20 +632,20 @@ nl80211_init(pcap_t *handle, struct nl80211_state *state, const char *device)
state->nl_sock = nl_socket_alloc();
if (!state->nl_sock) {
- snprintf(handle->errbuf, PCAP_ERRBUF_SIZE,
+ pcap_snprintf(handle->errbuf, PCAP_ERRBUF_SIZE,
"%s: failed to allocate netlink handle", device);
return PCAP_ERROR;
}
if (genl_connect(state->nl_sock)) {
- snprintf(handle->errbuf, PCAP_ERRBUF_SIZE,
+ pcap_snprintf(handle->errbuf, PCAP_ERRBUF_SIZE,
"%s: failed to connect to generic netlink", device);
goto out_handle_destroy;
}
err = genl_ctrl_alloc_cache(state->nl_sock, &state->nl_cache);
if (err < 0) {
- snprintf(handle->errbuf, PCAP_ERRBUF_SIZE,
+ pcap_snprintf(handle->errbuf, PCAP_ERRBUF_SIZE,
"%s: failed to allocate generic netlink cache: %s",
device, get_nl_errmsg(-err));
goto out_handle_destroy;
@@ -612,7 +653,7 @@ nl80211_init(pcap_t *handle, struct nl80211_state *state, const char *device)
state->nl80211 = genl_ctrl_search_by_name(state->nl_cache, "nl80211");
if (!state->nl80211) {
- snprintf(handle->errbuf, PCAP_ERRBUF_SIZE,
+ pcap_snprintf(handle->errbuf, PCAP_ERRBUF_SIZE,
"%s: nl80211 not found", device);
goto out_cache_free;
}
@@ -635,9 +676,14 @@ nl80211_cleanup(struct nl80211_state *state)
}
static int
+del_mon_if(pcap_t *handle, int sock_fd, struct nl80211_state *state,
+ const char *device, const char *mondevice);
+
+static int
add_mon_if(pcap_t *handle, int sock_fd, struct nl80211_state *state,
const char *device, const char *mondevice)
{
+ struct pcap_linux *handlep = handle->priv;
int ifindex;
struct nl_msg *msg;
int err;
@@ -648,7 +694,7 @@ add_mon_if(pcap_t *handle, int sock_fd, struct nl80211_state *state,
msg = nlmsg_alloc();
if (!msg) {
- snprintf(handle->errbuf, PCAP_ERRBUF_SIZE,
+ pcap_snprintf(handle->errbuf, PCAP_ERRBUF_SIZE,
"%s: failed to allocate netlink msg", device);
return PCAP_ERROR;
}
@@ -680,7 +726,7 @@ add_mon_if(pcap_t *handle, int sock_fd, struct nl80211_state *state,
* Real failure, not just "that device is not
* available.
*/
- snprintf(handle->errbuf, PCAP_ERRBUF_SIZE,
+ pcap_snprintf(handle->errbuf, PCAP_ERRBUF_SIZE,
"%s: nl_send_auto_complete failed adding %s interface: %s",
device, mondevice, get_nl_errmsg(-err));
nlmsg_free(msg);
@@ -708,7 +754,7 @@ add_mon_if(pcap_t *handle, int sock_fd, struct nl80211_state *state,
* Real failure, not just "that device is not
* available.
*/
- snprintf(handle->errbuf, PCAP_ERRBUF_SIZE,
+ pcap_snprintf(handle->errbuf, PCAP_ERRBUF_SIZE,
"%s: nl_wait_for_ack failed adding %s interface: %s",
device, mondevice, get_nl_errmsg(-err));
nlmsg_free(msg);
@@ -720,10 +766,24 @@ add_mon_if(pcap_t *handle, int sock_fd, struct nl80211_state *state,
* Success.
*/
nlmsg_free(msg);
+
+ /*
+ * Try to remember the monitor device.
+ */
+ handlep->mondevice = strdup(mondevice);
+ if (handlep->mondevice == NULL) {
+ pcap_snprintf(handle->errbuf, PCAP_ERRBUF_SIZE, "strdup: %s",
+ pcap_strerror(errno));
+ /*
+ * Get rid of the monitor device.
+ */
+ del_mon_if(handle, sock_fd, state, device, mondevice);
+ return PCAP_ERROR;
+ }
return 1;
nla_put_failure:
- snprintf(handle->errbuf, PCAP_ERRBUF_SIZE,
+ pcap_snprintf(handle->errbuf, PCAP_ERRBUF_SIZE,
"%s: nl_put failed adding %s interface",
device, mondevice);
nlmsg_free(msg);
@@ -744,7 +804,7 @@ del_mon_if(pcap_t *handle, int sock_fd, struct nl80211_state *state,
msg = nlmsg_alloc();
if (!msg) {
- snprintf(handle->errbuf, PCAP_ERRBUF_SIZE,
+ pcap_snprintf(handle->errbuf, PCAP_ERRBUF_SIZE,
"%s: failed to allocate netlink msg", device);
return PCAP_ERROR;
}
@@ -755,7 +815,7 @@ del_mon_if(pcap_t *handle, int sock_fd, struct nl80211_state *state,
err = nl_send_auto_complete(state->nl_sock, msg);
if (err < 0) {
- snprintf(handle->errbuf, PCAP_ERRBUF_SIZE,
+ pcap_snprintf(handle->errbuf, PCAP_ERRBUF_SIZE,
"%s: nl_send_auto_complete failed deleting %s interface: %s",
device, mondevice, get_nl_errmsg(-err));
nlmsg_free(msg);
@@ -763,7 +823,7 @@ del_mon_if(pcap_t *handle, int sock_fd, struct nl80211_state *state,
}
err = nl_wait_for_ack(state->nl_sock);
if (err < 0) {
- snprintf(handle->errbuf, PCAP_ERRBUF_SIZE,
+ pcap_snprintf(handle->errbuf, PCAP_ERRBUF_SIZE,
"%s: nl_wait_for_ack failed adding %s interface: %s",
device, mondevice, get_nl_errmsg(-err));
nlmsg_free(msg);
@@ -777,7 +837,7 @@ del_mon_if(pcap_t *handle, int sock_fd, struct nl80211_state *state,
return 1;
nla_put_failure:
- snprintf(handle->errbuf, PCAP_ERRBUF_SIZE,
+ pcap_snprintf(handle->errbuf, PCAP_ERRBUF_SIZE,
"%s: nl_put failed deleting %s interface",
device, mondevice);
nlmsg_free(msg);
@@ -822,10 +882,13 @@ enter_rfmon_mode_mac80211(pcap_t *handle, int sock_fd, const char *device)
*/
char mondevice[3+10+1]; /* mon{UINT_MAX}\0 */
- snprintf(mondevice, sizeof mondevice, "mon%u", n);
+ pcap_snprintf(mondevice, sizeof mondevice, "mon%u", n);
ret = add_mon_if(handle, sock_fd, &nlstate, device, mondevice);
if (ret == 1) {
- handlep->mondevice = strdup(mondevice);
+ /*
+ * Success. We don't clean up the libnl state
+ * yet, as we'll be using it later.
+ */
goto added;
}
if (ret < 0) {
@@ -838,7 +901,7 @@ enter_rfmon_mode_mac80211(pcap_t *handle, int sock_fd, const char *device)
}
}
- snprintf(handle->errbuf, PCAP_ERRBUF_SIZE,
+ pcap_snprintf(handle->errbuf, PCAP_ERRBUF_SIZE,
"%s: No free monN interfaces", device);
nl80211_cleanup(&nlstate);
return PCAP_ERROR;
@@ -863,7 +926,10 @@ added:
* "atexit()" failed; don't put the interface
* in rfmon mode, just give up.
*/
- return PCAP_ERROR_RFMON_NOTSUP;
+ del_mon_if(handle, sock_fd, &nlstate, device,
+ handlep->mondevice);
+ nl80211_cleanup(&nlstate);
+ return PCAP_ERROR;
}
/*
@@ -872,7 +938,7 @@ added:
memset(&ifr, 0, sizeof(ifr));
strlcpy(ifr.ifr_name, handlep->mondevice, sizeof(ifr.ifr_name));
if (ioctl(sock_fd, SIOCGIFFLAGS, &ifr) == -1) {
- snprintf(handle->errbuf, PCAP_ERRBUF_SIZE,
+ pcap_snprintf(handle->errbuf, PCAP_ERRBUF_SIZE,
"%s: Can't get flags for %s: %s", device,
handlep->mondevice, strerror(errno));
del_mon_if(handle, sock_fd, &nlstate, device,
@@ -882,7 +948,7 @@ added:
}
ifr.ifr_flags |= IFF_UP|IFF_RUNNING;
if (ioctl(sock_fd, SIOCSIFFLAGS, &ifr) == -1) {
- snprintf(handle->errbuf, PCAP_ERRBUF_SIZE,
+ pcap_snprintf(handle->errbuf, PCAP_ERRBUF_SIZE,
"%s: Can't set flags for %s: %s", device,
handlep->mondevice, strerror(errno));
del_mon_if(handle, sock_fd, &nlstate, device,
@@ -911,6 +977,37 @@ added:
}
#endif /* HAVE_LIBNL */
+#ifdef IW_MODE_MONITOR
+/*
+ * Bonding devices mishandle unknown ioctls; they fail with ENODEV
+ * rather than ENOTSUP, EOPNOTSUPP, or ENOTTY, so Wireless Extensions
+ * will fail with ENODEV if we try to do them on a bonding device,
+ * making us return a "no such device" indication rather than just
+ * saying "no Wireless Extensions".
+ *
+ * So we check for bonding devices, if we can, before trying those
+ * ioctls, by trying a bonding device information query ioctl to see
+ * whether it succeeds.
+ */
+static int
+is_bonding_device(int fd, const char *device)
+{
+#ifdef BOND_INFO_QUERY_IOCTL
+ struct ifreq ifr;
+ ifbond ifb;
+
+ memset(&ifr, 0, sizeof ifr);
+ strlcpy(ifr.ifr_name, device, sizeof ifr.ifr_name);
+ memset(&ifb, 0, sizeof ifb);
+ ifr.ifr_data = (caddr_t)&ifb;
+ if (ioctl(fd, BOND_INFO_QUERY_IOCTL, &ifr) == 0)
+ return 1; /* success, so it's a bonding device */
+#endif /* BOND_INFO_QUERY_IOCTL */
+
+ return 0; /* no, it's not a bonding device */
+}
+#endif /* IW_MODE_MONITOR */
+
static int
pcap_can_set_rfmon_linux(pcap_t *handle)
{
@@ -923,7 +1020,7 @@ pcap_can_set_rfmon_linux(pcap_t *handle)
struct iwreq ireq;
#endif
- if (strcmp(handle->opt.source, "any") == 0) {
+ if (strcmp(handle->opt.device, "any") == 0) {
/*
* Monitor mode makes no sense on the "any" device.
*/
@@ -943,7 +1040,7 @@ pcap_can_set_rfmon_linux(pcap_t *handle)
* wmaster device, so we don't bother checking whether
* a mac80211 device supports the Wireless Extensions.
*/
- ret = get_mac80211_phydev(handle, handle->opt.source, phydev_path,
+ ret = get_mac80211_phydev(handle, handle->opt.device, phydev_path,
PATH_MAX);
if (ret < 0)
return ret; /* error */
@@ -964,15 +1061,21 @@ pcap_can_set_rfmon_linux(pcap_t *handle)
*/
sock_fd = socket(PF_PACKET, SOCK_RAW, htons(ETH_P_ALL));
if (sock_fd == -1) {
- (void)snprintf(handle->errbuf, PCAP_ERRBUF_SIZE,
+ (void)pcap_snprintf(handle->errbuf, PCAP_ERRBUF_SIZE,
"socket: %s", pcap_strerror(errno));
return PCAP_ERROR;
}
+ if (is_bonding_device(sock_fd, handle->opt.device)) {
+ /* It's a bonding device, so don't even try. */
+ close(sock_fd);
+ return 0;
+ }
+
/*
* Attempt to get the current mode.
*/
- strlcpy(ireq.ifr_ifrn.ifrn_name, handle->opt.source,
+ strlcpy(ireq.ifr_ifrn.ifrn_name, handle->opt.device,
sizeof ireq.ifr_ifrn.ifrn_name);
if (ioctl(sock_fd, SIOCGIWMODE, &ireq) != -1) {
/*
@@ -983,7 +1086,7 @@ pcap_can_set_rfmon_linux(pcap_t *handle)
}
if (errno == ENODEV) {
/* The device doesn't even exist. */
- (void)snprintf(handle->errbuf, PCAP_ERRBUF_SIZE,
+ (void)pcap_snprintf(handle->errbuf, PCAP_ERRBUF_SIZE,
"SIOCGIWMODE failed: %s", pcap_strerror(errno));
close(sock_fd);
return PCAP_ERROR_NO_SUCH_DEVICE;
@@ -1009,7 +1112,7 @@ linux_if_drops(const char * if_name)
FILE * file;
int field_to_convert = 3, if_name_sz = strlen(if_name);
long int dropped_pkts = 0;
-
+
file = fopen("/proc/net/dev", "r");
if (!file)
return 0;
@@ -1024,7 +1127,7 @@ linux_if_drops(const char * if_name)
field_to_convert = 4;
continue;
}
-
+
/* find iface and make sure it actually matches -- space before the name and : after it */
if ((bufptr = strstr(buffer, if_name)) &&
(bufptr == buffer || *(bufptr-1) == ' ') &&
@@ -1038,20 +1141,20 @@ linux_if_drops(const char * if_name)
while (*bufptr != '\0' && *(bufptr++) == ' ');
while (*bufptr != '\0' && *(bufptr++) != ' ');
}
-
+
/* get rid of any final spaces */
while (*bufptr != '\0' && *bufptr == ' ') bufptr++;
-
+
if (*bufptr != '\0')
dropped_pkts = strtol(bufptr, NULL, 10);
break;
}
}
-
+
fclose(file);
return dropped_pkts;
-}
+}
/*
@@ -1221,6 +1324,94 @@ static void pcap_cleanup_linux( pcap_t *handle )
}
/*
+ * Set the timeout to be used in poll() with memory-mapped packet capture.
+ */
+static void
+set_poll_timeout(struct pcap_linux *handlep)
+{
+#ifdef HAVE_TPACKET3
+ struct utsname utsname;
+ char *version_component, *endp;
+ int major, minor;
+ int broken_tpacket_v3 = 1;
+
+ /*
+ * Some versions of TPACKET_V3 have annoying bugs/misfeatures
+ * around which we have to work. Determine if we have those
+ * problems or not.
+ */
+ if (uname(&utsname) == 0) {
+ /*
+ * 3.19 is the first release with a fixed version of
+ * TPACKET_V3. We treat anything before that as
+ * not haveing a fixed version; that may really mean
+ * it has *no* version.
+ */
+ version_component = utsname.release;
+ major = strtol(version_component, &endp, 10);
+ if (endp != version_component && *endp == '.') {
+ /*
+ * OK, that was a valid major version.
+ * Get the minor version.
+ */
+ version_component = endp + 1;
+ minor = strtol(version_component, &endp, 10);
+ if (endp != version_component &&
+ (*endp == '.' || *endp == '\0')) {
+ /*
+ * OK, that was a valid minor version.
+ * Is this 3.19 or newer?
+ */
+ if (major >= 4 || (major == 3 && minor >= 19)) {
+ /* Yes. TPACKET_V3 works correctly. */
+ broken_tpacket_v3 = 0;
+ }
+ }
+ }
+ }
+#endif
+ if (handlep->timeout == 0) {
+#ifdef HAVE_TPACKET3
+ /*
+ * XXX - due to a set of (mis)features in the TPACKET_V3
+ * kernel code prior to the 3.19 kernel, blocking forever
+ * with a TPACKET_V3 socket can, if few packets are
+ * arriving and passing the socket filter, cause most
+ * packets to be dropped. See libpcap issue #335 for the
+ * full painful story.
+ *
+ * The workaround is to have poll() time out very quickly,
+ * so we grab the frames handed to us, and return them to
+ * the kernel, ASAP.
+ */
+ if (handlep->tp_version == TPACKET_V3 && broken_tpacket_v3)
+ handlep->poll_timeout = 1; /* don't block for very long */
+ else
+#endif
+ handlep->poll_timeout = -1; /* block forever */
+ } else if (handlep->timeout > 0) {
+#ifdef HAVE_TPACKET3
+ /*
+ * For TPACKET_V3, the timeout is handled by the kernel,
+ * so block forever; that way, we don't get extra timeouts.
+ * Don't do that if we have a broken TPACKET_V3, though.
+ */
+ if (handlep->tp_version == TPACKET_V3 && !broken_tpacket_v3)
+ handlep->poll_timeout = -1; /* block forever, let TPACKET_V3 wake us up */
+ else
+#endif
+ handlep->poll_timeout = handlep->timeout; /* block for that amount of time */
+ } else {
+ /*
+ * Non-blocking mode; we call poll() to pick up error
+ * indications, but we don't want it to wait for
+ * anything.
+ */
+ handlep->poll_timeout = 0;
+ }
+}
+
+/*
* Get a handle for a live capture from the given device. You can
* pass NULL as device to get all packages (without link level
* information of course). If you pass 1 as promisc the interface
@@ -1237,7 +1428,7 @@ pcap_activate_linux(pcap_t *handle)
int status = 0;
int ret;
- device = handle->opt.source;
+ device = handle->opt.device;
/*
* Make sure the name we were handed will fit into the ioctls we
@@ -1274,7 +1465,7 @@ pcap_activate_linux(pcap_t *handle)
if (handle->opt.promisc) {
handle->opt.promisc = 0;
/* Just a warning. */
- snprintf(handle->errbuf, PCAP_ERRBUF_SIZE,
+ pcap_snprintf(handle->errbuf, PCAP_ERRBUF_SIZE,
"Promiscuous mode not supported on the \"any\" device");
status = PCAP_WARNING_PROMISC_NOTSUP;
}
@@ -1282,16 +1473,16 @@ pcap_activate_linux(pcap_t *handle)
handlep->device = strdup(device);
if (handlep->device == NULL) {
- snprintf(handle->errbuf, PCAP_ERRBUF_SIZE, "strdup: %s",
+ pcap_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
+ * 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
*/
@@ -1330,7 +1521,11 @@ pcap_activate_linux(pcap_t *handle)
* set to the status to return,
* which might be 0, or might be
* a PCAP_WARNING_ value.
+ *
+ * Set the timeout to use in poll() before
+ * returning.
*/
+ set_poll_timeout(handlep);
return status;
case 0:
@@ -1375,7 +1570,7 @@ pcap_activate_linux(pcap_t *handle)
if (setsockopt(handle->fd, SOL_SOCKET, SO_RCVBUF,
&handle->opt.buffer_size,
sizeof(handle->opt.buffer_size)) == -1) {
- snprintf(handle->errbuf, PCAP_ERRBUF_SIZE,
+ pcap_snprintf(handle->errbuf, PCAP_ERRBUF_SIZE,
"SO_RCVBUF: %s", pcap_strerror(errno));
status = PCAP_ERROR;
goto fail;
@@ -1386,7 +1581,7 @@ pcap_activate_linux(pcap_t *handle)
handle->buffer = malloc(handle->bufsize + handle->offset);
if (!handle->buffer) {
- snprintf(handle->errbuf, PCAP_ERRBUF_SIZE,
+ pcap_snprintf(handle->errbuf, PCAP_ERRBUF_SIZE,
"malloc: %s", pcap_strerror(errno));
status = PCAP_ERROR;
goto fail;
@@ -1448,6 +1643,22 @@ linux_check_direction(const pcap_t *handle, const struct sockaddr_ll *sll)
return 0;
/*
+ * If this is an outgoing CAN or CAN FD frame, and
+ * the user doesn't only want outgoing packets,
+ * reject it; CAN devices and drivers, and the CAN
+ * stack, always arrange to loop back transmitted
+ * packets, so they also appear as incoming packets.
+ * We don't want duplicate packets, and we can't
+ * easily distinguish packets looped back by the CAN
+ * layer than those received by the CAN layer, so we
+ * eliminate this packet instead.
+ */
+ if ((sll->sll_protocol == LINUX_SLL_P_CAN ||
+ sll->sll_protocol == LINUX_SLL_P_CANFD) &&
+ handle->direction != PCAP_D_OUT)
+ return 0;
+
+ /*
* If the user only wants incoming packets, reject it.
*/
if (handle->direction == PCAP_D_IN)
@@ -1494,6 +1705,7 @@ pcap_read_packet(pcap_t *handle, pcap_handler callback, u_char *userdata)
int packet_len, caplen;
struct pcap_pkthdr pcap_header;
+ struct bpf_aux_data aux_data;
#ifdef HAVE_PF_PACKET_SOCKETS
/*
* If this is a cooked device, leave extra room for a
@@ -1526,7 +1738,7 @@ pcap_read_packet(pcap_t *handle, pcap_handler callback, u_char *userdata)
* if we're using a memory-mapped buffer, we won't even
* get notified of "network down" events.
*/
- bp = handle->buffer + handle->offset;
+ bp = (u_char *)handle->buffer + handle->offset;
#if defined(HAVE_PACKET_AUXDATA) && defined(HAVE_LINUX_TPACKET_AUXDATA_TP_VLAN_TCI)
msg.msg_name = &from;
@@ -1582,12 +1794,12 @@ pcap_read_packet(pcap_t *handle, pcap_handler callback, u_char *userdata)
* PCAP_ERROR_IFACE_NOT_UP, but pcap_dispatch()
* etc. aren't defined to return that.
*/
- snprintf(handle->errbuf, PCAP_ERRBUF_SIZE,
+ pcap_snprintf(handle->errbuf, PCAP_ERRBUF_SIZE,
"The interface went down");
return PCAP_ERROR;
default:
- snprintf(handle->errbuf, PCAP_ERRBUF_SIZE,
+ pcap_snprintf(handle->errbuf, PCAP_ERRBUF_SIZE,
"recvfrom: %s", pcap_strerror(errno));
return PCAP_ERROR;
}
@@ -1666,17 +1878,35 @@ pcap_read_packet(pcap_t *handle, pcap_handler callback, u_char *userdata)
#endif
continue;
- len = packet_len > iov.iov_len ? iov.iov_len : packet_len;
- if (len < (unsigned int) handlep->vlan_offset)
+ len = (u_int)packet_len > iov.iov_len ? iov.iov_len : (u_int)packet_len;
+ if (len < (u_int)handlep->vlan_offset)
break;
+ /*
+ * Move everything in the header, except the
+ * type field, down VLAN_TAG_LEN bytes, to
+ * allow us to insert the VLAN tag between
+ * that stuff and the type field.
+ */
bp -= VLAN_TAG_LEN;
memmove(bp, bp + VLAN_TAG_LEN, handlep->vlan_offset);
+ /*
+ * Now insert the tag.
+ */
tag = (struct vlan_tag *)(bp + handlep->vlan_offset);
- tag->vlan_tpid = htons(ETH_P_8021Q);
+ tag->vlan_tpid = htons(VLAN_TPID(aux, aux));
tag->vlan_tci = htons(aux->tp_vlan_tci);
+ /* store vlan tci to bpf_aux_data struct for userland bpf filter */
+#if defined(TP_STATUS_VLAN_VALID)
+ aux_data.vlan_tag = htons(aux->tp_vlan_tci) & 0x0fff;
+ aux_data.vlan_tag_present = (aux->tp_status & TP_STATUS_VLAN_VALID);
+#endif
+
+ /*
+ * Add the tag to the packet lengths.
+ */
packet_len += VLAN_TAG_LEN;
}
}
@@ -1721,9 +1951,8 @@ pcap_read_packet(pcap_t *handle, pcap_handler callback, u_char *userdata)
/* Run the packet filter if not using kernel filter */
if (handlep->filter_in_userland && handle->fcode.bf_insns) {
- if (bpf_filter(handle->fcode.bf_insns, bp,
- packet_len, caplen) == 0)
- {
+ if (bpf_filter_with_aux_data(handle->fcode.bf_insns, bp,
+ packet_len, caplen, &aux_data) == 0) {
/* rejected by filter */
return 0;
}
@@ -1735,7 +1964,7 @@ pcap_read_packet(pcap_t *handle, pcap_handler callback, u_char *userdata)
#if defined(SIOCGSTAMPNS) && defined(SO_TIMESTAMPNS)
if (handle->opt.tstamp_precision == PCAP_TSTAMP_PRECISION_NANO) {
if (ioctl(handle->fd, SIOCGSTAMPNS, &pcap_header.ts) == -1) {
- snprintf(handle->errbuf, PCAP_ERRBUF_SIZE,
+ pcap_snprintf(handle->errbuf, PCAP_ERRBUF_SIZE,
"SIOCGSTAMPNS: %s", pcap_strerror(errno));
return PCAP_ERROR;
}
@@ -1743,7 +1972,7 @@ pcap_read_packet(pcap_t *handle, pcap_handler callback, u_char *userdata)
#endif
{
if (ioctl(handle->fd, SIOCGSTAMP, &pcap_header.ts) == -1) {
- snprintf(handle->errbuf, PCAP_ERRBUF_SIZE,
+ pcap_snprintf(handle->errbuf, PCAP_ERRBUF_SIZE,
"SIOCGSTAMP: %s", pcap_strerror(errno));
return PCAP_ERROR;
}
@@ -1841,12 +2070,12 @@ pcap_inject_linux(pcap_t *handle, const void *buf, size_t size)
ret = send(handle->fd, buf, size, 0);
if (ret == -1) {
- snprintf(handle->errbuf, PCAP_ERRBUF_SIZE, "send: %s",
+ pcap_snprintf(handle->errbuf, PCAP_ERRBUF_SIZE, "send: %s",
pcap_strerror(errno));
return (-1);
}
return (ret);
-}
+}
/*
* Get the statistics for the given packet capture handle.
@@ -1884,8 +2113,8 @@ pcap_stats_linux(pcap_t *handle, struct pcap_stat *stats)
#endif /* HAVE_TPACKET_STATS */
long if_dropped = 0;
-
- /*
+
+ /*
* To fill in ps_ifdrop, we parse /proc/net/dev for the number
*/
if (handle->opt.promisc)
@@ -1915,7 +2144,7 @@ pcap_stats_linux(pcap_t *handle, struct pcap_stat *stats)
* dropped by the interface driver. It counts only
* packets that passed the filter.
*
- * See above for ps_ifdrop.
+ * See above for ps_ifdrop.
*
* Both statistics include packets not yet read from
* the kernel by libpcap, and thus not yet seen by
@@ -1944,7 +2173,7 @@ pcap_stats_linux(pcap_t *handle, struct pcap_stat *stats)
* "tp_packets" as the count of packets and "tp_drops"
* as the count of drops.
*
- * Keep a running total because each call to
+ * Keep a running total because each call to
* getsockopt(handle->fd, SOL_PACKET, PACKET_STATISTICS, ....
* resets the counters to zero.
*/
@@ -1963,7 +2192,7 @@ pcap_stats_linux(pcap_t *handle, struct pcap_stat *stats)
* is built on a system without "struct tpacket_stats".
*/
if (errno != EOPNOTSUPP) {
- snprintf(handle->errbuf, PCAP_ERRBUF_SIZE,
+ pcap_snprintf(handle->errbuf, PCAP_ERRBUF_SIZE,
"pcap_stats: %s", pcap_strerror(errno));
return -1;
}
@@ -1990,10 +2219,10 @@ pcap_stats_linux(pcap_t *handle, struct pcap_stat *stats)
* We maintain the count of packets processed by libpcap in
* "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
+ * packets were dropped by the kernel buffers -- but we know
* how many the interface dropped, so we can return that.
*/
-
+
stats->ps_recv = handlep->packets_read;
stats->ps_drop = 0;
stats->ps_ifdrop = handlep->stat.ps_ifdrop;
@@ -2049,7 +2278,7 @@ add_linux_if(pcap_if_t **devlistp, const char *ifname, int fd, char *errbuf)
if (ioctl(fd, SIOCGIFFLAGS, (char *)&ifrflags) < 0) {
if (errno == ENXIO || errno == ENODEV)
return (0); /* device doesn't actually exist - ignore it */
- (void)snprintf(errbuf, PCAP_ERRBUF_SIZE,
+ (void)pcap_snprintf(errbuf, PCAP_ERRBUF_SIZE,
"SIOCGIFFLAGS: %.*s: %s",
(int)sizeof(ifrflags.ifr_name),
ifrflags.ifr_name,
@@ -2060,7 +2289,8 @@ add_linux_if(pcap_if_t **devlistp, const char *ifname, int fd, char *errbuf)
/*
* Add an entry for this interface, with no addresses.
*/
- if (pcap_add_if(devlistp, name, ifrflags.ifr_flags, NULL,
+ if (pcap_add_if(devlistp, name,
+ if_flags_to_pcap_flags(name, ifrflags.ifr_flags), NULL,
errbuf) == -1) {
/*
* Failure.
@@ -2108,7 +2338,7 @@ scan_sys_class_net(pcap_if_t **devlistp, char *errbuf)
/*
* Fail if we got some other error.
*/
- (void)snprintf(errbuf, PCAP_ERRBUF_SIZE,
+ (void)pcap_snprintf(errbuf, PCAP_ERRBUF_SIZE,
"Can't open /sys/class/net: %s", pcap_strerror(errno));
return (-1);
}
@@ -2116,9 +2346,9 @@ scan_sys_class_net(pcap_if_t **devlistp, char *errbuf)
/*
* Create a socket from which to fetch interface information.
*/
- fd = socket(AF_INET, SOCK_DGRAM, 0);
+ fd = socket(PF_UNIX, SOCK_RAW, 0);
if (fd < 0) {
- (void)snprintf(errbuf, PCAP_ERRBUF_SIZE,
+ (void)pcap_snprintf(errbuf, PCAP_ERRBUF_SIZE,
"socket: %s", pcap_strerror(errno));
(void)closedir(sys_class_net_d);
return (-1);
@@ -2155,7 +2385,7 @@ scan_sys_class_net(pcap_if_t **devlistp, char *errbuf)
* for devices, newer kernels have symlinks to
* directories.)
*/
- snprintf(subsystem_path, sizeof subsystem_path,
+ pcap_snprintf(subsystem_path, sizeof subsystem_path,
"/sys/class/net/%s/ifindex", ent->d_name);
if (lstat(subsystem_path, &statb) != 0) {
/*
@@ -2186,7 +2416,7 @@ scan_sys_class_net(pcap_if_t **devlistp, char *errbuf)
* fail due to an error reading the directory?
*/
if (errno != 0) {
- (void)snprintf(errbuf, PCAP_ERRBUF_SIZE,
+ (void)pcap_snprintf(errbuf, PCAP_ERRBUF_SIZE,
"Error reading /sys/class/net: %s",
pcap_strerror(errno));
ret = -1;
@@ -2226,7 +2456,7 @@ scan_proc_net_dev(pcap_if_t **devlistp, char *errbuf)
/*
* Fail if we got some other error.
*/
- (void)snprintf(errbuf, PCAP_ERRBUF_SIZE,
+ (void)pcap_snprintf(errbuf, PCAP_ERRBUF_SIZE,
"Can't open /proc/net/dev: %s", pcap_strerror(errno));
return (-1);
}
@@ -2234,9 +2464,9 @@ scan_proc_net_dev(pcap_if_t **devlistp, char *errbuf)
/*
* Create a socket from which to fetch interface information.
*/
- fd = socket(AF_INET, SOCK_DGRAM, 0);
+ fd = socket(PF_UNIX, SOCK_RAW, 0);
if (fd < 0) {
- (void)snprintf(errbuf, PCAP_ERRBUF_SIZE,
+ (void)pcap_snprintf(errbuf, PCAP_ERRBUF_SIZE,
"socket: %s", pcap_strerror(errno));
(void)fclose(proc_net_f);
return (-1);
@@ -2275,7 +2505,7 @@ scan_proc_net_dev(pcap_if_t **devlistp, char *errbuf)
* fail due to an error reading the file?
*/
if (ferror(proc_net_f)) {
- (void)snprintf(errbuf, PCAP_ERRBUF_SIZE,
+ (void)pcap_snprintf(errbuf, PCAP_ERRBUF_SIZE,
"Error reading /proc/net/dev: %s",
pcap_strerror(errno));
ret = -1;
@@ -2292,12 +2522,27 @@ scan_proc_net_dev(pcap_if_t **devlistp, char *errbuf)
*/
static const char any_descr[] = "Pseudo-device that captures on all interfaces";
+/*
+ * A SOCK_PACKET or PF_PACKET socket can be bound to any network interface.
+ */
+static int
+can_be_bound(const char *name _U_)
+{
+ return (1);
+}
+
int
pcap_platform_finddevs(pcap_if_t **alldevsp, char *errbuf)
{
int ret;
/*
+ * Get the list of regular interfaces first.
+ */
+ if (pcap_findalldevs_interfaces(alldevsp, errbuf, can_be_bound) == -1)
+ return (-1); /* failure */
+
+ /*
* Read "/sys/class/net", and add to the list of interfaces all
* interfaces listed there that we don't already have, because,
* on Linux, SIOCGIFCONF reports only interfaces with IPv4 addresses,
@@ -2319,7 +2564,7 @@ pcap_platform_finddevs(pcap_if_t **alldevsp, char *errbuf)
/*
* Add the "any" device.
*/
- if (pcap_add_if(alldevsp, "any", IFF_UP|IFF_RUNNING,
+ if (pcap_add_if(alldevsp, "any", PCAP_IF_UP|PCAP_IF_RUNNING,
any_descr, errbuf) < 0)
return (-1);
@@ -2478,8 +2723,14 @@ pcap_setfilter_linux_common(pcap_t *handle, struct bpf_program *filter,
* calling "pcap_setfilter()". Otherwise, the kernel filter may
* filter out packets that would pass the new userland filter.
*/
- if (handlep->filter_in_userland)
- reset_kernel_filter(handle);
+ if (handlep->filter_in_userland) {
+ if (reset_kernel_filter(handle) == -1) {
+ pcap_snprintf(handle->errbuf, PCAP_ERRBUF_SIZE,
+ "can't remove kernel filter: %s",
+ pcap_strerror(errno));
+ err = -2; /* fatal error */
+ }
+ }
/*
* Free up the copy of the filter that was made by "fix_program()".
@@ -2521,7 +2772,7 @@ pcap_setdirection_linux(pcap_t *handle, pcap_direction_t d)
* We're not using PF_PACKET sockets, so we can't determine
* the direction of the packet.
*/
- snprintf(handle->errbuf, PCAP_ERRBUF_SIZE,
+ pcap_snprintf(handle->errbuf, PCAP_ERRBUF_SIZE,
"Setting direction is not supported on SOCK_PACKET sockets");
return -1;
}
@@ -2561,6 +2812,51 @@ map_packet_type_to_sll_type(short int sll_pkttype)
}
#endif
+static int
+is_wifi(int sock_fd
+#ifndef IW_MODE_MONITOR
+_U_
+#endif
+, const char *device)
+{
+ char *pathstr;
+ struct stat statb;
+#ifdef IW_MODE_MONITOR
+ char errbuf[PCAP_ERRBUF_SIZE];
+#endif
+
+ /*
+ * See if there's a sysfs wireless directory for it.
+ * If so, it's a wireless interface.
+ */
+ if (asprintf(&pathstr, "/sys/class/net/%s/wireless", device) == -1) {
+ /*
+ * Just give up here.
+ */
+ return 0;
+ }
+ if (stat(pathstr, &statb) == 0) {
+ free(pathstr);
+ return 1;
+ }
+ free(pathstr);
+
+#ifdef IW_MODE_MONITOR
+ /*
+ * OK, maybe it's not wireless, or maybe this kernel doesn't
+ * support sysfs. Try the wireless extensions.
+ */
+ if (has_wext(sock_fd, device, errbuf) == 1) {
+ /*
+ * It supports the wireless extensions, so it's a Wi-Fi
+ * device.
+ */
+ return 1;
+ }
+#endif
+ return 0;
+}
+
/*
* Linux uses the ARP hardware type to identify the type of an
* interface. pcap uses the DLT_xxx constants for this. This
@@ -2579,8 +2875,8 @@ map_packet_type_to_sll_type(short int sll_pkttype)
*
* Sets the link type to -1 if unable to map the type.
*/
-static void map_arphrd_to_dlt(pcap_t *handle, int arptype, const char *device,
- int cooked_ok)
+static void map_arphrd_to_dlt(pcap_t *handle, int sock_fd, int arptype,
+ const char *device, int cooked_ok)
{
static const char cdma_rmnet[] = "cdma_rmnet";
@@ -2591,7 +2887,7 @@ static void map_arphrd_to_dlt(pcap_t *handle, int arptype, const char *device,
* For various annoying reasons having to do with DHCP
* software, some versions of Android give the mobile-
* phone-network interface an ARPHRD_ value of
- * ARPHRD_ETHER, even though the packet supplied by
+ * ARPHRD_ETHER, even though the packets supplied by
* that interface have no link-layer header, and begin
* with an IP header, so that the ARPHRD_ value should
* be ARPHRD_NONE.
@@ -2603,9 +2899,9 @@ static void map_arphrd_to_dlt(pcap_t *handle, int arptype, const char *device,
handle->linktype = DLT_RAW;
return;
}
-
+
/*
- * This is (presumably) a real Ethernet capture; give it a
+ * Is this a real Ethernet device? If so, give it a
* link-layer-type list with DLT_EN10MB and DLT_DOCSIS, so
* that an application can let you choose it, in case you're
* capturing DOCSIS traffic that a Cisco Cable Modem
@@ -2614,21 +2910,27 @@ static void map_arphrd_to_dlt(pcap_t *handle, int arptype, const char *device,
* DOCSIS frames out on the wire inside the low-level
* Ethernet framing).
*
- * XXX - are there any sorts of "fake Ethernet" that have
- * ARPHRD_ETHER but that *shouldn't offer DLT_DOCSIS as
+ * XXX - are there any other sorts of "fake Ethernet" that
+ * have ARPHRD_ETHER but that shouldn't offer DLT_DOCSIS as
* a Cisco CMTS won't put traffic onto it or get traffic
* bridged onto it? ISDN is handled in "activate_new()",
- * as we fall back on cooked mode there; are there any
+ * as we fall back on cooked mode there, and we use
+ * is_wifi() to check for 802.11 devices; are there any
* others?
*/
- handle->dlt_list = (u_int *) malloc(sizeof(u_int) * 2);
- /*
- * If that fails, just leave the list empty.
- */
- if (handle->dlt_list != NULL) {
- handle->dlt_list[0] = DLT_EN10MB;
- handle->dlt_list[1] = DLT_DOCSIS;
- handle->dlt_count = 2;
+ if (!is_wifi(sock_fd, device)) {
+ /*
+ * It's not a Wi-Fi device; offer DOCSIS.
+ */
+ handle->dlt_list = (u_int *) malloc(sizeof(u_int) * 2);
+ /*
+ * If that fails, just leave the list empty.
+ */
+ if (handle->dlt_list != NULL) {
+ handle->dlt_list[0] = DLT_EN10MB;
+ handle->dlt_list[1] = DLT_DOCSIS;
+ handle->dlt_count = 2;
+ }
}
/* FALLTHROUGH */
@@ -2657,7 +2959,14 @@ static void map_arphrd_to_dlt(pcap_t *handle, int arptype, const char *device,
#define ARPHRD_CAN 280
#endif
case ARPHRD_CAN:
- handle->linktype = DLT_CAN_SOCKETCAN;
+ /*
+ * Map this to DLT_LINUX_SLL; that way, CAN frames will
+ * have ETH_P_CAN/LINUX_SLL_P_CAN as the protocol and
+ * CAN FD frames will have ETH_P_CANFD/LINUX_SLL_P_CANFD
+ * as the protocol, so they can be distinguished by the
+ * protocol in the SLL header.
+ */
+ handle->linktype = DLT_LINUX_SLL;
break;
#ifndef ARPHRD_IEEE802_TR
@@ -2940,7 +3249,7 @@ static void map_arphrd_to_dlt(pcap_t *handle, int arptype, const char *device,
* so let's use "Linux-cooked" mode. Jean II
*
* XXX - this is handled in activate_new(). */
- //handlep->cooked = 1;
+ /* handlep->cooked = 1; */
break;
/* ARPHRD_LAPD is unofficial and randomly allocated, if reallocation
@@ -2983,7 +3292,7 @@ static void map_arphrd_to_dlt(pcap_t *handle, int arptype, const char *device,
*
* XXX - this is handled in activate_new().
*/
- //handlep->cooked = 1;
+ /* handlep->cooked = 1; */
break;
default:
@@ -3006,7 +3315,7 @@ activate_new(pcap_t *handle)
{
#ifdef HAVE_PF_PACKET_SOCKETS
struct pcap_linux *handlep = handle->priv;
- const char *device = handle->opt.source;
+ const char *device = handle->opt.device;
int is_any_device = (strcmp(device, "any") == 0);
int sock_fd = -1, arptype;
#ifdef HAVE_PACKET_AUXDATA
@@ -3014,6 +3323,10 @@ activate_new(pcap_t *handle)
#endif
int err = 0;
struct packet_mreq mr;
+#if defined(SO_BPF_EXTENSIONS) && defined(SKF_AD_VLAN_TAG_PRESENT)
+ int bpf_extensions;
+ socklen_t len = sizeof(bpf_extensions);
+#endif
/*
* Open a socket with protocol family packet. If the
@@ -3034,7 +3347,7 @@ activate_new(pcap_t *handle)
return 0;
}
- snprintf(handle->errbuf, PCAP_ERRBUF_SIZE, "socket: %s",
+ pcap_snprintf(handle->errbuf, PCAP_ERRBUF_SIZE, "socket: %s",
pcap_strerror(errno) );
if (errno == EPERM || errno == EACCES) {
/*
@@ -3117,7 +3430,7 @@ activate_new(pcap_t *handle)
close(sock_fd);
return arptype;
}
- map_arphrd_to_dlt(handle, arptype, device, 1);
+ map_arphrd_to_dlt(handle, sock_fd, arptype, device, 1);
if (handle->linktype == -1 ||
handle->linktype == DLT_LINUX_SLL ||
handle->linktype == DLT_LINUX_IRDA ||
@@ -3136,14 +3449,14 @@ activate_new(pcap_t *handle)
* kernels) - reopen in cooked mode.
*/
if (close(sock_fd) == -1) {
- snprintf(handle->errbuf, PCAP_ERRBUF_SIZE,
+ pcap_snprintf(handle->errbuf, PCAP_ERRBUF_SIZE,
"close: %s", pcap_strerror(errno));
return PCAP_ERROR;
}
sock_fd = socket(PF_PACKET, SOCK_DGRAM,
htons(ETH_P_ALL));
if (sock_fd == -1) {
- snprintf(handle->errbuf, PCAP_ERRBUF_SIZE,
+ pcap_snprintf(handle->errbuf, PCAP_ERRBUF_SIZE,
"socket: %s", pcap_strerror(errno));
if (errno == EPERM || errno == EACCES) {
/*
@@ -3178,7 +3491,7 @@ activate_new(pcap_t *handle)
* update "map_arphrd_to_dlt()"
* to handle the new type.
*/
- snprintf(handle->errbuf, PCAP_ERRBUF_SIZE,
+ pcap_snprintf(handle->errbuf, PCAP_ERRBUF_SIZE,
"arptype %d not "
"supported by libpcap - "
"falling back to cooked "
@@ -3268,7 +3581,7 @@ activate_new(pcap_t *handle)
mr.mr_type = PACKET_MR_PROMISC;
if (setsockopt(sock_fd, SOL_PACKET, PACKET_ADD_MEMBERSHIP,
&mr, sizeof(mr)) == -1) {
- snprintf(handle->errbuf, PCAP_ERRBUF_SIZE,
+ pcap_snprintf(handle->errbuf, PCAP_ERRBUF_SIZE,
"setsockopt: %s", pcap_strerror(errno));
close(sock_fd);
return PCAP_ERROR;
@@ -3281,7 +3594,7 @@ activate_new(pcap_t *handle)
val = 1;
if (setsockopt(sock_fd, SOL_PACKET, PACKET_AUXDATA, &val,
sizeof(val)) == -1 && errno != ENOPROTOOPT) {
- snprintf(handle->errbuf, PCAP_ERRBUF_SIZE,
+ pcap_snprintf(handle->errbuf, PCAP_ERRBUF_SIZE,
"setsockopt: %s", pcap_strerror(errno));
close(sock_fd);
return PCAP_ERROR;
@@ -3311,15 +3624,24 @@ activate_new(pcap_t *handle)
/*
* Set the offset at which to insert VLAN tags.
+ * That should be the offset of the type field.
*/
switch (handle->linktype) {
case DLT_EN10MB:
+ /*
+ * The type field is after the destination and source
+ * MAC address.
+ */
handlep->vlan_offset = 2 * ETH_ALEN;
break;
case DLT_LINUX_SLL:
- handlep->vlan_offset = 14;
+ /*
+ * The type field is in the last 2 bytes of the
+ * DLT_LINUX_SLL header.
+ */
+ handlep->vlan_offset = SLL_HDR_LEN - 2;
break;
default:
@@ -3332,7 +3654,7 @@ activate_new(pcap_t *handle)
int nsec_tstamps = 1;
if (setsockopt(sock_fd, SOL_SOCKET, SO_TIMESTAMPNS, &nsec_tstamps, sizeof(nsec_tstamps)) < 0) {
- snprintf(handle->errbuf, PCAP_ERRBUF_SIZE, "setsockopt: unable to set SO_TIMESTAMPNS");
+ pcap_snprintf(handle->errbuf, PCAP_ERRBUF_SIZE, "setsockopt: unable to set SO_TIMESTAMPNS");
close(sock_fd);
return PCAP_ERROR;
}
@@ -3344,6 +3666,23 @@ activate_new(pcap_t *handle)
*/
handle->fd = sock_fd;
+#if defined(SO_BPF_EXTENSIONS) && defined(SKF_AD_VLAN_TAG_PRESENT)
+ /*
+ * Can we generate special code for VLAN checks?
+ * (XXX - what if we need the special code but it's not supported
+ * by the OS? Is that possible?)
+ */
+ if (getsockopt(sock_fd, SOL_SOCKET, SO_BPF_EXTENSIONS,
+ &bpf_extensions, &len) == 0) {
+ if (bpf_extensions >= SKF_AD_VLAN_TAG_PRESENT) {
+ /*
+ * Yes, we can. Request that we do so.
+ */
+ handle->bpf_codegen_flags |= BPF_SPECIAL_VLAN_HANDLING;
+ }
+ }
+#endif /* defined(SO_BPF_EXTENSIONS) && defined(SKF_AD_VLAN_TAG_PRESENT) */
+
return 1;
#else /* HAVE_PF_PACKET_SOCKETS */
strlcpy(ebuf,
@@ -3366,7 +3705,7 @@ activate_new(pcap_t *handle)
* On error, returns -1, and sets *status to the appropriate error code;
* if that is PCAP_ERROR, sets handle->errbuf to the appropriate message.
*/
-static int
+static int
activate_mmap(pcap_t *handle, int *status)
{
struct pcap_linux *handlep = handle->priv;
@@ -3378,7 +3717,7 @@ activate_mmap(pcap_t *handle, int *status)
*/
handlep->oneshot_buffer = malloc(handle->snapshot);
if (handlep->oneshot_buffer == NULL) {
- snprintf(handle->errbuf, PCAP_ERRBUF_SIZE,
+ pcap_snprintf(handle->errbuf, PCAP_ERRBUF_SIZE,
"can't allocate oneshot buffer: %s",
pcap_strerror(errno));
*status = PCAP_ERROR;
@@ -3427,6 +3766,9 @@ activate_mmap(pcap_t *handle, int *status)
case TPACKET_V1:
handle->read_op = pcap_read_linux_mmap_v1;
break;
+ case TPACKET_V1_64:
+ handle->read_op = pcap_read_linux_mmap_v1_64;
+ break;
#ifdef HAVE_TPACKET2
case TPACKET_V2:
handle->read_op = pcap_read_linux_mmap_v2;
@@ -3447,7 +3789,7 @@ activate_mmap(pcap_t *handle, int *status)
return 1;
}
#else /* HAVE_PACKET_RING */
-static int
+static int
activate_mmap(pcap_t *handle _U_, int *status _U_)
{
return 0;
@@ -3471,13 +3813,16 @@ init_tpacket(pcap_t *handle, int version, const char *version_str)
int val = version;
socklen_t len = sizeof(val);
- /* Probe whether kernel supports the specified TPACKET version */
+ /*
+ * Probe whether kernel supports the specified TPACKET version;
+ * this also gets the length of the header for that version.
+ */
if (getsockopt(handle->fd, SOL_PACKET, PACKET_HDRLEN, &val, &len) < 0) {
if (errno == ENOPROTOOPT || errno == EINVAL)
return 1; /* no */
/* Failed to even find out; this is a fatal error. */
- snprintf(handle->errbuf, PCAP_ERRBUF_SIZE,
+ pcap_snprintf(handle->errbuf, PCAP_ERRBUF_SIZE,
"can't get %s header len on packet socket: %s",
version_str,
pcap_strerror(errno));
@@ -3488,7 +3833,7 @@ init_tpacket(pcap_t *handle, int version, const char *version_str)
val = version;
if (setsockopt(handle->fd, SOL_PACKET, PACKET_VERSION, &val,
sizeof(val)) < 0) {
- snprintf(handle->errbuf, PCAP_ERRBUF_SIZE,
+ pcap_snprintf(handle->errbuf, PCAP_ERRBUF_SIZE,
"can't activate %s on packet socket: %s",
version_str,
pcap_strerror(errno));
@@ -3500,7 +3845,7 @@ init_tpacket(pcap_t *handle, int version, const char *version_str)
val = VLAN_TAG_LEN;
if (setsockopt(handle->fd, SOL_PACKET, PACKET_RESERVE, &val,
sizeof(val)) < 0) {
- snprintf(handle->errbuf, PCAP_ERRBUF_SIZE,
+ pcap_snprintf(handle->errbuf, PCAP_ERRBUF_SIZE,
"can't set up reserve on packet socket: %s",
pcap_strerror(errno));
return -1;
@@ -3511,6 +3856,36 @@ init_tpacket(pcap_t *handle, int version, const char *version_str)
#endif /* defined HAVE_TPACKET2 || defined HAVE_TPACKET3 */
/*
+ * If the instruction set for which we're compiling has both 32-bit
+ * and 64-bit versions, and Linux support for the 64-bit version
+ * predates TPACKET_V2, define ISA_64_BIT as the .machine value
+ * you get from uname() for the 64-bit version. Otherwise, leave
+ * it undefined. (This includes ARM, which has a 64-bit version,
+ * but Linux support for it appeared well after TPACKET_V2 support
+ * did, so there should never be a case where 32-bit ARM code is
+ * running o a 64-bit kernel that only supports TPACKET_V1.)
+ *
+ * If we've omitted your favorite such architecture, please contribute
+ * a patch. (No patch is needed for architectures that are 32-bit-only
+ * or for which Linux has no support for 32-bit userland - or for which,
+ * as noted, 64-bit support appeared in Linux after TPACKET_V2 support
+ * did.)
+ */
+#if defined(__i386__)
+#define ISA_64_BIT "x86_64"
+#elif defined(__ppc__)
+#define ISA_64_BIT "ppc64"
+#elif defined(__sparc__)
+#define ISA_64_BIT "sparc64"
+#elif defined(__s390__)
+#define ISA_64_BIT "s390x"
+#elif defined(__mips__)
+#define ISA_64_BIT "mips64"
+#elif defined(__hppa__)
+#define ISA_64_BIT "parisc64"
+#endif
+
+/*
* Attempt to set the socket to version 3 of the memory-mapped header and,
* if that fails because version 3 isn't supported, attempt to fall
* back to version 2. If version 2 isn't supported, just leave it at
@@ -3527,11 +3902,10 @@ prepare_tpacket_socket(pcap_t *handle)
int ret;
#endif
- handlep->tp_version = TPACKET_V1;
- handlep->tp_hdrlen = sizeof(struct tpacket_hdr);
-
#ifdef HAVE_TPACKET3
/*
+ * Try setting the version to TPACKET_V3.
+ *
* The only mode in which buffering is done on PF_PACKET
* sockets, so that packets might not be delivered
* immediately, is TPACKET_V3 mode.
@@ -3540,28 +3914,87 @@ prepare_tpacket_socket(pcap_t *handle)
* if the user has requested immediate mode, we don't
* use TPACKET_V3.
*/
- if (handle->opt.immediate)
- ret = 1; /* pretend TPACKET_V3 couldn't be set */
- else
+ if (!handle->opt.immediate) {
ret = init_tpacket(handle, TPACKET_V3, "TPACKET_V3");
- if (-1 == ret) {
- /* Error during setting up TPACKET_V3. */
- return -1;
- } else if (1 == ret) {
- /* TPACKET_V3 not supported - fall back to TPACKET_V2. */
+ if (ret == 0) {
+ /*
+ * Success.
+ */
+ return 1;
+ }
+ if (ret == -1) {
+ /*
+ * We failed for some reason other than "the
+ * kernel doesn't support TPACKET_V3".
+ */
+ return -1;
+ }
+ }
#endif /* HAVE_TPACKET3 */
#ifdef HAVE_TPACKET2
- ret = init_tpacket(handle, TPACKET_V2, "TPACKET_V2");
- if (-1 == ret) {
- /* Error during setting up TPACKET_V2. */
- return -1;
- }
+ /*
+ * Try setting the version to TPACKET_V2.
+ */
+ ret = init_tpacket(handle, TPACKET_V2, "TPACKET_V2");
+ if (ret == 0) {
+ /*
+ * Success.
+ */
+ return 1;
+ }
+ if (ret == -1) {
+ /*
+ * We failed for some reason other than "the
+ * kernel doesn't support TPACKET_V2".
+ */
+ return -1;
+ }
#endif /* HAVE_TPACKET2 */
-#ifdef HAVE_TPACKET3
+ /*
+ * OK, we're using TPACKET_V1, as that's all the kernel supports.
+ */
+ handlep->tp_version = TPACKET_V1;
+ handlep->tp_hdrlen = sizeof(struct tpacket_hdr);
+
+#ifdef ISA_64_BIT
+ /*
+ * 32-bit userspace + 64-bit kernel + TPACKET_V1 are not compatible with
+ * each other due to platform-dependent data type size differences.
+ *
+ * If we have a 32-bit userland and a 64-bit kernel, use an
+ * internally-defined TPACKET_V1_64, with which we use a 64-bit
+ * version of the data structures.
+ */
+ if (sizeof(long) == 4) {
+ /*
+ * This is 32-bit code.
+ */
+ struct utsname utsname;
+
+ if (uname(&utsname) == -1) {
+ /*
+ * Failed.
+ */
+ pcap_snprintf(handle->errbuf, PCAP_ERRBUF_SIZE,
+ "uname failed: %s", pcap_strerror(errno));
+ return -1;
+ }
+ if (strcmp(utsname.machine, ISA_64_BIT) == 0) {
+ /*
+ * uname() tells us the machine is 64-bit,
+ * so we presumably have a 64-bit kernel.
+ *
+ * XXX - this presumes that uname() won't lie
+ * in 32-bit code and claim that the machine
+ * has the 32-bit version of the ISA.
+ */
+ handlep->tp_version = TPACKET_V1_64;
+ handlep->tp_hdrlen = sizeof(struct tpacket_hdr_64);
+ }
}
-#endif /* HAVE_TPACKET3 */
+#endif
return 1;
}
@@ -3605,6 +4038,7 @@ create_ring(pcap_t *handle, int *status)
switch (handlep->tp_version) {
case TPACKET_V1:
+ case TPACKET_V1_64:
#ifdef HAVE_TPACKET2
case TPACKET_V2:
#endif
@@ -3649,14 +4083,14 @@ create_ring(pcap_t *handle, int *status)
return -1;
}
if (!offload) {
- mtu = iface_get_mtu(handle->fd, handle->opt.source,
+ mtu = iface_get_mtu(handle->fd, handle->opt.device,
handle->errbuf);
if (mtu == -1) {
*status = PCAP_ERROR;
return -1;
}
- if (frame_size > mtu + 18)
- frame_size = mtu + 18;
+ if (frame_size > (unsigned int)mtu + 18)
+ frame_size = (unsigned int)mtu + 18;
}
}
@@ -3666,7 +4100,7 @@ create_ring(pcap_t *handle, int *status)
len = sizeof(sk_type);
if (getsockopt(handle->fd, SOL_SOCKET, SO_TYPE, &sk_type,
&len) < 0) {
- snprintf(handle->errbuf, PCAP_ERRBUF_SIZE,
+ pcap_snprintf(handle->errbuf, PCAP_ERRBUF_SIZE,
"getsockopt: %s", pcap_strerror(errno));
*status = PCAP_ERROR;
return -1;
@@ -3681,7 +4115,7 @@ create_ring(pcap_t *handle, int *status)
* PACKET_RESERVE", in which case we fall back
* as best we can.
*/
- snprintf(handle->errbuf, PCAP_ERRBUF_SIZE,
+ pcap_snprintf(handle->errbuf, PCAP_ERRBUF_SIZE,
"getsockopt: %s", pcap_strerror(errno));
*status = PCAP_ERROR;
return -1;
@@ -3736,14 +4170,20 @@ create_ring(pcap_t *handle, int *status)
req.tp_frame_nr = handle->opt.buffer_size/req.tp_frame_size;
break;
#endif
+ default:
+ pcap_snprintf(handle->errbuf, PCAP_ERRBUF_SIZE,
+ "Internal error: unknown TPACKET_ value %u",
+ handlep->tp_version);
+ *status = PCAP_ERROR;
+ return -1;
}
- /* compute the minumum block size that will handle this frame.
- * The block has to be page size aligned.
- * The max block size allowed by the kernel is arch-dependent and
+ /* compute the minumum block size that will handle this frame.
+ * The block has to be page size aligned.
+ * The max block size allowed by the kernel is arch-dependent and
* it's not explicitly checked here. */
req.tp_block_size = getpagesize();
- while (req.tp_block_size < req.tp_frame_size)
+ while (req.tp_block_size < req.tp_frame_size)
req.tp_block_size <<= 1;
frames_per_block = req.tp_block_size/req.tp_frame_size;
@@ -3784,7 +4224,7 @@ create_ring(pcap_t *handle, int *status)
hwconfig.rx_filter = HWTSTAMP_FILTER_ALL;
memset(&ifr, 0, sizeof(ifr));
- strlcpy(ifr.ifr_name, handle->opt.source, sizeof(ifr.ifr_name));
+ strlcpy(ifr.ifr_name, handle->opt.device, sizeof(ifr.ifr_name));
ifr.ifr_data = (void *)&hwconfig;
if (ioctl(handle->fd, SIOCSHWTSTAMP, &ifr) < 0) {
@@ -3802,18 +4242,26 @@ create_ring(pcap_t *handle, int *status)
return -1;
case EOPNOTSUPP:
+ case ERANGE:
/*
* Treat this as a warning, as the
* only way to fix the warning is to
* get an adapter that supports hardware
- * time stamps. We'll just fall back
- * on the standard host time stamps.
+ * time stamps for *all* packets.
+ * (ERANGE means "we support hardware
+ * time stamps, but for packets matching
+ * that particular filter", so it means
+ * "we don't support hardware time stamps
+ * for all incoming packets" here.)
+ *
+ * We'll just fall back on the standard
+ * host time stamps.
*/
*status = PCAP_WARNING_TSTAMP_TYPE_NOTSUP;
break;
default:
- snprintf(handle->errbuf, PCAP_ERRBUF_SIZE,
+ pcap_snprintf(handle->errbuf, PCAP_ERRBUF_SIZE,
"SIOCSHWTSTAMP failed: %s",
pcap_strerror(errno));
*status = PCAP_ERROR;
@@ -3841,8 +4289,8 @@ create_ring(pcap_t *handle, int *status)
}
if (setsockopt(handle->fd, SOL_PACKET, PACKET_TIMESTAMP,
(void *)&timesource, sizeof(timesource))) {
- snprintf(handle->errbuf, PCAP_ERRBUF_SIZE,
- "can't set PACKET_TIMESTAMP: %s",
+ pcap_snprintf(handle->errbuf, PCAP_ERRBUF_SIZE,
+ "can't set PACKET_TIMESTAMP: %s",
pcap_strerror(errno));
*status = PCAP_ERROR;
return -1;
@@ -3857,7 +4305,7 @@ retry:
/* req.tp_frame_nr is requested to match frames_per_block*req.tp_block_nr */
req.tp_frame_nr = req.tp_block_nr * frames_per_block;
-
+
#ifdef HAVE_TPACKET3
/* timeout value to retire block - use the configured buffering timeout, or default if <0. */
req.tp_retire_blk_tov = (handlep->timeout>=0)?handlep->timeout:0;
@@ -3891,7 +4339,7 @@ retry:
*/
return 0;
}
- snprintf(handle->errbuf, PCAP_ERRBUF_SIZE,
+ pcap_snprintf(handle->errbuf, PCAP_ERRBUF_SIZE,
"can't create rx ring on packet socket: %s",
pcap_strerror(errno));
*status = PCAP_ERROR;
@@ -3903,7 +4351,7 @@ retry:
handlep->mmapbuf = mmap(0, handlep->mmapbuflen,
PROT_READ|PROT_WRITE, MAP_SHARED, handle->fd, 0);
if (handlep->mmapbuf == MAP_FAILED) {
- snprintf(handle->errbuf, PCAP_ERRBUF_SIZE,
+ pcap_snprintf(handle->errbuf, PCAP_ERRBUF_SIZE,
"can't mmap rx ring: %s", pcap_strerror(errno));
/* clear the allocated ring on error*/
@@ -3916,7 +4364,7 @@ retry:
handle->cc = req.tp_frame_nr;
handle->buffer = malloc(handle->cc * sizeof(union thdr *));
if (!handle->buffer) {
- snprintf(handle->errbuf, PCAP_ERRBUF_SIZE,
+ pcap_snprintf(handle->errbuf, PCAP_ERRBUF_SIZE,
"can't allocate ring of frame headers: %s",
pcap_strerror(errno));
@@ -3930,7 +4378,7 @@ retry:
for (i=0; i<req.tp_block_nr; ++i) {
void *base = &handlep->mmapbuf[i*req.tp_block_size];
for (j=0; j<frames_per_block; ++j, ++handle->offset) {
- RING_GET_FRAME(handle) = base;
+ RING_GET_CURRENT_FRAME(handle) = base;
base += req.tp_frame_size;
}
}
@@ -3949,13 +4397,14 @@ destroy_ring(pcap_t *handle)
/* tell the kernel to destroy the ring*/
struct tpacket_req req;
memset(&req, 0, sizeof(req));
- setsockopt(handle->fd, SOL_PACKET, PACKET_RX_RING,
+ /* do not test for setsockopt failure, as we can't recover from any error */
+ (void)setsockopt(handle->fd, SOL_PACKET, PACKET_RX_RING,
(void *) &req, sizeof(req));
/* if ring is mapped, unmap it*/
if (handlep->mmapbuf) {
/* do not test for mmap failure, as we can't recover from any error */
- munmap(handlep->mmapbuf, handlep->mmapbuflen);
+ (void)munmap(handlep->mmapbuf, handlep->mmapbuflen);
handlep->mmapbuf = NULL;
}
}
@@ -3989,7 +4438,7 @@ pcap_oneshot_mmap(u_char *user, const struct pcap_pkthdr *h,
memcpy(handlep->oneshot_buffer, bytes, h->caplen);
*sp->pkt = handlep->oneshot_buffer;
}
-
+
static void
pcap_cleanup_linux_mmap( pcap_t *handle )
{
@@ -4042,151 +4491,131 @@ pcap_setnonblock_mmap(pcap_t *p, int nonblock, char *errbuf)
handlep->timeout = ~handlep->timeout;
}
}
+ /* Update the timeout to use in poll(). */
+ set_poll_timeout(handlep);
return 0;
}
-static inline union thdr *
-pcap_get_ring_frame(pcap_t *handle, int status)
+/*
+ * Get the status field of the ring buffer frame at a specified offset.
+ */
+static inline int
+pcap_get_ring_frame_status(pcap_t *handle, int offset)
{
struct pcap_linux *handlep = handle->priv;
union thdr h;
- h.raw = RING_GET_FRAME(handle);
+ h.raw = RING_GET_FRAME_AT(handle, offset);
switch (handlep->tp_version) {
case TPACKET_V1:
- if (status != (h.h1->tp_status ? TP_STATUS_USER :
- TP_STATUS_KERNEL))
- return NULL;
+ return (h.h1->tp_status);
+ break;
+ case TPACKET_V1_64:
+ return (h.h1_64->tp_status);
break;
#ifdef HAVE_TPACKET2
case TPACKET_V2:
- if (status != (h.h2->tp_status ? TP_STATUS_USER :
- TP_STATUS_KERNEL))
- return NULL;
+ return (h.h2->tp_status);
break;
#endif
#ifdef HAVE_TPACKET3
case TPACKET_V3:
- if (status != (h.h3->hdr.bh1.block_status ? TP_STATUS_USER :
- TP_STATUS_KERNEL))
- return NULL;
+ return (h.h3->hdr.bh1.block_status);
break;
#endif
}
- return h.raw;
+ /* This should not happen. */
+ return 0;
}
#ifndef POLLRDHUP
#define POLLRDHUP 0
#endif
-/* wait for frames availability.*/
+/*
+ * Block waiting for frames to be available.
+ */
static int pcap_wait_for_frames_mmap(pcap_t *handle)
{
- if (!pcap_get_ring_frame(handle, TP_STATUS_USER)) {
- struct pcap_linux *handlep = handle->priv;
- int timeout;
- char c;
- struct pollfd pollinfo;
- int ret;
+ struct pcap_linux *handlep = handle->priv;
+ char c;
+ struct pollfd pollinfo;
+ int ret;
- pollinfo.fd = handle->fd;
- pollinfo.events = POLLIN;
+ pollinfo.fd = handle->fd;
+ pollinfo.events = POLLIN;
- if (handlep->timeout == 0) {
-#ifdef HAVE_TPACKET3
+ do {
+ /*
+ * Yes, we do this even in non-blocking mode, as it's
+ * the only way to get error indications from a
+ * tpacket socket.
+ *
+ * The timeout is 0 in non-blocking mode, so poll()
+ * returns immediately.
+ */
+ ret = poll(&pollinfo, 1, handlep->poll_timeout);
+ if (ret < 0 && errno != EINTR) {
+ pcap_snprintf(handle->errbuf, PCAP_ERRBUF_SIZE,
+ "can't poll on packet socket: %s",
+ pcap_strerror(errno));
+ return PCAP_ERROR;
+ } else if (ret > 0 &&
+ (pollinfo.revents & (POLLHUP|POLLRDHUP|POLLERR|POLLNVAL))) {
/*
- * XXX - due to a set of (mis)features in the
- * TPACKET_V3 kernel code, blocking forever with
- * a TPACKET_V3 socket can, if few packets
- * are arriving and passing the socket filter,
- * cause most packets to be dropped. See
- * libpcap issue #335 for the full painful
- * story. The workaround is to have poll()
- * time out very quickly, so we grab the
- * frames handed to us, and return them to
- * the kernel, ASAP.
- *
- * If those issues are ever fixed, we might
- * want to check the kernel version and block
- * forever with TPACKET_V3 if we're running
- * with a kernel that has the fix.
+ * There's some indication other than
+ * "you can read on this descriptor" on
+ * the descriptor.
*/
- if (handlep->tp_version == TPACKET_V3)
- timeout = 1; /* don't block for very long */
- else
-#endif
- timeout = -1; /* block forever */
- } 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 {
- ret = poll(&pollinfo, 1, timeout);
- if (ret < 0 && errno != EINTR) {
- snprintf(handle->errbuf, PCAP_ERRBUF_SIZE,
- "can't poll on packet socket: %s",
- pcap_strerror(errno));
+ if (pollinfo.revents & (POLLHUP | POLLRDHUP)) {
+ pcap_snprintf(handle->errbuf,
+ PCAP_ERRBUF_SIZE,
+ "Hangup on packet socket");
return PCAP_ERROR;
- } else if (ret > 0 &&
- (pollinfo.revents & (POLLHUP|POLLRDHUP|POLLERR|POLLNVAL))) {
+ }
+ if (pollinfo.revents & POLLERR) {
/*
- * There's some indication other than
- * "you can read on this descriptor" on
- * the descriptor.
+ * A recv() will give us the actual error code.
+ *
+ * XXX - make the socket non-blocking?
*/
- if (pollinfo.revents & (POLLHUP | POLLRDHUP)) {
- snprintf(handle->errbuf,
- PCAP_ERRBUF_SIZE,
- "Hangup on packet socket");
- return PCAP_ERROR;
- }
- if (pollinfo.revents & POLLERR) {
+ if (recv(handle->fd, &c, sizeof c,
+ MSG_PEEK) != -1)
+ continue; /* what, no error? */
+ if (errno == ENETDOWN) {
/*
- * A recv() will give us the
- * actual error code.
+ * The device on which we're
+ * capturing went away.
*
- * XXX - make the socket non-blocking?
+ * XXX - we should really return
+ * PCAP_ERROR_IFACE_NOT_UP, but
+ * pcap_dispatch() etc. aren't
+ * defined to return that.
*/
- if (recv(handle->fd, &c, sizeof c,
- MSG_PEEK) != -1)
- continue; /* what, no error? */
- if (errno == ENETDOWN) {
- /*
- * The device on which we're
- * capturing went away.
- *
- * XXX - we should really return
- * PCAP_ERROR_IFACE_NOT_UP,
- * but pcap_dispatch() etc.
- * aren't defined to return
- * that.
- */
- snprintf(handle->errbuf,
- PCAP_ERRBUF_SIZE,
- "The interface went down");
- } else {
- snprintf(handle->errbuf,
- PCAP_ERRBUF_SIZE,
- "Error condition on packet socket: %s",
- strerror(errno));
- }
- return PCAP_ERROR;
- }
- if (pollinfo.revents & POLLNVAL) {
- snprintf(handle->errbuf,
+ pcap_snprintf(handle->errbuf,
PCAP_ERRBUF_SIZE,
- "Invalid polling request on packet socket");
- return PCAP_ERROR;
+ "The interface went down");
+ } else {
+ pcap_snprintf(handle->errbuf,
+ PCAP_ERRBUF_SIZE,
+ "Error condition on packet socket: %s",
+ strerror(errno));
}
+ return PCAP_ERROR;
}
- /* check for break loop condition on interrupted syscall*/
- if (handle->break_loop) {
- handle->break_loop = 0;
- return PCAP_ERROR_BREAK;
+ if (pollinfo.revents & POLLNVAL) {
+ pcap_snprintf(handle->errbuf,
+ PCAP_ERRBUF_SIZE,
+ "Invalid polling request on packet socket");
+ return PCAP_ERROR;
}
- } while (ret < 0);
- }
+ }
+ /* check for break loop condition on interrupted syscall*/
+ if (handle->break_loop) {
+ handle->break_loop = 0;
+ return PCAP_ERROR_BREAK;
+ }
+ } while (ret < 0);
return 0;
}
@@ -4202,7 +4631,8 @@ static int pcap_handle_packet_mmap(
unsigned int tp_sec,
unsigned int tp_usec,
int tp_vlan_tci_valid,
- __u16 tp_vlan_tci)
+ __u16 tp_vlan_tci,
+ __u16 tp_vlan_tpid)
{
struct pcap_linux *handlep = handle->priv;
unsigned char *bp;
@@ -4211,9 +4641,9 @@ static int pcap_handle_packet_mmap(
/* perform sanity check on internal offset. */
if (tp_mac + tp_snaplen > handle->bufsize) {
- snprintf(handle->errbuf, PCAP_ERRBUF_SIZE,
+ pcap_snprintf(handle->errbuf, PCAP_ERRBUF_SIZE,
"corrupted frame on kernel ring mac "
- "offset %d + caplen %d > frame len %d",
+ "offset %u + caplen %u > frame len %d",
tp_mac, tp_snaplen, handle->bufsize);
return -1;
}
@@ -4228,22 +4658,9 @@ static int pcap_handle_packet_mmap(
* the filter when the ring became empty, but it can possibly
* happen a lot later... */
bp = frame + tp_mac;
- if (handlep->filter_in_userland && handle->fcode.bf_insns &&
- (bpf_filter(handle->fcode.bf_insns, bp,
- tp_len, tp_snaplen) == 0))
- return 0;
-
- sll = (void *)frame + TPACKET_ALIGN(handlep->tp_hdrlen);
- if (!linux_check_direction(handle, sll))
- return 0;
-
- /* get required packet info from ring header */
- pcaphdr.ts.tv_sec = tp_sec;
- pcaphdr.ts.tv_usec = tp_usec;
- pcaphdr.caplen = tp_snaplen;
- pcaphdr.len = tp_len;
/* if required build in place the sll header*/
+ sll = (void *)frame + TPACKET_ALIGN(handlep->tp_hdrlen);
if (handlep->cooked) {
struct sll_header *hdrp;
@@ -4256,7 +4673,7 @@ static int pcap_handle_packet_mmap(
*/
bp -= SLL_HDR_LEN;
- /*/*
+ /*
* Let's make sure that's past the end of
* the tpacket header, i.e. >=
* ((u_char *)thdr + TPACKET_HDRLEN), so we
@@ -4266,7 +4683,7 @@ static int pcap_handle_packet_mmap(
if (bp < (u_char *)frame +
TPACKET_ALIGN(handlep->tp_hdrlen) +
sizeof(struct sockaddr_ll)) {
- snprintf(handle->errbuf, PCAP_ERRBUF_SIZE,
+ pcap_snprintf(handle->errbuf, PCAP_ERRBUF_SIZE,
"cooked-mode frame doesn't have room for sll header");
return -1;
}
@@ -4281,7 +4698,30 @@ static int pcap_handle_packet_mmap(
hdrp->sll_halen = htons(sll->sll_halen);
memcpy(hdrp->sll_addr, sll->sll_addr, SLL_ADDRLEN);
hdrp->sll_protocol = sll->sll_protocol;
+ }
+
+ if (handlep->filter_in_userland && handle->fcode.bf_insns) {
+ struct bpf_aux_data aux_data;
+
+ aux_data.vlan_tag = tp_vlan_tci & 0x0fff;
+ aux_data.vlan_tag_present = tp_vlan_tci_valid;
+ if (bpf_filter_with_aux_data(handle->fcode.bf_insns, bp,
+ tp_len, tp_snaplen, &aux_data) == 0)
+ return 0;
+ }
+
+ if (!linux_check_direction(handle, sll))
+ return 0;
+
+ /* get required packet info from ring header */
+ pcaphdr.ts.tv_sec = tp_sec;
+ pcaphdr.ts.tv_usec = tp_usec;
+ pcaphdr.caplen = tp_snaplen;
+ pcaphdr.len = tp_len;
+
+ /* if required build in place the sll header*/
+ if (handlep->cooked) {
/* update packet len */
pcaphdr.caplen += SLL_HDR_LEN;
pcaphdr.len += SLL_HDR_LEN;
@@ -4294,13 +4734,24 @@ static int pcap_handle_packet_mmap(
{
struct vlan_tag *tag;
+ /*
+ * Move everything in the header, except the type field,
+ * down VLAN_TAG_LEN bytes, to allow us to insert the
+ * VLAN tag between that stuff and the type field.
+ */
bp -= VLAN_TAG_LEN;
memmove(bp, bp + VLAN_TAG_LEN, handlep->vlan_offset);
+ /*
+ * Now insert the tag.
+ */
tag = (struct vlan_tag *)(bp + handlep->vlan_offset);
- tag->vlan_tpid = htons(ETH_P_8021Q);
+ tag->vlan_tpid = htons(tp_vlan_tpid);
tag->vlan_tci = htons(tp_vlan_tci);
+ /*
+ * Add the tag to the packet lengths.
+ */
pcaphdr.caplen += VLAN_TAG_LEN;
pcaphdr.len += VLAN_TAG_LEN;
}
@@ -4315,7 +4766,7 @@ static int pcap_handle_packet_mmap(
* Trim the snapshot length to be no longer than the
* specified snapshot length.
*/
- if (pcaphdr.caplen > handle->snapshot)
+ if (pcaphdr.caplen > (bpf_u_int32)handle->snapshot)
pcaphdr.caplen = handle->snapshot;
/* pass the packet to the user */
@@ -4329,22 +4780,32 @@ pcap_read_linux_mmap_v1(pcap_t *handle, int max_packets, pcap_handler callback,
u_char *user)
{
struct pcap_linux *handlep = handle->priv;
+ union thdr h;
int pkts = 0;
int ret;
/* wait for frames availability.*/
- ret = pcap_wait_for_frames_mmap(handle);
- if (ret) {
- return ret;
+ h.raw = RING_GET_CURRENT_FRAME(handle);
+ if (h.h1->tp_status == TP_STATUS_KERNEL) {
+ /*
+ * The current frame is owned by the kernel; wait for
+ * a frame to be handed to us.
+ */
+ ret = pcap_wait_for_frames_mmap(handle);
+ if (ret) {
+ return ret;
+ }
}
/* non-positive values of max_packets are used to require all
* packets currently available in the ring */
while ((pkts < max_packets) || PACKET_COUNT_IS_UNLIMITED(max_packets)) {
- union thdr h;
-
- h.raw = pcap_get_ring_frame(handle, TP_STATUS_USER);
- if (!h.raw)
+ /*
+ * Get the current ring buffer frame, and break if
+ * it's still owned by the kernel.
+ */
+ h.raw = RING_GET_CURRENT_FRAME(handle);
+ if (h.h1->tp_status == TP_STATUS_KERNEL)
break;
ret = pcap_handle_packet_mmap(
@@ -4358,6 +4819,7 @@ pcap_read_linux_mmap_v1(pcap_t *handle, int max_packets, pcap_handler callback,
h.h1->tp_sec,
h.h1->tp_usec,
0,
+ 0,
0);
if (ret == 1) {
pkts++;
@@ -4397,28 +4859,122 @@ pcap_read_linux_mmap_v1(pcap_t *handle, int max_packets, pcap_handler callback,
return pkts;
}
+static int
+pcap_read_linux_mmap_v1_64(pcap_t *handle, int max_packets, pcap_handler callback,
+ u_char *user)
+{
+ struct pcap_linux *handlep = handle->priv;
+ union thdr h;
+ int pkts = 0;
+ int ret;
+
+ /* wait for frames availability.*/
+ h.raw = RING_GET_CURRENT_FRAME(handle);
+ if (h.h1_64->tp_status == TP_STATUS_KERNEL) {
+ /*
+ * The current frame is owned by the kernel; wait for
+ * a frame to be handed to us.
+ */
+ ret = pcap_wait_for_frames_mmap(handle);
+ if (ret) {
+ return ret;
+ }
+ }
+
+ /* non-positive values of max_packets are used to require all
+ * packets currently available in the ring */
+ while ((pkts < max_packets) || PACKET_COUNT_IS_UNLIMITED(max_packets)) {
+ /*
+ * Get the current ring buffer frame, and break if
+ * it's still owned by the kernel.
+ */
+ h.raw = RING_GET_CURRENT_FRAME(handle);
+ if (h.h1_64->tp_status == TP_STATUS_KERNEL)
+ break;
+
+ ret = pcap_handle_packet_mmap(
+ handle,
+ callback,
+ user,
+ h.raw,
+ h.h1_64->tp_len,
+ h.h1_64->tp_mac,
+ h.h1_64->tp_snaplen,
+ h.h1_64->tp_sec,
+ h.h1_64->tp_usec,
+ 0,
+ 0,
+ 0);
+ if (ret == 1) {
+ pkts++;
+ handlep->packets_read++;
+ } else if (ret < 0) {
+ return ret;
+ }
+
+ /*
+ * Hand this block back to the kernel, and, if we're
+ * counting blocks that need to be filtered in userland
+ * after having been filtered by the kernel, count
+ * the one we've just processed.
+ */
+ h.h1_64->tp_status = TP_STATUS_KERNEL;
+ if (handlep->blocks_to_filter_in_userland > 0) {
+ handlep->blocks_to_filter_in_userland--;
+ if (handlep->blocks_to_filter_in_userland == 0) {
+ /*
+ * No more blocks need to be filtered
+ * in userland.
+ */
+ handlep->filter_in_userland = 0;
+ }
+ }
+
+ /* next block */
+ if (++handle->offset >= handle->cc)
+ handle->offset = 0;
+
+ /* check for break loop condition*/
+ if (handle->break_loop) {
+ handle->break_loop = 0;
+ return PCAP_ERROR_BREAK;
+ }
+ }
+ return pkts;
+}
+
#ifdef HAVE_TPACKET2
static int
pcap_read_linux_mmap_v2(pcap_t *handle, int max_packets, pcap_handler callback,
u_char *user)
{
struct pcap_linux *handlep = handle->priv;
+ union thdr h;
int pkts = 0;
int ret;
/* wait for frames availability.*/
- ret = pcap_wait_for_frames_mmap(handle);
- if (ret) {
- return ret;
+ h.raw = RING_GET_CURRENT_FRAME(handle);
+ if (h.h2->tp_status == TP_STATUS_KERNEL) {
+ /*
+ * The current frame is owned by the kernel; wait for
+ * a frame to be handed to us.
+ */
+ ret = pcap_wait_for_frames_mmap(handle);
+ if (ret) {
+ return ret;
+ }
}
/* non-positive values of max_packets are used to require all
* packets currently available in the ring */
while ((pkts < max_packets) || PACKET_COUNT_IS_UNLIMITED(max_packets)) {
- union thdr h;
-
- h.raw = pcap_get_ring_frame(handle, TP_STATUS_USER);
- if (!h.raw)
+ /*
+ * Get the current ring buffer frame, and break if
+ * it's still owned by the kernel.
+ */
+ h.raw = RING_GET_CURRENT_FRAME(handle);
+ if (h.h2->tp_status == TP_STATUS_KERNEL)
break;
ret = pcap_handle_packet_mmap(
@@ -4436,7 +4992,8 @@ pcap_read_linux_mmap_v2(pcap_t *handle, int max_packets, pcap_handler callback,
#else
h.h2->tp_vlan_tci != 0,
#endif
- h.h2->tp_vlan_tci);
+ h.h2->tp_vlan_tci,
+ VLAN_TPID(h.h2, h.h2));
if (ret == 1) {
pkts++;
handlep->packets_read++;
@@ -4489,13 +5046,20 @@ pcap_read_linux_mmap_v3(pcap_t *handle, int max_packets, pcap_handler callback,
again:
if (handlep->current_packet == NULL) {
/* wait for frames availability.*/
- ret = pcap_wait_for_frames_mmap(handle);
- if (ret) {
- return ret;
+ h.raw = RING_GET_CURRENT_FRAME(handle);
+ if (h.h3->hdr.bh1.block_status == TP_STATUS_KERNEL) {
+ /*
+ * The current frame is owned by the kernel; wait
+ * for a frame to be handed to us.
+ */
+ ret = pcap_wait_for_frames_mmap(handle);
+ if (ret) {
+ return ret;
+ }
}
}
- h.raw = pcap_get_ring_frame(handle, TP_STATUS_USER);
- if (!h.raw) {
+ h.raw = RING_GET_CURRENT_FRAME(handle);
+ if (h.h3->hdr.bh1.block_status == TP_STATUS_KERNEL) {
if (pkts == 0 && handlep->timeout == 0) {
/* Block until we see a packet. */
goto again;
@@ -4506,21 +5070,30 @@ again:
/* non-positive values of max_packets are used to require all
* packets currently available in the ring */
while ((pkts < max_packets) || PACKET_COUNT_IS_UNLIMITED(max_packets)) {
+ int packets_to_read;
+
if (handlep->current_packet == NULL) {
- h.raw = pcap_get_ring_frame(handle, TP_STATUS_USER);
- if (!h.raw)
+ h.raw = RING_GET_CURRENT_FRAME(handle);
+ if (h.h3->hdr.bh1.block_status == TP_STATUS_KERNEL)
break;
handlep->current_packet = h.raw + h.h3->hdr.bh1.offset_to_first_pkt;
handlep->packets_left = h.h3->hdr.bh1.num_pkts;
}
- int packets_to_read = handlep->packets_left;
+ packets_to_read = handlep->packets_left;
- if (!PACKET_COUNT_IS_UNLIMITED(max_packets) && packets_to_read > max_packets) {
- packets_to_read = max_packets;
+ if (!PACKET_COUNT_IS_UNLIMITED(max_packets) &&
+ packets_to_read > (max_packets - pkts)) {
+ /*
+ * We've been given a maximum number of packets
+ * to process, and there are more packets in
+ * this buffer than that. Only process enough
+ * of them to get us up to that maximum.
+ */
+ packets_to_read = max_packets - pkts;
}
- while(packets_to_read--) {
+ while (packets_to_read-- && !handle->break_loop) {
struct tpacket3_hdr* tp3_hdr = (struct tpacket3_hdr*) handlep->current_packet;
ret = pcap_handle_packet_mmap(
handle,
@@ -4537,7 +5110,8 @@ again:
#else
tp3_hdr->hv1.tp_vlan_tci != 0,
#endif
- tp3_hdr->hv1.tp_vlan_tci);
+ tp3_hdr->hv1.tp_vlan_tci,
+ VLAN_TPID(tp3_hdr, &tp3_hdr->hv1));
if (ret == 1) {
pkts++;
handlep->packets_read++;
@@ -4590,7 +5164,7 @@ again:
}
#endif /* HAVE_TPACKET3 */
-static int
+static int
pcap_setfilter_linux_mmap(pcap_t *handle, struct bpf_program *filter)
{
struct pcap_linux *handlep = handle->priv;
@@ -4624,12 +5198,12 @@ pcap_setfilter_linux_mmap(pcap_t *handle, struct bpf_program *filter)
* walk the ring backward and count the free blocks.
*/
offset = handle->offset;
- if (--handle->offset < 0)
- handle->offset = handle->cc - 1;
+ if (--offset < 0)
+ offset = handle->cc - 1;
for (n=0; n < handle->cc; ++n) {
- if (--handle->offset < 0)
- handle->offset = handle->cc - 1;
- if (!pcap_get_ring_frame(handle, TP_STATUS_KERNEL))
+ if (--offset < 0)
+ offset = handle->cc - 1;
+ if (pcap_get_ring_frame_status(handle, offset) != TP_STATUS_KERNEL)
break;
}
@@ -4650,9 +5224,6 @@ pcap_setfilter_linux_mmap(pcap_t *handle, struct bpf_program *filter)
if (n != 0)
n--;
- /* be careful to not change current ring position */
- handle->offset = offset;
-
/*
* Set the count of blocks worth of packets to filter
* in userland to the total number of blocks in the
@@ -4686,7 +5257,7 @@ iface_get_id(int fd, const char *device, char *ebuf)
strlcpy(ifr.ifr_name, device, sizeof(ifr.ifr_name));
if (ioctl(fd, SIOCGIFINDEX, &ifr) == -1) {
- snprintf(ebuf, PCAP_ERRBUF_SIZE,
+ pcap_snprintf(ebuf, PCAP_ERRBUF_SIZE,
"SIOCGIFINDEX: %s", pcap_strerror(errno));
return -1;
}
@@ -4722,7 +5293,7 @@ iface_bind(int fd, int ifindex, char *ebuf)
*/
return PCAP_ERROR_IFACE_NOT_UP;
} else {
- snprintf(ebuf, PCAP_ERRBUF_SIZE,
+ pcap_snprintf(ebuf, PCAP_ERRBUF_SIZE,
"bind: %s", pcap_strerror(errno));
return PCAP_ERROR;
}
@@ -4731,7 +5302,7 @@ iface_bind(int fd, int ifindex, char *ebuf)
/* Any pending errors, e.g., network is down? */
if (getsockopt(fd, SOL_SOCKET, SO_ERROR, &err, &errlen) == -1) {
- snprintf(ebuf, PCAP_ERRBUF_SIZE,
+ pcap_snprintf(ebuf, PCAP_ERRBUF_SIZE,
"getsockopt: %s", pcap_strerror(errno));
return 0;
}
@@ -4746,7 +5317,7 @@ iface_bind(int fd, int ifindex, char *ebuf)
*/
return PCAP_ERROR_IFACE_NOT_UP;
} else if (err > 0) {
- snprintf(ebuf, PCAP_ERRBUF_SIZE,
+ pcap_snprintf(ebuf, PCAP_ERRBUF_SIZE,
"bind: %s", pcap_strerror(err));
return 0;
}
@@ -4765,12 +5336,15 @@ has_wext(int sock_fd, const char *device, char *ebuf)
{
struct iwreq ireq;
+ if (is_bonding_device(sock_fd, device))
+ return 0; /* bonding device, so don't even try */
+
strlcpy(ireq.ifr_ifrn.ifrn_name, device,
sizeof ireq.ifr_ifrn.ifrn_name);
if (ioctl(sock_fd, SIOCGIWNAME, &ireq) >= 0)
return 1; /* yes */
- snprintf(ebuf, PCAP_ERRBUF_SIZE,
- "%s: SIOCGIWPRIV: %s", device, pcap_strerror(errno));
+ pcap_snprintf(ebuf, PCAP_ERRBUF_SIZE,
+ "%s: SIOCGIWNAME: %s", device, pcap_strerror(errno));
if (errno == ENODEV)
return PCAP_ERROR_NO_SUCH_DEVICE;
return 0;
@@ -4908,7 +5482,7 @@ enter_rfmon_mode_wext(pcap_t *handle, int sock_fd, const char *device)
ireq.u.data.length = 0;
ireq.u.data.flags = 0;
if (ioctl(sock_fd, SIOCGIWPRIV, &ireq) != -1) {
- snprintf(handle->errbuf, PCAP_ERRBUF_SIZE,
+ pcap_snprintf(handle->errbuf, PCAP_ERRBUF_SIZE,
"%s: SIOCGIWPRIV with a zero-length buffer didn't fail!",
device);
return PCAP_ERROR;
@@ -4921,7 +5495,7 @@ enter_rfmon_mode_wext(pcap_t *handle, int sock_fd, const char *device)
/*
* Failed.
*/
- snprintf(handle->errbuf, PCAP_ERRBUF_SIZE,
+ pcap_snprintf(handle->errbuf, PCAP_ERRBUF_SIZE,
"%s: SIOCGIWPRIV: %s", device,
pcap_strerror(errno));
return PCAP_ERROR;
@@ -4932,13 +5506,13 @@ enter_rfmon_mode_wext(pcap_t *handle, int sock_fd, const char *device)
*/
priv = malloc(ireq.u.data.length * sizeof (struct iw_priv_args));
if (priv == NULL) {
- snprintf(handle->errbuf, PCAP_ERRBUF_SIZE,
+ pcap_snprintf(handle->errbuf, PCAP_ERRBUF_SIZE,
"malloc: %s", pcap_strerror(errno));
return PCAP_ERROR;
}
ireq.u.data.pointer = (void *)priv;
if (ioctl(sock_fd, SIOCGIWPRIV, &ireq) == -1) {
- snprintf(handle->errbuf, PCAP_ERRBUF_SIZE,
+ pcap_snprintf(handle->errbuf, PCAP_ERRBUF_SIZE,
"%s: SIOCGIWPRIV: %s", device,
pcap_strerror(errno));
free(priv);
@@ -5194,7 +5768,7 @@ enter_rfmon_mode_wext(pcap_t *handle, int sock_fd, const char *device)
memset(&ifr, 0, sizeof(ifr));
strlcpy(ifr.ifr_name, device, sizeof(ifr.ifr_name));
if (ioctl(sock_fd, SIOCGIFFLAGS, &ifr) == -1) {
- snprintf(handle->errbuf, PCAP_ERRBUF_SIZE,
+ pcap_snprintf(handle->errbuf, PCAP_ERRBUF_SIZE,
"%s: Can't get flags: %s", device, strerror(errno));
return PCAP_ERROR;
}
@@ -5203,7 +5777,7 @@ enter_rfmon_mode_wext(pcap_t *handle, int sock_fd, const char *device)
oldflags = ifr.ifr_flags;
ifr.ifr_flags &= ~IFF_UP;
if (ioctl(sock_fd, SIOCSIFFLAGS, &ifr) == -1) {
- snprintf(handle->errbuf, PCAP_ERRBUF_SIZE,
+ pcap_snprintf(handle->errbuf, PCAP_ERRBUF_SIZE,
"%s: Can't set flags: %s", device, strerror(errno));
return PCAP_ERROR;
}
@@ -5222,7 +5796,7 @@ enter_rfmon_mode_wext(pcap_t *handle, int sock_fd, const char *device)
*/
ifr.ifr_flags = oldflags;
if (ioctl(sock_fd, SIOCSIFFLAGS, &ifr) == -1) {
- snprintf(handle->errbuf, PCAP_ERRBUF_SIZE,
+ pcap_snprintf(handle->errbuf, PCAP_ERRBUF_SIZE,
"%s: Can't set flags: %s", device, strerror(errno));
return PCAP_ERROR;
}
@@ -5306,7 +5880,7 @@ enter_rfmon_mode_wext(pcap_t *handle, int sock_fd, const char *device)
strlcpy(ireq.ifr_ifrn.ifrn_name, device,
sizeof ireq.ifr_ifrn.ifrn_name);
if (ioctl(sock_fd, SIOCGIWFREQ, &ireq) == -1) {
- snprintf(handle->errbuf, PCAP_ERRBUF_SIZE,
+ pcap_snprintf(handle->errbuf, PCAP_ERRBUF_SIZE,
"%s: SIOCGIWFREQ: %s", device,
pcap_strerror(errno));
return PCAP_ERROR;
@@ -5383,7 +5957,7 @@ enter_rfmon_mode_wext(pcap_t *handle, int sock_fd, const char *device)
if (oldflags != 0) {
ifr.ifr_flags = oldflags;
if (ioctl(sock_fd, SIOCSIFFLAGS, &ifr) == -1) {
- snprintf(handle->errbuf, PCAP_ERRBUF_SIZE,
+ pcap_snprintf(handle->errbuf, PCAP_ERRBUF_SIZE,
"%s: Can't set flags: %s", device, strerror(errno));
/*
@@ -5452,6 +6026,176 @@ enter_rfmon_mode(pcap_t *handle, int sock_fd, const char *device)
return 0;
}
+#if defined(HAVE_LINUX_NET_TSTAMP_H) && defined(PACKET_TIMESTAMP)
+/*
+ * Map SOF_TIMESTAMPING_ values to PCAP_TSTAMP_ values.
+ */
+static const struct {
+ int soft_timestamping_val;
+ int pcap_tstamp_val;
+} sof_ts_type_map[3] = {
+ { SOF_TIMESTAMPING_SOFTWARE, PCAP_TSTAMP_HOST },
+ { SOF_TIMESTAMPING_SYS_HARDWARE, PCAP_TSTAMP_ADAPTER },
+ { SOF_TIMESTAMPING_RAW_HARDWARE, PCAP_TSTAMP_ADAPTER_UNSYNCED }
+};
+#define NUM_SOF_TIMESTAMPING_TYPES (sizeof sof_ts_type_map / sizeof sof_ts_type_map[0])
+
+/*
+ * Set the list of time stamping types to include all types.
+ */
+static void
+iface_set_all_ts_types(pcap_t *handle)
+{
+ u_int i;
+
+ handle->tstamp_type_count = NUM_SOF_TIMESTAMPING_TYPES;
+ handle->tstamp_type_list = malloc(NUM_SOF_TIMESTAMPING_TYPES * sizeof(u_int));
+ for (i = 0; i < NUM_SOF_TIMESTAMPING_TYPES; i++)
+ handle->tstamp_type_list[i] = sof_ts_type_map[i].pcap_tstamp_val;
+}
+
+#ifdef ETHTOOL_GET_TS_INFO
+/*
+ * Get a list of time stamping capabilities.
+ */
+static int
+iface_ethtool_get_ts_info(const char *device, pcap_t *handle, char *ebuf)
+{
+ int fd;
+ struct ifreq ifr;
+ struct ethtool_ts_info info;
+ int num_ts_types;
+ u_int i, j;
+
+ /*
+ * This doesn't apply to the "any" device; you can't say "turn on
+ * hardware time stamping for all devices that exist now and arrange
+ * that it be turned on for any device that appears in the future",
+ * and not all devices even necessarily *support* hardware time
+ * stamping, so don't report any time stamp types.
+ */
+ if (strcmp(device, "any") == 0) {
+ handle->tstamp_type_list = NULL;
+ return 0;
+ }
+
+ /*
+ * Create a socket from which to fetch time stamping capabilities.
+ */
+ fd = socket(PF_UNIX, SOCK_RAW, 0);
+ if (fd < 0) {
+ (void)pcap_snprintf(ebuf, PCAP_ERRBUF_SIZE,
+ "socket for SIOCETHTOOL(ETHTOOL_GET_TS_INFO): %s", pcap_strerror(errno));
+ return -1;
+ }
+
+ memset(&ifr, 0, sizeof(ifr));
+ strlcpy(ifr.ifr_name, device, sizeof(ifr.ifr_name));
+ memset(&info, 0, sizeof(info));
+ info.cmd = ETHTOOL_GET_TS_INFO;
+ ifr.ifr_data = (caddr_t)&info;
+ if (ioctl(fd, SIOCETHTOOL, &ifr) == -1) {
+ int save_errno = errno;
+
+ close(fd);
+ switch (save_errno) {
+
+ case EOPNOTSUPP:
+ case EINVAL:
+ /*
+ * OK, this OS version or driver doesn't support
+ * asking for the time stamping types, so let's
+ * just return all the possible types.
+ */
+ iface_set_all_ts_types(handle);
+ return 0;
+
+ case ENODEV:
+ /*
+ * OK, no such device.
+ * The user will find that out when they try to
+ * activate the device; just return an empty
+ * list of time stamp types.
+ */
+ handle->tstamp_type_list = NULL;
+ return 0;
+
+ default:
+ /*
+ * Other error.
+ */
+ pcap_snprintf(ebuf, PCAP_ERRBUF_SIZE,
+ "%s: SIOCETHTOOL(ETHTOOL_GET_TS_INFO) ioctl failed: %s", device,
+ strerror(save_errno));
+ return -1;
+ }
+ }
+ close(fd);
+
+ /*
+ * Do we support hardware time stamping of *all* packets?
+ */
+ if (!(info.rx_filters & (1 << HWTSTAMP_FILTER_ALL))) {
+ /*
+ * No, so don't report any time stamp types.
+ *
+ * XXX - some devices either don't report
+ * HWTSTAMP_FILTER_ALL when they do support it, or
+ * report HWTSTAMP_FILTER_ALL but map it to only
+ * time stamping a few PTP packets. See
+ * http://marc.info/?l=linux-netdev&m=146318183529571&w=2
+ */
+ handle->tstamp_type_list = NULL;
+ return 0;
+ }
+
+ num_ts_types = 0;
+ for (i = 0; i < NUM_SOF_TIMESTAMPING_TYPES; i++) {
+ if (info.so_timestamping & sof_ts_type_map[i].soft_timestamping_val)
+ num_ts_types++;
+ }
+ handle->tstamp_type_count = num_ts_types;
+ if (num_ts_types != 0) {
+ handle->tstamp_type_list = malloc(num_ts_types * sizeof(u_int));
+ for (i = 0, j = 0; i < NUM_SOF_TIMESTAMPING_TYPES; i++) {
+ if (info.so_timestamping & sof_ts_type_map[i].soft_timestamping_val) {
+ handle->tstamp_type_list[j] = sof_ts_type_map[i].pcap_tstamp_val;
+ j++;
+ }
+ }
+ } else
+ handle->tstamp_type_list = NULL;
+
+ return 0;
+}
+#else /* ETHTOOL_GET_TS_INFO */
+static int
+iface_ethtool_get_ts_info(const char *device, pcap_t *handle, char *ebuf _U_)
+{
+ /*
+ * This doesn't apply to the "any" device; you can't say "turn on
+ * hardware time stamping for all devices that exist now and arrange
+ * that it be turned on for any device that appears in the future",
+ * and not all devices even necessarily *support* hardware time
+ * stamping, so don't report any time stamp types.
+ */
+ if (strcmp(device, "any") == 0) {
+ handle->tstamp_type_list = NULL;
+ return 0;
+ }
+
+ /*
+ * We don't have an ioctl to use to ask what's supported,
+ * so say we support everything.
+ */
+ iface_set_all_ts_types(handle);
+ return 0;
+}
+#endif /* ETHTOOL_GET_TS_INFO */
+
+#endif /* defined(HAVE_LINUX_NET_TSTAMP_H) && defined(PACKET_TIMESTAMP) */
+
+#ifdef HAVE_PACKET_RING
/*
* Find out if we have any form of fragmentation/reassembly offloading.
*
@@ -5462,13 +6206,13 @@ enter_rfmon_mode(pcap_t *handle, int sock_fd, const char *device)
*/
#if defined(SIOCETHTOOL) && (defined(ETHTOOL_GTSO) || defined(ETHTOOL_GUFO) || defined(ETHTOOL_GGSO) || defined(ETHTOOL_GFLAGS) || defined(ETHTOOL_GGRO))
static int
-iface_ethtool_ioctl(pcap_t *handle, int cmd, const char *cmdname)
+iface_ethtool_flag_ioctl(pcap_t *handle, int cmd, const char *cmdname)
{
struct ifreq ifr;
struct ethtool_value eval;
memset(&ifr, 0, sizeof(ifr));
- strlcpy(ifr.ifr_name, handle->opt.source, sizeof(ifr.ifr_name));
+ strlcpy(ifr.ifr_name, handle->opt.device, sizeof(ifr.ifr_name));
eval.cmd = cmd;
eval.data = 0;
ifr.ifr_data = (caddr_t)&eval;
@@ -5482,12 +6226,12 @@ iface_ethtool_ioctl(pcap_t *handle, int cmd, const char *cmdname)
*/
return 0;
}
- snprintf(handle->errbuf, PCAP_ERRBUF_SIZE,
- "%s: SIOETHTOOL(%s) ioctl failed: %s", handle->opt.source,
+ pcap_snprintf(handle->errbuf, PCAP_ERRBUF_SIZE,
+ "%s: SIOCETHTOOL(%s) ioctl failed: %s", handle->opt.device,
cmdname, strerror(errno));
return -1;
}
- return eval.data;
+ return eval.data;
}
static int
@@ -5496,7 +6240,7 @@ iface_get_offload(pcap_t *handle)
int ret;
#ifdef ETHTOOL_GTSO
- ret = iface_ethtool_ioctl(handle, ETHTOOL_GTSO, "ETHTOOL_GTSO");
+ ret = iface_ethtool_flag_ioctl(handle, ETHTOOL_GTSO, "ETHTOOL_GTSO");
if (ret == -1)
return -1;
if (ret)
@@ -5504,7 +6248,7 @@ iface_get_offload(pcap_t *handle)
#endif
#ifdef ETHTOOL_GUFO
- ret = iface_ethtool_ioctl(handle, ETHTOOL_GUFO, "ETHTOOL_GUFO");
+ ret = iface_ethtool_flag_ioctl(handle, ETHTOOL_GUFO, "ETHTOOL_GUFO");
if (ret == -1)
return -1;
if (ret)
@@ -5517,7 +6261,7 @@ iface_get_offload(pcap_t *handle)
* handed to PF_PACKET sockets on transmission? If not,
* this need not be checked.
*/
- ret = iface_ethtool_ioctl(handle, ETHTOOL_GGSO, "ETHTOOL_GGSO");
+ ret = iface_ethtool_flag_ioctl(handle, ETHTOOL_GGSO, "ETHTOOL_GGSO");
if (ret == -1)
return -1;
if (ret)
@@ -5525,7 +6269,7 @@ iface_get_offload(pcap_t *handle)
#endif
#ifdef ETHTOOL_GFLAGS
- ret = iface_ethtool_ioctl(handle, ETHTOOL_GFLAGS, "ETHTOOL_GFLAGS");
+ ret = iface_ethtool_flag_ioctl(handle, ETHTOOL_GFLAGS, "ETHTOOL_GFLAGS");
if (ret == -1)
return -1;
if (ret & ETH_FLAG_LRO)
@@ -5538,7 +6282,7 @@ iface_get_offload(pcap_t *handle)
* handed to PF_PACKET sockets on receipt? If not,
* this need not be checked.
*/
- ret = iface_ethtool_ioctl(handle, ETHTOOL_GGRO, "ETHTOOL_GGRO");
+ ret = iface_ethtool_flag_ioctl(handle, ETHTOOL_GGRO, "ETHTOOL_GGRO");
if (ret == -1)
return -1;
if (ret)
@@ -5559,6 +6303,8 @@ iface_get_offload(pcap_t *handle _U_)
}
#endif /* SIOCETHTOOL */
+#endif /* HAVE_PACKET_RING */
+
#endif /* HAVE_PF_PACKET_SOCKETS */
/* ===== Functions to interface to the older kernels ================== */
@@ -5573,7 +6319,7 @@ activate_old(pcap_t *handle)
struct pcap_linux *handlep = handle->priv;
int arptype;
struct ifreq ifr;
- const char *device = handle->opt.source;
+ const char *device = handle->opt.device;
struct utsname utsname;
int mtu;
@@ -5581,7 +6327,7 @@ activate_old(pcap_t *handle)
handle->fd = socket(PF_INET, SOCK_PACKET, htons(ETH_P_ALL));
if (handle->fd == -1) {
- snprintf(handle->errbuf, PCAP_ERRBUF_SIZE,
+ pcap_snprintf(handle->errbuf, PCAP_ERRBUF_SIZE,
"socket: %s", pcap_strerror(errno));
if (errno == EPERM || errno == EACCES) {
/*
@@ -5624,9 +6370,9 @@ activate_old(pcap_t *handle)
* Try to find the DLT_ type corresponding to that
* link-layer type.
*/
- map_arphrd_to_dlt(handle, arptype, device, 0);
+ map_arphrd_to_dlt(handle, handle->fd, arptype, device, 0);
if (handle->linktype == -1) {
- snprintf(handle->errbuf, PCAP_ERRBUF_SIZE,
+ pcap_snprintf(handle->errbuf, PCAP_ERRBUF_SIZE,
"unknown arptype %d", arptype);
return PCAP_ERROR;
}
@@ -5637,7 +6383,7 @@ activate_old(pcap_t *handle)
memset(&ifr, 0, sizeof(ifr));
strlcpy(ifr.ifr_name, device, sizeof(ifr.ifr_name));
if (ioctl(handle->fd, SIOCGIFFLAGS, &ifr) == -1) {
- snprintf(handle->errbuf, PCAP_ERRBUF_SIZE,
+ pcap_snprintf(handle->errbuf, PCAP_ERRBUF_SIZE,
"SIOCGIFFLAGS: %s", pcap_strerror(errno));
return PCAP_ERROR;
}
@@ -5665,7 +6411,7 @@ activate_old(pcap_t *handle)
ifr.ifr_flags |= IFF_PROMISC;
if (ioctl(handle->fd, SIOCSIFFLAGS, &ifr) == -1) {
- snprintf(handle->errbuf, PCAP_ERRBUF_SIZE,
+ pcap_snprintf(handle->errbuf, PCAP_ERRBUF_SIZE,
"SIOCSIFFLAGS: %s",
pcap_strerror(errno));
return PCAP_ERROR;
@@ -5734,8 +6480,8 @@ activate_old(pcap_t *handle)
if (mtu == -1)
return PCAP_ERROR;
handle->bufsize = MAX_LINKHEADER_SIZE + mtu;
- if (handle->bufsize < handle->snapshot)
- handle->bufsize = handle->snapshot;
+ if (handle->bufsize < (u_int)handle->snapshot)
+ handle->bufsize = (u_int)handle->snapshot;
} else {
/*
* This is a 2.2[.x] or later kernel.
@@ -5743,7 +6489,7 @@ activate_old(pcap_t *handle)
* We can safely pass "recvfrom()" a byte count
* based on the snapshot length.
*/
- handle->bufsize = handle->snapshot;
+ handle->bufsize = (u_int)handle->snapshot;
}
/*
@@ -5775,7 +6521,7 @@ iface_bind_old(int fd, const char *device, char *ebuf)
memset(&saddr, 0, sizeof(saddr));
strlcpy(saddr.sa_data, device, sizeof(saddr.sa_data));
if (bind(fd, &saddr, sizeof(saddr)) == -1) {
- snprintf(ebuf, PCAP_ERRBUF_SIZE,
+ pcap_snprintf(ebuf, PCAP_ERRBUF_SIZE,
"bind: %s", pcap_strerror(errno));
return -1;
}
@@ -5783,13 +6529,13 @@ iface_bind_old(int fd, const char *device, char *ebuf)
/* Any pending errors, e.g., network is down? */
if (getsockopt(fd, SOL_SOCKET, SO_ERROR, &err, &errlen) == -1) {
- snprintf(ebuf, PCAP_ERRBUF_SIZE,
+ pcap_snprintf(ebuf, PCAP_ERRBUF_SIZE,
"getsockopt: %s", pcap_strerror(errno));
return -1;
}
if (err > 0) {
- snprintf(ebuf, PCAP_ERRBUF_SIZE,
+ pcap_snprintf(ebuf, PCAP_ERRBUF_SIZE,
"bind: %s", pcap_strerror(err));
return -1;
}
@@ -5815,7 +6561,7 @@ iface_get_mtu(int fd, const char *device, char *ebuf)
strlcpy(ifr.ifr_name, device, sizeof(ifr.ifr_name));
if (ioctl(fd, SIOCGIFMTU, &ifr) == -1) {
- snprintf(ebuf, PCAP_ERRBUF_SIZE,
+ pcap_snprintf(ebuf, PCAP_ERRBUF_SIZE,
"SIOCGIFMTU: %s", pcap_strerror(errno));
return -1;
}
@@ -5835,7 +6581,7 @@ iface_get_arptype(int fd, const char *device, char *ebuf)
strlcpy(ifr.ifr_name, device, sizeof(ifr.ifr_name));
if (ioctl(fd, SIOCGIFHWADDR, &ifr) == -1) {
- snprintf(ebuf, PCAP_ERRBUF_SIZE,
+ pcap_snprintf(ebuf, PCAP_ERRBUF_SIZE,
"SIOCGIFHWADDR: %s", pcap_strerror(errno));
if (errno == ENODEV) {
/*
@@ -5868,7 +6614,7 @@ fix_program(pcap_t *handle, struct sock_fprog *fcode, int is_mmapped)
len = handle->fcode.bf_len;
f = (struct bpf_insn *)malloc(prog_size);
if (f == NULL) {
- snprintf(handle->errbuf, PCAP_ERRBUF_SIZE,
+ pcap_snprintf(handle->errbuf, PCAP_ERRBUF_SIZE,
"malloc: %s", pcap_strerror(errno));
return -1;
}
@@ -6044,20 +6790,40 @@ set_kernel_filter(pcap_t *handle, struct sock_fprog *fcode)
* "nothing more to be read" error).
*/
save_mode = fcntl(handle->fd, F_GETFL, 0);
- if (save_mode != -1 &&
- fcntl(handle->fd, F_SETFL, save_mode | O_NONBLOCK) >= 0) {
- while (recv(handle->fd, &drain, sizeof drain,
- MSG_TRUNC) >= 0)
- ;
- save_errno = errno;
- fcntl(handle->fd, F_SETFL, save_mode);
- if (save_errno != EAGAIN) {
- /* Fatal error */
- reset_kernel_filter(handle);
- snprintf(handle->errbuf, PCAP_ERRBUF_SIZE,
- "recv: %s", pcap_strerror(save_errno));
- return -2;
- }
+ if (save_mode == -1) {
+ pcap_snprintf(handle->errbuf, PCAP_ERRBUF_SIZE,
+ "can't get FD flags when changing filter: %s",
+ pcap_strerror(errno));
+ return -2;
+ }
+ if (fcntl(handle->fd, F_SETFL, save_mode | O_NONBLOCK) < 0) {
+ pcap_snprintf(handle->errbuf, PCAP_ERRBUF_SIZE,
+ "can't set nonblocking mode when changing filter: %s",
+ pcap_strerror(errno));
+ return -2;
+ }
+ while (recv(handle->fd, &drain, sizeof drain, MSG_TRUNC) >= 0)
+ ;
+ save_errno = errno;
+ if (save_errno != EAGAIN) {
+ /*
+ * Fatal error.
+ *
+ * If we can't restore the mode or reset the
+ * kernel filter, there's nothing we can do.
+ */
+ (void)fcntl(handle->fd, F_SETFL, save_mode);
+ (void)reset_kernel_filter(handle);
+ pcap_snprintf(handle->errbuf, PCAP_ERRBUF_SIZE,
+ "recv failed when changing filter: %s",
+ pcap_strerror(save_errno));
+ return -2;
+ }
+ if (fcntl(handle->fd, F_SETFL, save_mode) == -1) {
+ pcap_snprintf(handle->errbuf, PCAP_ERRBUF_SIZE,
+ "can't restore FD flags when changing filter: %s",
+ pcap_strerror(save_errno));
+ return -2;
}
}
@@ -6080,11 +6846,16 @@ set_kernel_filter(pcap_t *handle, struct sock_fprog *fcode)
save_errno = errno;
/*
- * XXX - if this fails, we're really screwed;
- * we have the total filter on the socket,
- * and it won't come off. What do we do then?
+ * If this fails, we're really screwed; we have the
+ * total filter on the socket, and it won't come off.
+ * Report it as a fatal error.
*/
- reset_kernel_filter(handle);
+ if (reset_kernel_filter(handle) == -1) {
+ pcap_snprintf(handle->errbuf, PCAP_ERRBUF_SIZE,
+ "can't remove kernel total filter: %s",
+ pcap_strerror(errno));
+ return -2; /* fatal error */
+ }
errno = save_errno;
}
diff --git a/contrib/libpcap/pcap-netfilter-linux.c b/contrib/libpcap/pcap-netfilter-linux.c
index 2a5812b273af..bde648f3ea59 100644
--- a/contrib/libpcap/pcap-netfilter-linux.c
+++ b/contrib/libpcap/pcap-netfilter-linux.c
@@ -11,8 +11,8 @@
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
- * 3. The name of the author may not be used to endorse or promote
- * products derived from this software without specific prior written
+ * 3. The name of the author may not be used to endorse or promote
+ * products derived from this software without specific prior written
* permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
@@ -57,14 +57,14 @@
#include <linux/netfilter/nfnetlink_queue.h>
/* NOTE: if your program drops privilages after pcap_activate() it WON'T work with nfqueue.
- * It took me quite some time to debug ;/
+ * It took me quite some time to debug ;/
*
* Sending any data to nfnetlink socket requires CAP_NET_ADMIN privilages,
* and in nfqueue we need to send verdict reply after recving packet.
*
* In tcpdump you can disable dropping privilages with -Z root
*/
-
+
#include "pcap-netfilter-linux.h"
#define HDR_LENGTH (NLMSG_LENGTH(NLMSG_ALIGN(sizeof(struct nfgenmsg))))
@@ -79,10 +79,12 @@ typedef enum { OTHER = -1, NFLOG, NFQUEUE } nftype_t;
*/
struct pcap_netfilter {
u_int packets_read; /* count of packets read with recvfrom() */
+ u_int packets_nobufs; /* ENOBUFS counter */
};
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)
{
@@ -98,28 +100,29 @@ netfilter_read_linux(pcap_t *handle, int max_packets, pcap_handler callback, u_c
handle->break_loop = 0;
return -2;
}
- } while ((len == -1) && (errno == EINTR));
+ if(errno == ENOBUFS) handlep->packets_nobufs++;
+ } while ((len == -1) && (errno == EINTR || errno == ENOBUFS));
if (len < 0) {
- snprintf(handle->errbuf, PCAP_ERRBUF_SIZE, "Can't receive packet %d:%s", errno, pcap_strerror(errno));
+ pcap_snprintf(handle->errbuf, PCAP_ERRBUF_SIZE, "Can't receive packet %d:%s", errno, pcap_strerror(errno));
return -1;
}
- buf = handle->buffer;
- while (len >= NLMSG_SPACE(0)) {
+ buf = (unsigned char *)handle->buffer;
+ while ((u_int)len >= NLMSG_SPACE(0)) {
const struct nlmsghdr *nlh = (const struct nlmsghdr *) buf;
u_int32_t msg_len;
nftype_t type = OTHER;
- if (nlh->nlmsg_len < sizeof(struct nlmsghdr) || len < nlh->nlmsg_len) {
- snprintf(handle->errbuf, PCAP_ERRBUF_SIZE, "Message truncated: (got: %d) (nlmsg_len: %u)", len, nlh->nlmsg_len);
+ if (nlh->nlmsg_len < sizeof(struct nlmsghdr) || (u_int)len < nlh->nlmsg_len) {
+ pcap_snprintf(handle->errbuf, PCAP_ERRBUF_SIZE, "Message truncated: (got: %d) (nlmsg_len: %u)", len, nlh->nlmsg_len);
return -1;
}
- if (NFNL_SUBSYS_ID(nlh->nlmsg_type) == NFNL_SUBSYS_ULOG &&
- NFNL_MSG_TYPE(nlh->nlmsg_type) == NFULNL_MSG_PACKET)
+ if (NFNL_SUBSYS_ID(nlh->nlmsg_type) == NFNL_SUBSYS_ULOG &&
+ NFNL_MSG_TYPE(nlh->nlmsg_type) == NFULNL_MSG_PACKET)
type = NFLOG;
- else if (NFNL_SUBSYS_ID(nlh->nlmsg_type) == NFNL_SUBSYS_QUEUE &&
+ else if (NFNL_SUBSYS_ID(nlh->nlmsg_type) == NFNL_SUBSYS_QUEUE &&
NFNL_MSG_TYPE(nlh->nlmsg_type) == NFQNL_MSG_PACKET)
type = NFQUEUE;
@@ -127,14 +130,14 @@ netfilter_read_linux(pcap_t *handle, int max_packets, pcap_handler callback, u_c
const unsigned char *payload = NULL;
struct pcap_pkthdr pkth;
- const struct nfgenmsg *nfg;
+ const struct nfgenmsg *nfg = NULL;
int id = 0;
if (handle->linktype != DLT_NFLOG) {
const struct nfattr *payload_attr = NULL;
if (nlh->nlmsg_len < HDR_LENGTH) {
- snprintf(handle->errbuf, PCAP_ERRBUF_SIZE, "Malformed message: (nlmsg_len: %u)", nlh->nlmsg_len);
+ pcap_snprintf(handle->errbuf, PCAP_ERRBUF_SIZE, "Malformed message: (nlmsg_len: %u)", nlh->nlmsg_len);
return -1;
}
@@ -184,7 +187,7 @@ netfilter_read_linux(pcap_t *handle, int max_packets, pcap_handler callback, u_c
gettimeofday(&pkth.ts, NULL);
if (handle->fcode.bf_insns == NULL ||
- bpf_filter(handle->fcode.bf_insns, payload, pkth.len, pkth.caplen))
+ bpf_filter(handle->fcode.bf_insns, payload, pkth.len, pkth.caplen))
{
handlep->packets_read++;
callback(user, &pkth, payload);
@@ -194,13 +197,16 @@ netfilter_read_linux(pcap_t *handle, int max_packets, pcap_handler callback, u_c
if (type == NFQUEUE) {
/* XXX, possible responses: NF_DROP, NF_ACCEPT, NF_STOLEN, NF_QUEUE, NF_REPEAT, NF_STOP */
- nfqueue_send_verdict(handle, ntohs(nfg->res_id), id, NF_ACCEPT);
+ /* if type == NFQUEUE, handle->linktype is always != DLT_NFLOG,
+ so nfg is always initialized to NLMSG_DATA(nlh). */
+ if (nfg != NULL)
+ nfqueue_send_verdict(handle, ntohs(nfg->res_id), id, NF_ACCEPT);
}
}
msg_len = NLMSG_ALIGN(nlh->nlmsg_len);
- if (msg_len > len)
- msg_len = len;
+ if (msg_len > (u_int)len)
+ msg_len = (u_int)len;
len -= msg_len;
buf += msg_len;
@@ -221,7 +227,7 @@ netfilter_stats_linux(pcap_t *handle, struct pcap_stat *stats)
struct pcap_netfilter *handlep = handle->priv;
stats->ps_recv = handlep->packets_read;
- stats->ps_drop = 0;
+ stats->ps_drop = handlep->packets_nobufs;
stats->ps_ifdrop = 0;
return 0;
}
@@ -229,9 +235,9 @@ netfilter_stats_linux(pcap_t *handle, struct pcap_stat *stats)
static int
netfilter_inject_linux(pcap_t *handle, const void *buf, size_t size)
{
- snprintf(handle->errbuf, PCAP_ERRBUF_SIZE, "inject not supported on netfilter devices");
+ pcap_snprintf(handle->errbuf, PCAP_ERRBUF_SIZE, "inject not supported on netfilter devices");
return (-1);
-}
+}
struct my_nfattr {
u_int16_t nfa_len;
@@ -249,7 +255,7 @@ netfilter_send_config_msg(const pcap_t *handle, u_int16_t msg_type, int ack, u_i
struct sockaddr_nl snl;
static unsigned int seq_id;
-
+
if (!seq_id)
seq_id = time(NULL);
++seq_id;
@@ -304,7 +310,7 @@ netfilter_send_config_msg(const pcap_t *handle, u_int16_t msg_type, int ack, u_i
if (snl.nl_pid != 0 || seq_id != nlh->nlmsg_seq) /* if not from kernel or wrong sequence skip */
continue;
- while (len >= NLMSG_SPACE(0) && NLMSG_OK(nlh, len)) {
+ while ((u_int)len >= NLMSG_SPACE(0) && NLMSG_OK(nlh, len)) {
if (nlh->nlmsg_type == NLMSG_ERROR || (nlh->nlmsg_type == NLMSG_DONE && nlh->nlmsg_flags & NLM_F_MULTI)) {
if (nlh->nlmsg_len < NLMSG_ALIGN(sizeof(struct nlmsgerr))) {
errno = EBADMSG;
@@ -341,7 +347,7 @@ nflog_send_config_cmd(const pcap_t *handle, u_int16_t group_id, u_int8_t cmd, u_
return nflog_send_config_msg(handle, family, group_id, &nfa);
}
-static int
+static int
nflog_send_config_mode(const pcap_t *handle, u_int16_t group_id, u_int8_t copy_mode, u_int32_t copy_range)
{
struct nfulnl_msg_config_mode msg;
@@ -395,7 +401,7 @@ nfqueue_send_config_cmd(const pcap_t *handle, u_int16_t group_id, u_int8_t cmd,
return nfqueue_send_config_msg(handle, AF_UNSPEC, group_id, &nfa);
}
-static int
+static int
nfqueue_send_config_mode(const pcap_t *handle, u_int16_t group_id, u_int8_t copy_mode, u_int32_t copy_range)
{
struct nfqnl_msg_config_params msg;
@@ -414,7 +420,7 @@ nfqueue_send_config_mode(const pcap_t *handle, u_int16_t group_id, u_int8_t copy
static int
netfilter_activate(pcap_t* handle)
{
- const char *dev = handle->opt.source;
+ const char *dev = handle->opt.device;
unsigned short groups[32];
int group_count = 0;
nftype_t type = OTHER;
@@ -428,7 +434,7 @@ netfilter_activate(pcap_t* handle)
dev += strlen(NFQUEUE_IFACE);
type = NFQUEUE;
}
-
+
if (type != OTHER && *dev == ':') {
dev++;
while (*dev) {
@@ -436,16 +442,16 @@ netfilter_activate(pcap_t* handle)
char *end_dev;
if (group_count == 32) {
- snprintf(handle->errbuf, PCAP_ERRBUF_SIZE,
- "Maximum 32 netfilter groups! dev: %s",
- handle->opt.source);
+ pcap_snprintf(handle->errbuf, PCAP_ERRBUF_SIZE,
+ "Maximum 32 netfilter groups! dev: %s",
+ handle->opt.device);
return PCAP_ERROR;
}
group_id = strtol(dev, &end_dev, 0);
if (end_dev != dev) {
if (group_id < 0 || group_id > 65535) {
- snprintf(handle->errbuf, PCAP_ERRBUF_SIZE,
+ pcap_snprintf(handle->errbuf, PCAP_ERRBUF_SIZE,
"Netfilter group range from 0 to 65535 (got %ld)",
group_id);
return PCAP_ERROR;
@@ -461,9 +467,9 @@ netfilter_activate(pcap_t* handle)
}
if (type == OTHER || *dev) {
- snprintf(handle->errbuf, PCAP_ERRBUF_SIZE,
- "Can't get netfilter group(s) index from %s",
- handle->opt.source);
+ pcap_snprintf(handle->errbuf, PCAP_ERRBUF_SIZE,
+ "Can't get netfilter group(s) index from %s",
+ handle->opt.device);
return PCAP_ERROR;
}
@@ -488,7 +494,7 @@ netfilter_activate(pcap_t* handle)
/* Create netlink socket */
handle->fd = socket(AF_NETLINK, SOCK_RAW, NETLINK_NETFILTER);
if (handle->fd < 0) {
- snprintf(handle->errbuf, PCAP_ERRBUF_SIZE, "Can't create raw socket %d:%s", errno, pcap_strerror(errno));
+ pcap_snprintf(handle->errbuf, PCAP_ERRBUF_SIZE, "Can't create raw socket %d:%s", errno, pcap_strerror(errno));
return PCAP_ERROR;
}
@@ -506,54 +512,54 @@ netfilter_activate(pcap_t* handle)
handle->buffer = malloc(handle->bufsize);
if (!handle->buffer) {
- snprintf(handle->errbuf, PCAP_ERRBUF_SIZE, "Can't allocate dump buffer: %s", pcap_strerror(errno));
+ pcap_snprintf(handle->errbuf, PCAP_ERRBUF_SIZE, "Can't allocate dump buffer: %s", pcap_strerror(errno));
goto close_fail;
}
if (type == NFLOG) {
if (nflog_send_config_cmd(handle, 0, NFULNL_CFG_CMD_PF_UNBIND, AF_INET) < 0) {
- snprintf(handle->errbuf, PCAP_ERRBUF_SIZE, "NFULNL_CFG_CMD_PF_UNBIND: %s", pcap_strerror(errno));
+ pcap_snprintf(handle->errbuf, PCAP_ERRBUF_SIZE, "NFULNL_CFG_CMD_PF_UNBIND: %s", pcap_strerror(errno));
goto close_fail;
}
if (nflog_send_config_cmd(handle, 0, NFULNL_CFG_CMD_PF_BIND, AF_INET) < 0) {
- snprintf(handle->errbuf, PCAP_ERRBUF_SIZE, "NFULNL_CFG_CMD_PF_BIND: %s", pcap_strerror(errno));
+ pcap_snprintf(handle->errbuf, PCAP_ERRBUF_SIZE, "NFULNL_CFG_CMD_PF_BIND: %s", pcap_strerror(errno));
goto close_fail;
}
/* Bind socket to the nflog groups */
for (i = 0; i < group_count; i++) {
if (nflog_send_config_cmd(handle, groups[i], NFULNL_CFG_CMD_BIND, AF_UNSPEC) < 0) {
- snprintf(handle->errbuf, PCAP_ERRBUF_SIZE, "Can't listen on group group index: %s", pcap_strerror(errno));
+ pcap_snprintf(handle->errbuf, PCAP_ERRBUF_SIZE, "Can't listen on group group index: %s", pcap_strerror(errno));
goto close_fail;
}
if (nflog_send_config_mode(handle, groups[i], NFULNL_COPY_PACKET, handle->snapshot) < 0) {
- snprintf(handle->errbuf, PCAP_ERRBUF_SIZE, "NFULNL_COPY_PACKET: %s", pcap_strerror(errno));
+ pcap_snprintf(handle->errbuf, PCAP_ERRBUF_SIZE, "NFULNL_COPY_PACKET: %s", pcap_strerror(errno));
goto close_fail;
}
}
} else {
if (nfqueue_send_config_cmd(handle, 0, NFQNL_CFG_CMD_PF_UNBIND, AF_INET) < 0) {
- snprintf(handle->errbuf, PCAP_ERRBUF_SIZE, "NFQNL_CFG_CMD_PF_UNBIND: %s", pcap_strerror(errno));
+ pcap_snprintf(handle->errbuf, PCAP_ERRBUF_SIZE, "NFQNL_CFG_CMD_PF_UNBIND: %s", pcap_strerror(errno));
goto close_fail;
}
if (nfqueue_send_config_cmd(handle, 0, NFQNL_CFG_CMD_PF_BIND, AF_INET) < 0) {
- snprintf(handle->errbuf, PCAP_ERRBUF_SIZE, "NFQNL_CFG_CMD_PF_BIND: %s", pcap_strerror(errno));
+ pcap_snprintf(handle->errbuf, PCAP_ERRBUF_SIZE, "NFQNL_CFG_CMD_PF_BIND: %s", pcap_strerror(errno));
goto close_fail;
}
/* Bind socket to the nfqueue groups */
for (i = 0; i < group_count; i++) {
if (nfqueue_send_config_cmd(handle, groups[i], NFQNL_CFG_CMD_BIND, AF_UNSPEC) < 0) {
- snprintf(handle->errbuf, PCAP_ERRBUF_SIZE, "Can't listen on group group index: %s", pcap_strerror(errno));
+ pcap_snprintf(handle->errbuf, PCAP_ERRBUF_SIZE, "Can't listen on group group index: %s", pcap_strerror(errno));
goto close_fail;
}
if (nfqueue_send_config_mode(handle, groups[i], NFQNL_COPY_PACKET, handle->snapshot) < 0) {
- snprintf(handle->errbuf, PCAP_ERRBUF_SIZE, "NFQNL_COPY_PACKET: %s", pcap_strerror(errno));
+ pcap_snprintf(handle->errbuf, PCAP_ERRBUF_SIZE, "NFQNL_COPY_PACKET: %s", pcap_strerror(errno));
goto close_fail;
}
}
@@ -572,7 +578,7 @@ netfilter_activate(pcap_t* handle)
* Set the socket buffer size to the specified value.
*/
if (setsockopt(handle->fd, SOL_SOCKET, SO_RCVBUF, &handle->opt.buffer_size, sizeof(handle->opt.buffer_size)) == -1) {
- snprintf(handle->errbuf, PCAP_ERRBUF_SIZE, "SO_RCVBUF: %s", pcap_strerror(errno));
+ pcap_snprintf(handle->errbuf, PCAP_ERRBUF_SIZE, "SO_RCVBUF: %s", pcap_strerror(errno));
goto close_fail;
}
}
@@ -599,7 +605,7 @@ netfilter_create(const char *device, char *ebuf, int *is_ours)
/* Does it begin with NFLOG_IFACE or NFQUEUE_IFACE? */
if (strncmp(cp, NFLOG_IFACE, sizeof NFLOG_IFACE - 1) == 0)
cp += sizeof NFLOG_IFACE - 1;
- else if (strncmp(cp, NFQUEUE_IFACE, sizeof NFQUEUE_IFACE - 1) == 0)
+ else if (strncmp(cp, NFQUEUE_IFACE, sizeof NFQUEUE_IFACE - 1) == 0)
cp += sizeof NFQUEUE_IFACE - 1;
else {
/* Nope, doesn't begin with NFLOG_IFACE nor NFQUEUE_IFACE */
@@ -620,7 +626,7 @@ netfilter_create(const char *device, char *ebuf, int *is_ours)
/* OK, it's probably ours. */
*is_ours = 1;
- p = pcap_create_common(device, ebuf, sizeof (struct pcap_netfilter));
+ p = pcap_create_common(ebuf, sizeof (struct pcap_netfilter));
if (p == NULL)
return (NULL);
@@ -628,17 +634,17 @@ netfilter_create(const char *device, char *ebuf, int *is_ours)
return (p);
}
-int
+int
netfilter_findalldevs(pcap_if_t **alldevsp, char *err_str)
{
int sock;
-
+
sock = socket(AF_NETLINK, SOCK_RAW, NETLINK_NETFILTER);
if (sock < 0) {
/* if netlink is not supported this is not fatal */
if (errno == EAFNOSUPPORT || errno == EPROTONOSUPPORT)
return 0;
- snprintf(err_str, PCAP_ERRBUF_SIZE, "Can't open netlink socket %d:%s",
+ pcap_snprintf(err_str, PCAP_ERRBUF_SIZE, "Can't open netlink socket %d:%s",
errno, pcap_strerror(errno));
return -1;
}
diff --git a/contrib/libpcap/pcap-netfilter-linux.h b/contrib/libpcap/pcap-netfilter-linux.h
index 882a40219172..01d9b394f5a8 100644
--- a/contrib/libpcap/pcap-netfilter-linux.h
+++ b/contrib/libpcap/pcap-netfilter-linux.h
@@ -11,8 +11,8 @@
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
- * 3. The name of the author may not be used to endorse or promote
- * products derived from this software without specific prior written
+ * 3. The name of the author may not be used to endorse or promote
+ * products derived from this software without specific prior written
* permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
diff --git a/contrib/libpcap/pcap-new.c b/contrib/libpcap/pcap-new.c
new file mode 100644
index 000000000000..494e425f8bb1
--- /dev/null
+++ b/contrib/libpcap/pcap-new.c
@@ -0,0 +1,1265 @@
+/*
+ * Copyright (c) 2002 - 2005 NetGroup, Politecnico di Torino (Italy)
+ * Copyright (c) 2005 - 2008 CACE Technologies, Davis (California)
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the Politecnico di Torino, CACE Technologies
+ * nor the names of its contributors may be used to endorse or promote
+ * products derived from this software without specific prior written
+ * permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include "pcap-int.h" // for the details of the pcap_t structure
+#include "pcap-rpcap.h"
+#include "sockutils.h"
+#include <errno.h> // for the errno variable
+#include <stdlib.h> // for malloc(), free(), ...
+#include <string.h> // for strstr, etc
+
+#ifndef WIN32
+#include <dirent.h> // for readdir
+#endif
+
+/* Keeps a list of all the opened connections in the active mode. */
+extern struct activehosts *activeHosts;
+
+/*
+ * \brief Keeps the main socket identifier when we want to accept a new remote connection (active mode only).
+ * See the documentation of pcap_remoteact_accept() and pcap_remoteact_cleanup() for more details.
+ */
+SOCKET sockmain;
+
+/* String identifier to be used in the pcap_findalldevs_ex() */
+#define PCAP_TEXT_SOURCE_FILE "File"
+/* String identifier to be used in the pcap_findalldevs_ex() */
+#define PCAP_TEXT_SOURCE_ADAPTER "Network adapter"
+
+/* String identifier to be used in the pcap_findalldevs_ex() */
+#define PCAP_TEXT_SOURCE_ON_LOCAL_HOST "on local host"
+/* String identifier to be used in the pcap_findalldevs_ex() */
+#define PCAP_TEXT_SOURCE_ON_REMOTE_HOST "on remote node"
+
+/*
+* Private data for capturing on WinPcap devices.
+*/
+struct pcap_win {
+ int nonblock;
+ int rfmon_selfstart; /* a flag tells whether the monitor mode is set by itself */
+ int filtering_in_kernel; /* using kernel filter */
+
+#ifdef HAVE_DAG_API
+ int dag_fcs_bits; /* Number of checksum bits from link layer */
+#endif
+};
+
+/****************************************************
+ * *
+ * Function bodies *
+ * *
+ ****************************************************/
+
+int pcap_findalldevs_ex(char *source, struct pcap_rmtauth *auth, pcap_if_t **alldevs, char *errbuf)
+{
+ SOCKET sockctrl; /* socket descriptor of the control connection */
+ uint32 totread = 0; /* number of bytes of the payload read from the socket */
+ int nread;
+ struct addrinfo hints; /* temp variable needed to resolve hostnames into to socket representation */
+ struct addrinfo *addrinfo; /* temp variable needed to resolve hostnames into to socket representation */
+ struct rpcap_header header; /* structure that keeps the general header of the rpcap protocol */
+ int i, j; /* temp variables */
+ int naddr; /* temp var needed to avoid problems with IPv6 addresses */
+ struct pcap_addr *addr; /* another such temp */
+ int retval; /* store the return value of the functions */
+ int nif; /* Number of interfaces listed */
+ int active = 0; /* 'true' if we the other end-party is in active mode */
+ char host[PCAP_BUF_SIZE], port[PCAP_BUF_SIZE], name[PCAP_BUF_SIZE], path[PCAP_BUF_SIZE], filename[PCAP_BUF_SIZE];
+ int type;
+ pcap_t *fp;
+ char tmpstring[PCAP_BUF_SIZE + 1]; /* Needed to convert names and descriptions from 'old' syntax to the 'new' one */
+ pcap_if_t *dev; /* Previous device into the pcap_if_t chain */
+
+
+ if (strlen(source) > PCAP_BUF_SIZE)
+ {
+ pcap_snprintf(errbuf, PCAP_ERRBUF_SIZE, "The source string is too long. Cannot handle it correctly.");
+ return -1;
+ }
+
+ /*
+ * Determine the type of the source (file, local, remote)
+ * There are some differences if pcap_findalldevs_ex() is called to list files and remote adapters.
+ * In the first case, the name of the directory we have to look into must be present (therefore
+ * the 'name' parameter of the pcap_parsesrcstr() is present).
+ * In the second case, the name of the adapter is not required (we need just the host). So, we have
+ * to use a first time this function to get the source type, and a second time to get the appropriate
+ * info, which depends on the source type.
+ */
+ if (pcap_parsesrcstr(source, &type, NULL, NULL, NULL, errbuf) == -1)
+ return -1;
+
+ if (type == PCAP_SRC_IFLOCAL)
+ {
+ if (pcap_parsesrcstr(source, &type, host, NULL, NULL, errbuf) == -1)
+ return -1;
+
+ /* Initialize temporary string */
+ tmpstring[PCAP_BUF_SIZE] = 0;
+
+ /* The user wants to retrieve adapters from a local host */
+ if (pcap_findalldevs(alldevs, errbuf) == -1)
+ return -1;
+
+ if ((alldevs == NULL) || (*alldevs == NULL))
+ {
+ pcap_snprintf(errbuf, PCAP_ERRBUF_SIZE,
+ "No interfaces found! Make sure libpcap/WinPcap is properly installed"
+ " on the local machine.");
+ return -1;
+ }
+
+ /* Scan all the interfaces and modify name and description */
+ /* This is a trick in order to avoid the re-implementation of the pcap_findalldevs here */
+ dev = *alldevs;
+ while (dev)
+ {
+ /* Create the new device identifier */
+ if (pcap_createsrcstr(tmpstring, PCAP_SRC_IFLOCAL, NULL, NULL, dev->name, errbuf) == -1)
+ return -1;
+
+ /* Delete the old pointer */
+ free(dev->name);
+
+ /* Make a copy of the new device identifier */
+ dev->name = strdup(tmpstring);
+ if (dev->name == NULL)
+ {
+ pcap_snprintf(errbuf, PCAP_ERRBUF_SIZE, "malloc() failed: %s", pcap_strerror(errno));
+ return -1;
+ }
+
+ /* Create the new device description */
+ if ((dev->description == NULL) || (dev->description[0] == 0))
+ pcap_snprintf(tmpstring, sizeof(tmpstring) - 1, "%s '%s' %s", PCAP_TEXT_SOURCE_ADAPTER,
+ dev->name, PCAP_TEXT_SOURCE_ON_LOCAL_HOST);
+ else
+ pcap_snprintf(tmpstring, sizeof(tmpstring) - 1, "%s '%s' %s", PCAP_TEXT_SOURCE_ADAPTER,
+ dev->description, PCAP_TEXT_SOURCE_ON_LOCAL_HOST);
+
+ /* Delete the old pointer */
+ free(dev->description);
+
+ /* Make a copy of the description */
+ dev->description = strdup(tmpstring);
+ if (dev->description == NULL)
+ {
+ pcap_snprintf(errbuf, PCAP_ERRBUF_SIZE, "malloc() failed: %s", pcap_strerror(errno));
+ return -1;
+ }
+
+ dev = dev->next;
+ }
+
+ return 0;
+ }
+
+ (*alldevs) = NULL;
+
+ if (type == PCAP_SRC_FILE)
+ {
+ size_t stringlen;
+#ifdef WIN32
+ WIN32_FIND_DATA filedata;
+ HANDLE filehandle;
+#else
+ struct dirent *filedata;
+ DIR *unixdir;
+#endif
+
+ if (pcap_parsesrcstr(source, &type, host, port, name, errbuf) == -1)
+ return -1;
+
+ /* Check that the filename is correct */
+ stringlen = strlen(name);
+
+ /* The directory must end with '\' in Win32 and '/' in UNIX */
+#ifdef WIN32
+#define ENDING_CHAR '\\'
+#else
+#define ENDING_CHAR '/'
+#endif
+
+ if (name[stringlen - 1] != ENDING_CHAR)
+ {
+ name[stringlen] = ENDING_CHAR;
+ name[stringlen + 1] = 0;
+
+ stringlen++;
+ }
+
+ /* Save the path for future reference */
+ pcap_snprintf(path, sizeof(path), "%s", name);
+
+#ifdef WIN32
+ /* To perform directory listing, Win32 must have an 'asterisk' as ending char */
+ if (name[stringlen - 1] != '*')
+ {
+ name[stringlen] = '*';
+ name[stringlen + 1] = 0;
+ }
+
+ filehandle = FindFirstFile(name, &filedata);
+
+ if (filehandle == INVALID_HANDLE_VALUE)
+ {
+ pcap_snprintf(errbuf, PCAP_ERRBUF_SIZE, "Error when listing files: does folder '%s' exist?", path);
+ return -1;
+ }
+
+#else
+ /* opening the folder */
+ unixdir= opendir(path);
+
+ /* get the first file into it */
+ filedata= readdir(unixdir);
+
+ if (filedata == NULL)
+ {
+ pcap_snprintf(errbuf, PCAP_ERRBUF_SIZE, "Error when listing files: does folder '%s' exist?", path);
+ return -1;
+ }
+#endif
+
+ do
+ {
+
+#ifdef WIN32
+ pcap_snprintf(filename, sizeof(filename), "%s%s", path, filedata.cFileName);
+#else
+ pcap_snprintf(filename, sizeof(filename), "%s%s", path, filedata->d_name);
+#endif
+
+ fp = pcap_open_offline(filename, errbuf);
+
+ if (fp)
+ {
+ /* allocate the main structure */
+ if (*alldevs == NULL) /* This is in case it is the first file */
+ {
+ (*alldevs) = (pcap_if_t *)malloc(sizeof(pcap_if_t));
+ dev = (*alldevs);
+ }
+ else
+ {
+ dev->next = (pcap_if_t *)malloc(sizeof(pcap_if_t));
+ dev = dev->next;
+ }
+
+ /* check that the malloc() didn't fail */
+ if (dev == NULL)
+ {
+ pcap_snprintf(errbuf, PCAP_ERRBUF_SIZE, "malloc() failed: %s", pcap_strerror(errno));
+ return -1;
+ }
+
+ /* Initialize the structure to 'zero' */
+ memset(dev, 0, sizeof(pcap_if_t));
+
+ /* Create the new source identifier */
+ if (pcap_createsrcstr(tmpstring, PCAP_SRC_FILE, NULL, NULL, filename, errbuf) == -1)
+ return -1;
+
+ stringlen = strlen(tmpstring);
+
+ dev->name = (char *)malloc(stringlen + 1);
+ if (dev->name == NULL)
+ {
+ pcap_snprintf(errbuf, PCAP_ERRBUF_SIZE, "malloc() failed: %s", pcap_strerror(errno));
+ return -1;
+ }
+
+ strlcpy(dev->name, tmpstring, stringlen);
+
+ dev->name[stringlen] = 0;
+
+ /* Create the description */
+ pcap_snprintf(tmpstring, sizeof(tmpstring) - 1, "%s '%s' %s", PCAP_TEXT_SOURCE_FILE,
+ filename, PCAP_TEXT_SOURCE_ON_LOCAL_HOST);
+
+ stringlen = strlen(tmpstring);
+
+ dev->description = (char *)malloc(stringlen + 1);
+
+ if (dev->description == NULL)
+ {
+ pcap_snprintf(errbuf, PCAP_ERRBUF_SIZE, "malloc() failed: %s", pcap_strerror(errno));
+ return -1;
+ }
+
+ /* Copy the new device description into the correct memory location */
+ strlcpy(dev->description, tmpstring, stringlen + 1);
+
+ pcap_close(fp);
+ }
+ }
+#ifdef WIN32
+ while (FindNextFile(filehandle, &filedata) != 0);
+#else
+ while ( (filedata= readdir(unixdir)) != NULL);
+#endif
+
+
+#ifdef WIN32
+ /* Close the search handle. */
+ FindClose(filehandle);
+#endif
+
+ return 0;
+ }
+
+ /* If we come here, it is a remote host */
+
+ /* Retrieve the needed data for getting adapter list */
+ if (pcap_parsesrcstr(source, &type, host, port, NULL, errbuf) == -1)
+ return -1;
+
+ /* Warning: this call can be the first one called by the user. */
+ /* For this reason, we have to initialize the WinSock support. */
+ if (sock_init(errbuf, PCAP_ERRBUF_SIZE) == -1)
+ return -1;
+
+ /* Check for active mode */
+ sockctrl = rpcap_remoteact_getsock(host, &active, errbuf);
+ if (sockctrl == INVALID_SOCKET)
+ return -1;
+
+ if (!active) {
+ /*
+ * We're not in active mode; let's try to open a new
+ * control connection.
+ */
+ addrinfo = NULL;
+
+ memset(&hints, 0, sizeof(struct addrinfo));
+ hints.ai_family = PF_UNSPEC;
+ hints.ai_socktype = SOCK_STREAM;
+
+ if (port[0] == 0)
+ {
+ /* the user chose not to specify the port */
+ if (sock_initaddress(host, RPCAP_DEFAULT_NETPORT, &hints, &addrinfo, errbuf, PCAP_ERRBUF_SIZE) == -1)
+ return -1;
+ }
+ else
+ {
+ if (sock_initaddress(host, port, &hints, &addrinfo, errbuf, PCAP_ERRBUF_SIZE) == -1)
+ return -1;
+ }
+
+ if ((sockctrl = sock_open(addrinfo, SOCKOPEN_CLIENT, 0, errbuf, PCAP_ERRBUF_SIZE)) == -1)
+ goto error;
+
+ /* addrinfo is no longer used */
+ freeaddrinfo(addrinfo);
+ addrinfo = NULL;
+
+ if (rpcap_sendauth(sockctrl, auth, errbuf) == -1)
+ {
+ sock_close(sockctrl, NULL, 0);
+ return -1;
+ }
+ }
+
+ /* RPCAP findalldevs command */
+ rpcap_createhdr(&header, RPCAP_MSG_FINDALLIF_REQ, 0, 0);
+
+ if (sock_send(sockctrl, (char *)&header, sizeof(struct rpcap_header), errbuf, PCAP_ERRBUF_SIZE) == -1)
+ goto error;
+
+ if (sock_recv(sockctrl, (char *)&header, sizeof(struct rpcap_header), SOCK_RECEIVEALL_YES, errbuf, PCAP_ERRBUF_SIZE) == -1)
+ goto error;
+
+ /* Checks if the message is correct */
+ retval = rpcap_checkmsg(errbuf, sockctrl, &header, RPCAP_MSG_FINDALLIF_REPLY, RPCAP_MSG_ERROR, 0);
+
+ if (retval != RPCAP_MSG_FINDALLIF_REPLY) /* the message is not the one expected */
+ {
+ switch (retval)
+ {
+ case -3: /* Unrecoverable network error */
+ case -2: /* The other endpoint send a message that is not allowed here */
+ case -1: /* The other endpoint has a version number that is not compatible with our */
+ break;
+
+ case RPCAP_MSG_ERROR: /* The other endpoint reported an error */
+ break;
+
+ default:
+ {
+ pcap_snprintf(errbuf, PCAP_ERRBUF_SIZE, "Internal error");
+ break;
+ };
+ }
+
+ if (!active)
+ sock_close(sockctrl, NULL, 0);
+
+ return -1;
+ }
+
+ /* read the number of interfaces */
+ nif = ntohs(header.value);
+
+ /* loop until all interfaces have been received */
+ for (i = 0; i < nif; i++)
+ {
+ struct rpcap_findalldevs_if findalldevs_if;
+ char tmpstring2[PCAP_BUF_SIZE + 1]; /* Needed to convert names and descriptions from 'old' syntax to the 'new' one */
+ size_t stringlen;
+
+ tmpstring2[PCAP_BUF_SIZE] = 0;
+
+ /* receive the findalldevs structure from remote host */
+ nread = sock_recv(sockctrl, (char *)&findalldevs_if,
+ sizeof(struct rpcap_findalldevs_if), SOCK_RECEIVEALL_YES,
+ errbuf, PCAP_ERRBUF_SIZE);
+ if (nread == -1)
+ goto error;
+ totread += nread;
+
+ findalldevs_if.namelen = ntohs(findalldevs_if.namelen);
+ findalldevs_if.desclen = ntohs(findalldevs_if.desclen);
+ findalldevs_if.naddr = ntohs(findalldevs_if.naddr);
+
+ /* allocate the main structure */
+ if (i == 0)
+ {
+ (*alldevs) = (pcap_if_t *)malloc(sizeof(pcap_if_t));
+ dev = (*alldevs);
+ }
+ else
+ {
+ dev->next = (pcap_if_t *)malloc(sizeof(pcap_if_t));
+ dev = dev->next;
+ }
+
+ /* check that the malloc() didn't fail */
+ if (dev == NULL)
+ {
+ pcap_snprintf(errbuf, PCAP_ERRBUF_SIZE, "malloc() failed: %s", pcap_strerror(errno));
+ goto error;
+ }
+
+ /* Initialize the structure to 'zero' */
+ memset(dev, 0, sizeof(pcap_if_t));
+
+ /* allocate mem for name and description */
+ if (findalldevs_if.namelen)
+ {
+
+ if (findalldevs_if.namelen >= sizeof(tmpstring))
+ {
+ pcap_snprintf(errbuf, PCAP_ERRBUF_SIZE, "Interface name too long");
+ goto error;
+ }
+
+ /* Retrieve adapter name */
+ nread = sock_recv(sockctrl, tmpstring,
+ findalldevs_if.namelen, SOCK_RECEIVEALL_YES,
+ errbuf, PCAP_ERRBUF_SIZE);
+ if (nread == -1)
+ goto error;
+ totread += nread;
+
+ tmpstring[findalldevs_if.namelen] = 0;
+
+ /* Create the new device identifier */
+ if (pcap_createsrcstr(tmpstring2, PCAP_SRC_IFREMOTE, host, port, tmpstring, errbuf) == -1)
+ return -1;
+
+ stringlen = strlen(tmpstring2);
+
+ dev->name = (char *)malloc(stringlen + 1);
+ if (dev->name == NULL)
+ {
+ pcap_snprintf(errbuf, PCAP_ERRBUF_SIZE, "malloc() failed: %s", pcap_strerror(errno));
+ goto error;
+ }
+
+ /* Copy the new device name into the correct memory location */
+ strlcpy(dev->name, tmpstring2, stringlen + 1);
+ }
+
+ if (findalldevs_if.desclen)
+ {
+ if (findalldevs_if.desclen >= sizeof(tmpstring))
+ {
+ pcap_snprintf(errbuf, PCAP_ERRBUF_SIZE, "Interface description too long");
+ goto error;
+ }
+
+ /* Retrieve adapter description */
+ nread = sock_recv(sockctrl, tmpstring,
+ findalldevs_if.desclen, SOCK_RECEIVEALL_YES,
+ errbuf, PCAP_ERRBUF_SIZE);
+ if (nread == -1)
+ goto error;
+ totread += nread;
+
+ tmpstring[findalldevs_if.desclen] = 0;
+
+ pcap_snprintf(tmpstring2, sizeof(tmpstring2) - 1, "%s '%s' %s %s", PCAP_TEXT_SOURCE_ADAPTER,
+ tmpstring, PCAP_TEXT_SOURCE_ON_REMOTE_HOST, host);
+
+ stringlen = strlen(tmpstring2);
+
+ dev->description = (char *)malloc(stringlen + 1);
+
+ if (dev->description == NULL)
+ {
+ pcap_snprintf(errbuf, PCAP_ERRBUF_SIZE, "malloc() failed: %s", pcap_strerror(errno));
+ goto error;
+ }
+
+ /* Copy the new device description into the correct memory location */
+ strlcpy(dev->description, tmpstring2, stringlen + 1);
+ }
+
+ dev->flags = ntohl(findalldevs_if.flags);
+
+ naddr = 0;
+ addr = NULL;
+ /* loop until all addresses have been received */
+ for (j = 0; j < findalldevs_if.naddr; j++)
+ {
+ struct rpcap_findalldevs_ifaddr ifaddr;
+
+ /* Retrieve the interface addresses */
+ nread = sock_recv(sockctrl, (char *)&ifaddr,
+ sizeof(struct rpcap_findalldevs_ifaddr),
+ SOCK_RECEIVEALL_YES, errbuf, PCAP_ERRBUF_SIZE);
+ if (nread == -1)
+ goto error;
+ totread += nread;
+
+ /*
+ * WARNING libpcap bug: the address listing is
+ * available only for AF_INET.
+ *
+ * XXX - IPv6?
+ */
+ if (ntohs(ifaddr.addr.ss_family) == AF_INET)
+ {
+ if (addr == NULL)
+ {
+ dev->addresses = (struct pcap_addr *) malloc(sizeof(struct pcap_addr));
+ addr = dev->addresses;
+ }
+ else
+ {
+ addr->next = (struct pcap_addr *) malloc(sizeof(struct pcap_addr));
+ addr = addr->next;
+ }
+ naddr++;
+
+ if (addr == NULL)
+ {
+ pcap_snprintf(errbuf, PCAP_ERRBUF_SIZE, "malloc() failed: %s", pcap_strerror(errno));
+ goto error;
+ }
+ addr->next = NULL;
+
+ if (rpcap_deseraddr((struct sockaddr_storage *) &ifaddr.addr,
+ (struct sockaddr_storage **) &addr->addr, errbuf) == -1)
+ goto error;
+ if (rpcap_deseraddr((struct sockaddr_storage *) &ifaddr.netmask,
+ (struct sockaddr_storage **) &addr->netmask, errbuf) == -1)
+ goto error;
+ if (rpcap_deseraddr((struct sockaddr_storage *) &ifaddr.broadaddr,
+ (struct sockaddr_storage **) &addr->broadaddr, errbuf) == -1)
+ goto error;
+ if (rpcap_deseraddr((struct sockaddr_storage *) &ifaddr.dstaddr,
+ (struct sockaddr_storage **) &addr->dstaddr, errbuf) == -1)
+ goto error;
+
+ if ((addr->addr == NULL) && (addr->netmask == NULL) &&
+ (addr->broadaddr == NULL) && (addr->dstaddr == NULL))
+ {
+ free(addr);
+ addr = NULL;
+ if (naddr == 1)
+ naddr = 0; /* the first item of the list had NULL addresses */
+ }
+ }
+ }
+ }
+
+ /* Checks if all the data has been read; if not, discard the data in excess */
+ if (totread != ntohl(header.plen))
+ {
+ if (sock_discard(sockctrl, ntohl(header.plen) - totread, errbuf, PCAP_ERRBUF_SIZE) == 1)
+ return -1;
+ }
+
+ /* Control connection has to be closed only in case the remote machine is in passive mode */
+ if (!active)
+ {
+ /* DO not send RPCAP_CLOSE, since we did not open a pcap_t; no need to free resources */
+ if (sock_close(sockctrl, errbuf, PCAP_ERRBUF_SIZE))
+ return -1;
+ }
+
+ /* To avoid inconsistencies in the number of sock_init() */
+ sock_cleanup();
+
+ return 0;
+
+error:
+ /*
+ * In case there has been an error, I don't want to overwrite it with a new one
+ * if the following call fails. I want to return always the original error.
+ *
+ * Take care: this connection can already be closed when we try to close it.
+ * This happens because a previous error in the rpcapd, which requested to
+ * closed the connection. In that case, we already recognized that into the
+ * rpspck_isheaderok() and we already acknowledged the closing.
+ * In that sense, this call is useless here (however it is needed in case
+ * the client generates the error).
+ *
+ * Checks if all the data has been read; if not, discard the data in excess
+ */
+ if (totread != ntohl(header.plen))
+ {
+ if (sock_discard(sockctrl, ntohl(header.plen) - totread, NULL, 0) == 1)
+ return -1;
+ }
+
+ /* Control connection has to be closed only in case the remote machine is in passive mode */
+ if (!active)
+ sock_close(sockctrl, NULL, 0);
+
+ /* To avoid inconsistencies in the number of sock_init() */
+ sock_cleanup();
+
+ return -1;
+}
+
+int pcap_createsrcstr(char *source, int type, const char *host, const char *port, const char *name, char *errbuf)
+{
+ switch (type)
+ {
+ case PCAP_SRC_FILE:
+ {
+ strlcpy(source, PCAP_SRC_FILE_STRING, PCAP_BUF_SIZE);
+ if ((name) && (*name))
+ {
+ strlcat(source, name, PCAP_BUF_SIZE);
+ return 0;
+ }
+ else
+ {
+ pcap_snprintf(errbuf, PCAP_ERRBUF_SIZE, "The file name cannot be NULL.");
+ return -1;
+ }
+ }
+
+ case PCAP_SRC_IFREMOTE:
+ {
+ strlcpy(source, PCAP_SRC_IF_STRING, PCAP_BUF_SIZE);
+ if ((host) && (*host))
+ {
+ if ((strcspn(host, "aAbBcCdDeEfFgGhHjJkKlLmMnNoOpPqQrRsStTuUvVwWxXyYzZ")) == strlen(host))
+ {
+ /* the host name does not contains alphabetic chars. So, it is a numeric address */
+ /* In this case we have to include it between square brackets */
+ strlcat(source, "[", PCAP_BUF_SIZE);
+ strlcat(source, host, PCAP_BUF_SIZE);
+ strlcat(source, "]", PCAP_BUF_SIZE);
+ }
+ else
+ strlcat(source, host, PCAP_BUF_SIZE);
+
+ if ((port) && (*port))
+ {
+ strlcat(source, ":", PCAP_BUF_SIZE);
+ strlcat(source, port, PCAP_BUF_SIZE);
+ }
+
+ strlcat(source, "/", PCAP_BUF_SIZE);
+ }
+ else
+ {
+ pcap_snprintf(errbuf, PCAP_ERRBUF_SIZE, "The host name cannot be NULL.");
+ return -1;
+ }
+
+ if ((name) && (*name))
+ strlcat(source, name, PCAP_BUF_SIZE);
+
+ return 0;
+ }
+
+ case PCAP_SRC_IFLOCAL:
+ {
+ strlcpy(source, PCAP_SRC_IF_STRING, PCAP_BUF_SIZE);
+
+ if ((name) && (*name))
+ strlcat(source, name, PCAP_BUF_SIZE);
+
+ return 0;
+ }
+
+ default:
+ {
+ pcap_snprintf(errbuf, PCAP_ERRBUF_SIZE, "The interface type is not valid.");
+ return -1;
+ }
+ }
+}
+
+int pcap_parsesrcstr(const char *source, int *type, char *host, char *port, char *name, char *errbuf)
+{
+ char *ptr;
+ int ntoken;
+ char tmpname[PCAP_BUF_SIZE];
+ char tmphost[PCAP_BUF_SIZE];
+ char tmpport[PCAP_BUF_SIZE];
+ int tmptype;
+
+ /* Initialization stuff */
+ tmpname[0] = 0;
+ tmphost[0] = 0;
+ tmpport[0] = 0;
+
+ if (host)
+ *host = 0;
+ if (port)
+ *port = 0;
+ if (name)
+ *name = 0;
+
+ /* Look for a 'rpcap://' identifier */
+ if ((ptr = strstr(source, PCAP_SRC_IF_STRING)) != NULL)
+ {
+ if (strlen(PCAP_SRC_IF_STRING) == strlen(source))
+ {
+ /* The source identifier contains only the 'rpcap://' string. */
+ /* So, this is a local capture. */
+ *type = PCAP_SRC_IFLOCAL;
+ return 0;
+ }
+
+ ptr += strlen(PCAP_SRC_IF_STRING);
+
+ if (strchr(ptr, '[')) /* This is probably a numeric address */
+ {
+ ntoken = sscanf(ptr, "[%[1234567890:.]]:%[^/]/%s", tmphost, tmpport, tmpname);
+
+ if (ntoken == 1) /* probably the port is missing */
+ ntoken = sscanf(ptr, "[%[1234567890:.]]/%s", tmphost, tmpname);
+
+ tmptype = PCAP_SRC_IFREMOTE;
+ }
+ else
+ {
+ ntoken = sscanf(ptr, "%[^/:]:%[^/]/%s", tmphost, tmpport, tmpname);
+
+ if (ntoken == 1)
+ {
+ /*
+ * This can be due to two reasons:
+ * - we want a remote capture, but the network port is missing
+ * - we want to do a local capture
+ * To distinguish between the two, we look for the '/' char
+ */
+ if (strchr(ptr, '/'))
+ {
+ /* We're on a remote capture */
+ sscanf(ptr, "%[^/]/%s", tmphost, tmpname);
+ tmptype = PCAP_SRC_IFREMOTE;
+ }
+ else
+ {
+ /* We're on a local capture */
+ if (*ptr)
+ strlcpy(tmpname, ptr, PCAP_BUF_SIZE);
+
+ /* Clean the host name, since it is a remote capture */
+ /* NOTE: the host name has been assigned in the previous "ntoken= sscanf(...)" line */
+ tmphost[0] = 0;
+
+ tmptype = PCAP_SRC_IFLOCAL;
+ }
+ }
+ else
+ tmptype = PCAP_SRC_IFREMOTE;
+ }
+
+ if (host)
+ strlcpy(host, tmphost, PCAP_BUF_SIZE);
+ if (port)
+ strlcpy(port, tmpport, PCAP_BUF_SIZE);
+ if (type)
+ *type = tmptype;
+
+ if (name)
+ {
+ /*
+ * If the user wants the host name, but it cannot be located into the source string, return error
+ * However, if the user is not interested in the interface name (e.g. if we're called by
+ * pcap_findalldevs_ex(), which does not have interface name, do not return error
+ */
+ if (tmpname[0])
+ {
+ strlcpy(name, tmpname, PCAP_BUF_SIZE);
+ }
+ else
+ {
+ if (errbuf)
+ pcap_snprintf(errbuf, PCAP_ERRBUF_SIZE, "The interface name has not been specified in the source string.");
+
+ return -1;
+ }
+ }
+
+ return 0;
+ }
+
+ /* Look for a 'file://' identifier */
+ if ((ptr = strstr(source, PCAP_SRC_FILE_STRING)) != NULL)
+ {
+ ptr += strlen(PCAP_SRC_FILE_STRING);
+ if (*ptr)
+ {
+ if (name)
+ strlcpy(name, ptr, PCAP_BUF_SIZE);
+
+ if (type)
+ *type = PCAP_SRC_FILE;
+
+ return 0;
+ }
+ else
+ {
+ if (errbuf)
+ pcap_snprintf(errbuf, PCAP_ERRBUF_SIZE, "The file name has not been specified in the source string.");
+
+ return -1;
+ }
+
+ }
+
+ /* Backward compatibility; the user didn't use the 'rpcap://, file://' specifiers */
+ if ((source) && (*source))
+ {
+ if (name)
+ strlcpy(name, source, PCAP_BUF_SIZE);
+
+ if (type)
+ *type = PCAP_SRC_IFLOCAL;
+
+ return 0;
+ }
+ else
+ {
+ if (errbuf)
+ pcap_snprintf(errbuf, PCAP_ERRBUF_SIZE, "The interface name has not been specified in the source string.");
+
+ return -1;
+ }
+};
+
+pcap_t *pcap_open(const char *source, int snaplen, int flags, int read_timeout, struct pcap_rmtauth *auth, char *errbuf)
+{
+ char host[PCAP_BUF_SIZE], port[PCAP_BUF_SIZE], name[PCAP_BUF_SIZE];
+ int type;
+ pcap_t *fp;
+ int result;
+
+ if (strlen(source) > PCAP_BUF_SIZE)
+ {
+ pcap_snprintf(errbuf, PCAP_ERRBUF_SIZE, "The source string is too long. Cannot handle it correctly.");
+ return NULL;
+ }
+
+ /* determine the type of the source (file, local, remote) */
+ if (pcap_parsesrcstr(source, &type, host, port, name, errbuf) == -1)
+ return NULL;
+
+
+ switch (type)
+ {
+ case PCAP_SRC_FILE:
+ fp = pcap_open_offline(name, errbuf);
+ break;
+
+ case PCAP_SRC_IFREMOTE:
+ fp = pcap_create(source, errbuf);
+ if (fp == NULL)
+ {
+ return NULL;
+ }
+
+ /*
+ * Although we already have host, port and iface, we prefer TO PASS only 'pars' to the
+ * pcap_open_remote() so that it has to call the pcap_parsesrcstr() again.
+ * This is less optimized, but much clearer.
+ */
+
+ result = pcap_opensource_remote(fp, auth);
+
+ if (result != 0)
+ {
+ pcap_close(fp);
+ return NULL;
+ }
+
+ struct pcap_md *md; /* structure used when doing a remote live capture */
+ md = (struct pcap_md *) ((u_char*)fp->priv + sizeof(struct pcap_win));
+
+ fp->snapshot = snaplen;
+ fp->opt.timeout = read_timeout;
+ md->rmt_flags = flags;
+ break;
+
+ case PCAP_SRC_IFLOCAL:
+
+ fp = pcap_open_live(name, snaplen, (flags & PCAP_OPENFLAG_PROMISCUOUS), read_timeout, errbuf);
+
+#ifdef WIN32
+ /*
+ * these flags are supported on Windows only
+ */
+ if (fp != NULL && fp->adapter != NULL)
+ {
+ /* disable loopback capture if requested */
+ if (flags & PCAP_OPENFLAG_NOCAPTURE_LOCAL)
+ {
+ if (!PacketSetLoopbackBehavior(fp->adapter, NPF_DISABLE_LOOPBACK))
+ {
+ pcap_snprintf(errbuf, PCAP_ERRBUF_SIZE, "Unable to disable the capture of loopback packets.");
+ pcap_close(fp);
+ return NULL;
+ }
+ }
+
+ /* set mintocopy to zero if requested */
+ if (flags & PCAP_OPENFLAG_MAX_RESPONSIVENESS)
+ {
+ if (!PacketSetMinToCopy(fp->adapter, 0))
+ {
+ pcap_snprintf(errbuf, PCAP_ERRBUF_SIZE, "Unable to set max responsiveness.");
+ pcap_close(fp);
+ return NULL;
+ }
+ }
+ }
+#endif /* WIN32 */
+
+ break;
+
+ default:
+ strlcpy(errbuf, "Source type not supported", PCAP_ERRBUF_SIZE);
+ return NULL;
+ }
+ return fp;
+}
+
+struct pcap_samp *pcap_setsampling(pcap_t *p)
+{
+ struct pcap_md *md; /* structure used when doing a remote live capture */
+
+ md = (struct pcap_md *) ((u_char*)p->priv + sizeof(struct pcap_win));
+ return &(md->rmt_samp);
+}
+
+SOCKET pcap_remoteact_accept(const char *address, const char *port, const char *hostlist, char *connectinghost, struct pcap_rmtauth *auth, char *errbuf)
+{
+ /* socket-related variables */
+ struct addrinfo hints; /* temporary struct to keep settings needed to open the new socket */
+ struct addrinfo *addrinfo; /* keeps the addrinfo chain; required to open a new socket */
+ struct sockaddr_storage from; /* generic sockaddr_storage variable */
+ socklen_t fromlen; /* keeps the length of the sockaddr_storage variable */
+ SOCKET sockctrl; /* keeps the main socket identifier */
+ struct activehosts *temp, *prev; /* temp var needed to scan he host list chain */
+
+ *connectinghost = 0; /* just in case */
+
+ /* Prepare to open a new server socket */
+ memset(&hints, 0, sizeof(struct addrinfo));
+ /* WARNING Currently it supports only ONE socket family among ipv4 and IPv6 */
+ hints.ai_family = AF_INET; /* PF_UNSPEC to have both IPv4 and IPv6 server */
+ hints.ai_flags = AI_PASSIVE; /* Ready to a bind() socket */
+ hints.ai_socktype = SOCK_STREAM;
+
+ /* Warning: this call can be the first one called by the user. */
+ /* For this reason, we have to initialize the WinSock support. */
+ if (sock_init(errbuf, PCAP_ERRBUF_SIZE) == -1)
+ return -1;
+
+ /* Do the work */
+ if ((port == NULL) || (port[0] == 0))
+ {
+ if (sock_initaddress(address, RPCAP_DEFAULT_NETPORT_ACTIVE, &hints, &addrinfo, errbuf, PCAP_ERRBUF_SIZE) == -1)
+ {
+ SOCK_ASSERT(errbuf, 1);
+ return -2;
+ }
+ }
+ else
+ {
+ if (sock_initaddress(address, port, &hints, &addrinfo, errbuf, PCAP_ERRBUF_SIZE) == -1)
+ {
+ SOCK_ASSERT(errbuf, 1);
+ return -2;
+ }
+ }
+
+
+ if ((sockmain = sock_open(addrinfo, SOCKOPEN_SERVER, 1, errbuf, PCAP_ERRBUF_SIZE)) == -1)
+ {
+ SOCK_ASSERT(errbuf, 1);
+ return -2;
+ }
+
+ /* Connection creation */
+ fromlen = sizeof(struct sockaddr_storage);
+
+ sockctrl = accept(sockmain, (struct sockaddr *) &from, &fromlen);
+
+ /* We're not using sock_close, since we do not want to send a shutdown */
+ /* (which is not allowed on a non-connected socket) */
+ closesocket(sockmain);
+ sockmain = 0;
+
+ if (sockctrl == -1)
+ {
+ sock_geterror("accept(): ", errbuf, PCAP_ERRBUF_SIZE);
+ return -2;
+ }
+
+ /* Get the numeric for of the name of the connecting host */
+ if (getnameinfo((struct sockaddr *) &from, fromlen, connectinghost, RPCAP_HOSTLIST_SIZE, NULL, 0, NI_NUMERICHOST))
+ {
+ sock_geterror("getnameinfo(): ", errbuf, PCAP_ERRBUF_SIZE);
+ rpcap_senderror(sockctrl, errbuf, PCAP_ERR_REMOTEACCEPT, NULL);
+ sock_close(sockctrl, NULL, 0);
+ return -1;
+ }
+
+ /* checks if the connecting host is among the ones allowed */
+ if (sock_check_hostlist((char *)hostlist, RPCAP_HOSTLIST_SEP, &from, errbuf, PCAP_ERRBUF_SIZE) < 0)
+ {
+ rpcap_senderror(sockctrl, errbuf, PCAP_ERR_REMOTEACCEPT, NULL);
+ sock_close(sockctrl, NULL, 0);
+ return -1;
+ }
+
+ /* Send authentication to the remote machine */
+ if (rpcap_sendauth(sockctrl, auth, errbuf) == -1)
+ {
+ rpcap_senderror(sockctrl, errbuf, PCAP_ERR_REMOTEACCEPT, NULL);
+ sock_close(sockctrl, NULL, 0);
+ return -3;
+ }
+
+ /* Checks that this host does not already have a cntrl connection in place */
+
+ /* Initialize pointers */
+ temp = activeHosts;
+ prev = NULL;
+
+ while (temp)
+ {
+ /* This host already has an active connection in place, so I don't have to update the host list */
+ if (sock_cmpaddr(&temp->host, &from) == 0)
+ return sockctrl;
+
+ prev = temp;
+ temp = temp->next;
+ }
+
+ /* The host does not exist in the list; so I have to update the list */
+ if (prev)
+ {
+ prev->next = (struct activehosts *) malloc(sizeof(struct activehosts));
+ temp = prev->next;
+ }
+ else
+ {
+ activeHosts = (struct activehosts *) malloc(sizeof(struct activehosts));
+ temp = activeHosts;
+ }
+
+ if (temp == NULL)
+ {
+ pcap_snprintf(errbuf, PCAP_ERRBUF_SIZE, "malloc() failed: %s", pcap_strerror(errno));
+ rpcap_senderror(sockctrl, errbuf, PCAP_ERR_REMOTEACCEPT, NULL);
+ sock_close(sockctrl, NULL, 0);
+ return -1;
+ }
+
+ memcpy(&temp->host, &from, fromlen);
+ temp->sockctrl = sockctrl;
+ temp->next = NULL;
+
+ return sockctrl;
+}
+
+int pcap_remoteact_close(const char *host, char *errbuf)
+{
+ struct activehosts *temp, *prev; /* temp var needed to scan the host list chain */
+ struct addrinfo hints, *addrinfo, *ai_next; /* temp var needed to translate between hostname to its address */
+ int retval;
+
+ temp = activeHosts;
+ prev = NULL;
+
+ /* retrieve the network address corresponding to 'host' */
+ addrinfo = NULL;
+ memset(&hints, 0, sizeof(struct addrinfo));
+ hints.ai_family = PF_UNSPEC;
+ hints.ai_socktype = SOCK_STREAM;
+
+ retval = getaddrinfo(host, "0", &hints, &addrinfo);
+ if (retval != 0)
+ {
+ pcap_snprintf(errbuf, PCAP_ERRBUF_SIZE, "getaddrinfo() %s", gai_strerror(retval));
+ return -1;
+ }
+
+ while (temp)
+ {
+ ai_next = addrinfo;
+ while (ai_next)
+ {
+ if (sock_cmpaddr(&temp->host, (struct sockaddr_storage *) ai_next->ai_addr) == 0)
+ {
+ struct rpcap_header header;
+
+ /* Close this connection */
+ rpcap_createhdr(&header, RPCAP_MSG_CLOSE, 0, 0);
+
+ /* I don't check for errors, since I'm going to close everything */
+ sock_send(temp->sockctrl, (char *)&header, sizeof(struct rpcap_header), errbuf, PCAP_ERRBUF_SIZE);
+
+ if (sock_close(temp->sockctrl, errbuf, PCAP_ERRBUF_SIZE))
+ {
+ /* To avoid inconsistencies in the number of sock_init() */
+ sock_cleanup();
+
+ return -1;
+ }
+
+ if (prev)
+ prev->next = temp->next;
+ else
+ activeHosts = temp->next;
+
+ freeaddrinfo(addrinfo);
+
+ free(temp);
+
+ /* To avoid inconsistencies in the number of sock_init() */
+ sock_cleanup();
+
+ return 0;
+ }
+
+ ai_next = ai_next->ai_next;
+ }
+ prev = temp;
+ temp = temp->next;
+ }
+
+ if (addrinfo)
+ freeaddrinfo(addrinfo);
+
+ /* To avoid inconsistencies in the number of sock_init() */
+ sock_cleanup();
+
+ pcap_snprintf(errbuf, PCAP_ERRBUF_SIZE, "The host you want to close the active connection is not known");
+ return -1;
+}
+
+void pcap_remoteact_cleanup(void)
+{
+ /* Very dirty, but it works */
+ if (sockmain)
+ {
+ closesocket(sockmain);
+
+ /* To avoid inconsistencies in the number of sock_init() */
+ sock_cleanup();
+ }
+
+}
+
+int pcap_remoteact_list(char *hostlist, char sep, int size, char *errbuf)
+{
+ struct activehosts *temp; /* temp var needed to scan the host list chain */
+ size_t len;
+ char hoststr[RPCAP_HOSTLIST_SIZE + 1];
+
+ temp = activeHosts;
+
+ len = 0;
+ *hostlist = 0;
+
+ while (temp)
+ {
+ /*int sock_getascii_addrport(const struct sockaddr_storage *sockaddr, char *address, int addrlen, char *port, int portlen, int flags, char *errbuf, int errbuflen) */
+
+ /* Get the numeric form of the name of the connecting host */
+ if (sock_getascii_addrport((struct sockaddr_storage *) &temp->host, hoststr,
+ RPCAP_HOSTLIST_SIZE, NULL, 0, NI_NUMERICHOST, errbuf, PCAP_ERRBUF_SIZE) != -1)
+ /* if (getnameinfo( (struct sockaddr *) &temp->host, sizeof (struct sockaddr_storage), hoststr, */
+ /* RPCAP_HOSTLIST_SIZE, NULL, 0, NI_NUMERICHOST) ) */
+ {
+ /* sock_geterror("getnameinfo(): ", errbuf, PCAP_ERRBUF_SIZE); */
+ return -1;
+ }
+
+ len = len + strlen(hoststr) + 1 /* the separator */;
+
+ if ((size < 0) || (len >= (size_t)size))
+ {
+ pcap_snprintf(errbuf, PCAP_ERRBUF_SIZE, "The string you provided is not able to keep "
+ "the hostnames for all the active connections");
+ return -1;
+ }
+
+ strlcat(hostlist, hoststr, PCAP_ERRBUF_SIZE);
+ hostlist[len - 1] = sep;
+ hostlist[len] = 0;
+
+ temp = temp->next;
+ }
+
+ return 0;
+}
diff --git a/contrib/libpcap/pcap-nit.c b/contrib/libpcap/pcap-nit.c
index ea81eb579f58..1b626e215a22 100644
--- a/contrib/libpcap/pcap-nit.c
+++ b/contrib/libpcap/pcap-nit.c
@@ -114,11 +114,11 @@ pcap_read_nit(pcap_t *p, int cnt, pcap_handler callback, u_char *user)
if (cc < 0) {
if (errno == EWOULDBLOCK)
return (0);
- snprintf(p->errbuf, sizeof(p->errbuf), "pcap_read: %s",
+ pcap_snprintf(p->errbuf, sizeof(p->errbuf), "pcap_read: %s",
pcap_strerror(errno));
return (-1);
}
- bp = p->buffer;
+ bp = (u_char *)p->buffer;
} else
bp = p->bp;
@@ -168,7 +168,7 @@ pcap_read_nit(pcap_t *p, int cnt, pcap_handler callback, u_char *user)
continue;
default:
- snprintf(p->errbuf, sizeof(p->errbuf),
+ pcap_snprintf(p->errbuf, sizeof(p->errbuf),
"bad nit state %d", nh->nh_state);
return (-1);
}
@@ -206,12 +206,12 @@ pcap_inject_nit(pcap_t *p, const void *buf, size_t size)
strncpy(sa.sa_data, device, sizeof(sa.sa_data));
ret = sendto(p->fd, buf, size, 0, &sa, sizeof(sa));
if (ret == -1) {
- snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "send: %s",
+ pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "send: %s",
pcap_strerror(errno));
return (-1);
}
return (ret);
-}
+}
static int
nit_setflags(pcap_t *p)
@@ -249,7 +249,7 @@ nit_setflags(pcap_t *p)
nioc.nioc_flags |= NF_PROMISC;
if (ioctl(p->fd, SIOCSNIT, &nioc) < 0) {
- snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "SIOCSNIT: %s",
+ pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "SIOCSNIT: %s",
pcap_strerror(errno));
return (-1);
}
@@ -280,15 +280,22 @@ pcap_activate_nit(pcap_t *p)
memset(p, 0, sizeof(*p));
p->fd = fd = socket(AF_NIT, SOCK_RAW, NITPROTO_RAW);
if (fd < 0) {
- snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
+ pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
"socket: %s", pcap_strerror(errno));
goto bad;
}
snit.snit_family = AF_NIT;
- (void)strncpy(snit.snit_ifname, p->opt.source, NITIFSIZ);
+ (void)strncpy(snit.snit_ifname, p->opt.device, NITIFSIZ);
if (bind(fd, (struct sockaddr *)&snit, sizeof(snit))) {
- snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
+ /*
+ * XXX - there's probably a particular bind error that
+ * means "there's no such device" and a particular bind
+ * error that means "that device doesn't support NIT";
+ * they might be the same error, if they both end up
+ * meaning "NIT doesn't know about that device".
+ */
+ pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
"bind: %s: %s", snit.snit_ifname, pcap_strerror(errno));
goto bad;
}
@@ -301,7 +308,7 @@ pcap_activate_nit(pcap_t *p)
p->linktype = DLT_EN10MB;
p->bufsize = BUFSPACE;
- p->buffer = (u_char *)malloc(p->bufsize);
+ p->buffer = malloc(p->bufsize);
if (p->buffer == NULL) {
strlcpy(p->errbuf, pcap_strerror(errno), PCAP_ERRBUF_SIZE);
goto bad;
@@ -348,11 +355,11 @@ pcap_activate_nit(pcap_t *p)
}
pcap_t *
-pcap_create_interface(const char *device, char *ebuf)
+pcap_create_interface(const char *device _U_, char *ebuf)
{
pcap_t *p;
- p = pcap_create_common(device, ebuf, sizeof (struct pcap_nit));
+ p = pcap_create_common(ebuf, sizeof (struct pcap_nit));
if (p == NULL)
return (NULL);
@@ -360,8 +367,18 @@ pcap_create_interface(const char *device, char *ebuf)
return (p);
}
+/*
+ * XXX - there's probably a particular bind error that means "that device
+ * doesn't support NIT"; if so, we should try a bind and use that.
+ */
+static int
+can_be_bound(const char *name _U_)
+{
+ return (1);
+}
+
int
pcap_platform_finddevs(pcap_if_t **alldevsp, char *errbuf)
{
- return (0);
+ return (pcap_findalldevs_interfaces(alldevsp, errbuf, can_be_bound));
}
diff --git a/contrib/libpcap/pcap-null.c b/contrib/libpcap/pcap-null.c
index 934fb2cc061c..b5fa3ab91fab 100644
--- a/contrib/libpcap/pcap-null.c
+++ b/contrib/libpcap/pcap-null.c
@@ -36,7 +36,7 @@
static char nosup[] = "live packet capture not supported on this system";
pcap_t *
-pcap_create_interface(const char *device, char *ebuf)
+pcap_create_interface(const char *device _U_, char *ebuf)
{
(void)strlcpy(ebuf, nosup, PCAP_ERRBUF_SIZE);
return (NULL);
@@ -45,5 +45,9 @@ pcap_create_interface(const char *device, char *ebuf)
int
pcap_platform_finddevs(pcap_if_t **alldevsp, char *errbuf)
{
+ /*
+ * There are no interfaces on which we can capture.
+ */
+ *alldevsp = NULL;
return (0);
}
diff --git a/contrib/libpcap/pcap-pf.c b/contrib/libpcap/pcap-pf.c
index 96a4a50979b4..73469086d8a4 100644
--- a/contrib/libpcap/pcap-pf.c
+++ b/contrib/libpcap/pcap-pf.c
@@ -107,7 +107,7 @@ pcap_read_pf(pcap_t *pc, int cnt, pcap_handler callback, u_char *user)
#ifdef LBL_ALIGN
struct enstamp stamp;
#endif
- register int pad;
+ register u_int pad;
again:
cc = pc->cc;
@@ -127,11 +127,11 @@ pcap_read_pf(pcap_t *pc, int cnt, pcap_handler callback, u_char *user)
(void)lseek(pc->fd, 0L, SEEK_SET);
goto again;
}
- snprintf(pc->errbuf, sizeof(pc->errbuf), "pf read: %s",
+ pcap_snprintf(pc->errbuf, sizeof(pc->errbuf), "pf read: %s",
pcap_strerror(errno));
return (-1);
}
- bp = pc->buffer + pc->offset;
+ bp = (u_char *)pc->buffer + pc->offset;
} else
bp = pc->bp;
/*
@@ -160,7 +160,7 @@ pcap_read_pf(pcap_t *pc, int cnt, pcap_handler callback, u_char *user)
}
}
if (cc < sizeof(*sp)) {
- snprintf(pc->errbuf, sizeof(pc->errbuf),
+ pcap_snprintf(pc->errbuf, sizeof(pc->errbuf),
"pf short read (%d)", cc);
return (-1);
}
@@ -172,7 +172,7 @@ pcap_read_pf(pcap_t *pc, int cnt, pcap_handler callback, u_char *user)
#endif
sp = (struct enstamp *)bp;
if (sp->ens_stamplen != sizeof(*sp)) {
- snprintf(pc->errbuf, sizeof(pc->errbuf),
+ pcap_snprintf(pc->errbuf, sizeof(pc->errbuf),
"pf short stamplen (%d)",
sp->ens_stamplen);
return (-1);
@@ -232,12 +232,12 @@ pcap_inject_pf(pcap_t *p, const void *buf, size_t size)
ret = write(p->fd, buf, size);
if (ret == -1) {
- snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "send: %s",
+ pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "send: %s",
pcap_strerror(errno));
return (-1);
}
return (ret);
-}
+}
static int
pcap_stats_pf(pcap_t *p, struct pcap_stat *ps)
@@ -321,14 +321,17 @@ pcap_activate_pf(pcap_t *p)
* its argument, even though it takes a "char *" rather than a
* "const char *" as its first argument. That appears to be
* the case, at least on Digital UNIX 4.0.
+ *
+ * XXX - is there an error that means "no such device"? Is
+ * there one that means "that device doesn't support pf"?
*/
- p->fd = pfopen(p->opt.source, O_RDWR);
+ p->fd = pfopen(p->opt.device, O_RDWR);
if (p->fd == -1 && errno == EACCES)
- p->fd = pfopen(p->opt.source, O_RDONLY);
+ p->fd = pfopen(p->opt.device, O_RDONLY);
if (p->fd < 0) {
- snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "pf open: %s: %s\n\
+ pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "pf open: %s: %s\n\
your system may not be properly configured; see the packetfilter(4) man page\n",
- p->opt.source, pcap_strerror(errno));
+ p->opt.device, pcap_strerror(errno));
goto bad;
}
pf->OrigMissed = -1;
@@ -338,7 +341,7 @@ your system may not be properly configured; see the packetfilter(4) man page\n",
if (p->opt.promisc)
enmode |= ENPROMISC;
if (ioctl(p->fd, EIOCMBIS, (caddr_t)&enmode) < 0) {
- snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "EIOCMBIS: %s",
+ pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "EIOCMBIS: %s",
pcap_strerror(errno));
goto bad;
}
@@ -349,13 +352,13 @@ your system may not be properly configured; see the packetfilter(4) man page\n",
#endif
/* set the backlog */
if (ioctl(p->fd, EIOCSETW, (caddr_t)&backlog) < 0) {
- snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "EIOCSETW: %s",
+ pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "EIOCSETW: %s",
pcap_strerror(errno));
goto bad;
}
/* discover interface type */
if (ioctl(p->fd, EIOCDEVP, (caddr_t)&devparams) < 0) {
- snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "EIOCDEVP: %s",
+ pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "EIOCDEVP: %s",
pcap_strerror(errno));
goto bad;
}
@@ -437,7 +440,7 @@ your system may not be properly configured; see the packetfilter(4) man page\n",
* framing", there's not much we can do, as that
* doesn't specify a particular type of header.
*/
- snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
+ pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
"unknown data-link type %u", devparams.end_dev_type);
goto bad;
}
@@ -450,7 +453,7 @@ your system may not be properly configured; see the packetfilter(4) man page\n",
} else
p->fddipad = 0;
if (ioctl(p->fd, EIOCTRUNCATE, (caddr_t)&p->snapshot) < 0) {
- snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "EIOCTRUNCATE: %s",
+ pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "EIOCTRUNCATE: %s",
pcap_strerror(errno));
goto bad;
}
@@ -459,7 +462,7 @@ your system may not be properly configured; see the packetfilter(4) man page\n",
Filter.enf_Priority = 37; /* anything > 2 */
Filter.enf_FilterLen = 0; /* means "always true" */
if (ioctl(p->fd, EIOCSETF, (caddr_t)&Filter) < 0) {
- snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "EIOCSETF: %s",
+ pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "EIOCSETF: %s",
pcap_strerror(errno));
goto bad;
}
@@ -469,14 +472,14 @@ your system may not be properly configured; see the packetfilter(4) man page\n",
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_snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "EIOCSRTIMEOUT: %s",
pcap_strerror(errno));
goto bad;
}
}
p->bufsize = BUFSPACE;
- p->buffer = (u_char*)malloc(p->bufsize + p->offset);
+ p->buffer = malloc(p->bufsize + p->offset);
if (p->buffer == NULL) {
strlcpy(p->errbuf, pcap_strerror(errno), PCAP_ERRBUF_SIZE);
goto bad;
@@ -503,11 +506,11 @@ your system may not be properly configured; see the packetfilter(4) man page\n",
}
pcap_t *
-pcap_create_interface(const char *device, char *ebuf)
+pcap_create_interface(const char *device _U_, char *ebuf)
{
pcap_t *p;
- p = pcap_create_common(device, ebuf, sizeof (struct pcap_pf));
+ p = pcap_create_common(ebuf, sizeof (struct pcap_pf));
if (p == NULL)
return (NULL);
@@ -515,10 +518,20 @@ pcap_create_interface(const char *device, char *ebuf)
return (p);
}
+/*
+ * XXX - is there an error from pfopen() that means "no such device"?
+ * Is there one that means "that device doesn't support pf"?
+ */
+static int
+can_be_bound(const char *name _U_)
+{
+ return (1);
+}
+
int
pcap_platform_finddevs(pcap_if_t **alldevsp, char *errbuf)
{
- return (0);
+ return (pcap_findalldevs_interfaces(alldevsp, errbuf, can_be_bound));
}
static int
@@ -547,7 +560,7 @@ pcap_setfilter_pf(pcap_t *p, struct bpf_program *fp)
* Yes. Try to install the filter.
*/
if (ioctl(p->fd, BIOCSETF, (caddr_t)fp) < 0) {
- snprintf(p->errbuf, sizeof(p->errbuf),
+ pcap_snprintf(p->errbuf, sizeof(p->errbuf),
"BIOCSETF: %s", pcap_strerror(errno));
return (-1);
}
diff --git a/contrib/libpcap/pcap-rpcap.c b/contrib/libpcap/pcap-rpcap.c
new file mode 100644
index 000000000000..b954058df939
--- /dev/null
+++ b/contrib/libpcap/pcap-rpcap.c
@@ -0,0 +1,2127 @@
+/*
+ * Copyright (c) 2002 - 2005 NetGroup, Politecnico di Torino (Italy)
+ * Copyright (c) 2005 - 2008 CACE Technologies, Davis (California)
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the Politecnico di Torino, CACE Technologies
+ * nor the names of its contributors may be used to endorse or promote
+ * products derived from this software without specific prior written
+ * permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <string.h> /* for strlen(), ... */
+#include <stdlib.h> /* for malloc(), free(), ... */
+#include <stdarg.h> /* for functions with variable number of arguments */
+#include <errno.h> /* for the errno variable */
+#include "pcap-int.h"
+#include "pcap-rpcap.h"
+#include "sockutils.h"
+
+/*
+ * \file pcap-rpcap.c
+ *
+ * This file keeps all the new funtions that are needed for the RPCAP protocol.
+ * Almost all the pcap functions need to be modified in order to become compatible
+ * with the RPCAP protocol. However, you can find here only the ones that are completely new.
+ *
+ * This file keeps also the functions that are 'private', i.e. are needed by the RPCAP
+ * protocol but are not exported to the user.
+ *
+ * \warning All the RPCAP functions that are allowed to return a buffer containing
+ * the error description can return max PCAP_ERRBUF_SIZE characters.
+ * However there is no guarantees that the string will be zero-terminated.
+ * Best practice is to define the errbuf variable as a char of size 'PCAP_ERRBUF_SIZE+1'
+ * and to insert manually a NULL character at the end of the buffer. This will
+ * guarantee that no buffer overflows occur even if we use the printf() to show
+ * the error on the screen.
+ */
+
+#define PCAP_STATS_STANDARD 0 /* Used by pcap_stats_remote to see if we want standard or extended statistics */
+#define PCAP_STATS_EX 1 /* Used by pcap_stats_remote to see if we want standard or extended statistics */
+
+/* Keeps a list of all the opened connections in the active mode. */
+struct activehosts *activeHosts;
+
+/*
+ * Private data for capturing on WinPcap devices.
+ */
+struct pcap_win {
+ int nonblock;
+ int rfmon_selfstart; /* a flag tells whether the monitor mode is set by itself */
+ int filtering_in_kernel; /* using kernel filter */
+
+#ifdef HAVE_DAG_API
+ int dag_fcs_bits; /* Number of checksum bits from link layer */
+#endif
+};
+
+/****************************************************
+ * *
+ * Locally defined functions *
+ * *
+ ****************************************************/
+static int rpcap_checkver(SOCKET sock, struct rpcap_header *header, char *errbuf);
+static struct pcap_stat *rpcap_stats_remote(pcap_t *p, struct pcap_stat *ps, int mode);
+static int pcap_pack_bpffilter(pcap_t *fp, char *sendbuf, int *sendbufidx, struct bpf_program *prog);
+static int pcap_createfilter_norpcappkt(pcap_t *fp, struct bpf_program *prog);
+static int pcap_updatefilter_remote(pcap_t *fp, struct bpf_program *prog);
+static int pcap_setfilter_remote(pcap_t *fp, struct bpf_program *prog);
+static int pcap_setsampling_remote(pcap_t *p);
+
+
+/****************************************************
+ * *
+ * Function bodies *
+ * *
+ ****************************************************/
+
+/*
+ * \ingroup remote_pri_func
+ *
+ * \brief It traslates (i.e. de-serializes) a 'sockaddr_storage' structure from
+ * the network byte order to the host byte order.
+ *
+ * It accepts a 'sockaddr_storage' structure as it is received from the network and it
+ * converts it into the host byte order (by means of a set of ntoh() ).
+ * The function will allocate the 'sockaddrout' variable according to the address family
+ * in use. In case the address does not belong to the AF_INET nor AF_INET6 families,
+ * 'sockaddrout' is not allocated and a NULL pointer is returned.
+ * This usually happens because that address does not exist on the other host, so the
+ * RPCAP daemon sent a 'sockaddr_storage' structure containing all 'zero' values.
+ *
+ * \param sockaddrin: a 'sockaddr_storage' pointer to the variable that has to be
+ * de-serialized.
+ *
+ * \param sockaddrout: a 'sockaddr_storage' pointer to the variable that will contain
+ * the de-serialized data. The structure returned can be either a 'sockaddr_in' or 'sockaddr_in6'.
+ * This variable will be allocated automatically inside this function.
+ *
+ * \param errbuf: a pointer to a user-allocated buffer (of size PCAP_ERRBUF_SIZE)
+ * that will contain the error message (in case there is one).
+ *
+ * \return '0' if everything is fine, '-1' if some errors occurred. Basically, the error
+ * can be only the fact that the malloc() failed to allocate memory.
+ * The error message is returned in the 'errbuf' variable, while the deserialized address
+ * is returned into the 'sockaddrout' variable.
+ *
+ * \warning This function supports only AF_INET and AF_INET6 address families.
+ *
+ * \warning The sockaddrout (if not NULL) must be deallocated by the user.
+ */
+int rpcap_deseraddr(struct sockaddr_storage *sockaddrin, struct sockaddr_storage **sockaddrout, char *errbuf)
+{
+ /* Warning: we support only AF_INET and AF_INET6 */
+ if (ntohs(sockaddrin->ss_family) == AF_INET)
+ {
+ struct sockaddr_in *sockaddr;
+
+ sockaddr = (struct sockaddr_in *) sockaddrin;
+ sockaddr->sin_family = ntohs(sockaddr->sin_family);
+ sockaddr->sin_port = ntohs(sockaddr->sin_port);
+
+ (*sockaddrout) = (struct sockaddr_storage *) malloc(sizeof(struct sockaddr_in));
+ if ((*sockaddrout) == NULL)
+ {
+ pcap_snprintf(errbuf, PCAP_ERRBUF_SIZE, "malloc() failed: %s", pcap_strerror(errno));
+ return -1;
+ }
+ memcpy(*sockaddrout, sockaddr, sizeof(struct sockaddr_in));
+ return 0;
+ }
+ if (ntohs(sockaddrin->ss_family) == AF_INET6)
+ {
+ struct sockaddr_in6 *sockaddr;
+
+ sockaddr = (struct sockaddr_in6 *) sockaddrin;
+ sockaddr->sin6_family = ntohs(sockaddr->sin6_family);
+ sockaddr->sin6_port = ntohs(sockaddr->sin6_port);
+ sockaddr->sin6_flowinfo = ntohl(sockaddr->sin6_flowinfo);
+ sockaddr->sin6_scope_id = ntohl(sockaddr->sin6_scope_id);
+
+ (*sockaddrout) = (struct sockaddr_storage *) malloc(sizeof(struct sockaddr_in6));
+ if ((*sockaddrout) == NULL)
+ {
+ pcap_snprintf(errbuf, PCAP_ERRBUF_SIZE, "malloc() failed: %s", pcap_strerror(errno));
+ return -1;
+ }
+ memcpy(*sockaddrout, sockaddr, sizeof(struct sockaddr_in6));
+ return 0;
+ }
+
+ /* It is neither AF_INET nor AF_INET6 */
+ *sockaddrout = NULL;
+ return 0;
+}
+
+/* \ingroup remote_pri_func
+ *
+ * \brief It reads a packet from the network socket. This does not make use of
+ * callback (hence the "nocb" string into its name).
+ *
+ * This function is called by the several pcap_next_ex() when they detect that
+ * we have a remote capture and they are the client side. In that case, they need
+ * to read packets from the socket.
+ *
+ * Parameters and return values are exactly the same of the pcap_next_ex().
+ *
+ * \warning By choice, this function does not make use of semaphores. A smarter
+ * implementation should put a semaphore into the data thread, and a signal will
+ * be raised as soon as there is data into the socket buffer.
+ * However this is complicated and it does not bring any advantages when reading
+ * from the network, in which network delays can be much more important than
+ * these optimizations. Therefore, we chose the following approach:
+ * - the 'timeout' chosen by the user is split in two (half on the server side,
+ * with the usual meaning, and half on the client side)
+ * - this function checks for packets; if there are no packets, it waits for
+ * timeout/2 and then it checks again. If packets are still missing, it returns,
+ * otherwise it reads packets.
+ */
+static int pcap_read_nocb_remote(pcap_t *p, struct pcap_pkthdr **pkt_header, u_char **pkt_data)
+{
+ struct rpcap_header *header; /* general header according to the RPCAP format */
+ struct rpcap_pkthdr *net_pkt_header; /* header of the packet */
+ char netbuf[RPCAP_NETBUF_SIZE]; /* size of the network buffer in which the packet is copied, just for UDP */
+ uint32 totread; /* number of bytes (of payload) currently read from the network (referred to the current pkt) */
+ int nread;
+ int retval; /* generic return value */
+
+ /* Structures needed for the select() call */
+ fd_set rfds; /* set of socket descriptors we have to check */
+ struct timeval tv; /* maximum time the select() can block waiting for data */
+ struct pcap_md *md; /* structure used when doing a remote live capture */
+
+ md = (struct pcap_md *) ((u_char*)p->priv + sizeof(struct pcap_win));
+
+ /*
+ * Define the read timeout, to be used in the select()
+ * 'timeout', in pcap_t, is in milliseconds; we have to convert it into sec and microsec
+ */
+ tv.tv_sec = p->opt.timeout / 1000;
+ tv.tv_usec = (p->opt.timeout - tv.tv_sec * 1000) * 1000;
+
+ /* Watch out sockdata to see if it has input */
+ FD_ZERO(&rfds);
+
+ /*
+ * 'fp->rmt_sockdata' has always to be set before calling the select(),
+ * since it is cleared by the select()
+ */
+ FD_SET(md->rmt_sockdata, &rfds);
+
+ retval = select((int) md->rmt_sockdata + 1, &rfds, NULL, NULL, &tv);
+ if (retval == -1)
+ {
+ sock_geterror("select(): ", p->errbuf, PCAP_ERRBUF_SIZE);
+ return -1;
+ }
+
+ /* There is no data waiting, so return '0' */
+ if (retval == 0)
+ return 0;
+
+ /*
+ * data is here; so, let's copy it into the user buffer.
+ * I'm going to read a new packet; so I reset the number of bytes (payload only) read
+ */
+ totread = 0;
+
+ /*
+ * We have to define 'header' as a pointer to a larger buffer,
+ * because in case of UDP we have to read all the message within a single call
+ */
+ header = (struct rpcap_header *) netbuf;
+ net_pkt_header = (struct rpcap_pkthdr *) (netbuf + sizeof(struct rpcap_header));
+
+ if (md->rmt_flags & PCAP_OPENFLAG_DATATX_UDP)
+ {
+ /* Read the entire message from the network */
+ if (sock_recv(md->rmt_sockdata, netbuf, RPCAP_NETBUF_SIZE, SOCK_RECEIVEALL_NO, p->errbuf, PCAP_ERRBUF_SIZE) == -1)
+ return -1;
+ }
+ else
+ {
+ if (sock_recv(md->rmt_sockdata, netbuf, sizeof(struct rpcap_header), SOCK_RECEIVEALL_YES, p->errbuf, PCAP_ERRBUF_SIZE) == -1)
+ return -1;
+ }
+
+ /* Checks if the message is correct */
+ retval = rpcap_checkmsg(p->errbuf, md->rmt_sockdata, header, RPCAP_MSG_PACKET, 0);
+
+ if (retval != RPCAP_MSG_PACKET) /* the message is not the one expected */
+ {
+ switch (retval)
+ {
+ case -3: /* Unrecoverable network error */
+ return -1; /* Do nothing; just exit from here; the error code is already into the errbuf */
+
+ case -2: /* The other endpoint sent a message that is not allowed here */
+ case -1: /* The other endpoint has a version number that is not compatible with our */
+ return 0; /* Return 'no packets received' */
+
+ default:
+ SOCK_ASSERT("Internal error", 1);
+ return 0; /* Return 'no packets received' */
+ }
+ }
+
+ /* In case of TCP, read the remaining of the packet from the socket */
+ if (!(md->rmt_flags & PCAP_OPENFLAG_DATATX_UDP))
+ {
+ /* Read the RPCAP packet header from the network */
+ nread = sock_recv(md->rmt_sockdata, (char *)net_pkt_header,
+ sizeof(struct rpcap_pkthdr), SOCK_RECEIVEALL_YES,
+ p->errbuf, PCAP_ERRBUF_SIZE);
+ if (nread == -1)
+ return -1;
+ totread += nread;
+ }
+
+ if ((ntohl(net_pkt_header->caplen) + sizeof(struct pcap_pkthdr)) <= p->bufsize)
+ {
+ /* Initialize returned structures */
+ *pkt_header = (struct pcap_pkthdr *) p->buffer;
+ *pkt_data = (u_char*)p->buffer + sizeof(struct pcap_pkthdr);
+
+ (*pkt_header)->caplen = ntohl(net_pkt_header->caplen);
+ (*pkt_header)->len = ntohl(net_pkt_header->len);
+ (*pkt_header)->ts.tv_sec = ntohl(net_pkt_header->timestamp_sec);
+ (*pkt_header)->ts.tv_usec = ntohl(net_pkt_header->timestamp_usec);
+
+ /*
+ * I don't update the counter of the packets dropped by the network since we're using TCP,
+ * therefore no packets are dropped. Just update the number of packets received correctly
+ */
+ md->TotCapt++;
+
+ /* Copies the packet into the data buffer */
+ if (md->rmt_flags & PCAP_OPENFLAG_DATATX_UDP)
+ {
+ unsigned int npkt;
+
+ /*
+ * In case of UDP the packet has already been read, we have to copy it into 'buffer'.
+ * Another option should be to declare 'netbuf' as 'static'. However this prevents
+ * using several pcap instances within the same process (because the static buffer is shared among
+ * all processes)
+ */
+ memcpy(*pkt_data, netbuf + sizeof(struct rpcap_header) + sizeof(struct rpcap_pkthdr), (*pkt_header)->caplen);
+
+ /* We're using UDP, so we need to update the counter of the packets dropped by the network */
+ npkt = ntohl(net_pkt_header->npkt);
+
+ if (md->TotCapt != npkt)
+ {
+ md->TotNetDrops += (npkt - md->TotCapt);
+ md->TotCapt = npkt;
+ }
+
+ }
+ else
+ {
+ /* In case of TCP, read the remaining of the packet from the socket */
+ nread = sock_recv(md->rmt_sockdata, *pkt_data,
+ (*pkt_header)->caplen, SOCK_RECEIVEALL_YES,
+ p->errbuf, PCAP_ERRBUF_SIZE);
+ if (nread == -1)
+ return -1;
+ totread += nread;
+
+ /* Checks if all the data has been read; if not, discard the data in excess */
+ /* This check has to be done only on TCP connections */
+ if (totread != ntohl(header->plen))
+ sock_discard(md->rmt_sockdata, ntohl(header->plen) - totread, NULL, 0);
+ }
+
+
+ /* Packet read successfully */
+ return 1;
+ }
+ else
+ {
+ pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "Received a packet that is larger than the internal buffer size.");
+ return -1;
+ }
+
+}
+
+/* \ingroup remote_pri_func
+ *
+ * \brief It reads a packet from the network socket.
+ *
+ * This function is called by the several pcap_read() when they detect that
+ * we have a remote capture and they are the client side. In that case, they need
+ * to read packets from the socket.
+ *
+ * This function relies on the pcap_read_nocb_remote to deliver packets. The
+ * difference, here, is that as soon as a packet is read, it is delivered
+ * to the application by means of a callback function.
+ *
+ * Parameters and return values are exactly the same of the pcap_read().
+ */
+static int pcap_read_remote(pcap_t *p, int cnt, pcap_handler callback, u_char *user)
+{
+ struct pcap_pkthdr *pkt_header;
+ u_char *pkt_data;
+ int n = 0;
+
+ while ((n < cnt) || (cnt < 0))
+ {
+ if (pcap_read_nocb_remote(p, &pkt_header, &pkt_data) == 1)
+ {
+ (*callback)(user, pkt_header, pkt_data);
+ n++;
+ }
+ else
+ return n;
+ }
+ return n;
+}
+
+/* \ingroup remote_pri_func
+ *
+ * \brief It sends a CLOSE command to the capture server.
+ *
+ * This function is called when the user wants to close a pcap_t adapter.
+ * In case we're capturing from the network, it sends a command to the other
+ * peer that says 'ok, let's stop capturing'.
+ * This function is called automatically when the user calls the pcap_close().
+ *
+ * Parameters and return values are exactly the same of the pcap_close().
+ *
+ * \warning Since we're closing the connection, we do not check for errors.
+ */
+static void pcap_cleanup_remote(pcap_t *fp)
+{
+ struct rpcap_header header; /* header of the RPCAP packet */
+ struct activehosts *temp; /* temp var needed to scan the host list chain, to detect if we're in active mode */
+ int active = 0; /* active mode or not? */
+ struct pcap_md *md; /* structure used when doing a remote live capture */
+
+ md = (struct pcap_md *) ((u_char*)fp->priv + sizeof(struct pcap_win));
+
+ /* detect if we're in active mode */
+ temp = activeHosts;
+ while (temp)
+ {
+ if (temp->sockctrl == md->rmt_sockctrl)
+ {
+ active = 1;
+ break;
+ }
+ temp = temp->next;
+ }
+
+ if (!active)
+ {
+ rpcap_createhdr(&header, RPCAP_MSG_CLOSE, 0, 0);
+
+ /* I don't check for errors, since I'm going to close everything */
+ sock_send(md->rmt_sockctrl, (char *)&header, sizeof(struct rpcap_header), NULL, 0);
+ }
+ else
+ {
+ rpcap_createhdr(&header, RPCAP_MSG_ENDCAP_REQ, 0, 0);
+
+ /* I don't check for errors, since I'm going to close everything */
+ sock_send(md->rmt_sockctrl, (char *)&header, sizeof(struct rpcap_header), NULL, 0);
+
+ /* wait for the answer */
+ /* Don't check what we got, since the present libpcap does not uses this pcap_t anymore */
+ sock_recv(md->rmt_sockctrl, (char *)&header, sizeof(struct rpcap_header), SOCK_RECEIVEALL_YES, NULL, 0);
+
+ if (ntohl(header.plen) != 0)
+ sock_discard(md->rmt_sockctrl, ntohl(header.plen), NULL, 0);
+ }
+
+ if (md->rmt_sockdata)
+ {
+ sock_close(md->rmt_sockdata, NULL, 0);
+ md->rmt_sockdata = 0;
+ }
+
+ if ((!active) && (md->rmt_sockctrl))
+ sock_close(md->rmt_sockctrl, NULL, 0);
+
+ md->rmt_sockctrl = 0;
+
+ if (md->currentfilter)
+ {
+ free(md->currentfilter);
+ md->currentfilter = NULL;
+ }
+
+ /* To avoid inconsistencies in the number of sock_init() */
+ sock_cleanup();
+}
+
+/* \ingroup remote_pri_func
+ *
+ * \brief It retrieves network statistics from the other peer.
+ *
+ * This function is just a void cointainer, since the work is done by the rpcap_stats_remote().
+ * See that funcion for more details.
+ *
+ * Parameters and return values are exactly the same of the pcap_stats().
+ */
+static int pcap_stats_remote(pcap_t *p, struct pcap_stat *ps)
+{
+ struct pcap_stat *retval;
+
+ retval = rpcap_stats_remote(p, ps, PCAP_STATS_STANDARD);
+
+ if (retval)
+ return 0;
+ else
+ return -1;
+}
+
+#ifdef _WIN32
+/* \ingroup remote_pri_func
+ *
+ * \brief It retrieves network statistics from the other peer.
+ *
+ * This function is just a void cointainer, since the work is done by the rpcap_stats_remote().
+ * See that funcion for more details.
+ *
+ * Parameters and return values are exactly the same of the pcap_stats_ex().
+ */
+static struct pcap_stat *pcap_stats_ex_remote(pcap_t *p, int *pcap_stat_size)
+{
+ *pcap_stat_size = sizeof (p->stat);
+
+ /* PCAP_STATS_EX (third param) means 'extended pcap_stats()' */
+ return (rpcap_stats_remote(p, &(p->stat), PCAP_STATS_EX));
+}
+#endif
+
+/* \ingroup remote_pri_func
+ *
+ * \brief It retrieves network statistics from the other peer.
+ *
+ * This function can be called in two modes:
+ * - PCAP_STATS_STANDARD: if we want just standard statistics (i.e. the pcap_stats() )
+ * - PCAP_STATS_EX: if we want extended statistics (i.e. the pcap_stats_ex() )
+ *
+ * This 'mode' parameter is needed because in the standard pcap_stats() the variable that keeps the
+ * statistics is allocated by the user. Unfortunately, this structure has been extended in order
+ * to keep new stats. However, if the user has a smaller structure and it passes it to the pcap_stats,
+ * thid function will try to fill in more data than the size of the structure, so that the application
+ * goes in memory overflow.
+ * So, we need to know it we have to copy just the standard fields, or the extended fields as well.
+ *
+ * In case we want to copy the extended fields as well, the problem of memory overflow does no
+ * longer exist because the structure pcap_stat is no longer allocated by the program;
+ * it is allocated by the library instead.
+ *
+ * \param p: the pcap_t structure related to the current instance.
+ *
+ * \param ps: a 'pcap_stat' structure, needed for compatibility with pcap_stat(), in which
+ * the structure is allocated by the user. In case of pcap_stats_ex, this structure and the
+ * function return value point to the same variable.
+ *
+ * \param mode: one of PCAP_STATS_STANDARD or PCAP_STATS_EX.
+ *
+ * \return The structure that keeps the statistics, or NULL in case of error.
+ * The error string is placed in the pcap_t structure.
+ */
+static struct pcap_stat *rpcap_stats_remote(pcap_t *p, struct pcap_stat *ps, int mode)
+{
+ struct rpcap_header header; /* header of the RPCAP packet */
+ struct rpcap_stats netstats; /* statistics sent on the network */
+ uint32 totread = 0; /* number of bytes of the payload read from the socket */
+ int nread;
+ int retval; /* temp variable which stores functions return value */
+ struct pcap_md *md; /* structure used when doing a remote live capture */
+
+ md = (struct pcap_md *) ((u_char*)p->priv + sizeof(struct pcap_win));
+
+ /*
+ * If the capture has still to start, we cannot ask statistics to the other peer,
+ * so we return a fake number
+ */
+ if (!md->rmt_capstarted)
+ {
+ if (mode == PCAP_STATS_STANDARD)
+ {
+ ps->ps_drop = 0;
+ ps->ps_ifdrop = 0;
+ ps->ps_recv = 0;
+ }
+ else
+ {
+ ps->ps_capt = 0;
+ ps->ps_drop = 0;
+ ps->ps_ifdrop = 0;
+ ps->ps_netdrop = 0;
+ ps->ps_recv = 0;
+ ps->ps_sent = 0;
+ }
+
+ return ps;
+ }
+
+ rpcap_createhdr(&header, RPCAP_MSG_STATS_REQ, 0, 0);
+
+ /* Send the PCAP_STATS command */
+ if (sock_send(md->rmt_sockctrl, (char *)&header, sizeof(struct rpcap_header), p->errbuf, PCAP_ERRBUF_SIZE))
+ goto error;
+
+ /* Receive the RPCAP stats reply message */
+ if (sock_recv(md->rmt_sockctrl, (char *)&header, sizeof(struct rpcap_header), SOCK_RECEIVEALL_YES, p->errbuf, PCAP_ERRBUF_SIZE) == -1)
+ goto error;
+
+ /* Checks if the message is correct */
+ retval = rpcap_checkmsg(p->errbuf, md->rmt_sockctrl, &header, RPCAP_MSG_STATS_REPLY, RPCAP_MSG_ERROR, 0);
+
+ if (retval != RPCAP_MSG_STATS_REPLY) /* the message is not the one expected */
+ {
+ switch (retval)
+ {
+ case -3: /* Unrecoverable network error */
+ case -2: /* The other endpoint send a message that is not allowed here */
+ case -1: /* The other endpoint has a version number that is not compatible with our */
+ goto error;
+
+ case RPCAP_MSG_ERROR: /* The other endpoint reported an error */
+ /* Update totread, since the rpcap_checkmsg() already purged the buffer */
+ totread = ntohl(header.plen);
+
+ /* Do nothing; just exit; the error code is already into the errbuf */
+ goto error;
+
+ default:
+ pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "Internal error");
+ goto error;
+ }
+ }
+
+ nread = sock_recv(md->rmt_sockctrl, (char *)&netstats,
+ sizeof(struct rpcap_stats), SOCK_RECEIVEALL_YES,
+ p->errbuf, PCAP_ERRBUF_SIZE);
+ if (nread == -1)
+ goto error;
+ totread += nread;
+
+ if (mode == PCAP_STATS_STANDARD)
+ {
+ ps->ps_drop = ntohl(netstats.krnldrop);
+ ps->ps_ifdrop = ntohl(netstats.ifdrop);
+ ps->ps_recv = ntohl(netstats.ifrecv);
+ }
+ else
+ {
+ ps->ps_capt = md->TotCapt;
+ ps->ps_drop = ntohl(netstats.krnldrop);
+ ps->ps_ifdrop = ntohl(netstats.ifdrop);
+ ps->ps_netdrop = md->TotNetDrops;
+ ps->ps_recv = ntohl(netstats.ifrecv);
+ ps->ps_sent = ntohl(netstats.svrcapt);
+ }
+
+ /* Checks if all the data has been read; if not, discard the data in excess */
+ if (totread != ntohl(header.plen))
+ {
+ if (sock_discard(md->rmt_sockctrl, ntohl(header.plen) - totread, NULL, 0) == 1)
+ goto error;
+ }
+
+ return ps;
+
+error:
+ if (totread != ntohl(header.plen))
+ sock_discard(md->rmt_sockctrl, ntohl(header.plen) - totread, NULL, 0);
+
+ return NULL;
+}
+
+/* \ingroup remote_pri_func
+ *
+ * \brief It opens a remote adapter by opening an RPCAP connection and so on.
+ *
+ * This function does basically the job of pcap_open_live() for a remote interface.
+ * In other words, we have a pcap_read for win32, which reads packets from NPF,
+ * another for LINUX, and so on. Now, we have a pcap_opensource_remote() as well.
+ * The difference, here, is the capture thread does not start until the
+ * pcap_startcapture_remote() is called.
+ *
+ * This is because, in remote capture, we cannot start capturing data as soon ad the
+ * 'open adapter' command is sent. Suppose the remote adapter is already overloaded;
+ * if we start a capture (which, by default, has a NULL filter) the new traffic can
+ * saturate the network.
+ *
+ * Instead, we want to "open" the adapter, then send a "start capture" command only
+ * when we're ready to start the capture.
+ * This funtion does this job: it sends a "open adapter" command (according to the
+ * RPCAP protocol), but it does not start the capture.
+ *
+ * Since the other libpcap functions do not share this way of life, we have to make
+ * some dirty things in order to make everyting working.
+ *
+ * \param fp: A pointer to a pcap_t structure that has been previously created with
+ * \ref pcap_create().
+ * \param source: see pcap_open().
+ * \param auth: see pcap_open().
+ *
+ * \return 0 in case of success, -1 otherwise. In case of success, the pcap_t pointer in fp can be
+ * used as a parameter to the following calls (pcap_compile() and so on). In case of
+ * problems, fp->errbuf contains a text explanation of error.
+ *
+ * \warning In case we call the pcap_compile() and the capture is not started, the filter
+ * will be saved into the pcap_t structure, and it will be sent to the other host later
+ * (when the pcap_startcapture_remote() is called).
+ */
+int pcap_opensource_remote(pcap_t *fp, struct pcap_rmtauth *auth)
+{
+ char host[PCAP_BUF_SIZE], ctrlport[PCAP_BUF_SIZE], iface[PCAP_BUF_SIZE];
+
+ char sendbuf[RPCAP_NETBUF_SIZE]; /* temporary buffer in which data to be sent is buffered */
+ int sendbufidx = 0; /* index which keeps the number of bytes currently buffered */
+ uint32 totread = 0; /* number of bytes of the payload read from the socket */
+ int nread;
+ int retval; /* store the return value of the functions */
+ int active = 0; /* '1' if we're in active mode */
+
+ /* socket-related variables */
+ struct addrinfo hints; /* temp, needed to open a socket connection */
+ struct addrinfo *addrinfo; /* temp, needed to open a socket connection */
+ SOCKET sockctrl = 0; /* socket descriptor of the control connection */
+
+ /* RPCAP-related variables */
+ struct rpcap_header header; /* header of the RPCAP packet */
+ struct rpcap_openreply openreply; /* open reply message */
+
+ struct pcap_md *md; /* structure used when doing a remote live capture */
+
+ md = (struct pcap_md *) ((u_char*)fp->priv + sizeof(struct pcap_win));
+
+
+ /*
+ * determine the type of the source (NULL, file, local, remote)
+ * You must have a valid source string even if we're in active mode, because otherwise
+ * the call to the following function will fail.
+ */
+ if (pcap_parsesrcstr(fp->opt.device, &retval, host, ctrlport, iface, fp->errbuf) == -1)
+ return -1;
+
+ if (retval != PCAP_SRC_IFREMOTE)
+ {
+ pcap_snprintf(fp->errbuf, PCAP_ERRBUF_SIZE, "This function is able to open only remote interfaces");
+ return -1;
+ }
+
+ addrinfo = NULL;
+
+ /*
+ * Warning: this call can be the first one called by the user.
+ * For this reason, we have to initialize the WinSock support.
+ */
+ if (sock_init(fp->errbuf, PCAP_ERRBUF_SIZE) == -1)
+ return -1;
+
+ sockctrl = rpcap_remoteact_getsock(host, &active, fp->errbuf);
+ if (sockctrl == INVALID_SOCKET)
+ return -1;
+
+ if (!active)
+ {
+ /*
+ * We're not in active mode; let's try to open a new
+ * control connection.
+ */
+ memset(&hints, 0, sizeof(struct addrinfo));
+ hints.ai_family = PF_UNSPEC;
+ hints.ai_socktype = SOCK_STREAM;
+
+ if ((ctrlport == NULL) || (ctrlport[0] == 0))
+ {
+ /* the user chose not to specify the port */
+ if (sock_initaddress(host, RPCAP_DEFAULT_NETPORT, &hints, &addrinfo, fp->errbuf, PCAP_ERRBUF_SIZE) == -1)
+ return -1;
+ }
+ else
+ {
+ /* the user chose not to specify the port */
+ if (sock_initaddress(host, ctrlport, &hints, &addrinfo, fp->errbuf, PCAP_ERRBUF_SIZE) == -1)
+ return -1;
+ }
+
+ if ((sockctrl = sock_open(addrinfo, SOCKOPEN_CLIENT, 0, fp->errbuf, PCAP_ERRBUF_SIZE)) == INVALID_SOCKET)
+ goto error;
+
+ freeaddrinfo(addrinfo);
+ addrinfo = NULL;
+
+ if (rpcap_sendauth(sockctrl, auth, fp->errbuf) == -1)
+ goto error;
+ }
+
+ /*
+ * Now it's time to start playing with the RPCAP protocol
+ * RPCAP open command: create the request message
+ */
+ if (sock_bufferize(NULL, sizeof(struct rpcap_header), NULL,
+ &sendbufidx, RPCAP_NETBUF_SIZE, SOCKBUF_CHECKONLY, fp->errbuf, PCAP_ERRBUF_SIZE))
+ goto error;
+
+ rpcap_createhdr((struct rpcap_header *) sendbuf, RPCAP_MSG_OPEN_REQ, 0, (uint32) strlen(iface));
+
+ if (sock_bufferize(iface, (int) strlen(iface), sendbuf, &sendbufidx,
+ RPCAP_NETBUF_SIZE, SOCKBUF_BUFFERIZE, fp->errbuf, PCAP_ERRBUF_SIZE))
+ goto error;
+
+ if (sock_send(sockctrl, sendbuf, sendbufidx, fp->errbuf, PCAP_ERRBUF_SIZE))
+ goto error;
+
+ /* Receive the RPCAP open reply message */
+ if (sock_recv(sockctrl, (char *)&header, sizeof(struct rpcap_header), SOCK_RECEIVEALL_YES, fp->errbuf, PCAP_ERRBUF_SIZE) == -1)
+ goto error;
+
+ /* Checks if the message is correct */
+ retval = rpcap_checkmsg(fp->errbuf, sockctrl, &header, RPCAP_MSG_OPEN_REPLY, RPCAP_MSG_ERROR, 0);
+
+ if (retval != RPCAP_MSG_OPEN_REPLY) /* the message is not the one expected */
+ {
+ switch (retval)
+ {
+ case -3: /* Unrecoverable network error */
+ case -2: /* The other endpoint send a message that is not allowed here */
+ case -1: /* The other endpoint has a version number that is not compatible with our */
+ goto error;
+
+ case RPCAP_MSG_ERROR: /* The other endpoint reported an error */
+ /* Update totread, since the rpcap_checkmsg() already purged the buffer */
+ totread = ntohl(header.plen);
+ /* Do nothing; just exit; the error code is already into the errbuf */
+ goto error;
+
+ default:
+ pcap_snprintf(fp->errbuf, PCAP_ERRBUF_SIZE, "Internal error");
+ goto error;
+ }
+ }
+
+ nread = sock_recv(sockctrl, (char *)&openreply,
+ sizeof(struct rpcap_openreply), SOCK_RECEIVEALL_YES,
+ fp->errbuf, PCAP_ERRBUF_SIZE);
+ if (nread == -1)
+ goto error;
+ totread += nread;
+
+ /* Set proper fields into the pcap_t struct */
+ fp->linktype = ntohl(openreply.linktype);
+ fp->tzoff = ntohl(openreply.tzoff);
+ md->rmt_sockctrl = sockctrl;
+ md->rmt_clientside = 1;
+
+
+ /* This code is duplicated from the end of this function */
+ fp->read_op = pcap_read_remote;
+ fp->setfilter_op = pcap_setfilter_remote;
+ fp->getnonblock_op = NULL; /* This is not implemented in remote capture */
+ fp->setnonblock_op = NULL; /* This is not implemented in remote capture */
+ fp->stats_op = pcap_stats_remote;
+#ifdef _WIN32
+ fp->stats_ex_op = pcap_stats_ex_remote;
+#endif
+ fp->cleanup_op = pcap_cleanup_remote;
+
+ /* Checks if all the data has been read; if not, discard the data in excess */
+ if (totread != ntohl(header.plen))
+ {
+ if (sock_discard(sockctrl, ntohl(header.plen) - totread, NULL, 0) == 1)
+ goto error;
+ }
+ return 0;
+
+error:
+ /*
+ * When the connection has been established, we have to close it. So, at the
+ * beginning of this function, if an error occur we return immediately with
+ * a return NULL; when the connection is established, we have to come here
+ * ('goto error;') in order to close everything properly.
+ *
+ * Checks if all the data has been read; if not, discard the data in excess
+ */
+ if (totread != ntohl(header.plen))
+ sock_discard(sockctrl, ntohl(header.plen) - totread, NULL, 0);
+
+ if (addrinfo)
+ freeaddrinfo(addrinfo);
+
+ if (!active)
+ sock_close(sockctrl, NULL, 0);
+
+ return -1;
+}
+
+/* \ingroup remote_pri_func
+ *
+ * \brief It starts a remote capture.
+ *
+ * This function is requires since the RPCAP protocol decouples the 'open' from the
+ * 'start capture' functions.
+ * This function takes all the parameters needed (which have been stored into the pcap_t structure)
+ * and sends them to the server.
+ * If everything is fine, it creates a new child thread that reads data from the network
+ * and puts data it into the user buffer.
+ * The pcap_read() will read data from the user buffer, as usual.
+ *
+ * The remote capture acts like a new "kernel", which puts packets directly into
+ * the buffer pointed by pcap_t.
+ * In fact, this function does not rely on a kernel that reads packets and put them
+ * into the user buffer; it has to do that on its own.
+ *
+ * \param fp: the pcap_t descriptor of the device currently open.
+ *
+ * \return '0' if everything is fine, '-1' otherwise. The error message (if one)
+ * is returned into the 'errbuf' field of the pcap_t structure.
+ */
+int pcap_startcapture_remote(pcap_t *fp)
+{
+ char sendbuf[RPCAP_NETBUF_SIZE]; /* temporary buffer in which data to be sent is buffered */
+ int sendbufidx = 0; /* index which keeps the number of bytes currently buffered */
+ char portdata[PCAP_BUF_SIZE]; /* temp variable needed to keep the network port for the the data connection */
+ uint32 totread = 0; /* number of bytes of the payload read from the socket */
+ int nread;
+ int retval; /* store the return value of the functions */
+ int active = 0; /* '1' if we're in active mode */
+ struct activehosts *temp; /* temp var needed to scan the host list chain, to detect if we're in active mode */
+ char host[INET6_ADDRSTRLEN + 1]; /* numeric name of the other host */
+
+ /* socket-related variables*/
+ struct addrinfo hints; /* temp, needed to open a socket connection */
+ struct addrinfo *addrinfo; /* temp, needed to open a socket connection */
+ SOCKET sockdata = 0; /* socket descriptor of the data connection */
+ struct sockaddr_storage saddr; /* temp, needed to retrieve the network data port chosen on the local machine */
+ socklen_t saddrlen; /* temp, needed to retrieve the network data port chosen on the local machine */
+ int ai_family; /* temp, keeps the address family used by the control connection */
+
+ /* RPCAP-related variables*/
+ struct rpcap_header header; /* header of the RPCAP packet */
+ struct rpcap_startcapreq *startcapreq; /* start capture request message */
+ struct rpcap_startcapreply startcapreply; /* start capture reply message */
+
+ /* Variables related to the buffer setting */
+ int res, itemp;
+ int sockbufsize = 0;
+
+ struct pcap_md *md; /* structure used when doing a remote live capture */
+
+ md = (struct pcap_md *) ((u_char*)fp->priv + sizeof(struct pcap_win));
+
+ /*
+ * Let's check if sampling has been required.
+ * If so, let's set it first
+ */
+ if (pcap_setsampling_remote(fp) != 0)
+ return -1;
+
+
+ /* detect if we're in active mode */
+ temp = activeHosts;
+ while (temp)
+ {
+ if (temp->sockctrl == md->rmt_sockctrl)
+ {
+ active = 1;
+ break;
+ }
+ temp = temp->next;
+ }
+
+ addrinfo = NULL;
+
+ /*
+ * Gets the complete sockaddr structure used in the ctrl connection
+ * This is needed to get the address family of the control socket
+ * Tip: I cannot save the ai_family of the ctrl sock in the pcap_t struct,
+ * since the ctrl socket can already be open in case of active mode;
+ * so I would have to call getpeername() anyway
+ */
+ saddrlen = sizeof(struct sockaddr_storage);
+ if (getpeername(md->rmt_sockctrl, (struct sockaddr *) &saddr, &saddrlen) == -1)
+ {
+ sock_geterror("getsockname(): ", fp->errbuf, PCAP_ERRBUF_SIZE);
+ goto error;
+ }
+ ai_family = ((struct sockaddr_storage *) &saddr)->ss_family;
+
+ /* Get the numeric address of the remote host we are connected to */
+ if (getnameinfo((struct sockaddr *) &saddr, saddrlen, host,
+ sizeof(host), NULL, 0, NI_NUMERICHOST))
+ {
+ sock_geterror("getnameinfo(): ", fp->errbuf, PCAP_ERRBUF_SIZE);
+ goto error;
+ }
+
+ /*
+ * Data connection is opened by the server toward the client if:
+ * - we're using TCP, and the user wants us to be in active mode
+ * - we're using UDP
+ */
+ if ((active) || (md->rmt_flags & PCAP_OPENFLAG_DATATX_UDP))
+ {
+ /*
+ * We have to create a new socket to receive packets
+ * We have to do that immediately, since we have to tell the other
+ * end which network port we picked up
+ */
+ memset(&hints, 0, sizeof(struct addrinfo));
+ /* TEMP addrinfo is NULL in case of active */
+ hints.ai_family = ai_family; /* Use the same address family of the control socket */
+ hints.ai_socktype = (md->rmt_flags & PCAP_OPENFLAG_DATATX_UDP) ? SOCK_DGRAM : SOCK_STREAM;
+ hints.ai_flags = AI_PASSIVE; /* Data connection is opened by the server toward the client */
+
+ /* Let's the server pick up a free network port for us */
+ if (sock_initaddress(NULL, "0", &hints, &addrinfo, fp->errbuf, PCAP_ERRBUF_SIZE) == -1)
+ goto error;
+
+ if ((sockdata = sock_open(addrinfo, SOCKOPEN_SERVER,
+ 1 /* max 1 connection in queue */, fp->errbuf, PCAP_ERRBUF_SIZE)) == INVALID_SOCKET)
+ goto error;
+
+ /* addrinfo is no longer used */
+ freeaddrinfo(addrinfo);
+ addrinfo = NULL;
+
+ /* get the complete sockaddr structure used in the data connection */
+ saddrlen = sizeof(struct sockaddr_storage);
+ if (getsockname(sockdata, (struct sockaddr *) &saddr, &saddrlen) == -1)
+ {
+ sock_geterror("getsockname(): ", fp->errbuf, PCAP_ERRBUF_SIZE);
+ goto error;
+ }
+
+ /* Get the local port the system picked up */
+ if (getnameinfo((struct sockaddr *) &saddr, saddrlen, NULL,
+ 0, portdata, sizeof(portdata), NI_NUMERICSERV))
+ {
+ sock_geterror("getnameinfo(): ", fp->errbuf, PCAP_ERRBUF_SIZE);
+ goto error;
+ }
+ }
+
+ /*
+ * Now it's time to start playing with the RPCAP protocol
+ * RPCAP start capture command: create the request message
+ */
+ if (sock_bufferize(NULL, sizeof(struct rpcap_header), NULL,
+ &sendbufidx, RPCAP_NETBUF_SIZE, SOCKBUF_CHECKONLY, fp->errbuf, PCAP_ERRBUF_SIZE))
+ goto error;
+
+ rpcap_createhdr((struct rpcap_header *) sendbuf, RPCAP_MSG_STARTCAP_REQ, 0,
+ sizeof(struct rpcap_startcapreq) + sizeof(struct rpcap_filter) + fp->fcode.bf_len * sizeof(struct rpcap_filterbpf_insn));
+
+ /* Fill the structure needed to open an adapter remotely */
+ startcapreq = (struct rpcap_startcapreq *) &sendbuf[sendbufidx];
+
+ if (sock_bufferize(NULL, sizeof(struct rpcap_startcapreq), NULL,
+ &sendbufidx, RPCAP_NETBUF_SIZE, SOCKBUF_CHECKONLY, fp->errbuf, PCAP_ERRBUF_SIZE))
+ goto error;
+
+ memset(startcapreq, 0, sizeof(struct rpcap_startcapreq));
+
+ /* By default, apply half the timeout on one side, half of the other */
+ fp->opt.timeout = fp->opt.timeout / 2;
+ startcapreq->read_timeout = htonl(fp->opt.timeout);
+
+ /* portdata on the openreq is meaningful only if we're in active mode */
+ if ((active) || (md->rmt_flags & PCAP_OPENFLAG_DATATX_UDP))
+ {
+ sscanf(portdata, "%d", (int *)&(startcapreq->portdata)); /* cast to avoid a compiler warning */
+ startcapreq->portdata = htons(startcapreq->portdata);
+ }
+
+ startcapreq->snaplen = htonl(fp->snapshot);
+ startcapreq->flags = 0;
+
+ if (md->rmt_flags & PCAP_OPENFLAG_PROMISCUOUS)
+ startcapreq->flags |= RPCAP_STARTCAPREQ_FLAG_PROMISC;
+ if (md->rmt_flags & PCAP_OPENFLAG_DATATX_UDP)
+ startcapreq->flags |= RPCAP_STARTCAPREQ_FLAG_DGRAM;
+ if (active)
+ startcapreq->flags |= RPCAP_STARTCAPREQ_FLAG_SERVEROPEN;
+
+ startcapreq->flags = htons(startcapreq->flags);
+
+ /* Pack the capture filter */
+ if (pcap_pack_bpffilter(fp, &sendbuf[sendbufidx], &sendbufidx, &fp->fcode))
+ goto error;
+
+ if (sock_send(md->rmt_sockctrl, sendbuf, sendbufidx, fp->errbuf, PCAP_ERRBUF_SIZE))
+ goto error;
+
+
+ /* Receive the RPCAP start capture reply message */
+ if (sock_recv(md->rmt_sockctrl, (char *)&header, sizeof(struct rpcap_header), SOCK_RECEIVEALL_YES, fp->errbuf, PCAP_ERRBUF_SIZE) == -1)
+ goto error;
+
+ /* Checks if the message is correct */
+ retval = rpcap_checkmsg(fp->errbuf, md->rmt_sockctrl, &header, RPCAP_MSG_STARTCAP_REPLY, RPCAP_MSG_ERROR, 0);
+
+ if (retval != RPCAP_MSG_STARTCAP_REPLY) /* the message is not the one expected */
+ {
+ switch (retval)
+ {
+ case -3: /* Unrecoverable network error */
+ case -2: /* The other endpoint send a message that is not allowed here */
+ case -1: /* The other endpoint has a version number that is not compatible with our */
+ goto error;
+
+ case RPCAP_MSG_ERROR: /* The other endpoint reported an error */
+ /* Update totread, since the rpcap_checkmsg() already purged the buffer */
+ totread = ntohl(header.plen);
+ /* Do nothing; just exit; the error code is already into the errbuf */
+ goto error;
+
+ default:
+ pcap_snprintf(fp->errbuf, PCAP_ERRBUF_SIZE, "Internal error");
+ goto error;
+ }
+ }
+
+ nread = sock_recv(md->rmt_sockctrl, (char *)&startcapreply,
+ sizeof(struct rpcap_startcapreply), SOCK_RECEIVEALL_YES,
+ fp->errbuf, PCAP_ERRBUF_SIZE);
+ if (nread == -1)
+ goto error;
+ totread += nread;
+
+ /*
+ * In case of UDP data stream, the connection is always opened by the daemon
+ * So, this case is already covered by the code above.
+ * Now, we have still to handle TCP connections, because:
+ * - if we're in active mode, we have to wait for a remote connection
+ * - if we're in passive more, we have to start a connection
+ *
+ * We have to do he job in two steps because in case we're opening a TCP connection, we have
+ * to tell the port we're using to the remote side; in case we're accepting a TCP
+ * connection, we have to wait this info from the remote side.
+ */
+
+ if (!(md->rmt_flags & PCAP_OPENFLAG_DATATX_UDP))
+ {
+ if (!active)
+ {
+ memset(&hints, 0, sizeof(struct addrinfo));
+ hints.ai_family = ai_family; /* Use the same address family of the control socket */
+ hints.ai_socktype = (md->rmt_flags & PCAP_OPENFLAG_DATATX_UDP) ? SOCK_DGRAM : SOCK_STREAM;
+ pcap_snprintf(portdata, PCAP_BUF_SIZE, "%d", ntohs(startcapreply.portdata));
+
+ /* Let's the server pick up a free network port for us */
+ if (sock_initaddress(host, portdata, &hints, &addrinfo, fp->errbuf, PCAP_ERRBUF_SIZE) == -1)
+ goto error;
+
+ if ((sockdata = sock_open(addrinfo, SOCKOPEN_CLIENT, 0, fp->errbuf, PCAP_ERRBUF_SIZE)) == INVALID_SOCKET)
+ goto error;
+
+ /* addrinfo is no longer used */
+ freeaddrinfo(addrinfo);
+ addrinfo = NULL;
+ }
+ else
+ {
+ SOCKET socktemp; /* We need another socket, since we're going to accept() a connection */
+
+ /* Connection creation */
+ saddrlen = sizeof(struct sockaddr_storage);
+
+ socktemp = accept(sockdata, (struct sockaddr *) &saddr, &saddrlen);
+
+ if (socktemp == -1)
+ {
+ sock_geterror("accept(): ", fp->errbuf, PCAP_ERRBUF_SIZE);
+ goto error;
+ }
+
+ /* Now that I accepted the connection, the server socket is no longer needed */
+ sock_close(sockdata, fp->errbuf, PCAP_ERRBUF_SIZE);
+ sockdata = socktemp;
+ }
+ }
+
+ /* Let's save the socket of the data connection */
+ md->rmt_sockdata = sockdata;
+
+ /* Allocates WinPcap/libpcap user buffer, which is a socket buffer in case of a remote capture */
+ /* It has the same size of the one used on the other side of the connection */
+ fp->bufsize = ntohl(startcapreply.bufsize);
+
+ /* Let's get the actual size of the socket buffer */
+ itemp = sizeof(sockbufsize);
+
+ res = getsockopt(sockdata, SOL_SOCKET, SO_RCVBUF, (char *)&sockbufsize, &itemp);
+ if (res == -1)
+ {
+ sock_geterror("pcap_startcapture_remote()", fp->errbuf, PCAP_ERRBUF_SIZE);
+ SOCK_ASSERT(fp->errbuf, 1);
+ }
+
+ /*
+ * Warning: on some kernels (e.g. Linux), the size of the user buffer does not take
+ * into account the pcap_header and such, and it is set equal to the snaplen.
+ * In my view, this is wrong (the meaning of the bufsize became a bit strange).
+ * So, here bufsize is the whole size of the user buffer.
+ * In case the bufsize returned is too small, let's adjust it accordingly.
+ */
+ if (fp->bufsize <= (u_int) fp->snapshot)
+ fp->bufsize += sizeof(struct pcap_pkthdr);
+
+ /* if the current socket buffer is smaller than the desired one */
+ if ((u_int) sockbufsize < fp->bufsize)
+ {
+ /* Loop until the buffer size is OK or the original socket buffer size is larger than this one */
+ while (1)
+ {
+ res = setsockopt(sockdata, SOL_SOCKET, SO_RCVBUF, (char *)&(fp->bufsize), sizeof(fp->bufsize));
+
+ if (res == 0)
+ break;
+
+ /*
+ * If something goes wrong, half the buffer size (checking that it does not become smaller than
+ * the current one)
+ */
+ fp->bufsize /= 2;
+
+ if ((u_int) sockbufsize >= fp->bufsize)
+ {
+ fp->bufsize = sockbufsize;
+ break;
+ }
+ }
+ }
+
+ /*
+ * Let's allocate the packet; this is required in order to put the packet somewhere when
+ * extracting data from the socket
+ * Since buffering has already been done in the socket buffer, here we need just a buffer,
+ * whose size is equal to the pcap header plus the snapshot length
+ */
+ fp->bufsize = fp->snapshot + sizeof(struct pcap_pkthdr);
+
+ fp->buffer = (u_char *)malloc(fp->bufsize);
+ if (fp->buffer == NULL)
+ {
+ pcap_snprintf(fp->errbuf, PCAP_ERRBUF_SIZE, "malloc: %s", pcap_strerror(errno));
+ goto error;
+ }
+
+
+ /* Checks if all the data has been read; if not, discard the data in excess */
+ if (totread != ntohl(header.plen))
+ {
+ if (sock_discard(md->rmt_sockctrl, ntohl(header.plen) - totread, NULL, 0) == 1)
+ goto error;
+ }
+
+ /*
+ * In case the user does not want to capture RPCAP packets, let's update the filter
+ * We have to update it here (instead of sending it into the 'StartCapture' message
+ * because when we generate the 'start capture' we do not know (yet) all the ports
+ * we're currently using.
+ */
+ if (md->rmt_flags & PCAP_OPENFLAG_NOCAPTURE_RPCAP)
+ {
+ struct bpf_program fcode;
+
+ if (pcap_createfilter_norpcappkt(fp, &fcode) == -1)
+ goto error;
+
+ /* We cannot use 'pcap_setfilter_remote' because formally the capture has not been started yet */
+ /* (the 'fp->rmt_capstarted' variable will be updated some lines below) */
+ if (pcap_updatefilter_remote(fp, &fcode) == -1)
+ goto error;
+
+ pcap_freecode(&fcode);
+ }
+
+ md->rmt_capstarted = 1;
+ return 0;
+
+error:
+ /*
+ * When the connection has been established, we have to close it. So, at the
+ * beginning of this function, if an error occur we return immediately with
+ * a return NULL; when the connection is established, we have to come here
+ * ('goto error;') in order to close everything properly.
+ *
+ * Checks if all the data has been read; if not, discard the data in excess
+ */
+ if (totread != ntohl(header.plen))
+ sock_discard(md->rmt_sockctrl, ntohl(header.plen) - totread, NULL, 0);
+
+ if ((sockdata) && (sockdata != -1)) /* we can be here because sockdata said 'error' */
+ sock_close(sockdata, NULL, 0);
+
+ if (!active)
+ sock_close(md->rmt_sockctrl, NULL, 0);
+
+ /*
+ * We do not have to call pcap_close() here, because this function is always called
+ * by the user in case something bad happens
+ */
+ // if (fp)
+ // {
+ // pcap_close(fp);
+ // fp= NULL;
+ // }
+
+ return -1;
+}
+
+/*
+ * \brief Takes a bpf program and sends it to the other host.
+ *
+ * This function can be called in two cases:
+ * - the pcap_startcapture() is called (we have to send the filter along with
+ * the 'start capture' command)
+ * - we want to udpate the filter during a capture (i.e. the pcap_setfilter()
+ * is called when the capture is still on)
+ *
+ * This function serializes the filter into the sending buffer ('sendbuf', passed
+ * as a parameter) and return back. It does not send anything on the network.
+ *
+ * \param fp: the pcap_t descriptor of the device currently opened.
+ *
+ * \param sendbuf: the buffer on which the serialized data has to copied.
+ *
+ * \param sendbufidx: it is used to return the abounf of bytes copied into the buffer.
+ *
+ * \param prog: the bpf program we have to copy.
+ *
+ * \return '0' if everything is fine, '-1' otherwise. The error message (if one)
+ * is returned into the 'errbuf' field of the pcap_t structure.
+ */
+static int pcap_pack_bpffilter(pcap_t *fp, char *sendbuf, int *sendbufidx, struct bpf_program *prog)
+{
+ struct rpcap_filter *filter;
+ struct rpcap_filterbpf_insn *insn;
+ struct bpf_insn *bf_insn;
+ struct bpf_program fake_prog; /* To be used just in case the user forgot to set a filter */
+ unsigned int i;
+
+
+ if (prog->bf_len == 0) /* No filters have been specified; so, let's apply a "fake" filter */
+ {
+ if (pcap_compile(fp, &fake_prog, NULL /* buffer */, 1, 0) == -1)
+ return -1;
+
+ prog = &fake_prog;
+ }
+
+ filter = (struct rpcap_filter *) sendbuf;
+
+ if (sock_bufferize(NULL, sizeof(struct rpcap_filter), NULL, sendbufidx,
+ RPCAP_NETBUF_SIZE, SOCKBUF_CHECKONLY, fp->errbuf, PCAP_ERRBUF_SIZE))
+ return -1;
+
+ filter->filtertype = htons(RPCAP_UPDATEFILTER_BPF);
+ filter->nitems = htonl((int32)prog->bf_len);
+
+ if (sock_bufferize(NULL, prog->bf_len * sizeof(struct rpcap_filterbpf_insn),
+ NULL, sendbufidx, RPCAP_NETBUF_SIZE, SOCKBUF_CHECKONLY, fp->errbuf, PCAP_ERRBUF_SIZE))
+ return -1;
+
+ insn = (struct rpcap_filterbpf_insn *) (filter + 1);
+ bf_insn = prog->bf_insns;
+
+ for (i = 0; i < prog->bf_len; i++)
+ {
+ insn->code = htons(bf_insn->code);
+ insn->jf = bf_insn->jf;
+ insn->jt = bf_insn->jt;
+ insn->k = htonl(bf_insn->k);
+
+ insn++;
+ bf_insn++;
+ }
+
+ return 0;
+}
+
+/* \ingroup remote_pri_func
+ *
+ * \brief Update a filter on a remote host.
+ *
+ * This function is called when the user wants to update a filter.
+ * In case we're capturing from the network, it sends the filter to the other peer.
+ * This function is *not* called automatically when the user calls the pcap_setfilter().
+ * There will be two cases:
+ * - the capture is already on: in this case, pcap_setfilter() calls pcap_updatefilter_remote()
+ * - the capture has not started yet: in this case, pcap_setfilter() stores the filter into
+ * the pcap_t structure, and then the filter is sent with the pcap_startcap().
+ *
+ * Parameters and return values are exactly the same of the pcap_setfilter().
+ *
+ * \warning This function *does not* clear the packet currently into the buffers. Therefore,
+ * the user has to expect to receive some packets that are related to the previous filter.
+ * If you want to discard all the packets before applying a new filter, you have to close
+ * the current capture session and start a new one.
+ */
+static int pcap_updatefilter_remote(pcap_t *fp, struct bpf_program *prog)
+{
+ int retval; /* general variable used to keep the return value of other functions */
+ char sendbuf[RPCAP_NETBUF_SIZE];/* temporary buffer in which data to be sent is buffered */
+ int sendbufidx = 0; /* index which keeps the number of bytes currently buffered */
+ struct rpcap_header header; /* To keep the reply message */
+ struct pcap_md *md; /* structure used when doing a remote live capture */
+
+ md = (struct pcap_md *) ((u_char*)fp->priv + sizeof(struct pcap_win));
+
+
+ if (sock_bufferize(NULL, sizeof(struct rpcap_header), NULL, &sendbufidx,
+ RPCAP_NETBUF_SIZE, SOCKBUF_CHECKONLY, fp->errbuf, PCAP_ERRBUF_SIZE))
+ return -1;
+
+ rpcap_createhdr((struct rpcap_header *) sendbuf, RPCAP_MSG_UPDATEFILTER_REQ, 0,
+ sizeof(struct rpcap_filter) + prog->bf_len * sizeof(struct rpcap_filterbpf_insn));
+
+ if (pcap_pack_bpffilter(fp, &sendbuf[sendbufidx], &sendbufidx, prog))
+ return -1;
+
+ if (sock_send(md->rmt_sockctrl, sendbuf, sendbufidx, fp->errbuf, PCAP_ERRBUF_SIZE))
+ return -1;
+
+ /* Waits for the answer */
+ if (sock_recv(md->rmt_sockctrl, (char *)&header, sizeof(struct rpcap_header), SOCK_RECEIVEALL_YES, fp->errbuf, PCAP_ERRBUF_SIZE) == -1)
+ return -1;
+
+ /* Checks if the message is correct */
+ retval = rpcap_checkmsg(fp->errbuf, md->rmt_sockctrl, &header, RPCAP_MSG_UPDATEFILTER_REPLY, 0);
+
+ if (retval != RPCAP_MSG_UPDATEFILTER_REPLY) /* the message is not the one expected */
+ {
+ switch (retval)
+ {
+ case -3: /* Unrecoverable network error */
+ case -2: /* The other endpoint sent a message that is not allowed here */
+ case -1: /* The other endpoint has a version number that is not compatible with our */
+ /* Do nothing; just exit from here; the error code is already into the errbuf */
+ return -1;
+
+ default:
+ SOCK_ASSERT("Internal error", 0);
+ return -1;
+ }
+ }
+
+ if (ntohl(header.plen) != 0) /* the message has an unexpected size */
+ {
+ if (sock_discard(md->rmt_sockctrl, ntohl(header.plen), fp->errbuf, PCAP_ERRBUF_SIZE) == -1)
+ return -1;
+ }
+
+ return 0;
+}
+
+/*
+ * \ingroup remote_pri_func
+ *
+ * \brief Send a filter to a remote host.
+ *
+ * This function is called when the user wants to set a filter.
+ * In case we're capturing from the network, it sends the filter to the other peer.
+ * This function is called automatically when the user calls the pcap_setfilter().
+ *
+ * Parameters and return values are exactly the same of the pcap_setfilter().
+ */
+static int pcap_setfilter_remote(pcap_t *fp, struct bpf_program *prog)
+{
+ struct pcap_md *md; /* structure used when doing a remote live capture */
+
+ md = (struct pcap_md *) ((u_char*)fp->priv + sizeof(struct pcap_win));
+
+ if (!md->rmt_capstarted)
+ {
+ /* copy filter into the pcap_t structure */
+ if (install_bpf_program(fp, prog) == -1)
+ return -1;
+ return 0;
+ }
+
+ /* we have to update a filter during run-time */
+ if (pcap_updatefilter_remote(fp, prog))
+ return -1;
+
+ return 0;
+}
+
+/*
+ * \ingroup remote_pri_func
+ *
+ * \brief Update the current filter in order not to capture rpcap packets.
+ *
+ * This function is called *only* when the user wants exclude RPCAP packets
+ * related to the current session from the captured packets.
+ *
+ * \return '0' if everything is fine, '-1' otherwise. The error message (if one)
+ * is returned into the 'errbuf' field of the pcap_t structure.
+ */
+static int pcap_createfilter_norpcappkt(pcap_t *fp, struct bpf_program *prog)
+{
+ int RetVal = 0;
+ struct pcap_md *md; /* structure used when doing a remote live capture */
+
+ md = (struct pcap_md *) ((u_char*)fp->priv + sizeof(struct pcap_win));
+
+ /* We do not want to capture our RPCAP traffic. So, let's update the filter */
+ if (md->rmt_flags & PCAP_OPENFLAG_NOCAPTURE_RPCAP)
+ {
+ struct sockaddr_storage saddr; /* temp, needed to retrieve the network data port chosen on the local machine */
+ socklen_t saddrlen; /* temp, needed to retrieve the network data port chosen on the local machine */
+ char myaddress[128];
+ char myctrlport[128];
+ char mydataport[128];
+ char peeraddress[128];
+ char peerctrlport[128];
+ char *newfilter;
+ const int newstringsize = 1024;
+ size_t currentfiltersize;
+
+ /* Get the name/port of the other peer */
+ saddrlen = sizeof(struct sockaddr_storage);
+ if (getpeername(md->rmt_sockctrl, (struct sockaddr *) &saddr, &saddrlen) == -1)
+ {
+ sock_geterror("getpeername(): ", fp->errbuf, PCAP_ERRBUF_SIZE);
+ return -1;
+ }
+
+ if (getnameinfo((struct sockaddr *) &saddr, saddrlen, peeraddress,
+ sizeof(peeraddress), peerctrlport, sizeof(peerctrlport), NI_NUMERICHOST | NI_NUMERICSERV))
+ {
+ sock_geterror("getnameinfo(): ", fp->errbuf, PCAP_ERRBUF_SIZE);
+ return -1;
+ }
+
+ /* We cannot check the data port, because this is available only in case of TCP sockets */
+ /* Get the name/port of the current host */
+ if (getsockname(md->rmt_sockctrl, (struct sockaddr *) &saddr, &saddrlen) == -1)
+ {
+ sock_geterror("getsockname(): ", fp->errbuf, PCAP_ERRBUF_SIZE);
+ return -1;
+ }
+
+ /* Get the local port the system picked up */
+ if (getnameinfo((struct sockaddr *) &saddr, saddrlen, myaddress,
+ sizeof(myaddress), myctrlport, sizeof(myctrlport), NI_NUMERICHOST | NI_NUMERICSERV))
+ {
+ sock_geterror("getnameinfo(): ", fp->errbuf, PCAP_ERRBUF_SIZE);
+ return -1;
+ }
+
+ /* Let's now check the data port */
+ if (getsockname(md->rmt_sockdata, (struct sockaddr *) &saddr, &saddrlen) == -1)
+ {
+ sock_geterror("getsockname(): ", fp->errbuf, PCAP_ERRBUF_SIZE);
+ return -1;
+ }
+
+ /* Get the local port the system picked up */
+ if (getnameinfo((struct sockaddr *) &saddr, saddrlen, NULL, 0, mydataport, sizeof(mydataport), NI_NUMERICSERV))
+ {
+ sock_geterror("getnameinfo(): ", fp->errbuf, PCAP_ERRBUF_SIZE);
+ return -1;
+ }
+
+ currentfiltersize = strlen(md->currentfilter);
+
+ newfilter = (char *)malloc(currentfiltersize + newstringsize + 1);
+
+ if (currentfiltersize)
+ {
+ pcap_snprintf(newfilter, currentfiltersize + newstringsize,
+ "(%s) and not (host %s and host %s and port %s and port %s) and not (host %s and host %s and port %s)",
+ md->currentfilter, myaddress, peeraddress, myctrlport, peerctrlport, myaddress, peeraddress, mydataport);
+ }
+ else
+ {
+ pcap_snprintf(newfilter, currentfiltersize + newstringsize,
+ "not (host %s and host %s and port %s and port %s) and not (host %s and host %s and port %s)",
+ myaddress, peeraddress, myctrlport, peerctrlport, myaddress, peeraddress, mydataport);
+ }
+
+ newfilter[currentfiltersize + newstringsize] = 0;
+
+ /* This is only an hack to make the pcap_compile() working properly */
+ md->rmt_clientside = 0;
+
+ if (pcap_compile(fp, prog, newfilter, 1, 0) == -1)
+ RetVal = -1;
+
+ /* This is only an hack to make the pcap_compile() working properly */
+ md->rmt_clientside = 1;
+
+ free(newfilter);
+ }
+
+ return RetVal;
+}
+
+/*
+ * \ingroup remote_pri_func
+ *
+ * \brief Set sampling parameters in the remote host.
+ *
+ * This function is called when the user wants to set activate sampling on the remote host.
+ *
+ * Sampling parameters are defined into the 'pcap_t' structure.
+ *
+ * \param p: the pcap_t descriptor of the device currently opened.
+ *
+ * \return '0' if everything is OK, '-1' is something goes wrong. The error message is returned
+ * in the 'errbuf' member of the pcap_t structure.
+ */
+static int pcap_setsampling_remote(pcap_t *p)
+{
+ int retval; /* general variable used to keep the return value of other functions */
+ char sendbuf[RPCAP_NETBUF_SIZE];/* temporary buffer in which data to be sent is buffered */
+ int sendbufidx = 0; /* index which keeps the number of bytes currently buffered */
+ struct rpcap_header header; /* To keep the reply message */
+ struct rpcap_sampling *sampling_pars; /* Structure that is needed to send sampling parameters to the remote host */
+ struct pcap_md *md; /* structure used when doing a remote live capture */
+
+ md = (struct pcap_md *) ((u_char*)p->priv + sizeof(struct pcap_win));
+
+ /* If no samping is requested, return 'ok' */
+ if (md->rmt_samp.method == PCAP_SAMP_NOSAMP)
+ return 0;
+
+ if (sock_bufferize(NULL, sizeof(struct rpcap_header), NULL,
+ &sendbufidx, RPCAP_NETBUF_SIZE, SOCKBUF_CHECKONLY, p->errbuf, PCAP_ERRBUF_SIZE))
+ return -1;
+
+ rpcap_createhdr((struct rpcap_header *) sendbuf, RPCAP_MSG_SETSAMPLING_REQ, 0, sizeof(struct rpcap_sampling));
+
+ /* Fill the structure needed to open an adapter remotely */
+ sampling_pars = (struct rpcap_sampling *) &sendbuf[sendbufidx];
+
+ if (sock_bufferize(NULL, sizeof(struct rpcap_sampling), NULL,
+ &sendbufidx, RPCAP_NETBUF_SIZE, SOCKBUF_CHECKONLY, p->errbuf, PCAP_ERRBUF_SIZE))
+ return -1;
+
+ memset(sampling_pars, 0, sizeof(struct rpcap_sampling));
+
+ sampling_pars->method = md->rmt_samp.method;
+ sampling_pars->value = htonl(md->rmt_samp.value);
+
+ if (sock_send(md->rmt_sockctrl, sendbuf, sendbufidx, p->errbuf, PCAP_ERRBUF_SIZE))
+ return -1;
+
+ /* Waits for the answer */
+ if (sock_recv(md->rmt_sockctrl, (char *)&header, sizeof(struct rpcap_header), SOCK_RECEIVEALL_YES, p->errbuf, PCAP_ERRBUF_SIZE) == -1)
+ return -1;
+
+ /* Checks if the message is correct */
+ retval = rpcap_checkmsg(p->errbuf, md->rmt_sockctrl, &header, RPCAP_MSG_SETSAMPLING_REPLY, 0);
+
+ if (retval != RPCAP_MSG_SETSAMPLING_REPLY) /* the message is not the one expected */
+ {
+ switch (retval)
+ {
+ case -3: /* Unrecoverable network error */
+ case -2: /* The other endpoint sent a message that is not allowed here */
+ case -1: /* The other endpoint has a version number that is not compatible with our */
+ case RPCAP_MSG_ERROR:
+ /* Do nothing; just exit from here; the error code is already into the errbuf */
+ return -1;
+
+ default:
+ SOCK_ASSERT("Internal error", 0);
+ return -1;
+ }
+ }
+
+ if (ntohl(header.plen) != 0) /* the message has an unexpected size */
+ {
+ if (sock_discard(md->rmt_sockctrl, ntohl(header.plen), p->errbuf, PCAP_ERRBUF_SIZE) == -1)
+ return -1;
+ }
+
+ return 0;
+
+}
+
+/*********************************************************
+ * *
+ * Miscellaneous functions *
+ * *
+ *********************************************************/
+
+
+/* \ingroup remote_pri_func
+ * \brief It sends a RPCAP error to the other peer.
+ *
+ * This function has to be called when the main program detects an error. This function
+ * will send on the other peer the 'buffer' specified by the user.
+ * This function *does not* request a RPCAP CLOSE connection. A CLOSE command must be sent
+ * explicitly by the program, since we do not know it the error can be recovered in some
+ * way or it is a non-recoverable one.
+ *
+ * \param sock: the socket we are currently using.
+ *
+ * \param error: an user-allocated (and '0' terminated) buffer that contains the error
+ * description that has to be transmitted on the other peer. The error message cannot
+ * be longer than PCAP_ERRBUF_SIZE.
+ *
+ * \param errcode: a integer which tells the other party the type of error we had;
+ * currently is is not too much used.
+ *
+ * \param errbuf: a pointer to a user-allocated buffer (of size PCAP_ERRBUF_SIZE)
+ * that will contain the error message (in case there is one). It could be network problem.
+ *
+ * \return '0' if everything is fine, '-1' if some errors occurred. The error message is returned
+ * in the 'errbuf' variable.
+ */
+int rpcap_senderror(SOCKET sock, char *error, unsigned short errcode, char *errbuf)
+{
+ char sendbuf[RPCAP_NETBUF_SIZE]; /* temporary buffer in which data to be sent is buffered */
+ int sendbufidx = 0; /* index which keeps the number of bytes currently buffered */
+ uint16 length;
+
+ length = (uint16)strlen(error);
+
+ if (length > PCAP_ERRBUF_SIZE)
+ length = PCAP_ERRBUF_SIZE;
+
+ rpcap_createhdr((struct rpcap_header *) sendbuf, RPCAP_MSG_ERROR, errcode, length);
+
+ if (sock_bufferize(NULL, sizeof(struct rpcap_header), NULL, &sendbufidx,
+ RPCAP_NETBUF_SIZE, SOCKBUF_CHECKONLY, errbuf, PCAP_ERRBUF_SIZE))
+ return -1;
+
+ if (sock_bufferize(error, length, sendbuf, &sendbufidx,
+ RPCAP_NETBUF_SIZE, SOCKBUF_BUFFERIZE, errbuf, PCAP_ERRBUF_SIZE))
+ return -1;
+
+ if (sock_send(sock, sendbuf, sendbufidx, errbuf, PCAP_ERRBUF_SIZE))
+ return -1;
+
+ return 0;
+}
+
+/* \ingroup remote_pri_func
+ * \brief Sends the authentication message.
+ *
+ * It sends the authentication parameters on the control socket.
+ * This function is required in order to open the connection with the other end party.
+ *
+ * \param sock: the socket we are currently using.
+ *
+ * \param auth: authentication parameters that have to be sent.
+ *
+ * \param errbuf: a pointer to a user-allocated buffer (of size PCAP_ERRBUF_SIZE)
+ * that will contain the error message (in case there is one). It could be network problem
+ * of the fact that the authorization failed.
+ *
+ * \return '0' if everything is fine, '-1' if some errors occurred. The error message is returned
+ * in the 'errbuf' variable.
+ * The error message could be also 'the authentication failed'.
+ */
+int rpcap_sendauth(SOCKET sock, struct pcap_rmtauth *auth, char *errbuf)
+{
+ char sendbuf[RPCAP_NETBUF_SIZE]; /* temporary buffer in which data that has to be sent is buffered */
+ int sendbufidx = 0; /* index which keeps the number of bytes currently buffered */
+ uint16 length; /* length of the payload of this message */
+ struct rpcap_auth *rpauth;
+ uint16 auth_type;
+ struct rpcap_header header;
+ int retval; /* temp variable which stores functions return value */
+
+ if (auth)
+ {
+ auth_type = auth->type;
+
+ switch (auth->type)
+ {
+ case RPCAP_RMTAUTH_NULL:
+ length = sizeof(struct rpcap_auth);
+ break;
+
+ case RPCAP_RMTAUTH_PWD:
+ length = sizeof(struct rpcap_auth);
+ if (auth->username) length += (uint16) strlen(auth->username);
+ if (auth->password) length += (uint16) strlen(auth->password);
+ break;
+
+ default:
+ pcap_snprintf(errbuf, PCAP_ERRBUF_SIZE, "Authentication type not recognized.");
+ return -1;
+ }
+ }
+ else
+ {
+ auth_type = RPCAP_RMTAUTH_NULL;
+ length = sizeof(struct rpcap_auth);
+ }
+
+
+ if (sock_bufferize(NULL, sizeof(struct rpcap_header), NULL,
+ &sendbufidx, RPCAP_NETBUF_SIZE, SOCKBUF_CHECKONLY, errbuf, PCAP_ERRBUF_SIZE))
+ return -1;
+
+ rpcap_createhdr((struct rpcap_header *) sendbuf, RPCAP_MSG_AUTH_REQ, 0, length);
+
+ rpauth = (struct rpcap_auth *) &sendbuf[sendbufidx];
+
+ if (sock_bufferize(NULL, sizeof(struct rpcap_auth), NULL,
+ &sendbufidx, RPCAP_NETBUF_SIZE, SOCKBUF_CHECKONLY, errbuf, PCAP_ERRBUF_SIZE))
+ return -1;
+
+ memset(rpauth, 0, sizeof(struct rpcap_auth));
+
+ rpauth->type = htons(auth_type);
+
+ if (auth_type == RPCAP_RMTAUTH_PWD)
+ {
+
+ if (auth->username)
+ rpauth->slen1 = (uint16) strlen(auth->username);
+ else
+ rpauth->slen1 = 0;
+
+ if (sock_bufferize(auth->username, rpauth->slen1, sendbuf,
+ &sendbufidx, RPCAP_NETBUF_SIZE, SOCKBUF_BUFFERIZE, errbuf, PCAP_ERRBUF_SIZE))
+ return -1;
+
+ if (auth->password)
+ rpauth->slen2 = (uint16) strlen(auth->password);
+ else
+ rpauth->slen2 = 0;
+
+ if (sock_bufferize(auth->password, rpauth->slen2, sendbuf,
+ &sendbufidx, RPCAP_NETBUF_SIZE, SOCKBUF_BUFFERIZE, errbuf, PCAP_ERRBUF_SIZE))
+ return -1;
+
+ rpauth->slen1 = htons(rpauth->slen1);
+ rpauth->slen2 = htons(rpauth->slen2);
+ }
+
+ if (sock_send(sock, sendbuf, sendbufidx, errbuf, PCAP_ERRBUF_SIZE))
+ return -1;
+
+ if (sock_recv(sock, (char *)&header, sizeof(struct rpcap_header), SOCK_RECEIVEALL_YES, errbuf, PCAP_ERRBUF_SIZE) == -1)
+ return -1;
+
+ retval = rpcap_checkmsg(errbuf, sock, &header, RPCAP_MSG_AUTH_REPLY, RPCAP_MSG_ERROR, 0);
+
+ if (retval != RPCAP_MSG_AUTH_REPLY) /* the message is not the one expected */
+ {
+ switch (retval)
+ {
+ case -3: /* Unrecoverable network error */
+ case -2: /* The other endpoint sent a message that is not allowed here */
+ case -1: /* The other endpoint has a version number that is not compatible with our */
+ /* Do nothing; just exit from here; the error code is already into the errbuf */
+ return -1;
+
+ case RPCAP_MSG_ERROR:
+ return -1;
+
+ default:
+ SOCK_ASSERT("Internal error", 0);
+ return -1;
+ }
+ }
+
+ if (ntohl(header.plen))
+ {
+ if (sock_discard(sock, ntohl(header.plen), errbuf, PCAP_ERRBUF_SIZE))
+ return -1;
+ }
+
+ return 0;
+}
+
+/* \ingroup remote_pri_func
+ * \brief Creates a structure of type rpcap_header.
+ *
+ * This function is provided just because the creation of an rpcap header is quite a common
+ * task. It accepts all the values that appears into an rpcap_header, and it puts them in
+ * place using the proper hton() calls.
+ *
+ * \param header: a pointer to a user-allocated buffer which will contain the serialized
+ * header, ready to be sent on the network.
+ *
+ * \param type: a value (in the host by order) which will be placed into the header.type
+ * field and that represents the type of the current message.
+ *
+ * \param value: a value (in the host by order) which will be placed into the header.value
+ * field and that has a message-dependent meaning.
+ *
+ * \param length: a value (in the host by order) which will be placed into the header.length
+ * field and that represents the payload length of the message.
+ *
+ * \return Nothing. The serialized header is returned into the 'header' variable.
+ */
+void rpcap_createhdr(struct rpcap_header *header, uint8 type, uint16 value, uint32 length)
+{
+ memset(header, 0, sizeof(struct rpcap_header));
+
+ header->ver = RPCAP_VERSION;
+ header->type = type;
+ header->value = htons(value);
+ header->plen = htonl(length);
+}
+
+/* ingroup remote_pri_func
+ * \brief Checks if the header of the received message is correct.
+ *
+ * This function is a way to easily check if the message received, in a certain
+ * state of the RPCAP protocol Finite State Machine, is valid. This function accepts,
+ * as a parameter, the list of message types that are allowed in a certain situation,
+ * and it returns the one which occurs.
+ *
+ * \param errbuf: a pointer to a user-allocated buffer (of size PCAP_ERRBUF_SIZE)
+ * that will contain the error message (in case there is one). It could be either problem
+ * occurred inside this function (e.g. a network problem in case it tries to send an
+ * error on the other peer and the send() call fails), an error message which has been
+ * sent to us from the other party, or a version error (the message receive has a version
+ * number that is incompatible with our).
+ *
+ * \param sock: the socket that has to be used to receive data. This function can
+ * read data from socket in case the version contained into the message is not compatible
+ * with our. In that case, all the message is purged from the socket, so that the following
+ * recv() calls will return a new message.
+ *
+ * \param header: a pointer to and 'rpcap_header' structure that keeps the data received from
+ * the network (still in network byte order) and that has to be checked.
+ *
+ * \param first: this function has a variable number of parameters. From this point on,
+ * all the messages that are valid in this context must be passed as parameters.
+ * The message type list must be terminated with a '0' value, the null message type,
+ * which means 'no more types to check'. The RPCAP protocol does not define anything with
+ * message type equal to zero, so there is no ambiguity in using this value as a list terminator.
+ *
+ * \return The message type of the message that has been detected. In case of errors (e.g. the
+ * header contains a type that is not listed among the allowed types), this function will
+ * return the following codes:
+ * - (-1) if the version is incompatible.
+ * - (-2) if the code is not among the one listed into the parameters list
+ * - (-3) if a network error (connection reset, ...)
+ * - RPCAP_MSG_ERROR if the message is an error message (it follow that the RPCAP_MSG_ERROR
+ * could not be present in the allowed message-types list, because this function checks
+ * for errors anyway)
+ *
+ * In case either the version is incompatible or nothing matches (i.e. it returns '-1' or '-2'),
+ * it discards the message body (i.e. it reads the remaining part of the message from the
+ * network and it discards it) so that the application is ready to receive a new message.
+ */
+int rpcap_checkmsg(char *errbuf, SOCKET sock, struct rpcap_header *header, uint8 first, ...)
+{
+ va_list ap;
+ uint8 type;
+ int32 len;
+
+ va_start(ap, first);
+
+ /* Check if the present version of the protocol can handle this message */
+ if (rpcap_checkver(sock, header, errbuf))
+ {
+ SOCK_ASSERT(errbuf, 1);
+
+ va_end(ap);
+ return -1;
+ }
+
+ type = first;
+
+ while (type != 0)
+ {
+ /*
+ * The message matches with one of the types listed
+ * There is no need of conversions since both values are uint8
+ *
+ * Check if the other side reported an error.
+ * If yes, it retrieves it and it returns it back to the caller
+ */
+ if (header->type == RPCAP_MSG_ERROR)
+ {
+ len = ntohl(header->plen);
+
+ if (len >= PCAP_ERRBUF_SIZE)
+ {
+ if (sock_recv(sock, errbuf, PCAP_ERRBUF_SIZE - 1, SOCK_RECEIVEALL_YES, errbuf, PCAP_ERRBUF_SIZE))
+ return -3;
+
+ sock_discard(sock, len - (PCAP_ERRBUF_SIZE - 1), NULL, 0);
+
+ /* Put '\0' at the end of the string */
+ errbuf[PCAP_ERRBUF_SIZE - 1] = 0;
+ }
+ else
+ {
+ if (sock_recv(sock, errbuf, len, SOCK_RECEIVEALL_YES, errbuf, PCAP_ERRBUF_SIZE) == -1)
+ return -3;
+
+ /* Put '\0' at the end of the string */
+ errbuf[len] = 0;
+ }
+
+
+ va_end(ap);
+ return header->type;
+ }
+
+ if (header->type == type)
+ {
+ va_end(ap);
+ return header->type;
+ }
+
+ /* get next argument */
+ type = va_arg(ap, int);
+ }
+
+ /* we already have an error, so please discard this one */
+ sock_discard(sock, ntohl(header->plen), NULL, 0);
+
+ pcap_snprintf(errbuf, PCAP_ERRBUF_SIZE, "The other endpoint sent a message that is not allowed here.");
+ SOCK_ASSERT(errbuf, 1);
+
+ va_end(ap);
+ return -2;
+}
+
+/* \ingroup remote_pri_func
+ * \brief Checks if the version contained into the message is compatible with
+ * the one handled by this implementation.
+ *
+ * Right now, this function does not have any sophisticated task: if the versions
+ * are different, it returns -1 and it discards the message.
+ * It is expected that in the future this message will become more complex.
+ *
+ * \param sock: the socket that has to be used to receive data. This function can
+ * read data from socket in case the version contained into the message is not compatible
+ * with our. In that case, all the message is purged from the socket, so that the following
+ * recv() calls will return a new (clean) message.
+ *
+ * \param header: a pointer to and 'rpcap_header' structure that keeps the data received from
+ * the network (still in network byte order) and that has to be checked.
+ *
+ * \param errbuf: a pointer to a user-allocated buffer (of size PCAP_ERRBUF_SIZE)
+ * that will contain the error message (in case there is one). The error message is
+ * "incompatible version".
+ *
+ * \return '0' if everything is fine, '-1' if some errors occurred. The error message is returned
+ * in the 'errbuf' variable.
+ */
+static int rpcap_checkver(SOCKET sock, struct rpcap_header *header, char *errbuf)
+{
+ /*
+ * This is a sample function.
+ *
+ * In the real world, you have to check at the type code,
+ * and decide accordingly.
+ */
+
+ if (header->ver != RPCAP_VERSION)
+ {
+ pcap_snprintf(errbuf, PCAP_ERRBUF_SIZE, "Incompatible version number: message discarded.");
+
+ /* we already have an error, so please discard this one */
+ sock_discard(sock, ntohl(header->plen), NULL, 0);
+ return -1;
+ }
+
+ return 0;
+}
+
+/* \ingroup remote_pri_func
+ *
+ * \brief It returns the socket currently used for this active connection
+ * (active mode only) and provides an indication of whether this connection
+ * is in active mode or not.
+ *
+ * This function is just for internal use; it returns the socket ID of the
+ * active connection currently opened.
+ *
+ * \param host: a string that keeps the host name of the host for which we
+ * want to get the socket ID for that active connection.
+ *
+ * \param isactive: a pointer to an int that is set to 1 if there's an
+ * active connection to that host and 0 otherwise.
+ *
+ * \param errbuf: a pointer to a user-allocated buffer (of size
+ * PCAP_ERRBUF_SIZE) that will contain the error message (in case
+ * there is one).
+ *
+ * \return the socket identifier if everything is fine, '0' if this host
+ * is not in the active host list. An indication of whether this host
+ * is in the active host list is returned into the isactive variable.
+ * It returns 'INVALID_SOCKET' in case of error. The error message is
+ * returned into the errbuf variable.
+ */
+SOCKET rpcap_remoteact_getsock(const char *host, int *isactive, char *errbuf)
+{
+ struct activehosts *temp; /* temp var needed to scan the host list chain */
+ struct addrinfo hints, *addrinfo, *ai_next; /* temp var needed to translate between hostname to its address */
+ int retval;
+
+ /* retrieve the network address corresponding to 'host' */
+ addrinfo = NULL;
+ memset(&hints, 0, sizeof(struct addrinfo));
+ hints.ai_family = PF_UNSPEC;
+ hints.ai_socktype = SOCK_STREAM;
+
+ retval = getaddrinfo(host, "0", &hints, &addrinfo);
+ if (retval != 0)
+ {
+ pcap_snprintf(errbuf, PCAP_ERRBUF_SIZE, "getaddrinfo() %s", gai_strerror(retval));
+ *isactive = 0;
+ return INVALID_SOCKET;
+ }
+
+ temp = activeHosts;
+
+ while (temp)
+ {
+ ai_next = addrinfo;
+ while (ai_next)
+ {
+ if (sock_cmpaddr(&temp->host, (struct sockaddr_storage *) ai_next->ai_addr) == 0) {
+ *isactive = 1;
+ return (temp->sockctrl);
+ }
+
+ ai_next = ai_next->ai_next;
+ }
+ temp = temp->next;
+ }
+
+ if (addrinfo)
+ freeaddrinfo(addrinfo);
+
+ /*
+ * The host for which you want to get the socket ID does not have an
+ * active connection.
+ */
+ *isactive = 0;
+ return 0;
+}
diff --git a/contrib/libpcap/pcap-rpcap.h b/contrib/libpcap/pcap-rpcap.h
new file mode 100644
index 000000000000..f84e8ba52577
--- /dev/null
+++ b/contrib/libpcap/pcap-rpcap.h
@@ -0,0 +1,465 @@
+/*
+ * Copyright (c) 2002 - 2005 NetGroup, Politecnico di Torino (Italy)
+ * Copyright (c) 2005 - 2008 CACE Technologies, Davis (California)
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the Politecnico di Torino, CACE Technologies
+ * nor the names of its contributors may be used to endorse or promote
+ * products derived from this software without specific prior written
+ * permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+#ifndef __PCAP_RPCAP_H__
+#define __PCAP_RPCAP_H__
+
+
+#include "pcap.h"
+#include "sockutils.h" /* Needed for some structures (like SOCKET, sockaddr_in) which are used here */
+
+
+/*
+ * \file pcap-pcap.h
+ *
+ * This file keeps all the new definitions and typedefs that are exported to the user and
+ * that are needed for the RPCAP protocol.
+ *
+ * \warning All the RPCAP functions that are allowed to return a buffer containing
+ * the error description can return max PCAP_ERRBUF_SIZE characters.
+ * However there is no guarantees that the string will be zero-terminated.
+ * Best practice is to define the errbuf variable as a char of size 'PCAP_ERRBUF_SIZE+1'
+ * and to insert manually the termination char at the end of the buffer. This will
+ * guarantee that no buffer overflows occur even if we use the printf() to show
+ * the error on the screen.
+ *
+ * \warning This file declares some typedefs that MUST be of a specific size.
+ * These definitions (i.e. typedefs) could need to be changed on other platforms than
+ * Intel IA32.
+ *
+ * \warning This file defines some structures that are used to transfer data on the network.
+ * Be careful that you compiler MUST not insert padding into these structures
+ * for better alignment.
+ * These structures have been created in order to be correctly aligned to a 32 bits
+ * boundary, but be careful in any case.
+ */
+
+
+
+
+
+
+
+
+/*********************************************************
+ * *
+ * General definitions / typedefs for the RPCAP protocol *
+ * *
+ *********************************************************/
+
+/* All the following structures and typedef belongs to the Private Documentation */
+/*
+ * \addtogroup remote_pri_struct
+ * \{
+ */
+
+#define RPCAP_DEFAULT_NETPORT "2002" /* Default port on which the RPCAP daemon is waiting for connections. */
+/* Default port on which the client workstation is waiting for connections in case of active mode. */
+#define RPCAP_DEFAULT_NETPORT_ACTIVE "2003"
+#define RPCAP_DEFAULT_NETADDR "" /* Default network address on which the RPCAP daemon binds to. */
+#define RPCAP_VERSION 0 /* Present version of the RPCAP protocol (0 = Experimental). */
+#define RPCAP_TIMEOUT_INIT 90 /* Initial timeout for RPCAP connections (default: 90 sec) */
+#define RPCAP_TIMEOUT_RUNTIME 180 /* Run-time timeout for RPCAP connections (default: 3 min) */
+#define RPCAP_ACTIVE_WAIT 30 /* Waiting time between two attempts to open a connection, in active mode (default: 30 sec) */
+#define RPCAP_SUSPEND_WRONGAUTH 1 /* If the authentication is wrong, stops 1 sec before accepting a new auth message */
+
+/*
+ * \brief Buffer used by socket functions to send-receive packets.
+ * In case you plan to have messages larger than this value, you have to increase it.
+ */
+#define RPCAP_NETBUF_SIZE 64000
+
+
+/*
+ * \brief Separators used for the host list.
+ *
+ * It is used:
+ * - by the rpcapd daemon, when you types a list of allowed connecting hosts
+ * - by the rpcap in active mode, when the client waits for incoming connections from other hosts
+ */
+#define RPCAP_HOSTLIST_SEP " ,;\n\r"
+
+
+
+
+/* WARNING: These could need to be changed on other platforms */
+typedef unsigned char uint8; /* Provides an 8-bits unsigned integer */
+typedef unsigned short uint16; /* Provides a 16-bits unsigned integer */
+typedef unsigned int uint32; /* Provides a 32-bits unsigned integer */
+typedef int int32; /* Provides a 32-bits integer */
+
+
+
+
+/*
+ * \brief Keeps a list of all the opened connections in the active mode.
+ *
+ * This structure defines a linked list of items that are needed to keep the info required to
+ * manage the active mode.
+ * In other words, when a new connection in active mode starts, this structure is updated so that
+ * it reflects the list of active mode connections currently opened.
+ * This structure is required by findalldevs() and open_remote() to see if they have to open a new
+ * control connection toward the host, or they already have a control connection in place.
+ */
+struct activehosts
+{
+ struct sockaddr_storage host;
+ SOCKET sockctrl;
+ struct activehosts *next;
+};
+
+
+/*********************************************************
+ * *
+ * Protocol messages formats *
+ * *
+ *********************************************************/
+/* WARNING Take care you compiler does not insert padding for better alignments into these structs */
+
+
+/* Common header for all the RPCAP messages */
+struct rpcap_header
+{
+ uint8 ver; /* RPCAP version number */
+ uint8 type; /* RPCAP message type (error, findalldevs, ...) */
+ uint16 value; /* Message-dependent value (not always used) */
+ uint32 plen; /* Length of the payload of this RPCAP message */
+};
+
+
+/* Format of the message for the interface description (findalldevs command) */
+struct rpcap_findalldevs_if
+{
+ uint16 namelen; /* Length of the interface name */
+ uint16 desclen; /* Length of the interface description */
+ uint32 flags; /* Interface flags */
+ uint16 naddr; /* Number of addresses */
+ uint16 dummy; /* Must be zero */
+};
+
+
+/* Format of the message for the address listing (findalldevs command) */
+struct rpcap_findalldevs_ifaddr
+{
+ struct sockaddr_storage addr; /* Network address */
+ struct sockaddr_storage netmask; /* Netmask for that address */
+ struct sockaddr_storage broadaddr; /* Broadcast address for that address */
+ struct sockaddr_storage dstaddr; /* P2P destination address for that address */
+};
+
+
+
+/*
+ * \brief Format of the message of the connection opening reply (open command).
+ *
+ * This structure transfers over the network some of the values useful on the client side.
+ */
+struct rpcap_openreply
+{
+ int32 linktype; /* Link type */
+ int32 tzoff; /* Timezone offset */
+};
+
+
+
+/* Format of the message that starts a remote capture (startcap command) */
+struct rpcap_startcapreq
+{
+ uint32 snaplen; /* Length of the snapshot (number of bytes to capture for each packet) */
+ uint32 read_timeout; /* Read timeout in milliseconds */
+ uint16 flags; /* Flags (see RPCAP_STARTCAPREQ_FLAG_xxx) */
+ uint16 portdata; /* Network port on which the client is waiting at (if 'serveropen') */
+};
+
+
+/* Format of the reply message that devoted to start a remote capture (startcap reply command) */
+struct rpcap_startcapreply
+{
+ int32 bufsize; /* Size of the user buffer allocated by WinPcap; it can be different from the one we chose */
+ uint16 portdata; /* Network port on which the server is waiting at (passive mode only) */
+ uint16 dummy; /* Must be zero */
+};
+
+
+/*
+ * \brief Format of the header which encapsulates captured packets when transmitted on the network.
+ *
+ * This message requires the general header as well, since we want to be able to exchange
+ * more information across the network in the future (for example statistics, and kind like that).
+ */
+struct rpcap_pkthdr
+{
+ uint32 timestamp_sec; /* 'struct timeval' compatible, it represents the 'tv_sec' field */
+ uint32 timestamp_usec; /* 'struct timeval' compatible, it represents the 'tv_usec' field */
+ uint32 caplen; /* Length of portion present in the capture */
+ uint32 len; /* Real length this packet (off wire) */
+ uint32 npkt; /* Ordinal number of the packet (i.e. the first one captured has '1', the second one '2', etc) */
+};
+
+
+/* General header used for the pcap_setfilter() command; keeps just the number of BPF instructions */
+struct rpcap_filter
+{
+ uint16 filtertype; /* type of the filter transferred (BPF instructions, ...) */
+ uint16 dummy; /* Must be zero */
+ uint32 nitems; /* Number of items contained into the filter (e.g. BPF instructions for BPF filters) */
+};
+
+
+/* Structure that keeps a single BPF instuction; it is repeated 'ninsn' times according to the 'rpcap_filterbpf' header */
+struct rpcap_filterbpf_insn
+{
+ uint16 code; /* opcode of the instruction */
+ uint8 jt; /* relative offset to jump to in case of 'true' */
+ uint8 jf; /* relative offset to jump to in case of 'false' */
+ int32 k; /* instruction-dependent value */
+};
+
+
+/* Structure that keeps the data required for the authentication on the remote host */
+struct rpcap_auth
+{
+ uint16 type; /* Authentication type */
+ uint16 dummy; /* Must be zero */
+ uint16 slen1; /* Length of the first authentication item (e.g. username) */
+ uint16 slen2; /* Length of the second authentication item (e.g. password) */
+};
+
+
+/* Structure that keeps the statistics about the number of packets captured, dropped, etc. */
+struct rpcap_stats
+{
+ uint32 ifrecv; /* Packets received by the kernel filter (i.e. pcap_stats.ps_recv) */
+ uint32 ifdrop; /* Packets dropped by the network interface (e.g. not enough buffers) (i.e. pcap_stats.ps_ifdrop) */
+ uint32 krnldrop; /* Packets dropped by the kernel filter (i.e. pcap_stats.ps_drop) */
+ uint32 svrcapt; /* Packets captured by the RPCAP daemon and sent on the network */
+};
+
+
+/* Structure that is needed to set sampling parameters */
+struct rpcap_sampling
+{
+ uint8 method; /* Sampling method */
+ uint8 dummy1; /* Must be zero */
+ uint16 dummy2; /* Must be zero */
+ uint32 value; /* Parameter related to the sampling method */
+};
+
+
+/*
+ * Private data for doing a live capture.
+ */
+struct pcap_md {
+ struct pcap_stat stat;
+ /* XXX */
+ int use_bpf; /* using kernel filter */
+ u_long TotPkts; /* can't overflow 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_clear; /* stuff we must clear when we close */
+ struct pcap *next; /* list of open pcaps that need stuff cleared on close */
+#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 */
+ u_int packets_read; /* count of packets read with recvfrom() */
+ bpf_u_int32 oldmode; /* mode to restore when turning monitor mode off */
+ u_int tp_version; /* version of tpacket_hdr for mmaped ring */
+ u_int tp_hdrlen; /* hdrlen of tpacket_hdr for mmaped ring */
+#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_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
+ * associated 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 */
+
+
+
+#ifdef HAVE_REMOTE
+ /*
+ * There is really a mess with previous variables, and it seems to me that they are not used
+ * (they are used in pcap_pf.c only). I think we have to start using them.
+ * The meaning is the following:
+ *
+ * - TotPkts: the amount of packets received by the bpf filter, *before* applying the filter
+ * - TotAccepted: the amount of packets that satisfies the filter
+ * - TotDrops: the amount of packet that were dropped into the kernel buffer because of lack of space
+ * - TotMissed: the amount of packets that were dropped by the physical interface; it is basically
+ * the value of the hardware counter into the card. This number is never put to zero, so this number
+ * takes into account the *total* number of interface drops starting from the interface power-on.
+ * - OrigMissed: the amount of packets that were dropped by the interface *when the capture begins*.
+ * This value is used to detect the number of packets dropped by the interface *during the present
+ * capture*, so that (ps_ifdrops= TotMissed - OrigMissed).
+ */
+ unsigned int TotNetDrops; /* keeps the number of packets that have been dropped by the network */
+ /*
+ * \brief It keeps the number of packets that have been received by the application.
+ *
+ * Packets dropped by the kernel buffer are not counted in this variable. The variable is always
+ * equal to (TotAccepted - TotDrops), except for the case of remote capture, in which we have also
+ * packets in flight, i.e. that have been transmitted by the remote host, but that have not been
+ * received (yet) from the client. In this case, (TotAccepted - TotDrops - TotNetDrops) gives a
+ * wrong result, since this number does not corresponds always to the number of packet received by
+ * the application. For this reason, in the remote capture we need another variable that takes
+ * into account of the number of packets actually received by the application.
+ */
+ unsigned int TotCapt;
+
+ /*! \brief '1' if we're the network client; needed by several functions (like pcap_setfilter() ) to know if
+ they have to use the socket or they have to open the local adapter. */
+ int rmt_clientside;
+
+ SOCKET rmt_sockctrl; //!< socket ID of the socket used for the control connection
+ SOCKET rmt_sockdata; //!< socket ID of the socket used for the data connection
+ int rmt_flags; //!< we have to save flags, since they are passed by the pcap_open_live(), but they are used by the pcap_startcapture()
+ int rmt_capstarted; //!< 'true' if the capture is already started (needed to knoe if we have to call the pcap_startcapture()
+ struct pcap_samp rmt_samp; //!< Keeps the parameters related to the sampling process.
+ char *currentfilter; //!< Pointer to a buffer (allocated at run-time) that stores the current filter. Needed when flag PCAP_OPENFLAG_NOCAPTURE_RPCAP is turned on.
+#endif /* HAVE_REMOTE */
+
+};
+
+
+/* Messages field coding */
+#define RPCAP_MSG_ERROR 1 /* Message that keeps an error notification */
+#define RPCAP_MSG_FINDALLIF_REQ 2 /* Request to list all the remote interfaces */
+#define RPCAP_MSG_OPEN_REQ 3 /* Request to open a remote device */
+#define RPCAP_MSG_STARTCAP_REQ 4 /* Request to start a capture on a remote device */
+#define RPCAP_MSG_UPDATEFILTER_REQ 5 /* Send a compiled filter into the remote device */
+#define RPCAP_MSG_CLOSE 6 /* Close the connection with the remote peer */
+#define RPCAP_MSG_PACKET 7 /* This is a 'data' message, which carries a network packet */
+#define RPCAP_MSG_AUTH_REQ 8 /* Message that keeps the authentication parameters */
+#define RPCAP_MSG_STATS_REQ 9 /* It requires to have network statistics */
+#define RPCAP_MSG_ENDCAP_REQ 10 /* Stops the current capture, keeping the device open */
+#define RPCAP_MSG_SETSAMPLING_REQ 11 /* Set sampling parameters */
+
+#define RPCAP_MSG_FINDALLIF_REPLY (128+RPCAP_MSG_FINDALLIF_REQ) /* Keeps the list of all the remote interfaces */
+#define RPCAP_MSG_OPEN_REPLY (128+RPCAP_MSG_OPEN_REQ) /* The remote device has been opened correctly */
+#define RPCAP_MSG_STARTCAP_REPLY (128+RPCAP_MSG_STARTCAP_REQ) /* The capture is starting correctly */
+#define RPCAP_MSG_UPDATEFILTER_REPLY (128+RPCAP_MSG_UPDATEFILTER_REQ) /* The filter has been applied correctly on the remote device */
+#define RPCAP_MSG_AUTH_REPLY (128+RPCAP_MSG_AUTH_REQ) /* Sends a message that says 'ok, authorization successful' */
+#define RPCAP_MSG_STATS_REPLY (128+RPCAP_MSG_STATS_REQ) /* Message that keeps the network statistics */
+#define RPCAP_MSG_ENDCAP_REPLY (128+RPCAP_MSG_ENDCAP_REQ) /* Confirms that the capture stopped successfully */
+#define RPCAP_MSG_SETSAMPLING_REPLY (128+RPCAP_MSG_SETSAMPLING_REQ) /* Confirms that the capture stopped successfully */
+
+#define RPCAP_STARTCAPREQ_FLAG_PROMISC 1 /* Enables promiscuous mode (default: disabled) */
+#define RPCAP_STARTCAPREQ_FLAG_DGRAM 2 /* Use a datagram (i.e. UDP) connection for the data stream (default: use TCP)*/
+#define RPCAP_STARTCAPREQ_FLAG_SERVEROPEN 4 /* The server has to open the data connection toward the client */
+#define RPCAP_STARTCAPREQ_FLAG_INBOUND 8 /* Capture only inbound packets (take care: the flag has no effects with promiscuous enabled) */
+#define RPCAP_STARTCAPREQ_FLAG_OUTBOUND 16 /* Capture only outbound packets (take care: the flag has no effects with promiscuous enabled) */
+
+#define RPCAP_UPDATEFILTER_BPF 1 /* This code tells us that the filter is encoded with the BPF/NPF syntax */
+
+
+/* Network error codes */
+#define PCAP_ERR_NETW 1 /* Network error */
+#define PCAP_ERR_INITTIMEOUT 2 /* The RPCAP initial timeout has expired */
+#define PCAP_ERR_AUTH 3 /* Generic authentication error */
+#define PCAP_ERR_FINDALLIF 4 /* Generic findalldevs error */
+#define PCAP_ERR_NOREMOTEIF 5 /* The findalldevs was ok, but the remote end had no interfaces to list */
+#define PCAP_ERR_OPEN 6 /* Generic pcap_open error */
+#define PCAP_ERR_UPDATEFILTER 7 /* Generic updatefilter error */
+#define PCAP_ERR_GETSTATS 8 /* Generic pcap_stats error */
+#define PCAP_ERR_READEX 9 /* Generic pcap_next_ex error */
+#define PCAP_ERR_HOSTNOAUTH 10 /* The host is not authorized to connect to this server */
+#define PCAP_ERR_REMOTEACCEPT 11 /* Generic pcap_remoteaccept error */
+#define PCAP_ERR_STARTCAPTURE 12 /* Generic pcap_startcapture error */
+#define PCAP_ERR_ENDCAPTURE 13 /* Generic pcap_endcapture error */
+#define PCAP_ERR_RUNTIMETIMEOUT 14 /* The RPCAP run-time timeout has expired */
+#define PCAP_ERR_SETSAMPLING 15 /* Error during the settings of sampling parameters */
+#define PCAP_ERR_WRONGMSG 16 /* The other end endpoint sent a message which has not been recognized */
+#define PCAP_ERR_WRONGVER 17 /* The other end endpoint has a version number that is not compatible with our */
+/*
+ * \}
+ * // end of private documentation
+ */
+
+
+/*********************************************************
+ * *
+ * Exported function prototypes *
+ * *
+ *********************************************************/
+int pcap_opensource_remote(pcap_t *p, struct pcap_rmtauth *auth);
+int pcap_startcapture_remote(pcap_t *fp);
+
+void rpcap_createhdr(struct rpcap_header *header, uint8 type, uint16 value, uint32 length);
+int rpcap_deseraddr(struct sockaddr_storage *sockaddrin, struct sockaddr_storage **sockaddrout, char *errbuf);
+int rpcap_checkmsg(char *errbuf, SOCKET sock, struct rpcap_header *header, uint8 first, ...);
+int rpcap_senderror(SOCKET sock, char *error, unsigned short errcode, char *errbuf);
+int rpcap_sendauth(SOCKET sock, struct pcap_rmtauth *auth, char *errbuf);
+
+SOCKET rpcap_remoteact_getsock(const char *host, int *isactive, char *errbuf);
+
+#endif
+
diff --git a/contrib/libpcap/pcap-savefile.manfile.in b/contrib/libpcap/pcap-savefile.manfile.in
index 2b93c143781d..451dd90b7e2f 100644
--- a/contrib/libpcap/pcap-savefile.manfile.in
+++ b/contrib/libpcap/pcap-savefile.manfile.in
@@ -17,12 +17,12 @@
.\" WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
.\" MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
.\"
-.TH PCAP-SAVEFILE @MAN_FILE_FORMATS@ "29 July 2013"
+.TH PCAP-SAVEFILE @MAN_FILE_FORMATS@ "8 March 2015"
.SH NAME
pcap-savefile \- libpcap savefile format
.SH DESCRIPTION
NOTE: applications and libraries should, if possible, use libpcap to
-read savefiles, rather than having their own code to read savefiles.
+read savefiles, rather than having their own code to read savefiles.
If, in the future, a new file format is supported by libpcap,
applications and libraries using libpcap to read savefiles will be able
to read the new format of savefiles, but applications and libraries
diff --git a/contrib/libpcap/pcap-septel.c b/contrib/libpcap/pcap-septel.c
index 2f0ff33beb7e..88dc89df62dc 100644
--- a/contrib/libpcap/pcap-septel.c
+++ b/contrib/libpcap/pcap-septel.c
@@ -194,9 +194,9 @@ septel_inject(pcap_t *handle, const void *buf _U_, size_t size _U_)
* See also pcap(3).
*/
static pcap_t *septel_activate(pcap_t* handle) {
- /* Initialize some components of the pcap structure. */
+ /* Initialize some components of the pcap structure. */
handle->linktype = DLT_MTP2;
-
+
handle->bufsize = 0;
/*
@@ -232,7 +232,7 @@ pcap_t *septel_create(const char *device, char *ebuf, int *is_ours) {
/* OK, it's probably ours. */
*is_ours = 1;
- p = pcap_create_common(device, ebuf, sizeof (struct pcap_septel));
+ p = pcap_create_common(ebuf, sizeof (struct pcap_septel));
if (p == NULL)
return NULL;
@@ -244,9 +244,9 @@ static int septel_stats(pcap_t *p, struct pcap_stat *ps) {
struct pcap_septel *handlep = p->priv;
/*handlep->stat.ps_recv = 0;*/
/*handlep->stat.ps_drop = 0;*/
-
+
*ps = handlep->stat;
-
+
return 0;
}
@@ -276,7 +276,7 @@ static int septel_setfilter(pcap_t *p, struct bpf_program *fp) {
/* Make our private copy of the filter */
if (install_bpf_program(p, fp) < 0) {
- snprintf(p->errbuf, sizeof(p->errbuf),
+ pcap_snprintf(p->errbuf, sizeof(p->errbuf),
"malloc: %s", pcap_strerror(errno));
return -1;
}
@@ -291,3 +291,31 @@ septel_setnonblock(pcap_t *p, int nonblock, char *errbuf)
fprintf(errbuf, PCAP_ERRBUF_SIZE, "Non-blocking mode not supported on Septel devices");
return (-1);
}
+
+#ifdef SEPTEL_ONLY
+/*
+ * This libpcap build supports only Septel cards, not regular network
+ * interfaces.
+ */
+
+/*
+ * There are no regular interfaces, just Septel interfaces.
+ */
+int
+pcap_platform_finddevs(pcap_if_t **alldevsp, char *errbuf)
+{
+ *alldevsp = NULL;
+ return (0);
+}
+
+/*
+ * Attempts to open a regular interface fail.
+ */
+pcap_t *
+pcap_create_interface(const char *device, char *errbuf)
+{
+ pcap_snprintf(errbuf, PCAP_ERRBUF_SIZE,
+ "This version of libpcap only supports Septel cards");
+ return (NULL);
+}
+#endif
diff --git a/contrib/libpcap/pcap-sita.c b/contrib/libpcap/pcap-sita.c
index d507e1eecd8a..1cd5f7510a04 100644
--- a/contrib/libpcap/pcap-sita.c
+++ b/contrib/libpcap/pcap-sita.c
@@ -183,7 +183,7 @@ static int read_client_nbytes(int fd, int count, unsigned char *buf) {
find_unit_by_fd(fd, &chassis, &geoslot, &u);
while (count) {
if ((len = recv(fd, buf, count, 0)) <= 0) return -1; /* read in whatever data was sent to us */
- count -= len;
+ count -= len;
buf += len;
} /* till we have everything we are looking for */
return 0;
@@ -208,10 +208,14 @@ static void empty_unit(int chassis, int geoslot) {
empty_unit_iface(u);
if (u->imsg) { /* then if an inbound message buffer exists */
- u->imsg = (char *)realloc(u->imsg, 1); /* and re-allocate the old large buffer into a new small one */
- if (u->imsg == NULL) { /* oops, realloc call failed */
+ void *bigger_buffer;
+
+ bigger_buffer = (char *)realloc(u->imsg, 1); /* and re-allocate the old large buffer into a new small one */
+ if (bigger_buffer == NULL) { /* oops, realloc call failed */
fprintf(stderr, "Warning...call to realloc() failed, value of errno is %d\n", errno);
-
+ return;
+ }
+ u->imsg = bigger_buffer;
}
}
@@ -262,7 +266,7 @@ int acn_parse_hosts_file(char *errbuf) { /* returns: -1 = error, 0 = OK */
empty_unit_table();
if ((fp = fopen("/etc/hosts", "r")) == NULL) { /* try to open the hosts file and if it fails */
- snprintf(errbuf, PCAP_ERRBUF_SIZE, "Cannot open '/etc/hosts' for reading."); /* return the nohostsfile error response */
+ pcap_snprintf(errbuf, PCAP_ERRBUF_SIZE, "Cannot open '/etc/hosts' for reading."); /* return the nohostsfile error response */
return -1;
}
while (fgets(buf, MAX_LINE_SIZE-1, fp)) { /* while looping over the file */
@@ -285,11 +289,11 @@ int acn_parse_hosts_file(char *errbuf) { /* returns: -1 = error, 0 = OK */
geoslot = *(ptr2 + 5) - '0'; /* and geo-slot number */
if (chassis < 1 || chassis > MAX_CHASSIS ||
geoslot < 1 || geoslot > MAX_GEOSLOT) { /* if the chassis and/or slot numbers appear to be bad... */
- snprintf(errbuf, PCAP_ERRBUF_SIZE, "Invalid ACN name in '/etc/hosts'."); /* warn the user */
+ pcap_snprintf(errbuf, PCAP_ERRBUF_SIZE, "Invalid ACN name in '/etc/hosts'."); /* warn the user */
continue; /* and ignore the entry */
}
if ((ptr2 = (char *)malloc(strlen(ptr) + 1)) == NULL) {
- snprintf(errbuf, PCAP_ERRBUF_SIZE, "malloc: %s", pcap_strerror(errno));
+ pcap_snprintf(errbuf, PCAP_ERRBUF_SIZE, "malloc: %s", pcap_strerror(errno));
continue;
}
strcpy(ptr2, ptr); /* copy the IP address into our malloc'ed memory */
@@ -402,14 +406,14 @@ static void acn_freealldevs(void) {
static void nonUnified_IOP_port_name(char *buf, size_t bufsize, const char *proto, unit_t *u) {
- snprintf(buf, bufsize, "%s_%d_%d", proto, u->chassis, u->geoslot);
+ pcap_snprintf(buf, bufsize, "%s_%d_%d", proto, u->chassis, u->geoslot);
}
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;
- snprintf(buf, bufsize, "%s_%d", proto, portnum);
+ pcap_snprintf(buf, bufsize, "%s_%d", proto, portnum);
}
static char *translate_IOP_to_pcap_name(unit_t *u, char *IOPname, bpf_u_int32 iftype) {
@@ -553,10 +557,10 @@ static void sort_if_table(void) {
}
if (has_swapped == 0)
return;
- }
+ }
return;
}
-
+
static int process_client_data (char *errbuf) { /* returns: -1 = error, 0 = OK */
int chassis, geoslot;
unit_t *u;
@@ -568,6 +572,7 @@ static int process_client_data (char *errbuf) { /* returns: -1 = error, 0
char *newname;
bpf_u_int32 interfaceType;
unsigned char flags;
+ void *bigger_buffer;
prev_iff = 0;
for (chassis = 0; chassis <= MAX_CHASSIS; chassis++) {
@@ -577,7 +582,7 @@ static int process_client_data (char *errbuf) { /* returns: -1 = error, 0
ptr = u->imsg; /* point to the start of the msg for this IOP */
while (ptr < (u->imsg + u->len)) {
if ((iff = malloc(sizeof(pcap_if_t))) == NULL) {
- snprintf(errbuf, PCAP_ERRBUF_SIZE, "malloc: %s", pcap_strerror(errno));
+ pcap_snprintf(errbuf, PCAP_ERRBUF_SIZE, "malloc: %s", pcap_strerror(errno));
return -1;
}
memset((char *)iff, 0, sizeof(pcap_if_t)); /* bzero() is deprecated, replaced with memset() */
@@ -586,7 +591,7 @@ static int process_client_data (char *errbuf) { /* returns: -1 = error, 0
if (*ptr) { /* if there is a count for the name */
if ((iff->name = malloc(*ptr + 1)) == NULL) { /* get that amount of space */
- snprintf(errbuf, PCAP_ERRBUF_SIZE, "malloc: %s", pcap_strerror(errno));
+ pcap_snprintf(errbuf, PCAP_ERRBUF_SIZE, "malloc: %s", pcap_strerror(errno));
return -1;
}
memcpy(iff->name, (ptr + 1), *ptr); /* copy the name into the malloc'ed space */
@@ -597,7 +602,7 @@ static int process_client_data (char *errbuf) { /* returns: -1 = error, 0
if (*ptr) { /* if there is a count for the description */
if ((iff->description = malloc(*ptr + 1)) == NULL) { /* get that amount of space */
- snprintf(errbuf, PCAP_ERRBUF_SIZE, "malloc: %s", pcap_strerror(errno));
+ pcap_snprintf(errbuf, PCAP_ERRBUF_SIZE, "malloc: %s", pcap_strerror(errno));
return -1;
}
memcpy(iff->description, (ptr + 1), *ptr); /* copy the name into the malloc'ed space */
@@ -617,15 +622,15 @@ static int process_client_data (char *errbuf) { /* returns: -1 = error, 0
prev_addr = 0;
while (address_count--) {
if ((addr = malloc(sizeof(pcap_addr_t))) == NULL) {
- snprintf(errbuf, PCAP_ERRBUF_SIZE, "malloc: %s", pcap_strerror(errno));
+ pcap_snprintf(errbuf, PCAP_ERRBUF_SIZE, "malloc: %s", pcap_strerror(errno));
return -1;
}
-+ memset((char *)addr, 0, sizeof(pcap_addr_t)); /* bzero() is deprecated, replaced with memset() */
+ memset((char *)addr, 0, sizeof(pcap_addr_t)); /* bzero() is deprecated, replaced with memset() */
if (iff->addresses == 0) iff->addresses = addr;
if (prev_addr) prev_addr->next = addr; /* insert a forward link */
if (*ptr) { /* if there is a count for the address */
if ((s = malloc(sizeof(struct sockaddr_in))) == NULL) { /* get that amount of space */
- snprintf(errbuf, PCAP_ERRBUF_SIZE, "malloc: %s", pcap_strerror(errno));
+ pcap_snprintf(errbuf, PCAP_ERRBUF_SIZE, "malloc: %s", pcap_strerror(errno));
return -1;
}
memset((char *)s, 0, sizeof(struct sockaddr_in)); /* bzero() is deprecated, replaced with memset() */
@@ -637,7 +642,7 @@ static int process_client_data (char *errbuf) { /* returns: -1 = error, 0
ptr++; /* then forwards one more for the 'length of the address' field */
if (*ptr) { /* process any netmask */
if ((s = malloc(sizeof(struct sockaddr_in))) == NULL) {
- snprintf(errbuf, PCAP_ERRBUF_SIZE, "malloc: %s", pcap_strerror(errno));
+ pcap_snprintf(errbuf, PCAP_ERRBUF_SIZE, "malloc: %s", pcap_strerror(errno));
return -1;
}
/* bzero() is deprecated, replaced with memset() */
@@ -651,7 +656,7 @@ static int process_client_data (char *errbuf) { /* returns: -1 = error, 0
ptr++;
if (*ptr) { /* process any broadcast address */
if ((s = malloc(sizeof(struct sockaddr_in))) == NULL) {
- snprintf(errbuf, PCAP_ERRBUF_SIZE, "malloc: %s", pcap_strerror(errno));
+ pcap_snprintf(errbuf, PCAP_ERRBUF_SIZE, "malloc: %s", pcap_strerror(errno));
return -1;
}
/* bzero() is deprecated, replaced with memset() */
@@ -665,7 +670,7 @@ static int process_client_data (char *errbuf) { /* returns: -1 = error, 0
ptr++;
if (*ptr) { /* process any destination address */
if ((s = malloc(sizeof(struct sockaddr_in))) == NULL) {
- snprintf(errbuf, PCAP_ERRBUF_SIZE, "malloc: %s", pcap_strerror(errno));
+ pcap_snprintf(errbuf, PCAP_ERRBUF_SIZE, "malloc: %s", pcap_strerror(errno));
return -1;
}
/* bzero() is deprecated, replaced with memset() */
@@ -682,10 +687,12 @@ static int process_client_data (char *errbuf) { /* returns: -1 = error, 0
prev_iff = iff;
newname = translate_IOP_to_pcap_name(u, iff->name, interfaceType); /* add a translation entry and get a point to the mangled name */
- if ((iff->name = realloc(iff->name, strlen(newname) + 1)) == NULL) { /* we now re-write the name stored in the interface list */
- snprintf(errbuf, PCAP_ERRBUF_SIZE, "realloc: %s", pcap_strerror(errno));
+ bigger_buffer = realloc(iff->name, strlen(newname) + 1));
+ if (bigger_buffer == NULL) { /* we now re-write the name stored in the interface list */
+ pcap_snprintf(errbuf, PCAP_ERRBUF_SIZE, "realloc: %s", pcap_strerror(errno));
return -1;
}
+ iff->name = bigger_buffer;
strcpy(iff->name, newname); /* to this new name */
}
}
@@ -816,7 +823,7 @@ static int acn_open_live(const char *name, char *errbuf, int *linktype) { /* re
iface_t *p;
pcap_if_t *alldevsp;
- pcap_findalldevs_interfaces(&alldevsp, errbuf);
+ pcap_platform_finddevs(&alldevsp, errbuf);
for (chassis = 0; chassis <= MAX_CHASSIS; chassis++) { /* scan the table... */
for (geoslot = 0; geoslot <= MAX_GEOSLOT; geoslot++) {
u = &units[chassis][geoslot];
@@ -892,7 +899,7 @@ static int pcap_setfilter_acn(pcap_t *handle, struct bpf_program *bpf) {
}
static int pcap_setdirection_acn(pcap_t *handle, pcap_direction_t d) {
- snprintf(handle->errbuf, sizeof(handle->errbuf),
+ pcap_snprintf(handle->errbuf, sizeof(handle->errbuf),
"Setting direction is not supported on ACN adapters");
return -1;
}
@@ -951,7 +958,7 @@ static int pcap_read_acn(pcap_t *handle, int max_packets, pcap_handler callback,
pcap_header.caplen = ntohl(*(uint32_t *)&packet_header[8]); /* caplen */
pcap_header.len = ntohl(*(uint32_t *)&packet_header[12]); /* len */
- handle->bp = handle->buffer + handle->offset; /* start off the receive pointer at the right spot */
+ handle->bp = (u_char *)handle->buffer + handle->offset; /* start off the receive pointer at the right spot */
if (acn_read_n_bytes_with_timeout(handle, pcap_header.caplen) == -1) return 0; /* then try to read in the rest of the data */
callback(user, &pcap_header, handle->bp); /* call the user supplied callback function */
@@ -981,7 +988,7 @@ static int pcap_activate_sita(pcap_t *handle) {
handle->read_op = pcap_read_acn;
handle->stats_op = pcap_stats_acn;
- fd = acn_open_live(handle->opt.source, handle->errbuf,
+ fd = acn_open_live(handle->opt.device, handle->errbuf,
&handle->linktype);
if (fd == -1)
return PCAP_ERROR;
@@ -992,7 +999,7 @@ static int pcap_activate_sita(pcap_t *handle) {
handle->buffer = malloc(handle->bufsize + handle->offset);
if (!handle->buffer) {
- snprintf(handle->errbuf, PCAP_ERRBUF_SIZE,
+ pcap_snprintf(handle->errbuf, PCAP_ERRBUF_SIZE,
"malloc: %s", pcap_strerror(errno));
pcap_cleanup_acn(handle);
return PCAP_ERROR;
@@ -1007,13 +1014,36 @@ static int pcap_activate_sita(pcap_t *handle) {
return 0;
}
-pcap_t *pcap_create_interface(const char *device, char *ebuf) {
+pcap_t *pcap_create_interface(const char *device _U_, char *ebuf) {
pcap_t *p;
- p = pcap_create_common(device, ebuf, 0);
+ p = pcap_create_common(ebuf, 0);
if (p == NULL)
return (NULL);
p->activate_op = pcap_activate_sita;
return (p);
}
+
+int pcap_platform_finddevs(pcap_if_t **alldevsp, char *errbuf) {
+
+ //printf("pcap_findalldevs()\n"); // fulko
+
+ *alldevsp = 0; /* initialize the returned variables before we do anything */
+ strcpy(errbuf, "");
+ if (acn_parse_hosts_file(errbuf)) /* scan the hosts file for potential IOPs */
+ {
+ //printf("pcap_findalldevs() returning BAD after parsehosts\n"); // fulko
+ return -1;
+ }
+ //printf("pcap_findalldevs() got hostlist now finding devs\n"); // fulko
+ if (acn_findalldevs(errbuf)) /* then ask the IOPs for their monitorable devices */
+ {
+ //printf("pcap_findalldevs() returning BAD after findalldevs\n"); // fulko
+ return -1;
+ }
+ *alldevsp = acn_if_list;
+ acn_if_list = 0; /* then forget our list head, because someone will call pcap_freealldevs() to empty the malloc'ed stuff */
+ //printf("pcap_findalldevs() returning ZERO OK\n"); // fulko
+ return 0;
+}
diff --git a/contrib/libpcap/pcap-snf.c b/contrib/libpcap/pcap-snf.c
index b8025ba8ba89..207c495926b1 100644
--- a/contrib/libpcap/pcap-snf.c
+++ b/contrib/libpcap/pcap-snf.c
@@ -16,6 +16,9 @@
#include <unistd.h>
#include <snf.h>
+#if SNF_VERSION_API >= 0x0003
+#define SNF_HAVE_INJECT_API
+#endif
#include "pcap-int.h"
#include "pcap-snf.h"
@@ -26,6 +29,9 @@
struct pcap_snf {
snf_handle_t snf_handle; /* opaque device handle */
snf_ring_t snf_ring; /* opaque device ring handle */
+#ifdef SNF_HAVE_INJECT_API
+ snf_inject_t snf_inj; /* inject handle, if inject is used */
+#endif
int snf_timeout;
int snf_boardnum;
};
@@ -41,10 +47,11 @@ static int
snf_pcap_stats(pcap_t *p, struct pcap_stat *ps)
{
struct snf_ring_stats stats;
+ struct pcap_snf *snfps = p->priv;
int rc;
- if ((rc = snf_ring_getstats(ps->snf_ring, &stats))) {
- snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "snf_get_stats: %s",
+ if ((rc = snf_ring_getstats(snfps->snf_ring, &stats))) {
+ pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "snf_get_stats: %s",
pcap_strerror(rc));
return -1;
}
@@ -57,12 +64,12 @@ snf_pcap_stats(pcap_t *p, struct pcap_stat *ps)
static void
snf_platform_cleanup(pcap_t *p)
{
- struct pcap_snf *ps;
-
- if (p == NULL)
- return;
- ps = p->priv;
+ struct pcap_snf *ps = p->priv;
+#ifdef SNF_HAVE_INJECT_API
+ if (ps->snf_inj)
+ snf_inject_close(ps->snf_inj);
+#endif
snf_ring_close(ps->snf_ring);
snf_close(ps->snf_handle);
pcap_cleanup_live_common(p);
@@ -96,14 +103,23 @@ snf_setnonblock(pcap_t *p, int nonblock, char *errbuf)
static inline
struct timeval
-snf_timestamp_to_timeval(const int64_t ts_nanosec)
+snf_timestamp_to_timeval(const int64_t ts_nanosec, const int tstamp_precision)
{
struct timeval tv;
- int32_t rem;
+ long tv_nsec;
+
if (ts_nanosec == 0)
return (struct timeval) { 0, 0 };
+
tv.tv_sec = ts_nanosec / _NSEC_PER_SEC;
- tv.tv_usec = (ts_nanosec % _NSEC_PER_SEC) / 1000;
+ tv_nsec = (ts_nanosec % _NSEC_PER_SEC);
+
+ /* libpcap expects tv_usec to be nanos if using nanosecond precision. */
+ if (tstamp_precision == PCAP_TSTAMP_PRECISION_NANO)
+ tv.tv_usec = tv_nsec;
+ else
+ tv.tv_usec = tv_nsec / 1000;
+
return tv;
}
@@ -114,11 +130,13 @@ snf_read(pcap_t *p, int cnt, pcap_handler callback, u_char *user)
struct pcap_pkthdr hdr;
int i, flags, err, caplen, n;
struct snf_recv_req req;
+ int nonblock, timeout;
- if (!p || cnt == 0)
+ if (!p)
return -1;
n = 0;
+ timeout = ps->snf_timeout;
while (n < cnt || PACKET_COUNT_IS_UNLIMITED(cnt)) {
/*
* Has "pcap_breakloop()" been called?
@@ -132,15 +150,18 @@ snf_read(pcap_t *p, int cnt, pcap_handler callback, u_char *user)
}
}
- err = snf_ring_recv(ps->snf_ring, ps->snf_timeout, &req);
+ err = snf_ring_recv(ps->snf_ring, timeout, &req);
if (err) {
- if (err == EBUSY || err == EAGAIN)
- return (0);
- if (err == EINTR)
+ if (err == EBUSY || err == EAGAIN) {
+ return (n);
+ }
+ else if (err == EINTR) {
+ timeout = 0;
continue;
- if (err != 0) {
- snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "snf_read: %s",
+ }
+ else {
+ pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "snf_read: %s",
pcap_strerror(err));
return -1;
}
@@ -152,12 +173,17 @@ snf_read(pcap_t *p, int cnt, pcap_handler callback, u_char *user)
if ((p->fcode.bf_insns == NULL) ||
bpf_filter(p->fcode.bf_insns, req.pkt_addr, req.length, caplen)) {
- hdr.ts = snf_timestamp_to_timeval(req.timestamp);
+ hdr.ts = snf_timestamp_to_timeval(req.timestamp, p->opt.tstamp_precision);
hdr.caplen = caplen;
hdr.len = req.length;
callback(user, &hdr, req.pkt_addr);
}
n++;
+
+ /* After one successful packet is received, we won't block
+ * again for that timeout. */
+ if (timeout != 0)
+ timeout = 0;
}
return (n);
}
@@ -184,30 +210,55 @@ snf_setfilter(pcap_t *p, struct bpf_program *fp)
static int
snf_inject(pcap_t *p, const void *buf _U_, size_t size _U_)
{
- strlcpy(p->errbuf, "Sending packets isn't supported with snf",
+#ifdef SNF_HAVE_INJECT_API
+ struct pcap_snf *ps = p->priv;
+ int rc;
+ if (ps->snf_inj == NULL) {
+ rc = snf_inject_open(ps->snf_boardnum, 0, &ps->snf_inj);
+ if (rc) {
+ pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
+ "snf_inject_open: %s", pcap_strerror(rc));
+ return (-1);
+ }
+ }
+
+ rc = snf_inject_send(ps->snf_inj, -1, 0, buf, size);
+ if (!rc) {
+ return (size);
+ }
+ else {
+ pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "snf_inject_send: %s",
+ pcap_strerror(rc));
+ return (-1);
+ }
+#else
+ strlcpy(p->errbuf, "Sending packets isn't supported with this snf version",
PCAP_ERRBUF_SIZE);
return (-1);
+#endif
}
static int
snf_activate(pcap_t* p)
{
struct pcap_snf *ps = p->priv;
- char *device = p->opt.source;
+ char *device = p->opt.device;
const char *nr = NULL;
int err;
- int flags = 0;
+ int flags = -1, ring_id = -1;
if (device == NULL) {
- snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
+ pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
"device is NULL: %s", pcap_strerror(errno));
return -1;
}
/* In Libpcap, we set pshared by default if NUM_RINGS is set to > 1.
* Since libpcap isn't thread-safe */
- if ((nr = getenv("SNF_NUM_RINGS")) && *nr && atoi(nr) > 1)
- flags |= SNF_F_PSHARED;
+ if ((nr = getenv("SNF_FLAGS")) && *nr)
+ flags = strtol(nr, NULL, 0);
+ else if ((nr = getenv("SNF_NUM_RINGS")) && *nr && atoi(nr) > 1)
+ flags = SNF_F_PSHARED;
else
nr = NULL;
@@ -218,15 +269,19 @@ snf_activate(pcap_t* p)
flags, /* may want pshared */
&ps->snf_handle);
if (err != 0) {
- snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
+ pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
"snf_open failed: %s", pcap_strerror(err));
return -1;
}
- err = snf_ring_open(ps->snf_handle, &ps->snf_ring);
+ if ((nr = getenv("SNF_PCAP_RING_ID")) && *nr) {
+ ring_id = (int) strtol(nr, NULL, 0);
+ }
+ err = snf_ring_open_id(ps->snf_handle, ring_id, &ps->snf_ring);
if (err != 0) {
- snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
- "snf_ring_open failed: %s", pcap_strerror(err));
+ pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
+ "snf_ring_open_id(ring=%d) failed: %s",
+ ring_id, pcap_strerror(err));
return -1;
}
@@ -237,7 +292,7 @@ snf_activate(pcap_t* p)
err = snf_start(ps->snf_handle);
if (err != 0) {
- snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
+ pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
"snf_start failed: %s", pcap_strerror(err));
return -1;
}
@@ -256,12 +311,104 @@ snf_activate(pcap_t* p)
p->setnonblock_op = snf_setnonblock;
p->stats_op = snf_pcap_stats;
p->cleanup_op = snf_platform_cleanup;
+#ifdef SNF_HAVE_INJECT_API
+ ps->snf_inj = NULL;
+#endif
return 0;
}
+#define MAX_DESC_LENGTH 128
int
snf_findalldevs(pcap_if_t **devlistp, char *errbuf)
{
+ pcap_if_t *devlist = NULL,*curdev,*prevdev;
+ pcap_addr_t *curaddr;
+ struct snf_ifaddrs *ifaddrs, *ifa;
+ char desc[MAX_DESC_LENGTH];
+ int ret;
+
+ if (snf_init(SNF_VERSION_API))
+ return (-1);
+
+ if (snf_getifaddrs(&ifaddrs) || ifaddrs == NULL)
+ {
+ (void)pcap_snprintf(errbuf, PCAP_ERRBUF_SIZE,
+ "snf_getifaddrs: %s", pcap_strerror(errno));
+ return (-1);
+ }
+ ifa = ifaddrs;
+ while (ifa)
+ {
+ /*
+ * Allocate a new entry
+ */
+ curdev = (pcap_if_t *)malloc(sizeof(pcap_if_t));
+ if (curdev == NULL) {
+ (void)pcap_snprintf(errbuf, PCAP_ERRBUF_SIZE,
+ "snf_findalldevs malloc: %s", pcap_strerror(errno));
+ return (-1);
+ }
+ if (devlist == NULL) /* save first entry */
+ devlist = curdev;
+ else
+ prevdev->next = curdev;
+ /*
+ * Fill in the entry.
+ */
+ curdev->next = NULL;
+ curdev->name = strdup(ifa->snf_ifa_name);
+ if (curdev->name == NULL) {
+ (void)pcap_snprintf(errbuf, PCAP_ERRBUF_SIZE,
+ "snf_findalldevs strdup: %s", pcap_strerror(errno));
+ free(curdev);
+ return (-1);
+ }
+ (void)pcap_snprintf(desc,MAX_DESC_LENGTH,"Myricom snf%d",
+ ifa->snf_ifa_portnum);
+ curdev->description = strdup(desc);
+ if (curdev->description == NULL) {
+ (void)pcap_snprintf(errbuf, PCAP_ERRBUF_SIZE,
+ "snf_findalldevs strdup1: %s", pcap_strerror(errno));
+ free(curdev->name);
+ free(curdev);
+ return (-1);
+ }
+ curdev->addresses = NULL;
+ curdev->flags = 0;
+
+ curaddr = (pcap_addr_t *)malloc(sizeof(pcap_addr_t));
+ if (curaddr == NULL) {
+ (void)pcap_snprintf(errbuf, PCAP_ERRBUF_SIZE,
+ "snf_findalldevs malloc1: %s", pcap_strerror(errno));
+ free(curdev->description);
+ free(curdev->name);
+ free(curdev);
+ return (-1);
+ }
+ curdev->addresses = curaddr;
+ curaddr->next = NULL;
+ curaddr->addr = (struct sockaddr*)malloc(sizeof(struct sockaddr_storage));
+ if (curaddr->addr == NULL) {
+ (void)pcap_snprintf(errbuf, PCAP_ERRBUF_SIZE,
+ "malloc2: %s", pcap_strerror(errno));
+ free(curdev->description);
+ free(curdev->name);
+ free(curaddr);
+ free(curdev);
+ return (-1);
+ }
+ curaddr->addr->sa_family = AF_INET;
+ curaddr->netmask = NULL;
+ curaddr->broadaddr = NULL;
+ curaddr->dstaddr = NULL;
+ curaddr->next = NULL;
+
+ prevdev = curdev;
+ ifa = ifa->snf_ifa_next;
+ }
+ snf_freeifaddrs(ifaddrs);
+ *devlistp = devlist;
+
/*
* There are no platform-specific devices since each device
* exists as a regular Ethernet device.
@@ -320,12 +467,54 @@ snf_create(const char *device, char *ebuf, int *is_ours)
/* OK, it's probably ours. */
*is_ours = 1;
- p = pcap_create_common(device, ebuf, sizeof (struct pcap_snf));
+ p = pcap_create_common(ebuf, sizeof (struct pcap_snf));
if (p == NULL)
return NULL;
ps = p->priv;
+ /*
+ * We support microsecond and nanosecond time stamps.
+ */
+ p->tstamp_precision_count = 2;
+ p->tstamp_precision_list = malloc(2 * sizeof(u_int));
+ if (p->tstamp_precision_list == NULL) {
+ pcap_snprintf(ebuf, PCAP_ERRBUF_SIZE, "malloc: %s",
+ pcap_strerror(errno));
+ pcap_close(p);
+ return NULL;
+ }
+ p->tstamp_precision_list[0] = PCAP_TSTAMP_PRECISION_MICRO;
+ p->tstamp_precision_list[1] = PCAP_TSTAMP_PRECISION_NANO;
+
p->activate_op = snf_activate;
ps->snf_boardnum = boardnum;
return p;
}
+
+#ifdef SNF_ONLY
+/*
+ * This libpcap build supports only SNF cards, not regular network
+ * interfaces..
+ */
+
+/*
+ * There are no regular interfaces, just DAG interfaces.
+ */
+int
+pcap_platform_finddevs(pcap_if_t **alldevsp, char *errbuf)
+{
+ *alldevsp = NULL;
+ return (0);
+}
+
+/*
+ * Attempts to open a regular interface fail.
+ */
+pcap_t *
+pcap_create_interface(const char *device, char *errbuf)
+{
+ pcap_snprintf(errbuf, PCAP_ERRBUF_SIZE,
+ "This version of libpcap only supports SNF cards");
+ return NULL;
+}
+#endif
diff --git a/contrib/libpcap/pcap-snit.c b/contrib/libpcap/pcap-snit.c
index e6232c2e8420..79349456bbac 100644
--- a/contrib/libpcap/pcap-snit.c
+++ b/contrib/libpcap/pcap-snit.c
@@ -130,11 +130,11 @@ pcap_read_snit(pcap_t *p, int cnt, pcap_handler callback, u_char *user)
if (cc < 0) {
if (errno == EWOULDBLOCK)
return (0);
- snprintf(p->errbuf, sizeof(p->errbuf), "pcap_read: %s",
+ pcap_snprintf(p->errbuf, sizeof(p->errbuf), "pcap_read: %s",
pcap_strerror(errno));
return (-1);
}
- bp = p->buffer;
+ bp = (u_char *)p->buffer;
} else
bp = p->bp;
@@ -211,7 +211,7 @@ static int
pcap_inject_snit(pcap_t *p, const void *buf, size_t size)
{
struct strbuf ctl, data;
-
+
/*
* XXX - can we just do
*
@@ -223,7 +223,7 @@ pcap_inject_snit(pcap_t *p, const void *buf, size_t size)
data.len = size;
ret = putmsg(p->fd, &ctl, &data);
if (ret == -1) {
- snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "send: %s",
+ pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "send: %s",
pcap_strerror(errno));
return (-1);
}
@@ -247,7 +247,7 @@ nit_setflags(pcap_t *p)
si.ic_len = sizeof(zero);
si.ic_dp = (char *)&zero;
if (ioctl(p->fd, I_STR, (char *)&si) < 0) {
- snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "NIOCSCHUNK: %s",
+ pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "NIOCSCHUNK: %s",
pcap_strerror(errno));
return (-1);
}
@@ -260,7 +260,7 @@ nit_setflags(pcap_t *p)
si.ic_len = sizeof(timeout);
si.ic_dp = (char *)&timeout;
if (ioctl(p->fd, I_STR, (char *)&si) < 0) {
- snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "NIOCSTIME: %s",
+ pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "NIOCSTIME: %s",
pcap_strerror(errno));
return (-1);
}
@@ -272,7 +272,7 @@ nit_setflags(pcap_t *p)
si.ic_len = sizeof(flags);
si.ic_dp = (char *)&flags;
if (ioctl(p->fd, I_STR, (char *)&si) < 0) {
- snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "NIOCSFLAGS: %s",
+ pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "NIOCSFLAGS: %s",
pcap_strerror(errno));
return (-1);
}
@@ -286,7 +286,7 @@ pcap_activate_snit(pcap_t *p)
struct ifreq ifr; /* interface request struct */
int chunksize = CHUNKSIZE;
int fd;
- static char dev[] = "/dev/nit";
+ static const char dev[] = "/dev/nit";
if (p->opt.rfmon) {
/*
@@ -320,19 +320,19 @@ pcap_activate_snit(pcap_t *p)
if (fd < 0 && errno == EACCES)
p->fd = fd = open(dev, O_RDONLY);
if (fd < 0) {
- snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "%s: %s", dev,
+ pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "%s: %s", dev,
pcap_strerror(errno));
goto bad;
}
/* arrange to get discrete messages from the STREAM and use NIT_BUF */
if (ioctl(fd, I_SRDOPT, (char *)RMSGD) < 0) {
- snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "I_SRDOPT: %s",
+ pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "I_SRDOPT: %s",
pcap_strerror(errno));
goto bad;
}
if (ioctl(fd, I_PUSH, "nbuf") < 0) {
- snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "push nbuf: %s",
+ pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "push nbuf: %s",
pcap_strerror(errno));
goto bad;
}
@@ -342,19 +342,24 @@ pcap_activate_snit(pcap_t *p)
si.ic_len = sizeof(chunksize);
si.ic_dp = (char *)&chunksize;
if (ioctl(fd, I_STR, (char *)&si) < 0) {
- snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "NIOCSCHUNK: %s",
+ pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "NIOCSCHUNK: %s",
pcap_strerror(errno));
goto bad;
}
/* request the interface */
- strncpy(ifr.ifr_name, p->opt.source, sizeof(ifr.ifr_name));
+ strncpy(ifr.ifr_name, p->opt.device, sizeof(ifr.ifr_name));
ifr.ifr_name[sizeof(ifr.ifr_name) - 1] = '\0';
si.ic_cmd = NIOCBIND;
si.ic_len = sizeof(ifr);
si.ic_dp = (char *)&ifr;
if (ioctl(fd, I_STR, (char *)&si) < 0) {
- snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "NIOCBIND: %s: %s",
+ /*
+ * XXX - is there an error that means "no such device"?
+ * Is there one that means "that device doesn't support
+ * STREAMS NIT"?
+ */
+ pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "NIOCBIND: %s: %s",
ifr.ifr_name, pcap_strerror(errno));
goto bad;
}
@@ -364,7 +369,7 @@ pcap_activate_snit(pcap_t *p)
si.ic_len = sizeof(p->snapshot);
si.ic_dp = (char *)&p->snapshot;
if (ioctl(fd, I_STR, (char *)&si) < 0) {
- snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "NIOCSSNAP: %s",
+ pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "NIOCSSNAP: %s",
pcap_strerror(errno));
goto bad;
}
@@ -378,7 +383,7 @@ pcap_activate_snit(pcap_t *p)
p->linktype = DLT_EN10MB;
p->bufsize = BUFSPACE;
- p->buffer = (u_char *)malloc(p->bufsize);
+ p->buffer = malloc(p->bufsize);
if (p->buffer == NULL) {
strlcpy(p->errbuf, pcap_strerror(errno), PCAP_ERRBUF_SIZE);
goto bad;
@@ -426,11 +431,11 @@ pcap_activate_snit(pcap_t *p)
}
pcap_t *
-pcap_create_interface(const char *device, char *ebuf)
+pcap_create_interface(const char *device _U_, char *ebuf)
{
pcap_t *p;
- p = pcap_create_common(device, ebuf, sizeof (struct pcap_snit));
+ p = pcap_create_common(ebuf, sizeof (struct pcap_snit));
if (p == NULL)
return (NULL);
@@ -438,8 +443,18 @@ pcap_create_interface(const char *device, char *ebuf)
return (p);
}
+/*
+ * XXX - there's probably a NIOCBIND error that means "that device
+ * doesn't support NIT"; if so, we should try an NIOCBIND and use that.
+ */
+static int
+can_be_bound(const char *name _U_)
+{
+ return (1);
+}
+
int
pcap_platform_finddevs(pcap_if_t **alldevsp, char *errbuf)
{
- return (0);
+ return (pcap_findalldevs_interfaces(alldevsp, errbuf, can_be_bound));
}
diff --git a/contrib/libpcap/pcap-snoop.c b/contrib/libpcap/pcap-snoop.c
index 9dcb7c1df058..2bc0bac58cdd 100644
--- a/contrib/libpcap/pcap-snoop.c
+++ b/contrib/libpcap/pcap-snoop.c
@@ -95,7 +95,7 @@ again:
case EWOULDBLOCK:
return (0); /* XXX */
}
- snprintf(p->errbuf, sizeof(p->errbuf),
+ pcap_snprintf(p->errbuf, sizeof(p->errbuf),
"read: %s", pcap_strerror(errno));
return (-1);
}
@@ -114,7 +114,7 @@ again:
caplen = (datalen < p->snapshot) ? datalen : p->snapshot;
cp = (u_char *)(sh + 1) + p->offset; /* XXX */
- /*
+ /*
* XXX unfortunately snoop loopback isn't exactly like
* BSD's. The address family is encoded in the first 2
* bytes rather than the first 4 bytes! Luckily the last
@@ -150,12 +150,12 @@ pcap_inject_snoop(pcap_t *p, const void *buf, size_t size)
*/
ret = write(p->fd, buf, size);
if (ret == -1) {
- snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "send: %s",
+ pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "send: %s",
pcap_strerror(errno));
return (-1);
}
return (ret);
-}
+}
static int
pcap_stats_snoop(pcap_t *p, struct pcap_stat *ps)
@@ -167,7 +167,7 @@ pcap_stats_snoop(pcap_t *p, struct pcap_stat *ps)
rs = &rawstats;
memset(rs, 0, sizeof(*rs));
if (ioctl(p->fd, SIOCRAWSTATS, (char *)rs) < 0) {
- snprintf(p->errbuf, sizeof(p->errbuf),
+ pcap_snprintf(p->errbuf, sizeof(p->errbuf),
"SIOCRAWSTATS: %s", pcap_strerror(errno));
return (-1);
}
@@ -212,22 +212,29 @@ pcap_activate_snoop(pcap_t *p)
fd = socket(PF_RAW, SOCK_RAW, RAWPROTO_SNOOP);
if (fd < 0) {
- snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "snoop socket: %s",
+ pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "snoop socket: %s",
pcap_strerror(errno));
goto bad;
}
p->fd = fd;
memset(&sr, 0, sizeof(sr));
sr.sr_family = AF_RAW;
- (void)strncpy(sr.sr_ifname, p->opt.source, sizeof(sr.sr_ifname));
+ (void)strncpy(sr.sr_ifname, p->opt.device, sizeof(sr.sr_ifname));
if (bind(fd, (struct sockaddr *)&sr, sizeof(sr))) {
- snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "snoop bind: %s",
+ /*
+ * XXX - there's probably a particular bind error that
+ * means "there's no such device" and a particular bind
+ * error that means "that device doesn't support snoop";
+ * they might be the same error, if they both end up
+ * meaning "snoop doesn't know about that device".
+ */
+ pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "snoop bind: %s",
pcap_strerror(errno));
goto bad;
}
memset(&sf, 0, sizeof(sf));
if (ioctl(fd, SIOCADDSNOOP, &sf) < 0) {
- snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "SIOCADDSNOOP: %s",
+ pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "SIOCADDSNOOP: %s",
pcap_strerror(errno));
goto bad;
}
@@ -239,19 +246,19 @@ pcap_activate_snoop(pcap_t *p)
/*
* XXX hack - map device name to link layer type
*/
- if (strncmp("et", p->opt.source, 2) == 0 || /* Challenge 10 Mbit */
- strncmp("ec", p->opt.source, 2) == 0 || /* Indigo/Indy 10 Mbit,
+ if (strncmp("et", p->opt.device, 2) == 0 || /* Challenge 10 Mbit */
+ strncmp("ec", p->opt.device, 2) == 0 || /* Indigo/Indy 10 Mbit,
O2 10/100 */
- strncmp("ef", p->opt.source, 2) == 0 || /* O200/2000 10/100 Mbit */
- strncmp("eg", p->opt.source, 2) == 0 || /* Octane/O2xxx/O3xxx Gigabit */
- strncmp("gfe", p->opt.source, 3) == 0 || /* GIO 100 Mbit */
- strncmp("fxp", p->opt.source, 3) == 0 || /* Challenge VME Enet */
- strncmp("ep", p->opt.source, 2) == 0 || /* Challenge 8x10 Mbit EPLEX */
- strncmp("vfe", p->opt.source, 3) == 0 || /* Challenge VME 100Mbit */
- strncmp("fa", p->opt.source, 2) == 0 ||
- strncmp("qaa", p->opt.source, 3) == 0 ||
- strncmp("cip", p->opt.source, 3) == 0 ||
- strncmp("el", p->opt.source, 2) == 0) {
+ strncmp("ef", p->opt.device, 2) == 0 || /* O200/2000 10/100 Mbit */
+ strncmp("eg", p->opt.device, 2) == 0 || /* Octane/O2xxx/O3xxx Gigabit */
+ strncmp("gfe", p->opt.device, 3) == 0 || /* GIO 100 Mbit */
+ strncmp("fxp", p->opt.device, 3) == 0 || /* Challenge VME Enet */
+ strncmp("ep", p->opt.device, 2) == 0 || /* Challenge 8x10 Mbit EPLEX */
+ strncmp("vfe", p->opt.device, 3) == 0 || /* Challenge VME 100Mbit */
+ strncmp("fa", p->opt.device, 2) == 0 ||
+ strncmp("qaa", p->opt.device, 3) == 0 ||
+ strncmp("cip", p->opt.device, 3) == 0 ||
+ strncmp("el", p->opt.device, 2) == 0) {
p->linktype = DLT_EN10MB;
p->offset = RAW_HDRPAD(sizeof(struct ether_header));
ll_hdrlen = sizeof(struct ether_header);
@@ -284,26 +291,26 @@ pcap_activate_snoop(pcap_t *p)
p->dlt_list[1] = DLT_DOCSIS;
p->dlt_count = 2;
}
- } else if (strncmp("ipg", p->opt.source, 3) == 0 ||
- strncmp("rns", p->opt.source, 3) == 0 || /* O2/200/2000 FDDI */
- strncmp("xpi", p->opt.source, 3) == 0) {
+ } else if (strncmp("ipg", p->opt.device, 3) == 0 ||
+ strncmp("rns", p->opt.device, 3) == 0 || /* O2/200/2000 FDDI */
+ strncmp("xpi", p->opt.device, 3) == 0) {
p->linktype = DLT_FDDI;
p->offset = 3; /* XXX yeah? */
ll_hdrlen = 13;
- } else if (strncmp("ppp", p->opt.source, 3) == 0) {
+ } else if (strncmp("ppp", p->opt.device, 3) == 0) {
p->linktype = DLT_RAW;
ll_hdrlen = 0; /* DLT_RAW meaning "no PPP header, just the IP packet"? */
- } else if (strncmp("qfa", p->opt.source, 3) == 0) {
+ } else if (strncmp("qfa", p->opt.device, 3) == 0) {
p->linktype = DLT_IP_OVER_FC;
ll_hdrlen = 24;
- } else if (strncmp("pl", p->opt.source, 2) == 0) {
+ } else if (strncmp("pl", p->opt.device, 2) == 0) {
p->linktype = DLT_RAW;
ll_hdrlen = 0; /* Cray UNICOS/mp pseudo link */
- } else if (strncmp("lo", p->opt.source, 2) == 0) {
+ } else if (strncmp("lo", p->opt.device, 2) == 0) {
p->linktype = DLT_NULL;
ll_hdrlen = 4;
} else {
- snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
+ pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
"snoop: unknown physical layer type");
goto bad;
}
@@ -323,9 +330,9 @@ pcap_activate_snoop(pcap_t *p)
* the MTU first and, if that succeeds, trim the snap length
* to be no greater than the MTU.
*/
- (void)strncpy(ifr.ifr_name, p->opt.source, sizeof(ifr.ifr_name));
+ (void)strncpy(ifr.ifr_name, p->opt.device, sizeof(ifr.ifr_name));
if (ioctl(fd, SIOCGIFMTU, (char *)&ifr) < 0) {
- snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "SIOCGIFMTU: %s",
+ pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "SIOCGIFMTU: %s",
pcap_strerror(errno));
goto bad;
}
@@ -359,21 +366,21 @@ pcap_activate_snoop(pcap_t *p)
if (snooplen < 0)
snooplen = 0;
if (ioctl(fd, SIOCSNOOPLEN, &snooplen) < 0) {
- snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "SIOCSNOOPLEN: %s",
+ pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "SIOCSNOOPLEN: %s",
pcap_strerror(errno));
goto bad;
}
v = 1;
if (ioctl(fd, SIOCSNOOPING, &v) < 0) {
- snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "SIOCSNOOPING: %s",
+ pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "SIOCSNOOPING: %s",
pcap_strerror(errno));
goto bad;
}
p->bufsize = 4096; /* XXX */
- p->buffer = (u_char *)malloc(p->bufsize);
+ p->buffer = malloc(p->bufsize);
if (p->buffer == NULL) {
- snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "malloc: %s",
+ pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "malloc: %s",
pcap_strerror(errno));
goto bad;
}
@@ -399,11 +406,11 @@ pcap_activate_snoop(pcap_t *p)
}
pcap_t *
-pcap_create_interface(const char *device, char *ebuf)
+pcap_create_interface(const char *device _U_, char *ebuf)
{
pcap_t *p;
- p = pcap_create_common(device, ebuf, sizeof (struct pcap_snoop));
+ p = pcap_create_common(ebuf, sizeof (struct pcap_snoop));
if (p == NULL)
return (NULL);
@@ -411,8 +418,18 @@ pcap_create_interface(const char *device, char *ebuf)
return (p);
}
+/*
+ * XXX - there's probably a particular bind error that means "that device
+ * doesn't support snoop"; if so, we should try a bind and use that.
+ */
+static int
+can_be_bound(const char *name _U_)
+{
+ return (1);
+}
+
int
pcap_platform_finddevs(pcap_if_t **alldevsp, char *errbuf)
{
- return (0);
+ return (pcap_findalldevs_interfaces(alldevsp, errbuf, can_be_bound));
}
diff --git a/contrib/libpcap/pcap-stdinc.h b/contrib/libpcap/pcap-stdinc.h
index f70dcce86bed..a1be68098865 100644
--- a/contrib/libpcap/pcap-stdinc.h
+++ b/contrib/libpcap/pcap-stdinc.h
@@ -28,6 +28,35 @@
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
+
+/*
+ * Copyright (C) 1999 WIDE Project.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the project nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
#ifndef pcap_stdinc_h
#define pcap_stdinc_h
@@ -45,39 +74,53 @@
#include <time.h>
#include <io.h>
-#include "bittypes.h"
-#include "IP6_misc.h"
-
-#define caddr_t char*
+#include <ws2tcpip.h>
#if defined(_MSC_VER)
- #define snprintf _snprintf
- #define vsnprintf _vsnprintf
- #define strdup _strdup
-#endif
+ /*
+ * MSVC.
+ */
+ #if _MSC_VER >= 1800
+ /*
+ * VS 2013 or newer; we have <inttypes.h>.
+ */
+ #include <inttypes.h>
-#define inline __inline
+ #define u_int8_t uint8_t
+ #define u_int16_t uint16_t
+ #define u_int32_t uint32_t
+ #define u_int64_t uint64_t
+ #else
+ /*
+ * Earlier VS; we have to define this stuff ourselves.
+ */
+ #ifndef HAVE_U_INT8_T
+ typedef unsigned char u_int8_t;
+ typedef signed char int8_t;
+ #endif
-#ifdef __MINGW32__
- #include <stdint.h>
-#else
- #ifndef _UINTPTR_T_DEFINED
- #ifdef _WIN64
- typedef unsigned __int64 uintptr_t;
- #else
- typedef _W64 unsigned int uintptr_t;
+ #ifndef HAVE_U_INT16_T
+ typedef unsigned short u_int16_t;
+ typedef signed short int16_t;
+ #endif
+
+ #ifndef HAVE_U_INT32_T
+ typedef unsigned int u_int32_t;
+ typedef signed int int32_t;
#endif
- #define _UINTPTR_T_DEFINED
- #endif
- #ifndef _INTPTR_T_DEFINED
- #ifdef _WIN64
- typedef __int64 intptr_t;
- #else
- typedef _W64 int intptr_t;
+ #ifndef HAVE_U_INT64_T
+ #ifdef _MSC_EXTENSIONS
+ typedef unsigned _int64 u_int64_t;
+ typedef _int64 int64_t;
+ #else /* _MSC_EXTENSIONS */
+ typedef unsigned long long u_int64_t;
+ typedef long long int64_t;
+ #endif
#endif
- #define _INTPTR_T_DEFINED
#endif
-#endif /*__MINGW32__*/
+#elif defined(__MINGW32__)
+ #include <stdint.h>
+#endif
#endif /* pcap_stdinc_h */
diff --git a/contrib/libpcap/pcap-tc.c b/contrib/libpcap/pcap-tc.c
new file mode 100644
index 000000000000..768dbd7c5f81
--- /dev/null
+++ b/contrib/libpcap/pcap-tc.c
@@ -0,0 +1,1284 @@
+/*
+ * Copyright (c) 2008 CACE Technologies, Davis (California)
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of CACE Technologies nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <pcap.h>
+#include <pcap-int.h>
+
+#include "pcap-tc.h"
+
+#include <malloc.h>
+#include <memory.h>
+#include <string.h>
+#include <errno.h>
+
+#ifdef _WIN32
+#include <tchar.h>
+#endif
+
+typedef TC_STATUS (TC_CALLCONV *TcFcnQueryPortList) (PTC_PORT *ppPorts, PULONG pLength);
+typedef TC_STATUS (TC_CALLCONV *TcFcnFreePortList) (TC_PORT *pPorts);
+
+typedef PCHAR (TC_CALLCONV *TcFcnStatusGetString) (TC_STATUS status);
+
+typedef PCHAR (TC_CALLCONV *TcFcnPortGetName) (TC_PORT port);
+typedef PCHAR (TC_CALLCONV *TcFcnPortGetDescription) (TC_PORT port);
+
+typedef TC_STATUS (TC_CALLCONV *TcFcnInstanceOpenByName) (PCHAR name, PTC_INSTANCE pInstance);
+typedef TC_STATUS (TC_CALLCONV *TcFcnInstanceClose) (TC_INSTANCE instance);
+typedef TC_STATUS (TC_CALLCONV *TcFcnInstanceSetFeature) (TC_INSTANCE instance, ULONG feature, ULONG value);
+typedef TC_STATUS (TC_CALLCONV *TcFcnInstanceQueryFeature) (TC_INSTANCE instance, ULONG feature, PULONG pValue);
+typedef TC_STATUS (TC_CALLCONV *TcFcnInstanceReceivePackets) (TC_INSTANCE instance, PTC_PACKETS_BUFFER pBuffer);
+typedef HANDLE (TC_CALLCONV *TcFcnInstanceGetReceiveWaitHandle) (TC_INSTANCE instance);
+typedef TC_STATUS (TC_CALLCONV *TcFcnInstanceTransmitPackets) (TC_INSTANCE instance, TC_PACKETS_BUFFER pBuffer);
+typedef TC_STATUS (TC_CALLCONV *TcFcnInstanceQueryStatistics) (TC_INSTANCE instance, PTC_STATISTICS pStatistics);
+
+typedef TC_STATUS (TC_CALLCONV *TcFcnPacketsBufferCreate) (ULONG size, PTC_PACKETS_BUFFER pBuffer);
+typedef VOID (TC_CALLCONV *TcFcnPacketsBufferDestroy) (TC_PACKETS_BUFFER buffer);
+typedef TC_STATUS (TC_CALLCONV *TcFcnPacketsBufferQueryNextPacket)(TC_PACKETS_BUFFER buffer, PTC_PACKET_HEADER pHeader, PVOID *ppData);
+typedef TC_STATUS (TC_CALLCONV *TcFcnPacketsBufferCommitNextPacket)(TC_PACKETS_BUFFER buffer, PTC_PACKET_HEADER pHeader, PVOID pData);
+
+typedef VOID (TC_CALLCONV *TcFcnStatisticsDestroy) (TC_STATISTICS statistics);
+typedef TC_STATUS (TC_CALLCONV *TcFcnStatisticsUpdate) (TC_STATISTICS statistics);
+typedef TC_STATUS (TC_CALLCONV *TcFcnStatisticsQueryValue) (TC_STATISTICS statistics, ULONG counterId, PULONGLONG pValue);
+
+typedef enum LONG
+{
+ TC_API_UNLOADED = 0,
+ TC_API_LOADED,
+ TC_API_CANNOT_LOAD,
+ TC_API_LOADING
+}
+ TC_API_LOAD_STATUS;
+
+
+typedef struct _TC_FUNCTIONS
+{
+ TC_API_LOAD_STATUS LoadStatus;
+#ifdef _WIN32
+ HMODULE hTcApiDllHandle;
+#endif
+ TcFcnQueryPortList QueryPortList;
+ TcFcnFreePortList FreePortList;
+ TcFcnStatusGetString StatusGetString;
+
+ TcFcnPortGetName PortGetName;
+ TcFcnPortGetDescription PortGetDescription;
+
+ TcFcnInstanceOpenByName InstanceOpenByName;
+ TcFcnInstanceClose InstanceClose;
+ TcFcnInstanceSetFeature InstanceSetFeature;
+ TcFcnInstanceQueryFeature InstanceQueryFeature;
+ TcFcnInstanceReceivePackets InstanceReceivePackets;
+#ifdef _WIN32
+ TcFcnInstanceGetReceiveWaitHandle InstanceGetReceiveWaitHandle;
+#endif
+ TcFcnInstanceTransmitPackets InstanceTransmitPackets;
+ TcFcnInstanceQueryStatistics InstanceQueryStatistics;
+
+ TcFcnPacketsBufferCreate PacketsBufferCreate;
+ TcFcnPacketsBufferDestroy PacketsBufferDestroy;
+ TcFcnPacketsBufferQueryNextPacket PacketsBufferQueryNextPacket;
+ TcFcnPacketsBufferCommitNextPacket PacketsBufferCommitNextPacket;
+
+ TcFcnStatisticsDestroy StatisticsDestroy;
+ TcFcnStatisticsUpdate StatisticsUpdate;
+ TcFcnStatisticsQueryValue StatisticsQueryValue;
+}
+ TC_FUNCTIONS;
+
+static pcap_if_t* TcCreatePcapIfFromPort(TC_PORT port);
+static int TcSetDatalink(pcap_t *p, int dlt);
+static int TcGetNonBlock(pcap_t *p, char *errbuf);
+static int TcSetNonBlock(pcap_t *p, int nonblock, char *errbuf);
+static void TcCleanup(pcap_t *p);
+static int TcInject(pcap_t *p, const void *buf, size_t size);
+static int TcRead(pcap_t *p, int cnt, pcap_handler callback, u_char *user);
+static int TcStats(pcap_t *p, struct pcap_stat *ps);
+static int TcSetFilter(pcap_t *p, struct bpf_program *fp);
+#ifdef _WIN32
+static struct pcap_stat *TcStatsEx(pcap_t *p, int *pcap_stat_size);
+static int TcSetBuff(pcap_t *p, int dim);
+static int TcSetMode(pcap_t *p, int mode);
+static int TcSetMinToCopy(pcap_t *p, int size);
+static HANDLE TcGetReceiveWaitHandle(pcap_t *p);
+static int TcOidGetRequest(pcap_t *p, bpf_u_int32 oid, void *data, size_t *lenp);
+static int TcOidSetRequest(pcap_t *p, bpf_u_int32 oid, const void *data, size_t *lenp);
+static u_int TcSendqueueTransmit(pcap_t *p, pcap_send_queue *queue, int sync);
+static int TcSetUserBuffer(pcap_t *p, int size);
+static int TcLiveDump(pcap_t *p, char *filename, int maxsize, int maxpacks);
+static int TcLiveDumpEnded(pcap_t *p, int sync);
+static PAirpcapHandle TcGetAirPcapHandle(pcap_t *p);
+#endif
+
+#ifdef _WIN32
+TC_FUNCTIONS g_TcFunctions =
+{
+ TC_API_UNLOADED, /* LoadStatus */
+ NULL, /* hTcApiDllHandle */
+ NULL, /* QueryPortList */
+ NULL, /* FreePortList */
+ NULL, /* StatusGetString */
+ NULL, /* PortGetName */
+ NULL, /* PortGetDescription */
+ NULL, /* InstanceOpenByName */
+ NULL, /* InstanceClose */
+ NULL, /* InstanceSetFeature */
+ NULL, /* InstanceQueryFeature */
+ NULL, /* InstanceReceivePackets */
+ NULL, /* InstanceGetReceiveWaitHandle */
+ NULL, /* InstanceTransmitPackets */
+ NULL, /* InstanceQueryStatistics */
+ NULL, /* PacketsBufferCreate */
+ NULL, /* PacketsBufferDestroy */
+ NULL, /* PacketsBufferQueryNextPacket */
+ NULL, /* PacketsBufferCommitNextPacket */
+ NULL, /* StatisticsDestroy */
+ NULL, /* StatisticsUpdate */
+ NULL /* StatisticsQueryValue */
+};
+#else
+TC_FUNCTIONS g_TcFunctions =
+{
+ TC_API_LOADED, /* LoadStatus */
+ TcQueryPortList,
+ TcFreePortList,
+ TcStatusGetString,
+ TcPortGetName,
+ TcPortGetDescription,
+ TcInstanceOpenByName,
+ TcInstanceClose,
+ TcInstanceSetFeature,
+ TcInstanceQueryFeature,
+ TcInstanceReceivePackets,
+#ifdef _WIN32
+ TcInstanceGetReceiveWaitHandle,
+#endif
+ TcInstanceTransmitPackets,
+ TcInstanceQueryStatistics,
+ TcPacketsBufferCreate,
+ TcPacketsBufferDestroy,
+ TcPacketsBufferQueryNextPacket,
+ TcPacketsBufferCommitNextPacket,
+ TcStatisticsDestroy,
+ TcStatisticsUpdate,
+ TcStatisticsQueryValue,
+};
+#endif
+
+#define MAX_TC_PACKET_SIZE 9500
+
+#pragma pack(push, 1)
+
+#define PPH_PH_FLAG_PADDING ((UCHAR)0x01)
+#define PPH_PH_VERSION ((UCHAR)0x00)
+
+typedef struct _PPI_PACKET_HEADER
+{
+ UCHAR PphVersion;
+ UCHAR PphFlags;
+ USHORT PphLength;
+ ULONG PphDlt;
+}
+ PPI_PACKET_HEADER, *PPPI_PACKET_HEADER;
+
+typedef struct _PPI_FIELD_HEADER
+{
+ USHORT PfhType;
+ USHORT PfhLength;
+}
+ PPI_FIELD_HEADER, *PPPI_FIELD_HEADER;
+
+
+#define PPI_FIELD_TYPE_AGGREGATION_EXTENSION ((UCHAR)0x08)
+
+typedef struct _PPI_FIELD_AGGREGATION_EXTENSION
+{
+ ULONG InterfaceId;
+}
+ PPI_FIELD_AGGREGATION_EXTENSION, *PPPI_FIELD_AGGREGATION_EXTENSION;
+
+
+#define PPI_FIELD_TYPE_802_3_EXTENSION ((UCHAR)0x09)
+
+#define PPI_FLD_802_3_EXT_FLAG_FCS_PRESENT ((ULONG)0x00000001)
+
+typedef struct _PPI_FIELD_802_3_EXTENSION
+{
+ ULONG Flags;
+ ULONG Errors;
+}
+ PPI_FIELD_802_3_EXTENSION, *PPPI_FIELD_802_3_EXTENSION;
+
+typedef struct _PPI_HEADER
+{
+ PPI_PACKET_HEADER PacketHeader;
+ PPI_FIELD_HEADER AggregationFieldHeader;
+ PPI_FIELD_AGGREGATION_EXTENSION AggregationField;
+ PPI_FIELD_HEADER Dot3FieldHeader;
+ PPI_FIELD_802_3_EXTENSION Dot3Field;
+}
+ PPI_HEADER, *PPPI_HEADER;
+#pragma pack(pop)
+
+#ifdef _WIN32
+//
+// This wrapper around loadlibrary appends the system folder (usually c:\windows\system32)
+// to the relative path of the DLL, so that the DLL is always loaded from an absolute path
+// (It's no longer possible to load airpcap.dll from the application folder).
+// This solves the DLL Hijacking issue discovered in August 2010
+// http://blog.metasploit.com/2010/08/exploiting-dll-hijacking-flaws.html
+//
+HMODULE LoadLibrarySafe(LPCTSTR lpFileName)
+{
+ TCHAR path[MAX_PATH];
+ TCHAR fullFileName[MAX_PATH];
+ UINT res;
+ HMODULE hModule = NULL;
+ do
+ {
+ res = GetSystemDirectory(path, MAX_PATH);
+
+ if (res == 0)
+ {
+ //
+ // some bad failure occurred;
+ //
+ break;
+ }
+
+ if (res > MAX_PATH)
+ {
+ //
+ // the buffer was not big enough
+ //
+ SetLastError(ERROR_INSUFFICIENT_BUFFER);
+ break;
+ }
+
+ if (res + 1 + _tcslen(lpFileName) + 1 < MAX_PATH)
+ {
+ memcpy(fullFileName, path, res * sizeof(TCHAR));
+ fullFileName[res] = _T('\\');
+ memcpy(&fullFileName[res + 1], lpFileName, (_tcslen(lpFileName) + 1) * sizeof(TCHAR));
+
+ hModule = LoadLibrary(fullFileName);
+ }
+ else
+ {
+ SetLastError(ERROR_INSUFFICIENT_BUFFER);
+ }
+
+ }while(FALSE);
+
+ return hModule;
+}
+
+/*
+ * NOTE: this function should be called by the pcap functions that can theoretically
+ * deal with the Tc library for the first time, namely listing the adapters and
+ * opening one. All the other ones (close, read, write, set parameters) work
+ * on an open instance of TC, so we do not care to call this function
+ */
+TC_API_LOAD_STATUS LoadTcFunctions(void)
+{
+ TC_API_LOAD_STATUS currentStatus;
+
+ do
+ {
+ currentStatus = InterlockedCompareExchange((LONG*)&g_TcFunctions.LoadStatus, TC_API_LOADING, TC_API_UNLOADED);
+
+ while(currentStatus == TC_API_LOADING)
+ {
+ currentStatus = InterlockedCompareExchange((LONG*)&g_TcFunctions.LoadStatus, TC_API_LOADING, TC_API_LOADING);
+ Sleep(10);
+ }
+
+ /*
+ * at this point we are either in the LOADED state, unloaded state (i.e. we are the ones loading everything)
+ * or in cannot load
+ */
+ if(currentStatus == TC_API_LOADED)
+ {
+ return TC_API_LOADED;
+ }
+
+ if (currentStatus == TC_API_CANNOT_LOAD)
+ {
+ return TC_API_CANNOT_LOAD;
+ }
+
+ currentStatus = TC_API_CANNOT_LOAD;
+
+ g_TcFunctions.hTcApiDllHandle = LoadLibrarySafe("TcApi.dll");
+ if (g_TcFunctions.hTcApiDllHandle == NULL) break;
+
+ g_TcFunctions.QueryPortList = (TcFcnQueryPortList) GetProcAddress(g_TcFunctions.hTcApiDllHandle, "TcQueryPortList");
+ g_TcFunctions.FreePortList = (TcFcnFreePortList) GetProcAddress(g_TcFunctions.hTcApiDllHandle, "TcFreePortList");
+
+ g_TcFunctions.StatusGetString = (TcFcnStatusGetString) GetProcAddress(g_TcFunctions.hTcApiDllHandle, "TcStatusGetString");
+
+ g_TcFunctions.PortGetName = (TcFcnPortGetName) GetProcAddress(g_TcFunctions.hTcApiDllHandle, "TcPortGetName");
+ g_TcFunctions.PortGetDescription = (TcFcnPortGetDescription) GetProcAddress(g_TcFunctions.hTcApiDllHandle, "TcPortGetDescription");
+
+ g_TcFunctions.InstanceOpenByName = (TcFcnInstanceOpenByName) GetProcAddress(g_TcFunctions.hTcApiDllHandle, "TcInstanceOpenByName");
+ g_TcFunctions.InstanceClose = (TcFcnInstanceClose) GetProcAddress(g_TcFunctions.hTcApiDllHandle, "TcInstanceClose");
+ g_TcFunctions.InstanceSetFeature = (TcFcnInstanceSetFeature) GetProcAddress(g_TcFunctions.hTcApiDllHandle, "TcInstanceSetFeature");
+ g_TcFunctions.InstanceQueryFeature = (TcFcnInstanceQueryFeature) GetProcAddress(g_TcFunctions.hTcApiDllHandle, "TcInstanceQueryFeature");
+ g_TcFunctions.InstanceReceivePackets = (TcFcnInstanceReceivePackets) GetProcAddress(g_TcFunctions.hTcApiDllHandle, "TcInstanceReceivePackets");
+ g_TcFunctions.InstanceGetReceiveWaitHandle = (TcFcnInstanceGetReceiveWaitHandle)GetProcAddress(g_TcFunctions.hTcApiDllHandle, "TcInstanceGetReceiveWaitHandle");
+ g_TcFunctions.InstanceTransmitPackets = (TcFcnInstanceTransmitPackets)GetProcAddress(g_TcFunctions.hTcApiDllHandle, "TcInstanceTransmitPackets");
+ g_TcFunctions.InstanceQueryStatistics = (TcFcnInstanceQueryStatistics)GetProcAddress(g_TcFunctions.hTcApiDllHandle, "TcInstanceQueryStatistics");
+
+ g_TcFunctions.PacketsBufferCreate = (TcFcnPacketsBufferCreate) GetProcAddress(g_TcFunctions.hTcApiDllHandle, "TcPacketsBufferCreate");
+ g_TcFunctions.PacketsBufferDestroy = (TcFcnPacketsBufferDestroy) GetProcAddress(g_TcFunctions.hTcApiDllHandle, "TcPacketsBufferDestroy");
+ g_TcFunctions.PacketsBufferQueryNextPacket = (TcFcnPacketsBufferQueryNextPacket)GetProcAddress(g_TcFunctions.hTcApiDllHandle, "TcPacketsBufferQueryNextPacket");
+ g_TcFunctions.PacketsBufferCommitNextPacket = (TcFcnPacketsBufferCommitNextPacket)GetProcAddress(g_TcFunctions.hTcApiDllHandle, "TcPacketsBufferCommitNextPacket");
+
+ g_TcFunctions.StatisticsDestroy = (TcFcnStatisticsDestroy) GetProcAddress(g_TcFunctions.hTcApiDllHandle, "TcStatisticsDestroy");
+ g_TcFunctions.StatisticsUpdate = (TcFcnStatisticsUpdate) GetProcAddress(g_TcFunctions.hTcApiDllHandle, "TcStatisticsUpdate");
+ g_TcFunctions.StatisticsQueryValue = (TcFcnStatisticsQueryValue) GetProcAddress(g_TcFunctions.hTcApiDllHandle, "TcStatisticsQueryValue");
+
+ if ( g_TcFunctions.QueryPortList == NULL
+ || g_TcFunctions.FreePortList == NULL
+ || g_TcFunctions.StatusGetString == NULL
+ || g_TcFunctions.PortGetName == NULL
+ || g_TcFunctions.PortGetDescription == NULL
+ || g_TcFunctions.InstanceOpenByName == NULL
+ || g_TcFunctions.InstanceClose == NULL
+ || g_TcFunctions.InstanceSetFeature == NULL
+ || g_TcFunctions.InstanceQueryFeature == NULL
+ || g_TcFunctions.InstanceReceivePackets == NULL
+ || g_TcFunctions.InstanceGetReceiveWaitHandle == NULL
+ || g_TcFunctions.InstanceTransmitPackets == NULL
+ || g_TcFunctions.InstanceQueryStatistics == NULL
+ || g_TcFunctions.PacketsBufferCreate == NULL
+ || g_TcFunctions.PacketsBufferDestroy == NULL
+ || g_TcFunctions.PacketsBufferQueryNextPacket == NULL
+ || g_TcFunctions.PacketsBufferCommitNextPacket == NULL
+ || g_TcFunctions.StatisticsDestroy == NULL
+ || g_TcFunctions.StatisticsUpdate == NULL
+ || g_TcFunctions.StatisticsQueryValue == NULL
+ )
+ {
+ break;
+ }
+
+ /*
+ * everything got loaded, yay!!
+ */
+ currentStatus = TC_API_LOADED;
+ }while(FALSE);
+
+ if (currentStatus != TC_API_LOADED)
+ {
+ if (g_TcFunctions.hTcApiDllHandle != NULL)
+ {
+ FreeLibrary(g_TcFunctions.hTcApiDllHandle);
+ g_TcFunctions.hTcApiDllHandle = NULL;
+ }
+ }
+
+ InterlockedExchange((LONG*)&g_TcFunctions.LoadStatus, currentStatus);
+
+ return currentStatus;
+}
+#else
+// static linking
+TC_API_LOAD_STATUS LoadTcFunctions(void)
+{
+ return TC_API_LOADED;
+}
+#endif
+
+/*
+ * Private data for capturing on TurboCap devices.
+ */
+struct pcap_tc {
+ TC_INSTANCE TcInstance;
+ TC_PACKETS_BUFFER TcPacketsBuffer;
+ ULONG TcAcceptedCount;
+ u_char *PpiPacket;
+};
+
+int
+TcFindAllDevs(pcap_if_t **alldevsp, char *errbuf)
+{
+ TC_API_LOAD_STATUS loadStatus;
+ ULONG numPorts;
+ PTC_PORT pPorts = NULL;
+ TC_STATUS status;
+ int result = 0;
+ pcap_if_t *dev, *cursor;
+ ULONG i;
+
+ do
+ {
+ loadStatus = LoadTcFunctions();
+
+ if (loadStatus != TC_API_LOADED)
+ {
+ result = 0;
+ break;
+ }
+
+ /*
+ * enumerate the ports, and add them to the list
+ */
+ status = g_TcFunctions.QueryPortList(&pPorts, &numPorts);
+
+ if (status != TC_SUCCESS)
+ {
+ result = 0;
+ break;
+ }
+
+ for (i = 0; i < numPorts; i++)
+ {
+ /*
+ * transform the port into an entry in the list
+ */
+ dev = TcCreatePcapIfFromPort(pPorts[i]);
+
+ if (dev != NULL)
+ {
+ /*
+ * append it at the end
+ */
+ if (*alldevsp == NULL)
+ {
+ *alldevsp = dev;
+ }
+ else
+ {
+ for(cursor = *alldevsp; cursor->next != NULL; cursor = cursor->next);
+ cursor->next = dev;
+ }
+ }
+ }
+
+ if (numPorts > 0)
+ {
+ /*
+ * ignore the result here
+ */
+ status = g_TcFunctions.FreePortList(pPorts);
+ }
+
+ }while(FALSE);
+
+ return result;
+}
+
+static pcap_if_t* TcCreatePcapIfFromPort(TC_PORT port)
+{
+ CHAR *name;
+ CHAR *description;
+ pcap_if_t *newIf = NULL;
+
+ newIf = (pcap_if_t*)malloc(sizeof(*newIf));
+ if (newIf == NULL)
+ {
+ return NULL;
+ }
+
+ memset(newIf, 0, sizeof(*newIf));
+
+ name = g_TcFunctions.PortGetName(port);
+ description = g_TcFunctions.PortGetDescription(port);
+
+ newIf->name = (char*)malloc(strlen(name) + 1);
+ if (newIf->name == NULL)
+ {
+ free(newIf);
+ return NULL;
+ }
+
+ newIf->description = (char*)malloc(strlen(description) + 1);
+ if (newIf->description == NULL)
+ {
+ free(newIf->name);
+ free(newIf);
+ return NULL;
+ }
+
+ strcpy(newIf->name, name);
+ strcpy(newIf->description, description);
+
+ newIf->addresses = NULL;
+ newIf->next = NULL;
+ newIf->flags = 0;
+
+ return newIf;
+
+}
+
+static int
+TcActivate(pcap_t *p)
+{
+ struct pcap_tc *pt = p->priv;
+ TC_STATUS status;
+ ULONG timeout;
+ PPPI_HEADER pPpiHeader;
+
+ if (p->opt.rfmon)
+ {
+ /*
+ * No monitor mode on Tc cards; they're Ethernet
+ * capture adapters.
+ */
+ return PCAP_ERROR_RFMON_NOTSUP;
+ }
+
+ pt->PpiPacket = malloc(sizeof(PPI_HEADER) + MAX_TC_PACKET_SIZE);
+
+ if (pt->PpiPacket == NULL)
+ {
+ pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "Error allocating memory");
+ return PCAP_ERROR;
+ }
+
+ /*
+ * Initialize the PPI fixed fields
+ */
+ pPpiHeader = (PPPI_HEADER)pt->PpiPacket;
+ pPpiHeader->PacketHeader.PphDlt = DLT_EN10MB;
+ pPpiHeader->PacketHeader.PphLength = sizeof(PPI_HEADER);
+ pPpiHeader->PacketHeader.PphFlags = 0;
+ pPpiHeader->PacketHeader.PphVersion = 0;
+
+ pPpiHeader->AggregationFieldHeader.PfhLength = sizeof(PPI_FIELD_AGGREGATION_EXTENSION);
+ pPpiHeader->AggregationFieldHeader.PfhType = PPI_FIELD_TYPE_AGGREGATION_EXTENSION;
+
+ pPpiHeader->Dot3FieldHeader.PfhLength = sizeof(PPI_FIELD_802_3_EXTENSION);
+ pPpiHeader->Dot3FieldHeader.PfhType = PPI_FIELD_TYPE_802_3_EXTENSION;
+
+ status = g_TcFunctions.InstanceOpenByName(p->opt.device, &pt->TcInstance);
+
+ if (status != TC_SUCCESS)
+ {
+ /* Adapter detected but we are not able to open it. Return failure. */
+ pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "Error opening TurboCap adapter: %s", g_TcFunctions.StatusGetString(status));
+ return PCAP_ERROR;
+ }
+
+ p->linktype = DLT_EN10MB;
+ p->dlt_list = (u_int *) malloc(sizeof(u_int) * 2);
+ /*
+ * If that fails, just leave the list empty.
+ */
+ if (p->dlt_list != NULL) {
+ p->dlt_list[0] = DLT_EN10MB;
+ p->dlt_list[1] = DLT_PPI;
+ p->dlt_count = 2;
+ }
+
+ /*
+ * ignore promiscuous mode
+ * p->opt.promisc
+ */
+
+
+ /*
+ * ignore all the buffer sizes
+ */
+
+ /*
+ * enable reception
+ */
+ status = g_TcFunctions.InstanceSetFeature(pt->TcInstance, TC_INST_FT_RX_STATUS, 1);
+
+ if (status != TC_SUCCESS)
+ {
+ pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE,"Error enabling reception on a TurboCap instance: %s", g_TcFunctions.StatusGetString(status));
+ goto bad;
+ }
+
+ /*
+ * enable transmission
+ */
+ status = g_TcFunctions.InstanceSetFeature(pt->TcInstance, TC_INST_FT_TX_STATUS, 1);
+ /*
+ * Ignore the error here.
+ */
+
+ p->inject_op = TcInject;
+ /*
+ * if the timeout is -1, it means immediate return, no timeout
+ * if the timeout is 0, it means INFINITE
+ */
+
+ if (p->opt.timeout == 0)
+ {
+ timeout = 0xFFFFFFFF;
+ }
+ else
+ if (p->opt.timeout < 0)
+ {
+ /*
+ * we insert a minimal timeout here
+ */
+ timeout = 10;
+ }
+ else
+ {
+ timeout = p->opt.timeout;
+ }
+
+ status = g_TcFunctions.InstanceSetFeature(pt->TcInstance, TC_INST_FT_READ_TIMEOUT, timeout);
+
+ if (status != TC_SUCCESS)
+ {
+ pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE,"Error setting the read timeout a TurboCap instance: %s", g_TcFunctions.StatusGetString(status));
+ goto bad;
+ }
+
+ p->read_op = TcRead;
+ p->setfilter_op = TcSetFilter;
+ p->setdirection_op = NULL; /* Not implemented. */
+ p->set_datalink_op = TcSetDatalink;
+ p->getnonblock_op = TcGetNonBlock;
+ p->setnonblock_op = TcSetNonBlock;
+ p->stats_op = TcStats;
+#ifdef _WIN32
+ p->stats_ex_op = TcStatsEx;
+ p->setbuff_op = TcSetBuff;
+ p->setmode_op = TcSetMode;
+ p->setmintocopy_op = TcSetMinToCopy;
+ p->getevent_op = TcGetReceiveWaitHandle;
+ p->oid_get_request_op = TcOidGetRequest;
+ p->oid_set_request_op = TcOidSetRequest;
+ p->sendqueue_transmit_op = TcSendqueueTransmit;
+ p->setuserbuffer_op = TcSetUserBuffer;
+ p->live_dump_op = TcLiveDump;
+ p->live_dump_ended_op = TcLiveDumpEnded;
+ p->get_airpcap_handle_op = TcGetAirPcapHandle;
+#else
+ p->selectable_fd = -1;
+#endif
+
+ p->cleanup_op = TcCleanup;
+
+ return 0;
+bad:
+ TcCleanup(p);
+ return PCAP_ERROR;
+}
+
+pcap_t *
+TcCreate(const char *device, char *ebuf, int *is_ours)
+{
+ ULONG numPorts;
+ PTC_PORT pPorts = NULL;
+ TC_STATUS status;
+ int is_tc;
+ ULONG i;
+ pcap_t *p;
+
+ if (LoadTcFunctions() != TC_API_LOADED)
+ {
+ /*
+ * XXX - report this as an error rather than as
+ * "not a TurboCap device"?
+ */
+ *is_ours = 0;
+ return NULL;
+ }
+
+ /*
+ * enumerate the ports, and add them to the list
+ */
+ status = g_TcFunctions.QueryPortList(&pPorts, &numPorts);
+
+ if (status != TC_SUCCESS)
+ {
+ /*
+ * XXX - report this as an error rather than as
+ * "not a TurboCap device"?
+ */
+ *is_ours = 0;
+ return NULL;
+ }
+
+ is_tc = FALSE;
+ for (i = 0; i < numPorts; i++)
+ {
+ if (strcmp(g_TcFunctions.PortGetName(pPorts[i]), device) == 0)
+ {
+ is_tc = TRUE;
+ break;
+ }
+ }
+
+ if (numPorts > 0)
+ {
+ /*
+ * ignore the result here
+ */
+ (void)g_TcFunctions.FreePortList(pPorts);
+ }
+
+ if (!is_tc)
+ {
+ *is_ours = 0;
+ return NULL;
+ }
+
+ /* OK, it's probably ours. */
+ *is_ours = 1;
+
+ p = pcap_create_common(ebuf, sizeof (struct pcap_tc));
+ if (p == NULL)
+ return NULL;
+
+ p->activate_op = TcActivate;
+ return p;
+}
+
+static int TcSetDatalink(pcap_t *p, int dlt)
+{
+ /*
+ * always return 0, as the check is done by pcap_set_datalink
+ */
+ return 0;
+}
+
+static int TcGetNonBlock(pcap_t *p, char *errbuf)
+{
+ pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
+ "Getting the non blocking status is not available for TurboCap ports");
+ pcap_snprintf(errbuf, PCAP_ERRBUF_SIZE,
+ "Getting the non blocking status is not available for TurboCap ports");
+ return -1;
+
+}
+static int TcSetNonBlock(pcap_t *p, int nonblock, char *errbuf)
+{
+ pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
+ "Setting the non blocking status is not available for TurboCap ports");
+ pcap_snprintf(errbuf, PCAP_ERRBUF_SIZE,
+ "Setting the non blocking status is not available for TurboCap ports");
+ return -1;
+}
+
+
+static void TcCleanup(pcap_t *p)
+{
+ struct pcap_tc *pt = p->priv;
+
+ if (pt->TcPacketsBuffer != NULL)
+ {
+ g_TcFunctions.PacketsBufferDestroy(pt->TcPacketsBuffer);
+ pt->TcPacketsBuffer = NULL;
+ }
+ if (pt->TcInstance != NULL)
+ {
+ /*
+ * here we do not check for the error values
+ */
+ g_TcFunctions.InstanceClose(pt->TcInstance);
+ pt->TcInstance = NULL;
+ }
+
+ if (pt->PpiPacket != NULL)
+ {
+ free(pt->PpiPacket);
+ pt->PpiPacket = NULL;
+ }
+
+ pcap_cleanup_live_common(p);
+}
+
+/* Send a packet to the network */
+static int TcInject(pcap_t *p, const void *buf, size_t size)
+{
+ struct pcap_tc *pt = p->priv;
+ TC_STATUS status;
+ TC_PACKETS_BUFFER buffer;
+ TC_PACKET_HEADER header;
+
+ if (size >= 0xFFFF)
+ {
+ pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "send error: the TurboCap API does not support packets larger than 64k");
+ return -1;
+ }
+
+ status = g_TcFunctions.PacketsBufferCreate(sizeof(TC_PACKET_HEADER) + TC_ALIGN_USHORT_TO_64BIT((USHORT)size), &buffer);
+
+ if (status != TC_SUCCESS)
+ {
+ pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "send error: TcPacketsBufferCreate failure: %s (%08x)", g_TcFunctions.StatusGetString(status), status);
+ return -1;
+ }
+
+ /*
+ * we assume that the packet is without the checksum, as common with WinPcap
+ */
+ memset(&header, 0, sizeof(header));
+
+ header.Length = (USHORT)size;
+ header.CapturedLength = header.Length;
+
+ status = g_TcFunctions.PacketsBufferCommitNextPacket(buffer, &header, (PVOID)buf);
+
+ if (status == TC_SUCCESS)
+ {
+ status = g_TcFunctions.InstanceTransmitPackets(pt->TcInstance, buffer);
+
+ if (status != TC_SUCCESS)
+ {
+ pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "send error: TcInstanceTransmitPackets failure: %s (%08x)", g_TcFunctions.StatusGetString(status), status);
+ }
+ }
+ else
+ {
+ pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "send error: TcPacketsBufferCommitNextPacket failure: %s (%08x)", g_TcFunctions.StatusGetString(status), status);
+ }
+
+ g_TcFunctions.PacketsBufferDestroy(buffer);
+
+ if (status != TC_SUCCESS)
+ {
+ return -1;
+ }
+ else
+ {
+ return 0;
+ }
+}
+
+static int TcRead(pcap_t *p, int cnt, pcap_handler callback, u_char *user)
+{
+ struct pcap_tc *pt = p->priv;
+ TC_STATUS status;
+ int n = 0;
+
+ /*
+ * Has "pcap_breakloop()" been called?
+ */
+ if (p->break_loop)
+ {
+ /*
+ * Yes - clear the flag that indicates that it
+ * has, and return -2 to indicate that we were
+ * told to break out of the loop.
+ */
+ p->break_loop = 0;
+ return -2;
+ }
+
+ if (pt->TcPacketsBuffer == NULL)
+ {
+ status = g_TcFunctions.InstanceReceivePackets(pt->TcInstance, &pt->TcPacketsBuffer);
+ if (status != TC_SUCCESS)
+ {
+ pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "read error, TcInstanceReceivePackets failure: %s (%08x)", g_TcFunctions.StatusGetString(status), status);
+ return -1;
+ }
+ }
+
+ while (TRUE)
+ {
+ struct pcap_pkthdr hdr;
+ TC_PACKET_HEADER tcHeader;
+ PVOID data;
+ ULONG filterResult;
+
+ /*
+ * Has "pcap_breakloop()" been called?
+ * If so, return immediately - if we haven't read any
+ * packets, clear the flag and return -2 to indicate
+ * that we were told to break out of the loop, otherwise
+ * leave the flag set, so that the *next* call will break
+ * out of the loop without having read any packets, and
+ * return the number of packets we've processed so far.
+ */
+ if (p->break_loop)
+ {
+ if (n == 0)
+ {
+ p->break_loop = 0;
+ return -2;
+ }
+ else
+ {
+ return n;
+ }
+ }
+
+ if (pt->TcPacketsBuffer == NULL)
+ {
+ break;
+ }
+
+ status = g_TcFunctions.PacketsBufferQueryNextPacket(pt->TcPacketsBuffer, &tcHeader, &data);
+
+ if (status == TC_ERROR_END_OF_BUFFER)
+ {
+ g_TcFunctions.PacketsBufferDestroy(pt->TcPacketsBuffer);
+ pt->TcPacketsBuffer = NULL;
+ break;
+ }
+
+ if (status != TC_SUCCESS)
+ {
+ pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "read error, TcPacketsBufferQueryNextPacket failure: %s (%08x)", g_TcFunctions.StatusGetString(status), status);
+ return -1;
+ }
+
+ /* No underlaying filtering system. We need to filter on our own */
+ if (p->fcode.bf_insns)
+ {
+ filterResult = bpf_filter(p->fcode.bf_insns, data, tcHeader.Length, tcHeader.CapturedLength);
+
+ if (filterResult == 0)
+ {
+ continue;
+ }
+
+ if (filterResult > tcHeader.CapturedLength)
+ {
+ filterResult = tcHeader.CapturedLength;
+ }
+ }
+ else
+ {
+ filterResult = tcHeader.CapturedLength;
+ }
+
+ pt->TcAcceptedCount ++;
+
+ hdr.ts.tv_sec = (bpf_u_int32)(tcHeader.Timestamp / (ULONGLONG)(1000 * 1000 * 1000));
+ hdr.ts.tv_usec = (bpf_u_int32)((tcHeader.Timestamp % (ULONGLONG)(1000 * 1000 * 1000)) / 1000);
+
+ if (p->linktype == DLT_EN10MB)
+ {
+ hdr.caplen = filterResult;
+ hdr.len = tcHeader.Length;
+ (*callback)(user, &hdr, data);
+ }
+ else
+ {
+ PPPI_HEADER pPpiHeader = (PPPI_HEADER)pt->PpiPacket;
+ PVOID data2 = pPpiHeader + 1;
+
+ pPpiHeader->AggregationField.InterfaceId = TC_PH_FLAGS_RX_PORT_ID(tcHeader.Flags);
+ pPpiHeader->Dot3Field.Errors = tcHeader.Errors;
+ if (tcHeader.Flags & TC_PH_FLAGS_CHECKSUM)
+ {
+ pPpiHeader->Dot3Field.Flags = PPI_FLD_802_3_EXT_FLAG_FCS_PRESENT;
+ }
+ else
+ {
+ pPpiHeader->Dot3Field.Flags = 0;
+ }
+
+ if (filterResult <= MAX_TC_PACKET_SIZE)
+ {
+ memcpy(data2, data, filterResult);
+ hdr.caplen = sizeof(PPI_HEADER) + filterResult;
+ hdr.len = sizeof(PPI_HEADER) + tcHeader.Length;
+ }
+ else
+ {
+ memcpy(data2, data, MAX_TC_PACKET_SIZE);
+ hdr.caplen = sizeof(PPI_HEADER) + MAX_TC_PACKET_SIZE;
+ hdr.len = sizeof(PPI_HEADER) + tcHeader.Length;
+ }
+
+ (*callback)(user, &hdr, pt->PpiPacket);
+
+ }
+
+ if (++n >= cnt && cnt > 0)
+ {
+ return n;
+ }
+ }
+
+ return n;
+}
+
+static int
+TcStats(pcap_t *p, struct pcap_stat *ps)
+{
+ struct pcap_tc *pt = p->priv;
+ TC_STATISTICS statistics;
+ TC_STATUS status;
+ ULONGLONG counter;
+ struct pcap_stat s;
+
+ status = g_TcFunctions.InstanceQueryStatistics(pt->TcInstance, &statistics);
+
+ if (status != TC_SUCCESS)
+ {
+ pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "TurboCap error in TcInstanceQueryStatistics: %s (%08x)", g_TcFunctions.StatusGetString(status), status);
+ return -1;
+ }
+
+ memset(&s, 0, sizeof(s));
+
+ status = g_TcFunctions.StatisticsQueryValue(statistics, TC_COUNTER_INSTANCE_TOTAL_RX_PACKETS, &counter);
+ if (status != TC_SUCCESS)
+ {
+ pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "TurboCap error in TcStatisticsQueryValue: %s (%08x)", g_TcFunctions.StatusGetString(status), status);
+ return -1;
+ }
+ if (counter <= (ULONGLONG)0xFFFFFFFF)
+ {
+ s.ps_recv = (ULONG)counter;
+ }
+ else
+ {
+ s.ps_recv = 0xFFFFFFFF;
+ }
+
+ status = g_TcFunctions.StatisticsQueryValue(statistics, TC_COUNTER_INSTANCE_RX_DROPPED_PACKETS, &counter);
+ if (status != TC_SUCCESS)
+ {
+ pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "TurboCap error in TcStatisticsQueryValue: %s (%08x)", g_TcFunctions.StatusGetString(status), status);
+ return -1;
+ }
+ if (counter <= (ULONGLONG)0xFFFFFFFF)
+ {
+ s.ps_ifdrop = (ULONG)counter;
+ s.ps_drop = (ULONG)counter;
+ }
+ else
+ {
+ s.ps_ifdrop = 0xFFFFFFFF;
+ s.ps_drop = 0xFFFFFFFF;
+ }
+
+#if defined(_WIN32) && defined(HAVE_REMOTE)
+ s.ps_capt = pt->TcAcceptedCount;
+#endif
+ *ps = s;
+
+ return 0;
+}
+
+
+/*
+ * We filter at user level, since the kernel driver does't process the packets
+ */
+static int
+TcSetFilter(pcap_t *p, struct bpf_program *fp)
+{
+ if(!fp)
+ {
+ strncpy(p->errbuf, "setfilter: No filter specified", sizeof(p->errbuf));
+ return -1;
+ }
+
+ /* Install a user level filter */
+ if (install_bpf_program(p, fp) < 0)
+ {
+ pcap_snprintf(p->errbuf, sizeof(p->errbuf),
+ "setfilter, unable to install the filter: %s", pcap_strerror(errno));
+ return -1;
+ }
+
+ return 0;
+}
+
+#ifdef _WIN32
+static struct pcap_stat *
+TcStatsEx(pcap_t *p, int *pcap_stat_size)
+{
+ struct pcap_tc *pt = p->priv;
+ TC_STATISTICS statistics;
+ TC_STATUS status;
+ ULONGLONG counter;
+
+ *pcap_stat_size = sizeof (p->stat);
+
+ status = g_TcFunctions.InstanceQueryStatistics(pt->TcInstance, &statistics);
+
+ if (status != TC_SUCCESS)
+ {
+ pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "TurboCap error in TcInstanceQueryStatistics: %s (%08x)", g_TcFunctions.StatusGetString(status), status);
+ return NULL;
+ }
+
+ memset(&p->stat, 0, sizeof(p->stat));
+
+ status = g_TcFunctions.StatisticsQueryValue(statistics, TC_COUNTER_INSTANCE_TOTAL_RX_PACKETS, &counter);
+ if (status != TC_SUCCESS)
+ {
+ pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "TurboCap error in TcStatisticsQueryValue: %s (%08x)", g_TcFunctions.StatusGetString(status), status);
+ return NULL;
+ }
+ if (counter <= (ULONGLONG)0xFFFFFFFF)
+ {
+ p->stat.ps_recv = (ULONG)counter;
+ }
+ else
+ {
+ p->stat.ps_recv = 0xFFFFFFFF;
+ }
+
+ status = g_TcFunctions.StatisticsQueryValue(statistics, TC_COUNTER_INSTANCE_RX_DROPPED_PACKETS, &counter);
+ if (status != TC_SUCCESS)
+ {
+ pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "TurboCap error in TcStatisticsQueryValue: %s (%08x)", g_TcFunctions.StatusGetString(status), status);
+ return NULL;
+ }
+ if (counter <= (ULONGLONG)0xFFFFFFFF)
+ {
+ p->stat.ps_ifdrop = (ULONG)counter;
+ p->stat.ps_drop = (ULONG)counter;
+ }
+ else
+ {
+ p->stat.ps_ifdrop = 0xFFFFFFFF;
+ p->stat.ps_drop = 0xFFFFFFFF;
+ }
+
+#ifdef HAVE_REMOTE
+ p->stat.ps_capt = pt->TcAcceptedCount;
+#endif
+
+ return &p->stat;
+}
+
+/* Set the dimension of the kernel-level capture buffer */
+static int
+TcSetBuff(pcap_t *p, int dim)
+{
+ /*
+ * XXX turbocap has an internal way of managing buffers.
+ * And at the moment it's not configurable, so we just
+ * silently ignore the request to set the buffer.
+ */
+ return 0;
+}
+
+static int
+TcSetMode(pcap_t *p, int mode)
+{
+ if (mode != MODE_CAPT)
+ {
+ pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "Mode %u not supported by TurboCap devices. TurboCap only supports capture.", mode);
+ return -1;
+ }
+
+ return 0;
+}
+
+static int
+TcSetMinToCopy(pcap_t *p, int size)
+{
+ struct pcap_tc *pt = p->priv;
+ TC_STATUS status;
+
+ if (size < 0)
+ {
+ pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "Mintocopy cannot be less than 0.");
+ return -1;
+ }
+
+ status = g_TcFunctions.InstanceSetFeature(pt->TcInstance, TC_INST_FT_MINTOCOPY, (ULONG)size);
+
+ if (status != TC_SUCCESS)
+ {
+ pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "TurboCap error setting the mintocopy: %s (%08x)", g_TcFunctions.StatusGetString(status), status);
+ }
+
+ return 0;
+}
+
+static HANDLE
+TcGetReceiveWaitHandle(pcap_t *p)
+{
+ struct pcap_tc *pt = p->priv;
+
+ return g_TcFunctions.InstanceGetReceiveWaitHandle(pt->TcInstance);
+}
+
+static int
+TcOidGetRequest(pcap_t *p, bpf_u_int32 oid _U_, void *data _U_, size_t *lenp _U_)
+{
+ pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
+ "An OID get request cannot be performed on a TurboCap device");
+ return PCAP_ERROR;
+}
+
+static int
+TcOidSetRequest(pcap_t *p, bpf_u_int32 oid _U_, const void *data _U_,
+ size_t *lenp _U_)
+{
+ pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
+ "An OID set request cannot be performed on a TurboCap device");
+ return PCAP_ERROR;
+}
+
+static u_int
+TcSendqueueTransmit(pcap_t *p, pcap_send_queue *queue _U_, int sync _U_)
+{
+ pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
+ "Packets cannot be bulk transmitted on a TurboCap device");
+ return 0;
+}
+
+static int
+TcSetUserBuffer(pcap_t *p, int size _U_)
+{
+ pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
+ "The user buffer cannot be set on a TurboCap device");
+ return -1;
+}
+
+static int
+TcLiveDump(pcap_t *p, char *filename _U_, int maxsize _U_, int maxpacks _U_)
+{
+ pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
+ "Live packet dumping cannot be performed on a TurboCap device");
+ return -1;
+}
+
+static int
+TcLiveDumpEnded(pcap_t *p, int sync _U_)
+{
+ pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
+ "Live packet dumping cannot be performed on a TurboCap device");
+ return -1;
+}
+
+static PAirpcapHandle
+TcGetAirPcapHandle(pcap_t *p _U_)
+{
+ return NULL;
+}
+#endif
diff --git a/contrib/libpcap/pcap-canusb-linux.h b/contrib/libpcap/pcap-tc.h
index c8f3be1d9c65..59ddec262c6a 100644
--- a/contrib/libpcap/pcap-canusb-linux.h
+++ b/contrib/libpcap/pcap-tc.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2009 Felix Obenhuber
+ * Copyright (c) 2008 CACE Technologies, Davis (California)
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -11,9 +11,9 @@
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
- * 3. The name of the author may not be used to endorse or promote
- * products derived from this software without specific prior written
- * permission.
+ * 3. Neither the name of CACE Technologies nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
@@ -29,9 +29,26 @@
*
*/
+#ifndef __PCAP_TC_H__
+#define __PCAP_TC_H__
+
/*
- * Prototypes for SocketCAN related functions
+ * needed because gcc headers do not have C_ASSERT
*/
-pcap_t* canusb_create(const char *device, char *ebuf, int *is_ours);
-int canusb_findalldevs(pcap_if_t **pdevlist, char* errbuf);
+#ifndef C_ASSERT
+#define C_ASSERT(a)
+#endif
+
+#include <TcApi.h>
+
+/*
+ * functions used effectively by the pcap library
+ */
+
+pcap_t *
+TcCreate(const char *device, char *ebuf, int *is_ours);
+
+int
+TcFindAllDevs(pcap_if_t **alldevsp, char *errbuf);
+#endif
diff --git a/contrib/libpcap/pcap-tstamp.manmisc.in b/contrib/libpcap/pcap-tstamp.manmisc.in
index f86f83324a57..2e1ef61d1f46 100644
--- a/contrib/libpcap/pcap-tstamp.manmisc.in
+++ b/contrib/libpcap/pcap-tstamp.manmisc.in
@@ -19,7 +19,7 @@
.\" WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
.\" MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
.\"
-.TH PCAP-TSTAMP @MAN_MISC_INFO@ "21 December 2013"
+.TH PCAP-TSTAMP @MAN_MISC_INFO@ "8 March 2015"
.SH NAME
pcap-tstamp \- packet time stamps in libpcap
.SH DESCRIPTION
@@ -104,12 +104,12 @@ precision of this time stamp is unspecified; it might or might not be
synchronized with the host operating system's clock.
.TP 5
.BR PCAP_TSTAMP_HOST_LOWPREC " - " host_lowprec
-Time stamp provided by the host on which the capture is being done.
+Time stamp provided by the host on which the capture is being done.
This is a low-precision time stamp, synchronized with the host operating
system's clock.
.TP 5
.BR PCAP_TSTAMP_HOST_HIPREC " - " host_hiprec
-Time stamp provided by the host on which the capture is being done.
+Time stamp provided by the host on which the capture is being done.
This is a high-precision time stamp; it might or might not be
synchronized with the host operating system's clock. It might be more
expensive to fetch than
@@ -125,8 +125,51 @@ Time stamp provided by the network adapter on which the capture is being
done. This is a high-precision time stamp; it is not synchronized with
the host operating system's clock.
.RE
+.LP
+By default, when performing a live capture or reading from a savefile,
+time stamps are supplied as seconds since January 1, 1970, 00:00:00 UTC,
+and microseconds since that seconds value, even if higher-resolution
+time stamps are available from the capture device or in the savefile.
+If, when reading a savefile, the time stamps in the file have a higher
+resolution than one microsecond, the additional digits of resolution are
+discarded.
+.LP
+The
+.BR pcap_set_tstamp_precision (3PCAP)
+routine can be used after a
+.B pcap_create()
+call and after a
+.B pcap_activate()
+call to specify the resolution of the time stamps to get for the device.
+If the hardware or software cannot supply a higher-resolution time
+stamp, the
+.B pcap_set_tstamp_precision()
+call will fail, and the time stamps supplied after the
+.B pcap_activate()
+call will have microsecond resolution.
+.LP
+When opening a savefile, the
+.BR pcap_open_offline_with_tstamp_precision (3PCAP)
+and
+.BR pcap_fopen_offline_with_tstamp_precision (3PCAP)
+routines can be used to specify the resolution of time stamps to be read
+from the file; if the time stamps in the file have a lower resolution,
+the fraction-of-a-second portion of the time stamps will be scaled to
+the specified resolution.
+.LP
+The
+.BR pcap_get_tstamp_precision (3PCAP)
+routine returns the resolution of time stamps that will be supplied;
+when capturing packets, this does not reflect the actual precision of
+the time stamp supplied by the hardware or operating system and, when
+reading a savefile, this does not indicate the actual precision of time
+stamps in the file.
.SH SEE ALSO
pcap_set_tstamp_type(3PCAP),
pcap_list_tstamp_types(3PCAP),
pcap_tstamp_type_val_to_name(3PCAP),
-pcap_tstamp_type_name_to_val(3PCAP)
+pcap_tstamp_type_name_to_val(3PCAP),
+pcap_set_tstamp_precision(3PCAP),
+pcap_open_offline_with_tstamp_precision(3PCAP),
+pcap_fopen_offline_with_tstamp_precision(3PCAP),
+pcap_get_tstamp_precision(3PCAP)
diff --git a/contrib/libpcap/pcap-usb-linux.c b/contrib/libpcap/pcap-usb-linux.c
index bdabf005ccae..fb1188a7d33c 100644
--- a/contrib/libpcap/pcap-usb-linux.c
+++ b/contrib/libpcap/pcap-usb-linux.c
@@ -11,8 +11,8 @@
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
- * 3. The name of the author may not be used to endorse or promote
- * products derived from this software without specific prior written
+ * 3. The name of the author may not be used to endorse or promote
+ * products derived from this software without specific prior written
* permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
@@ -32,7 +32,7 @@
* Modifications: Kris Katterjohn <katterjohn@gmail.com>
*
*/
-
+
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
@@ -139,23 +139,24 @@ static int usb_setdirection_linux(pcap_t *, pcap_direction_t);
static void usb_cleanup_linux_mmap(pcap_t *);
/* facility to add an USB device to the device list*/
-static int
+static int
usb_dev_add(pcap_if_t** alldevsp, int n, char *err_str)
{
char dev_name[10];
- char dev_descr[30];
- snprintf(dev_name, 10, USB_IFACE"%d", n);
- snprintf(dev_descr, 30, "USB bus number %d", n);
+ char dev_descr[30];
+ pcap_snprintf(dev_name, 10, USB_IFACE"%d", n);
+ pcap_snprintf(dev_descr, 30, "USB bus number %d", n);
- if (pcap_add_if(alldevsp, dev_name, 0,
+ if (pcap_add_if(alldevsp, dev_name, 0,
dev_descr, err_str) < 0)
return -1;
- return 0;
+ return 0;
}
-int
+int
usb_findalldevs(pcap_if_t **alldevsp, char *err_str)
{
+ int fd;
struct dirent* data;
int ret = 0;
DIR* dir;
@@ -163,7 +164,46 @@ usb_findalldevs(pcap_if_t **alldevsp, char *err_str)
char* name;
size_t len;
- /* try scanning sysfs usb bus directory */
+ /*
+ * Do we have a "scan all buses" device?
+ * First, try the binary device.
+ */
+ fd = open(LINUX_USB_MON_DEV"0", O_RDONLY, 0);
+ if (fd >= 0) {
+ /*
+ * Yes.
+ */
+ close(fd);
+ if (pcap_add_if(alldevsp, "usbmon0", 0, "All USB buses",
+ err_str) < 0)
+ return -1;
+ } else {
+ /*
+ * No binary device; do we have the text device?
+ */
+ fd = open(USB_TEXT_DIR"/0t", O_RDONLY, 0);
+ if (fd < 0) {
+ /*
+ * Not at the new location; try the old location.
+ */
+ fd = open(USB_TEXT_DIR_OLD"/0t", O_RDONLY, 0);
+ }
+ if (fd >= 0) {
+ /*
+ * We found it.
+ */
+ close(fd);
+ if (pcap_add_if(alldevsp, "usbmon0", 0, "All USB buses",
+ err_str) < 0)
+ return -1;
+ }
+ }
+
+ /*
+ * Now look for individual USB buses.
+ *
+ * First, try scanning sysfs USB bus directory.
+ */
dir = opendir(SYS_USB_BUS_DIR);
if (dir != NULL) {
while ((ret == 0) && ((data = readdir(dir)) != 0)) {
@@ -172,7 +212,7 @@ usb_findalldevs(pcap_if_t **alldevsp, char *err_str)
if (strncmp(name, "usb", 3) != 0)
continue;
- if (sscanf(&name[3], "%d", &n) == 0)
+ if (sscanf(&name[3], "%d", &n) == 0)
continue;
ret = usb_dev_add(alldevsp, n, err_str);
@@ -182,7 +222,7 @@ usb_findalldevs(pcap_if_t **alldevsp, char *err_str)
return ret;
}
- /* that didn't work; try scanning procfs usb bus directory */
+ /* That didn't work; try scanning procfs USB bus directory. */
dir = opendir(PROC_USB_BUS_DIR);
if (dir != NULL) {
while ((ret == 0) && ((data = readdir(dir)) != 0)) {
@@ -193,7 +233,7 @@ usb_findalldevs(pcap_if_t **alldevsp, char *err_str)
if ((len < 1) || !isdigit(name[--len]))
continue;
while (isdigit(name[--len]));
- if (sscanf(&name[len+1], "%d", &n) != 1)
+ if (sscanf(&name[len+1], "%d", &n) != 1)
continue;
ret = usb_dev_add(alldevsp, n, err_str);
@@ -207,12 +247,12 @@ usb_findalldevs(pcap_if_t **alldevsp, char *err_str)
return 0;
}
-static
+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)
+ if (len < 0)
return 0;
handlep->mmapbuflen = len;
@@ -247,7 +287,7 @@ probe_devices(int bus)
DIR* dir;
/* scan usb bus directories for device nodes */
- snprintf(buf, sizeof(buf), "/dev/bus/usb/%03d", bus);
+ pcap_snprintf(buf, sizeof(buf), "/dev/bus/usb/%03d", bus);
dir = opendir(buf);
if (!dir)
return;
@@ -259,8 +299,8 @@ probe_devices(int bus)
if (name[0] == '.')
continue;
- snprintf(buf, sizeof(buf), "/dev/bus/usb/%03d/%s", bus, data->d_name);
-
+ pcap_snprintf(buf, sizeof(buf), "/dev/bus/usb/%03d/%s", bus, data->d_name);
+
fd = open(buf, O_RDWR);
if (fd == -1)
continue;
@@ -328,7 +368,7 @@ usb_create(const char *device, char *ebuf, int *is_ours)
/* OK, it's probably ours. */
*is_ours = 1;
- p = pcap_create_common(device, ebuf, sizeof (struct pcap_usb_linux));
+ p = pcap_create_common(ebuf, sizeof (struct pcap_usb_linux));
if (p == NULL)
return (NULL);
@@ -355,15 +395,15 @@ usb_activate(pcap_t* handle)
handle->setnonblock_op = pcap_setnonblock_fd;
/*get usb bus index from device name */
- if (sscanf(handle->opt.source, USB_IFACE"%d", &handlep->bus_index) != 1)
+ if (sscanf(handle->opt.device, USB_IFACE"%d", &handlep->bus_index) != 1)
{
- snprintf(handle->errbuf, PCAP_ERRBUF_SIZE,
- "Can't get USB bus index from %s", handle->opt.source);
+ pcap_snprintf(handle->errbuf, PCAP_ERRBUF_SIZE,
+ "Can't get USB bus index from %s", handle->opt.device);
return PCAP_ERROR;
}
/*now select the read method: try to open binary interface */
- snprintf(full_path, USB_LINE_LEN, LINUX_USB_MON_DEV"%d", handlep->bus_index);
+ pcap_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)
{
@@ -402,7 +442,7 @@ usb_activate(pcap_t* handle)
}
else {
/*Binary interface not available, try open text interface */
- snprintf(full_path, USB_LINE_LEN, USB_TEXT_DIR"/%dt", handlep->bus_index);
+ pcap_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)
{
@@ -412,12 +452,12 @@ usb_activate(pcap_t* handle)
* Not found at the new location; try
* the old location.
*/
- snprintf(full_path, USB_LINE_LEN, USB_TEXT_DIR_OLD"/%dt", handlep->bus_index);
+ pcap_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) {
/* no more fallback, give it up*/
- snprintf(handle->errbuf, PCAP_ERRBUF_SIZE,
+ pcap_snprintf(handle->errbuf, PCAP_ERRBUF_SIZE,
"Can't open USB bus file %s: %s", full_path, strerror(errno));
return PCAP_ERROR;
}
@@ -445,7 +485,7 @@ usb_activate(pcap_t* handle)
* buffer */
handle->buffer = malloc(handle->bufsize);
if (!handle->buffer) {
- snprintf(handle->errbuf, PCAP_ERRBUF_SIZE,
+ pcap_snprintf(handle->errbuf, PCAP_ERRBUF_SIZE,
"malloc: %s", pcap_strerror(errno));
close(handle->fd);
return PCAP_ERROR;
@@ -453,22 +493,22 @@ usb_activate(pcap_t* handle)
return 0;
}
-static inline int
+static inline int
ascii_to_int(char c)
{
return c < 'A' ? c- '0': ((c<'a') ? c - 'A' + 10: c-'a'+10);
}
/*
- * see <linux-kernel-source>/Documentation/usb/usbmon.txt and
- * <linux-kernel-source>/drivers/usb/mon/mon_text.c for urb string
+ * see <linux-kernel-source>/Documentation/usb/usbmon.txt and
+ * <linux-kernel-source>/drivers/usb/mon/mon_text.c for urb string
* format description
*/
static int
usb_read_linux(pcap_t *handle, int max_packets, pcap_handler callback, u_char *user)
{
/* see:
- * /usr/src/linux/Documentation/usb/usbmon.txt
+ * /usr/src/linux/Documentation/usb/usbmon.txt
* for message format
*/
struct pcap_usb_linux *handlep = handle->priv;
@@ -496,20 +536,20 @@ usb_read_linux(pcap_t *handle, int max_packets, pcap_handler callback, u_char *u
if (errno == EAGAIN)
return 0; /* no data there */
- snprintf(handle->errbuf, PCAP_ERRBUF_SIZE,
+ pcap_snprintf(handle->errbuf, PCAP_ERRBUF_SIZE,
"Can't read from fd %d: %s", handle->fd, strerror(errno));
return -1;
}
- /* read urb header; %n argument may increment return value, but it's
+ /* read urb header; %n argument may increment return value, but it's
* not mandatory, so does not count on it*/
string[ret] = 0;
- ret = sscanf(string, "%x %d %c %c%c:%d:%d %s%n", &tag, &timestamp, &etype,
- &pipeid1, &pipeid2, &dev_addr, &ep_num, status,
+ ret = sscanf(string, "%x %d %c %c%c:%d:%d %s%n", &tag, &timestamp, &etype,
+ &pipeid1, &pipeid2, &dev_addr, &ep_num, status,
&cnt);
if (ret < 8)
{
- snprintf(handle->errbuf, PCAP_ERRBUF_SIZE,
+ pcap_snprintf(handle->errbuf, PCAP_ERRBUF_SIZE,
"Can't parse USB bus message '%s', too few tokens (expected 8 got %d)",
string, ret);
return -1;
@@ -521,10 +561,10 @@ usb_read_linux(pcap_t *handle, int max_packets, pcap_handler callback, u_char *u
string += cnt;
/* don't use usbmon provided timestamp, since it have low precision*/
- if (gettimeofday(&pkth.ts, NULL) < 0)
+ if (gettimeofday(&pkth.ts, NULL) < 0)
{
- snprintf(handle->errbuf, PCAP_ERRBUF_SIZE,
- "Can't get timestamp for message '%s' %d:%s",
+ pcap_snprintf(handle->errbuf, PCAP_ERRBUF_SIZE,
+ "Can't get timestamp for message '%s' %d:%s",
string, errno, strerror(errno));
return -1;
}
@@ -567,15 +607,15 @@ usb_read_linux(pcap_t *handle, int max_packets, pcap_handler callback, u_char *u
if (ret != 1)
{
/* this a setup packet, setup data can be filled with underscore if
- * usbmon has not been able to read them, so we must parse this fields as
+ * usbmon has not been able to read them, so we must parse this fields as
* strings */
pcap_usb_setup* shdr;
char str1[3], str2[3], str3[5], str4[5], str5[5];
- ret = sscanf(string, "%s %s %s %s %s%n", str1, str2, str3, str4,
+ ret = sscanf(string, "%s %s %s %s %s%n", str1, str2, str3, str4,
str5, &cnt);
if (ret < 5)
{
- snprintf(handle->errbuf, PCAP_ERRBUF_SIZE,
+ pcap_snprintf(handle->errbuf, PCAP_ERRBUF_SIZE,
"Can't parse USB bus message '%s', too few tokens (expected 5 got %d)",
string, ret);
return -1;
@@ -592,20 +632,20 @@ usb_read_linux(pcap_t *handle, int max_packets, pcap_handler callback, u_char *u
uhdr->setup_flag = 0;
}
- else
+ else
uhdr->setup_flag = 1;
/* read urb data */
ret = sscanf(string, " %d%n", &urb_len, &cnt);
if (ret < 1)
{
- snprintf(handle->errbuf, PCAP_ERRBUF_SIZE,
+ pcap_snprintf(handle->errbuf, PCAP_ERRBUF_SIZE,
"Can't parse urb length from '%s'", string);
return -1;
}
string += cnt;
- /* urb tag is not present if urb length is 0, so we can stop here
+ /* urb tag is not present if urb length is 0, so we can stop here
* text parsing */
pkth.len = urb_len+pkth.caplen;
uhdr->urb_len = urb_len;
@@ -617,12 +657,12 @@ usb_read_linux(pcap_t *handle, int max_packets, pcap_handler callback, u_char *u
/* check for data presence; data is present if and only if urb tag is '=' */
if (sscanf(string, " %c", &urb_tag) != 1)
{
- snprintf(handle->errbuf, PCAP_ERRBUF_SIZE,
+ pcap_snprintf(handle->errbuf, PCAP_ERRBUF_SIZE,
"Can't parse urb tag from '%s'", string);
return -1;
}
- if (urb_tag != '=')
+ if (urb_tag != '=')
goto got;
/* skip urb tag and following space */
@@ -631,12 +671,12 @@ usb_read_linux(pcap_t *handle, int max_packets, pcap_handler callback, u_char *u
/* if we reach this point we got some urb data*/
uhdr->data_flag = 0;
- /* read all urb data; if urb length is greater then the usbmon internal
+ /* read all urb data; if urb length is greater then the usbmon internal
* buffer length used by the kernel to spool the URB, we get only
* a partial information.
* At least until linux 2.6.17 there is no way to set usbmon intenal buffer
* length and default value is 130. */
- while ((string[0] != 0) && (string[1] != 0) && (pkth.caplen < handle->snapshot))
+ while ((string[0] != 0) && (string[1] != 0) && (pkth.caplen < (bpf_u_int32)handle->snapshot))
{
rawdata[0] = ascii_to_int(string[0]) * 16 + ascii_to_int(string[1]);
rawdata++;
@@ -649,8 +689,8 @@ usb_read_linux(pcap_t *handle, int max_packets, pcap_handler callback, u_char *u
got:
uhdr->data_len = data_len;
- if (pkth.caplen > handle->snapshot)
- pkth.caplen = handle->snapshot;
+ if (pkth.caplen > (bpf_u_int32)handle->snapshot)
+ pkth.caplen = (bpf_u_int32)handle->snapshot;
if (handle->fcode.bf_insns == NULL ||
bpf_filter(handle->fcode.bf_insns, handle->buffer,
@@ -665,12 +705,12 @@ got:
static int
usb_inject_linux(pcap_t *handle, const void *buf, size_t size)
{
- snprintf(handle->errbuf, PCAP_ERRBUF_SIZE, "inject not supported on "
+ pcap_snprintf(handle->errbuf, PCAP_ERRBUF_SIZE, "inject not supported on "
"USB devices");
return (-1);
}
-static int
+static int
usb_stats_linux(pcap_t *handle, struct pcap_stat *stats)
{
struct pcap_usb_linux *handlep = handle->priv;
@@ -680,7 +720,7 @@ usb_stats_linux(pcap_t *handle, struct pcap_stat *stats)
char * ptr = string;
int fd;
- snprintf(string, USB_LINE_LEN, USB_TEXT_DIR"/%ds", handlep->bus_index);
+ pcap_snprintf(string, USB_LINE_LEN, USB_TEXT_DIR"/%ds", handlep->bus_index);
fd = open(string, O_RDONLY, 0);
if (fd < 0)
{
@@ -690,12 +730,12 @@ usb_stats_linux(pcap_t *handle, struct pcap_stat *stats)
* Not found at the new location; try the old
* location.
*/
- snprintf(string, USB_LINE_LEN, USB_TEXT_DIR_OLD"/%ds", handlep->bus_index);
+ pcap_snprintf(string, USB_LINE_LEN, USB_TEXT_DIR_OLD"/%ds", handlep->bus_index);
fd = open(string, O_RDONLY, 0);
}
if (fd < 0) {
- snprintf(handle->errbuf, PCAP_ERRBUF_SIZE,
- "Can't open USB stats file %s: %s",
+ pcap_snprintf(handle->errbuf, PCAP_ERRBUF_SIZE,
+ "Can't open USB stats file %s: %s",
string, strerror(errno));
return -1;
}
@@ -709,7 +749,7 @@ usb_stats_linux(pcap_t *handle, struct pcap_stat *stats)
if (ret < 0)
{
- snprintf(handle->errbuf, PCAP_ERRBUF_SIZE,
+ pcap_snprintf(handle->errbuf, PCAP_ERRBUF_SIZE,
"Can't read stats from fd %d ", fd);
return -1;
}
@@ -717,11 +757,11 @@ usb_stats_linux(pcap_t *handle, struct pcap_stat *stats)
/* extract info on dropped urbs */
for (consumed=0; consumed < ret; ) {
- /* from the sscanf man page:
- * The C standard says: "Execution of a %n directive does
+ /* from the sscanf man page:
+ * The C standard says: "Execution of a %n directive does
* not increment the assignment count returned at the completion
* of execution" but the Corrigendum seems to contradict this.
- * Do not make any assumptions on the effect of %n conversions
+ * Do not make any assumptions on the effect of %n conversions
* on the return value and explicitly check for cnt assignmet*/
int ntok;
@@ -733,7 +773,7 @@ usb_stats_linux(pcap_t *handle, struct pcap_stat *stats)
ptr += cnt;
if (strcmp(token, "nreaders") == 0)
ret = sscanf(ptr, "%d", &stats->ps_drop);
- else
+ else
ret = sscanf(ptr, "%d", &dummy);
if (ntok != 1)
break;
@@ -746,7 +786,7 @@ usb_stats_linux(pcap_t *handle, struct pcap_stat *stats)
return 0;
}
-static int
+static int
usb_setdirection_linux(pcap_t *p, pcap_direction_t d)
{
p->direction = d;
@@ -754,7 +794,7 @@ usb_setdirection_linux(pcap_t *p, pcap_direction_t d)
}
-static int
+static int
usb_stats_linux_bin(pcap_t *handle, struct pcap_stat *stats)
{
struct pcap_usb_linux *handlep = handle->priv;
@@ -763,7 +803,7 @@ usb_stats_linux_bin(pcap_t *handle, struct pcap_stat *stats)
ret = ioctl(handle->fd, MON_IOCG_STATS, &st);
if (ret < 0)
{
- snprintf(handle->errbuf, PCAP_ERRBUF_SIZE,
+ pcap_snprintf(handle->errbuf, PCAP_ERRBUF_SIZE,
"Can't read stats from fd %d:%s ", handle->fd, strerror(errno));
return -1;
}
@@ -775,7 +815,7 @@ usb_stats_linux_bin(pcap_t *handle, struct pcap_stat *stats)
}
/*
- * see <linux-kernel-source>/Documentation/usb/usbmon.txt and
+ * see <linux-kernel-source>/Documentation/usb/usbmon.txt and
* <linux-kernel-source>/drivers/usb/mon/mon_bin.c binary ABI
*/
static int
@@ -785,11 +825,11 @@ usb_read_linux_bin(pcap_t *handle, int max_packets, pcap_handler callback, u_cha
struct mon_bin_get info;
int ret;
struct pcap_pkthdr pkth;
- int clen = handle->snapshot - sizeof(pcap_usb_header);
+ u_int clen = handle->snapshot - sizeof(pcap_usb_header);
/* the usb header is going to be part of 'packet' data*/
info.hdr = (pcap_usb_header*) handle->buffer;
- info.data = handle->buffer + sizeof(pcap_usb_header);
+ info.data = (u_char *)handle->buffer + sizeof(pcap_usb_header);
info.data_len = clen;
/* ignore interrupt system call errors */
@@ -806,7 +846,7 @@ usb_read_linux_bin(pcap_t *handle, int max_packets, pcap_handler callback, u_cha
if (errno == EAGAIN)
return 0; /* no data there */
- snprintf(handle->errbuf, PCAP_ERRBUF_SIZE,
+ pcap_snprintf(handle->errbuf, PCAP_ERRBUF_SIZE,
"Can't read from fd %d: %s", handle->fd, strerror(errno));
return -1;
}
@@ -833,7 +873,7 @@ usb_read_linux_bin(pcap_t *handle, int max_packets, pcap_handler callback, u_cha
}
/*
- * see <linux-kernel-source>/Documentation/usb/usbmon.txt and
+ * see <linux-kernel-source>/Documentation/usb/usbmon.txt and
* <linux-kernel-source>/drivers/usb/mon/mon_bin.c binary ABI
*/
#define VEC_SIZE 32
@@ -847,7 +887,7 @@ usb_read_linux_mmap(pcap_t *handle, int max_packets, pcap_handler callback, u_ch
pcap_usb_header* hdr;
int nflush = 0;
int packets = 0;
- int clen, max_clen;
+ u_int clen, max_clen;
max_clen = handle->snapshot - sizeof(pcap_usb_header);
@@ -877,7 +917,7 @@ usb_read_linux_mmap(pcap_t *handle, int max_packets, pcap_handler callback, u_ch
if (errno == EAGAIN)
return 0; /* no data there */
- snprintf(handle->errbuf, PCAP_ERRBUF_SIZE,
+ pcap_snprintf(handle->errbuf, PCAP_ERRBUF_SIZE,
"Can't mfetch fd %d: %s", handle->fd, strerror(errno));
return -1;
}
@@ -887,7 +927,7 @@ usb_read_linux_mmap(pcap_t *handle, int max_packets, pcap_handler callback, u_ch
for (i=0; i<fetch.nfetch; ++i) {
/* discard filler */
hdr = (pcap_usb_header*) &handlep->mmapbuf[vec[i]];
- if (hdr->event_type == '@')
+ if (hdr->event_type == '@')
continue;
/* we can get less that than really captured from kernel, depending on
@@ -917,7 +957,11 @@ usb_read_linux_mmap(pcap_t *handle, int max_packets, pcap_handler callback, u_ch
}
/* flush pending events*/
- ioctl(handle->fd, MON_IOCH_MFLUSH, nflush);
+ if (ioctl(handle->fd, MON_IOCH_MFLUSH, nflush) == -1) {
+ pcap_snprintf(handle->errbuf, PCAP_ERRBUF_SIZE,
+ "Can't mflush fd %d: %s", handle->fd, strerror(errno));
+ return -1;
+ }
return packets;
}
diff --git a/contrib/libpcap/pcap-usb-linux.h b/contrib/libpcap/pcap-usb-linux.h
index 06dee01339a5..234a262f9093 100644
--- a/contrib/libpcap/pcap-usb-linux.h
+++ b/contrib/libpcap/pcap-usb-linux.h
@@ -11,8 +11,8 @@
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
- * 3. The name of the author may not be used to endorse or promote
- * products derived from this software without specific prior written
+ * 3. The name of the author may not be used to endorse or promote
+ * products derived from this software without specific prior written
* permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
diff --git a/contrib/libpcap/pcap-win32.c b/contrib/libpcap/pcap-win32.c
index f63b5c472b93..d998637e6baa 100644
--- a/contrib/libpcap/pcap-win32.c
+++ b/contrib/libpcap/pcap-win32.c
@@ -1,6 +1,6 @@
/*
* Copyright (c) 1999 - 2005 NetGroup, Politecnico di Torino (Italy)
- * Copyright (c) 2005 - 2008 CACE Technologies, Davis (California)
+ * Copyright (c) 2005 - 2010 CACE Technologies, Davis (California)
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -12,9 +12,9 @@
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
- * 3. Neither the name of the Politecnico di Torino, CACE Technologies
- * nor the names of its contributors may be used to endorse or promote
- * products derived from this software without specific prior written
+ * 3. Neither the name of the Politecnico di Torino, CACE Technologies
+ * nor the names of its contributors may be used to endorse or promote
+ * products derived from this software without specific prior written
* permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
@@ -31,8 +31,10 @@
*
*/
-#include <pcap-int.h>
+#define PCAP_DONT_INCLUDE_PCAP_BPF_H
#include <Packet32.h>
+#include <pcap-int.h>
+#include <pcap/dlt.h>
#ifdef __MINGW32__
#ifdef __MINGW64__
#include <ntddndis.h>
@@ -51,6 +53,9 @@
int* _errno();
#define errno (*_errno())
#endif /* __MINGW32__ */
+#ifdef HAVE_REMOTE
+#include "pcap-rpcap.h"
+#endif /* HAVE_REMOTE */
static int pcap_setfilter_win32_npf(pcap_t *, struct bpf_program *);
static int pcap_setfilter_win32_dag(pcap_t *, struct bpf_program *);
@@ -71,45 +76,64 @@ static int pcap_setnonblock_win32(pcap_t *, int, char *);
*/
struct pcap_win {
int nonblock;
-
- int filtering_in_kernel; /* using kernel filter */
+ int rfmon_selfstart; /* a flag tells whether the monitor mode is set by itself */
+ int filtering_in_kernel; /* using kernel filter */
#ifdef HAVE_DAG_API
- int dag_fcs_bits; /* Number of checksum bits from link layer */
+ 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
- */
-struct bpf_hdr {
- struct timeval bh_tstamp; /* time stamp */
- bpf_u_int32 bh_caplen; /* length of captured portion */
- bpf_u_int32 bh_datalen; /* original length of packet */
- u_short bh_hdrlen; /* length of bpf header (this struct
- plus alignment padding) */
-};
-
-CRITICAL_SECTION g_PcapCompileCriticalSection;
-
BOOL WINAPI DllMain(
HANDLE hinstDLL,
DWORD dwReason,
LPVOID lpvReserved
)
{
- if (dwReason == DLL_PROCESS_ATTACH)
- {
- InitializeCriticalSection(&g_PcapCompileCriticalSection);
- }
+ return (TRUE);
+}
+
+/*
+ * Define stub versions of the monitor-mode support routines if this
+ * isn't Npcap. HAVE_NPCAP_PACKET_API is defined by Npcap but not
+ * WinPcap.
+ */
+#ifndef HAVE_NPCAP_PACKET_API
+static int
+PacketIsMonitorModeSupported(PCHAR AdapterName _U_)
+{
+ /*
+ * We don't support monitor mode.
+ */
+ return (0);
+}
+
+static int
+PacketSetMonitorMode(PCHAR AdapterName _U_, int mode _U_)
+{
+ /*
+ * This should never be called, as PacketIsMonitorModeSupported()
+ * will return 0, meaning "we don't support monitor mode, so
+ * don't try to turn it on or off".
+ */
+ return (0);
+}
- return TRUE;
+static int
+PacketGetMonitorMode(PCHAR AdapterName _U_)
+{
+ /*
+ * This should fail, so that pcap_activate_win32() returns
+ * PCAP_ERROR_RFMON_NOTSUP if our caller requested monitor
+ * mode.
+ */
+ return (-1);
}
+#endif
/* Start winsock */
-int
-wsockinit()
+int
+wsockinit(void)
{
WORD wVersionRequested;
WSADATA wsaData;
@@ -117,34 +141,114 @@ wsockinit()
static int done = 0;
if (done)
- return err;
-
- wVersionRequested = MAKEWORD( 1, 1);
+ return (err);
+
+ wVersionRequested = MAKEWORD( 1, 1);
err = WSAStartup( wVersionRequested, &wsaData );
atexit ((void(*)(void))WSACleanup);
- InitializeCriticalSection(&g_PcapCompileCriticalSection);
done = 1;
-
+
if ( err != 0 )
err = -1;
- return err;
+ return (err);
}
-int pcap_wsockinit()
+int
+pcap_wsockinit(void)
{
- return wsockinit();
+ return (wsockinit());
}
static int
pcap_stats_win32(pcap_t *p, struct pcap_stat *ps)
{
+ struct bpf_stat bstats;
+ char errbuf[PCAP_ERRBUF_SIZE+1];
- if(PacketGetStats(p->adapter, (struct bpf_stat*)ps) != TRUE){
- snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "PacketGetStats error: %s", pcap_win32strerror());
- return -1;
+ /*
+ * Try to get statistics.
+ *
+ * (Please note - "struct pcap_stat" is *not* the same as
+ * WinPcap's "struct bpf_stat". It might currently have the
+ * same layout, but let's not cheat.
+ *
+ * Note also that we don't fill in ps_capt, as we might have
+ * been called by code compiled against an earlier version of
+ * WinPcap that didn't have ps_capt, in which case filling it
+ * in would stomp on whatever comes after the structure passed
+ * to us.
+ */
+ if (!PacketGetStats(p->adapter, &bstats)) {
+ pcap_win32_err_to_str(GetLastError(), errbuf);
+ pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
+ "PacketGetStats error: %s", errbuf);
+ return (-1);
}
+ ps->ps_recv = bstats.bs_recv;
+ ps->ps_drop = bstats.bs_drop;
+
+ /*
+ * XXX - PacketGetStats() doesn't fill this in, so we just
+ * return 0.
+ */
+#if 0
+ ps->ps_ifdrop = bstats.ps_ifdrop;
+#else
+ ps->ps_ifdrop = 0;
+#endif
- return 0;
+ return (0);
+}
+
+/*
+ * Win32-only routine for getting statistics.
+ *
+ * This way is definitely safer than passing the pcap_stat * from the userland.
+ * In fact, there could happen than the user allocates a variable which is not
+ * big enough for the new structure, and the library will write in a zone
+ * which is not allocated to this variable.
+ *
+ * In this way, we're pretty sure we are writing on memory allocated to this
+ * variable.
+ *
+ * XXX - but this is the wrong way to handle statistics. Instead, we should
+ * have an API that returns data in a form like the Options section of a
+ * pcapng Interface Statistics Block:
+ *
+ * http://xml2rfc.tools.ietf.org/cgi-bin/xml2rfc.cgi?url=https://raw.githubusercontent.com/pcapng/pcapng/master/draft-tuexen-opsawg-pcapng.xml&modeAsFormat=html/ascii&type=ascii#rfc.section.4.6
+ *
+ * which would let us add new statistics straightforwardly and indicate which
+ * statistics we are and are *not* providing, rather than having to provide
+ * possibly-bogus values for statistics we can't provide.
+ */
+struct pcap_stat *
+pcap_stats_ex_win32(pcap_t *p, int *pcap_stat_size)
+{
+ struct bpf_stat bstats;
+ char errbuf[PCAP_ERRBUF_SIZE+1];
+
+ *pcap_stat_size = sizeof (p->stat);
+
+ /*
+ * Try to get statistics.
+ *
+ * (Please note - "struct pcap_stat" is *not* the same as
+ * WinPcap's "struct bpf_stat". It might currently have the
+ * same layout, but let's not cheat.)
+ */
+ if (!PacketGetStatsEx(p->adapter, &bstats)) {
+ pcap_win32_err_to_str(GetLastError(), errbuf);
+ pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
+ "PacketGetStatsEx error: %s", errbuf);
+ return (NULL);
+ }
+ p->stat.ps_recv = bstats.bs_recv;
+ p->stat.ps_drop = bstats.bs_drop;
+ p->stat.ps_ifdrop = bstats.ps_ifdrop;
+#ifdef HAVE_REMOTE
+ p->stat.ps_capt = bstats.bs_capt;
+#endif
+ return (&p->stat);
}
/* Set the dimension of the kernel-level capture buffer */
@@ -153,10 +257,10 @@ pcap_setbuff_win32(pcap_t *p, int dim)
{
if(PacketSetBuff(p->adapter,dim)==FALSE)
{
- snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "driver error: not enough memory to allocate the kernel buffer");
- return -1;
+ pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "driver error: not enough memory to allocate the kernel buffer");
+ return (-1);
}
- return 0;
+ return (0);
}
/* Set the driver working mode */
@@ -165,11 +269,11 @@ pcap_setmode_win32(pcap_t *p, int mode)
{
if(PacketSetMode(p->adapter,mode)==FALSE)
{
- snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "driver error: working mode not recognized");
- return -1;
+ pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "driver error: working mode not recognized");
+ return (-1);
}
- return 0;
+ return (0);
}
/*set the minimum amount of data that will release a read call*/
@@ -178,22 +282,210 @@ pcap_setmintocopy_win32(pcap_t *p, int size)
{
if(PacketSetMinToCopy(p->adapter, size)==FALSE)
{
- snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "driver error: unable to set the requested mintocopy size");
- return -1;
+ pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "driver error: unable to set the requested mintocopy size");
+ return (-1);
+ }
+ return (0);
+}
+
+static HANDLE
+pcap_getevent_win32(pcap_t *p)
+{
+ return (PacketGetReadEvent(p->adapter));
+}
+
+static int
+pcap_oid_get_request_win32(pcap_t *p, bpf_u_int32 oid, void *data, size_t *lenp)
+{
+ PACKET_OID_DATA *oid_data_arg;
+ char errbuf[PCAP_ERRBUF_SIZE+1];
+
+ /*
+ * Allocate a PACKET_OID_DATA structure to hand to PacketRequest().
+ * It should be big enough to hold "*lenp" bytes of data; it
+ * will actually be slightly larger, as PACKET_OID_DATA has a
+ * 1-byte data array at the end, standing in for the variable-length
+ * data that's actually there.
+ */
+ oid_data_arg = malloc(sizeof (PACKET_OID_DATA) + *lenp);
+ if (oid_data_arg == NULL) {
+ pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
+ "Couldn't allocate argument buffer for PacketRequest");
+ return (PCAP_ERROR);
+ }
+
+ /*
+ * No need to copy the data - we're doing a fetch.
+ */
+ oid_data_arg->Oid = oid;
+ oid_data_arg->Length = (ULONG)(*lenp); /* XXX - check for ridiculously large value? */
+ if (!PacketRequest(p->adapter, FALSE, oid_data_arg)) {
+ pcap_win32_err_to_str(GetLastError(), errbuf);
+ pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
+ "Error calling PacketRequest: %s", errbuf);
+ free(oid_data_arg);
+ return (PCAP_ERROR);
+ }
+
+ /*
+ * Get the length actually supplied.
+ */
+ *lenp = oid_data_arg->Length;
+
+ /*
+ * Copy back the data we fetched.
+ */
+ memcpy(data, oid_data_arg->Data, *lenp);
+ free(oid_data_arg);
+ return (0);
+}
+
+static int
+pcap_oid_set_request_win32(pcap_t *p, bpf_u_int32 oid, const void *data,
+ size_t *lenp)
+{
+ PACKET_OID_DATA *oid_data_arg;
+ char errbuf[PCAP_ERRBUF_SIZE+1];
+
+ /*
+ * Allocate a PACKET_OID_DATA structure to hand to PacketRequest().
+ * It should be big enough to hold "*lenp" bytes of data; it
+ * will actually be slightly larger, as PACKET_OID_DATA has a
+ * 1-byte data array at the end, standing in for the variable-length
+ * data that's actually there.
+ */
+ oid_data_arg = malloc(sizeof (PACKET_OID_DATA) + *lenp);
+ if (oid_data_arg == NULL) {
+ pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
+ "Couldn't allocate argument buffer for PacketRequest");
+ return (PCAP_ERROR);
+ }
+
+ oid_data_arg->Oid = oid;
+ oid_data_arg->Length = (ULONG)(*lenp); /* XXX - check for ridiculously large value? */
+ memcpy(oid_data_arg->Data, data, *lenp);
+ if (!PacketRequest(p->adapter, TRUE, oid_data_arg)) {
+ pcap_win32_err_to_str(GetLastError(), errbuf);
+ pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
+ "Error calling PacketRequest: %s", errbuf);
+ free(oid_data_arg);
+ return (PCAP_ERROR);
+ }
+
+ /*
+ * Get the length actually copied.
+ */
+ *lenp = oid_data_arg->Length;
+
+ /*
+ * No need to copy the data - we're doing a set.
+ */
+ free(oid_data_arg);
+ return (0);
+}
+
+static u_int
+pcap_sendqueue_transmit_win32(pcap_t *p, pcap_send_queue *queue, int sync)
+{
+ u_int res;
+ char errbuf[PCAP_ERRBUF_SIZE+1];
+
+ if (p->adapter==NULL) {
+ pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
+ "Cannot transmit a queue to an offline capture or to a TurboCap port");
+ return (0);
}
- return 0;
+
+ res = PacketSendPackets(p->adapter,
+ queue->buffer,
+ queue->len,
+ (BOOLEAN)sync);
+
+ if(res != queue->len){
+ pcap_win32_err_to_str(GetLastError(), errbuf);
+ pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
+ "Error opening adapter: %s", errbuf);
+ }
+
+ return (res);
}
-/*return the Adapter for a pcap_t*/
-static Adapter *
-pcap_getadapter_win32(pcap_t *p)
+static int
+pcap_setuserbuffer_win32(pcap_t *p, int size)
{
- return p->adapter;
+ unsigned char *new_buff;
+
+ if (size<=0) {
+ /* Bogus parameter */
+ pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
+ "Error: invalid size %d",size);
+ return (-1);
+ }
+
+ /* Allocate the buffer */
+ new_buff=(unsigned char*)malloc(sizeof(char)*size);
+
+ if (!new_buff) {
+ pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
+ "Error: not enough memory");
+ return (-1);
+ }
+
+ free(p->buffer);
+
+ p->buffer=new_buff;
+ p->bufsize=size;
+
+ return (0);
+}
+
+static int
+pcap_live_dump_win32(pcap_t *p, char *filename, int maxsize, int maxpacks)
+{
+ BOOLEAN res;
+
+ /* Set the packet driver in dump mode */
+ res = PacketSetMode(p->adapter, PACKET_MODE_DUMP);
+ if(res == FALSE){
+ pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
+ "Error setting dump mode");
+ return (-1);
+ }
+
+ /* Set the name of the dump file */
+ res = PacketSetDumpName(p->adapter, filename, (int)strlen(filename));
+ if(res == FALSE){
+ pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
+ "Error setting kernel dump file name");
+ return (-1);
+ }
+
+ /* Set the limits of the dump file */
+ res = PacketSetDumpLimits(p->adapter, maxsize, maxpacks);
+
+ return (0);
+}
+
+static int
+pcap_live_dump_ended_win32(pcap_t *p, int sync)
+{
+ return (PacketIsDumpEnded(p->adapter, (BOOLEAN)sync));
+}
+
+static PAirpcapHandle
+pcap_get_airpcap_handle_win32(pcap_t *p)
+{
+#ifdef HAVE_AIRPCAP_API
+ return (PacketGetAirPcapHandle(p->adapter));
+#else
+ return (NULL);
+#endif /* HAVE_AIRPCAP_API */
}
static int
pcap_read_win32_npf(pcap_t *p, int cnt, pcap_handler callback, u_char *user)
{
+ PACKET Packet;
int cc;
int n = 0;
register u_char *bp, *ep;
@@ -215,16 +507,28 @@ pcap_read_win32_npf(pcap_t *p, int cnt, pcap_handler callback, u_char *user)
return (PCAP_ERROR_BREAK);
}
- /* capture the packets */
- if(PacketReceivePacket(p->adapter,p->Packet,TRUE)==FALSE){
- snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "read error: PacketReceivePacket failed");
+ /*
+ * Capture the packets.
+ *
+ * The PACKET structure had a bunch of extra stuff for
+ * Windows 9x/Me, but the only interesting data in it
+ * in the versions of Windows that we support is just
+ * a copy of p->buffer, a copy of p->buflen, and the
+ * actual number of bytes read returned from
+ * PacketReceivePacket(), none of which has to be
+ * retained from call to call, so we just keep one on
+ * the stack.
+ */
+ PacketInitPacket(&Packet, (BYTE *)p->buffer, p->bufsize);
+ if (!PacketReceivePacket(p->adapter, &Packet, TRUE)) {
+ pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "read error: PacketReceivePacket failed");
return (PCAP_ERROR);
}
-
- cc = p->Packet->ulBytesReceived;
- bp = p->Packet->Buffer;
- }
+ cc = Packet.ulBytesReceived;
+
+ bp = p->buffer;
+ }
else
bp = p->bp;
@@ -252,7 +556,7 @@ pcap_read_win32_npf(pcap_t *p, int cnt, pcap_handler callback, u_char *user)
return (PCAP_ERROR_BREAK);
} else {
p->bp = bp;
- p->cc = ep - bp;
+ p->cc = (int) (ep - bp);
return (n);
}
}
@@ -282,7 +586,7 @@ pcap_read_win32_npf(pcap_t *p, int cnt, pcap_handler callback, u_char *user)
bp += Packet_WORDALIGN(caplen + hdrlen);
if (++n >= cnt && !PACKET_COUNT_IS_UNLIMITED(cnt)) {
p->bp = bp;
- p->cc = ep - bp;
+ p->cc = (int) (ep - bp);
return (n);
}
} else {
@@ -302,6 +606,7 @@ static int
pcap_read_win32_dag(pcap_t *p, int cnt, pcap_handler callback, u_char *user)
{
struct pcap_win *pw = p->priv;
+ PACKET Packet;
u_char *dp = NULL;
int packet_len = 0, caplen = 0;
struct pcap_pkthdr pcap_header;
@@ -317,25 +622,37 @@ pcap_read_win32_dag(pcap_t *p, int cnt, pcap_handler callback, u_char *user)
cc = p->cc;
if (cc == 0) /* Get new packets only if we have processed all the ones of the previous read */
{
- /* Get new packets from the network */
- if(PacketReceivePacket(p->adapter, p->Packet, TRUE)==FALSE){
- snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "read error: PacketReceivePacket failed");
+ /*
+ * Get new packets from the network.
+ *
+ * The PACKET structure had a bunch of extra stuff for
+ * Windows 9x/Me, but the only interesting data in it
+ * in the versions of Windows that we support is just
+ * a copy of p->buffer, a copy of p->buflen, and the
+ * actual number of bytes read returned from
+ * PacketReceivePacket(), none of which has to be
+ * retained from call to call, so we just keep one on
+ * the stack.
+ */
+ PacketInitPacket(&Packet, (BYTE *)p->buffer, p->bufsize);
+ if (!PacketReceivePacket(p->adapter, &Packet, TRUE)) {
+ pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "read error: PacketReceivePacket failed");
return (-1);
}
- cc = p->Packet->ulBytesReceived;
+ cc = Packet.ulBytesReceived;
if(cc == 0)
/* The timeout has expired but we no packets arrived */
- return 0;
+ return (0);
header = (dag_record_t*)p->adapter->DagBuffer;
- }
+ }
else
header = (dag_record_t*)p->bp;
-
+
endofbuf = (char*)header + cc;
-
- /*
- * Cycle through the packets
+
+ /*
+ * Cycle through the packets
*/
do
{
@@ -344,13 +661,13 @@ pcap_read_win32_dag(pcap_t *p, int cnt, pcap_handler callback, u_char *user)
break;
/* Increase the number of captured packets */
- pw->stat.ps_recv++;
-
+ p->stat.ps_recv++;
+
/* Find the beginning of the packet */
dp = ((u_char *)header) + dag_record_size;
/* Determine actual packet len */
- switch(header->type)
+ switch(header->type)
{
case TYPE_ATM:
packet_len = ATM_SNAPLEN;
@@ -368,9 +685,9 @@ pcap_read_win32_dag(pcap_t *p, int cnt, pcap_handler callback, u_char *user)
caplen = packet_len;
}
dp += 2;
-
+
break;
-
+
case TYPE_HDLC_POS:
swt = SWAPS(header->wlen);
packet_len = swt - (pw->dag_fcs_bits);
@@ -379,10 +696,10 @@ pcap_read_win32_dag(pcap_t *p, int cnt, pcap_handler callback, u_char *user)
{
caplen = packet_len;
}
-
+
break;
}
-
+
if(caplen > p->snapshot)
caplen = p->snapshot;
@@ -395,14 +712,14 @@ pcap_read_win32_dag(pcap_t *p, int cnt, pcap_handler callback, u_char *user)
* out of the loop without having read any packets, and
* return the number of packets we've processed so far.
*/
- if (p->break_loop)
+ if (p->break_loop)
{
- if (n == 0)
+ if (n == 0)
{
p->break_loop = 0;
return (-2);
- }
- else
+ }
+ else
{
p->bp = (char*)header;
p->cc = endofbuf - (char*)header;
@@ -423,30 +740,30 @@ pcap_read_win32_dag(pcap_t *p, int cnt, pcap_handler callback, u_char *user)
pcap_header.ts.tv_sec++;
}
}
-
+
/* No underlaying filtering system. We need to filter on our own */
- if (p->fcode.bf_insns)
+ if (p->fcode.bf_insns)
{
- if (bpf_filter(p->fcode.bf_insns, dp, packet_len, caplen) == 0)
+ if (bpf_filter(p->fcode.bf_insns, dp, packet_len, caplen) == 0)
{
/* Move to next packet */
header = (dag_record_t*)((char*)header + erf_record_len);
continue;
}
}
-
+
/* Fill the header for the user suppplied callback function */
pcap_header.caplen = caplen;
pcap_header.len = packet_len;
-
+
/* Call the callback function */
(*callback)(user, &pcap_header, dp);
-
+
/* Move to next packet */
header = (dag_record_t*)((char*)header + erf_record_len);
/* Stop if the number of packets requested by user has been reached*/
- if (++n >= cnt && !PACKET_COUNT_IS_UNLIMITED(cnt))
+ if (++n >= cnt && !PACKET_COUNT_IS_UNLIMITED(cnt))
{
p->bp = (char*)header;
p->cc = endofbuf - (char*)header;
@@ -454,29 +771,29 @@ pcap_read_win32_dag(pcap_t *p, int cnt, pcap_handler callback, u_char *user)
}
}
while((u_char*)header < endofbuf);
-
- return 1;
+
+ return (1);
}
#endif /* HAVE_DAG_API */
/* Send a packet to the network */
-static int
+static int
pcap_inject_win32(pcap_t *p, const void *buf, size_t size){
LPPACKET PacketToSend;
PacketToSend=PacketAllocatePacket();
-
+
if (PacketToSend == NULL)
{
- snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "send error: PacketAllocatePacket failed");
- return -1;
+ pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "send error: PacketAllocatePacket failed");
+ return (-1);
}
-
- PacketInitPacket(PacketToSend,(PVOID)buf,size);
+
+ PacketInitPacket(PacketToSend, (PVOID)buf, (UINT)size);
if(PacketSendPacket(p->adapter,PacketToSend,TRUE) == FALSE){
- snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "send error: PacketSendPacket failed");
+ pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "send error: PacketSendPacket failed");
PacketFreePacket(PacketToSend);
- return -1;
+ return (-1);
}
PacketFreePacket(PacketToSend);
@@ -486,19 +803,20 @@ pcap_inject_win32(pcap_t *p, const void *buf, size_t size){
* "pcap_inject()" is expected to return the number of bytes
* sent.
*/
- return size;
+ return ((int)size);
}
static void
pcap_cleanup_win32(pcap_t *p)
{
+ struct pcap_win *pw = p->priv;
if (p->adapter != NULL) {
PacketCloseAdapter(p->adapter);
p->adapter = NULL;
}
- if (p->Packet) {
- PacketFreePacket(p->Packet);
- p->Packet = NULL;
+ if (pw->rfmon_selfstart)
+ {
+ PacketSetMonitorMode(p->opt.device, 0);
}
pcap_cleanup_live_common(p);
}
@@ -508,42 +826,133 @@ pcap_activate_win32(pcap_t *p)
{
struct pcap_win *pw = p->priv;
NetType type;
+ int res;
+ char errbuf[PCAP_ERRBUF_SIZE+1];
+
+#ifdef HAVE_REMOTE
+ char host[PCAP_BUF_SIZE + 1];
+ char port[PCAP_BUF_SIZE + 1];
+ char name[PCAP_BUF_SIZE + 1];
+ int srctype;
+ int opensource_remote_result;
+
+ struct pcap_md *md; /* structure used when doing a remote live capture */
+ md = (struct pcap_md *) ((u_char*)p->priv + sizeof(struct pcap_win));
+
+ /*
+ Retrofit; we have to make older applications compatible with the remote capture
+ So, we're calling the pcap_open_remote() from here, that is a very dirty thing.
+ Obviously, we cannot exploit all the new features; for instance, we cannot
+ send authentication, we cannot use a UDP data connection, and so on.
+ */
+ if (pcap_parsesrcstr(p->opt.device, &srctype, host, port, name, p->errbuf))
+ return PCAP_ERROR;
+
+ if (srctype == PCAP_SRC_IFREMOTE)
+ {
+ opensource_remote_result = pcap_opensource_remote(p, NULL);
+
+ if (opensource_remote_result != 0)
+ return opensource_remote_result;
+
+ md->rmt_flags = (p->opt.promisc) ? PCAP_OPENFLAG_PROMISCUOUS : 0;
+
+ return 0;
+ }
+
+ if (srctype == PCAP_SRC_IFLOCAL)
+ {
+ /*
+ * If it starts with rpcap://, cut down the string
+ */
+ if (strncmp(p->opt.device, PCAP_SRC_IF_STRING, strlen(PCAP_SRC_IF_STRING)) == 0)
+ {
+ size_t len = strlen(p->opt.device) - strlen(PCAP_SRC_IF_STRING) + 1;
+ char *new_string;
+ /*
+ * allocate a new string and free the old one
+ */
+ if (len > 0)
+ {
+ new_string = (char*)malloc(len);
+ if (new_string != NULL)
+ {
+ char *tmp;
+ strcpy_s(new_string, len, p->opt.device + strlen(PCAP_SRC_IF_STRING));
+ tmp = p->opt.device;
+ p->opt.device = new_string;
+ free(tmp);
+ }
+ }
+ }
+ }
+
+#endif /* HAVE_REMOTE */
if (p->opt.rfmon) {
/*
- * No monitor mode on Windows. It could be done on
- * Vista with drivers that support the native 802.11
- * mechanism and monitor mode.
+ * Monitor mode is supported on Windows Vista and later.
*/
- return (PCAP_ERROR_RFMON_NOTSUP);
+ if (PacketGetMonitorMode(p->opt.device) == 1)
+ {
+ pw->rfmon_selfstart = 0;
+ }
+ else
+ {
+ if ((res = PacketSetMonitorMode(p->opt.device, 1)) != 1)
+ {
+ pw->rfmon_selfstart = 0;
+ // Monitor mode is not supported.
+ if (res == 0)
+ {
+ return PCAP_ERROR_RFMON_NOTSUP;
+ }
+ else
+ {
+ return PCAP_ERROR;
+ }
+ }
+ else
+ {
+ pw->rfmon_selfstart = 1;
+ }
+ }
}
/* Init WinSock */
wsockinit();
- p->adapter = PacketOpenAdapter(p->opt.source);
-
+ p->adapter = PacketOpenAdapter(p->opt.device);
+
if (p->adapter == NULL)
{
/* Adapter detected but we are not able to open it. Return failure. */
- snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "Error opening adapter: %s", pcap_win32strerror());
- return PCAP_ERROR;
+ pcap_win32_err_to_str(GetLastError(), errbuf);
+ if (pw->rfmon_selfstart)
+ {
+ PacketSetMonitorMode(p->opt.device, 0);
+ }
+ pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
+ "Error opening adapter: %s", errbuf);
+ return (PCAP_ERROR);
}
-
+
/*get network type*/
if(PacketGetNetType (p->adapter,&type) == FALSE)
{
- snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "Cannot determine the network type: %s", pcap_win32strerror());
+ pcap_win32_err_to_str(GetLastError(), errbuf);
+ pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
+ "Cannot determine the network type: %s", errbuf);
goto bad;
}
-
+
/*Set the linktype*/
- switch (type.LinkType)
+ switch (type.LinkType)
{
case NdisMediumWan:
p->linktype = DLT_EN10MB;
break;
-
+
case NdisMedium802_3:
p->linktype = DLT_EN10MB;
/*
@@ -566,27 +975,27 @@ pcap_activate_win32(pcap_t *p)
p->dlt_count = 2;
}
break;
-
+
case NdisMediumFddi:
p->linktype = DLT_FDDI;
break;
-
- case NdisMedium802_5:
- p->linktype = DLT_IEEE802;
+
+ case NdisMedium802_5:
+ p->linktype = DLT_IEEE802;
break;
-
+
case NdisMediumArcnetRaw:
p->linktype = DLT_ARCNET;
break;
-
+
case NdisMediumArcnet878_2:
p->linktype = DLT_ARCNET;
break;
-
+
case NdisMediumAtm:
p->linktype = DLT_ATM_RFC1483;
break;
-
+
case NdisMediumCHDLC:
p->linktype = DLT_CHDLC;
break;
@@ -617,20 +1026,20 @@ pcap_activate_win32(pcap_t *p)
}
/* Set promiscuous mode */
- if (p->opt.promisc)
+ if (p->opt.promisc)
{
if (PacketSetHwFilter(p->adapter,NDIS_PACKET_TYPE_PROMISCUOUS) == FALSE)
{
- snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "failed to set hardware filter to promiscuous mode");
+ pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "failed to set hardware filter to promiscuous mode");
goto bad;
}
}
- else
+ else
{
if (PacketSetHwFilter(p->adapter,NDIS_PACKET_TYPE_ALL_LOCAL) == FALSE)
{
- snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "failed to set hardware filter to non-promiscuous mode");
+ pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "failed to set hardware filter to non-promiscuous mode");
goto bad;
}
}
@@ -638,46 +1047,40 @@ pcap_activate_win32(pcap_t *p)
/* Set the buffer size */
p->bufsize = WIN32_DEFAULT_USER_BUFFER_SIZE;
- /* allocate Packet structure used during the capture */
- if((p->Packet = PacketAllocatePacket())==NULL)
- {
- snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "failed to allocate the PACKET structure");
- goto bad;
- }
-
if(!(p->adapter->Flags & INFO_FLAG_DAG_CARD))
{
- /*
- * Traditional Adapter
+ /*
+ * Traditional Adapter
*/
/*
* If the buffer size wasn't explicitly set, default to
- * WIN32_DEFAULT_USER_BUFFER_SIZE.
+ * WIN32_DEFAULT_KERNEL_BUFFER_SIZE.
*/
if (p->opt.buffer_size == 0)
p->opt.buffer_size = WIN32_DEFAULT_KERNEL_BUFFER_SIZE;
if(PacketSetBuff(p->adapter,p->opt.buffer_size)==FALSE)
{
- snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "driver error: not enough memory to allocate the kernel buffer");
+ pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "driver error: not enough memory to allocate the kernel buffer");
goto bad;
}
-
- p->buffer = (u_char *)malloc(p->bufsize);
- if (p->buffer == NULL)
+
+ p->buffer = malloc(p->bufsize);
+ if (p->buffer == NULL)
{
- snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "malloc: %s", pcap_strerror(errno));
+ pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "malloc: %s", pcap_strerror(errno));
goto bad;
}
-
- PacketInitPacket(p->Packet,(BYTE*)p->buffer,p->bufsize);
-
+
if (p->opt.immediate)
{
/* 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());
+ pcap_win32_err_to_str(GetLastError(), errbuf);
+ pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
+ "Error calling PacketSetMinToCopy: %s",
+ errbuf);
goto bad;
}
}
@@ -686,7 +1089,10 @@ pcap_activate_win32(pcap_t *p)
/* 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());
+ pcap_win32_err_to_str(GetLastError(), errbuf);
+ pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
+ "Error calling PacketSetMinToCopy: %s",
+ errbuf);
goto bad;
}
}
@@ -694,8 +1100,8 @@ pcap_activate_win32(pcap_t *p)
else
#ifdef HAVE_DAG_API
{
- /*
- * Dag Card
+ /*
+ * Dag Card
*/
LONG status;
HKEY dagkey;
@@ -703,45 +1109,45 @@ pcap_activate_win32(pcap_t *p)
DWORD lpcbdata;
int postype = 0;
char keyname[512];
-
- snprintf(keyname, sizeof(keyname), "%s\\CardParams\\%s",
+
+ pcap_snprintf(keyname, sizeof(keyname), "%s\\CardParams\\%s",
"SYSTEM\\CurrentControlSet\\Services\\DAG",
- strstr(_strlwr(p->opt.source), "dag"));
+ strstr(_strlwr(p->opt.device), "dag"));
do
{
status = RegOpenKeyEx(HKEY_LOCAL_MACHINE, keyname, 0, KEY_READ, &dagkey);
if(status != ERROR_SUCCESS)
break;
-
+
status = RegQueryValueEx(dagkey,
"PosType",
NULL,
&lptype,
(char*)&postype,
&lpcbdata);
-
+
if(status != ERROR_SUCCESS)
{
postype = 0;
}
-
+
RegCloseKey(dagkey);
}
while(FALSE);
-
-
+
+
p->snapshot = PacketSetSnapLen(p->adapter, snaplen);
-
- /* Set the length of the FCS associated to any packet. This value
+
+ /* Set the length of the FCS associated to any packet. This value
* will be subtracted to the packet length */
pw->dag_fcs_bits = p->adapter->DagFcsLen;
}
#else
goto bad;
#endif /* HAVE_DAG_API */
-
+
PacketSetReadTimeout(p->adapter, p->opt.timeout);
-
+
#ifdef HAVE_DAG_API
if(p->adapter->Flags & INFO_FLAG_DAG_CARD)
{
@@ -765,10 +1171,18 @@ pcap_activate_win32(pcap_t *p)
p->getnonblock_op = pcap_getnonblock_win32;
p->setnonblock_op = pcap_setnonblock_win32;
p->stats_op = pcap_stats_win32;
+ p->stats_ex_op = pcap_stats_ex_win32;
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->getevent_op = pcap_getevent_win32;
+ p->oid_get_request_op = pcap_oid_get_request_win32;
+ p->oid_set_request_op = pcap_oid_set_request_win32;
+ p->sendqueue_transmit_op = pcap_sendqueue_transmit_win32;
+ p->setuserbuffer_op = pcap_setuserbuffer_win32;
+ p->live_dump_op = pcap_live_dump_win32;
+ p->live_dump_ended_op = pcap_live_dump_ended_win32;
+ p->get_airpcap_handle_op = pcap_get_airpcap_handle_win32;
p->cleanup_op = pcap_cleanup_win32;
return (0);
@@ -777,47 +1191,30 @@ bad:
return (PCAP_ERROR);
}
+/*
+* Check if rfmon mode is supported on the pcap_t for Windows systems.
+*/
+static int
+pcap_can_set_rfmon_win32(pcap_t *p)
+{
+ return (PacketIsMonitorModeSupported(p->opt.device) == 1);
+}
+
pcap_t *
-pcap_create_interface(const char *device, char *ebuf)
+pcap_create_interface(const char *device _U_, char *ebuf)
{
pcap_t *p;
- if (strlen(device) == 1)
- {
- /*
- * It's probably a unicode string
- * Convert to ascii and pass it to pcap_create_common
- *
- * This wonderful hack is needed because pcap_lookupdev still returns
- * unicode strings, and it's used by windump when no device is specified
- * in the command line
- */
- size_t length;
- char* deviceAscii;
-
- length = wcslen((wchar_t*)device);
-
- deviceAscii = (char*)malloc(length + 1);
-
- if (deviceAscii == NULL)
- {
- snprintf(ebuf, PCAP_ERRBUF_SIZE, "Malloc failed");
- return NULL;
- }
-
- snprintf(deviceAscii, length + 1, "%ws", (wchar_t*)device);
- p = pcap_create_common(deviceAscii, ebuf, sizeof (struct pcap_win));
- free(deviceAscii);
- }
- else
- {
- p = pcap_create_common(device, ebuf, sizeof (struct pcap_win));
- }
-
+#ifdef HAVE_REMOTE
+ p = pcap_create_common(ebuf, sizeof(struct pcap_win) + sizeof(struct pcap_md));
+#else
+ p = pcap_create_common(ebuf, sizeof(struct pcap_win));
+#endif /* HAVE_REMOTE */
if (p == NULL)
return (NULL);
p->activate_op = pcap_activate_win32;
+ p->can_set_rfmon_op = pcap_can_set_rfmon_win32;
return (p);
}
@@ -882,23 +1279,23 @@ pcap_setfilter_win32_npf(pcap_t *p, struct bpf_program *fp)
/*
* We filter at user level, since the kernel driver does't process the packets
*/
-static int
+static int
pcap_setfilter_win32_dag(pcap_t *p, struct bpf_program *fp) {
-
- if(!fp)
+
+ if(!fp)
{
- strncpy(p->errbuf, "setfilter: No filter specified", sizeof(p->errbuf));
- return -1;
+ strlcpy(p->errbuf, "setfilter: No filter specified", sizeof(p->errbuf));
+ return (-1);
}
-
+
/* Install a user level filter */
- if (install_bpf_program(p, fp) < 0)
+ if (install_bpf_program(p, fp) < 0)
{
- snprintf(p->errbuf, sizeof(p->errbuf),
+ pcap_snprintf(p->errbuf, sizeof(p->errbuf),
"setfilter, unable to install the filter: %s", pcap_strerror(errno));
- return -1;
+ return (-1);
}
-
+
return (0);
}
@@ -920,6 +1317,7 @@ pcap_setnonblock_win32(pcap_t *p, int nonblock, char *errbuf)
{
struct pcap_win *pw = p->priv;
int newtimeout;
+ char win_errbuf[PCAP_ERRBUF_SIZE+1];
if (nonblock) {
/*
@@ -930,22 +1328,221 @@ pcap_setnonblock_win32(pcap_t *p, int nonblock, char *errbuf)
/*
* Restore the timeout set when the device was opened.
* (Note that this may be -1, in which case we're not
- * really leaving non-blocking mode.)
+ * really leaving non-blocking mode. However, although
+ * the timeout argument to pcap_set_timeout() and
+ * pcap_open_live() is an int, you're not supposed to
+ * supply a negative value, so that "shouldn't happen".)
*/
newtimeout = p->opt.timeout;
}
if (!PacketSetReadTimeout(p->adapter, newtimeout)) {
- snprintf(errbuf, PCAP_ERRBUF_SIZE,
- "PacketSetReadTimeout: %s", pcap_win32strerror());
+ pcap_win32_err_to_str(GetLastError(), win_errbuf);
+ pcap_snprintf(errbuf, PCAP_ERRBUF_SIZE,
+ "PacketSetReadTimeout: %s", win_errbuf);
return (-1);
}
pw->nonblock = (newtimeout == -1);
return (0);
}
-/*platform-dependent routine to add devices other than NDIS interfaces*/
+static int
+pcap_add_if_win32(pcap_if_t **devlist, char *name, bpf_u_int32 flags,
+ const char *description, char *errbuf)
+{
+ pcap_if_t *curdev;
+ npf_if_addr if_addrs[MAX_NETWORK_ADDRESSES];
+ LONG if_addr_size;
+ int res = 0;
+
+ if_addr_size = MAX_NETWORK_ADDRESSES;
+
+ /*
+ * Add an entry for this interface, with no addresses.
+ */
+ if (add_or_find_if(&curdev, devlist, name, flags, description,
+ errbuf) == -1) {
+ /*
+ * Failure.
+ */
+ return (-1);
+ }
+
+ /*
+ * Get the list of addresses for the interface.
+ */
+ if (!PacketGetNetInfoEx((void *)name, if_addrs, &if_addr_size)) {
+ /*
+ * Failure.
+ *
+ * We don't return an error, because this can happen with
+ * NdisWan interfaces, and we want to supply them even
+ * if we can't supply their addresses.
+ *
+ * We return an entry with an empty address list.
+ */
+ return (0);
+ }
+
+ /*
+ * Now add the addresses.
+ */
+ while (if_addr_size-- > 0) {
+ /*
+ * "curdev" is an entry for this interface; add an entry for
+ * this address to its list of addresses.
+ */
+ if(curdev == NULL)
+ break;
+ res = add_addr_to_dev(curdev,
+ (struct sockaddr *)&if_addrs[if_addr_size].IPAddress,
+ sizeof (struct sockaddr_storage),
+ (struct sockaddr *)&if_addrs[if_addr_size].SubnetMask,
+ sizeof (struct sockaddr_storage),
+ (struct sockaddr *)&if_addrs[if_addr_size].Broadcast,
+ sizeof (struct sockaddr_storage),
+ NULL,
+ 0,
+ errbuf);
+ if (res == -1) {
+ /*
+ * Failure.
+ */
+ break;
+ }
+ }
+
+ return (res);
+}
+
int
pcap_platform_finddevs(pcap_if_t **alldevsp, char *errbuf)
{
- return (0);
+ pcap_if_t *devlist = NULL;
+ int ret = 0;
+ const char *desc;
+ char *AdaptersName;
+ ULONG NameLength;
+ char *name;
+ char our_errbuf[PCAP_ERRBUF_SIZE+1];
+
+ /*
+ * 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();
+
+ if (last_error != ERROR_INSUFFICIENT_BUFFER)
+ {
+ pcap_win32_err_to_str(last_error, our_errbuf);
+ pcap_snprintf(errbuf, PCAP_ERRBUF_SIZE,
+ "PacketGetAdapterNames: %s", our_errbuf);
+ return (-1);
+ }
+ }
+
+ if (NameLength > 0)
+ AdaptersName = (char*) malloc(NameLength);
+ else
+ {
+ *alldevsp = NULL;
+ return 0;
+ }
+ if (AdaptersName == NULL)
+ {
+ pcap_snprintf(errbuf, PCAP_ERRBUF_SIZE, "Cannot allocate enough memory to list the adapters.");
+ return (-1);
+ }
+
+ if (!PacketGetAdapterNames(AdaptersName, &NameLength)) {
+ pcap_win32_err_to_str(GetLastError(), our_errbuf);
+ pcap_snprintf(errbuf, PCAP_ERRBUF_SIZE, "PacketGetAdapterNames: %s",
+ our_errbuf);
+ free(AdaptersName);
+ return (-1);
+ }
+
+ /*
+ * "PacketGetAdapterNames()" returned a list of
+ * null-terminated ASCII interface name strings,
+ * terminated by a null string, followed by a list
+ * of null-terminated ASCII interface description
+ * strings, terminated by a null string.
+ * This means there are two ASCII nulls at the end
+ * of the first list.
+ *
+ * Find the end of the first list; that's the
+ * beginning of the second list.
+ */
+ desc = &AdaptersName[0];
+ while (*desc != '\0' || *(desc + 1) != '\0')
+ desc++;
+
+ /*
+ * Found it - "desc" points to the first of the two
+ * nulls at the end of the list of names, so the
+ * first byte of the list of descriptions is two bytes
+ * after it.
+ */
+ desc += 2;
+
+ /*
+ * Loop over the elements in the first list.
+ */
+ name = &AdaptersName[0];
+ while (*name != '\0') {
+ bpf_u_int32 flags = 0;
+#ifdef HAVE_PACKET_IS_LOOPBACK_ADAPTER
+ /*
+ * Is this a loopback interface?
+ */
+ if (PacketIsLoopbackAdapter(name)) {
+ /* Yes */
+ flags |= PCAP_IF_LOOPBACK;
+ }
+#endif
+
+ /*
+ * Add an entry for this interface.
+ */
+ if (pcap_add_if_win32(&devlist, name, flags, desc,
+ errbuf) == -1) {
+ /*
+ * Failure.
+ */
+ ret = -1;
+ break;
+ }
+ name += strlen(name) + 1;
+ desc += strlen(desc) + 1;
+ }
+
+ if (ret == -1) {
+ /*
+ * We had an error; free the list we've been constructing.
+ */
+ if (devlist != NULL) {
+ pcap_freealldevs(devlist);
+ devlist = NULL;
+ }
+ }
+
+ *alldevsp = devlist;
+ free(AdaptersName);
+ return (ret);
}
diff --git a/contrib/libpcap/pcap.3pcap.in b/contrib/libpcap/pcap.3pcap.in
index f5a7e0ca217a..93478f1cd30f 100644
--- a/contrib/libpcap/pcap.3pcap.in
+++ b/contrib/libpcap/pcap.3pcap.in
@@ -17,7 +17,7 @@
.\" WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
.\" MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
.\"
-.TH PCAP 3PCAP "16 April 2014"
+.TH PCAP 3PCAP "8 March 2015"
.SH NAME
pcap \- Packet Capture library
.SH SYNOPSIS
@@ -354,12 +354,25 @@ open a
.B pcap_t
for a ``savefile'', given a pathname
.TP
+.BR pcap_open_offline_with_tstamp_precision (3PCAP)
+open a
+.B pcap_t
+for a ``savefile'', given a pathname, and specify the precision to
+provide for packet time stamps
+.TP
.BR pcap_fopen_offline (3PCAP)
open a
.B pcap_t
for a ``savefile'', given a
.B "FILE\ *"
.TP
+.BR pcap_fopen_offline_with_tstamp_precision (3PCAP)
+open a
+.B pcap_t
+for a ``savefile'', given a
+.BR "FILE\ *" ,
+and specify the precision to provide for packet time stamps
+.TP
.BR pcap_open_dead (3PCAP)
create a ``fake''
.B pcap_t
@@ -424,6 +437,16 @@ get description for a time stamp type
.BR pcap_tstamp_type_name_to_val (3PCAP)
get time stamp type corresponding to a name
.TP
+.BR pcap_set_tstamp_precision (3PCAP)
+set time stamp precision for a not-yet-activated
+.B pcap_t
+for live capture
+.TP
+.BR pcap_get_tstamp_precision (3PCAP)
+get the time stamp precision of a
+.B pcap_t
+for live capture
+.TP
.BR pcap_datalink (3PCAP)
get link-layer header type for a
.B pcap_t
@@ -552,7 +575,7 @@ bytes of the packet on success, and NULL on error.
.BR pcap_next_ex ()
is passed two pointer arguments, one of which points to a
.IR struct pcap_pkthdr *
-and one of which points to a
+and one of which points to a
.IR "const u_char" *.
It sets the first pointer to point to a
.I struct pcap_pkthdr
@@ -580,7 +603,9 @@ for packets to become available. On some, but
all, platforms, if a read timeout was specified, the wait will terminate
after the read timeout expires; applications should be prepared for
this, as it happens on some platforms, but should not rely on it, as it
-does not happen on other platforms.
+does not happen on other platforms. Note that the wait might, or might
+not, terminate even if no packets are available; applications should be
+prepared for this to happen, but must not rely on it happening.
.PP
A handle can be put into ``non-blocking mode'', so that those routines
will, rather than blocking, return an indication that no packets are
@@ -596,8 +621,8 @@ Non-blocking mode is often combined with routines such as
.BR select (2)
or
.BR poll (2)
-or other routines a platform offers to wait for the availability of data
-on any of a set of descriptors. To obtain, for a handle, a descriptor
+or other routines a platform offers to wait for any of a set of
+descriptors to be ready to read. To obtain, for a handle, a descriptor
that can be used in those routines, call
.BR pcap_get_selectable_fd ().
Not all handles have such a descriptor available;
@@ -606,7 +631,14 @@ will return \-1 if no such descriptor exists. In addition, for various
reasons, one or more of those routines will not work properly with the
descriptor; the documentation for
.BR pcap_get_selectable_fd ()
-gives details.
+gives details. Note that, just as an attempt to read packets from a
+.B pcap_t
+may not return any packets if the read timeout expires, a
+.BR select (),
+.BR poll (),
+or other such call may, if the read timeout expires, indicate that a
+descriptor is ready to read even if there are no packets available to
+read.
.TP
.B Routines
.RS
diff --git a/contrib/libpcap/pcap.c b/contrib/libpcap/pcap.c
index 517b8ba4a6ad..1590346cf8f6 100644
--- a/contrib/libpcap/pcap.c
+++ b/contrib/libpcap/pcap.c
@@ -35,9 +35,9 @@
#include "config.h"
#endif
-#ifdef WIN32
+#ifdef _WIN32
#include <pcap-stdinc.h>
-#else /* WIN32 */
+#else /* _WIN32 */
#if HAVE_INTTYPES_H
#include <inttypes.h>
#elif HAVE_STDINT_H
@@ -48,7 +48,7 @@
#endif
#include <sys/types.h>
#include <sys/mman.h>
-#endif /* WIN32 */
+#endif /* _WIN32 */
#include <stdio.h>
#include <stdlib.h>
@@ -81,6 +81,10 @@
#include "pcap-snf.h"
#endif /* HAVE_SNF_API */
+#ifdef HAVE_TC_API
+#include "pcap-tc.h"
+#endif /* HAVE_TC_API */
+
#ifdef PCAP_SUPPORT_USB
#include "pcap-usb-linux.h"
#endif
@@ -93,14 +97,6 @@
#include "pcap-bt-monitor-linux.h"
#endif
-#ifdef PCAP_SUPPORT_CAN
-#include "pcap-can-linux.h"
-#endif
-
-#ifdef PCAP_SUPPORT_CANUSB
-#include "pcap-canusb-linux.h"
-#endif
-
#ifdef PCAP_SUPPORT_NETFILTER
#include "pcap-netfilter-linux.h"
#endif
@@ -113,17 +109,46 @@ pcap_t* pcap_netmap_create(const char *device, char *ebuf, int *is_ours);
#include "pcap-dbus.h"
#endif
-int
-pcap_not_initialized(pcap_t *pcap _U_)
+static int
+pcap_not_initialized(pcap_t *pcap)
{
+ /* in case the caller doesn't check for PCAP_ERROR_NOT_ACTIVATED */
+ (void)pcap_snprintf(pcap->errbuf, sizeof(pcap->errbuf),
+ "This handle hasn't been activated yet");
/* this means 'not initialized' */
return (PCAP_ERROR_NOT_ACTIVATED);
}
-#ifdef WIN32
-Adapter *
-pcap_no_adapter(pcap_t *pcap _U_)
+#ifdef _WIN32
+static void *
+pcap_not_initialized_ptr(pcap_t *pcap)
+{
+ (void)pcap_snprintf(pcap->errbuf, sizeof(pcap->errbuf),
+ "This handle hasn't been activated yet");
+ return (NULL);
+}
+
+static HANDLE
+pcap_getevent_not_initialized(pcap_t *pcap)
+{
+ (void)pcap_snprintf(pcap->errbuf, sizeof(pcap->errbuf),
+ "This handle hasn't been activated yet");
+ return (INVALID_HANDLE_VALUE);
+}
+
+static u_int
+pcap_sendqueue_transmit_not_initialized(pcap_t *pcap, pcap_send_queue* queue, int sync)
+{
+ (void)pcap_snprintf(pcap->errbuf, sizeof(pcap->errbuf),
+ "This handle hasn't been activated yet");
+ return (0);
+}
+
+static PAirpcapHandle
+pcap_get_airpcap_handle_not_initialized(pcap_t *pcap)
{
+ (void)pcap_snprintf(pcap->errbuf, sizeof(pcap->errbuf),
+ "This handle hasn't been activated yet");
return (NULL);
}
#endif
@@ -170,7 +195,7 @@ pcap_list_tstamp_types(pcap_t *p, int **tstamp_typesp)
*tstamp_typesp = (int*)calloc(sizeof(**tstamp_typesp),
p->tstamp_type_count);
if (*tstamp_typesp == NULL) {
- (void)snprintf(p->errbuf, sizeof(p->errbuf),
+ (void)pcap_snprintf(p->errbuf, sizeof(p->errbuf),
"malloc: %s", pcap_strerror(errno));
return (PCAP_ERROR);
}
@@ -275,44 +300,7 @@ pcap_next_ex(pcap_t *p, struct pcap_pkthdr **pkt_header,
return (p->read_op(p, 1, p->oneshot_callback, (u_char *)&s));
}
-#if defined(DAG_ONLY)
-int
-pcap_findalldevs(pcap_if_t **alldevsp, char *errbuf)
-{
- return (dag_findalldevs(alldevsp, errbuf));
-}
-
-pcap_t *
-pcap_create(const char *source, char *errbuf)
-{
- return (dag_create(source, errbuf));
-}
-#elif defined(SEPTEL_ONLY)
-int
-pcap_findalldevs(pcap_if_t **alldevsp, char *errbuf)
-{
- return (septel_findalldevs(alldevsp, errbuf));
-}
-
-pcap_t *
-pcap_create(const char *source, char *errbuf)
-{
- return (septel_create(source, errbuf));
-}
-#elif defined(SNF_ONLY)
-int
-pcap_findalldevs(pcap_if_t **alldevsp, char *errbuf)
-{
- return (snf_findalldevs(alldevsp, errbuf));
-}
-
-pcap_t *
-pcap_create(const char *source, char *errbuf)
-{
- return (snf_create(source, errbuf));
-}
-#else /* regular pcap */
-struct capture_source_type {
+static struct capture_source_type {
int (*findalldevs_op)(pcap_if_t **, char *);
pcap_t *(*create_op)(const char *, char *, int *);
} capture_source_types[] = {
@@ -328,18 +316,15 @@ struct capture_source_type {
#ifdef HAVE_SNF_API
{ snf_findalldevs, snf_create },
#endif
+#ifdef HAVE_TC_API
+ { TcFindAllDevs, TcCreate },
+#endif
#ifdef PCAP_SUPPORT_BT
{ bt_findalldevs, bt_create },
#endif
#ifdef PCAP_SUPPORT_BT_MONITOR
{ bt_monitor_findalldevs, bt_monitor_create },
#endif
-#if PCAP_SUPPORT_CANUSB
- { canusb_findalldevs, canusb_create },
-#endif
-#ifdef PCAP_SUPPORT_CAN
- { can_findalldevs, can_create },
-#endif
#ifdef PCAP_SUPPORT_USB
{ usb_findalldevs, usb_create },
#endif
@@ -364,26 +349,11 @@ pcap_findalldevs(pcap_if_t **alldevsp, char *errbuf)
size_t i;
/*
- * Get the list of regular interfaces first.
- */
- if (pcap_findalldevs_interfaces(alldevsp, errbuf) == -1)
- return (-1); /* failure */
-
- /*
- * Add any interfaces that need a platform-specific mechanism
- * to find.
+ * Find all the local network interfaces on which we
+ * can capture.
*/
- if (pcap_platform_finddevs(alldevsp, errbuf) == -1) {
- /*
- * We had an error; free the list we've been
- * constructing.
- */
- if (*alldevsp != NULL) {
- pcap_freealldevs(*alldevsp);
- *alldevsp = NULL;
- }
+ if (pcap_platform_finddevs(alldevsp, errbuf) == -1)
return (-1);
- }
/*
* Ask each of the non-local-network-interface capture
@@ -407,21 +377,53 @@ pcap_findalldevs(pcap_if_t **alldevsp, char *errbuf)
}
pcap_t *
-pcap_create(const char *source, char *errbuf)
+pcap_create(const char *device, char *errbuf)
{
size_t i;
int is_theirs;
pcap_t *p;
+ char *device_str;
/*
- * A null source name is equivalent to the "any" device -
+ * A null device name is equivalent to the "any" device -
* which might not be supported on this platform, but
* this means that you'll get a "not supported" error
* rather than, say, a crash when we try to dereference
* the null pointer.
*/
- if (source == NULL)
- source = "any";
+ if (device == NULL)
+ device_str = strdup("any");
+ else {
+#ifdef _WIN32
+ /*
+ * If the string appears to be little-endian UCS-2/UTF-16,
+ * convert it to ASCII.
+ *
+ * XXX - to UTF-8 instead? Or report an error if any
+ * character isn't ASCII?
+ */
+ if (device[0] != '\0' && device[1] == '\0') {
+ size_t length;
+
+ length = wcslen((wchar_t *)device);
+ device_str = (char *)malloc(length + 1);
+ if (device_str == NULL) {
+ pcap_snprintf(errbuf, PCAP_ERRBUF_SIZE,
+ "malloc: %s", pcap_strerror(errno));
+ return (NULL);
+ }
+
+ pcap_snprintf(device_str, length + 1, "%ws",
+ (const wchar_t *)device);
+ } else
+#endif
+ device_str = strdup(device);
+ }
+ if (device_str == NULL) {
+ pcap_snprintf(errbuf, PCAP_ERRBUF_SIZE,
+ "malloc: %s", pcap_strerror(errno));
+ return (NULL);
+ }
/*
* Try each of the non-local-network-interface capture
@@ -430,7 +432,8 @@ pcap_create(const char *source, char *errbuf)
*/
for (i = 0; capture_source_types[i].create_op != NULL; i++) {
is_theirs = 0;
- p = capture_source_types[i].create_op(source, errbuf, &is_theirs);
+ p = capture_source_types[i].create_op(device_str, errbuf,
+ &is_theirs);
if (is_theirs) {
/*
* The device name refers to a device of the
@@ -441,6 +444,14 @@ pcap_create(const char *source, char *errbuf)
* should return that to report the failure
* to create.
*/
+ if (p == NULL) {
+ /*
+ * We assume the caller filled in errbuf.
+ */
+ free(device_str);
+ return (NULL);
+ }
+ p->opt.device = device_str;
return (p);
}
}
@@ -448,9 +459,17 @@ pcap_create(const char *source, char *errbuf)
/*
* OK, try it as a regular network interface.
*/
- return (pcap_create_interface(source, errbuf));
+ p = pcap_create_interface(device_str, errbuf);
+ if (p == NULL) {
+ /*
+ * We assume the caller filled in errbuf.
+ */
+ free(device_str);
+ return (NULL);
+ }
+ p->opt.device = device_str;
+ return (p);
}
-#endif
static void
initialize_ops(pcap_t *p)
@@ -468,11 +487,19 @@ initialize_ops(pcap_t *p)
p->getnonblock_op = (getnonblock_op_t)pcap_not_initialized;
p->setnonblock_op = (setnonblock_op_t)pcap_not_initialized;
p->stats_op = (stats_op_t)pcap_not_initialized;
-#ifdef WIN32
+#ifdef _WIN32
+ p->stats_ex_op = (stats_ex_op_t)pcap_not_initialized_ptr;
p->setbuff_op = (setbuff_op_t)pcap_not_initialized;
p->setmode_op = (setmode_op_t)pcap_not_initialized;
p->setmintocopy_op = (setmintocopy_op_t)pcap_not_initialized;
- p->getadapter_op = pcap_no_adapter;
+ p->getevent_op = pcap_getevent_not_initialized;
+ p->oid_get_request_op = (oid_get_request_op_t)pcap_not_initialized;
+ p->oid_set_request_op = (oid_set_request_op_t)pcap_not_initialized;
+ p->sendqueue_transmit_op = pcap_sendqueue_transmit_not_initialized;
+ p->setuserbuffer_op = (setuserbuffer_op_t)pcap_not_initialized;
+ p->live_dump_op = (live_dump_op_t)pcap_not_initialized;
+ p->live_dump_ended_op = (live_dump_ended_op_t)pcap_not_initialized;
+ p->get_airpcap_handle_op = pcap_get_airpcap_handle_not_initialized;
#endif
/*
@@ -503,7 +530,7 @@ pcap_alloc_pcap_t(char *ebuf, size_t size)
*/
chunk = malloc(sizeof (pcap_t) + size);
if (chunk == NULL) {
- snprintf(ebuf, PCAP_ERRBUF_SIZE, "malloc: %s",
+ pcap_snprintf(ebuf, PCAP_ERRBUF_SIZE, "malloc: %s",
pcap_strerror(errno));
return (NULL);
}
@@ -514,7 +541,7 @@ pcap_alloc_pcap_t(char *ebuf, size_t size)
*/
p = (pcap_t *)chunk;
-#ifndef WIN32
+#ifndef _WIN32
p->fd = -1; /* not opened yet */
p->selectable_fd = -1;
#endif
@@ -534,7 +561,7 @@ pcap_alloc_pcap_t(char *ebuf, size_t size)
}
pcap_t *
-pcap_create_common(const char *source, char *ebuf, size_t size)
+pcap_create_common(char *ebuf, size_t size)
{
pcap_t *p;
@@ -542,14 +569,6 @@ pcap_create_common(const char *source, char *ebuf, size_t size)
if (p == NULL)
return (NULL);
- p->opt.source = strdup(source);
- if (p->opt.source == NULL) {
- snprintf(ebuf, PCAP_ERRBUF_SIZE, "malloc: %s",
- pcap_strerror(errno));
- free(p);
- return (NULL);
- }
-
/*
* Default to "can't set rfmon mode"; if it's supported by
* a platform, the create routine that called us can set
@@ -561,14 +580,20 @@ pcap_create_common(const char *source, char *ebuf, size_t size)
initialize_ops(p);
/* put in some defaults*/
- pcap_set_snaplen(p, MAXIMUM_SNAPLEN); /* max packet size */
- p->opt.timeout = 0; /* no timeout specified */
- p->opt.buffer_size = 0; /* use the platform's default */
+ p->snapshot = MAXIMUM_SNAPLEN; /* max packet size */
+ p->opt.timeout = 0; /* no timeout specified */
+ p->opt.buffer_size = 0; /* use the platform's default */
p->opt.promisc = 0;
p->opt.rfmon = 0;
p->opt.immediate = 0;
p->opt.tstamp_type = -1; /* default to not setting time stamp type */
p->opt.tstamp_precision = PCAP_TSTAMP_PRECISION_MICRO;
+
+ /*
+ * Start out with no BPF code generation flags set.
+ */
+ p->bpf_codegen_flags = 0;
+
return (p);
}
@@ -576,7 +601,7 @@ int
pcap_check_activated(pcap_t *p)
{
if (p->activated) {
- snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "can't perform "
+ pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "can't perform "
" operation on activated capture");
return (-1);
}
@@ -588,6 +613,16 @@ pcap_set_snaplen(pcap_t *p, int snaplen)
{
if (pcap_check_activated(p))
return (PCAP_ERROR_ACTIVATED);
+
+ /*
+ * Turn invalid values, or excessively large values, into
+ * the maximum allowed value.
+ *
+ * If some application really *needs* a bigger snapshot
+ * length, we should just increase MAXIMUM_SNAPLEN.
+ */
+ if (snaplen <= 0 || snaplen > MAXIMUM_SNAPLEN)
+ snaplen = MAXIMUM_SNAPLEN;
p->snapshot = snaplen;
return (0);
}
@@ -628,6 +663,13 @@ pcap_set_tstamp_type(pcap_t *p, int tstamp_type)
return (PCAP_ERROR_ACTIVATED);
/*
+ * The argument should have been u_int, but that's too late
+ * to change now - it's an API.
+ */
+ if (tstamp_type < 0)
+ return (PCAP_WARNING_TSTAMP_TYPE_NOTSUP);
+
+ /*
* If p->tstamp_type_count is 0, we only support PCAP_TSTAMP_HOST;
* the default time stamp type is PCAP_TSTAMP_HOST.
*/
@@ -641,7 +683,7 @@ pcap_set_tstamp_type(pcap_t *p, int tstamp_type)
* Check whether we claim to support this type of time stamp.
*/
for (i = 0; i < p->tstamp_type_count; i++) {
- if (p->tstamp_type_list[i] == tstamp_type) {
+ if (p->tstamp_type_list[i] == (u_int)tstamp_type) {
/*
* Yes.
*/
@@ -671,6 +713,12 @@ pcap_set_buffer_size(pcap_t *p, int buffer_size)
{
if (pcap_check_activated(p))
return (PCAP_ERROR_ACTIVATED);
+ if (buffer_size <= 0) {
+ /*
+ * Silently ignore invalid values.
+ */
+ return (0);
+ }
p->opt.buffer_size = buffer_size;
return (0);
}
@@ -684,6 +732,13 @@ pcap_set_tstamp_precision(pcap_t *p, int tstamp_precision)
return (PCAP_ERROR_ACTIVATED);
/*
+ * The argument should have been u_int, but that's too late
+ * to change now - it's an API.
+ */
+ if (tstamp_precision < 0)
+ return (PCAP_ERROR_TSTAMP_PRECISION_NOTSUP);
+
+ /*
* If p->tstamp_precision_count is 0, we only support setting
* the time stamp precision to microsecond precision; every
* pcap module *MUST* support microsecond precision, even if
@@ -701,7 +756,7 @@ pcap_set_tstamp_precision(pcap_t *p, int tstamp_precision)
* time stamp.
*/
for (i = 0; i < p->tstamp_precision_count; i++) {
- if (p->tstamp_precision_list[i] == tstamp_precision) {
+ if (p->tstamp_precision_list[i] == (u_int)tstamp_precision) {
/*
* Yes.
*/
@@ -748,7 +803,7 @@ pcap_activate(pcap_t *p)
* handle errors other than PCAP_ERROR, return the
* error message corresponding to the status.
*/
- snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "%s",
+ pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "%s",
pcap_statustostr(status));
}
@@ -762,12 +817,12 @@ pcap_activate(pcap_t *p)
}
pcap_t *
-pcap_open_live(const char *source, int snaplen, int promisc, int to_ms, char *errbuf)
+pcap_open_live(const char *device, int snaplen, int promisc, int to_ms, char *errbuf)
{
pcap_t *p;
int status;
- p = pcap_create(source, errbuf);
+ p = pcap_create(device, errbuf);
if (p == NULL)
return (NULL);
status = pcap_set_snaplen(p, snaplen);
@@ -796,15 +851,15 @@ pcap_open_live(const char *source, int snaplen, int promisc, int to_ms, char *er
return (p);
fail:
if (status == PCAP_ERROR)
- snprintf(errbuf, PCAP_ERRBUF_SIZE, "%s: %s", source,
+ pcap_snprintf(errbuf, PCAP_ERRBUF_SIZE, "%s: %s", device,
p->errbuf);
else if (status == PCAP_ERROR_NO_SUCH_DEVICE ||
status == PCAP_ERROR_PERM_DENIED ||
status == PCAP_ERROR_PROMISC_PERM_DENIED)
- snprintf(errbuf, PCAP_ERRBUF_SIZE, "%s: %s (%s)", source,
+ pcap_snprintf(errbuf, PCAP_ERRBUF_SIZE, "%s: %s (%s)", device,
pcap_statustostr(status), p->errbuf);
else
- snprintf(errbuf, PCAP_ERRBUF_SIZE, "%s: %s", source,
+ pcap_snprintf(errbuf, PCAP_ERRBUF_SIZE, "%s: %s", device,
pcap_statustostr(status));
pcap_close(p);
return (NULL);
@@ -820,13 +875,6 @@ pcap_open_offline_common(char *ebuf, size_t size)
return (NULL);
p->opt.tstamp_precision = PCAP_TSTAMP_PRECISION_MICRO;
- 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);
}
@@ -837,16 +885,6 @@ pcap_dispatch(pcap_t *p, int cnt, pcap_handler callback, u_char *user)
return (p->read_op(p, cnt, callback, user));
}
-/*
- * XXX - is this necessary?
- */
-int
-pcap_read(pcap_t *p, int cnt, pcap_handler callback, u_char *user)
-{
-
- return (p->read_op(p, cnt, callback, user));
-}
-
int
pcap_loop(pcap_t *p, int cnt, pcap_handler callback, u_char *user)
{
@@ -916,7 +954,7 @@ pcap_list_datalinks(pcap_t *p, int **dlt_buffer)
*/
*dlt_buffer = (int*)malloc(sizeof(**dlt_buffer));
if (*dlt_buffer == NULL) {
- (void)snprintf(p->errbuf, sizeof(p->errbuf),
+ (void)pcap_snprintf(p->errbuf, sizeof(p->errbuf),
"malloc: %s", pcap_strerror(errno));
return (PCAP_ERROR);
}
@@ -925,7 +963,7 @@ pcap_list_datalinks(pcap_t *p, int **dlt_buffer)
} else {
*dlt_buffer = (int*)calloc(sizeof(**dlt_buffer), p->dlt_count);
if (*dlt_buffer == NULL) {
- (void)snprintf(p->errbuf, sizeof(p->errbuf),
+ (void)pcap_snprintf(p->errbuf, sizeof(p->errbuf),
"malloc: %s", pcap_strerror(errno));
return (PCAP_ERROR);
}
@@ -958,6 +996,9 @@ pcap_set_datalink(pcap_t *p, int dlt)
int i;
const char *dlt_name;
+ if (dlt < 0)
+ goto unsupported;
+
if (p->dlt_count == 0 || p->set_datalink_op == NULL) {
/*
* We couldn't fetch the list of DLTs, or we don't
@@ -975,7 +1016,7 @@ pcap_set_datalink(pcap_t *p, int dlt)
return (0);
}
for (i = 0; i < p->dlt_count; i++)
- if (p->dlt_list[i] == dlt)
+ if (p->dlt_list[i] == (u_int)dlt)
break;
if (i >= p->dlt_count)
goto unsupported;
@@ -1003,11 +1044,11 @@ pcap_set_datalink(pcap_t *p, int dlt)
unsupported:
dlt_name = pcap_datalink_val_to_name(dlt);
if (dlt_name != NULL) {
- (void) snprintf(p->errbuf, sizeof(p->errbuf),
+ (void) pcap_snprintf(p->errbuf, sizeof(p->errbuf),
"%s is not one of the DLTs supported by this device",
dlt_name);
} else {
- (void) snprintf(p->errbuf, sizeof(p->errbuf),
+ (void) pcap_snprintf(p->errbuf, sizeof(p->errbuf),
"DLT %d is not one of the DLTs supported by this device",
dlt);
}
@@ -1105,133 +1146,139 @@ struct dlt_choice {
int dlt;
};
-#define DLT_CHOICE(code, description) { #code, description, code }
+#define DLT_CHOICE(code, description) { #code, description, DLT_ ## code }
#define DLT_CHOICE_SENTINEL { NULL, NULL, 0 }
static struct dlt_choice dlt_choices[] = {
- DLT_CHOICE(DLT_NULL, "BSD loopback"),
- DLT_CHOICE(DLT_EN10MB, "Ethernet"),
- DLT_CHOICE(DLT_IEEE802, "Token ring"),
- DLT_CHOICE(DLT_ARCNET, "BSD ARCNET"),
- DLT_CHOICE(DLT_SLIP, "SLIP"),
- DLT_CHOICE(DLT_PPP, "PPP"),
- DLT_CHOICE(DLT_FDDI, "FDDI"),
- DLT_CHOICE(DLT_ATM_RFC1483, "RFC 1483 LLC-encapsulated ATM"),
- DLT_CHOICE(DLT_RAW, "Raw IP"),
- DLT_CHOICE(DLT_SLIP_BSDOS, "BSD/OS SLIP"),
- DLT_CHOICE(DLT_PPP_BSDOS, "BSD/OS PPP"),
- DLT_CHOICE(DLT_ATM_CLIP, "Linux Classical IP-over-ATM"),
- DLT_CHOICE(DLT_PPP_SERIAL, "PPP over serial"),
- DLT_CHOICE(DLT_PPP_ETHER, "PPPoE"),
- DLT_CHOICE(DLT_SYMANTEC_FIREWALL, "Symantec Firewall"),
- DLT_CHOICE(DLT_C_HDLC, "Cisco HDLC"),
- DLT_CHOICE(DLT_IEEE802_11, "802.11"),
- DLT_CHOICE(DLT_FRELAY, "Frame Relay"),
- DLT_CHOICE(DLT_LOOP, "OpenBSD loopback"),
- DLT_CHOICE(DLT_ENC, "OpenBSD encapsulated IP"),
- DLT_CHOICE(DLT_LINUX_SLL, "Linux cooked"),
- DLT_CHOICE(DLT_LTALK, "Localtalk"),
- DLT_CHOICE(DLT_PFLOG, "OpenBSD pflog file"),
- DLT_CHOICE(DLT_PFSYNC, "Packet filter state syncing"),
- DLT_CHOICE(DLT_PRISM_HEADER, "802.11 plus Prism header"),
- DLT_CHOICE(DLT_IP_OVER_FC, "RFC 2625 IP-over-Fibre Channel"),
- DLT_CHOICE(DLT_SUNATM, "Sun raw ATM"),
- DLT_CHOICE(DLT_IEEE802_11_RADIO, "802.11 plus radiotap header"),
- DLT_CHOICE(DLT_ARCNET_LINUX, "Linux ARCNET"),
- DLT_CHOICE(DLT_JUNIPER_MLPPP, "Juniper Multi-Link PPP"),
- DLT_CHOICE(DLT_JUNIPER_MLFR, "Juniper Multi-Link Frame Relay"),
- DLT_CHOICE(DLT_JUNIPER_ES, "Juniper Encryption Services PIC"),
- DLT_CHOICE(DLT_JUNIPER_GGSN, "Juniper GGSN PIC"),
- DLT_CHOICE(DLT_JUNIPER_MFR, "Juniper FRF.16 Frame Relay"),
- DLT_CHOICE(DLT_JUNIPER_ATM2, "Juniper ATM2 PIC"),
- DLT_CHOICE(DLT_JUNIPER_SERVICES, "Juniper Advanced Services PIC"),
- DLT_CHOICE(DLT_JUNIPER_ATM1, "Juniper ATM1 PIC"),
- DLT_CHOICE(DLT_APPLE_IP_OVER_IEEE1394, "Apple IP-over-IEEE 1394"),
- DLT_CHOICE(DLT_MTP2_WITH_PHDR, "SS7 MTP2 with Pseudo-header"),
- DLT_CHOICE(DLT_MTP2, "SS7 MTP2"),
- DLT_CHOICE(DLT_MTP3, "SS7 MTP3"),
- DLT_CHOICE(DLT_SCCP, "SS7 SCCP"),
- DLT_CHOICE(DLT_DOCSIS, "DOCSIS"),
- DLT_CHOICE(DLT_LINUX_IRDA, "Linux IrDA"),
- DLT_CHOICE(DLT_IEEE802_11_RADIO_AVS, "802.11 plus AVS radio information header"),
- DLT_CHOICE(DLT_JUNIPER_MONITOR, "Juniper Passive Monitor PIC"),
- DLT_CHOICE(DLT_BACNET_MS_TP, "BACnet MS/TP"),
- DLT_CHOICE(DLT_PPP_PPPD, "PPP for pppd, with direction flag"),
- DLT_CHOICE(DLT_JUNIPER_PPPOE, "Juniper PPPoE"),
- DLT_CHOICE(DLT_JUNIPER_PPPOE_ATM, "Juniper PPPoE/ATM"),
- DLT_CHOICE(DLT_GPRS_LLC, "GPRS LLC"),
- DLT_CHOICE(DLT_GPF_T, "GPF-T"),
- DLT_CHOICE(DLT_GPF_F, "GPF-F"),
- DLT_CHOICE(DLT_JUNIPER_PIC_PEER, "Juniper PIC Peer"),
- DLT_CHOICE(DLT_ERF_ETH, "Ethernet with Endace ERF header"),
- DLT_CHOICE(DLT_ERF_POS, "Packet-over-SONET with Endace ERF header"),
- DLT_CHOICE(DLT_LINUX_LAPD, "Linux vISDN LAPD"),
- DLT_CHOICE(DLT_JUNIPER_ETHER, "Juniper Ethernet"),
- DLT_CHOICE(DLT_JUNIPER_PPP, "Juniper PPP"),
- DLT_CHOICE(DLT_JUNIPER_FRELAY, "Juniper Frame Relay"),
- DLT_CHOICE(DLT_JUNIPER_CHDLC, "Juniper C-HDLC"),
- DLT_CHOICE(DLT_MFR, "FRF.16 Frame Relay"),
- DLT_CHOICE(DLT_JUNIPER_VP, "Juniper Voice PIC"),
- DLT_CHOICE(DLT_A429, "Arinc 429"),
- DLT_CHOICE(DLT_A653_ICM, "Arinc 653 Interpartition Communication"),
- DLT_CHOICE(DLT_USB, "USB"),
- DLT_CHOICE(DLT_BLUETOOTH_HCI_H4, "Bluetooth HCI UART transport layer"),
- DLT_CHOICE(DLT_IEEE802_16_MAC_CPS, "IEEE 802.16 MAC Common Part Sublayer"),
- DLT_CHOICE(DLT_USB_LINUX, "USB with Linux header"),
- DLT_CHOICE(DLT_CAN20B, "Controller Area Network (CAN) v. 2.0B"),
- DLT_CHOICE(DLT_IEEE802_15_4_LINUX, "IEEE 802.15.4 with Linux padding"),
- DLT_CHOICE(DLT_PPI, "Per-Packet Information"),
- DLT_CHOICE(DLT_IEEE802_16_MAC_CPS_RADIO, "IEEE 802.16 MAC Common Part Sublayer plus radiotap header"),
- DLT_CHOICE(DLT_JUNIPER_ISM, "Juniper Integrated Service Module"),
- DLT_CHOICE(DLT_IEEE802_15_4, "IEEE 802.15.4 with FCS"),
- DLT_CHOICE(DLT_SITA, "SITA pseudo-header"),
- DLT_CHOICE(DLT_ERF, "Endace ERF header"),
- DLT_CHOICE(DLT_RAIF1, "Ethernet with u10 Networks pseudo-header"),
- DLT_CHOICE(DLT_IPMB, "IPMB"),
- DLT_CHOICE(DLT_JUNIPER_ST, "Juniper Secure Tunnel"),
- DLT_CHOICE(DLT_BLUETOOTH_HCI_H4_WITH_PHDR, "Bluetooth HCI UART transport layer plus pseudo-header"),
- DLT_CHOICE(DLT_AX25_KISS, "AX.25 with KISS header"),
- DLT_CHOICE(DLT_IEEE802_15_4_NONASK_PHY, "IEEE 802.15.4 with non-ASK PHY data"),
- DLT_CHOICE(DLT_MPLS, "MPLS with label as link-layer header"),
- DLT_CHOICE(DLT_LINUX_EVDEV, "Linux evdev events"),
- DLT_CHOICE(DLT_USB_LINUX_MMAPPED, "USB with padded Linux header"),
- DLT_CHOICE(DLT_DECT, "DECT"),
- DLT_CHOICE(DLT_AOS, "AOS Space Data Link protocol"),
- DLT_CHOICE(DLT_WIHART, "Wireless HART"),
- DLT_CHOICE(DLT_FC_2, "Fibre Channel FC-2"),
- DLT_CHOICE(DLT_FC_2_WITH_FRAME_DELIMS, "Fibre Channel FC-2 with frame delimiters"),
- DLT_CHOICE(DLT_IPNET, "Solaris ipnet"),
- DLT_CHOICE(DLT_CAN_SOCKETCAN, "CAN-bus with SocketCAN headers"),
- DLT_CHOICE(DLT_IPV4, "Raw IPv4"),
- DLT_CHOICE(DLT_IPV6, "Raw IPv6"),
- DLT_CHOICE(DLT_IEEE802_15_4_NOFCS, "IEEE 802.15.4 without FCS"),
- DLT_CHOICE(DLT_DBUS, "D-Bus"),
- DLT_CHOICE(DLT_JUNIPER_VS, "Juniper Virtual Server"),
- DLT_CHOICE(DLT_JUNIPER_SRX_E2E, "Juniper SRX E2E"),
- DLT_CHOICE(DLT_JUNIPER_FIBRECHANNEL, "Juniper Fibre Channel"),
- DLT_CHOICE(DLT_DVB_CI, "DVB-CI"),
- DLT_CHOICE(DLT_MUX27010, "MUX27010"),
- DLT_CHOICE(DLT_STANAG_5066_D_PDU, "STANAG 5066 D_PDUs"),
- DLT_CHOICE(DLT_JUNIPER_ATM_CEMIC, "Juniper ATM CEMIC"),
- DLT_CHOICE(DLT_NFLOG, "Linux netfilter log messages"),
- DLT_CHOICE(DLT_NETANALYZER, "Ethernet with Hilscher netANALYZER pseudo-header"),
- DLT_CHOICE(DLT_NETANALYZER_TRANSPARENT, "Ethernet with Hilscher netANALYZER pseudo-header and with preamble and SFD"),
- DLT_CHOICE(DLT_IPOIB, "RFC 4391 IP-over-Infiniband"),
- DLT_CHOICE(DLT_MPEG_2_TS, "MPEG-2 transport stream"),
- DLT_CHOICE(DLT_NG40, "ng40 protocol tester Iub/Iur"),
- DLT_CHOICE(DLT_NFC_LLCP, "NFC LLCP PDUs with pseudo-header"),
- DLT_CHOICE(DLT_INFINIBAND, "InfiniBand"),
- DLT_CHOICE(DLT_SCTP, "SCTP"),
- DLT_CHOICE(DLT_USBPCAP, "USB with USBPcap header"),
- DLT_CHOICE(DLT_RTAC_SERIAL, "Schweitzer Engineering Laboratories RTAC packets"),
- DLT_CHOICE(DLT_BLUETOOTH_LE_LL, "Bluetooth Low Energy air interface"),
- DLT_CHOICE(DLT_NETLINK, "Linux netlink"),
- DLT_CHOICE(DLT_BLUETOOTH_LINUX_MONITOR, "Bluetooth Linux Monitor"),
- DLT_CHOICE(DLT_BLUETOOTH_BREDR_BB, "Bluetooth Basic Rate/Enhanced Data Rate baseband packets"),
- DLT_CHOICE(DLT_BLUETOOTH_LE_LL_WITH_PHDR, "Bluetooth Low Energy air interface with pseudo-header"),
- DLT_CHOICE(DLT_PROFIBUS_DL, "PROFIBUS data link layer"),
- DLT_CHOICE(DLT_PKTAP, "Apple DLT_PKTAP"),
- DLT_CHOICE(DLT_EPON, "Ethernet with 802.3 Clause 65 EPON preamble"),
+ DLT_CHOICE(NULL, "BSD loopback"),
+ DLT_CHOICE(EN10MB, "Ethernet"),
+ DLT_CHOICE(IEEE802, "Token ring"),
+ DLT_CHOICE(ARCNET, "BSD ARCNET"),
+ DLT_CHOICE(SLIP, "SLIP"),
+ DLT_CHOICE(PPP, "PPP"),
+ DLT_CHOICE(FDDI, "FDDI"),
+ DLT_CHOICE(ATM_RFC1483, "RFC 1483 LLC-encapsulated ATM"),
+ DLT_CHOICE(RAW, "Raw IP"),
+ DLT_CHOICE(SLIP_BSDOS, "BSD/OS SLIP"),
+ DLT_CHOICE(PPP_BSDOS, "BSD/OS PPP"),
+ DLT_CHOICE(ATM_CLIP, "Linux Classical IP-over-ATM"),
+ DLT_CHOICE(PPP_SERIAL, "PPP over serial"),
+ DLT_CHOICE(PPP_ETHER, "PPPoE"),
+ DLT_CHOICE(SYMANTEC_FIREWALL, "Symantec Firewall"),
+ DLT_CHOICE(C_HDLC, "Cisco HDLC"),
+ DLT_CHOICE(IEEE802_11, "802.11"),
+ DLT_CHOICE(FRELAY, "Frame Relay"),
+ DLT_CHOICE(LOOP, "OpenBSD loopback"),
+ DLT_CHOICE(ENC, "OpenBSD encapsulated IP"),
+ DLT_CHOICE(LINUX_SLL, "Linux cooked"),
+ DLT_CHOICE(LTALK, "Localtalk"),
+ DLT_CHOICE(PFLOG, "OpenBSD pflog file"),
+ DLT_CHOICE(PFSYNC, "Packet filter state syncing"),
+ DLT_CHOICE(PRISM_HEADER, "802.11 plus Prism header"),
+ DLT_CHOICE(IP_OVER_FC, "RFC 2625 IP-over-Fibre Channel"),
+ DLT_CHOICE(SUNATM, "Sun raw ATM"),
+ DLT_CHOICE(IEEE802_11_RADIO, "802.11 plus radiotap header"),
+ DLT_CHOICE(ARCNET_LINUX, "Linux ARCNET"),
+ DLT_CHOICE(JUNIPER_MLPPP, "Juniper Multi-Link PPP"),
+ DLT_CHOICE(JUNIPER_MLFR, "Juniper Multi-Link Frame Relay"),
+ DLT_CHOICE(JUNIPER_ES, "Juniper Encryption Services PIC"),
+ DLT_CHOICE(JUNIPER_GGSN, "Juniper GGSN PIC"),
+ DLT_CHOICE(JUNIPER_MFR, "Juniper FRF.16 Frame Relay"),
+ DLT_CHOICE(JUNIPER_ATM2, "Juniper ATM2 PIC"),
+ DLT_CHOICE(JUNIPER_SERVICES, "Juniper Advanced Services PIC"),
+ DLT_CHOICE(JUNIPER_ATM1, "Juniper ATM1 PIC"),
+ DLT_CHOICE(APPLE_IP_OVER_IEEE1394, "Apple IP-over-IEEE 1394"),
+ DLT_CHOICE(MTP2_WITH_PHDR, "SS7 MTP2 with Pseudo-header"),
+ DLT_CHOICE(MTP2, "SS7 MTP2"),
+ DLT_CHOICE(MTP3, "SS7 MTP3"),
+ DLT_CHOICE(SCCP, "SS7 SCCP"),
+ DLT_CHOICE(DOCSIS, "DOCSIS"),
+ DLT_CHOICE(LINUX_IRDA, "Linux IrDA"),
+ DLT_CHOICE(IEEE802_11_RADIO_AVS, "802.11 plus AVS radio information header"),
+ DLT_CHOICE(JUNIPER_MONITOR, "Juniper Passive Monitor PIC"),
+ DLT_CHOICE(BACNET_MS_TP, "BACnet MS/TP"),
+ DLT_CHOICE(PPP_PPPD, "PPP for pppd, with direction flag"),
+ DLT_CHOICE(JUNIPER_PPPOE, "Juniper PPPoE"),
+ DLT_CHOICE(JUNIPER_PPPOE_ATM, "Juniper PPPoE/ATM"),
+ DLT_CHOICE(GPRS_LLC, "GPRS LLC"),
+ DLT_CHOICE(GPF_T, "GPF-T"),
+ DLT_CHOICE(GPF_F, "GPF-F"),
+ DLT_CHOICE(JUNIPER_PIC_PEER, "Juniper PIC Peer"),
+ DLT_CHOICE(ERF_ETH, "Ethernet with Endace ERF header"),
+ DLT_CHOICE(ERF_POS, "Packet-over-SONET with Endace ERF header"),
+ DLT_CHOICE(LINUX_LAPD, "Linux vISDN LAPD"),
+ DLT_CHOICE(JUNIPER_ETHER, "Juniper Ethernet"),
+ DLT_CHOICE(JUNIPER_PPP, "Juniper PPP"),
+ DLT_CHOICE(JUNIPER_FRELAY, "Juniper Frame Relay"),
+ DLT_CHOICE(JUNIPER_CHDLC, "Juniper C-HDLC"),
+ DLT_CHOICE(MFR, "FRF.16 Frame Relay"),
+ DLT_CHOICE(JUNIPER_VP, "Juniper Voice PIC"),
+ DLT_CHOICE(A429, "Arinc 429"),
+ DLT_CHOICE(A653_ICM, "Arinc 653 Interpartition Communication"),
+ DLT_CHOICE(USB_FREEBSD, "USB with FreeBSD header"),
+ DLT_CHOICE(BLUETOOTH_HCI_H4, "Bluetooth HCI UART transport layer"),
+ DLT_CHOICE(IEEE802_16_MAC_CPS, "IEEE 802.16 MAC Common Part Sublayer"),
+ DLT_CHOICE(USB_LINUX, "USB with Linux header"),
+ DLT_CHOICE(CAN20B, "Controller Area Network (CAN) v. 2.0B"),
+ DLT_CHOICE(IEEE802_15_4_LINUX, "IEEE 802.15.4 with Linux padding"),
+ DLT_CHOICE(PPI, "Per-Packet Information"),
+ DLT_CHOICE(IEEE802_16_MAC_CPS_RADIO, "IEEE 802.16 MAC Common Part Sublayer plus radiotap header"),
+ DLT_CHOICE(JUNIPER_ISM, "Juniper Integrated Service Module"),
+ DLT_CHOICE(IEEE802_15_4, "IEEE 802.15.4 with FCS"),
+ DLT_CHOICE(SITA, "SITA pseudo-header"),
+ DLT_CHOICE(ERF, "Endace ERF header"),
+ DLT_CHOICE(RAIF1, "Ethernet with u10 Networks pseudo-header"),
+ DLT_CHOICE(IPMB, "IPMB"),
+ DLT_CHOICE(JUNIPER_ST, "Juniper Secure Tunnel"),
+ DLT_CHOICE(BLUETOOTH_HCI_H4_WITH_PHDR, "Bluetooth HCI UART transport layer plus pseudo-header"),
+ DLT_CHOICE(AX25_KISS, "AX.25 with KISS header"),
+ DLT_CHOICE(IEEE802_15_4_NONASK_PHY, "IEEE 802.15.4 with non-ASK PHY data"),
+ DLT_CHOICE(MPLS, "MPLS with label as link-layer header"),
+ DLT_CHOICE(LINUX_EVDEV, "Linux evdev events"),
+ DLT_CHOICE(USB_LINUX_MMAPPED, "USB with padded Linux header"),
+ DLT_CHOICE(DECT, "DECT"),
+ DLT_CHOICE(AOS, "AOS Space Data Link protocol"),
+ DLT_CHOICE(WIHART, "Wireless HART"),
+ DLT_CHOICE(FC_2, "Fibre Channel FC-2"),
+ DLT_CHOICE(FC_2_WITH_FRAME_DELIMS, "Fibre Channel FC-2 with frame delimiters"),
+ DLT_CHOICE(IPNET, "Solaris ipnet"),
+ DLT_CHOICE(CAN_SOCKETCAN, "CAN-bus with SocketCAN headers"),
+ DLT_CHOICE(IPV4, "Raw IPv4"),
+ DLT_CHOICE(IPV6, "Raw IPv6"),
+ DLT_CHOICE(IEEE802_15_4_NOFCS, "IEEE 802.15.4 without FCS"),
+ DLT_CHOICE(DBUS, "D-Bus"),
+ DLT_CHOICE(JUNIPER_VS, "Juniper Virtual Server"),
+ DLT_CHOICE(JUNIPER_SRX_E2E, "Juniper SRX E2E"),
+ DLT_CHOICE(JUNIPER_FIBRECHANNEL, "Juniper Fibre Channel"),
+ DLT_CHOICE(DVB_CI, "DVB-CI"),
+ DLT_CHOICE(MUX27010, "MUX27010"),
+ DLT_CHOICE(STANAG_5066_D_PDU, "STANAG 5066 D_PDUs"),
+ DLT_CHOICE(JUNIPER_ATM_CEMIC, "Juniper ATM CEMIC"),
+ DLT_CHOICE(NFLOG, "Linux netfilter log messages"),
+ DLT_CHOICE(NETANALYZER, "Ethernet with Hilscher netANALYZER pseudo-header"),
+ DLT_CHOICE(NETANALYZER_TRANSPARENT, "Ethernet with Hilscher netANALYZER pseudo-header and with preamble and SFD"),
+ DLT_CHOICE(IPOIB, "RFC 4391 IP-over-Infiniband"),
+ DLT_CHOICE(MPEG_2_TS, "MPEG-2 transport stream"),
+ DLT_CHOICE(NG40, "ng40 protocol tester Iub/Iur"),
+ DLT_CHOICE(NFC_LLCP, "NFC LLCP PDUs with pseudo-header"),
+ DLT_CHOICE(INFINIBAND, "InfiniBand"),
+ DLT_CHOICE(SCTP, "SCTP"),
+ DLT_CHOICE(USBPCAP, "USB with USBPcap header"),
+ DLT_CHOICE(RTAC_SERIAL, "Schweitzer Engineering Laboratories RTAC packets"),
+ DLT_CHOICE(BLUETOOTH_LE_LL, "Bluetooth Low Energy air interface"),
+ DLT_CHOICE(NETLINK, "Linux netlink"),
+ DLT_CHOICE(BLUETOOTH_LINUX_MONITOR, "Bluetooth Linux Monitor"),
+ DLT_CHOICE(BLUETOOTH_BREDR_BB, "Bluetooth Basic Rate/Enhanced Data Rate baseband packets"),
+ DLT_CHOICE(BLUETOOTH_LE_LL_WITH_PHDR, "Bluetooth Low Energy air interface with pseudo-header"),
+ DLT_CHOICE(PROFIBUS_DL, "PROFIBUS data link layer"),
+ DLT_CHOICE(PKTAP, "Apple DLT_PKTAP"),
+ DLT_CHOICE(EPON, "Ethernet with 802.3 Clause 65 EPON preamble"),
+ DLT_CHOICE(IPMI_HPM_2, "IPMI trace packets"),
+ DLT_CHOICE(ZWAVE_R1_R2, "Z-Wave RF profile R1 and R2 packets"),
+ DLT_CHOICE(ZWAVE_R3, "Z-Wave RF profile R3 packets"),
+ DLT_CHOICE(WATTSTOPPER_DLM, "WattStopper Digital Lighting Management (DLM) and Legrand Nitoo Open protocol"),
+ DLT_CHOICE(ISO_14443, "ISO 14443 messages"),
+ DLT_CHOICE(RDS, "IEC 62106 Radio Data System groups"),
DLT_CHOICE_SENTINEL
};
@@ -1241,8 +1288,7 @@ pcap_datalink_name_to_val(const char *name)
int i;
for (i = 0; dlt_choices[i].name != NULL; i++) {
- if (pcap_strcasecmp(dlt_choices[i].name + sizeof("DLT_") - 1,
- name) == 0)
+ if (pcap_strcasecmp(dlt_choices[i].name, name) == 0)
return (dlt_choices[i].dlt);
}
return (-1);
@@ -1255,7 +1301,7 @@ pcap_datalink_val_to_name(int dlt)
for (i = 0; dlt_choices[i].name != NULL; i++) {
if (dlt_choices[i].dlt == dlt)
- return (dlt_choices[i].name + sizeof("DLT_") - 1);
+ return (dlt_choices[i].name);
}
return (NULL);
}
@@ -1364,7 +1410,7 @@ pcap_file(pcap_t *p)
int
pcap_fileno(pcap_t *p)
{
-#ifndef WIN32
+#ifndef _WIN32
return (p->fd);
#else
if (p->adapter != NULL)
@@ -1374,7 +1420,7 @@ pcap_fileno(pcap_t *p)
#endif
}
-#if !defined(WIN32) && !defined(MSDOS)
+#if !defined(_WIN32) && !defined(MSDOS)
int
pcap_get_selectable_fd(pcap_t *p)
{
@@ -1383,7 +1429,7 @@ pcap_get_selectable_fd(pcap_t *p)
#endif
void
-pcap_perror(pcap_t *p, char *prefix)
+pcap_perror(pcap_t *p, const char *prefix)
{
fprintf(stderr, "%s: %s\n", prefix, p->errbuf);
}
@@ -1414,11 +1460,8 @@ pcap_getnonblock(pcap_t *p, char *errbuf)
/*
* Get the current non-blocking mode setting, under the assumption that
* it's just the standard POSIX non-blocking flag.
- *
- * We don't look at "p->nonblock", in case somebody tweaked the FD
- * directly.
*/
-#if !defined(WIN32) && !defined(MSDOS)
+#if !defined(_WIN32) && !defined(MSDOS)
int
pcap_getnonblock_fd(pcap_t *p, char *errbuf)
{
@@ -1426,7 +1469,7 @@ pcap_getnonblock_fd(pcap_t *p, char *errbuf)
fdflags = fcntl(p->fd, F_GETFL, 0);
if (fdflags == -1) {
- snprintf(errbuf, PCAP_ERRBUF_SIZE, "F_GETFL: %s",
+ pcap_snprintf(errbuf, PCAP_ERRBUF_SIZE, "F_GETFL: %s",
pcap_strerror(errno));
return (-1);
}
@@ -1454,7 +1497,7 @@ pcap_setnonblock(pcap_t *p, int nonblock, char *errbuf)
return (ret);
}
-#if !defined(WIN32) && !defined(MSDOS)
+#if !defined(_WIN32) && !defined(MSDOS)
/*
* Set non-blocking mode, under the assumption that it's just the
* standard POSIX non-blocking flag. (This can be called by the
@@ -1468,7 +1511,7 @@ pcap_setnonblock_fd(pcap_t *p, int nonblock, char *errbuf)
fdflags = fcntl(p->fd, F_GETFL, 0);
if (fdflags == -1) {
- snprintf(errbuf, PCAP_ERRBUF_SIZE, "F_GETFL: %s",
+ pcap_snprintf(errbuf, PCAP_ERRBUF_SIZE, "F_GETFL: %s",
pcap_strerror(errno));
return (-1);
}
@@ -1477,7 +1520,7 @@ pcap_setnonblock_fd(pcap_t *p, int nonblock, char *errbuf)
else
fdflags &= ~O_NONBLOCK;
if (fcntl(p->fd, F_SETFL, fdflags) == -1) {
- snprintf(errbuf, PCAP_ERRBUF_SIZE, "F_SETFL: %s",
+ pcap_snprintf(errbuf, PCAP_ERRBUF_SIZE, "F_SETFL: %s",
pcap_strerror(errno));
return (-1);
}
@@ -1485,21 +1528,18 @@ pcap_setnonblock_fd(pcap_t *p, int nonblock, char *errbuf)
}
#endif
-#ifdef WIN32
+#ifdef _WIN32
/*
- * Generate a string for the last Win32-specific error (i.e. an error generated when
+ * Generate a string for a Win32-specific error (i.e. an error generated when
* calling a Win32 API).
* For errors occurred during standard C calls, we still use pcap_strerror()
*/
-char *
-pcap_win32strerror(void)
+void
+pcap_win32_err_to_str(DWORD error, char *errbuf)
{
- DWORD error;
- static char errbuf[PCAP_ERRBUF_SIZE+1];
- int errlen;
+ size_t errlen;
char *p;
- error = GetLastError();
FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM, NULL, error, 0, errbuf,
PCAP_ERRBUF_SIZE, NULL);
@@ -1513,8 +1553,7 @@ pcap_win32strerror(void)
errbuf[errlen - 2] = '\0';
}
p = strchr(errbuf, '\0');
- snprintf (p, sizeof(errbuf)-(p-errbuf), " (%lu)", error);
- return (errbuf);
+ pcap_snprintf (p, PCAP_ERRBUF_SIZE+1-(p-errbuf), " (%lu)", error);
}
#endif
@@ -1573,7 +1612,7 @@ pcap_statustostr(int errnum)
case PCAP_ERROR_TSTAMP_PRECISION_NOTSUP:
return ("That device doesn't support that time stamp precision");
}
- (void)snprintf(ebuf, sizeof ebuf, "Unknown error: %d", errnum);
+ (void)pcap_snprintf(ebuf, sizeof ebuf, "Unknown error: %d", errnum);
return(ebuf);
}
@@ -1584,16 +1623,25 @@ const char *
pcap_strerror(int errnum)
{
#ifdef HAVE_STRERROR
+#ifdef _WIN32
+ static char errbuf[PCAP_ERRBUF_SIZE];
+ errno_t errno;
+ errno = strerror_s(errbuf, PCAP_ERRBUF_SIZE, errnum);
+ if (errno != 0) /* errno = 0 if successful */
+ strlcpy(errbuf, "strerror_s() error", PCAP_ERRBUF_SIZE);
+ return (errbuf);
+#else
return (strerror(errnum));
+#endif /* _WIN32 */
#else
extern int sys_nerr;
extern const char *const sys_errlist[];
- static char ebuf[15+10+1];
+ static char errbuf[PCAP_ERRBUF_SIZE];
if ((unsigned int)errnum < sys_nerr)
return ((char *)sys_errlist[errnum]);
- (void)snprintf(ebuf, sizeof ebuf, "Unknown error: %d", errnum);
- return(ebuf);
+ (void)pcap_snprintf(errbuf, sizeof errbuf, "Unknown error: %d", errnum);
+ return (errbuf);
#endif
}
@@ -1613,7 +1661,7 @@ int
pcap_setdirection(pcap_t *p, pcap_direction_t d)
{
if (p->setdirection_op == NULL) {
- snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
+ pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
"Setting direction is not implemented on this platform");
return (-1);
} else
@@ -1629,12 +1677,18 @@ pcap_stats(pcap_t *p, struct pcap_stat *ps)
static int
pcap_stats_dead(pcap_t *p, struct pcap_stat *ps _U_)
{
- snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
+ pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
"Statistics aren't available from a pcap_open_dead pcap_t");
return (-1);
}
-#ifdef WIN32
+#ifdef _WIN32
+struct pcap_stat *
+pcap_stats_ex(pcap_t *p, int *pcap_stat_size)
+{
+ return (p->stats_ex_op(p, pcap_stat_size));
+}
+
int
pcap_setbuff(pcap_t *p, int dim)
{
@@ -1644,7 +1698,7 @@ pcap_setbuff(pcap_t *p, int dim)
static int
pcap_setbuff_dead(pcap_t *p, int dim)
{
- snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
+ pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
"The kernel buffer size cannot be set on a pcap_open_dead pcap_t");
return (-1);
}
@@ -1658,7 +1712,7 @@ pcap_setmode(pcap_t *p, int mode)
static int
pcap_setmode_dead(pcap_t *p, int mode)
{
- snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
+ pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
"impossible to set mode on a pcap_open_dead pcap_t");
return (-1);
}
@@ -1669,19 +1723,181 @@ pcap_setmintocopy(pcap_t *p, int size)
return (p->setmintocopy_op(p, size));
}
-Adapter *
-pcap_get_adapter(pcap_t *p)
+static int
+pcap_setmintocopy_dead(pcap_t *p, int size)
+{
+ pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
+ "The mintocopy parameter cannot be set on a pcap_open_dead pcap_t");
+ return (-1);
+}
+
+HANDLE
+pcap_getevent(pcap_t *p)
+{
+ return (p->getevent_op(p));
+}
+
+static HANDLE
+pcap_getevent_dead(pcap_t *p)
+{
+ pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
+ "A pcap_open_dead pcap_t has no event handle");
+ return (INVALID_HANDLE_VALUE);
+}
+
+int
+pcap_oid_get_request(pcap_t *p, bpf_u_int32 oid, void *data, size_t *lenp)
{
- return (p->getadapter_op(p));
+ return (p->oid_get_request_op(p, oid, data, lenp));
}
static int
-pcap_setmintocopy_dead(pcap_t *p, int size)
+pcap_oid_get_request_dead(pcap_t *p, bpf_u_int32 oid _U_, void *data _U_,
+ size_t *lenp _U_)
{
- snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
- "The mintocopy parameter cannot be set on a pcap_open_dead pcap_t");
+ pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
+ "An OID get request cannot be performed on a pcap_open_dead pcap_t");
+ return (PCAP_ERROR);
+}
+
+int
+pcap_oid_set_request(pcap_t *p, bpf_u_int32 oid, const void *data, size_t *lenp)
+{
+ return (p->oid_set_request_op(p, oid, data, lenp));
+}
+
+static int
+pcap_oid_set_request_dead(pcap_t *p, bpf_u_int32 oid _U_, const void *data _U_,
+ size_t *lenp _U_)
+{
+ pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
+ "An OID set request cannot be performed on a pcap_open_dead pcap_t");
+ return (PCAP_ERROR);
+}
+
+pcap_send_queue *
+pcap_sendqueue_alloc(u_int memsize)
+{
+ pcap_send_queue *tqueue;
+
+ /* Allocate the queue */
+ tqueue = (pcap_send_queue *)malloc(sizeof(pcap_send_queue));
+ if (tqueue == NULL){
+ return (NULL);
+ }
+
+ /* Allocate the buffer */
+ tqueue->buffer = (char *)malloc(memsize);
+ if (tqueue->buffer == NULL) {
+ free(tqueue);
+ return (NULL);
+ }
+
+ tqueue->maxlen = memsize;
+ tqueue->len = 0;
+
+ return (tqueue);
+}
+
+void
+pcap_sendqueue_destroy(pcap_send_queue *queue)
+{
+ free(queue->buffer);
+ free(queue);
+}
+
+int
+pcap_sendqueue_queue(pcap_send_queue *queue, const struct pcap_pkthdr *pkt_header, const u_char *pkt_data)
+{
+ if (queue->len + sizeof(struct pcap_pkthdr) + pkt_header->caplen > queue->maxlen){
+ return (-1);
+ }
+
+ /* Copy the pcap_pkthdr header*/
+ memcpy(queue->buffer + queue->len, pkt_header, sizeof(struct pcap_pkthdr));
+ queue->len += sizeof(struct pcap_pkthdr);
+
+ /* copy the packet */
+ memcpy(queue->buffer + queue->len, pkt_data, pkt_header->caplen);
+ queue->len += pkt_header->caplen;
+
+ return (0);
+}
+
+u_int
+pcap_sendqueue_transmit(pcap_t *p, pcap_send_queue *queue, int sync)
+{
+ return (p->sendqueue_transmit_op(p, queue, sync));
+}
+
+static u_int
+pcap_sendqueue_transmit_dead(pcap_t *p, pcap_send_queue *queue, int sync)
+{
+ pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
+ "Packets cannot be transmitted on a pcap_open_dead pcap_t");
+ return (0);
+}
+
+int
+pcap_setuserbuffer(pcap_t *p, int size)
+{
+ return (p->setuserbuffer_op(p, size));
+}
+
+static int
+pcap_setuserbuffer_dead(pcap_t *p, int size)
+{
+ pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
+ "The user buffer cannot be set on a pcap_open_dead pcap_t");
return (-1);
}
+
+int
+pcap_live_dump(pcap_t *p, char *filename, int maxsize, int maxpacks)
+{
+ return (p->live_dump_op(p, filename, maxsize, maxpacks));
+}
+
+static int
+pcap_live_dump_dead(pcap_t *p, char *filename, int maxsize, int maxpacks)
+{
+ pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
+ "Live packet dumping cannot be performed on a pcap_open_dead pcap_t");
+ return (-1);
+}
+
+int
+pcap_live_dump_ended(pcap_t *p, int sync)
+{
+ return (p->live_dump_ended_op(p, sync));
+}
+
+static int
+pcap_live_dump_ended_dead(pcap_t *p, int sync)
+{
+ pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
+ "Live packet dumping cannot be performed on a pcap_open_dead pcap_t");
+ return (-1);
+}
+
+PAirpcapHandle
+pcap_get_airpcap_handle(pcap_t *p)
+{
+ PAirpcapHandle handle;
+
+ handle = p->get_airpcap_handle_op(p);
+ if (handle == NULL) {
+ (void)pcap_snprintf(p->errbuf, sizeof(p->errbuf),
+ "This isn't an AirPcap device");
+ }
+ return (handle);
+}
+
+static PAirpcapHandle
+pcap_get_airpcap_handle_dead(pcap_t *p)
+{
+ return (NULL);
+}
#endif
/*
@@ -1726,12 +1942,11 @@ pcap_do_addexit(pcap_t *p)
* "pcap_close_all()" called when we exit.
*/
if (!did_atexit) {
- if (atexit(pcap_close_all) == -1) {
+ if (atexit(pcap_close_all) != 0) {
/*
* "atexit()" failed; let our caller know.
*/
- strncpy(p->errbuf, "atexit failed",
- PCAP_ERRBUF_SIZE);
+ strlcpy(p->errbuf, "atexit failed", PCAP_ERRBUF_SIZE);
return (0);
}
did_atexit = 1;
@@ -1796,7 +2011,7 @@ pcap_cleanup_live_common(pcap_t *p)
p->tstamp_precision_count = 0;
}
pcap_freecode(&p->fcode);
-#if !defined(WIN32) && !defined(MSDOS)
+#if !defined(_WIN32) && !defined(MSDOS)
if (p->fd >= 0) {
close(p->fd);
p->fd = -1;
@@ -1833,12 +2048,27 @@ pcap_open_dead_with_tstamp_precision(int linktype, int snaplen, u_int precision)
p->linktype = linktype;
p->opt.tstamp_precision = precision;
p->stats_op = pcap_stats_dead;
-#ifdef WIN32
+#ifdef _WIN32
+ p->stats_ex_op = (stats_ex_op_t)pcap_not_initialized_ptr;
p->setbuff_op = pcap_setbuff_dead;
p->setmode_op = pcap_setmode_dead;
p->setmintocopy_op = pcap_setmintocopy_dead;
+ p->getevent_op = pcap_getevent_dead;
+ p->oid_get_request_op = pcap_oid_get_request_dead;
+ p->oid_set_request_op = pcap_oid_set_request_dead;
+ p->sendqueue_transmit_op = pcap_sendqueue_transmit_dead;
+ p->setuserbuffer_op = pcap_setuserbuffer_dead;
+ p->live_dump_op = pcap_live_dump_dead;
+ p->live_dump_ended_op = pcap_live_dump_ended_dead;
+ p->get_airpcap_handle_op = pcap_get_airpcap_handle_dead;
#endif
p->cleanup_op = pcap_cleanup_dead;
+
+ /*
+ * A "dead" pcap_t never requires special BPF code generation.
+ */
+ p->bpf_codegen_flags = 0;
+
p->activated = 1;
return (p);
}
@@ -1877,8 +2107,8 @@ pcap_inject(pcap_t *p, const void *buf, size_t size)
void
pcap_close(pcap_t *p)
{
- if (p->opt.source != NULL)
- free(p->opt.source);
+ if (p->opt.device != NULL)
+ free(p->opt.device);
p->cleanup_op(p);
free(p);
}
@@ -1901,36 +2131,29 @@ pcap_offline_filter(const struct bpf_program *fp, const struct pcap_pkthdr *h,
return (0);
}
-/*
- * We make the version string static, and return a pointer to it, rather
- * than exporting the version string directly. On at least some UNIXes,
- * if you import data from a shared library into an program, the data is
- * bound into the program binary, so if the string in the version of the
- * library with which the program was linked isn't the same as the
- * string in the version of the library with which the program is being
- * run, various undesirable things may happen (warnings, the string
- * being the one from the version of the library with which the program
- * was linked, or even weirder things, such as the string being the one
- * from the library but being truncated).
- */
-#ifdef HAVE_VERSION_H
-#include "version.h"
-#else
-static const char pcap_version_string[] = "libpcap version 1.x.y";
-#endif
+#include "pcap_version.h"
+
+#ifdef _WIN32
+
+static char *full_pcap_version_string;
-#ifdef WIN32
+#ifdef HAVE_VERSION_H
/*
- * XXX - it'd be nice if we could somehow generate the WinPcap and libpcap
- * version numbers when building WinPcap. (It'd be nice to do so for
- * the packet.dll version number as well.)
+ * libpcap being built for Windows, as part of a WinPcap/Npcap source
+ * tree. Include version.h from that source tree to get the WinPcap/Npcap
+ * version.
+ *
+ * XXX - it'd be nice if we could somehow generate the WinPcap version number
+ * when building WinPcap. (It'd be nice to do so for the packet.dll version
+ * number as well.)
*/
-static const char wpcap_version_string[] = "4.0";
+#include "../../version.h"
+
+static const char wpcap_version_string[] = WINPCAP_VER_STRING;
static const char pcap_version_string_fmt[] =
- "WinPcap version %s, based on %s";
+ WINPCAP_PRODUCT_NAME " version %s, based on %s";
static const char pcap_version_string_packet_dll_fmt[] =
- "WinPcap version %s (packet.dll version %s), based on %s";
-static char *full_pcap_version_string;
+ WINPCAP_PRODUCT_NAME " version %s (packet.dll version %s), based on %s";
const char *
pcap_lib_version(void)
@@ -1957,8 +2180,10 @@ pcap_lib_version(void)
malloc(full_pcap_version_string_len);
if (full_pcap_version_string == NULL)
return (NULL);
- sprintf(full_pcap_version_string,
- pcap_version_string_fmt, wpcap_version_string,
+ pcap_snprintf(full_pcap_version_string,
+ full_pcap_version_string_len,
+ pcap_version_string_fmt,
+ wpcap_version_string,
pcap_version_string);
} else {
/*
@@ -1976,15 +2201,55 @@ pcap_lib_version(void)
full_pcap_version_string = malloc(full_pcap_version_string_len);
if (full_pcap_version_string == NULL)
return (NULL);
- sprintf(full_pcap_version_string,
+ pcap_snprintf(full_pcap_version_string,
+ full_pcap_version_string_len,
pcap_version_string_packet_dll_fmt,
- wpcap_version_string, packet_version_string,
+ wpcap_version_string,
+ packet_version_string,
pcap_version_string);
}
}
return (full_pcap_version_string);
}
+#else /* HAVE_VERSION_H */
+
+/*
+ * libpcap being built for Windows, not as part of a WinPcap/Npcap source
+ * tree.
+ */
+static const char pcap_version_string_packet_dll_fmt[] =
+ "%s (packet.dll version %s)";
+const char *
+pcap_lib_version(void)
+{
+ char *packet_version_string;
+ size_t full_pcap_version_string_len;
+
+ if (full_pcap_version_string == NULL) {
+ /*
+ * Generate the version string. Report the packet.dll
+ * version.
+ */
+ packet_version_string = PacketGetVersion();
+ full_pcap_version_string_len =
+ (sizeof pcap_version_string_packet_dll_fmt - 4) +
+ strlen(pcap_version_string) +
+ strlen(packet_version_string);
+ full_pcap_version_string = malloc(full_pcap_version_string_len);
+ if (full_pcap_version_string == NULL)
+ return (NULL);
+ pcap_snprintf(full_pcap_version_string,
+ full_pcap_version_string_len,
+ pcap_version_string_packet_dll_fmt,
+ pcap_version_string,
+ packet_version_string);
+ }
+ return (full_pcap_version_string);
+}
+
+#endif /* HAVE_VERSION_H */
+
#elif defined(MSDOS)
static char *full_pcap_version_string;
@@ -2020,3 +2285,51 @@ pcap_lib_version(void)
return (pcap_version_string);
}
#endif
+
+#ifdef YYDEBUG
+/*
+ * Set the internal "debug printout" flag for the filter expression parser.
+ * The code to print that stuff is present only if YYDEBUG is defined, so
+ * the flag, and the routine to set it, are defined only if YYDEBUG is
+ * defined.
+ *
+ * This is intended for libpcap developers, not for general use.
+ * If you want to set these in a program, you'll have to declare this
+ * routine yourself, with the appropriate DLL import attribute on Windows;
+ * it's not declared in any header file, and won't be declared in any
+ * header file provided by libpcap.
+ */
+PCAP_API void pcap_set_parser_debug(int value);
+
+PCAP_API_DEF void
+pcap_set_parser_debug(int value)
+{
+ extern int pcap_debug;
+
+ pcap_debug = value;
+}
+#endif
+
+#ifdef BDEBUG
+/*
+ * Set the internal "debug printout" flag for the filter expression optimizer.
+ * The code to print that stuff is present only if BDEBUG is defined, so
+ * the flag, and the routine to set it, are defined only if BDEBUG is
+ * defined.
+ *
+ * This is intended for libpcap developers, not for general use.
+ * If you want to set these in a program, you'll have to declare this
+ * routine yourself, with the appropriate DLL import attribute on Windows;
+ * it's not declared in any header file, and won't be declared in any
+ * header file provided by libpcap.
+ */
+PCAP_API void pcap_set_optimizer_debug(int value);
+
+PCAP_API_DEF void
+pcap_set_optimizer_debug(int value)
+{
+ extern int pcap_optimizer_debug;
+
+ pcap_optimizer_debug = value;
+}
+#endif
diff --git a/contrib/libpcap/pcap/bluetooth.h b/contrib/libpcap/pcap/bluetooth.h
index 7cb0a8e8c05a..c5f378abbe78 100644
--- a/contrib/libpcap/pcap/bluetooth.h
+++ b/contrib/libpcap/pcap/bluetooth.h
@@ -11,8 +11,8 @@
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
- * 3. The name of the author may not be used to endorse or promote
- * products derived from this software without specific prior written
+ * 3. The name of the author may not be used to endorse or promote
+ * products derived from this software without specific prior written
* permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
@@ -30,9 +30,9 @@
* bluetooth data struct
* By Paolo Abeni <paolo.abeni@email.it>
*/
-
-#ifndef _PCAP_BLUETOOTH_STRUCTS_H__
-#define _PCAP_BLUETOOTH_STRUCTS_H__
+
+#ifndef lib_pcap_bluetooth_h
+#define lib_pcap_bluetooth_h
/*
* Header prepended libpcap to each bluetooth h4 frame,
diff --git a/contrib/libpcap/pcap/bpf.h b/contrib/libpcap/pcap/bpf.h
index ff88fd0f4fa7..78ad8905d02d 100644
--- a/contrib/libpcap/pcap/bpf.h
+++ b/contrib/libpcap/pcap/bpf.h
@@ -4,7 +4,7 @@
*
* This code is derived from the Stanford/CMU enet packet filter,
* (net/enet.c) distributed as part of 4.3BSD, and code contributed
- * to Berkeley by Steven McCanne and Van Jacobson both of Lawrence
+ * to Berkeley by Steven McCanne and Van Jacobson both of Lawrence
* Berkeley Laboratory.
*
* Redistribution and use in source and binary forms, with or without
@@ -59,7 +59,8 @@
* or Tru64 UNIX-style multiple-include protection (or, at least,
* Tru64 UNIX 5.x-style; I don't have earlier versions available to check),
* or AIX-style multiple-include protection (or, at least, AIX 5.x-style;
- * I don't have earlier versions available to check).
+ * I don't have earlier versions available to check), or QNX-style
+ * multiple-include protection (as per GitHub pull request #394).
*
* We do not check for BPF_MAJOR_VERSION, as that's defined by
* <linux/filter.h>, which is directly or indirectly included in some
@@ -68,9 +69,11 @@
*
* This also provides our own multiple-include protection.
*/
-#if !defined(_NET_BPF_H_) && !defined(_BPF_H_) && !defined(_H_BPF) && !defined(lib_pcap_bpf_h)
+#if !defined(_NET_BPF_H_) && !defined(_NET_BPF_H_INCLUDED) && !defined(_BPF_H_) && !defined(_H_BPF) && !defined(lib_pcap_bpf_h)
#define lib_pcap_bpf_h
+#include <pcap/export-defs.h>
+
#ifdef __cplusplus
extern "C" {
#endif
@@ -87,7 +90,7 @@ typedef u_int bpf_u_int32;
#endif
/*
- * Alignment macros. BPF_WORDALIGN rounds up to the next
+ * Alignment macros. BPF_WORDALIGN rounds up to the next
* even multiple of BPF_ALIGNMENT.
*
* Tcpdump's print-pflog.c uses this, so we define it here.
@@ -106,1232 +109,8 @@ struct bpf_program {
u_int bf_len;
struct bpf_insn *bf_insns;
};
-
-/*
- * Link-layer header type codes.
- *
- * Do *NOT* add new values to this list without asking
- * "tcpdump-workers@lists.tcpdump.org" for a value. Otherwise, you run
- * the risk of using a value that's already being used for some other
- * purpose, and of having tools that read libpcap-format captures not
- * being able to handle captures with your new DLT_ value, with no hope
- * that they will ever be changed to do so (as that would destroy their
- * ability to read captures using that value for that other purpose).
- *
- * See
- *
- * http://www.tcpdump.org/linktypes.html
- *
- * for detailed descriptions of some of these link-layer header types.
- */
-
-/*
- * These are the types that are the same on all platforms, and that
- * have been defined by <net/bpf.h> for ages.
- */
-#define DLT_NULL 0 /* BSD loopback encapsulation */
-#define DLT_EN10MB 1 /* Ethernet (10Mb) */
-#define DLT_EN3MB 2 /* Experimental Ethernet (3Mb) */
-#define DLT_AX25 3 /* Amateur Radio AX.25 */
-#define DLT_PRONET 4 /* Proteon ProNET Token Ring */
-#define DLT_CHAOS 5 /* Chaos */
-#define DLT_IEEE802 6 /* 802.5 Token Ring */
-#define DLT_ARCNET 7 /* ARCNET, with BSD-style header */
-#define DLT_SLIP 8 /* Serial Line IP */
-#define DLT_PPP 9 /* Point-to-point Protocol */
-#define DLT_FDDI 10 /* FDDI */
-
-/*
- * These are types that are different on some platforms, and that
- * have been defined by <net/bpf.h> for ages. We use #ifdefs to
- * detect the BSDs that define them differently from the traditional
- * libpcap <net/bpf.h>
- *
- * XXX - DLT_ATM_RFC1483 is 13 in BSD/OS, and DLT_RAW is 14 in BSD/OS,
- * but I don't know what the right #define is for BSD/OS.
- */
-#define DLT_ATM_RFC1483 11 /* LLC-encapsulated ATM */
-
-#ifdef __OpenBSD__
-#define DLT_RAW 14 /* raw IP */
-#else
-#define DLT_RAW 12 /* raw IP */
-#endif
-
-/*
- * Given that the only OS that currently generates BSD/OS SLIP or PPP
- * is, well, BSD/OS, arguably everybody should have chosen its values
- * for DLT_SLIP_BSDOS and DLT_PPP_BSDOS, which are 15 and 16, but they
- * didn't. So it goes.
- */
-#if defined(__NetBSD__) || defined(__FreeBSD__)
-#ifndef DLT_SLIP_BSDOS
-#define DLT_SLIP_BSDOS 13 /* BSD/OS Serial Line IP */
-#define DLT_PPP_BSDOS 14 /* BSD/OS Point-to-point Protocol */
-#endif
-#else
-#define DLT_SLIP_BSDOS 15 /* BSD/OS Serial Line IP */
-#define DLT_PPP_BSDOS 16 /* BSD/OS Point-to-point Protocol */
-#endif
-
-/*
- * 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 */
-
-/*
- * Apparently Redback uses this for its SmartEdge 400/800. I hope
- * nobody else decided to use it, too.
- */
-#define DLT_REDBACK_SMARTEDGE 32
-
-/*
- * These values are defined by NetBSD; other platforms should refrain from
- * using them for other purposes, so that NetBSD savefiles with link
- * types of 50 or 51 can be read as this type on all platforms.
- */
-#define DLT_PPP_SERIAL 50 /* PPP over serial with HDLC encapsulation */
-#define DLT_PPP_ETHER 51 /* PPP over Ethernet */
-
-/*
- * The Axent Raptor firewall - now the Symantec Enterprise Firewall - uses
- * a link-layer type of 99 for the tcpdump it supplies. The link-layer
- * header has 6 bytes of unknown data, something that appears to be an
- * Ethernet type, and 36 bytes that appear to be 0 in at least one capture
- * I've seen.
- */
-#define DLT_SYMANTEC_FIREWALL 99
-
-/*
- * Values between 100 and 103 are used in capture file headers as
- * link-layer header type LINKTYPE_ values corresponding to DLT_ types
- * that differ between platforms; don't use those values for new DLT_
- * new types.
- */
-
-/*
- * Values starting with 104 are used for newly-assigned link-layer
- * header type values; for those link-layer header types, the DLT_
- * value returned by pcap_datalink() and passed to pcap_open_dead(),
- * and the LINKTYPE_ value that appears in capture files, are the
- * same.
- *
- * DLT_MATCHING_MIN is the lowest such value; DLT_MATCHING_MAX is
- * the highest such value.
- */
-#define DLT_MATCHING_MIN 104
-
-/*
- * This value was defined by libpcap 0.5; platforms that have defined
- * it with a different value should define it here with that value -
- * a link type of 104 in a save file will be mapped to DLT_C_HDLC,
- * whatever value that happens to be, so programs will correctly
- * handle files with that link type regardless of the value of
- * DLT_C_HDLC.
- *
- * The name DLT_C_HDLC was used by BSD/OS; we use that name for source
- * compatibility with programs written for BSD/OS.
- *
- * libpcap 0.5 defined it as DLT_CHDLC; we define DLT_CHDLC as well,
- * for source compatibility with programs written for libpcap 0.5.
- */
-#define DLT_C_HDLC 104 /* Cisco HDLC */
-#define DLT_CHDLC DLT_C_HDLC
-
-#define DLT_IEEE802_11 105 /* IEEE 802.11 wireless */
-
-/*
- * 106 is reserved for Linux Classical IP over ATM; it's like DLT_RAW,
- * except when it isn't. (I.e., sometimes it's just raw IP, and
- * sometimes it isn't.) We currently handle it as DLT_LINUX_SLL,
- * so that we don't have to worry about the link-layer header.)
- */
-
-/*
- * Frame Relay; BSD/OS has a DLT_FR with a value of 11, but that collides
- * with other values.
- * DLT_FR and DLT_FRELAY packets start with the Q.922 Frame Relay header
- * (DLCI, etc.).
- */
-#define DLT_FRELAY 107
-
-/*
- * OpenBSD DLT_LOOP, for loopback devices; it's like DLT_NULL, except
- * that the AF_ type in the link-layer header is in network byte order.
- *
- * DLT_LOOP is 12 in OpenBSD, but that's DLT_RAW in other OSes, so
- * we don't use 12 for it in OSes other than OpenBSD.
- */
-#ifdef __OpenBSD__
-#define DLT_LOOP 12
-#else
-#define DLT_LOOP 108
-#endif
-
-/*
- * Encapsulated packets for IPsec; DLT_ENC is 13 in OpenBSD, but that's
- * DLT_SLIP_BSDOS in NetBSD, so we don't use 13 for it in OSes other
- * than OpenBSD.
- */
-#ifdef __OpenBSD__
-#define DLT_ENC 13
-#else
-#define DLT_ENC 109
-#endif
-
-/*
- * Values between 110 and 112 are reserved for use in capture file headers
- * as link-layer types corresponding to DLT_ types that might differ
- * between platforms; don't use those values for new DLT_ types
- * other than the corresponding DLT_ types.
- */
-
-/*
- * This is for Linux cooked sockets.
- */
-#define DLT_LINUX_SLL 113
-
-/*
- * Apple LocalTalk hardware.
- */
-#define DLT_LTALK 114
-
-/*
- * Acorn Econet.
- */
-#define DLT_ECONET 115
-
-/*
- * Reserved for use with OpenBSD ipfilter.
- */
-#define DLT_IPFILTER 116
-
-/*
- * OpenBSD DLT_PFLOG.
- */
-#define DLT_PFLOG 117
-
-/*
- * Registered for Cisco-internal use.
- */
-#define DLT_CISCO_IOS 118
-
-/*
- * For 802.11 cards using the Prism II chips, with a link-layer
- * header including Prism monitor mode information plus an 802.11
- * header.
- */
-#define DLT_PRISM_HEADER 119
-
-/*
- * Reserved for Aironet 802.11 cards, with an Aironet link-layer header
- * (see Doug Ambrisko's FreeBSD patches).
- */
-#define DLT_AIRONET_HEADER 120
-
-/*
- * 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.
- *
- * This is not for use with raw Fibre Channel, where the link-layer
- * header starts with a Fibre Channel frame header; it's for IP-over-FC,
- * where the link-layer header starts with an RFC 2625 Network_Header
- * field.
- */
-#define DLT_IP_OVER_FC 122
-
-/*
- * This is for Full Frontal ATM on Solaris with SunATM, with a
- * pseudo-header followed by an AALn PDU.
- *
- * There may be other forms of Full Frontal ATM on other OSes,
- * with different pseudo-headers.
- *
- * If ATM software returns a pseudo-header with VPI/VCI information
- * (and, ideally, packet type information, e.g. signalling, ILMI,
- * LANE, LLC-multiplexed traffic, etc.), it should not use
- * DLT_ATM_RFC1483, but should get a new DLT_ value, so tcpdump
- * and the like don't have to infer the presence or absence of a
- * pseudo-header and the form of the pseudo-header.
- */
-#define DLT_SUNATM 123 /* Solaris+SunATM */
-
-/*
- * Reserved as per request from Kent Dahlgren <kent@praesum.com>
- * for private use.
- */
-#define DLT_RIO 124 /* RapidIO */
-#define DLT_PCI_EXP 125 /* PCI Express */
-#define DLT_AURORA 126 /* Xilinx Aurora link layer */
-
-/*
- * Header for 802.11 plus a number of bits of link-layer information
- * including radio information, used by some recent BSD drivers as
- * well as the madwifi Atheros driver for Linux.
- */
-#define DLT_IEEE802_11_RADIO 127 /* 802.11 plus radiotap radio header */
-
-/*
- * Reserved for the TZSP encapsulation, as per request from
- * Chris Waters <chris.waters@networkchemistry.com>
- * TZSP is a generic encapsulation for any other link type,
- * which includes a means to include meta-information
- * with the packet, e.g. signal strength and channel
- * for 802.11 packets.
- */
-#define DLT_TZSP 128 /* Tazmen Sniffer Protocol */
-
-/*
- * BSD's ARCNET headers have the source host, destination host,
- * and type at the beginning of the packet; that's what's handed
- * up to userland via BPF.
- *
- * Linux's ARCNET headers, however, have a 2-byte offset field
- * between the host IDs and the type; that's what's handed up
- * to userland via PF_PACKET sockets.
- *
- * We therefore have to have separate DLT_ values for them.
- */
-#define DLT_ARCNET_LINUX 129 /* ARCNET */
-
-/*
- * Juniper-private data link types, as per request from
- * Hannes Gredler <hannes@juniper.net>. The DLT_s are used
- * for passing on chassis-internal metainformation such as
- * QOS profiles, etc..
- */
-#define DLT_JUNIPER_MLPPP 130
-#define DLT_JUNIPER_MLFR 131
-#define DLT_JUNIPER_ES 132
-#define DLT_JUNIPER_GGSN 133
-#define DLT_JUNIPER_MFR 134
-#define DLT_JUNIPER_ATM2 135
-#define DLT_JUNIPER_SERVICES 136
-#define DLT_JUNIPER_ATM1 137
-
-/*
- * Apple IP-over-IEEE 1394, as per a request from Dieter Siegmund
- * <dieter@apple.com>. The header that's presented is an Ethernet-like
- * header:
- *
- * #define FIREWIRE_EUI64_LEN 8
- * struct firewire_header {
- * u_char firewire_dhost[FIREWIRE_EUI64_LEN];
- * u_char firewire_shost[FIREWIRE_EUI64_LEN];
- * u_short firewire_type;
- * };
- *
- * with "firewire_type" being an Ethernet type value, rather than,
- * for example, raw GASP frames being handed up.
- */
-#define DLT_APPLE_IP_OVER_IEEE1394 138
-
-/*
- * Various SS7 encapsulations, as per a request from Jeff Morriss
- * <jeff.morriss[AT]ulticom.com> and subsequent discussions.
- */
-#define DLT_MTP2_WITH_PHDR 139 /* pseudo-header with various info, followed by MTP2 */
-#define DLT_MTP2 140 /* MTP2, without pseudo-header */
-#define DLT_MTP3 141 /* MTP3, without pseudo-header or MTP2 */
-#define DLT_SCCP 142 /* SCCP, without pseudo-header or MTP2 or MTP3 */
-
-/*
- * DOCSIS MAC frames.
- */
-#define DLT_DOCSIS 143
-
-/*
- * Linux-IrDA packets. Protocol defined at http://www.irda.org.
- * Those packets include IrLAP headers and above (IrLMP...), but
- * don't include Phy framing (SOF/EOF/CRC & byte stuffing), because Phy
- * framing can be handled by the hardware and depend on the bitrate.
- * This is exactly the format you would get capturing on a Linux-IrDA
- * interface (irdaX), but not on a raw serial port.
- * Note the capture is done in "Linux-cooked" mode, so each packet include
- * a fake packet header (struct sll_header). This is because IrDA packet
- * decoding is dependant on the direction of the packet (incomming or
- * outgoing).
- * When/if other platform implement IrDA capture, we may revisit the
- * issue and define a real DLT_IRDA...
- * Jean II
- */
-#define DLT_LINUX_IRDA 144
-
-/*
- * Reserved for IBM SP switch and IBM Next Federation switch.
- */
-#define DLT_IBM_SP 145
-#define DLT_IBM_SN 146
-
-/*
- * Reserved for private use. If you have some link-layer header type
- * that you want to use within your organization, with the capture files
- * using that link-layer header type not ever be sent outside your
- * organization, you can use these values.
- *
- * No libpcap release will use these for any purpose, nor will any
- * tcpdump release use them, either.
- *
- * Do *NOT* use these in capture files that you expect anybody not using
- * your private versions of capture-file-reading tools to read; in
- * particular, do *NOT* use them in products, otherwise you may find that
- * people won't be able to use tcpdump, or snort, or Ethereal, or... to
- * read capture files from your firewall/intrusion detection/traffic
- * monitoring/etc. appliance, or whatever product uses that DLT_ value,
- * and you may also find that the developers of those applications will
- * not accept patches to let them read those files.
- *
- * Also, do not use them if somebody might send you a capture using them
- * for *their* private type and tools using them for *your* private type
- * would have to read them.
- *
- * Instead, ask "tcpdump-workers@lists.tcpdump.org" for a new DLT_ value,
- * as per the comment above, and use the type you're given.
- */
-#define DLT_USER0 147
-#define DLT_USER1 148
-#define DLT_USER2 149
-#define DLT_USER3 150
-#define DLT_USER4 151
-#define DLT_USER5 152
-#define DLT_USER6 153
-#define DLT_USER7 154
-#define DLT_USER8 155
-#define DLT_USER9 156
-#define DLT_USER10 157
-#define DLT_USER11 158
-#define DLT_USER12 159
-#define DLT_USER13 160
-#define DLT_USER14 161
-#define DLT_USER15 162
-
-/*
- * For future use with 802.11 captures - defined by AbsoluteValue
- * Systems to store a number of bits of link-layer information
- * including radio information:
- *
- * http://www.shaftnet.org/~pizza/software/capturefrm.txt
- *
- * but it might be used by some non-AVS drivers now or in the
- * future.
- */
-#define DLT_IEEE802_11_RADIO_AVS 163 /* 802.11 plus AVS radio header */
-
-/*
- * Juniper-private data link type, as per request from
- * Hannes Gredler <hannes@juniper.net>. The DLT_s are used
- * for passing on chassis-internal metainformation such as
- * QOS profiles, etc..
- */
-#define DLT_JUNIPER_MONITOR 164
-
-/*
- * BACnet MS/TP frames.
- */
-#define DLT_BACNET_MS_TP 165
-
-/*
- * Another PPP variant as per request from Karsten Keil <kkeil@suse.de>.
- *
- * This is used in some OSes to allow a kernel socket filter to distinguish
- * between incoming and outgoing packets, on a socket intended to
- * supply pppd with outgoing packets so it can do dial-on-demand and
- * hangup-on-lack-of-demand; incoming packets are filtered out so they
- * don't cause pppd to hold the connection up (you don't want random
- * input packets such as port scans, packets from old lost connections,
- * etc. to force the connection to stay up).
- *
- * The first byte of the PPP header (0xff03) is modified to accomodate
- * the direction - 0x00 = IN, 0x01 = OUT.
- */
-#define DLT_PPP_PPPD 166
-
-/*
- * Names for backwards compatibility with older versions of some PPP
- * software; new software should use DLT_PPP_PPPD.
- */
-#define DLT_PPP_WITH_DIRECTION DLT_PPP_PPPD
-#define DLT_LINUX_PPP_WITHDIRECTION DLT_PPP_PPPD
-
-/*
- * Juniper-private data link type, as per request from
- * Hannes Gredler <hannes@juniper.net>. The DLT_s are used
- * for passing on chassis-internal metainformation such as
- * QOS profiles, cookies, etc..
- */
-#define DLT_JUNIPER_PPPOE 167
-#define DLT_JUNIPER_PPPOE_ATM 168
-
-#define DLT_GPRS_LLC 169 /* GPRS LLC */
-#define DLT_GPF_T 170 /* GPF-T (ITU-T G.7041/Y.1303) */
-#define DLT_GPF_F 171 /* GPF-F (ITU-T G.7041/Y.1303) */
-
-/*
- * Requested by Oolan Zimmer <oz@gcom.com> for use in Gcom's T1/E1 line
- * monitoring equipment.
- */
-#define DLT_GCOM_T1E1 172
-#define DLT_GCOM_SERIAL 173
-
-/*
- * Juniper-private data link type, as per request from
- * Hannes Gredler <hannes@juniper.net>. The DLT_ is used
- * for internal communication to Physical Interface Cards (PIC)
- */
-#define DLT_JUNIPER_PIC_PEER 174
-
-/*
- * Link types requested by Gregor Maier <gregor@endace.com> of Endace
- * Measurement Systems. They add an ERF header (see
- * http://www.endace.com/support/EndaceRecordFormat.pdf) in front of
- * the link-layer header.
- */
-#define DLT_ERF_ETH 175 /* Ethernet */
-#define DLT_ERF_POS 176 /* Packet-over-SONET */
-
-/*
- * Requested by Daniele Orlandi <daniele@orlandi.com> for raw LAPD
- * for vISDN (http://www.orlandi.com/visdn/). Its link-layer header
- * includes additional information before the LAPD header, so it's
- * not necessarily a generic LAPD header.
- */
-#define DLT_LINUX_LAPD 177
-
-/*
- * Juniper-private data link type, as per request from
- * Hannes Gredler <hannes@juniper.net>.
- * The DLT_ are used for prepending meta-information
- * like interface index, interface name
- * before standard Ethernet, PPP, Frelay & C-HDLC Frames
- */
-#define DLT_JUNIPER_ETHER 178
-#define DLT_JUNIPER_PPP 179
-#define DLT_JUNIPER_FRELAY 180
-#define DLT_JUNIPER_CHDLC 181
-
-/*
- * Multi Link Frame Relay (FRF.16)
- */
-#define DLT_MFR 182
-
-/*
- * Juniper-private data link type, as per request from
- * Hannes Gredler <hannes@juniper.net>.
- * The DLT_ is used for internal communication with a
- * voice Adapter Card (PIC)
- */
-#define DLT_JUNIPER_VP 183
-
-/*
- * Arinc 429 frames.
- * DLT_ requested by Gianluca Varenni <gianluca.varenni@cacetech.com>.
- * Every frame contains a 32bit A429 label.
- * More documentation on Arinc 429 can be found at
- * http://www.condoreng.com/support/downloads/tutorials/ARINCTutorial.pdf
- */
-#define DLT_A429 184
-
-/*
- * Arinc 653 Interpartition Communication messages.
- * DLT_ requested by Gianluca Varenni <gianluca.varenni@cacetech.com>.
- * Please refer to the A653-1 standard for more information.
- */
-#define DLT_A653_ICM 185
-
-/*
- * USB packets, beginning with a USB setup header; requested by
- * Paolo Abeni <paolo.abeni@email.it>.
- */
-#define DLT_USB 186
-
-/*
- * Bluetooth HCI UART transport layer (part H:4); requested by
- * Paolo Abeni.
- */
-#define DLT_BLUETOOTH_HCI_H4 187
-
-/*
- * IEEE 802.16 MAC Common Part Sublayer; requested by Maria Cruz
- * <cruz_petagay@bah.com>.
- */
-#define DLT_IEEE802_16_MAC_CPS 188
-
-/*
- * USB packets, beginning with a Linux USB header; requested by
- * Paolo Abeni <paolo.abeni@email.it>.
- */
-#define DLT_USB_LINUX 189
-
-/*
- * Controller Area Network (CAN) v. 2.0B packets.
- * DLT_ requested by Gianluca Varenni <gianluca.varenni@cacetech.com>.
- * Used to dump CAN packets coming from a CAN Vector board.
- * More documentation on the CAN v2.0B frames can be found at
- * http://www.can-cia.org/downloads/?269
- */
-#define DLT_CAN20B 190
-
-/*
- * IEEE 802.15.4, with address fields padded, as is done by Linux
- * drivers; requested by Juergen Schimmer.
- */
-#define DLT_IEEE802_15_4_LINUX 191
-
-/*
- * Per Packet Information encapsulated packets.
- * DLT_ requested by Gianluca Varenni <gianluca.varenni@cacetech.com>.
- */
-#define DLT_PPI 192
-
-/*
- * Header for 802.16 MAC Common Part Sublayer plus a radiotap radio header;
- * requested by Charles Clancy.
- */
-#define DLT_IEEE802_16_MAC_CPS_RADIO 193
-
-/*
- * Juniper-private data link type, as per request from
- * Hannes Gredler <hannes@juniper.net>.
- * The DLT_ is used for internal communication with a
- * integrated service module (ISM).
- */
-#define DLT_JUNIPER_ISM 194
-
-/*
- * IEEE 802.15.4, exactly as it appears in the spec (no padding, no
- * nothing); requested by Mikko Saarnivala <mikko.saarnivala@sensinode.com>.
- * For this one, we expect the FCS to be present at the end of the frame;
- * if the frame has no FCS, DLT_IEEE802_15_4_NOFCS should be used.
- */
-#define DLT_IEEE802_15_4 195
-
-/*
- * Various link-layer types, with a pseudo-header, for SITA
- * (http://www.sita.aero/); requested by Fulko Hew (fulko.hew@gmail.com).
- */
-#define DLT_SITA 196
-
-/*
- * Various link-layer types, with a pseudo-header, for Endace DAG cards;
- * encapsulates Endace ERF records. Requested by Stephen Donnelly
- * <stephen@endace.com>.
- */
-#define DLT_ERF 197
-
-/*
- * Special header prepended to Ethernet packets when capturing from a
- * u10 Networks board. Requested by Phil Mulholland
- * <phil@u10networks.com>.
- */
-#define DLT_RAIF1 198
-
-/*
- * IPMB packet for IPMI, beginning with the I2C slave address, followed
- * by the netFn and LUN, etc.. Requested by Chanthy Toeung
- * <chanthy.toeung@ca.kontron.com>.
- */
-#define DLT_IPMB 199
-
-/*
- * Juniper-private data link type, as per request from
- * Hannes Gredler <hannes@juniper.net>.
- * The DLT_ is used for capturing data on a secure tunnel interface.
- */
-#define DLT_JUNIPER_ST 200
-
-/*
- * Bluetooth HCI UART transport layer (part H:4), with pseudo-header
- * that includes direction information; requested by Paolo Abeni.
- */
-#define DLT_BLUETOOTH_HCI_H4_WITH_PHDR 201
-
-/*
- * AX.25 packet with a 1-byte KISS header; see
- *
- * http://www.ax25.net/kiss.htm
- *
- * as per Richard Stearn <richard@rns-stearn.demon.co.uk>.
- */
-#define DLT_AX25_KISS 202
-
-/*
- * LAPD packets from an ISDN channel, starting with the address field,
- * with no pseudo-header.
- * Requested by Varuna De Silva <varunax@gmail.com>.
- */
-#define DLT_LAPD 203
-
-/*
- * Variants of various link-layer headers, with a one-byte direction
- * pseudo-header prepended - zero means "received by this host",
- * non-zero (any non-zero value) means "sent by this host" - as per
- * Will Barker <w.barker@zen.co.uk>.
- */
-#define DLT_PPP_WITH_DIR 204 /* PPP - don't confuse with DLT_PPP_WITH_DIRECTION */
-#define DLT_C_HDLC_WITH_DIR 205 /* Cisco HDLC */
-#define DLT_FRELAY_WITH_DIR 206 /* Frame Relay */
-#define DLT_LAPB_WITH_DIR 207 /* LAPB */
-
-/*
- * 208 is reserved for an as-yet-unspecified proprietary link-layer
- * type, as requested by Will Barker.
- */
-
-/*
- * IPMB with a Linux-specific pseudo-header; as requested by Alexey Neyman
- * <avn@pigeonpoint.com>.
- */
-#define DLT_IPMB_LINUX 209
-
-/*
- * FlexRay automotive bus - http://www.flexray.com/ - as requested
- * by Hannes Kaelber <hannes.kaelber@x2e.de>.
- */
-#define DLT_FLEXRAY 210
-
-/*
- * Media Oriented Systems Transport (MOST) bus for multimedia
- * transport - http://www.mostcooperation.com/ - as requested
- * by Hannes Kaelber <hannes.kaelber@x2e.de>.
- */
-#define DLT_MOST 211
-
-/*
- * Local Interconnect Network (LIN) bus for vehicle networks -
- * http://www.lin-subbus.org/ - as requested by Hannes Kaelber
- * <hannes.kaelber@x2e.de>.
- */
-#define DLT_LIN 212
-
-/*
- * X2E-private data link type used for serial line capture,
- * as requested by Hannes Kaelber <hannes.kaelber@x2e.de>.
- */
-#define DLT_X2E_SERIAL 213
-
-/*
- * X2E-private data link type used for the Xoraya data logger
- * family, as requested by Hannes Kaelber <hannes.kaelber@x2e.de>.
- */
-#define DLT_X2E_XORAYA 214
-
-/*
- * IEEE 802.15.4, exactly as it appears in the spec (no padding, no
- * nothing), but with the PHY-level data for non-ASK PHYs (4 octets
- * of 0 as preamble, one octet of SFD, one octet of frame length+
- * reserved bit, and then the MAC-layer data, starting with the
- * frame control field).
- *
- * Requested by Max Filippov <jcmvbkbc@gmail.com>.
- */
-#define DLT_IEEE802_15_4_NONASK_PHY 215
-
-/*
- * David Gibson <david@gibson.dropbear.id.au> requested this for
- * captures from the Linux kernel /dev/input/eventN devices. This
- * is used to communicate keystrokes and mouse movements from the
- * Linux kernel to display systems, such as Xorg.
- */
-#define DLT_LINUX_EVDEV 216
-
-/*
- * GSM Um and Abis interfaces, preceded by a "gsmtap" header.
- *
- * Requested by Harald Welte <laforge@gnumonks.org>.
- */
-#define DLT_GSMTAP_UM 217
-#define DLT_GSMTAP_ABIS 218
-
-/*
- * MPLS, with an MPLS label as the link-layer header.
- * Requested by Michele Marchetto <michele@openbsd.org> on behalf
- * of OpenBSD.
- */
-#define DLT_MPLS 219
-
-/*
- * USB packets, beginning with a Linux USB header, with the USB header
- * padded to 64 bytes; required for memory-mapped access.
- */
-#define DLT_USB_LINUX_MMAPPED 220
-
-/*
- * DECT packets, with a pseudo-header; requested by
- * Matthias Wenzel <tcpdump@mazzoo.de>.
- */
-#define DLT_DECT 221
-
-/*
- * From: "Lidwa, Eric (GSFC-582.0)[SGT INC]" <eric.lidwa-1@nasa.gov>
- * Date: Mon, 11 May 2009 11:18:30 -0500
- *
- * DLT_AOS. We need it for AOS Space Data Link Protocol.
- * I have already written dissectors for but need an OK from
- * legal before I can submit a patch.
- *
- */
-#define DLT_AOS 222
-
-/*
- * Wireless HART (Highway Addressable Remote Transducer)
- * From the HART Communication Foundation
- * IES/PAS 62591
- *
- * Requested by Sam Roberts <vieuxtech@gmail.com>.
- */
-#define DLT_WIHART 223
-
-/*
- * Fibre Channel FC-2 frames, beginning with a Frame_Header.
- * Requested by Kahou Lei <kahou82@gmail.com>.
- */
-#define DLT_FC_2 224
-
-/*
- * Fibre Channel FC-2 frames, beginning with an encoding of the
- * SOF, and ending with an encoding of the EOF.
- *
- * The encodings represent the frame delimiters as 4-byte sequences
- * representing the corresponding ordered sets, with K28.5
- * represented as 0xBC, and the D symbols as the corresponding
- * byte values; for example, SOFi2, which is K28.5 - D21.5 - D1.2 - D21.2,
- * is represented as 0xBC 0xB5 0x55 0x55.
- *
- * Requested by Kahou Lei <kahou82@gmail.com>.
- */
-#define DLT_FC_2_WITH_FRAME_DELIMS 225
-
-/*
- * Solaris ipnet pseudo-header; requested by Darren Reed <Darren.Reed@Sun.COM>.
- *
- * The pseudo-header starts with a one-byte version number; for version 2,
- * the pseudo-header is:
- *
- * struct dl_ipnetinfo {
- * u_int8_t dli_version;
- * u_int8_t dli_family;
- * u_int16_t dli_htype;
- * u_int32_t dli_pktlen;
- * u_int32_t dli_ifindex;
- * u_int32_t dli_grifindex;
- * u_int32_t dli_zsrc;
- * u_int32_t dli_zdst;
- * };
- *
- * dli_version is 2 for the current version of the pseudo-header.
- *
- * dli_family is a Solaris address family value, so it's 2 for IPv4
- * and 26 for IPv6.
- *
- * dli_htype is a "hook type" - 0 for incoming packets, 1 for outgoing
- * packets, and 2 for packets arriving from another zone on the same
- * machine.
- *
- * dli_pktlen is the length of the packet data following the pseudo-header
- * (so the captured length minus dli_pktlen is the length of the
- * pseudo-header, assuming the entire pseudo-header was captured).
- *
- * dli_ifindex is the interface index of the interface on which the
- * packet arrived.
- *
- * dli_grifindex is the group interface index number (for IPMP interfaces).
- *
- * dli_zsrc is the zone identifier for the source of the packet.
- *
- * dli_zdst is the zone identifier for the destination of the packet.
- *
- * A zone number of 0 is the global zone; a zone number of 0xffffffff
- * means that the packet arrived from another host on the network, not
- * from another zone on the same machine.
- *
- * An IPv4 or IPv6 datagram follows the pseudo-header; dli_family indicates
- * which of those it is.
- */
-#define DLT_IPNET 226
-
-/*
- * CAN (Controller Area Network) frames, with a pseudo-header as supplied
- * by Linux SocketCAN. See Documentation/networking/can.txt in the Linux
- * source.
- *
- * Requested by Felix Obenhuber <felix@obenhuber.de>.
- */
-#define DLT_CAN_SOCKETCAN 227
-
-/*
- * Raw IPv4/IPv6; different from DLT_RAW in that the DLT_ value specifies
- * whether it's v4 or v6. Requested by Darren Reed <Darren.Reed@Sun.COM>.
- */
-#define DLT_IPV4 228
-#define DLT_IPV6 229
-
-/*
- * IEEE 802.15.4, exactly as it appears in the spec (no padding, no
- * nothing), and with no FCS at the end of the frame; requested by
- * Jon Smirl <jonsmirl@gmail.com>.
- */
-#define DLT_IEEE802_15_4_NOFCS 230
-
-/*
- * Raw D-Bus:
- *
- * http://www.freedesktop.org/wiki/Software/dbus
- *
- * messages:
- *
- * http://dbus.freedesktop.org/doc/dbus-specification.html#message-protocol-messages
- *
- * starting with the endianness flag, followed by the message type, etc.,
- * but without the authentication handshake before the message sequence:
- *
- * http://dbus.freedesktop.org/doc/dbus-specification.html#auth-protocol
- *
- * Requested by Martin Vidner <martin@vidner.net>.
- */
-#define DLT_DBUS 231
-
-/*
- * Juniper-private data link type, as per request from
- * Hannes Gredler <hannes@juniper.net>.
- */
-#define DLT_JUNIPER_VS 232
-#define DLT_JUNIPER_SRX_E2E 233
-#define DLT_JUNIPER_FIBRECHANNEL 234
-
-/*
- * DVB-CI (DVB Common Interface for communication between a PC Card
- * module and a DVB receiver). See
- *
- * http://www.kaiser.cx/pcap-dvbci.html
- *
- * for the specification.
- *
- * Requested by Martin Kaiser <martin@kaiser.cx>.
- */
-#define DLT_DVB_CI 235
-
-/*
- * Variant of 3GPP TS 27.010 multiplexing protocol (similar to, but
- * *not* the same as, 27.010). Requested by Hans-Christoph Schemmel
- * <hans-christoph.schemmel@cinterion.com>.
- */
-#define DLT_MUX27010 236
-
-/*
- * STANAG 5066 D_PDUs. Requested by M. Baris Demiray
- * <barisdemiray@gmail.com>.
- */
-#define DLT_STANAG_5066_D_PDU 237
-
-/*
- * Juniper-private data link type, as per request from
- * Hannes Gredler <hannes@juniper.net>.
- */
-#define DLT_JUNIPER_ATM_CEMIC 238
-
-/*
- * NetFilter LOG messages
- * (payload of netlink NFNL_SUBSYS_ULOG/NFULNL_MSG_PACKET packets)
- *
- * Requested by Jakub Zawadzki <darkjames-ws@darkjames.pl>
- */
-#define DLT_NFLOG 239
-
-/*
- * Hilscher Gesellschaft fuer Systemautomation mbH link-layer type
- * for Ethernet packets with a 4-byte pseudo-header and always
- * with the payload including the FCS, as supplied by their
- * netANALYZER hardware and software.
- *
- * Requested by Holger P. Frommer <HPfrommer@hilscher.com>
- */
-#define DLT_NETANALYZER 240
-
-/*
- * Hilscher Gesellschaft fuer Systemautomation mbH link-layer type
- * for Ethernet packets with a 4-byte pseudo-header and FCS and
- * with the Ethernet header preceded by 7 bytes of preamble and
- * 1 byte of SFD, as supplied by their netANALYZER hardware and
- * software.
- *
- * Requested by Holger P. Frommer <HPfrommer@hilscher.com>
- */
-#define DLT_NETANALYZER_TRANSPARENT 241
-
-/*
- * IP-over-InfiniBand, as specified by RFC 4391.
- *
- * Requested by Petr Sumbera <petr.sumbera@oracle.com>.
- */
-#define DLT_IPOIB 242
-
-/*
- * 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
-
-/*
- * DLT type for the netlink protocol (nlmon devices).
- */
-#define DLT_NETLINK 253
-
-/*
- * Bluetooth Linux Monitor headers for the BlueZ stack.
- */
-#define DLT_BLUETOOTH_LINUX_MONITOR 254
-
-/*
- * Bluetooth Basic Rate/Enhanced Data Rate baseband packets, as
- * captured by Ubertooth.
- */
-#define DLT_BLUETOOTH_BREDR_BB 255
-
-/*
- * Bluetooth Low Energy link layer packets, as captured by Ubertooth.
- */
-#define DLT_BLUETOOTH_LE_LL_WITH_PHDR 256
-
-/*
- * PROFIBUS data link layer.
- */
-#define DLT_PROFIBUS_DL 257
-
-/*
- * Apple's DLT_PKTAP headers.
- *
- * Sadly, the folks at Apple either had no clue that the DLT_USERn values
- * are for internal use within an organization and partners only, and
- * didn't know that the right way to get a link-layer header type is to
- * ask tcpdump.org for one, or knew and didn't care, so they just
- * used DLT_USER2, which causes problems for everything except for
- * their version of tcpdump.
- *
- * So I'll just give them one; hopefully this will show up in a
- * libpcap release in time for them to get this into 10.10 Big Sur
- * or whatever Mavericks' successor is called. LINKTYPE_PKTAP
- * will be 258 *even on OS X*; that is *intentional*, so that
- * PKTAP files look the same on *all* OSes (different OSes can have
- * different numerical values for a given DLT_, but *MUST NOT* have
- * different values for what goes in a file, as files can be moved
- * between OSes!).
- *
- * When capturing, on a system with a Darwin-based OS, on a device
- * that returns 149 (DLT_USER2 and Apple's DLT_PKTAP) with this
- * version of libpcap, the DLT_ value for the pcap_t will be DLT_PKTAP,
- * and that will continue to be DLT_USER2 on Darwin-based OSes. That way,
- * binary compatibility with Mavericks is preserved for programs using
- * this version of libpcap. This does mean that if you were using
- * DLT_USER2 for some capture device on OS X, you can't do so with
- * this version of libpcap, just as you can't with Apple's libpcap -
- * on OS X, they define DLT_PKTAP to be DLT_USER2, so programs won't
- * be able to distinguish between PKTAP and whatever you were using
- * DLT_USER2 for.
- *
- * If the program saves the capture to a file using this version of
- * libpcap's pcap_dump code, the LINKTYPE_ value in the file will be
- * LINKTYPE_PKTAP, which will be 258, even on Darwin-based OSes.
- * That way, the file will *not* be a DLT_USER2 file. That means
- * that the latest version of tcpdump, when built with this version
- * of libpcap, and sufficiently recent versions of Wireshark will
- * be able to read those files and interpret them correctly; however,
- * Apple's version of tcpdump in OS X 10.9 won't be able to handle
- * them. (Hopefully, Apple will pick up this version of libpcap,
- * and the corresponding version of tcpdump, so that tcpdump will
- * be able to handle the old LINKTYPE_USER2 captures *and* the new
- * LINKTYPE_PKTAP captures.)
- */
-#ifdef __APPLE__
-#define DLT_PKTAP DLT_USER2
-#else
-#define DLT_PKTAP 258
-#endif
-
-/*
- * Ethernet packets preceded by a header giving the last 6 octets
- * of the preamble specified by 802.3-2012 Clause 65, section
- * 65.1.3.2 "Transmit".
- */
-#define DLT_EPON 259
-
-/*
- * IPMI trace packets, as specified by Table 3-20 "Trace Data Block Format"
- * in the PICMG HPM.2 specification.
- */
-#define DLT_IPMI_HPM_2 260
-
-#define DLT_MATCHING_MAX 260 /* 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.
- */
-#define DLT_CLASS(x) ((x) & 0x03ff0000)
-
-/*
- * NetBSD-specific generic "raw" link type. The class value indicates
- * that this is the generic raw type, and the lower 16 bits are the
- * address family we're dealing with. Those values are NetBSD-specific;
- * do not assume that they correspond to AF_ values for your operating
- * system.
- */
-#define DLT_CLASS_NETBSD_RAWAF 0x02240000
-#define DLT_NETBSD_RAWAF(af) (DLT_CLASS_NETBSD_RAWAF | (af))
-#define DLT_NETBSD_RAWAF_AF(x) ((x) & 0x0000ffff)
-#define DLT_IS_NETBSD_RAWAF(x) (DLT_CLASS(x) == DLT_CLASS_NETBSD_RAWAF)
+#include <pcap/dlt.h>
/*
* The instruction encodings.
@@ -1464,17 +243,29 @@ struct bpf_insn {
};
/*
+ * Auxiliary data, for use when interpreting a filter intended for the
+ * Linux kernel when the kernel rejects the filter (requiring us to
+ * run it in userland). It contains VLAN tag information.
+ */
+struct bpf_aux_data {
+ u_short vlan_tag_present;
+ u_short vlan_tag;
+};
+
+/*
* Macros for insn array initializers.
*/
#define BPF_STMT(code, k) { (u_short)(code), 0, 0, k }
#define BPF_JUMP(code, k, jt, jf) { (u_short)(code), jt, jf, k }
#if __STDC__ || defined(__cplusplus)
-extern int bpf_validate(const struct bpf_insn *, int);
-extern u_int bpf_filter(const struct bpf_insn *, const u_char *, u_int, u_int);
+PCAP_API int bpf_validate(const struct bpf_insn *, int);
+PCAP_API u_int bpf_filter(const struct bpf_insn *, const u_char *, u_int, u_int);
+extern u_int bpf_filter_with_aux_data(const struct bpf_insn *, const u_char *, u_int, u_int, const struct bpf_aux_data *);
#else
-extern int bpf_validate();
-extern u_int bpf_filter();
+PCAP_API int bpf_validate();
+PCAP_API u_int bpf_filter();
+extern u_int bpf_filter_with_aux_data();
#endif
/*
diff --git a/contrib/libpcap/pcap/can_socketcan.h b/contrib/libpcap/pcap/can_socketcan.h
new file mode 100644
index 000000000000..68d2a131c8ae
--- /dev/null
+++ b/contrib/libpcap/pcap/can_socketcan.h
@@ -0,0 +1,54 @@
+/*-
+ * Copyright (c) 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1997
+ * The Regents of the University of California. All rights reserved.
+ *
+ * This code is derived from the Stanford/CMU enet packet filter,
+ * (net/enet.c) distributed as part of 4.3BSD, and code contributed
+ * to Berkeley by Steven McCanne and Van Jacobson both of Lawrence
+ * Berkeley Laboratory.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the University of
+ * California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#ifndef lib_pcap_can_socketcan_h
+#define lib_pcap_can_socketcan_h
+
+/*
+ * SocketCAN header, as per Documentation/networking/can.txt in the
+ * Linux source.
+ */
+typedef struct {
+ u_int32_t can_id;
+ u_int8_t payload_length;
+ u_int8_t pad;
+ u_int8_t reserved1;
+ u_int8_t reserved2;
+} pcap_can_socketcan_hdr;
+
+#endif
diff --git a/contrib/libpcap/pcap/dlt.h b/contrib/libpcap/pcap/dlt.h
new file mode 100644
index 000000000000..2d74713e8ab7
--- /dev/null
+++ b/contrib/libpcap/pcap/dlt.h
@@ -0,0 +1,1340 @@
+/*-
+ * Copyright (c) 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1997
+ * The Regents of the University of California. All rights reserved.
+ *
+ * This code is derived from the Stanford/CMU enet packet filter,
+ * (net/enet.c) distributed as part of 4.3BSD, and code contributed
+ * to Berkeley by Steven McCanne and Van Jacobson both of Lawrence
+ * Berkeley Laboratory.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the University of
+ * California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * @(#)bpf.h 7.1 (Berkeley) 5/7/91
+ */
+
+#ifndef lib_pcap_dlt_h
+#define lib_pcap_dlt_h
+
+/*
+ * Link-layer header type codes.
+ *
+ * Do *NOT* add new values to this list without asking
+ * "tcpdump-workers@lists.tcpdump.org" for a value. Otherwise, you run
+ * the risk of using a value that's already being used for some other
+ * purpose, and of having tools that read libpcap-format captures not
+ * being able to handle captures with your new DLT_ value, with no hope
+ * that they will ever be changed to do so (as that would destroy their
+ * ability to read captures using that value for that other purpose).
+ *
+ * See
+ *
+ * http://www.tcpdump.org/linktypes.html
+ *
+ * for detailed descriptions of some of these link-layer header types.
+ */
+
+/*
+ * These are the types that are the same on all platforms, and that
+ * have been defined by <net/bpf.h> for ages.
+ */
+#define DLT_NULL 0 /* BSD loopback encapsulation */
+#define DLT_EN10MB 1 /* Ethernet (10Mb) */
+#define DLT_EN3MB 2 /* Experimental Ethernet (3Mb) */
+#define DLT_AX25 3 /* Amateur Radio AX.25 */
+#define DLT_PRONET 4 /* Proteon ProNET Token Ring */
+#define DLT_CHAOS 5 /* Chaos */
+#define DLT_IEEE802 6 /* 802.5 Token Ring */
+#define DLT_ARCNET 7 /* ARCNET, with BSD-style header */
+#define DLT_SLIP 8 /* Serial Line IP */
+#define DLT_PPP 9 /* Point-to-point Protocol */
+#define DLT_FDDI 10 /* FDDI */
+
+/*
+ * These are types that are different on some platforms, and that
+ * have been defined by <net/bpf.h> for ages. We use #ifdefs to
+ * detect the BSDs that define them differently from the traditional
+ * libpcap <net/bpf.h>
+ *
+ * XXX - DLT_ATM_RFC1483 is 13 in BSD/OS, and DLT_RAW is 14 in BSD/OS,
+ * but I don't know what the right #define is for BSD/OS.
+ */
+#define DLT_ATM_RFC1483 11 /* LLC-encapsulated ATM */
+
+#ifdef __OpenBSD__
+#define DLT_RAW 14 /* raw IP */
+#else
+#define DLT_RAW 12 /* raw IP */
+#endif
+
+/*
+ * Given that the only OS that currently generates BSD/OS SLIP or PPP
+ * is, well, BSD/OS, arguably everybody should have chosen its values
+ * for DLT_SLIP_BSDOS and DLT_PPP_BSDOS, which are 15 and 16, but they
+ * didn't. So it goes.
+ */
+#if defined(__NetBSD__) || defined(__FreeBSD__)
+#ifndef DLT_SLIP_BSDOS
+#define DLT_SLIP_BSDOS 13 /* BSD/OS Serial Line IP */
+#define DLT_PPP_BSDOS 14 /* BSD/OS Point-to-point Protocol */
+#endif
+#else
+#define DLT_SLIP_BSDOS 15 /* BSD/OS Serial Line IP */
+#define DLT_PPP_BSDOS 16 /* BSD/OS Point-to-point Protocol */
+#endif
+
+/*
+ * 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 */
+
+/*
+ * Apparently Redback uses this for its SmartEdge 400/800. I hope
+ * nobody else decided to use it, too.
+ */
+#define DLT_REDBACK_SMARTEDGE 32
+
+/*
+ * These values are defined by NetBSD; other platforms should refrain from
+ * using them for other purposes, so that NetBSD savefiles with link
+ * types of 50 or 51 can be read as this type on all platforms.
+ */
+#define DLT_PPP_SERIAL 50 /* PPP over serial with HDLC encapsulation */
+#define DLT_PPP_ETHER 51 /* PPP over Ethernet */
+
+/*
+ * The Axent Raptor firewall - now the Symantec Enterprise Firewall - uses
+ * a link-layer type of 99 for the tcpdump it supplies. The link-layer
+ * header has 6 bytes of unknown data, something that appears to be an
+ * Ethernet type, and 36 bytes that appear to be 0 in at least one capture
+ * I've seen.
+ */
+#define DLT_SYMANTEC_FIREWALL 99
+
+/*
+ * Values between 100 and 103 are used in capture file headers as
+ * link-layer header type LINKTYPE_ values corresponding to DLT_ types
+ * that differ between platforms; don't use those values for new DLT_
+ * new types.
+ */
+
+/*
+ * Values starting with 104 are used for newly-assigned link-layer
+ * header type values; for those link-layer header types, the DLT_
+ * value returned by pcap_datalink() and passed to pcap_open_dead(),
+ * and the LINKTYPE_ value that appears in capture files, are the
+ * same.
+ *
+ * DLT_MATCHING_MIN is the lowest such value; DLT_MATCHING_MAX is
+ * the highest such value.
+ */
+#define DLT_MATCHING_MIN 104
+
+/*
+ * This value was defined by libpcap 0.5; platforms that have defined
+ * it with a different value should define it here with that value -
+ * a link type of 104 in a save file will be mapped to DLT_C_HDLC,
+ * whatever value that happens to be, so programs will correctly
+ * handle files with that link type regardless of the value of
+ * DLT_C_HDLC.
+ *
+ * The name DLT_C_HDLC was used by BSD/OS; we use that name for source
+ * compatibility with programs written for BSD/OS.
+ *
+ * libpcap 0.5 defined it as DLT_CHDLC; we define DLT_CHDLC as well,
+ * for source compatibility with programs written for libpcap 0.5.
+ */
+#define DLT_C_HDLC 104 /* Cisco HDLC */
+#define DLT_CHDLC DLT_C_HDLC
+
+#define DLT_IEEE802_11 105 /* IEEE 802.11 wireless */
+
+/*
+ * 106 is reserved for Linux Classical IP over ATM; it's like DLT_RAW,
+ * except when it isn't. (I.e., sometimes it's just raw IP, and
+ * sometimes it isn't.) We currently handle it as DLT_LINUX_SLL,
+ * so that we don't have to worry about the link-layer header.)
+ */
+
+/*
+ * Frame Relay; BSD/OS has a DLT_FR with a value of 11, but that collides
+ * with other values.
+ * DLT_FR and DLT_FRELAY packets start with the Q.922 Frame Relay header
+ * (DLCI, etc.).
+ */
+#define DLT_FRELAY 107
+
+/*
+ * OpenBSD DLT_LOOP, for loopback devices; it's like DLT_NULL, except
+ * that the AF_ type in the link-layer header is in network byte order.
+ *
+ * DLT_LOOP is 12 in OpenBSD, but that's DLT_RAW in other OSes, so
+ * we don't use 12 for it in OSes other than OpenBSD.
+ */
+#ifdef __OpenBSD__
+#define DLT_LOOP 12
+#else
+#define DLT_LOOP 108
+#endif
+
+/*
+ * Encapsulated packets for IPsec; DLT_ENC is 13 in OpenBSD, but that's
+ * DLT_SLIP_BSDOS in NetBSD, so we don't use 13 for it in OSes other
+ * than OpenBSD.
+ */
+#ifdef __OpenBSD__
+#define DLT_ENC 13
+#else
+#define DLT_ENC 109
+#endif
+
+/*
+ * Values between 110 and 112 are reserved for use in capture file headers
+ * as link-layer types corresponding to DLT_ types that might differ
+ * between platforms; don't use those values for new DLT_ types
+ * other than the corresponding DLT_ types.
+ */
+
+/*
+ * This is for Linux cooked sockets.
+ */
+#define DLT_LINUX_SLL 113
+
+/*
+ * Apple LocalTalk hardware.
+ */
+#define DLT_LTALK 114
+
+/*
+ * Acorn Econet.
+ */
+#define DLT_ECONET 115
+
+/*
+ * Reserved for use with OpenBSD ipfilter.
+ */
+#define DLT_IPFILTER 116
+
+/*
+ * OpenBSD DLT_PFLOG.
+ */
+#define DLT_PFLOG 117
+
+/*
+ * Registered for Cisco-internal use.
+ */
+#define DLT_CISCO_IOS 118
+
+/*
+ * For 802.11 cards using the Prism II chips, with a link-layer
+ * header including Prism monitor mode information plus an 802.11
+ * header.
+ */
+#define DLT_PRISM_HEADER 119
+
+/*
+ * Reserved for Aironet 802.11 cards, with an Aironet link-layer header
+ * (see Doug Ambrisko's FreeBSD patches).
+ */
+#define DLT_AIRONET_HEADER 120
+
+/*
+ * Sigh.
+ *
+ * 121 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. In current versions, its libpcap
+ * does DLT_ <-> LINKTYPE_ mapping, mapping DLT_PFSYNC to a
+ * LINKTYPE_PFSYNC value of 246, so it should write out DLT_PFSYNC
+ * dump files with 246 as the link-layer header type. (Earlier
+ * versions might not have done mapping, in which case they would
+ * have written them out with a link-layer header type of 121.)
+ *
+ * OpenBSD, from which pf came, however, uses 18 for DLT_PFSYNC;
+ * its libpcap does no DLT_ <-> LINKTYPE_ mapping, so it would
+ * write out DLT_PFSYNC dump files with use 18 as the link-layer
+ * header type.
+ *
+ * NetBSD, DragonFly BSD, and Darwin also use 18 for DLT_PFSYNC; in
+ * current versions, their libpcaps do DLT_ <-> LINKTYPE_ mapping,
+ * mapping DLT_PFSYNC to a LINKTYPE_PFSYNC value of 246, so they
+ * should write out DLT_PFSYNC dump files with 246 as the link-layer
+ * header type. (Earlier versions might not have done mapping,
+ * in which case they'd work the same way OpenBSD does, writing
+ * them out with a link-layer header type of 18.)
+ *
+ * We'll define DLT_PFSYNC as:
+ *
+ * 18 on NetBSD, OpenBSD, DragonFly BSD, and Darwin;
+ *
+ * 121 on FreeBSD;
+ *
+ * 246 everywhere else.
+ *
+ * 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 246 on *all* platforms, so that
+ * savefiles written using *this* code won't use 18 or 121 for PFSYNC,
+ * they'll all use 246.
+ *
+ * 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, as pcap_datalink() will give 121 for both of them. Code
+ * that doesn't, such as the code in Wireshark, will be able to
+ * distinguish between them.
+ *
+ * FreeBSD's libpcap won't map a link-layer header type of 18 - i.e.,
+ * DLT_PFSYNC files from OpenBSD and possibly older versions of NetBSD,
+ * DragonFly BSD, and OS X - to DLT_PFSYNC, so code built with FreeBSD's
+ * libpcap won't treat those files as DLT_PFSYNC files.
+ *
+ * Other libpcaps won't map a link-layer header type of 121 to DLT_PFSYNC;
+ * this means they can read DLT_HHDLC files, if any exist, but won't
+ * treat pcap files written by any older versions of FreeBSD libpcap that
+ * didn't map to 246 as DLT_PFSYNC files.
+ */
+#ifdef __FreeBSD__
+#define DLT_PFSYNC 121
+#else
+#define DLT_HHDLC 121
+#endif
+
+/*
+ * This is for RFC 2625 IP-over-Fibre Channel.
+ *
+ * This is not for use with raw Fibre Channel, where the link-layer
+ * header starts with a Fibre Channel frame header; it's for IP-over-FC,
+ * where the link-layer header starts with an RFC 2625 Network_Header
+ * field.
+ */
+#define DLT_IP_OVER_FC 122
+
+/*
+ * This is for Full Frontal ATM on Solaris with SunATM, with a
+ * pseudo-header followed by an AALn PDU.
+ *
+ * There may be other forms of Full Frontal ATM on other OSes,
+ * with different pseudo-headers.
+ *
+ * If ATM software returns a pseudo-header with VPI/VCI information
+ * (and, ideally, packet type information, e.g. signalling, ILMI,
+ * LANE, LLC-multiplexed traffic, etc.), it should not use
+ * DLT_ATM_RFC1483, but should get a new DLT_ value, so tcpdump
+ * and the like don't have to infer the presence or absence of a
+ * pseudo-header and the form of the pseudo-header.
+ */
+#define DLT_SUNATM 123 /* Solaris+SunATM */
+
+/*
+ * Reserved as per request from Kent Dahlgren <kent@praesum.com>
+ * for private use.
+ */
+#define DLT_RIO 124 /* RapidIO */
+#define DLT_PCI_EXP 125 /* PCI Express */
+#define DLT_AURORA 126 /* Xilinx Aurora link layer */
+
+/*
+ * Header for 802.11 plus a number of bits of link-layer information
+ * including radio information, used by some recent BSD drivers as
+ * well as the madwifi Atheros driver for Linux.
+ */
+#define DLT_IEEE802_11_RADIO 127 /* 802.11 plus radiotap radio header */
+
+/*
+ * Reserved for the TZSP encapsulation, as per request from
+ * Chris Waters <chris.waters@networkchemistry.com>
+ * TZSP is a generic encapsulation for any other link type,
+ * which includes a means to include meta-information
+ * with the packet, e.g. signal strength and channel
+ * for 802.11 packets.
+ */
+#define DLT_TZSP 128 /* Tazmen Sniffer Protocol */
+
+/*
+ * BSD's ARCNET headers have the source host, destination host,
+ * and type at the beginning of the packet; that's what's handed
+ * up to userland via BPF.
+ *
+ * Linux's ARCNET headers, however, have a 2-byte offset field
+ * between the host IDs and the type; that's what's handed up
+ * to userland via PF_PACKET sockets.
+ *
+ * We therefore have to have separate DLT_ values for them.
+ */
+#define DLT_ARCNET_LINUX 129 /* ARCNET */
+
+/*
+ * Juniper-private data link types, as per request from
+ * Hannes Gredler <hannes@juniper.net>. The DLT_s are used
+ * for passing on chassis-internal metainformation such as
+ * QOS profiles, etc..
+ */
+#define DLT_JUNIPER_MLPPP 130
+#define DLT_JUNIPER_MLFR 131
+#define DLT_JUNIPER_ES 132
+#define DLT_JUNIPER_GGSN 133
+#define DLT_JUNIPER_MFR 134
+#define DLT_JUNIPER_ATM2 135
+#define DLT_JUNIPER_SERVICES 136
+#define DLT_JUNIPER_ATM1 137
+
+/*
+ * Apple IP-over-IEEE 1394, as per a request from Dieter Siegmund
+ * <dieter@apple.com>. The header that's presented is an Ethernet-like
+ * header:
+ *
+ * #define FIREWIRE_EUI64_LEN 8
+ * struct firewire_header {
+ * u_char firewire_dhost[FIREWIRE_EUI64_LEN];
+ * u_char firewire_shost[FIREWIRE_EUI64_LEN];
+ * u_short firewire_type;
+ * };
+ *
+ * with "firewire_type" being an Ethernet type value, rather than,
+ * for example, raw GASP frames being handed up.
+ */
+#define DLT_APPLE_IP_OVER_IEEE1394 138
+
+/*
+ * Various SS7 encapsulations, as per a request from Jeff Morriss
+ * <jeff.morriss[AT]ulticom.com> and subsequent discussions.
+ */
+#define DLT_MTP2_WITH_PHDR 139 /* pseudo-header with various info, followed by MTP2 */
+#define DLT_MTP2 140 /* MTP2, without pseudo-header */
+#define DLT_MTP3 141 /* MTP3, without pseudo-header or MTP2 */
+#define DLT_SCCP 142 /* SCCP, without pseudo-header or MTP2 or MTP3 */
+
+/*
+ * DOCSIS MAC frames.
+ */
+#define DLT_DOCSIS 143
+
+/*
+ * Linux-IrDA packets. Protocol defined at http://www.irda.org.
+ * Those packets include IrLAP headers and above (IrLMP...), but
+ * don't include Phy framing (SOF/EOF/CRC & byte stuffing), because Phy
+ * framing can be handled by the hardware and depend on the bitrate.
+ * This is exactly the format you would get capturing on a Linux-IrDA
+ * interface (irdaX), but not on a raw serial port.
+ * Note the capture is done in "Linux-cooked" mode, so each packet include
+ * a fake packet header (struct sll_header). This is because IrDA packet
+ * decoding is dependant on the direction of the packet (incomming or
+ * outgoing).
+ * When/if other platform implement IrDA capture, we may revisit the
+ * issue and define a real DLT_IRDA...
+ * Jean II
+ */
+#define DLT_LINUX_IRDA 144
+
+/*
+ * Reserved for IBM SP switch and IBM Next Federation switch.
+ */
+#define DLT_IBM_SP 145
+#define DLT_IBM_SN 146
+
+/*
+ * Reserved for private use. If you have some link-layer header type
+ * that you want to use within your organization, with the capture files
+ * using that link-layer header type not ever be sent outside your
+ * organization, you can use these values.
+ *
+ * No libpcap release will use these for any purpose, nor will any
+ * tcpdump release use them, either.
+ *
+ * Do *NOT* use these in capture files that you expect anybody not using
+ * your private versions of capture-file-reading tools to read; in
+ * particular, do *NOT* use them in products, otherwise you may find that
+ * people won't be able to use tcpdump, or snort, or Ethereal, or... to
+ * read capture files from your firewall/intrusion detection/traffic
+ * monitoring/etc. appliance, or whatever product uses that DLT_ value,
+ * and you may also find that the developers of those applications will
+ * not accept patches to let them read those files.
+ *
+ * Also, do not use them if somebody might send you a capture using them
+ * for *their* private type and tools using them for *your* private type
+ * would have to read them.
+ *
+ * Instead, ask "tcpdump-workers@lists.tcpdump.org" for a new DLT_ value,
+ * as per the comment above, and use the type you're given.
+ */
+#define DLT_USER0 147
+#define DLT_USER1 148
+#define DLT_USER2 149
+#define DLT_USER3 150
+#define DLT_USER4 151
+#define DLT_USER5 152
+#define DLT_USER6 153
+#define DLT_USER7 154
+#define DLT_USER8 155
+#define DLT_USER9 156
+#define DLT_USER10 157
+#define DLT_USER11 158
+#define DLT_USER12 159
+#define DLT_USER13 160
+#define DLT_USER14 161
+#define DLT_USER15 162
+
+/*
+ * For future use with 802.11 captures - defined by AbsoluteValue
+ * Systems to store a number of bits of link-layer information
+ * including radio information:
+ *
+ * http://www.shaftnet.org/~pizza/software/capturefrm.txt
+ *
+ * but it might be used by some non-AVS drivers now or in the
+ * future.
+ */
+#define DLT_IEEE802_11_RADIO_AVS 163 /* 802.11 plus AVS radio header */
+
+/*
+ * Juniper-private data link type, as per request from
+ * Hannes Gredler <hannes@juniper.net>. The DLT_s are used
+ * for passing on chassis-internal metainformation such as
+ * QOS profiles, etc..
+ */
+#define DLT_JUNIPER_MONITOR 164
+
+/*
+ * BACnet MS/TP frames.
+ */
+#define DLT_BACNET_MS_TP 165
+
+/*
+ * Another PPP variant as per request from Karsten Keil <kkeil@suse.de>.
+ *
+ * This is used in some OSes to allow a kernel socket filter to distinguish
+ * between incoming and outgoing packets, on a socket intended to
+ * supply pppd with outgoing packets so it can do dial-on-demand and
+ * hangup-on-lack-of-demand; incoming packets are filtered out so they
+ * don't cause pppd to hold the connection up (you don't want random
+ * input packets such as port scans, packets from old lost connections,
+ * etc. to force the connection to stay up).
+ *
+ * The first byte of the PPP header (0xff03) is modified to accomodate
+ * the direction - 0x00 = IN, 0x01 = OUT.
+ */
+#define DLT_PPP_PPPD 166
+
+/*
+ * Names for backwards compatibility with older versions of some PPP
+ * software; new software should use DLT_PPP_PPPD.
+ */
+#define DLT_PPP_WITH_DIRECTION DLT_PPP_PPPD
+#define DLT_LINUX_PPP_WITHDIRECTION DLT_PPP_PPPD
+
+/*
+ * Juniper-private data link type, as per request from
+ * Hannes Gredler <hannes@juniper.net>. The DLT_s are used
+ * for passing on chassis-internal metainformation such as
+ * QOS profiles, cookies, etc..
+ */
+#define DLT_JUNIPER_PPPOE 167
+#define DLT_JUNIPER_PPPOE_ATM 168
+
+#define DLT_GPRS_LLC 169 /* GPRS LLC */
+#define DLT_GPF_T 170 /* GPF-T (ITU-T G.7041/Y.1303) */
+#define DLT_GPF_F 171 /* GPF-F (ITU-T G.7041/Y.1303) */
+
+/*
+ * Requested by Oolan Zimmer <oz@gcom.com> for use in Gcom's T1/E1 line
+ * monitoring equipment.
+ */
+#define DLT_GCOM_T1E1 172
+#define DLT_GCOM_SERIAL 173
+
+/*
+ * Juniper-private data link type, as per request from
+ * Hannes Gredler <hannes@juniper.net>. The DLT_ is used
+ * for internal communication to Physical Interface Cards (PIC)
+ */
+#define DLT_JUNIPER_PIC_PEER 174
+
+/*
+ * Link types requested by Gregor Maier <gregor@endace.com> of Endace
+ * Measurement Systems. They add an ERF header (see
+ * http://www.endace.com/support/EndaceRecordFormat.pdf) in front of
+ * the link-layer header.
+ */
+#define DLT_ERF_ETH 175 /* Ethernet */
+#define DLT_ERF_POS 176 /* Packet-over-SONET */
+
+/*
+ * Requested by Daniele Orlandi <daniele@orlandi.com> for raw LAPD
+ * for vISDN (http://www.orlandi.com/visdn/). Its link-layer header
+ * includes additional information before the LAPD header, so it's
+ * not necessarily a generic LAPD header.
+ */
+#define DLT_LINUX_LAPD 177
+
+/*
+ * Juniper-private data link type, as per request from
+ * Hannes Gredler <hannes@juniper.net>.
+ * The DLT_ are used for prepending meta-information
+ * like interface index, interface name
+ * before standard Ethernet, PPP, Frelay & C-HDLC Frames
+ */
+#define DLT_JUNIPER_ETHER 178
+#define DLT_JUNIPER_PPP 179
+#define DLT_JUNIPER_FRELAY 180
+#define DLT_JUNIPER_CHDLC 181
+
+/*
+ * Multi Link Frame Relay (FRF.16)
+ */
+#define DLT_MFR 182
+
+/*
+ * Juniper-private data link type, as per request from
+ * Hannes Gredler <hannes@juniper.net>.
+ * The DLT_ is used for internal communication with a
+ * voice Adapter Card (PIC)
+ */
+#define DLT_JUNIPER_VP 183
+
+/*
+ * Arinc 429 frames.
+ * DLT_ requested by Gianluca Varenni <gianluca.varenni@cacetech.com>.
+ * Every frame contains a 32bit A429 label.
+ * More documentation on Arinc 429 can be found at
+ * http://www.condoreng.com/support/downloads/tutorials/ARINCTutorial.pdf
+ */
+#define DLT_A429 184
+
+/*
+ * Arinc 653 Interpartition Communication messages.
+ * DLT_ requested by Gianluca Varenni <gianluca.varenni@cacetech.com>.
+ * Please refer to the A653-1 standard for more information.
+ */
+#define DLT_A653_ICM 185
+
+/*
+ * This used to be "USB packets, beginning with a USB setup header;
+ * requested by Paolo Abeni <paolo.abeni@email.it>."
+ *
+ * However, that header didn't work all that well - it left out some
+ * useful information - and was abandoned in favor of the DLT_USB_LINUX
+ * header.
+ *
+ * This is now used by FreeBSD for its BPF taps for USB; that has its
+ * own headers. So it is written, so it is done.
+ *
+ * For source-code compatibility, we also define DLT_USB to have this
+ * value. We do it numerically so that, if code that includes this
+ * file (directly or indirectly) also includes an OS header that also
+ * defines DLT_USB as 186, we don't get a redefinition warning.
+ * (NetBSD 7 does that.)
+ */
+#define DLT_USB_FREEBSD 186
+#define DLT_USB 186
+
+/*
+ * Bluetooth HCI UART transport layer (part H:4); requested by
+ * Paolo Abeni.
+ */
+#define DLT_BLUETOOTH_HCI_H4 187
+
+/*
+ * IEEE 802.16 MAC Common Part Sublayer; requested by Maria Cruz
+ * <cruz_petagay@bah.com>.
+ */
+#define DLT_IEEE802_16_MAC_CPS 188
+
+/*
+ * USB packets, beginning with a Linux USB header; requested by
+ * Paolo Abeni <paolo.abeni@email.it>.
+ */
+#define DLT_USB_LINUX 189
+
+/*
+ * Controller Area Network (CAN) v. 2.0B packets.
+ * DLT_ requested by Gianluca Varenni <gianluca.varenni@cacetech.com>.
+ * Used to dump CAN packets coming from a CAN Vector board.
+ * More documentation on the CAN v2.0B frames can be found at
+ * http://www.can-cia.org/downloads/?269
+ */
+#define DLT_CAN20B 190
+
+/*
+ * IEEE 802.15.4, with address fields padded, as is done by Linux
+ * drivers; requested by Juergen Schimmer.
+ */
+#define DLT_IEEE802_15_4_LINUX 191
+
+/*
+ * Per Packet Information encapsulated packets.
+ * DLT_ requested by Gianluca Varenni <gianluca.varenni@cacetech.com>.
+ */
+#define DLT_PPI 192
+
+/*
+ * Header for 802.16 MAC Common Part Sublayer plus a radiotap radio header;
+ * requested by Charles Clancy.
+ */
+#define DLT_IEEE802_16_MAC_CPS_RADIO 193
+
+/*
+ * Juniper-private data link type, as per request from
+ * Hannes Gredler <hannes@juniper.net>.
+ * The DLT_ is used for internal communication with a
+ * integrated service module (ISM).
+ */
+#define DLT_JUNIPER_ISM 194
+
+/*
+ * IEEE 802.15.4, exactly as it appears in the spec (no padding, no
+ * nothing); requested by Mikko Saarnivala <mikko.saarnivala@sensinode.com>.
+ * For this one, we expect the FCS to be present at the end of the frame;
+ * if the frame has no FCS, DLT_IEEE802_15_4_NOFCS should be used.
+ */
+#define DLT_IEEE802_15_4 195
+
+/*
+ * Various link-layer types, with a pseudo-header, for SITA
+ * (http://www.sita.aero/); requested by Fulko Hew (fulko.hew@gmail.com).
+ */
+#define DLT_SITA 196
+
+/*
+ * Various link-layer types, with a pseudo-header, for Endace DAG cards;
+ * encapsulates Endace ERF records. Requested by Stephen Donnelly
+ * <stephen@endace.com>.
+ */
+#define DLT_ERF 197
+
+/*
+ * Special header prepended to Ethernet packets when capturing from a
+ * u10 Networks board. Requested by Phil Mulholland
+ * <phil@u10networks.com>.
+ */
+#define DLT_RAIF1 198
+
+/*
+ * IPMB packet for IPMI, beginning with the I2C slave address, followed
+ * by the netFn and LUN, etc.. Requested by Chanthy Toeung
+ * <chanthy.toeung@ca.kontron.com>.
+ */
+#define DLT_IPMB 199
+
+/*
+ * Juniper-private data link type, as per request from
+ * Hannes Gredler <hannes@juniper.net>.
+ * The DLT_ is used for capturing data on a secure tunnel interface.
+ */
+#define DLT_JUNIPER_ST 200
+
+/*
+ * Bluetooth HCI UART transport layer (part H:4), with pseudo-header
+ * that includes direction information; requested by Paolo Abeni.
+ */
+#define DLT_BLUETOOTH_HCI_H4_WITH_PHDR 201
+
+/*
+ * AX.25 packet with a 1-byte KISS header; see
+ *
+ * http://www.ax25.net/kiss.htm
+ *
+ * as per Richard Stearn <richard@rns-stearn.demon.co.uk>.
+ */
+#define DLT_AX25_KISS 202
+
+/*
+ * LAPD packets from an ISDN channel, starting with the address field,
+ * with no pseudo-header.
+ * Requested by Varuna De Silva <varunax@gmail.com>.
+ */
+#define DLT_LAPD 203
+
+/*
+ * Variants of various link-layer headers, with a one-byte direction
+ * pseudo-header prepended - zero means "received by this host",
+ * non-zero (any non-zero value) means "sent by this host" - as per
+ * Will Barker <w.barker@zen.co.uk>.
+ */
+#define DLT_PPP_WITH_DIR 204 /* PPP - don't confuse with DLT_PPP_WITH_DIRECTION */
+#define DLT_C_HDLC_WITH_DIR 205 /* Cisco HDLC */
+#define DLT_FRELAY_WITH_DIR 206 /* Frame Relay */
+#define DLT_LAPB_WITH_DIR 207 /* LAPB */
+
+/*
+ * 208 is reserved for an as-yet-unspecified proprietary link-layer
+ * type, as requested by Will Barker.
+ */
+
+/*
+ * IPMB with a Linux-specific pseudo-header; as requested by Alexey Neyman
+ * <avn@pigeonpoint.com>.
+ */
+#define DLT_IPMB_LINUX 209
+
+/*
+ * FlexRay automotive bus - http://www.flexray.com/ - as requested
+ * by Hannes Kaelber <hannes.kaelber@x2e.de>.
+ */
+#define DLT_FLEXRAY 210
+
+/*
+ * Media Oriented Systems Transport (MOST) bus for multimedia
+ * transport - http://www.mostcooperation.com/ - as requested
+ * by Hannes Kaelber <hannes.kaelber@x2e.de>.
+ */
+#define DLT_MOST 211
+
+/*
+ * Local Interconnect Network (LIN) bus for vehicle networks -
+ * http://www.lin-subbus.org/ - as requested by Hannes Kaelber
+ * <hannes.kaelber@x2e.de>.
+ */
+#define DLT_LIN 212
+
+/*
+ * X2E-private data link type used for serial line capture,
+ * as requested by Hannes Kaelber <hannes.kaelber@x2e.de>.
+ */
+#define DLT_X2E_SERIAL 213
+
+/*
+ * X2E-private data link type used for the Xoraya data logger
+ * family, as requested by Hannes Kaelber <hannes.kaelber@x2e.de>.
+ */
+#define DLT_X2E_XORAYA 214
+
+/*
+ * IEEE 802.15.4, exactly as it appears in the spec (no padding, no
+ * nothing), but with the PHY-level data for non-ASK PHYs (4 octets
+ * of 0 as preamble, one octet of SFD, one octet of frame length+
+ * reserved bit, and then the MAC-layer data, starting with the
+ * frame control field).
+ *
+ * Requested by Max Filippov <jcmvbkbc@gmail.com>.
+ */
+#define DLT_IEEE802_15_4_NONASK_PHY 215
+
+/*
+ * David Gibson <david@gibson.dropbear.id.au> requested this for
+ * captures from the Linux kernel /dev/input/eventN devices. This
+ * is used to communicate keystrokes and mouse movements from the
+ * Linux kernel to display systems, such as Xorg.
+ */
+#define DLT_LINUX_EVDEV 216
+
+/*
+ * GSM Um and Abis interfaces, preceded by a "gsmtap" header.
+ *
+ * Requested by Harald Welte <laforge@gnumonks.org>.
+ */
+#define DLT_GSMTAP_UM 217
+#define DLT_GSMTAP_ABIS 218
+
+/*
+ * MPLS, with an MPLS label as the link-layer header.
+ * Requested by Michele Marchetto <michele@openbsd.org> on behalf
+ * of OpenBSD.
+ */
+#define DLT_MPLS 219
+
+/*
+ * USB packets, beginning with a Linux USB header, with the USB header
+ * padded to 64 bytes; required for memory-mapped access.
+ */
+#define DLT_USB_LINUX_MMAPPED 220
+
+/*
+ * DECT packets, with a pseudo-header; requested by
+ * Matthias Wenzel <tcpdump@mazzoo.de>.
+ */
+#define DLT_DECT 221
+
+/*
+ * From: "Lidwa, Eric (GSFC-582.0)[SGT INC]" <eric.lidwa-1@nasa.gov>
+ * Date: Mon, 11 May 2009 11:18:30 -0500
+ *
+ * DLT_AOS. We need it for AOS Space Data Link Protocol.
+ * I have already written dissectors for but need an OK from
+ * legal before I can submit a patch.
+ *
+ */
+#define DLT_AOS 222
+
+/*
+ * Wireless HART (Highway Addressable Remote Transducer)
+ * From the HART Communication Foundation
+ * IES/PAS 62591
+ *
+ * Requested by Sam Roberts <vieuxtech@gmail.com>.
+ */
+#define DLT_WIHART 223
+
+/*
+ * Fibre Channel FC-2 frames, beginning with a Frame_Header.
+ * Requested by Kahou Lei <kahou82@gmail.com>.
+ */
+#define DLT_FC_2 224
+
+/*
+ * Fibre Channel FC-2 frames, beginning with an encoding of the
+ * SOF, and ending with an encoding of the EOF.
+ *
+ * The encodings represent the frame delimiters as 4-byte sequences
+ * representing the corresponding ordered sets, with K28.5
+ * represented as 0xBC, and the D symbols as the corresponding
+ * byte values; for example, SOFi2, which is K28.5 - D21.5 - D1.2 - D21.2,
+ * is represented as 0xBC 0xB5 0x55 0x55.
+ *
+ * Requested by Kahou Lei <kahou82@gmail.com>.
+ */
+#define DLT_FC_2_WITH_FRAME_DELIMS 225
+
+/*
+ * Solaris ipnet pseudo-header; requested by Darren Reed <Darren.Reed@Sun.COM>.
+ *
+ * The pseudo-header starts with a one-byte version number; for version 2,
+ * the pseudo-header is:
+ *
+ * struct dl_ipnetinfo {
+ * u_int8_t dli_version;
+ * u_int8_t dli_family;
+ * u_int16_t dli_htype;
+ * u_int32_t dli_pktlen;
+ * u_int32_t dli_ifindex;
+ * u_int32_t dli_grifindex;
+ * u_int32_t dli_zsrc;
+ * u_int32_t dli_zdst;
+ * };
+ *
+ * dli_version is 2 for the current version of the pseudo-header.
+ *
+ * dli_family is a Solaris address family value, so it's 2 for IPv4
+ * and 26 for IPv6.
+ *
+ * dli_htype is a "hook type" - 0 for incoming packets, 1 for outgoing
+ * packets, and 2 for packets arriving from another zone on the same
+ * machine.
+ *
+ * dli_pktlen is the length of the packet data following the pseudo-header
+ * (so the captured length minus dli_pktlen is the length of the
+ * pseudo-header, assuming the entire pseudo-header was captured).
+ *
+ * dli_ifindex is the interface index of the interface on which the
+ * packet arrived.
+ *
+ * dli_grifindex is the group interface index number (for IPMP interfaces).
+ *
+ * dli_zsrc is the zone identifier for the source of the packet.
+ *
+ * dli_zdst is the zone identifier for the destination of the packet.
+ *
+ * A zone number of 0 is the global zone; a zone number of 0xffffffff
+ * means that the packet arrived from another host on the network, not
+ * from another zone on the same machine.
+ *
+ * An IPv4 or IPv6 datagram follows the pseudo-header; dli_family indicates
+ * which of those it is.
+ */
+#define DLT_IPNET 226
+
+/*
+ * CAN (Controller Area Network) frames, with a pseudo-header as supplied
+ * by Linux SocketCAN, and with multi-byte numerical fields in that header
+ * in big-endian byte order.
+ *
+ * See Documentation/networking/can.txt in the Linux source.
+ *
+ * Requested by Felix Obenhuber <felix@obenhuber.de>.
+ */
+#define DLT_CAN_SOCKETCAN 227
+
+/*
+ * Raw IPv4/IPv6; different from DLT_RAW in that the DLT_ value specifies
+ * whether it's v4 or v6. Requested by Darren Reed <Darren.Reed@Sun.COM>.
+ */
+#define DLT_IPV4 228
+#define DLT_IPV6 229
+
+/*
+ * IEEE 802.15.4, exactly as it appears in the spec (no padding, no
+ * nothing), and with no FCS at the end of the frame; requested by
+ * Jon Smirl <jonsmirl@gmail.com>.
+ */
+#define DLT_IEEE802_15_4_NOFCS 230
+
+/*
+ * Raw D-Bus:
+ *
+ * http://www.freedesktop.org/wiki/Software/dbus
+ *
+ * messages:
+ *
+ * http://dbus.freedesktop.org/doc/dbus-specification.html#message-protocol-messages
+ *
+ * starting with the endianness flag, followed by the message type, etc.,
+ * but without the authentication handshake before the message sequence:
+ *
+ * http://dbus.freedesktop.org/doc/dbus-specification.html#auth-protocol
+ *
+ * Requested by Martin Vidner <martin@vidner.net>.
+ */
+#define DLT_DBUS 231
+
+/*
+ * Juniper-private data link type, as per request from
+ * Hannes Gredler <hannes@juniper.net>.
+ */
+#define DLT_JUNIPER_VS 232
+#define DLT_JUNIPER_SRX_E2E 233
+#define DLT_JUNIPER_FIBRECHANNEL 234
+
+/*
+ * DVB-CI (DVB Common Interface for communication between a PC Card
+ * module and a DVB receiver). See
+ *
+ * http://www.kaiser.cx/pcap-dvbci.html
+ *
+ * for the specification.
+ *
+ * Requested by Martin Kaiser <martin@kaiser.cx>.
+ */
+#define DLT_DVB_CI 235
+
+/*
+ * Variant of 3GPP TS 27.010 multiplexing protocol (similar to, but
+ * *not* the same as, 27.010). Requested by Hans-Christoph Schemmel
+ * <hans-christoph.schemmel@cinterion.com>.
+ */
+#define DLT_MUX27010 236
+
+/*
+ * STANAG 5066 D_PDUs. Requested by M. Baris Demiray
+ * <barisdemiray@gmail.com>.
+ */
+#define DLT_STANAG_5066_D_PDU 237
+
+/*
+ * Juniper-private data link type, as per request from
+ * Hannes Gredler <hannes@juniper.net>.
+ */
+#define DLT_JUNIPER_ATM_CEMIC 238
+
+/*
+ * NetFilter LOG messages
+ * (payload of netlink NFNL_SUBSYS_ULOG/NFULNL_MSG_PACKET packets)
+ *
+ * Requested by Jakub Zawadzki <darkjames-ws@darkjames.pl>
+ */
+#define DLT_NFLOG 239
+
+/*
+ * Hilscher Gesellschaft fuer Systemautomation mbH link-layer type
+ * for Ethernet packets with a 4-byte pseudo-header and always
+ * with the payload including the FCS, as supplied by their
+ * netANALYZER hardware and software.
+ *
+ * Requested by Holger P. Frommer <HPfrommer@hilscher.com>
+ */
+#define DLT_NETANALYZER 240
+
+/*
+ * Hilscher Gesellschaft fuer Systemautomation mbH link-layer type
+ * for Ethernet packets with a 4-byte pseudo-header and FCS and
+ * with the Ethernet header preceded by 7 bytes of preamble and
+ * 1 byte of SFD, as supplied by their netANALYZER hardware and
+ * software.
+ *
+ * Requested by Holger P. Frommer <HPfrommer@hilscher.com>
+ */
+#define DLT_NETANALYZER_TRANSPARENT 241
+
+/*
+ * IP-over-InfiniBand, as specified by RFC 4391.
+ *
+ * Requested by Petr Sumbera <petr.sumbera@oracle.com>.
+ */
+#define DLT_IPOIB 242
+
+/*
+ * 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
+
+/*
+ * 246 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 246.
+ */
+#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
+
+/*
+ * DLT type for the netlink protocol (nlmon devices).
+ */
+#define DLT_NETLINK 253
+
+/*
+ * Bluetooth Linux Monitor headers for the BlueZ stack.
+ */
+#define DLT_BLUETOOTH_LINUX_MONITOR 254
+
+/*
+ * Bluetooth Basic Rate/Enhanced Data Rate baseband packets, as
+ * captured by Ubertooth.
+ */
+#define DLT_BLUETOOTH_BREDR_BB 255
+
+/*
+ * Bluetooth Low Energy link layer packets, as captured by Ubertooth.
+ */
+#define DLT_BLUETOOTH_LE_LL_WITH_PHDR 256
+
+/*
+ * PROFIBUS data link layer.
+ */
+#define DLT_PROFIBUS_DL 257
+
+/*
+ * Apple's DLT_PKTAP headers.
+ *
+ * Sadly, the folks at Apple either had no clue that the DLT_USERn values
+ * are for internal use within an organization and partners only, and
+ * didn't know that the right way to get a link-layer header type is to
+ * ask tcpdump.org for one, or knew and didn't care, so they just
+ * used DLT_USER2, which causes problems for everything except for
+ * their version of tcpdump.
+ *
+ * So I'll just give them one; hopefully this will show up in a
+ * libpcap release in time for them to get this into 10.10 Big Sur
+ * or whatever Mavericks' successor is called. LINKTYPE_PKTAP
+ * will be 258 *even on OS X*; that is *intentional*, so that
+ * PKTAP files look the same on *all* OSes (different OSes can have
+ * different numerical values for a given DLT_, but *MUST NOT* have
+ * different values for what goes in a file, as files can be moved
+ * between OSes!).
+ *
+ * When capturing, on a system with a Darwin-based OS, on a device
+ * that returns 149 (DLT_USER2 and Apple's DLT_PKTAP) with this
+ * version of libpcap, the DLT_ value for the pcap_t will be DLT_PKTAP,
+ * and that will continue to be DLT_USER2 on Darwin-based OSes. That way,
+ * binary compatibility with Mavericks is preserved for programs using
+ * this version of libpcap. This does mean that if you were using
+ * DLT_USER2 for some capture device on OS X, you can't do so with
+ * this version of libpcap, just as you can't with Apple's libpcap -
+ * on OS X, they define DLT_PKTAP to be DLT_USER2, so programs won't
+ * be able to distinguish between PKTAP and whatever you were using
+ * DLT_USER2 for.
+ *
+ * If the program saves the capture to a file using this version of
+ * libpcap's pcap_dump code, the LINKTYPE_ value in the file will be
+ * LINKTYPE_PKTAP, which will be 258, even on Darwin-based OSes.
+ * That way, the file will *not* be a DLT_USER2 file. That means
+ * that the latest version of tcpdump, when built with this version
+ * of libpcap, and sufficiently recent versions of Wireshark will
+ * be able to read those files and interpret them correctly; however,
+ * Apple's version of tcpdump in OS X 10.9 won't be able to handle
+ * them. (Hopefully, Apple will pick up this version of libpcap,
+ * and the corresponding version of tcpdump, so that tcpdump will
+ * be able to handle the old LINKTYPE_USER2 captures *and* the new
+ * LINKTYPE_PKTAP captures.)
+ */
+#ifdef __APPLE__
+#define DLT_PKTAP DLT_USER2
+#else
+#define DLT_PKTAP 258
+#endif
+
+/*
+ * Ethernet packets preceded by a header giving the last 6 octets
+ * of the preamble specified by 802.3-2012 Clause 65, section
+ * 65.1.3.2 "Transmit".
+ */
+#define DLT_EPON 259
+
+/*
+ * IPMI trace packets, as specified by Table 3-20 "Trace Data Block Format"
+ * in the PICMG HPM.2 specification.
+ */
+#define DLT_IPMI_HPM_2 260
+
+/*
+ * per Joshua Wright <jwright@hasborg.com>, formats for Zwave captures.
+ */
+#define DLT_ZWAVE_R1_R2 261
+#define DLT_ZWAVE_R3 262
+
+/*
+ * per Steve Karg <skarg@users.sourceforge.net>, formats for Wattstopper
+ * Digital Lighting Management room bus serial protocol captures.
+ */
+#define DLT_WATTSTOPPER_DLM 263
+
+/*
+ * ISO 14443 contactless smart card messages.
+ */
+#define DLT_ISO_14443 264
+
+/*
+ * Radio data system (RDS) groups. IEC 62106.
+ * Per Jonathan Brucker <jonathan.brucke@gmail.com>.
+ */
+#define DLT_RDS 265
+
+/*
+ * In case the code that includes this file (directly or indirectly)
+ * has also included OS files that happen to define DLT_MATCHING_MAX,
+ * with a different value (perhaps because that OS hasn't picked up
+ * the latest version of our DLT definitions), we undefine the
+ * previous value of DLT_MATCHING_MAX.
+ */
+#ifdef DLT_MATCHING_MAX
+#undef DLT_MATCHING_MAX
+#endif
+#define DLT_MATCHING_MAX 265 /* 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.
+ */
+#define DLT_CLASS(x) ((x) & 0x03ff0000)
+
+/*
+ * NetBSD-specific generic "raw" link type. The class value indicates
+ * that this is the generic raw type, and the lower 16 bits are the
+ * address family we're dealing with. Those values are NetBSD-specific;
+ * do not assume that they correspond to AF_ values for your operating
+ * system.
+ */
+#define DLT_CLASS_NETBSD_RAWAF 0x02240000
+#define DLT_NETBSD_RAWAF(af) (DLT_CLASS_NETBSD_RAWAF | (af))
+#define DLT_NETBSD_RAWAF_AF(x) ((x) & 0x0000ffff)
+#define DLT_IS_NETBSD_RAWAF(x) (DLT_CLASS(x) == DLT_CLASS_NETBSD_RAWAF)
+
+#endif /* !defined(lib_pcap_dlt_h) */
diff --git a/contrib/libpcap/pcap/export-defs.h b/contrib/libpcap/pcap/export-defs.h
new file mode 100644
index 000000000000..a2350579dc4e
--- /dev/null
+++ b/contrib/libpcap/pcap/export-defs.h
@@ -0,0 +1,108 @@
+/* -*- Mode: c; tab-width: 8; indent-tabs-mode: 1; c-basic-offset: 8; -*- */
+/*
+ * Copyright (c) 1993, 1994, 1995, 1996, 1997
+ * The Regents of the University of California. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the Computer Systems
+ * Engineering Group at Lawrence Berkeley Laboratory.
+ * 4. Neither the name of the University nor of the Laboratory may be used
+ * to endorse or promote products derived from this software without
+ * specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#ifndef lib_pcap_export_defs_h
+#define lib_pcap_export_defs_h
+
+/*
+ * PCAP_API_DEF must be used when defining *data* exported from
+ * libpcap. It can be used when defining *functions* exported
+ * from libpcap, but it doesn't have to be used there. It
+ * should not be used in declarations in headers.
+ *
+ * PCAP_API must be used when *declaring* data or functions
+ * exported from libpcap; PCAP_API_DEF won't work on all platforms.
+ */
+
+/*
+ * Check whether this is GCC major.minor or a later release, or some
+ * compiler that claims to be "just like GCC" of that version or a
+ * later release.
+ */
+#define IS_AT_LEAST_GNUC_VERSION(major, minor) \
+ (defined(__GNUC__) && \
+ (__GNUC__ > (major) || \
+ (__GNUC__ == (major) && __GNUC_MINOR__ >= (minor))))
+
+#if defined(_WIN32)
+ #ifdef BUILDING_PCAP
+ /*
+ * We're compiling libpcap, so we should export functions in our
+ * API.
+ */
+ #define PCAP_API_DEF __declspec(dllexport)
+ #else
+ #define PCAP_API_DEF __declspec(dllimport)
+ #endif
+#elif defined(MSDOS)
+ /* XXX - does this need special treatment? */
+ #define PCAP_API_DEF
+#else /* UN*X */
+ #ifdef BUILDING_PCAP
+ /*
+ * We're compiling libpcap, so we should export functions in our API.
+ * The compiler might be configured not to export functions from a
+ * shared library by default, so we might have to explicitly mark
+ * functions as exported.
+ */
+ #if IS_AT_LEAST_GNUC_VERSION(3, 4)
+ /*
+ * GCC 3.4 or later, or some compiler asserting compatibility with
+ * GCC 3.4 or later, so we have __attribute__((visibility()).
+ */
+ #define PCAP_API_DEF __attribute__((visibility("default")))
+ #elif defined(__SUNPRO_C) && (__SUNPRO_C >= 0x550)
+ /*
+ * Sun C 5.5 or later, so we have __global.
+ * (Sun C 5.9 and later also have __attribute__((visibility()),
+ * but there's no reason to prefer it with Sun C.)
+ */
+ #define PCAP_API_DEF __global
+ #else
+ /*
+ * We don't have anything to say.
+ */
+ #define PCAP_API_DEF
+ #endif
+ #else
+ /*
+ * We're not building libpcap.
+ */
+ #define PCAP_API_DEF
+ #endif
+#endif /* _WIN32/MSDOS/UN*X */
+
+#define PCAP_API PCAP_API_DEF extern
+
+#endif /* lib_pcap_export_defs_h */
diff --git a/contrib/libpcap/pcap/namedb.h b/contrib/libpcap/pcap/namedb.h
index d3a343225f04..73fb40a4cf3f 100644
--- a/contrib/libpcap/pcap/namedb.h
+++ b/contrib/libpcap/pcap/namedb.h
@@ -43,7 +43,10 @@ extern "C" {
* XXX this stuff doesn't belong in this interface, but this
* library already must do name to address translation, so
* on systems that don't have support for /etc/ethers, we
- * export these hooks since they'll
+ * export these hooks since they're already being used by
+ * some applications (such as tcpdump) and already being
+ * marked as exported in some OSes offering libpcap (such
+ * as Debian).
*/
struct pcap_etherent {
u_char addr[6];
@@ -52,21 +55,21 @@ struct pcap_etherent {
#ifndef PCAP_ETHERS_FILE
#define PCAP_ETHERS_FILE "/etc/ethers"
#endif
-struct pcap_etherent *pcap_next_etherent(FILE *);
-u_char *pcap_ether_hostton(const char*);
-u_char *pcap_ether_aton(const char *);
+PCAP_API struct pcap_etherent *pcap_next_etherent(FILE *);
+PCAP_API u_char *pcap_ether_hostton(const char*);
+PCAP_API u_char *pcap_ether_aton(const char *);
-bpf_u_int32 **pcap_nametoaddr(const char *);
+PCAP_API bpf_u_int32 **pcap_nametoaddr(const char *);
#ifdef INET6
-struct addrinfo *pcap_nametoaddrinfo(const char *);
+PCAP_API struct addrinfo *pcap_nametoaddrinfo(const char *);
#endif
-bpf_u_int32 pcap_nametonetaddr(const char *);
+PCAP_API bpf_u_int32 pcap_nametonetaddr(const char *);
-int pcap_nametoport(const char *, int *, int *);
-int pcap_nametoportrange(const char *, int *, int *, int *);
-int pcap_nametoproto(const char *);
-int pcap_nametoeproto(const char *);
-int pcap_nametollc(const char *);
+PCAP_API int pcap_nametoport(const char *, int *, int *);
+PCAP_API int pcap_nametoportrange(const char *, int *, int *, int *);
+PCAP_API int pcap_nametoproto(const char *);
+PCAP_API int pcap_nametoeproto(const char *);
+PCAP_API int pcap_nametollc(const char *);
/*
* If a protocol is unknown, PROTO_UNDEF is returned.
* Also, pcap_nametoport() returns the protocol along with the port number.
@@ -75,11 +78,6 @@ int pcap_nametollc(const char *);
*/
#define PROTO_UNDEF -1
-/* XXX move these to pcap-int.h? */
-int __pcap_atodn(const char *, bpf_u_int32 *);
-int __pcap_atoin(const char *, bpf_u_int32 *);
-u_short __pcap_nametodnaddr(const char *);
-
#ifdef __cplusplus
}
#endif
diff --git a/contrib/libpcap/pcap/nflog.h b/contrib/libpcap/pcap/nflog.h
index 388dd0c55d08..a3867cdd6cbc 100644
--- a/contrib/libpcap/pcap/nflog.h
+++ b/contrib/libpcap/pcap/nflog.h
@@ -25,8 +25,8 @@
* DAMAGE.
*/
-#ifndef _PCAP_NFLOG_H__
-#define _PCAP_NFLOG_H__
+#ifndef lib_pcap_nflog_h
+#define lib_pcap_nflog_h
/*
* Structure of an NFLOG header and TLV parts, as described at
diff --git a/contrib/libpcap/pcap/pcap.h b/contrib/libpcap/pcap/pcap.h
index 7949122cd291..9c27712441f0 100644
--- a/contrib/libpcap/pcap/pcap.h
+++ b/contrib/libpcap/pcap/pcap.h
@@ -35,7 +35,9 @@
#ifndef lib_pcap_pcap_h
#define lib_pcap_pcap_h
-#if defined(WIN32)
+#include <pcap/export-defs.h>
+
+#if defined(_WIN32)
#include <pcap-stdinc.h>
#elif defined(MSDOS)
#include <sys/types.h>
@@ -43,7 +45,7 @@
#else /* UN*X */
#include <sys/types.h>
#include <sys/time.h>
-#endif /* WIN32/MSDOS/UN*X */
+#endif /* _WIN32/MSDOS/UN*X */
#include <net/bpf.h>
@@ -168,9 +170,11 @@ struct pcap_stat {
u_int ps_recv; /* number of packets received */
u_int ps_drop; /* number of packets dropped */
u_int ps_ifdrop; /* drops by interface -- only supported on some platforms */
-#ifdef WIN32
- u_int bs_capt; /* number of packets that reach the application */
-#endif /* WIN32 */
+#if defined(_WIN32) && defined(HAVE_REMOTE)
+ u_int ps_capt; /* number of packets that reach the application */
+ u_int ps_sent; /* number of packets sent by the server on the network */
+ u_int ps_netdrop; /* number of packets lost on the network */
+#endif /* _WIN32 && HAVE_REMOTE */
};
#ifdef MSDOS
@@ -269,27 +273,27 @@ typedef void (*pcap_handler)(u_char *, const struct pcap_pkthdr *,
*/
#define PCAP_NETMASK_UNKNOWN 0xffffffff
-char *pcap_lookupdev(char *);
-int pcap_lookupnet(const char *, bpf_u_int32 *, bpf_u_int32 *, char *);
-
-pcap_t *pcap_create(const char *, char *);
-int pcap_set_snaplen(pcap_t *, int);
-int pcap_set_promisc(pcap_t *, int);
-int pcap_can_set_rfmon(pcap_t *);
-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 **);
-void pcap_free_tstamp_types(int *);
-int pcap_tstamp_type_name_to_val(const char *);
-const char *pcap_tstamp_type_val_to_name(int);
-const char *pcap_tstamp_type_val_to_description(int);
+PCAP_API char *pcap_lookupdev(char *);
+PCAP_API int pcap_lookupnet(const char *, bpf_u_int32 *, bpf_u_int32 *, char *);
+
+PCAP_API pcap_t *pcap_create(const char *, char *);
+PCAP_API int pcap_set_snaplen(pcap_t *, int);
+PCAP_API int pcap_set_promisc(pcap_t *, int);
+PCAP_API int pcap_can_set_rfmon(pcap_t *);
+PCAP_API int pcap_set_rfmon(pcap_t *, int);
+PCAP_API int pcap_set_timeout(pcap_t *, int);
+PCAP_API int pcap_set_tstamp_type(pcap_t *, int);
+PCAP_API int pcap_set_immediate_mode(pcap_t *, int);
+PCAP_API int pcap_set_buffer_size(pcap_t *, int);
+PCAP_API int pcap_set_tstamp_precision(pcap_t *, int);
+PCAP_API int pcap_get_tstamp_precision(pcap_t *);
+PCAP_API int pcap_activate(pcap_t *);
+
+PCAP_API int pcap_list_tstamp_types(pcap_t *, int **);
+PCAP_API void pcap_free_tstamp_types(int *);
+PCAP_API int pcap_tstamp_type_name_to_val(const char *);
+PCAP_API const char *pcap_tstamp_type_val_to_name(int);
+PCAP_API const char *pcap_tstamp_type_val_to_description(int);
/*
* Time stamp types.
@@ -344,136 +348,186 @@ const char *pcap_tstamp_type_val_to_description(int);
#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_API pcap_t *pcap_open_live(const char *, int, int, int, char *);
+PCAP_API pcap_t *pcap_open_dead(int, int);
+PCAP_API pcap_t *pcap_open_dead_with_tstamp_precision(int, int, u_int);
+PCAP_API pcap_t *pcap_open_offline_with_tstamp_precision(const char *, u_int, char *);
+PCAP_API pcap_t *pcap_open_offline(const char *, char *);
+#ifdef _WIN32
+ PCAP_API pcap_t *pcap_hopen_offline_with_tstamp_precision(intptr_t, u_int, char *);
+ PCAP_API pcap_t *pcap_hopen_offline(intptr_t, char *);
+ /*
+ * If we're building libpcap, these are internal routines in savefile.c,
+ * so we mustn't define them as macros.
+ */
+ #ifndef BUILDING_PCAP
+ #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) \
+ #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*/
-
-void pcap_close(pcap_t *);
-int pcap_loop(pcap_t *, int, pcap_handler, u_char *);
-int pcap_dispatch(pcap_t *, int, pcap_handler, u_char *);
-const u_char*
- pcap_next(pcap_t *, struct pcap_pkthdr *);
-int pcap_next_ex(pcap_t *, struct pcap_pkthdr **, const u_char **);
-void pcap_breakloop(pcap_t *);
-int pcap_stats(pcap_t *, struct pcap_stat *);
-int pcap_setfilter(pcap_t *, struct bpf_program *);
-int pcap_setdirection(pcap_t *, pcap_direction_t);
-int pcap_getnonblock(pcap_t *, char *);
-int pcap_setnonblock(pcap_t *, int, char *);
-int pcap_inject(pcap_t *, const void *, size_t);
-int pcap_sendpacket(pcap_t *, const u_char *, int);
-const char *pcap_statustostr(int);
-const char *pcap_strerror(int);
-char *pcap_geterr(pcap_t *);
-void pcap_perror(pcap_t *, char *);
-int pcap_compile(pcap_t *, struct bpf_program *, const char *, int,
+ #endif
+#else /*_WIN32*/
+ PCAP_API pcap_t *pcap_fopen_offline_with_tstamp_precision(FILE *, u_int, char *);
+ PCAP_API pcap_t *pcap_fopen_offline(FILE *, char *);
+#endif /*_WIN32*/
+
+PCAP_API void pcap_close(pcap_t *);
+PCAP_API int pcap_loop(pcap_t *, int, pcap_handler, u_char *);
+PCAP_API int pcap_dispatch(pcap_t *, int, pcap_handler, u_char *);
+PCAP_API const u_char *pcap_next(pcap_t *, struct pcap_pkthdr *);
+PCAP_API int pcap_next_ex(pcap_t *, struct pcap_pkthdr **, const u_char **);
+PCAP_API void pcap_breakloop(pcap_t *);
+PCAP_API int pcap_stats(pcap_t *, struct pcap_stat *);
+PCAP_API int pcap_setfilter(pcap_t *, struct bpf_program *);
+PCAP_API int pcap_setdirection(pcap_t *, pcap_direction_t);
+PCAP_API int pcap_getnonblock(pcap_t *, char *);
+PCAP_API int pcap_setnonblock(pcap_t *, int, char *);
+PCAP_API int pcap_inject(pcap_t *, const void *, size_t);
+PCAP_API int pcap_sendpacket(pcap_t *, const u_char *, int);
+PCAP_API const char *pcap_statustostr(int);
+PCAP_API const char *pcap_strerror(int);
+PCAP_API char *pcap_geterr(pcap_t *);
+PCAP_API void pcap_perror(pcap_t *, const char *);
+PCAP_API int pcap_compile(pcap_t *, struct bpf_program *, const char *, int,
bpf_u_int32);
-int pcap_compile_nopcap(int, int, struct bpf_program *,
+PCAP_API 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(const struct bpf_program *,
+PCAP_API void pcap_freecode(struct bpf_program *);
+PCAP_API 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 **);
-int pcap_set_datalink(pcap_t *, int);
-void pcap_free_datalinks(int *);
-int pcap_datalink_name_to_val(const char *);
-const char *pcap_datalink_val_to_name(int);
-const char *pcap_datalink_val_to_description(int);
-int pcap_snapshot(pcap_t *);
-int pcap_is_swapped(pcap_t *);
-int pcap_major_version(pcap_t *);
-int pcap_minor_version(pcap_t *);
+PCAP_API int pcap_datalink(pcap_t *);
+PCAP_API int pcap_datalink_ext(pcap_t *);
+PCAP_API int pcap_list_datalinks(pcap_t *, int **);
+PCAP_API int pcap_set_datalink(pcap_t *, int);
+PCAP_API void pcap_free_datalinks(int *);
+PCAP_API int pcap_datalink_name_to_val(const char *);
+PCAP_API const char *pcap_datalink_val_to_name(int);
+PCAP_API const char *pcap_datalink_val_to_description(int);
+PCAP_API int pcap_snapshot(pcap_t *);
+PCAP_API int pcap_is_swapped(pcap_t *);
+PCAP_API int pcap_major_version(pcap_t *);
+PCAP_API int pcap_minor_version(pcap_t *);
/* XXX */
-FILE *pcap_file(pcap_t *);
-int pcap_fileno(pcap_t *);
+PCAP_API FILE *pcap_file(pcap_t *);
+PCAP_API int pcap_fileno(pcap_t *);
+
+#ifdef _WIN32
+ PCAP_API int pcap_wsockinit(void);
+#endif
-pcap_dumper_t *pcap_dump_open(pcap_t *, const char *);
-pcap_dumper_t *pcap_dump_fopen(pcap_t *, FILE *fp);
-FILE *pcap_dump_file(pcap_dumper_t *);
-long pcap_dump_ftell(pcap_dumper_t *);
-int pcap_dump_flush(pcap_dumper_t *);
-void pcap_dump_close(pcap_dumper_t *);
-void pcap_dump(u_char *, const struct pcap_pkthdr *, const u_char *);
+PCAP_API pcap_dumper_t *pcap_dump_open(pcap_t *, const char *);
+PCAP_API pcap_dumper_t *pcap_dump_fopen(pcap_t *, FILE *fp);
+PCAP_API pcap_dumper_t *pcap_dump_open_append(pcap_t *, const char *);
+PCAP_API FILE *pcap_dump_file(pcap_dumper_t *);
+PCAP_API long pcap_dump_ftell(pcap_dumper_t *);
+PCAP_API int pcap_dump_flush(pcap_dumper_t *);
+PCAP_API void pcap_dump_close(pcap_dumper_t *);
+PCAP_API void pcap_dump(u_char *, const struct pcap_pkthdr *, const u_char *);
-int pcap_findalldevs(pcap_if_t **, char *);
-void pcap_freealldevs(pcap_if_t *);
+PCAP_API int pcap_findalldevs(pcap_if_t **, char *);
+PCAP_API void pcap_freealldevs(pcap_if_t *);
-const char *pcap_lib_version(void);
+PCAP_API const char *pcap_lib_version(void);
/*
- * On at least some versions of NetBSD, we don't want to declare
+ * On at least some versions of NetBSD and QNX, we don't want to declare
* bpf_filter() here, as it's also be declared in <net/bpf.h>, with a
* different signature, but, on other BSD-flavored UN*Xes, it's not
* declared in <net/bpf.h>, so we *do* want to declare it here, so it's
* declared when we build pcap-bpf.c.
*/
-#ifndef __NetBSD__
-u_int bpf_filter(const struct bpf_insn *, const u_char *, u_int, u_int);
+#if !defined(__NetBSD__) && !defined(__QNX__)
+ PCAP_API u_int bpf_filter(const struct bpf_insn *, const u_char *, u_int, u_int);
#endif
-int bpf_validate(const struct bpf_insn *f, int len);
-char *bpf_image(const struct bpf_insn *, int);
-void bpf_dump(const struct bpf_program *, int);
+PCAP_API int bpf_validate(const struct bpf_insn *f, int len);
+PCAP_API char *bpf_image(const struct bpf_insn *, int);
+PCAP_API void bpf_dump(const struct bpf_program *, int);
-#if defined(WIN32)
+#if defined(_WIN32)
-/*
- * Win32 definitions
- */
+ /*
+ * Win32 definitions
+ */
+
+ /*!
+ \brief A queue of raw packets that will be sent to the network with pcap_sendqueue_transmit().
+ */
+ struct pcap_send_queue
+ {
+ u_int maxlen; /* Maximum size of the the queue, in bytes. This
+ variable contains the size of the buffer field. */
+ u_int len; /* Current size of the queue, in bytes. */
+ char *buffer; /* Buffer containing the packets to be sent. */
+ };
+
+ typedef struct pcap_send_queue pcap_send_queue;
+
+ /*!
+ \brief This typedef is a support for the pcap_get_airpcap_handle() function
+ */
+ #if !defined(AIRPCAP_HANDLE__EAE405F5_0171_9592_B3C2_C19EC426AD34__DEFINED_)
+ #define AIRPCAP_HANDLE__EAE405F5_0171_9592_B3C2_C19EC426AD34__DEFINED_
+ typedef struct _AirpcapHandle *PAirpcapHandle;
+ #endif
+
+ PCAP_API int pcap_setbuff(pcap_t *p, int dim);
+ PCAP_API int pcap_setmode(pcap_t *p, int mode);
+ PCAP_API int pcap_setmintocopy(pcap_t *p, int size);
+
+ PCAP_API HANDLE pcap_getevent(pcap_t *p);
+
+ PCAP_API int pcap_oid_get_request(pcap_t *, bpf_u_int32, void *, size_t *);
+ PCAP_API int pcap_oid_set_request(pcap_t *, bpf_u_int32, const void *, size_t *);
+
+ PCAP_API pcap_send_queue* pcap_sendqueue_alloc(u_int memsize);
-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);
+ PCAP_API void pcap_sendqueue_destroy(pcap_send_queue* queue);
-#ifdef WPCAP
-/* Include file with the wpcap-specific extensions */
-#include <Win32-Extensions.h>
-#endif /* WPCAP */
+ PCAP_API int pcap_sendqueue_queue(pcap_send_queue* queue, const struct pcap_pkthdr *pkt_header, const u_char *pkt_data);
-#define MODE_CAPT 0
-#define MODE_STAT 1
-#define MODE_MON 2
+ PCAP_API u_int pcap_sendqueue_transmit(pcap_t *p, pcap_send_queue* queue, int sync);
+
+ PCAP_API struct pcap_stat *pcap_stats_ex(pcap_t *p, int *pcap_stat_size);
+
+ PCAP_API int pcap_setuserbuffer(pcap_t *p, int size);
+
+ PCAP_API int pcap_live_dump(pcap_t *p, char *filename, int maxsize, int maxpacks);
+
+ PCAP_API int pcap_live_dump_ended(pcap_t *p, int sync);
+
+ PCAP_API int pcap_start_oem(char* err_str, int flags);
+
+ PCAP_API PAirpcapHandle pcap_get_airpcap_handle(pcap_t *p);
+
+ #define MODE_CAPT 0
+ #define MODE_STAT 1
+ #define MODE_MON 2
#elif defined(MSDOS)
-/*
- * MS-DOS definitions
- */
+ /*
+ * MS-DOS definitions
+ */
-int pcap_stats_ex (pcap_t *, struct pcap_stat_ex *);
-void pcap_set_wait (pcap_t *p, void (*yield)(void), int wait);
-u_long pcap_mac_packets (void);
+ PCAP_API int pcap_stats_ex (pcap_t *, struct pcap_stat_ex *);
+ PCAP_API void pcap_set_wait (pcap_t *p, void (*yield)(void), int wait);
+ PCAP_API u_long pcap_mac_packets (void);
#else /* UN*X */
-/*
- * UN*X definitions
- */
+ /*
+ * UN*X definitions
+ */
+
+ PCAP_API int pcap_get_selectable_fd(pcap_t *);
-int pcap_get_selectable_fd(pcap_t *);
+#endif /* _WIN32/MSDOS/UN*X */
-#endif /* WIN32/MSDOS/UN*X */
+#ifdef HAVE_REMOTE
+ /* Includes most of the public stuff that is needed for the remote capture */
+ #include <remote-ext.h>
+#endif /* HAVE_REMOTE */
#ifdef __cplusplus
}
diff --git a/contrib/libpcap/pcap/sll.h b/contrib/libpcap/pcap/sll.h
index 38da29f5090e..b46d15f25d83 100644
--- a/contrib/libpcap/pcap/sll.h
+++ b/contrib/libpcap/pcap/sll.h
@@ -123,5 +123,7 @@ struct sll_header {
*/
#define LINUX_SLL_P_802_3 0x0001 /* Novell 802.3 frames without 802.2 LLC header */
#define LINUX_SLL_P_802_2 0x0004 /* 802.2 frames (not D/I/X Ethernet) */
+#define LINUX_SLL_P_CAN 0x000C /* CAN frames, with SocketCAN pseudo-headers */
+#define LINUX_SLL_P_CANFD 0x000D /* CAN FD frames, with SocketCAN pseudo-headers */
#endif
diff --git a/contrib/libpcap/pcap/usb.h b/contrib/libpcap/pcap/usb.h
index 52cb5a322a5e..26a9046b44ed 100644
--- a/contrib/libpcap/pcap/usb.h
+++ b/contrib/libpcap/pcap/usb.h
@@ -11,8 +11,8 @@
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
- * 3. The name of the author may not be used to endorse or promote
- * products derived from this software without specific prior written
+ * 3. The name of the author may not be used to endorse or promote
+ * products derived from this software without specific prior written
* permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
@@ -30,11 +30,11 @@
* Basic USB data struct
* By Paolo Abeni <paolo.abeni@email.it>
*/
-
-#ifndef _PCAP_USB_STRUCTS_H__
-#define _PCAP_USB_STRUCTS_H__
-/*
+#ifndef lib_pcap_usb_h
+#define lib_pcap_usb_h
+
+/*
* possible transfer mode
*/
#define URB_TRANSFER_IN 0x80
diff --git a/contrib/libpcap/pcap_activate.3pcap b/contrib/libpcap/pcap_activate.3pcap
index 61887a7bead3..8c89939fddc0 100644
--- a/contrib/libpcap/pcap_activate.3pcap
+++ b/contrib/libpcap/pcap_activate.3pcap
@@ -17,7 +17,7 @@
.\" WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
.\" MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
.\"
-.TH PCAP_ACTIVATE 3PCAP "21 September 2010"
+.TH PCAP_ACTIVATE 3PCAP "7 April 2014"
.SH NAME
pcap_activate \- activate a capture handle
.SH SYNOPSIS
@@ -37,46 +37,65 @@ at packets on the network, with the options that were set on the handle
being in effect.
.SH RETURN VALUE
.B pcap_activate()
-returns 0 on success without warnings,
+returns 0 on success without warnings, a non-zero positive value on
+success with warnings, and a negative value on error.
+A non-zero return value indicates what warning or error condition
+occurred.
+.LP
+The possible warning values are:
+.TP
.B PCAP_WARNING_PROMISC_NOTSUP
-on success on a device that doesn't support promiscuous mode if
-promiscuous mode was requested,
+Promiscuous mode was requested, but the capture source doesn't support
+promiscuous mode.
+.TP
.B PCAP_WARNING_TSTAMP_TYPE_NOTSUP
-on success if the time stamp type specified in a previous
+The time stamp type specified in a previous
.B pcap_set_tstamp_type()
call isn't supported by the capture source (the time stamp type is
left as the default),
+.TP
.B PCAP_WARNING
-on success with any other warning,
+Another warning condition occurred;
+.B pcap_geterr()
+or
+.B pcap_perror()
+may be called with
+.I p
+as an argument to fetch or display a message describing the warning
+condition.
+.LP
+The possible error values are:
+.TP
.B PCAP_ERROR_ACTIVATED
-if the handle has already been activated,
+The handle has already been activated.
+.TP
.B PCAP_ERROR_NO_SUCH_DEVICE
-if the capture source specified when the handle was created doesn't
-exist,
+The capture source specified when the handle was created doesn't
+exist.
+.TP
.B PCAP_ERROR_PERM_DENIED
-if the process doesn't have permission to open the capture source,
+The process doesn't have permission to open the capture source.
+.TP
.B PCAP_ERROR_PROMISC_PERM_DENIED
-if the process has permission to open the capture source but doesn't
-have permission to put it into promiscuous mode,
+The process has permission to open the capture source but doesn't
+have permission to put it into promiscuous mode.
+.TP
.B PCAP_ERROR_RFMON_NOTSUP
-if monitor mode was specified but the capture source doesn't support
-monitor mode,
+Monitor mode was specified but the capture source doesn't support
+monitor mode.
+.TP
.B PCAP_ERROR_IFACE_NOT_UP
-if the capture source is not up, and
+The capture source device is not up.
+.TP
.B PCAP_ERROR
-if another error occurred.
-If
-.B PCAP_WARNING
-or
-.B PCAP_ERROR
-is returned,
+Another error occurred.
.B pcap_geterr()
or
.B pcap_perror()
may be called with
.I p
-as an argument to fetch or display a message describing the warning or
-error.
+as an argument to fetch or display a message describing the error.
+.LP
If
.BR PCAP_WARNING_PROMISC_NOTSUP ,
.BR PCAP_ERROR_NO_SUCH_DEVICE ,
@@ -91,5 +110,13 @@ may be called with
as an argument to fetch or display an message giving additional details
about the problem that might be useful for debugging the problem if it's
unexpected.
+.LP
+Additional warning and error codes may be added in the future; a program
+should check for positive, negative, and zero return codes, and treat
+all positive return codes as warnings and all negative return
+codes as errors.
+.B pcap_statustostr()
+can be called, with a warning or error code as an argument, to fetch a
+message describing the warning or error code.
.SH SEE ALSO
pcap(3PCAP)
diff --git a/contrib/libpcap/pcap_breakloop.3pcap b/contrib/libpcap/pcap_breakloop.3pcap
index a39582069b69..3f9327b198ef 100644
--- a/contrib/libpcap/pcap_breakloop.3pcap
+++ b/contrib/libpcap/pcap_breakloop.3pcap
@@ -17,7 +17,7 @@
.\" WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
.\" MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
.\"
-.TH PCAP_BREAKLOOP 3PCAP "5 April 2008"
+.TH PCAP_BREAKLOOP 3PCAP "8 March 2015"
.SH NAME
pcap_breakloop \- force a pcap_dispatch() or pcap_loop() call to return
.SH SYNOPSIS
@@ -91,7 +91,7 @@ If \-2 is returned from
.B pcap_dispatch()
or
.BR pcap_loop() ,
-the flag is cleared, so a subsequent call will resume reading packets.
+the flag is cleared, so a subsequent call will resume reading packets.
If a positive number is returned, the flag is not cleared, so a
subsequent call will return \-2 and clear the flag.
.SH SEE ALSO
diff --git a/contrib/libpcap/pcap_can_set_rfmon.3pcap b/contrib/libpcap/pcap_can_set_rfmon.3pcap
index b5798046db33..389e50ddaa60 100644
--- a/contrib/libpcap/pcap_can_set_rfmon.3pcap
+++ b/contrib/libpcap/pcap_can_set_rfmon.3pcap
@@ -17,7 +17,7 @@
.\" WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
.\" MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
.\"
-.TH PCAP_CAN_SET_RFMON 3PCAP "18 May 2010"
+.TH PCAP_CAN_SET_RFMON 3PCAP "3 January 2014"
.SH NAME
pcap_can_set_rfmon \- check whether monitor mode can be set for a
not-yet-activated capture handle
@@ -37,26 +37,36 @@ the handle is activated.
.SH RETURN VALUE
.B pcap_can_set_rfmon()
returns 0 if monitor mode could not be set,
-1 if monitor mode could be set,
+1 if monitor mode could be set, and a negative value on error.
+A negative return value indicates what error condition occurred.
+The possible error values are:
+.TP
.B PCAP_ERROR_NO_SUCH_DEVICE
-if the capture source specified when the handle was created doesn't
-exist,
+The capture source specified when the handle was created doesn't
+exist.
+.TP
.B PCAP_ERROR_PERM_DENIED
-if the process doesn't have permission to check whether monitor mode
-could be supported,
+The process doesn't have permission to check whether monitor mode
+could be supported.
+.TP
.B PCAP_ERROR_ACTIVATED
-if called on a capture handle that has been activated, or
+The capture handle has already been activated.
+.TP
.B PCAP_ERROR
-if an error occurred.
-If
-.B PCAP_ERROR
-is returned,
+Another error occurred.
.B pcap_geterr()
or
.B pcap_perror()
may be called with
.I p
-as an argument to fetch or display the error text.
+as an argument to fetch or display a message describing the error.
+.LP
+Additional error codes may be added in the future; a program should
+check for 0, 1, and negative, return codes, and treat all negative
+return codes as errors.
+.B pcap_statustostr()
+can be called, with a warning or error code as an argument, to fetch a
+message describing the warning or error code.
.SH SEE ALSO
pcap(3PCAP), pcap_create(3PCAP), pcap_activate(3PCAP),
pcap_set_rfmon(3PCAP)
diff --git a/contrib/libpcap/pcap_close.3pcap b/contrib/libpcap/pcap_close.3pcap
index 91eb677ef3b8..e2316a417dfd 100644
--- a/contrib/libpcap/pcap_close.3pcap
+++ b/contrib/libpcap/pcap_close.3pcap
@@ -17,7 +17,7 @@
.\" WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
.\" MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
.\"
-.TH PCAP_CLOSE 3PCAP "5 April 2008"
+.TH PCAP_CLOSE 3PCAP "3 January 2014"
.SH NAME
pcap_close \- close a capture device or savefile
.SH SYNOPSIS
diff --git a/contrib/libpcap/pcap_compile.3pcap.in b/contrib/libpcap/pcap_compile.3pcap.in
index 0e5276a165c7..2bd0eb469440 100644
--- a/contrib/libpcap/pcap_compile.3pcap.in
+++ b/contrib/libpcap/pcap_compile.3pcap.in
@@ -17,7 +17,7 @@
.\" WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
.\" MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
.\"
-.TH PCAP_COMPILE 3PCAP "1 December 2009"
+.TH PCAP_COMPILE 3PCAP "7 April 2014"
.SH NAME
pcap_compile \- compile a filter expression
.SH SYNOPSIS
diff --git a/contrib/libpcap/pcap_create.3pcap b/contrib/libpcap/pcap_create.3pcap
index 5c537fc55421..3040b3b20037 100644
--- a/contrib/libpcap/pcap_create.3pcap
+++ b/contrib/libpcap/pcap_create.3pcap
@@ -17,7 +17,7 @@
.\" WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
.\" MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
.\"
-.TH PCAP_CREATE 3PCAP "5 April 2008"
+.TH PCAP_CREATE 3PCAP "3 January 2014"
.SH NAME
pcap_create \- create a live capture handle
.SH SYNOPSIS
diff --git a/contrib/libpcap/pcap_datalink.3pcap.in b/contrib/libpcap/pcap_datalink.3pcap.in
index b07fc28f0982..be50a649ee31 100644
--- a/contrib/libpcap/pcap_datalink.3pcap.in
+++ b/contrib/libpcap/pcap_datalink.3pcap.in
@@ -17,7 +17,7 @@
.\" WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
.\" MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
.\"
-.TH PCAP_DATALINK 3PCAP "13 October 2013"
+.TH PCAP_DATALINK 3PCAP "7 April 2014"
.SH NAME
pcap_datalink \- get the link-layer header type
.SH SYNOPSIS
diff --git a/contrib/libpcap/pcap_datalink_name_to_val.3pcap b/contrib/libpcap/pcap_datalink_name_to_val.3pcap
index c61e91e3f91e..8a6905a2c576 100644
--- a/contrib/libpcap/pcap_datalink_name_to_val.3pcap
+++ b/contrib/libpcap/pcap_datalink_name_to_val.3pcap
@@ -17,7 +17,7 @@
.\" WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
.\" MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
.\"
-.TH PCAP_DATALINK_NAME_TO_VAL 3PCAP "22 August 2010"
+.TH PCAP_DATALINK_NAME_TO_VAL 3PCAP "5 December 2014"
.SH NAME
pcap_datalink_name_to_val \- get the link-layer header type value
corresponding to a header type name
@@ -41,6 +41,7 @@ removed, to the corresponding link-layer header type value. The
translation is case-insensitive.
.SH RETURN VALUE
.B pcap_datalink_name_to_val()
-returns 0 on success and \-1 on failure.
+returns the type value on success and \-1 if the name is not a known
+type name..
.SH SEE ALSO
pcap(3PCAP)
diff --git a/contrib/libpcap/pcap_datalink_val_to_name.3pcap b/contrib/libpcap/pcap_datalink_val_to_name.3pcap
index 0b178253d3ac..aa3e89a6e0b2 100644
--- a/contrib/libpcap/pcap_datalink_val_to_name.3pcap
+++ b/contrib/libpcap/pcap_datalink_val_to_name.3pcap
@@ -17,7 +17,7 @@
.\" WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
.\" MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
.\"
-.TH PCAP_DATALINK_VAL_TO_NAME 3PCAP "22 August 2010"
+.TH PCAP_DATALINK_VAL_TO_NAME 3PCAP "3 January 2014"
.SH NAME
pcap_datalink_val_to_name, pcap_datalink_val_to_description \- get a
name or description for a link-layer header type value
@@ -35,12 +35,20 @@ const char *pcap_datalink_val_to_description(int dlt);
.SH DESCRIPTION
.B pcap_datalink_val_to_name()
translates a link-layer header type value to the corresponding
-link-layer header type name.
+link-layer header type name, which is the
+.B DLT_
+name for the link-layer header type value with the
+.B DLT_
+removed.
.B NULL
-is returned on failure.
+is returned if the type value does not correspond to a known
+.B DLT_
+value.
.PP
.B pcap_datalink_val_to_description()
translates a link-layer header type value to a short description of that
link-layer header type.
.B NULL
-is returned on failure.
+is returned if the type value does not correspond to a known
+.B DLT_
+value.
diff --git a/contrib/libpcap/pcap_dump.3pcap b/contrib/libpcap/pcap_dump.3pcap
index c7d29f5140e4..6402b4b4519b 100644
--- a/contrib/libpcap/pcap_dump.3pcap
+++ b/contrib/libpcap/pcap_dump.3pcap
@@ -17,7 +17,7 @@
.\" WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
.\" MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
.\"
-.TH PCAP_DUMP 3PCAP "5 April 2008"
+.TH PCAP_DUMP 3PCAP "8 March 2015"
.SH NAME
pcap_dump \- write a packet to a capture file
.SH SYNOPSIS
@@ -40,9 +40,9 @@ Note that its calling arguments are suitable for use with
.B pcap_dispatch()
or
.BR pcap_loop() .
-If called directly, the
+If called directly, the
.I user
-parameter is of type
+parameter is of type
.B pcap_dumper_t
as returned by
.BR pcap_dump_open() .
diff --git a/contrib/libpcap/pcap_dump_close.3pcap b/contrib/libpcap/pcap_dump_close.3pcap
index afd00cb498eb..bd95a52b290e 100644
--- a/contrib/libpcap/pcap_dump_close.3pcap
+++ b/contrib/libpcap/pcap_dump_close.3pcap
@@ -17,7 +17,7 @@
.\" WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
.\" MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
.\"
-.TH PCAP_DUMP_CLOSE 3PCAP "5 April 2008"
+.TH PCAP_DUMP_CLOSE 3PCAP "3 January 2014"
.SH NAME
pcap_dump_close \- close a savefile being written to
.SH SYNOPSIS
diff --git a/contrib/libpcap/pcap_dump_file.3pcap b/contrib/libpcap/pcap_dump_file.3pcap
index 982b0dc9df65..8fea610a4f9a 100644
--- a/contrib/libpcap/pcap_dump_file.3pcap
+++ b/contrib/libpcap/pcap_dump_file.3pcap
@@ -17,7 +17,7 @@
.\" WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
.\" MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
.\"
-.TH PCAP_DUMP_FILE 3PCAP "5 April 2008"
+.TH PCAP_DUMP_FILE 3PCAP "3 January 2014"
.SH NAME
pcap_dump_file \- get the standard I/O stream for a savefile being written
.SH SYNOPSIS
diff --git a/contrib/libpcap/pcap_dump_flush.3pcap b/contrib/libpcap/pcap_dump_flush.3pcap
index ba98dee1dd23..c8f110bb6f24 100644
--- a/contrib/libpcap/pcap_dump_flush.3pcap
+++ b/contrib/libpcap/pcap_dump_flush.3pcap
@@ -17,7 +17,7 @@
.\" WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
.\" MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
.\"
-.TH PCAP_DUMP_FLUSH 3PCAP "5 April 2008"
+.TH PCAP_DUMP_FLUSH 3PCAP "3 January 2014"
.SH NAME
pcap_dump_flush \- flush to a savefile packets dumped
.SH SYNOPSIS
diff --git a/contrib/libpcap/pcap_dump_ftell.3pcap b/contrib/libpcap/pcap_dump_ftell.3pcap
index 6d5c8280589f..757e9482bafd 100644
--- a/contrib/libpcap/pcap_dump_ftell.3pcap
+++ b/contrib/libpcap/pcap_dump_ftell.3pcap
@@ -17,7 +17,7 @@
.\" WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
.\" MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
.\"
-.TH PCAP_DUMP_FTELL 3PCAP "5 April 2008"
+.TH PCAP_DUMP_FTELL 3PCAP "3 January 2014"
.SH NAME
pcap_dump_ftell \- get the current file offset for a savefile being written
.SH SYNOPSIS
diff --git a/contrib/libpcap/pcap_dump_open.3pcap.in b/contrib/libpcap/pcap_dump_open.3pcap.in
index 47ea321e4872..3f91d13bf88a 100644
--- a/contrib/libpcap/pcap_dump_open.3pcap.in
+++ b/contrib/libpcap/pcap_dump_open.3pcap.in
@@ -17,7 +17,7 @@
.\" WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
.\" MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
.\"
-.TH PCAP_DUMP_OPEN 3PCAP "5 April 2008"
+.TH PCAP_DUMP_OPEN 3PCAP "16 February 2015"
.SH NAME
pcap_dump_open, pcap_dump_fopen \- open a file to which to write packets
.SH SYNOPSIS
@@ -29,6 +29,7 @@ pcap_dump_open, pcap_dump_fopen \- open a file to which to write packets
.LP
.ft B
pcap_dumper_t *pcap_dump_open(pcap_t *p, const char *fname);
+pcap_dumper_t *pcap_dump_open_append(pcap_t *p, const char *fname);
pcap_dumper_t *pcap_dump_fopen(pcap_t *p, FILE *fp);
.ft
.fi
@@ -60,9 +61,19 @@ or returned by an earlier call to
.BR pcap_open_live() ,
or
.BR pcap_open_dead() .
-The link-layer type and snapshot length from
+The time stamp precision, link-layer type, and snapshot length from
.I p
are used as the link-layer type and snapshot length of the output file.
+.PP
+.B pcap_dump_open_append()
+is like
+.B pcap_dump_open
+but does not create the file if it does not exist and, if it does
+already exist, and is a pcap file with the same byte order as the host
+opening the file, and has the same time stamp precision, link-layer
+header type, and snapshot length as
+.IR p ,
+it will write new packets at the end of the file.
.SH RETURN VALUES
A pointer to a
.B pcap_dumper_t
diff --git a/contrib/libpcap/pcap_file.3pcap b/contrib/libpcap/pcap_file.3pcap
index 7b18c81dc252..cd6b06bb8a40 100644
--- a/contrib/libpcap/pcap_file.3pcap
+++ b/contrib/libpcap/pcap_file.3pcap
@@ -17,7 +17,7 @@
.\" WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
.\" MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
.\"
-.TH PCAP_FILE 3PCAP "5 April 2008"
+.TH PCAP_FILE 3PCAP "3 January 2014"
.SH NAME
pcap_file \- get the standard I/O stream for a savefile being read
.SH SYNOPSIS
diff --git a/contrib/libpcap/pcap_fileno.3pcap b/contrib/libpcap/pcap_fileno.3pcap
index 39d068b44ece..7aeb06947b1b 100644
--- a/contrib/libpcap/pcap_fileno.3pcap
+++ b/contrib/libpcap/pcap_fileno.3pcap
@@ -17,7 +17,7 @@
.\" WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
.\" MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
.\"
-.TH PCAP_FILENO 3PCAP "3 November 2009"
+.TH PCAP_FILENO 3PCAP "7 April 2014"
.SH NAME
pcap_fileno \- get the file descriptor for a live capture
.SH SYNOPSIS
diff --git a/contrib/libpcap/pcap_findalldevs.3pcap b/contrib/libpcap/pcap_findalldevs.3pcap
index 00bb911f9132..2dd3e59b9c93 100644
--- a/contrib/libpcap/pcap_findalldevs.3pcap
+++ b/contrib/libpcap/pcap_findalldevs.3pcap
@@ -17,7 +17,7 @@
.\" WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
.\" MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
.\"
-.TH PCAP_FINDALLDEVS 3PCAP "10 January 2014"
+.TH PCAP_FINDALLDEVS 3PCAP "7 April 2014"
.SH NAME
pcap_findalldevs, pcap_freealldevs \- get a list of capture devices, and
free that list
diff --git a/contrib/libpcap/pcap_freecode.3pcap b/contrib/libpcap/pcap_freecode.3pcap
index c3c3ea6e0c96..fac4b3df2a6d 100644
--- a/contrib/libpcap/pcap_freecode.3pcap
+++ b/contrib/libpcap/pcap_freecode.3pcap
@@ -17,7 +17,7 @@
.\" WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
.\" MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
.\"
-.TH PCAP_FREECODE 3PCAP "5 April 2008"
+.TH PCAP_FREECODE 3PCAP "3 January 2014"
.SH NAME
pcap_freecode \- free a BPF program
.SH SYNOPSIS
diff --git a/contrib/libpcap/pcap_get_selectable_fd.3pcap b/contrib/libpcap/pcap_get_selectable_fd.3pcap
index 6ae06a1bc429..86b0c2683fa3 100644
--- a/contrib/libpcap/pcap_get_selectable_fd.3pcap
+++ b/contrib/libpcap/pcap_get_selectable_fd.3pcap
@@ -17,7 +17,7 @@
.\" WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
.\" MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
.\"
-.TH PCAP_GET_SELECTABLE_FD 3PCAP "22 July 2011"
+.TH PCAP_GET_SELECTABLE_FD 3PCAP "18 October 2014"
.SH NAME
pcap_get_selectable_fd \- get a file descriptor on which a select() can
be done for a live capture
@@ -36,9 +36,9 @@ int pcap_get_selectable_fd(pcap_t *p);
returns, on UNIX, a file descriptor number for a file descriptor on
which one can
do a
-.B select()
-or
-.B poll()
+.BR select() ,
+.BR poll() ,
+or other such call
to wait for it to be possible to read packets without blocking, if such
a descriptor exists, or \-1, if no such descriptor exists. Some network
devices opened with
@@ -54,6 +54,12 @@ or
(for example, regular network devices on FreeBSD 4.3 and 4.4, and Endace
DAG devices), so \-1 is returned for those devices.
.PP
+Note that a descriptor on which a read can be done without blocking may,
+on some platforms, not have any packets to read if the read timeout has
+expired. A call to
+.B pcap_dispatch()
+will return 0 in this case, but will not block.
+.PP
Note that in:
.IP
FreeBSD prior to FreeBSD 4.6;
diff --git a/contrib/libpcap/pcap_get_tstamp_precision.3pcap.in b/contrib/libpcap/pcap_get_tstamp_precision.3pcap.in
index 656c14291ff0..285e77095e43 100644
--- a/contrib/libpcap/pcap_get_tstamp_precision.3pcap.in
+++ b/contrib/libpcap/pcap_get_tstamp_precision.3pcap.in
@@ -19,7 +19,7 @@
.\"IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
.\"WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
-.TH PCAP_GET_TSTAMP_PRECISION 3PCAP "27 August 2013"
+.TH PCAP_GET_TSTAMP_PRECISION 3PCAP "18 December 2013"
.SH NAME
pcap_get_tstamp_precision \- get the time stamp precision returned in
captures
diff --git a/contrib/libpcap/pcap_geterr.3pcap b/contrib/libpcap/pcap_geterr.3pcap
index fcabec3b5bed..2e99c37de31c 100644
--- a/contrib/libpcap/pcap_geterr.3pcap
+++ b/contrib/libpcap/pcap_geterr.3pcap
@@ -17,7 +17,7 @@
.\" WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
.\" MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
.\"
-.TH PCAP_GETERR 3PCAP "5 April 2008"
+.TH PCAP_GETERR 3PCAP "3 January 2014"
.SH NAME
pcap_geterr, pcap_perror \- get or print libpcap error message text
.SH SYNOPSIS
@@ -28,7 +28,7 @@ pcap_geterr, pcap_perror \- get or print libpcap error message text
.LP
.ft B
char *pcap_geterr(pcap_t *p);
-void pcap_perror(pcap_t *p, char *prefix);
+void pcap_perror(pcap_t *p, const char *prefix);
.ft
.fi
.SH DESCRIPTION
diff --git a/contrib/libpcap/pcap_inject.3pcap b/contrib/libpcap/pcap_inject.3pcap
index 7ccdf2c506c9..ff9792d20966 100644
--- a/contrib/libpcap/pcap_inject.3pcap
+++ b/contrib/libpcap/pcap_inject.3pcap
@@ -17,7 +17,7 @@
.\" WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
.\" MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
.\"
-.TH PCAP_INJECT 3PCAP "5 April 2008"
+.TH PCAP_INJECT 3PCAP "3 January 2014"
.SH NAME
pcap_inject, pcap_sendpacket \- transmit a packet
.SH SYNOPSIS
diff --git a/contrib/libpcap/pcap_is_swapped.3pcap b/contrib/libpcap/pcap_is_swapped.3pcap
index a120616d3291..c4e62ae54769 100644
--- a/contrib/libpcap/pcap_is_swapped.3pcap
+++ b/contrib/libpcap/pcap_is_swapped.3pcap
@@ -17,7 +17,7 @@
.\" WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
.\" MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
.\"
-.TH PCAP_IS_SWAPPED 3PCAP "17 September 2013"
+.TH PCAP_IS_SWAPPED 3PCAP "7 April 2014"
.SH NAME
pcap_is_swapped \- find out whether a savefile has the native byte order
.SH SYNOPSIS
diff --git a/contrib/libpcap/pcap_lib_version.3pcap b/contrib/libpcap/pcap_lib_version.3pcap
index 3ec2e32d5f56..4b86b2d5771c 100644
--- a/contrib/libpcap/pcap_lib_version.3pcap
+++ b/contrib/libpcap/pcap_lib_version.3pcap
@@ -17,7 +17,7 @@
.\" WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
.\" MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
.\"
-.TH PCAP_LIB_VERSION 3PCAP "5 April 2008"
+.TH PCAP_LIB_VERSION 3PCAP "3 January 2014"
.SH NAME
pcap_lib_version \- get the version information for libpcap
.SH SYNOPSIS
diff --git a/contrib/libpcap/pcap_list_datalinks.3pcap.in b/contrib/libpcap/pcap_list_datalinks.3pcap.in
index 607efdecafc0..9f52b63bb98c 100644
--- a/contrib/libpcap/pcap_list_datalinks.3pcap.in
+++ b/contrib/libpcap/pcap_list_datalinks.3pcap.in
@@ -17,7 +17,7 @@
.\" WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
.\" MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
.\"
-.TH PCAP_LIST_DATALINKS 3PCAP "17 September 2013"
+.TH PCAP_LIST_DATALINKS 3PCAP "8 March 2015"
.SH NAME
pcap_list_datalinks, pcap_free_datalinks \- get a list of link-layer header
types supported by a capture device, and free that list
@@ -38,7 +38,7 @@ is used to get a list of the supported link-layer header types of the
interface associated with the pcap descriptor.
.B pcap_list_datalinks()
allocates an array to hold the list and sets
-.IR *dlt_buf
+.IR *dlt_buf
to point to that array.
.LP
The caller is responsible for freeing the array with
diff --git a/contrib/libpcap/pcap_list_tstamp_types.3pcap.in b/contrib/libpcap/pcap_list_tstamp_types.3pcap.in
index 66d3d6679310..a139324f31c3 100644
--- a/contrib/libpcap/pcap_list_tstamp_types.3pcap.in
+++ b/contrib/libpcap/pcap_list_tstamp_types.3pcap.in
@@ -18,7 +18,7 @@
.\" WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
.\" MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
.\"
-.TH PCAP_LIST_TSTAMP_TYPES 3PCAP "21 August 2010"
+.TH PCAP_LIST_TSTAMP_TYPES 3PCAP "22 August 2010"
.SH NAME
pcap_list_tstamp_types, pcap_free_tstamp_types \- get a list of time
stamp types supported by a capture device, and free that list
diff --git a/contrib/libpcap/pcap_lookupdev.3pcap b/contrib/libpcap/pcap_lookupdev.3pcap
index 79dda429e437..aaa3a2013aa7 100644
--- a/contrib/libpcap/pcap_lookupdev.3pcap
+++ b/contrib/libpcap/pcap_lookupdev.3pcap
@@ -17,7 +17,7 @@
.\" WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
.\" MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
.\"
-.TH PCAP_LOOKUPDEV 3PCAP "5 April 2008"
+.TH PCAP_LOOKUPDEV 3PCAP "3 January 2014"
.SH NAME
pcap_lookupdev \- find the default device on which to capture
.SH SYNOPSIS
diff --git a/contrib/libpcap/pcap_lookupnet.3pcap b/contrib/libpcap/pcap_lookupnet.3pcap
index a3d14ae7f477..c38ff3a8e339 100644
--- a/contrib/libpcap/pcap_lookupnet.3pcap
+++ b/contrib/libpcap/pcap_lookupnet.3pcap
@@ -17,7 +17,7 @@
.\" WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
.\" MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
.\"
-.TH PCAP_LOOKUPNET 3PCAP "5 April 2008"
+.TH PCAP_LOOKUPNET 3PCAP "3 January 2014"
.SH NAME
pcap_lookupnet \- find the IPv4 network number and netmask for a device
.SH SYNOPSIS
diff --git a/contrib/libpcap/pcap_loop.3pcap b/contrib/libpcap/pcap_loop.3pcap
index d18dc06c28b8..0eaf6e5e598c 100644
--- a/contrib/libpcap/pcap_loop.3pcap
+++ b/contrib/libpcap/pcap_loop.3pcap
@@ -17,7 +17,7 @@
.\" WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
.\" MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
.\"
-.TH PCAP_LOOP 3PCAP "13 October 2013"
+.TH PCAP_LOOP 3PCAP "18 October 2014"
.SH NAME
pcap_loop, pcap_dispatch \- process packets from a live capture or savefile
.SH SYNOPSIS
@@ -77,6 +77,13 @@ causes all the packets received in one buffer to be processed when
reading a live capture, and causes all the packets in the file to be
processed when reading a ``savefile''.
.PP
+Note that, when doing a live capture on some platforms, if the read
+timeout expires when there are no packets available,
+.B pcap_dispatch()
+will return 0, even when not in non-blocking mode, as there are no
+packets to process. Applications should be prepared for this to happen,
+but must not rely on it happening.
+.PP
.ft B
(In older versions of libpcap, the behavior when
\fIcnt\fP
diff --git a/contrib/libpcap/pcap_major_version.3pcap b/contrib/libpcap/pcap_major_version.3pcap
index a0858380cb14..8334e16c34c6 100644
--- a/contrib/libpcap/pcap_major_version.3pcap
+++ b/contrib/libpcap/pcap_major_version.3pcap
@@ -17,7 +17,7 @@
.\" WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
.\" MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
.\"
-.TH PCAP_MAJOR_VERSION 3PCAP "21 December 2011"
+.TH PCAP_MAJOR_VERSION 3PCAP "7 April 2014"
.SH NAME
pcap_major_version, pcap_minor_version \- get the version number of a savefile
.SH SYNOPSIS
diff --git a/contrib/libpcap/pcap_next_ex.3pcap b/contrib/libpcap/pcap_next_ex.3pcap
index c310c2f004b5..d69e7283d826 100644
--- a/contrib/libpcap/pcap_next_ex.3pcap
+++ b/contrib/libpcap/pcap_next_ex.3pcap
@@ -17,7 +17,7 @@
.\" WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
.\" MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
.\"
-.TH PCAP_NEXT_EX 3PCAP "13 October 2013"
+.TH PCAP_NEXT_EX 3PCAP "7 April 2014"
.SH NAME
pcap_next_ex, pcap_next \- read the next packet from a pcap_t
.SH SYNOPSIS
diff --git a/contrib/libpcap/pcap_offline_filter.3pcap b/contrib/libpcap/pcap_offline_filter.3pcap
index b471c6a7403e..08c0b66b3349 100644
--- a/contrib/libpcap/pcap_offline_filter.3pcap
+++ b/contrib/libpcap/pcap_offline_filter.3pcap
@@ -17,7 +17,7 @@
.\" WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
.\" MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
.\"
-.TH PCAP_OFFLINE_FILTER 3PCAP "25 November 2012"
+.TH PCAP_OFFLINE_FILTER 3PCAP "7 April 2014"
.SH NAME
pcap_offline_filter \- check whether a filter matches a packet
.SH SYNOPSIS
diff --git a/contrib/libpcap/pcap_open_dead.3pcap.in b/contrib/libpcap/pcap_open_dead.3pcap.in
index 2d1b48cca75d..a3dc5921074b 100644
--- a/contrib/libpcap/pcap_open_dead.3pcap.in
+++ b/contrib/libpcap/pcap_open_dead.3pcap.in
@@ -17,7 +17,7 @@
.\" WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
.\" MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
.\"
-.TH PCAP_OPEN_DEAD 3PCAP "1 July 2013"
+.TH PCAP_OPEN_DEAD 3PCAP "3 January 2014"
.SH NAME
pcap_open_dead, pcap_open_dead_with_tstamp_precision \- open a fake
pcap_t for compiling filters or opening a capture for output
diff --git a/contrib/libpcap/pcap_open_live.3pcap b/contrib/libpcap/pcap_open_live.3pcap
index 715994b0fd0c..8c5d47469b6a 100644
--- a/contrib/libpcap/pcap_open_live.3pcap
+++ b/contrib/libpcap/pcap_open_live.3pcap
@@ -17,7 +17,7 @@
.\" WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
.\" MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
.\"
-.TH PCAP_OPEN_LIVE 3PCAP "5 April 2008"
+.TH PCAP_OPEN_LIVE 3PCAP "3 January 2014"
.SH NAME
pcap_open_live \- open a device for capturing
.SH SYNOPSIS
diff --git a/contrib/libpcap/pcap_open_offline.3pcap.in b/contrib/libpcap/pcap_open_offline.3pcap.in
index 72397298d8ae..7fe551eefa28 100644
--- a/contrib/libpcap/pcap_open_offline.3pcap.in
+++ b/contrib/libpcap/pcap_open_offline.3pcap.in
@@ -17,7 +17,7 @@
.\" WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
.\" MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
.\"
-.TH PCAP_OPEN_OFFLINE 3PCAP "1 July 2013"
+.TH PCAP_OPEN_OFFLINE 3PCAP "3 January 2014"
.SH NAME
pcap_open_offline, pcap_open_offline_with_tstamp_precision,
pcap_fopen_offline, pcap_fopen_offline_with_tstamp_precision \- open a saved capture file for reading
diff --git a/contrib/libpcap/pcap_set_buffer_size.3pcap b/contrib/libpcap/pcap_set_buffer_size.3pcap
index fea1df74a9a5..684f739cc6b9 100644
--- a/contrib/libpcap/pcap_set_buffer_size.3pcap
+++ b/contrib/libpcap/pcap_set_buffer_size.3pcap
@@ -17,7 +17,7 @@
.\" WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
.\" MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
.\"
-.TH PCAP_SET_BUFFER_SIZE 3PCAP "5 April 2008"
+.TH PCAP_SET_BUFFER_SIZE 3PCAP "3 January 2014"
.SH NAME
pcap_set_buffer_size \- set the buffer size for a not-yet-activated
capture handle
diff --git a/contrib/libpcap/pcap_set_datalink.3pcap b/contrib/libpcap/pcap_set_datalink.3pcap
index 60a7bfc81c80..24d57a541c83 100644
--- a/contrib/libpcap/pcap_set_datalink.3pcap
+++ b/contrib/libpcap/pcap_set_datalink.3pcap
@@ -17,7 +17,7 @@
.\" WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
.\" MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
.\"
-.TH PCAP_SET_DATALINK 3PCAP "22 August 2010"
+.TH PCAP_SET_DATALINK 3PCAP "3 January 2014"
.SH NAME
pcap_set_datalink \- set the link-layer header type to be used by a
capture device
diff --git a/contrib/libpcap/pcap_set_immediate_mode.3pcap b/contrib/libpcap/pcap_set_immediate_mode.3pcap
index 87ec98bb146b..b3ad24315189 100644
--- a/contrib/libpcap/pcap_set_immediate_mode.3pcap
+++ b/contrib/libpcap/pcap_set_immediate_mode.3pcap
@@ -18,7 +18,7 @@
.\" WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
.\" MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
.\"
-.TH PCAP_SET_IMMEDIATE_MODE 3PCAP "8 May 2013"
+.TH PCAP_SET_IMMEDIATE_MODE 3PCAP "5 December 2013"
.SH NAME
pcap_set_immediate_mode \- set immediate mode for a not-yet-activated capture
handle
diff --git a/contrib/libpcap/pcap_set_promisc.3pcap b/contrib/libpcap/pcap_set_promisc.3pcap
index 5d1757275a76..fcd797a34c50 100644
--- a/contrib/libpcap/pcap_set_promisc.3pcap
+++ b/contrib/libpcap/pcap_set_promisc.3pcap
@@ -17,7 +17,7 @@
.\" WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
.\" MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
.\"
-.TH PCAP_SET_PROMISC 3PCAP "5 April 2008"
+.TH PCAP_SET_PROMISC 3PCAP "3 January 2014"
.SH NAME
pcap_set_promisc \- set promiscuous mode for a not-yet-activated
capture handle
diff --git a/contrib/libpcap/pcap_set_rfmon.3pcap b/contrib/libpcap/pcap_set_rfmon.3pcap
index a386e8b1f2a3..691518a5b28c 100644
--- a/contrib/libpcap/pcap_set_rfmon.3pcap
+++ b/contrib/libpcap/pcap_set_rfmon.3pcap
@@ -17,7 +17,7 @@
.\" WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
.\" MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
.\"
-.TH PCAP_SET_RFMON 3PCAP "5 April 2008"
+.TH PCAP_SET_RFMON 3PCAP "3 January 2014"
.SH NAME
pcap_set_rfmon \- set monitor mode for a not-yet-activated capture
handle
diff --git a/contrib/libpcap/pcap_set_snaplen.3pcap b/contrib/libpcap/pcap_set_snaplen.3pcap
index 8080ea12940d..44eb15488a11 100644
--- a/contrib/libpcap/pcap_set_snaplen.3pcap
+++ b/contrib/libpcap/pcap_set_snaplen.3pcap
@@ -17,7 +17,7 @@
.\" WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
.\" MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
.\"
-.TH PCAP_SET_SNAPLEN 3PCAP "5 April 2008"
+.TH PCAP_SET_SNAPLEN 3PCAP "3 January 2014"
.SH NAME
pcap_set_snaplen \- set the snapshot length for a not-yet-activated
capture handle
diff --git a/contrib/libpcap/pcap_set_timeout.3pcap b/contrib/libpcap/pcap_set_timeout.3pcap
index b7282037b3e7..a89327f2ebd2 100644
--- a/contrib/libpcap/pcap_set_timeout.3pcap
+++ b/contrib/libpcap/pcap_set_timeout.3pcap
@@ -17,7 +17,7 @@
.\" WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
.\" MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
.\"
-.TH PCAP_SET_TIMEOUT 3PCAP "16 April 2014"
+.TH PCAP_SET_TIMEOUT 3PCAP "1 December 2015"
.SH NAME
pcap_set_timeout \- set the read timeout for a not-yet-activated
capture handle
@@ -36,10 +36,15 @@ sets the read timeout that will be used on a capture handle when
the handle is activated to
.IR to_ms ,
which is in units of milliseconds.
+.LP
+The behavior, if the timeout isn't specified, is undefined. We
+recommend always setting the timeout to a non-zero value unless
+immediate mode is set, in which case the timeout has no effect.
.SH RETURN VALUE
.B pcap_set_timeout()
returns 0 on success or
.B PCAP_ERROR_ACTIVATED
if called on a capture handle that has been activated.
.SH SEE ALSO
-pcap(3PCAP), pcap_create(3PCAP), pcap_activate(3PCAP)
+pcap(3PCAP), pcap_create(3PCAP), pcap_activate(3PCAP),
+pcap_set_immediate_mode(3PCAP)
diff --git a/contrib/libpcap/pcap_set_tstamp_precision.3pcap.in b/contrib/libpcap/pcap_set_tstamp_precision.3pcap.in
index 053a4c6bcef5..57c4ea301cf3 100644
--- a/contrib/libpcap/pcap_set_tstamp_precision.3pcap.in
+++ b/contrib/libpcap/pcap_set_tstamp_precision.3pcap.in
@@ -19,7 +19,7 @@
.\"IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
.\"WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
-.TH PCAP_SET_TSTAMP_PRECISION 3PCAP "27 August 2013"
+.TH PCAP_SET_TSTAMP_PRECISION 3PCAP "5 February 2015"
.SH NAME
pcap_set_tstamp_precision \- set the time stamp precision returned in
captures
@@ -48,7 +48,7 @@ use options
.B PCAP_TSTAMP_PRECISION_NANO
to request desired precision. By default, time stamps are in microseconds.
.SH RETURN VALUE
-.B pcap_set_tstamp_type()
+.B pcap_set_tstamp_precision()
returns 0 on success if the specified time stamp precision is expected to be
supported by the operating system,
.B PCAP_ERROR_TSTAMP_PRECISION_NOTSUP
diff --git a/contrib/libpcap/pcap_set_tstamp_type.3pcap.in b/contrib/libpcap/pcap_set_tstamp_type.3pcap.in
index 261c315200c0..e58cdd4b0d77 100644
--- a/contrib/libpcap/pcap_set_tstamp_type.3pcap.in
+++ b/contrib/libpcap/pcap_set_tstamp_type.3pcap.in
@@ -18,7 +18,7 @@
.\" WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
.\" MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
.\"
-.TH PCAP_SET_TSTAMP_TYPE 3PCAP "21 August 2010"
+.TH PCAP_SET_TSTAMP_TYPE 3PCAP "5 December 2014"
.SH NAME
pcap_set_tstamp_type \- set the time stamp type to be used by a
capture device
@@ -52,7 +52,7 @@ for a list of all the time stamp types.
returns 0 on success if the specified time stamp type is expected to be
supported by the capture device,
.B PCAP_WARNING_TSTAMP_TYPE_NOTSUP
-on success if the specified time stamp type is not supported by the
+if the specified time stamp type is not supported by the
capture device,
.B PCAP_ERROR_ACTIVATED
if called on a capture handle that has been activated, and
diff --git a/contrib/libpcap/pcap_setdirection.3pcap b/contrib/libpcap/pcap_setdirection.3pcap
index 70920b174aba..11945f5421d5 100644
--- a/contrib/libpcap/pcap_setdirection.3pcap
+++ b/contrib/libpcap/pcap_setdirection.3pcap
@@ -17,7 +17,7 @@
.\" WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
.\" MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
.\"
-.TH PCAP_SETDIRECTION 3PCAP "5 April 2008"
+.TH PCAP_SETDIRECTION 3PCAP "8 March 2015"
.SH NAME
pcap_setdirection \- set the direction for which packets will be captured
.SH SYNOPSIS
@@ -37,7 +37,7 @@ is used to specify a direction that packets will be captured.
is one of the constants
.BR PCAP_D_IN ,
.B PCAP_D_OUT
-or
+or
.BR PCAP_D_INOUT .
.B PCAP_D_IN
will only capture packets received by the device,
diff --git a/contrib/libpcap/pcap_setfilter.3pcap b/contrib/libpcap/pcap_setfilter.3pcap
index c737797f3108..6efd25398281 100644
--- a/contrib/libpcap/pcap_setfilter.3pcap
+++ b/contrib/libpcap/pcap_setfilter.3pcap
@@ -17,7 +17,7 @@
.\" WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
.\" MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
.\"
-.TH PCAP_SETFILTER 3PCAP "13 May 2008"
+.TH PCAP_SETFILTER 3PCAP "7 April 2014"
.SH NAME
pcap_setfilter \- set the filter
.SH SYNOPSIS
diff --git a/contrib/libpcap/pcap_setnonblock.3pcap b/contrib/libpcap/pcap_setnonblock.3pcap
index 37b22031d451..695912701f5c 100644
--- a/contrib/libpcap/pcap_setnonblock.3pcap
+++ b/contrib/libpcap/pcap_setnonblock.3pcap
@@ -17,7 +17,7 @@
.\" WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
.\" MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
.\"
-.TH PCAP_SETNONBLOCK 3PCAP "5 April 2008"
+.TH PCAP_SETNONBLOCK 3PCAP "18 October 2014"
.SH NAME
pcap_setnonblock, pcap_getnonblock \- set or get the state of
non-blocking mode on a capture device
@@ -57,6 +57,14 @@ immediately rather than blocking waiting for packets to arrive.
and
.B pcap_next()
will not work in ``non-blocking'' mode.
+.PP
+When first activated with
+.B pcap_activate()
+or opened with
+.B pcap_open_live() ,
+a capture handle is not in ``non-blocking mode''; a call to
+.B pcap_setnonblock()
+is required in order to put it into ``non-blocking'' mode.
.SH RETURN VALUE
.B pcap_getnonblock()
returns the current ``non-blocking'' state of the capture descriptor; it
diff --git a/contrib/libpcap/pcap_snapshot.3pcap b/contrib/libpcap/pcap_snapshot.3pcap
index 47eb42a3843f..7af8c33dc437 100644
--- a/contrib/libpcap/pcap_snapshot.3pcap
+++ b/contrib/libpcap/pcap_snapshot.3pcap
@@ -17,7 +17,7 @@
.\" WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
.\" MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
.\"
-.TH PCAP_SNAPSHOT 3PCAP "17 September 2013"
+.TH PCAP_SNAPSHOT 3PCAP "7 April 2014"
.SH NAME
pcap_snapshot \- get the snapshot length
.SH SYNOPSIS
diff --git a/contrib/libpcap/pcap_stats.3pcap b/contrib/libpcap/pcap_stats.3pcap
index 159054e74485..2dce4b501c52 100644
--- a/contrib/libpcap/pcap_stats.3pcap
+++ b/contrib/libpcap/pcap_stats.3pcap
@@ -17,7 +17,7 @@
.\" WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
.\" MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
.\"
-.TH PCAP_STATS 3PCAP "7 September 2009"
+.TH PCAP_STATS 3PCAP "3 January 2014"
.SH NAME
pcap_stats \- get capture statistics
.SH SYNOPSIS
diff --git a/contrib/libpcap/pcap_statustostr.3pcap b/contrib/libpcap/pcap_statustostr.3pcap
index 77b8c5f1079c..9c2057ae4f95 100644
--- a/contrib/libpcap/pcap_statustostr.3pcap
+++ b/contrib/libpcap/pcap_statustostr.3pcap
@@ -17,7 +17,7 @@
.\" WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
.\" MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
.\"
-.TH PCAP_STATUSTOSTR 3PCAP "9 April 2008"
+.TH PCAP_STATUSTOSTR 3PCAP "3 January 2014"
.SH NAME
pcap_statustostr \- convert a PCAP_ERROR_ or PCAP_WARNING_ value to a string
.SH SYNOPSIS
diff --git a/contrib/libpcap/pcap_strerror.3pcap b/contrib/libpcap/pcap_strerror.3pcap
index 71851623ddd0..7c7d53f5a941 100644
--- a/contrib/libpcap/pcap_strerror.3pcap
+++ b/contrib/libpcap/pcap_strerror.3pcap
@@ -17,7 +17,7 @@
.\" WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
.\" MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
.\"
-.TH PCAP_STRERROR 3PCAP "4 April 2008"
+.TH PCAP_STRERROR 3PCAP "3 January 2014"
.SH NAME
pcap_strerror \- convert an errno value to a string
.SH SYNOPSIS
diff --git a/contrib/libpcap/pcap_tstamp_type_name_to_val.3pcap b/contrib/libpcap/pcap_tstamp_type_name_to_val.3pcap
index 8fcc4d75c00f..ac2e35dd76da 100644
--- a/contrib/libpcap/pcap_tstamp_type_name_to_val.3pcap
+++ b/contrib/libpcap/pcap_tstamp_type_name_to_val.3pcap
@@ -18,7 +18,7 @@
.\" WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
.\" MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
.\"
-.TH PCAP_TSTAMP_TYPE_NAME_TO_VAL 3PCAP "21 August 2010"
+.TH PCAP_TSTAMP_TYPE_NAME_TO_VAL 3PCAP "5 December 2014"
.SH NAME
pcap_tstamp_type_name_to_val \- get the time stamp type value
corresponding to a time stamp type name
@@ -38,7 +38,7 @@ translates a time stamp type name to the corresponding time stamp type
value. The translation is case-insensitive.
.SH RETURN VALUE
.B pcap_tstamp_type_name_to_val()
-returns 0 on success and
+returns time stamp type value on success and
.B PCAP_ERROR
on failure.
.SH SEE ALSO
diff --git a/contrib/libpcap/pcap_tstamp_type_val_to_name.3pcap b/contrib/libpcap/pcap_tstamp_type_val_to_name.3pcap
index 903cea7b11a2..261554ec798a 100644
--- a/contrib/libpcap/pcap_tstamp_type_val_to_name.3pcap
+++ b/contrib/libpcap/pcap_tstamp_type_val_to_name.3pcap
@@ -18,7 +18,7 @@
.\" WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
.\" MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
.\"
-.TH PCAP_TSTAMP_TYPE_VAL_TO_NAME 3PCAP "21 August 2010"
+.TH PCAP_TSTAMP_TYPE_VAL_TO_NAME 3PCAP "12 December 2013"
.SH NAME
pcap_tstamp_type_val_to_name, pcap_tstamp_type_val_to_description \- get
a name or description for a time stamp type value
diff --git a/contrib/libpcap/pcap_version.h.in b/contrib/libpcap/pcap_version.h.in
new file mode 100644
index 000000000000..3104c8ea1579
--- /dev/null
+++ b/contrib/libpcap/pcap_version.h.in
@@ -0,0 +1,13 @@
+/*
+ * We make the version string static, and return a pointer to it, rather
+ * than exporting the version string directly. On at least some UNIXes,
+ * if you import data from a shared library into an program, the data is
+ * bound into the program binary, so if the string in the version of the
+ * library with which the program was linked isn't the same as the
+ * string in the version of the library with which the program is being
+ * run, various undesirable things may happen (warnings, the string
+ * being the one from the version of the library with which the program
+ * was linked, or even weirder things, such as the string being the one
+ * from the library but being truncated).
+ */
+static const char pcap_version_string[] = "libpcap version %%LIBPCAP_VERSION%%";
diff --git a/contrib/libpcap/portability.h b/contrib/libpcap/portability.h
new file mode 100644
index 000000000000..8a6bf40e8bb4
--- /dev/null
+++ b/contrib/libpcap/portability.h
@@ -0,0 +1,216 @@
+/*
+ * Copyright (c) 1994, 1995, 1996
+ * The Regents of the University of California. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the Computer Systems
+ * Engineering Group at Lawrence Berkeley Laboratory.
+ * 4. Neither the name of the University nor of the Laboratory may be used
+ * to endorse or promote products derived from this software without
+ * specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#ifndef portability_h
+#define portability_h
+
+/*
+ * Helpers for portability between Windows and UN*X and between different
+ * flavors of UN*X.
+ */
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#ifndef HAVE_STRLCPY
+ /*
+ * Macro that does the same thing as strlcpy().
+ */
+ #ifdef _MSC_VER
+ /*
+ * strncpy_s() is supported at least back to Visual
+ * Studio 2005.
+ */
+ #define strlcpy(x, y, z) \
+ strncpy_s((x), (z), (y), _TRUNCATE)
+
+ #else
+ #define strlcpy(x, y, z) \
+ (strncpy((x), (y), (z)), \
+ ((z) <= 0 ? 0 : ((x)[(z) - 1] = '\0')), \
+ (void) strlen((y)))
+ #endif
+#endif
+
+/*
+ * For flagging arguments as format strings in MSVC.
+ */
+#if _MSC_VER >= 1400
+ #include <sal.h>
+ #if _MSC_VER > 1400
+ #define FORMAT_STRING(p) _Printf_format_string_ p
+ #else
+ #define FORMAT_STRING(p) __format_string p
+ #endif
+#else
+ #define FORMAT_STRING(p) p
+#endif
+
+#ifdef _MSC_VER
+ #define strdup _strdup
+ #define sscanf sscanf_s
+ #define setbuf(x, y) \
+ setvbuf((x), (y), _IONBF, 0)
+ #define fopen(x, y) \
+ fopen_safe((x), (y))
+ FILE *fopen_safe(const char *filename, const char* mode);
+#endif
+
+#if defined(_MSC_VER) || defined(__MINGW32__)
+ #define strlcat(x, y, z) \
+ strncat_s((x), (z), (y), _TRUNCATE)
+#endif
+
+#ifdef _MSC_VER
+ /*
+ * MSVC.
+ */
+ #if _MSC_VER >= 1900
+ /*
+ * VS 2015 or newer; we have snprintf() function.
+ */
+ #define HAVE_SNPRINTF
+ #endif
+#endif
+
+/*
+ * On Windows, snprintf(), with that name and with C99 behavior - i.e.,
+ * guaranteeing that the formatted string is null-terminated - didn't
+ * appear until Visual Studio 2015. Prior to that, the C runtime had
+ * only _snprintf(), which *doesn't* guarantee that the string is
+ * null-terminated if it is truncated due to the buffer being too
+ * small. We therefore can't just define snprintf to be _snprintf
+ * and define vsnprintf to be _vsnprintf, as we're relying on null-
+ * termination of strings in all cases.
+ *
+ * We also want to allow this to be built with versions of Visual Studio
+ * prior to VS 2015, so we can't rely on snprintf() being present.
+ *
+ * And we want to make sure that, if we support plugins in the future,
+ * a routine with C99 snprintf() behavior will be available to them.
+ * We also don't want it to collide with the C library snprintf() if
+ * there is one.
+ *
+ * So we make pcap_snprintf() and pcap_vsnprintf() available, either by
+ * #defining them to be snprintf or vsnprintf, respectively, or by
+ * defining our own versions and exporting them.
+ */
+#ifdef HAVE_SNPRINTF
+#define pcap_snprintf snprintf
+#else
+extern int pcap_snprintf(char *, size_t, FORMAT_STRING(const char *), ...)
+#ifdef __ATTRIBUTE___FORMAT_OK
+ __attribute__((format (printf, 3, 4)))
+#endif /* __ATTRIBUTE___FORMAT_OK */
+ ;
+#endif
+
+#ifdef HAVE_VSNPRINTF
+#define pcap_vsnprintf vsnprintf
+#else
+extern int pcap_vsnprintf(char *, size_t, const char *, va_list ap);
+#endif
+
+#ifdef HAVE_STRTOK_R
+ #define pcap_strtok_r strtok_r
+#else
+ #ifdef _MSC_VER
+ /*
+ * Microsoft gives it a different name.
+ */
+ #define pcap_strtok_r strtok_s
+ #else
+ /*
+ * Define it ourselves.
+ */
+ #define NEED_STRTOK_R
+ extern int pcap_strtok_r(char *, const char *, char **);
+ #endif
+#endif /* HAVE_STRTOK_R */
+
+#ifdef _WIN32
+ /*
+ * These may be defined by <inttypes.h>.
+ *
+ * XXX - for MSVC, we always want the _MSC_EXTENSIONS versions.
+ * What about other compilers? If, as the MinGW Web site says MinGW
+ * does, the other compilers just use Microsoft's run-time library,
+ * then they should probably use the _MSC_EXTENSIONS even if the
+ * compiler doesn't define _MSC_EXTENSIONS.
+ *
+ * XXX - we currently aren't using any of these, but this allows
+ * their use in the future.
+ */
+ #ifndef PRId64
+ #ifdef _MSC_EXTENSIONS
+ #define PRId64 "I64d"
+ #else
+ #define PRId64 "lld"
+ #endif
+ #endif /* PRId64 */
+
+ #ifndef PRIo64
+ #ifdef _MSC_EXTENSIONS
+ #define PRIo64 "I64o"
+ #else
+ #define PRIo64 "llo"
+ #endif
+ #endif /* PRIo64 */
+
+ #ifndef PRIx64
+ #ifdef _MSC_EXTENSIONS
+ #define PRIx64 "I64x"
+ #else
+ #define PRIx64 "llx"
+ #endif
+ #endif
+
+ #ifndef PRIu64
+ #ifdef _MSC_EXTENSIONS
+ #define PRIu64 "I64u"
+ #else
+ #define PRIu64 "llu"
+ #endif
+ #endif
+
+ #if !defined(__cplusplus)
+ #define inline __inline
+ #endif
+#endif /* _WIN32 */
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/contrib/libpcap/remote-ext.h b/contrib/libpcap/remote-ext.h
new file mode 100644
index 000000000000..ed2f9bb2be84
--- /dev/null
+++ b/contrib/libpcap/remote-ext.h
@@ -0,0 +1,467 @@
+/*
+ * Copyright (c) 2002 - 2003
+ * NetGroup, Politecnico di Torino (Italy)
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the Politecnico di Torino nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+
+#ifndef __REMOTE_EXT_H__
+#define __REMOTE_EXT_H__
+
+
+#ifndef HAVE_REMOTE
+#error Please do not include this file directly. Just define HAVE_REMOTE and then include pcap.h
+#endif
+
+/*// Definition for Microsoft Visual Studio */
+#if _MSC_VER > 1000
+#pragma once
+#endif
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/*
+ * \file remote-ext.h
+ *
+ * The goal of this file it to include most of the new definitions that should be
+ * placed into the pcap.h file.
+ *
+ * It includes all new definitions (structures and functions like pcap_open().
+ * Some of the functions are not really a remote feature, but, right now,
+ * they are placed here.
+ */
+
+
+
+/*// All this stuff is public */
+/*
+ * \addtogroup remote_struct
+ * \{
+ */
+
+
+
+
+/*
+ * \brief Defines the maximum buffer size in which address, port, interface names are kept.
+ *
+ * In case the adapter name or such is larger than this value, it is truncated.
+ * This is not used by the user; however it must be aware that an hostname / interface
+ * name longer than this value will be truncated.
+ */
+#define PCAP_BUF_SIZE 1024
+
+
+/*
+ * \addtogroup remote_source_ID
+ * \{
+ */
+
+
+/*
+ * \brief Internal representation of the type of source in use (file,
+ * remote/local interface).
+ *
+ * This indicates a file, i.e. the user want to open a capture from a local file.
+ */
+#define PCAP_SRC_FILE 2
+/*
+ * \brief Internal representation of the type of source in use (file,
+ * remote/local interface).
+ *
+ * This indicates a local interface, i.e. the user want to open a capture from
+ * a local interface. This does not involve the RPCAP protocol.
+ */
+#define PCAP_SRC_IFLOCAL 3
+/*
+ * \brief Internal representation of the type of source in use (file,
+ * remote/local interface).
+ *
+ * This indicates a remote interface, i.e. the user want to open a capture from
+ * an interface on a remote host. This does involve the RPCAP protocol.
+ */
+#define PCAP_SRC_IFREMOTE 4
+
+/*
+ * \}
+ */
+
+
+
+/* \addtogroup remote_source_string
+ *
+ * The formats allowed by the pcap_open() are the following:
+ * - file://path_and_filename [opens a local file]
+ * - rpcap://devicename [opens the selected device devices available on the local host, without using the RPCAP protocol]
+ * - rpcap://host/devicename [opens the selected device available on a remote host]
+ * - rpcap://host:port/devicename [opens the selected device available on a remote host, using a non-standard port for RPCAP]
+ * - adaptername [to open a local adapter; kept for compability, but it is strongly discouraged]
+ * - (NULL) [to open the first local adapter; kept for compability, but it is strongly discouraged]
+ *
+ * The formats allowed by the pcap_findalldevs_ex() are the following:
+ * - file://folder/ [lists all the files in the given folder]
+ * - rpcap:// [lists all local adapters]
+ * - rpcap://host:port/ [lists the devices available on a remote host]
+ *
+ * Referring to the 'host' and 'port' parameters, they can be either numeric or literal. Since
+ * IPv6 is fully supported, these are the allowed formats:
+ *
+ * - host (literal): e.g. host.foo.bar
+ * - host (numeric IPv4): e.g. 10.11.12.13
+ * - host (numeric IPv4, IPv6 style): e.g. [10.11.12.13]
+ * - host (numeric IPv6): e.g. [1:2:3::4]
+ * - port: can be either numeric (e.g. '80') or literal (e.g. 'http')
+ *
+ * Here you find some allowed examples:
+ * - rpcap://host.foo.bar/devicename [everything literal, no port number]
+ * - rpcap://host.foo.bar:1234/devicename [everything literal, with port number]
+ * - rpcap://10.11.12.13/devicename [IPv4 numeric, no port number]
+ * - rpcap://10.11.12.13:1234/devicename [IPv4 numeric, with port number]
+ * - rpcap://[10.11.12.13]:1234/devicename [IPv4 numeric with IPv6 format, with port number]
+ * - rpcap://[1:2:3::4]/devicename [IPv6 numeric, no port number]
+ * - rpcap://[1:2:3::4]:1234/devicename [IPv6 numeric, with port number]
+ * - rpcap://[1:2:3::4]:http/devicename [IPv6 numeric, with literal port number]
+ *
+ * \{
+ */
+
+
+/*
+ * \brief String that will be used to determine the type of source in use (file,
+ * remote/local interface).
+ *
+ * This string will be prepended to the interface name in order to create a string
+ * that contains all the information required to open the source.
+ *
+ * This string indicates that the user wants to open a capture from a local file.
+ */
+#define PCAP_SRC_FILE_STRING "file://"
+/*
+ * \brief String that will be used to determine the type of source in use (file,
+ * remote/local interface).
+ *
+ * This string will be prepended to the interface name in order to create a string
+ * that contains all the information required to open the source.
+ *
+ * This string indicates that the user wants to open a capture from a network interface.
+ * This string does not necessarily involve the use of the RPCAP protocol. If the
+ * interface required resides on the local host, the RPCAP protocol is not involved
+ * and the local functions are used.
+ */
+#define PCAP_SRC_IF_STRING "rpcap://"
+
+/*
+ * \}
+ */
+
+
+
+
+
+/*
+ * \addtogroup remote_open_flags
+ * \{
+ */
+
+/*
+ * \brief Defines if the adapter has to go in promiscuous mode.
+ *
+ * It is '1' if you have to open the adapter in promiscuous mode, '0' otherwise.
+ * Note that even if this parameter is false, the interface could well be in promiscuous
+ * mode for some other reason (for example because another capture process with
+ * promiscuous mode enabled is currently using that interface).
+ * On on Linux systems with 2.2 or later kernels (that have the "any" device), this
+ * flag does not work on the "any" device; if an argument of "any" is supplied,
+ * the 'promisc' flag is ignored.
+ */
+#define PCAP_OPENFLAG_PROMISCUOUS 1
+
+/*
+ * \brief Defines if the data transfer (in case of a remote
+ * capture) has to be done with UDP protocol.
+ *
+ * If it is '1' if you want a UDP data connection, '0' if you want
+ * a TCP data connection; control connection is always TCP-based.
+ * A UDP connection is much lighter, but it does not guarantee that all
+ * the captured packets arrive to the client workstation. Moreover,
+ * it could be harmful in case of network congestion.
+ * This flag is meaningless if the source is not a remote interface.
+ * In that case, it is simply ignored.
+ */
+#define PCAP_OPENFLAG_DATATX_UDP 2
+
+
+/*
+ * \brief Defines if the remote probe will capture its own generated traffic.
+ *
+ * In case the remote probe uses the same interface to capture traffic and to send
+ * data back to the caller, the captured traffic includes the RPCAP traffic as well.
+ * If this flag is turned on, the RPCAP traffic is excluded from the capture, so that
+ * the trace returned back to the collector is does not include this traffic.
+ */
+#define PCAP_OPENFLAG_NOCAPTURE_RPCAP 4
+
+/*
+ * \brief Defines if the local adapter will capture its own generated traffic.
+ *
+ * This flag tells the underlying capture driver to drop the packets that were sent by itself.
+ * This is useful when building applications like bridges, that should ignore the traffic
+ * they just sent.
+ */
+#define PCAP_OPENFLAG_NOCAPTURE_LOCAL 8
+
+/*
+ * \brief This flag configures the adapter for maximum responsiveness.
+ *
+ * In presence of a large value for nbytes, WinPcap waits for the arrival of several packets before
+ * copying the data to the user. This guarantees a low number of system calls, i.e. lower processor usage,
+ * i.e. better performance, which is good for applications like sniffers. If the user sets the
+ * PCAP_OPENFLAG_MAX_RESPONSIVENESS flag, the capture driver will copy the packets as soon as the application
+ * is ready to receive them. This is suggested for real time applications (like, for example, a bridge)
+ * that need the best responsiveness.
+ */
+#define PCAP_OPENFLAG_MAX_RESPONSIVENESS 16
+
+/*
+ * \}
+ */
+
+
+/*
+ * \addtogroup remote_samp_methods
+ * \{
+ */
+
+/*
+ *\brief No sampling has to be done on the current capture.
+ *
+ * In this case, no sampling algorithms are applied to the current capture.
+ */
+#define PCAP_SAMP_NOSAMP 0
+
+/*
+ * \brief It defines that only 1 out of N packets must be returned to the user.
+ *
+ * In this case, the 'value' field of the 'pcap_samp' structure indicates the
+ * number of packets (minus 1) that must be discarded before one packet got accepted.
+ * In other words, if 'value = 10', the first packet is returned to the caller, while
+ * the following 9 are discarded.
+ */
+#define PCAP_SAMP_1_EVERY_N 1
+
+/*
+ * \brief It defines that we have to return 1 packet every N milliseconds.
+ *
+ * In this case, the 'value' field of the 'pcap_samp' structure indicates the 'waiting
+ * time' in milliseconds before one packet got accepted.
+ * In other words, if 'value = 10', the first packet is returned to the caller; the next
+ * returned one will be the first packet that arrives when 10ms have elapsed.
+ */
+#define PCAP_SAMP_FIRST_AFTER_N_MS 2
+
+/*
+ * \}
+ */
+
+
+/*
+ * \addtogroup remote_auth_methods
+ * \{
+ */
+
+/*
+ * \brief It defines the NULL authentication.
+ *
+ * This value has to be used within the 'type' member of the pcap_rmtauth structure.
+ * The 'NULL' authentication has to be equal to 'zero', so that old applications
+ * can just put every field of struct pcap_rmtauth to zero, and it does work.
+ */
+#define RPCAP_RMTAUTH_NULL 0
+/*
+ * \brief It defines the username/password authentication.
+ *
+ * With this type of authentication, the RPCAP protocol will use the username/
+ * password provided to authenticate the user on the remote machine. If the
+ * authentication is successful (and the user has the right to open network devices)
+ * the RPCAP connection will continue; otherwise it will be dropped.
+ *
+ * This value has to be used within the 'type' member of the pcap_rmtauth structure.
+ */
+#define RPCAP_RMTAUTH_PWD 1
+
+/*
+ * \}
+ */
+
+
+
+
+/*
+ * \brief This structure keeps the information needed to autheticate
+ * the user on a remote machine.
+ *
+ * The remote machine can either grant or refuse the access according
+ * to the information provided.
+ * In case the NULL authentication is required, both 'username' and
+ * 'password' can be NULL pointers.
+ *
+ * This structure is meaningless if the source is not a remote interface;
+ * in that case, the functions which requires such a structure can accept
+ * a NULL pointer as well.
+ */
+struct pcap_rmtauth
+{
+ /*
+ * \brief Type of the authentication required.
+ *
+ * In order to provide maximum flexibility, we can support different types
+ * of authentication based on the value of this 'type' variable. The currently
+ * supported authentication methods are defined into the
+ * \link remote_auth_methods Remote Authentication Methods Section\endlink.
+ */
+ int type;
+ /*
+ * \brief Zero-terminated string containing the username that has to be
+ * used on the remote machine for authentication.
+ *
+ * This field is meaningless in case of the RPCAP_RMTAUTH_NULL authentication
+ * and it can be NULL.
+ */
+ char *username;
+ /*
+ * \brief Zero-terminated string containing the password that has to be
+ * used on the remote machine for authentication.
+ *
+ * This field is meaningless in case of the RPCAP_RMTAUTH_NULL authentication
+ * and it can be NULL.
+ */
+ char *password;
+};
+
+
+/*
+ * \brief This structure defines the information related to sampling.
+ *
+ * In case the sampling is requested, the capturing device should read
+ * only a subset of the packets coming from the source. The returned packets depend
+ * on the sampling parameters.
+ *
+ * \warning The sampling process is applied <strong>after</strong> the filtering process.
+ * In other words, packets are filtered first, then the sampling process selects a
+ * subset of the 'filtered' packets and it returns them to the caller.
+ */
+struct pcap_samp
+{
+ /*
+ * Method used for sampling. Currently, the supported methods are listed in the
+ * \link remote_samp_methods Sampling Methods Section\endlink.
+ */
+ int method;
+
+ /*
+ * This value depends on the sampling method defined. For its meaning, please check
+ * at the \link remote_samp_methods Sampling Methods Section\endlink.
+ */
+ int value;
+};
+
+
+
+
+// Maximum length of an host name (needed for the RPCAP active mode)
+#define RPCAP_HOSTLIST_SIZE 1024
+
+
+/*
+ * \}
+ */ // end of public documentation
+
+
+// Exported functions
+
+
+
+/*
+ * \name New WinPcap functions
+ *
+ * This section lists the new functions that are able to help considerably in writing
+ * WinPcap programs because of their easiness of use.
+ */
+// \{
+PCAP_API pcap_t *pcap_open(const char *source, int snaplen, int flags, int read_timeout, struct pcap_rmtauth *auth, char *errbuf);
+PCAP_API int pcap_createsrcstr(char *source, int type, const char *host, const char *port, const char *name, char *errbuf);
+PCAP_API int pcap_parsesrcstr(const char *source, int *type, char *host, char *port, char *name, char *errbuf);
+PCAP_API int pcap_findalldevs_ex(char *source, struct pcap_rmtauth *auth, pcap_if_t **alldevs, char *errbuf);
+PCAP_API struct pcap_samp *pcap_setsampling(pcap_t *p);
+
+// \}
+// End of new WinPcap functions
+
+/*
+ * \name Remote Capture functions
+ */
+
+/*
+ * Some minor differences between UN*X sockets and and Winsock sockets.
+ */
+#ifndef _WIN32
+ /*!
+ * \brief In Winsock, a socket handle is of type SOCKET; in UN*X, it's
+ * a file descriptor, and therefore a signed integer.
+ * We define SOCKET to be a signed integer on UN*X, so that it can
+ * be used on both platforms.
+ */
+ #define SOCKET int
+
+ /*!
+ * \brief In Winsock, the error return if socket() fails is INVALID_SOCKET;
+ * in UN*X, it's -1.
+ * We define INVALID_SOCKET to be -1 on UN*X, so that it can be used on
+ * both platforms.
+ */
+ #define INVALID_SOCKET -1
+#endif
+
+// \{
+PCAP_API SOCKET pcap_remoteact_accept(const char *address, const char *port, const char *hostlist, char *connectinghost, struct pcap_rmtauth *auth, char *errbuf);
+PCAP_API int pcap_remoteact_list(char *hostlist, char sep, int size, char *errbuf);
+PCAP_API int pcap_remoteact_close(const char *host, char *errbuf);
+PCAP_API void pcap_remoteact_cleanup();
+// \}
+// End of remote capture functions
+
+#ifdef __cplusplus
+}
+#endif
+
+
+#endif
+
diff --git a/contrib/libpcap/runlex.sh b/contrib/libpcap/runlex.sh
deleted file mode 100755
index 24c3c2e1344a..000000000000
--- a/contrib/libpcap/runlex.sh
+++ /dev/null
@@ -1,233 +0,0 @@
-#! /bin/sh
-
-#
-# runlex.sh
-# Script to run Lex/Flex.
-# First argument is the (quoted) name of the command; if it's null, that
-# means that neither Flex nor Lex was found, so we report an error and
-# quit.
-#
-
-#
-# Get the name of the command to run, and then shift to get the arguments.
-#
-if [ $# -eq 0 ]
-then
- echo "Usage: runlex <lex/flex command to run> [ arguments ]" 1>&2
- exit 1
-fi
-LEX="$1"
-shift
-
-#
-# Check whether we have Lex or Flex.
-#
-if [ -z "${LEX}" ]
-then
- echo "Neither lex nor flex was found" 1>&2
- exit 1
-fi
-
-#
-# Process the flags. We don't use getopt because we don't want to
-# embed complete knowledge of what options are supported by Lex/Flex.
-#
-flags=""
-outfile=lex.yy.c
-while [ $# -ne 0 ]
-do
- case "$1" in
-
- -o*)
- #
- # Set the output file name.
- #
- outfile=`echo "$1" | sed 's/-o\(.*\)/\1/'`
- ;;
-
- -*)
- #
- # Add this to the list of flags.
- #
- flags="$flags $1"
- ;;
-
- --|*)
- #
- # End of flags.
- #
- break
- ;;
- esac
- shift
-done
-
-#
-# Is it Lex, or is it Flex?
-#
-if [ "${LEX}" = flex ]
-then
- #
- # It's Flex.
- #
- have_flex=yes
-
- #
- # Does it support the --noFUNCTION options? If so, we pass
- # --nounput, as at least some versions that support those
- # options don't support disabling yyunput by defining
- # YY_NO_UNPUT.
- #
- if flex --help | egrep noFUNCTION >/dev/null
- then
- flags="$flags --nounput"
-
- #
- # Does it support -R, for generating reentrant scanners?
- # If so, we're not currently using that feature, but
- # it'll generate some unused functions anyway - and there
- # won't be any header file declaring them, so there'll be
- # defined-but-not-declared warnings. Therefore, we use
- # --noFUNCTION options to suppress generating those
- # functions.
- #
- if flex --help | egrep reentrant >/dev/null
- then
- flags="$flags --noyyget_lineno --noyyget_in --noyyget_out --noyyget_leng --noyyget_text --noyyset_lineno --noyyset_in --noyyset_out"
- fi
- fi
-else
- #
- # It's Lex.
- #
- have_flex=no
-fi
-
-#
-# OK, run it.
-# If it's lex, it doesn't support -o, so we just write to
-# lex.yy.c and, if it succeeds, rename it to the right name,
-# otherwise we remove lex.yy.c.
-# If it's flex, it supports -o, so we use that - flex with -P doesn't
-# write to lex.yy.c, it writes to a lex.{prefix from -P}.c.
-#
-if [ $have_flex = yes ]
-then
- ${LEX} $flags -o"$outfile" "$@"
-
- #
- # Did it succeed?
- #
- status=$?
- if [ $status -ne 0 ]
- then
- #
- # No. Exit with the failing exit status.
- #
- exit $status
- fi
-
- #
- # Flex has the annoying habit of stripping all but the last
- # component of the "-o" flag argument and using that as the
- # place to put the output. This gets in the way of building
- # in a directory different from the source directory. Try
- # to work around this.
- #
- # Is the outfile where we think it is?
- #
- outfile_base=`basename "$outfile"`
- if [ "$outfile_base" != "$outfile" -a \( ! -r "$outfile" \) -a -r "$outfile_base" ]
- then
- #
- # No, it's not, but it is in the current directory. Put it
- # where it's supposed to be.
- #
- mv "$outfile_base" "$outfile"
-
- #
- # Did that succeed?
- #
- status=$?
- if [ $status -ne 0 ]
- then
- #
- # No. Exit with the failing exit status.
- #
- exit $status
- fi
- fi
-else
- ${LEX} $flags "$@"
-
- #
- # Did it succeed?
- #
- status=$?
- if [ $status -ne 0 ]
- then
- #
- # No. Get rid of any lex.yy.c file we generated, and
- # exit with the failing exit status.
- #
- rm -f lex.yy.c
- exit $status
- fi
-
- #
- # OK, rename lex.yy.c to the right output file.
- #
- mv lex.yy.c "$outfile"
-
- #
- # Did that succeed?
- #
- status=$?
- if [ $status -ne 0 ]
- then
- #
- # No. Get rid of any lex.yy.c file we generated, and
- # exit with the failing exit status.
- #
- rm -f lex.yy.c
- exit $status
- fi
-fi
-
-#
-# OK, now let's generate a header file declaring the relevant functions
-# defined by the .c file; if the .c file is .../foo.c, the header file
-# will be .../foo.h.
-#
-# This works around some other Flex suckage, wherein it doesn't declare
-# the lex routine before defining it, causing compiler warnings.
-# XXX - newer versions of Flex support --header-file=, to generate the
-# appropriate header file. With those versions, we should use that option.
-#
-
-#
-# Get the name of the prefix; scan the source files for a %option prefix
-# line. We use the last one.
-#
-prefix=`sed -n 's/%option[ ][ ]*prefix="\(.*\)".*/\1/p' "$@" | tail -1`
-if [ ! -z "$prefix" ]
-then
- prefixline="#define yylex ${prefix}lex"
-fi
-
-#
-# Construct the name of the header file.
-#
-header_file=`dirname "$outfile"`/`basename "$outfile" .c`.h
-
-#
-# Spew out the declaration.
-#
-cat <<EOF >$header_file
-/* This is generated by runlex.sh. Do not edit it. */
-$prefixline
-#ifndef YY_DECL
-#define YY_DECL int yylex(void)
-#endif
-YY_DECL;
-EOF
diff --git a/contrib/libpcap/savefile.c b/contrib/libpcap/savefile.c
index 0ab2fdefb201..247338c5b879 100644
--- a/contrib/libpcap/savefile.c
+++ b/contrib/libpcap/savefile.c
@@ -32,9 +32,9 @@
#include "config.h"
#endif
-#ifdef WIN32
+#ifdef _WIN32
#include <pcap-stdinc.h>
-#else /* WIN32 */
+#else /* _WIN32 */
#if HAVE_INTTYPES_H
#include <inttypes.h>
#elif HAVE_STDINT_H
@@ -44,7 +44,7 @@
#include <sys/bitypes.h>
#endif
#include <sys/types.h>
-#endif /* WIN32 */
+#endif /* _WIN32 */
#include <errno.h>
#include <memory.h>
@@ -53,7 +53,6 @@
#include <string.h>
#include "pcap-int.h"
-#include "pcap/usb.h"
#ifdef HAVE_OS_PROTO_H
#include "os-proto.h"
@@ -62,10 +61,27 @@
#include "sf-pcap.h"
#include "sf-pcap-ng.h"
+#ifdef _WIN32
+/*
+ * These aren't exported on Windows, because they would only work if both
+ * WinPcap and the code using it were to use the Universal CRT; otherwise,
+ * a FILE structure in WinPcap and a FILE structure in the code using it
+ * could be different if they're using different versions of the C runtime.
+ *
+ * Instead, pcap/pcap.h defines them as macros that wrap the hopen versions,
+ * with the wrappers calling _fileno() and _get_osfhandle() themselves,
+ * so that they convert the appropriate CRT version's FILE structure to
+ * a HANDLE (which is OS-defined, not CRT-defined, and is part of the Win32
+ * and Win64 ABIs).
+ */
+static pcap_t *pcap_fopen_offline_with_tstamp_precision(FILE *, u_int, char *);
+static pcap_t *pcap_fopen_offline(FILE *, char *);
+#endif
+
/*
* Setting O_BINARY on DOS/Windows is a bit tricky
*/
-#if defined(WIN32)
+#if defined(_WIN32)
#define SET_BINMODE(f) _setmode(_fileno(f), _O_BINARY)
#elif defined(MSDOS)
#if defined(__HIGHC__)
@@ -96,7 +112,7 @@ sf_setnonblock(pcap_t *p, int nonblock, char *errbuf)
* as it would have to handle reading partial packets and
* keeping the state of the read.)
*/
- snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
+ pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
"Savefiles cannot be put into non-blocking mode");
return (-1);
}
@@ -104,16 +120,24 @@ sf_setnonblock(pcap_t *p, int nonblock, char *errbuf)
static int
sf_stats(pcap_t *p, struct pcap_stat *ps)
{
- snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
+ pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
"Statistics aren't available from savefiles");
return (-1);
}
-#ifdef WIN32
+#ifdef _WIN32
+static struct pcap_stat *
+sf_stats_ex(pcap_t *p, int *size)
+{
+ pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
+ "Statistics aren't available from savefiles");
+ return (NULL);
+}
+
static int
sf_setbuff(pcap_t *p, int dim)
{
- snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
+ pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
"The kernel buffer size cannot be set while reading from a file");
return (-1);
}
@@ -121,7 +145,7 @@ sf_setbuff(pcap_t *p, int dim)
static int
sf_setmode(pcap_t *p, int mode)
{
- snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
+ pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
"impossible to set mode while reading from a file");
return (-1);
}
@@ -129,10 +153,74 @@ sf_setmode(pcap_t *p, int mode)
static int
sf_setmintocopy(pcap_t *p, int size)
{
- snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
+ pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
"The mintocopy parameter cannot be set while reading from a file");
return (-1);
}
+
+static HANDLE
+sf_getevent(pcap_t *pcap)
+{
+ (void)pcap_snprintf(pcap->errbuf, sizeof(pcap->errbuf),
+ "The read event cannot be retrieved while reading from a file");
+ return (INVALID_HANDLE_VALUE);
+}
+
+static int
+sf_oid_get_request(pcap_t *p, bpf_u_int32 oid _U_, void *data _U_,
+ size_t *lenp _U_)
+{
+ pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
+ "An OID get request cannot be performed on a file");
+ return (PCAP_ERROR);
+}
+
+static int
+sf_oid_set_request(pcap_t *p, bpf_u_int32 oid _U_, const void *data _U_,
+ size_t *lenp _U_)
+{
+ pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
+ "An OID set request cannot be performed on a file");
+ return (PCAP_ERROR);
+}
+
+static u_int
+sf_sendqueue_transmit(pcap_t *p, pcap_send_queue *queue, int sync)
+{
+ strlcpy(p->errbuf, "Sending packets isn't supported on savefiles",
+ PCAP_ERRBUF_SIZE);
+ return (0);
+}
+
+static int
+sf_setuserbuffer(pcap_t *p, int size)
+{
+ pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
+ "The user buffer cannot be set when reading from a file");
+ return (-1);
+}
+
+static int
+sf_live_dump(pcap_t *p, char *filename, int maxsize, int maxpacks)
+{
+ pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
+ "Live packet dumping cannot be performed when reading from a file");
+ return (-1);
+}
+
+static int
+sf_live_dump_ended(pcap_t *p, int sync)
+{
+ pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
+ "Live packet dumping cannot be performed on a pcap_open_dead pcap_t");
+ return (-1);
+}
+
+static PAirpcapHandle
+sf_get_airpcap_handle(pcap_t *pcap)
+{
+ return (NULL);
+}
#endif
static int
@@ -150,7 +238,7 @@ sf_inject(pcap_t *p, const void *buf _U_, size_t size _U_)
static int
sf_setdirection(pcap_t *p, pcap_direction_t d)
{
- snprintf(p->errbuf, sizeof(p->errbuf),
+ pcap_snprintf(p->errbuf, sizeof(p->errbuf),
"Setting direction is not supported on savefiles");
return (-1);
}
@@ -165,17 +253,38 @@ sf_cleanup(pcap_t *p)
pcap_freecode(&p->fcode);
}
+/*
+* fopen's safe version on Windows.
+*/
+#ifdef _MSC_VER
+FILE *fopen_safe(const char *filename, const char* mode)
+{
+ FILE *fp = NULL;
+ errno_t errno;
+ errno = fopen_s(&fp, filename, mode);
+ if (errno == 0)
+ return fp;
+ else
+ return NULL;
+}
+#endif
+
pcap_t *
pcap_open_offline_with_tstamp_precision(const char *fname, u_int precision,
- char *errbuf)
+ char *errbuf)
{
FILE *fp;
pcap_t *p;
+ if (fname == NULL) {
+ pcap_snprintf(errbuf, PCAP_ERRBUF_SIZE,
+ "A null pointer was supplied as the file name");
+ return (NULL);
+ }
if (fname[0] == '-' && fname[1] == '\0')
{
fp = stdin;
-#if defined(WIN32) || defined(MSDOS)
+#if defined(_WIN32) || defined(MSDOS)
/*
* We're reading from the standard input, so put it in binary
* mode, as savefiles are binary files.
@@ -184,13 +293,13 @@ pcap_open_offline_with_tstamp_precision(const char *fname, u_int precision,
#endif
}
else {
-#if !defined(WIN32) && !defined(MSDOS)
+#if !defined(_WIN32) && !defined(MSDOS)
fp = fopen(fname, "r");
#else
fp = fopen(fname, "rb");
#endif
if (fp == NULL) {
- snprintf(errbuf, PCAP_ERRBUF_SIZE, "%s: %s", fname,
+ pcap_snprintf(errbuf, PCAP_ERRBUF_SIZE, "%s: %s", fname,
pcap_strerror(errno));
return (NULL);
}
@@ -210,7 +319,7 @@ pcap_open_offline(const char *fname, char *errbuf)
PCAP_TSTAMP_PRECISION_MICRO, errbuf));
}
-#ifdef WIN32
+#ifdef _WIN32
pcap_t* pcap_hopen_offline_with_tstamp_precision(intptr_t osfd, u_int precision,
char *errbuf)
{
@@ -218,16 +327,16 @@ pcap_t* pcap_hopen_offline_with_tstamp_precision(intptr_t osfd, u_int precision,
FILE *file;
fd = _open_osfhandle(osfd, _O_RDONLY);
- if ( fd < 0 )
+ if ( fd < 0 )
{
- snprintf(errbuf, PCAP_ERRBUF_SIZE, pcap_strerror(errno));
+ pcap_snprintf(errbuf, PCAP_ERRBUF_SIZE, pcap_strerror(errno));
return NULL;
}
file = _fdopen(fd, "rb");
- if ( file == NULL )
+ if ( file == NULL )
{
- snprintf(errbuf, PCAP_ERRBUF_SIZE, pcap_strerror(errno));
+ pcap_snprintf(errbuf, PCAP_ERRBUF_SIZE, pcap_strerror(errno));
return NULL;
}
@@ -249,7 +358,7 @@ static pcap_t *(*check_headers[])(bpf_u_int32, FILE *, u_int, char *, int *) = {
#define N_FILE_TYPES (sizeof check_headers / sizeof check_headers[0])
-#ifdef WIN32
+#ifdef _WIN32
static
#endif
pcap_t *
@@ -272,11 +381,11 @@ pcap_fopen_offline_with_tstamp_precision(FILE *fp, u_int precision,
amt_read = fread((char *)&magic, 1, sizeof(magic), fp);
if (amt_read != sizeof(magic)) {
if (ferror(fp)) {
- snprintf(errbuf, PCAP_ERRBUF_SIZE,
+ pcap_snprintf(errbuf, PCAP_ERRBUF_SIZE,
"error reading dump file: %s",
pcap_strerror(errno));
} else {
- snprintf(errbuf, PCAP_ERRBUF_SIZE,
+ pcap_snprintf(errbuf, PCAP_ERRBUF_SIZE,
"truncated dump file; tried to read %lu file header bytes, only got %lu",
(unsigned long)sizeof(magic),
(unsigned long)amt_read);
@@ -304,7 +413,7 @@ pcap_fopen_offline_with_tstamp_precision(FILE *fp, u_int precision,
/*
* Well, who knows what this mess is....
*/
- snprintf(errbuf, PCAP_ERRBUF_SIZE, "unknown file format");
+ pcap_snprintf(errbuf, PCAP_ERRBUF_SIZE, "unknown file format");
return (NULL);
found:
@@ -313,7 +422,7 @@ found:
/* Padding only needed for live capture fcode */
p->fddipad = 0;
-#if !defined(WIN32) && !defined(MSDOS)
+#if !defined(_WIN32) && !defined(MSDOS)
/*
* You can do "select()" and "poll()" on plain files on most
* platforms, and should be able to do so on pipes.
@@ -332,10 +441,19 @@ found:
p->getnonblock_op = sf_getnonblock;
p->setnonblock_op = sf_setnonblock;
p->stats_op = sf_stats;
-#ifdef WIN32
+#ifdef _WIN32
+ p->stats_ex_op = sf_stats_ex;
p->setbuff_op = sf_setbuff;
p->setmode_op = sf_setmode;
p->setmintocopy_op = sf_setmintocopy;
+ p->getevent_op = sf_getevent;
+ p->oid_get_request_op = sf_oid_get_request;
+ p->oid_set_request_op = sf_oid_set_request;
+ p->sendqueue_transmit_op = sf_sendqueue_transmit;
+ p->setuserbuffer_op = sf_setuserbuffer;
+ p->live_dump_op = sf_live_dump;
+ p->live_dump_ended_op = sf_live_dump_ended;
+ p->get_airpcap_handle_op = sf_get_airpcap_handle;
#endif
/*
@@ -344,12 +462,17 @@ found:
*/
p->oneshot_callback = pcap_oneshot;
+ /*
+ * Savefiles never require special BPF code generation.
+ */
+ p->bpf_codegen_flags = 0;
+
p->activated = 1;
return (p);
}
-#ifdef WIN32
+#ifdef _WIN32
static
#endif
pcap_t *
diff --git a/contrib/libpcap/scanner.l b/contrib/libpcap/scanner.l
index 98c78428ccb2..d71a9bed1b5d 100644
--- a/contrib/libpcap/scanner.l
+++ b/contrib/libpcap/scanner.l
@@ -1,3 +1,46 @@
+%top {
+/* Must come first for _LARGE_FILE_API on AIX. */
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+}
+
+/*
+ * We want a reentrant scanner.
+ */
+%option reentrant
+
+/*
+ * And we need to pass the compiler state to the scanner.
+ */
+%option extra-type="compiler_state_t *"
+
+/*
+ * We don't use input, so don't generate code for it.
+ */
+%option noinput
+
+/*
+ * We don't use unput, so don't generate code for it.
+ */
+%option nounput
+
+/*
+ * We don't read from the terminal.
+ */
+%option never-interactive
+
+/*
+ * We want to stop processing when we get to the end of the input.
+ */
+%option noyywrap
+
+/*
+ * We want to generate code that can be used by a reentrant parser
+ * generated by Bison or Berkeley YACC.
+ */
+%option bison-bridge
+
%{
/*
* Copyright (c) 1988, 1989, 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1997
@@ -22,23 +65,19 @@
* $FreeBSD$
*/
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-
-#ifdef WIN32
-#include <pcap-stdinc.h>
-#else /* WIN32 */
-#if HAVE_INTTYPES_H
-#include <inttypes.h>
-#elif HAVE_STDINT_H
-#include <stdint.h>
-#endif
-#ifdef HAVE_SYS_BITYPES_H
-#include <sys/bitypes.h>
+#ifdef _WIN32
+ #include <pcap-stdinc.h>
+#else
+ #if HAVE_INTTYPES_H
+ #include <inttypes.h>
+ #elif HAVE_STDINT_H
+ #include <stdint.h>
+ #endif
+ #ifdef HAVE_SYS_BITYPES_H
+ #include <sys/bitypes.h>
+ #endif
+ #include <sys/types.h>
#endif
-#include <sys/types.h>
-#endif /* WIN32 */
#include <ctype.h>
#include <string.h>
@@ -46,25 +85,56 @@
#include "pcap-int.h"
#include "gencode.h"
+
+#include "grammar.h"
+
+/*
+ * Earlier versions of Flex don't declare these, so we declare them
+ * ourselves to squelch warnings.
+ */
+int pcap_get_column(yyscan_t);
+void pcap_set_column(int, yyscan_t);
+
#ifdef INET6
-#ifdef WIN32
-#include <pcap-stdinc.h>
-#ifdef __MINGW32__
-#include "ip6_misc.h"
-#endif
-#else /* WIN32 */
+#ifdef _WIN32
+/*
+ * To quote the MSDN page for getaddrinfo() at
+ *
+ * https://msdn.microsoft.com/en-us/library/windows/desktop/ms738520(v=vs.85).aspx
+ *
+ * "Support for getaddrinfo on Windows 2000 and older versions
+ * The getaddrinfo function was added to the Ws2_32.dll on Windows XP and
+ * later. To execute an application that uses this function on earlier
+ * versions of Windows, then you need to include the Ws2tcpip.h and
+ * Wspiapi.h files. When the Wspiapi.h include file is added, the
+ * getaddrinfo function is defined to the WspiapiGetAddrInfo inline
+ * function in the Wspiapi.h file. At runtime, the WspiapiGetAddrInfo
+ * function is implemented in such a way that if the Ws2_32.dll or the
+ * Wship6.dll (the file containing getaddrinfo in the IPv6 Technology
+ * Preview for Windows 2000) does not include getaddrinfo, then a
+ * version of getaddrinfo is implemented inline based on code in the
+ * Wspiapi.h header file. This inline code will be used on older Windows
+ * platforms that do not natively support the getaddrinfo function."
+ *
+ * We use getaddrinfo(), so we include Wspiapi.h here. pcap-stdinc.h
+ * includes Ws2tcpip.h, so we don't need to include it ourselves.
+ */
+#include <Wspiapi.h>
+#else /* _WIN32 */
#include <sys/socket.h> /* for "struct sockaddr" in "struct addrinfo" */
#include <netdb.h> /* for "struct addrinfo" */
-#endif /* WIN32 */
+#endif /* _WIN32 */
/* Workaround for AIX 4.3 */
#if !defined(AI_NUMERICHOST)
#define AI_NUMERICHOST 0x04
#endif
+
#endif /*INET6*/
+
#include <pcap/namedb.h>
-#include "tokdefs.h"
+#include "grammar.h"
#ifdef HAVE_OS_PROTO_H
#include "os-proto.h"
@@ -73,19 +143,6 @@
static int stoi(char *);
static inline int xdtoi(int);
-#ifdef FLEX_SCANNER
-#define YY_NO_INPUT
-#define YY_NO_UNPUT
-static YY_BUFFER_STATE in_buffer;
-#else
-static const char *in_buffer;
-
-#undef getc
-#define getc(fp) (*in_buffer == 0 ? EOF : *in_buffer++)
-#endif
-
-extern YYSTYPE yylval;
-
%}
N ([0-9]+|(0X|0x)[0-9A-Fa-f]+)
@@ -244,7 +301,7 @@ portrange return PORTRANGE;
proto return PROTO;
protochain {
#ifdef NO_PROTOCHAIN
- bpf_error("%s not supported", yytext);
+ bpf_error(yyextra, "%s not supported", yytext);
#else
return PROTOCHAIN;
#endif
@@ -280,6 +337,7 @@ vlan return VLAN;
mpls return MPLS;
pppoed return PPPOED;
pppoes return PPPOES;
+geneve return GENEVE;
lane return LANE;
llc return LLC;
@@ -327,17 +385,17 @@ hsls return HSLS;
"==" return '=';
"<<" return LSH;
">>" return RSH;
-${B} { yylval.e = pcap_ether_aton(((char *)yytext)+1);
- if (yylval.e == NULL)
- bpf_error("malloc");
+${B} { yylval->e = pcap_ether_aton(((char *)yytext)+1);
+ if (yylval->e == NULL)
+ bpf_error(yyextra, "malloc");
return AID; }
-{MAC} { yylval.e = pcap_ether_aton((char *)yytext);
- if (yylval.e == NULL)
- bpf_error("malloc");
+{MAC} { yylval->e = pcap_ether_aton((char *)yytext);
+ if (yylval->e == NULL)
+ bpf_error(yyextra, "malloc");
return EID; }
-{N} { yylval.i = stoi((char *)yytext); return NUM; }
+{N} { yylval->i = stoi((char *)yytext); return NUM; }
({N}\.{N})|({N}\.{N}\.{N})|({N}\.{N}\.{N}\.{N}) {
- yylval.s = sdup((char *)yytext); return HID; }
+ yylval->s = sdup(yyextra, (char *)yytext); return HID; }
{V6} {
#ifdef INET6
struct addrinfo hints, *res;
@@ -345,82 +403,49 @@ ${B} { yylval.e = pcap_ether_aton(((char *)yytext)+1);
hints.ai_family = AF_INET6;
hints.ai_flags = AI_NUMERICHOST;
if (getaddrinfo(yytext, NULL, &hints, &res))
- bpf_error("bogus IPv6 address %s", yytext);
+ bpf_error(yyextra, "bogus IPv6 address %s", yytext);
else {
freeaddrinfo(res);
- yylval.s = sdup((char *)yytext); return HID6;
+ yylval->s = sdup(yyextra, (char *)yytext); return HID6;
}
#else
- bpf_error("IPv6 address %s not supported", yytext);
+ bpf_error(yyextra, "IPv6 address %s not supported", yytext);
#endif /*INET6*/
}
-{B}:+({B}:+)+ { bpf_error("bogus ethernet address %s", yytext); }
-icmptype { yylval.i = 0; return NUM; }
-icmpcode { yylval.i = 1; return NUM; }
-icmp-echoreply { yylval.i = 0; return NUM; }
-icmp-unreach { yylval.i = 3; return NUM; }
-icmp-sourcequench { yylval.i = 4; return NUM; }
-icmp-redirect { yylval.i = 5; return NUM; }
-icmp-echo { yylval.i = 8; return NUM; }
-icmp-routeradvert { yylval.i = 9; return NUM; }
-icmp-routersolicit { yylval.i = 10; return NUM; }
-icmp-timxceed { yylval.i = 11; return NUM; }
-icmp-paramprob { yylval.i = 12; return NUM; }
-icmp-tstamp { yylval.i = 13; return NUM; }
-icmp-tstampreply { yylval.i = 14; return NUM; }
-icmp-ireq { yylval.i = 15; return NUM; }
-icmp-ireqreply { yylval.i = 16; return NUM; }
-icmp-maskreq { yylval.i = 17; return NUM; }
-icmp-maskreply { yylval.i = 18; return NUM; }
-tcpflags { yylval.i = 13; return NUM; }
-tcp-fin { yylval.i = 0x01; return NUM; }
-tcp-syn { yylval.i = 0x02; return NUM; }
-tcp-rst { yylval.i = 0x04; return NUM; }
-tcp-push { yylval.i = 0x08; return NUM; }
-tcp-ack { yylval.i = 0x10; return NUM; }
-tcp-urg { yylval.i = 0x20; return NUM; }
-tcp-ece { yylval.i = 0x40; return NUM; }
-tcp-cwr { yylval.i = 0x80; return NUM; }
+{B}:+({B}:+)+ { bpf_error(yyextra, "bogus ethernet address %s", yytext); }
+icmptype { yylval->i = 0; return NUM; }
+icmpcode { yylval->i = 1; return NUM; }
+icmp-echoreply { yylval->i = 0; return NUM; }
+icmp-unreach { yylval->i = 3; return NUM; }
+icmp-sourcequench { yylval->i = 4; return NUM; }
+icmp-redirect { yylval->i = 5; return NUM; }
+icmp-echo { yylval->i = 8; return NUM; }
+icmp-routeradvert { yylval->i = 9; return NUM; }
+icmp-routersolicit { yylval->i = 10; return NUM; }
+icmp-timxceed { yylval->i = 11; return NUM; }
+icmp-paramprob { yylval->i = 12; return NUM; }
+icmp-tstamp { yylval->i = 13; return NUM; }
+icmp-tstampreply { yylval->i = 14; return NUM; }
+icmp-ireq { yylval->i = 15; return NUM; }
+icmp-ireqreply { yylval->i = 16; return NUM; }
+icmp-maskreq { yylval->i = 17; return NUM; }
+icmp-maskreply { yylval->i = 18; return NUM; }
+tcpflags { yylval->i = 13; return NUM; }
+tcp-fin { yylval->i = 0x01; return NUM; }
+tcp-syn { yylval->i = 0x02; return NUM; }
+tcp-rst { yylval->i = 0x04; return NUM; }
+tcp-push { yylval->i = 0x08; return NUM; }
+tcp-ack { yylval->i = 0x10; return NUM; }
+tcp-urg { yylval->i = 0x20; return NUM; }
+tcp-ece { yylval->i = 0x40; return NUM; }
+tcp-cwr { yylval->i = 0x80; return NUM; }
[A-Za-z0-9]([-_.A-Za-z0-9]*[.A-Za-z0-9])? {
- yylval.s = sdup((char *)yytext); return ID; }
-"\\"[^ !()\n\t]+ { yylval.s = sdup((char *)yytext + 1); return ID; }
+ yylval->s = sdup(yyextra, (char *)yytext); return ID; }
+"\\"[^ !()\n\t]+ { yylval->s = sdup(yyextra, (char *)yytext + 1); return ID; }
[^ \[\]\t\n\-_.A-Za-z0-9!<>()&|=]+ {
- bpf_error("illegal token: %s", yytext); }
-. { bpf_error("illegal char '%c'", *yytext); }
+ bpf_error(yyextra, "illegal token: %s", yytext); }
+. { bpf_error(yyextra, "illegal char '%c'", *yytext); }
%%
-void
-lex_init(buf)
- const char *buf;
-{
-#ifdef FLEX_SCANNER
- in_buffer = yy_scan_string(buf);
-#else
- in_buffer = buf;
-#endif
-}
-
-/*
- * Do any cleanup necessary after parsing.
- */
-void
-lex_cleanup()
-{
-#ifdef FLEX_SCANNER
- if (in_buffer != NULL)
- yy_delete_buffer(in_buffer);
- in_buffer = NULL;
-#endif
-}
-
-/*
- * Also define a yywrap. Note that if we're using flex, it will
- * define a macro to map this identifier to pcap_wrap.
- */
-int
-yywrap()
-{
- return 1;
-}
/* Hex digit to integer. */
static inline int
diff --git a/contrib/libpcap/sf-pcap-ng.c b/contrib/libpcap/sf-pcap-ng.c
index fae408679a5d..0c02829e71e5 100644
--- a/contrib/libpcap/sf-pcap-ng.c
+++ b/contrib/libpcap/sf-pcap-ng.c
@@ -30,9 +30,9 @@ static const char rcsid[] _U_ =
#include "config.h"
#endif
-#ifdef WIN32
+#ifdef _WIN32
#include <pcap-stdinc.h>
-#else /* WIN32 */
+#else /* _WIN32 */
#if HAVE_INTTYPES_H
#include <inttypes.h>
#elif HAVE_STDINT_H
@@ -42,7 +42,7 @@ static const char rcsid[] _U_ =
#include <sys/bitypes.h>
#endif
#include <sys/types.h>
-#endif /* WIN32 */
+#endif /* _WIN32 */
#include <errno.h>
#include <memory.h>
@@ -121,6 +121,7 @@ struct section_header_block {
* that means that this code can't read the file.
*/
#define PCAP_NG_VERSION_MAJOR 1
+#define PCAP_NG_VERSION_MINOR 0
/*
* Interface Description Block.
@@ -203,8 +204,10 @@ struct block_cursor {
typedef enum {
PASS_THROUGH,
- SCALE_UP,
- SCALE_DOWN
+ SCALE_UP_DEC,
+ SCALE_DOWN_DEC,
+ SCALE_UP_BIN,
+ SCALE_DOWN_BIN
} tstamp_scale_type_t;
/*
@@ -212,14 +215,15 @@ typedef enum {
*/
struct pcap_ng_if {
u_int tsresol; /* time stamp resolution */
- u_int64_t tsoffset; /* time stamp offset */
tstamp_scale_type_t scale_type; /* how to scale */
+ u_int scale_factor; /* time stamp scale factor for power-of-10 tsresol */
+ u_int64_t tsoffset; /* time stamp offset */
};
struct pcap_ng_sf {
u_int user_tsresol; /* time stamp resolution requested by the user */
bpf_u_int32 ifcount; /* number of interfaces seen in this capture */
- bpf_u_int32 ifaces_size; /* size of arrary below */
+ bpf_u_int32 ifaces_size; /* size of array below */
struct pcap_ng_if *ifaces; /* array of interface information */
};
@@ -236,13 +240,13 @@ read_bytes(FILE *fp, void *buf, size_t bytes_to_read, int fail_on_eof,
amt_read = fread(buf, 1, bytes_to_read, fp);
if (amt_read != bytes_to_read) {
if (ferror(fp)) {
- snprintf(errbuf, PCAP_ERRBUF_SIZE,
+ pcap_snprintf(errbuf, PCAP_ERRBUF_SIZE,
"error reading dump file: %s",
pcap_strerror(errno));
} else {
if (amt_read == 0 && !fail_on_eof)
return (0); /* EOF */
- snprintf(errbuf, PCAP_ERRBUF_SIZE,
+ pcap_snprintf(errbuf, PCAP_ERRBUF_SIZE,
"truncated dump file; tried to read %lu bytes, only got %lu",
(unsigned long)bytes_to_read,
(unsigned long)amt_read);
@@ -257,6 +261,8 @@ read_block(FILE *fp, pcap_t *p, struct block_cursor *cursor, char *errbuf)
{
int status;
struct block_header bhdr;
+ u_char *bdata;
+ size_t data_remaining;
status = read_bytes(fp, &bhdr, sizeof(bhdr), 0, errbuf);
if (status <= 0)
@@ -275,7 +281,7 @@ read_block(FILE *fp, pcap_t *p, struct block_cursor *cursor, char *errbuf)
* memory if we read a malformed file.
*/
if (bhdr.total_length > 16*1024*1024) {
- snprintf(errbuf, PCAP_ERRBUF_SIZE,
+ pcap_snprintf(errbuf, PCAP_ERRBUF_SIZE,
"pcap-ng block size %u > maximum %u",
bhdr.total_length, 16*1024*1024);
return (-1);
@@ -287,7 +293,7 @@ read_block(FILE *fp, pcap_t *p, struct block_cursor *cursor, char *errbuf)
*/
if (bhdr.total_length < sizeof(struct block_header) +
sizeof(struct block_trailer)) {
- snprintf(errbuf, PCAP_ERRBUF_SIZE,
+ pcap_snprintf(errbuf, PCAP_ERRBUF_SIZE,
"block in pcap-ng dump file has a length of %u < %lu",
bhdr.total_length,
(unsigned long)(sizeof(struct block_header) + sizeof(struct block_trailer)));
@@ -301,11 +307,14 @@ read_block(FILE *fp, pcap_t *p, struct block_cursor *cursor, char *errbuf)
/*
* No - make it big enough.
*/
- p->buffer = realloc(p->buffer, bhdr.total_length);
- if (p->buffer == NULL) {
- snprintf(errbuf, PCAP_ERRBUF_SIZE, "out of memory");
+ void *bigger_buffer;
+
+ bigger_buffer = realloc(p->buffer, bhdr.total_length);
+ if (bigger_buffer == NULL) {
+ pcap_snprintf(errbuf, PCAP_ERRBUF_SIZE, "out of memory");
return (-1);
}
+ p->buffer = bigger_buffer;
}
/*
@@ -313,16 +322,16 @@ read_block(FILE *fp, pcap_t *p, struct block_cursor *cursor, char *errbuf)
* of the block.
*/
memcpy(p->buffer, &bhdr, sizeof(bhdr));
- if (read_bytes(fp, p->buffer + sizeof(bhdr),
- bhdr.total_length - sizeof(bhdr), 1, errbuf) == -1)
+ bdata = (u_char *)p->buffer + sizeof(bhdr);
+ data_remaining = bhdr.total_length - sizeof(bhdr);
+ if (read_bytes(fp, bdata, data_remaining, 1, errbuf) == -1)
return (-1);
/*
* Initialize the cursor.
*/
- cursor->data = p->buffer + sizeof(bhdr);
- cursor->data_remaining = bhdr.total_length - sizeof(bhdr) -
- sizeof(struct block_trailer);
+ cursor->data = bdata;
+ cursor->data_remaining = data_remaining - sizeof(struct block_trailer);
cursor->block_type = bhdr.block_type;
return (1);
}
@@ -338,7 +347,7 @@ get_from_block_data(struct block_cursor *cursor, size_t chunk_size,
* the block data.
*/
if (cursor->data_remaining < chunk_size) {
- snprintf(errbuf, PCAP_ERRBUF_SIZE,
+ pcap_snprintf(errbuf, PCAP_ERRBUF_SIZE,
"block of type %u in pcap-ng dump file is too short",
cursor->block_type);
return (NULL);
@@ -401,7 +410,7 @@ get_optvalue_from_block_data(struct block_cursor *cursor,
static int
process_idb_options(pcap_t *p, struct block_cursor *cursor, u_int *tsresol,
- u_int64_t *tsoffset, char *errbuf)
+ u_int64_t *tsoffset, int *is_binary, char *errbuf)
{
struct option_header *opthdr;
void *optvalue;
@@ -439,7 +448,7 @@ process_idb_options(pcap_t *p, struct block_cursor *cursor, u_int *tsresol,
case OPT_ENDOFOPT:
if (opthdr->option_length != 0) {
- snprintf(errbuf, PCAP_ERRBUF_SIZE,
+ pcap_snprintf(errbuf, PCAP_ERRBUF_SIZE,
"Interface Description Block has opt_endofopt option with length %u != 0",
opthdr->option_length);
return (-1);
@@ -448,13 +457,13 @@ process_idb_options(pcap_t *p, struct block_cursor *cursor, u_int *tsresol,
case IF_TSRESOL:
if (opthdr->option_length != 1) {
- snprintf(errbuf, PCAP_ERRBUF_SIZE,
+ pcap_snprintf(errbuf, PCAP_ERRBUF_SIZE,
"Interface Description Block has if_tsresol option with length %u != 1",
opthdr->option_length);
return (-1);
}
if (saw_tsresol) {
- snprintf(errbuf, PCAP_ERRBUF_SIZE,
+ pcap_snprintf(errbuf, PCAP_ERRBUF_SIZE,
"Interface Description Block has more than one if_tsresol option");
return (-1);
}
@@ -464,11 +473,13 @@ process_idb_options(pcap_t *p, struct block_cursor *cursor, u_int *tsresol,
/*
* Resolution is negative power of 2.
*/
+ *is_binary = 1;
*tsresol = 1 << (tsresol_opt & 0x7F);
} else {
/*
* Resolution is negative power of 10.
*/
+ *is_binary = 0;
*tsresol = 1;
for (i = 0; i < tsresol_opt; i++)
*tsresol *= 10;
@@ -478,11 +489,11 @@ process_idb_options(pcap_t *p, struct block_cursor *cursor, u_int *tsresol,
* Resolution is too high.
*/
if (tsresol_opt & 0x80) {
- snprintf(errbuf, PCAP_ERRBUF_SIZE,
+ pcap_snprintf(errbuf, PCAP_ERRBUF_SIZE,
"Interface Description Block if_tsresol option resolution 2^-%u is too high",
tsresol_opt & 0x7F);
} else {
- snprintf(errbuf, PCAP_ERRBUF_SIZE,
+ pcap_snprintf(errbuf, PCAP_ERRBUF_SIZE,
"Interface Description Block if_tsresol option resolution 10^-%u is too high",
tsresol_opt);
}
@@ -492,13 +503,13 @@ process_idb_options(pcap_t *p, struct block_cursor *cursor, u_int *tsresol,
case IF_TSOFFSET:
if (opthdr->option_length != 8) {
- snprintf(errbuf, PCAP_ERRBUF_SIZE,
+ pcap_snprintf(errbuf, PCAP_ERRBUF_SIZE,
"Interface Description Block has if_tsoffset option with length %u != 8",
opthdr->option_length);
return (-1);
}
if (saw_tsoffset) {
- snprintf(errbuf, PCAP_ERRBUF_SIZE,
+ pcap_snprintf(errbuf, PCAP_ERRBUF_SIZE,
"Interface Description Block has more than one if_tsoffset option");
return (-1);
}
@@ -523,6 +534,7 @@ add_interface(pcap_t *p, struct block_cursor *cursor, char *errbuf)
struct pcap_ng_sf *ps;
u_int tsresol;
u_int64_t tsoffset;
+ int is_binary;
ps = p->priv;
@@ -538,43 +550,107 @@ add_interface(pcap_t *p, struct block_cursor *cursor, char *errbuf)
/*
* We need to grow the array.
*/
- if (ps->ifaces == NULL) {
+ bpf_u_int32 new_ifaces_size;
+ struct pcap_ng_if *new_ifaces;
+
+ if (ps->ifaces_size == 0) {
/*
* It's currently empty.
+ *
+ * (The Clang static analyzer doesn't do enough,
+ * err, umm, dataflow *analysis* to realize that
+ * ps->ifaces_size == 0 if ps->ifaces == NULL,
+ * and so complains about a possible zero argument
+ * to realloc(), so we check for the former
+ * condition to shut it up.
+ *
+ * However, it doesn't complain that one of the
+ * multiplications below could overflow, which is
+ * a real, albeit extremely unlikely, problem (you'd
+ * need a pcap-ng file with tens of millions of
+ * interfaces).)
*/
- ps->ifaces_size = 1;
- ps->ifaces = malloc(sizeof (struct pcap_ng_if));
+ new_ifaces_size = 1;
+ new_ifaces = malloc(sizeof (struct pcap_ng_if));
} else {
/*
* It's not currently empty; double its size.
* (Perhaps overkill once we have a lot of interfaces.)
+ *
+ * Check for overflow if we double it.
*/
- ps->ifaces_size *= 2;
- ps->ifaces = realloc(ps->ifaces, ps->ifaces_size * sizeof (struct pcap_ng_if));
+ if (ps->ifaces_size * 2 < ps->ifaces_size) {
+ /*
+ * The maximum number of interfaces before
+ * ps->ifaces_size overflows is the largest
+ * possible 32-bit power of 2, as we do
+ * size doubling.
+ */
+ pcap_snprintf(errbuf, PCAP_ERRBUF_SIZE,
+ "more than %u interfaces in the file",
+ 0x80000000U);
+ return (0);
+ }
+
+ /*
+ * ps->ifaces_size * 2 doesn't overflow, so it's
+ * safe to multiply.
+ */
+ new_ifaces_size = ps->ifaces_size * 2;
+
+ /*
+ * Now make sure that's not so big that it overflows
+ * if we multiply by sizeof (struct pcap_ng_if).
+ *
+ * That can happen on 32-bit platforms, with a 32-bit
+ * size_t; it shouldn't happen on 64-bit platforms,
+ * with a 64-bit size_t, as new_ifaces_size is
+ * 32 bits.
+ */
+ if (new_ifaces_size * sizeof (struct pcap_ng_if) < new_ifaces_size) {
+ /*
+ * As this fails only with 32-bit size_t,
+ * the multiplication was 32x32->32, and
+ * the largest 32-bit value that can safely
+ * be multiplied by sizeof (struct pcap_ng_if)
+ * without overflow is the largest 32-bit
+ * (unsigned) value divided by
+ * sizeof (struct pcap_ng_if).
+ */
+ pcap_snprintf(errbuf, PCAP_ERRBUF_SIZE,
+ "more than %u interfaces in the file",
+ 0xFFFFFFFFU / ((u_int)sizeof (struct pcap_ng_if)));
+ return (0);
+ }
+ new_ifaces = realloc(ps->ifaces, new_ifaces_size * sizeof (struct pcap_ng_if));
}
- if (ps->ifaces == NULL) {
+ if (new_ifaces == NULL) {
/*
* We ran out of memory.
* Give up.
*/
- snprintf(errbuf, PCAP_ERRBUF_SIZE,
+ pcap_snprintf(errbuf, PCAP_ERRBUF_SIZE,
"out of memory for per-interface information (%u interfaces)",
ps->ifcount);
return (0);
}
+ ps->ifaces_size = new_ifaces_size;
+ ps->ifaces = new_ifaces;
}
/*
* Set the default time stamp resolution and offset.
*/
tsresol = 1000000; /* microsecond resolution */
+ is_binary = 0; /* which is a power of 10 */
tsoffset = 0; /* absolute timestamps */
/*
* Now look for various time stamp options, so we know
* how to interpret the time stamps for this interface.
*/
- if (process_idb_options(p, cursor, &tsresol, &tsoffset, errbuf) == -1)
+ if (process_idb_options(p, cursor, &tsresol, &tsoffset, &is_binary,
+ errbuf) == -1)
return (0);
ps->ifaces[ps->ifcount - 1].tsresol = tsresol;
@@ -584,55 +660,40 @@ add_interface(pcap_t *p, struct block_cursor *cursor, char *errbuf)
* Determine whether we're scaling up or down or not
* at all for this interface.
*/
- switch (p->opt.tstamp_precision) {
-
- case PCAP_TSTAMP_PRECISION_MICRO:
- if (tsresol == 1000000) {
- /*
- * The resolution is 1 microsecond,
- * so we don't have to do scaling.
- */
- ps->ifaces[ps->ifcount - 1].scale_type = PASS_THROUGH;
- } else if (tsresol > 1000000) {
- /*
- * The resolution is greater than
- * 1 microsecond, so we have to
- * scale the timestamps down.
- */
- ps->ifaces[ps->ifcount - 1].scale_type = SCALE_DOWN;
- } else {
+ if (tsresol == ps->user_tsresol) {
+ /*
+ * The resolution is the resolution the user wants,
+ * so we don't have to do scaling.
+ */
+ ps->ifaces[ps->ifcount - 1].scale_type = PASS_THROUGH;
+ } else if (tsresol > ps->user_tsresol) {
+ /*
+ * The resolution is greater than what the user wants,
+ * so we have to scale the timestamps down.
+ */
+ if (is_binary)
+ ps->ifaces[ps->ifcount - 1].scale_type = SCALE_DOWN_BIN;
+ else {
/*
- * The resolution is less than 1
- * microsecond, so we have to scale
- * the timestamps up.
+ * Calculate the scale factor.
*/
- ps->ifaces[ps->ifcount - 1].scale_type = SCALE_UP;
+ ps->ifaces[ps->ifcount - 1].scale_factor = tsresol/ps->user_tsresol;
+ ps->ifaces[ps->ifcount - 1].scale_type = SCALE_DOWN_DEC;
}
- break;
-
- case PCAP_TSTAMP_PRECISION_NANO:
- if (tsresol == 1000000000) {
- /*
- * The resolution is 1 nanosecond,
- * so we don't have to do scaling.
- */
- ps->ifaces[ps->ifcount - 1].scale_type = PASS_THROUGH;
- } else if (tsresol > 1000000000) {
- /*
- * The resolution is greater than
- * 1 nanosecond, so we have to
- * scale the timestamps down.
- */
- ps->ifaces[ps->ifcount - 1].scale_type = SCALE_DOWN;
- } else {
+ } else {
+ /*
+ * The resolution is less than what the user wants,
+ * so we have to scale the timestamps up.
+ */
+ if (is_binary)
+ ps->ifaces[ps->ifcount - 1].scale_type = SCALE_UP_BIN;
+ else {
/*
- * The resolution is less than 1
- * nanosecond, so we have to scale
- * the timestamps up.
+ * Calculate the scale factor.
*/
- ps->ifaces[ps->ifcount - 1].scale_type = SCALE_UP;
+ ps->ifaces[ps->ifcount - 1].scale_factor = ps->user_tsresol/tsresol;
+ ps->ifaces[ps->ifcount - 1].scale_type = SCALE_UP_DEC;
}
- break;
}
return (1);
}
@@ -664,7 +725,7 @@ pcap_ng_check_header(bpf_u_int32 magic, FILE *fp, u_int precision, char *errbuf,
/*
* Check whether the first 4 bytes of the file are the block
- * type for a pcap-ng savefile.
+ * type for a pcap-ng savefile.
*/
if (magic != BT_SHB) {
/*
@@ -693,7 +754,7 @@ pcap_ng_check_header(bpf_u_int32 magic, FILE *fp, u_int precision, char *errbuf,
amt_read = fread(&total_length, 1, sizeof(total_length), fp);
if (amt_read < sizeof(total_length)) {
if (ferror(fp)) {
- snprintf(errbuf, PCAP_ERRBUF_SIZE,
+ pcap_snprintf(errbuf, PCAP_ERRBUF_SIZE,
"error reading dump file: %s",
pcap_strerror(errno));
*err = 1;
@@ -709,7 +770,7 @@ pcap_ng_check_header(bpf_u_int32 magic, FILE *fp, u_int precision, char *errbuf,
amt_read = fread(&byte_order_magic, 1, sizeof(byte_order_magic), fp);
if (amt_read < sizeof(byte_order_magic)) {
if (ferror(fp)) {
- snprintf(errbuf, PCAP_ERRBUF_SIZE,
+ pcap_snprintf(errbuf, PCAP_ERRBUF_SIZE,
"error reading dump file: %s",
pcap_strerror(errno));
*err = 1;
@@ -738,7 +799,7 @@ pcap_ng_check_header(bpf_u_int32 magic, FILE *fp, u_int precision, char *errbuf,
* Check the sanity of the total length.
*/
if (total_length < sizeof(*bhdrp) + sizeof(*shbp) + sizeof(struct block_trailer)) {
- snprintf(errbuf, PCAP_ERRBUF_SIZE,
+ pcap_snprintf(errbuf, PCAP_ERRBUF_SIZE,
"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)));
@@ -773,7 +834,7 @@ pcap_ng_check_header(bpf_u_int32 magic, FILE *fp, u_int precision, char *errbuf,
break;
default:
- snprintf(errbuf, PCAP_ERRBUF_SIZE,
+ pcap_snprintf(errbuf, PCAP_ERRBUF_SIZE,
"unknown time stamp resolution %u", precision);
free(p);
*err = 1;
@@ -799,7 +860,7 @@ pcap_ng_check_header(bpf_u_int32 magic, FILE *fp, u_int precision, char *errbuf,
p->bufsize = total_length;
p->buffer = malloc(p->bufsize);
if (p->buffer == NULL) {
- snprintf(errbuf, PCAP_ERRBUF_SIZE, "out of memory");
+ pcap_snprintf(errbuf, PCAP_ERRBUF_SIZE, "out of memory");
free(p);
*err = 1;
return (NULL);
@@ -810,12 +871,12 @@ pcap_ng_check_header(bpf_u_int32 magic, FILE *fp, u_int precision, char *errbuf,
* of the SHB.
*/
bhdrp = (struct block_header *)p->buffer;
- shbp = (struct section_header_block *)(p->buffer + sizeof(struct block_header));
+ shbp = (struct section_header_block *)((u_char *)p->buffer + sizeof(struct block_header));
bhdrp->block_type = magic;
bhdrp->total_length = total_length;
shbp->byte_order_magic = byte_order_magic;
if (read_bytes(fp,
- p->buffer + (sizeof(magic) + sizeof(total_length) + sizeof(byte_order_magic)),
+ (u_char *)p->buffer + (sizeof(magic) + sizeof(total_length) + sizeof(byte_order_magic)),
total_length - (sizeof(magic) + sizeof(total_length) + sizeof(byte_order_magic)),
1, errbuf) == -1)
goto fail;
@@ -831,10 +892,12 @@ pcap_ng_check_header(bpf_u_int32 magic, FILE *fp, u_int precision, char *errbuf,
* XXX - we don't care about the section length.
*/
}
- if (shbp->major_version != PCAP_NG_VERSION_MAJOR) {
- snprintf(errbuf, PCAP_ERRBUF_SIZE,
- "unknown pcap-ng savefile major version number %u",
- shbp->major_version);
+ /* currently only SHB version 1.0 is supported */
+ if (! (shbp->major_version == PCAP_NG_VERSION_MAJOR &&
+ shbp->minor_version == PCAP_NG_VERSION_MINOR)) {
+ pcap_snprintf(errbuf, PCAP_ERRBUF_SIZE,
+ "unsupported pcap-ng savefile version %u.%u",
+ shbp->major_version, shbp->minor_version);
goto fail;
}
p->version_major = shbp->major_version;
@@ -855,7 +918,7 @@ pcap_ng_check_header(bpf_u_int32 magic, FILE *fp, u_int precision, char *errbuf,
status = read_block(fp, p, &cursor, errbuf);
if (status == 0) {
/* EOF - no IDB in this file */
- snprintf(errbuf, PCAP_ERRBUF_SIZE,
+ pcap_snprintf(errbuf, PCAP_ERRBUF_SIZE,
"the capture file has no Interface Description Blocks");
goto fail;
}
@@ -882,10 +945,22 @@ pcap_ng_check_header(bpf_u_int32 magic, FILE *fp, u_int precision, char *errbuf,
}
/*
+ * Interface capture length sanity check
+ */
+ if (idbp->snaplen > MAXIMUM_SNAPLEN) {
+ pcap_snprintf(errbuf, PCAP_ERRBUF_SIZE,
+ "invalid interface capture length %u, "
+ "bigger than maximum of %u",
+ idbp->snaplen, MAXIMUM_SNAPLEN);
+ goto fail;
+ }
+
+ /*
* Try to add this interface.
*/
if (!add_interface(p, &cursor, errbuf))
goto fail;
+
goto done;
case BT_EPB:
@@ -896,7 +971,7 @@ pcap_ng_check_header(bpf_u_int32 magic, FILE *fp, u_int precision, char *errbuf,
* not valid, as we don't know what link-layer
* encapsulation the packet has.
*/
- snprintf(errbuf, PCAP_ERRBUF_SIZE,
+ pcap_snprintf(errbuf, PCAP_ERRBUF_SIZE,
"the capture file has a packet block before any Interface Description Blocks");
goto fail;
@@ -1000,7 +1075,7 @@ pcap_ng_next_packet(pcap_t *p, struct pcap_pkthdr *hdr, u_char **data)
epbp->timestamp_low;
}
goto found;
-
+
case BT_SPB:
/*
* Get a pointer to the fixed-length portion of the
@@ -1032,7 +1107,7 @@ pcap_ng_next_packet(pcap_t *p, struct pcap_pkthdr *hdr, u_char **data)
* and the packet length.
*/
hdr->caplen = hdr->len;
- if (hdr->caplen > p->snapshot)
+ if (hdr->caplen > (bpf_u_int32)p->snapshot)
hdr->caplen = p->snapshot;
t = 0; /* no time stamps */
goto found;
@@ -1093,13 +1168,13 @@ pcap_ng_next_packet(pcap_t *p, struct pcap_pkthdr *hdr, u_char **data)
* interfaces?
*/
if (p->linktype != idbp->linktype) {
- snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
+ pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
"an interface has a type %u different from the type of the first interface",
idbp->linktype);
return (-1);
}
- if (p->snapshot != idbp->snaplen) {
- snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
+ if ((bpf_u_int32)p->snapshot != idbp->snaplen) {
+ pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
"an interface has a snapshot length %u different from the type of the first interface",
idbp->snaplen);
return (-1);
@@ -1151,7 +1226,7 @@ pcap_ng_next_packet(pcap_t *p, struct pcap_pkthdr *hdr, u_char **data)
/*
* Byte order changes.
*/
- snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
+ pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
"the file has sections with different byte orders");
return (-1);
@@ -1159,7 +1234,7 @@ pcap_ng_next_packet(pcap_t *p, struct pcap_pkthdr *hdr, u_char **data)
/*
* Not a valid SHB.
*/
- snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
+ pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
"the file has a section with a bad byte order magic field");
return (-1);
}
@@ -1169,7 +1244,7 @@ pcap_ng_next_packet(pcap_t *p, struct pcap_pkthdr *hdr, u_char **data)
* we handle.
*/
if (shbp->major_version != PCAP_NG_VERSION_MAJOR) {
- snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
+ pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
"unknown pcap-ng savefile major version number %u",
shbp->major_version);
return (-1);
@@ -1192,7 +1267,7 @@ pcap_ng_next_packet(pcap_t *p, struct pcap_pkthdr *hdr, u_char **data)
* Not a packet block, IDB, or SHB; ignore it.
*/
break;
- }
+ }
}
found:
@@ -1203,17 +1278,23 @@ found:
/*
* Yes. Fail.
*/
- snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
+ pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
"a packet arrived on interface %u, but there's no Interface Description Block for that interface",
interface_id);
return (-1);
}
/*
- * Convert the time stamp to a struct timeval.
+ * Convert the time stamp to seconds and fractions of a second,
+ * with the fractions being in units of the file-supplied resolution.
*/
sec = t / ps->ifaces[interface_id].tsresol + ps->ifaces[interface_id].tsoffset;
frac = t % ps->ifaces[interface_id].tsresol;
+
+ /*
+ * Convert the fractions from units of the file-supplied resolution
+ * to units of the user-requested resolution.
+ */
switch (ps->ifaces[interface_id].scale_type) {
case PASS_THROUGH:
@@ -1223,29 +1304,111 @@ found:
*/
break;
- case SCALE_UP:
- case SCALE_DOWN:
+ case SCALE_UP_DEC:
/*
- * The interface resolution is different from what the
- * user wants; scale up or down to that resolution.
+ * The interface resolution is less than what the user
+ * wants; scale the fractional part up to the units of
+ * the resolution the user requested by multiplying by
+ * the quotient of the user-requested resolution and the
+ * file-supplied resolution.
*
- * XXX - if ps->ifaces[interface_id].tsresol is a power
- * of 10, we could just multiply by the quotient of
- * ps->ifaces[interface_id].tsresol and ps->user_tsresol
- * in the scale-up case, and divide by the quotient of
- * ps->user_tsresol and ps->ifaces[interface_id].tsresol
- * in the scale-down case, as we know those are integers,
- * which would involve fewer arithmetic operations.
+ * Those resolutions are both powers of 10, and the user-
+ * requested resolution is greater than the file-supplied
+ * resolution, so the quotient in question is an integer.
+ * We've calculated that quotient already, so we just
+ * multiply by it.
+ */
+ frac *= ps->ifaces[interface_id].scale_factor;
+ break;
+
+ case SCALE_UP_BIN:
+ /*
+ * The interface resolution is less than what the user
+ * wants; scale the fractional part up to the units of
+ * the resolution the user requested by multiplying by
+ * the quotient of the user-requested resolution and the
+ * file-supplied resolution.
*
- * Is there something clever we could do if
- * ps->ifaces[interface_id].tsresol is a power of 2?
+ * The file-supplied resolution is a power of 2, so the
+ * quotient is not an integer, so, in order to do this
+ * entirely with integer arithmetic, we multiply by the
+ * user-requested resolution and divide by the file-
+ * supplied resolution.
+ *
+ * XXX - Is there something clever we could do here,
+ * given that we know that the file-supplied resolution
+ * is a power of 2? Doing a multiplication followed by
+ * a division runs the risk of overflowing, and involves
+ * two non-simple arithmetic operations.
+ */
+ frac *= ps->user_tsresol;
+ frac /= ps->ifaces[interface_id].tsresol;
+ break;
+
+ case SCALE_DOWN_DEC:
+ /*
+ * The interface resolution is greater than what the user
+ * wants; scale the fractional part up to the units of
+ * the resolution the user requested by multiplying by
+ * the quotient of the user-requested resolution and the
+ * file-supplied resolution.
+ *
+ * Those resolutions are both powers of 10, and the user-
+ * requested resolution is less than the file-supplied
+ * resolution, so the quotient in question isn't an
+ * integer, but its reciprocal is, and we can just divide
+ * by the reciprocal of the quotient. We've calculated
+ * the reciprocal of that quotient already, so we must
+ * divide by it.
+ */
+ frac /= ps->ifaces[interface_id].scale_factor;
+ break;
+
+
+ case SCALE_DOWN_BIN:
+ /*
+ * The interface resolution is greater than what the user
+ * wants; convert the fractional part to units of the
+ * resolution the user requested by multiplying by the
+ * quotient of the user-requested resolution and the
+ * file-supplied resolution. We do that by multiplying
+ * by the user-requested resolution and dividing by the
+ * file-supplied resolution, as the quotient might not
+ * fit in an integer.
+ *
+ * The file-supplied resolution is a power of 2, so the
+ * quotient is not an integer, and neither is its
+ * reciprocal, so, in order to do this entirely with
+ * integer arithmetic, we multiply by the user-requested
+ * resolution and divide by the file-supplied resolution.
+ *
+ * XXX - Is there something clever we could do here,
+ * given that we know that the file-supplied resolution
+ * is a power of 2? Doing a multiplication followed by
+ * a division runs the risk of overflowing, and involves
+ * two non-simple arithmetic operations.
*/
- frac *= ps->ifaces[interface_id].tsresol;
- frac /= ps->user_tsresol;
+ frac *= ps->user_tsresol;
+ frac /= ps->ifaces[interface_id].tsresol;
break;
}
- hdr->ts.tv_sec = sec;
- hdr->ts.tv_usec = frac;
+#ifdef _WIN32
+ /*
+ * tv_sec and tv_used in the Windows struct timeval are both
+ * longs.
+ */
+ hdr->ts.tv_sec = (long)sec;
+ hdr->ts.tv_usec = (long)frac;
+#else
+ /*
+ * tv_sec in the UN*X struct timeval is a time_t; tv_usec is
+ * suseconds_t in UN*Xes that work the way the current Single
+ * UNIX Standard specify - but not all older UN*Xes necessarily
+ * support that type, so just cast to int.
+ */
+ hdr->ts.tv_sec = (time_t)sec;
+ hdr->ts.tv_usec = (int)frac;
+#endif
/*
* Get a pointer to the packet data.
diff --git a/contrib/libpcap/sf-pcap.c b/contrib/libpcap/sf-pcap.c
index 8180bc9d8da9..ac305d4b01f3 100644
--- a/contrib/libpcap/sf-pcap.c
+++ b/contrib/libpcap/sf-pcap.c
@@ -37,9 +37,9 @@ static const char rcsid[] _U_ =
#include "config.h"
#endif
-#ifdef WIN32
+#ifdef _WIN32
#include <pcap-stdinc.h>
-#else /* WIN32 */
+#else /* _WIN32 */
#if HAVE_INTTYPES_H
#include <inttypes.h>
#elif HAVE_STDINT_H
@@ -49,7 +49,7 @@ static const char rcsid[] _U_ =
#include <sys/bitypes.h>
#endif
#include <sys/types.h>
-#endif /* WIN32 */
+#endif /* _WIN32 */
#include <errno.h>
#include <memory.h>
@@ -70,7 +70,7 @@ static const char rcsid[] _U_ =
/*
* Setting O_BINARY on DOS/Windows is a bit tricky
*/
-#if defined(WIN32)
+#if defined(_WIN32)
#define SET_BINMODE(f) _setmode(_fileno(f), _O_BINARY)
#elif defined(MSDOS)
#if defined(__HIGHC__)
@@ -149,7 +149,7 @@ struct pcap_sf {
*/
pcap_t *
pcap_check_header(bpf_u_int32 magic, FILE *fp, u_int precision, char *errbuf,
- int *err)
+ int *err)
{
struct pcap_file_header hdr;
size_t amt_read;
@@ -185,11 +185,11 @@ pcap_check_header(bpf_u_int32 magic, FILE *fp, u_int precision, char *errbuf,
sizeof(hdr) - sizeof(hdr.magic), fp);
if (amt_read != sizeof(hdr) - sizeof(hdr.magic)) {
if (ferror(fp)) {
- snprintf(errbuf, PCAP_ERRBUF_SIZE,
+ pcap_snprintf(errbuf, PCAP_ERRBUF_SIZE,
"error reading dump file: %s",
pcap_strerror(errno));
} else {
- snprintf(errbuf, PCAP_ERRBUF_SIZE,
+ pcap_snprintf(errbuf, PCAP_ERRBUF_SIZE,
"truncated dump file; tried to read %lu file header bytes, only got %lu",
(unsigned long)sizeof(hdr),
(unsigned long)amt_read);
@@ -211,13 +211,36 @@ pcap_check_header(bpf_u_int32 magic, FILE *fp, u_int precision, char *errbuf,
}
if (hdr.version_major < PCAP_VERSION_MAJOR) {
- snprintf(errbuf, PCAP_ERRBUF_SIZE,
+ pcap_snprintf(errbuf, PCAP_ERRBUF_SIZE,
"archaic pcap savefile format");
*err = 1;
return (NULL);
}
/*
+ * currently only versions 2.[0-4] are supported with
+ * the exception of 543.0 for DG/UX tcpdump.
+ */
+ if (! ((hdr.version_major == PCAP_VERSION_MAJOR &&
+ hdr.version_minor <= PCAP_VERSION_MINOR) ||
+ (hdr.version_major == 543 &&
+ hdr.version_minor == 0))) {
+ pcap_snprintf(errbuf, PCAP_ERRBUF_SIZE,
+ "unsupported pcap savefile version %u.%u",
+ hdr.version_major, hdr.version_minor);
+ *err = 1;
+ return NULL;
+ }
+
+ if (hdr.snaplen > MAXIMUM_SNAPLEN) {
+ pcap_snprintf(errbuf, PCAP_ERRBUF_SIZE,
+ "invalid file capture length %u, bigger than "
+ "maximum of %u", hdr.snaplen, MAXIMUM_SNAPLEN);
+ *err = 1;
+ return NULL;
+ }
+
+ /*
* OK, this is a good pcap file.
* Allocate a pcap_t for it.
*/
@@ -282,7 +305,7 @@ pcap_check_header(bpf_u_int32 magic, FILE *fp, u_int precision, char *errbuf,
break;
default:
- snprintf(errbuf, PCAP_ERRBUF_SIZE,
+ pcap_snprintf(errbuf, PCAP_ERRBUF_SIZE,
"unknown time stamp resolution %u", precision);
free(p);
*err = 1;
@@ -377,7 +400,7 @@ pcap_check_header(bpf_u_int32 magic, FILE *fp, u_int precision, char *errbuf,
}
p->buffer = malloc(p->bufsize);
if (p->buffer == NULL) {
- snprintf(errbuf, PCAP_ERRBUF_SIZE, "out of memory");
+ pcap_snprintf(errbuf, PCAP_ERRBUF_SIZE, "out of memory");
free(p);
*err = 1;
return (NULL);
@@ -412,13 +435,13 @@ pcap_next_packet(pcap_t *p, struct pcap_pkthdr *hdr, u_char **data)
amt_read = fread(&sf_hdr, 1, ps->hdrsize, fp);
if (amt_read != ps->hdrsize) {
if (ferror(fp)) {
- snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
+ pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
"error reading dump file: %s",
pcap_strerror(errno));
return (-1);
} else {
if (amt_read != 0) {
- snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
+ pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
"truncated dump file; tried to read %lu header bytes, only got %lu",
(unsigned long)ps->hdrsize,
(unsigned long)amt_read);
@@ -494,63 +517,93 @@ pcap_next_packet(pcap_t *p, struct pcap_pkthdr *hdr, u_char **data)
/*
* This can happen due to Solaris 2.3 systems tripping
* over the BUFMOD problem and not setting the snapshot
- * correctly in the savefile header. If the caplen isn't
- * grossly wrong, try to salvage.
+ * correctly in the savefile header.
+ * This can also happen with a corrupted savefile or a
+ * savefile built/modified by a fuzz tester.
+ * If the caplen isn't grossly wrong, try to salvage.
*/
- static u_char *tp = NULL;
- static size_t tsize = 0;
+ size_t bytes_to_discard;
+ size_t bytes_to_read, bytes_read;
+ char discard_buf[4096];
if (hdr->caplen > MAXIMUM_SNAPLEN) {
- snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
- "bogus savefile header");
+ pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
+ "invalid packet capture length %u, bigger than "
+ "maximum of %u", hdr->caplen, MAXIMUM_SNAPLEN);
return (-1);
}
- if (tsize < hdr->caplen) {
- tsize = ((hdr->caplen + 1023) / 1024) * 1024;
- if (tp != NULL)
- free((u_char *)tp);
- tp = (u_char *)malloc(tsize);
- if (tp == NULL) {
- tsize = 0;
- snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
- "BUFMOD hack malloc");
- return (-1);
- }
- }
- amt_read = fread((char *)tp, 1, hdr->caplen, fp);
- if (amt_read != hdr->caplen) {
+ /*
+ * XXX - we don't grow the buffer here because some
+ * program might assume that it will never get packets
+ * bigger than the snapshot length; for example, it might
+ * copy data from our buffer to a buffer of its own,
+ * allocated based on the return value of pcap_snapshot().
+ *
+ * Read the first p->bufsize bytes into the buffer.
+ */
+ amt_read = fread(p->buffer, 1, p->bufsize, fp);
+ if (amt_read != p->bufsize) {
if (ferror(fp)) {
- snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
+ pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
"error reading dump file: %s",
pcap_strerror(errno));
} else {
- snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
+ /*
+ * Yes, this uses hdr->caplen; technically,
+ * it's true, because we would try to read
+ * and discard the rest of those bytes, and
+ * that would fail because we got EOF before
+ * the read finished.
+ */
+ pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
"truncated dump file; tried to read %u captured bytes, only got %lu",
hdr->caplen, (unsigned long)amt_read);
}
return (-1);
}
+
/*
- * We can only keep up to p->bufsize bytes. Since
- * caplen > p->bufsize is exactly how we got here,
- * we know we can only keep the first p->bufsize bytes
- * and must drop the remainder. Adjust caplen accordingly,
- * so we don't get confused later as to how many bytes we
- * have to play with.
+ * Now read and discard what's left.
+ */
+ bytes_to_discard = hdr->caplen - p->bufsize;
+ bytes_read = amt_read;
+ while (bytes_to_discard != 0) {
+ bytes_to_read = bytes_to_discard;
+ if (bytes_to_read > sizeof (discard_buf))
+ bytes_to_read = sizeof (discard_buf);
+ amt_read = fread(discard_buf, 1, bytes_to_read, fp);
+ bytes_read += amt_read;
+ if (amt_read != bytes_to_read) {
+ if (ferror(fp)) {
+ pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
+ "error reading dump file: %s",
+ pcap_strerror(errno));
+ } else {
+ pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
+ "truncated dump file; tried to read %u captured bytes, only got %lu",
+ hdr->caplen, (unsigned long)bytes_read);
+ }
+ return (-1);
+ }
+ bytes_to_discard -= amt_read;
+ }
+
+ /*
+ * Adjust caplen accordingly, so we don't get confused later
+ * as to how many bytes we have to play with.
*/
hdr->caplen = p->bufsize;
- memcpy(p->buffer, (char *)tp, p->bufsize);
} else {
/* read the packet itself */
amt_read = fread(p->buffer, 1, hdr->caplen, fp);
if (amt_read != hdr->caplen) {
if (ferror(fp)) {
- snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
+ pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
"error reading dump file: %s",
pcap_strerror(errno));
} else {
- snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
+ pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
"truncated dump file; tried to read %u captured bytes, only got %lu",
hdr->caplen, (unsigned long)amt_read);
}
@@ -608,7 +661,7 @@ static pcap_dumper_t *
pcap_setup_dump(pcap_t *p, int linktype, FILE *f, const char *fname)
{
-#if defined(WIN32) || defined(MSDOS)
+#if defined(_WIN32) || defined(MSDOS)
/*
* If we're writing to the standard output, put it in binary
* mode, as savefiles are binary files.
@@ -622,7 +675,7 @@ pcap_setup_dump(pcap_t *p, int linktype, FILE *f, const char *fname)
setbuf(f, NULL);
#endif
if (sf_write_header(p, f, linktype, p->tzoff, p->snapshot) == -1) {
- snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "Can't write to %s: %s",
+ pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "Can't write to %s: %s",
fname, pcap_strerror(errno));
if (f != stdout)
(void)fclose(f);
@@ -645,31 +698,36 @@ pcap_dump_open(pcap_t *p, const char *fname)
* link-layer type, so we can't use it.
*/
if (!p->activated) {
- snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
+ pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
"%s: not-yet-activated pcap_t passed to pcap_dump_open",
fname);
return (NULL);
}
linktype = dlt_to_linktype(p->linktype);
if (linktype == -1) {
- snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
+ pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
"%s: link-layer type %d isn't supported in savefiles",
fname, p->linktype);
return (NULL);
}
linktype |= p->linktype_ext;
+ if (fname == NULL) {
+ pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
+ "A null pointer was supplied as the file name");
+ return NULL;
+ }
if (fname[0] == '-' && fname[1] == '\0') {
f = stdout;
fname = "standard output";
} else {
-#if !defined(WIN32) && !defined(MSDOS)
+#if !defined(_WIN32) && !defined(MSDOS)
f = fopen(fname, "w");
#else
f = fopen(fname, "wb");
#endif
if (f == NULL) {
- snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "%s: %s",
+ pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "%s: %s",
fname, pcap_strerror(errno));
return (NULL);
}
@@ -682,12 +740,12 @@ pcap_dump_open(pcap_t *p, const char *fname)
*/
pcap_dumper_t *
pcap_dump_fopen(pcap_t *p, FILE *f)
-{
+{
int linktype;
linktype = dlt_to_linktype(p->linktype);
if (linktype == -1) {
- snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
+ pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
"stream: link-layer type %d isn't supported in savefiles",
p->linktype);
return (NULL);
@@ -697,6 +755,174 @@ pcap_dump_fopen(pcap_t *p, FILE *f)
return (pcap_setup_dump(p, linktype, f, "stream"));
}
+pcap_dumper_t *
+pcap_dump_open_append(pcap_t *p, const char *fname)
+{
+ FILE *f;
+ int linktype;
+ size_t amt_read;
+ struct pcap_file_header ph;
+
+ linktype = dlt_to_linktype(p->linktype);
+ if (linktype == -1) {
+ pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
+ "%s: link-layer type %d isn't supported in savefiles",
+ fname, linktype);
+ return (NULL);
+ }
+
+ if (fname == NULL) {
+ pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
+ "A null pointer was supplied as the file name");
+ return NULL;
+ }
+ if (fname[0] == '-' && fname[1] == '\0')
+ return (pcap_setup_dump(p, linktype, stdout, "standard output"));
+
+#if !defined(_WIN32) && !defined(MSDOS)
+ f = fopen(fname, "r+");
+#else
+ f = fopen(fname, "rb+");
+#endif
+ if (f == NULL) {
+ pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "%s: %s",
+ fname, pcap_strerror(errno));
+ return (NULL);
+ }
+
+ /*
+ * Try to read a pcap header.
+ */
+ amt_read = fread(&ph, 1, sizeof (ph), f);
+ if (amt_read != sizeof (ph)) {
+ if (ferror(f)) {
+ pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "%s: %s",
+ fname, pcap_strerror(errno));
+ fclose(f);
+ return (NULL);
+ } else if (feof(f) && amt_read > 0) {
+ pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
+ "%s: truncated pcap file header", fname);
+ fclose(f);
+ return (NULL);
+ }
+ }
+
+#if defined(_WIN32) || defined(MSDOS)
+ /*
+ * We turn off buffering.
+ * XXX - why? And why not on the standard output?
+ */
+ setbuf(f, NULL);
+#endif
+
+ /*
+ * If a header is already present and:
+ *
+ * it's not for a pcap file of the appropriate resolution
+ * and the right byte order for this machine;
+ *
+ * the link-layer header types don't match;
+ *
+ * the snapshot lengths don't match;
+ *
+ * return an error.
+ */
+ if (amt_read > 0) {
+ /*
+ * A header is already present.
+ * Do the checks.
+ */
+ switch (ph.magic) {
+
+ case TCPDUMP_MAGIC:
+ if (p->opt.tstamp_precision != PCAP_TSTAMP_PRECISION_MICRO) {
+ pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
+ "%s: different time stamp precision, cannot append to file", fname);
+ fclose(f);
+ return (NULL);
+ }
+ break;
+
+ case NSEC_TCPDUMP_MAGIC:
+ if (p->opt.tstamp_precision != PCAP_TSTAMP_PRECISION_NANO) {
+ pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
+ "%s: different time stamp precision, cannot append to file", fname);
+ fclose(f);
+ return (NULL);
+ }
+ break;
+
+ case SWAPLONG(TCPDUMP_MAGIC):
+ case SWAPLONG(NSEC_TCPDUMP_MAGIC):
+ pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
+ "%s: different byte order, cannot append to file", fname);
+ fclose(f);
+ return (NULL);
+
+ case KUZNETZOV_TCPDUMP_MAGIC:
+ case SWAPLONG(KUZNETZOV_TCPDUMP_MAGIC):
+ case NAVTEL_TCPDUMP_MAGIC:
+ case SWAPLONG(NAVTEL_TCPDUMP_MAGIC):
+ pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
+ "%s: not a pcap file to which we can append", fname);
+ fclose(f);
+ return (NULL);
+
+ default:
+ pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
+ "%s: not a pcap file", fname);
+ fclose(f);
+ return (NULL);
+ }
+
+ /*
+ * Good version?
+ */
+ if (ph.version_major != PCAP_VERSION_MAJOR ||
+ ph.version_minor != PCAP_VERSION_MINOR) {
+ pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
+ "%s: version is %u.%u, cannot append to file", fname,
+ ph.version_major, ph.version_minor);
+ fclose(f);
+ return (NULL);
+ }
+ if ((bpf_u_int32)linktype != ph.linktype) {
+ pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
+ "%s: different linktype, cannot append to file", fname);
+ fclose(f);
+ return (NULL);
+ }
+ if ((bpf_u_int32)p->snapshot != ph.snaplen) {
+ pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
+ "%s: different snaplen, cannot append to file", fname);
+ fclose(f);
+ return (NULL);
+ }
+ } else {
+ /*
+ * A header isn't present; attempt to write it.
+ */
+ if (sf_write_header(p, f, linktype, p->tzoff, p->snapshot) == -1) {
+ pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "Can't write to %s: %s",
+ fname, pcap_strerror(errno));
+ (void)fclose(f);
+ return (NULL);
+ }
+ }
+
+ /*
+ * Start writing at the end of the file.
+ */
+ if (fseek(f, 0, SEEK_END) == -1) {
+ pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "Can't seek to end of %s: %s",
+ fname, pcap_strerror(errno));
+ (void)fclose(f);
+ return (NULL);
+ }
+ return ((pcap_dumper_t *)f);
+}
+
FILE *
pcap_dump_file(pcap_dumper_t *p)
{
diff --git a/contrib/libpcap/sockutils.c b/contrib/libpcap/sockutils.c
new file mode 100644
index 000000000000..c05ff1a1b58b
--- /dev/null
+++ b/contrib/libpcap/sockutils.c
@@ -0,0 +1,1230 @@
+/*
+ * Copyright (c) 2002 - 2003
+ * NetGroup, Politecnico di Torino (Italy)
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the Politecnico di Torino nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+/*
+ * \file sockutils.c
+ *
+ * The goal of this file is to provide a common set of primitives for socket
+ * manipulation.
+ *
+ * Although the socket interface defined in the RFC 2553 (and its updates)
+ * is excellent, there are still differences between the behavior of those
+ * routines on UN*X and Windows, and between UN*Xes.
+ *
+ * These calls provide an interface similar to the socket interface, but
+ * that hides the differences between operating systems. It does not
+ * attempt to significantly improve on the socket interface in other
+ * ways.
+ */
+
+#include <string.h> /* for strerror() */
+#include <errno.h> /* for the errno variable */
+#include <stdio.h> /* for the stderr file */
+#include <stdlib.h> /* for malloc() and free() */
+#ifdef HAVE_LIMITS_H
+#include <limits.h>
+#else
+#define INT_MAX 2147483647
+#endif
+
+#include "portability.h"
+#include "sockutils.h"
+
+#ifdef _WIN32
+ /*
+ * Winsock initialization.
+ *
+ * Ask for WinSock 2.2.
+ */
+ #define WINSOCK_MAJOR_VERSION 2
+ #define WINSOCK_MINOR_VERSION 2
+
+ static int sockcount = 0; /*!< Variable that allows calling the WSAStartup() only one time */
+#endif
+
+/* Some minor differences between UNIX and Win32 */
+#ifdef _WIN32
+ #define SHUT_WR SD_SEND /* The control code for shutdown() is different in Win32 */
+#endif
+
+/* Size of the buffer that has to keep error messages */
+#define SOCK_ERRBUF_SIZE 1024
+
+/* Constants; used in order to keep strings here */
+#define SOCKET_NO_NAME_AVAILABLE "No name available"
+#define SOCKET_NO_PORT_AVAILABLE "No port available"
+#define SOCKET_NAME_NULL_DAD "Null address (possibly DAD Phase)"
+
+/****************************************************
+ * *
+ * Locally defined functions *
+ * *
+ ****************************************************/
+
+static int sock_ismcastaddr(const struct sockaddr *saddr);
+
+/****************************************************
+ * *
+ * Function bodies *
+ * *
+ ****************************************************/
+
+/*
+ * \brief It retrieves the error message after an error occurred in the socket interface.
+ *
+ * This function is defined because of the different way errors are returned in UNIX
+ * and Win32. This function provides a consistent way to retrieve the error message
+ * (after a socket error occurred) on all the platforms.
+ *
+ * \param caller: a pointer to a user-allocated string which contains a message that has
+ * to be printed *before* the true error message. It could be, for example, 'this error
+ * comes from the recv() call at line 31'. It may be NULL.
+ *
+ * \param errbuf: a pointer to an user-allocated buffer that will contain the complete
+ * error message. This buffer has to be at least 'errbuflen' in length.
+ * It can be NULL; in this case the error cannot be printed.
+ *
+ * \param errbuflen: length of the buffer that will contains the error. The error message cannot be
+ * larger than 'errbuflen - 1' because the last char is reserved for the string terminator.
+ *
+ * \return No return values. The error message is returned in the 'string' parameter.
+ */
+void sock_geterror(const char *caller, char *errbuf, int errbuflen)
+{
+#ifdef _WIN32
+ int retval;
+ int code;
+ TCHAR message[SOCK_ERRBUF_SIZE]; /* It will be char (if we're using ascii) or wchar_t (if we're using unicode) */
+
+ if (errbuf == NULL)
+ return;
+
+ code = GetLastError();
+
+ retval = FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS |
+ FORMAT_MESSAGE_MAX_WIDTH_MASK,
+ NULL, code, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
+ message, sizeof(message) / sizeof(TCHAR), NULL);
+
+ if (retval == 0)
+ {
+ if ((caller) && (*caller))
+ pcap_snprintf(errbuf, errbuflen, "%sUnable to get the exact error message", caller);
+ else
+ pcap_snprintf(errbuf, errbuflen, "Unable to get the exact error message");
+ return;
+ }
+ else
+ {
+ if ((caller) && (*caller))
+ pcap_snprintf(errbuf, errbuflen, "%s%s (code %d)", caller, message, code);
+ else
+ pcap_snprintf(errbuf, errbuflen, "%s (code %d)", message, code);
+ }
+#else
+ char *message;
+
+ if (errbuf == NULL)
+ return;
+
+ message = strerror(errno);
+
+ if ((caller) && (*caller))
+ pcap_snprintf(errbuf, errbuflen, "%s%s (code %d)", caller, message, errno);
+ else
+ pcap_snprintf(errbuf, errbuflen, "%s (code %d)", message, errno);
+#endif
+}
+
+/*
+ * \brief It initializes sockets.
+ *
+ * This function is pretty useless on UNIX, since socket initialization is not required.
+ * However it is required on Win32. In UNIX, this function appears to be completely empty.
+ *
+ * \param errbuf: a pointer to an user-allocated buffer that will contain the complete
+ * error message. This buffer has to be at least 'errbuflen' in length.
+ * It can be NULL; in this case the error cannot be printed.
+ *
+ * \param errbuflen: length of the buffer that will contains the error. The error message cannot be
+ * larger than 'errbuflen - 1' because the last char is reserved for the string terminator.
+ *
+ * \return '0' if everything is fine, '-1' if some errors occurred. The error message is returned
+ * in the 'errbuf' variable.
+ */
+int sock_init(char *errbuf, int errbuflen)
+{
+#ifdef _WIN32
+ if (sockcount == 0)
+ {
+ WSADATA wsaData; /* helper variable needed to initialize Winsock */
+
+ if (WSAStartup(MAKEWORD(WINSOCK_MAJOR_VERSION,
+ WINSOCK_MINOR_VERSION), &wsaData) != 0)
+ {
+ if (errbuf)
+ pcap_snprintf(errbuf, errbuflen, "Failed to initialize Winsock\n");
+
+ WSACleanup();
+
+ return -1;
+ }
+ }
+
+ sockcount++;
+#endif
+
+ return 0;
+}
+
+/*
+ * \brief It deallocates sockets.
+ *
+ * This function is pretty useless on UNIX, since socket deallocation is not required.
+ * However it is required on Win32. In UNIX, this function appears to be completely empty.
+ *
+ * \return No error values.
+ */
+void sock_cleanup(void)
+{
+#ifdef _WIN32
+ sockcount--;
+
+ if (sockcount == 0)
+ WSACleanup();
+#endif
+}
+
+/*
+ * \brief It checks if the sockaddr variable contains a multicast address.
+ *
+ * \return '0' if the address is multicast, '-1' if it is not.
+ */
+static int sock_ismcastaddr(const struct sockaddr *saddr)
+{
+ if (saddr->sa_family == PF_INET)
+ {
+ struct sockaddr_in *saddr4 = (struct sockaddr_in *) saddr;
+ if (IN_MULTICAST(ntohl(saddr4->sin_addr.s_addr))) return 0;
+ else return -1;
+ }
+ else
+ {
+ struct sockaddr_in6 *saddr6 = (struct sockaddr_in6 *) saddr;
+ if (IN6_IS_ADDR_MULTICAST(&saddr6->sin6_addr)) return 0;
+ else return -1;
+ }
+}
+
+/*
+ * \brief It initializes a network connection both from the client and the server side.
+ *
+ * In case of a client socket, this function calls socket() and connect().
+ * In the meanwhile, it checks for any socket error.
+ * If an error occurs, it writes the error message into 'errbuf'.
+ *
+ * In case of a server socket, the function calls socket(), bind() and listen().
+ *
+ * This function is usually preceeded by the sock_initaddress().
+ *
+ * \param addrinfo: pointer to an addrinfo variable which will be used to
+ * open the socket and such. This variable is the one returned by the previous call to
+ * sock_initaddress().
+ *
+ * \param server: '1' if this is a server socket, '0' otherwise.
+ *
+ * \param nconn: number of the connections that are allowed to wait into the listen() call.
+ * This value has no meanings in case of a client socket.
+ *
+ * \param errbuf: a pointer to an user-allocated buffer that will contain the complete
+ * error message. This buffer has to be at least 'errbuflen' in length.
+ * It can be NULL; in this case the error cannot be printed.
+ *
+ * \param errbuflen: length of the buffer that will contains the error. The error message cannot be
+ * larger than 'errbuflen - 1' because the last char is reserved for the string terminator.
+ *
+ * \return the socket that has been opened (that has to be used in the following sockets calls)
+ * if everything is fine, '0' if some errors occurred. The error message is returned
+ * in the 'errbuf' variable.
+ */
+SOCKET sock_open(struct addrinfo *addrinfo, int server, int nconn, char *errbuf, int errbuflen)
+{
+ SOCKET sock;
+
+ sock = socket(addrinfo->ai_family, addrinfo->ai_socktype, addrinfo->ai_protocol);
+ if (sock == -1)
+ {
+ sock_geterror("socket(): ", errbuf, errbuflen);
+ return -1;
+ }
+
+
+ /* This is a server socket */
+ if (server)
+ {
+#ifdef BSD
+ /*
+ * Force the use of IPv6-only addresses; in BSD you can accept both v4 and v6
+ * connections if you have a "NULL" pointer as the nodename in the getaddrinfo()
+ * This behavior is not clear in the RFC 2553, so each system implements the
+ * bind() differently from this point of view
+ */
+ if (addrinfo->ai_family == PF_INET6)
+ {
+ int on;
+
+ if (setsockopt(sock, IPPROTO_IPV6, IPV6_BINDV6ONLY, (char *)&on, sizeof (int)) == -1)
+ {
+ if (errbuf)
+ pcap_snprintf(errbuf, errbuflen, "setsockopt(IPV6_BINDV6ONLY)");
+ return -1;
+ }
+ }
+#endif
+
+ /* WARNING: if the address is a mcast one, I should place the proper Win32 code here */
+ if (bind(sock, addrinfo->ai_addr, (int) addrinfo->ai_addrlen) != 0)
+ {
+ sock_geterror("bind(): ", errbuf, errbuflen);
+ return -1;
+ }
+
+ if (addrinfo->ai_socktype == SOCK_STREAM)
+ if (listen(sock, nconn) == -1)
+ {
+ sock_geterror("listen(): ", errbuf, errbuflen);
+ return -1;
+ }
+
+ /* server side ended */
+ return sock;
+ }
+ else /* we're the client */
+ {
+ struct addrinfo *tempaddrinfo;
+ char *errbufptr;
+ size_t bufspaceleft;
+
+ tempaddrinfo = addrinfo;
+ errbufptr = errbuf;
+ bufspaceleft = errbuflen;
+ *errbufptr = 0;
+
+ /*
+ * We have to loop though all the addinfo returned.
+ * For instance, we can have both IPv6 and IPv4 addresses, but the service we're trying
+ * to connect to is unavailable in IPv6, so we have to try in IPv4 as well
+ */
+ while (tempaddrinfo)
+ {
+
+ if (connect(sock, tempaddrinfo->ai_addr, (int) tempaddrinfo->ai_addrlen) == -1)
+ {
+ size_t msglen;
+ char TmpBuffer[100];
+ char SocketErrorMessage[SOCK_ERRBUF_SIZE];
+
+ /*
+ * We have to retrieve the error message before any other socket call completes, otherwise
+ * the error message is lost
+ */
+ sock_geterror(NULL, SocketErrorMessage, sizeof(SocketErrorMessage));
+
+ /* Returns the numeric address of the host that triggered the error */
+ sock_getascii_addrport((struct sockaddr_storage *) tempaddrinfo->ai_addr, TmpBuffer, sizeof(TmpBuffer), NULL, 0, NI_NUMERICHOST, TmpBuffer, sizeof(TmpBuffer));
+
+ pcap_snprintf(errbufptr, bufspaceleft,
+ "Is the server properly installed on %s? connect() failed: %s", TmpBuffer, SocketErrorMessage);
+
+ /* In case more then one 'connect' fails, we manage to keep all the error messages */
+ msglen = strlen(errbufptr);
+
+ errbufptr[msglen] = ' ';
+ errbufptr[msglen + 1] = 0;
+
+ bufspaceleft = bufspaceleft - (msglen + 1);
+ errbufptr += (msglen + 1);
+
+ tempaddrinfo = tempaddrinfo->ai_next;
+ }
+ else
+ break;
+ }
+
+ /*
+ * Check how we exit from the previous loop
+ * If tempaddrinfo is equal to NULL, it means that all the connect() failed.
+ */
+ if (tempaddrinfo == NULL)
+ {
+ closesocket(sock);
+ return -1;
+ }
+ else
+ return sock;
+ }
+}
+
+/*
+ * \brief Closes the present (TCP and UDP) socket connection.
+ *
+ * This function sends a shutdown() on the socket in order to disable send() calls
+ * (while recv() ones are still allowed). Then, it closes the socket.
+ *
+ * \param sock: the socket identifier of the connection that has to be closed.
+ *
+ * \param errbuf: a pointer to an user-allocated buffer that will contain the complete
+ * error message. This buffer has to be at least 'errbuflen' in length.
+ * It can be NULL; in this case the error cannot be printed.
+ *
+ * \param errbuflen: length of the buffer that will contains the error. The error message cannot be
+ * larger than 'errbuflen - 1' because the last char is reserved for the string terminator.
+ *
+ * \return '0' if everything is fine, '-1' if some errors occurred. The error message is returned
+ * in the 'errbuf' variable.
+ */
+int sock_close(SOCKET sock, char *errbuf, int errbuflen)
+{
+ /*
+ * SHUT_WR: subsequent calls to the send function are disallowed.
+ * For TCP sockets, a FIN will be sent after all data is sent and
+ * acknowledged by the Server.
+ */
+ if (shutdown(sock, SHUT_WR))
+ {
+ sock_geterror("shutdown(): ", errbuf, errbuflen);
+ /* close the socket anyway */
+ closesocket(sock);
+ return -1;
+ }
+
+ closesocket(sock);
+ return 0;
+}
+
+/*
+ * \brief Checks that the address, port and flags given are valids and it returns an 'addrinfo' structure.
+ *
+ * This function basically calls the getaddrinfo() calls, and it performs a set of sanity checks
+ * to control that everything is fine (e.g. a TCP socket cannot have a mcast address, and such).
+ * If an error occurs, it writes the error message into 'errbuf'.
+ *
+ * \param host: a pointer to a string identifying the host. It can be
+ * a host name, a numeric literal address, or NULL or "" (useful
+ * in case of a server socket which has to bind to all addresses).
+ *
+ * \param port: a pointer to a user-allocated buffer containing the network port to use.
+ *
+ * \param hints: an addrinfo variable (passed by reference) containing the flags needed to create the
+ * addrinfo structure appropriately.
+ *
+ * \param addrinfo: it represents the true returning value. This is a pointer to an addrinfo variable
+ * (passed by reference), which will be allocated by this function and returned back to the caller.
+ * This variable will be used in the next sockets calls.
+ *
+ * \param errbuf: a pointer to an user-allocated buffer that will contain the complete
+ * error message. This buffer has to be at least 'errbuflen' in length.
+ * It can be NULL; in this case the error cannot be printed.
+ *
+ * \param errbuflen: length of the buffer that will contains the error. The error message cannot be
+ * larger than 'errbuflen - 1' because the last char is reserved for the string terminator.
+ *
+ * \return '0' if everything is fine, '-1' if some errors occurred. The error message is returned
+ * in the 'errbuf' variable. The addrinfo variable that has to be used in the following sockets calls is
+ * returned into the addrinfo parameter.
+ *
+ * \warning The 'addrinfo' variable has to be deleted by the programmer by calling freeaddrinfo() when
+ * it is no longer needed.
+ *
+ * \warning This function requires the 'hints' variable as parameter. The semantic of this variable is the same
+ * of the one of the corresponding variable used into the standard getaddrinfo() socket function. We suggest
+ * the programmer to look at that function in order to set the 'hints' variable appropriately.
+ */
+int sock_initaddress(const char *host, const char *port,
+ struct addrinfo *hints, struct addrinfo **addrinfo, char *errbuf, int errbuflen)
+{
+ int retval;
+
+ retval = getaddrinfo(host, port, hints, addrinfo);
+ if (retval != 0)
+ {
+ /*
+ * if the getaddrinfo() fails, you have to use gai_strerror(), instead of using the standard
+ * error routines (errno) in UNIX; Winsock suggests using the GetLastError() instead.
+ */
+ if (errbuf)
+ {
+#ifdef _WIN32
+ sock_geterror("getaddrinfo(): ", errbuf, errbuflen);
+#else
+ pcap_snprintf(errbuf, errbuflen, "getaddrinfo() %s", gai_strerror(retval));
+#endif
+ }
+ return -1;
+ }
+ /*
+ * \warning SOCKET: I should check all the accept() in order to bind to all addresses in case
+ * addrinfo has more han one pointers
+ */
+
+ /*
+ * This software only supports PF_INET and PF_INET6.
+ *
+ * XXX - should we just check that at least *one* address is
+ * either PF_INET or PF_INET6, and, when using the list,
+ * ignore all addresses that are neither? (What, no IPX
+ * support? :-))
+ */
+ if (((*addrinfo)->ai_family != PF_INET) &&
+ ((*addrinfo)->ai_family != PF_INET6))
+ {
+ if (errbuf)
+ pcap_snprintf(errbuf, errbuflen, "getaddrinfo(): socket type not supported");
+ return -1;
+ }
+
+ /*
+ * You can't do multicast (or broadcast) TCP.
+ */
+ if (((*addrinfo)->ai_socktype == SOCK_STREAM) &&
+ (sock_ismcastaddr((*addrinfo)->ai_addr) == 0))
+ {
+ if (errbuf)
+ pcap_snprintf(errbuf, errbuflen, "getaddrinfo(): multicast addresses are not valid when using TCP streams");
+ return -1;
+ }
+
+ return 0;
+}
+
+/*
+ * \brief It sends the amount of data contained into 'buffer' on the given socket.
+ *
+ * This function basically calls the send() socket function and it checks that all
+ * the data specified in 'buffer' (of size 'size') will be sent. If an error occurs,
+ * it writes the error message into 'errbuf'.
+ * In case the socket buffer does not have enough space, it loops until all data
+ * has been sent.
+ *
+ * \param socket: the connected socket currently opened.
+ *
+ * \param buffer: a char pointer to a user-allocated buffer in which data is contained.
+ *
+ * \param size: number of bytes that have to be sent.
+ *
+ * \param errbuf: a pointer to an user-allocated buffer that will contain the complete
+ * error message. This buffer has to be at least 'errbuflen' in length.
+ * It can be NULL; in this case the error cannot be printed.
+ *
+ * \param errbuflen: length of the buffer that will contains the error. The error message cannot be
+ * larger than 'errbuflen - 1' because the last char is reserved for the string terminator.
+ *
+ * \return '0' if everything is fine, '-1' if some errors occurred. The error message is returned
+ * in the 'errbuf' variable.
+ */
+int sock_send(SOCKET socket, const char *buffer, int size, char *errbuf, int errbuflen)
+{
+ int nsent;
+
+send:
+#ifdef linux
+ /*
+ * Another pain... in Linux there's this flag
+ * MSG_NOSIGNAL
+ * Requests not to send SIGPIPE on errors on stream-oriented
+ * sockets when the other end breaks the connection.
+ * The EPIPE error is still returned.
+ */
+ nsent = send(socket, buffer, size, MSG_NOSIGNAL);
+#else
+ nsent = send(socket, buffer, size, 0);
+#endif
+
+ if (nsent == -1)
+ {
+ sock_geterror("send(): ", errbuf, errbuflen);
+ return -1;
+ }
+
+ if (nsent != size)
+ {
+ size -= nsent;
+ buffer += nsent;
+ goto send;
+ }
+
+ return 0;
+}
+
+/*
+ * \brief It copies the amount of data contained into 'buffer' into 'tempbuf'.
+ * and it checks for buffer overflows.
+ *
+ * This function basically copies 'size' bytes of data contained into 'buffer'
+ * into 'tempbuf', starting at offset 'offset'. Before that, it checks that the
+ * resulting buffer will not be larger than 'totsize'. Finally, it updates
+ * the 'offset' variable in order to point to the first empty location of the buffer.
+ *
+ * In case the function is called with 'checkonly' equal to 1, it does not copy
+ * the data into the buffer. It only checks for buffer overflows and it updates the
+ * 'offset' variable. This mode can be useful when the buffer already contains the
+ * data (maybe because the producer writes directly into the target buffer), so
+ * only the buffer overflow check has to be made.
+ * In this case, both 'buffer' and 'tempbuf' can be NULL values.
+ *
+ * This function is useful in case the userland application does not know immediately
+ * all the data it has to write into the socket. This function provides a way to create
+ * the "stream" step by step, appending the new data to the old one. Then, when all the
+ * data has been bufferized, the application can call the sock_send() function.
+ *
+ * \param buffer: a char pointer to a user-allocated buffer that keeps the data
+ * that has to be copied.
+ *
+ * \param size: number of bytes that have to be copied.
+ *
+ * \param tempbuf: user-allocated buffer (of size 'totsize') in which data
+ * has to be copied.
+ *
+ * \param offset: an index into 'tempbuf' which keeps the location of its first
+ * empty location.
+ *
+ * \param totsize: total size of the buffer in which data is being copied.
+ *
+ * \param checkonly: '1' if we do not want to copy data into the buffer and we
+ * want just do a buffer ovreflow control, '0' if data has to be copied as well.
+ *
+ * \param errbuf: a pointer to an user-allocated buffer that will contain the complete
+ * error message. This buffer has to be at least 'errbuflen' in length.
+ * It can be NULL; in this case the error cannot be printed.
+ *
+ * \param errbuflen: length of the buffer that will contains the error. The error message cannot be
+ * larger than 'errbuflen - 1' because the last char is reserved for the string terminator.
+ *
+ * \return '0' if everything is fine, '-1' if some errors occurred. The error message
+ * is returned in the 'errbuf' variable. When the function returns, 'tempbuf' will
+ * have the new string appended, and 'offset' will keep the length of that buffer.
+ * In case of 'checkonly == 1', data is not copied, but 'offset' is updated in any case.
+ *
+ * \warning This function assumes that the buffer in which data has to be stored is
+ * large 'totbuf' bytes.
+ *
+ * \warning In case of 'checkonly', be carefully to call this function *before* copying
+ * the data into the buffer. Otherwise, the control about the buffer overflow is useless.
+ */
+int sock_bufferize(const char *buffer, int size, char *tempbuf, int *offset, int totsize, int checkonly, char *errbuf, int errbuflen)
+{
+ if ((*offset + size) > totsize)
+ {
+ if (errbuf)
+ pcap_snprintf(errbuf, errbuflen, "Not enough space in the temporary send buffer.");
+ return -1;
+ }
+
+ if (!checkonly)
+ memcpy(tempbuf + (*offset), buffer, size);
+
+ (*offset) += size;
+
+ return 0;
+}
+
+/*
+ * \brief It waits on a connected socket and it manages to receive data.
+ *
+ * This function basically calls the recv() socket function and it checks that no
+ * error occurred. If that happens, it writes the error message into 'errbuf'.
+ *
+ * This function changes its behavior according to the 'receiveall' flag: if we
+ * want to receive exactly 'size' byte, it loops on the recv() until all the requested
+ * data is arrived. Otherwise, it returns the data currently available.
+ *
+ * In case the socket does not have enough data available, it cycles on the recv()
+ * until the requested data (of size 'size') is arrived.
+ * In this case, it blocks until the number of bytes read is equal to 'size'.
+ *
+ * \param sock: the connected socket currently opened.
+ *
+ * \param buffer: a char pointer to a user-allocated buffer in which data has to be stored
+ *
+ * \param size: size of the allocated buffer. WARNING: this indicates the number of bytes
+ * that we are expecting to be read.
+ *
+ * \param receiveall: if '0' (or SOCK_RECEIVEALL_NO), it returns as soon as some data
+ * is ready; otherwise, (or SOCK_RECEIVEALL_YES) it waits until 'size' data has been
+ * received (in case the socket does not have enough data available).
+ *
+ * \param errbuf: a pointer to an user-allocated buffer that will contain the complete
+ * error message. This buffer has to be at least 'errbuflen' in length.
+ * It can be NULL; in this case the error cannot be printed.
+ *
+ * \param errbuflen: length of the buffer that will contains the error. The error message cannot be
+ * larger than 'errbuflen - 1' because the last char is reserved for the string terminator.
+ *
+ * \return the number of bytes read if everything is fine, '-1' if some errors occurred.
+ * The error message is returned in the 'errbuf' variable.
+ */
+
+/*
+ * On UN*X, recv() returns ssize_t.
+ * On Windows, there *is* no ssize_t, and it returns an int.
+ * Define ssize_t as int on Windows so we can use it as the return value
+ * from recv().
+ */
+#ifdef _WIN32
+typedef int ssize_t;
+#endif
+
+int sock_recv(SOCKET sock, void *buffer, size_t size, int receiveall,
+ char *errbuf, int errbuflen)
+{
+ char *bufp = buffer;
+ int remaining;
+ ssize_t nread;
+
+ if (size == 0)
+ {
+ SOCK_ASSERT("I have been requested to read zero bytes", 1);
+ return 0;
+ }
+ if (size > INT_MAX)
+ {
+ pcap_snprintf(errbuf, errbuflen, "Can't read more than %u bytes with sock_recv",
+ INT_MAX);
+ return -1;
+ }
+
+ bufp = (char *) buffer;
+ remaining = (int) size;
+
+ /*
+ * We don't use MSG_WAITALL because it's not supported in
+ * Win32.
+ */
+ for (;;) {
+ nread = recv(sock, bufp, remaining, 0);
+
+ if (nread == -1)
+ {
+#ifndef _WIN32
+ if (errno == EINTR)
+ return -3;
+#endif
+ sock_geterror("recv(): ", errbuf, errbuflen);
+ return -1;
+ }
+
+ if (nread == 0)
+ {
+ if (errbuf)
+ {
+ pcap_snprintf(errbuf, errbuflen,
+ "The other host terminated the connection.");
+ }
+ return -1;
+ }
+
+ /*
+ * Do we want to read the amount requested, or just return
+ * what we got?
+ */
+ if (!receiveall)
+ {
+ /*
+ * Just return what we got.
+ */
+ return (int) nread;
+ }
+
+ bufp += nread;
+ remaining -= nread;
+
+ if (remaining == 0)
+ return (int) size;
+ }
+}
+
+/*
+ * \brief It discards N bytes that are currently waiting to be read on the current socket.
+ *
+ * This function is useful in case we receive a message we cannot understand (e.g.
+ * wrong version number when receiving a network packet), so that we have to discard all
+ * data before reading a new message.
+ *
+ * This function will read 'size' bytes from the socket and discard them.
+ * It defines an internal buffer in which data will be copied; however, in case
+ * this buffer is not large enough, it will cycle in order to read everything as well.
+ *
+ * \param sock: the connected socket currently opened.
+ *
+ * \param size: number of bytes that have to be discarded.
+ *
+ * \param errbuf: a pointer to an user-allocated buffer that will contain the complete
+ * error message. This buffer has to be at least 'errbuflen' in length.
+ * It can be NULL; in this case the error cannot be printed.
+ *
+ * \param errbuflen: length of the buffer that will contains the error. The error message cannot be
+ * larger than 'errbuflen - 1' because the last char is reserved for the string terminator.
+ *
+ * \return '0' if everything is fine, '-1' if some errors occurred.
+ * The error message is returned in the 'errbuf' variable.
+ */
+int sock_discard(SOCKET sock, int size, char *errbuf, int errbuflen)
+{
+#define TEMP_BUF_SIZE 32768
+
+ char buffer[TEMP_BUF_SIZE]; /* network buffer, to be used when the message is discarded */
+
+ /*
+ * A static allocation avoids the need of a 'malloc()' each time we want to discard a message
+ * Our feeling is that a buffer if 32KB is enough for most of the application;
+ * in case this is not enough, the "while" loop discards the message by calling the
+ * sockrecv() several times.
+ * We do not want to create a bigger variable because this causes the program to exit on
+ * some platforms (e.g. BSD)
+ */
+ while (size > TEMP_BUF_SIZE)
+ {
+ if (sock_recv(sock, buffer, TEMP_BUF_SIZE, SOCK_RECEIVEALL_YES, errbuf, errbuflen) == -1)
+ return -1;
+
+ size -= TEMP_BUF_SIZE;
+ }
+
+ /*
+ * If there is still data to be discarded
+ * In this case, the data can fit into the temporary buffer
+ */
+ if (size)
+ {
+ if (sock_recv(sock, buffer, size, SOCK_RECEIVEALL_YES, errbuf, errbuflen) == -1)
+ return -1;
+ }
+
+ SOCK_ASSERT("I'm currently discarding data\n", 1);
+
+ return 0;
+}
+
+/*
+ * \brief Checks that one host (identified by the sockaddr_storage structure) belongs to an 'allowed list'.
+ *
+ * This function is useful after an accept() call in order to check if the connecting
+ * host is allowed to connect to me. To do that, we have a buffer that keeps the list of the
+ * allowed host; this function checks the sockaddr_storage structure of the connecting host
+ * against this host list, and it returns '0' is the host is included in this list.
+ *
+ * \param hostlist: pointer to a string that contains the list of the allowed host.
+ *
+ * \param sep: a string that keeps the separators used between the hosts (for example the
+ * space character) in the host list.
+ *
+ * \param from: a sockaddr_storage structure, as it is returned by the accept() call.
+ *
+ * \param errbuf: a pointer to an user-allocated buffer that will contain the complete
+ * error message. This buffer has to be at least 'errbuflen' in length.
+ * It can be NULL; in this case the error cannot be printed.
+ *
+ * \param errbuflen: length of the buffer that will contains the error. The error message cannot be
+ * larger than 'errbuflen - 1' because the last char is reserved for the string terminator.
+ *
+ * \return It returns:
+ * - '1' if the host list is empty
+ * - '0' if the host belongs to the host list (and therefore it is allowed to connect)
+ * - '-1' in case the host does not belong to the host list (and therefore it is not allowed to connect
+ * - '-2' in case or error. The error message is returned in the 'errbuf' variable.
+ */
+int sock_check_hostlist(char *hostlist, const char *sep, struct sockaddr_storage *from, char *errbuf, int errbuflen)
+{
+ /* checks if the connecting host is among the ones allowed */
+ if ((hostlist) && (hostlist[0]))
+ {
+ char *token; /* temp, needed to separate items into the hostlist */
+ struct addrinfo *addrinfo, *ai_next;
+ char *temphostlist;
+ char *lasts;
+
+ /*
+ * The problem is that strtok modifies the original variable by putting '0' at the end of each token
+ * So, we have to create a new temporary string in which the original content is kept
+ */
+ temphostlist = strdup(hostlist);
+ if (temphostlist == NULL)
+ {
+ sock_geterror("sock_check_hostlist(), malloc() failed", errbuf, errbuflen);
+ return -2;
+ }
+
+ token = pcap_strtok_r(temphostlist, sep, &lasts);
+
+ /* it avoids a warning in the compilation ('addrinfo used but not initialized') */
+ addrinfo = NULL;
+
+ while (token != NULL)
+ {
+ struct addrinfo hints;
+ int retval;
+
+ addrinfo = NULL;
+ memset(&hints, 0, sizeof(struct addrinfo));
+ hints.ai_family = PF_UNSPEC;
+ hints.ai_socktype = SOCK_STREAM;
+
+ retval = getaddrinfo(token, "0", &hints, &addrinfo);
+ if (retval != 0)
+ {
+ if (errbuf)
+ pcap_snprintf(errbuf, errbuflen, "getaddrinfo() %s", gai_strerror(retval));
+
+ SOCK_ASSERT(errbuf, 1);
+
+ /* Get next token */
+ token = pcap_strtok_r(NULL, sep, &lasts);
+ continue;
+ }
+
+ /* ai_next is required to preserve the content of addrinfo, in order to deallocate it properly */
+ ai_next = addrinfo;
+ while (ai_next)
+ {
+ if (sock_cmpaddr(from, (struct sockaddr_storage *) ai_next->ai_addr) == 0)
+ {
+ free(temphostlist);
+ return 0;
+ }
+
+ /*
+ * If we are here, it means that the current address does not matches
+ * Let's try with the next one in the header chain
+ */
+ ai_next = ai_next->ai_next;
+ }
+
+ freeaddrinfo(addrinfo);
+ addrinfo = NULL;
+
+ /* Get next token */
+ token = pcap_strtok_r(NULL, sep, &lasts);
+ }
+
+ if (addrinfo)
+ {
+ freeaddrinfo(addrinfo);
+ addrinfo = NULL;
+ }
+
+ if (errbuf)
+ pcap_snprintf(errbuf, errbuflen, "The host is not in the allowed host list. Connection refused.");
+
+ free(temphostlist);
+ return -1;
+ }
+
+ /* No hostlist, so we have to return 'empty list' */
+ return 1;
+}
+
+/*
+ * \brief Compares two addresses contained into two sockaddr_storage structures.
+ *
+ * This function is useful to compare two addresses, given their internal representation,
+ * i.e. an sockaddr_storage structure.
+ *
+ * The two structures do not need to be sockaddr_storage; you can have both 'sockaddr_in' and
+ * sockaddr_in6, properly acsted in order to be compliant to the function interface.
+ *
+ * This function will return '0' if the two addresses matches, '-1' if not.
+ *
+ * \param first: a sockaddr_storage structure, (for example the one that is returned by an
+ * accept() call), containing the first address to compare.
+ *
+ * \param second: a sockaddr_storage structure containing the second address to compare.
+ *
+ * \return '0' if the addresses are equal, '-1' if they are different.
+ */
+int sock_cmpaddr(struct sockaddr_storage *first, struct sockaddr_storage *second)
+{
+ if (first->ss_family == second->ss_family)
+ {
+ if (first->ss_family == AF_INET)
+ {
+ if (memcmp(&(((struct sockaddr_in *) first)->sin_addr),
+ &(((struct sockaddr_in *) second)->sin_addr),
+ sizeof(struct in_addr)) == 0)
+ return 0;
+ }
+ else /* address family is AF_INET6 */
+ {
+ if (memcmp(&(((struct sockaddr_in6 *) first)->sin6_addr),
+ &(((struct sockaddr_in6 *) second)->sin6_addr),
+ sizeof(struct in6_addr)) == 0)
+ return 0;
+ }
+ }
+
+ return -1;
+}
+
+/*
+ * \brief It gets the address/port the system picked for this socket (on connected sockets).
+ *
+ * It is used to return the address and port the server picked for our socket on the local machine.
+ * It works only on:
+ * - connected sockets
+ * - server sockets
+ *
+ * On unconnected client sockets it does not work because the system dynamically chooses a port
+ * only when the socket calls a send() call.
+ *
+ * \param sock: the connected socket currently opened.
+ *
+ * \param address: it contains the address that will be returned by the function. This buffer
+ * must be properly allocated by the user. The address can be either literal or numeric depending
+ * on the value of 'Flags'.
+ *
+ * \param addrlen: the length of the 'address' buffer.
+ *
+ * \param port: it contains the port that will be returned by the function. This buffer
+ * must be properly allocated by the user.
+ *
+ * \param portlen: the length of the 'port' buffer.
+ *
+ * \param flags: a set of flags (the ones defined into the getnameinfo() standard socket function)
+ * that determine if the resulting address must be in numeric / literal form, and so on.
+ *
+ * \param errbuf: a pointer to an user-allocated buffer that will contain the complete
+ * error message. This buffer has to be at least 'errbuflen' in length.
+ * It can be NULL; in this case the error cannot be printed.
+ *
+ * \param errbuflen: length of the buffer that will contains the error. The error message cannot be
+ * larger than 'errbuflen - 1' because the last char is reserved for the string terminator.
+ *
+ * \return It returns '-1' if this function succeeds, '0' otherwise.
+ * The address and port corresponding are returned back in the buffers 'address' and 'port'.
+ * In any case, the returned strings are '0' terminated.
+ *
+ * \warning If the socket is using a connectionless protocol, the address may not be available
+ * until I/O occurs on the socket.
+ */
+int sock_getmyinfo(SOCKET sock, char *address, int addrlen, char *port, int portlen, int flags, char *errbuf, int errbuflen)
+{
+ struct sockaddr_storage mysockaddr;
+ socklen_t sockaddrlen;
+
+
+ sockaddrlen = sizeof(struct sockaddr_storage);
+
+ if (getsockname(sock, (struct sockaddr *) &mysockaddr, &sockaddrlen) == -1)
+ {
+ sock_geterror("getsockname(): ", errbuf, errbuflen);
+ return 0;
+ }
+ else
+ {
+ /* Returns the numeric address of the host that triggered the error */
+ return sock_getascii_addrport(&mysockaddr, address, addrlen, port, portlen, flags, errbuf, errbuflen);
+ }
+
+ return 0;
+}
+
+/*
+ * \brief It retrieves two strings containing the address and the port of a given 'sockaddr' variable.
+ *
+ * This function is basically an extended version of the inet_ntop(), which does not exist in
+ * Winsock because the same result can be obtained by using the getnameinfo().
+ * However, differently from inet_ntop(), this function is able to return also literal names
+ * (e.g. 'localhost') dependently from the 'Flags' parameter.
+ *
+ * The function accepts a sockaddr_storage variable (which can be returned by several functions
+ * like bind(), connect(), accept(), and more) and it transforms its content into a 'human'
+ * form. So, for instance, it is able to translate an hex address (stored in binary form) into
+ * a standard IPv6 address like "::1".
+ *
+ * The behavior of this function depends on the parameters we have in the 'Flags' variable, which
+ * are the ones allowed in the standard getnameinfo() socket function.
+ *
+ * \param sockaddr: a 'sockaddr_in' or 'sockaddr_in6' structure containing the address that
+ * need to be translated from network form into the presentation form. This structure must be
+ * zero-ed prior using it, and the address family field must be filled with the proper value.
+ * The user must cast any 'sockaddr_in' or 'sockaddr_in6' structures to 'sockaddr_storage' before
+ * calling this function.
+ *
+ * \param address: it contains the address that will be returned by the function. This buffer
+ * must be properly allocated by the user. The address can be either literal or numeric depending
+ * on the value of 'Flags'.
+ *
+ * \param addrlen: the length of the 'address' buffer.
+ *
+ * \param port: it contains the port that will be returned by the function. This buffer
+ * must be properly allocated by the user.
+ *
+ * \param portlen: the length of the 'port' buffer.
+ *
+ * \param flags: a set of flags (the ones defined into the getnameinfo() standard socket function)
+ * that determine if the resulting address must be in numeric / literal form, and so on.
+ *
+ * \param errbuf: a pointer to an user-allocated buffer that will contain the complete
+ * error message. This buffer has to be at least 'errbuflen' in length.
+ * It can be NULL; in this case the error cannot be printed.
+ *
+ * \param errbuflen: length of the buffer that will contains the error. The error message cannot be
+ * larger than 'errbuflen - 1' because the last char is reserved for the string terminator.
+ *
+ * \return It returns '-1' if this function succeeds, '0' otherwise.
+ * The address and port corresponding to the given SockAddr are returned back in the buffers 'address'
+ * and 'port'.
+ * In any case, the returned strings are '0' terminated.
+ */
+int sock_getascii_addrport(const struct sockaddr_storage *sockaddr, char *address, int addrlen, char *port, int portlen, int flags, char *errbuf, int errbuflen)
+{
+ socklen_t sockaddrlen;
+ int retval; /* Variable that keeps the return value; */
+
+ retval = -1;
+
+#ifdef _WIN32
+ if (sockaddr->ss_family == AF_INET)
+ sockaddrlen = sizeof(struct sockaddr_in);
+ else
+ sockaddrlen = sizeof(struct sockaddr_in6);
+#else
+ sockaddrlen = sizeof(struct sockaddr_storage);
+#endif
+
+ if ((flags & NI_NUMERICHOST) == 0) /* Check that we want literal names */
+ {
+ if ((sockaddr->ss_family == AF_INET6) &&
+ (memcmp(&((struct sockaddr_in6 *) sockaddr)->sin6_addr, "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0", sizeof(struct in6_addr)) == 0))
+ {
+ if (address)
+ strlcpy(address, SOCKET_NAME_NULL_DAD, addrlen);
+ return retval;
+ }
+ }
+
+ if (getnameinfo((struct sockaddr *) sockaddr, sockaddrlen, address, addrlen, port, portlen, flags) != 0)
+ {
+ /* If the user wants to receive an error message */
+ if (errbuf)
+ {
+ sock_geterror("getnameinfo(): ", errbuf, errbuflen);
+ errbuf[errbuflen - 1] = 0;
+ }
+
+ if (address)
+ {
+ strlcpy(address, SOCKET_NO_NAME_AVAILABLE, addrlen);
+ address[addrlen - 1] = 0;
+ }
+
+ if (port)
+ {
+ strlcpy(port, SOCKET_NO_PORT_AVAILABLE, portlen);
+ port[portlen - 1] = 0;
+ }
+
+ retval = 0;
+ }
+
+ return retval;
+}
+
+/*
+ * \brief It translates an address from the 'presentation' form into the 'network' form.
+ *
+ * This function basically replaces inet_pton(), which does not exist in Winsock because
+ * the same result can be obtained by using the getaddrinfo().
+ * An additional advantage is that 'Address' can be both a numeric address (e.g. '127.0.0.1',
+ * like in inet_pton() ) and a literal name (e.g. 'localhost').
+ *
+ * This function does the reverse job of sock_getascii_addrport().
+ *
+ * \param address: a zero-terminated string which contains the name you have to
+ * translate. The name can be either literal (e.g. 'localhost') or numeric (e.g. '::1').
+ *
+ * \param sockaddr: a user-allocated sockaddr_storage structure which will contains the
+ * 'network' form of the requested address.
+ *
+ * \param addr_family: a constant which can assume the following values:
+ * - 'AF_INET' if we want to ping an IPv4 host
+ * - 'AF_INET6' if we want to ping an IPv6 host
+ * - 'AF_UNSPEC' if we do not have preferences about the protocol used to ping the host
+ *
+ * \param errbuf: a pointer to an user-allocated buffer that will contain the complete
+ * error message. This buffer has to be at least 'errbuflen' in length.
+ * It can be NULL; in this case the error cannot be printed.
+ *
+ * \param errbuflen: length of the buffer that will contains the error. The error message cannot be
+ * larger than 'errbuflen - 1' because the last char is reserved for the string terminator.
+ *
+ * \return '-1' if the translation succeeded, '-2' if there was some non critical error, '0'
+ * otherwise. In case it fails, the content of the SockAddr variable remains unchanged.
+ * A 'non critical error' can occur in case the 'Address' is a literal name, which can be mapped
+ * to several network addresses (e.g. 'foo.bar.com' => '10.2.2.2' and '10.2.2.3'). In this case
+ * the content of the SockAddr parameter will be the address corresponding to the first mapping.
+ *
+ * \warning The sockaddr_storage structure MUST be allocated by the user.
+ */
+int sock_present2network(const char *address, struct sockaddr_storage *sockaddr, int addr_family, char *errbuf, int errbuflen)
+{
+ int retval;
+ struct addrinfo *addrinfo;
+ struct addrinfo hints;
+
+ memset(&hints, 0, sizeof(hints));
+
+ hints.ai_family = addr_family;
+
+ if ((retval = sock_initaddress(address, "22222" /* fake port */, &hints, &addrinfo, errbuf, errbuflen)) == -1)
+ return 0;
+
+ if (addrinfo->ai_family == PF_INET)
+ memcpy(sockaddr, addrinfo->ai_addr, sizeof(struct sockaddr_in));
+ else
+ memcpy(sockaddr, addrinfo->ai_addr, sizeof(struct sockaddr_in6));
+
+ if (addrinfo->ai_next != NULL)
+ {
+ freeaddrinfo(addrinfo);
+
+ if (errbuf)
+ pcap_snprintf(errbuf, errbuflen, "More than one socket requested; using the first one returned");
+ return -2;
+ }
+
+ freeaddrinfo(addrinfo);
+ return -1;
+}
diff --git a/contrib/libpcap/sockutils.h b/contrib/libpcap/sockutils.h
new file mode 100644
index 000000000000..f50bbce881f6
--- /dev/null
+++ b/contrib/libpcap/sockutils.h
@@ -0,0 +1,241 @@
+/*
+ * Copyright (c) 2002 - 2003
+ * NetGroup, Politecnico di Torino (Italy)
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the Politecnico di Torino nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+#ifndef __SOCKUTILS_H__
+#define __SOCKUTILS_H__
+
+#if _MSC_VER > 1000
+#pragma once
+#endif
+
+#ifdef _WIN32
+ /* Windows */
+ /*
+ * Prevents a compiler warning in case this was already defined (to
+ * avoid that windows.h includes winsock.h)
+ */
+ #ifdef _WINSOCKAPI_
+ #undef _WINSOCKAPI_
+ #endif
+ /* Need windef.h for defines used in winsock2.h under MingW32 */
+ #ifdef __MINGW32__
+ #include <windef.h>
+ #endif
+ #include <winsock2.h>
+ #include <ws2tcpip.h>
+#else
+ /* UN*X */
+ #include <stdio.h>
+ #include <string.h> /* for memset() */
+ #include <sys/types.h>
+ #include <sys/socket.h>
+ #include <netdb.h> /* DNS lookup */
+ #include <unistd.h> /* close() */
+ #include <errno.h> /* errno() */
+ #include <netinet/in.h> /* for sockaddr_in, in BSD at least */
+ #include <arpa/inet.h>
+ #include <net/if.h>
+
+ /*!
+ * \brief In Winsock, a socket handle is of type SOCKET; in UN*X, it's
+ * a file descriptor, and therefore a signed integer.
+ * We define SOCKET to be a signed integer on UN*X, so that it can
+ * be used on both platforms.
+ */
+ #ifndef SOCKET
+ #define SOCKET int
+ #endif
+
+ /*!
+ * \brief In Winsock, the error return if socket() fails is INVALID_SOCKET;
+ * in UN*X, it's -1.
+ * We define INVALID_SOCKET to be -1 on UN*X, so that it can be used on
+ * both platforms.
+ */
+ #ifndef INVALID_SOCKET
+ #define INVALID_SOCKET -1
+ #endif
+#endif
+
+/*
+ * MingW headers include this definition, but only for Windows XP and above.
+ * MSDN states that this function is available for most versions on Windows.
+ */
+#if ((defined(__MINGW32__)) && (_WIN32_WINNT < 0x0501))
+int WSAAPI getnameinfo(const struct sockaddr*,socklen_t,char*,DWORD,
+ char*,DWORD,int);
+#endif
+
+/*
+ * \defgroup SockUtils Cross-platform socket utilities (IPv4-IPv6)
+ */
+
+/*
+ * \addtogroup SockUtils
+ * \{
+ */
+
+/*
+ * \defgroup ExportedStruct Exported Structures and Definitions
+ */
+
+/*
+ * \addtogroup ExportedStruct
+ * \{
+ */
+
+/*
+ * Some minor differences between UN*X sockets and and Winsock sockets.
+ */
+#ifdef _WIN32
+ /*
+ * Winsock doesn't have these UN*X types; they're used in the UN*X
+ * sockets API.
+ *
+ * XXX - do we need to worry about UN*Xes so old that *they* don't
+ * have them, either?
+ */
+ typedef int socklen_t;
+#else
+ /*!
+ * \brief In Winsock, the close() call cannot be used on a socket;
+ * closesocket() must be used.
+ * We define closesocket() to be a wrapper around close() on UN*X,
+ * so that it can be used on both platforms.
+ */
+ #define closesocket(a) close(a)
+#endif
+
+/*
+ * \brief DEBUG facility: it prints an error message on the screen (stderr)
+ *
+ * This macro prints the error on the standard error stream (stderr);
+ * if we are working in debug mode (i.e. there is no NDEBUG defined) and we are in
+ * Microsoft Visual C++, the error message will appear on the MSVC console as well.
+ *
+ * When NDEBUG is defined, this macro is empty.
+ *
+ * \param msg: the message you want to print.
+ *
+ * \param expr: 'false' if you want to abort the program, 'true' it you want
+ * to print the message and continue.
+ *
+ * \return No return values.
+ */
+#ifdef NDEBUG
+ #define SOCK_ASSERT(msg, expr) ((void)0)
+#else
+ #include <assert.h>
+ #if (defined(_WIN32) && defined(_MSC_VER))
+ #include <crtdbg.h> /* for _CrtDbgReport */
+ /* Use MessageBox(NULL, msg, "warning", MB_OK)' instead of the other calls if you want to debug a Win32 service */
+ /* Remember to activate the 'allow service to interact with desktop' flag of the service */
+ #define SOCK_ASSERT(msg, expr) { _CrtDbgReport(_CRT_WARN, NULL, 0, NULL, "%s\n", msg); fprintf(stderr, "%s\n", msg); assert(expr); }
+ #else
+ #define SOCK_ASSERT(msg, expr) { fprintf(stderr, "%s\n", msg); assert(expr); }
+ #endif
+#endif
+
+/****************************************************
+ * *
+ * Exported functions / definitions *
+ * *
+ ****************************************************/
+
+/* 'checkonly' flag, into the rpsock_bufferize() */
+#define SOCKBUF_CHECKONLY 1
+/* no 'checkonly' flag, into the rpsock_bufferize() */
+#define SOCKBUF_BUFFERIZE 0
+
+/* no 'server' flag; it opens a client socket */
+#define SOCKOPEN_CLIENT 0
+/* 'server' flag; it opens a server socket */
+#define SOCKOPEN_SERVER 1
+
+/* Changes the behaviour of the sock_recv(); it does not wait to receive all data */
+#define SOCK_RECEIVEALL_NO 0
+/* Changes the behaviour of the sock_recv(); it waits to receive all data */
+#define SOCK_RECEIVEALL_YES 1
+
+/*
+ * \}
+ */
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/*
+ * \defgroup ExportedFunc Exported Functions
+ */
+
+/*
+ * \addtogroup ExportedFunc
+ * \{
+ */
+
+int sock_init(char *errbuf, int errbuflen);
+void sock_cleanup(void);
+/* It is 'public' because there are calls (like accept() ) which are not managed from inside the sockutils files */
+void sock_geterror(const char *caller, char *errbuf, int errbufsize);
+int sock_initaddress(const char *address, const char *port,
+ struct addrinfo *hints, struct addrinfo **addrinfo,
+ char *errbuf, int errbuflen);
+int sock_recv(SOCKET socket, void *buffer, size_t size, int receiveall,
+ char *errbuf, int errbuflen);
+SOCKET sock_open(struct addrinfo *addrinfo, int server, int nconn, char *errbuf, int errbuflen);
+int sock_close(SOCKET sock, char *errbuf, int errbuflen);
+
+int sock_send(SOCKET socket, const char *buffer, int size, char *errbuf, int errbuflen);
+int sock_bufferize(const char *buffer, int size, char *tempbuf, int *offset, int totsize, int checkonly, char *errbuf, int errbuflen);
+int sock_discard(SOCKET socket, int size, char *errbuf, int errbuflen);
+int sock_check_hostlist(char *hostlist, const char *sep, struct sockaddr_storage *from, char *errbuf, int errbuflen);
+int sock_cmpaddr(struct sockaddr_storage *first, struct sockaddr_storage *second);
+
+int sock_getmyinfo(SOCKET sock, char *address, int addrlen, char *port, int portlen, int flags, char *errbuf, int errbuflen);
+
+int sock_getascii_addrport(const struct sockaddr_storage *sockaddr, char *address, int addrlen, char *port, int portlen, int flags, char *errbuf, int errbuflen);
+int sock_present2network(const char *address, struct sockaddr_storage *sockaddr, int addr_family, char *errbuf, int errbuflen);
+
+#ifdef __cplusplus
+}
+#endif
+
+/*
+ * \}
+ */
+
+/*
+ * \}
+ */
+
+#endif
diff --git a/contrib/libpcap/tests/can_set_rfmon_test.c b/contrib/libpcap/tests/can_set_rfmon_test.c
new file mode 100644
index 000000000000..f1644e66b768
--- /dev/null
+++ b/contrib/libpcap/tests/can_set_rfmon_test.c
@@ -0,0 +1,92 @@
+/*
+ * Copyright (c) 1988, 1989, 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1997, 2000
+ * The Regents of the University of California. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that: (1) source code distributions
+ * retain the above copyright notice and this paragraph in its entirety, (2)
+ * distributions including binary code include the above copyright notice and
+ * this paragraph in its entirety in the documentation or other materials
+ * provided with the distribution, and (3) all advertising materials mentioning
+ * features or use of this software display the following acknowledgement:
+ * ``This product includes software developed by the University of California,
+ * Lawrence Berkeley Laboratory and its contributors.'' Neither the name of
+ * the University nor the names of its contributors may be used to endorse
+ * or promote products derived from this software without specific prior
+ * written permission.
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+ */
+
+#ifndef lint
+static const char copyright[] _U_ =
+ "@(#) Copyright (c) 1988, 1989, 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1997, 2000\n\
+The Regents of the University of California. All rights reserved.\n";
+#endif
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <stdarg.h>
+
+#include <pcap.h>
+
+static const char *program_name;
+
+/* Forwards */
+static void error(const char *, ...);
+
+int
+main(int argc, char **argv)
+{
+ const char *cp;
+ pcap_t *pd;
+ char ebuf[PCAP_ERRBUF_SIZE];
+ int status;
+
+ if ((cp = strrchr(argv[0], '/')) != NULL)
+ program_name = cp + 1;
+ else
+ program_name = argv[0];
+
+ if (argc != 2) {
+ fprintf(stderr, "Usage: %s <device>\n", program_name);
+ return 2;
+ }
+
+ pd = pcap_create(argv[1], ebuf);
+ if (pd == NULL)
+ error("%s", ebuf);
+ status = pcap_can_set_rfmon(pd);
+ if (status < 0) {
+ if (status == PCAP_ERROR)
+ error("%s: pcap_can_set_rfmon failed: %s", argv[1],
+ pcap_geterr(pd));
+ else
+ error("%s: pcap_can_set_rfmon failed: %s", argv[1],
+ pcap_statustostr(status));
+ return 1;
+ }
+ printf("%s: Monitor mode %s be set\n", argv[1], status ? "can" : "cannot");
+ return 0;
+}
+
+/* VARARGS */
+static void
+error(const char *fmt, ...)
+{
+ va_list ap;
+
+ (void)fprintf(stderr, "%s: ", program_name);
+ va_start(ap, fmt);
+ (void)vfprintf(stderr, fmt, ap);
+ va_end(ap);
+ if (*fmt) {
+ fmt += strlen(fmt);
+ if (fmt[-1] != '\n')
+ (void)fputc('\n', stderr);
+ }
+ exit(1);
+ /* NOTREACHED */
+}
diff --git a/contrib/libpcap/tests/capturetest.c b/contrib/libpcap/tests/capturetest.c
index e70e69a514c1..14b1554b5189 100644
--- a/contrib/libpcap/tests/capturetest.c
+++ b/contrib/libpcap/tests/capturetest.c
@@ -20,7 +20,7 @@
*/
#ifndef lint
-static const char copyright[] =
+static const char copyright[] _U_ =
"@(#) Copyright (c) 1988, 1989, 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1997, 2000\n\
The Regents of the University of California. All rights reserved.\n";
#endif
@@ -30,29 +30,76 @@ The Regents of the University of California. All rights reserved.\n";
#include <string.h>
#include <stdarg.h>
#include <limits.h>
+#ifdef _WIN32
+#include "getopt.h"
+#else
#include <unistd.h>
+#endif
#include <errno.h>
#include <sys/types.h>
-#include <sys/select.h>
-#include <poll.h>
#include <pcap.h>
static char *program_name;
+/*
+ * This was introduced by Clang:
+ *
+ * http://clang.llvm.org/docs/LanguageExtensions.html#has-attribute
+ *
+ * in some version (which version?); it has been picked up by GCC 5.0.
+ */
+#ifndef __has_attribute
+ /*
+ * It's a macro, so you can check whether it's defined to check
+ * whether it's supported.
+ *
+ * If it's not, define it to always return 0, so that we move on to
+ * the fallback checks.
+ */
+ #define __has_attribute(x) 0
+#endif
+
+#if __has_attribute(noreturn) \
+ || (defined(__GNUC__) && ((__GNUC__ * 100 + __GNUC_MINOR__) >= 205)) \
+ || (defined(__SUNPRO_C) && (__SUNPRO_C >= 0x590)) \
+ || (defined(__xlC__) && __xlC__ >= 0x0A01) \
+ || (defined(__HP_aCC) && __HP_aCC >= 61000)
+ /*
+ * Compiler with support for it, or GCC 2.5 and later, or Solaris Studio 12
+ * (Sun C 5.9) and later, or IBM XL C 10.1 and later (do any earlier
+ * versions of XL C support this?), or HP aCC A.06.10 and later.
+ */
+ #define PCAP_NORETURN __attribute((noreturn))
+#elif defined( _MSC_VER )
+ #define PCAP_NORETURN __declspec(noreturn)
+#else
+ #define PCAP_NORETURN
+#endif
+
+#if __has_attribute(__format__) \
+ || (defined(__GNUC__) && ((__GNUC__ * 100 + __GNUC_MINOR__) >= 203)) \
+ || (defined(__xlC__) && __xlC__ >= 0x0A01) \
+ || (defined(__HP_aCC) && __HP_aCC >= 61000)
+ /*
+ * Compiler with support for it, or GCC 2.3 and later, or IBM XL C 10.1
+ * and later (do any earlier versions of XL C support this?),
+ * or HP aCC A.06.10 and later.
+ */
+ #define PCAP_PRINTFLIKE(x,y) __attribute__((__format__(__printf__,x,y)))
+#else
+ #define PCAP_PRINTFLIKE(x,y)
+#endif
+
/* Forwards */
static void countme(u_char *, const struct pcap_pkthdr *, const u_char *);
-static void usage(void) __attribute__((noreturn));
-static void error(const char *, ...);
-static void warning(const char *, ...);
+static void PCAP_NORETURN usage(void);
+static void PCAP_NORETURN error(const char *, ...) PCAP_PRINTFLIKE(1, 2);
+static void warning(const char *, ...) PCAP_PRINTFLIKE(1, 2);
static char *copy_argv(char **);
static pcap_t *pd;
-extern int optind;
-extern int opterr;
-extern char *optarg;
-
int
main(int argc, char **argv)
{
diff --git a/contrib/libpcap/tests/filtertest.c b/contrib/libpcap/tests/filtertest.c
index d603376da64e..d4440eb06b3d 100644
--- a/contrib/libpcap/tests/filtertest.c
+++ b/contrib/libpcap/tests/filtertest.c
@@ -34,29 +34,81 @@ The Regents of the University of California. All rights reserved.\n";
#include <stdlib.h>
#include <string.h>
#include <stdarg.h>
+#ifdef _WIN32
+#include "getopt.h"
+#else
#include <unistd.h>
+#endif
#include <fcntl.h>
#include <errno.h>
-#include <arpa/inet.h>
+#ifdef _WIN32
+ #include <winsock2.h>
+ typedef unsigned __int32 in_addr_t;
+#else
+ #include <arpa/inet.h>
+#endif
#include <sys/types.h>
#include <sys/stat.h>
-#ifndef HAVE___ATTRIBUTE__
-#define __attribute__(x)
+/*
+ * This was introduced by Clang:
+ *
+ * http://clang.llvm.org/docs/LanguageExtensions.html#has-attribute
+ *
+ * in some version (which version?); it has been picked up by GCC 5.0.
+ */
+#ifndef __has_attribute
+ /*
+ * It's a macro, so you can check whether it's defined to check
+ * whether it's supported.
+ *
+ * If it's not, define it to always return 0, so that we move on to
+ * the fallback checks.
+ */
+ #define __has_attribute(x) 0
+#endif
+
+#if __has_attribute(noreturn) \
+ || (defined(__GNUC__) && ((__GNUC__ * 100 + __GNUC_MINOR__) >= 205)) \
+ || (defined(__SUNPRO_C) && (__SUNPRO_C >= 0x590)) \
+ || (defined(__xlC__) && __xlC__ >= 0x0A01) \
+ || (defined(__HP_aCC) && __HP_aCC >= 61000)
+ /*
+ * Compiler with support for it, or GCC 2.5 and later, or Solaris Studio 12
+ * (Sun C 5.9) and later, or IBM XL C 10.1 and later (do any earlier
+ * versions of XL C support this?), or HP aCC A.06.10 and later.
+ */
+ #define PCAP_NORETURN __attribute((noreturn))
+#elif defined( _MSC_VER )
+ #define PCAP_NORETURN __declspec(noreturn)
+#else
+ #define PCAP_NORETURN
+#endif
+
+#if __has_attribute(__format__) \
+ || (defined(__GNUC__) && ((__GNUC__ * 100 + __GNUC_MINOR__) >= 203)) \
+ || (defined(__xlC__) && __xlC__ >= 0x0A01) \
+ || (defined(__HP_aCC) && __HP_aCC >= 61000)
+ /*
+ * Compiler with support for it, or GCC 2.3 and later, or IBM XL C 10.1
+ * and later (do any earlier versions of XL C support this?),
+ * or HP aCC A.06.10 and later.
+ */
+ #define PCAP_PRINTFLIKE(x,y) __attribute__((__format__(__printf__,x,y)))
+#else
+ #define PCAP_PRINTFLIKE(x,y)
#endif
static char *program_name;
/* Forwards */
-static void usage(void) __attribute__((noreturn));
-static void error(const char *, ...)
- __attribute__((noreturn, format (printf, 1, 2)));
-static void warn(const char *, ...)
- __attribute__((format (printf, 1, 2)));
+static void PCAP_NORETURN usage(void);
+static void PCAP_NORETURN error(const char *, ...) PCAP_PRINTFLIKE(1, 2);
+static void warn(const char *, ...) PCAP_PRINTFLIKE(1, 2);
-extern int optind;
-extern int opterr;
-extern char *optarg;
+#ifdef BDEBUG
+int dflag;
+#endif
/*
* On Windows, we need to open the file in binary mode, so that
@@ -178,25 +230,36 @@ main(int argc, char **argv)
{
char *cp;
int op;
+#ifndef BDEBUG
int dflag;
+#endif
char *infile;
int Oflag;
long snaplen;
+ char *p;
int dlt;
bpf_u_int32 netmask = PCAP_NETMASK_UNKNOWN;
char *cmdbuf;
pcap_t *pd;
struct bpf_program fcode;
-#ifdef WIN32
+#ifdef _WIN32
if(wsockinit() != 0) return 1;
-#endif /* WIN32 */
+#endif /* _WIN32 */
+#ifndef BDEBUG
dflag = 1;
+#else
+ /* if optimizer debugging is enabled, output DOT graph
+ * `dflag=4' is equivalent to -dddd to follow -d/-dd/-ddd
+ * convention in tcpdump command line
+ */
+ dflag = 4;
+#endif
infile = NULL;
Oflag = 1;
snaplen = 68;
-
+
if ((cp = strrchr(argv[0], '/')) != NULL)
program_name = cp + 1;
else
@@ -222,7 +285,7 @@ main(int argc, char **argv)
in_addr_t addr;
addr = inet_addr(optarg);
- if (addr == INADDR_NONE)
+ if (addr == (in_addr_t)(-1))
error("invalid netmask %s", optarg);
netmask = addr;
break;
@@ -252,9 +315,12 @@ main(int argc, char **argv)
}
dlt = pcap_datalink_name_to_val(argv[optind]);
- if (dlt < 0)
- error("invalid data link type %s", argv[optind]);
-
+ if (dlt < 0) {
+ dlt = (int)strtol(argv[optind], &p, 10);
+ if (p == argv[optind] || *p != '\0')
+ error("invalid data link type %s", argv[optind]);
+ }
+
if (infile)
cmdbuf = read_infile(infile);
else
@@ -266,8 +332,21 @@ main(int argc, char **argv)
if (pcap_compile(pd, &fcode, cmdbuf, Oflag, netmask) < 0)
error("%s", pcap_geterr(pd));
+
if (!bpf_validate(fcode.bf_insns, fcode.bf_len))
warn("Filter doesn't pass validation");
+
+#ifdef BDEBUG
+ // replace line feed with space
+ for (cp = cmdbuf; *cp != '\0'; ++cp) {
+ if (*cp == '\r' || *cp == '\n') {
+ *cp = ' ';
+ }
+ }
+ // only show machine code if BDEBUG defined, since dflag > 3
+ printf("machine codes for filter: %s\n", cmdbuf);
+#endif
+
bpf_dump(&fcode, dflag);
pcap_close(pd);
exit(0);
diff --git a/contrib/libpcap/tests/findalldevstest.c b/contrib/libpcap/tests/findalldevstest.c
index ec7c95015c9e..5925bf6a8176 100644
--- a/contrib/libpcap/tests/findalldevstest.c
+++ b/contrib/libpcap/tests/findalldevstest.c
@@ -4,14 +4,18 @@
#include <stdlib.h>
#include <sys/types.h>
-#include <sys/socket.h>
-#include <netinet/in.h>
-#include <arpa/inet.h>
-#include <netdb.h>
+#ifdef _WIN32
+ #include <winsock2.h>
+#else
+ #include <sys/socket.h>
+ #include <netinet/in.h>
+ #include <arpa/inet.h>
+ #include <netdb.h>
+#endif
#include <pcap.h>
-static void ifprint(pcap_if_t *d);
+static int ifprint(pcap_if_t *d);
static char *iptos(bpf_u_int32 in);
int main(int argc, char **argv)
@@ -20,7 +24,8 @@ int main(int argc, char **argv)
pcap_if_t *d;
char *s;
bpf_u_int32 net, mask;
-
+ int exit_status = 0;
+
char errbuf[PCAP_ERRBUF_SIZE+1];
if (pcap_findalldevs(&alldevs, errbuf) == -1)
{
@@ -29,12 +34,14 @@ int main(int argc, char **argv)
}
for(d=alldevs;d;d=d->next)
{
- ifprint(d);
+ if (!ifprint(d))
+ exit_status = 2;
}
if ( (s = pcap_lookupdev(errbuf)) == NULL)
{
fprintf(stderr,"Error in pcap_lookupdev: %s\n",errbuf);
+ exit_status = 2;
}
else
{
@@ -44,30 +51,47 @@ int main(int argc, char **argv)
if (pcap_lookupnet(s, &net, &mask, errbuf) < 0)
{
fprintf(stderr,"Error in pcap_lookupnet: %s\n",errbuf);
+ exit_status = 2;
}
else
{
printf("Preferred device is on network: %s/%s\n",iptos(net), iptos(mask));
}
-
- exit(0);
+
+ exit(exit_status);
}
-static void ifprint(pcap_if_t *d)
+static int ifprint(pcap_if_t *d)
{
pcap_addr_t *a;
#ifdef INET6
char ntop_buf[INET6_ADDRSTRLEN];
#endif
+ const char *sep;
+ int status = 1; /* success */
printf("%s\n",d->name);
if (d->description)
printf("\tDescription: %s\n",d->description);
- printf("\tLoopback: %s\n",(d->flags & PCAP_IF_LOOPBACK)?"yes":"no");
+ printf("\tFlags: ");
+ sep = "";
+ if (d->flags & PCAP_IF_UP) {
+ printf("%sUP", sep);
+ sep = ", ";
+ }
+ if (d->flags & PCAP_IF_RUNNING) {
+ printf("%sRUNNING", sep);
+ sep = ", ";
+ }
+ if (d->flags & PCAP_IF_LOOPBACK) {
+ printf("%sLOOPBACK", sep);
+ sep = ", ";
+ }
+ printf("\n");
for(a=d->addresses;a;a=a->next) {
- switch(a->addr->sa_family)
- {
+ if (a->addr != NULL)
+ switch(a->addr->sa_family) {
case AF_INET:
printf("\tAddress Family: AF_INET\n");
if (a->addr)
@@ -111,9 +135,15 @@ static void ifprint(pcap_if_t *d)
default:
printf("\tAddress Family: Unknown (%d)\n", a->addr->sa_family);
break;
+ }
+ else
+ {
+ fprintf(stderr, "\tWarning: a->addr is NULL, skipping this address.\n");
+ status = 0;
}
}
printf("\n");
+ return status;
}
/* From tcptraceroute */
diff --git a/contrib/libpcap/tests/opentest.c b/contrib/libpcap/tests/opentest.c
index 0c91531018db..b6d634f0d901 100644
--- a/contrib/libpcap/tests/opentest.c
+++ b/contrib/libpcap/tests/opentest.c
@@ -20,7 +20,7 @@
*/
#ifndef lint
-static const char copyright[] =
+static const char copyright[] _U_ =
"@(#) Copyright (c) 1988, 1989, 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1997, 2000\n\
The Regents of the University of California. All rights reserved.\n";
#endif
@@ -30,21 +30,70 @@ The Regents of the University of California. All rights reserved.\n";
#include <stdlib.h>
#include <string.h>
#include <stdarg.h>
+#ifdef _WIN32
+#include "getopt.h"
+#else
#include <unistd.h>
+#endif
#include <errno.h>
#define MAXIMUM_SNAPLEN 65535
static char *program_name;
-/* Forwards */
-static void usage(void) __attribute__((noreturn));
-static void error(const char *, ...);
-static void warning(const char *, ...);
+/*
+ * This was introduced by Clang:
+ *
+ * http://clang.llvm.org/docs/LanguageExtensions.html#has-attribute
+ *
+ * in some version (which version?); it has been picked up by GCC 5.0.
+ */
+#ifndef __has_attribute
+ /*
+ * It's a macro, so you can check whether it's defined to check
+ * whether it's supported.
+ *
+ * If it's not, define it to always return 0, so that we move on to
+ * the fallback checks.
+ */
+ #define __has_attribute(x) 0
+#endif
-extern int optind;
-extern int opterr;
-extern char *optarg;
+#if __has_attribute(noreturn) \
+ || (defined(__GNUC__) && ((__GNUC__ * 100 + __GNUC_MINOR__) >= 205)) \
+ || (defined(__SUNPRO_C) && (__SUNPRO_C >= 0x590)) \
+ || (defined(__xlC__) && __xlC__ >= 0x0A01) \
+ || (defined(__HP_aCC) && __HP_aCC >= 61000)
+ /*
+ * Compiler with support for it, or GCC 2.5 and later, or Solaris Studio 12
+ * (Sun C 5.9) and later, or IBM XL C 10.1 and later (do any earlier
+ * versions of XL C support this?), or HP aCC A.06.10 and later.
+ */
+ #define PCAP_NORETURN __attribute((noreturn))
+#elif defined( _MSC_VER )
+ #define PCAP_NORETURN __declspec(noreturn)
+#else
+ #define PCAP_NORETURN
+#endif
+
+#if __has_attribute(__format__) \
+ || (defined(__GNUC__) && ((__GNUC__ * 100 + __GNUC_MINOR__) >= 203)) \
+ || (defined(__xlC__) && __xlC__ >= 0x0A01) \
+ || (defined(__HP_aCC) && __HP_aCC >= 61000)
+ /*
+ * Compiler with support for it, or GCC 2.3 and later, or IBM XL C 10.1
+ * and later (do any earlier versions of XL C support this?),
+ * or HP aCC A.06.10 and later.
+ */
+ #define PCAP_PRINTFLIKE(x,y) __attribute__((__format__(__printf__,x,y)))
+#else
+ #define PCAP_PRINTFLIKE(x,y)
+#endif
+
+/* Forwards */
+static void PCAP_NORETURN usage(void);
+static void PCAP_NORETURN error(const char *, ...) PCAP_PRINTFLIKE(1, 2);
+static void warning(const char *, ...) PCAP_PRINTFLIKE(1, 2);
int
main(int argc, char **argv)
@@ -113,10 +162,15 @@ main(int argc, char **argv)
}
}
+ if (device == NULL) {
+ device = pcap_lookupdev(ebuf);
+ if (device == NULL)
+ error("pcap_lookupdev failed: %s", ebuf);
+ }
if (useactivate) {
pd = pcap_create(device, ebuf);
if (pd == NULL)
- error("%s", ebuf);
+ error("%s: pcap_create failed: %s", device, ebuf);
status = pcap_set_snaplen(pd, snaplen);
if (status != 0)
error("%s: pcap_set_snaplen failed: %s",
@@ -157,7 +211,8 @@ main(int argc, char **argv)
*/
warning("%s: %s\n(%s)", device,
pcap_statustostr(status), pcap_geterr(pd));
- }
+ } else
+ printf("%s opened successfully\n", device);
} else {
*ebuf = '\0';
pd = pcap_open_live(device, 65535, 0, 1000, ebuf);
@@ -165,6 +220,8 @@ main(int argc, char **argv)
error("%s", ebuf);
else if (*ebuf)
warning("%s", ebuf);
+ else
+ printf("%s opened successfully\n", device);
}
pcap_close(pd);
exit(status < 0 ? 1 : 0);
diff --git a/contrib/libpcap/tests/reactivatetest.c b/contrib/libpcap/tests/reactivatetest.c
index 9031a64a619e..2e1b7b67adb7 100644
--- a/contrib/libpcap/tests/reactivatetest.c
+++ b/contrib/libpcap/tests/reactivatetest.c
@@ -20,7 +20,7 @@
*/
#ifndef lint
-static const char copyright[] =
+static const char copyright[] _U_ =
"@(#) Copyright (c) 1988, 1989, 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1997, 2000\n\
The Regents of the University of California. All rights reserved.\n";
#endif
diff --git a/contrib/libpcap/tests/selpolltest.c b/contrib/libpcap/tests/selpolltest.c
index d94fb567fb20..4c1415b68354 100644
--- a/contrib/libpcap/tests/selpolltest.c
+++ b/contrib/libpcap/tests/selpolltest.c
@@ -20,11 +20,19 @@
*/
#ifndef lint
-static const char copyright[] =
+static const char copyright[] _U_ =
"@(#) Copyright (c) 1988, 1989, 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1997, 2000\n\
The Regents of the University of California. All rights reserved.\n";
#endif
+/*
+ * Tests how select() and poll() behave on the selectable file descriptor
+ * for a pcap_t.
+ *
+ * This would be significantly different on Windows, as it'd test
+ * how WaitForMultipleObjects() would work on the event handle for a
+ * pcap_t.
+ */
#include <pcap.h>
#include <stdio.h>
#include <stdlib.h>
@@ -33,24 +41,73 @@ The Regents of the University of California. All rights reserved.\n";
#include <unistd.h>
#include <errno.h>
#include <sys/types.h>
+#ifdef HAVE_SYS_SELECT_H
#include <sys/select.h>
+#else
+#include <sys/time.h> /* older UN*Xes */
+#endif
#include <poll.h>
char *program_name;
+/*
+ * This was introduced by Clang:
+ *
+ * http://clang.llvm.org/docs/LanguageExtensions.html#has-attribute
+ *
+ * in some version (which version?); it has been picked up by GCC 5.0.
+ */
+#ifndef __has_attribute
+ /*
+ * It's a macro, so you can check whether it's defined to check
+ * whether it's supported.
+ *
+ * If it's not, define it to always return 0, so that we move on to
+ * the fallback checks.
+ */
+ #define __has_attribute(x) 0
+#endif
+
+#if __has_attribute(noreturn) \
+ || (defined(__GNUC__) && ((__GNUC__ * 100 + __GNUC_MINOR__) >= 205)) \
+ || (defined(__SUNPRO_C) && (__SUNPRO_C >= 0x590)) \
+ || (defined(__xlC__) && __xlC__ >= 0x0A01) \
+ || (defined(__HP_aCC) && __HP_aCC >= 61000)
+ /*
+ * Compiler with support for it, or GCC 2.5 and later, or Solaris Studio 12
+ * (Sun C 5.9) and later, or IBM XL C 10.1 and later (do any earlier
+ * versions of XL C support this?), or HP aCC A.06.10 and later.
+ */
+ #define PCAP_NORETURN __attribute((noreturn))
+#elif defined( _MSC_VER )
+ #define PCAP_NORETURN __declspec(noreturn)
+#else
+ #define PCAP_NORETURN
+#endif
+
+#if __has_attribute(__format__) \
+ || (defined(__GNUC__) && ((__GNUC__ * 100 + __GNUC_MINOR__) >= 203)) \
+ || (defined(__xlC__) && __xlC__ >= 0x0A01) \
+ || (defined(__HP_aCC) && __HP_aCC >= 61000)
+ /*
+ * Compiler with support for it, or GCC 2.3 and later, or IBM XL C 10.1
+ * and later (do any earlier versions of XL C support this?),
+ * or HP aCC A.06.10 and later.
+ */
+ #define PCAP_PRINTFLIKE(x,y) __attribute__((__format__(__printf__,x,y)))
+#else
+ #define PCAP_PRINTFLIKE(x,y)
+#endif
+
/* Forwards */
static void countme(u_char *, const struct pcap_pkthdr *, const u_char *);
-static void usage(void) __attribute__((noreturn));
-static void error(const char *, ...);
-static void warning(const char *, ...);
+static void PCAP_NORETURN usage(void);
+static void PCAP_NORETURN error(const char *, ...) PCAP_PRINTFLIKE(1, 2);
+static void warning(const char *, ...) PCAP_PRINTFLIKE(1, 2);
static char *copy_argv(char **);
static pcap_t *pd;
-extern int optind;
-extern int opterr;
-extern char *optarg;
-
int
main(int argc, char **argv)
{
diff --git a/contrib/libpcap/tests/valgrindtest.c b/contrib/libpcap/tests/valgrindtest.c
index 1d883776b04e..011fe117b2cd 100644
--- a/contrib/libpcap/tests/valgrindtest.c
+++ b/contrib/libpcap/tests/valgrindtest.c
@@ -19,6 +19,30 @@
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
*/
+/*
+ * This doesn't actually test libpcap itself; it tests whether
+ * valgrind properly handles the APIs libpcap uses. If it doesn't,
+ * we end up getting patches submitted to "fix" references that
+ * valgrind claims are being made to uninitialized data, when, in
+ * fact, the OS isn't making any such references - or we get
+ * valgrind *not* detecting *actual* incorrect references.
+ *
+ * Both BPF and Linux socket filters aren't handled correctly
+ * by some versions of valgrind. See valgrind bug 318203 for
+ * Linux:
+ *
+ * https://bugs.kde.org/show_bug.cgi?id=318203
+ *
+ * and valgrind bug 312989 for OS X:
+ *
+ * https://bugs.kde.org/show_bug.cgi?id=312989
+ *
+ * The fixes for both of those are checked into the official valgrind
+ * repository.
+ *
+ * The unofficial FreeBSD port has similar issues to the official OS X
+ * port, for similar reasons.
+ */
#ifndef lint
static const char copyright[] _U_ =
"@(#) Copyright (c) 1988, 1989, 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1997, 2000\n\
@@ -72,22 +96,62 @@ The Regents of the University of California. All rights reserved.\n";
#endif
#include <pcap.h>
-#ifndef HAVE___ATTRIBUTE__
-#define __attribute__(x)
-#endif
static char *program_name;
-/* Forwards */
-static void usage(void) __attribute__((noreturn));
-static void error(const char *, ...)
- __attribute__((noreturn, format (printf, 1, 2)));
-static void warning(const char *, ...)
- __attribute__((format (printf, 1, 2)));
+/*
+ * This was introduced by Clang:
+ *
+ * http://clang.llvm.org/docs/LanguageExtensions.html#has-attribute
+ *
+ * in some version (which version?); it has been picked up by GCC 5.0.
+ */
+#ifndef __has_attribute
+ /*
+ * It's a macro, so you can check whether it's defined to check
+ * whether it's supported.
+ *
+ * If it's not, define it to always return 0, so that we move on to
+ * the fallback checks.
+ */
+ #define __has_attribute(x) 0
+#endif
-extern int optind;
-extern int opterr;
-extern char *optarg;
+#if __has_attribute(noreturn) \
+ || (defined(__GNUC__) && ((__GNUC__ * 100 + __GNUC_MINOR__) >= 205)) \
+ || (defined(__SUNPRO_C) && (__SUNPRO_C >= 0x590)) \
+ || (defined(__xlC__) && __xlC__ >= 0x0A01) \
+ || (defined(__HP_aCC) && __HP_aCC >= 61000)
+ /*
+ * Compiler with support for it, or GCC 2.5 and later, or Solaris Studio 12
+ * (Sun C 5.9) and later, or IBM XL C 10.1 and later (do any earlier
+ * versions of XL C support this?), or HP aCC A.06.10 and later.
+ */
+ #define PCAP_NORETURN __attribute((noreturn))
+#elif defined( _MSC_VER )
+ #define PCAP_NORETURN __declspec(noreturn)
+#else
+ #define PCAP_NORETURN
+#endif
+
+#if __has_attribute(__format__) \
+ || (defined(__GNUC__) && ((__GNUC__ * 100 + __GNUC_MINOR__) >= 203)) \
+ || (defined(__xlC__) && __xlC__ >= 0x0A01) \
+ || (defined(__HP_aCC) && __HP_aCC >= 61000)
+ /*
+ * Compiler with support for it, or GCC 2.3 and later, or IBM XL C 10.1
+ * and later (do any earlier versions of XL C support this?),
+ * or HP aCC A.06.10 and later.
+ */
+ #define PCAP_PRINTFLIKE(x,y) __attribute__((__format__(__printf__,x,y)))
+#else
+ #define PCAP_PRINTFLIKE(x,y)
+#endif
+
+/* Forwards */
+static void PCAP_NORETURN usage(void);
+static void PCAP_NORETURN error(const char *, ...) PCAP_PRINTFLIKE(1, 2);
+static void warning(const char *, ...) PCAP_PRINTFLIKE(1, 2);
/*
* On Windows, we need to open the file in binary mode, so that
@@ -231,7 +295,7 @@ main(int argc, char **argv)
dorfmon = 0;
useactivate = 0;
infile = NULL;
-
+
if ((cp = strrchr(argv[0], '/')) != NULL)
program_name = cp + 1;
else
diff --git a/lib/libpcap/Makefile b/lib/libpcap/Makefile
index 9b7ffe96e13e..b83c5f1e4beb 100644
--- a/lib/libpcap/Makefile
+++ b/lib/libpcap/Makefile
@@ -7,8 +7,8 @@ SHLIBDIR?= /lib
PACKAGE=lib${LIB}
LIB= pcap
-SRCS= grammar.y tokdefs.h version.h pcap-bpf.c \
- pcap-netmap.c \
+SRCS= grammar.y tokdefs.h pcap_version.h pcap-bpf.c \
+ pcap-netmap.c fad-helpers.c \
pcap.c pcap-common.c inet.c fad-getad.c gencode.c optimize.c nametoaddr.c \
etherent.c savefile.c bpf_filter.c bpf_image.c bpf_dump.c \
scanner.l sf-pcap.c sf-pcap-ng.c version.c
@@ -16,7 +16,7 @@ SRCS= grammar.y tokdefs.h version.h pcap-bpf.c \
# Old compatibility headers
INCS= pcap.h pcap-int.h pcap-namedb.h pcap-bpf.h
-PCAPINCS= pcap/pcap.h pcap/namedb.h pcap/bpf.h
+PCAPINCS= pcap/pcap.h pcap/namedb.h pcap/bpf.h pcap/dlt.h pcap/export-defs.h
PCAPINCSDIR= ${INCLUDEDIR}/pcap
INCSGROUPS= INCS PCAPINCS
@@ -93,13 +93,14 @@ MLINKS= pcap_datalink_val_to_name.3 pcap_datalink_val_to_description.3 \
# Our man pages are a special copy from the distdir. See below.
CLEANFILES+=${MAN}
-CLEANFILES+=tokdefs.h version.h version.c
+CLEANFILES+=tokdefs.h scanner.h pcap_version.h version.c
-YFLAGS+=-p pcapyy
-LFLAGS+=-Ppcapyy
-CFLAGS+=-DHAVE_CONFIG_H -Dyylval=pcapyylval -I${.CURDIR} -I.
+YFLAGS+=-p pcap_
+LFLAGS+=-Ppcap_ --header-file=${.OBJDIR}/scanner.h --nounput
+CFLAGS+=-DHAVE_CONFIG_H -I${.CURDIR} -I${.OBJDIR}
CFLAGS+=-D_U_="__attribute__((unused))"
CFLAGS+=-DHAVE_SNPRINTF -DHAVE_VSNPRINTF
+CFLAGS+=-DBUILDING_PCAP
.if ${MK_INET6_SUPPORT} != "no"
CFLAGS+=-DINET6
.endif
@@ -123,7 +124,7 @@ version.c: ${PCAP_DISTDIR}/VERSION
@rm -f $@
sed 's/.*/char pcap_version[] = "&";/' ${PCAP_DISTDIR}/VERSION > $@
-version.h: ${PCAP_DISTDIR}/VERSION
+pcap_version.h: ${PCAP_DISTDIR}/VERSION
@rm -f $@
sed 's/.*/char pcap_version_string[] = "libpcap version &";/' ${PCAP_DISTDIR}/VERSION > $@
diff --git a/lib/libpcap/config.h b/lib/libpcap/config.h
index 4033b278ac70..de0ad67d0b64 100644
--- a/lib/libpcap/config.h
+++ b/lib/libpcap/config.h
@@ -2,7 +2,7 @@
/* This is an edited copy of the config.h generated by configure. */
/* config.h. Generated from config.h.in by configure. */
-/* config.h.in. Generated from configure.in by autoheader. */
+/* config.h.in. Generated from configure.ac by autoheader. */
/* Enable optimizer debugging */
/* #undef BDEBUG */
@@ -80,12 +80,18 @@
/* Define to 1 if you have the <linux/ethtool.h> header file. */
/* #undef HAVE_LINUX_ETHTOOL_H */
+/* Define to 1 if you have the <linux/if_bonding.h> header file. */
+/* #undef HAVE_LINUX_IF_BONDING_H */
+
/* Define to 1 if you have the <linux/if_packet.h> header file. */
/* #undef HAVE_LINUX_IF_PACKET_H */
/* Define to 1 if you have the <linux/net_tstamp.h> header file. */
/* #undef HAVE_LINUX_NET_TSTAMP_H */
+/* Define to 1 if you have the <linux/sockios.h> header file. */
+/* #undef HAVE_LINUX_SOCKIOS_H */
+
/* if tp_vlan_tci exists */
/* #undef HAVE_LINUX_TPACKET_AUXDATA_TP_VLAN_TCI */
@@ -123,16 +129,13 @@
/* if there's an os_proto.h for this platform, to use additional prototypes */
/* #undef HAVE_OS_PROTO_H */
-/* Define to 1 if you have the <paths.h> header file. */
-#define HAVE_PATHS_H 1
-
/* define if net/pfvar.h defines PF_NAT through PF_NORDR */
#define HAVE_PF_NAT_THROUGH_PF_NORDR 1
-/* define if you have a Septel API */
+/* define if you have the Septel API */
/* #undef HAVE_SEPTEL_API */
-/* define if you have Myricom SNF API */
+/* define if you have the Myricom SNF API */
/* #undef HAVE_SNF_API */
/* Define to 1 if you have the `snprintf' function. */
@@ -168,6 +171,9 @@
/* Define to 1 if you have the `strlcpy' function. */
#define HAVE_STRLCPY 1
+/* Define to 1 if you have the `strtok_r' function. */
+#define HAVE_STRTOK_R 1
+
/* Define to 1 if the system has the type `struct BPF_TIMEVAL'. */
/* #undef HAVE_STRUCT_BPF_TIMEVAL */
@@ -186,6 +192,9 @@
/* Define to 1 if you have the <sys/ioccom.h> header file. */
#define HAVE_SYS_IOCCOM_H 1
+/* Define to 1 if you have the <sys/select.h> header file. */
+#define HAVE_SYS_SELECT_H 1
+
/* Define to 1 if you have the <sys/sockio.h> header file. */
#define HAVE_SYS_SOCKIO_H 1
@@ -195,6 +204,9 @@
/* Define to 1 if you have the <sys/types.h> header file. */
#define HAVE_SYS_TYPES_H 1
+/* define if you have the TurboCap API */
+/* #undef HAVE_TC_API */
+
/* if if_packet.h has tpacket_stats defined */
/* #undef HAVE_TPACKET_STATS */
@@ -204,9 +216,6 @@
/* if struct usbdevfs_ctrltransfer has bRequestType */
/* #undef HAVE_USBDEVFS_CTRLTRANSFER_BREQUESTTYPE */
-/* define if version.h is generated in the build procedure */
-#define HAVE_VERSION_H 1
-
/* Define to 1 if you have the `vsnprintf' function. */
#define HAVE_VSNPRINTF 1
@@ -226,9 +235,6 @@
/* path for device for USB sniffing */
/* #undef LINUX_USB_MON_DEV */
-/* if we need a pcap_parse wrapper around yyparse */
-#define NEED_YYPARSE_WRAPPER 1
-
/* Define to 1 if netinet/ether.h declares `ether_hostton' */
/* #undef NETINET_ETHER_H_DECLARES_ETHER_HOSTTON */
@@ -265,18 +271,15 @@
/* target host supports Bluetooth Monitor */
/* #undef PCAP_SUPPORT_BT_MONITOR */
-/* target host supports CAN sniffing */
-/* #undef PCAP_SUPPORT_CAN */
-
-/* target host supports canusb */
-/* #undef PCAP_SUPPORT_CANUSB */
-
/* support D-Bus sniffing */
/* #undef PCAP_SUPPORT_DBUS */
/* target host supports netfilter sniffing */
/* #undef PCAP_SUPPORT_NETFILTER */
+/* use Linux packet ring capture if available */
+#define PCAP_SUPPORT_PACKET_RING 1
+
/* target host supports USB sniffing */
/* #undef PCAP_SUPPORT_USB */
@@ -295,6 +298,10 @@
/* Enable parser debugging */
/* #undef YYDEBUG */
+/* Define to 1 if `lex' declares `yytext' as a `char *' by default, not a
+ `char[]'. */
+#define YYTEXT_POINTER 1
+
/* Enable large inode numbers on Mac OS X 10.5. */
#ifndef _DARWIN_USE_64_BIT_INODE
# define _DARWIN_USE_64_BIT_INODE 1
diff --git a/lib/libpcap/pcap-netmap.c b/lib/libpcap/pcap-netmap.c
index 19af71eed8ad..31f23569df89 100644
--- a/lib/libpcap/pcap-netmap.c
+++ b/lib/libpcap/pcap-netmap.c
@@ -209,13 +209,13 @@ static int
pcap_netmap_activate(pcap_t *p)
{
struct pcap_netmap *pn = NM_PRIV(p);
- struct nm_desc *d = nm_open(p->opt.source, NULL, 0, NULL);
+ struct nm_desc *d = nm_open(p->opt.device, NULL, 0, NULL);
uint32_t if_flags = 0;
if (d == NULL) {
snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
"netmap open: cannot access %s: %s\n",
- p->opt.source, pcap_strerror(errno));
+ p->opt.device, pcap_strerror(errno));
#ifdef HAVE_NO_PRIV
free(pn);
SET_PRIV(p, NULL); // unnecessary
@@ -225,7 +225,7 @@ pcap_netmap_activate(pcap_t *p)
}
if (0)
fprintf(stderr, "%s device %s priv %p fd %d ports %d..%d\n",
- __FUNCTION__, p->opt.source, d, d->fd,
+ __FUNCTION__, p->opt.device, d, d->fd,
d->first_rx_ring, d->last_rx_ring);
pn->d = d;
p->fd = d->fd;
@@ -274,7 +274,7 @@ pcap_netmap_create(const char *device, char *ebuf, int *is_ours)
SET_PRIV(p, pn);
}
#else
- p = pcap_create_common(device, ebuf, sizeof (struct pcap_netmap));
+ p = pcap_create_common(ebuf, sizeof (struct pcap_netmap));
if (p == NULL)
return (NULL);
#endif
diff --git a/sbin/pflogd/Makefile b/sbin/pflogd/Makefile
index bb74500dcf53..774ab14db6e2 100644
--- a/sbin/pflogd/Makefile
+++ b/sbin/pflogd/Makefile
@@ -8,6 +8,7 @@ SRCS= pflogd.c pidfile.c privsep.c privsep_fdpass.c
MAN= pflogd.8
CFLAGS+=-include ${.CURDIR}/../../lib/libpcap/config.h
+CFLAGS+=-I${.CURDIR}/../../contrib/libpcap
LIBADD= pcap
diff --git a/sys/net/bpf.h b/sys/net/bpf.h
index 058f3c048c33..679f896d9538 100644
--- a/sys/net/bpf.h
+++ b/sys/net/bpf.h
@@ -231,1056 +231,8 @@ struct bpf_zbuf_header {
u_int _bzh_pad[5];
};
-/*
- * Data-link level type codes.
- */
-#define DLT_NULL 0 /* BSD loopback encapsulation */
-#define DLT_EN10MB 1 /* Ethernet (10Mb) */
-#define DLT_EN3MB 2 /* Experimental Ethernet (3Mb) */
-#define DLT_AX25 3 /* Amateur Radio AX.25 */
-#define DLT_PRONET 4 /* Proteon ProNET Token Ring */
-#define DLT_CHAOS 5 /* Chaos */
-#define DLT_IEEE802 6 /* IEEE 802 Networks */
-#define DLT_ARCNET 7 /* ARCNET */
-#define DLT_SLIP 8 /* Serial Line IP */
-#define DLT_PPP 9 /* Point-to-point Protocol */
-#define DLT_FDDI 10 /* FDDI */
-#define DLT_ATM_RFC1483 11 /* LLC/SNAP encapsulated atm */
-#define DLT_RAW 12 /* raw IP */
-
-/*
- * These are values from BSD/OS's "bpf.h".
- * These are not the same as the values from the traditional libpcap
- * "bpf.h"; however, these values shouldn't be generated by any
- * OS other than BSD/OS, so the correct values to use here are the
- * BSD/OS values.
- *
- * Platforms that have already assigned these values to other
- * DLT_ codes, however, should give these codes the values
- * from that platform, so that programs that use these codes will
- * continue to compile - even though they won't correctly read
- * files of these types.
- */
-#define DLT_SLIP_BSDOS 15 /* BSD/OS Serial Line IP */
-#define DLT_PPP_BSDOS 16 /* BSD/OS Point-to-point Protocol */
-
-#define DLT_ATM_CLIP 19 /* Linux Classical-IP over ATM */
-
-/*
- * These values are defined by NetBSD; other platforms should refrain from
- * using them for other purposes, so that NetBSD savefiles with link
- * types of 50 or 51 can be read as this type on all platforms.
- */
-#define DLT_PPP_SERIAL 50 /* PPP over serial with HDLC encapsulation */
-#define DLT_PPP_ETHER 51 /* PPP over Ethernet */
-
-/*
- * Reserved for the Symantec Enterprise Firewall.
- */
-#define DLT_SYMANTEC_FIREWALL 99
-
-/*
- * Values between 100 and 103 are used in capture file headers as
- * link-layer header type LINKTYPE_ values corresponding to DLT_ types
- * that differ between platforms; don't use those values for new DLT_
- * new types.
- */
-
-/*
- * Values starting with 104 are used for newly-assigned link-layer
- * header type values; for those link-layer header types, the DLT_
- * value returned by pcap_datalink() and passed to pcap_open_dead(),
- * and the LINKTYPE_ value that appears in capture files, are the
- * same.
- *
- * DLT_MATCHING_MIN is the lowest such value; DLT_MATCHING_MAX is
- * the highest such value.
- */
-#define DLT_MATCHING_MIN 104
-
-/*
- * This value was defined by libpcap 0.5; platforms that have defined
- * it with a different value should define it here with that value -
- * a link type of 104 in a save file will be mapped to DLT_C_HDLC,
- * whatever value that happens to be, so programs will correctly
- * handle files with that link type regardless of the value of
- * DLT_C_HDLC.
- *
- * The name DLT_C_HDLC was used by BSD/OS; we use that name for source
- * compatibility with programs written for BSD/OS.
- *
- * libpcap 0.5 defined it as DLT_CHDLC; we define DLT_CHDLC as well,
- * for source compatibility with programs written for libpcap 0.5.
- */
-#define DLT_C_HDLC 104 /* Cisco HDLC */
-#define DLT_CHDLC DLT_C_HDLC
-
-#define DLT_IEEE802_11 105 /* IEEE 802.11 wireless */
-
-/*
- * Values between 106 and 107 are used in capture file headers as
- * link-layer types corresponding to DLT_ types that might differ
- * between platforms; don't use those values for new DLT_ new types.
- */
-
-/*
- * Frame Relay; BSD/OS has a DLT_FR with a value of 11, but that collides
- * with other values.
- * DLT_FR and DLT_FRELAY packets start with the Q.922 Frame Relay header
- * (DLCI, etc.).
- */
-#define DLT_FRELAY 107
-
-/*
- * OpenBSD DLT_LOOP, for loopback devices; it's like DLT_NULL, except
- * that the AF_ type in the link-layer header is in network byte order.
- *
- * OpenBSD defines it as 12, but that collides with DLT_RAW, so we
- * define it as 108 here. If OpenBSD picks up this file, it should
- * define DLT_LOOP as 12 in its version, as per the comment above -
- * and should not use 108 as a DLT_ value.
- */
-#define DLT_LOOP 108
-
-/*
- * Values between 109 and 112 are used in capture file headers as
- * link-layer types corresponding to DLT_ types that might differ
- * between platforms; don't use those values for new DLT_ new types.
- */
-
-/*
- * Encapsulated packets for IPsec; DLT_ENC is 13 in OpenBSD, but that's
- * DLT_SLIP_BSDOS in NetBSD, so we don't use 13 for it in OSes other
- * than OpenBSD.
- */
-#define DLT_ENC 109
-
-/*
- * This is for Linux cooked sockets.
- */
-#define DLT_LINUX_SLL 113
-
-/*
- * Apple LocalTalk hardware.
- */
-#define DLT_LTALK 114
-
-/*
- * Acorn Econet.
- */
-#define DLT_ECONET 115
-
-/*
- * Reserved for use with OpenBSD ipfilter.
- */
-#define DLT_IPFILTER 116
-
-/*
- * Reserved for use in capture-file headers as a link-layer type
- * corresponding to 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.
- */
-#define DLT_PFLOG 117
-
-/*
- * Registered for Cisco-internal use.
- */
-#define DLT_CISCO_IOS 118
-
-/*
- * Reserved for 802.11 cards using the Prism II chips, with a link-layer
- * header including Prism monitor mode information plus an 802.11
- * header.
- */
-#define DLT_PRISM_HEADER 119
-
-/*
- * Reserved for Aironet 802.11 cards, with an Aironet link-layer header
- * (see Doug Ambrisko's FreeBSD patches).
- */
-#define DLT_AIRONET_HEADER 120
-
-/*
- * Reserved for use by OpenBSD's pfsync device.
- */
-#define DLT_PFSYNC 121
-
-/*
- * Reserved for Siemens HiPath HDLC. XXX
- */
-#define DLT_HHDLC 121
-
-/*
- * Reserved for RFC 2625 IP-over-Fibre Channel.
- */
-#define DLT_IP_OVER_FC 122
-
-/*
- * Reserved for Full Frontal ATM on Solaris.
- */
-#define DLT_SUNATM 123
-
-/*
- * Reserved as per request from Kent Dahlgren <kent@praesum.com>
- * for private use.
- */
-#define DLT_RIO 124 /* RapidIO */
-#define DLT_PCI_EXP 125 /* PCI Express */
-#define DLT_AURORA 126 /* Xilinx Aurora link layer */
-
-/*
- * BSD header for 802.11 plus a number of bits of link-layer information
- * including radio information.
- */
-#ifndef DLT_IEEE802_11_RADIO
-#define DLT_IEEE802_11_RADIO 127
-#endif
-
-/*
- * Reserved for TZSP encapsulation.
- */
-#define DLT_TZSP 128 /* Tazmen Sniffer Protocol */
-
-/*
- * Reserved for Linux ARCNET.
- */
-#define DLT_ARCNET_LINUX 129
-
-/*
- * Juniper-private data link types.
- */
-#define DLT_JUNIPER_MLPPP 130
-#define DLT_JUNIPER_MLFR 131
-#define DLT_JUNIPER_ES 132
-#define DLT_JUNIPER_GGSN 133
-#define DLT_JUNIPER_MFR 134
-#define DLT_JUNIPER_ATM2 135
-#define DLT_JUNIPER_SERVICES 136
-#define DLT_JUNIPER_ATM1 137
-
-/*
- * Apple IP-over-IEEE 1394, as per a request from Dieter Siegmund
- * <dieter@apple.com>. The header that's presented is an Ethernet-like
- * header:
- *
- * #define FIREWIRE_EUI64_LEN 8
- * struct firewire_header {
- * u_char firewire_dhost[FIREWIRE_EUI64_LEN];
- * u_char firewire_shost[FIREWIRE_EUI64_LEN];
- * u_short firewire_type;
- * };
- *
- * with "firewire_type" being an Ethernet type value, rather than,
- * for example, raw GASP frames being handed up.
- */
-#define DLT_APPLE_IP_OVER_IEEE1394 138
-
-/*
- * Various SS7 encapsulations, as per a request from Jeff Morriss
- * <jeff.morriss[AT]ulticom.com> and subsequent discussions.
- */
-#define DLT_MTP2_WITH_PHDR 139 /* pseudo-header with various info, followed by MTP2 */
-#define DLT_MTP2 140 /* MTP2, without pseudo-header */
-#define DLT_MTP3 141 /* MTP3, without pseudo-header or MTP2 */
-#define DLT_SCCP 142 /* SCCP, without pseudo-header or MTP2 or MTP3 */
-
-/*
- * Reserved for DOCSIS.
- */
-#define DLT_DOCSIS 143
-
-/*
- * Reserved for Linux IrDA.
- */
-#define DLT_LINUX_IRDA 144
-
-/*
- * Reserved for IBM SP switch and IBM Next Federation switch.
- */
-#define DLT_IBM_SP 145
-#define DLT_IBM_SN 146
-
-/*
- * Reserved for private use. If you have some link-layer header type
- * that you want to use within your organization, with the capture files
- * using that link-layer header type not ever be sent outside your
- * organization, you can use these values.
- *
- * No libpcap release will use these for any purpose, nor will any
- * tcpdump release use them, either.
- *
- * Do *NOT* use these in capture files that you expect anybody not using
- * your private versions of capture-file-reading tools to read; in
- * particular, do *NOT* use them in products, otherwise you may find that
- * people won't be able to use tcpdump, or snort, or Ethereal, or... to
- * read capture files from your firewall/intrusion detection/traffic
- * monitoring/etc. appliance, or whatever product uses that DLT_ value,
- * and you may also find that the developers of those applications will
- * not accept patches to let them read those files.
- *
- * Also, do not use them if somebody might send you a capture using them
- * for *their* private type and tools using them for *your* private type
- * would have to read them.
- *
- * Instead, ask "tcpdump-workers@tcpdump.org" for a new DLT_ value,
- * as per the comment above, and use the type you're given.
- */
-#define DLT_USER0 147
-#define DLT_USER1 148
-#define DLT_USER2 149
-#define DLT_USER3 150
-#define DLT_USER4 151
-#define DLT_USER5 152
-#define DLT_USER6 153
-#define DLT_USER7 154
-#define DLT_USER8 155
-#define DLT_USER9 156
-#define DLT_USER10 157
-#define DLT_USER11 158
-#define DLT_USER12 159
-#define DLT_USER13 160
-#define DLT_USER14 161
-#define DLT_USER15 162
-
-/*
- * For future use with 802.11 captures - defined by AbsoluteValue
- * Systems to store a number of bits of link-layer information
- * including radio information:
- *
- * http://www.shaftnet.org/~pizza/software/capturefrm.txt
- *
- * but it might be used by some non-AVS drivers now or in the
- * future.
- */
-#define DLT_IEEE802_11_RADIO_AVS 163 /* 802.11 plus AVS radio header */
-
-/*
- * Juniper-private data link type, as per request from
- * Hannes Gredler <hannes@juniper.net>. The DLT_s are used
- * for passing on chassis-internal metainformation such as
- * QOS profiles, etc..
- */
-#define DLT_JUNIPER_MONITOR 164
-
-/*
- * Reserved for BACnet MS/TP.
- */
-#define DLT_BACNET_MS_TP 165
-
-/*
- * Another PPP variant as per request from Karsten Keil <kkeil@suse.de>.
- *
- * This is used in some OSes to allow a kernel socket filter to distinguish
- * between incoming and outgoing packets, on a socket intended to
- * supply pppd with outgoing packets so it can do dial-on-demand and
- * hangup-on-lack-of-demand; incoming packets are filtered out so they
- * don't cause pppd to hold the connection up (you don't want random
- * input packets such as port scans, packets from old lost connections,
- * etc. to force the connection to stay up).
- *
- * The first byte of the PPP header (0xff03) is modified to accommodate
- * the direction - 0x00 = IN, 0x01 = OUT.
- */
-#define DLT_PPP_PPPD 166
-
-/*
- * Names for backwards compatibility with older versions of some PPP
- * software; new software should use DLT_PPP_PPPD.
- */
-#define DLT_PPP_WITH_DIRECTION DLT_PPP_PPPD
-#define DLT_LINUX_PPP_WITHDIRECTION DLT_PPP_PPPD
-
-/*
- * Juniper-private data link type, as per request from
- * Hannes Gredler <hannes@juniper.net>. The DLT_s are used
- * for passing on chassis-internal metainformation such as
- * QOS profiles, cookies, etc..
- */
-#define DLT_JUNIPER_PPPOE 167
-#define DLT_JUNIPER_PPPOE_ATM 168
-
-#define DLT_GPRS_LLC 169 /* GPRS LLC */
-#define DLT_GPF_T 170 /* GPF-T (ITU-T G.7041/Y.1303) */
-#define DLT_GPF_F 171 /* GPF-F (ITU-T G.7041/Y.1303) */
-
-/*
- * Requested by Oolan Zimmer <oz@gcom.com> for use in Gcom's T1/E1 line
- * monitoring equipment.
- */
-#define DLT_GCOM_T1E1 172
-#define DLT_GCOM_SERIAL 173
-
-/*
- * Juniper-private data link type, as per request from
- * Hannes Gredler <hannes@juniper.net>. The DLT_ is used
- * for internal communication to Physical Interface Cards (PIC)
- */
-#define DLT_JUNIPER_PIC_PEER 174
-
-/*
- * Link types requested by Gregor Maier <gregor@endace.com> of Endace
- * Measurement Systems. They add an ERF header (see
- * http://www.endace.com/support/EndaceRecordFormat.pdf) in front of
- * the link-layer header.
- */
-#define DLT_ERF_ETH 175 /* Ethernet */
-#define DLT_ERF_POS 176 /* Packet-over-SONET */
-
-/*
- * Requested by Daniele Orlandi <daniele@orlandi.com> for raw LAPD
- * for vISDN (http://www.orlandi.com/visdn/). Its link-layer header
- * includes additional information before the LAPD header, so it's
- * not necessarily a generic LAPD header.
- */
-#define DLT_LINUX_LAPD 177
-
-/*
- * Juniper-private data link type, as per request from
- * Hannes Gredler <hannes@juniper.net>.
- * The DLT_ are used for prepending meta-information
- * like interface index, interface name
- * before standard Ethernet, PPP, Frelay & C-HDLC Frames
- */
-#define DLT_JUNIPER_ETHER 178
-#define DLT_JUNIPER_PPP 179
-#define DLT_JUNIPER_FRELAY 180
-#define DLT_JUNIPER_CHDLC 181
-
-/*
- * Multi Link Frame Relay (FRF.16)
- */
-#define DLT_MFR 182
-
-/*
- * Juniper-private data link type, as per request from
- * Hannes Gredler <hannes@juniper.net>.
- * The DLT_ is used for internal communication with a
- * voice Adapter Card (PIC)
- */
-#define DLT_JUNIPER_VP 183
-
-/*
- * Arinc 429 frames.
- * DLT_ requested by Gianluca Varenni <gianluca.varenni@cacetech.com>.
- * Every frame contains a 32bit A429 label.
- * More documentation on Arinc 429 can be found at
- * http://www.condoreng.com/support/downloads/tutorials/ARINCTutorial.pdf
- */
-#define DLT_A429 184
-
-/*
- * Arinc 653 Interpartition Communication messages.
- * DLT_ requested by Gianluca Varenni <gianluca.varenni@cacetech.com>.
- * Please refer to the A653-1 standard for more information.
- */
-#define DLT_A653_ICM 185
-
-/*
- * USB packets, beginning with a USB setup header; requested by
- * Paolo Abeni <paolo.abeni@email.it>.
- */
-#define DLT_USB 186
-
-/*
- * Bluetooth HCI UART transport layer (part H:4); requested by
- * Paolo Abeni.
- */
-#define DLT_BLUETOOTH_HCI_H4 187
-
-/*
- * IEEE 802.16 MAC Common Part Sublayer; requested by Maria Cruz
- * <cruz_petagay@bah.com>.
- */
-#define DLT_IEEE802_16_MAC_CPS 188
-
-/*
- * USB packets, beginning with a Linux USB header; requested by
- * Paolo Abeni <paolo.abeni@email.it>.
- */
-#define DLT_USB_LINUX 189
-
-/*
- * Controller Area Network (CAN) v. 2.0B packets.
- * DLT_ requested by Gianluca Varenni <gianluca.varenni@cacetech.com>.
- * Used to dump CAN packets coming from a CAN Vector board.
- * More documentation on the CAN v2.0B frames can be found at
- * http://www.can-cia.org/downloads/?269
- */
-#define DLT_CAN20B 190
-
-/*
- * IEEE 802.15.4, with address fields padded, as is done by Linux
- * drivers; requested by Juergen Schimmer.
- */
-#define DLT_IEEE802_15_4_LINUX 191
-
-/*
- * Per Packet Information encapsulated packets.
- * DLT_ requested by Gianluca Varenni <gianluca.varenni@cacetech.com>.
- */
-#define DLT_PPI 192
-
-/*
- * Header for 802.16 MAC Common Part Sublayer plus a radiotap radio header;
- * requested by Charles Clancy.
- */
-#define DLT_IEEE802_16_MAC_CPS_RADIO 193
-
-/*
- * Juniper-private data link type, as per request from
- * Hannes Gredler <hannes@juniper.net>.
- * The DLT_ is used for internal communication with a
- * integrated service module (ISM).
- */
-#define DLT_JUNIPER_ISM 194
-
-/*
- * IEEE 802.15.4, exactly as it appears in the spec (no padding, no
- * nothing); requested by Mikko Saarnivala <mikko.saarnivala@sensinode.com>.
- */
-#define DLT_IEEE802_15_4 195
-
-/*
- * Various link-layer types, with a pseudo-header, for SITA
- * (http://www.sita.aero/); requested by Fulko Hew (fulko.hew@gmail.com).
- */
-#define DLT_SITA 196
-
-/*
- * Various link-layer types, with a pseudo-header, for Endace DAG cards;
- * encapsulates Endace ERF records. Requested by Stephen Donnelly
- * <stephen@endace.com>.
- */
-#define DLT_ERF 197
-
-/*
- * Special header prepended to Ethernet packets when capturing from a
- * u10 Networks board. Requested by Phil Mulholland
- * <phil@u10networks.com>.
- */
-#define DLT_RAIF1 198
-
-/*
- * IPMB packet for IPMI, beginning with the I2C slave address, followed
- * by the netFn and LUN, etc.. Requested by Chanthy Toeung
- * <chanthy.toeung@ca.kontron.com>.
- */
-#define DLT_IPMB 199
-
-/*
- * Juniper-private data link type, as per request from
- * Hannes Gredler <hannes@juniper.net>.
- * The DLT_ is used for capturing data on a secure tunnel interface.
- */
-#define DLT_JUNIPER_ST 200
-
-/*
- * Bluetooth HCI UART transport layer (part H:4), with pseudo-header
- * that includes direction information; requested by Paolo Abeni.
- */
-#define DLT_BLUETOOTH_HCI_H4_WITH_PHDR 201
-
-/*
- * AX.25 packet with a 1-byte KISS header; see
- *
- * http://www.ax25.net/kiss.htm
- *
- * as per Richard Stearn <richard@rns-stearn.demon.co.uk>.
- */
-#define DLT_AX25_KISS 202
-
-/*
- * LAPD packets from an ISDN channel, starting with the address field,
- * with no pseudo-header.
- * Requested by Varuna De Silva <varunax@gmail.com>.
- */
-#define DLT_LAPD 203
-
-/*
- * Variants of various link-layer headers, with a one-byte direction
- * pseudo-header prepended - zero means "received by this host",
- * non-zero (any non-zero value) means "sent by this host" - as per
- * Will Barker <w.barker@zen.co.uk>.
- */
-#define DLT_PPP_WITH_DIR 204 /* PPP - don't confuse with DLT_PPP_WITH_DIRECTION */
-#define DLT_C_HDLC_WITH_DIR 205 /* Cisco HDLC */
-#define DLT_FRELAY_WITH_DIR 206 /* Frame Relay */
-#define DLT_LAPB_WITH_DIR 207 /* LAPB */
-
-/*
- * 208 is reserved for an as-yet-unspecified proprietary link-layer
- * type, as requested by Will Barker.
- */
-
-/*
- * IPMB with a Linux-specific pseudo-header; as requested by Alexey Neyman
- * <avn@pigeonpoint.com>.
- */
-#define DLT_IPMB_LINUX 209
-
-/*
- * FlexRay automotive bus - http://www.flexray.com/ - as requested
- * by Hannes Kaelber <hannes.kaelber@x2e.de>.
- */
-#define DLT_FLEXRAY 210
-
-/*
- * Media Oriented Systems Transport (MOST) bus for multimedia
- * transport - http://www.mostcooperation.com/ - as requested
- * by Hannes Kaelber <hannes.kaelber@x2e.de>.
- */
-#define DLT_MOST 211
-
-/*
- * Local Interconnect Network (LIN) bus for vehicle networks -
- * http://www.lin-subbus.org/ - as requested by Hannes Kaelber
- * <hannes.kaelber@x2e.de>.
- */
-#define DLT_LIN 212
-
-/*
- * X2E-private data link type used for serial line capture,
- * as requested by Hannes Kaelber <hannes.kaelber@x2e.de>.
- */
-#define DLT_X2E_SERIAL 213
-
-/*
- * X2E-private data link type used for the Xoraya data logger
- * family, as requested by Hannes Kaelber <hannes.kaelber@x2e.de>.
- */
-#define DLT_X2E_XORAYA 214
-
-/*
- * IEEE 802.15.4, exactly as it appears in the spec (no padding, no
- * nothing), but with the PHY-level data for non-ASK PHYs (4 octets
- * of 0 as preamble, one octet of SFD, one octet of frame length+
- * reserved bit, and then the MAC-layer data, starting with the
- * frame control field).
- *
- * Requested by Max Filippov <jcmvbkbc@gmail.com>.
- */
-#define DLT_IEEE802_15_4_NONASK_PHY 215
-
-/*
- * David Gibson <david@gibson.dropbear.id.au> requested this for
- * captures from the Linux kernel /dev/input/eventN devices. This
- * is used to communicate keystrokes and mouse movements from the
- * Linux kernel to display systems, such as Xorg.
- */
-#define DLT_LINUX_EVDEV 216
-
-/*
- * GSM Um and Abis interfaces, preceded by a "gsmtap" header.
- *
- * Requested by Harald Welte <laforge@gnumonks.org>.
- */
-#define DLT_GSMTAP_UM 217
-#define DLT_GSMTAP_ABIS 218
-
-/*
- * MPLS, with an MPLS label as the link-layer header.
- * Requested by Michele Marchetto <michele@openbsd.org> on behalf
- * of OpenBSD.
- */
-#define DLT_MPLS 219
-
-/*
- * USB packets, beginning with a Linux USB header, with the USB header
- * padded to 64 bytes; required for memory-mapped access.
- */
-#define DLT_USB_LINUX_MMAPPED 220
-
-/*
- * DECT packets, with a pseudo-header; requested by
- * Matthias Wenzel <tcpdump@mazzoo.de>.
- */
-#define DLT_DECT 221
-/*
- * From: "Lidwa, Eric (GSFC-582.0)[SGT INC]" <eric.lidwa-1@nasa.gov>
- * Date: Mon, 11 May 2009 11:18:30 -0500
- *
- * DLT_AOS. We need it for AOS Space Data Link Protocol.
- * I have already written dissectors for but need an OK from
- * legal before I can submit a patch.
- *
- */
-#define DLT_AOS 222
-
-/*
- * Wireless HART (Highway Addressable Remote Transducer)
- * From the HART Communication Foundation
- * IES/PAS 62591
- *
- * Requested by Sam Roberts <vieuxtech@gmail.com>.
- */
-#define DLT_WIHART 223
-
-/*
- * Fibre Channel FC-2 frames, beginning with a Frame_Header.
- * Requested by Kahou Lei <kahou82@gmail.com>.
- */
-#define DLT_FC_2 224
-
-/*
- * Fibre Channel FC-2 frames, beginning with an encoding of the
- * SOF, and ending with an encoding of the EOF.
- *
- * The encodings represent the frame delimiters as 4-byte sequences
- * representing the corresponding ordered sets, with K28.5
- * represented as 0xBC, and the D symbols as the corresponding
- * byte values; for example, SOFi2, which is K28.5 - D21.5 - D1.2 - D21.2,
- * is represented as 0xBC 0xB5 0x55 0x55.
- *
- * Requested by Kahou Lei <kahou82@gmail.com>.
- */
-#define DLT_FC_2_WITH_FRAME_DELIMS 225
-/*
- * Solaris ipnet pseudo-header; requested by Darren Reed <Darren.Reed@Sun.COM>.
- *
- * The pseudo-header starts with a one-byte version number; for version 2,
- * the pseudo-header is:
- *
- * struct dl_ipnetinfo {
- * u_int8_t dli_version;
- * u_int8_t dli_family;
- * u_int16_t dli_htype;
- * u_int32_t dli_pktlen;
- * u_int32_t dli_ifindex;
- * u_int32_t dli_grifindex;
- * u_int32_t dli_zsrc;
- * u_int32_t dli_zdst;
- * };
- *
- * dli_version is 2 for the current version of the pseudo-header.
- *
- * dli_family is a Solaris address family value, so it's 2 for IPv4
- * and 26 for IPv6.
- *
- * dli_htype is a "hook type" - 0 for incoming packets, 1 for outgoing
- * packets, and 2 for packets arriving from another zone on the same
- * machine.
- *
- * dli_pktlen is the length of the packet data following the pseudo-header
- * (so the captured length minus dli_pktlen is the length of the
- * pseudo-header, assuming the entire pseudo-header was captured).
- *
- * dli_ifindex is the interface index of the interface on which the
- * packet arrived.
- *
- * dli_grifindex is the group interface index number (for IPMP interfaces).
- *
- * dli_zsrc is the zone identifier for the source of the packet.
- *
- * dli_zdst is the zone identifier for the destination of the packet.
- *
- * A zone number of 0 is the global zone; a zone number of 0xffffffff
- * means that the packet arrived from another host on the network, not
- * from another zone on the same machine.
- *
- * An IPv4 or IPv6 datagram follows the pseudo-header; dli_family indicates
- * which of those it is.
- */
-#define DLT_IPNET 226
-
-/*
- * CAN (Controller Area Network) frames, with a pseudo-header as supplied
- * by Linux SocketCAN. See Documentation/networking/can.txt in the Linux
- * source.
- *
- * Requested by Felix Obenhuber <felix@obenhuber.de>.
- */
-#define DLT_CAN_SOCKETCAN 227
-
-/*
- * Raw IPv4/IPv6; different from DLT_RAW in that the DLT_ value specifies
- * whether it's v4 or v6. Requested by Darren Reed <Darren.Reed@Sun.COM>.
- */
-#define DLT_IPV4 228
-#define DLT_IPV6 229
-
-/*
- * IEEE 802.15.4, exactly as it appears in the spec (no padding, no
- * nothing), and with no FCS at the end of the frame; requested by
- * Jon Smirl <jonsmirl@gmail.com>.
- */
-#define DLT_IEEE802_15_4_NOFCS 230
-
-/*
- * Raw D-Bus:
- *
- * http://www.freedesktop.org/wiki/Software/dbus
- *
- * messages:
- *
- * http://dbus.freedesktop.org/doc/dbus-specification.html#message-protocol-messages
- *
- * starting with the endianness flag, followed by the message type, etc.,
- * but without the authentication handshake before the message sequence:
- *
- * http://dbus.freedesktop.org/doc/dbus-specification.html#auth-protocol
- *
- * Requested by Martin Vidner <martin@vidner.net>.
- */
-#define DLT_DBUS 231
-
-/*
- * Juniper-private data link type, as per request from
- * Hannes Gredler <hannes@juniper.net>.
- */
-#define DLT_JUNIPER_VS 232
-#define DLT_JUNIPER_SRX_E2E 233
-#define DLT_JUNIPER_FIBRECHANNEL 234
-
-/*
- * DVB-CI (DVB Common Interface for communication between a PC Card
- * module and a DVB receiver). See
- *
- * http://www.kaiser.cx/pcap-dvbci.html
- *
- * for the specification.
- *
- * Requested by Martin Kaiser <martin@kaiser.cx>.
- */
-#define DLT_DVB_CI 235
-
-/*
- * Variant of 3GPP TS 27.010 multiplexing protocol (similar to, but
- * *not* the same as, 27.010). Requested by Hans-Christoph Schemmel
- * <hans-christoph.schemmel@cinterion.com>.
- */
-#define DLT_MUX27010 236
-
-/*
- * STANAG 5066 D_PDUs. Requested by M. Baris Demiray
- * <barisdemiray@gmail.com>.
- */
-#define DLT_STANAG_5066_D_PDU 237
-
-/*
- * Juniper-private data link type, as per request from
- * Hannes Gredler <hannes@juniper.net>.
- */
-#define DLT_JUNIPER_ATM_CEMIC 238
-
-/*
- * NetFilter LOG messages
- * (payload of netlink NFNL_SUBSYS_ULOG/NFULNL_MSG_PACKET packets)
- *
- * Requested by Jakub Zawadzki <darkjames-ws@darkjames.pl>
- */
-#define DLT_NFLOG 239
-
-/*
- * Hilscher Gesellschaft fuer Systemautomation mbH link-layer type
- * for Ethernet packets with a 4-byte pseudo-header and always
- * with the payload including the FCS, as supplied by their
- * netANALYZER hardware and software.
- *
- * Requested by Holger P. Frommer <HPfrommer@hilscher.com>
- */
-#define DLT_NETANALYZER 240
-
-/*
- * Hilscher Gesellschaft fuer Systemautomation mbH link-layer type
- * for Ethernet packets with a 4-byte pseudo-header and FCS and
- * with the Ethernet header preceded by 7 bytes of preamble and
- * 1 byte of SFD, as supplied by their netANALYZER hardware and
- * software.
- *
- * Requested by Holger P. Frommer <HPfrommer@hilscher.com>
- */
-#define DLT_NETANALYZER_TRANSPARENT 241
-
-/*
- * IP-over-InfiniBand, as specified by RFC 4391.
- *
- * Requested by Petr Sumbera <petr.sumbera@oracle.com>.
- */
-#define DLT_IPOIB 242
-
-/*
- * 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
-
-/*
- * DLT type for the netlink protocol (nlmon devices).
- */
-#define DLT_NETLINK 253
-
-/*
- * Bluetooth Linux Monitor headers for the BlueZ stack.
- */
-#define DLT_BLUETOOTH_LINUX_MONITOR 254
-
-/*
- * Bluetooth Basic Rate/Enhanced Data Rate baseband packets, as
- * captured by Ubertooth.
- */
-#define DLT_BLUETOOTH_BREDR_BB 255
-
-/*
- * Bluetooth Low Energy link layer packets, as captured by Ubertooth.
- */
-#define DLT_BLUETOOTH_LE_LL_WITH_PHDR 256
-
-/*
- * PROFIBUS data link layer.
- */
-#define DLT_PROFIBUS_DL 257
-
-/*
- * Apple's DLT_PKTAP headers.
- *
- * Sadly, the folks at Apple either had no clue that the DLT_USERn values
- * are for internal use within an organization and partners only, and
- * didn't know that the right way to get a link-layer header type is to
- * ask tcpdump.org for one, or knew and didn't care, so they just
- * used DLT_USER2, which causes problems for everything except for
- * their version of tcpdump.
- *
- * So I'll just give them one; hopefully this will show up in a
- * libpcap release in time for them to get this into 10.10 Big Sur
- * or whatever Mavericks' successor is called. LINKTYPE_PKTAP
- * will be 258 *even on OS X*; that is *intentional*, so that
- * PKTAP files look the same on *all* OSes (different OSes can have
- * different numerical values for a given DLT_, but *MUST NOT* have
- * different values for what goes in a file, as files can be moved
- * between OSes!).
- *
- * When capturing, on a system with a Darwin-based OS, on a device
- * that returns 149 (DLT_USER2 and Apple's DLT_PKTAP) with this
- * version of libpcap, the DLT_ value for the pcap_t will be DLT_PKTAP,
- * and that will continue to be DLT_USER2 on Darwin-based OSes. That way,
- * binary compatibility with Mavericks is preserved for programs using
- * this version of libpcap. This does mean that if you were using
- * DLT_USER2 for some capture device on OS X, you can't do so with
- * this version of libpcap, just as you can't with Apple's libpcap -
- * on OS X, they define DLT_PKTAP to be DLT_USER2, so programs won't
- * be able to distinguish between PKTAP and whatever you were using
- * DLT_USER2 for.
- *
- * If the program saves the capture to a file using this version of
- * libpcap's pcap_dump code, the LINKTYPE_ value in the file will be
- * LINKTYPE_PKTAP, which will be 258, even on Darwin-based OSes.
- * That way, the file will *not* be a DLT_USER2 file. That means
- * that the latest version of tcpdump, when built with this version
- * of libpcap, and sufficiently recent versions of Wireshark will
- * be able to read those files and interpret them correctly; however,
- * Apple's version of tcpdump in OS X 10.9 won't be able to handle
- * them. (Hopefully, Apple will pick up this version of libpcap,
- * and the corresponding version of tcpdump, so that tcpdump will
- * be able to handle the old LINKTYPE_USER2 captures *and* the new
- * LINKTYPE_PKTAP captures.)
- */
-#ifdef __APPLE__
-#define DLT_PKTAP DLT_USER2
-#else
-#define DLT_PKTAP 258
-#endif
-
-/*
- * Ethernet packets preceded by a header giving the last 6 octets
- * of the preamble specified by 802.3-2012 Clause 65, section
- * 65.1.3.2 "Transmit".
- */
-#define DLT_EPON 259
-
-/*
- * IPMI trace packets, as specified by Table 3-20 "Trace Data Block Format"
- * in the PICMG HPM.2 specification.
- */
-#define DLT_IPMI_HPM_2 260
-
-#define DLT_MATCHING_MAX 260 /* 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.
- */
-#define DLT_CLASS(x) ((x) & 0x03ff0000)
+/* Pull in data-link level type codes. */
+#include <net/dlt.h>
/*
* The instruction encodings.
diff --git a/sys/net/dlt.h b/sys/net/dlt.h
new file mode 100644
index 000000000000..ee6c32bb1580
--- /dev/null
+++ b/sys/net/dlt.h
@@ -0,0 +1,1342 @@
+/*-
+ * Copyright (c) 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1997
+ * The Regents of the University of California. All rights reserved.
+ *
+ * This code is derived from the Stanford/CMU enet packet filter,
+ * (net/enet.c) distributed as part of 4.3BSD, and code contributed
+ * to Berkeley by Steven McCanne and Van Jacobson both of Lawrence
+ * Berkeley Laboratory.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the University of
+ * California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * @(#)bpf.h 7.1 (Berkeley) 5/7/91
+ *
+ * $FreeBSD$
+ */
+
+#ifndef _NET_DLT_H_
+#define _NET_DLT_H_
+
+/*
+ * Link-layer header type codes.
+ *
+ * Do *NOT* add new values to this list without asking
+ * "tcpdump-workers@lists.tcpdump.org" for a value. Otherwise, you run
+ * the risk of using a value that's already being used for some other
+ * purpose, and of having tools that read libpcap-format captures not
+ * being able to handle captures with your new DLT_ value, with no hope
+ * that they will ever be changed to do so (as that would destroy their
+ * ability to read captures using that value for that other purpose).
+ *
+ * See
+ *
+ * http://www.tcpdump.org/linktypes.html
+ *
+ * for detailed descriptions of some of these link-layer header types.
+ */
+
+/*
+ * These are the types that are the same on all platforms, and that
+ * have been defined by <net/bpf.h> for ages.
+ */
+#define DLT_NULL 0 /* BSD loopback encapsulation */
+#define DLT_EN10MB 1 /* Ethernet (10Mb) */
+#define DLT_EN3MB 2 /* Experimental Ethernet (3Mb) */
+#define DLT_AX25 3 /* Amateur Radio AX.25 */
+#define DLT_PRONET 4 /* Proteon ProNET Token Ring */
+#define DLT_CHAOS 5 /* Chaos */
+#define DLT_IEEE802 6 /* 802.5 Token Ring */
+#define DLT_ARCNET 7 /* ARCNET, with BSD-style header */
+#define DLT_SLIP 8 /* Serial Line IP */
+#define DLT_PPP 9 /* Point-to-point Protocol */
+#define DLT_FDDI 10 /* FDDI */
+
+/*
+ * These are types that are different on some platforms, and that
+ * have been defined by <net/bpf.h> for ages. We use #ifdefs to
+ * detect the BSDs that define them differently from the traditional
+ * libpcap <net/bpf.h>
+ *
+ * XXX - DLT_ATM_RFC1483 is 13 in BSD/OS, and DLT_RAW is 14 in BSD/OS,
+ * but I don't know what the right #define is for BSD/OS.
+ */
+#define DLT_ATM_RFC1483 11 /* LLC-encapsulated ATM */
+
+#ifdef __OpenBSD__
+#define DLT_RAW 14 /* raw IP */
+#else
+#define DLT_RAW 12 /* raw IP */
+#endif
+
+/*
+ * Given that the only OS that currently generates BSD/OS SLIP or PPP
+ * is, well, BSD/OS, arguably everybody should have chosen its values
+ * for DLT_SLIP_BSDOS and DLT_PPP_BSDOS, which are 15 and 16, but they
+ * didn't. So it goes.
+ */
+#if defined(__NetBSD__) || defined(__FreeBSD__)
+#ifndef DLT_SLIP_BSDOS
+#define DLT_SLIP_BSDOS 13 /* BSD/OS Serial Line IP */
+#define DLT_PPP_BSDOS 14 /* BSD/OS Point-to-point Protocol */
+#endif
+#else
+#define DLT_SLIP_BSDOS 15 /* BSD/OS Serial Line IP */
+#define DLT_PPP_BSDOS 16 /* BSD/OS Point-to-point Protocol */
+#endif
+
+/*
+ * 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 */
+
+/*
+ * Apparently Redback uses this for its SmartEdge 400/800. I hope
+ * nobody else decided to use it, too.
+ */
+#define DLT_REDBACK_SMARTEDGE 32
+
+/*
+ * These values are defined by NetBSD; other platforms should refrain from
+ * using them for other purposes, so that NetBSD savefiles with link
+ * types of 50 or 51 can be read as this type on all platforms.
+ */
+#define DLT_PPP_SERIAL 50 /* PPP over serial with HDLC encapsulation */
+#define DLT_PPP_ETHER 51 /* PPP over Ethernet */
+
+/*
+ * The Axent Raptor firewall - now the Symantec Enterprise Firewall - uses
+ * a link-layer type of 99 for the tcpdump it supplies. The link-layer
+ * header has 6 bytes of unknown data, something that appears to be an
+ * Ethernet type, and 36 bytes that appear to be 0 in at least one capture
+ * I've seen.
+ */
+#define DLT_SYMANTEC_FIREWALL 99
+
+/*
+ * Values between 100 and 103 are used in capture file headers as
+ * link-layer header type LINKTYPE_ values corresponding to DLT_ types
+ * that differ between platforms; don't use those values for new DLT_
+ * new types.
+ */
+
+/*
+ * Values starting with 104 are used for newly-assigned link-layer
+ * header type values; for those link-layer header types, the DLT_
+ * value returned by pcap_datalink() and passed to pcap_open_dead(),
+ * and the LINKTYPE_ value that appears in capture files, are the
+ * same.
+ *
+ * DLT_MATCHING_MIN is the lowest such value; DLT_MATCHING_MAX is
+ * the highest such value.
+ */
+#define DLT_MATCHING_MIN 104
+
+/*
+ * This value was defined by libpcap 0.5; platforms that have defined
+ * it with a different value should define it here with that value -
+ * a link type of 104 in a save file will be mapped to DLT_C_HDLC,
+ * whatever value that happens to be, so programs will correctly
+ * handle files with that link type regardless of the value of
+ * DLT_C_HDLC.
+ *
+ * The name DLT_C_HDLC was used by BSD/OS; we use that name for source
+ * compatibility with programs written for BSD/OS.
+ *
+ * libpcap 0.5 defined it as DLT_CHDLC; we define DLT_CHDLC as well,
+ * for source compatibility with programs written for libpcap 0.5.
+ */
+#define DLT_C_HDLC 104 /* Cisco HDLC */
+#define DLT_CHDLC DLT_C_HDLC
+
+#define DLT_IEEE802_11 105 /* IEEE 802.11 wireless */
+
+/*
+ * 106 is reserved for Linux Classical IP over ATM; it's like DLT_RAW,
+ * except when it isn't. (I.e., sometimes it's just raw IP, and
+ * sometimes it isn't.) We currently handle it as DLT_LINUX_SLL,
+ * so that we don't have to worry about the link-layer header.)
+ */
+
+/*
+ * Frame Relay; BSD/OS has a DLT_FR with a value of 11, but that collides
+ * with other values.
+ * DLT_FR and DLT_FRELAY packets start with the Q.922 Frame Relay header
+ * (DLCI, etc.).
+ */
+#define DLT_FRELAY 107
+
+/*
+ * OpenBSD DLT_LOOP, for loopback devices; it's like DLT_NULL, except
+ * that the AF_ type in the link-layer header is in network byte order.
+ *
+ * DLT_LOOP is 12 in OpenBSD, but that's DLT_RAW in other OSes, so
+ * we don't use 12 for it in OSes other than OpenBSD.
+ */
+#ifdef __OpenBSD__
+#define DLT_LOOP 12
+#else
+#define DLT_LOOP 108
+#endif
+
+/*
+ * Encapsulated packets for IPsec; DLT_ENC is 13 in OpenBSD, but that's
+ * DLT_SLIP_BSDOS in NetBSD, so we don't use 13 for it in OSes other
+ * than OpenBSD.
+ */
+#ifdef __OpenBSD__
+#define DLT_ENC 13
+#else
+#define DLT_ENC 109
+#endif
+
+/*
+ * Values between 110 and 112 are reserved for use in capture file headers
+ * as link-layer types corresponding to DLT_ types that might differ
+ * between platforms; don't use those values for new DLT_ types
+ * other than the corresponding DLT_ types.
+ */
+
+/*
+ * This is for Linux cooked sockets.
+ */
+#define DLT_LINUX_SLL 113
+
+/*
+ * Apple LocalTalk hardware.
+ */
+#define DLT_LTALK 114
+
+/*
+ * Acorn Econet.
+ */
+#define DLT_ECONET 115
+
+/*
+ * Reserved for use with OpenBSD ipfilter.
+ */
+#define DLT_IPFILTER 116
+
+/*
+ * OpenBSD DLT_PFLOG.
+ */
+#define DLT_PFLOG 117
+
+/*
+ * Registered for Cisco-internal use.
+ */
+#define DLT_CISCO_IOS 118
+
+/*
+ * For 802.11 cards using the Prism II chips, with a link-layer
+ * header including Prism monitor mode information plus an 802.11
+ * header.
+ */
+#define DLT_PRISM_HEADER 119
+
+/*
+ * Reserved for Aironet 802.11 cards, with an Aironet link-layer header
+ * (see Doug Ambrisko's FreeBSD patches).
+ */
+#define DLT_AIRONET_HEADER 120
+
+/*
+ * Sigh.
+ *
+ * 121 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. In current versions, its libpcap
+ * does DLT_ <-> LINKTYPE_ mapping, mapping DLT_PFSYNC to a
+ * LINKTYPE_PFSYNC value of 246, so it should write out DLT_PFSYNC
+ * dump files with 246 as the link-layer header type. (Earlier
+ * versions might not have done mapping, in which case they would
+ * have written them out with a link-layer header type of 121.)
+ *
+ * OpenBSD, from which pf came, however, uses 18 for DLT_PFSYNC;
+ * its libpcap does no DLT_ <-> LINKTYPE_ mapping, so it would
+ * write out DLT_PFSYNC dump files with use 18 as the link-layer
+ * header type.
+ *
+ * NetBSD, DragonFly BSD, and Darwin also use 18 for DLT_PFSYNC; in
+ * current versions, their libpcaps do DLT_ <-> LINKTYPE_ mapping,
+ * mapping DLT_PFSYNC to a LINKTYPE_PFSYNC value of 246, so they
+ * should write out DLT_PFSYNC dump files with 246 as the link-layer
+ * header type. (Earlier versions might not have done mapping,
+ * in which case they'd work the same way OpenBSD does, writing
+ * them out with a link-layer header type of 18.)
+ *
+ * We'll define DLT_PFSYNC as:
+ *
+ * 18 on NetBSD, OpenBSD, DragonFly BSD, and Darwin;
+ *
+ * 121 on FreeBSD;
+ *
+ * 246 everywhere else.
+ *
+ * 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 246 on *all* platforms, so that
+ * savefiles written using *this* code won't use 18 or 121 for PFSYNC,
+ * they'll all use 246.
+ *
+ * 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, as pcap_datalink() will give 121 for both of them. Code
+ * that doesn't, such as the code in Wireshark, will be able to
+ * distinguish between them.
+ *
+ * FreeBSD's libpcap won't map a link-layer header type of 18 - i.e.,
+ * DLT_PFSYNC files from OpenBSD and possibly older versions of NetBSD,
+ * DragonFly BSD, and OS X - to DLT_PFSYNC, so code built with FreeBSD's
+ * libpcap won't treat those files as DLT_PFSYNC files.
+ *
+ * Other libpcaps won't map a link-layer header type of 121 to DLT_PFSYNC;
+ * this means they can read DLT_HHDLC files, if any exist, but won't
+ * treat pcap files written by any older versions of FreeBSD libpcap that
+ * didn't map to 246 as DLT_PFSYNC files.
+ */
+#ifdef __FreeBSD__
+#define DLT_PFSYNC 121
+#else
+#define DLT_HHDLC 121
+#endif
+
+/*
+ * This is for RFC 2625 IP-over-Fibre Channel.
+ *
+ * This is not for use with raw Fibre Channel, where the link-layer
+ * header starts with a Fibre Channel frame header; it's for IP-over-FC,
+ * where the link-layer header starts with an RFC 2625 Network_Header
+ * field.
+ */
+#define DLT_IP_OVER_FC 122
+
+/*
+ * This is for Full Frontal ATM on Solaris with SunATM, with a
+ * pseudo-header followed by an AALn PDU.
+ *
+ * There may be other forms of Full Frontal ATM on other OSes,
+ * with different pseudo-headers.
+ *
+ * If ATM software returns a pseudo-header with VPI/VCI information
+ * (and, ideally, packet type information, e.g. signalling, ILMI,
+ * LANE, LLC-multiplexed traffic, etc.), it should not use
+ * DLT_ATM_RFC1483, but should get a new DLT_ value, so tcpdump
+ * and the like don't have to infer the presence or absence of a
+ * pseudo-header and the form of the pseudo-header.
+ */
+#define DLT_SUNATM 123 /* Solaris+SunATM */
+
+/*
+ * Reserved as per request from Kent Dahlgren <kent@praesum.com>
+ * for private use.
+ */
+#define DLT_RIO 124 /* RapidIO */
+#define DLT_PCI_EXP 125 /* PCI Express */
+#define DLT_AURORA 126 /* Xilinx Aurora link layer */
+
+/*
+ * Header for 802.11 plus a number of bits of link-layer information
+ * including radio information, used by some recent BSD drivers as
+ * well as the madwifi Atheros driver for Linux.
+ */
+#define DLT_IEEE802_11_RADIO 127 /* 802.11 plus radiotap radio header */
+
+/*
+ * Reserved for the TZSP encapsulation, as per request from
+ * Chris Waters <chris.waters@networkchemistry.com>
+ * TZSP is a generic encapsulation for any other link type,
+ * which includes a means to include meta-information
+ * with the packet, e.g. signal strength and channel
+ * for 802.11 packets.
+ */
+#define DLT_TZSP 128 /* Tazmen Sniffer Protocol */
+
+/*
+ * BSD's ARCNET headers have the source host, destination host,
+ * and type at the beginning of the packet; that's what's handed
+ * up to userland via BPF.
+ *
+ * Linux's ARCNET headers, however, have a 2-byte offset field
+ * between the host IDs and the type; that's what's handed up
+ * to userland via PF_PACKET sockets.
+ *
+ * We therefore have to have separate DLT_ values for them.
+ */
+#define DLT_ARCNET_LINUX 129 /* ARCNET */
+
+/*
+ * Juniper-private data link types, as per request from
+ * Hannes Gredler <hannes@juniper.net>. The DLT_s are used
+ * for passing on chassis-internal metainformation such as
+ * QOS profiles, etc..
+ */
+#define DLT_JUNIPER_MLPPP 130
+#define DLT_JUNIPER_MLFR 131
+#define DLT_JUNIPER_ES 132
+#define DLT_JUNIPER_GGSN 133
+#define DLT_JUNIPER_MFR 134
+#define DLT_JUNIPER_ATM2 135
+#define DLT_JUNIPER_SERVICES 136
+#define DLT_JUNIPER_ATM1 137
+
+/*
+ * Apple IP-over-IEEE 1394, as per a request from Dieter Siegmund
+ * <dieter@apple.com>. The header that's presented is an Ethernet-like
+ * header:
+ *
+ * #define FIREWIRE_EUI64_LEN 8
+ * struct firewire_header {
+ * u_char firewire_dhost[FIREWIRE_EUI64_LEN];
+ * u_char firewire_shost[FIREWIRE_EUI64_LEN];
+ * u_short firewire_type;
+ * };
+ *
+ * with "firewire_type" being an Ethernet type value, rather than,
+ * for example, raw GASP frames being handed up.
+ */
+#define DLT_APPLE_IP_OVER_IEEE1394 138
+
+/*
+ * Various SS7 encapsulations, as per a request from Jeff Morriss
+ * <jeff.morriss[AT]ulticom.com> and subsequent discussions.
+ */
+#define DLT_MTP2_WITH_PHDR 139 /* pseudo-header with various info, followed by MTP2 */
+#define DLT_MTP2 140 /* MTP2, without pseudo-header */
+#define DLT_MTP3 141 /* MTP3, without pseudo-header or MTP2 */
+#define DLT_SCCP 142 /* SCCP, without pseudo-header or MTP2 or MTP3 */
+
+/*
+ * DOCSIS MAC frames.
+ */
+#define DLT_DOCSIS 143
+
+/*
+ * Linux-IrDA packets. Protocol defined at http://www.irda.org.
+ * Those packets include IrLAP headers and above (IrLMP...), but
+ * don't include Phy framing (SOF/EOF/CRC & byte stuffing), because Phy
+ * framing can be handled by the hardware and depend on the bitrate.
+ * This is exactly the format you would get capturing on a Linux-IrDA
+ * interface (irdaX), but not on a raw serial port.
+ * Note the capture is done in "Linux-cooked" mode, so each packet include
+ * a fake packet header (struct sll_header). This is because IrDA packet
+ * decoding is dependant on the direction of the packet (incomming or
+ * outgoing).
+ * When/if other platform implement IrDA capture, we may revisit the
+ * issue and define a real DLT_IRDA...
+ * Jean II
+ */
+#define DLT_LINUX_IRDA 144
+
+/*
+ * Reserved for IBM SP switch and IBM Next Federation switch.
+ */
+#define DLT_IBM_SP 145
+#define DLT_IBM_SN 146
+
+/*
+ * Reserved for private use. If you have some link-layer header type
+ * that you want to use within your organization, with the capture files
+ * using that link-layer header type not ever be sent outside your
+ * organization, you can use these values.
+ *
+ * No libpcap release will use these for any purpose, nor will any
+ * tcpdump release use them, either.
+ *
+ * Do *NOT* use these in capture files that you expect anybody not using
+ * your private versions of capture-file-reading tools to read; in
+ * particular, do *NOT* use them in products, otherwise you may find that
+ * people won't be able to use tcpdump, or snort, or Ethereal, or... to
+ * read capture files from your firewall/intrusion detection/traffic
+ * monitoring/etc. appliance, or whatever product uses that DLT_ value,
+ * and you may also find that the developers of those applications will
+ * not accept patches to let them read those files.
+ *
+ * Also, do not use them if somebody might send you a capture using them
+ * for *their* private type and tools using them for *your* private type
+ * would have to read them.
+ *
+ * Instead, ask "tcpdump-workers@lists.tcpdump.org" for a new DLT_ value,
+ * as per the comment above, and use the type you're given.
+ */
+#define DLT_USER0 147
+#define DLT_USER1 148
+#define DLT_USER2 149
+#define DLT_USER3 150
+#define DLT_USER4 151
+#define DLT_USER5 152
+#define DLT_USER6 153
+#define DLT_USER7 154
+#define DLT_USER8 155
+#define DLT_USER9 156
+#define DLT_USER10 157
+#define DLT_USER11 158
+#define DLT_USER12 159
+#define DLT_USER13 160
+#define DLT_USER14 161
+#define DLT_USER15 162
+
+/*
+ * For future use with 802.11 captures - defined by AbsoluteValue
+ * Systems to store a number of bits of link-layer information
+ * including radio information:
+ *
+ * http://www.shaftnet.org/~pizza/software/capturefrm.txt
+ *
+ * but it might be used by some non-AVS drivers now or in the
+ * future.
+ */
+#define DLT_IEEE802_11_RADIO_AVS 163 /* 802.11 plus AVS radio header */
+
+/*
+ * Juniper-private data link type, as per request from
+ * Hannes Gredler <hannes@juniper.net>. The DLT_s are used
+ * for passing on chassis-internal metainformation such as
+ * QOS profiles, etc..
+ */
+#define DLT_JUNIPER_MONITOR 164
+
+/*
+ * BACnet MS/TP frames.
+ */
+#define DLT_BACNET_MS_TP 165
+
+/*
+ * Another PPP variant as per request from Karsten Keil <kkeil@suse.de>.
+ *
+ * This is used in some OSes to allow a kernel socket filter to distinguish
+ * between incoming and outgoing packets, on a socket intended to
+ * supply pppd with outgoing packets so it can do dial-on-demand and
+ * hangup-on-lack-of-demand; incoming packets are filtered out so they
+ * don't cause pppd to hold the connection up (you don't want random
+ * input packets such as port scans, packets from old lost connections,
+ * etc. to force the connection to stay up).
+ *
+ * The first byte of the PPP header (0xff03) is modified to accomodate
+ * the direction - 0x00 = IN, 0x01 = OUT.
+ */
+#define DLT_PPP_PPPD 166
+
+/*
+ * Names for backwards compatibility with older versions of some PPP
+ * software; new software should use DLT_PPP_PPPD.
+ */
+#define DLT_PPP_WITH_DIRECTION DLT_PPP_PPPD
+#define DLT_LINUX_PPP_WITHDIRECTION DLT_PPP_PPPD
+
+/*
+ * Juniper-private data link type, as per request from
+ * Hannes Gredler <hannes@juniper.net>. The DLT_s are used
+ * for passing on chassis-internal metainformation such as
+ * QOS profiles, cookies, etc..
+ */
+#define DLT_JUNIPER_PPPOE 167
+#define DLT_JUNIPER_PPPOE_ATM 168
+
+#define DLT_GPRS_LLC 169 /* GPRS LLC */
+#define DLT_GPF_T 170 /* GPF-T (ITU-T G.7041/Y.1303) */
+#define DLT_GPF_F 171 /* GPF-F (ITU-T G.7041/Y.1303) */
+
+/*
+ * Requested by Oolan Zimmer <oz@gcom.com> for use in Gcom's T1/E1 line
+ * monitoring equipment.
+ */
+#define DLT_GCOM_T1E1 172
+#define DLT_GCOM_SERIAL 173
+
+/*
+ * Juniper-private data link type, as per request from
+ * Hannes Gredler <hannes@juniper.net>. The DLT_ is used
+ * for internal communication to Physical Interface Cards (PIC)
+ */
+#define DLT_JUNIPER_PIC_PEER 174
+
+/*
+ * Link types requested by Gregor Maier <gregor@endace.com> of Endace
+ * Measurement Systems. They add an ERF header (see
+ * http://www.endace.com/support/EndaceRecordFormat.pdf) in front of
+ * the link-layer header.
+ */
+#define DLT_ERF_ETH 175 /* Ethernet */
+#define DLT_ERF_POS 176 /* Packet-over-SONET */
+
+/*
+ * Requested by Daniele Orlandi <daniele@orlandi.com> for raw LAPD
+ * for vISDN (http://www.orlandi.com/visdn/). Its link-layer header
+ * includes additional information before the LAPD header, so it's
+ * not necessarily a generic LAPD header.
+ */
+#define DLT_LINUX_LAPD 177
+
+/*
+ * Juniper-private data link type, as per request from
+ * Hannes Gredler <hannes@juniper.net>.
+ * The DLT_ are used for prepending meta-information
+ * like interface index, interface name
+ * before standard Ethernet, PPP, Frelay & C-HDLC Frames
+ */
+#define DLT_JUNIPER_ETHER 178
+#define DLT_JUNIPER_PPP 179
+#define DLT_JUNIPER_FRELAY 180
+#define DLT_JUNIPER_CHDLC 181
+
+/*
+ * Multi Link Frame Relay (FRF.16)
+ */
+#define DLT_MFR 182
+
+/*
+ * Juniper-private data link type, as per request from
+ * Hannes Gredler <hannes@juniper.net>.
+ * The DLT_ is used for internal communication with a
+ * voice Adapter Card (PIC)
+ */
+#define DLT_JUNIPER_VP 183
+
+/*
+ * Arinc 429 frames.
+ * DLT_ requested by Gianluca Varenni <gianluca.varenni@cacetech.com>.
+ * Every frame contains a 32bit A429 label.
+ * More documentation on Arinc 429 can be found at
+ * http://www.condoreng.com/support/downloads/tutorials/ARINCTutorial.pdf
+ */
+#define DLT_A429 184
+
+/*
+ * Arinc 653 Interpartition Communication messages.
+ * DLT_ requested by Gianluca Varenni <gianluca.varenni@cacetech.com>.
+ * Please refer to the A653-1 standard for more information.
+ */
+#define DLT_A653_ICM 185
+
+/*
+ * This used to be "USB packets, beginning with a USB setup header;
+ * requested by Paolo Abeni <paolo.abeni@email.it>."
+ *
+ * However, that header didn't work all that well - it left out some
+ * useful information - and was abandoned in favor of the DLT_USB_LINUX
+ * header.
+ *
+ * This is now used by FreeBSD for its BPF taps for USB; that has its
+ * own headers. So it is written, so it is done.
+ *
+ * For source-code compatibility, we also define DLT_USB to have this
+ * value. We do it numerically so that, if code that includes this
+ * file (directly or indirectly) also includes an OS header that also
+ * defines DLT_USB as 186, we don't get a redefinition warning.
+ * (NetBSD 7 does that.)
+ */
+#define DLT_USB_FREEBSD 186
+#define DLT_USB 186
+
+/*
+ * Bluetooth HCI UART transport layer (part H:4); requested by
+ * Paolo Abeni.
+ */
+#define DLT_BLUETOOTH_HCI_H4 187
+
+/*
+ * IEEE 802.16 MAC Common Part Sublayer; requested by Maria Cruz
+ * <cruz_petagay@bah.com>.
+ */
+#define DLT_IEEE802_16_MAC_CPS 188
+
+/*
+ * USB packets, beginning with a Linux USB header; requested by
+ * Paolo Abeni <paolo.abeni@email.it>.
+ */
+#define DLT_USB_LINUX 189
+
+/*
+ * Controller Area Network (CAN) v. 2.0B packets.
+ * DLT_ requested by Gianluca Varenni <gianluca.varenni@cacetech.com>.
+ * Used to dump CAN packets coming from a CAN Vector board.
+ * More documentation on the CAN v2.0B frames can be found at
+ * http://www.can-cia.org/downloads/?269
+ */
+#define DLT_CAN20B 190
+
+/*
+ * IEEE 802.15.4, with address fields padded, as is done by Linux
+ * drivers; requested by Juergen Schimmer.
+ */
+#define DLT_IEEE802_15_4_LINUX 191
+
+/*
+ * Per Packet Information encapsulated packets.
+ * DLT_ requested by Gianluca Varenni <gianluca.varenni@cacetech.com>.
+ */
+#define DLT_PPI 192
+
+/*
+ * Header for 802.16 MAC Common Part Sublayer plus a radiotap radio header;
+ * requested by Charles Clancy.
+ */
+#define DLT_IEEE802_16_MAC_CPS_RADIO 193
+
+/*
+ * Juniper-private data link type, as per request from
+ * Hannes Gredler <hannes@juniper.net>.
+ * The DLT_ is used for internal communication with a
+ * integrated service module (ISM).
+ */
+#define DLT_JUNIPER_ISM 194
+
+/*
+ * IEEE 802.15.4, exactly as it appears in the spec (no padding, no
+ * nothing); requested by Mikko Saarnivala <mikko.saarnivala@sensinode.com>.
+ * For this one, we expect the FCS to be present at the end of the frame;
+ * if the frame has no FCS, DLT_IEEE802_15_4_NOFCS should be used.
+ */
+#define DLT_IEEE802_15_4 195
+
+/*
+ * Various link-layer types, with a pseudo-header, for SITA
+ * (http://www.sita.aero/); requested by Fulko Hew (fulko.hew@gmail.com).
+ */
+#define DLT_SITA 196
+
+/*
+ * Various link-layer types, with a pseudo-header, for Endace DAG cards;
+ * encapsulates Endace ERF records. Requested by Stephen Donnelly
+ * <stephen@endace.com>.
+ */
+#define DLT_ERF 197
+
+/*
+ * Special header prepended to Ethernet packets when capturing from a
+ * u10 Networks board. Requested by Phil Mulholland
+ * <phil@u10networks.com>.
+ */
+#define DLT_RAIF1 198
+
+/*
+ * IPMB packet for IPMI, beginning with the I2C slave address, followed
+ * by the netFn and LUN, etc.. Requested by Chanthy Toeung
+ * <chanthy.toeung@ca.kontron.com>.
+ */
+#define DLT_IPMB 199
+
+/*
+ * Juniper-private data link type, as per request from
+ * Hannes Gredler <hannes@juniper.net>.
+ * The DLT_ is used for capturing data on a secure tunnel interface.
+ */
+#define DLT_JUNIPER_ST 200
+
+/*
+ * Bluetooth HCI UART transport layer (part H:4), with pseudo-header
+ * that includes direction information; requested by Paolo Abeni.
+ */
+#define DLT_BLUETOOTH_HCI_H4_WITH_PHDR 201
+
+/*
+ * AX.25 packet with a 1-byte KISS header; see
+ *
+ * http://www.ax25.net/kiss.htm
+ *
+ * as per Richard Stearn <richard@rns-stearn.demon.co.uk>.
+ */
+#define DLT_AX25_KISS 202
+
+/*
+ * LAPD packets from an ISDN channel, starting with the address field,
+ * with no pseudo-header.
+ * Requested by Varuna De Silva <varunax@gmail.com>.
+ */
+#define DLT_LAPD 203
+
+/*
+ * Variants of various link-layer headers, with a one-byte direction
+ * pseudo-header prepended - zero means "received by this host",
+ * non-zero (any non-zero value) means "sent by this host" - as per
+ * Will Barker <w.barker@zen.co.uk>.
+ */
+#define DLT_PPP_WITH_DIR 204 /* PPP - don't confuse with DLT_PPP_WITH_DIRECTION */
+#define DLT_C_HDLC_WITH_DIR 205 /* Cisco HDLC */
+#define DLT_FRELAY_WITH_DIR 206 /* Frame Relay */
+#define DLT_LAPB_WITH_DIR 207 /* LAPB */
+
+/*
+ * 208 is reserved for an as-yet-unspecified proprietary link-layer
+ * type, as requested by Will Barker.
+ */
+
+/*
+ * IPMB with a Linux-specific pseudo-header; as requested by Alexey Neyman
+ * <avn@pigeonpoint.com>.
+ */
+#define DLT_IPMB_LINUX 209
+
+/*
+ * FlexRay automotive bus - http://www.flexray.com/ - as requested
+ * by Hannes Kaelber <hannes.kaelber@x2e.de>.
+ */
+#define DLT_FLEXRAY 210
+
+/*
+ * Media Oriented Systems Transport (MOST) bus for multimedia
+ * transport - http://www.mostcooperation.com/ - as requested
+ * by Hannes Kaelber <hannes.kaelber@x2e.de>.
+ */
+#define DLT_MOST 211
+
+/*
+ * Local Interconnect Network (LIN) bus for vehicle networks -
+ * http://www.lin-subbus.org/ - as requested by Hannes Kaelber
+ * <hannes.kaelber@x2e.de>.
+ */
+#define DLT_LIN 212
+
+/*
+ * X2E-private data link type used for serial line capture,
+ * as requested by Hannes Kaelber <hannes.kaelber@x2e.de>.
+ */
+#define DLT_X2E_SERIAL 213
+
+/*
+ * X2E-private data link type used for the Xoraya data logger
+ * family, as requested by Hannes Kaelber <hannes.kaelber@x2e.de>.
+ */
+#define DLT_X2E_XORAYA 214
+
+/*
+ * IEEE 802.15.4, exactly as it appears in the spec (no padding, no
+ * nothing), but with the PHY-level data for non-ASK PHYs (4 octets
+ * of 0 as preamble, one octet of SFD, one octet of frame length+
+ * reserved bit, and then the MAC-layer data, starting with the
+ * frame control field).
+ *
+ * Requested by Max Filippov <jcmvbkbc@gmail.com>.
+ */
+#define DLT_IEEE802_15_4_NONASK_PHY 215
+
+/*
+ * David Gibson <david@gibson.dropbear.id.au> requested this for
+ * captures from the Linux kernel /dev/input/eventN devices. This
+ * is used to communicate keystrokes and mouse movements from the
+ * Linux kernel to display systems, such as Xorg.
+ */
+#define DLT_LINUX_EVDEV 216
+
+/*
+ * GSM Um and Abis interfaces, preceded by a "gsmtap" header.
+ *
+ * Requested by Harald Welte <laforge@gnumonks.org>.
+ */
+#define DLT_GSMTAP_UM 217
+#define DLT_GSMTAP_ABIS 218
+
+/*
+ * MPLS, with an MPLS label as the link-layer header.
+ * Requested by Michele Marchetto <michele@openbsd.org> on behalf
+ * of OpenBSD.
+ */
+#define DLT_MPLS 219
+
+/*
+ * USB packets, beginning with a Linux USB header, with the USB header
+ * padded to 64 bytes; required for memory-mapped access.
+ */
+#define DLT_USB_LINUX_MMAPPED 220
+
+/*
+ * DECT packets, with a pseudo-header; requested by
+ * Matthias Wenzel <tcpdump@mazzoo.de>.
+ */
+#define DLT_DECT 221
+
+/*
+ * From: "Lidwa, Eric (GSFC-582.0)[SGT INC]" <eric.lidwa-1@nasa.gov>
+ * Date: Mon, 11 May 2009 11:18:30 -0500
+ *
+ * DLT_AOS. We need it for AOS Space Data Link Protocol.
+ * I have already written dissectors for but need an OK from
+ * legal before I can submit a patch.
+ *
+ */
+#define DLT_AOS 222
+
+/*
+ * Wireless HART (Highway Addressable Remote Transducer)
+ * From the HART Communication Foundation
+ * IES/PAS 62591
+ *
+ * Requested by Sam Roberts <vieuxtech@gmail.com>.
+ */
+#define DLT_WIHART 223
+
+/*
+ * Fibre Channel FC-2 frames, beginning with a Frame_Header.
+ * Requested by Kahou Lei <kahou82@gmail.com>.
+ */
+#define DLT_FC_2 224
+
+/*
+ * Fibre Channel FC-2 frames, beginning with an encoding of the
+ * SOF, and ending with an encoding of the EOF.
+ *
+ * The encodings represent the frame delimiters as 4-byte sequences
+ * representing the corresponding ordered sets, with K28.5
+ * represented as 0xBC, and the D symbols as the corresponding
+ * byte values; for example, SOFi2, which is K28.5 - D21.5 - D1.2 - D21.2,
+ * is represented as 0xBC 0xB5 0x55 0x55.
+ *
+ * Requested by Kahou Lei <kahou82@gmail.com>.
+ */
+#define DLT_FC_2_WITH_FRAME_DELIMS 225
+
+/*
+ * Solaris ipnet pseudo-header; requested by Darren Reed <Darren.Reed@Sun.COM>.
+ *
+ * The pseudo-header starts with a one-byte version number; for version 2,
+ * the pseudo-header is:
+ *
+ * struct dl_ipnetinfo {
+ * u_int8_t dli_version;
+ * u_int8_t dli_family;
+ * u_int16_t dli_htype;
+ * u_int32_t dli_pktlen;
+ * u_int32_t dli_ifindex;
+ * u_int32_t dli_grifindex;
+ * u_int32_t dli_zsrc;
+ * u_int32_t dli_zdst;
+ * };
+ *
+ * dli_version is 2 for the current version of the pseudo-header.
+ *
+ * dli_family is a Solaris address family value, so it's 2 for IPv4
+ * and 26 for IPv6.
+ *
+ * dli_htype is a "hook type" - 0 for incoming packets, 1 for outgoing
+ * packets, and 2 for packets arriving from another zone on the same
+ * machine.
+ *
+ * dli_pktlen is the length of the packet data following the pseudo-header
+ * (so the captured length minus dli_pktlen is the length of the
+ * pseudo-header, assuming the entire pseudo-header was captured).
+ *
+ * dli_ifindex is the interface index of the interface on which the
+ * packet arrived.
+ *
+ * dli_grifindex is the group interface index number (for IPMP interfaces).
+ *
+ * dli_zsrc is the zone identifier for the source of the packet.
+ *
+ * dli_zdst is the zone identifier for the destination of the packet.
+ *
+ * A zone number of 0 is the global zone; a zone number of 0xffffffff
+ * means that the packet arrived from another host on the network, not
+ * from another zone on the same machine.
+ *
+ * An IPv4 or IPv6 datagram follows the pseudo-header; dli_family indicates
+ * which of those it is.
+ */
+#define DLT_IPNET 226
+
+/*
+ * CAN (Controller Area Network) frames, with a pseudo-header as supplied
+ * by Linux SocketCAN, and with multi-byte numerical fields in that header
+ * in big-endian byte order.
+ *
+ * See Documentation/networking/can.txt in the Linux source.
+ *
+ * Requested by Felix Obenhuber <felix@obenhuber.de>.
+ */
+#define DLT_CAN_SOCKETCAN 227
+
+/*
+ * Raw IPv4/IPv6; different from DLT_RAW in that the DLT_ value specifies
+ * whether it's v4 or v6. Requested by Darren Reed <Darren.Reed@Sun.COM>.
+ */
+#define DLT_IPV4 228
+#define DLT_IPV6 229
+
+/*
+ * IEEE 802.15.4, exactly as it appears in the spec (no padding, no
+ * nothing), and with no FCS at the end of the frame; requested by
+ * Jon Smirl <jonsmirl@gmail.com>.
+ */
+#define DLT_IEEE802_15_4_NOFCS 230
+
+/*
+ * Raw D-Bus:
+ *
+ * http://www.freedesktop.org/wiki/Software/dbus
+ *
+ * messages:
+ *
+ * http://dbus.freedesktop.org/doc/dbus-specification.html#message-protocol-messages
+ *
+ * starting with the endianness flag, followed by the message type, etc.,
+ * but without the authentication handshake before the message sequence:
+ *
+ * http://dbus.freedesktop.org/doc/dbus-specification.html#auth-protocol
+ *
+ * Requested by Martin Vidner <martin@vidner.net>.
+ */
+#define DLT_DBUS 231
+
+/*
+ * Juniper-private data link type, as per request from
+ * Hannes Gredler <hannes@juniper.net>.
+ */
+#define DLT_JUNIPER_VS 232
+#define DLT_JUNIPER_SRX_E2E 233
+#define DLT_JUNIPER_FIBRECHANNEL 234
+
+/*
+ * DVB-CI (DVB Common Interface for communication between a PC Card
+ * module and a DVB receiver). See
+ *
+ * http://www.kaiser.cx/pcap-dvbci.html
+ *
+ * for the specification.
+ *
+ * Requested by Martin Kaiser <martin@kaiser.cx>.
+ */
+#define DLT_DVB_CI 235
+
+/*
+ * Variant of 3GPP TS 27.010 multiplexing protocol (similar to, but
+ * *not* the same as, 27.010). Requested by Hans-Christoph Schemmel
+ * <hans-christoph.schemmel@cinterion.com>.
+ */
+#define DLT_MUX27010 236
+
+/*
+ * STANAG 5066 D_PDUs. Requested by M. Baris Demiray
+ * <barisdemiray@gmail.com>.
+ */
+#define DLT_STANAG_5066_D_PDU 237
+
+/*
+ * Juniper-private data link type, as per request from
+ * Hannes Gredler <hannes@juniper.net>.
+ */
+#define DLT_JUNIPER_ATM_CEMIC 238
+
+/*
+ * NetFilter LOG messages
+ * (payload of netlink NFNL_SUBSYS_ULOG/NFULNL_MSG_PACKET packets)
+ *
+ * Requested by Jakub Zawadzki <darkjames-ws@darkjames.pl>
+ */
+#define DLT_NFLOG 239
+
+/*
+ * Hilscher Gesellschaft fuer Systemautomation mbH link-layer type
+ * for Ethernet packets with a 4-byte pseudo-header and always
+ * with the payload including the FCS, as supplied by their
+ * netANALYZER hardware and software.
+ *
+ * Requested by Holger P. Frommer <HPfrommer@hilscher.com>
+ */
+#define DLT_NETANALYZER 240
+
+/*
+ * Hilscher Gesellschaft fuer Systemautomation mbH link-layer type
+ * for Ethernet packets with a 4-byte pseudo-header and FCS and
+ * with the Ethernet header preceded by 7 bytes of preamble and
+ * 1 byte of SFD, as supplied by their netANALYZER hardware and
+ * software.
+ *
+ * Requested by Holger P. Frommer <HPfrommer@hilscher.com>
+ */
+#define DLT_NETANALYZER_TRANSPARENT 241
+
+/*
+ * IP-over-InfiniBand, as specified by RFC 4391.
+ *
+ * Requested by Petr Sumbera <petr.sumbera@oracle.com>.
+ */
+#define DLT_IPOIB 242
+
+/*
+ * 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
+
+/*
+ * 246 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 246.
+ */
+#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
+
+/*
+ * DLT type for the netlink protocol (nlmon devices).
+ */
+#define DLT_NETLINK 253
+
+/*
+ * Bluetooth Linux Monitor headers for the BlueZ stack.
+ */
+#define DLT_BLUETOOTH_LINUX_MONITOR 254
+
+/*
+ * Bluetooth Basic Rate/Enhanced Data Rate baseband packets, as
+ * captured by Ubertooth.
+ */
+#define DLT_BLUETOOTH_BREDR_BB 255
+
+/*
+ * Bluetooth Low Energy link layer packets, as captured by Ubertooth.
+ */
+#define DLT_BLUETOOTH_LE_LL_WITH_PHDR 256
+
+/*
+ * PROFIBUS data link layer.
+ */
+#define DLT_PROFIBUS_DL 257
+
+/*
+ * Apple's DLT_PKTAP headers.
+ *
+ * Sadly, the folks at Apple either had no clue that the DLT_USERn values
+ * are for internal use within an organization and partners only, and
+ * didn't know that the right way to get a link-layer header type is to
+ * ask tcpdump.org for one, or knew and didn't care, so they just
+ * used DLT_USER2, which causes problems for everything except for
+ * their version of tcpdump.
+ *
+ * So I'll just give them one; hopefully this will show up in a
+ * libpcap release in time for them to get this into 10.10 Big Sur
+ * or whatever Mavericks' successor is called. LINKTYPE_PKTAP
+ * will be 258 *even on OS X*; that is *intentional*, so that
+ * PKTAP files look the same on *all* OSes (different OSes can have
+ * different numerical values for a given DLT_, but *MUST NOT* have
+ * different values for what goes in a file, as files can be moved
+ * between OSes!).
+ *
+ * When capturing, on a system with a Darwin-based OS, on a device
+ * that returns 149 (DLT_USER2 and Apple's DLT_PKTAP) with this
+ * version of libpcap, the DLT_ value for the pcap_t will be DLT_PKTAP,
+ * and that will continue to be DLT_USER2 on Darwin-based OSes. That way,
+ * binary compatibility with Mavericks is preserved for programs using
+ * this version of libpcap. This does mean that if you were using
+ * DLT_USER2 for some capture device on OS X, you can't do so with
+ * this version of libpcap, just as you can't with Apple's libpcap -
+ * on OS X, they define DLT_PKTAP to be DLT_USER2, so programs won't
+ * be able to distinguish between PKTAP and whatever you were using
+ * DLT_USER2 for.
+ *
+ * If the program saves the capture to a file using this version of
+ * libpcap's pcap_dump code, the LINKTYPE_ value in the file will be
+ * LINKTYPE_PKTAP, which will be 258, even on Darwin-based OSes.
+ * That way, the file will *not* be a DLT_USER2 file. That means
+ * that the latest version of tcpdump, when built with this version
+ * of libpcap, and sufficiently recent versions of Wireshark will
+ * be able to read those files and interpret them correctly; however,
+ * Apple's version of tcpdump in OS X 10.9 won't be able to handle
+ * them. (Hopefully, Apple will pick up this version of libpcap,
+ * and the corresponding version of tcpdump, so that tcpdump will
+ * be able to handle the old LINKTYPE_USER2 captures *and* the new
+ * LINKTYPE_PKTAP captures.)
+ */
+#ifdef __APPLE__
+#define DLT_PKTAP DLT_USER2
+#else
+#define DLT_PKTAP 258
+#endif
+
+/*
+ * Ethernet packets preceded by a header giving the last 6 octets
+ * of the preamble specified by 802.3-2012 Clause 65, section
+ * 65.1.3.2 "Transmit".
+ */
+#define DLT_EPON 259
+
+/*
+ * IPMI trace packets, as specified by Table 3-20 "Trace Data Block Format"
+ * in the PICMG HPM.2 specification.
+ */
+#define DLT_IPMI_HPM_2 260
+
+/*
+ * per Joshua Wright <jwright@hasborg.com>, formats for Zwave captures.
+ */
+#define DLT_ZWAVE_R1_R2 261
+#define DLT_ZWAVE_R3 262
+
+/*
+ * per Steve Karg <skarg@users.sourceforge.net>, formats for Wattstopper
+ * Digital Lighting Management room bus serial protocol captures.
+ */
+#define DLT_WATTSTOPPER_DLM 263
+
+/*
+ * ISO 14443 contactless smart card messages.
+ */
+#define DLT_ISO_14443 264
+
+/*
+ * Radio data system (RDS) groups. IEC 62106.
+ * Per Jonathan Brucker <jonathan.brucke@gmail.com>.
+ */
+#define DLT_RDS 265
+
+/*
+ * In case the code that includes this file (directly or indirectly)
+ * has also included OS files that happen to define DLT_MATCHING_MAX,
+ * with a different value (perhaps because that OS hasn't picked up
+ * the latest version of our DLT definitions), we undefine the
+ * previous value of DLT_MATCHING_MAX.
+ */
+#ifdef DLT_MATCHING_MAX
+#undef DLT_MATCHING_MAX
+#endif
+#define DLT_MATCHING_MAX 265 /* 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.
+ */
+#define DLT_CLASS(x) ((x) & 0x03ff0000)
+
+/*
+ * NetBSD-specific generic "raw" link type. The class value indicates
+ * that this is the generic raw type, and the lower 16 bits are the
+ * address family we're dealing with. Those values are NetBSD-specific;
+ * do not assume that they correspond to AF_ values for your operating
+ * system.
+ */
+#define DLT_CLASS_NETBSD_RAWAF 0x02240000
+#define DLT_NETBSD_RAWAF(af) (DLT_CLASS_NETBSD_RAWAF | (af))
+#define DLT_NETBSD_RAWAF_AF(x) ((x) & 0x0000ffff)
+#define DLT_IS_NETBSD_RAWAF(x) (DLT_CLASS(x) == DLT_CLASS_NETBSD_RAWAF)
+
+#endif /* !_NET_DLT_H_ */
diff --git a/usr.sbin/ipfwpcap/Makefile b/usr.sbin/ipfwpcap/Makefile
index 2fde8900a16c..3911945f7af6 100644
--- a/usr.sbin/ipfwpcap/Makefile
+++ b/usr.sbin/ipfwpcap/Makefile
@@ -7,6 +7,7 @@
PROG= ipfwpcap
LIBADD= pcap
+CFLAGS+=-I${.CURDIR}/../../contrib/libpcap
MAN= ipfwpcap.8