Imported Upstream version 1.9.1 49/215849/1 upstream upstream/1.9.1
authorCheoleun Moon <chleun.moon@samsung.com>
Thu, 17 Oct 2019 10:20:32 +0000 (19:20 +0900)
committerCheoleun Moon <chleun.moon@samsung.com>
Thu, 17 Oct 2019 10:22:32 +0000 (19:22 +0900)
Change-Id: I8ccc371679c730299ebe8068ed5af0ae033c4f7d
Signed-off-by: Cheoleun Moon <chleun.moon@samsung.com>
296 files changed:
CHANGES
CMakeLists.txt [new file with mode: 0644]
CONTRIBUTING.md [new file with mode: 0644]
CREDITS
INSTALL.md [moved from INSTALL.txt with 78% similarity]
LICENSE
Makefile-devel-adds
Makefile.in
README.Win32 [deleted file]
README.md [moved from README with 60% similarity]
SUNOS4/nit_if.o.sparc [deleted file]
SUNOS4/nit_if.o.sun3 [deleted file]
SUNOS4/nit_if.o.sun4c.4.0.3c [deleted file]
TODO
VERSION
Win32/Include/Gnuc.h [deleted file]
Win32/Include/addrinfo.h [deleted file]
Win32/Include/arpa/nameser.h [deleted file]
Win32/Include/bittypes.h [deleted file]
Win32/Include/cdecl_ext.h [deleted file]
Win32/Include/ip6_misc.h [deleted file]
Win32/Include/net/if.h [deleted file]
Win32/Include/net/netdb.h [deleted file]
Win32/Include/net/paths.h [deleted file]
Win32/Include/sockstorage.h [deleted file]
Win32/Prj/libpcap.dsp [deleted file]
Win32/Prj/libpcap.dsw [deleted file]
Win32/Prj/wpcap.sln [new file with mode: 0644]
Win32/Prj/wpcap.vcxproj [new file with mode: 0644]
Win32/Prj/wpcap.vcxproj.filters [new file with mode: 0644]
Win32/Src/gai_strerror.c [deleted file]
Win32/Src/getaddrinfo.c [deleted file]
Win32/Src/getnetbynm.c [deleted file]
Win32/Src/getnetent.c [deleted file]
Win32/Src/getservent.c [deleted file]
Win32/Src/inet_net.c [deleted file]
aclocal.m4
bpf_dump.c
bpf_filter.c [moved from bpf/net/bpf_filter.c with 69% similarity]
bpf_image.c
chmod_bpf
cmake/Modules/FindDAG.cmake [new file with mode: 0644]
cmake/Modules/FindFseeko.cmake [new file with mode: 0644]
cmake/Modules/FindLFS.cmake [new file with mode: 0644]
cmake/Modules/FindPacket.cmake [new file with mode: 0644]
cmake/Modules/FindSNF.cmake [new file with mode: 0644]
cmake/Modules/FindTC.cmake [new file with mode: 0644]
cmake/have_siocglifconf.c [new file with mode: 0644]
cmake_uninstall.cmake.in [new file with mode: 0644]
cmakeconfig.h.in [new file with mode: 0644]
config.guess
config.h.in
config.sub
configure
configure.ac [new file with mode: 0644]
configure.in [deleted file]
diag-control.h [new file with mode: 0644]
dlpisubs.c
doc/DLT_ALLOCATE_HOWTO.md [new file with mode: 0644]
doc/README.Win32.md [new file with mode: 0644]
doc/README.aix [moved from README.aix with 99% similarity]
doc/README.dag [moved from README.dag with 97% similarity]
doc/README.hpux [moved from README.hpux with 96% similarity]
doc/README.linux.md [moved from README.linux with 97% similarity]
doc/README.macos [moved from README.macosx with 86% similarity]
doc/README.septel [moved from README.septel with 95% similarity]
doc/README.sita [moved from README.sita with 94% similarity]
doc/README.tru64 [moved from README.tru64 with 96% similarity]
etherent.c
ethertype.h
extract.h [new file with mode: 0644]
fad-getad.c
fad-gifc.c
fad-glifc.c
fad-sita.c [deleted file]
fad-win32.c [deleted file]
fmtutils.c [new file with mode: 0644]
fmtutils.h [moved from Win32/Src/inet_aton.c with 56% similarity]
ftmacros.h [new file with mode: 0644]
gencode.c
gencode.h
grammar.y
inet.c [deleted file]
install-sh
lbl/os-aix7.h [new file with mode: 0644]
lbl/os-osf4.h
lbl/os-osf5.h
lbl/os-solaris2.h
lbl/os-sunos4.h
lbl/os-ultrix4.h
libpcap.pc.in [new file with mode: 0644]
missing/asprintf.c [new file with mode: 0644]
missing/getopt.c [moved from Win32/Src/getopt.c with 93% similarity]
missing/getopt.h [new file with mode: 0644]
missing/snprintf.c
missing/strlcat.c [new file with mode: 0644]
missing/strlcpy.c [new file with mode: 0644]
missing/strtok_r.c [new file with mode: 0644]
missing/win_asprintf.c [new file with mode: 0644]
missing/win_snprintf.c [new file with mode: 0644]
mkdep
msdos/bin2c.c
msdos/common.dj [deleted file]
msdos/makefile
msdos/makefile.dj
msdos/makefile.wc
msdos/ndis2.c [deleted file]
msdos/ndis2.h [deleted file]
msdos/ndis_0.asm [deleted file]
msdos/pkt_rx0.asm
msdos/pkt_rx1.s
msdos/pktdrvr.c
msdos/pktdrvr.h
msdos/readme.dos
nametoaddr.c
nametoaddr.h [moved from Win32/Src/inet_pton.c with 54% similarity]
nomkdep [new file with mode: 0755]
optimize.c
optimize.h [new file with mode: 0644]
packaging/pcap.spec.in [deleted file]
pcap-bpf.c
pcap-bpf.h
pcap-bt-linux.c
pcap-bt-linux.h
pcap-bt-monitor-linux.c
pcap-bt-monitor-linux.h
pcap-can-linux.c [deleted file]
pcap-canusb-linux.c [deleted file]
pcap-common.c
pcap-common.h
pcap-config.1
pcap-config.in
pcap-dag.c
pcap-dag.h
pcap-dbus.c
pcap-dbus.h
pcap-dll.rc [new file with mode: 0644]
pcap-dlpi.c
pcap-dos.c
pcap-dos.h
pcap-enet.c
pcap-filter.manmisc.in
pcap-int.h
pcap-libdlpi.c
pcap-linktype.manmisc.in
pcap-linux.c
pcap-netfilter-linux.c
pcap-netfilter-linux.h
pcap-netmap.c [new file with mode: 0644]
pcap-netmap.h [new file with mode: 0644]
pcap-new.c [new file with mode: 0644]
pcap-nit.c
pcap-npf.c [new file with mode: 0644]
pcap-null.c
pcap-pf.c
pcap-rdmasniff.c [new file with mode: 0644]
pcap-rdmasniff.h [new file with mode: 0644]
pcap-rpcap-int.h [new file with mode: 0644]
pcap-rpcap.c [new file with mode: 0644]
pcap-rpcap.h [new file with mode: 0644]
pcap-savefile.manfile.in
pcap-septel.c
pcap-septel.h
pcap-sita.c
pcap-sita.html
pcap-snf.c
pcap-snf.h
pcap-snit.c
pcap-snoop.c
pcap-tc.c [new file with mode: 0644]
pcap-tc.h [new file with mode: 0644]
pcap-tstamp.manmisc.in
pcap-types.h [moved from pcap-stdinc.h with 62% similarity]
pcap-usb-linux.c
pcap-usb-linux.h
pcap-win32.c [deleted file]
pcap.3pcap.in
pcap.c
pcap/bluetooth.h
pcap/bpf.h
pcap/can_socketcan.h [moved from Win32/Src/ffs.c with 69% similarity]
pcap/compiler-tests.h [new file with mode: 0644]
pcap/dlt.h [new file with mode: 0644]
pcap/funcattrs.h [new file with mode: 0644]
pcap/namedb.h
pcap/nflog.h
pcap/pcap-inttypes.h [new file with mode: 0644]
pcap/pcap.h
pcap/sll.h
pcap/socket.h [new file with mode: 0644]
pcap/usb.h
pcap/vlan.h
pcap_activate.3pcap
pcap_breakloop.3pcap
pcap_can_set_rfmon.3pcap
pcap_close.3pcap
pcap_compile.3pcap.in
pcap_create.3pcap
pcap_datalink.3pcap.in
pcap_datalink_name_to_val.3pcap
pcap_datalink_val_to_name.3pcap
pcap_dump.3pcap
pcap_dump_close.3pcap
pcap_dump_file.3pcap
pcap_dump_flush.3pcap
pcap_dump_ftell.3pcap
pcap_dump_open.3pcap.in
pcap_file.3pcap
pcap_fileno.3pcap
pcap_findalldevs.3pcap
pcap_freecode.3pcap
pcap_get_required_select_timeout.3pcap [new file with mode: 0644]
pcap_get_selectable_fd.3pcap
pcap_get_tstamp_precision.3pcap.in
pcap_geterr.3pcap
pcap_inject.3pcap
pcap_is_swapped.3pcap
pcap_lib_version.3pcap
pcap_list_datalinks.3pcap.in
pcap_list_tstamp_types.3pcap.in
pcap_lookupdev.3pcap
pcap_lookupnet.3pcap
pcap_loop.3pcap
pcap_major_version.3pcap
pcap_next_ex.3pcap
pcap_offline_filter.3pcap
pcap_open_dead.3pcap.in
pcap_open_live.3pcap
pcap_open_offline.3pcap.in
pcap_set_buffer_size.3pcap
pcap_set_datalink.3pcap
pcap_set_immediate_mode.3pcap.in [moved from pcap_set_immediate_mode.3pcap with 54% similarity]
pcap_set_promisc.3pcap
pcap_set_protocol_linux.3pcap [new file with mode: 0644]
pcap_set_rfmon.3pcap
pcap_set_snaplen.3pcap
pcap_set_timeout.3pcap
pcap_set_tstamp_precision.3pcap.in
pcap_set_tstamp_type.3pcap.in
pcap_setdirection.3pcap
pcap_setfilter.3pcap
pcap_setnonblock.3pcap
pcap_snapshot.3pcap
pcap_stats.3pcap
pcap_statustostr.3pcap
pcap_strerror.3pcap
pcap_tstamp_type_name_to_val.3pcap
pcap_tstamp_type_val_to_name.3pcap
portability.h [new file with mode: 0644]
rpcap-protocol.c [new file with mode: 0644]
rpcap-protocol.h [new file with mode: 0644]
rpcapd/CMakeLists.txt [new file with mode: 0644]
rpcapd/Makefile.in [new file with mode: 0644]
rpcapd/config_params.h [moved from Win32/Include/inetprivate.h with 55% similarity]
rpcapd/daemon.c [new file with mode: 0644]
rpcapd/daemon.h [new file with mode: 0644]
rpcapd/fileconf.c [new file with mode: 0644]
rpcapd/fileconf.h [moved from pcap-canusb-linux.h with 77% similarity]
rpcapd/log.c [new file with mode: 0644]
rpcapd/log.h [new file with mode: 0644]
rpcapd/org.tcpdump.rpcapd.plist [new file with mode: 0644]
rpcapd/rpcapd-config.manfile.in [new file with mode: 0644]
rpcapd/rpcapd.c [new file with mode: 0644]
rpcapd/rpcapd.h [new file with mode: 0644]
rpcapd/rpcapd.inetd.conf [new file with mode: 0644]
rpcapd/rpcapd.manadmin.in [new file with mode: 0644]
rpcapd/rpcapd.rc [new file with mode: 0644]
rpcapd/rpcapd.socket [new file with mode: 0644]
rpcapd/rpcapd.xinetd.conf [new file with mode: 0644]
rpcapd/rpcapd@.service [new file with mode: 0644]
rpcapd/win32-svc.c [new file with mode: 0644]
rpcapd/win32-svc.h [moved from pcap-can-linux.h with 78% similarity]
runlex.sh [deleted file]
savefile.c
scanner.l
sf-pcap.c
sf-pcap.h
sf-pcapng.c [moved from sf-pcap-ng.c with 58% similarity]
sf-pcapng.h [moved from sf-pcap-ng.h with 86% similarity]
sockutils.c [new file with mode: 0644]
sockutils.h [new file with mode: 0644]
testprogs/CMakeLists.txt [new file with mode: 0644]
testprogs/Makefile.in [new file with mode: 0644]
testprogs/can_set_rfmon_test.c [new file with mode: 0644]
testprogs/capturetest.c [moved from tests/capturetest.c with 89% similarity]
testprogs/filtertest.c [moved from tests/filtertest.c with 71% similarity]
testprogs/findalldevstest.c [new file with mode: 0644]
testprogs/opentest.c [moved from tests/opentest.c with 86% similarity]
testprogs/reactivatetest.c [moved from tests/reactivatetest.c with 93% similarity]
testprogs/selpolltest.c [moved from tests/selpolltest.c with 57% similarity]
testprogs/threadsignaltest.c [new file with mode: 0644]
testprogs/unix.h [new file with mode: 0644]
testprogs/valgrindtest.c [moved from tests/valgrindtest.c with 86% similarity]
tests/findalldevstest.c [deleted file]
tests/shb-option-too-long.pcapng [new file with mode: 0644]
varattrs.h [moved from fad-null.c with 73% similarity]

diff --git a/CHANGES b/CHANGES
index b42e404..89e739c 100644 (file)
--- a/CHANGES
+++ b/CHANGES
+Sunday, July 22, 2018
+  Summary for 1.9.1 libpcap release
+    Mention pcap_get_required_select_timeout() in the main pcap man page
+    Fix pcap-usb-linux.c build on systems with musl
+    Fix assorted man page and other documentation issues
+    Plug assorted memory leaks
+    Documentation changes to use https:
+    Changes to how time stamp calculations are done
+    Lots of tweaks to make newer compilers happier and warning-free and
+        to fix instances of C undefined behavior
+    Warn if AC_PROG_CC_C99 can't enable C99 support
+    Rename pcap_set_protocol() to  pcap_set_protocol_linux().
+    Align pcap_t private data on an 8-byte boundary.
+    Fix various error messages
+    Use 64-bit clean API in dag_findalldevs()
+    Fix cleaning up after some errors
+    Work around some ethtool ioctl bugs in newer Linux kernels (GitHub
+        issue #689)
+    Add backwards compatibility sections to some man pages (GitHub issue
+        #745)
+    Fix autotool configuration on AIX and macOS
+    Don't export bpf_filter_with_aux_data() or struct bpf_aux_data;
+        they're internal-only and subject to change
+    Fix pcapng block size checking
+    On macOS, don't build rpcapd or test programs any fatter than they
+        need to be
+    Fix reading of capture statistics for Linux USB
+    Fix packet size values for Linux USB packets (GitHub issue #808)
+    Check only VID in VLAN test in filterss (GitHub issue #461)
+    Fix pcap_list_datalinks on 802.11 devices on macOS
+    Fix overflows with very large snapshot length in pcap file
+    Improve parsing of rpcapd configuration file (GitHub issue #767)
+    Handle systems without strlcpy() or strlcat() better
+    Fix crashes and other errors with invalid filter expressions
+    Fix use of uninitialized file descriptor in remote capture
+    Fix some CMake issues
+    Fix some divide-by-zero issues with the filter compiler
+    Work around a GNU libc bug in pcap_nametonetaddr()
+    Add support for DLT_LINUX_SLL2
+    Fix handling of the packet-count argument for Myricom SNF devices
+    Fix --disable-rdma in configure script (GitHub issue #782)
+    Fix compilation of TurboCap support (GitHub issue #764)
+    Constify first argument to pcap_findalldevs_ex()
+    Fix a number of issues when running rpcapd as an inetd-style daemon
+    Fix CMake issues with D-Bus libraries
+    In rpcapd, clean up termination of a capture session
+    Redo remote capture protocol negotiation
+    In rpcapd, report the same error for "invalid user name" and
+        "invalid password", to make brute-forcing harder
+    For remote captures, add an error code for "the server requires TLS"
+    Fix pcap_dump_fopen() on Windows to avoid clashes between
+        {Win,N}Pcap and application C runtimes
+    Fix exporting of functions from Windows DLLs (GitHub issue #810)
+    Fix building as part of Npcap
+    Allow rpcapd to rebind more rapidly
+    Fix building shared libpcap library on midipix (midipix.org)
+    Fix hack to detect UTF-16LE adapter names on Windows not to go past
+        the end of the string
+    Fix handling of "wireless WAN" (mobile phone network modems) on
+        Windows with WinPcap/Npcap (GitHub issue #824)
+    Have pcap_dump_open_append() create the dump file if it doesn't
+        exists (GitHub issue #247)
+    Fix the maxmum snapshot length for DLT_USBPCAP
+    Use -fPIC when building for 64-bit SPARC on Linux (GitHub issue #837)
+    Fix CMake 64-bit library installation directory on some Linux
+        distributions
+    Boost the TPACKET_V3 timeout to the maximum if a timeout of 0 was
+        specified
+    Five CVE-2019-15161, CVE-2019-15162, CVE-2019-15163, CVE-2019-15164, CVE-2019-15165
+    Fixes for CVE-2018-16301, errors in pcapng reading.
+    PCAPNG reader applies some sanity checks before doing malloc().
+
+Sunday, June 24, 2018, by mcr@sandelman.ca
+  Summary for 1.9.0 libpcap release
+    Added testing system to libpcap, independent of tcpdump
+    Changes to how pcap_t is activated
+    Adding support for Large stream buffers on Endace DAG cards
+    Changes to BSD 3-clause license to 2-clause licence
+    Additions to TCP header parsing, per RFC3168
+    Add CMake build process (extensive number of changes)
+    Assign a value for OpenBSD DLT_OPENFLOW.
+    Support setting non-blocking mode before activating.
+    Extensive build support for Windows VS2010 and MINGW (many many changes, over many months)
+    Added RPCAPD support when --enable-remote (default no)
+    Add the rpcap daemon source and build instructions.
+    Put back the greasy "save the capture filter string so we can tweak it"
+        hack, that keeps libpcap from capturing rpcap traffic.
+    Fixes for captures on MacOS, utun0
+    fixes so that non-AF_INET addresses, are not ==AF_INET6 addresses.
+    Add a linktype for IBM SDLC frames containing SNA PDUs.
+    pcap_compile() in 1.8.0 and later is newly thread-safe.
+    bound snaplen for linux tpacket_v2 to ~64k
+    Make VLAN filter handle both metadata and inline tags
+    D-Bus captures can now be up to 128MB in size
+    Added LORATAP DLT value
+    Added DLT_VSOCK for http://qemu-project.org/Features/VirtioVsock
+    probe_devices() fixes not to overrun buffer for name of device
+    Add linux-specific pcap_set_protocol_linux() to allow specifying a specific capture protocol.
+    RDMA sniffing support for pcap
+    Add Nordic Semiconductor Bluetooth LE sniffer link-layer header type.
+    fixes for reading /etc/ethers
+    Make it possible to build on Windows without packet.dll.
+    Add tests for large file support on UN*X.
+    Solaris fixes to work with 2.8.6
+    configuration test now looks for header files, not capture devices present
+    Fix to work with Berkeley YACC.
+    fixes for DragonBSD compilation of pcap-netmap.c
+    Clean up the ether_hostton() stuff.
+    Add an option to disable Linux memory-mapped capture support.
+    Add DAG API support checks.
+    Add Septel, Myricom SNF, and Riverbed TurboCap checks.
+    Add checks for Linux USB, Linux Bluetooth, D-Bus, and RDMA sniffing support.
+    Add a check for hardware time stamping on Linux.
+    Don't bother supporting pre-2005 Visual Studio.
+    Increased minimum autoconf version requirement to 2.64
+    Add DLT value 273 for XRA-31 sniffer
+    Clean up handing of signal interrupts in pcap_read_nocb_remote().
+    Use the XPG 4.2 versions of the networking APIs in Solaris.
+    Fix, and better explain, the "IPv6 means IPv6, not IPv4" option setting.
+    Explicitly warn that negative packet buffer timeouts should not be used.
+    rpcapd: Add support inetd-likes, including xinetd.conf, and systemd units
+    Rename DLT_IEEE802_15_4 to DLT_IEEE802_15_4_WITHFCS.
+    Add DISPLAYPORT AUX link type
+    Remove the sunos4 kernel modules and all references to them.
+    Add more interface flags to pcap_findalldevs().
+  Summary for 1.9.0 libpcap release (to 2017-01-25 by guy@alum.mit.edu)
+    Man page improvements
+    Fix Linux cooked mode userspace filtering (GitHub pull request #429)
+    Fix compilation if IPv6 support not enabled
+    Fix some Linux memory-mapped capture buffer size issues
+    Don't fail if kernel filter can't be set on Linux (GitHub issue
+      #549)
+    Improve sorting of interfaces for pcap_findalldevs()
+    Don't list Linux usbmon devices if usbmon module isn't loaded
+    Report PCAP_ERROR_PERM_DENIED if no permission to open Linux usbmon
+      devices
+    Fix DLT_ type for Solaris IPNET devices
+    Always return an error message for errors finding DAG or Myricom
+      devices
+    If possible, don't require that a device be openable when
+      enumerating them for pcap_findalldevs()
+    Don't put incompletely-initialized addresses in the address list for
+    When finding Myricom devices, update description for regular
+      interfaces that are Myricom devices and handle SNF_FLAGS=0x2(port
+      aggregation enabled)
+    Fix compilation error in DAG support
+    Fix issues with CMake configuration
+    Add support for stream buffers larger than 2GB on newer DAG cards
+    Remove support for building against DAG versions without STREAMS
+      support (before dag-3.0.0 2007)
+
+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 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
+           capture.
+       Fix timestamps when reading pcap-ng files on big-endian
+           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/CMakeLists.txt b/CMakeLists.txt
new file mode 100644 (file)
index 0000000..55b93f1
--- /dev/null
@@ -0,0 +1,2464 @@
+cmake_minimum_required(VERSION 2.8.6)
+
+#
+# Apple doesn't build with an install_name starting with @rpath, and
+# neither do we with autotools; don't do so with CMake, either, and
+# suppress warnings about that.
+#
+if(POLICY CMP0042)
+    cmake_policy(SET CMP0042 OLD)
+endif()
+
+set(CMAKE_MODULE_PATH ${CMAKE_CURRENT_SOURCE_DIR}/cmake/Modules)
+
+project(pcap)
+
+#
+# Try to enable as many C99 features as we can.
+# At minimum, we want C++/C99-style // comments.
+#
+# Newer versions of compilers might default to supporting C99, but older
+# versions may require a special flag.
+#
+# Prior to CMake 3.1, setting CMAKE_C_STANDARD will not have any effect,
+# so, unless and until we require CMake 3.1 or later, we have to do it
+# ourselves on pre-3.1 CMake, so we just do it ourselves on all versions
+# of CMake.
+#
+# Note: with CMake 3.1 through 3.5, the only compilers for which CMake
+# handles CMAKE_C_STANDARD are GCC and Clang.  3.6 adds support only
+# for Intel C; 3.9 adds support for PGI C, Sun C, and IBM XL C, and
+# 3.10 adds support for Cray C and IAR C, but no version of CMake has
+# support for HP C.  Therefore, even if we use CMAKE_C_STANDARD with
+# compilers for which CMake supports it, we may still have to do it
+# ourselves on other compilers.
+#
+# See the CMake documentation for the CMAKE_<LANG>_COMPILER_ID variables
+# for a list of compiler IDs.
+#
+# We don't worry about MSVC; it doesn't have such a flag - either it
+# doesn't support the C99 features we need at all, or it supports them
+# regardless of the compiler flag.
+#
+# XXX - this just tests whether the option works and adds it if it does.
+# We don't test whether it's necessary in order to get the C99 features
+# that we use; if we ever have a user who tries to compile with a compiler
+# that can't be made to support those features, we can add a test to make
+# sure we actually *have* C99 support.
+#
+include(CheckCCompilerFlag)
+macro(check_and_add_compiler_option _option)
+    message(STATUS "Checking C compiler flag ${_option}")
+    string(REPLACE "=" "-" _temp_option_variable ${_option})
+    string(REGEX REPLACE "^-" "" _option_variable ${_temp_option_variable})
+    check_c_compiler_flag("${_option}" ${_option_variable})
+    if(${${_option_variable}})
+        set(C_ADDITIONAL_FLAGS "${C_ADDITIONAL_FLAGS} ${_option}")
+    endif()
+endmacro()
+
+set(C_ADDITIONAL_FLAGS "")
+if(CMAKE_C_COMPILER_ID MATCHES "GNU" OR
+   CMAKE_C_COMPILER_ID MATCHES "Clang")
+    check_and_add_compiler_option("-std=gnu99")
+elseif(CMAKE_C_COMPILER_ID MATCHES "XL")
+    #
+    # We want support for extensions picked up for GNU C compatibility,
+    # so we use -qlanglvl=extc99.
+    #
+    check_and_add_compiler_option("-qlanglvl=extc99")
+elseif(CMAKE_C_COMPILER_ID MATCHES "HP")
+    check_and_add_compiler_option("-AC99")
+elseif(CMAKE_C_COMPILER_ID MATCHES "Sun")
+    check_and_add_compiler_option("-xc99")
+elseif(CMAKE_C_COMPILER_ID MATCHES "Intel")
+    check_and_add_compiler_option("-c99")
+endif()
+
+#
+# Build all runtimes in the top-level binary directory; that way,
+# on Windows, the executables will be in the same directory as
+# the DLLs, so the system will find pcap.dll when any of the
+# executables are run.
+#
+set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/run)
+
+###################################################################
+#   Parameters
+###################################################################
+
+if(WIN32)
+    #
+    # On Windows, allow the library name to be overridden, for the
+    # benefit of projects that combine libpcap with their own
+    # kernel-mode code to support capturing.
+    #
+    set(LIBRARY_NAME pcap CACHE STRING "Library name")
+else()
+    #
+    # On UN*X, it's always been libpcap.
+    #
+    set(LIBRARY_NAME pcap)
+endif()
+
+option(INET6 "Enable IPv6" ON)
+if(WIN32)
+    option(USE_STATIC_RT "Use static Runtime" ON)
+endif(WIN32)
+option(BUILD_SHARED_LIBS "Build shared libraries" ON)
+if(WIN32)
+    set(PACKET_DLL_DIR "" CACHE PATH "Path to directory with include and lib subdirectories for packet.dll")
+endif(WIN32)
+
+# To pacify those who hate the protochain instruction
+option(NO_PROTOCHAIN "Disable protochain instruction" OFF)
+
+#
+# Start out with the capture mechanism type unspecified; the user
+# can explicitly specify it and, if they don't, we'll pick an
+# appropriate one.
+#
+set(PCAP_TYPE "" CACHE STRING "Packet capture type")
+
+#
+# Default to having remote capture support on Windows and, for now, to
+# not having it on UN*X.
+#
+if(WIN32)
+    option(ENABLE_REMOTE "Enable remote capture" ON)
+else()
+    option(ENABLE_REMOTE "Enable remote capture" OFF)
+endif(WIN32)
+
+if(CMAKE_SYSTEM_NAME STREQUAL "Linux")
+    option(PCAP_SUPPORT_PACKET_RING "Enable Linux packet ring support" ON)
+    option(BUILD_WITH_LIBNL "Build with libnl" ON)
+endif()
+
+#
+# Additional capture modules.
+#
+option(DISABLE_USB "Disable USB sniffing support" OFF)
+option(DISABLE_BLUETOOTH "Disable Bluetooth sniffing support" OFF)
+option(DISABLE_NETMAP "Disable netmap support" OFF)
+#
+# We don't support D-Bus sniffing on macOS; see
+#
+# https://bugs.freedesktop.org/show_bug.cgi?id=74029
+#
+if(APPLE)
+    option(DISABLE_DBUS "Disable D-Bus sniffing support" ON)
+else(APPLE)
+    option(DISABLE_DBUS "Disable D-Bus sniffing support" OFF)
+endif(APPLE)
+option(DISABLE_RDMA "Disable RDMA sniffing support" OFF)
+
+option(DISABLE_DAG "Disable Endace DAG card support" OFF)
+
+option(DISABLE_SEPTEL "Disable Septel card support" OFF)
+set(SEPTEL_ROOT "${CMAKE_CURRENT_SOURCE_DIR}/../septel" CACHE PATH "Path to directory with include and lib subdirectories for Septel API")
+
+option(DISABLE_SNF "Disable Myricom SNF support" OFF)
+
+option(DISABLE_TC "Disable Riverbed TurboCap support" OFF)
+
+#
+# Debugging options.
+#
+option(BDEBUG "Build optimizer debugging code" OFF)
+option(YYDEBUG "Build parser debugging code" OFF)
+
+###################################################################
+#   Versioning
+###################################################################
+
+# Get, parse, format and set pcap's version string from [pcap_root]/VERSION
+# for later use.
+
+# Get MAJOR, MINOR, PATCH & SUFFIX
+file(STRINGS ${pcap_SOURCE_DIR}/VERSION
+    PACKAGE_VERSION
+    LIMIT_COUNT 1 # Read only the first line
+)
+
+# Get "just" MAJOR
+string(REGEX MATCH "^([0-9]+)" PACKAGE_VERSION_MAJOR "${PACKAGE_VERSION}")
+
+# Get MAJOR, MINOR & PATCH
+string(REGEX MATCH "^([0-9]+.)?([0-9]+.)?([0-9]+)" PACKAGE_VERSION_NOSUFFIX "${PACKAGE_VERSION}")
+
+if(WIN32)
+    # Convert PCAP_VERSION_NOSUFFIX to Windows preferred version format
+    string(REPLACE "." "," PACKAGE_VERSION_PREDLL ${PACKAGE_VERSION_NOSUFFIX})
+
+    # Append NANO (used for Windows internal versioning) to PCAP_VERSION_PREDLL
+    # 0 means unused.
+    set(PACKAGE_VERSION_DLL ${PACKAGE_VERSION_PREDLL},0)
+endif(WIN32)
+
+set(PACKAGE_NAME "${LIBRARY_NAME}")
+set(PACKAGE_STRING "${LIBRARY_NAME} ${PACKAGE_VERSION}")
+
+######################################
+# Project settings
+######################################
+
+add_definitions(-DHAVE_CONFIG_H)
+
+include_directories(
+    ${CMAKE_CURRENT_BINARY_DIR}
+    ${pcap_SOURCE_DIR}
+)
+
+include(CheckFunctionExists)
+include(CMakePushCheckState)
+include(CheckSymbolExists)
+
+if(WIN32)
+
+    if(IS_DIRECTORY ${CMAKE_HOME_DIRECTORY}/../../Common)
+        include_directories(${CMAKE_HOME_DIRECTORY}/../../Common)
+    endif(IS_DIRECTORY ${CMAKE_HOME_DIRECTORY}/../../Common)
+
+    find_package(Packet)
+    if(PACKET_FOUND)
+        set(HAVE_PACKET32 TRUE)
+        include_directories(${PACKET_INCLUDE_DIRS})
+        #
+        # Check whether we have the NPcap PacketIsLoopbackAdapter()
+        # function.
+        #
+        cmake_push_check_state()
+        set(CMAKE_REQUIRED_LIBRARIES ${PACKET_LIBRARIES})
+        check_function_exists(PacketIsLoopbackAdapter HAVE_PACKET_IS_LOOPBACK_ADAPTER)
+        cmake_pop_check_state()
+    endif(PACKET_FOUND)
+
+    message(STATUS "checking for Npcap's version.h")
+    check_symbol_exists(WINPCAP_PRODUCT_NAME "../../version.h" HAVE_VERSION_H)
+    if(HAVE_VERSION_H)
+           message(STATUS "HAVE version.h")
+    else(HAVE_VERSION_H)
+           message(STATUS "MISSING version.h")
+    endif(HAVE_VERSION_H)
+
+endif(WIN32)
+
+if(MSVC)
+    add_definitions(-D__STDC__)
+    add_definitions(-D_CRT_SECURE_NO_WARNINGS)
+endif(MSVC)
+
+if(USE_STATIC_RT)
+    message(STATUS "Use STATIC runtime")
+        if(MSVC)
+            foreach(RT_FLAG
+                CMAKE_C_FLAGS CMAKE_C_FLAGS_DEBUG CMAKE_C_FLAGS_RELEASE
+                CMAKE_C_FLAGS_MINSIZEREL CMAKE_C_FLAGS_RELWITHDEBINFO
+                CMAKE_CXX_FLAGS CMAKE_CXX_FLAGS_DEBUG CMAKE_CXX_FLAGS_RELEASE
+                CMAKE_CXX_FLAGS_MINSIZEREL CMAKE_CXX_FLAGS_RELWITHDEBINFO)
+                string(REGEX REPLACE "/MD" "/MT" ${RT_FLAG} "${${RT_FLAG}}")
+            endforeach(RT_FLAG)
+        elseif(MINGW)
+            set(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} -static-libgcc")
+        endif()
+else (USE_STATIC_RT)
+    message(STATUS "Use DYNAMIC runtime")
+endif(USE_STATIC_RT)
+
+###################################################################
+#   Detect available platform features
+###################################################################
+
+include(CheckIncludeFile)
+include(CheckIncludeFiles)
+include(CheckStructHasMember)
+include(CheckTypeSize)
+
+#
+# Tests are a bit expensive with Visual Studio on Windows, so, on
+# Windows, we skip tests for UN*X-only headers and functions.
+#
+
+#
+# Header files.
+#
+check_include_file(inttypes.h HAVE_INTTYPES_H)
+check_include_file(stdint.h HAVE_STDINT_H)
+check_include_file(unistd.h HAVE_UNISTD_H)
+if(NOT HAVE_UNISTD_H)
+    add_definitions(-DYY_NO_UNISTD_H)
+endif(NOT HAVE_UNISTD_H)
+check_include_file(bitypes.h HAVE_SYS_BITYPES_H)
+if(NOT WIN32)
+    check_include_file(sys/ioccom.h HAVE_SYS_IOCCOM_H)
+    check_include_file(sys/sockio.h HAVE_SYS_SOCKIO_H)
+    check_include_file(sys/select.h HAVE_SYS_SELECT_H)
+endif(NOT WIN32)
+check_include_file(limits.h HAVE_LIMITS_H)
+if(NOT WIN32)
+    check_include_file(netpacket/packet.h HAVE_NETPACKET_PACKET_H)
+    check_include_files("sys/types.h;sys/socket.h;net/if.h;net/pfvar.h" HAVE_NET_PFVAR_H)
+    if(HAVE_NET_PFVAR_H)
+        #
+        # Check for various PF actions.
+        #
+        check_c_source_compiles(
+"#include <sys/types.h>
+#include <sys/socket.h>
+#include <net/if.h>
+#include <net/pfvar.h>
+
+int
+main(void)
+{
+    return PF_NAT+PF_NONAT+PF_BINAT+PF_NOBINAT+PF_RDR+PF_NORDR;
+}
+"
+            HAVE_PF_NAT_THROUGH_PF_NORDR)
+    endif(HAVE_NET_PFVAR_H)
+    check_include_file(netinet/if_ether.h HAVE_NETINET_IF_ETHER_H)
+    if(CMAKE_SYSTEM_NAME STREQUAL "Linux")
+        check_include_file(linux/sockios.h HAVE_LINUX_SOCKIOS_H)
+        #
+        # linux/if_bonding.h requires sys/socket.h.
+        #
+        check_include_files("sys/socket.h;linux/if_bonding.h" HAVE_LINUX_IF_BONDING_H)
+    endif()
+endif(NOT WIN32)
+
+#
+# Functions.
+#
+check_function_exists(strerror HAVE_STRERROR)
+check_function_exists(strerror_r HAVE_STRERROR_R)
+if(HAVE_STRERROR_R)
+    #
+    # We have strerror_r; if we define _GNU_SOURCE, is it a
+    # POSIX-compliant strerror_r() or a GNU strerror_r()?
+    #
+    check_c_source_compiles(
+"#define _GNU_SOURCE
+#include <string.h>
+
+/* Define it GNU-style; that will cause an error if it's not GNU-style */
+extern char *strerror_r(int, char *, size_t);
+
+int
+main(void)
+{
+       return 0;
+}
+"
+            HAVE_GNU_STRERROR_R)
+    if(NOT HAVE_GNU_STRERROR_R)
+        set(HAVE_POSIX_STRERROR_R YES)
+    endif(NOT HAVE_GNU_STRERROR_R)
+else(HAVE_STRERROR_R)
+    #
+    # We don't have strerror_r; do we have strerror_s?
+    #
+    check_function_exists(strerror_s HAVE_STRERROR_S)
+endif(HAVE_STRERROR_R)
+check_function_exists(strlcpy HAVE_STRLCPY)
+check_function_exists(strlcat HAVE_STRLCAT)
+check_function_exists(snprintf HAVE_SNPRINTF)
+check_function_exists(vsnprintf HAVE_VSNPRINTF)
+check_function_exists(asprintf HAVE_ASPRINTF)
+check_function_exists(vasprintf HAVE_VASPRINTF)
+check_function_exists(strtok_r HAVE_STRTOK_R)
+if(NOT WIN32)
+    check_function_exists(vsyslog HAVE_VSYSLOG)
+endif()
+
+#
+# These tests are for network applications that need socket functions
+# and getaddrinfo()/getnameinfo()-ish functions.  We now require
+# getaddrinfo() and getnameinfo().  On UN*X systems, we also prefer
+# versions of recvmsg() that conform to the Single UNIX Specification,
+# so that we can check whether a datagram received with recvmsg() was
+# truncated when received due to the buffer being too small.
+#
+# On Windows, getaddrinfo() is in the ws2_32 library.
+
+# On most UN*X systems, they're available in the system library.
+#
+# Under Solaris, we need to link with libsocket and libnsl to get
+# getaddrinfo() and getnameinfo() and, if we have libxnet, we need to
+# link with libxnet before libsocket to get a version of recvmsg()
+# that conforms to the Single UNIX Specification.
+#
+# We use getaddrinfo() because we want a portable thread-safe way
+# of getting information for a host name or port; there exist _r
+# versions of gethostbyname() and getservbyname() on some platforms,
+# but not on all platforms.
+#
+# NOTE: if you hand check_library_exists as its last argument a variable
+# that's been set, it skips the test, so we need different variables.
+#
+set(PCAP_LINK_LIBRARIES "")
+include(CheckLibraryExists)
+if(WIN32)
+    #
+    # We need winsock2.h and ws2tcpip.h.
+    #
+    cmake_push_check_state()
+    set(CMAKE_REQUIRED_LIBRARIES ws2_32)
+    check_symbol_exists(getaddrinfo "winsock2.h;ws2tcpip.h" LIBWS2_32_HAS_GETADDRINFO)
+    cmake_pop_check_state()
+    if(LIBWS2_32_HAS_GETADDRINFO)
+        set(PCAP_LINK_LIBRARIES ws2_32 ${PCAP_LINK_LIBRARIES})
+    else(LIBWS2_32_HAS_GETADDRINFO)
+        message(FATAL_ERROR "getaddrinfo is required, but wasn't found")
+    endif(LIBWS2_32_HAS_GETADDRINFO)
+else(WIN32)
+    #
+    # UN*X.  First try the system libraries, then try the libraries
+    # for Solaris and possibly other systems that picked up the
+    # System V library split.
+    #
+    check_function_exists(getaddrinfo STDLIBS_HAVE_GETADDRINFO)
+    if(NOT STDLIBS_HAVE_GETADDRINFO)
+        #
+        # Not found in the standard system libraries.
+        # Try libsocket, which requires libnsl.
+        #
+        cmake_push_check_state()
+        set(CMAKE_REQUIRED_LIBRARIES nsl)
+        check_library_exists(socket getaddrinfo "" LIBSOCKET_HAS_GETADDRINFO)
+        cmake_pop_check_state()
+        if(LIBSOCKET_HAS_GETADDRINFO)
+            #
+            # OK, we found it in libsocket.
+            #
+            set(PCAP_LINK_LIBRARIES socket nsl ${PCAP_LINK_LIBRARIES})
+        else(LIBSOCKET_HAS_GETADDRINFO)
+            #
+            # We didn't find it.
+            #
+            message(FATAL_ERROR "getaddrinfo is required, but wasn't found")
+        endif(LIBSOCKET_HAS_GETADDRINFO)
+
+        #
+        # OK, do we have recvmsg() in libxnet?
+        # We also link with libsocket and libnsl.
+        #
+        cmake_push_check_state()
+        set(CMAKE_REQUIRED_LIBRARIES socket nsl)
+        check_library_exists(xnet recvmsg "" LIBXNET_HAS_RECVMSG)
+        cmake_pop_check_state()
+        if(LIBXNET_HAS_RECVMSG)
+            #
+            # Yes - link with it as well.
+            #
+            set(PCAP_LINK_LIBRARIES xnet ${PCAP_LINK_LIBRARIES})
+        endif(LIBXNET_HAS_RECVMSG)
+    endif(NOT STDLIBS_HAVE_GETADDRINFO)
+
+    # DLPI needs putmsg under HPUX so test for -lstr while we're at it
+    check_function_exists(putmsg STDLIBS_HAVE_PUTMSG)
+    if(NOT STDLIBS_HAVE_PUTMSG)
+        check_library_exists(str putmsg "" LIBSTR_HAS_PUTMSG)
+        if(LIBSTR_HAS_PUTMSG)
+            set(PCAP_LINK_LIBRARIES str ${PCAP_LINK_LIBRARIES})
+        endif(LIBSTR_HAS_PUTMSG)
+    endif(NOT STDLIBS_HAVE_PUTMSG)
+endif(WIN32)
+
+#
+# Check for reentrant versions of getnetbyname_r(), as provided by
+# Linux (glibc), Solaris/IRIX, and AIX (with three different APIs!).
+# If we don't find one, we just use getnetbyname(), which uses
+# thread-specific data on many platforms, but doesn't use it on
+# NetBSD or OpenBSD, and may not use it on older versions of other
+# platforms.
+#
+# Only do the check if we have a declaration of getnetbyname_r();
+# without it, we can't check which API it has.  (We assume that
+# if there's a declaration, it has a prototype, so that the API
+# can be checked.)
+#
+cmake_push_check_state()
+set(CMAKE_REQUIRED_LIBRARIES ${PCAP_LINK_LIBRARIES})
+check_symbol_exists(getnetbyname_r netdb.h NETDB_H_DECLARES_GETNETBYNAME_R)
+if(NETDB_H_DECLARES_GETNETBYNAME_R)
+    check_c_source_compiles(
+"#include <netdb.h>
+
+int
+main(void)
+{
+    struct netent netent_buf;
+    char buf[1024];
+    struct netent *resultp;
+    int h_errnoval;
+
+    return getnetbyname_r((const char *)0, &netent_buf, buf, sizeof buf, &resultp, &h_errnoval);
+}
+"
+        HAVE_LINUX_GETNETBYNAME_R)
+    if(NOT HAVE_LINUX_GETNETBYNAME_R)
+        check_c_source_compiles(
+"#include <netdb.h>
+
+int
+main(void)
+{
+    struct netent netent_buf;
+    char buf[1024];
+
+    return getnetbyname_r((const char *)0, &netent_buf, buf, (int)sizeof buf) != NULL;
+}
+"
+            HAVE_SOLARIS_IRIX_GETNETBYNAME_R)
+        if(NOT HAVE_SOLARIS_IRIX_GETNETBYNAME_R)
+            check_c_source_compiles(
+"#include <netdb.h>
+
+int
+main(void)
+{
+    struct netent netent_buf;
+    struct netent_data net_data;
+
+    return getnetbyname_r((const char *)0, &netent_buf, &net_data);
+}
+"
+                HAVE_AIX_GETNETBYNAME_R)
+        endif(NOT HAVE_SOLARIS_IRIX_GETNETBYNAME_R)
+    endif(NOT HAVE_LINUX_GETNETBYNAME_R)
+endif(NETDB_H_DECLARES_GETNETBYNAME_R)
+cmake_pop_check_state()
+
+#
+# Check for reentrant versions of getprotobyname_r(), as provided by
+# Linux (glibc), Solaris/IRIX, and AIX (with three different APIs!).
+# If we don't find one, we just use getprotobyname(), which uses
+# thread-specific data on many platforms, but doesn't use it on
+# NetBSD or OpenBSD, and may not use it on older versions of other
+# platforms.
+#
+# Only do the check if we have a declaration of getprotobyname_r();
+# without it, we can't check which API it has.  (We assume that
+# if there's a declaration, it has a prototype, so that the API
+# can be checked.)
+#
+cmake_push_check_state()
+set(CMAKE_REQUIRED_LIBRARIES ${PCAP_LINK_LIBRARIES})
+check_symbol_exists(getprotobyname_r netdb.h NETDB_H_DECLARES_GETPROTOBYNAME_R)
+if(NETDB_H_DECLARES_GETPROTOBYNAME_R)
+    check_c_source_compiles(
+"#include <netdb.h>
+
+int
+main(void)
+{
+    struct protoent protoent_buf;
+    char buf[1024];
+    struct protoent *resultp;
+
+    return getprotobyname_r((const char *)0, &protoent_buf, buf, sizeof buf, &resultp);
+}
+"
+        HAVE_LINUX_GETPROTOBYNAME_R)
+    if(NOT HAVE_LINUX_GETPROTOBYNAME_R)
+        check_c_source_compiles(
+"#include <netdb.h>
+
+int
+main(void)
+{
+    struct protoent protoent_buf;
+    char buf[1024];
+
+    return getprotobyname_r((const char *)0, &protoent_buf, buf, (int)sizeof buf) != NULL;
+}
+"
+            HAVE_SOLARIS_IRIX_GETPROTOBYNAME_R)
+        if(NOT HAVE_SOLARIS_IRIX_GETPROTOBYNAME_R)
+            check_c_source_compiles(
+"#include <netdb.h>
+
+int
+main(void)
+{
+    struct protoent protoent_buf;
+    struct protoent_data proto_data;
+
+    return getprotobyname_r((const char *)0, &protoent_buf, &proto_data);
+}
+"
+                HAVE_AIX_GETPROTOBYNAME_R)
+        endif(NOT HAVE_SOLARIS_IRIX_GETPROTOBYNAME_R)
+    endif(NOT HAVE_LINUX_GETPROTOBYNAME_R)
+endif(NETDB_H_DECLARES_GETPROTOBYNAME_R)
+cmake_pop_check_state()
+
+#
+# Data types.
+#
+# XXX - there's no check_type() macro that's like check_type_size()
+# except that it only checks for the existence of the structure type,
+# so we use check_type_size() and ignore the size.
+#
+cmake_push_check_state()
+if(WIN32)
+    set(CMAKE_EXTRA_INCLUDE_FILES winsock2.h)
+else(WIN32)
+    set(CMAKE_EXTRA_INCLUDE_FILES unistd.h sys/socket.h)
+endif(WIN32)
+check_type_size("struct sockaddr_storage" STRUCT_SOCKADDR_STORAGE)
+check_type_size("socklen_t" SOCKLEN_T)
+cmake_pop_check_state()
+
+#
+# Structure fields.
+#
+if(WIN32)
+    check_struct_has_member("struct sockaddr" sa_len winsock2.h HAVE_STRUCT_SOCKADDR_SA_LEN)
+else(WIN32)
+    check_struct_has_member("struct sockaddr" sa_len sys/socket.h HAVE_STRUCT_SOCKADDR_SA_LEN)
+endif(WIN32)
+
+#
+# Do we have ffs(), and is it declared in <strings.h>?
+#
+check_function_exists(ffs HAVE_FFS)
+if(HAVE_FFS)
+    #
+    # OK, we have ffs().  Is it declared in <strings.h>?
+    #
+    # This test fails if we don't have <strings.h> or if we do
+    # but it doesn't declare ffs().
+    #
+    check_symbol_exists(ffs strings.h STRINGS_H_DECLARES_FFS)
+endif()
+
+#
+# This requires the libraries that we require, as ether_hostton might be
+# in one of those libraries.  That means we have to do this after
+# we check for those libraries.
+#
+# You are in a twisty little maze of UN*Xes, all different.
+# Some might not have ether_hostton().
+# Some might have it and declare it in <net/ethernet.h>.
+# Some might have it and declare it in <netinet/ether.h>
+# Some might have it and declare it in <sys/ethernet.h>.
+# Some might have it and declare it in <arpa/inet.h>.
+# Some might have it and declare it in <netinet/if_ether.h>.
+# Some might have it and not declare it in any header file.
+#
+# Before you is a C compiler.
+#
+cmake_push_check_state()
+set(CMAKE_REQUIRED_LIBRARIES ${PCAP_LINK_LIBRARIES})
+check_function_exists(ether_hostton HAVE_ETHER_HOSTTON)
+if(HAVE_ETHER_HOSTTON)
+    #
+    # OK, we have ether_hostton().  Is it declared in <net/ethernet.h>?
+    #
+    # This test fails if we don't have <net/ethernet.h> or if we do
+    # but it doesn't declare ether_hostton().
+    #
+    check_symbol_exists(ether_hostton net/ethernet.h NET_ETHERNET_H_DECLARES_ETHER_HOSTTON)
+    if(NET_ETHERNET_H_DECLARES_ETHER_HOSTTON)
+        #
+        # Yes - we have it declared.
+        #
+        set(HAVE_DECL_ETHER_HOSTTON TRUE)
+    endif()
+    #
+    # Did that succeed?
+    #
+    if(NOT HAVE_DECL_ETHER_HOSTTON)
+        #
+        # No - how about <netinet/ether.h>, as on Linux?
+        #
+        # This test fails if we don't have <netinet/ether.h>
+        # or if we do but it doesn't declare ether_hostton().
+        #
+        check_symbol_exists(ether_hostton netinet/ether.h NETINET_ETHER_H_DECLARES_ETHER_HOSTTON)
+        if(NETINET_ETHER_H_DECLARES_ETHER_HOSTTON)
+            #
+            # Yes - we have it declared.
+            #
+            set(HAVE_DECL_ETHER_HOSTTON TRUE)
+        endif()
+    endif()
+    #
+    # Did that succeed?
+    #
+    if(NOT HAVE_DECL_ETHER_HOSTTON)
+        #
+        # No - how about <sys/ethernet.h>, as on Solaris 10 and later?
+        #
+        # This test fails if we don't have <sys/ethernet.h>
+        # or if we do but it doesn't declare ether_hostton().
+        #
+        check_symbol_exists(ether_hostton sys/ethernet.h SYS_ETHERNET_H_DECLARES_ETHER_HOSTTON)
+        if(SYS_ETHERNET_H_DECLARES_ETHER_HOSTTON)
+            #
+            # Yes - we have it declared.
+            #
+            set(HAVE_DECL_ETHER_HOSTTON TRUE)
+        endif()
+    endif()
+    #
+    # Did that succeed?
+    #
+    if(NOT HAVE_DECL_ETHER_HOSTTON)
+        #
+        # No, how about <arpa/inet.h>, as on AIX?
+        #
+        # This test fails if we don't have <arpa/inet.h>
+        # or if we do but it doesn't declare ether_hostton().
+        #
+        check_symbol_exists(ether_hostton arpa/inet.h ARPA_INET_H_DECLARES_ETHER_HOSTTON)
+        if(ARPA_INET_H_DECLARES_ETHER_HOSTTON)
+            #
+            # Yes - we have it declared.
+            #
+            set(HAVE_DECL_ETHER_HOSTTON TRUE)
+        endif()
+    endif()
+    #
+    # Did that succeed?
+    #
+    if(NOT HAVE_DECL_ETHER_HOSTTON)
+        #
+        # No, how about <netinet/if_ether.h>?
+        # On some platforms, it requires <net/if.h> and
+        # <netinet/in.h>, and we always include it with
+        # both of them, so test it with both of them.
+        #
+        # This test fails if we don't have <netinet/if_ether.h>
+        # and the headers we include before it, or if we do but
+        # <netinet/if_ether.h> doesn't declare ether_hostton().
+        #
+        check_symbol_exists(ether_hostton "sys/types.h;sys/socket.h;net/if.h;netinet/in.h;netinet/if_ether.h" NETINET_IF_ETHER_H_DECLARES_ETHER_HOSTTON)
+        if(NETINET_IF_ETHER_H_DECLARES_ETHER_HOSTTON)
+            #
+            # Yes - we have it declared.
+            #
+            set(HAVE_DECL_ETHER_HOSTTON TRUE)
+        endif()
+    endif()
+    #
+    # After all that, is ether_hostton() declared?
+    #
+    if(NOT HAVE_DECL_ETHER_HOSTTON)
+        #
+        # No, we'll have to declare it ourselves.
+        # Do we have "struct ether_addr" if we include <netinet/if_ether.h>?
+        #
+        # XXX - there's no check_type() macro that's like check_type_size()
+        # except that it only checks for the existence of the structure type,
+        # so we use check_type_size() and ignore the size.
+        #
+        cmake_push_check_state()
+        set(CMAKE_EXTRA_INCLUDE_FILES sys/types.h sys/socket.h net/if.h netinet/in.h netinet/if_ether.h)
+        check_type_size("struct ether_addr" STRUCT_ETHER_ADDR)
+        cmake_pop_check_state()
+    endif()
+endif()
+cmake_pop_check_state()
+
+#
+# Large file support on UN*X, a/k/a LFS.
+#
+if(NOT WIN32)
+  include(FindLFS)
+  if(LFS_FOUND)
+    #
+    # Add the required #defines.
+    #
+    add_definitions(${LFS_DEFINITIONS})
+  endif()
+
+  #
+  # Check for fseeko as well.
+  #
+  include(FindFseeko)
+  if(FSEEKO_FOUND)
+    set(HAVE_FSEEKO ON)
+
+    #
+    # Add the required #defines.
+    #
+    add_definitions(${FSEEKO_DEFINITIONS})
+  endif()
+endif()
+
+if(INET6)
+    message(STATUS "Support IPv6")
+endif(INET6)
+
+#
+# Pthreads.
+# We might need them, because some libraries we use might use them,
+# but we don't necessarily need them.
+# That's only on UN*X; on Windows, if they use threads, we assume
+# they're native Windows threads.
+#
+if(NOT WIN32)
+  set(CMAKE_THREAD_PREFER_PTHREAD ON)
+  find_package(Threads)
+  if(NOT CMAKE_USE_PTHREADS_INIT)
+    #
+    # If it's not pthreads, we won't use it; we use it for libraries
+    # that require it.
+    #
+    set(CMAKE_THREAD_LIBS_INIT "")
+  endif(NOT CMAKE_USE_PTHREADS_INIT)
+endif(NOT WIN32)
+
+######################################
+# Input files
+######################################
+
+set(PROJECT_SOURCE_LIST_C
+    bpf_dump.c
+    bpf_filter.c
+    bpf_image.c
+    etherent.c
+    fmtutils.c
+    gencode.c
+    nametoaddr.c
+    optimize.c
+    pcap-common.c
+    pcap.c
+    savefile.c
+    sf-pcapng.c
+    sf-pcap.c
+)
+
+if(WIN32)
+    #
+    # For now, we assume we don't have snprintf() or that it's not one
+    # that behaves enough like C99's snprintf() for our purposes (i.e.,
+    # it doesn't null-terminate the string if it truncates it to fit in
+    # the buffer), so we have to provide our own (a wrapper around
+    # _snprintf() that null-terminates the buffer).
+    #
+    # We also assume we don't have asprintf(), and provide an implementation
+    # that uses _vscprintf() to determine how big the string needs to be.
+    #
+    set(PROJECT_SOURCE_LIST_C ${PROJECT_SOURCE_LIST_C}
+        missing/win_snprintf.c missing/win_asprintf.c)
+else()
+    #
+    # Either:
+    #
+    #  we have snprintf() and vsnprintf(), and have asprintf() and
+    #  vasprintf();
+    #
+    #  we have snprintf() and vsnprintf(), but don't have asprintf()
+    #  or vasprintf();
+    #
+    #  we have neither snprintf() nor vsnprintf(), and don't have
+    #  asprintf() or vasprintf(), either.
+    #
+    # We assume that if we have asprintf() we have vasprintf(), as well
+    # as snprintf() and vsnprintf(), and that if we have snprintf() we
+    # have vsnprintf().
+    #
+    # For the first case, we don't need any replacement routines.
+    # For the second case, we need replacement asprintf()/vasprintf()
+    # routines.
+    # For the third case, we need replacement snprintf()/vsnprintf() and
+    # asprintf()/vasprintf() routines.
+    #
+    if(NOT HAVE_SNPRINTF)
+        #
+        # We assume we have none of them; missing/snprintf.c supplies
+        # all of them.
+        #
+        set(PROJECT_SOURCE_LIST_C ${PROJECT_SOURCE_LIST_C} missing/snprintf.c)
+    elif(NOT HAVE_ASPRINTF)
+        #
+        # We assume we have snprintf()/vsnprintf() but lack
+        # asprintf()/vasprintf(); missing/asprintf.c supplies
+        # the latter (using vsnprintf()).
+        #
+        set(PROJECT_SOURCE_LIST_C ${PROJECT_SOURCE_LIST_C} missing/asprintf.c)
+    endif()
+    if(NOT HAVE_STRLCAT)
+        set(PROJECT_SOURCE_LIST_C ${PROJECT_SOURCE_LIST_C} missing/strlcat.c)
+    endif(NOT HAVE_STRLCAT)
+    if(NOT HAVE_STRLCPY)
+        set(PROJECT_SOURCE_LIST_C ${PROJECT_SOURCE_LIST_C} missing/strlcpy.c)
+    endif(NOT HAVE_STRLCPY)
+    if(NOT HAVE_STRTOK_R)
+        set(PROJECT_SOURCE_LIST_C ${PROJECT_SOURCE_LIST_C} missing/strtok_r.c)
+    endif(NOT HAVE_STRTOK_R)
+endif(WIN32)
+
+#
+# Determine the main pcap-XXX.c file to use, and the libraries with
+# which we need to link libpcap, if any.
+#
+if(WIN32)
+    #
+    # Windows.
+    #
+    # Has the user explicitly specified a capture type?
+    #
+    if(PCAP_TYPE STREQUAL "")
+        #
+        # The user didn't explicitly specify a capture mechanism.
+        # Check whether we have packet.dll.
+        #
+        if(HAVE_PACKET32)
+            #
+            # We have packet.dll.
+            # Set the capture type to NPF.
+            #
+            set(PCAP_TYPE npf)
+        else()
+            #
+            # We don't have any capture type we know about, so just use
+            # the null capture type, and only support reading (and writing)
+            # capture files.
+            #
+            set(PCAP_TYPE null)
+        endif()
+    endif()
+else()
+    #
+    # UN*X.
+    #
+    # Figure out what type of packet capture mechanism we have, and
+    # what libraries we'd need to link libpcap with, if any.
+    #
+
+    #
+    # Has the user explicitly specified a capture type?
+    #
+    if(PCAP_TYPE STREQUAL "")
+        #
+        # Check for a bunch of headers for various packet capture mechanisms.
+        #
+        check_include_files("sys/types.h;net/bpf.h" HAVE_NET_BPF_H)
+        if(HAVE_NET_BPF_H)
+            #
+            # Does it define BIOCSETIF?
+            # I.e., is it a header for an LBL/BSD-style capture
+            # mechanism, or is it just a header for a BPF filter
+            # engine?  Some versions of Arch Linux, for example,
+            # have a net/bpf.h that doesn't define BIOCSETIF;
+            # as it's a Linux, it should use packet sockets,
+            # instead.
+            #
+            # We need:
+            #
+            #  sys/types.h, because FreeBSD 10's net/bpf.h
+            #  requires that various BSD-style integer types
+            #  be defined;
+            #
+            #  sys/time.h, because AIX 5.2 and 5.3's net/bpf.h
+            #  doesn't include it but does use struct timeval
+            #  in ioctl definitions;
+            #
+            #  sys/ioctl.h and, if we have it, sys/ioccom.h,
+            #  because net/bpf.h defines ioctls;
+            #
+            #  net/if.h, because it defines some structures
+            #  used in ioctls defined by net/bpf.h;
+            #
+            #  sys/socket.h, because OpenBSD 5.9's net/bpf.h
+            #  defines some structure fields as being
+            #  struct sockaddrs;
+            #
+            # and net/bpf.h doesn't necessarily include all
+            # of those headers itself.
+            #
+            if(HAVE_SYS_IOCCOM_H)
+                check_symbol_exists(BIOCSETIF "sys/types.h;sys/time.h;sys/ioctl.h;sys/socket.h;sys/ioccom.h;net/bpf.h;net/if.h" BPF_H_DEFINES_BIOCSETIF)
+            else(HAVE_SYS_IOCCOM_H)
+                check_symbol_exists(BIOCSETIF "sys/types.h;sys/time.h;sys/ioctl.h;sys/socket.h;net/bpf.h;net/if.h" BPF_H_DEFINES_BIOCSETIF)
+            endif(HAVE_SYS_IOCCOM_H)
+        endif(HAVE_NET_BPF_H)
+        check_include_file(net/pfilt.h HAVE_NET_PFILT_H)
+        check_include_file(net/enet.h HAVE_NET_ENET_H)
+        check_include_file(net/nit.h HAVE_NET_NIT_H)
+        check_include_file(sys/net/nit.h HAVE_SYS_NET_NIT_H)
+        check_include_file(linux/socket.h HAVE_LINUX_SOCKET_H)
+        check_include_file(net/raw.h HAVE_NET_RAW_H)
+        check_include_file(sys/dlpi.h HAVE_SYS_DLPI_H)
+
+        if(BPF_H_DEFINES_BIOCSETIF)
+            #
+            # BPF.
+            # Check this before DLPI, so that we pick BPF on
+            # Solaris 11 and later.
+            #
+            set(PCAP_TYPE bpf)
+        elseif(HAVE_LINUX_SOCKET_H)
+            #
+            # No prizes for guessing this one.
+            #
+            set(PCAP_TYPE linux)
+        elseif(HAVE_NET_PFILT_H)
+            #
+            # DEC OSF/1, Digital UNIX, Tru64 UNIX
+            #
+            set(PCAP_TYPE pf)
+        elseif(HAVE_NET_ENET_H)
+            #
+            # Stanford Enetfilter.
+            #
+            set(PCAP_TYPE enet)
+        elseif(HAVE_NET_NIT_H)
+            #
+            # SunOS 4.x STREAMS NIT.
+            #
+            set(PCAP_TYPE snit)
+        elseif(HAVE_SYS_NET_NIT_H)
+            #
+            # Pre-SunOS 4.x non-STREAMS NIT.
+            #
+            set(PCAP_TYPE nit)
+        elseif(HAVE_NET_RAW_H)
+            #
+            # IRIX snoop.
+            #
+            set(PCAP_TYPE snoop)
+        elseif(HAVE_SYS_DLPI_H)
+            #
+            # DLPI on pre-Solaris 11 SunOS 5, HP-UX, possibly others.
+            #
+            set(PCAP_TYPE dlpi)
+        else()
+            #
+            # Nothing we support.
+            #
+            set(PCAP_TYPE null)
+        endif()
+    endif()
+endif(WIN32)
+message(STATUS "Packet capture mechanism type: ${PCAP_TYPE}")
+
+#
+# Do capture-mechanism-dependent tests.
+#
+if(WIN32)
+    if(PCAP_TYPE STREQUAL "npf")
+        #
+        # Link with packet.dll before WinSock2.
+        #
+        set(PCAP_LINK_LIBRARIES ${PACKET_LIBRARIES} ${PCAP_LINK_LIBRARIES})
+    elseif(PCAP_TYPE STREQUAL "null")
+    else()
+        message(ERROR "${PCAP_TYPE} is not a valid pcap type")
+    endif()
+else(WIN32)
+    if(PCAP_TYPE STREQUAL "dlpi")
+        #
+        # Needed for common functions used by pcap-[dlpi,libdlpi].c
+        #
+        set(PROJECT_SOURCE_LIST_C ${PROJECT_SOURCE_LIST_C} dlpisubs.c)
+
+        #
+        # Checks for some header files.
+        #
+        check_include_file(sys/bufmod.h HAVE_SYS_BUFMOD_H)
+        check_include_file(sys/dlpi_ext.h HAVE_SYS_DLPI_EXT_H)
+
+        #
+        # 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.
+        # 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].
+        # Also, due to the bug above applications that link to libpcap with
+        # libdlpi will have to add "-L/lib" option to "configure".
+        #
+        cmake_push_check_state()
+        set(CMAKE_REQUIRED_FLAGS "-L/lib")
+        set(CMAKE_REQUIRED_LIBRARIES dlpi)
+        check_function_exists(dlpi_walk HAVE_LIBDLPI)
+        cmake_pop_check_state()
+        if(HAVE_LIBDLPI)
+            #
+            # XXX - add -L/lib
+            #
+            set(PCAP_LINK_LIBRARIES ${PCAP_LINK_LIBRARIES} dlpi)
+            set(PCAP_TYPE libdlpi)
+        endif()
+
+        #
+        # This check is for Solaris with DLPI support for passive modes.
+        # See dlpi(7P) for more details.
+        #
+        # XXX - there's no check_type() macro that's like check_type_size()
+        # except that it only checks for the existence of the structure type,
+        # so we use check_type_size() and ignore the size.
+        #
+        cmake_push_check_state()
+        set(CMAKE_EXTRA_INCLUDE_FILES sys/types.h sys/dlpi.h)
+        check_type_size(dl_passive_req_t DL_PASSIVE_REQ_T)
+        cmake_pop_check_state()
+    elseif(PCAP_TYPE STREQUAL "linux")
+        #
+        # Do we have the wireless extensions?
+        # linux/wireless.h requires sys/socket.h.
+        #
+        check_include_files("sys/socket.h;linux/wireless.h" HAVE_LINUX_WIRELESS_H)
+
+        #
+        # Do we have libnl?
+        #
+        if(BUILD_WITH_LIBNL)
+            #
+            # Try libnl 3.x first.
+            #
+            cmake_push_check_state()
+            set(CMAKE_REQUIRED_LIBRARIES nl-3)
+            check_function_exists(nl_socket_alloc HAVE_LIBNL)
+            cmake_pop_check_state()
+            if(HAVE_LIBNL)
+                #
+                # Yes, we have libnl 3.x.
+                #
+                set(PCAP_LINK_LIBRARIES nl-genl-3 nl-3 ${PCAP_LINK_LIBRARIES})
+                set(HAVE_LIBNL_3_x ON)
+                set(HAVE_LIBNL_NLE ON)
+                set(HAVE_LIBNL_SOCKETS ON)
+                include_directories("/usr/include/libnl3")
+            else()
+                #
+                # Try libnl 2.x.
+                #
+                cmake_push_check_state()
+                set(CMAKE_REQUIRED_LIBRARIES nl)
+                check_function_exists(nl_socket_alloc HAVE_LIBNL)
+                cmake_pop_check_state()
+                if(HAVE_LIBNL)
+                    #
+                    # Yes, we have libnl 2.x.
+                    #
+                    set(PCAP_LINK_LIBRARIES nl-genl nl ${PCAP_LINK_LIBRARIES})
+                    set(HAVE_LIBNL_2_x ON)
+                    set(HAVE_LIBNL_NLE ON)
+                    set(HAVE_LIBNL_SOCKETS ON)
+                else()
+                    #
+                    # No, we don't; do we have libnl 1.x?
+                    #
+                    cmake_push_check_state()
+                    set(CMAKE_REQUIRED_LIBRARIES nl)
+                    check_function_exists(nl_handle_alloc HAVE_LIBNL)
+                    cmake_pop_check_state()
+                    if(HAVE_LIBNL)
+                        set(PCAP_LINK_LIBRARIES nl ${PCAP_LINK_LIBRARIES})
+                    endif()
+                endif()
+            endif()
+        endif()
+
+        check_include_file(linux/ethtool.h HAVE_LINUX_ETHTOOL_H)
+
+        #
+        # Checks to see if tpacket_stats is defined in linux/if_packet.h
+        # If so then pcap-linux.c can use this to report proper statistics.
+        #
+        # XXX - there's no check_type() macro that's like check_type_size()
+        # except that it only checks for the existence of the structure type,
+        # so we use check_type_size() and ignore the size.
+        #
+        cmake_push_check_state()
+        set(CMAKE_EXTRA_INCLUDE_FILES linux/if_packet.h)
+        check_type_size("struct tpacket_stats" STRUCT_TPACKET_STATS)
+        cmake_pop_check_state()
+
+        check_struct_has_member("struct tpacket_auxdata" tp_vlan_tci linux/if_packet.h HAVE_STRUCT_TPACKET_AUXDATA_TP_VLAN_TCI)
+    elseif(PCAP_TYPE STREQUAL "bpf")
+        #
+        # Check whether we have the *BSD-style ioctls.
+        #
+        check_include_files("sys/types.h;net/if_media.h" HAVE_NET_IF_MEDIA_H)
+
+        #
+        # Check whether we have struct BPF_TIMEVAL.
+        #
+        # XXX - there's no check_type() macro that's like check_type_size()
+        # except that it only checks for the existence of the structure type,
+        # so we use check_type_size() and ignore the size.
+        #
+        cmake_push_check_state()
+        if(HAVE_SYS_IOCCOM_H)
+            set(CMAKE_EXTRA_INCLUDE_FILES sys/types.h sys/ioccom.h net/bpf.h)
+            check_type_size("struct BPF_TIMEVAL" STRUCT_BPF_TIMEVAL)
+        else()
+            set(CMAKE_EXTRA_INCLUDE_FILES  sys/types.h net/bpf.h)
+            check_type_size("struct BPF_TIMEVAL" STRUCT_BPF_TIMEVAL)
+        endif()
+        cmake_pop_check_state()
+    elseif(PCAP_TYPE STREQUAL "null")
+    else()
+        message(FATAL_ERROR "${PCAP_TYPE} is not a valid pcap type")
+    endif()
+endif(WIN32)
+
+set(PROJECT_SOURCE_LIST_C ${PROJECT_SOURCE_LIST_C} pcap-${PCAP_TYPE}.c)
+
+#
+# Now figure out how we get a list of interfaces and addresses,
+# if we support capturing.  Don't bother if we don't support
+# capturing.
+#
+if(NOT WIN32)
+    #
+    # UN*X - figure out what type of interface list mechanism we
+    # have.
+    #
+    # If the capture type is null, that means we can't capture,
+    # so we can't open any capture devices, so we won't return
+    # any interfaces.
+    #
+    if(NOT PCAP_TYPE STREQUAL "null")
+        cmake_push_check_state()
+        set(CMAKE_REQUIRED_LIBRARIES ${PCAP_LINK_LIBRARIES})
+        check_function_exists(getifaddrs HAVE_GETIFADDRS)
+        cmake_pop_check_state()
+        if(NOT HAVE_GETIFADDRS)
+            #
+            # It's not in the libraries that, at this point, we've
+            # found we need to link libpcap with.
+            #
+            # It's in libsocket on Solaris and possibly other OSes;
+            # as long as we're not linking with libxnet, check there.
+            #
+            # NOTE: if you hand check_library_exists as its last
+            # argument a variable that's been set, it skips the test,
+            # so we need different variables.
+            #
+            if(NOT LIBXNET_HAS_GETHOSTBYNAME)
+                check_library_exists(socket getifaddrs "" SOCKET_HAS_GETIFADDRS)
+                if(SOCKET_HAS_GETIFADDRS)
+                    set(PCAP_LINK_LIBRARIES socket ${PCAP_LINK_LIBRARIES})
+                    set(HAVE_GETIFADDRS TRUE)
+                endif()
+            endif()
+        endif()
+        if(HAVE_GETIFADDRS)
+            #
+            # We have "getifaddrs()"; make sure we have <ifaddrs.h>
+            # as well, just in case some platform is really weird.
+            # It may require that sys/types.h be included first,
+            # so include it first.
+            #
+            check_include_files("sys/types.h;ifaddrs.h" HAVE_IFADDRS_H)
+            if(HAVE_IFADDRS_H)
+                #
+                # We have the header, so we use "getifaddrs()" to
+                # get the list of interfaces.
+                #
+                set(FINDALLDEVS_TYPE getad)
+            else()
+                #
+                # We don't have the header - give up.
+                # XXX - we could also fall back on some other
+                # mechanism, but, for now, this'll catch this
+                # problem so that we can at least try to figure
+                # out something to do on systems with "getifaddrs()"
+                # but without "ifaddrs.h", if there is something
+                # we can do on those systems.
+                #
+                message(FATAL_ERROR "Your system has getifaddrs() but doesn't have a usable <ifaddrs.h>.")
+            endif()
+        else()
+            #
+            # Well, we don't have "getifaddrs()", at least not with the
+            # libraries with which we've decided we need to link
+            # libpcap with, so we have to use some other mechanism.
+            #
+            # Note that this may happen on Solaris, which has
+            # getifaddrs(), but in -lsocket, not in -lxnet, so we
+            # won't find it if we link with -lxnet, which we want
+            # to do for other reasons.
+            #
+            # For now, we use either the SIOCGIFCONF ioctl or the
+            # SIOCGLIFCONF ioctl, preferring the latter if we have
+            # it; the latter is a Solarisism that first appeared
+            # in Solaris 8.  (Solaris's getifaddrs() appears to
+            # be built atop SIOCGLIFCONF; using it directly
+            # avoids a not-all-that-useful middleman.)
+            #
+            try_compile(HAVE_SIOCGLIFCONF ${CMAKE_CURRENT_BINARY_DIR} "${pcap_SOURCE_DIR}/cmake/have_siocglifconf.c" )
+            if(HAVE_SIOCGLIFCONF)
+                set(FINDALLDEVS_TYPE glifc)
+            else()
+                set(FINDALLDEVS_TYPE gifc)
+            endif()
+        endif()
+        message(STATUS "Find-interfaces mechanism type: ${FINDALLDEVS_TYPE}")
+        set(PROJECT_SOURCE_LIST_C ${PROJECT_SOURCE_LIST_C} fad-${FINDALLDEVS_TYPE}.c)
+    endif()
+endif()
+
+# Check for hardware timestamp support.
+if(CMAKE_SYSTEM_NAME STREQUAL "Linux")
+    check_include_file(linux/net_tstamp.h HAVE_LINUX_NET_TSTAMP_H)
+endif()
+
+#
+# Check for additional native sniffing capabilities.
+#
+
+# Check for USB sniffing support on Linux.
+# On FreeBSD, it uses BPF, so we don't need to do anything special here.
+if(NOT DISABLE_USB)
+    if(CMAKE_SYSTEM_NAME STREQUAL "Linux")
+        set(PCAP_SUPPORT_USB TRUE)
+        set(PROJECT_SOURCE_LIST_C ${PROJECT_SOURCE_LIST_C} pcap-usb-linux.c)
+        set(LINUX_USB_MON_DEV /dev/usbmon)
+        #
+        # Do we have a version of <linux/compiler.h> available?
+        # If so, we might need it for <linux/usbdevice_fs.h>.
+        #
+        check_include_files("linux/compiler.h" HAVE_LINUX_COMPILER_H)
+        if(HAVE_LINUX_COMPILER_H)
+            #
+            # Yes - include it when testing for <linux/usbdevice_fs.h>.
+            #
+            check_include_files("linux/compiler.h;linux/usbdevice_fs.h" HAVE_LINUX_USBDEVICE_FS_H)
+        else(HAVE_LINUX_COMPILER_H)
+            check_include_files("linux/usbdevice_fs.h" HAVE_LINUX_USBDEVICE_FS_H)
+        endif(HAVE_LINUX_COMPILER_H)
+        if(HAVE_LINUX_USBDEVICE_FS_H)
+            #
+            # OK, does it define bRequestType?  Older versions of the kernel
+            # define fields with names like "requesttype, "request", and
+            # "value", rather than "bRequestType", "bRequest", and
+            # "wValue".
+            #
+            if(HAVE_LINUX_COMPILER_H)
+                check_struct_has_member("struct usbdevfs_ctrltransfer" bRequestType "linux/compiler.h;linux/usbdevice_fs.h" HAVE_STRUCT_USBDEVFS_CTRLTRANSFER_BREQUESTTYPE)
+            else(HAVE_LINUX_COMPILER_H)
+                check_struct_has_member("struct usbdevfs_ctrltransfer" bRequestType "linux/usbdevice_fs.h" HAVE_STRUCT_USBDEVFS_CTRLTRANSFER_BREQUESTTYPE)
+            endif(HAVE_LINUX_COMPILER_H)
+        endif()
+    endif()
+endif()
+
+# Check for netfilter sniffing support.
+if(CMAKE_SYSTEM_NAME STREQUAL "Linux")
+    #
+    # 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.
+    #
+    check_c_source_compiles(
+"#include <sys/socket.h>
+#include <netinet/in.h>
+#include <linux/types.h>
+
+#include <linux/netlink.h>
+#include <linux/netfilter.h>
+#include <linux/netfilter/nfnetlink.h>
+#include <linux/netfilter/nfnetlink_log.h>
+#include <linux/netfilter/nfnetlink_queue.h>
+
+int
+main(void)
+{
+    return 0;
+}
+"
+        PCAP_SUPPORT_NETFILTER)
+    if(PCAP_SUPPORT_NETFILTER)
+        set(PROJECT_SOURCE_LIST_C ${PROJECT_SOURCE_LIST_C} pcap-netfilter-linux.c)
+    endif(PCAP_SUPPORT_NETFILTER)
+endif()
+
+# Check for netmap sniffing support.
+if(NOT DISABLE_NETMAP)
+    #
+    # Check whether net/netmap_user.h is usable if NETMAP_WITH_LIBS is
+    # defined; it's not usable on DragonFly BSD 4.6 if NETMAP_WITH_LIBS
+    # is defined, for example, as it includes a non-existent malloc.h
+    # header.
+    #
+    check_c_source_compiles(
+"#define NETMAP_WITH_LIBS
+#include <net/netmap_user.h>
+
+int
+main(void)
+{
+    return 0;
+}
+"
+        PCAP_SUPPORT_NETMAP)
+    if(PCAP_SUPPORT_NETMAP)
+        set(PROJECT_SOURCE_LIST_C ${PROJECT_SOURCE_LIST_C} pcap-netmap.c)
+    endif(PCAP_SUPPORT_NETMAP)
+endif()
+
+# Check for Bluetooth sniffing support
+if(NOT DISABLE_BLUETOOTH)
+    if(CMAKE_SYSTEM_NAME STREQUAL "Linux")
+        check_include_file(bluetooth/bluetooth.h HAVE_BLUETOOTH_BLUETOOTH_H)
+        if(HAVE_BLUETOOTH_BLUETOOTH_H)
+            set(PCAP_SUPPORT_BT TRUE)
+            set(PROJECT_SOURCE_LIST_C ${PROJECT_SOURCE_LIST_C} pcap-bt-linux.c)
+            #
+            # OK, does struct sockaddr_hci have an hci_channel
+            # member?
+            #
+            check_struct_has_member("struct sockaddr_hci" hci_channel "bluetooth/bluetooth.h;bluetooth/hci.h" HAVE_STRUCT_SOCKADDR_HCI_HCI_CHANNEL)
+            if(HAVE_STRUCT_SOCKADDR_HCI_HCI_CHANNEL)
+                #
+                # OK, is HCI_CHANNEL_MONITOR defined?
+                #
+               check_c_source_compiles(
+"#include <bluetooth/bluetooth.h>
+#include <bluetooth/hci.h>
+
+int
+main(void)
+{
+    u_int i = HCI_CHANNEL_MONITOR;
+    return 0;
+}
+"
+                   PCAP_SUPPORT_BT_MONITOR)
+               if(PCAP_SUPPORT_BT_MONITOR)
+                   #
+                   # Yes, so we can also support Bluetooth monitor
+                   # sniffing.
+                   #
+                   set(PROJECT_SOURCE_LIST_C ${PROJECT_SOURCE_LIST_C} pcap-bt-monitor-linux.c)
+               endif(PCAP_SUPPORT_BT_MONITOR)
+            endif(HAVE_STRUCT_SOCKADDR_HCI_HCI_CHANNEL)
+        endif(HAVE_BLUETOOTH_BLUETOOTH_H)
+    endif()
+endif()
+
+# Check for Bluetooth sniffing support
+if(NOT DISABLE_DBUS)
+    #
+    # We don't support D-Bus sniffing on macOS; see
+    #
+    # https://bugs.freedesktop.org/show_bug.cgi?id=74029
+    #
+    if(APPLE)
+        message(FATAL_ERROR "Due to freedesktop.org bug 74029, D-Bus capture support is not available on macOS")
+    endif(APPLE)
+    include(FindPkgConfig)
+    pkg_check_modules(DBUS dbus-1)
+    if(DBUS_FOUND)
+        set(PCAP_SUPPORT_DBUS TRUE)
+        set(PROJECT_SOURCE_LIST_C ${PROJECT_SOURCE_LIST_C} pcap-dbus.c)
+        include_directories(${DBUS_INCLUDE_DIRS})
+
+        #
+        # This "helpfully" supplies DBUS_LIBRARIES as a bunch of
+        # library names - not paths - and DBUS_LIBRARY_DIRS as
+        # a bunch of directories.
+        #
+        # CMake *really* doesn't like the notion of specifying "here are
+        # the directories in which to look for libraries" except in
+        # find_library() calls; it *really* prefers using full paths to
+        # library files, rather than library names.
+        #
+        # Find the libraries and add their full paths.
+        #
+        set(DBUS_LIBRARY_FULLPATHS)
+        foreach(_lib IN LISTS DBUS_LIBRARIES)
+            #
+            # Try to find this library, so we get its full path.
+            #
+            find_library(_libfullpath ${_lib} HINTS ${DBUS_LIBRARY_DIRS})
+            list(APPEND DBUS_LIBRARY_FULLPATHS ${_libfullpath})
+        endforeach()
+        set(PCAP_LINK_LIBRARIES ${PCAP_LINK_LIBRARIES} ${DBUS_LIBRARY_FULLPATHS})
+    endif(DBUS_FOUND)
+endif(NOT DISABLE_DBUS)
+
+# Check for RDMA sniffing support
+if(NOT DISABLE_RDMA)
+    check_library_exists(ibverbs ibv_get_device_list "" LIBIBVERBS_HAS_IBV_GET_DEVICE_LIST)
+    if(LIBIBVERBS_HAS_IBV_GET_DEVICE_LIST)
+        check_include_file(infiniband/verbs.h HAVE_INFINIBAND_VERBS_H)
+        if(HAVE_INFINIBAND_VERBS_H)
+            check_symbol_exists(ibv_create_flow infiniband/verbs.h PCAP_SUPPORT_RDMASNIFF)
+            if(PCAP_SUPPORT_RDMASNIFF)
+                set(PROJECT_SOURCE_LIST_C ${PROJECT_SOURCE_LIST_C} pcap-rdmasniff.c)
+                set(PCAP_LINK_LIBRARIES ibverbs ${PCAP_LINK_LIBRARIES})
+            endif(PCAP_SUPPORT_RDMASNIFF)
+        endif(HAVE_INFINIBAND_VERBS_H)
+    endif(LIBIBVERBS_HAS_IBV_GET_DEVICE_LIST)
+endif(NOT DISABLE_RDMA)
+
+#
+# Check for sniffing capabilities using third-party APIs.
+#
+
+# Check for Endace DAG card support.
+if(NOT DISABLE_DAG)
+    #
+    # Try to find the DAG header file and library.
+    #
+    find_package(DAG)
+
+    #
+    # Did we succeed?
+    #
+    if(DAG_FOUND)
+        #
+        # Yes.
+        # Check for various DAG API functions.
+        #
+        cmake_push_check_state()
+        set(CMAKE_REQUIRED_INCLUDES ${DAG_INCLUDE_DIRS})
+        set(CMAKE_REQUIRED_LIBRARIES ${DAG_LIBRARIES})
+        check_function_exists(dag_attach_stream HAVE_DAG_STREAMS_API)
+        if(NOT HAVE_DAG_STREAMS_API)
+            message(FATAL_ERROR "DAG library lacks streams support")
+        endif()
+        check_function_exists(dag_attach_stream64 HAVE_DAG_LARGE_STREAMS_API)
+        check_function_exists(dag_get_erf_types HAVE_DAG_GET_ERF_TYPES)
+        check_function_exists(dag_get_stream_erf_types HAVE_DAG_GET_STREAM_ERF_TYPES)
+        cmake_pop_check_state()
+
+        include_directories(AFTER ${DAG_INCLUDE_DIRS})
+        set(PROJECT_SOURCE_LIST_C ${PROJECT_SOURCE_LIST_C} pcap-dag.c)
+        set(HAVE_DAG_API TRUE)
+        set(PCAP_LINK_LIBRARIES ${PCAP_LINK_LIBRARIES} ${DAG_LIBRARIES})
+
+        if(HAVE_DAG_LARGE_STREAMS_API)
+            get_filename_component(DAG_LIBRARY_DIR ${DAG_LIBRARY} PATH)
+            check_library_exists(vdag vdag_set_device_info ${DAG_LIBRARY_DIR} HAVE_DAG_VDAG)
+            if(HAVE_DAG_VDAG)
+                set(PCAP_LINK_LIBRARIES ${PCAP_LINK_LIBRARIES} ${CMAKE_THREAD_LIBS_INIT})
+            endif()
+        endif()
+    endif()
+endif()
+
+# Check for Septel card support.
+set(PROJECT_EXTERNAL_OBJECT_LIST "")
+if(NOT DISABLE_SEPTEL)
+    #
+    # Do we have the msg.h header?
+    #
+    set(SEPTEL_INCLUDE_DIRS "${SEPTEL_ROOT}/INC")
+    cmake_push_check_state()
+    set(CMAKE_REQUIRED_INCLUDES ${SEPTEL_INCLUDE_DIRS})
+    check_include_file(msg.h HAVE_INC_MSG_H)
+    cmake_pop_check_state()
+    if(HAVE_INC_MSG_H)
+        #
+        # Yes.
+        #
+        include_directories(AFTER ${SEPTEL_INCLUDE_DIRS})
+        set(PROJECT_SOURCE_LIST_C ${PROJECT_SOURCE_LIST_C} pcap-septel.c)
+        set(PROJECT_EXTERNAL_OBJECT_LIST ${PROJECT_EXTERNAL_OBJECT_LIST} "${SEPTEL_ROOT}/asciibin.o ${SEPTEL_ROOT}/bit2byte.o ${SEPTEL_ROOT}/confirm.o ${SEPTEL_ROOT}/fmtmsg.o ${SEPTEL_ROOT}/gct_unix.o ${SEPTEL_ROOT}/hqueue.o ${SEPTEL_ROOT}/ident.o ${SEPTEL_ROOT}/mem.o ${SEPTEL_ROOT}/pack.o ${SEPTEL_ROOT}/parse.o ${SEPTEL_ROOT}/pool.o ${SEPTEL_ROOT}/sdlsig.o ${SEPTEL_ROOT}/strtonum.o ${SEPTEL_ROOT}/timer.o ${SEPTEL_ROOT}/trace.o")
+        set(HAVE_SEPTEL_API TRUE)
+    endif()
+endif()
+
+# Check for Myricom SNF support.
+if(NOT DISABLE_SNF)
+    #
+    # Try to find the SNF header file and library.
+    #
+    find_package(SNF)
+
+    #
+    # Did we succeed?
+    #
+    if(SNF_FOUND)
+        #
+        # Yes.
+        #
+        include_directories(AFTER ${SNF_INCLUDE_DIRS})
+        set(PROJECT_SOURCE_LIST_C ${PROJECT_SOURCE_LIST_C} pcap-snf.c)
+        set(HAVE_SNF_API TRUE)
+        set(PCAP_LINK_LIBRARIES ${PCAP_LINK_LIBRARIES} ${SNF_LIBRARIES})
+    endif()
+endif()
+
+# Check for Riverbed TurboCap support.
+if(NOT DISABLE_TC)
+    #
+    # Try to find the TurboCap header file and library.
+    #
+    find_package(TC)
+
+    #
+    # Did we succeed?
+    #
+    if(TC_FOUND)
+        #
+        # Yes.
+        #
+        include_directories(AFTER ${TC_INCLUDE_DIRS})
+        set(PROJECT_SOURCE_LIST_C ${PROJECT_SOURCE_LIST_C} pcap-tc.c)
+        set(HAVE_TC_API TRUE)
+        set(PCAP_LINK_LIBRARIES "${PCAP_LINK_LIBRARIES} ${TC_LIBRARIES} ${CMAKE_USE_PTHREADS_INIT} stdc++")
+    endif()
+endif()
+
+#
+# Remote capture support.
+#
+
+if(ENABLE_REMOTE)
+    #
+    # Check for various members of struct msghdr.
+    # We need to include ftmacros.h on some platforms, to make sure we
+    # get the POSIX/Single USER Specification version of struct msghdr,
+    # which has those members, rather than the backwards-compatible
+    # version, which doesn't.  That's not a system header file, and
+    # at least some versions of CMake include it as <ftmacros.h>, which
+    # won't check the current directory, so we add the top-level
+    # source directory to the list of include directories when we do
+    # the check.
+    #
+    cmake_push_check_state()
+    set(CMAKE_REQUIRED_INCLUDES ${CMAKE_CURRENT_SOURCE_DIR})
+    check_struct_has_member("struct msghdr" msg_control "ftmacros.h;sys/socket.h" HAVE_STRUCT_MSGHDR_MSG_CONTROL)
+    check_struct_has_member("struct msghdr" msg_flags "ftmacros.h;sys/socket.h" HAVE_STRUCT_MSGHDR_MSG_FLAGS)
+    cmake_pop_check_state()
+    set(PROJECT_SOURCE_LIST_C ${PROJECT_SOURCE_LIST_C}
+        pcap-new.c pcap-rpcap.c rpcap-protocol.c sockutils.c)
+endif(ENABLE_REMOTE)
+
+###################################################################
+#   Warning options
+###################################################################
+
+#
+# Check and add warning options if we have a .devel file.
+#
+if(EXISTS ${CMAKE_CURRENT_SOURCE_DIR}/.devel OR EXISTS ${CMAKE_BINARY_DIR}/.devel)
+    #
+    # Warning options.
+    #
+    if(MSVC AND NOT ${CMAKE_C_COMPILER} MATCHES "clang*")
+        #
+        # MSVC, with Microsoft's front end and code generator.
+        # "MSVC" is also set for Microsoft's compiler with a Clang
+        # front end and their code generator ("Clang/C2"), so we
+        # check for clang.exe and treat that differently.
+        #
+        check_and_add_compiler_option(-Wall)
+        #
+        # Disable some pointless warnings that /Wall turns on.
+        #
+        # Unfortunately, MSVC does not appear to have an equivalent
+        # to "__attribute__((unused))" to mark a particular function
+        # parameter as being known to be unused, so that the compiler
+        # won't warn about it (for example, the function might have
+        # that parameter because a pointer to it is being used, and
+        # the signature of that function includes that parameter).
+        # C++ lets you give a parameter a type but no name, but C
+        # doesn't have that.
+        #
+        check_and_add_compiler_option(-wd4100)
+        #
+        # In theory, we care whether somebody uses f() rather than
+        # f(void) to declare a function with no arguments, but, in
+        # practice, there are places in the Windows header files
+        # that appear to do that, so we squelch that warning.
+        #
+        check_and_add_compiler_option(-wd4255)
+        #
+        # Windows FD_SET() generates this, so we suppress it.
+        #
+        check_and_add_compiler_option(-wd4548)
+        #
+        # Perhaps testing something #defined to be 0 with #ifdef is an
+        # error, and it should be tested with #if, but perhaps it's
+        # not, and Microsoft does that in its headers, so we squelch
+        # that warning.
+        #
+        check_and_add_compiler_option(-wd4574)
+        #
+        # The Windows headers also test not-defined values in #if, so
+        # we don't want warnings about that, either.
+        #
+        check_and_add_compiler_option(-wd4668)
+        #
+        # We do *not* care whether some function is, or isn't, going to be
+        # expanded inline.
+        #
+        check_and_add_compiler_option(-wd4710)
+        check_and_add_compiler_option(-wd4711)
+        #
+        # We do *not* care whether we're adding padding bytes after
+        # structure members.
+        #
+        check_and_add_compiler_option(-wd4820)
+    else()
+        #
+        # Other compilers, including MSVC with a Clang front end and
+        # Microsoft's code generator.  We currently treat them as if
+        # they might support GCC-style -W options.
+        #
+        check_and_add_compiler_option(-Wall)
+        check_and_add_compiler_option(-Wsign-compare)
+        check_and_add_compiler_option(-Wmissing-prototypes)
+        check_and_add_compiler_option(-Wstrict-prototypes)
+        check_and_add_compiler_option(-Wshadow)
+        check_and_add_compiler_option(-Wdeclaration-after-statement)
+        check_and_add_compiler_option(-Wused-but-marked-unused)
+        check_and_add_compiler_option(-Wdocumentation)
+        check_and_add_compiler_option(-Wcomma)
+        check_and_add_compiler_option(-Wmissing-noreturn)
+        # Warns about safeguards added in case the enums are extended
+        # check_and_add_compiler_option(-Wcovered-switch-default)
+        check_and_add_compiler_option(-Wmissing-variable-declarations)
+        check_and_add_compiler_option(-Wunused-parameter)
+        check_and_add_compiler_option(-Wformat-nonliteral)
+        check_and_add_compiler_option(-Wunreachable-code)
+    endif()
+endif()
+
+#
+# Suppress some warnings we get with MSVC even without /Wall.
+#
+if(MSVC AND NOT ${CMAKE_C_COMPILER} MATCHES "clang*")
+    #
+    # Yes, we have some functions that never return but that
+    # have a non-void return type.  That's because, on some
+    # platforms, they *do* return values but, on other
+    # platforms, including Windows, they just fail and
+    # longjmp out by calling bpf_error().
+    #
+    check_and_add_compiler_option(-wd4646)
+endif()
+
+file(GLOB PROJECT_SOURCE_LIST_H
+    *.h
+    pcap/*.h
+)
+
+#
+# Try to have the compiler default to hiding symbols, so that only
+# symbols explicitly exported with PCAP_API will be visible outside
+# (shared) libraries.
+#
+# Not necessary with MSVC, as that's the default.
+#
+# XXX - we don't use ADD_COMPILER_EXPORT_FLAGS, because, as of CMake
+# 2.8.12.2, it doesn't know about Sun C/Oracle Studio, and, as of
+# CMake 2.8.6, it only sets the C++ compiler flags, rather than
+# allowing an arbitrary variable to be set with the "hide symbols
+# not explicitly exported" flag.
+#
+if(NOT MSVC)
+    if(CMAKE_C_COMPILER_ID MATCHES "SunPro")
+        #
+        # Sun C/Oracle Studio.
+        #
+        check_and_add_compiler_option(-xldscope=hidden)
+    else()
+        #
+        # Try this for all other compilers; it's what GCC uses,
+        # and a number of other compilers, such as Clang and Intel C,
+        # use it as well.
+        #
+        check_and_add_compiler_option(-fvisibility=hidden)
+    endif()
+endif(NOT MSVC)
+
+#
+# Flex/Lex and YACC/Berkeley YACC/Bison.
+# From a mail message to the CMake mailing list by Andy Cedilnik of
+# Kitware.
+#
+
+#
+# Try to find Flex, a Windows version of Flex, or Lex.
+#
+find_program(LEX_EXECUTABLE NAMES flex win_flex lex)
+if(LEX_EXECUTABLE STREQUAL "LEX_EXECUTABLE-NOTFOUND")
+    message(FATAL_ERROR "Neither flex nor win_flex nor lex was found.")
+endif()
+message(STATUS "Lexical analyzer generator: ${LEX_EXECUTABLE}")
+
+add_custom_command(
+    OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/scanner.c ${CMAKE_CURRENT_BINARY_DIR}/scanner.h
+    SOURCE ${pcap_SOURCE_DIR}/scanner.l
+    COMMAND ${LEX_EXECUTABLE} -P pcap_ --header-file=scanner.h --nounput -o${CMAKE_CURRENT_BINARY_DIR}/scanner.c ${pcap_SOURCE_DIR}/scanner.l
+    DEPENDS ${pcap_SOURCE_DIR}/scanner.l
+)
+
+#
+# Since scanner.c does not exist yet when cmake is run, mark
+# it as generated.
+#
+# Since scanner.c includes grammar.h, mark that as a dependency.
+#
+set_source_files_properties(${CMAKE_CURRENT_BINARY_DIR}/scanner.c PROPERTIES
+    GENERATED TRUE
+    OBJECT_DEPENDS ${CMAKE_CURRENT_BINARY_DIR}/grammar.h
+)
+
+#
+# Add scanner.c to the list of sources.
+#
+#set(PROJECT_SOURCE_LIST_C ${PROJECT_SOURCE_LIST_C} ${CMAKE_CURRENT_BINARY_DIR}/scanner.c)
+
+#
+# Try to find YACC or Bison.
+#
+find_program(YACC_EXECUTABLE NAMES bison win_bison byacc yacc)
+if(YACC_EXECUTABLE STREQUAL "YACC_EXECUTABLE-NOTFOUND")
+    message(FATAL_ERROR "Neither bison nor win_bison nor byacc nor yacc was found.")
+endif()
+message(STATUS "Parser generator: ${YACC_EXECUTABLE}")
+
+#
+# Create custom command for the scanner.
+# Find out whether it's Bison or not by looking at the last component
+# of the path (without a .exe extension, if this is Windows).
+#
+get_filename_component(YACC_NAME ${YACC_EXECUTABLE} NAME_WE)
+if("${YACC_NAME}" STREQUAL "bison" OR "${YACC_NAME}" STREQUAL "win_bison")
+    set(YACC_COMPATIBILITY_FLAG "-y")
+endif()
+add_custom_command(
+    OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/grammar.c ${CMAKE_CURRENT_BINARY_DIR}/grammar.h
+    SOURCE ${pcap_SOURCE_DIR}/grammar.y
+    COMMAND ${YACC_EXECUTABLE} ${YACC_COMPATIBILITY_FLAG} -p pcap_ -o ${CMAKE_CURRENT_BINARY_DIR}/grammar.c -d ${pcap_SOURCE_DIR}/grammar.y
+    DEPENDS ${pcap_SOURCE_DIR}/grammar.y
+)
+
+#
+# Since grammar.c does not exists yet when cmake is run, mark
+# it as generated.
+#
+set_source_files_properties(${CMAKE_CURRENT_BINARY_DIR}/grammar.c PROPERTIES
+    GENERATED TRUE
+    OBJECT_DEPENDS ${CMAKE_CURRENT_BINARY_DIR}/scanner.h
+)
+
+#
+# Add grammar.c to the list of sources.
+#
+#set(PROJECT_SOURCE_LIST_C ${PROJECT_SOURCE_LIST_C} ${CMAKE_CURRENT_BINARY_DIR}/grammar.c)
+
+#
+# Assume, by default, no support for shared libraries and V7/BSD
+# convention for man pages (devices in section 4, file formats in
+# section 5, miscellaneous info in section 7, administrative commands
+# and daemons in section 8).  Individual cases can override this.
+# Individual cases can override this.
+#
+set(MAN_DEVICES 4)
+set(MAN_FILE_FORMATS 5)
+set(MAN_MISC_INFO 7)
+set(MAN_ADMIN_COMMANDS 8)
+if(CMAKE_SYSTEM_NAME STREQUAL "AIX")
+    # Workaround to enable certain features
+    set(_SUN TRUE)
+    if(PCAP_TYPE STREQUAL "bpf")
+        #
+        # If we're using BPF, we need libodm and libcfg, as
+        # we use them to load the BPF module.
+        #
+        set(PCAP_LINK_LIBRARIES ${PCAP_LINK_LIBRARIES} odm cfg)
+    endif()
+elseif(CMAKE_SYSTEM_NAME STREQUAL "HP-UX")
+    if(CMAKE_SYSTEM_VERSION MATCHES "[A-Z.]*9\.[0-9]*")
+        #
+        # HP-UX 9.x.
+        #
+        set(HAVE_HPUX9 TRUE)
+    elseif(CMAKE_SYSTEM_VERSION MATCHES "[A-Z.]*10\.0")
+        #
+        # HP-UX 10.0.
+        #
+    elseif(CMAKE_SYSTEM_VERSION MATCHES "[A-Z.]*10\.1")
+        #
+        # HP-UX 10.1.
+        #
+    else()
+        #
+        # HP-UX 10.20 and later.
+        #
+        set(HAVE_HPUX10_20_OR_LATER TRUE)
+    endif()
+
+    #
+    # Use System V conventions for man pages.
+    #
+    set(MAN_ADMIN_COMMANDS 1m)
+    set(MAN_FILE_FORMATS 4)
+    set(MAN_MISC_INFO 5)
+elseif(CMAKE_SYSTEM_NAME STREQUAL "IRIX" OR CMAKE_SYSTEM_NAME STREQUAL "IRIX64")
+    #
+    # Use IRIX conventions for man pages; they're the same as the
+    # System V conventions, except that they use section 8 for
+    # administrative commands and daemons.
+    #
+    set(MAN_FILE_FORMATS 4)
+    set(MAN_MISC_INFO 5)
+elseif(CMAKE_SYSTEM_NAME STREQUAL "OSF1")
+    #
+    # DEC OSF/1, a/k/a Digial UNIX, a/k/a Tru64 UNIX.
+    # Use Tru64 UNIX conventions for man pages; they're the same as the
+    # System V conventions except that they use section 8 for
+    # administrative commands and daemons.
+    #
+    set(MAN_FILE_FORMATS 4)
+    set(MAN_MISC_INFO 5)
+    set(MAN_DEVICES 7)
+elseif(CMAKE_SYSTEM_NAME STREQUAL "SunOS" AND CMAKE_SYSTEM_VERSION MATCHES "5[.][0-9.]*")
+    #
+    # SunOS 5.x.
+    #
+    set(HAVE_SOLARIS TRUE)
+    #
+    # Make sure errno is thread-safe, in case we're called in
+    # a multithreaded program.  We don't guarantee that two
+    # threads can use the *same* pcap_t safely, but the
+    # current version does guarantee that you can use different
+    # pcap_t's in different threads, and even that pcap_compile()
+    # is thread-safe (it wasn't thread-safe in some older versions).
+    #
+    add_definitions(-D_TS_ERRNO)
+
+    if(CMAKE_SYSTEM_VERSION STREQUAL "5.12")
+    else()
+        #
+        # Use System V conventions for man pages.
+        #
+        set(MAN_ADMIN_COMMANDS 1m)
+        set(MAN_FILE_FORMATS 4)
+        set(MAN_MISC_INFO 5)
+        set(MAN_DEVICES 7D)
+    endif()
+endif()
+
+source_group("Source Files" FILES ${PROJECT_SOURCE_LIST_C})
+source_group("Header Files" FILES ${PROJECT_SOURCE_LIST_H})
+
+if(WIN32)
+    #
+    # Add pcap-dll.rc to the list of sources.
+    #
+    set(PROJECT_SOURCE_LIST_C ${PROJECT_SOURCE_LIST_C} ${pcap_SOURCE_DIR}/pcap-dll.rc)
+endif(WIN32)
+
+#
+# Add subdirectories after we've set various variables, so they pick up
+# pick up those variables.
+#
+if(ENABLE_REMOTE)
+    add_subdirectory(rpcapd)
+endif(ENABLE_REMOTE)
+add_subdirectory(testprogs)
+
+######################################
+# Register targets
+######################################
+
+#
+# Special target to serialize the building of the generated source.
+#
+# See
+#
+#  http://public.kitware.com/pipermail/cmake/2013-August/055510.html
+#
+add_custom_target(SerializeTarget
+    DEPENDS
+    ${CMAKE_CURRENT_BINARY_DIR}/grammar.c
+    ${CMAKE_CURRENT_BINARY_DIR}/scanner.c
+)
+
+set_source_files_properties(${PROJECT_EXTERNAL_OBJECT_LIST} PROPERTIES
+    EXTERNAL_OBJECT TRUE)
+
+if(BUILD_SHARED_LIBS)
+    add_library(${LIBRARY_NAME} SHARED
+        ${PROJECT_SOURCE_LIST_C}
+        ${CMAKE_CURRENT_BINARY_DIR}/grammar.c
+        ${CMAKE_CURRENT_BINARY_DIR}/scanner.c
+        ${PROJECT_EXTERNAL_OBJECT_LIST}
+    )
+    add_dependencies(${LIBRARY_NAME} SerializeTarget)
+    set_target_properties(${LIBRARY_NAME} PROPERTIES
+        COMPILE_DEFINITIONS BUILDING_PCAP)
+    #
+    # No matter what the library is called - it might be called "wpcap"
+    # in a Windows build - the symbol to define to indicate that we're
+    # building the library, rather than a program using the library,
+    # and thus that we're exporting functions defined in our public
+    # header files, rather than importing those functions, is
+    # pcap_EXPORTS.
+    #
+    set_target_properties(${LIBRARY_NAME} PROPERTIES
+        DEFINE_SYMBOL pcap_EXPORTS)
+endif(BUILD_SHARED_LIBS)
+
+add_library(${LIBRARY_NAME}_static STATIC
+    ${PROJECT_SOURCE_LIST_C}
+    ${CMAKE_CURRENT_BINARY_DIR}/grammar.c
+    ${CMAKE_CURRENT_BINARY_DIR}/scanner.c
+    ${PROJECT_EXTERNAL_OBJECT_LIST}
+)
+add_dependencies(${LIBRARY_NAME}_static SerializeTarget)
+set_target_properties(${LIBRARY_NAME}_static PROPERTIES
+    COMPILE_DEFINITIONS BUILDING_PCAP)
+
+if(WIN32)
+    if(BUILD_SHARED_LIBS)
+        set_target_properties(${LIBRARY_NAME} PROPERTIES
+            VERSION ${PACKAGE_VERSION_NOSUFFIX} # only MAJOR and MINOR are needed
+        )
+    endif(BUILD_SHARED_LIBS)
+    if(MSVC)
+        # XXX For DLLs, the TARGET_PDB_FILE generator expression can be used to locate
+        # its PDB file's output directory for installation.
+        # cmake doesn't offer a generator expression for PDB files generated by the
+        # compiler (static libraries).
+        # So instead of considering any possible output there is (there are many),
+        # this will search for the PDB file in the compiler's initial output directory,
+        # which is always ${CMAKE_CURRENT_BINARY_DIR}/CMakeFiles\wpcap_static.dir
+        # regardless of architecture, build generator etc.
+        # Quite hackish indeed.
+        set(CMAKE_COMPILE_PDB_OUTPUT_DIRECTORY $<TARGET_FILE_DIR:${LIBRARY_NAME}_static>)
+        set_target_properties(${LIBRARY_NAME}_static PROPERTIES
+            COMPILE_PDB_NAME ${LIBRARY_NAME}_static
+            OUTPUT_NAME "${LIBRARY_NAME}_static"
+        )
+    elseif(MINGW)
+        #
+        # For compatibility, build the shared library without the "lib" prefix on
+        # MinGW as well.
+        #
+        set_target_properties(${LIBRARY_NAME} PROPERTIES
+            PREFIX ""
+            OUTPUT_NAME "${LIBRARY_NAME}"
+        )
+        set_target_properties(${LIBRARY_NAME}_static PROPERTIES
+            OUTPUT_NAME "${LIBRARY_NAME}"
+        )
+    endif()
+else(WIN32) # UN*X
+    if(BUILD_SHARED_LIBS)
+        if(APPLE)
+            set_target_properties(${LIBRARY_NAME} PROPERTIES
+                VERSION ${PACKAGE_VERSION}
+                SOVERSION A
+            )
+        else(APPLE)
+            set_target_properties(${LIBRARY_NAME} PROPERTIES
+                VERSION ${PACKAGE_VERSION}
+                SOVERSION ${PACKAGE_VERSION_MAJOR}
+            )
+        endif(APPLE)
+    endif(BUILD_SHARED_LIBS)
+    set_target_properties(${LIBRARY_NAME}_static PROPERTIES
+        OUTPUT_NAME "${LIBRARY_NAME}"
+    )
+endif(WIN32)
+
+if(BUILD_SHARED_LIBS)
+    if(NOT C_ADDITIONAL_FLAGS STREQUAL "")
+        set_target_properties(${LIBRARY_NAME} PROPERTIES COMPILE_FLAGS ${C_ADDITIONAL_FLAGS})
+    endif()
+    target_link_libraries(${LIBRARY_NAME} ${PCAP_LINK_LIBRARIES})
+endif(BUILD_SHARED_LIBS)
+
+if(NOT C_ADDITIONAL_FLAGS STREQUAL "")
+    set_target_properties(${LIBRARY_NAME}_static PROPERTIES COMPILE_FLAGS ${C_ADDITIONAL_FLAGS})
+endif()
+
+#
+# On macOS, build libpcap for the appropriate architectures, if
+# CMAKE_OSX_ARCHITECTURES isn't set (if it is, let that control
+# the architectures for which to build it).
+#
+if(APPLE AND "${CMAKE_OSX_ARCHITECTURES}" STREQUAL "")
+    #
+    # Get the major version of Darwin.
+    #
+    string(REGEX MATCH "^([0-9]+)" SYSTEM_VERSION_MAJOR "${CMAKE_SYSTEM_VERSION}")
+
+    if(SYSTEM_VERSION_MAJOR LESS 8)
+        #
+        # Pre-Tiger.  Build only for 32-bit PowerPC.
+        #
+        set(OSX_LIBRARY_ARCHITECTURES "ppc")
+    elseif(SYSTEM_VERSION_MAJOR EQUAL 8)
+        #
+        # Tiger.  Is this prior to, or with, Intel support?
+        #
+        # Get the minor version of Darwin.
+        #
+        string(REPLACE "${SYSTEM_VERSION_MAJOR}." "" SYSTEM_MINOR_AND_PATCH_VERSION ${CMAKE_SYSTEM_VERSION})
+        string(REGEX MATCH "^([0-9]+)" SYSTEM_VERSION_MINOR "${SYSTEM_MINOR_AND_PATCH_VERSION}")
+        if(SYSTEM_VERSION_MINOR LESS 4)
+            #
+            # Prior to Intel support.  Build for 32-bit
+            # PowerPC and 64-bit PowerPC, with 32-bit PowerPC
+            # first.  (I'm guessing that's what Apple does.)
+            #
+            set(OSX_LIBRARY_ARCHITECTURES "ppc;ppc64")
+        elseif(SYSTEM_VERSION_MINOR LESS 7)
+            #
+            # With Intel support but prior to x86-64 support.
+            # Build for 32-bit PowerPC, 64-bit PowerPC, and 32-bit x86,
+            # with 32-bit PowerPC first.
+            # (I'm guessing that's what Apple does.)
+            #
+            set(OSX_LIBRARY_ARCHITECTURES "ppc;ppc64;i386")
+        else()
+            #
+            # With Intel support including x86-64 support.
+            # Build for 32-bit PowerPC, 64-bit PowerPC, 32-bit x86,
+            # and x86-64, with 32-bit PowerPC first.
+            # (I'm guessing that's what Apple does.)
+            #
+            set(OSX_LIBRARY_ARCHITECTURES "ppc;ppc64;i386;x86_64")
+        endif()
+    elseif(SYSTEM_VERSION_MAJOR EQUAL 9)
+        #
+        # Leopard.  Build for 32-bit PowerPC, 64-bit
+        # PowerPC, 32-bit x86, and x86-64, with 32-bit PowerPC
+        # first.  (That's what Apple does.)
+        #
+        set(OSX_LIBRARY_ARCHITECTURES "ppc;ppc64;i386;x86_64")
+    elseif(SYSTEM_VERSION_MAJOR EQUAL 10)
+        #
+        # Snow Leopard.  Build for x86-64, 32-bit x86, and
+        # 32-bit PowerPC, with x86-64 first.  (That's
+        # what Apple does, even though Snow Leopard
+        # doesn't run on PPC, so PPC libpcap runs under
+        # Rosetta, and Rosetta doesn't support BPF
+        # ioctls, so PPC programs can't do live
+        # captures.)
+        #
+        set(OSX_LIBRARY_ARCHITECTURES "x86_64;i386;ppc")
+    else()
+        #
+        # Post-Snow Leopard.  Build for x86-64 and 32-bit x86,
+        # with x86-64 first.  (That's what Apple does)
+        # XXX - update if and when Apple drops support
+        # for 32-bit x86 code and if and when Apple adds
+        # ARM-based Macs.  (You're on your own for iOS etc.)
+        #
+        # XXX - check whether we *can* build for i386 and, if not,
+        # suggest that the user install the /usr/include headers if
+        # they want to build fat.
+        #
+        cmake_push_check_state()
+        set(CMAKE_REQUIRED_FLAGS "-arch i386")
+        check_c_source_compiles(
+"int
+main(void)
+{
+    return 0;
+}
+"
+                   X86_32_BIT_SUPPORTED)
+        cmake_pop_check_state()
+        if(X86_32_BIT_SUPPORTED)
+            set(OSX_LIBRARY_ARCHITECTURES "x86_64;i386")
+        else()
+            set(OSX_LIBRARY_ARCHITECTURES "x86_64")
+            if(SYSTEM_VERSION_MAJOR LESS 18)
+                #
+                # Pre-Mojave; the command-line tools should be sufficient to
+                # enable 32-bit x86 builds.
+                #
+                message(WARNING "Compiling for 32-bit x86 gives an error; try installing the command-line tools")
+            else()
+                message(WARNING "Compiling for 32-bit x86 gives an error; try installing the command-line tools and, after that, installing the /usr/include headers from the /Library/Developer/CommandLineTools/Packages/macOS_SDK_headers_for_macOS_10.14.pkg package")
+            endif()
+        endif()
+    endif()
+    if(BUILD_SHARED_LIBS)
+        set_target_properties(${LIBRARY_NAME} PROPERTIES
+            OSX_ARCHITECTURES "${OSX_LIBRARY_ARCHITECTURES}")
+    endif(BUILD_SHARED_LIBS)
+    set_target_properties(${LIBRARY_NAME}_static PROPERTIES
+        OSX_ARCHITECTURES "${OSX_LIBRARY_ARCHITECTURES}")
+endif()
+
+######################################
+# Write out the config.h file
+######################################
+
+configure_file(${CMAKE_CURRENT_SOURCE_DIR}/cmakeconfig.h.in ${CMAKE_CURRENT_BINARY_DIR}/config.h)
+
+######################################
+# Install pcap library, include files, and man pages
+######################################
+
+#
+# "Define GNU standard installation directories", which actually
+# are also defined, to some degree, by autotools, and at least
+# some of which are general UN*X conventions.
+#
+include(GNUInstallDirs)
+
+set(LIBRARY_NAME_STATIC ${LIBRARY_NAME}_static)
+
+function(install_manpage_symlink SOURCE TARGET MANDIR)
+    if(MINGW)
+        find_program(LINK_EXECUTABLE ln)
+            if(LINK_EXECUTABLE)
+                set(LINK_COMMAND "\"${LINK_EXECUTABLE}\" \"-s\" \"${SOURCE}\" \"${TARGET}\"")
+            else(LINK_EXECUTABLE)
+                message(FATAL_ERROR "ln (http://pubs.opengroup.org/onlinepubs/9699919799/utilities/ln.html) not found.")
+            endif(LINK_EXECUTABLE)
+    else(MINGW)
+        set(LINK_COMMAND "\"${CMAKE_COMMAND}\" \"-E\" \"create_symlink\" \"${SOURCE}\" \"${TARGET}\"")
+    endif(MINGW)
+
+    install(CODE
+        "message(STATUS \"Symlinking: ${CMAKE_INSTALL_PREFIX}/${MANDIR}/${SOURCE} to ${TARGET}\")
+         execute_process(
+            COMMAND \"${CMAKE_COMMAND}\" \"-E\" \"remove\" \"${TARGET}\"
+            WORKING_DIRECTORY ${CMAKE_INSTALL_PREFIX}/${MANDIR}
+          )
+         execute_process(
+            COMMAND ${LINK_COMMAND}
+            WORKING_DIRECTORY ${CMAKE_INSTALL_PREFIX}/${MANDIR}
+            RESULT_VARIABLE EXIT_STATUS
+          )
+          if(NOT EXIT_STATUS EQUAL 0)
+              message(FATAL_ERROR \"Could not create symbolic link from ${CMAKE_INSTALL_PREFIX}/${MANDIR}/${SOURCE} to ${TARGET}\")
+          endif()
+          set(CMAKE_INSTALL_MANIFEST_FILES \${CMAKE_INSTALL_MANIFEST_FILES} ${CMAKE_INSTALL_PREFIX}/${MANDIR}/${TARGET})")
+endfunction(install_manpage_symlink)
+
+set(MAN1_NOEXPAND pcap-config.1)
+set(MAN3PCAP_EXPAND
+    pcap.3pcap.in
+    pcap_compile.3pcap.in
+    pcap_datalink.3pcap.in
+    pcap_dump_open.3pcap.in
+    pcap_get_tstamp_precision.3pcap.in
+    pcap_list_datalinks.3pcap.in
+    pcap_list_tstamp_types.3pcap.in
+    pcap_open_dead.3pcap.in
+    pcap_open_offline.3pcap.in
+    pcap_set_immediate_mode.3pcap.in
+    pcap_set_tstamp_precision.3pcap.in
+    pcap_set_tstamp_type.3pcap.in
+)
+set(MAN3PCAP_NOEXPAND
+    pcap_activate.3pcap
+    pcap_breakloop.3pcap
+    pcap_can_set_rfmon.3pcap
+    pcap_close.3pcap
+    pcap_create.3pcap
+    pcap_datalink_name_to_val.3pcap
+    pcap_datalink_val_to_name.3pcap
+    pcap_dump.3pcap
+    pcap_dump_close.3pcap
+    pcap_dump_file.3pcap
+    pcap_dump_flush.3pcap
+    pcap_dump_ftell.3pcap
+    pcap_file.3pcap
+    pcap_fileno.3pcap
+    pcap_findalldevs.3pcap
+    pcap_freecode.3pcap
+    pcap_get_required_select_timeout.3pcap
+    pcap_get_selectable_fd.3pcap
+    pcap_geterr.3pcap
+    pcap_inject.3pcap
+    pcap_is_swapped.3pcap
+    pcap_lib_version.3pcap
+    pcap_lookupdev.3pcap
+    pcap_lookupnet.3pcap
+    pcap_loop.3pcap
+    pcap_major_version.3pcap
+    pcap_next_ex.3pcap
+    pcap_offline_filter.3pcap
+    pcap_open_live.3pcap
+    pcap_set_buffer_size.3pcap
+    pcap_set_datalink.3pcap
+    pcap_set_promisc.3pcap
+    pcap_set_protocol_linux.3pcap
+    pcap_set_rfmon.3pcap
+    pcap_set_snaplen.3pcap
+    pcap_set_timeout.3pcap
+    pcap_setdirection.3pcap
+    pcap_setfilter.3pcap
+    pcap_setnonblock.3pcap
+    pcap_snapshot.3pcap
+    pcap_stats.3pcap
+    pcap_statustostr.3pcap
+    pcap_strerror.3pcap
+    pcap_tstamp_type_name_to_val.3pcap
+    pcap_tstamp_type_val_to_name.3pcap
+)
+set(MANFILE_EXPAND pcap-savefile.manfile.in)
+set(MANMISC_EXPAND
+    pcap-filter.manmisc.in
+    pcap-linktype.manmisc.in
+    pcap-tstamp.manmisc.in
+)
+
+if(NOT BUILD_SHARED_LIBS)
+    unset(LIBRARY_NAME)
+endif(NOT BUILD_SHARED_LIBS)
+
+if(WIN32)
+    if(MSVC AND CMAKE_SIZEOF_VOID_P EQUAL 8)
+        #
+        # Install 64-bit code built with MSVC in the amd64 subdirectories,
+        # as that's where it expects it to be.
+        #
+        install(TARGETS ${LIBRARY_NAME} ${LIBRARY_NAME_STATIC}
+                RUNTIME DESTINATION bin/amd64
+                LIBRARY DESTINATION lib/amd64
+                ARCHIVE DESTINATION lib/amd64)
+        if(NOT MINGW)
+            install(FILES $<TARGET_FILE_DIR:${LIBRARY_NAME_STATIC}>/${LIBRARY_NAME_STATIC}.pdb
+                    DESTINATION bin/amd64 OPTIONAL)
+            if(BUILD_SHARED_LIBS)
+                install(FILES $<TARGET_PDB_FILE:${LIBRARY_NAME}>
+                        DESTINATION bin/amd64 OPTIONAL)
+            endif(BUILD_SHARED_LIBS)
+        endif(NOT MINGW)
+    else(MSVC AND CMAKE_SIZEOF_VOID_P EQUAL 8)
+        #
+        # Install 32-bit code, and 64-bit code not built with MSVC
+        # in the top-level directories, as those are where they
+        # expect it to be.
+        #
+        install(TARGETS ${LIBRARY_NAME} ${LIBRARY_NAME_STATIC}
+                RUNTIME DESTINATION bin
+                LIBRARY DESTINATION lib
+                ARCHIVE DESTINATION lib)
+        if(NOT MINGW)
+            install(FILES $<TARGET_FILE_DIR:${LIBRARY_NAME_STATIC}>/${LIBRARY_NAME_STATIC}.pdb
+                    DESTINATION bin OPTIONAL)
+            if(BUILD_SHARED_LIBS)
+                install(FILES $<TARGET_PDB_FILE:${LIBRARY_NAME}>
+                        DESTINATION bin OPTIONAL)
+            endif(BUILD_SHARED_LIBS)
+        endif(NOT MINGW)
+    endif(MSVC AND CMAKE_SIZEOF_VOID_P EQUAL 8)
+else(WIN32)
+    install(TARGETS ${LIBRARY_NAME} ${LIBRARY_NAME_STATIC} DESTINATION ${CMAKE_INSTALL_FULL_LIBDIR})
+endif(WIN32)
+
+install(DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/pcap/ DESTINATION include/pcap)
+install(FILES ${CMAKE_CURRENT_SOURCE_DIR}/pcap.h DESTINATION include)
+install(FILES ${CMAKE_CURRENT_SOURCE_DIR}/pcap-bpf.h DESTINATION include)
+install(FILES ${CMAKE_CURRENT_SOURCE_DIR}/pcap-namedb.h DESTINATION include)
+
+# On UN*X, and on Windows when not using MSVC, generate libpcap.pc and
+# pcap-config and process man pages and arrange that they be installed.
+if(NOT MSVC)
+    set(PACKAGE_NAME ${LIBRARY_NAME})
+    set(prefix ${CMAKE_INSTALL_PREFIX})
+    set(exec_prefix "\${prefix}")
+    set(includedir "\${prefix}/include")
+    set(libdir "\${exec_prefix}/lib")
+    if(CMAKE_SYSTEM_NAME STREQUAL "FreeBSD" OR
+       CMAKE_SYSTEM_NAME STREQUAL "NetBSD" OR
+       CMAKE_SYSTEM_NAME STREQUAL "OpenBSD" OR
+       CMAKE_SYSTEM_NAME STREQUAL "DragonFly BSD" OR
+       CMAKE_SYSTEM_NAME STREQUAL "Linux" OR
+       CMAKE_SYSTEM_NAME STREQUAL "OSF1")
+        #
+        # Platforms where the linker is the GNU linker
+        # or accepts command-line arguments like
+        # those the GNU linker accepts.
+        #
+        set(V_RPATH_OPT "-Wl,-rpath,")
+    elseif(CMAKE_SYSTEM_NAME STREQUAL "SunOS" AND CMAKE_SYSTEM_VERSION MATCHES "5[.][0-9.]*")
+        #
+        # SunOS 5.x.
+        #
+        # XXX - this assumes GCC is using the Sun linker,
+        # rather than the GNU linker.
+        #
+        set(V_RPATH_OPT "-Wl,-R,")
+    else()
+        #
+        # No option needed to set the RPATH.
+        #
+        set(V_RPATH_OPT "")
+    endif()
+    set(LIBS "")
+    foreach(LIB ${PCAP_LINK_LIBRARIES})
+        set(LIBS "${LIBS} -l${LIB}")
+    endforeach(LIB)
+    configure_file(${CMAKE_CURRENT_SOURCE_DIR}/pcap-config.in ${CMAKE_CURRENT_BINARY_DIR}/pcap-config @ONLY)
+    configure_file(${CMAKE_CURRENT_SOURCE_DIR}/libpcap.pc.in ${CMAKE_CURRENT_BINARY_DIR}/libpcap.pc @ONLY)
+    install(PROGRAMS ${CMAKE_CURRENT_BINARY_DIR}/pcap-config DESTINATION bin)
+    install(FILES ${CMAKE_CURRENT_BINARY_DIR}/libpcap.pc DESTINATION lib/pkgconfig)
+
+    #
+    # Man pages.
+    #
+    # For each section of the manual for which we have man pages
+    # that require macro expansion, do the expansion.
+    #
+    set(MAN1 "")
+    foreach(MANPAGE ${MAN1_NOEXPAND})
+        set(MAN1 ${MAN1} ${CMAKE_CURRENT_SOURCE_DIR}/${MANPAGE})
+    endforeach(MANPAGE)
+    install(FILES ${MAN1} DESTINATION ${CMAKE_INSTALL_MANDIR}/man1)
+
+    set(MAN3PCAP "")
+    foreach(MANPAGE ${MAN3PCAP_NOEXPAND})
+        set(MAN3PCAP ${MAN3PCAP} ${CMAKE_CURRENT_SOURCE_DIR}/${MANPAGE})
+    endforeach(MANPAGE)
+    foreach(TEMPLATE_MANPAGE ${MAN3PCAP_EXPAND})
+        string(REPLACE ".in" "" MANPAGE ${TEMPLATE_MANPAGE})
+        configure_file(${CMAKE_CURRENT_SOURCE_DIR}/${TEMPLATE_MANPAGE} ${CMAKE_CURRENT_BINARY_DIR}/${MANPAGE} @ONLY)
+        set(MAN3PCAP ${MAN3PCAP} ${CMAKE_CURRENT_BINARY_DIR}/${MANPAGE})
+    endforeach(TEMPLATE_MANPAGE)
+    install(FILES ${MAN3PCAP} DESTINATION ${CMAKE_INSTALL_MANDIR}/man3)
+    install_manpage_symlink(pcap_datalink_val_to_name.3pcap pcap_datalink_val_to_description.3pcap ${CMAKE_INSTALL_MANDIR}/man3)
+    install_manpage_symlink(pcap_dump_open.3pcap pcap_dump_fopen.3pcap ${CMAKE_INSTALL_MANDIR}/man3)
+    install_manpage_symlink(pcap_findalldevs.3pcap pcap_freealldevs.3pcap ${CMAKE_INSTALL_MANDIR}/man3)
+    install_manpage_symlink(pcap_geterr.3pcap pcap_perror.3pcap ${CMAKE_INSTALL_MANDIR}/man3)
+    install_manpage_symlink(pcap_inject.3pcap pcap_sendpacket.3pcap ${CMAKE_INSTALL_MANDIR}/man3)
+    install_manpage_symlink(pcap_list_datalinks.3pcap pcap_free_datalinks.3pcap ${CMAKE_INSTALL_MANDIR}/man3)
+    install_manpage_symlink(pcap_list_tstamp_types.3pcap pcap_free_tstamp_types.3pcap ${CMAKE_INSTALL_MANDIR}/man3)
+    install_manpage_symlink(pcap_loop.3pcap pcap_dispatch.3pcap ${CMAKE_INSTALL_MANDIR}/man3)
+    install_manpage_symlink(pcap_major_version.3pcap pcap_minor_version.3pcap ${CMAKE_INSTALL_MANDIR}/man3)
+    install_manpage_symlink(pcap_next_ex.3pcap pcap_next.3pcap ${CMAKE_INSTALL_MANDIR}/man3)
+    install_manpage_symlink(pcap_open_dead.3pcap pcap_open_dead_with_tstamp_precision.3pcap ${CMAKE_INSTALL_MANDIR}/man3)
+    install_manpage_symlink(pcap_open_offline.3pcap pcap_open_offline_with_tstamp_precision.3pcap ${CMAKE_INSTALL_MANDIR}/man3)
+    install_manpage_symlink(pcap_open_offline.3pcap pcap_fopen_offline.3pcap ${CMAKE_INSTALL_MANDIR}/man3)
+    install_manpage_symlink(pcap_open_offline.3pcap pcap_fopen_offline_with_tstamp_precision.3pcap ${CMAKE_INSTALL_MANDIR}/man3)
+    install_manpage_symlink(pcap_tstamp_type_val_to_name.3pcap pcap_tstamp_type_val_to_description.3pcap ${CMAKE_INSTALL_MANDIR}/man3)
+    install_manpage_symlink(pcap_setnonblock.3pcap pcap_getnonblock.3pcap ${CMAKE_INSTALL_MANDIR}/man3)
+
+    set(MANFILE "")
+    foreach(TEMPLATE_MANPAGE ${MANFILE_EXPAND})
+        string(REPLACE ".manfile.in" ".${MAN_FILE_FORMATS}" MANPAGE ${TEMPLATE_MANPAGE})
+        configure_file(${CMAKE_CURRENT_SOURCE_DIR}/${TEMPLATE_MANPAGE} ${CMAKE_CURRENT_BINARY_DIR}/${MANPAGE} @ONLY)
+        set(MANFILE ${MANFILE} ${CMAKE_CURRENT_BINARY_DIR}/${MANPAGE})
+    endforeach(TEMPLATE_MANPAGE)
+    install(FILES ${MANFILE} DESTINATION ${CMAKE_INSTALL_MANDIR}/man${MAN_FILE_FORMATS})
+
+    set(MANMISC "")
+    foreach(TEMPLATE_MANPAGE ${MANMISC_EXPAND})
+        string(REPLACE ".manmisc.in" ".${MAN_MISC_INFO}" MANPAGE ${TEMPLATE_MANPAGE})
+        configure_file(${CMAKE_CURRENT_SOURCE_DIR}/${TEMPLATE_MANPAGE} ${CMAKE_CURRENT_BINARY_DIR}/${MANPAGE} @ONLY)
+        set(MANMISC ${MANMISC} ${CMAKE_CURRENT_BINARY_DIR}/${MANPAGE})
+    endforeach(TEMPLATE_MANPAGE)
+    install(FILES ${MANMISC} DESTINATION ${CMAKE_INSTALL_MANDIR}/man${MAN_MISC_INFO})
+endif(NOT MSVC)
+
+# uninstall target
+configure_file(
+    "${CMAKE_CURRENT_SOURCE_DIR}/cmake_uninstall.cmake.in"
+    "${CMAKE_CURRENT_BINARY_DIR}/cmake_uninstall.cmake"
+    IMMEDIATE @ONLY)
+
+add_custom_target(uninstall
+    COMMAND ${CMAKE_COMMAND} -P ${CMAKE_CURRENT_BINARY_DIR}/cmake_uninstall.cmake)
diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md
new file mode 100644 (file)
index 0000000..69b5972
--- /dev/null
@@ -0,0 +1,29 @@
+Guidelines for contributing
+===========================
+
+To report a security issue (segfault, buffer overflow, infinite loop, arbitrary
+code execution etc) please send an e-mail to security@tcpdump.org, do not use
+the bug tracker!
+
+To report a non-security problem (failure to compile, failure to capture packets
+properly, missing support for a network interface type or DLT) please check
+first that it reproduces with the latest stable release of libpcap. If it does,
+please check that the problem reproduces with the current git master branch of
+libpcap. If it does (and it is not a security-related problem, otherwise see
+above), please navigate to https://github.com/the-tcpdump-group/libpcap/issues
+and check if the problem has already been reported. If it has not, please open
+a new issue and provide the following details:
+
+* libpcap version (e.g. from tcpdump --version)
+* operating system name and version and any other details that may be relevant
+  (uname -a, compiler name and version, CPU type etc.)
+* configure flags if any were used
+* statement of the problem
+* steps to reproduce
+
+Please note that if you know exactly how to solve the problem and the solution
+would not be too intrusive, it would be best to contribute some development time
+and open a pull request instead.
+
+Still not sure how to do? Feel free to [subscribe](https://www.tcpdump.org/#mailing-lists)
+to the mailing list tcpdump-workers@lists.tcpdump.org and ask!
diff --git a/CREDITS b/CREDITS
index dfc4e41..f7abc1f 100644 (file)
--- a/CREDITS
+++ b/CREDITS
@@ -1,20 +1,18 @@
-This file lists people who have contributed to libpcap:
+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>
-    Fulvio Risso                  <risso at polito dot it>
+The current maintainers (in alphabetical order):
+    Denis Ovsienko                <denis at ovsienko dot info>
+    Francois-Xavier Le Bail       <devel dot fx dot lebail at orange dot fr>
     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>
 
-Additional people who have contributed patches:
-
+Additional people who have contributed patches (in alphabetical order):
     Akos Vandra                   <axos88 at gmail dot com>
     Alan Bawden                   <Alan at LCS dot MIT dot EDU>
     Albert Chin                   <china at thewrittenword dot com>
     Alexander 'Leo' Bergolth      <Leo dot Bergolth at wu-wien dot ac dot at>
     Alexey Kuznetsov              <kuznet at ms2 dot inr dot ac dot ru>
+    Ali Abdulkadir                <autostart dot ini at gmail dot com>
     Alon Bar-Lev                  <alonbl at sourceforge dot net>
     Andres Perera                 <andres dot p at zoho dot com>
     Andrew Brown                  <atatat at atatdot dot net>
@@ -45,7 +43,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>
@@ -61,9 +59,10 @@ Additional people who have contributed patches:
     Gabor Tatarka                 <gabor dot tatarka at ericsson dot com>
     Garrett Cooper                <yaberauneya at sourceforge dot net>
     George Neville-Neil           <gnn at freebsd dot org>
+    Gerard Garcia                 <nouboh at gmail dot com>
     Gianluca Varenni              <gianluca dot varenni at gmail dot com>
     Gilbert Hoyek                 <gil_hoyek at hotmail dot com>
-    Gisle Vanem                   <gvanem at broadpark dot no>
+    Gisle Vanem                   <gvanem at yahoo dot no>
     Graeme Hewson                 <ghewson at cix dot compulink dot co dot uk>
     Gregor Maier                  <gregor at net dot in dot tum dot de>
     Greg Stark                    <gsstark at mit dot edu>
@@ -83,6 +82,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>
@@ -97,6 +97,7 @@ Additional people who have contributed patches:
     Koryn Grant                   <koryn at endace dot com>
     Kris Katterjohn               <katterjohn at gmail dot com>
     Krzysztof Halasa              <khc at pm dot waw dot pl>
+    Lennert Buytenhek             <buytenh at wantstofly dot org>
     Lorenzo Cavallaro             <sullivan at sikurezza dot org>
     Loris Degioanni               <loris at netgroup-serv dot polito dot it>
     Love Hörnquist-Ã…strand        <lha at stacken dot kth dot se>
@@ -105,12 +106,14 @@ 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>
     Márton Németh                 <nm127 at freemail dot hu>
     Matthew Luckie                <mjl at luckie dot org dot nz>
     Max Laier                     <max at love2party dot net>
+    Michal Kubecek                <mkubecek at suse dot cz>
     Michal Labedzki               <michal dot labedzki at tieto dot com>
     Michal Sekletar               <msekleta at redhat dot com>
     Mike Frysinger                <vapier at gmail dot com>
@@ -126,7 +129,7 @@ Additional people who have contributed patches:
     Olaf Kirch                    <okir at caldera dot de>
     Ollie Wild                    <aaw at users dot sourceforge dot net>
     Onno van der Linden           <onno at simplex dot nl>
-    Paolo Abeni                   <paolo dot abeni at email dot it>
+    Paolo Abeni                   <pabeni at redhat dot com>
     Patrick Marie                 <mycroft at virgaria dot org>
     Patrick McHardy               <kaber at trash not net>
     Paul Mundt                    <lethal at linux-sh dot org>
@@ -142,6 +145,8 @@ Additional people who have contributed patches:
     Rick Jones                    <raj at cup dot hp dot com>
     Robert Edmonds                <stu-42 at sourceforge dot net>
     Roberto Mariani               <jelot-tcpdump at jelot dot it>
+    Rongxi Li                     <rongxi dot li at chaitin dot com>
+    Roland Dreier                 <roland at purestorage dot com>
     Romain Francoise              <rfrancoise at debian dot org>
     Sagun Shakya                  <sagun dot shakya at sun dot com>
     Scott Barron                  <sb125499 at ohiou dot edu>
@@ -164,6 +169,7 @@ Additional people who have contributed patches:
     Wesley Shields                <wxs at FreeBSD dot org>
     Xianjie Zhang                 <xzhang at cup dot hp dot com>
     Xin Li                        <delphij at FreeBSD dot org>
+    Xue Jiang Qing                <xuejianqing at star-net dot cn>
     Yen Yen Lim
     Yoann Vandoorselaere          <yoann at prelude-ids dot org>
     Yvan Vanhullebus              <vanhu at sourceforge dot net>
@@ -173,5 +179,8 @@ The original LBL crew:
     Craig Leres
     Van Jacobson
 
-Past maintainers:
-    Jun-ichiro itojun Hagino         <itojun at iijlab dot net>                Also see: http://www.wide.ad.jp/itojun-award/
+Past maintainers (in alphabetical order):
+    Bill Fenner                   <fenner at research dot att dot com>
+    Fulvio Risso                  <risso at polito dot it>
+    Hannes Gredler                <hannes at gredler dot at>
+    Jun-ichiro itojun Hagino      <itojun at iijlab dot net>           Also see: http://www.wide.ad.jp/itojun-award/
similarity index 78%
rename from INSTALL.txt
rename to INSTALL.md
index 7bbbf0c..3a303fe 100644 (file)
@@ -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
@@ -87,10 +69,6 @@ before /usr/ucb or else:
 before running configure. (You might have to do a "make distclean"
 if you already ran configure once).
 
-Also note that "make depend" won't work; while all of the known
-universe uses -M, the SPARCompiler uses -xM to generate makefile
-dependencies.
-
 If you are trying to do packet capture with a FORE ATM card, you may or
 may not be able to. They usually only release their driver in object
 code so unless their driver supports packet capture, there's not much
@@ -178,14 +156,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 +217,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:
 
@@ -268,56 +246,40 @@ libpcap program and it dies with:
 You must add streams NIT support to your kernel configuration, run
 config and boot the new kernel.
 
-If you are running a version of SunOS earlier than 4.1, you will need
-to replace the Sun supplied /sys/sun{3,4,4c}/OBJ/nit_if.o with the
-appropriate version from this distribution's SUNOS4 subdirectory and
-build a new kernel:
-
-       nit_if.o.sun3-sunos4            (any flavor of sun3)
-       nit_if.o.sun4c-sunos4.0.3c      (SS1, SS1+, IPC, SLC, etc.)
-       nit_if.o.sun4-sunos4            (Sun4's not covered by
-                                           nit_if.o.sun4c-sunos4.0.3c)
-
-These nit replacements fix a bug that makes nit essentially unusable in
-pre-SunOS 4.1.  In addition, our sun4c-sunos4.0.3c nit gives you
-timestamps to the resolution of the SS-1 clock (1 us) rather than the
-lousy 20ms timestamps Sun gives you  (tcpdump will print out the full
-timestamp resolution if it finds it's running on a SS-1).
-
 FILES
 -----
 CHANGES                - description of differences between releases
-ChmodBPF/*     - Mac OS X startup item to set ownership and permissions
+ChmodBPF/*     - macOS startup item to set ownership and permissions
                  on /dev/bpf*
+CMakeLists.txt - CMake file
+CONTRIBUTING   - guidelines for contributing
 CREDITS                - people that have helped libpcap along
-INSTALL.txt    - this file
+INSTALL.md     - this file
 LICENSE                - the license under which tcpdump is distributed
 Makefile.in    - compilation rules (input to the configure script)
-README         - description of distribution
-README.aix     - notes on using libpcap on AIX
-README.dag     - notes on using libpcap to capture on Endace DAG devices
-README.hpux    - notes on using libpcap on HP-UX
-README.linux   - notes on using libpcap on Linux
-README.macosx  - notes on using libpcap on Mac OS X
-README.septel   - notes on using libpcap to capture on Intel/Septel devices
-README.sita    - notes on using libpcap to capture on SITA devices
-README.tru64   - notes on using libpcap on Digital/Tru64 UNIX
-README.Win32   - notes on using libpcap on Win32 systems (with WinPcap)
-SUNOS4         - pre-SunOS 4.1 replacement kernel nit modules
+README.md      - description of distribution
+doc/README.aix - notes on using libpcap on AIX
+doc/README.dag - notes on using libpcap to capture on Endace DAG devices
+doc/README.hpux        - notes on using libpcap on HP-UX
+doc/README.linux.md - notes on using libpcap on Linux
+doc/README.macos       - notes on using libpcap on macOS
+doc/README.septel   - notes on using libpcap to capture on Intel/Septel devices
+doc/README.sita        - notes on using libpcap to capture on SITA devices
+doc/README.tru64       - notes on using libpcap on Digital/Tru64 UNIX
+doc/README.Win32       - notes on using libpcap on Win32 systems (with Npcap)
 VERSION                - version of this release
 acconfig.h     - support for post-2.13 autoconf
 aclocal.m4     - autoconf macros
 arcnet.h       - ARCNET definitions
 atmuni31.h     - ATM Q.2931 definitions
-bpf/net                - copy of bpf_filter.c
 bpf_dump.c     - BPF program printing routines
-bpf_filter.c   - symlink to bpf/net/bpf_filter.c
+bpf_filter.c   - BPF filtering routines
 bpf_image.c    - BPF disassembly routine
 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,16 +287,12 @@ 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
 gencode.h      - BPF code generation definitions
 grammar.y      - filter string grammar
 ieee80211.h    - 802.11 definitions
-inet.c         - network routines
 install-sh     - BSD style install script
 lbl/os-*.h     - OS-dependent defines and prototypes
 llc.h          - 802.2 LLC SAP definitions
@@ -345,7 +303,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
@@ -368,6 +325,7 @@ pcap-linux.c        - Linux packet socket support
 pcap-namedb.h  - header for backwards compatibility
 pcap-nit.c     - SunOS Network Interface Tap support
 pcap-nit.h     - SunOS Network Interface Tap definitions
+pcap-npf.c     - WinPcap capture support
 pcap-null.c    - dummy monitor support (allows offline use of libpcap)
 pcap-pf.c      - Ultrix and Digital/Tru64 UNIX Packet Filter support
 pcap-pf.h      - Ultrix and Digital/Tru64 UNIX Packet Filter definitions
@@ -381,7 +339,6 @@ pcap-snit.c - SunOS 4.x STREAMS-based Network Interface Tap support
 pcap-snoop.c   - IRIX Snoop network monitoring support
 pcap-usb-linux.c - USB capture support for Linux
 pcap-usb-linux.h - USB capture support for Linux
-pcap-win32.c   - WinPcap capture support
 pcap.3pcap     - manual entry for the library
 pcap.c         - pcap utility routines
 pcap.h         - header for backwards compatibility
@@ -389,7 +346,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/LICENSE b/LICENSE
index dea5f7d..a10474d 100644 (file)
--- a/LICENSE
+++ b/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.
index 7bf6420..fea63bb 100644 (file)
@@ -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
 
index 1c2d745..5a6b165 100644 (file)
@@ -27,6 +27,8 @@ exec_prefix = @exec_prefix@
 datarootdir = @datarootdir@
 # Pathname of directory to install the configure program
 bindir = @bindir@
+# Pathname of directory to install the rpcapd daemon
+sbindir = @sbindir@
 # Pathname of directory to install the include files
 includedir = @includedir@
 # Pathname of directory to install the library
@@ -48,33 +50,34 @@ AR = @AR@
 LN_S = @LN_S@
 MKDEP = @MKDEP@
 CCOPT = @V_CCOPT@
+SHLIB_CCOPT = @V_SHLIB_CCOPT@
 INCLS = -I. @V_INCLS@
-DEFS = @DEFS@ @V_DEFS@
+DEFS = -DBUILDING_PCAP -Dpcap_EXPORTS @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@
 PROG=libpcap
+PTHREAD_LIBS=@PTHREAD_LIBS@
+BUILD_RPCAPD=@BUILD_RPCAPD@
+INSTALL_RPCAPD=@INSTALL_RPCAPD@
+EXTRA_NETWORK_LIBS=@EXTRA_NETWORK_LIBS@
 
-# Standard CFLAGS
-FULL_CFLAGS = $(CCOPT) $(INCLS) $(DEFS) $(CFLAGS)
+# Standard CFLAGS for building members of a shared library
+FULL_CFLAGS = $(CCOPT) @V_LIB_CCOPT_FAT@ $(SHLIB_CCOPT) $(INCLS) $(DEFS) $(CFLAGS)
 
 INSTALL = @INSTALL@
 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,13 +86,14 @@ 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@ @NETMAP_SRC@ @RDMA_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 \
-       bpf_image.c bpf_dump.c
-GENSRC = scanner.c grammar.c bpf_filter.c version.c
+CSRC = pcap.c gencode.c optimize.c nametoaddr.c etherent.c \
+       fmtutils.c \
+       savefile.c sf-pcap.c sf-pcapng.c pcap-common.c \
+       bpf_image.c bpf_filter.c bpf_dump.c
+GENSRC = scanner.c grammar.c
 LIBOBJS = @LIBOBJS@
 
 SRC =  $(PSRC) $(FSRC) $(CSRC) $(SSRC) $(GENSRC)
@@ -103,56 +107,55 @@ PUBHDR = \
        pcap-namedb.h \
        pcap/bpf.h \
        pcap/bluetooth.h \
+       pcap/can_socketcan.h \
+       pcap/compiler-tests.h \
+       pcap/dlt.h \
+       pcap/funcattrs.h \
+       pcap/pcap-inttypes.h \
        pcap/ipnet.h \
        pcap/namedb.h \
        pcap/nflog.h \
        pcap/pcap.h \
        pcap/sll.h \
+       pcap/socket.h \
        pcap/vlan.h \
        pcap/usb.h
 
 HDR = $(PUBHDR) \
        arcnet.h \
        atmuni31.h \
+       diag-control.h \
        ethertype.h \
+       extract.h \
+       fmtutils.h \
+       ftmacros.h \
        gencode.h \
        ieee80211.h \
        llc.h \
+       nametoaddr.h \
        nlpid.h \
+       optimize.h \
        pcap-common.h \
        pcap-int.h \
-       pcap-stdinc.h \
+       pcap-rpcap.h \
+       pcap-types.h \
+       portability.h \
        ppp.h \
+       rpcap-protocol.h \
        sf-pcap.h \
-       sf-pcap-ng.h \
-       sunatmpos.h
-
-TESTS = \
-       capturetest \
-       filtertest \
-       findalldevstest \
-       opentest \
-       selpolltest \
-       valgrindtest
-
-TESTS_SRC = \
-       tests/capturetest.c \
-       tests/filtertest.c \
-       tests/findalldevstest.c \
-       tests/opentest.c \
-       tests/reactivatetest.c \
-       tests/selpolltest.c \
-       tests/valgrindtest.c
+       sf-pcapng.h \
+       sunatmpos.h \
+       varattrs.h
 
 GENHDR = \
-       scanner.h tokdefs.h version.h
+       scanner.h grammar.h
 
 TAGFILES = \
        $(SRC) $(HDR)
 
-CLEANFILES = $(OBJ) libpcap.* $(TESTS) \
+CLEANFILES = $(OBJ) libpcap.a libpcap.so.`cat $(srcdir)/VERSION` \
        $(PROG)-`cat $(srcdir)/VERSION`.tar.gz $(GENSRC) $(GENHDR) \
-       lex.yy.c pcap-config
+       lex.yy.c pcap-config libpcap.pc
 
 MAN1 = pcap-config.1
 
@@ -166,6 +169,7 @@ MAN3PCAP_EXPAND = \
        pcap_list_tstamp_types.3pcap.in \
        pcap_open_dead.3pcap.in \
        pcap_open_offline.3pcap.in \
+       pcap_set_immediate_mode.3pcap.in \
        pcap_set_tstamp_precision.3pcap.in \
        pcap_set_tstamp_type.3pcap.in
 
@@ -186,6 +190,7 @@ MAN3PCAP_NOEXPAND = \
        pcap_fileno.3pcap \
        pcap_findalldevs.3pcap \
        pcap_freecode.3pcap \
+       pcap_get_required_select_timeout.3pcap \
        pcap_get_selectable_fd.3pcap \
        pcap_geterr.3pcap \
        pcap_inject.3pcap \
@@ -200,8 +205,8 @@ MAN3PCAP_NOEXPAND = \
        pcap_open_live.3pcap \
        pcap_set_buffer_size.3pcap \
        pcap_set_datalink.3pcap \
-       pcap_set_immediate_mode.3pcap \
        pcap_set_promisc.3pcap \
+       pcap_set_protocol_linux.3pcap \
        pcap_set_rfmon.3pcap \
        pcap_set_snaplen.3pcap \
        pcap_set_timeout.3pcap \
@@ -226,86 +231,84 @@ MANMISC = \
        pcap-tstamp.manmisc.in
 
 EXTRA_DIST = \
-       $(TESTS_SRC) \
        CHANGES \
        ChmodBPF/ChmodBPF \
        ChmodBPF/StartupParameters.plist \
        CREDITS \
-       INSTALL.txt \
+       CMakeLists.txt \
+       INSTALL.md \
        LICENSE \
        Makefile.in \
        Makefile-devel-adds \
-       README \
-       README.aix \
-       README.dag \
-       README.hpux \
-       README.linux \
-       README.macosx \
-       README.septel \
-       README.sita \
-       README.tru64 \
-       README.Win32 \
-       SUNOS4/nit_if.o.sparc \
-       SUNOS4/nit_if.o.sun3 \
-       SUNOS4/nit_if.o.sun4c.4.0.3c \
+       README.md \
+       doc \
+       CONTRIBUTING.md \
        TODO \
        VERSION \
        aclocal.m4 \
-       bpf/net/bpf_filter.c \
        chmod_bpf \
+       cmake_uninstall.cmake.in \
+       cmakeconfig.h.in \
+       cmake/Modules/FindDAG.cmake \
+       cmake/Modules/FindFseeko.cmake \
+       cmake/Modules/FindLFS.cmake \
+       cmake/Modules/FindPacket.cmake \
+       cmake/Modules/FindSNF.cmake \
+       cmake/Modules/FindTC.cmake \
+       cmake/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 \
        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 \
+       libpcap.pc.in \
+       missing/asprintf.c \
+       missing/getopt.c \
+       missing/getopt.h \
        missing/snprintf.c \
+       missing/strlcat.c \
+       missing/strlcpy.c \
+       missing/strtok_r.c \
+       missing/win_asprintf.c \
+       missing/win_snprintf.c \
        mkdep \
        msdos/bin2c.c \
-       msdos/common.dj \
        msdos/makefile \
        msdos/makefile.dj \
        msdos/makefile.wc \
-       msdos/ndis2.c \
-       msdos/ndis2.h \
-       msdos/ndis_0.asm \
        msdos/pkt_rx0.asm \
        msdos/pkt_rx1.s \
        msdos/pktdrvr.c \
        msdos/pktdrvr.h \
        msdos/readme.dos \
+       nomkdep \
        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 \
        pcap-dbus.c \
        pcap-dbus.h \
+       pcap-dll.rc \
        pcap-dlpi.c \
        pcap-dos.c \
        pcap-dos.h \
@@ -314,11 +317,19 @@ EXTRA_DIST = \
        pcap-libdlpi.c \
        pcap-linux.c \
        pcap-namedb.h \
+       pcap-new.c \
        pcap-netfilter-linux.c \
        pcap-netfilter-linux.h \
+       pcap-netmap.c \
+       pcap-netmap.h \
        pcap-nit.c \
+       pcap-npf.c \
        pcap-null.c \
        pcap-pf.c \
+       pcap-rdmasniff.c \
+       pcap-rdmasniff.h \
+       pcap-rpcap.c \
+       pcap-rpcap-int.h \
        pcap-septel.c \
        pcap-septel.h \
        pcap-sita.h \
@@ -328,36 +339,53 @@ 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 \
+       rpcap-protocol.c \
+       rpcapd/CMakeLists.txt \
+       rpcapd/Makefile.in \
+       rpcapd/config_params.h \
+       rpcapd/daemon.h \
+       rpcapd/daemon.c \
+       rpcapd/fileconf.c \
+       rpcapd/fileconf.h \
+       rpcapd/log.h \
+       rpcapd/log.c \
+       rpcapd/org.tcpdump.rpcapd.plist \
+       rpcapd/rpcapd.c \
+       rpcapd/rpcapd.h \
+       rpcapd/rpcapd.inetd.conf \
+       rpcapd/rpcapd.manadmin.in \
+       rpcapd/rpcapd-config.manfile.in \
+       rpcapd/rpcapd.rc \
+       rpcapd/rpcapd.socket \
+       rpcapd/rpcapd.xinetd.conf \
+       rpcapd/rpcapd@.service \
+       rpcapd/win32-svc.c \
+       rpcapd/win32-svc.h \
+       sockutils.c \
+       sockutils.h \
        scanner.l \
-       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
-
-all: libpcap.a shared pcap-config
+       testprogs/CMakeLists.txt \
+       testprogs/Makefile.in \
+       testprogs/can_set_rfmon_test.c \
+       testprogs/capturetest.c \
+       testprogs/filtertest.c \
+       testprogs/findalldevstest.c \
+       testprogs/opentest.c \
+       testprogs/reactivatetest.c \
+       testprogs/selpolltest.c \
+       testprogs/threadsignaltest.c \
+       testprogs/unix.h \
+       testprogs/valgrindtest.c \
+       tests/shb-option-too-long.pcapng \
+       Win32/Prj/wpcap.sln \
+       Win32/Prj/wpcap.vcxproj \
+       Win32/Prj/wpcap.vcxproj.filters
+
+all: libpcap.a shared $(BUILD_RPCAPD) libpcap.pc pcap-config
 
 libpcap.a: $(OBJ)
        @rm -f $@
@@ -370,20 +398,18 @@ libpcap.so: $(OBJ)
        @rm -f $@
        VER=`cat $(srcdir)/VERSION`; \
        MAJOR_VER=`sed 's/\([0-9][0-9]*\)\..*/\1/' $(srcdir)/VERSION`; \
-       @V_SHLIB_CMD@ @V_SHLIB_OPT@ @V_SONAME_OPT@$@.$$MAJOR_VER $(LDFLAGS) \
+       @V_SHLIB_CMD@ $(LDFLAGS) @V_SHLIB_OPT@ @V_SONAME_OPT@$@.$$MAJOR_VER \
            -o $@.$$VER $(OBJ) $(ADDLOBJS) $(LIBS)
 
 #
 # The following rule succeeds, but the result is untested.
 #
-# In Mac OS X, the libpcap dylib has the name "libpcap.A.dylib", with
-# its full path as the install_name, and with the compatibility and
-# current version both set to 1.  The compatibility version is set to
-# 1 so that programs built with a newer version of the library will run
-# against older versions; multi-platform software probably will fail if
-# it uses APIs added in the newer version, but Mac OS X-specific software
-# will use weak linking and check at run time whether those APIs are
-# available.
+# In macOS, the libpcap dylib has the name "libpcap.A.dylib", with its
+# full path as the install_name, and with the compatibility and current
+# version both set to 1.  The compatibility version is set to 1 so that
+# programs built with a newer version of the library will run against
+# older versions if they don't use APIs available in the newer version
+# but not in the older version.
 #
 # We also use "A" as the major version, and 1 as the compatibility version,
 # but set the current version to the value in VERSION, with any non-numeric
@@ -397,7 +423,7 @@ libpcap.dylib: $(OBJ)
        MAJOR_VER=A; \
        COMPAT_VER=1; \
        CURRENT_VER=`sed 's/[^0-9.].*$$//' $(srcdir)/VERSION`; \
-       $(CC) -dynamiclib -undefined error $(LDFLAGS) \
+       $(CC) -dynamiclib -undefined error $(LDFLAGS) @V_LIB_LDFLAGS_FAT@ \
            -o libpcap.$$VER.dylib $(OBJ) $(ADDLOBJS) $(LIBS) \
            -install_name $(libdir)/libpcap.$$MAJOR_VER.dylib \
            -compatibility_version $$COMPAT_VER \
@@ -433,7 +459,7 @@ libpcap.sl: $(OBJ)
 #
 libpcap.shareda: $(OBJ)
        @rm -f $@ shr.o
-       $(CC) @V_SHLIB_OPT@ -o shr.o $(OBJ) $(ADDLOBJS) $(LDFLAGS) $(LIBS)
+       $(CC) $(LDFLAGS) @V_SHLIB_OPT@ -o shr.o $(OBJ) $(ADDLOBJS) $(LIBS)
        $(AR) rc $@ shr.o
 
 #
@@ -443,67 +469,49 @@ 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
-
-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
+grammar.o: grammar.c scanner.h
+       $(CC) $(FULL_CFLAGS) -c grammar.c
 
-version.o: version.c
-       $(CC) $(FULL_CFLAGS) -c version.c
+gencode.o: $(srcdir)/gencode.c grammar.h scanner.h
+       $(CC) $(FULL_CFLAGS) -c $(srcdir)/gencode.c
+
+asprintf.o: $(srcdir)/missing/asprintf.c
+       $(CC) $(FULL_CFLAGS) -o $@ -c $(srcdir)/missing/asprintf.c
 
 snprintf.o: $(srcdir)/missing/snprintf.c
        $(CC) $(FULL_CFLAGS) -o $@ -c $(srcdir)/missing/snprintf.c
 
-version.c: $(srcdir)/VERSION
-       @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[] = "&";/' > $@
-
-#
-# 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
-       @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 &";/' > $@
+strlcat.o: $(srcdir)/missing/strlcat.c
+       $(CC) $(FULL_CFLAGS) -o $@ -c $(srcdir)/missing/strlcat.c
 
-bpf_filter.c: $(srcdir)/bpf/net/bpf_filter.c
-       rm -f bpf_filter.c
-       ln -s $(srcdir)/bpf/net/bpf_filter.c bpf_filter.c
+strlcpy.o: $(srcdir)/missing/strlcpy.c
+       $(CC) $(FULL_CFLAGS) -o $@ -c $(srcdir)/missing/strlcpy.c
 
-bpf_filter.o: bpf_filter.c
-       $(CC) $(FULL_CFLAGS) -c bpf_filter.c
+strtok_r.o: $(srcdir)/missing/strtok_r.c
+       $(CC) $(FULL_CFLAGS) -o $@ -c $(srcdir)/missing/strtok_r.c
 
 #
-# Generate the pcap-config script.
+# Generate the libpcap.pc file.
 #
 # Some Makes, e.g. AIX Make and Solaris Make, can't handle "--file=$@.tmp:$<";
 # for example, the Solaris 9 make man page says
@@ -514,7 +522,16 @@ bpf_filter.o: bpf_filter.c
 #
 # and this is an explicit target entry.
 #
-# Therefore, instead of using $<, we explicitly put in $(srcdir)/pcap-config.in.
+# Therefore, instead of using $<, we explicitly put in $(srcdir)/libpcap.pc.in.
+#
+libpcap.pc: $(srcdir)/libpcap.pc.in ./config.status
+       @rm -f $@ $@.tmp
+       ./config.status --file=$@.tmp:$(srcdir)/libpcap.pc.in
+       mv $@.tmp $@
+       chmod a+x $@
+
+#
+# Generate the pcap-config script.  See above.
 #
 pcap-config: $(srcdir)/pcap-config.in ./config.status
        @rm -f $@ $@.tmp
@@ -523,29 +540,20 @@ pcap-config: $(srcdir)/pcap-config.in ./config.status
        chmod a+x $@
 
 #
-# Test programs - not built by default, and not installed.
+# Remote pcap daemon.
 #
-tests: $(TESTS)
-
-capturetest: tests/capturetest.c libpcap.a
-       $(CC) $(FULL_CFLAGS) -I. -L. -o capturetest $(srcdir)/tests/capturetest.c libpcap.a $(LIBS)
+build-rpcapd: libpcap.a
+       cd rpcapd; $(MAKE)
 
-filtertest: tests/filtertest.c libpcap.a
-       $(CC) $(FULL_CFLAGS) -I. -L. -o filtertest $(srcdir)/tests/filtertest.c libpcap.a $(LIBS)
-
-findalldevstest: tests/findalldevstest.c libpcap.a
-       $(CC) $(FULL_CFLAGS) -I. -L. -o findalldevstest $(srcdir)/tests/findalldevstest.c libpcap.a $(LIBS)
-
-opentest: tests/opentest.c libpcap.a
-       $(CC) $(FULL_CFLAGS) -I. -L. -o opentest $(srcdir)/tests/opentest.c libpcap.a $(LIBS)
-
-selpolltest: tests/selpolltest.c libpcap.a
-       $(CC) $(FULL_CFLAGS) -I. -L. -o selpolltest $(srcdir)/tests/selpolltest.c libpcap.a $(LIBS)
+#
+# Test programs - not built by default, and not installed.
+#
+testprogs: FORCE
+       cd testprogs; $(MAKE)
 
-valgrindtest: tests/valgrindtest.c libpcap.a
-       $(CC) $(FULL_CFLAGS) -I. -L. -o valgrindtest $(srcdir)/tests/valgrindtest.c libpcap.a $(LIBS)
+FORCE:
 
-install: install-shared install-archive pcap-config
+install: install-shared install-archive libpcap.pc pcap-config @INSTALL_RPCAPD@
        [ -d $(DESTDIR)$(libdir) ] || \
            (mkdir -p $(DESTDIR)$(libdir); chmod 755 $(DESTDIR)$(libdir))
        [ -d $(DESTDIR)$(includedir) ] || \
@@ -566,6 +574,9 @@ install: install-shared install-archive pcap-config
        [ -d $(DESTDIR)$(bindir) ] || \
            (mkdir -p $(DESTDIR)$(bindir); chmod 755 $(DESTDIR)$(bindir))
        $(INSTALL_PROGRAM) pcap-config $(DESTDIR)$(bindir)/pcap-config
+       [ -d $(DESTDIR)$(libdir)/pkgconfig ] || \
+           (mkdir -p $(DESTDIR)$(libdir)/pkgconfig; chmod 755 $(DESTDIR)$(libdir)/pkgconfig)
+       $(INSTALL_DATA) libpcap.pc $(DESTDIR)$(libdir)/pkgconfig/libpcap.pc
        for i in $(MAN1); do \
                $(INSTALL_DATA) $(srcdir)/$$i \
                    $(DESTDIR)$(mandir)/man1/$$i; done
@@ -579,6 +590,9 @@ install: install-shared install-archive pcap-config
        rm -f pcap_datalink_val_to_description.3pcap && \
        $(LN_S) pcap_datalink_val_to_name.3pcap \
                 pcap_datalink_val_to_description.3pcap && \
+       rm -f pcap_datalink_val_to_description_or_dlt.3pcap && \
+       $(LN_S) pcap_datalink_val_to_name.3pcap \
+                pcap_datalink_val_to_description_or_dlt.3pcap && \
        rm -f pcap_dump_fopen.3pcap && \
        $(LN_S) pcap_dump_open.3pcap pcap_dump_fopen.3pcap && \
        rm -f pcap_freealldevs.3pcap && \
@@ -666,11 +680,15 @@ install-archive-shareda:
        # library on AIX.
        #
 
-uninstall: uninstall-shared
+install-rpcapd:
+       cd rpcapd; $(MAKE) DESTDIR=$(DESTDIR) install
+
+uninstall: uninstall-shared uninstall-rpcapd
        rm -f $(DESTDIR)$(libdir)/libpcap.a
        for i in $(PUBHDR); do \
                rm -f $(DESTDIR)$(includedir)/$$i; done
        -rmdir $(DESTDIR)$(includedir)/pcap
+       rm -f $(DESTDIR)/$(libdir)/pkgconfig/libpcap.pc
        rm -f $(DESTDIR)/$(bindir)/pcap-config
        for i in $(MAN1); do \
                rm -f $(DESTDIR)$(mandir)/man1/$$i; done
@@ -718,31 +736,39 @@ uninstall-shared-shareda:
        rm -f $(DESTDIR)$(libdir)/libpcap.a
 uninstall-shared-none:
 
+uninstall-rpcapd:
+       cd rpcapd; $(MAKE) DESTDIR=$(DESTDIR) uninstall
+
 clean:
        rm -f $(CLEANFILES)
+       cd rpcapd; $(MAKE) clean
+       cd testprogs; $(MAKE) clean
 
 distclean: clean
        rm -f Makefile config.cache config.log config.status \
-           config.h gnuc.h net os-proto.h bpf_filter.c pcap-config \
-           stamp-h stamp-h.in
+           config.h gnuc.h net os-proto.h libpcap.pc \
+           pcap-config stamp-h stamp-h.in
        rm -f $(MAN3PCAP_EXPAND:.in=) $(MANFILE:.in=) $(MANMISC:.in=)
        rm -rf autom4te.cache
+       cd rpcapd; $(MAKE) distclean
+       cd testprogs; $(MAKE) distclean
+
+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; \
-          tar cf - $(CSRC) $(HDR) $(MAN1) $(MAN3PCAP_EXPAND) \
+          tar -c --exclude='*~' -f - $(CSRC) $(HDR) $(MAN1) $(MAN3PCAP_EXPAND) \
              $(MAN3PCAP_NOEXPAND) $(MANFILE) $(MANMISC) $(EXTRA_DIST) | \
              (cd $$name; tar xf -); \
           tar -c -z -f $$name.tar.gz $$name; \
           rm -rf $$name
 
-depend:        $(GENSRC) $(GENHDR) bpf_filter.c
-       $(MKDEP) -c $(CC) -m $(CFLAGS) $(DEPENDENCY_CFLAG) $(DEFS) $(INCLS) $(SRC)
+depend:        $(GENSRC) $(GENHDR)
+       $(MKDEP) -c "$(CC)" -m "$(DEPENDENCY_CFLAG)" $(CFLAGS) $(DEFS) $(INCLS) $(SRC)
+       cd rpcapd; $(MAKE) depend
+       cd testprogs; $(MAKE) depend
diff --git a/README.Win32 b/README.Win32
deleted file mode 100644 (file)
index 503836e..0000000
+++ /dev/null
@@ -1,46 +0,0 @@
-Under Win32, libpcap is integrated in the WinPcap packet capture system. 
-WinPcap provides a framework that allows libpcap to capture the packets 
-under Windows 95, Windows 98, Windows ME, Windows NT 4, Windows 2000 
-and Windows XP.
-WinPcap binaries and source code can be found at http://winpcap.polito.it: 
-they include also a developer's pack with all the necessary to compile 
-libpcap-based applications under Windows.
-
-How to compile libpcap with Visual Studio
------------------------------------------
-
-In order to compile libpcap you will need:
-
-- version 6 (or higher) of Microsoft Visual Studio
-- The November 2001 (or later) edition of Microsoft Platform 
-Software Development Kit (SDK), that contains some necessary includes 
-for IPv6 support. You can download it from http://www.microsoft.com/sdk
-- the latest WinPcap sources from http://winpcap.polito.it/install 
-
-The WinPcap source code already contains a recent (usually the latest 
-stable) version of libpcap. If you need to compile a different one, 
-simply download it from www.tcpdump.org and copy the sources in the 
-winpcap\wpcap\libpcap folder of the WinPcap distribution. If you want to
-compile a libpcap source retrieved from the tcpdump.org Git, you will 
-have to create the scanner and the grammar by hand (with lex and yacc) 
-or with the cygnus makefile, since The Visual Studio project is not able
-to build them.
-
-Open the project file winpcap\wpcap\prj\wpcap.dsw with Visual Studio and 
-build wpcap.dll. wpcap.lib, the library file to link with the applications, 
-will be generated in winpcap\wpcap\lib\. wpcap.dll will be generated in 
-winpcap\wpcap\prj\release or winpcap\wpcap\prj\debug depending on the type 
-of binary that is being created.
-
-How to compile libpcap with Cygnus
-----------------------------------
-
-To build wpcap.dll, cd to the directory WPCAP/PRJ of the WinPcap source code 
-distribution and type "make". libwpcap.a, the library file to link with the 
-applications, will be generated in winpcap\wpcap\lib\. wpcap.dll will be 
-generated in winpcap\wpcap\prj.
-
-Remember, you CANNOT use the MSVC-generated .lib files with gcc, use 
-libwpcap.a instead.
-
-"make install" installs wpcap.dll in the Windows system folder.
similarity index 60%
rename from README
rename to README.md
index 46fcc56..78cc3c4 100644 (file)
--- a/README
+++ b/README.md
@@ -1,18 +1,18 @@
-LIBPCAP 1.x.y
-
-www.tcpdump.org
-
-Please send inquiries/comments/reports to:
-       tcpdump-workers@lists.tcpdump.org
+To report a security issue please send an e-mail to security@tcpdump.org.
 
-Anonymous Git is available via:
-       git clone git://bpf.tcpdump.org/libpcap
+To report bugs and other problems, contribute patches, request a
+feature, provide generic feedback etc please see the file
+[CONTRIBUTING](CONTRIBUTING.md) in the libpcap source tree root.
 
-Please submit patches by forking the branch on GitHub at
+The directory doc/ has README files about specific operating systems and
+options.
 
-       http://github.com/the-tcpdump-group/libpcap/tree/master
+LIBPCAP 1.x.y
+Now maintained by "The Tcpdump Group"
+https://www.tcpdump.org
 
-and issuing a pull request.
+Anonymous Git is available via:
+        https://github.com/the-tcpdump-group/libpcap.git
 
 formerly from  Lawrence Berkeley National Laboratory
                Network Research Group <libpcap@ee.lbl.gov>
@@ -43,15 +43,15 @@ found at
 
 or
 
-       http://www.tcpdump.org/papers/bpf-usenix93.ps.Z
+       https://www.tcpdump.org/papers/bpf-usenix93.ps.Z
 
 and a gzipped version can be found at
 
-       http://www.tcpdump.org/papers/bpf-usenix93.ps.gz
+       https://www.tcpdump.org/papers/bpf-usenix93.ps.gz
 
 A PDF version can be found at
 
-       http://www.tcpdump.org/papers/bpf-usenix93.pdf
+       https://www.tcpdump.org/papers/bpf-usenix93.pdf
 
 Although most packet capture interfaces support in-kernel filtering,
 libpcap utilizes in-kernel filtering only for the BPF interface.
@@ -62,45 +62,32 @@ would translate BPF filters into a filter program that is compatible
 with the underlying kernel subsystem, but this is not yet implemented.
 
 BPF is standard in 4.4BSD, BSD/OS, NetBSD, FreeBSD, OpenBSD, DragonFly
-BSD, and Mac OS X; an older, modified and undocumented version is
-standard in AIX.  {DEC OSF/1, Digital UNIX, Tru64 UNIX} uses the
-packetfilter interface but has been extended to accept BPF filters
-(which libpcap utilizes).  Also, you can add BPF filter support to
-Ultrix using the kernel source and/or object patches available in:
+BSD, and macOS; an older, modified and undocumented version is standard
+in AIX.  {DEC OSF/1, Digital UNIX, Tru64 UNIX} uses the packetfilter
+interface but has been extended to accept BPF filters (which libpcap
+utilizes).  Also, you can add BPF filter support to Ultrix using the
+kernel source and/or object patches available in:
 
-       http://www.tcpdump.org/other/bpfext42.tar.Z
+       https://www.tcpdump.org/other/bpfext42.tar.Z
 
-Linux, in the 2.2 kernel and later kernels, has a "Socket Filter"
-mechanism that accepts BPF filters; see the README.linux file for
-information on configuring that option.
+Linux has a number of BPF based systems, and libpcap does not support
+any of the eBPF mechanisms as yet, although it supports many of the
+memory mapped receive mechanisms.
+See the [README.linux](doc/README.linux.md) file for more information.
 
 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
-to the address "tcpdump-workers@lists.tcpdump.org".  Bugs, support
-requests, and feature requests may also be submitted on the GitHub issue
-tracker for libpcap at
-
-       https://github.com/the-tcpdump-group/libpcap/issues
-
-Source code contributions, etc. should be sent to the email address
-above or submitted by forking the branch on GitHub at
-
-       http://github.com/the-tcpdump-group/libpcap/tree/master
-
-and issuing a pull request.
-
-Current versions can be found at www.tcpdump.org.
+Current versions can be found at https://www.tcpdump.org.
 
- - The TCPdump team
+ - The TCPdump group
diff --git a/SUNOS4/nit_if.o.sparc b/SUNOS4/nit_if.o.sparc
deleted file mode 100644 (file)
index d05073e..0000000
Binary files a/SUNOS4/nit_if.o.sparc and /dev/null differ
diff --git a/SUNOS4/nit_if.o.sun3 b/SUNOS4/nit_if.o.sun3
deleted file mode 100644 (file)
index c393fc6..0000000
Binary files a/SUNOS4/nit_if.o.sun3 and /dev/null differ
diff --git a/SUNOS4/nit_if.o.sun4c.4.0.3c b/SUNOS4/nit_if.o.sun4c.4.0.3c
deleted file mode 100644 (file)
index ef01039..0000000
Binary files a/SUNOS4/nit_if.o.sun4c.4.0.3c and /dev/null differ
diff --git a/TODO b/TODO
index 73325e1..aae24c2 100644 (file)
--- a/TODO
+++ b/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/VERSION b/VERSION
index 9c6d629..9ab8337 100644 (file)
--- a/VERSION
+++ b/VERSION
@@ -1 +1 @@
-1.6.1
+1.9.1
diff --git a/Win32/Include/Gnuc.h b/Win32/Include/Gnuc.h
deleted file mode 100644 (file)
index aa49598..0000000
+++ /dev/null
@@ -1,44 +0,0 @@
-/* Define __P() macro, if necessary */
-
-#ifndef __P
-#if __STDC__
-#define __P(protos) protos
-#else
-#define __P(protos) ()
-#endif
-#endif
-
-/* inline foo */
-#ifndef __cplusplus
-#ifdef __GNUC__
-#define inline __inline
-#else
-#define inline
-#endif
-#endif
-
-/*
- * Handle new and old "dead" routine prototypes
- *
- * For example:
- *
- *     __dead void foo(void) __attribute__((volatile));
- *
- */
-#ifdef __GNUC__
-#ifndef __dead
-#define __dead volatile
-#endif
-#if __GNUC__ < 2  || (__GNUC__ == 2 && __GNUC_MINOR__ < 5)
-#ifndef __attribute__
-#define __attribute__(args)
-#endif
-#endif
-#else
-#ifndef __dead
-#define __dead
-#endif
-#ifndef __attribute__
-#define __attribute__(args)
-#endif
-#endif
diff --git a/Win32/Include/addrinfo.h b/Win32/Include/addrinfo.h
deleted file mode 100644 (file)
index 4db7384..0000000
+++ /dev/null
@@ -1,144 +0,0 @@
-/*
- * Copyright (C) 1995, 1996, 1997, 1998, and 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 HAVE_ADDRINFO
-
-/*
- * Error return codes from getaddrinfo()
- */
-#define        EAI_ADDRFAMILY   1      /* address family for hostname not supported */
-#define        EAI_AGAIN        2      /* temporary failure in name resolution */
-#define        EAI_BADFLAGS     3      /* invalid value for ai_flags */
-#define        EAI_FAIL         4      /* non-recoverable failure in name resolution */
-#define        EAI_FAMILY       5      /* ai_family not supported */
-#define        EAI_MEMORY       6      /* memory allocation failure */
-#define        EAI_NODATA       7      /* no address associated with hostname */
-#define        EAI_NONAME       8      /* hostname nor servname provided, or not known */
-#define        EAI_SERVICE      9      /* servname not supported for ai_socktype */
-#define        EAI_SOCKTYPE    10      /* ai_socktype not supported */
-#define        EAI_SYSTEM      11      /* system error returned in errno */
-#define EAI_BADHINTS   12
-#define EAI_PROTOCOL   13
-#define EAI_MAX                14
-
-/* internal error */
-#define        NETDB_INTERNAL  -1      /* see errno */
-
-/*
- * Flag values for getaddrinfo()
- */
-#define        AI_PASSIVE      0x00000001 /* get address to use bind() */
-#define        AI_CANONNAME    0x00000002 /* fill ai_canonname */
-#define        AI_NUMERICHOST  0x00000004 /* prevent name resolution */
-/* valid flags for addrinfo */
-#define        AI_MASK         (AI_PASSIVE | AI_CANONNAME | AI_NUMERICHOST)
-
-#define        AI_ALL          0x00000100 /* IPv6 and IPv4-mapped (with AI_V4MAPPED) */
-#define        AI_V4MAPPED_CFG 0x00000200 /* accept IPv4-mapped if kernel supports */
-#define        AI_ADDRCONFIG   0x00000400 /* only if any address is assigned */
-#define        AI_V4MAPPED     0x00000800 /* accept IPv4-mapped IPv6 address */
-/* special recommended flags for getipnodebyname */
-#define        AI_DEFAULT      (AI_V4MAPPED_CFG | AI_ADDRCONFIG)
-
-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 */
-};
-
-extern void freeaddrinfo (struct addrinfo *);
-extern void freehostent (struct hostent *);
-extern char *gai_strerror (int);
-extern int getaddrinfo (const char *, const char *,
-                           const struct addrinfo *, struct addrinfo **);
-extern int getnameinfo (const struct sockaddr *, size_t, char *,
-                           size_t, char *, size_t, int);
-extern struct hostent *getipnodebyaddr (const void *, size_t, int, int *);
-extern struct hostent *getipnodebyname (const char *, int, int, int *);
-extern int inet_pton (int, const char *, void *);
-extern const char *inet_ntop (int, const void *, char *, size_t);
-#else
-
-#ifndef EAI_BADHINTS
-#define EAI_BADHINTS   12
-#endif 
-
-#ifndef EAI_PROTOCOL   
-#define EAI_PROTOCOL   13
-#endif
-
-#ifndef EAI_MAX        
-#define EAI_MAX                14
-#endif
-
-#ifndef NETDB_INTERNAL
-#define        NETDB_INTERNAL  -1      /* see errno */
-#endif
-
-#ifndef AI_MASK
-/* valid flags for addrinfo */
-#define        AI_MASK         (AI_PASSIVE | AI_CANONNAME | AI_NUMERICHOST)
-#endif
-
-#endif /* HAVE_ADDRINFO */
-
-/*
- * Constants for getnameinfo()
- */
-#ifndef NI_MAXHOST
-#define        NI_MAXHOST      1025
-#endif
-#ifndef NI_MAXSERV
-#define        NI_MAXSERV      32
-#endif
-
-/*
- * Flag values for getnameinfo()
- */
-#ifndef NI_NOFQDN
-#define        NI_NOFQDN       0x00000001
-#endif
-#ifndef NI_NUMERICHOST
-#define        NI_NUMERICHOST  0x00000002
-#endif
-#ifndef NI_NAMEREQD
-#define        NI_NAMEREQD     0x00000004
-#endif
-#ifndef NI_NUMERICSERV
-#define        NI_NUMERICSERV  0x00000008
-#endif
-#ifndef NI_DGRAM
-#define        NI_DGRAM        0x00000010
-#endif
-
diff --git a/Win32/Include/arpa/nameser.h b/Win32/Include/arpa/nameser.h
deleted file mode 100644 (file)
index 18f185c..0000000
+++ /dev/null
@@ -1,349 +0,0 @@
-/*
- * ++Copyright++ 1983, 1989, 1993
- * -
- * Copyright (c) 1983, 1989, 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
- *    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.
- * -
- * Portions Copyright (c) 1993 by Digital Equipment Corporation.
- * 
- * Permission to use, copy, modify, and distribute this software for any
- * purpose with or without fee is hereby granted, provided that the above
- * copyright notice and this permission notice appear in all copies, and that
- * the name of Digital Equipment Corporation not be used in advertising or
- * publicity pertaining to distribution of the document or software without
- * specific, written prior permission.
- * 
- * THE SOFTWARE IS PROVIDED "AS IS" AND DIGITAL EQUIPMENT CORP. DISCLAIMS ALL
- * WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS.   IN NO EVENT SHALL DIGITAL EQUIPMENT
- * CORPORATION BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
- * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
- * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS
- * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
- * SOFTWARE.
- * -
- * --Copyright--
- */
-
-/*
- *      @(#)nameser.h  8.1 (Berkeley) 6/2/93
- *     nameser.h,v 1.2 1995/05/06 14:23:54 hjl Exp
- */
-
-#ifndef _NAMESER_H_
-#define        _NAMESER_H_
-
-#ifndef WIN32
-#include <sys/param.h>
-#if (!defined(BSD)) || (BSD < 199306)
-# include <sys/bitypes.h>
-#else
-# include <sys/types.h>
-#endif
-#include <sys/cdefs.h>
-#else 
-#include <pcap-stdinc.h>
-#define __LITTLE_ENDIAN 1
-#define __BYTE_ORDER __LITTLE_ENDIAN
-#endif
-
-/*
- * revision information.  this is the release date in YYYYMMDD format.
- * it can change every day so the right thing to do with it is use it
- * in preprocessor commands such as "#if (__BIND > 19931104)".  do not
- * compare for equality; rather, use it to determine whether your resolver
- * is new enough to contain a certain feature.
- */
-
-#define        __BIND          19940417        /* interface version stamp */
-
-/*
- * Define constants based on rfc883
- */
-#define PACKETSZ       512             /* maximum packet size */
-#define MAXDNAME       256             /* maximum domain name */
-#define MAXCDNAME      255             /* maximum compressed domain name */
-#define MAXLABEL       63              /* maximum length of domain label */
-#define        HFIXEDSZ        12              /* #/bytes of fixed data in header */
-#define QFIXEDSZ       4               /* #/bytes of fixed data in query */
-#define RRFIXEDSZ      10              /* #/bytes of fixed data in r record */
-#define        INT32SZ         4               /* for systems without 32-bit ints */
-#define        INT16SZ         2               /* for systems without 16-bit ints */
-#define        INADDRSZ        4               /* for sizeof(struct inaddr) != 4 */
-
-/*
- * Internet nameserver port number
- */
-#define NAMESERVER_PORT        53
-
-/*
- * Currently defined opcodes
- */
-#define QUERY          0x0             /* standard query */
-#define IQUERY         0x1             /* inverse query */
-#define STATUS         0x2             /* nameserver status query */
-/*#define xxx          0x3             *//* 0x3 reserved */
-#define        NS_NOTIFY_OP    0x4             /* notify secondary of SOA change */
-#ifdef ALLOW_UPDATES
-       /* non standard - supports ALLOW_UPDATES stuff from Mike Schwartz */
-# define UPDATEA       0x9             /* add resource record */
-# define UPDATED       0xa             /* delete a specific resource record */
-# define UPDATEDA      0xb             /* delete all named resource record */
-# define UPDATEM       0xc             /* modify a specific resource record */
-# define UPDATEMA      0xd             /* modify all named resource record */
-# define ZONEINIT      0xe             /* initial zone transfer */
-# define ZONEREF       0xf             /* incremental zone referesh */
-#endif
-
-/*
- * Currently defined response codes
- */
-#ifdef HAVE_ADDRINFO
-#define NOERROR                0               /* no error */
-#endif /* HAVE_ADDRINFO */
-#define FORMERR                1               /* format error */
-#define SERVFAIL       2               /* server failure */
-#define NXDOMAIN       3               /* non existent domain */
-#define NOTIMP         4               /* not implemented */
-#define REFUSED                5               /* query refused */
-#ifdef ALLOW_UPDATES
-       /* non standard */
-# define NOCHANGE      0xf             /* update failed to change db */
-#endif
-
-/*
- * Type values for resources and queries
- */
-#define T_A            1               /* host address */
-#define T_NS           2               /* authoritative server */
-#define T_MD           3               /* mail destination */
-#define T_MF           4               /* mail forwarder */
-#define T_CNAME                5               /* canonical name */
-#define T_SOA          6               /* start of authority zone */
-#define T_MB           7               /* mailbox domain name */
-#define T_MG           8               /* mail group member */
-#define T_MR           9               /* mail rename name */
-#define T_NULL         10              /* null resource record */
-#define T_WKS          11              /* well known service */
-#define T_PTR          12              /* domain name pointer */
-#define T_HINFO                13              /* host information */
-#define T_MINFO                14              /* mailbox information */
-#define T_MX           15              /* mail routing information */
-#define T_TXT          16              /* text strings */
-#define        T_RP            17              /* responsible person */
-#define T_AFSDB                18              /* AFS cell database */
-#define T_X25          19              /* X_25 calling address */
-#define T_ISDN         20              /* ISDN calling address */
-#define T_RT           21              /* router */
-#define T_NSAP         22              /* NSAP address */
-#define T_NSAP_PTR     23              /* reverse NSAP lookup (deprecated) */
-#define        T_SIG           24              /* security signature */
-#define        T_KEY           25              /* security key */
-#define        T_PX            26              /* X.400 mail mapping */
-#define        T_GPOS          27              /* geographical position (withdrawn) */
-#define        T_AAAA          28              /* IP6 Address */
-#define        T_LOC           29              /* Location Information */
-       /* non standard */
-#define T_UINFO                100             /* user (finger) information */
-#define T_UID          101             /* user ID */
-#define T_GID          102             /* group ID */
-#define T_UNSPEC       103             /* Unspecified format (binary data) */
-       /* Query type values which do not appear in resource records */
-#define T_AXFR         252             /* transfer zone of authority */
-#define T_MAILB                253             /* transfer mailbox records */
-#define T_MAILA                254             /* transfer mail agent records */
-#define T_ANY          255             /* wildcard match */
-
-/*
- * Values for class field
- */
-
-#define C_IN           1               /* the arpa internet */
-#define C_CHAOS                3               /* for chaos net (MIT) */
-#define C_HS           4               /* for Hesiod name server (MIT) (XXX) */
-       /* Query class values which do not appear in resource records */
-#define C_ANY          255             /* wildcard match */
-
-/*
- * Status return codes for T_UNSPEC conversion routines
- */
-#define CONV_SUCCESS   0
-#define CONV_OVERFLOW  (-1)
-#define CONV_BADFMT    (-2)
-#define CONV_BADCKSUM  (-3)
-#define CONV_BADBUFLEN (-4)
-
-#ifndef __BYTE_ORDER
-#if (BSD >= 199103)
-# include <machine/endian.h>
-#else
-#ifdef linux
-# include <endian.h>
-#else
-#define        __LITTLE_ENDIAN 1234    /* least-significant byte first (vax, pc) */
-#define        __BIG_ENDIAN    4321    /* most-significant byte first (IBM, net) */
-#define        __PDP_ENDIAN    3412    /* LSB first in word, MSW first in long (pdp)*/
-
-#if defined(vax) || defined(ns32000) || defined(sun386) || defined(i386) || \
-    defined(MIPSEL) || defined(_MIPSEL) || defined(BIT_ZERO_ON_RIGHT) || \
-    defined(__alpha__) || defined(__alpha)
-#define __BYTE_ORDER   __LITTLE_ENDIAN
-#endif
-
-#if defined(sel) || defined(pyr) || defined(mc68000) || defined(sparc) || \
-    defined(is68k) || defined(tahoe) || defined(ibm032) || defined(ibm370) || \
-    defined(MIPSEB) || defined(_MIPSEB) || defined(_IBMR2) || defined(DGUX) ||\
-    defined(apollo) || defined(__convex__) || defined(_CRAY) || \
-    defined(__hppa) || defined(__hp9000) || \
-    defined(__hp9000s300) || defined(__hp9000s700) || \
-    defined (BIT_ZERO_ON_LEFT) || defined(m68k)
-#define __BYTE_ORDER   __BIG_ENDIAN
-#endif
-#endif /* linux */
-#endif /* BSD */
-#endif /* __BYTE_ORDER */
-
-#if !defined(__BYTE_ORDER) || \
-    (__BYTE_ORDER != __BIG_ENDIAN && __BYTE_ORDER != __LITTLE_ENDIAN && \
-    __BYTE_ORDER != __PDP_ENDIAN)
-       /* you must determine what the correct bit order is for
-        * your compiler - the next line is an intentional error
-        * which will force your compiles to bomb until you fix
-        * the above macros.
-        */
-  error "Undefined or invalid __BYTE_ORDER";
-#endif
-
-/*
- * Structure for query header.  The order of the fields is machine- and
- * compiler-dependent, depending on the byte/bit order and the layout
- * of bit fields.  We use bit fields only in int variables, as this
- * is all ANSI requires.  This requires a somewhat confusing rearrangement.
- */
-
-typedef struct {
-       unsigned        id :16;         /* query identification number */
-#if __BYTE_ORDER == __BIG_ENDIAN
-                       /* fields in third byte */
-       unsigned        qr: 1;          /* response flag */
-       unsigned        opcode: 4;      /* purpose of message */
-       unsigned        aa: 1;          /* authoritive answer */
-       unsigned        tc: 1;          /* truncated message */
-       unsigned        rd: 1;          /* recursion desired */
-                       /* fields in fourth byte */
-       unsigned        ra: 1;          /* recursion available */
-       unsigned        pr: 1;          /* primary server req'd (!standard) */
-       unsigned        unused :2;      /* unused bits (MBZ as of 4.9.3a3) */
-       unsigned        rcode :4;       /* response code */
-#endif
-#if __BYTE_ORDER == __LITTLE_ENDIAN || __BYTE_ORDER == __PDP_ENDIAN
-                       /* fields in third byte */
-       unsigned        rd :1;          /* recursion desired */
-       unsigned        tc :1;          /* truncated message */
-       unsigned        aa :1;          /* authoritive answer */
-       unsigned        opcode :4;      /* purpose of message */
-       unsigned        qr :1;          /* response flag */
-                       /* fields in fourth byte */
-       unsigned        rcode :4;       /* response code */
-       unsigned        unused :2;      /* unused bits (MBZ as of 4.9.3a3) */
-       unsigned        pr :1;          /* primary server req'd (!standard) */
-       unsigned        ra :1;          /* recursion available */
-#endif
-                       /* remaining bytes */
-       unsigned        qdcount :16;    /* number of question entries */
-       unsigned        ancount :16;    /* number of answer entries */
-       unsigned        nscount :16;    /* number of authority entries */
-       unsigned        arcount :16;    /* number of resource entries */
-} HEADER;
-
-/*
- * Defines for handling compressed domain names
- */
-#define INDIR_MASK     0xc0
-
-/*
- * Structure for passing resource records around.
- */
-struct rrec {
-       int16_t         r_zone;                 /* zone number */
-       int16_t         r_class;                /* class number */
-       int16_t         r_type;                 /* type number */
-       u_int32_t       r_ttl;                  /* time to live */
-       int             r_size;                 /* size of data area */
-       char            *r_data;                /* pointer to data */
-};
-
-//extern       u_int16_t       _getshort __P((const u_char *));
-//extern       u_int32_t       _getlong __P((const u_char *));
-
-/*
- * Inline versions of get/put short/long.  Pointer is advanced.
- *
- * These macros demonstrate the property of C whereby it can be
- * portable or it can be elegant but rarely both.
- */
-#define GETSHORT(s, cp) { \
-       register u_char *t_cp = (u_char *)(cp); \
-       (s) = ((u_int16_t)t_cp[0] << 8) \
-           | ((u_int16_t)t_cp[1]) \
-           ; \
-       (cp) += INT16SZ; \
-}
-
-#define GETLONG(l, cp) { \
-       register u_char *t_cp = (u_char *)(cp); \
-       (l) = ((u_int32_t)t_cp[0] << 24) \
-           | ((u_int32_t)t_cp[1] << 16) \
-           | ((u_int32_t)t_cp[2] << 8) \
-           | ((u_int32_t)t_cp[3]) \
-           ; \
-       (cp) += INT32SZ; \
-}
-
-#define PUTSHORT(s, cp) { \
-       register u_int16_t t_s = (u_int16_t)(s); \
-       register u_char *t_cp = (u_char *)(cp); \
-       *t_cp++ = t_s >> 8; \
-       *t_cp   = t_s; \
-       (cp) += INT16SZ; \
-}
-
-#define PUTLONG(l, cp) { \
-       register u_int32_t t_l = (u_int32_t)(l); \
-       register u_char *t_cp = (u_char *)(cp); \
-       *t_cp++ = t_l >> 24; \
-       *t_cp++ = t_l >> 16; \
-       *t_cp++ = t_l >> 8; \
-       *t_cp   = t_l; \
-       (cp) += INT32SZ; \
-}
-
-#endif /* !_NAMESER_H_ */
diff --git a/Win32/Include/bittypes.h b/Win32/Include/bittypes.h
deleted file mode 100644 (file)
index 7c0cbde..0000000
+++ /dev/null
@@ -1,89 +0,0 @@
-/*
- * 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 _BITTYPES_H
-#define _BITTYPES_H
-
-#ifndef HAVE_U_INT8_T
-typedef unsigned char u_int8_t;
-typedef signed char int8_t;
-#endif /* HAVE_U_INT8_T */
-
-#ifndef HAVE_U_INT16_T 
-typedef unsigned short u_int16_t;
-typedef signed short int16_t;
-#endif /* HAVE_U_INT16_T */
-
-#ifndef HAVE_U_INT32_T
-typedef unsigned int u_int32_t;
-typedef signed int int32_t;
-#endif /* HAVE_U_INT32_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 /* _MSC_EXTENSIONS */
-#endif /* HAVE_U_INT64_T */
-
-#ifndef PRId64
-#ifdef _MSC_EXTENSIONS
-#define PRId64 "I64d"
-#else /* _MSC_EXTENSIONS */
-#define PRId64 "lld"
-#endif /* _MSC_EXTENSIONS */
-#endif /* PRId64 */
-
-#ifndef PRIo64
-#ifdef _MSC_EXTENSIONS
-#define PRIo64 "I64o"
-#else /* _MSC_EXTENSIONS */
-#define PRIo64 "llo"
-#endif /* _MSC_EXTENSIONS */
-#endif /* PRIo64 */
-
-#ifndef PRIx64
-#ifdef _MSC_EXTENSIONS
-#define PRIx64 "I64x"
-#else /* _MSC_EXTENSIONS */
-#define PRIx64 "llx"
-#endif /* _MSC_EXTENSIONS */
-#endif /* PRIx64 */
-
-#ifndef PRIu64
-#ifdef _MSC_EXTENSIONS
-#define PRIu64 "I64u"
-#else /* _MSC_EXTENSIONS */
-#define PRIu64 "llu"
-#endif /* _MSC_EXTENSIONS */
-#endif /* PRIu64 */
-
-#endif /* _BITTYPES_H */
diff --git a/Win32/Include/cdecl_ext.h b/Win32/Include/cdecl_ext.h
deleted file mode 100644 (file)
index 9591db2..0000000
+++ /dev/null
@@ -1,37 +0,0 @@
-/*
- * 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 HAVE_PORTABLE_PROTOTYPE
-
-#if defined(__STDC__) || defined(__cplusplus)
-#define        __P(protos)     protos          /* full-blown ANSI C */
-#else
-#define        __P(protos)     ()              /* traditional C preprocessor */
-#endif
-
-#endif /* !HAVE_PORTABLE_PROTOTYPE */
diff --git a/Win32/Include/ip6_misc.h b/Win32/Include/ip6_misc.h
deleted file mode 100644 (file)
index 0b578c3..0000000
+++ /dev/null
@@ -1,161 +0,0 @@
-/*
- * Copyright (c) 1993, 1994, 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.
- */
-
-/*
- * This file contains a collage of declarations for IPv6 from FreeBSD not present in Windows
- */
-
-#include <winsock2.h>
-
-#include <ws2tcpip.h>
-
-#ifndef __MINGW32__
-#define        IN_MULTICAST(a)         IN_CLASSD(a)
-#endif
-
-#define        IN_EXPERIMENTAL(a)      ((((u_int32_t) (a)) & 0xf0000000) == 0xf0000000)
-
-#define        IN_LOOPBACKNET          127
-
-#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
-  };
-
-#define IN6ADDR_ANY_INIT { 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 }
-#define IN6ADDR_LOOPBACK_INIT { 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1 }
-#endif /* __MINGW32__ */
-
-
-#if (defined _MSC_VER) || (defined(__MINGW32__) && defined(DEFINE_ADDITIONAL_IPV6_STUFF))
-typedef unsigned short sa_family_t;
-#endif
-
-
-#if defined(__MINGW32__) && defined(DEFINE_ADDITIONAL_IPV6_STUFF)
-
-#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 */
-  };
-
-#define IN6_IS_ADDR_V4MAPPED(a) \
-       ((((u_int32_t *) (a))[0] == 0) && (((u_int32_t *) (a))[1] == 0) && \
-        (((u_int32_t *) (a))[2] == htonl (0xffff)))
-
-#define IN6_IS_ADDR_MULTICAST(a) (((u_int8_t *) (a))[0] == 0xff)
-
-#define IN6_IS_ADDR_LINKLOCAL(a) \
-       ((((u_int32_t *) (a))[0] & htonl (0xffc00000)) == htonl (0xfe800000))
-
-#define IN6_IS_ADDR_LOOPBACK(a) \
-       (((u_int32_t *) (a))[0] == 0 && ((u_int32_t *) (a))[1] == 0 && \
-        ((u_int32_t *) (a))[2] == 0 && ((u_int32_t *) (a))[3] == htonl (1))
-#endif /* __MINGW32__ */
-
-#define ip6_vfc   ip6_ctlun.ip6_un2_vfc
-#define ip6_flow  ip6_ctlun.ip6_un1.ip6_un1_flow
-#define ip6_plen  ip6_ctlun.ip6_un1.ip6_un1_plen
-#define ip6_nxt   ip6_ctlun.ip6_un1.ip6_un1_nxt
-#define ip6_hlim  ip6_ctlun.ip6_un1.ip6_un1_hlim
-#define ip6_hops  ip6_ctlun.ip6_un1.ip6_un1_hlim
-
-#define nd_rd_type               nd_rd_hdr.icmp6_type
-#define nd_rd_code               nd_rd_hdr.icmp6_code
-#define nd_rd_cksum              nd_rd_hdr.icmp6_cksum
-#define nd_rd_reserved           nd_rd_hdr.icmp6_data32[0]
-
-/*
- *     IPV6 extension headers
- */
-#define IPPROTO_HOPOPTS                0       /* IPv6 hop-by-hop options      */
-#define IPPROTO_IPV6           41  /* IPv6 header.  */
-#define IPPROTO_ROUTING                43      /* IPv6 routing header          */
-#define IPPROTO_FRAGMENT       44      /* IPv6 fragmentation header    */
-#define IPPROTO_ESP            50      /* encapsulating security payload */
-#define IPPROTO_AH             51      /* authentication header        */
-#define IPPROTO_ICMPV6         58      /* ICMPv6                       */
-#define IPPROTO_NONE           59      /* IPv6 no next header          */
-#define IPPROTO_DSTOPTS                60      /* IPv6 destination options     */
-#define IPPROTO_PIM                    103 /* Protocol Independent Multicast.  */
-
-#define         IPV6_RTHDR_TYPE_0 0
-
-/* Option types and related macros */
-#define IP6OPT_PAD1            0x00    /* 00 0 00000 */
-#define IP6OPT_PADN            0x01    /* 00 0 00001 */
-#define IP6OPT_JUMBO           0xC2    /* 11 0 00010 = 194 */
-#define IP6OPT_JUMBO_LEN       6
-#define IP6OPT_ROUTER_ALERT    0x05    /* 00 0 00101 */
-
-#define IP6OPT_RTALERT_LEN     4
-#define IP6OPT_RTALERT_MLD     0       /* Datagram contains an MLD message */
-#define IP6OPT_RTALERT_RSVP    1       /* Datagram contains an RSVP message */
-#define IP6OPT_RTALERT_ACTNET  2       /* contains an Active Networks msg */
-#define IP6OPT_MINLEN          2
-
-#define IP6OPT_BINDING_UPDATE  0xc6    /* 11 0 00110 */
-#define IP6OPT_BINDING_ACK     0x07    /* 00 0 00111 */
-#define IP6OPT_BINDING_REQ     0x08    /* 00 0 01000 */
-#define IP6OPT_HOME_ADDRESS    0xc9    /* 11 0 01001 */
-#define IP6OPT_EID             0x8a    /* 10 0 01010 */
-
-#define IP6OPT_TYPE(o)         ((o) & 0xC0)
-#define IP6OPT_TYPE_SKIP       0x00
-#define IP6OPT_TYPE_DISCARD    0x40
-#define IP6OPT_TYPE_FORCEICMP  0x80
-#define IP6OPT_TYPE_ICMP       0xC0
-
-#define IP6OPT_MUTABLE         0x20
-
-
-#if defined(__MINGW32__) && defined(DEFINE_ADDITIONAL_IPV6_STUFF)
-#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
-#endif /* __MINGW32__ */
diff --git a/Win32/Include/net/if.h b/Win32/Include/net/if.h
deleted file mode 100644 (file)
index bf926b6..0000000
+++ /dev/null
@@ -1,230 +0,0 @@
-/*
- * Copyright (c) 1982, 1986, 1989, 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
- *    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.h        8.1 (Berkeley) 6/10/93
- * $FreeBSD: src/sys/net/if.h,v 1.49.2.1 1999/08/29 16:28:15 peter Exp $
- */
-
-#ifndef _NET_IF_H_
-#define        _NET_IF_H_
-/*
- * <net/if.h> does not depend on <sys/time.h> on most other systems.  This
- * helps userland compatability.  (struct timeval ifi_lastchange)
- */
-#ifndef KERNEL
-#include <pcap-stdinc.h>
-#endif
-
-/*
- * Structure describing information about an interface
- * which may be of interest to management entities.
- */
-struct if_data {
-       /* generic interface information */
-       u_char  ifi_type;               /* ethernet, tokenring, etc */
-       u_char  ifi_physical;           /* e.g., AUI, Thinnet, 10base-T, etc */
-       u_char  ifi_addrlen;            /* media address length */
-       u_char  ifi_hdrlen;             /* media header length */
-       u_char  ifi_recvquota;          /* polling quota for receive intrs */
-       u_char  ifi_xmitquota;          /* polling quota for xmit intrs */
-       u_long  ifi_mtu;                /* maximum transmission unit */
-       u_long  ifi_metric;             /* routing metric (external only) */
-       u_long  ifi_baudrate;           /* linespeed */
-       /* volatile statistics */
-       u_long  ifi_ipackets;           /* packets received on interface */
-       u_long  ifi_ierrors;            /* input errors on interface */
-       u_long  ifi_opackets;           /* packets sent on interface */
-       u_long  ifi_oerrors;            /* output errors on interface */
-       u_long  ifi_collisions;         /* collisions on csma interfaces */
-       u_long  ifi_ibytes;             /* total number of octets received */
-       u_long  ifi_obytes;             /* total number of octets sent */
-       u_long  ifi_imcasts;            /* packets received via multicast */
-       u_long  ifi_omcasts;            /* packets sent via multicast */
-       u_long  ifi_iqdrops;            /* dropped on input, this interface */
-       u_long  ifi_noproto;            /* destined for unsupported protocol */
-       u_long  ifi_recvtiming;         /* usec spent receiving when timing */
-       u_long  ifi_xmittiming;         /* usec spent xmitting when timing */
-       struct  timeval ifi_lastchange; /* time of last administrative change */
-};
-
-/* ws2tcpip.h has interface flags: IFF_* */
-#if 0
-#define        IFF_UP          0x1             /* interface is up */
-#define        IFF_BROADCAST   0x2             /* broadcast address valid */
-#define        IFF_DEBUG       0x4             /* turn on debugging */
-#define        IFF_LOOPBACK    0x8             /* is a loopback net */
-#define        IFF_POINTOPOINT 0x10            /* interface is point-to-point link */
-/*#define IFF_NOTRAILERS 0x20           * obsolete: avoid use of trailers */
-#define        IFF_RUNNING     0x40            /* resources allocated */
-#define        IFF_NOARP       0x80            /* no address resolution protocol */
-#define        IFF_PROMISC     0x100           /* receive all packets */
-#define        IFF_ALLMULTI    0x200           /* receive all multicast packets */
-#define        IFF_OACTIVE     0x400           /* transmission in progress */
-#define        IFF_SIMPLEX     0x800           /* can't hear own transmissions */
-#define        IFF_LINK0       0x1000          /* per link layer defined bit */
-#define        IFF_LINK1       0x2000          /* per link layer defined bit */
-#define        IFF_LINK2       0x4000          /* per link layer defined bit */
-#define        IFF_ALTPHYS     IFF_LINK2       /* use alternate physical connection */
-#define        IFF_MULTICAST   0x8000          /* supports multicast */
-#endif /* 0 */
-
-/* flags set internally only: */
-#define        IFF_CANTCHANGE \
-       (IFF_BROADCAST|IFF_POINTOPOINT|IFF_RUNNING|IFF_OACTIVE|\
-           IFF_SIMPLEX|IFF_MULTICAST|IFF_ALLMULTI)
-
-#define        IFQ_MAXLEN      50
-#define        IFNET_SLOWHZ    1               /* granularity is 1 second */
-
-/*
- * Message format for use in obtaining information about interfaces
- * from getkerninfo and the routing socket
- */
-struct if_msghdr {
-       u_short ifm_msglen;     /* to skip over non-understood messages */
-       u_char  ifm_version;    /* future binary compatability */
-       u_char  ifm_type;       /* message type */
-       int     ifm_addrs;      /* like rtm_addrs */
-       int     ifm_flags;      /* value of if_flags */
-       u_short ifm_index;      /* index for associated ifp */
-       struct  if_data ifm_data;/* statistics and other data about if */
-};
-
-/*
- * Message format for use in obtaining information about interface addresses
- * from getkerninfo and the routing socket
- */
-struct ifa_msghdr {
-       u_short ifam_msglen;    /* to skip over non-understood messages */
-       u_char  ifam_version;   /* future binary compatability */
-       u_char  ifam_type;      /* message type */
-       int     ifam_addrs;     /* like rtm_addrs */
-       int     ifam_flags;     /* value of ifa_flags */
-       u_short ifam_index;     /* index for associated ifp */
-       int     ifam_metric;    /* value of ifa_metric */
-};
-
-/*
- * Message format for use in obtaining information about multicast addresses
- * from the routing socket
- */
-struct ifma_msghdr {
-       u_short ifmam_msglen;   /* to skip over non-understood messages */
-       u_char  ifmam_version;  /* future binary compatability */
-       u_char  ifmam_type;     /* message type */
-       int     ifmam_addrs;    /* like rtm_addrs */
-       int     ifmam_flags;    /* value of ifa_flags */
-       u_short ifmam_index;    /* index for associated ifp */
-};
-
-/*
- * Interface request structure used for socket
- * ioctl's.  All interface ioctl's must have parameter
- * definitions which begin with ifr_name.  The
- * remainder may be interface specific.
- */
-struct ifreq {
-#define        IFNAMSIZ        16
-       char    ifr_name[IFNAMSIZ];             /* if name, e.g. "en0" */
-       union {
-               struct  sockaddr ifru_addr;
-               struct  sockaddr ifru_dstaddr;
-               struct  sockaddr ifru_broadaddr;
-               short   ifru_flags;
-               int     ifru_metric;
-               int     ifru_mtu;
-               int     ifru_phys;
-               int     ifru_media;
-               caddr_t ifru_data;
-       } ifr_ifru;
-#define        ifr_addr        ifr_ifru.ifru_addr      /* address */
-#define        ifr_dstaddr     ifr_ifru.ifru_dstaddr   /* other end of p-to-p link */
-#define        ifr_broadaddr   ifr_ifru.ifru_broadaddr /* broadcast address */
-#define        ifr_flags       ifr_ifru.ifru_flags     /* flags */
-#define        ifr_metric      ifr_ifru.ifru_metric    /* metric */
-#define        ifr_mtu         ifr_ifru.ifru_mtu       /* mtu */
-#define ifr_phys       ifr_ifru.ifru_phys      /* physical wire */
-#define ifr_media      ifr_ifru.ifru_media     /* physical media */
-#define        ifr_data        ifr_ifru.ifru_data      /* for use by interface */
-};
-
-#define        _SIZEOF_ADDR_IFREQ(ifr) \
-       ((ifr).ifr_addr.sa_len > sizeof(struct sockaddr) ? \
-        (sizeof(struct ifreq) - sizeof(struct sockaddr) + \
-         (ifr).ifr_addr.sa_len) : sizeof(struct ifreq))
-
-struct ifaliasreq {
-       char    ifra_name[IFNAMSIZ];            /* if name, e.g. "en0" */
-       struct  sockaddr ifra_addr;
-       struct  sockaddr ifra_broadaddr;
-       struct  sockaddr ifra_mask;
-};
-
-struct ifmediareq {
-       char    ifm_name[IFNAMSIZ];     /* if name, e.g. "en0" */
-       int     ifm_current;            /* current media options */
-       int     ifm_mask;               /* don't care mask */
-       int     ifm_status;             /* media status */
-       int     ifm_active;             /* active options */
-       int     ifm_count;              /* # entries in ifm_ulist array */
-       int     *ifm_ulist;             /* media words */
-};
-/*
- * Structure used in SIOCGIFCONF request.
- * Used to retrieve interface configuration
- * for machine (useful for programs which
- * must know all networks accessible).
- */
-struct ifconf {
-       int     ifc_len;                /* size of associated buffer */
-       union {
-               caddr_t ifcu_buf;
-               struct  ifreq *ifcu_req;
-       } ifc_ifcu;
-#define        ifc_buf ifc_ifcu.ifcu_buf       /* buffer address */
-#define        ifc_req ifc_ifcu.ifcu_req       /* array of structures returned */
-};
-
-#ifdef KERNEL
-#ifdef MALLOC_DECLARE
-MALLOC_DECLARE(M_IFADDR);
-MALLOC_DECLARE(M_IFMADDR);
-#endif
-#endif
-
-/* XXX - this should go away soon */
-#ifdef KERNEL
-#include <net/if_var.h>
-#endif
-
-#endif /* !_NET_IF_H_ */
diff --git a/Win32/Include/net/netdb.h b/Win32/Include/net/netdb.h
deleted file mode 100644 (file)
index b9d45ac..0000000
+++ /dev/null
@@ -1,164 +0,0 @@
-/*-
- * Copyright (c) 1980, 1983, 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
- *    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.
- *
- *     @(#)netdb.h     8.1 (Berkeley) 6/2/93
- *      netdb.h,v 1.4 1995/08/14 04:05:04 hjl Exp
- * -
- * Portions Copyright (c) 1993 by Digital Equipment Corporation.
- *
- * Permission to use, copy, modify and distribute this software for any
- * purpose with or without fee is hereby granted, provided that the above
- * copyright notice and this permission notice appear in all copies, and that
- * the name of Digital Equipment Corporation not be used in advertising or
- * publicity pertaining to distribution of the document or software without
- * specific, written prior permission.
- *
- * THE SOFTWARE IS PROVIDED "AS IS" AND DIGITAL EQUIPMENT CORP. DISCLAIMS ALL
- * WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS.   IN NO EVENT SHALL DIGITAL EQUIPMENT
- * CORPORATION BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
- * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
- * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS
- * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
- * SOFTWARE.
- * -
- * --Copyright--
- */
-
-#ifndef _NETDB_H_
-#define _NETDB_H_
-
-#if defined(_POSIX_THREAD_SAFE_FUNCTIONS) || defined(_REENTRANT)
-#include <stdio.h>
-#include <netinet/in.h>
-#endif
-
-#include <winsock2.h>
-#include <net/paths.h>
-
-#define _PATH_HEQUIV   __PATH_ETC_INET"/hosts.equiv"
-#define _PATH_HOSTS    __PATH_ETC_INET"/hosts"
-#define _PATH_NETWORKS __PATH_ETC_INET"/networks"
-#define _PATH_PROTOCOLS        __PATH_ETC_INET"/protocols"
-#define _PATH_SERVICES __PATH_ETC_INET"/services"
-#define _PATH_RESCONF  __PATH_ETC_INET"/resolv.conf"
-#define _PATH_RPC      __PATH_ETC_INET"/rpc"
-
-struct rpcent {
-       char    *r_name;        /* name of server for this rpc program */
-       char    **r_aliases;    /* alias list */
-       int     r_number;       /* rpc program number */
-};
-
-#ifndef WIN32
-#if defined(_POSIX_THREAD_SAFE_FUNCTIONS) || defined(_REENTRANT)
-
-#define __NETDB_MAXALIASES     35
-#define __NETDB_MAXADDRS       35
-
-/*
- * Error return codes from gethostbyname() and gethostbyaddr()
- * (left in extern int h_errno).
- */
-#define h_errno                (*__h_errno_location ())
-#else
-extern int h_errno;
-#endif
-#endif
-
-#define        NETDB_INTERNAL -1 /* see errno */
-#define        NETDB_SUCCESS   0 /* no problem */
-
-//#include <features.h>
-
-void           endhostent (void);
-void           endnetent (void);
-void           endprotoent (void);
-void           endservent (void);
-void           endrpcent (void);
-struct hostent *gethostent (void);
-struct netent  *getnetbyaddr (long, int); /* u_long? */
-struct netent  *getnetbyname (const char *);
-struct netent  *getnetent (void);
-struct protoent        *getprotoent (void);
-struct servent *getservent (void);
-struct rpcent  *getrpcent (void);
-struct rpcent  *getrpcbyname (const char *);
-struct rpcent  *getrpcbynumber (int);
-void           herror (const char *);
-void           sethostent (int);
-/* void                sethostfile (const char *); */
-void           setnetent (int);
-void           setprotoent (int);
-void           setservent (int);
-void           setrpcent (int);
-
-#if defined(_POSIX_THREAD_SAFE_FUNCTIONS) || defined(_REENTRANT)
-struct hostent *gethostbyaddr_r (const char *__addr,
-                       int __length, int __type,
-                       struct hostent *__result,
-                       char *__buffer, int __buflen, int *__h_errnop);
-struct hostent *gethostbyname_r (const char * __name,
-                       struct hostent *__result, char *__buffer,
-                       int __buflen, int *__h_errnop);
-struct hostent *gethostent_r (struct hostent *__result,
-                       char *__buffer, int __buflen, int *__h_errnop);
-struct netent  *getnetbyaddr_r (long __net, int __type,
-                       struct netent *__result, char *__buffer,
-                       int __buflen);
-struct netent  *getnetbyname_r (const char * __name,
-                       struct netent *__result, char *__buffer,
-                       int __buflen);
-struct netent  *getnetent_r (struct netent *__result,
-                       char *__buffer, int __buflen);
-struct protoent        *getprotobyname_r (const char * __name,
-                       struct protoent *__result, char *__buffer,
-                       int __buflen);
-struct protoent        *getprotobynumber_r (int __proto,
-                       struct protoent *__result, char *__buffer,
-                       int __buflen);
-struct protoent        *getprotoent_r (struct protoent *__result,
-                       char *__buffer, int __buflen);
-struct servent *getservbyname_r (const char * __name,
-                       const char *__proto, struct servent *__result,
-                       char *__buffer, int __buflen);
-struct servent *getservbyport_r (int __port,
-                       const char *__proto, struct servent *__result,
-                       char *__buffer, int __buflen);
-struct servent *getservent_r (struct servent *__result,
-                       char *__buffer, int __buflen);
-
-int *__h_errno_location (void);
-
-#endif
-
-#endif /* !_NETDB_H_ */
diff --git a/Win32/Include/net/paths.h b/Win32/Include/net/paths.h
deleted file mode 100644 (file)
index 987de4f..0000000
+++ /dev/null
@@ -1,105 +0,0 @@
-/*
- * Copyright (c) 1989 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.
- *
- *     @(#)paths.h     5.15 (Berkeley) 5/29/91
- */
-
-#ifndef _PATHS_H_
-#define        _PATHS_H_
-
-#if 0
-#define        __PATH_ETC_INET "/usr/etc/inet"
-#else
-#define        __PATH_ETC_INET "/etc"
-#endif
-
-/* Default search path. */
-#define        _PATH_DEFPATH           "/usr/local/bin:/usr/bin:/bin:."
-#define _PATH_DEFPATH_ROOT     "/sbin:/bin:/usr/sbin:/usr/bin"
-
-#define        _PATH_BSHELL    "/bin/sh"
-#define        _PATH_CONSOLE   "/dev/console"
-#define        _PATH_CSHELL    "/bin/csh"
-#define        _PATH_DEVDB     "/var/run/dev.db"
-#define        _PATH_DEVNULL   "/dev/null"
-#define        _PATH_DRUM      "/dev/drum"
-#define        _PATH_HEQUIV    __PATH_ETC_INET"/hosts.equiv"
-#define        _PATH_KMEM      "/dev/kmem"
-#define        _PATH_MAILDIR   "/var/spool/mail"
-#define        _PATH_MAN       "/usr/man"
-#define        _PATH_MEM       "/dev/mem"
-#define        _PATH_LOGIN     "/bin/login"
-#define        _PATH_NOLOGIN   "/etc/nologin"
-#define        _PATH_SENDMAIL  "/usr/sbin/sendmail"
-#define        _PATH_SHELLS    "/etc/shells"
-#define        _PATH_TTY       "/dev/tty"
-#define        _PATH_UNIX      "/vmlinux"
-#define        _PATH_VI        "/usr/bin/vi"
-
-/* Provide trailing slash, since mostly used for building pathnames. */
-#define        _PATH_DEV       "/dev/"
-#define        _PATH_TMP       "/tmp/"
-#define        _PATH_VARRUN    "/var/run/"
-#define        _PATH_VARTMP    "/var/tmp/"
-
-#define _PATH_KLOG     "/proc/kmsg"
-#define _PATH_LOGCONF  __PATH_ETC_INET"/syslog.conf"
-#if 0
-#define _PATH_LOGPID   __PATH_ETC_INET"/syslog.pid"
-#else
-#define _PATH_LOGPID   "/var/run/syslog.pid"
-#endif
-#define _PATH_LOG      "/dev/log"
-#define _PATH_CONSOLE  "/dev/console"
-
-#if 0
-#define _PATH_UTMP     "/var/adm/utmp"
-#define _PATH_WTMP     "/var/adm/wtmp"
-#define _PATH_LASTLOG  "/var/adm/lastlog"
-#else
-#define _PATH_UTMP     "/var/run/utmp"
-#define _PATH_WTMP     "/var/log/wtmp"
-#define _PATH_LASTLOG  "/var/log/lastlog"
-#endif
-
-#define _PATH_LOCALE   "/usr/lib/locale"
-
-#define _PATH_RWHODIR  "/var/spool/rwho"
-
-#if _MIT_POSIX_THREADS
-/* For the MIT pthreads */
-#define _PATH_PTY      "/dev/"
-#define _PATH_TZDIR    "/usr/lib/zoneinfo"
-#define _PATH_TZFILE   "/usr/lib/zoneinfo/localtime"
-#endif
-
-#endif /* !_PATHS_H_ */
diff --git a/Win32/Include/sockstorage.h b/Win32/Include/sockstorage.h
deleted file mode 100644 (file)
index 557eb4d..0000000
+++ /dev/null
@@ -1,38 +0,0 @@
-/*
- * 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.
- */
-struct sockaddr_storage {
-#ifdef HAVE_SOCKADDR_SA_LEN
-       u_int8_t __ss_len;
-       u_int8_t __ss_family;
-       u_int8_t fill[126];
-#else
-       u_int8_t __ss_family;
-       u_int8_t fill[127];
-#endif /* HAVE_SOCKADDR_SA_LEN */
-};
diff --git a/Win32/Prj/libpcap.dsp b/Win32/Prj/libpcap.dsp
deleted file mode 100644 (file)
index 17e5a70..0000000
+++ /dev/null
@@ -1,168 +0,0 @@
-# Microsoft Developer Studio Project File - Name="libpcap" - Package Owner=<4>
-# Microsoft Developer Studio Generated Build File, Format Version 6.00
-# ** DO NOT EDIT **
-
-# TARGTYPE "Win32 (x86) Static Library" 0x0104
-
-CFG=libpcap - Win32 Debug
-!MESSAGE This is not a valid makefile. To build this project using NMAKE,
-!MESSAGE use the Export Makefile command and run
-!MESSAGE 
-!MESSAGE NMAKE /f "libpcap.mak".
-!MESSAGE 
-!MESSAGE You can specify a configuration when running NMAKE
-!MESSAGE by defining the macro CFG on the command line. For example:
-!MESSAGE 
-!MESSAGE NMAKE /f "libpcap.mak" CFG="libpcap - Win32 Debug"
-!MESSAGE 
-!MESSAGE Possible choices for configuration are:
-!MESSAGE 
-!MESSAGE "libpcap - Win32 Release" (based on "Win32 (x86) Static Library")
-!MESSAGE "libpcap - Win32 Debug" (based on "Win32 (x86) Static Library")
-!MESSAGE 
-
-# Begin Project
-# PROP AllowPerConfigDependencies 0
-# PROP Scc_ProjName ""
-# PROP Scc_LocalPath ""
-CPP=cl.exe
-RSC=rc.exe
-
-!IF  "$(CFG)" == "libpcap - Win32 Release"
-
-# PROP BASE Use_MFC 0
-# PROP BASE Use_Debug_Libraries 0
-# PROP BASE Output_Dir "Release"
-# PROP BASE Intermediate_Dir "Release"
-# PROP BASE Target_Dir ""
-# PROP Use_MFC 0
-# PROP Use_Debug_Libraries 0
-# PROP Output_Dir "Release"
-# PROP Intermediate_Dir "Release"
-# PROP Target_Dir ""
-# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_MBCS" /D "_LIB" /YX /FD /c
-# ADD CPP /nologo /MT /W3 /GX /O2 /I "../../" /I "../../lbl/" /I "../../bpf/" /I "../include/" /I "../../../../common" /I "../../../../dag/include" /I "../../../../dag/drv/windows" /D "NDEBUG" /D "YY_NEVER_INTERACTIVE" /D yylval=pcap_lval /D "_USRDLL" /D "LIBPCAP_EXPORTS" /D "HAVE_STRERROR" /D "__STDC__" /D "INET6" /D "_WINDOWS" /D "_MBCS" /D "HAVE_ADDRINFO" /D "WIN32" /D _U_= /D "HAVE_SNPRINTF" /D "HAVE_VSNPRINTF" /YX /FD /c
-# ADD BASE RSC /l 0x409 /d "NDEBUG"
-# ADD RSC /l 0x409 /d "NDEBUG"
-BSC32=bscmake.exe
-# ADD BASE BSC32 /nologo
-# ADD BSC32 /nologo
-LIB32=link.exe -lib
-# ADD BASE LIB32 /nologo
-# ADD LIB32 /nologo
-
-!ELSEIF  "$(CFG)" == "libpcap - Win32 Debug"
-
-# PROP BASE Use_MFC 0
-# PROP BASE Use_Debug_Libraries 1
-# PROP BASE Output_Dir "Debug"
-# PROP BASE Intermediate_Dir "Debug"
-# PROP BASE Target_Dir ""
-# PROP Use_MFC 0
-# PROP Use_Debug_Libraries 1
-# PROP Output_Dir "Debug"
-# PROP Intermediate_Dir "Debug"
-# PROP Target_Dir ""
-# ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_MBCS" /D "_LIB" /YX /FD /GZ /c
-# ADD CPP /nologo /MTd /W3 /Gm /GX /ZI /Od /I "../../" /I "../../lbl/" /I "../../bpf/" /I "../include/" /I "../../../../common" /I "../../../../dag/include" /I "../../../../dag/drv/windows" /D "_DEBUG" /D "YY_NEVER_INTERACTIVE" /D yylval=pcap_lval /D "_USRDLL" /D "LIBPCAP_EXPORTS" /D "HAVE_STRERROR" /D "__STDC__" /D "INET6" /D "_WINDOWS" /D "_MBCS" /D "HAVE_ADDRINFO" /D "WIN32" /D _U_= /D "HAVE_SNPRINTF" /D "HAVE_VSNPRINTF" /YX /FD /GZ /c
-# ADD BASE RSC /l 0x409 /d "_DEBUG"
-# ADD RSC /l 0x409 /d "_DEBUG"
-BSC32=bscmake.exe
-# ADD BASE BSC32 /nologo
-# ADD BSC32 /nologo
-LIB32=link.exe -lib
-# ADD BASE LIB32 /nologo
-# ADD LIB32 /nologo
-
-!ENDIF 
-
-# Begin Target
-
-# Name "libpcap - Win32 Release"
-# Name "libpcap - Win32 Debug"
-# Begin Source File
-
-SOURCE=..\..\bpf_dump.c
-# End Source File
-# Begin Source File
-
-SOURCE=..\..\bpf\net\bpf_filter.c
-# End Source File
-# Begin Source File
-
-SOURCE=..\..\bpf_image.c
-# End Source File
-# Begin Source File
-
-SOURCE=..\..\etherent.c
-# End Source File
-# Begin Source File
-
-SOURCE="..\..\fad-win32.c"
-# End Source File
-# Begin Source File
-
-SOURCE=..\Src\ffs.c
-# End Source File
-# Begin Source File
-
-SOURCE=..\..\gencode.c
-# End Source File
-# Begin Source File
-
-SOURCE=..\Src\getnetbynm.c
-# End Source File
-# Begin Source File
-
-SOURCE=..\Src\getnetent.c
-# End Source File
-# Begin Source File
-
-SOURCE=..\Src\getservent.c
-# End Source File
-# Begin Source File
-
-SOURCE=..\..\grammar.c
-# End Source File
-# Begin Source File
-
-SOURCE=..\..\inet.c
-# End Source File
-# Begin Source File
-
-SOURCE=..\Src\inet_aton.c
-# End Source File
-# Begin Source File
-
-SOURCE=..\Src\inet_net.c
-# End Source File
-# Begin Source File
-
-SOURCE=..\Src\inet_pton.c
-# End Source File
-# Begin Source File
-
-SOURCE=..\..\nametoaddr.c
-# End Source File
-# Begin Source File
-
-SOURCE=..\..\optimize.c
-# End Source File
-# Begin Source File
-
-SOURCE="..\..\Pcap-win32.c"
-# End Source File
-# Begin Source File
-
-SOURCE=..\..\pcap.c
-# End Source File
-# Begin Source File
-
-SOURCE=..\..\savefile.c
-# End Source File
-# Begin Source File
-
-SOURCE=..\..\scanner.c
-# End Source File
-# End Target
-# End Project
diff --git a/Win32/Prj/libpcap.dsw b/Win32/Prj/libpcap.dsw
deleted file mode 100644 (file)
index 8cdff2d..0000000
+++ /dev/null
@@ -1,29 +0,0 @@
-Microsoft Developer Studio Workspace File, Format Version 6.00
-# WARNING: DO NOT EDIT OR DELETE THIS WORKSPACE FILE!
-
-###############################################################################
-
-Project: "libpcap"=".\libpcap.dsp" - Package Owner=<4>
-
-Package=<5>
-{{{
-}}}
-
-Package=<4>
-{{{
-}}}
-
-###############################################################################
-
-Global:
-
-Package=<5>
-{{{
-}}}
-
-Package=<3>
-{{{
-}}}
-
-###############################################################################
-
diff --git a/Win32/Prj/wpcap.sln b/Win32/Prj/wpcap.sln
new file mode 100644 (file)
index 0000000..5a9fce9
--- /dev/null
@@ -0,0 +1,28 @@
+
+Microsoft Visual Studio Solution File, Format Version 12.00
+# Visual Studio 2013
+VisualStudioVersion = 12.0.40629.0
+MinimumVisualStudioVersion = 10.0.40219.1
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "wpcap", "wpcap.vcxproj", "{8E92D840-6A36-452A-A13C-6E1BA5A2C5A9}"
+EndProject
+Global
+       GlobalSection(SolutionConfigurationPlatforms) = preSolution
+               Debug|Win32 = Debug|Win32
+               Debug|x64 = Debug|x64
+               Release|Win32 = Release|Win32
+               Release|x64 = Release|x64
+       EndGlobalSection
+       GlobalSection(ProjectConfigurationPlatforms) = postSolution
+               {8E92D840-6A36-452A-A13C-6E1BA5A2C5A9}.Debug|Win32.ActiveCfg = Debug|Win32
+               {8E92D840-6A36-452A-A13C-6E1BA5A2C5A9}.Debug|Win32.Build.0 = Debug|Win32
+               {8E92D840-6A36-452A-A13C-6E1BA5A2C5A9}.Debug|x64.ActiveCfg = Debug|x64
+               {8E92D840-6A36-452A-A13C-6E1BA5A2C5A9}.Debug|x64.Build.0 = Debug|x64
+               {8E92D840-6A36-452A-A13C-6E1BA5A2C5A9}.Release|Win32.ActiveCfg = Release|Win32
+               {8E92D840-6A36-452A-A13C-6E1BA5A2C5A9}.Release|Win32.Build.0 = Release|Win32
+               {8E92D840-6A36-452A-A13C-6E1BA5A2C5A9}.Release|x64.ActiveCfg = Release|x64
+               {8E92D840-6A36-452A-A13C-6E1BA5A2C5A9}.Release|x64.Build.0 = Release|x64
+       EndGlobalSection
+       GlobalSection(SolutionProperties) = preSolution
+               HideSolutionNode = FALSE
+       EndGlobalSection
+EndGlobal
diff --git a/Win32/Prj/wpcap.vcxproj b/Win32/Prj/wpcap.vcxproj
new file mode 100644 (file)
index 0000000..43b7099
--- /dev/null
@@ -0,0 +1,233 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project DefaultTargets="Build" ToolsVersion="12.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+  <ItemGroup Label="ProjectConfigurations">
+    <ProjectConfiguration Include="Debug|Win32">
+      <Configuration>Debug</Configuration>
+      <Platform>Win32</Platform>
+    </ProjectConfiguration>
+    <ProjectConfiguration Include="Debug|x64">
+      <Configuration>Debug</Configuration>
+      <Platform>x64</Platform>
+    </ProjectConfiguration>
+    <ProjectConfiguration Include="Release|Win32">
+      <Configuration>Release</Configuration>
+      <Platform>Win32</Platform>
+    </ProjectConfiguration>
+    <ProjectConfiguration Include="Release|x64">
+      <Configuration>Release</Configuration>
+      <Platform>x64</Platform>
+    </ProjectConfiguration>
+  </ItemGroup>
+  <PropertyGroup Label="Globals">
+    <SccProjectName />
+    <SccLocalPath />
+    <ProjectGuid>{8E92D840-6A36-452A-A13C-6E1BA5A2C5A9}</ProjectGuid>
+  </PropertyGroup>
+  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
+    <ConfigurationType>DynamicLibrary</ConfigurationType>
+    <PlatformToolset>v120</PlatformToolset>
+    <UseOfMfc>false</UseOfMfc>
+    <CharacterSet>MultiByte</CharacterSet>
+  </PropertyGroup>
+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
+    <ConfigurationType>DynamicLibrary</ConfigurationType>
+    <PlatformToolset>v120</PlatformToolset>
+    <UseOfMfc>false</UseOfMfc>
+    <CharacterSet>MultiByte</CharacterSet>
+  </PropertyGroup>
+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
+    <ConfigurationType>DynamicLibrary</ConfigurationType>
+    <PlatformToolset>v120</PlatformToolset>
+    <UseOfMfc>false</UseOfMfc>
+    <CharacterSet>MultiByte</CharacterSet>
+    <WholeProgramOptimization>true</WholeProgramOptimization>
+  </PropertyGroup>
+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
+    <ConfigurationType>DynamicLibrary</ConfigurationType>
+    <PlatformToolset>v120</PlatformToolset>
+    <UseOfMfc>false</UseOfMfc>
+    <CharacterSet>MultiByte</CharacterSet>
+    <WholeProgramOptimization>true</WholeProgramOptimization>
+  </PropertyGroup>
+  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
+  <ImportGroup Label="ExtensionSettings">
+  </ImportGroup>
+  <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="PropertySheets">
+    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+    <Import Project="$(VCTargetsPath)Microsoft.Cpp.UpgradeFromVC60.props" />
+  </ImportGroup>
+  <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="PropertySheets">
+    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+    <Import Project="$(VCTargetsPath)Microsoft.Cpp.UpgradeFromVC60.props" />
+  </ImportGroup>
+  <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="PropertySheets">
+    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+    <Import Project="$(VCTargetsPath)Microsoft.Cpp.UpgradeFromVC60.props" />
+  </ImportGroup>
+  <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="PropertySheets">
+    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+    <Import Project="$(VCTargetsPath)Microsoft.Cpp.UpgradeFromVC60.props" />
+  </ImportGroup>
+  <PropertyGroup Label="UserMacros" />
+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
+    <OutDir>.\Release\</OutDir>
+    <IntDir>.\Release\</IntDir>
+    <LinkIncremental>false</LinkIncremental>
+    <IncludePath>../../../;$(IncludePath)</IncludePath>
+  </PropertyGroup>
+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
+    <LinkIncremental>false</LinkIncremental>
+    <IncludePath>../../../;$(IncludePath)</IncludePath>
+  </PropertyGroup>
+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
+    <OutDir>.\Debug\</OutDir>
+    <IntDir>.\Debug\</IntDir>
+    <LinkIncremental>true</LinkIncremental>
+    <IncludePath>../../../;$(IncludePath)</IncludePath>
+  </PropertyGroup>
+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
+    <LinkIncremental>true</LinkIncremental>
+    <IncludePath>../../../;$(IncludePath)</IncludePath>
+  </PropertyGroup>
+  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
+    <ClCompile>
+      <RuntimeLibrary>MultiThreaded</RuntimeLibrary>
+      <InlineFunctionExpansion>Default</InlineFunctionExpansion>
+      <StringPooling>true</StringPooling>
+      <FunctionLevelLinking>true</FunctionLevelLinking>
+      <Optimization>MaxSpeed</Optimization>
+      <SuppressStartupBanner>true</SuppressStartupBanner>
+      <WarningLevel>Level3</WarningLevel>
+      <AdditionalIncludeDirectories>../../;../../lbl/;../../bpf/;../include/;../../../../common;../../../../dag/include;../../../../dag/drv/windows;../../../Win32-Extensions;./;Win32-Extensions;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+      <PreprocessorDefinitions>HAVE_VERSION_H;__STDC_VERSION__=199901L;HAVE_PACKET_IS_LOOPBACK_ADAPTER;NDEBUG;YY_NEVER_INTERACTIVE;_USRDLL;pcap_EXPORTS;HAVE_STRERROR;__STDC__;INET6;_WINDOWS;ENABLE_REMOTE;WIN32;_U_=;YY_NO_UNISTD_H;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+    </ClCompile>
+    <ResourceCompile>
+      <Culture>0x0409</Culture>
+      <PreprocessorDefinitions>NDEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+    </ResourceCompile>
+    <Link>
+      <AdditionalDependencies>ws2_32.lib;..\..\..\..\packetWin7\Dll\Project\Release No NetMon and AirPcap\Packet.lib;%(AdditionalDependencies)</AdditionalDependencies>
+    </Link>
+    <PreBuildEvent>
+      <Command>call ..\..\GenVersion.bat ..\..\VERSION ..\..\pcap_version.h.in ..\..\pcap_version.h
+win_flex -Ppcap_ -7 --outfile=..\..\scanner.c --header-file=..\..\scanner.h ..\..\scanner.l
+win_bison -ppcap_ --yacc --output=..\..\grammar.c --defines ..\..\grammar.y</Command>
+    </PreBuildEvent>
+  </ItemDefinitionGroup>
+  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
+    <ClCompile>
+      <RuntimeLibrary>MultiThreaded</RuntimeLibrary>
+      <InlineFunctionExpansion>Default</InlineFunctionExpansion>
+      <StringPooling>true</StringPooling>
+      <FunctionLevelLinking>true</FunctionLevelLinking>
+      <Optimization>MaxSpeed</Optimization>
+      <SuppressStartupBanner>true</SuppressStartupBanner>
+      <WarningLevel>Level3</WarningLevel>
+      <AdditionalIncludeDirectories>../../;../../lbl/;../../bpf/;../include/;../../../../common;../../../../dag/include;../../../../dag/drv/windows;../../../Win32-Extensions;./;Win32-Extensions;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+      <PreprocessorDefinitions>HAVE_VERSION_H;__STDC_VERSION__=199901L;HAVE_PACKET_IS_LOOPBACK_ADAPTER;NDEBUG;YY_NEVER_INTERACTIVE;_USRDLL;pcap_EXPORTS;HAVE_STRERROR;__STDC__;INET6;_WINDOWS;ENABLE_REMOTE;WIN32;_U_=;YY_NO_UNISTD_H;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+    </ClCompile>
+    <ResourceCompile>
+      <Culture>0x0409</Culture>
+      <PreprocessorDefinitions>NDEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+    </ResourceCompile>
+    <Link>
+      <AdditionalDependencies>ws2_32.lib;..\..\..\..\packetWin7\Dll\Project\x64\Release No NetMon and AirPcap\Packet.lib;%(AdditionalDependencies)</AdditionalDependencies>
+    </Link>
+    <PreBuildEvent>
+      <Command>call ..\..\GenVersion.bat ..\..\VERSION ..\..\pcap_version.h.in ..\..\pcap_version.h
+win_flex -Ppcap_ -7 --outfile=..\..\scanner.c --header-file=..\..\scanner.h ..\..\scanner.l
+win_bison -ppcap_ --yacc --output=..\..\grammar.c --defines ..\..\grammar.y</Command>
+    </PreBuildEvent>
+  </ItemDefinitionGroup>
+  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
+    <ClCompile>
+      <RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary>
+      <InlineFunctionExpansion>Default</InlineFunctionExpansion>
+      <FunctionLevelLinking>false</FunctionLevelLinking>
+      <Optimization>Disabled</Optimization>
+      <SuppressStartupBanner>true</SuppressStartupBanner>
+      <WarningLevel>Level3</WarningLevel>
+      <MinimalRebuild>true</MinimalRebuild>
+      <DebugInformationFormat>EditAndContinue</DebugInformationFormat>
+      <AdditionalIncludeDirectories>../../;../../lbl/;../../bpf/;../include/;../../../../common;../../../../dag/include;../../../../dag/drv/windows;../../../Win32-Extensions;./;Win32-Extensions;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+      <PreprocessorDefinitions>HAVE_VERSION_H;__STDC_VERSION__=199901L;HAVE_PACKET_IS_LOOPBACK_ADAPTER;_DEBUG;YY_NEVER_INTERACTIVE;_USRDLL;pcap_EXPORTS;HAVE_STRERROR;__STDC__;INET6;_WINDOWS;ENABLE_REMOTE;WIN32;_U_=;YY_NO_UNISTD_H;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+      <BasicRuntimeChecks>EnableFastChecks</BasicRuntimeChecks>
+    </ClCompile>
+    <ResourceCompile>
+      <Culture>0x0409</Culture>
+      <PreprocessorDefinitions>_DEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+    </ResourceCompile>
+    <Link>
+      <AdditionalDependencies>ws2_32.lib;..\..\..\..\packetWin7\Dll\Project\Release No NetMon and AirPcap\Packet.lib;%(AdditionalDependencies)</AdditionalDependencies>
+    </Link>
+    <PreBuildEvent>
+      <Command>call ..\..\GenVersion.bat ..\..\VERSION ..\..\pcap_version.h.in ..\..\pcap_version.h
+win_flex -Ppcap_ -7 --outfile=..\..\scanner.c --header-file=..\..\scanner.h ..\..\scanner.l
+win_bison -ppcap_ --yacc --output=..\..\grammar.c --defines ..\..\grammar.y</Command>
+    </PreBuildEvent>
+  </ItemDefinitionGroup>
+  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
+    <ClCompile>
+      <RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary>
+      <InlineFunctionExpansion>Default</InlineFunctionExpansion>
+      <FunctionLevelLinking>false</FunctionLevelLinking>
+      <Optimization>Disabled</Optimization>
+      <SuppressStartupBanner>true</SuppressStartupBanner>
+      <WarningLevel>Level3</WarningLevel>
+      <DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
+      <AdditionalIncludeDirectories>../../;../../lbl/;../../bpf/;../include/;../../../../common;../../../../dag/include;../../../../dag/drv/windows;../../../Win32-Extensions;./;Win32-Extensions;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+      <PreprocessorDefinitions>HAVE_VERSION_H;__STDC_VERSION__=199901L;HAVE_PACKET_IS_LOOPBACK_ADAPTER;_DEBUG;YY_NEVER_INTERACTIVE;_USRDLL;pcap_EXPORTS;HAVE_STRERROR;__STDC__;INET6;_WINDOWS;ENABLE_REMOTE;WIN32;_U_=;YY_NO_UNISTD_H;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+      <BasicRuntimeChecks>EnableFastChecks</BasicRuntimeChecks>
+    </ClCompile>
+    <ResourceCompile>
+      <Culture>0x0409</Culture>
+      <PreprocessorDefinitions>_DEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+    </ResourceCompile>
+    <Link>
+      <AdditionalDependencies>ws2_32.lib;..\..\..\..\packetWin7\Dll\Project\x64\Release No NetMon and AirPcap\Packet.lib;%(AdditionalDependencies)</AdditionalDependencies>
+    </Link>
+    <PreBuildEvent>
+      <Command>call ..\..\GenVersion.bat ..\..\VERSION ..\..\pcap_version.h.in ..\..\pcap_version.h
+win_flex -Ppcap_ -7 --outfile=..\..\scanner.c --header-file=..\..\scanner.h ..\..\scanner.l
+win_bison -ppcap_ --yacc --output=..\..\grammar.c --defines ..\..\grammar.y</Command>
+    </PreBuildEvent>
+  </ItemDefinitionGroup>
+  <ItemGroup>
+    <ClCompile Include="..\..\bpf\net\bpf_filter.c" />
+    <ClCompile Include="..\..\bpf_dump.c" />
+    <ClCompile Include="..\..\bpf_image.c" />
+    <ClCompile Include="..\..\etherent.c" />
+    <ClCompile Include="..\..\gencode.c" />
+    <ClCompile Include="..\..\grammar.c" />
+    <ClCompile Include="..\..\inet.c" />
+    <ClCompile Include="..\..\missing\win_snprintf.c" />
+    <ClCompile Include="..\..\nametoaddr.c" />
+    <ClCompile Include="..\..\optimize.c" />
+    <ClCompile Include="..\..\pcap-common.c" />
+    <ClCompile Include="..\..\pcap-new.c" />
+    <ClCompile Include="..\..\pcap-rpcap.c" />
+    <ClCompile Include="..\..\pcap-win32.c" />
+    <ClCompile Include="..\..\pcap.c" />
+    <ClCompile Include="..\..\savefile.c" />
+    <ClCompile Include="..\..\scanner.c" />
+    <ClCompile Include="..\..\sf-pcapng.c" />
+    <ClCompile Include="..\..\sf-pcap.c" />
+    <ClCompile Include="..\..\sockutils.c" />
+  </ItemGroup>
+  <ItemGroup>
+    <ClInclude Include="..\..\pcap-common.h" />
+    <ClInclude Include="..\..\pcap-int.h" />
+    <ClInclude Include="..\..\pcap-rpcap.h" />
+    <ClInclude Include="..\..\pcap-stdinc.h" />
+    <ClInclude Include="..\..\pcap.h" />
+    <ClInclude Include="..\..\remote-ext.h" />
+    <ClInclude Include="..\..\sockutils.h" />
+  </ItemGroup>
+  <ItemGroup>
+    <ResourceCompile Include="..\..\..\Win32-Extensions\version.rc" />
+  </ItemGroup>
+  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
+  <ImportGroup Label="ExtensionTargets">
+  </ImportGroup>
+</Project>
diff --git a/Win32/Prj/wpcap.vcxproj.filters b/Win32/Prj/wpcap.vcxproj.filters
new file mode 100644 (file)
index 0000000..6e06ccb
--- /dev/null
@@ -0,0 +1,107 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+  <ItemGroup>
+    <ClCompile Include="..\..\bpf_dump.c">
+      <Filter>Source Files</Filter>
+    </ClCompile>
+    <ClCompile Include="..\..\bpf\net\bpf_filter.c">
+      <Filter>Source Files</Filter>
+    </ClCompile>
+    <ClCompile Include="..\..\bpf_image.c">
+      <Filter>Source Files</Filter>
+    </ClCompile>
+    <ClCompile Include="..\..\etherent.c">
+      <Filter>Source Files</Filter>
+    </ClCompile>
+    <ClCompile Include="..\..\gencode.c">
+      <Filter>Source Files</Filter>
+    </ClCompile>
+    <ClCompile Include="..\..\grammar.c">
+      <Filter>Source Files</Filter>
+    </ClCompile>
+    <ClCompile Include="..\..\inet.c">
+      <Filter>Source Files</Filter>
+    </ClCompile>
+    <ClCompile Include="..\..\nametoaddr.c">
+      <Filter>Source Files</Filter>
+    </ClCompile>
+    <ClCompile Include="..\..\optimize.c">
+      <Filter>Source Files</Filter>
+    </ClCompile>
+    <ClCompile Include="..\..\pcap.c">
+      <Filter>Source Files</Filter>
+    </ClCompile>
+    <ClCompile Include="..\..\pcap-win32.c">
+      <Filter>Source Files</Filter>
+    </ClCompile>
+    <ClCompile Include="..\..\savefile.c">
+      <Filter>Source Files</Filter>
+    </ClCompile>
+    <ClCompile Include="..\..\scanner.c">
+      <Filter>Source Files</Filter>
+    </ClCompile>
+    <ClCompile Include="..\..\sf-pcap.c">
+      <Filter>Source Files</Filter>
+    </ClCompile>
+    <ClCompile Include="..\..\sf-pcapng.c">
+      <Filter>Source Files</Filter>
+    </ClCompile>
+    <ClCompile Include="..\..\pcap-common.c">
+      <Filter>Source Files</Filter>
+    </ClCompile>
+    <ClCompile Include="..\..\fad-helpers.c">
+      <Filter>Source Files</Filter>
+    </ClCompile>
+    <ClCompile Include="..\..\missing\win_snprintf.c">
+      <Filter>Source Files</Filter>
+    </ClCompile>
+    <ClCompile Include="..\..\pcap-new.c">
+      <Filter>Source Files</Filter>
+    </ClCompile>
+    <ClCompile Include="..\..\pcap-rpcap.c">
+      <Filter>Source Files</Filter>
+    </ClCompile>
+    <ClCompile Include="..\..\sockutils.c">
+      <Filter>Source Files</Filter>
+    </ClCompile>
+  </ItemGroup>
+  <ItemGroup>
+    <Filter Include="Header Files">
+      <UniqueIdentifier>{c51dce5e-0da9-4e33-a235-d5c76c76485c}</UniqueIdentifier>
+    </Filter>
+    <Filter Include="Source Files">
+      <UniqueIdentifier>{5ec9fd4b-10b5-4527-b249-56b53d844fb1}</UniqueIdentifier>
+    </Filter>
+    <Filter Include="Resource Files">
+      <UniqueIdentifier>{c90886f0-8973-436b-a7a1-b9e881544f9a}</UniqueIdentifier>
+    </Filter>
+  </ItemGroup>
+  <ItemGroup>
+    <ClInclude Include="..\..\pcap-stdinc.h">
+      <Filter>Header Files</Filter>
+    </ClInclude>
+    <ClInclude Include="..\..\pcap-common.h">
+      <Filter>Header Files</Filter>
+    </ClInclude>
+    <ClInclude Include="..\..\pcap.h">
+      <Filter>Header Files</Filter>
+    </ClInclude>
+    <ClInclude Include="..\..\pcap-int.h">
+      <Filter>Header Files</Filter>
+    </ClInclude>
+    <ClInclude Include="..\..\pcap-rpcap.h">
+      <Filter>Header Files</Filter>
+    </ClInclude>
+    <ClInclude Include="..\..\remote-ext.h">
+      <Filter>Header Files</Filter>
+    </ClInclude>
+    <ClInclude Include="..\..\sockutils.h">
+      <Filter>Header Files</Filter>
+    </ClInclude>
+  </ItemGroup>
+  <ItemGroup>
+    <ResourceCompile Include="..\..\..\Win32-Extensions\version.rc">
+      <Filter>Resource Files</Filter>
+    </ResourceCompile>
+  </ItemGroup>
+</Project>
diff --git a/Win32/Src/gai_strerror.c b/Win32/Src/gai_strerror.c
deleted file mode 100644 (file)
index edd970b..0000000
+++ /dev/null
@@ -1,83 +0,0 @@
-/*
- * Copyright (C) 1995, 1996, 1997, and 1998 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.
- */
-
-/*
-#include <sys/cdefs.h>
-
-__FBSDID("$FreeBSD: /repoman/r/ncvs/src/lib/libc/net/gai_strerror.c,v 1.1 2005/04/06 12:45:51 ume Exp $");
-
-*/
-
-#ifdef WIN32
-
-#include <ws2tcpip.h>
-
-#else
-
-#include <netdb.h>
-
-#endif
-
-/* Entries EAI_ADDRFAMILY (1) and EAI_NODATA (7) are obsoleted, but left */
-/* for backward compatibility with userland code prior to 2553bis-02 */
-static char *ai_errlist[] = {
-       "Success",                                      /* 0 */
-       "Address family for hostname not supported",    /* 1 */
-       "Temporary failure in name resolution",         /* EAI_AGAIN */
-       "Invalid value for ai_flags",                   /* EAI_BADFLAGS */
-       "Non-recoverable failure in name resolution",   /* EAI_FAIL */
-       "ai_family not supported",                      /* EAI_FAMILY */
-       "Memory allocation failure",                    /* EAI_MEMORY */
-       "No address associated with hostname",          /* 7 */
-       "hostname nor servname provided, or not known", /* EAI_NONAME */
-       "servname not supported for ai_socktype",       /* EAI_SERVICE */
-       "ai_socktype not supported",                    /* EAI_SOCKTYPE */
-       "System error returned in errno",               /* EAI_SYSTEM */
-       "Invalid value for hints",                      /* EAI_BADHINTS */
-       "Resolved protocol is unknown"                  /* EAI_PROTOCOL */
-};
-
-#ifndef EAI_MAX
-#define EAI_MAX (sizeof(ai_errlist)/sizeof(ai_errlist[0]))
-#endif
-
-/* on MingW, gai_strerror is available. 
-   We need to compile gai_strerrorA only for Cygwin
- */
-#ifndef gai_strerror
-
-char *
-WSAAPI gai_strerrorA(int ecode)
-{
-       if (ecode >= 0 && ecode < EAI_MAX)
-               return ai_errlist[ecode];
-       return "Unknown error";
-}
-
-#endif /* gai_strerror */
\ No newline at end of file
diff --git a/Win32/Src/getaddrinfo.c b/Win32/Src/getaddrinfo.c
deleted file mode 100644 (file)
index 19ffa68..0000000
+++ /dev/null
@@ -1,1124 +0,0 @@
-/*
- * Copyright (C) 1995, 1996, 1997, and 1998 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.
- */
-
-/*
- * "#ifdef FAITH" part is local hack for supporting IPv4-v6 translator.
- *
- * Issues to be discussed:
- * - Thread safe-ness must be checked.
- * - Return values.  There are nonstandard return values defined and used
- *   in the source code.  This is because RFC2553 is silent about which error
- *   code must be returned for which situation.
- * Note:
- * - We use getipnodebyname() just for thread-safeness.  There's no intent
- *   to let it do PF_UNSPEC (actually we never pass PF_UNSPEC to
- *   getipnodebyname().
- * - The code filters out AFs that are not supported by the kernel,
- *   when globbing NULL hostname (to loopback, or wildcard).  Is it the right
- *   thing to do?  What is the relationship with post-RFC2553 AI_ADDRCONFIG
- *   in ai_flags?
- */
-
-/*
- * Mingw64 has its own implementation of getaddrinfo, mingw32 no
- */
-#ifndef __MINGW64__
-
-#ifdef HAVE_CONFIG_H
-#include <config.h>
-#endif 
-
-#include <pcap-stdinc.h>
-#if 0
-#include <sys/sysctl.h>
-#endif
-#ifndef __MINGW32__
-#include <arpa/nameser.h>
-#endif
-#include <string.h>
-#include <stdlib.h>
-#include <stddef.h>
-#include <ctype.h>
-#include <stdio.h>
-#include <errno.h>
-
-#ifndef HAVE_PORTABLE_PROTOTYPE
-#include "cdecl_ext.h"
-#endif 
-
-#ifndef HAVE_U_INT32_T
-#include "bittypes.h"
-#endif 
-
-#ifndef HAVE_SOCKADDR_STORAGE
-#ifndef __MINGW32__
-#include "sockstorage.h"
-#endif
-#endif 
-
-#ifdef NEED_ADDRINFO_H
-#include "addrinfo.h"
-#ifdef WIN32
-#include "ip6_misc.h"
-#endif
-#endif
-
-
-#if defined(__KAME__) && defined(INET6)
-# define FAITH
-#endif
-
-#define SUCCESS 0
-#define ANY 0
-#define YES 1
-#define NO  0
-
-#ifdef FAITH
-static int translate = NO;
-static struct in6_addr faith_prefix = IN6ADDR_ANY_INIT;
-#endif
-
-static const char in_addrany[] = { 0, 0, 0, 0 };
-static const char in6_addrany[] = {
-       0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
-};
-static const char in_loopback[] = { 127, 0, 0, 1 }; 
-static const char in6_loopback[] = {
-       0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1
-};
-
-struct sockinet {
-       u_char  si_len;
-       u_char  si_family;
-       u_short si_port;
-       u_int32_t si_scope_id;
-};
-
-static const struct afd {
-       int a_af;
-       int a_addrlen;
-       int a_socklen;
-       int a_off;
-       const char *a_addrany;
-       const char *a_loopback; 
-       int a_scoped;
-} afdl [] = {
-#ifdef INET6
-       {PF_INET6, sizeof(struct in6_addr),
-        sizeof(struct sockaddr_in6),
-        offsetof(struct sockaddr_in6, sin6_addr),
-        in6_addrany, in6_loopback, 1},
-#endif
-       {PF_INET, sizeof(struct in_addr),
-        sizeof(struct sockaddr_in),
-        offsetof(struct sockaddr_in, sin_addr),
-        in_addrany, in_loopback, 0},
-       {0, 0, 0, 0, NULL, NULL, 0},
-};
-
-struct explore {
-       int e_af;
-       int e_socktype;
-       int e_protocol;
-       const char *e_protostr;
-       int e_wild;
-#define WILD_AF(ex)            ((ex)->e_wild & 0x01)
-#define WILD_SOCKTYPE(ex)      ((ex)->e_wild & 0x02)
-#define WILD_PROTOCOL(ex)      ((ex)->e_wild & 0x04)
-};
-
-static const struct explore explore[] = {
-#if 0
-       { PF_LOCAL, 0, ANY, ANY, NULL, 0x01 },
-#endif
-#ifdef INET6
-       { PF_INET6, SOCK_DGRAM, IPPROTO_UDP, "udp", 0x07 },
-       { PF_INET6, SOCK_STREAM, IPPROTO_TCP, "tcp", 0x07 },
-       { PF_INET6, SOCK_RAW, ANY, NULL, 0x05 },
-#endif
-       { PF_INET, SOCK_DGRAM, IPPROTO_UDP, "udp", 0x07 },
-       { PF_INET, SOCK_STREAM, IPPROTO_TCP, "tcp", 0x07 },
-       { PF_INET, SOCK_RAW, ANY, NULL, 0x05 },
-       { -1, 0, 0, NULL, 0 },
-};
-
-#ifdef INET6
-#define PTON_MAX       16
-#else
-#define PTON_MAX       4
-#endif
-
-
-static int str_isnumber __P((const char *));
-static int explore_fqdn __P((const struct addrinfo *, const char *,
-       const char *, struct addrinfo **));
-static int explore_null __P((const struct addrinfo *, const char *,
-       const char *, struct addrinfo **));
-static int explore_numeric __P((const struct addrinfo *, const char *,
-       const char *, struct addrinfo **));
-static int explore_numeric_scope __P((const struct addrinfo *, const char *,
-       const char *, struct addrinfo **));
-static int get_name __P((const char *, const struct afd *, struct addrinfo **,
-       char *, const struct addrinfo *, const char *));
-static int get_canonname __P((const struct addrinfo *,
-       struct addrinfo *, const char *));
-static struct addrinfo *get_ai __P((const struct addrinfo *,
-       const struct afd *, const char *));
-static int get_portmatch __P((const struct addrinfo *, const char *));
-static int get_port __P((struct addrinfo *, const char *, int));
-static const struct afd *find_afd __P((int));
-
-static char *ai_errlist[] = {
-       "Success",
-       "Address family for hostname not supported",    /* EAI_ADDRFAMILY */
-       "Temporary failure in name resolution",         /* EAI_AGAIN      */
-       "Invalid value for ai_flags",                   /* EAI_BADFLAGS   */
-       "Non-recoverable failure in name resolution",   /* EAI_FAIL       */
-       "ai_family not supported",                      /* EAI_FAMILY     */
-       "Memory allocation failure",                    /* EAI_MEMORY     */
-       "No address associated with hostname",          /* EAI_NODATA     */
-       "hostname nor servname provided, or not known", /* EAI_NONAME     */
-       "servname not supported for ai_socktype",       /* EAI_SERVICE    */
-       "ai_socktype not supported",                    /* EAI_SOCKTYPE   */
-       "System error returned in errno",               /* EAI_SYSTEM     */
-       "Invalid value for hints",                      /* EAI_BADHINTS   */
-       "Resolved protocol is unknown",                 /* EAI_PROTOCOL   */
-       "Unknown error",                                /* EAI_MAX        */
-};
-
-/* XXX macros that make external reference is BAD. */
-
-#define GET_AI(ai, afd, addr) \
-do { \
-       /* external reference: pai, error, and label free */ \
-       (ai) = get_ai(pai, (afd), (addr)); \
-       if ((ai) == NULL) { \
-               error = EAI_MEMORY; \
-               goto free; \
-       } \
-} while (0)
-
-#define GET_PORT(ai, serv) \
-do { \
-       /* external reference: error and label free */ \
-       error = get_port((ai), (serv), 0); \
-       if (error != 0) \
-               goto free; \
-} while (0)
-
-#define GET_CANONNAME(ai, str) \
-do { \
-       /* external reference: pai, error and label free */ \
-       error = get_canonname(pai, (ai), (str)); \
-       if (error != 0) \
-               goto free; \
-} while (0)
-
-#define ERR(err) \
-do { \
-       /* external reference: error, and label bad */ \
-       error = (err); \
-       goto bad; \
-} while (0)
-
-#define MATCH_FAMILY(x, y, w) \
-       ((x) == (y) || ((w) && ((x) == PF_UNSPEC || (y) == PF_UNSPEC)))
-#define MATCH(x, y, w) \
-       ((x) == (y) || ((w) && ((x) == ANY || (y) == ANY)))
-
-#if  defined(DEFINE_ADDITIONAL_IPV6_STUFF)
-char *
-gai_strerror(ecode)
-       int ecode;
-{
-       if (ecode < 0 || ecode > EAI_MAX)
-               ecode = EAI_MAX;
-       return ai_errlist[ecode];
-}
-#endif
-
-void
-freeaddrinfo(ai)
-       struct addrinfo *ai;
-{
-       struct addrinfo *next;
-
-       do {
-               next = ai->ai_next;
-               if (ai->ai_canonname)
-                       free(ai->ai_canonname);
-               /* no need to free(ai->ai_addr) */
-               free(ai);
-       } while ((ai = next) != NULL);
-}
-
-static int
-str_isnumber(p)
-       const char *p;
-{
-       char *q = (char *)p;
-       while (*q) {
-               if (! isdigit(*q))
-                       return NO;
-               q++;
-       }
-       return YES;
-}
-
-int
-getaddrinfo(hostname, servname, hints, res)
-       const char *hostname, *servname;
-       const struct addrinfo *hints;
-       struct addrinfo **res;
-{
-       struct addrinfo sentinel;
-       struct addrinfo *cur;
-       int error = 0;
-       struct addrinfo ai;
-       struct addrinfo ai0;
-       struct addrinfo *pai;
-       const struct afd *afd;
-       const struct explore *ex;
-
-#ifdef FAITH
-       static int firsttime = 1;
-
-       if (firsttime) {
-               /* translator hack */
-               char *q = getenv("GAI");
-               if (q && inet_pton(AF_INET6, q, &faith_prefix) == 1)
-                       translate = YES;
-               firsttime = 0;
-       }
-#endif
-
-       sentinel.ai_next = NULL;
-       cur = &sentinel;
-       pai = &ai;
-       pai->ai_flags = 0;
-       pai->ai_family = PF_UNSPEC;
-       pai->ai_socktype = ANY;
-       pai->ai_protocol = ANY;
-       pai->ai_addrlen = 0;
-       pai->ai_canonname = NULL;
-       pai->ai_addr = NULL;
-       pai->ai_next = NULL;
-       
-       if (hostname == NULL && servname == NULL)
-               return EAI_NONAME;
-       if (hints) {
-               /* error check for hints */
-               if (hints->ai_addrlen || hints->ai_canonname ||
-                   hints->ai_addr || hints->ai_next)
-                       ERR(EAI_BADHINTS); /* xxx */
-               if (hints->ai_flags & ~AI_MASK)
-                       ERR(EAI_BADFLAGS);
-               switch (hints->ai_family) {
-               case PF_UNSPEC:
-               case PF_INET:
-#ifdef INET6
-               case PF_INET6:
-#endif
-                       break;
-               default:
-                       ERR(EAI_FAMILY);
-               }
-               memcpy(pai, hints, sizeof(*pai));
-
-               /*
-                * if both socktype/protocol are specified, check if they
-                * are meaningful combination.
-                */
-               if (pai->ai_socktype != ANY && pai->ai_protocol != ANY) {
-                       for (ex = explore; ex->e_af >= 0; ex++) {
-                               if (pai->ai_family != ex->e_af)
-                                       continue;
-                               if (ex->e_socktype == ANY)
-                                       continue;
-                               if (ex->e_protocol == ANY)
-                                       continue;
-                               if (pai->ai_socktype == ex->e_socktype
-                                && pai->ai_protocol != ex->e_protocol) {
-                                       ERR(EAI_BADHINTS);
-                               }
-                       }
-               }
-       }
-
-       /*
-        * check for special cases.  (1) numeric servname is disallowed if
-        * socktype/protocol are left unspecified. (2) servname is disallowed
-        * for raw and other inet{,6} sockets.
-        */
-       if (MATCH_FAMILY(pai->ai_family, PF_INET, 1)
-#ifdef PF_INET6
-        || MATCH_FAMILY(pai->ai_family, PF_INET6, 1)
-#endif
-           ) {
-               ai0 = *pai;
-
-               if (pai->ai_family == PF_UNSPEC) {
-#ifdef PF_INET6
-                       pai->ai_family = PF_INET6;
-#else
-                       pai->ai_family = PF_INET;
-#endif
-               }
-               error = get_portmatch(pai, servname);
-               if (error)
-                       ERR(error);
-
-               *pai = ai0;
-       }
-
-       ai0 = *pai;
-
-       /* NULL hostname, or numeric hostname */
-       for (ex = explore; ex->e_af >= 0; ex++) {
-               *pai = ai0;
-
-               if (!MATCH_FAMILY(pai->ai_family, ex->e_af, WILD_AF(ex)))
-                       continue;
-               if (!MATCH(pai->ai_socktype, ex->e_socktype, WILD_SOCKTYPE(ex)))
-                       continue;
-               if (!MATCH(pai->ai_protocol, ex->e_protocol, WILD_PROTOCOL(ex)))
-                       continue;
-
-               if (pai->ai_family == PF_UNSPEC)
-                       pai->ai_family = ex->e_af;
-               if (pai->ai_socktype == ANY && ex->e_socktype != ANY)
-                       pai->ai_socktype = ex->e_socktype;
-               if (pai->ai_protocol == ANY && ex->e_protocol != ANY)
-                       pai->ai_protocol = ex->e_protocol;
-
-               if (hostname == NULL)
-                       error = explore_null(pai, hostname, servname, &cur->ai_next);
-               else
-                       error = explore_numeric_scope(pai, hostname, servname, &cur->ai_next);
-
-               if (error)
-                       goto free;
-
-               while (cur && cur->ai_next)
-                       cur = cur->ai_next;
-       }
-
-       /*
-        * XXX
-        * If numreic representation of AF1 can be interpreted as FQDN
-        * representation of AF2, we need to think again about the code below.
-        */
-       if (sentinel.ai_next)
-               goto good;
-
-       if (pai->ai_flags & AI_NUMERICHOST)
-               ERR(EAI_NONAME);
-       if (hostname == NULL)
-               ERR(EAI_NONAME);
-
-       /*
-        * hostname as alphabetical name.
-        * we would like to prefer AF_INET6 than AF_INET, so we'll make a
-        * outer loop by AFs.
-        */
-       for (afd = afdl; afd->a_af; afd++) {
-               *pai = ai0;
-
-               if (!MATCH_FAMILY(pai->ai_family, afd->a_af, 1))
-                       continue;
-
-               for (ex = explore; ex->e_af >= 0; ex++) {
-                       *pai = ai0;
-
-                       if (pai->ai_family == PF_UNSPEC)
-                               pai->ai_family = afd->a_af;
-
-                       if (!MATCH_FAMILY(pai->ai_family, ex->e_af, WILD_AF(ex)))
-                               continue;
-                       if (!MATCH(pai->ai_socktype, ex->e_socktype,
-                                       WILD_SOCKTYPE(ex))) {
-                               continue;
-                       }
-                       if (!MATCH(pai->ai_protocol, ex->e_protocol,
-                                       WILD_PROTOCOL(ex))) {
-                               continue;
-                       }
-
-                       if (pai->ai_family == PF_UNSPEC)
-                               pai->ai_family = ex->e_af;
-                       if (pai->ai_socktype == ANY && ex->e_socktype != ANY)
-                               pai->ai_socktype = ex->e_socktype;
-                       if (pai->ai_protocol == ANY && ex->e_protocol != ANY)
-                               pai->ai_protocol = ex->e_protocol;
-
-                       error = explore_fqdn(pai, hostname, servname,
-                               &cur->ai_next);
-
-                       while (cur && cur->ai_next)
-                               cur = cur->ai_next;
-               }
-       }
-
-       /* XXX */
-       if (sentinel.ai_next)
-               error = 0;
-
-       if (error)
-               goto free;
-       if (error == 0) {
-               if (sentinel.ai_next) {
- good:
-                       *res = sentinel.ai_next;
-                       return SUCCESS;
-               } else
-                       error = EAI_FAIL;
-       }
- free:
- bad:
-       if (sentinel.ai_next)
-               freeaddrinfo(sentinel.ai_next);
-       *res = NULL;
-       return error;
-}
-
-/*
- * FQDN hostname, DNS lookup
- */
-static int
-explore_fqdn(pai, hostname, servname, res)
-       const struct addrinfo *pai;
-       const char *hostname;
-       const char *servname;
-       struct addrinfo **res;
-{
-       struct hostent *hp;
-       int h_error;
-       int af;
-       char **aplist = NULL, *apbuf = NULL;
-       char *ap;
-       struct addrinfo sentinel, *cur;
-       int i;
-#ifndef USE_GETIPNODEBY
-       int naddrs;
-#endif
-       const struct afd *afd;
-       int error;
-
-       *res = NULL;
-       sentinel.ai_next = NULL;
-       cur = &sentinel;
-
-       /*
-        * Do not filter unsupported AFs here.  We need to honor content of
-        * databases (/etc/hosts, DNS and others).  Otherwise we cannot
-        * replace gethostbyname() by getaddrinfo().
-        */
-
-       /*
-        * if the servname does not match socktype/protocol, ignore it.
-        */
-       if (get_portmatch(pai, servname) != 0)
-               return 0;
-
-       afd = find_afd(pai->ai_family);
-
-       /*
-        * post-RFC2553: should look at (pai->ai_flags & AI_ADDRCONFIG)
-        * rather than hardcoding it.  we may need to add AI_ADDRCONFIG
-        * handling code by ourselves in case we don't have getipnodebyname().
-        */
-#ifdef USE_GETIPNODEBY
-       hp = getipnodebyname(hostname, pai->ai_family, AI_ADDRCONFIG, &h_error);
-#else
-#ifdef HAVE_GETHOSTBYNAME2
-       hp = gethostbyname2(hostname, pai->ai_family);
-#else
-       if (pai->ai_family != AF_INET)
-               return 0;
-       hp = gethostbyname(hostname);
-#ifdef HAVE_H_ERRNO
-       h_error = h_errno;
-#else
-       h_error = EINVAL;
-#endif
-#endif /*HAVE_GETHOSTBYNAME2*/
-#endif /*USE_GETIPNODEBY*/
-
-       if (hp == NULL) {
-               switch (h_error) {
-               case HOST_NOT_FOUND:
-               case NO_DATA:
-                       error = EAI_NODATA;
-                       break;
-               case TRY_AGAIN:
-                       error = EAI_AGAIN;
-                       break;
-               case NO_RECOVERY:
-               case NETDB_INTERNAL:
-               default:
-                       error = EAI_FAIL;
-                       break;
-               }
-       } else if ((hp->h_name == NULL) || (hp->h_name[0] == 0)
-                       || (hp->h_addr_list[0] == NULL)) {
-#ifdef USE_GETIPNODEBY
-               freehostent(hp);
-#endif
-               hp = NULL;
-               error = EAI_FAIL;
-       }
-
-       if (hp == NULL)
-               goto free;
-
-#ifdef USE_GETIPNODEBY
-       aplist = hp->h_addr_list;
-#else
-       /*
-        * hp will be overwritten if we use gethostbyname2().
-        * always deep copy for simplification.
-        */
-       for (naddrs = 0; hp->h_addr_list[naddrs] != NULL; naddrs++)
-               ;
-       naddrs++;
-       aplist = (char **)malloc(sizeof(aplist[0]) * naddrs);
-       apbuf = (char *)malloc(hp->h_length * naddrs);
-       if (aplist == NULL || apbuf == NULL) {
-               error = EAI_MEMORY;
-               goto free;
-       }
-       memset(aplist, 0, sizeof(aplist[0]) * naddrs);
-       for (i = 0; i < naddrs; i++) {
-               if (hp->h_addr_list[i] == NULL) {
-                       aplist[i] = NULL;
-                       continue;
-               }
-               memcpy(&apbuf[i * hp->h_length], hp->h_addr_list[i],
-                       hp->h_length);
-               aplist[i] = &apbuf[i * hp->h_length];
-       }
-#endif
-
-       for (i = 0; aplist[i] != NULL; i++) {
-               af = hp->h_addrtype;
-               ap = aplist[i];
-#ifdef AF_INET6
-               if (af == AF_INET6
-                && IN6_IS_ADDR_V4MAPPED((struct in6_addr *)ap)) {
-                       af = AF_INET;
-                       ap = ap + sizeof(struct in6_addr)
-                               - sizeof(struct in_addr);
-               }
-#endif
-
-               if (af != pai->ai_family)
-                       continue;
-
-               if ((pai->ai_flags & AI_CANONNAME) == 0) {
-                       GET_AI(cur->ai_next, afd, ap);
-                       GET_PORT(cur->ai_next, servname);
-               } else {
-                       /*
-                        * if AI_CANONNAME and if reverse lookup
-                        * fail, return ai anyway to pacify
-                        * calling application.
-                        *
-                        * XXX getaddrinfo() is a name->address
-                        * translation function, and it looks
-                        * strange that we do addr->name
-                        * translation here.
-                        */
-                       get_name(ap, afd, &cur->ai_next,
-                               ap, pai, servname);
-               }
-
-               while (cur && cur->ai_next)
-                       cur = cur->ai_next;
-       }
-
-       *res = sentinel.ai_next;
-       return 0;
-
-free:
-#ifdef USE_GETIPNODEBY
-       if (hp)
-               freehostent(hp);
-#endif
-       if (aplist)
-               free(aplist);
-       if (apbuf)
-               free(apbuf);
-       if (sentinel.ai_next)
-               freeaddrinfo(sentinel.ai_next);
-       return error;
-}
-
-/*
- * hostname == NULL.
- * passive socket -> anyaddr (0.0.0.0 or ::)
- * non-passive socket -> localhost (127.0.0.1 or ::1)
- */
-static int
-explore_null(pai, hostname, servname, res)
-       const struct addrinfo *pai;
-       const char *hostname;
-       const char *servname;
-       struct addrinfo **res;
-{
-       int s;
-       const struct afd *afd;
-       struct addrinfo *cur;
-       struct addrinfo sentinel;
-       int error;
-
-       *res = NULL;
-       sentinel.ai_next = NULL;
-       cur = &sentinel;
-
-       /*
-        * filter out AFs that are not supported by the kernel
-        * XXX errno?
-        */
-       s = socket(pai->ai_family, SOCK_DGRAM, 0);
-       if (s < 0) {
-               if (errno != EMFILE)
-                       return 0;
-       } else
-               close(s);
-
-       /*
-        * if the servname does not match socktype/protocol, ignore it.
-        */
-       if (get_portmatch(pai, servname) != 0)
-               return 0;
-
-       afd = find_afd(pai->ai_family);
-
-       if (pai->ai_flags & AI_PASSIVE) {
-               GET_AI(cur->ai_next, afd, afd->a_addrany);
-               /* xxx meaningless?
-                * GET_CANONNAME(cur->ai_next, "anyaddr");
-                */
-               GET_PORT(cur->ai_next, servname);
-       } else {
-               GET_AI(cur->ai_next, afd, afd->a_loopback);
-               /* xxx meaningless?
-                * GET_CANONNAME(cur->ai_next, "localhost");
-                */
-               GET_PORT(cur->ai_next, servname);
-       }
-       cur = cur->ai_next;
-
-       *res = sentinel.ai_next;
-       return 0;
-
-free:
-       if (sentinel.ai_next)
-               freeaddrinfo(sentinel.ai_next);
-       return error;
-}
-
-/*
- * numeric hostname
- */
-static int
-explore_numeric(pai, hostname, servname, res)
-       const struct addrinfo *pai;
-       const char *hostname;
-       const char *servname;
-       struct addrinfo **res;
-{
-       const struct afd *afd;
-       struct addrinfo *cur;
-       struct addrinfo sentinel;
-       int error;
-       char pton[PTON_MAX];
-       int flags;
-
-       *res = NULL;
-       sentinel.ai_next = NULL;
-       cur = &sentinel;
-
-       /*
-        * if the servname does not match socktype/protocol, ignore it.
-        */
-       if (get_portmatch(pai, servname) != 0)
-               return 0;
-
-       afd = find_afd(pai->ai_family);
-       flags = pai->ai_flags;
-
-       if (inet_pton(afd->a_af, hostname, pton) == 1) {
-               u_int32_t v4a;
-#ifdef INET6
-               u_char pfx;
-#endif
-
-               switch (afd->a_af) {
-               case AF_INET:
-                       v4a = (u_int32_t)ntohl(((struct in_addr *)pton)->s_addr);
-                       if (IN_MULTICAST(v4a) || IN_EXPERIMENTAL(v4a))
-                               flags &= ~AI_CANONNAME;
-                       v4a >>= IN_CLASSA_NSHIFT;
-                       if (v4a == 0 || v4a == IN_LOOPBACKNET)
-                               flags &= ~AI_CANONNAME;
-                       break;
-#ifdef INET6
-               case AF_INET6:
-                       pfx = ((struct in6_addr *)pton)->s6_addr[0];
-                       if (pfx == 0 || pfx == 0xfe || pfx == 0xff)
-                               flags &= ~AI_CANONNAME;
-                       break;
-#endif
-               }
-
-               if (pai->ai_family == afd->a_af ||
-                   pai->ai_family == PF_UNSPEC /*?*/) {
-                       if ((flags & AI_CANONNAME) == 0) {
-                               GET_AI(cur->ai_next, afd, pton);
-                               GET_PORT(cur->ai_next, servname);
-                       } else {
-                               /*
-                                * if AI_CANONNAME and if reverse lookup
-                                * fail, return ai anyway to pacify
-                                * calling application.
-                                *
-                                * XXX getaddrinfo() is a name->address
-                                * translation function, and it looks
-                                * strange that we do addr->name
-                                * translation here.
-                                */
-                               get_name(pton, afd, &cur->ai_next,
-                                       pton, pai, servname);
-                       }
-                       while (cur && cur->ai_next)
-                               cur = cur->ai_next;
-               } else 
-                       ERR(EAI_FAMILY);        /*xxx*/
-       }
-
-       *res = sentinel.ai_next;
-       return 0;
-
-free:
-bad:
-       if (sentinel.ai_next)
-               freeaddrinfo(sentinel.ai_next);
-       return error;
-}
-
-/*
- * numeric hostname with scope
- */
-static int
-explore_numeric_scope(pai, hostname, servname, res)
-       const struct addrinfo *pai;
-       const char *hostname;
-       const char *servname;
-       struct addrinfo **res;
-{
-#ifndef SCOPE_DELIMITER
-       return explore_numeric(pai, hostname, servname, res);
-#else
-       const struct afd *afd;
-       struct addrinfo *cur;
-       int error;
-       char *cp, *hostname2 = NULL;
-       int scope;
-       struct sockaddr_in6 *sin6;
-
-       /*
-        * if the servname does not match socktype/protocol, ignore it.
-        */
-       if (get_portmatch(pai, servname) != 0)
-               return 0;
-
-       afd = find_afd(pai->ai_family);
-       if (!afd->a_scoped)
-               return explore_numeric(pai, hostname, servname, res);
-
-       cp = strchr(hostname, SCOPE_DELIMITER);
-       if (cp == NULL)
-               return explore_numeric(pai, hostname, servname, res);
-
-       /*
-        * Handle special case of <scoped_address><delimiter><scope id>
-        */
-       hostname2 = strdup(hostname);
-       if (hostname2 == NULL)
-               return EAI_MEMORY;
-       /* terminate at the delimiter */
-       hostname2[cp - hostname] = '\0';
-
-       cp++;
-       switch (pai->ai_family) {
-#ifdef INET6
-       case AF_INET6:
-               scope = if_nametoindex(cp);
-               if (scope == 0) {
-                       free(hostname2);
-                       return (EAI_NONAME);
-               }
-               break;
-#endif
-       }
-
-       error = explore_numeric(pai, hostname2, servname, res);
-       if (error == 0) {
-               for (cur = *res; cur; cur = cur->ai_next) {
-                       if (cur->ai_family != AF_INET6)
-                               continue;
-                       sin6 = (struct sockaddr_in6 *)cur->ai_addr;
-                       if (IN6_IS_ADDR_LINKLOCAL(&sin6->sin6_addr) ||
-                           IN6_IS_ADDR_MC_LINKLOCAL(&sin6->sin6_addr))
-                               sin6->sin6_scope_id = scope;
-               }
-       }
-
-       free(hostname2);
-
-       return error;
-#endif
-}
-
-static int
-get_name(addr, afd, res, numaddr, pai, servname)
-       const char *addr;
-       const struct afd *afd;
-       struct addrinfo **res;
-       char *numaddr;
-       const struct addrinfo *pai;
-       const char *servname;
-{
-       struct hostent *hp = NULL;
-       struct addrinfo *cur = NULL;
-       int error = 0;
-       char *ap = NULL, *cn = NULL;
-#ifdef USE_GETIPNODEBY
-       int h_error;
-
-       hp = getipnodebyaddr(addr, afd->a_addrlen, afd->a_af, &h_error);
-#else
-       hp = gethostbyaddr(addr, afd->a_addrlen, afd->a_af);
-#endif
-       if (hp && hp->h_name && hp->h_name[0] && hp->h_addr_list[0]) {
-#ifdef USE_GETIPNODEBY
-               GET_AI(cur, afd, hp->h_addr_list[0]);
-               GET_PORT(cur, servname);
-               GET_CANONNAME(cur, hp->h_name);
-#else
-               /* hp will be damaged if we use gethostbyaddr() */
-               if ((ap = (char *)malloc(hp->h_length)) == NULL) {
-                       error = EAI_MEMORY;
-                       goto free;
-               }
-               memcpy(ap, hp->h_addr_list[0], hp->h_length);
-               if ((cn = strdup(hp->h_name)) == NULL) {
-                       error = EAI_MEMORY;
-                       goto free;
-               }
-
-               GET_AI(cur, afd, ap);
-               GET_PORT(cur, servname);
-               GET_CANONNAME(cur, cn);
-               free(ap); ap = NULL;
-               free(cn); cn = NULL;
-#endif
-       } else {
-               GET_AI(cur, afd, numaddr);
-               GET_PORT(cur, servname);
-       }
-       
-#ifdef USE_GETIPNODEBY
-       if (hp)
-               freehostent(hp);
-#endif
-       *res = cur;
-       return SUCCESS;
- free:
-       if (cur)
-               freeaddrinfo(cur);
-       if (ap)
-               free(ap);
-       if (cn)
-               free(cn);
-#ifdef USE_GETIPNODEBY
-       if (hp)
-               freehostent(hp);
-#endif
-       *res = NULL;
-       return error;
-}
-
-static int
-get_canonname(pai, ai, str)
-       const struct addrinfo *pai;
-       struct addrinfo *ai;
-       const char *str;
-{
-       if ((pai->ai_flags & AI_CANONNAME) != 0) {
-               ai->ai_canonname = strdup(str);
-               if (ai->ai_canonname == NULL)
-                       return EAI_MEMORY;
-       }
-       return 0;
-}
-
-static struct addrinfo *
-get_ai(pai, afd, addr)
-       const struct addrinfo *pai;
-       const struct afd *afd;
-       const char *addr;
-{
-       char *p;
-       struct addrinfo *ai;
-
-       ai = (struct addrinfo *)malloc(sizeof(struct addrinfo)
-               + (afd->a_socklen));
-       if (ai == NULL)
-               return NULL;
-
-       memcpy(ai, pai, sizeof(struct addrinfo));
-       ai->ai_addr = (struct sockaddr *)(ai + 1);
-       memset(ai->ai_addr, 0, afd->a_socklen);
-#ifdef HAVE_SOCKADDR_SA_LEN
-       ai->ai_addr->sa_len = afd->a_socklen;
-#endif
-       ai->ai_addrlen = afd->a_socklen;
-       ai->ai_addr->sa_family = ai->ai_family = afd->a_af;
-       p = (char *)(ai->ai_addr);
-       memcpy(p + afd->a_off, addr, afd->a_addrlen);
-       return ai;
-}
-
-static int
-get_portmatch(ai, servname)
-       const struct addrinfo *ai;
-       const char *servname;
-{
-
-       /* get_port does not touch first argument. when matchonly == 1. */
-       return get_port((struct addrinfo *)ai, servname, 1);
-}
-
-static int
-get_port(ai, servname, matchonly)
-       struct addrinfo *ai;
-       const char *servname;
-       int matchonly;
-{
-       const char *proto;
-       struct servent *sp;
-       int port;
-       int allownumeric;
-
-       if (servname == NULL)
-               return 0;
-       switch (ai->ai_family) {
-       case AF_INET:
-#ifdef AF_INET6
-       case AF_INET6:
-#endif
-               break;
-       default:
-               return 0;
-       }
-
-       switch (ai->ai_socktype) {
-       case SOCK_RAW:
-               return EAI_SERVICE;
-       case SOCK_DGRAM:
-       case SOCK_STREAM:
-               allownumeric = 1;
-               break;
-       case ANY:
-               allownumeric = 0;
-               break;
-       default:
-               return EAI_SOCKTYPE;
-       }
-
-       if (str_isnumber(servname)) {
-               if (!allownumeric)
-                       return EAI_SERVICE;
-               port = htons(atoi(servname));
-               if (port < 0 || port > 65535)
-                       return EAI_SERVICE;
-       } else {
-               switch (ai->ai_socktype) {
-               case SOCK_DGRAM:
-                       proto = "udp";
-                       break;
-               case SOCK_STREAM:
-                       proto = "tcp";
-                       break;
-               default:
-                       proto = NULL;
-                       break;
-               }
-
-               if ((sp = getservbyname(servname, proto)) == NULL)
-                       return EAI_SERVICE;
-               port = sp->s_port;
-       }
-
-       if (!matchonly) {
-               switch (ai->ai_family) {
-               case AF_INET:
-                       ((struct sockaddr_in *)ai->ai_addr)->sin_port = port;
-                       break;
-#ifdef INET6
-               case AF_INET6:
-                       ((struct sockaddr_in6 *)ai->ai_addr)->sin6_port = port;
-                       break;
-#endif
-               }
-       }
-
-       return 0;
-}
-
-static const struct afd *
-find_afd(af)
-       int af;
-{
-       const struct afd *afd;
-
-       if (af == PF_UNSPEC)
-               return NULL;
-       for (afd = afdl; afd->a_af; afd++) {
-               if (afd->a_af == af)
-                       return afd;
-       }
-       return NULL;
-}
-
-
-#endif /*__MING64__*/
diff --git a/Win32/Src/getnetbynm.c b/Win32/Src/getnetbynm.c
deleted file mode 100644 (file)
index fa4d398..0000000
+++ /dev/null
@@ -1,44 +0,0 @@
-/*
- * Copyright (c) 1983 Regents of the University of California.
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms are permitted
- * provided that the above copyright notice and this paragraph are
- * duplicated in all such forms and that any documentation,
- * advertising materials, and other materials related to such
- * distribution and use acknowledge that the software was developed
- * by the University of California, Berkeley.  The name of the
- * University 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 MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
- */
-
-#if defined(LIBC_SCCS) && !defined(lint)
-static char sccsid[] = "@(#)getnetbyname.c     5.5 (Berkeley) 6/27/88";
-#endif /* LIBC_SCCS and not lint */
-
-#include "inetprivate.h"
-
-extern int _net_stayopen;
-
-struct netent *
-getnetbyname(const char *name)
-{
-       register struct netent *p;
-       register char **cp;
-
-       setnetent(_net_stayopen);
-       while (p = getnetent()) {
-               if (strcmp(p->n_name, name) == 0)
-                       break;
-               for (cp = p->n_aliases; *cp != 0; cp++)
-                       if (strcmp(*cp, name) == 0)
-                               goto found;
-       }
-found:
-       if (!_net_stayopen)
-               endnetent();
-       return (p);
-}
diff --git a/Win32/Src/getnetent.c b/Win32/Src/getnetent.c
deleted file mode 100644 (file)
index d4cceb3..0000000
+++ /dev/null
@@ -1,119 +0,0 @@
-/*
- * Copyright (c) 1983 Regents of the University of California.
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms are permitted
- * provided that the above copyright notice and this paragraph are
- * duplicated in all such forms and that any documentation,
- * advertising materials, and other materials related to such
- * distribution and use acknowledge that the software was developed
- * by the University of California, Berkeley.  The name of the
- * University 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 MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
- */
-
-#if defined(LIBC_SCCS) && !defined(lint)
-static char sccsid[] = "@(#)getnetent.c        5.5 (Berkeley) 6/27/88";
-#endif /* LIBC_SCCS and not lint */
-
-#include "inetprivate.h"
-
-#define        MAXALIASES      35
-
-static char NETDB[] = _PATH_NETWORKS;
-static FILE *netf = NULL;
-static char line[BUFSIZ+1];
-static struct netent net;
-static char *net_aliases[MAXALIASES];
-static char *any(char *, char *);
-
-int _net_stayopen;
-extern u_int32_t inet_network(const char *cp);
-
-void
-setnetent(f)
-       int f;
-{
-       if (netf == NULL)
-               netf = fopen(NETDB, "r" );
-       else
-               rewind(netf);
-       _net_stayopen |= f;
-}
-
-void
-endnetent()
-{
-       if (netf) {
-               fclose(netf);
-               netf = NULL;
-       }
-       _net_stayopen = 0;
-}
-
-struct netent *
-getnetent()
-{
-       char *p;
-       register char *cp, **q;
-
-       if (netf == NULL && (netf = fopen(NETDB, "r" )) == NULL)
-               return (NULL);
-again:
-       p = fgets(line, BUFSIZ, netf);
-       if (p == NULL)
-               return (NULL);
-       if (*p == '#')
-               goto again;
-       cp = any(p, "#\n");
-       if (cp == NULL)
-               goto again;
-       *cp = '\0';
-       net.n_name = p;
-       cp = any(p, " \t");
-       if (cp == NULL)
-               goto again;
-       *cp++ = '\0';
-       while (*cp == ' ' || *cp == '\t')
-               cp++;
-       p = any(cp, " \t");
-       if (p != NULL)
-               *p++ = '\0';
-       net.n_net = inet_network(cp);
-       net.n_addrtype = AF_INET;
-       q = net.n_aliases = net_aliases;
-       if (p != NULL) 
-               cp = p;
-       while (cp && *cp) {
-               if (*cp == ' ' || *cp == '\t') {
-                       cp++;
-                       continue;
-               }
-               if (q < &net_aliases[MAXALIASES - 1])
-                       *q++ = cp;
-               cp = any(cp, " \t");
-               if (cp != NULL)
-                       *cp++ = '\0';
-       }
-       *q = NULL;
-       return (&net);
-}
-
-static char *
-any(cp, match)
-       register char *cp;
-       char *match;
-{
-       register char *mp, c;
-
-       while (c = *cp) {
-               for (mp = match; *mp; mp++)
-                       if (*mp == c)
-                               return (cp);
-               cp++;
-       }
-       return ((char *)0);
-}
diff --git a/Win32/Src/getservent.c b/Win32/Src/getservent.c
deleted file mode 100644 (file)
index 61b8cb0..0000000
+++ /dev/null
@@ -1,125 +0,0 @@
-/*
- * Copyright (c) 1983, 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
- *    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[] = "@(#)getservent.c       8.1 (Berkeley) 6/4/93";
-#endif /* LIBC_SCCS and not lint */
-
-#include <sys/types.h>
-#include <string.h>
-
-#include <stdlib.h>
-#include <ctype.h>
-#include <net/netdb.h>
-#include <stdio.h>
-#include <errno.h>
-#include <arpa/nameser.h>
-
-#define        MAXALIASES      35
-
-static char SERVDB[] = _PATH_SERVICES;
-static FILE *servf = NULL;
-static char line[BUFSIZ+1];
-static struct servent serv;
-static char *serv_aliases[MAXALIASES];
-int _serv_stayopen;
-
-void
-setservent(f)
-       int f;
-{
-       if (servf == NULL)
-               servf = fopen(SERVDB, "r" );
-       else
-               rewind(servf);
-       _serv_stayopen |= f;
-}
-
-void
-endservent()
-{
-       if (servf) {
-               fclose(servf);
-               servf = NULL;
-       }
-       _serv_stayopen = 0;
-}
-
-struct servent *
-getservent()
-{
-       char *p;
-       register char *cp, **q;
-
-       if (servf == NULL && (servf = fopen(SERVDB, "r" )) == NULL)
-               return (NULL);
-again:
-       if ((p = fgets(line, BUFSIZ, servf)) == NULL)
-               return (NULL);
-       if (*p == '#')
-               goto again;
-       cp = strpbrk(p, "#\n");
-       if (cp == NULL)
-               goto again;
-       *cp = '\0';
-       serv.s_name = p;
-       p = strpbrk(p, " \t");
-       if (p == NULL)
-               goto again;
-       *p++ = '\0';
-       while (*p == ' ' || *p == '\t')
-               p++;
-       cp = strpbrk(p, ",/");
-       if (cp == NULL)
-               goto again;
-       *cp++ = '\0';
-       serv.s_port = htons((u_short)atoi(p));
-       serv.s_proto = cp;
-       q = serv.s_aliases = serv_aliases;
-       cp = strpbrk(cp, " \t");
-       if (cp != NULL)
-               *cp++ = '\0';
-       while (cp && *cp) {
-               if (*cp == ' ' || *cp == '\t') {
-                       cp++;
-                       continue;
-               }
-               if (q < &serv_aliases[MAXALIASES - 1])
-                       *q++ = cp;
-               cp = strpbrk(cp, " \t");
-               if (cp != NULL)
-                       *cp++ = '\0';
-       }
-       *q = NULL;
-       return (&serv);
-}
diff --git a/Win32/Src/inet_net.c b/Win32/Src/inet_net.c
deleted file mode 100644 (file)
index 5bbe391..0000000
+++ /dev/null
@@ -1,101 +0,0 @@
-/*
- * Copyright (c) 1983, 1993
- *     The Regents of the University of California.  All rights reserved.
- * 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[] = "@(#)inet_network.c     8.1 (Berkeley) 6/4/93";
-#endif /* LIBC_SCCS and not lint */
-
-#include "inetprivate.h"
-
-/*
- * Internet network address interpretation routine.
- * The library routines call this routine to interpret
- * network numbers.
- */
-u_int32_t
-inet_network(const char *cp)
-{
-       register u_long val, base, n;
-       register char c;
-       u_long parts[4], *pp = parts;
-       register int i;
-
-again:
-       /*
-        * Collect number up to ``.''.
-        * Values are specified as for C:
-        * 0x=hex, 0=octal, other=decimal.
-        */
-       val = 0; base = 10;
-       /*
-        * The 4.4BSD version of this file also accepts 'x__' as a hexa
-        * number.  I don't think this is correct.  -- Uli
-        */
-       if (*cp == '0') {
-               if (*++cp == 'x' || *cp == 'X')
-                       base = 16, cp++;
-               else
-                       base = 8;
-       }
-       while ((c = *cp)) {
-               if (isdigit(c)) {
-                       val = (val * base) + (c - '0');
-                       cp++;
-                       continue;
-               }
-               if (base == 16 && isxdigit(c)) {
-                       val = (val << 4) + (c + 10 - (islower(c) ? 'a' : 'A'));
-                       cp++;
-                       continue;
-               }
-               break;
-       }
-       if (*cp == '.') {
-               if (pp >= parts + 4)
-                       return (INADDR_NONE);
-               *pp++ = val, cp++;
-               goto again;
-       }
-       if (*cp && !isspace(*cp))
-               return (INADDR_NONE);
-       *pp++ = val;
-       n = pp - parts;
-       if (n > 4)
-               return (INADDR_NONE);
-       for (val = 0, i = 0; i < (int)n; i++) {
-               val <<= 8;
-               val |= parts[i] & 0xff;
-       }
-       return (val);
-}
index 31a18e1..aa91e84 100644 (file)
@@ -102,6 +102,13 @@ AC_DEFUN(AC_LBL_C_INIT,
            # -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.
+           #
+           AC_LBL_CHECK_COMPILER_OPT($1, -fvisibility=hidden)
     else
            $2="$$2 -I/usr/local/include"
            LDFLAGS="$LDFLAGS -L/usr/local/lib"
@@ -114,6 +121,13 @@ AC_DEFUN(AC_LBL_C_INIT,
                    # 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.
+                   #
+                   AC_LBL_CHECK_COMPILER_OPT($1, -fvisibility=hidden)
                    ;;
 
            hpux*)
@@ -188,6 +202,13 @@ AC_DEFUN(AC_LBL_C_INIT,
                    # 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.
+                   #
+                   AC_LBL_CHECK_COMPILER_OPT($1, -xldscope=hidden)
                    ;;
 
            ultrix*)
@@ -231,7 +252,7 @@ AC_DEFUN(AC_LBL_CHECK_UNKNOWN_WARNING_OPTION_ERROR,
                # We're assuming this is clang, where
                # -Werror=unknown-warning-option is the appropriate
                # option to force the compiler to fail.
-               # 
+               #
                ac_lbl_unknown_warning_option_error="-Werror=unknown-warning-option"
            ],
            [
@@ -245,18 +266,67 @@ dnl Check whether the compiler option specified as the second argument
 dnl is supported by the compiler and, if so, add it to the macro
 dnl specified as the first argument
 dnl
+dnl If a third argument is supplied, treat it as C code to be compiled
+dnl with the flag in question, and the "treat warnings as errors" flag
+dnl set, and don't add the flag to the first argument if the compile
+dnl fails; this is for warning options cause problems that can't be
+dnl worked around.  If a third argument is supplied, a fourth argument
+dnl should also be supplied; it's a message desribing what the test
+dnl program is checking.
+dnl
 AC_DEFUN(AC_LBL_CHECK_COMPILER_OPT,
     [
        AC_MSG_CHECKING([whether the compiler supports the $2 option])
        save_CFLAGS="$CFLAGS"
-       CFLAGS="$CFLAGS $ac_lbl_unknown_warning_option_error $2"
+       if expr "x$2" : "x-W.*" >/dev/null
+       then
+           CFLAGS="$CFLAGS $ac_lbl_unknown_warning_option_error $2"
+       elif expr "x$2" : "x-f.*" >/dev/null
+       then
+           CFLAGS="$CFLAGS -Werror $2"
+       elif expr "x$2" : "x-m.*" >/dev/null
+       then
+           CFLAGS="$CFLAGS -Werror $2"
+       else
+           CFLAGS="$CFLAGS $2"
+       fi
        AC_TRY_COMPILE(
            [],
            [return 0],
            [
                AC_MSG_RESULT([yes])
+               can_add_to_cflags=yes
+               #
+               # The compile supports this; do we have some C code for
+               # which the warning should *not* appear?
+               # We test the fourth argument because the third argument
+               # could contain quotes, breaking the test.
+               #
+               if test "x$4" != "x"
+               then
+                   CFLAGS="$CFLAGS $ac_lbl_cc_force_warning_errors"
+                   AC_MSG_CHECKING(whether $2 $4)
+                   AC_COMPILE_IFELSE(
+                     [AC_LANG_SOURCE($3)],
+                     [
+                       #
+                       # Not a problem.
+                       #
+                       AC_MSG_RESULT(no)
+                     ],
+                     [
+                       #
+                       # A problem.
+                       #
+                       AC_MSG_RESULT(yes)
+                       can_add_to_cflags=no
+                     ])
+               fi
                CFLAGS="$save_CFLAGS"
-               $1="$$1 $2"
+               if test x"$can_add_to_cflags" = "xyes"
+               then
+                   $1="$$1 $2"
+               fi
            ],
            [
                AC_MSG_RESULT([no])
@@ -352,8 +422,7 @@ AC_DEFUN(AC_LBL_CHECK_DEPENDENCY_GENERATION_OPT,
        if test ! -z "$ac_lbl_dependency_flag"; then
                AC_LANG_CONFTEST(
                    [AC_LANG_SOURCE([[int main(void) { return 0; }]])])
-               echo "$CC" $ac_lbl_dependency_flag conftest.c >&5
-               if "$CC" $ac_lbl_dependency_flag conftest.c >/dev/null 2>&1; then
+               if AC_RUN_LOG([eval "$CC $ac_lbl_dependency_flag conftest.c >/dev/null 2>&1"]); then
                        AC_MSG_RESULT([yes, with $ac_lbl_dependency_flag])
                        DEPENDENCY_CFLAG="$ac_lbl_dependency_flag"
                        MKDEP='${srcdir}/mkdep'
@@ -363,7 +432,7 @@ AC_DEFUN(AC_LBL_CHECK_DEPENDENCY_GENERATION_OPT,
                        # We can't run mkdep, so have "make depend" do
                        # nothing.
                        #
-                       MKDEP=:
+                       MKDEP='${srcdir}/nomkdep'
                fi
                rm -rf conftest*
        else
@@ -372,7 +441,7 @@ AC_DEFUN(AC_LBL_CHECK_DEPENDENCY_GENERATION_OPT,
                # We can't run mkdep, so have "make depend" do
                # nothing.
                #
-               MKDEP=:
+               MKDEP='${srcdir}/nomkdep'
        fi
        AC_SUBST(DEPENDENCY_CFLAG)
        AC_SUBST(MKDEP)
@@ -387,7 +456,7 @@ dnl AC_LBL_SHLIBS_INIT
 dnl
 dnl results:
 dnl
-dnl    V_CCOPT (modified to build position-independent code)
+dnl    V_SHLIB_CCOPT (modified to build position-independent code)
 dnl    V_SHLIB_CMD
 dnl    V_SHLIB_OPT
 dnl    V_SONAME_OPT
@@ -400,7 +469,7 @@ AC_DEFUN(AC_LBL_SHLIBS_INIT,
            # On platforms where we build a shared library:
            #
            #   add options to generate position-independent code,
-           #   if necessary (it's the default in AIX and Darwin/OS X);
+           #   if necessary (it's the default in AIX and Darwin/macOS);
            #
            #   define option to set the soname of the shared library,
            #   if the OS supports that;
@@ -415,7 +484,7 @@ AC_DEFUN(AC_LBL_SHLIBS_INIT,
            aix*)
                    ;;
 
-           freebsd*|netbsd*|openbsd*|dragonfly*|linux*|osf*)
+           freebsd*|netbsd*|openbsd*|dragonfly*|linux*|osf*|midipix*)
                    #
                    # Platforms where the linker is the GNU linker
                    # or accepts command-line arguments like
@@ -432,19 +501,19 @@ AC_DEFUN(AC_LBL_SHLIBS_INIT,
                    sparc64*)
                        case "$host_os" in
 
-                       freebsd*|openbsd*)
+                       freebsd*|openbsd*|linux*)
                            PIC_OPT=-fPIC
                            ;;
                        esac
                        ;;
                    esac
-                   V_CCOPT="$V_CCOPT $PIC_OPT"
+                   V_SHLIB_CCOPT="$V_SHLIB_CCOPT $PIC_OPT"
                    V_SONAME_OPT="-Wl,-soname,"
                    V_RPATH_OPT="-Wl,-rpath,"
                    ;;
 
            hpux*)
-                   V_CCOPT="$V_CCOPT -fpic"
+                   V_SHLIB_CCOPT="$V_SHLIB_CCOPT -fpic"
                    #
                    # XXX - this assumes GCC is using the HP linker,
                    # rather than the GNU linker, and that the "+h"
@@ -460,7 +529,7 @@ AC_DEFUN(AC_LBL_SHLIBS_INIT,
                    ;;
 
            solaris*)
-                   V_CCOPT="$V_CCOPT -fpic"
+                   V_SHLIB_CCOPT="$V_SHLIB_CCOPT -fpic"
                    #
                    # XXX - this assumes GCC is using the Sun linker,
                    # rather than the GNU linker.
@@ -475,7 +544,7 @@ AC_DEFUN(AC_LBL_SHLIBS_INIT,
            # where we build a shared library:
            #
            #   add options to generate position-independent code,
-           #   if necessary (it's the default in Darwin/OS X);
+           #   if necessary (it's the default in Darwin/macOS);
            #
            #   if we generate ".so" shared libraries, define the
            #   appropriate options for building the shared library;
@@ -501,7 +570,7 @@ AC_DEFUN(AC_LBL_SHLIBS_INIT,
                    #
                    # "cc" is GCC.
                    #
-                   V_CCOPT="$V_CCOPT -fpic"
+                   V_SHLIB_CCOPT="$V_SHLIB_CCOPT -fpic"
                    V_SHLIB_CMD="\$(CC)"
                    V_SHLIB_OPT="-shared"
                    V_SONAME_OPT="-Wl,-soname,"
@@ -509,7 +578,7 @@ AC_DEFUN(AC_LBL_SHLIBS_INIT,
                    ;;
 
            hpux*)
-                   V_CCOPT="$V_CCOPT +z"
+                   V_SHLIB_CCOPT="$V_SHLIB_CCOPT +z"
                    V_SHLIB_CMD="\$(LD)"
                    V_SHLIB_OPT="-b"
                    V_SONAME_OPT="+h "
@@ -532,7 +601,7 @@ AC_DEFUN(AC_LBL_SHLIBS_INIT,
                    ;;
 
            solaris*)
-                   V_CCOPT="$V_CCOPT -Kpic"
+                   V_SHLIB_CCOPT="$V_SHLIB_CCOPT -Kpic"
                    V_SHLIB_CMD="\$(CC)"
                    V_SHLIB_OPT="-G"
                    V_SONAME_OPT="-h "
@@ -630,82 +699,6 @@ AC_DEFUN(AC_LBL_FIXINCLUDES,
     fi])
 
 dnl
-dnl Check for flex, default to lex
-dnl Require flex 2.4 or higher
-dnl Check for bison, default to yacc
-dnl Default to lex/yacc if both flex and bison are not available
-dnl
-dnl If we're using flex and bison, pass -P to flex and -p to bison
-dnl to define a prefix string for the lexer and parser
-dnl
-dnl If we're not using flex and bison, don't pass those options
-dnl (as they might not work - although if "lex" is a wrapper for
-dnl Flex and "yacc" is a wrapper for Bison, they will work), and
-dnl define NEED_YYPARSE_WRAPPER (we *CANNOT* use YYBISON to check
-dnl whether the wrapper is needed, as some people apparently, for
-dnl some unknown reason, choose to use --without-flex and
-dnl --without-bison on systems that have Flex and Bison, which
-dnl means that the "yacc" they end up using is a wrapper that
-dnl runs "bison -y", and at least some versions of Bison define
-dnl YYBISON even if run with "-y", so we end up not compiling
-dnl the yyparse wrapper and end up with a libpcap that doesn't
-dnl define pcap_parse())
-dnl
-dnl usage:
-dnl
-dnl    AC_LBL_LEX_AND_YACC(lex, yacc, yyprefix)
-dnl
-dnl results:
-dnl
-dnl    $1 (lex set)
-dnl    $2 (yacc appended)
-dnl    $3 (optional flex and bison -P prefix)
-dnl
-AC_DEFUN(AC_LBL_LEX_AND_YACC,
-    [AC_ARG_WITH(flex, [  --without-flex          don't use flex])
-    AC_ARG_WITH(bison, [  --without-bison         don't use bison])
-    if test "$with_flex" = no ; then
-           $1=lex
-    else
-           AC_CHECK_PROGS($1, flex, lex)
-    fi
-    if test "$$1" = flex ; then
-           # The -V flag was added in 2.4
-           AC_MSG_CHECKING(for flex 2.4 or higher)
-           AC_CACHE_VAL(ac_cv_lbl_flex_v24,
-               if flex -V >/dev/null 2>&1; then
-                       ac_cv_lbl_flex_v24=yes
-               else
-                       ac_cv_lbl_flex_v24=no
-               fi)
-           AC_MSG_RESULT($ac_cv_lbl_flex_v24)
-           if test $ac_cv_lbl_flex_v24 = no ; then
-                   s="2.4 or higher required"
-                   AC_MSG_WARN(ignoring obsolete flex executable ($s))
-                   $1=lex
-           fi
-    fi
-    if test "$with_bison" = no ; then
-           $2=yacc
-    else
-           AC_CHECK_PROGS($2, bison, yacc)
-    fi
-    if test "$$2" = bison ; then
-           $2="$$2 -y"
-    fi
-    if test "$$1" != lex -a "$$2" = yacc -o "$$1" = lex -a "$$2" != yacc ; then
-           AC_MSG_WARN(don't have both flex and bison; reverting to lex/yacc)
-           $1=lex
-           $2=yacc
-    fi
-    if test "$$1" = flex -a -n "$3" ; then
-           $1="$$1 -P$3"
-           $2="$$2 -p $3"
-    else
-           AC_DEFINE(NEED_YYPARSE_WRAPPER,1,[if we need a pcap_parse wrapper around yyparse])
-    fi])
-
-dnl
 dnl Checks to see if union wait is used with WEXITSTATUS()
 dnl
 dnl usage:
@@ -735,90 +728,6 @@ AC_DEFUN(AC_LBL_UNION_WAIT,
     fi])
 
 dnl
-dnl Checks to see if the sockaddr struct has the 4.4 BSD sa_len member
-dnl
-dnl usage:
-dnl
-dnl    AC_LBL_SOCKADDR_SA_LEN
-dnl
-dnl results:
-dnl
-dnl    HAVE_SOCKADDR_SA_LEN (defined)
-dnl
-AC_DEFUN(AC_LBL_SOCKADDR_SA_LEN,
-    [AC_MSG_CHECKING(if sockaddr struct has the sa_len member)
-    AC_CACHE_VAL(ac_cv_lbl_sockaddr_has_sa_len,
-       AC_TRY_COMPILE([
-#      include <sys/types.h>
-#      include <sys/socket.h>],
-       [u_int i = sizeof(((struct sockaddr *)0)->sa_len)],
-       ac_cv_lbl_sockaddr_has_sa_len=yes,
-       ac_cv_lbl_sockaddr_has_sa_len=no))
-    AC_MSG_RESULT($ac_cv_lbl_sockaddr_has_sa_len)
-    if test $ac_cv_lbl_sockaddr_has_sa_len = yes ; then
-           AC_DEFINE(HAVE_SOCKADDR_SA_LEN,1,[if struct sockaddr has the sa_len member])
-    fi])
-
-dnl
-dnl Checks to see if there's a sockaddr_storage structure
-dnl
-dnl usage:
-dnl
-dnl    AC_LBL_SOCKADDR_STORAGE
-dnl
-dnl results:
-dnl
-dnl    HAVE_SOCKADDR_STORAGE (defined)
-dnl
-AC_DEFUN(AC_LBL_SOCKADDR_STORAGE,
-    [AC_MSG_CHECKING(if sockaddr_storage struct exists)
-    AC_CACHE_VAL(ac_cv_lbl_has_sockaddr_storage,
-       AC_TRY_COMPILE([
-#      include <sys/types.h>
-#      include <sys/socket.h>],
-       [u_int i = sizeof (struct sockaddr_storage)],
-       ac_cv_lbl_has_sockaddr_storage=yes,
-       ac_cv_lbl_has_sockaddr_storage=no))
-    AC_MSG_RESULT($ac_cv_lbl_has_sockaddr_storage)
-    if test $ac_cv_lbl_has_sockaddr_storage = yes ; then
-           AC_DEFINE(HAVE_SOCKADDR_STORAGE,1,[if struct sockaddr_storage exists])
-    fi])
-
-dnl
-dnl Checks to see if the dl_hp_ppa_info_t struct has the HP-UX 11.00
-dnl dl_module_id_1 member
-dnl
-dnl usage:
-dnl
-dnl    AC_LBL_HP_PPA_INFO_T_DL_MODULE_ID_1
-dnl
-dnl results:
-dnl
-dnl    HAVE_HP_PPA_INFO_T_DL_MODULE_ID_1 (defined)
-dnl
-dnl NOTE: any compile failure means we conclude that it doesn't have
-dnl that member, so if we don't have DLPI, don't have a <sys/dlpi_ext.h>
-dnl header, or have one that doesn't declare a dl_hp_ppa_info_t type,
-dnl we conclude it doesn't have that member (which is OK, as either we
-dnl won't be using code that would use that member, or we wouldn't
-dnl compile in any case).
-dnl
-AC_DEFUN(AC_LBL_HP_PPA_INFO_T_DL_MODULE_ID_1,
-    [AC_MSG_CHECKING(if dl_hp_ppa_info_t struct has dl_module_id_1 member)
-    AC_CACHE_VAL(ac_cv_lbl_dl_hp_ppa_info_t_has_dl_module_id_1,
-       AC_TRY_COMPILE([
-#      include <sys/types.h>
-#      include <sys/dlpi.h>
-#      include <sys/dlpi_ext.h>],
-       [u_int i = sizeof(((dl_hp_ppa_info_t *)0)->dl_module_id_1)],
-       ac_cv_lbl_dl_hp_ppa_info_t_has_dl_module_id_1=yes,
-       ac_cv_lbl_dl_hp_ppa_info_t_has_dl_module_id_1=no))
-    AC_MSG_RESULT($ac_cv_lbl_dl_hp_ppa_info_t_has_dl_module_id_1)
-    if test $ac_cv_lbl_dl_hp_ppa_info_t_has_dl_module_id_1 = yes ; then
-           AC_DEFINE(HAVE_HP_PPA_INFO_T_DL_MODULE_ID_1,1,[if ppa_info_t_dl_module_id exists])
-    fi])
-
-dnl
 dnl Checks to see if -R is used
 dnl
 dnl usage:
@@ -969,9 +878,58 @@ AC_DEFUN(AC_LBL_DEVEL,
            #
            if test "$ac_lbl_cc_dont_try_gcc_dashW" != yes; then
                    AC_LBL_CHECK_UNKNOWN_WARNING_OPTION_ERROR()
+                   AC_LBL_CHECK_COMPILER_OPT($1, -W)
                    AC_LBL_CHECK_COMPILER_OPT($1, -Wall)
+                   AC_LBL_CHECK_COMPILER_OPT($1, -Wcomma)
+                   AC_LBL_CHECK_COMPILER_OPT($1, -Wdeclaration-after-statement)
+                   AC_LBL_CHECK_COMPILER_OPT($1, -Wdocumentation)
+                   AC_LBL_CHECK_COMPILER_OPT($1, -Wformat-nonliteral)
+                   AC_LBL_CHECK_COMPILER_OPT($1, -Wmissing-noreturn)
                    AC_LBL_CHECK_COMPILER_OPT($1, -Wmissing-prototypes)
+                   AC_LBL_CHECK_COMPILER_OPT($1, -Wmissing-variable-declarations)
+                   AC_LBL_CHECK_COMPILER_OPT($1, -Wshadow)
+                   AC_LBL_CHECK_COMPILER_OPT($1, -Wsign-compare)
                    AC_LBL_CHECK_COMPILER_OPT($1, -Wstrict-prototypes)
+                   AC_LBL_CHECK_COMPILER_OPT($1, -Wunused-parameter)
+                   AC_LBL_CHECK_COMPILER_OPT($1, -Wused-but-marked-unused)
+                   # Warns about safeguards added in case the enums are
+                   # extended
+                   # AC_LBL_CHECK_COMPILER_OPT($1, -Wcovered-switch-default)
+                   #
+                   # This can cause problems with ntohs(), ntohl(),
+                   # htons(), and htonl() on some platforms, such
+                   # as OpenBSD 6.3 with Clang 5.0.1.  I guess the
+                   # problem is that the macro that ultimately does
+                   # the byte-swapping involves a conditional
+                   # expression that tests whether the value being
+                   # swapped is a compile-time constant or not,
+                   # using __builtin_constant_p(), and, depending
+                   # on whether it is, does a compile-time swap or
+                   # a run-time swap; perhaps the compiler always
+                   # considers one of the two results of the
+                   # conditional expressin is never evaluated,
+                   # because the conditional check is done at
+                   # compile time, and thus always says "that
+                   # expression is never executed".
+                   #
+                   # (Perhaps there should be a way of flagging
+                   # an expression that you *want* evaluated at
+                   # compile time, so that the compiler 1) warns
+                   # if it *can't* be evaluated at compile time
+                   # and 2) *doesn't* warn that the true or false
+                   # branch will never be reached.)
+                   #
+                   AC_LBL_CHECK_COMPILER_OPT($1, -Wunreachable-code,
+                     [
+#include <arpa/inet.h>
+
+unsigned short
+testme(unsigned short a)
+{
+       return ntohs(a);
+}
+                     ],
+                     [generates warnings from ntohs()])
            fi
            AC_LBL_CHECK_DEPENDENCY_GENERATION_OPT()
            #
 dnl
 dnl AC_LBL_LIBRARY_NET
 dnl
-dnl This test is for network applications that need socket() and
-dnl gethostbyname() -ish functions.  Under Solaris, those applications
-dnl need to link with "-lsocket -lnsl".  Under IRIX, they need to link
-dnl with "-lnsl" but should *not* link with "-lsocket" because
-dnl libsocket.a breaks a number of things (for instance:
-dnl gethostbyname() under IRIX 5.2, and snoop sockets under most
-dnl versions of IRIX).
-dnl
-dnl Unfortunately, many application developers are not aware of this,
-dnl and mistakenly write tests that cause -lsocket to be used under
-dnl IRIX.  It is also easy to write tests that cause -lnsl to be used
-dnl under operating systems where neither are necessary (or useful),
-dnl such as SunOS 4.1.4, which uses -lnsl for TLI.
-dnl
-dnl This test exists so that every application developer does not test
-dnl this in a different, and subtly broken fashion.
-
-dnl It has been argued that this test should be broken up into two
-dnl seperate tests, one for the resolver libraries, and one for the
-dnl libraries necessary for using Sockets API. Unfortunately, the two
-dnl are carefully intertwined and allowing the autoconf user to use
-dnl them independantly potentially results in unfortunate ordering
-dnl dependancies -- as such, such component macros would have to
-dnl carefully use indirection and be aware if the other components were
-dnl executed. Since other autoconf macros do not go to this trouble,
-dnl and almost no applications use sockets without the resolver, this
-dnl complexity has not been implemented.
-dnl
-dnl The check for libresolv is in case you are attempting to link
-dnl statically and happen to have a libresolv.a lying around (and no
-dnl libnsl.a).
+dnl This test is for network applications that need socket functions and
+dnl getaddrinfo()/getnameinfo()-ish functions.  We now require
+dnl getaddrinfo() and getnameinfo().  We also prefer versions of
+dnl recvmsg() that conform to the Single UNIX Specification, so that we
+dnl can check whether a datagram received with recvmsg() was truncated
+dnl when received due to the buffer being too small.
 dnl
-AC_DEFUN(AC_LBL_LIBRARY_NET, [
-    # Most operating systems have gethostbyname() in the default searched
-    # libraries (i.e. libc):
-    # Some OSes (eg. Solaris) place it in libnsl
-    # Some strange OSes (SINIX) have it in libsocket:
-    AC_SEARCH_LIBS(gethostbyname, nsl socket resolv)
-    # Unfortunately libsocket sometimes depends on libnsl and
-    # AC_SEARCH_LIBS isn't up to the task of handling dependencies like this.
-    if test "$ac_cv_search_gethostbyname" = "no"
-    then
-       AC_CHECK_LIB(socket, gethostbyname,
-                     LIBS="-lsocket -lnsl $LIBS", , -lnsl)
-    fi
-    AC_SEARCH_LIBS(socket, socket, ,
-       AC_CHECK_LIB(socket, socket, LIBS="-lsocket -lnsl $LIBS", , -lnsl))
-    # DLPI needs putmsg under HPUX so test for -lstr while we're at it
-    AC_SEARCH_LIBS(putmsg, str)
-    ])
-
+dnl On most operating systems, they're available in the system library.
 dnl
-dnl Test for __attribute__
+dnl Under Solaris, we need to link with libsocket and libnsl to get
+dnl getaddrinfo() and getnameinfo() and, if we have libxnet, we need to
+dnl link with libxnet before libsocket to get a version of recvmsg()
+dnl that conforms to the Single UNIX Specification.
 dnl
-
-AC_DEFUN(AC_C___ATTRIBUTE__, [
-AC_MSG_CHECKING(for __attribute__)
-AC_CACHE_VAL(ac_cv___attribute__, [
-AC_COMPILE_IFELSE([
-  AC_LANG_SOURCE([[
-#include <stdlib.h>
-
-static void foo(void) __attribute__ ((noreturn));
-
-static void
-foo(void)
-{
-  exit(1);
-}
-
-int
-main(int argc, char **argv)
-{
-  foo();
-}
-  ]])],
-ac_cv___attribute__=yes,
-ac_cv___attribute__=no)])
-if test "$ac_cv___attribute__" = "yes"; then
-  AC_DEFINE(HAVE___ATTRIBUTE__, 1, [define if your compiler has __attribute__])
-else
-  #
-  # We can't use __attribute__, so we can't use __attribute__((unused)),
-  # so we define _U_ to an empty string.
-  #
-  V_DEFS="$V_DEFS -D_U_=\"\""
-fi
-AC_MSG_RESULT($ac_cv___attribute__)
-])
-
-dnl
-dnl Test whether __attribute__((unused)) can be used without warnings
+dnl We use getaddrinfo() because we want a portable thread-safe way
+dnl of getting information for a host name or port; there exist _r
+dnl versions of gethostbyname() and getservbyname() on some platforms,
+dnl but not on all platforms.
 dnl
+AC_DEFUN(AC_LBL_LIBRARY_NET, [
+    #
+    # Most operating systems have getaddrinfo() in the default searched
+    # libraries (i.e. libc).  Check there first.
+    #
+    AC_CHECK_FUNC(getaddrinfo,,
+    [
+       #
+       # Not found in the standard system libraries.
+       # Try libsocket, which requires libnsl.
+       #
+       AC_CHECK_LIB(socket, getaddrinfo,
+       [
+           #
+           # OK, we found it in libsocket.
+           #
+           LIBS="-lsocket -lnsl $LIBS"
+       ],
+       [
+           #
+           # We didn't find it.
+           #
+           AC_MSG_ERROR([getaddrinfo is required, but wasn't found])
+       ], -lnsl)
 
-AC_DEFUN(AC_C___ATTRIBUTE___UNUSED, [
-AC_MSG_CHECKING([whether __attribute__((unused)) can be used without warnings])
-AC_CACHE_VAL(ac_cv___attribute___unused, [
-save_CFLAGS="$CFLAGS"
-CFLAGS="$CFLAGS $ac_lbl_cc_force_warning_errors"
-AC_COMPILE_IFELSE([
-  AC_LANG_SOURCE([[
-#include <stdlib.h>
-#include <stdio.h>
-
-int
-main(int argc  __attribute((unused)), char **argv __attribute((unused)))
-{
-  printf("Hello, world!\n");
-  return 0;
-}
-  ]])],
-ac_cv___attribute___unused=yes,
-ac_cv___attribute___unused=no)])
-CFLAGS="$save_CFLAGS"
-if test "$ac_cv___attribute___unused" = "yes"; then
-  V_DEFS="$V_DEFS -D_U_=\"__attribute__((unused))\""
-else
-  V_DEFS="$V_DEFS -D_U_=\"\""
-fi
-AC_MSG_RESULT($ac_cv___attribute___unused)
-])
-
-dnl
-dnl Test whether __attribute__((format)) can be used without warnings
-dnl
-
-AC_DEFUN(AC_C___ATTRIBUTE___FORMAT, [
-AC_MSG_CHECKING([whether __attribute__((format)) can be used without warnings])
-AC_CACHE_VAL(ac_cv___attribute___format, [
-save_CFLAGS="$CFLAGS"
-CFLAGS="$CFLAGS $ac_lbl_cc_force_warning_errors"
-AC_COMPILE_IFELSE([
-  AC_LANG_SOURCE([[
-#include <stdlib.h>
-
-extern int foo(const char *fmt, ...)
-                 __attribute__ ((format (printf, 1, 2)));
-
-int
-main(int argc, char **argv)
-{
-  foo("%s", "test");
-}
-  ]])],
-ac_cv___attribute___format=yes,
-ac_cv___attribute___format=no)])
-CFLAGS="$save_CFLAGS"
-if test "$ac_cv___attribute___format" = "yes"; then
-  AC_DEFINE(__ATTRIBUTE___FORMAT_OK, 1,
-    [define if your compiler allows __attribute__((format)) without a warning])
-fi
-AC_MSG_RESULT($ac_cv___attribute___format)
+       #
+       # OK, do we have recvmsg() in libxnet?
+       # We also link with libsocket and libnsl.
+       #
+       AC_CHECK_LIB(xnet, recvmsg,
+       [
+           #
+           # Yes - link with it as well.
+           #
+           LIBS="-lxnet $LIBS"
+       ], , -lsocket -lnsl)
+    ])
+    # DLPI needs putmsg under HPUX so test for -lstr while we're at it
+    AC_SEARCH_LIBS(putmsg, str)
 ])
-
-dnl
-dnl Checks to see if tpacket_stats is defined in linux/if_packet.h
-dnl If so then pcap-linux.c can use this to report proper statistics.
-dnl
-dnl -Scott Barron
-dnl
-AC_DEFUN(AC_LBL_TPACKET_STATS,
-   [AC_MSG_CHECKING(if if_packet.h has tpacket_stats defined)
-   AC_CACHE_VAL(ac_cv_lbl_tpacket_stats,
-   AC_TRY_COMPILE([
-#  include <linux/if_packet.h>],
-   [struct tpacket_stats stats],
-   ac_cv_lbl_tpacket_stats=yes,
-   ac_cv_lbl_tpacket_stats=no))
-   AC_MSG_RESULT($ac_cv_lbl_tpacket_stats)
-   if test $ac_cv_lbl_tpacket_stats = yes; then
-       AC_DEFINE(HAVE_TPACKET_STATS,1,[if if_packet.h has tpacket_stats defined])
-   fi])
-
-dnl
-dnl Checks to see if the tpacket_auxdata struct has a tp_vlan_tci member.
-dnl
-dnl usage:
-dnl
-dnl    AC_LBL_LINUX_TPACKET_AUXDATA_TP_VLAN_TCI
-dnl
-dnl results:
-dnl
-dnl    HAVE_LINUX_TPACKET_AUXDATA_TP_VLAN_TCI (defined)
-dnl
-dnl NOTE: any compile failure means we conclude that it doesn't have
-dnl that member, so if we don't have tpacket_auxdata, we conclude it
-dnl doesn't have that member (which is OK, as either we won't be using
-dnl code that would use that member, or we wouldn't compile in any case).
-dnl
-AC_DEFUN(AC_LBL_LINUX_TPACKET_AUXDATA_TP_VLAN_TCI,
-    [AC_MSG_CHECKING(if tpacket_auxdata struct has tp_vlan_tci member)
-    AC_CACHE_VAL(ac_cv_lbl_linux_tpacket_auxdata_tp_vlan_tci,
-       AC_TRY_COMPILE([
-#      include <sys/types.h>
-#      include <linux/if_packet.h>],
-       [u_int i = sizeof(((struct tpacket_auxdata *)0)->tp_vlan_tci)],
-       ac_cv_lbl_linux_tpacket_auxdata_tp_vlan_tci=yes,
-       ac_cv_lbl_linux_tpacket_auxdata_tp_vlan_tci=no))
-    AC_MSG_RESULT($ac_cv_lbl_linux_tpacket_auxdata_tp_vlan_tci)
-    if test $ac_cv_lbl_linux_tpacket_auxdata_tp_vlan_tci = yes ; then
-           HAVE_LINUX_TPACKET_AUXDATA=tp_vlan_tci
-           AC_SUBST(HAVE_LINUX_TPACKET_AUXDATA)
-           AC_DEFINE(HAVE_LINUX_TPACKET_AUXDATA_TP_VLAN_TCI,1,[if tp_vlan_tci exists])
-    fi])
-
-dnl
-dnl Checks to see if Solaris has the dl_passive_req_t struct defined
-dnl in <sys/dlpi.h>.
-dnl
-dnl usage:
-dnl
-dnl    AC_LBL_DL_PASSIVE_REQ_T
-dnl
-dnl results:
-dnl 
-dnl    HAVE_DLPI_PASSIVE (defined)
-dnl
-AC_DEFUN(AC_LBL_DL_PASSIVE_REQ_T,
-        [AC_MSG_CHECKING(if dl_passive_req_t struct exists)
-       AC_CACHE_VAL(ac_cv_lbl_has_dl_passive_req_t,
-                AC_TRY_COMPILE([
-#       include <sys/types.h>
-#       include <sys/dlpi.h>],
-        [u_int i = sizeof(dl_passive_req_t)],
-        ac_cv_lbl_has_dl_passive_req_t=yes,
-        ac_cv_lbl_has_dl_passive_req_t=no))
-    AC_MSG_RESULT($ac_cv_lbl_has_dl_passive_req_t)
-    if test $ac_cv_lbl_has_dl_passive_req_t = yes ; then
-            AC_DEFINE(HAVE_DLPI_PASSIVE,1,[if passive_req_t primitive
-               exists])
-    fi])
index 5eaadc0..a9c9116 100644 (file)
  */
 
 #ifdef HAVE_CONFIG_H
-#include "config.h"
+#include <config.h>
 #endif
 
 #include <pcap.h>
 #include <stdio.h>
 
+#include "optimize.h"
+
 void
 bpf_dump(const struct bpf_program *p, int option)
 {
@@ -50,8 +52,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 (i < NBIDS && bids[i] > 0)
+                       printf("[%02d]", bids[i] - 1);
+               else
+                       printf(" -- ");
 #endif
                puts(bpf_image(insn, i));
        }
similarity index 69%
rename from bpf/net/bpf_filter.c
rename to bpf_filter.c
index ad689e1..33872ff 100644 (file)
  */
 
 #ifdef HAVE_CONFIG_H
-#include "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>
-#endif
+#include <pcap/pcap-inttypes.h>
+#include "pcap-types.h"
 
+#ifndef _WIN32
 #include <sys/param.h>
 #include <sys/types.h>
 #include <sys/time.h>
+#endif /* _WIN32 */
 
-#define        SOLARIS (defined(sun) && (defined(__SVR4) || defined(__svr4__)))
-#if defined(__hpux) || SOLARIS
-# include <sys/sysmacros.h>
-# include <sys/stream.h>
-# define       mbuf    msgb
-# define       m_next  b_cont
-# define       MLEN(m) ((m)->b_wptr - (m)->b_rptr)
-# define       mtod(m,t)       ((t)(m)->b_rptr)
-#else /* defined(__hpux) || SOLARIS */
-# define       MLEN(m) ((m)->m_len)
-#endif /* defined(__hpux) || SOLARIS */
-
-#endif /* WIN32 */
+#include <pcap-int.h>
 
-#include <pcap/bpf.h>
-
-#if !defined(KERNEL) && !defined(_KERNEL)
 #include <stdlib.h>
-#endif
 
 #define int32 bpf_int32
 #define u_int32 bpf_u_int32
@@ -99,7 +73,7 @@
 #endif
 
 #ifndef LBL_ALIGN
-#ifndef WIN32
+#ifndef _WIN32
 #include <netinet/in.h>
 #endif
 
                 (u_int32)*((u_char *)p+3)<<0)
 #endif
 
-#if defined(KERNEL) || defined(_KERNEL)
-# if !defined(__hpux) && !SOLARIS
-#include <sys/mbuf.h>
-# endif
-#define MINDEX(len, _m, _k) \
-{ \
-       len = MLEN(m); \
-       while ((_k) >= len) { \
-               (_k) -= len; \
-               (_m) = (_m)->m_next; \
-               if ((_m) == 0) \
-                       return 0; \
-               len = MLEN(m); \
-       } \
-}
-
-static int
-m_xword(m, k, err)
-       register struct mbuf *m;
-       register int k, *err;
-{
-       register int len;
-       register u_char *cp, *np;
-       register struct mbuf *m0;
-
-       MINDEX(len, m, k);
-       cp = mtod(m, u_char *) + k;
-       if (len - k >= 4) {
-               *err = 0;
-               return EXTRACT_LONG(cp);
-       }
-       m0 = m->m_next;
-       if (m0 == 0 || MLEN(m0) + len - k < 4)
-               goto bad;
-       *err = 0;
-       np = mtod(m0, u_char *);
-       switch (len - k) {
-
-       case 1:
-               return (cp[0] << 24) | (np[0] << 16) | (np[1] << 8) | np[2];
-
-       case 2:
-               return (cp[0] << 24) | (cp[1] << 16) | (np[0] << 8) | np[1];
-
-       default:
-               return (cp[0] << 24) | (cp[1] << 16) | (cp[2] << 8) | np[0];
-       }
-    bad:
-       *err = 1;
-       return 0;
-}
-
-static int
-m_xhalf(m, k, err)
-       register struct mbuf *m;
-       register int k, *err;
-{
-       register int len;
-       register u_char *cp;
-       register struct mbuf *m0;
-
-       MINDEX(len, m, k);
-       cp = mtod(m, u_char *) + k;
-       if (len - k >= 2) {
-               *err = 0;
-               return EXTRACT_SHORT(cp);
-       }
-       m0 = m->m_next;
-       if (m0 == 0)
-               goto bad;
-       *err = 0;
-       return (cp[0] << 8) | mtod(m0, u_char *)[0];
- bad:
-       *err = 1;
-       return 0;
-}
+#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)
-       register const struct bpf_insn *pc;
-       register const u_char *p;
-       u_int wirelen;
-       register u_int buflen;
+bpf_filter_with_aux_data(const struct bpf_insn *pc, const u_char *p,
+    u_int wirelen, u_int buflen, const struct bpf_aux_data *aux_data)
 {
        register u_int32 A, X;
-       register int k;
-       int32 mem[BPF_MEMWORDS];
-#if defined(KERNEL) || defined(_KERNEL)
-       struct mbuf *m, *n;
-       int merr, len;
-
-       if (buflen == 0) {
-               m = (struct mbuf *)p;
-               p = mtod(m, u_char *);
-               buflen = MLEN(m);
-       } else
-               m = NULL;
-#endif
+       register bpf_u_int32 k;
+       u_int32 mem[BPF_MEMWORDS];
 
        if (pc == 0)
                /*
@@ -232,16 +131,12 @@ bpf_filter(pc, p, wirelen, buflen)
        A = 0;
        X = 0;
        --pc;
-       while (1) {
+       for (;;) {
                ++pc;
                switch (pc->code) {
 
                default:
-#if defined(KERNEL) || defined(_KERNEL)
-                       return 0;
-#else
                        abort();
-#endif
                case BPF_RET|BPF_K:
                        return (u_int)pc->k;
 
@@ -250,53 +145,44 @@ bpf_filter(pc, p, wirelen, buflen)
 
                case BPF_LD|BPF_W|BPF_ABS:
                        k = pc->k;
-                       if (k + sizeof(int32) > buflen) {
-#if defined(KERNEL) || defined(_KERNEL)
-                               if (m == NULL)
-                                       return 0;
-                               A = m_xword(m, k, &merr);
-                               if (merr != 0)
-                                       return 0;
-                               continue;
-#else
+                       if (k > buflen || sizeof(int32_t) > buflen - k) {
                                return 0;
-#endif
                        }
                        A = EXTRACT_LONG(&p[k]);
                        continue;
 
                case BPF_LD|BPF_H|BPF_ABS:
                        k = pc->k;
-                       if (k + sizeof(short) > buflen) {
-#if defined(KERNEL) || defined(_KERNEL)
-                               if (m == NULL)
-                                       return 0;
-                               A = m_xhalf(m, k, &merr);
-                               if (merr != 0)
-                                       return 0;
-                               continue;
-#else
+                       if (k > buflen || sizeof(int16_t) > buflen - k) {
                                return 0;
-#endif
                        }
                        A = EXTRACT_SHORT(&p[k]);
                        continue;
 
                case BPF_LD|BPF_B|BPF_ABS:
-                       k = pc->k;
-                       if (k >= buflen) {
-#if defined(KERNEL) || defined(_KERNEL)
-                               if (m == NULL)
+                       switch (pc->k) {
+
+#if defined(SKF_AD_VLAN_TAG_PRESENT)
+                       case SKF_AD_OFF + SKF_AD_VLAN_TAG:
+                               if (!aux_data)
                                        return 0;
-                               n = m;
-                               MINDEX(len, n, k);
-                               A = mtod(n, u_char *)[k];
-                               continue;
-#else
-                               return 0;
+                               A = aux_data->vlan_tag;
+                               break;
+
+                       case SKF_AD_OFF + SKF_AD_VLAN_TAG_PRESENT:
+                               if (!aux_data)
+                                       return 0;
+                               A = aux_data->vlan_tag_present;
+                               break;
 #endif
+                       default:
+                               k = pc->k;
+                               if (k >= buflen) {
+                                       return 0;
+                               }
+                               A = p[k];
+                               break;
                        }
-                       A = p[k];
                        continue;
 
                case BPF_LD|BPF_W|BPF_LEN:
@@ -309,51 +195,26 @@ bpf_filter(pc, p, wirelen, buflen)
 
                case BPF_LD|BPF_W|BPF_IND:
                        k = X + pc->k;
-                       if (k + sizeof(int32) > buflen) {
-#if defined(KERNEL) || defined(_KERNEL)
-                               if (m == NULL)
-                                       return 0;
-                               A = m_xword(m, k, &merr);
-                               if (merr != 0)
-                                       return 0;
-                               continue;
-#else
+                       if (pc->k > buflen || X > buflen - pc->k ||
+                           sizeof(int32_t) > buflen - k) {
                                return 0;
-#endif
                        }
                        A = EXTRACT_LONG(&p[k]);
                        continue;
 
                case BPF_LD|BPF_H|BPF_IND:
                        k = X + pc->k;
-                       if (k + sizeof(short) > buflen) {
-#if defined(KERNEL) || defined(_KERNEL)
-                               if (m == NULL)
-                                       return 0;
-                               A = m_xhalf(m, k, &merr);
-                               if (merr != 0)
-                                       return 0;
-                               continue;
-#else
+                       if (X > buflen || pc->k > buflen - X ||
+                           sizeof(int16_t) > buflen - k) {
                                return 0;
-#endif
                        }
                        A = EXTRACT_SHORT(&p[k]);
                        continue;
 
                case BPF_LD|BPF_B|BPF_IND:
                        k = X + 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;
-#else
+                       if (pc->k >= buflen || X >= buflen - pc->k) {
                                return 0;
-#endif
                        }
                        A = p[k];
                        continue;
@@ -361,16 +222,7 @@ bpf_filter(pc, p, wirelen, buflen)
                case BPF_LDX|BPF_MSH|BPF_B:
                        k = pc->k;
                        if (k >= buflen) {
-#if defined(KERNEL) || defined(_KERNEL)
-                               if (m == NULL)
-                                       return 0;
-                               n = m;
-                               MINDEX(len, n, k);
-                               X = (mtod(n, char *)[k] & 0xf) << 2;
-                               continue;
-#else
                                return 0;
-#endif
                        }
                        X = (p[pc->k] & 0xf) << 2;
                        continue;
@@ -400,18 +252,11 @@ bpf_filter(pc, p, wirelen, buflen)
                        continue;
 
                case BPF_JMP|BPF_JA:
-#if defined(KERNEL) || defined(_KERNEL)
-                       /*
-                        * No backward jumps allowed.
-                        */
-                       pc += pc->k;
-#else
                        /*
                         * XXX - we currently implement "ip6 protochain"
                         * with backward jumps, so sign-extend pc->k.
                         */
                        pc += (bpf_int32)pc->k;
-#endif
                        continue;
 
                case BPF_JMP|BPF_JGT|BPF_K:
@@ -483,11 +328,17 @@ bpf_filter(pc, p, wirelen, buflen)
                        continue;
 
                case BPF_ALU|BPF_LSH|BPF_X:
-                       A <<= X;
+                       if (X < 32)
+                               A <<= X;
+                       else
+                               A = 0;
                        continue;
 
                case BPF_ALU|BPF_RSH|BPF_X:
-                       A >>= X;
+                       if (X < 32)
+                               A >>= X;
+                       else
+                               A = 0;
                        continue;
 
                case BPF_ALU|BPF_ADD|BPF_K:
@@ -531,7 +382,15 @@ 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; respecify it as subtracting
+                        * the accumulator from 0U, so that 1) we don't
+                        * get compiler warnings about negating an unsigned
+                        * value and 2) don't get UBSan warnings about
+                        * the result of negating 0x80000000 being undefined.
+                        */
+                       A = (0U - A);
                        continue;
 
                case BPF_MISC|BPF_TAX:
@@ -545,6 +404,14 @@ bpf_filter(pc, p, wirelen, buflen)
        }
 }
 
+u_int
+bpf_filter(const struct bpf_insn *pc, const u_char *p, u_int wirelen,
+    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
@@ -557,24 +424,15 @@ bpf_filter(pc, p, wirelen, buflen)
  * Otherwise, a bogus program could easily crash the system.
  */
 int
-bpf_validate(f, len)
-       const struct bpf_insn *f;
-       int len;
+bpf_validate(const struct bpf_insn *f, int len)
 {
        u_int i, from;
        const struct bpf_insn *p;
 
        if (len < 1)
                return 0;
-       /*
-        * There's no maximum program length in userland.
-        */
-#if defined(KERNEL) || defined(_KERNEL)
-       if (len > BPF_MAXINSNS)
-               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)) {
                /*
@@ -593,14 +451,6 @@ bpf_validate(f, len)
                                 * in userland.  The runtime packet length
                                 * check suffices.
                                 */
-#if defined(KERNEL) || defined(_KERNEL)
-                               /*
-                                * More strict check with actual packet length
-                                * is done runtime.
-                                */
-                               if (p->k >= bpf_maxbufsize)
-                                       return 0;
-#endif
                                break;
                        case BPF_MEM:
                                if (p->k >= BPF_MEMWORDS)
@@ -672,18 +522,14 @@ bpf_validate(f, len)
                        from = i + 1;
                        switch (BPF_OP(p->code)) {
                        case BPF_JA:
-#if defined(KERNEL) || defined(_KERNEL)
-                               if (from + p->k < from || from + p->k >= len)
-#else
-                               if (from + p->k >= len)
-#endif
+                               if (from + p->k >= (u_int)len)
                                        return 0;
                                break;
                        case BPF_JEQ:
                        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:
index 3e9a23f..ab41d1e 100644 (file)
  */
 
 #ifdef HAVE_CONFIG_H
-#include "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>
-#endif
-#include <sys/types.h>
-#endif /* WIN32 */
+#include <pcap-types.h>
 
 #include <stdio.h>
 #include <string.h>
 #endif
 
 char *
-bpf_image(p, n)
-       const struct bpf_insn *p;
-       int n;
+bpf_image(const struct bpf_insn *p, int n)
 {
-       int v;
-       const char *fmt, *op;
+       const char *op;
        static char image[256];
-       char operand[64];
+       char operand_buf[64];
+       const char *operand;
 
-       v = p->k;
        switch (p->code) {
 
        default:
                op = "unimp";
-               fmt = "0x%x";
-               v = p->code;
+               (void)pcap_snprintf(operand_buf, sizeof operand_buf, "0x%x", p->code);
+               operand = operand_buf;
                break;
 
        case BPF_RET|BPF_K:
                op = "ret";
-               fmt = "#%d";
+               (void)pcap_snprintf(operand_buf, sizeof operand_buf, "#%d", p->k);
+               operand = operand_buf;
                break;
 
        case BPF_RET|BPF_A:
                op = "ret";
-               fmt = "";
+               operand = "";
                break;
 
        case BPF_LD|BPF_W|BPF_ABS:
                op = "ld";
-               fmt = "[%d]";
+               (void)pcap_snprintf(operand_buf, sizeof operand_buf, "[%d]", p->k);
+               operand = operand_buf;
                break;
 
        case BPF_LD|BPF_H|BPF_ABS:
                op = "ldh";
-               fmt = "[%d]";
+               (void)pcap_snprintf(operand_buf, sizeof operand_buf, "[%d]", p->k);
+               operand = operand_buf;
                break;
 
        case BPF_LD|BPF_B|BPF_ABS:
                op = "ldb";
-               fmt = "[%d]";
+               (void)pcap_snprintf(operand_buf, sizeof operand_buf, "[%d]", p->k);
+               operand = operand_buf;
                break;
 
        case BPF_LD|BPF_W|BPF_LEN:
                op = "ld";
-               fmt = "#pktlen";
+               operand = "#pktlen";
                break;
 
        case BPF_LD|BPF_W|BPF_IND:
                op = "ld";
-               fmt = "[x + %d]";
+               (void)pcap_snprintf(operand_buf, sizeof operand_buf, "[x + %d]", p->k);
+               operand = operand_buf;
                break;
 
        case BPF_LD|BPF_H|BPF_IND:
                op = "ldh";
-               fmt = "[x + %d]";
+               (void)pcap_snprintf(operand_buf, sizeof operand_buf, "[x + %d]", p->k);
+               operand = operand_buf;
                break;
 
        case BPF_LD|BPF_B|BPF_IND:
                op = "ldb";
-               fmt = "[x + %d]";
+               (void)pcap_snprintf(operand_buf, sizeof operand_buf, "[x + %d]", p->k);
+               operand = operand_buf;
                break;
 
        case BPF_LD|BPF_IMM:
                op = "ld";
-               fmt = "#0x%x";
+               (void)pcap_snprintf(operand_buf, sizeof operand_buf, "#0x%x", p->k);
+               operand = operand_buf;
                break;
 
        case BPF_LDX|BPF_IMM:
                op = "ldx";
-               fmt = "#0x%x";
+               (void)pcap_snprintf(operand_buf, sizeof operand_buf, "#0x%x", p->k);
+               operand = operand_buf;
                break;
 
        case BPF_LDX|BPF_MSH|BPF_B:
                op = "ldxb";
-               fmt = "4*([%d]&0xf)";
+               (void)pcap_snprintf(operand_buf, sizeof operand_buf, "4*([%d]&0xf)", p->k);
+               operand = operand_buf;
                break;
 
        case BPF_LD|BPF_MEM:
                op = "ld";
-               fmt = "M[%d]";
+               (void)pcap_snprintf(operand_buf, sizeof operand_buf, "M[%d]", p->k);
+               operand = operand_buf;
                break;
 
        case BPF_LDX|BPF_MEM:
                op = "ldx";
-               fmt = "M[%d]";
+               (void)pcap_snprintf(operand_buf, sizeof operand_buf, "M[%d]", p->k);
+               operand = operand_buf;
                break;
 
        case BPF_ST:
                op = "st";
-               fmt = "M[%d]";
+               (void)pcap_snprintf(operand_buf, sizeof operand_buf, "M[%d]", p->k);
+               operand = operand_buf;
                break;
 
        case BPF_STX:
                op = "stx";
-               fmt = "M[%d]";
+               (void)pcap_snprintf(operand_buf, sizeof operand_buf, "M[%d]", p->k);
+               operand = operand_buf;
                break;
 
        case BPF_JMP|BPF_JA:
                op = "ja";
-               fmt = "%d";
-               v = n + 1 + p->k;
+               (void)pcap_snprintf(operand_buf, sizeof operand_buf, "%d", n + 1 + p->k);
+               operand = operand_buf;
                break;
 
        case BPF_JMP|BPF_JGT|BPF_K:
                op = "jgt";
-               fmt = "#0x%x";
+               (void)pcap_snprintf(operand_buf, sizeof operand_buf, "#0x%x", p->k);
+               operand = operand_buf;
                break;
 
        case BPF_JMP|BPF_JGE|BPF_K:
                op = "jge";
-               fmt = "#0x%x";
+               (void)pcap_snprintf(operand_buf, sizeof operand_buf, "#0x%x", p->k);
+               operand = operand_buf;
                break;
 
        case BPF_JMP|BPF_JEQ|BPF_K:
                op = "jeq";
-               fmt = "#0x%x";
+               (void)pcap_snprintf(operand_buf, sizeof operand_buf, "#0x%x", p->k);
+               operand = operand_buf;
                break;
 
        case BPF_JMP|BPF_JSET|BPF_K:
                op = "jset";
-               fmt = "#0x%x";
+               (void)pcap_snprintf(operand_buf, sizeof operand_buf, "#0x%x", p->k);
+               operand = operand_buf;
                break;
 
        case BPF_JMP|BPF_JGT|BPF_X:
                op = "jgt";
-               fmt = "x";
+               operand = "x";
                break;
 
        case BPF_JMP|BPF_JGE|BPF_X:
                op = "jge";
-               fmt = "x";
+               operand = "x";
                break;
 
        case BPF_JMP|BPF_JEQ|BPF_X:
                op = "jeq";
-               fmt = "x";
+               operand = "x";
                break;
 
        case BPF_JMP|BPF_JSET|BPF_X:
                op = "jset";
-               fmt = "x";
+               operand = "x";
                break;
 
        case BPF_ALU|BPF_ADD|BPF_X:
                op = "add";
-               fmt = "x";
+               operand = "x";
                break;
 
        case BPF_ALU|BPF_SUB|BPF_X:
                op = "sub";
-               fmt = "x";
+               operand = "x";
                break;
 
        case BPF_ALU|BPF_MUL|BPF_X:
                op = "mul";
-               fmt = "x";
+               operand = "x";
                break;
 
        case BPF_ALU|BPF_DIV|BPF_X:
                op = "div";
-               fmt = "x";
+               operand = "x";
                break;
 
        case BPF_ALU|BPF_MOD|BPF_X:
                op = "mod";
-               fmt = "x";
+               operand = "x";
                break;
 
        case BPF_ALU|BPF_AND|BPF_X:
                op = "and";
-               fmt = "x";
+               operand = "x";
                break;
 
        case BPF_ALU|BPF_OR|BPF_X:
                op = "or";
-               fmt = "x";
+               operand = "x";
                break;
 
        case BPF_ALU|BPF_XOR|BPF_X:
                op = "xor";
-               fmt = "x";
+               operand = "x";
                break;
 
        case BPF_ALU|BPF_LSH|BPF_X:
                op = "lsh";
-               fmt = "x";
+               operand = "x";
                break;
 
        case BPF_ALU|BPF_RSH|BPF_X:
                op = "rsh";
-               fmt = "x";
+               operand = "x";
                break;
 
        case BPF_ALU|BPF_ADD|BPF_K:
                op = "add";
-               fmt = "#%d";
+               (void)pcap_snprintf(operand_buf, sizeof operand_buf, "#%d", p->k);
+               operand = operand_buf;
                break;
 
        case BPF_ALU|BPF_SUB|BPF_K:
                op = "sub";
-               fmt = "#%d";
+               (void)pcap_snprintf(operand_buf, sizeof operand_buf, "#%d", p->k);
+               operand = operand_buf;
                break;
 
        case BPF_ALU|BPF_MUL|BPF_K:
                op = "mul";
-               fmt = "#%d";
+               (void)pcap_snprintf(operand_buf, sizeof operand_buf, "#%d", p->k);
+               operand = operand_buf;
                break;
 
        case BPF_ALU|BPF_DIV|BPF_K:
                op = "div";
-               fmt = "#%d";
+               (void)pcap_snprintf(operand_buf, sizeof operand_buf, "#%d", p->k);
+               operand = operand_buf;
                break;
 
        case BPF_ALU|BPF_MOD|BPF_K:
                op = "mod";
-               fmt = "#%d";
+               (void)pcap_snprintf(operand_buf, sizeof operand_buf, "#%d", p->k);
+               operand = operand_buf;
                break;
 
        case BPF_ALU|BPF_AND|BPF_K:
                op = "and";
-               fmt = "#0x%x";
+               (void)pcap_snprintf(operand_buf, sizeof operand_buf, "#0x%x", p->k);
+               operand = operand_buf;
                break;
 
        case BPF_ALU|BPF_OR|BPF_K:
                op = "or";
-               fmt = "#0x%x";
+               (void)pcap_snprintf(operand_buf, sizeof operand_buf, "#0x%x", p->k);
+               operand = operand_buf;
                break;
 
        case BPF_ALU|BPF_XOR|BPF_K:
                op = "xor";
-               fmt = "#0x%x";
+               (void)pcap_snprintf(operand_buf, sizeof operand_buf, "#0x%x", p->k);
+               operand = operand_buf;
                break;
 
        case BPF_ALU|BPF_LSH|BPF_K:
                op = "lsh";
-               fmt = "#%d";
+               (void)pcap_snprintf(operand_buf, sizeof operand_buf, "#%d", p->k);
+               operand = operand_buf;
                break;
 
        case BPF_ALU|BPF_RSH|BPF_K:
                op = "rsh";
-               fmt = "#%d";
+               (void)pcap_snprintf(operand_buf, sizeof operand_buf, "#%d", p->k);
+               operand = operand_buf;
                break;
 
        case BPF_ALU|BPF_NEG:
                op = "neg";
-               fmt = "";
+               operand = "";
                break;
 
        case BPF_MISC|BPF_TAX:
                op = "tax";
-               fmt = "";
+               operand = "";
                break;
 
        case BPF_MISC|BPF_TXA:
                op = "txa";
-               fmt = "";
+               operand = "";
                break;
        }
-       (void)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);
        }
index 0a30d99..946fec3 100755 (executable)
--- a/chmod_bpf
+++ b/chmod_bpf
@@ -1,7 +1,7 @@
 #! /bin/sh
 
 #
-# Unfortunately, Mac OS X's devfs is based on the old FreeBSD
+# Unfortunately, macOS's devfs is based on the old FreeBSD
 # one, not the current one, so there's no way to configure it
 # to create BPF devices with particular owners or groups.
 # This startup item will make it owned by the admin group,
diff --git a/cmake/Modules/FindDAG.cmake b/cmake/Modules/FindDAG.cmake
new file mode 100644 (file)
index 0000000..ef13528
--- /dev/null
@@ -0,0 +1,32 @@
+#
+# Try to find the Endace DAG library.
+#
+
+# Try to find the header
+find_path(DAG_INCLUDE_DIR dagapi.h)
+
+#
+# Try to find the libraries
+#
+# We assume that if we have libdag we have libdagconf, as they're
+# installed at the same time from the same package.
+#
+find_library(DAG_LIBRARY dag)
+find_library(DAGCONF_LIBRARY dagconf)
+
+include(FindPackageHandleStandardArgs)
+find_package_handle_standard_args(DAG
+  DEFAULT_MSG
+  DAG_INCLUDE_DIR
+  DAG_LIBRARY
+  DAGCONF_LIBRARY
+)
+
+mark_as_advanced(
+  DAG_INCLUDE_DIR
+  DAG_LIBRARY
+  DAGCONF_LIBRARY
+)
+
+set(DAG_INCLUDE_DIRS ${DAG_INCLUDE_DIR})
+set(DAG_LIBRARIES ${DAG_LIBRARY} ${DAGCONF_LIBRARY})
diff --git a/cmake/Modules/FindFseeko.cmake b/cmake/Modules/FindFseeko.cmake
new file mode 100644 (file)
index 0000000..ca53a5a
--- /dev/null
@@ -0,0 +1,85 @@
+# CMake support for fseeko
+#
+# Based on FindLFS.cmake by
+# Copyright (C) 2016 Julian Andres Klode <jak@debian.org>.
+#
+# Permission is hereby granted, free of charge, to any person
+# obtaining a copy of this software and associated documentation files
+# (the "Software"), to deal in the Software without restriction,
+# including without limitation the rights to use, copy, modify, merge,
+# publish, distribute, sublicense, and/or sell copies of the Software,
+# and to permit persons to whom the Software is furnished to do so,
+# subject to the following conditions:
+#
+# The above copyright notice and this permission notice shall be
+# included in all copies or substantial portions of the Software.
+#
+# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+# BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+# ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+# CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+# SOFTWARE.
+#
+# This defines the following variables
+#
+# FSEEKO_DEFINITIONS - List of definitions to pass to add_definitions()
+# FSEEKO_COMPILE_OPTIONS - List of definitions to pass to add_compile_options()
+# FSEEKO_LIBRARIES - List of libraries and linker flags
+# FSEEKO_FOUND - If there is Large files support
+#
+
+include(CheckCSourceCompiles)
+include(FindPackageHandleStandardArgs)
+include(CMakePushCheckState)
+
+# Check for the availability of fseeko()
+# The cases handled are:
+#
+#  * Native fseeko()
+#  * Preprocessor flag -D_LARGEFILE_SOURCE
+#
+function(_fseeko_check)
+    set(_fseeko_cppflags)
+    cmake_push_check_state()
+    set(CMAKE_REQUIRED_QUIET 1)
+    set(CMAKE_REQUIRED_DEFINITIONS ${LFS_DEFINITIONS})
+    message(STATUS "Looking for native fseeko support")
+    check_symbol_exists(fseeko stdio.h fseeko_native)
+    cmake_pop_check_state()
+    if (fseeko_native)
+        message(STATUS "Looking for native fseeko support - found")
+        set(FSEEKO_FOUND TRUE)
+    else()
+        message(STATUS "Looking for native fseeko support - not found")
+    endif()
+
+    if (NOT FSEEKO_FOUND)
+        # See if it's available with _LARGEFILE_SOURCE.
+        cmake_push_check_state()
+        set(CMAKE_REQUIRED_QUIET 1)
+        set(CMAKE_REQUIRED_DEFINITIONS ${LFS_DEFINITIONS} "-D_LARGEFILE_SOURCE")
+        check_symbol_exists(fseeko stdio.h fseeko_need_largefile_source)
+        cmake_pop_check_state()
+        if (fseeko_need_largefile_source)
+            message(STATUS "Looking for fseeko support with _LARGEFILE_SOURCE - found")
+            set(FSEEKO_FOUND TRUE)
+            set(_fseeko_cppflags "-D_LARGEFILE_SOURCE")
+        else()
+            message(STATUS "Looking for fseeko support with _LARGEFILE_SOURCE - not found")
+        endif()
+    endif()
+
+    set(FSEEKO_DEFINITIONS ${_fseeko_cppflags} CACHE STRING "Extra definitions for fseeko support")
+    set(FSEEKO_COMPILE_OPTIONS "" CACHE STRING "Extra compiler options for fseeko support")
+    set(FSEEKO_LIBRARIES "" CACHE STRING "Extra definitions for fseeko support")
+    set(FSEEKO_FOUND ${FSEEKO_FOUND} CACHE INTERNAL "Found fseeko")
+endfunction()
+
+if (NOT FSEEKO_FOUND)
+    _fseeko_check()
+endif()
+
+find_package_handle_standard_args(FSEEKO "Could not find fseeko. Set FSEEKO_DEFINITIONS, FSEEKO_COMPILE_OPTIONS, FSEEKO_LIBRARIES." FSEEKO_FOUND)
diff --git a/cmake/Modules/FindLFS.cmake b/cmake/Modules/FindLFS.cmake
new file mode 100644 (file)
index 0000000..be5f0d4
--- /dev/null
@@ -0,0 +1,153 @@
+# CMake support for large files
+#
+# Copyright (C) 2016 Julian Andres Klode <jak@debian.org>.
+#
+# Permission is hereby granted, free of charge, to any person
+# obtaining a copy of this software and associated documentation files
+# (the "Software"), to deal in the Software without restriction,
+# including without limitation the rights to use, copy, modify, merge,
+# publish, distribute, sublicense, and/or sell copies of the Software,
+# and to permit persons to whom the Software is furnished to do so,
+# subject to the following conditions:
+#
+# The above copyright notice and this permission notice shall be
+# included in all copies or substantial portions of the Software.
+#
+# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+# BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+# ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+# CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+# SOFTWARE.
+#
+# This defines the following variables
+#
+# LFS_DEFINITIONS - List of definitions to pass to add_definitions()
+# LFS_COMPILE_OPTIONS - List of definitions to pass to add_compile_options()
+# LFS_LIBRARIES - List of libraries and linker flags
+# LFS_FOUND - If there is Large files support
+#
+
+include(CheckCSourceCompiles)
+include(FindPackageHandleStandardArgs)
+include(CMakePushCheckState)
+
+# Test program to check for LFS. Requires that off_t has at least 8 byte large
+set(_lfs_test_source
+    "
+    #include <sys/types.h>
+    typedef char my_static_assert[sizeof(off_t) >= 8 ? 1 : -1];
+    int main(void) { return 0; }
+    "
+)
+
+# Check if the given options are needed
+#
+# This appends to the variables _lfs_cppflags, _lfs_cflags, and _lfs_ldflags,
+# it also sets LFS_FOUND to 1 if it works.
+function(_lfs_check_compiler_option var options definitions libraries)
+    cmake_push_check_state()
+    set(CMAKE_REQUIRED_QUIET 1)
+    set(CMAKE_REQUIRED_FLAGS ${CMAKE_REQUIRED_FLAGS} ${options})
+    set(CMAKE_REQUIRED_DEFINITIONS ${CMAKE_REQUIRED_DEFINITIONS} ${definitions})
+    set(CMAKE_REQUIRED_LIBRARIES ${CMAKE_REQUIRED_DEFINITIONS} ${libraries})
+
+    message(STATUS "Looking for LFS support using ${options} ${definitions} ${libraries}")
+    check_c_source_compiles("${_lfs_test_source}" ${var})
+    cmake_pop_check_state()
+
+    if(${var})
+        message(STATUS "Looking for LFS support using ${options} ${definitions} ${libraries} - found")
+        set(_lfs_cppflags ${_lfs_cppflags} ${definitions} PARENT_SCOPE)
+        set(_lfs_cflags ${_lfs_cflags} ${options} PARENT_SCOPE)
+        set(_lfs_ldflags ${_lfs_ldflags} ${libraries} PARENT_SCOPE)
+        set(LFS_FOUND TRUE PARENT_SCOPE)
+    else()
+        message(STATUS "Looking for LFS support using ${options} ${definitions} ${libraries} - not found")
+    endif()
+endfunction()
+
+# Check for the availability of LFS.
+# The cases handled are:
+#
+#  * Native LFS
+#  * Output of getconf LFS_CFLAGS; getconf LFS_LIBS; getconf LFS_LDFLAGS
+#  * Preprocessor flag -D_FILE_OFFSET_BITS=64
+#  * Preprocessor flag -D_LARGE_FILES
+#
+function(_lfs_check)
+    set(_lfs_cflags)
+    set(_lfs_cppflags)
+    set(_lfs_ldflags)
+    set(_lfs_libs)
+    cmake_push_check_state()
+    set(CMAKE_REQUIRED_QUIET 1)
+    message(STATUS "Looking for native LFS support")
+    check_c_source_compiles("${_lfs_test_source}" lfs_native)
+    cmake_pop_check_state()
+    if (lfs_native)
+        message(STATUS "Looking for native LFS support - found")
+        set(LFS_FOUND TRUE)
+    else()
+        message(STATUS "Looking for native LFS support - not found")
+    endif()
+
+    if (NOT LFS_FOUND)
+        # Check using getconf. If getconf fails, don't worry, the check in
+        # _lfs_check_compiler_option will fail as well.
+        execute_process(COMMAND getconf LFS_CFLAGS
+                        OUTPUT_VARIABLE _lfs_cflags_raw
+                        OUTPUT_STRIP_TRAILING_WHITESPACE
+                        ERROR_QUIET)
+        execute_process(COMMAND getconf LFS_LIBS
+                        OUTPUT_VARIABLE _lfs_libs_tmp
+                        OUTPUT_STRIP_TRAILING_WHITESPACE
+                        ERROR_QUIET)
+        execute_process(COMMAND getconf LFS_LDFLAGS
+                        OUTPUT_VARIABLE _lfs_ldflags_tmp
+                        OUTPUT_STRIP_TRAILING_WHITESPACE
+                        ERROR_QUIET)
+
+        separate_arguments(_lfs_cflags_raw)
+        separate_arguments(_lfs_ldflags_tmp)
+        separate_arguments(_lfs_libs_tmp)
+
+        # Move -D flags to the place they are supposed to be
+        foreach(flag ${_lfs_cflags_raw})
+            if (flag MATCHES "-D.*")
+                list(APPEND _lfs_cppflags_tmp ${flag})
+            else()
+                list(APPEND _lfs_cflags_tmp ${flag})
+            endif()
+        endforeach()
+
+        # Check if the flags we received (if any) produce working LFS support
+        _lfs_check_compiler_option(lfs_getconf_works
+                                   "${_lfs_cflags_tmp}"
+                                   "${_lfs_cppflags_tmp}"
+                                   "${_lfs_libs_tmp};${_lfs_ldflags_tmp}")
+    endif()
+
+    if(NOT LFS_FOUND)  # IRIX stuff
+        _lfs_check_compiler_option(lfs_need_n32 "-n32" "" "")
+    endif()
+    if(NOT LFS_FOUND)  # Linux and friends
+        _lfs_check_compiler_option(lfs_need_file_offset_bits "" "-D_FILE_OFFSET_BITS=64" "")
+    endif()
+    if(NOT LFS_FOUND)  # AIX
+        _lfs_check_compiler_option(lfs_need_large_files "" "-D_LARGE_FILES=1" "")
+    endif()
+
+    set(LFS_DEFINITIONS ${_lfs_cppflags} CACHE STRING "Extra definitions for large file support")
+    set(LFS_COMPILE_OPTIONS ${_lfs_cflags} CACHE STRING "Extra definitions for large file support")
+    set(LFS_LIBRARIES ${_lfs_libs} ${_lfs_ldflags} CACHE STRING "Extra definitions for large file support")
+    set(LFS_FOUND ${LFS_FOUND} CACHE INTERNAL "Found LFS")
+endfunction()
+
+if (NOT LFS_FOUND)
+    _lfs_check()
+endif()
+
+find_package_handle_standard_args(LFS "Could not find LFS. Set LFS_DEFINITIONS, LFS_COMPILE_OPTIONS, LFS_LIBRARIES." LFS_FOUND)
diff --git a/cmake/Modules/FindPacket.cmake b/cmake/Modules/FindPacket.cmake
new file mode 100644 (file)
index 0000000..f114875
--- /dev/null
@@ -0,0 +1,88 @@
+#
+# Copyright (C) 2017 Ali Abdulkadir <autostart.ini@gmail.com>.
+#
+# Permission is hereby granted, free of charge, to any person
+# obtaining a copy of this software and associated documentation files
+# (the "Software"), to deal in the Software without restriction,
+# including without limitation the rights to use, copy, modify, merge,
+# publish, distribute, sub-license, and/or sell copies of the Software,
+# and to permit persons to whom the Software is furnished to do so,
+# subject to the following conditions:
+#
+# The above copyright notice and this permission notice shall be
+# included in all copies or substantial portions of the Software.
+#
+# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+# BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+# ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+# CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+# SOFTWARE.
+#
+# FindPacket
+# ==========
+#
+# Find the Packet library and include files.
+#
+# This module defines the following variables:
+#
+# PACKET_INCLUDE_DIR     - absolute path to the directory containing Packet32.h.
+#
+# PACKET_LIBRARY         - relative or absolute path to the Packet library to
+#                          link with. An absolute path is will be used if the
+#                          Packet library is not located in the compiler's
+#                          default search path. See e.g. PACKET_DLL_DIR
+#                          variable below.
+
+# PACKET_FOUND           - TRUE if the Packet library *and* header are found.
+#
+# Hints and Backward Compatibility
+# ================================
+#
+# To tell this module where to look, a user may set the environment variable
+# PACKET_DLL_DIR to point cmake to the *root* of a directory with include and
+# lib subdirectories for packet.dll (e.g WpdPack/npcap-sdk).
+# Alternatively, PACKET_DLL_DIR may also be set from cmake command line or GUI
+# (e.g cmake -DPACKET_DLL_DIR=/path/to/packet [...])
+#
+
+# The 64-bit Packet.lib is located under /x64
+if(CMAKE_SIZEOF_VOID_P EQUAL 8)
+  #
+  # For the WinPcap and Npcap SDKs, the Lib subdirectory of the top-level
+  # directory contains 32-bit libraries; the 64-bit libraries are in the
+  # Lib/x64 directory.
+  #
+  # The only way to *FORCE* CMake to look in the Lib/x64 directory
+  # without searching in the Lib directory first appears to be to set
+  # CMAKE_LIBRARY_ARCHITECTURE to "x64".
+  #
+  set(CMAKE_LIBRARY_ARCHITECTURE "x64")
+endif()
+
+# Find the header
+find_path(PACKET_INCLUDE_DIR Packet32.h
+  HINTS "${PACKET_DLL_DIR}" ENV PACKET_DLL_DIR
+  PATH_SUFFIXES include Include
+)
+
+# Find the library
+find_library(PACKET_LIBRARY
+  NAMES Packet packet
+  HINTS "${PACKET_DLL_DIR}" ENV PACKET_DLL_DIR
+)
+
+# Set PACKET_FOUND to TRUE if PACKET_INCLUDE_DIR and PACKET_LIBRARY are TRUE.
+include(FindPackageHandleStandardArgs)
+find_package_handle_standard_args(PACKET
+  DEFAULT_MSG
+  PACKET_INCLUDE_DIR
+  PACKET_LIBRARY
+)
+
+mark_as_advanced(PACKET_INCLUDE_DIR PACKET_LIBRARY)
+
+set(PACKET_INCLUDE_DIRS ${PACKET_INCLUDE_DIR})
+set(PACKET_LIBRARIES ${PACKET_LIBRARY})
diff --git a/cmake/Modules/FindSNF.cmake b/cmake/Modules/FindSNF.cmake
new file mode 100644 (file)
index 0000000..76dcced
--- /dev/null
@@ -0,0 +1,24 @@
+#
+# Try to find the Myricom SNF library.
+#
+
+# Try to find the header
+find_path(SNF_INCLUDE_DIR snf.h /opt/snf)
+
+# Try to find the library
+find_library(SNF_LIBRARY snf /opt/snf)
+
+include(FindPackageHandleStandardArgs)
+find_package_handle_standard_args(SNF
+  DEFAULT_MSG
+  SNF_INCLUDE_DIR
+  SNF_LIBRARY
+)
+
+mark_as_advanced(
+  SNF_INCLUDE_DIR
+  SNF_LIBRARY
+)
+
+set(SNF_INCLUDE_DIRS ${SNF_INCLUDE_DIR})
+set(SNF_LIBRARIES ${SNF_LIBRARY})
diff --git a/cmake/Modules/FindTC.cmake b/cmake/Modules/FindTC.cmake
new file mode 100644 (file)
index 0000000..bb24c66
--- /dev/null
@@ -0,0 +1,24 @@
+#
+# Try to find the Riverbed TurboCap library.
+#
+
+# Try to find the header
+find_path(TC_INCLUDE_DIR TcApi.h)
+
+# Try to find the library
+find_library(TC_LIBRARY TcApi)
+
+include(FindPackageHandleStandardArgs)
+find_package_handle_standard_args(TC
+  DEFAULT_MSG
+  TC_INCLUDE_DIR
+  TC_LIBRARY
+)
+
+mark_as_advanced(
+  TC_INCLUDE_DIR
+  TC_LIBRARY
+)
+
+set(TC_INCLUDE_DIRS ${TC_INCLUDE_DIR})
+set(TC_LIBRARIES ${TC_LIBRARY})
diff --git a/cmake/have_siocglifconf.c b/cmake/have_siocglifconf.c
new file mode 100644 (file)
index 0000000..5a67abc
--- /dev/null
@@ -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/cmake_uninstall.cmake.in b/cmake_uninstall.cmake.in
new file mode 100644 (file)
index 0000000..2037e36
--- /dev/null
@@ -0,0 +1,21 @@
+if(NOT EXISTS "@CMAKE_CURRENT_BINARY_DIR@/install_manifest.txt")
+  message(FATAL_ERROR "Cannot find install manifest: @CMAKE_CURRENT_BINARY_DIR@/install_manifest.txt")
+endif(NOT EXISTS "@CMAKE_CURRENT_BINARY_DIR@/install_manifest.txt")
+
+file(READ "@CMAKE_CURRENT_BINARY_DIR@/install_manifest.txt" files)
+string(REGEX REPLACE "\n" ";" files "${files}")
+foreach(file ${files})
+  message(STATUS "Uninstalling $ENV{DESTDIR}${file}")
+  if(IS_SYMLINK "$ENV{DESTDIR}${file}" OR EXISTS "$ENV{DESTDIR}${file}")
+    exec_program(
+      "@CMAKE_COMMAND@" ARGS "-E remove \"$ENV{DESTDIR}${file}\""
+      OUTPUT_VARIABLE rm_out
+      RETURN_VALUE rm_retval
+      )
+    if(NOT "${rm_retval}" STREQUAL 0)
+      message(FATAL_ERROR "Problem when removing $ENV{DESTDIR}${file}")
+    endif(NOT "${rm_retval}" STREQUAL 0)
+  else(IS_SYMLINK "$ENV{DESTDIR}${file}" OR EXISTS "$ENV{DESTDIR}${file}")
+    message(STATUS "File $ENV{DESTDIR}${file} does not exist.")
+  endif(IS_SYMLINK "$ENV{DESTDIR}${file}" OR EXISTS "$ENV{DESTDIR}${file}")
+endforeach(file)
diff --git a/cmakeconfig.h.in b/cmakeconfig.h.in
new file mode 100644 (file)
index 0000000..1639925
--- /dev/null
@@ -0,0 +1,381 @@
+/* cmakeconfig.h.in */
+
+/* Define to 1 if arpa/inet.h declares `ether_hostton' */
+#cmakedefine ARPA_INET_H_DECLARES_ETHER_HOSTTON 1
+
+/* Enable optimizer debugging */
+#cmakedefine BDEBUG 1
+
+/* Define to 1 if remote packet capture is to be supported */
+#cmakedefine ENABLE_REMOTE 1
+
+/* define if we have the AIX getnetbyname_r() */
+#cmakedefine HAVE_AIX_GETNETBYNAME_R 1
+
+/* define if we have the AIX getprotobyname_r() */
+#cmakedefine HAVE_AIX_GETPROTOBYNAME_R 1
+
+/* Define to 1 if you have the `asprintf' function. */
+#cmakedefine HAVE_ASPRINTF 1
+
+/* define if you have the DAG API */
+#cmakedefine HAVE_DAG_API 1
+
+/* define if you have dag_get_erf_types() */
+#cmakedefine HAVE_DAG_GET_ERF_TYPES 1
+
+/* define if you have dag_get_stream_erf_types() */
+#cmakedefine HAVE_DAG_GET_STREAM_ERF_TYPES 1
+
+/* define if you have large streams capable DAG API */
+#cmakedefine HAVE_DAG_LARGE_STREAMS_API 1
+
+/* define if you have vdag_set_device_info() */
+#cmakedefine HAVE_DAG_VDAG 1
+
+/* Define to 1 if you have the declaration of `ether_hostton' */
+#cmakedefine HAVE_DECL_ETHER_HOSTTON 1
+
+/* Define to 1 if `dl_module_id_1' is a member of `dl_hp_ppa_info_t'. */
+#cmakedefine HAVE_DL_HP_PPA_INFO_T_DL_MODULE_ID_1 1
+
+/* Define to 1 if the system has the type `dl_passive_req_t'. */
+#cmakedefine HAVE_DL_PASSIVE_REQ_T 1
+
+/* Define to 1 if you have the `ether_hostton' function. */
+#cmakedefine HAVE_ETHER_HOSTTON 1
+
+/* Define to 1 if fseeko (and presumably ftello) exists and is declared. */
+#cmakedefine HAVE_FSEEKO 1
+
+/* Define to 1 if you have the `getspnam' function. */
+#cmakedefine HAVE_GETSPNAM 1
+
+/* Define to 1 if you have a GNU-style `strerror_r' function. */
+#cmakedefine HAVE_GNU_STRERROR_R 1
+
+/* on HP-UX 10.20 or later */
+#cmakedefine HAVE_HPUX10_20_OR_LATER 1
+
+/* on HP-UX 9.x */
+#cmakedefine HAVE_HPUX9 1
+
+/* Define to 1 if you have the <inttypes.h> header file. */
+#cmakedefine HAVE_INTTYPES_H 1
+
+/* if libdlpi exists */
+#cmakedefine HAVE_LIBDLPI 1
+
+/* if libnl exists */
+#cmakedefine HAVE_LIBNL 1
+
+/* if libnl exists and is version 2.x */
+#cmakedefine HAVE_LIBNL_2_x 1
+
+/* if libnl exists and is version 3.x */
+#cmakedefine HAVE_LIBNL_3_x 1
+
+/* libnl has NLE_FAILURE */
+#cmakedefine HAVE_LIBNL_NLE 1
+
+/* libnl has new-style socket api */
+#cmakedefine HAVE_LIBNL_SOCKETS 1
+
+/* Define to 1 if you have the <limits.h> header file. */
+#cmakedefine HAVE_LIMITS_H 1
+
+/* Define to 1 if you have the <linux/compiler.h> header file. */
+#cmakedefine HAVE_LINUX_COMPILER_H 1
+
+/* Define to 1 if you have the <linux/ethtool.h> header file. */
+#cmakedefine HAVE_LINUX_ETHTOOL_H 1
+
+/* define if we have the Linux getnetbyname_r() */
+#cmakedefine HAVE_LINUX_GETNETBYNAME_R 1
+
+/* define if we have the Linux getprotobyname_r() */
+#cmakedefine HAVE_LINUX_GETPROTOBYNAME_R 1
+
+/* Define to 1 if you have the <linux/if_bonding.h> header file. */
+#cmakedefine HAVE_LINUX_IF_BONDING_H 1
+
+/* Define to 1 if you have the <linux/net_tstamp.h> header file. */
+#cmakedefine HAVE_LINUX_NET_TSTAMP_H 1
+
+/* Define to 1 if you have the <linux/socket.h> header file. */
+#cmakedefine HAVE_LINUX_SOCKET_H 1
+
+/* Define to 1 if you have the <linux/sockios.h> header file. */
+#cmakedefine HAVE_LINUX_SOCKIOS_H 1
+
+/* Define to 1 if you have the <linux/usbdevice_fs.h> header file. */
+#cmakedefine HAVE_LINUX_USBDEVICE_FS_H 1
+
+/* Define to 1 if you have the <linux/wireless.h> header file. */
+#cmakedefine HAVE_LINUX_WIRELESS_H 1
+
+/* Define to 1 if you have the <memory.h> header file. */
+#cmakedefine HAVE_MEMORY_H 1
+
+/* Define to 1 if you have the <netpacket/packet.h> header file. */
+#cmakedefine HAVE_NETPACKET_PACKET_H 1
+
+/* Define to 1 if you have the <net/bpf.h> header file. */
+#cmakedefine HAVE_NET_BPF_H 1
+
+/* Define to 1 if you have the <net/enet.h> header file. */
+#cmakedefine HAVE_NET_ENET_H 1
+
+/* Define to 1 if you have the <net/if_media.h> header file. */
+#cmakedefine HAVE_NET_IF_MEDIA_H 1
+
+/* Define to 1 if you have the <net/nit.h> header file. */
+#cmakedefine HAVE_NET_NIT_H 1
+
+/* Define to 1 if you have the <net/pfilt.h> header file. */
+#cmakedefine HAVE_NET_PFILT_H 1
+
+/* Define to 1 if you have the <net/pfvar.h> header file. */
+#cmakedefine HAVE_NET_PFVAR_H 1
+
+/* Define to 1 if you have the <net/raw.h> header file. */
+#cmakedefine HAVE_NET_RAW_H 1
+
+/* if there's an os_proto.h for this platform, to use additional prototypes */
+#cmakedefine HAVE_OS_PROTO_H 1
+
+/* Define to 1 if Packet32 API (Npcap driver) is available */
+#cmakedefine HAVE_PACKET32 1
+
+/* Define to 1 if NPcap's version.h is available */
+#cmakedefine HAVE_VERSION_H 1
+
+/* Define to 1 if you have a POSIX-style `strerror_r' function. */
+#cmakedefine HAVE_POSIX_STRERROR_R 1
+
+/* define if net/pfvar.h defines PF_NAT through PF_NORDR */
+#cmakedefine HAVE_PF_NAT_THROUGH_PF_NORDR 1
+
+/* define if you have the Septel API */
+#cmakedefine HAVE_SEPTEL_API 1
+
+/* define if you have the Myricom SNF API */
+#cmakedefine HAVE_SNF_API 1
+
+/* Define to 1 if you have the `snprintf' function. */
+#cmakedefine HAVE_SNPRINTF 1
+
+/* Define to 1 if the system has the type `socklen_t'. */
+#cmakedefine HAVE_SOCKLEN_T 1
+
+/* On solaris */
+#cmakedefine HAVE_SOLARIS 1
+
+/* define if we have the Solaris/IRIX getnetbyname_r() */
+#cmakedefine HAVE_SOLARIS_IRIX_GETNETBYNAME_R 1
+
+/* define if we have the Solaris/IRIX getprotobyname_r() */
+#cmakedefine HAVE_SOLARIS_IRIX_GETPROTOBYNAME_R 1
+
+/* Define to 1 if you have the <stdint.h> header file. */
+#cmakedefine HAVE_STDINT_H 1
+
+/* Define to 1 if you have the <stdlib.h> header file. */
+#cmakedefine HAVE_STDLIB_H 1
+
+/* Define to 1 if you have the `strerror' function. */
+#cmakedefine HAVE_STRERROR 1
+
+/* Define to 1 if you have the `strerror_s' function. */
+#cmakedefine HAVE_STRERROR_S 1
+
+/* Define to 1 if you have the <strings.h> header file. */
+#cmakedefine HAVE_STRINGS_H 1
+
+/* Define to 1 if you have the <string.h> header file. */
+#cmakedefine HAVE_STRING_H 1
+
+/* Define to 1 if you have the `strlcat' function. */
+#cmakedefine HAVE_STRLCAT 1
+
+/* Define to 1 if you have the `strlcpy' function. */
+#cmakedefine HAVE_STRLCPY 1
+
+/* Define to 1 if you have the `strtok_r' function. */
+#cmakedefine HAVE_STRTOK_R 1
+
+/* Define to 1 if the system has the type `struct BPF_TIMEVAL'. */
+#cmakedefine HAVE_STRUCT_BPF_TIMEVAL 1
+
+/* Define to 1 if the system has the type `struct ether_addr'. */
+#cmakedefine HAVE_STRUCT_ETHER_ADDR 1
+
+/* Define to 1 if `msg_control' is a member of `struct msghdr'. */
+#cmakedefine HAVE_STRUCT_MSGHDR_MSG_CONTROL 1
+
+/* Define to 1 if `msg_flags' is a member of `struct msghdr'. */
+#cmakedefine HAVE_STRUCT_MSGHDR_MSG_FLAGS 1
+
+/* Define to 1 if `hci_channel' is a member of `struct sockaddr_hci'. */
+#cmakedefine HAVE_STRUCT_SOCKADDR_HCI_HCI_CHANNEL 1
+
+/* Define to 1 if `sa_len' is a member of `struct sockaddr'. */
+#cmakedefine HAVE_STRUCT_SOCKADDR_SA_LEN 1
+
+/* Define to 1 if the system has the type `struct sockaddr_storage'. */
+#cmakedefine HAVE_STRUCT_SOCKADDR_STORAGE 1
+
+/* Define to 1 if `tp_vlan_tci' is a member of `struct tpacket_auxdata'. */
+#cmakedefine HAVE_STRUCT_TPACKET_AUXDATA_TP_VLAN_TCI 1
+
+/* Define to 1 if the system has the type `struct tpacket_stats'. */
+#cmakedefine HAVE_STRUCT_TPACKET_STATS 1
+
+/* Define to 1 if `bRequestType' is a member of `struct
+   usbdevfs_ctrltransfer'. */
+#cmakedefine HAVE_STRUCT_USBDEVFS_CTRLTRANSFER_BREQUESTTYPE 1
+
+/* Define to 1 if you have the <sys/bufmod.h> header file. */
+#cmakedefine HAVE_SYS_BUFMOD_H 1
+
+/* Define to 1 if you have the <sys/dlpi_ext.h> header file. */
+#cmakedefine HAVE_SYS_DLPI_EXT_H 1
+
+/* Define to 1 if you have the <sys/dlpi.h> header file. */
+#cmakedefine HAVE_SYS_DLPI_H 1
+
+/* Define to 1 if you have the <sys/ioccom.h> header file. */
+#cmakedefine HAVE_SYS_IOCCOM_H 1
+
+/* Define to 1 if you have the <sys/net/nit.h> header file. */
+#cmakedefine HAVE_SYS_NET_NIT_H 1
+
+/* Define to 1 if you have the <sys/sockio.h> header file. */
+#cmakedefine HAVE_SYS_SOCKIO_H 1
+
+/* Define to 1 if you have the <sys/stat.h> header file. */
+#cmakedefine HAVE_SYS_STAT_H 1
+
+/* Define to 1 if you have the <sys/types.h> header file. */
+#cmakedefine HAVE_SYS_TYPES_H 1
+
+/* define if you have the TurboCap API */
+#cmakedefine HAVE_TC_API 1
+
+/* Define to 1 if you have the <unistd.h> header file. */
+#cmakedefine HAVE_UNISTD_H 1
+
+/* Define to 1 if you have the `vasprintf' function. */
+#cmakedefine HAVE_VASPRINTF 1
+
+/* Define to 1 if you have the `vsnprintf' function. */
+#cmakedefine HAVE_VSNPRINTF 1
+
+/* Define to 1 if you have the `vsyslog' function. */
+#undef HAVE_VSYSLOG
+
+/* Define to 1 if you have the `PacketIsLoopbackAdapter' function. */
+#cmakedefine HAVE_PACKET_IS_LOOPBACK_ADAPTER 1
+
+/* IPv6 */
+#cmakedefine INET6 1
+
+/* if unaligned access fails */
+#cmakedefine LBL_ALIGN 1
+
+/* path for device for USB sniffing */
+#cmakedefine LINUX_USB_MON_DEV "@LINUX_USB_MON_DEV@"
+
+/* Define to 1 if netinet/ether.h declares `ether_hostton' */
+#cmakedefine NETINET_ETHER_H_DECLARES_ETHER_HOSTTON 1
+
+/* Define to 1 if netinet/if_ether.h declares `ether_hostton' */
+#cmakedefine NETINET_IF_ETHER_H_DECLARES_ETHER_HOSTTON 1
+
+/* Define to 1 if net/ethernet.h declares `ether_hostton' */
+#cmakedefine NET_ETHERNET_H_DECLARES_ETHER_HOSTTON 1
+
+/* do not use protochain */
+#cmakedefine NO_PROTOCHAIN 1
+
+/* Define to the address where bug reports for this package should be sent. */
+#cmakedefine PACKAGE_BUGREPORT 1
+
+/* Define to the DLL-preferred version string of of this package. */
+#cmakedefine PACKAGE_VERSION_DLL @PACKAGE_VERSION_DLL@
+
+/* Define to the full name of this package. */
+#cmakedefine PACKAGE_NAME "@PACKAGE_NAME@"
+
+/* Define to the full name and version of this package. */
+#cmakedefine PACKAGE_STRING "@PACKAGE_STRING@"
+
+/* Define to the one symbol short name of this package. */
+#cmakedefine PACKAGE_TARNAME 1
+
+/* Define to the home page for this package. */
+#cmakedefine PACKAGE_URL 1
+
+/* Define to the version of this package. */
+#cmakedefine PACKAGE_VERSION "@PACKAGE_VERSION@"
+
+/* target host supports Bluetooth sniffing */
+#cmakedefine PCAP_SUPPORT_BT 1
+
+/* target host supports Bluetooth Monitor */
+#cmakedefine PCAP_SUPPORT_BT_MONITOR 1
+
+/* support D-Bus sniffing */
+#cmakedefine PCAP_SUPPORT_DBUS 1
+
+/* target host supports netfilter sniffing */
+#cmakedefine PCAP_SUPPORT_NETFILTER 1
+
+/* target host supports netmap */
+#cmakedefine PCAP_SUPPORT_NETMAP 1
+
+/* use packet ring capture support on Linux if available */
+#cmakedefine PCAP_SUPPORT_PACKET_RING 1
+
+/* target host supports RDMA sniffing */
+#cmakedefine PCAP_SUPPORT_RDMASNIFF 1
+
+/* target host supports USB sniffing */
+#cmakedefine PCAP_SUPPORT_USB 1
+
+/* include ACN support */
+#cmakedefine SITA 1
+
+/* Define to 1 if you have the ANSI C header files. */
+#cmakedefine STDC_HEADERS 1
+
+/* Define to 1 if strings.h declares `ffs' */
+#cmakedefine STRINGS_H_DECLARES_FFS 1
+
+/* Define to 1 if sys/ethernet.h declares `ether_hostton' */
+#cmakedefine SYS_ETHERNET_H_DECLARES_ETHER_HOSTTON 1
+
+/* Enable parser debugging */
+#cmakedefine YYDEBUG 1
+
+/* Enable large inode numbers on Mac OS X 10.5.  */
+#ifndef _DARWIN_USE_64_BIT_INODE
+# define _DARWIN_USE_64_BIT_INODE 1
+#endif
+
+/* Number of bits in a file offset, on hosts where this is settable. */
+#cmakedefine _FILE_OFFSET_BITS 1
+
+/* Define to 1 to make fseeko visible on some hosts (e.g. glibc 2.2). */
+#cmakedefine _LARGEFILE_SOURCE 1
+
+/* Define for large files, on AIX-style hosts. */
+#cmakedefine _LARGE_FILES 1
+
+/* define on AIX to get certain functions */
+#cmakedefine _SUN 1
+
+#if 0
+/* on sinix */
+#cmakedefine sinix 1
+#endif
index d622a44..2b79f6d 100755 (executable)
@@ -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-2018 Free Software Foundation, Inc.
 
-timestamp='2012-02-10'
+timestamp='2018-07-06'
 
 # 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
@@ -17,24 +15,22 @@ timestamp='2012-02-10'
 # 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/>.
+# along with this program; if not, see <https://www.gnu.org/licenses/>.
 #
 # 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
+# https://git.savannah.gnu.org/gitweb/?p=config.git;a=blob_plain;f=config.guess
+#
+# Please send patches to <config-patches@gnu.org>.
+
 
 me=`echo "$0" | sed -e 's,.*/,,'`
 
@@ -43,7 +39,7 @@ Usage: $0 [OPTION]
 
 Output the configuration name of the system \`$me' is run on.
 
-Operation modes:
+Options:
   -h, --help         print this help, then exit
   -t, --time-stamp   print date of last modification, then exit
   -v, --version      print version number, then exit
@@ -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-2018 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."
@@ -107,15 +101,15 @@ trap "exitcode=\$?; (rm -f \$tmpfiles 2>/dev/null; rmdir \$tmp 2>/dev/null) && e
 trap "rm -f \$tmpfiles 2>/dev/null; rmdir \$tmp 2>/dev/null; exit 1" 1 2 13 15 ;
 : ${TMPDIR=/tmp} ;
  { tmp=`(umask 077 && mktemp -d "$TMPDIR/cgXXXXXX") 2>/dev/null` && test -n "$tmp" && test -d "$tmp" ; } ||
- { test -n "$RANDOM" && tmp=$TMPDIR/cg$$-$RANDOM && (umask 077 && mkdir $tmp) ; } ||
- { tmp=$TMPDIR/cg-$$ && (umask 077 && mkdir $tmp) && echo "Warning: creating insecure temp directory" >&2 ; } ||
+ { test -n "$RANDOM" && tmp=$TMPDIR/cg$$-$RANDOM && (umask 077 && mkdir $tmp 2>/dev/null) ; } ||
+ { tmp=$TMPDIR/cg-$$ && (umask 077 && mkdir $tmp 2>/dev/null) && echo "Warning: creating insecure temp directory" >&2 ; } ||
  { echo "$me: cannot create a temporary directory in $TMPDIR" >&2 ; exit 1 ; } ;
 dummy=$tmp/dummy ;
 tmpfiles="$dummy.c $dummy.o $dummy.rel $dummy" ;
-case $CC_FOR_BUILD,$HOST_CC,$CC in
- ,,)    echo "int x;" > $dummy.c ;
+case ${CC_FOR_BUILD-},${HOST_CC-},${CC-} in
+ ,,)    echo "int x;" > "$dummy.c" ;
        for c in cc gcc c89 c99 ; do
-         if ($c -c -o $dummy.o $dummy.c) >/dev/null 2>&1 ; then
+         if ($c -c -o "$dummy.o" "$dummy.c") >/dev/null 2>&1 ; then
             CC_FOR_BUILD="$c"; break ;
          fi ;
        done ;
@@ -138,9 +132,37 @@ 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'`"
+
+       # If ldd exists, use it to detect musl libc.
+       if command -v ldd >/dev/null && \
+               ldd --version 2>&1 | grep -q ^musl
+       then
+           LIBC=musl
+       fi
+       ;;
+esac
+
 # Note: order is significant - the case branches are not exclusive.
 
-case "${UNAME_MACHINE}:${UNAME_SYSTEM}:${UNAME_RELEASE}:${UNAME_VERSION}" in
+case "$UNAME_MACHINE:$UNAME_SYSTEM:$UNAME_RELEASE:$UNAME_VERSION" in
     *:NetBSD:*:*)
        # NetBSD (nbsd) targets should (where applicable) match one or
        # more of the tuples: *-*-netbsdelf*, *-*-netbsdaout*,
@@ -153,21 +175,31 @@ 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)`
-       case "${UNAME_MACHINE_ARCH}" in
+       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 ;;
-           *) machine=${UNAME_MACHINE_ARCH}-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
+       # to ELF recently (or will in the future) and ABI.
+       case "$UNAME_MACHINE_ARCH" in
+           earm*)
+               os=netbsdelf
+               ;;
            arm*|i386|m68k|ns32k|sh3*|sparc|vax)
-               eval $set_cc_for_build
+               eval "$set_cc_for_build"
                if echo __ELF__ | $CC_FOR_BUILD -E - 2>/dev/null \
                        | grep -q __ELF__
                then
@@ -182,40 +214,67 @@ 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
        # kernel version information, so it can be replaced with a
        # suitable tag, in the style of linux-gnu.
-       case "${UNAME_VERSION}" in
+       case "$UNAME_VERSION" in
            Debian*)
                release='-gnu'
                ;;
            *)
-               release=`echo ${UNAME_RELEASE}|sed -e 's/[-_].*/\./'`
+               release=`echo "$UNAME_RELEASE" | sed -e 's/[-_].*//' | cut -d. -f1,2`
                ;;
        esac
        # 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.//'`
-       echo ${UNAME_MACHINE_ARCH}-unknown-openbsd${UNAME_RELEASE}
+       echo "$UNAME_MACHINE_ARCH"-unknown-openbsd"$UNAME_RELEASE"
+       exit ;;
+    *:LibertyBSD:*:*)
+       UNAME_MACHINE_ARCH=`arch | sed 's/^.*BSD\.//'`
+       echo "$UNAME_MACHINE_ARCH"-unknown-libertybsd"$UNAME_RELEASE"
+       exit ;;
+    *:MidnightBSD:*:*)
+       echo "$UNAME_MACHINE"-unknown-midnightbsd"$UNAME_RELEASE"
        exit ;;
     *:ekkoBSD:*:*)
-       echo ${UNAME_MACHINE}-unknown-ekkobsd${UNAME_RELEASE}
+       echo "$UNAME_MACHINE"-unknown-ekkobsd"$UNAME_RELEASE"
        exit ;;
     *:SolidBSD:*:*)
-       echo ${UNAME_MACHINE}-unknown-solidbsd${UNAME_RELEASE}
+       echo "$UNAME_MACHINE"-unknown-solidbsd"$UNAME_RELEASE"
        exit ;;
     macppc:MirBSD:*:*)
-       echo powerpc-unknown-mirbsd${UNAME_RELEASE}
+       echo powerpc-unknown-mirbsd"$UNAME_RELEASE"
        exit ;;
     *:MirBSD:*:*)
-       echo ${UNAME_MACHINE}-unknown-mirbsd${UNAME_RELEASE}
+       echo "$UNAME_MACHINE"-unknown-mirbsd"$UNAME_RELEASE"
        exit ;;
+    *:Sortix:*:*)
+       echo "$UNAME_MACHINE"-unknown-sortix
+       exit ;;
+    *:Redox:*:*)
+       echo "$UNAME_MACHINE"-unknown-redox
+       exit ;;
+    mips:OSF1:*.*)
+        echo mips-dec-osf1
+        exit ;;
     alpha:OSF1:*:*)
        case $UNAME_RELEASE in
        *4.0)
@@ -232,63 +291,54 @@ case "${UNAME_MACHINE}:${UNAME_SYSTEM}:${UNAME_RELEASE}:${UNAME_VERSION}" in
        ALPHA_CPU_TYPE=`/usr/sbin/psrinfo -v | sed -n -e 's/^  The alpha \(.*\) processor.*$/\1/p' | head -n 1`
        case "$ALPHA_CPU_TYPE" in
            "EV4 (21064)")
-               UNAME_MACHINE="alpha" ;;
+               UNAME_MACHINE=alpha ;;
            "EV4.5 (21064)")
-               UNAME_MACHINE="alpha" ;;
+               UNAME_MACHINE=alpha ;;
            "LCA4 (21066/21068)")
-               UNAME_MACHINE="alpha" ;;
+               UNAME_MACHINE=alpha ;;
            "EV5 (21164)")
-               UNAME_MACHINE="alphaev5" ;;
+               UNAME_MACHINE=alphaev5 ;;
            "EV5.6 (21164A)")
-               UNAME_MACHINE="alphaev56" ;;
+               UNAME_MACHINE=alphaev56 ;;
            "EV5.6 (21164PC)")
-               UNAME_MACHINE="alphapca56" ;;
+               UNAME_MACHINE=alphapca56 ;;
            "EV5.7 (21164PC)")
-               UNAME_MACHINE="alphapca57" ;;
+               UNAME_MACHINE=alphapca57 ;;
            "EV6 (21264)")
-               UNAME_MACHINE="alphaev6" ;;
+               UNAME_MACHINE=alphaev6 ;;
            "EV6.7 (21264A)")
-               UNAME_MACHINE="alphaev67" ;;
+               UNAME_MACHINE=alphaev67 ;;
            "EV6.8CB (21264C)")
-               UNAME_MACHINE="alphaev68" ;;
+               UNAME_MACHINE=alphaev68 ;;
            "EV6.8AL (21264B)")
-               UNAME_MACHINE="alphaev68" ;;
+               UNAME_MACHINE=alphaev68 ;;
            "EV6.8CX (21264D)")
-               UNAME_MACHINE="alphaev68" ;;
+               UNAME_MACHINE=alphaev68 ;;
            "EV6.9A (21264/EV69A)")
-               UNAME_MACHINE="alphaev69" ;;
+               UNAME_MACHINE=alphaev69 ;;
            "EV7 (21364)")
-               UNAME_MACHINE="alphaev7" ;;
+               UNAME_MACHINE=alphaev7 ;;
            "EV7.9 (21364A)")
-               UNAME_MACHINE="alphaev79" ;;
+               UNAME_MACHINE=alphaev79 ;;
        esac
        # A Pn.n version is a patched version.
        # A Vn.n version is a released version.
        # A Tn.n version is a released field test version.
        # A Xn.n version is an unreleased experimental baselevel.
        # 1.2 uses "1.2" for uname -r.
-       echo ${UNAME_MACHINE}-dec-osf`echo ${UNAME_RELEASE} | sed -e 's/^[PVTX]//' | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz'`
+       echo "$UNAME_MACHINE"-dec-osf"`echo "$UNAME_RELEASE" | sed -e 's/^[PVTX]//' | tr ABCDEFGHIJKLMNOPQRSTUVWXYZ abcdefghijklmnopqrstuvwxyz`"
        # Reset EXIT trap before exiting to avoid spurious non-zero exit code.
        exitcode=$?
        trap '' 0
        exit $exitcode ;;
-    Alpha\ *:Windows_NT*:*)
-       # How do we know it's Interix rather than the generic POSIX subsystem?
-       # Should we change UNAME_MACHINE based on the output of uname instead
-       # of the specific Alpha model?
-       echo alpha-pc-interix
-       exit ;;
-    21064:Windows_NT:50:3)
-       echo alpha-dec-winnt3.5
-       exit ;;
     Amiga*:UNIX_System_V:4.0:*)
        echo m68k-unknown-sysv4
        exit ;;
     *:[Aa]miga[Oo][Ss]:*:*)
-       echo ${UNAME_MACHINE}-unknown-amigaos
+       echo "$UNAME_MACHINE"-unknown-amigaos
        exit ;;
     *:[Mm]orph[Oo][Ss]:*:*)
-       echo ${UNAME_MACHINE}-unknown-morphos
+       echo "$UNAME_MACHINE"-unknown-morphos
        exit ;;
     *:OS/390:*:*)
        echo i370-ibm-openedition
@@ -300,9 +350,9 @@ case "${UNAME_MACHINE}:${UNAME_SYSTEM}:${UNAME_RELEASE}:${UNAME_VERSION}" in
        echo powerpc-ibm-os400
        exit ;;
     arm:RISC*:1.[012]*:*|arm:riscix:1.[012]*:*)
-       echo arm-acorn-riscix${UNAME_RELEASE}
+       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:*:*)
@@ -327,38 +377,38 @@ case "${UNAME_MACHINE}:${UNAME_SYSTEM}:${UNAME_RELEASE}:${UNAME_VERSION}" in
            sparc) echo sparc-icl-nx7; exit ;;
        esac ;;
     s390x:SunOS:*:*)
-       echo ${UNAME_MACHINE}-ibm-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'`
+       echo "$UNAME_MACHINE"-ibm-solaris2"`echo "$UNAME_RELEASE" | sed -e 's/[^.]*//'`"
        exit ;;
     sun4H:SunOS:5.*:*)
-       echo sparc-hal-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'`
+       echo sparc-hal-solaris2"`echo "$UNAME_RELEASE"|sed -e 's/[^.]*//'`"
        exit ;;
     sun4*:SunOS:5.*:* | tadpole*:SunOS:5.*:*)
-       echo sparc-sun-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'`
+       echo sparc-sun-solaris2"`echo "$UNAME_RELEASE" | sed -e 's/[^.]*//'`"
        exit ;;
     i86pc:AuroraUX:5.*:* | i86xen:AuroraUX:5.*:*)
-       echo i386-pc-auroraux${UNAME_RELEASE}
+       echo i386-pc-auroraux"$UNAME_RELEASE"
        exit ;;
     i86pc:SunOS:5.*:* | i86xen:SunOS:5.*:*)
-       eval $set_cc_for_build
-       SUN_ARCH="i386"
+       eval "$set_cc_for_build"
+       SUN_ARCH=i386
        # If there is a compiler, see if it is configured for 64-bit objects.
        # Note that the Sun cc does not turn __LP64__ into 1 like gcc does.
        # This test works for both compilers.
-       if [ "$CC_FOR_BUILD" != 'no_compiler_found' ]; then
+       if [ "$CC_FOR_BUILD" != no_compiler_found ]; then
            if (echo '#ifdef __amd64'; echo IS_64BIT_ARCH; echo '#endif') | \
-               (CCOPTS= $CC_FOR_BUILD -E - 2>/dev/null) | \
+               (CCOPTS="" $CC_FOR_BUILD -E - 2>/dev/null) | \
                grep IS_64BIT_ARCH >/dev/null
            then
-               SUN_ARCH="x86_64"
+               SUN_ARCH=x86_64
            fi
        fi
-       echo ${SUN_ARCH}-pc-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'`
+       echo "$SUN_ARCH"-pc-solaris2"`echo "$UNAME_RELEASE"|sed -e 's/[^.]*//'`"
        exit ;;
     sun4*:SunOS:6*:*)
        # According to config.sub, this is the proper way to canonicalize
        # SunOS6.  Hard to guess exactly what SunOS6 will be like, but
        # it's likely to be more like Solaris than SunOS4.
-       echo sparc-sun-solaris3`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'`
+       echo sparc-sun-solaris3"`echo "$UNAME_RELEASE"|sed -e 's/[^.]*//'`"
        exit ;;
     sun4*:SunOS:*:*)
        case "`/usr/bin/arch -k`" in
@@ -367,25 +417,25 @@ case "${UNAME_MACHINE}:${UNAME_SYSTEM}:${UNAME_RELEASE}:${UNAME_VERSION}" in
                ;;
        esac
        # Japanese Language versions have a version number like `4.1.3-JL'.
-       echo sparc-sun-sunos`echo ${UNAME_RELEASE}|sed -e 's/-/_/'`
+       echo sparc-sun-sunos"`echo "$UNAME_RELEASE"|sed -e 's/-/_/'`"
        exit ;;
     sun3*:SunOS:*:*)
-       echo m68k-sun-sunos${UNAME_RELEASE}
+       echo m68k-sun-sunos"$UNAME_RELEASE"
        exit ;;
     sun*:*:4.2BSD:*)
        UNAME_RELEASE=`(sed 1q /etc/motd | awk '{print substr($5,1,3)}') 2>/dev/null`
-       test "x${UNAME_RELEASE}" = "x" && UNAME_RELEASE=3
+       test "x$UNAME_RELEASE" = x && UNAME_RELEASE=3
        case "`/bin/arch`" in
            sun3)
-               echo m68k-sun-sunos${UNAME_RELEASE}
+               echo m68k-sun-sunos"$UNAME_RELEASE"
                ;;
            sun4)
-               echo sparc-sun-sunos${UNAME_RELEASE}
+               echo sparc-sun-sunos"$UNAME_RELEASE"
                ;;
        esac
        exit ;;
     aushp:SunOS:*:*)
-       echo sparc-auspex-sunos${UNAME_RELEASE}
+       echo sparc-auspex-sunos"$UNAME_RELEASE"
        exit ;;
     # The situation for MiNT is a little confusing.  The machine name
     # can be virtually everything (everything which is not
@@ -396,44 +446,44 @@ case "${UNAME_MACHINE}:${UNAME_SYSTEM}:${UNAME_RELEASE}:${UNAME_VERSION}" in
     # MiNT.  But MiNT is downward compatible to TOS, so this should
     # be no problem.
     atarist[e]:*MiNT:*:* | atarist[e]:*mint:*:* | atarist[e]:*TOS:*:*)
-       echo m68k-atari-mint${UNAME_RELEASE}
+       echo m68k-atari-mint"$UNAME_RELEASE"
        exit ;;
     atari*:*MiNT:*:* | atari*:*mint:*:* | atarist[e]:*TOS:*:*)
-       echo m68k-atari-mint${UNAME_RELEASE}
+       echo m68k-atari-mint"$UNAME_RELEASE"
        exit ;;
     *falcon*:*MiNT:*:* | *falcon*:*mint:*:* | *falcon*:*TOS:*:*)
-       echo m68k-atari-mint${UNAME_RELEASE}
+       echo m68k-atari-mint"$UNAME_RELEASE"
        exit ;;
     milan*:*MiNT:*:* | milan*:*mint:*:* | *milan*:*TOS:*:*)
-       echo m68k-milan-mint${UNAME_RELEASE}
+       echo m68k-milan-mint"$UNAME_RELEASE"
        exit ;;
     hades*:*MiNT:*:* | hades*:*mint:*:* | *hades*:*TOS:*:*)
-       echo m68k-hades-mint${UNAME_RELEASE}
+       echo m68k-hades-mint"$UNAME_RELEASE"
        exit ;;
     *:*MiNT:*:* | *:*mint:*:* | *:*TOS:*:*)
-       echo m68k-unknown-mint${UNAME_RELEASE}
+       echo m68k-unknown-mint"$UNAME_RELEASE"
        exit ;;
     m68k:machten:*:*)
-       echo m68k-apple-machten${UNAME_RELEASE}
+       echo m68k-apple-machten"$UNAME_RELEASE"
        exit ;;
     powerpc:machten:*:*)
-       echo powerpc-apple-machten${UNAME_RELEASE}
+       echo powerpc-apple-machten"$UNAME_RELEASE"
        exit ;;
     RISC*:Mach:*:*)
        echo mips-dec-mach_bsd4.3
        exit ;;
     RISC*:ULTRIX:*:*)
-       echo mips-dec-ultrix${UNAME_RELEASE}
+       echo mips-dec-ultrix"$UNAME_RELEASE"
        exit ;;
     VAX*:ULTRIX*:*:*)
-       echo vax-dec-ultrix${UNAME_RELEASE}
+       echo vax-dec-ultrix"$UNAME_RELEASE"
        exit ;;
     2020:CLIX:*:* | 2430:CLIX:*:*)
-       echo clipper-intergraph-clix${UNAME_RELEASE}
+       echo clipper-intergraph-clix"$UNAME_RELEASE"
        exit ;;
     mips:*:*:UMIPS | mips:*:*:RISCos)
-       eval $set_cc_for_build
-       sed 's/^        //' << EOF >$dummy.c
+       eval "$set_cc_for_build"
+       sed 's/^        //' << EOF > "$dummy.c"
 #ifdef __cplusplus
 #include <stdio.h>  /* for printf() prototype */
        int main (int argc, char *argv[]) {
@@ -442,23 +492,23 @@ case "${UNAME_MACHINE}:${UNAME_SYSTEM}:${UNAME_RELEASE}:${UNAME_VERSION}" in
 #endif
        #if defined (host_mips) && defined (MIPSEB)
        #if defined (SYSTYPE_SYSV)
-         printf ("mips-mips-riscos%ssysv\n", argv[1]); exit (0);
+         printf ("mips-mips-riscos%ssysv\\n", argv[1]); exit (0);
        #endif
        #if defined (SYSTYPE_SVR4)
-         printf ("mips-mips-riscos%ssvr4\n", argv[1]); exit (0);
+         printf ("mips-mips-riscos%ssvr4\\n", argv[1]); exit (0);
        #endif
        #if defined (SYSTYPE_BSD43) || defined(SYSTYPE_BSD)
-         printf ("mips-mips-riscos%sbsd\n", argv[1]); exit (0);
+         printf ("mips-mips-riscos%sbsd\\n", argv[1]); exit (0);
        #endif
        #endif
          exit (-1);
        }
 EOF
-       $CC_FOR_BUILD -o $dummy $dummy.c &&
-         dummyarg=`echo "${UNAME_RELEASE}" | sed -n 's/\([0-9]*\).*/\1/p'` &&
-         SYSTEM_NAME=`$dummy $dummyarg` &&
+       $CC_FOR_BUILD -o "$dummy" "$dummy.c" &&
+         dummyarg=`echo "$UNAME_RELEASE" | sed -n 's/\([0-9]*\).*/\1/p'` &&
+         SYSTEM_NAME=`"$dummy" "$dummyarg"` &&
            { echo "$SYSTEM_NAME"; exit; }
-       echo mips-mips-riscos${UNAME_RELEASE}
+       echo mips-mips-riscos"$UNAME_RELEASE"
        exit ;;
     Motorola:PowerMAX_OS:*:*)
        echo powerpc-motorola-powermax
@@ -484,17 +534,17 @@ EOF
     AViiON:dgux:*:*)
        # DG/UX returns AViiON for all architectures
        UNAME_PROCESSOR=`/usr/bin/uname -p`
-       if [ $UNAME_PROCESSOR = mc88100 ] || [ $UNAME_PROCESSOR = mc88110 ]
+       if [ "$UNAME_PROCESSOR" = mc88100 ] || [ "$UNAME_PROCESSOR" = mc88110 ]
        then
-           if [ ${TARGET_BINARY_INTERFACE}x = m88kdguxelfx ] || \
-              [ ${TARGET_BINARY_INTERFACE}x = x ]
+           if [ "$TARGET_BINARY_INTERFACE"x = m88kdguxelfx ] || \
+              [ "$TARGET_BINARY_INTERFACE"x = x ]
            then
-               echo m88k-dg-dgux${UNAME_RELEASE}
+               echo m88k-dg-dgux"$UNAME_RELEASE"
            else
-               echo m88k-dg-dguxbcs${UNAME_RELEASE}
+               echo m88k-dg-dguxbcs"$UNAME_RELEASE"
            fi
        else
-           echo i586-dg-dgux${UNAME_RELEASE}
+           echo i586-dg-dgux"$UNAME_RELEASE"
        fi
        exit ;;
     M88*:DolphinOS:*:*)        # DolphinOS (SVR3)
@@ -511,7 +561,7 @@ EOF
        echo m68k-tektronix-bsd
        exit ;;
     *:IRIX*:*:*)
-       echo mips-sgi-irix`echo ${UNAME_RELEASE}|sed -e 's/-/_/g'`
+       echo mips-sgi-irix"`echo "$UNAME_RELEASE"|sed -e 's/-/_/g'`"
        exit ;;
     ????????:AIX?:[12].1:2)   # AIX 2.2.1 or AIX 2.1.1 is RT/PC AIX.
        echo romp-ibm-aix     # uname -m gives an 8 hex-code CPU id
@@ -523,14 +573,14 @@ EOF
        if [ -x /usr/bin/oslevel ] ; then
                IBM_REV=`/usr/bin/oslevel`
        else
-               IBM_REV=${UNAME_VERSION}.${UNAME_RELEASE}
+               IBM_REV="$UNAME_VERSION.$UNAME_RELEASE"
        fi
-       echo ${UNAME_MACHINE}-ibm-aix${IBM_REV}
+       echo "$UNAME_MACHINE"-ibm-aix"$IBM_REV"
        exit ;;
     *:AIX:2:3)
        if grep bos325 /usr/include/stdio.h >/dev/null 2>&1; then
-               eval $set_cc_for_build
-               sed 's/^                //' << EOF >$dummy.c
+               eval "$set_cc_for_build"
+               sed 's/^                //' << EOF > "$dummy.c"
                #include <sys/systemcfg.h>
 
                main()
@@ -541,7 +591,7 @@ EOF
                        exit(0);
                        }
 EOF
-               if $CC_FOR_BUILD -o $dummy $dummy.c && SYSTEM_NAME=`$dummy`
+               if $CC_FOR_BUILD -o "$dummy" "$dummy.c" && SYSTEM_NAME=`"$dummy"`
                then
                        echo "$SYSTEM_NAME"
                else
@@ -555,26 +605,27 @@ EOF
        exit ;;
     *:AIX:*:[4567])
        IBM_CPU_ID=`/usr/sbin/lsdev -C -c processor -S available | sed 1q | awk '{ print $1 }'`
-       if /usr/sbin/lsattr -El ${IBM_CPU_ID} | grep ' POWER' >/dev/null 2>&1; then
+       if /usr/sbin/lsattr -El "$IBM_CPU_ID" | grep ' POWER' >/dev/null 2>&1; then
                IBM_ARCH=rs6000
        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}
+               IBM_REV="$UNAME_VERSION.$UNAME_RELEASE"
        fi
-       echo ${IBM_ARCH}-ibm-aix${IBM_REV}
+       echo "$IBM_ARCH"-ibm-aix"$IBM_REV"
        exit ;;
     *:AIX:*:*)
        echo rs6000-ibm-aix
        exit ;;
-    ibmrt:4.4BSD:*|romp-ibm:BSD:*)
+    ibmrt:4.4BSD:*|romp-ibm:4.4BSD:*)
        echo romp-ibm-bsd4.4
        exit ;;
     ibmrt:*BSD:*|romp-ibm:BSD:*)            # covers RT/PC BSD and
-       echo romp-ibm-bsd${UNAME_RELEASE}   # 4.3 with uname added to
+       echo romp-ibm-bsd"$UNAME_RELEASE"   # 4.3 with uname added to
        exit ;;                             # report: romp-ibm BSD 4.3
     *:BOSX:*:*)
        echo rs6000-bull-bosx
@@ -589,28 +640,28 @@ EOF
        echo m68k-hp-bsd4.4
        exit ;;
     9000/[34678]??:HP-UX:*:*)
-       HPUX_REV=`echo ${UNAME_RELEASE}|sed -e 's/[^.]*.[0B]*//'`
-       case "${UNAME_MACHINE}" in
-           9000/31? )            HP_ARCH=m68000 ;;
-           9000/[34]?? )         HP_ARCH=m68k ;;
+       HPUX_REV=`echo "$UNAME_RELEASE"|sed -e 's/[^.]*.[0B]*//'`
+       case "$UNAME_MACHINE" in
+           9000/31?)            HP_ARCH=m68000 ;;
+           9000/[34]??)         HP_ARCH=m68k ;;
            9000/[678][0-9][0-9])
                if [ -x /usr/bin/getconf ]; then
                    sc_cpu_version=`/usr/bin/getconf SC_CPU_VERSION 2>/dev/null`
                    sc_kernel_bits=`/usr/bin/getconf SC_KERNEL_BITS 2>/dev/null`
-                   case "${sc_cpu_version}" in
-                     523) HP_ARCH="hppa1.0" ;; # CPU_PA_RISC1_0
-                     528) HP_ARCH="hppa1.1" ;; # CPU_PA_RISC1_1
+                   case "$sc_cpu_version" in
+                     523) HP_ARCH=hppa1.0 ;; # CPU_PA_RISC1_0
+                     528) HP_ARCH=hppa1.1 ;; # CPU_PA_RISC1_1
                      532)                      # CPU_PA_RISC2_0
-                       case "${sc_kernel_bits}" in
-                         32) HP_ARCH="hppa2.0n" ;;
-                         64) HP_ARCH="hppa2.0w" ;;
-                         '') HP_ARCH="hppa2.0" ;;   # HP-UX 10.20
+                       case "$sc_kernel_bits" in
+                         32) HP_ARCH=hppa2.0n ;;
+                         64) HP_ARCH=hppa2.0w ;;
+                         '') HP_ARCH=hppa2.0 ;;   # HP-UX 10.20
                        esac ;;
                    esac
                fi
-               if [ "${HP_ARCH}" = "" ]; then
-                   eval $set_cc_for_build
-                   sed 's/^            //' << EOF >$dummy.c
+               if [ "$HP_ARCH" = "" ]; then
+                   eval "$set_cc_for_build"
+                   sed 's/^            //' << EOF > "$dummy.c"
 
                #define _HPUX_SOURCE
                #include <stdlib.h>
@@ -643,13 +694,13 @@ EOF
                    exit (0);
                }
 EOF
-                   (CCOPTS= $CC_FOR_BUILD -o $dummy $dummy.c 2>/dev/null) && HP_ARCH=`$dummy`
+                   (CCOPTS="" $CC_FOR_BUILD -o "$dummy" "$dummy.c" 2>/dev/null) && HP_ARCH=`"$dummy"`
                    test -z "$HP_ARCH" && HP_ARCH=hppa
                fi ;;
        esac
-       if [ ${HP_ARCH} = "hppa2.0w" ]
+       if [ "$HP_ARCH" = hppa2.0w ]
        then
-           eval $set_cc_for_build
+           eval "$set_cc_for_build"
 
            # hppa2.0w-hp-hpux* has a 64-bit kernel and a compiler generating
            # 32-bit code.  hppa64-hp-hpux* has the same kernel and a compiler
@@ -660,23 +711,23 @@ EOF
            # $ CC_FOR_BUILD="cc +DA2.0w" ./config.guess
            # => hppa64-hp-hpux11.23
 
-           if echo __LP64__ | (CCOPTS= $CC_FOR_BUILD -E - 2>/dev/null) |
+           if echo __LP64__ | (CCOPTS="" $CC_FOR_BUILD -E - 2>/dev/null) |
                grep -q __LP64__
            then
-               HP_ARCH="hppa2.0w"
+               HP_ARCH=hppa2.0w
            else
-               HP_ARCH="hppa64"
+               HP_ARCH=hppa64
            fi
        fi
-       echo ${HP_ARCH}-hp-hpux${HPUX_REV}
+       echo "$HP_ARCH"-hp-hpux"$HPUX_REV"
        exit ;;
     ia64:HP-UX:*:*)
-       HPUX_REV=`echo ${UNAME_RELEASE}|sed -e 's/[^.]*.[0B]*//'`
-       echo ia64-hp-hpux${HPUX_REV}
+       HPUX_REV=`echo "$UNAME_RELEASE"|sed -e 's/[^.]*.[0B]*//'`
+       echo ia64-hp-hpux"$HPUX_REV"
        exit ;;
     3050*:HI-UX:*:*)
-       eval $set_cc_for_build
-       sed 's/^        //' << EOF >$dummy.c
+       eval "$set_cc_for_build"
+       sed 's/^        //' << EOF > "$dummy.c"
        #include <unistd.h>
        int
        main ()
@@ -701,11 +752,11 @@ EOF
          exit (0);
        }
 EOF
-       $CC_FOR_BUILD -o $dummy $dummy.c && SYSTEM_NAME=`$dummy` &&
+       $CC_FOR_BUILD -o "$dummy" "$dummy.c" && SYSTEM_NAME=`"$dummy"` &&
                { echo "$SYSTEM_NAME"; exit; }
        echo unknown-hitachi-hiuxwe2
        exit ;;
-    9000/7??:4.3bsd:*:* | 9000/8?[79]:4.3bsd:*:* )
+    9000/7??:4.3bsd:*:* | 9000/8?[79]:4.3bsd:*:*)
        echo hppa1.1-hp-bsd
        exit ;;
     9000/8??:4.3bsd:*:*)
@@ -714,7 +765,7 @@ EOF
     *9??*:MPE/iX:*:* | *3000*:MPE/iX:*:*)
        echo hppa1.0-hp-mpeix
        exit ;;
-    hp7??:OSF1:*:* | hp8?[79]:OSF1:*:* )
+    hp7??:OSF1:*:* | hp8?[79]:OSF1:*:*)
        echo hppa1.1-hp-osf
        exit ;;
     hp8??:OSF1:*:*)
@@ -722,9 +773,9 @@ EOF
        exit ;;
     i*86:OSF1:*:*)
        if [ -x /usr/sbin/sysversion ] ; then
-           echo ${UNAME_MACHINE}-unknown-osf1mk
+           echo "$UNAME_MACHINE"-unknown-osf1mk
        else
-           echo ${UNAME_MACHINE}-unknown-osf1
+           echo "$UNAME_MACHINE"-unknown-osf1
        fi
        exit ;;
     parisc*:Lites*:*:*)
@@ -749,124 +800,109 @@ EOF
        echo c4-convex-bsd
        exit ;;
     CRAY*Y-MP:*:*:*)
-       echo ymp-cray-unicos${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/'
+       echo ymp-cray-unicos"$UNAME_RELEASE" | sed -e 's/\.[^.]*$/.X/'
        exit ;;
     CRAY*[A-Z]90:*:*:*)
-       echo ${UNAME_MACHINE}-cray-unicos${UNAME_RELEASE} \
+       echo "$UNAME_MACHINE"-cray-unicos"$UNAME_RELEASE" \
        | sed -e 's/CRAY.*\([A-Z]90\)/\1/' \
              -e y/ABCDEFGHIJKLMNOPQRSTUVWXYZ/abcdefghijklmnopqrstuvwxyz/ \
              -e 's/\.[^.]*$/.X/'
        exit ;;
     CRAY*TS:*:*:*)
-       echo t90-cray-unicos${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/'
+       echo t90-cray-unicos"$UNAME_RELEASE" | sed -e 's/\.[^.]*$/.X/'
        exit ;;
     CRAY*T3E:*:*:*)
-       echo alphaev5-cray-unicosmk${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/'
+       echo alphaev5-cray-unicosmk"$UNAME_RELEASE" | sed -e 's/\.[^.]*$/.X/'
        exit ;;
     CRAY*SV1:*:*:*)
-       echo sv1-cray-unicos${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/'
+       echo sv1-cray-unicos"$UNAME_RELEASE" | sed -e 's/\.[^.]*$/.X/'
        exit ;;
     *:UNICOS/mp:*:*)
-       echo craynv-cray-unicosmp${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/'
+       echo craynv-cray-unicosmp"$UNAME_RELEASE" | sed -e 's/\.[^.]*$/.X/'
        exit ;;
     F30[01]:UNIX_System_V:*:* | F700:UNIX_System_V:*:*)
-       FUJITSU_PROC=`uname -m | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz'`
-       FUJITSU_SYS=`uname -p | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz' | sed -e 's/\///'`
-       FUJITSU_REL=`echo ${UNAME_RELEASE} | sed -e 's/ /_/'`
+       FUJITSU_PROC=`uname -m | tr ABCDEFGHIJKLMNOPQRSTUVWXYZ abcdefghijklmnopqrstuvwxyz`
+       FUJITSU_SYS=`uname -p | tr ABCDEFGHIJKLMNOPQRSTUVWXYZ abcdefghijklmnopqrstuvwxyz | sed -e 's/\///'`
+       FUJITSU_REL=`echo "$UNAME_RELEASE" | sed -e 's/ /_/'`
        echo "${FUJITSU_PROC}-fujitsu-${FUJITSU_SYS}${FUJITSU_REL}"
        exit ;;
     5000:UNIX_System_V:4.*:*)
-       FUJITSU_SYS=`uname -p | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz' | sed -e 's/\///'`
-       FUJITSU_REL=`echo ${UNAME_RELEASE} | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz' | sed -e 's/ /_/'`
+       FUJITSU_SYS=`uname -p | tr ABCDEFGHIJKLMNOPQRSTUVWXYZ abcdefghijklmnopqrstuvwxyz | sed -e 's/\///'`
+       FUJITSU_REL=`echo "$UNAME_RELEASE" | tr ABCDEFGHIJKLMNOPQRSTUVWXYZ abcdefghijklmnopqrstuvwxyz | sed -e 's/ /_/'`
        echo "sparc-fujitsu-${FUJITSU_SYS}${FUJITSU_REL}"
        exit ;;
     i*86:BSD/386:*:* | i*86:BSD/OS:*:* | *:Ascend\ Embedded/OS:*:*)
-       echo ${UNAME_MACHINE}-pc-bsdi${UNAME_RELEASE}
+       echo "$UNAME_MACHINE"-pc-bsdi"$UNAME_RELEASE"
        exit ;;
     sparc*:BSD/OS:*:*)
-       echo sparc-unknown-bsdi${UNAME_RELEASE}
+       echo sparc-unknown-bsdi"$UNAME_RELEASE"
        exit ;;
     *:BSD/OS:*:*)
-       echo ${UNAME_MACHINE}-unknown-bsdi${UNAME_RELEASE}
+       echo "$UNAME_MACHINE"-unknown-bsdi"$UNAME_RELEASE"
        exit ;;
     *:FreeBSD:*:*)
        UNAME_PROCESSOR=`/usr/bin/uname -p`
-       case ${UNAME_PROCESSOR} in
+       case "$UNAME_PROCESSOR" in
            amd64)
-               echo x86_64-unknown-freebsd`echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'` ;;
-           *)
-               echo ${UNAME_PROCESSOR}-unknown-freebsd`echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'` ;;
+               UNAME_PROCESSOR=x86_64 ;;
+           i386)
+               UNAME_PROCESSOR=i586 ;;
        esac
+       echo "$UNAME_PROCESSOR"-unknown-freebsd"`echo "$UNAME_RELEASE"|sed -e 's/[-(].*//'`"
        exit ;;
     i*:CYGWIN*:*)
-       echo ${UNAME_MACHINE}-pc-cygwin
+       echo "$UNAME_MACHINE"-pc-cygwin
        exit ;;
-    *:MINGW*:*)
-       echo ${UNAME_MACHINE}-pc-mingw32
+    *:MINGW64*:*)
+       echo "$UNAME_MACHINE"-pc-mingw64
        exit ;;
-    i*:MSYS*:*)
-       echo ${UNAME_MACHINE}-pc-msys
+    *:MINGW*:*)
+       echo "$UNAME_MACHINE"-pc-mingw32
        exit ;;
-    i*:windows32*:*)
-       # uname -m includes "-pc" on this system.
-       echo ${UNAME_MACHINE}-mingw32
+    *:MSYS*:*)
+       echo "$UNAME_MACHINE"-pc-msys
        exit ;;
     i*:PW*:*)
-       echo ${UNAME_MACHINE}-pc-pw32
+       echo "$UNAME_MACHINE"-pc-pw32
        exit ;;
     *:Interix*:*)
-       case ${UNAME_MACHINE} in
+       case "$UNAME_MACHINE" in
            x86)
-               echo i586-pc-interix${UNAME_RELEASE}
+               echo i586-pc-interix"$UNAME_RELEASE"
                exit ;;
            authenticamd | genuineintel | EM64T)
-               echo x86_64-unknown-interix${UNAME_RELEASE}
+               echo x86_64-unknown-interix"$UNAME_RELEASE"
                exit ;;
            IA64)
-               echo ia64-unknown-interix${UNAME_RELEASE}
+               echo ia64-unknown-interix"$UNAME_RELEASE"
                exit ;;
        esac ;;
-    [345]86:Windows_95:* | [345]86:Windows_98:* | [345]86:Windows_NT:*)
-       echo i${UNAME_MACHINE}-pc-mks
-       exit ;;
-    8664:Windows_NT:*)
-       echo x86_64-pc-mks
-       exit ;;
-    i*:Windows_NT*:* | Pentium*:Windows_NT*:*)
-       # How do we know it's Interix rather than the generic POSIX subsystem?
-       # It also conflicts with pre-2.0 versions of AT&T UWIN. Should we
-       # UNAME_MACHINE based on the output of uname instead of i386?
-       echo i586-pc-interix
-       exit ;;
     i*:UWIN*:*)
-       echo ${UNAME_MACHINE}-pc-uwin
+       echo "$UNAME_MACHINE"-pc-uwin
        exit ;;
     amd64:CYGWIN*:*:* | x86_64:CYGWIN*:*:*)
        echo x86_64-unknown-cygwin
        exit ;;
-    p*:CYGWIN*:*)
-       echo powerpcle-unknown-cygwin
-       exit ;;
     prep*:SunOS:5.*:*)
-       echo powerpcle-unknown-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'`
+       echo powerpcle-unknown-solaris2"`echo "$UNAME_RELEASE"|sed -e 's/[^.]*//'`"
        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 "[:upper:]" "[:lower:]"``echo "$UNAME_RELEASE"|sed -e 's/[-(].*//'`-$LIBC"
        exit ;;
-    i*86:Minix:*:*)
-       echo ${UNAME_MACHINE}-pc-minix
+    *:Minix:*:*)
+       echo "$UNAME_MACHINE"-unknown-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,63 +915,64 @@ 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
+       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 ;;
+    e2k:Linux:*:*)
+       echo "$UNAME_MACHINE"-unknown-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 ;;
+    k1om:Linux:*:*)
+       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
-       sed 's/^        //' << EOF >$dummy.c
+       eval "$set_cc_for_build"
+       sed 's/^        //' << EOF > "$dummy.c"
        #undef CPU
        #undef ${UNAME_MACHINE}
        #undef ${UNAME_MACHINE}el
@@ -949,55 +986,70 @@ EOF
        #endif
        #endif
 EOF
-       eval `$CC_FOR_BUILD -E $dummy.c 2>/dev/null | grep '^CPU'`
-       test x"${CPU}" != x && { echo "${CPU}-unknown-linux-gnu"; exit; }
+       eval "`$CC_FOR_BUILD -E "$dummy.c" 2>/dev/null | grep '^CPU'`"
+       test "x$CPU" != x && { echo "$CPU-unknown-linux-$LIBC"; exit; }
        ;;
-    or32:Linux:*:*)
-       echo ${UNAME_MACHINE}-unknown-linux-gnu
+    mips64el:Linux:*:*)
+       echo "$UNAME_MACHINE"-unknown-linux-"$LIBC"
+       exit ;;
+    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 ;;
+    riscv32:Linux:*:* | riscv64:Linux:*:*)
+       echo "$UNAME_MACHINE"-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"-pc-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.
@@ -1011,34 +1063,34 @@ EOF
        # I am not positive that other SVR4 systems won't match this,
        # I just have to hope.  -- rms.
        # Use sysv4.2uw... so that sysv4* matches it.
-       echo ${UNAME_MACHINE}-pc-sysv4.2uw${UNAME_VERSION}
+       echo "$UNAME_MACHINE"-pc-sysv4.2uw"$UNAME_VERSION"
        exit ;;
     i*86:OS/2:*:*)
        # If we were able to find `uname', then EMX Unix compatibility
        # is probably installed.
-       echo ${UNAME_MACHINE}-pc-os2-emx
+       echo "$UNAME_MACHINE"-pc-os2-emx
        exit ;;
     i*86:XTS-300:*:STOP)
-       echo ${UNAME_MACHINE}-unknown-stop
+       echo "$UNAME_MACHINE"-unknown-stop
        exit ;;
     i*86:atheos:*:*)
-       echo ${UNAME_MACHINE}-unknown-atheos
+       echo "$UNAME_MACHINE"-unknown-atheos
        exit ;;
     i*86:syllable:*:*)
-       echo ${UNAME_MACHINE}-pc-syllable
+       echo "$UNAME_MACHINE"-pc-syllable
        exit ;;
     i*86:LynxOS:2.*:* | i*86:LynxOS:3.[01]*:* | i*86:LynxOS:4.[02]*:*)
-       echo i386-unknown-lynxos${UNAME_RELEASE}
+       echo i386-unknown-lynxos"$UNAME_RELEASE"
        exit ;;
     i*86:*DOS:*:*)
-       echo ${UNAME_MACHINE}-pc-msdosdjgpp
+       echo "$UNAME_MACHINE"-pc-msdosdjgpp
        exit ;;
-    i*86:*:4.*:* | i*86:SYSTEM_V:4.*:*)
-       UNAME_REL=`echo ${UNAME_RELEASE} | sed 's/\/MP$//'`
+    i*86:*:4.*:*)
+       UNAME_REL=`echo "$UNAME_RELEASE" | sed 's/\/MP$//'`
        if grep Novell /usr/include/link.h >/dev/null 2>/dev/null; then
-               echo ${UNAME_MACHINE}-univel-sysv${UNAME_REL}
+               echo "$UNAME_MACHINE"-univel-sysv"$UNAME_REL"
        else
-               echo ${UNAME_MACHINE}-pc-sysv${UNAME_REL}
+               echo "$UNAME_MACHINE"-pc-sysv"$UNAME_REL"
        fi
        exit ;;
     i*86:*:5:[678]*)
@@ -1048,12 +1100,12 @@ EOF
            *Pentium)        UNAME_MACHINE=i586 ;;
            *Pent*|*Celeron) UNAME_MACHINE=i686 ;;
        esac
-       echo ${UNAME_MACHINE}-unknown-sysv${UNAME_RELEASE}${UNAME_SYSTEM}${UNAME_VERSION}
+       echo "$UNAME_MACHINE-unknown-sysv${UNAME_RELEASE}${UNAME_SYSTEM}{$UNAME_VERSION}"
        exit ;;
     i*86:*:3.2:*)
        if test -f /usr/options/cb.name; then
                UNAME_REL=`sed -n 's/.*Version //p' </usr/options/cb.name`
-               echo ${UNAME_MACHINE}-pc-isc$UNAME_REL
+               echo "$UNAME_MACHINE"-pc-isc"$UNAME_REL"
        elif /bin/uname -X 2>/dev/null >/dev/null ; then
                UNAME_REL=`(/bin/uname -X|grep Release|sed -e 's/.*= //')`
                (/bin/uname -X|grep i80486 >/dev/null) && UNAME_MACHINE=i486
@@ -1063,9 +1115,9 @@ EOF
                        && UNAME_MACHINE=i686
                (/bin/uname -X|grep '^Machine.*Pentium Pro' >/dev/null) \
                        && UNAME_MACHINE=i686
-               echo ${UNAME_MACHINE}-pc-sco$UNAME_REL
+               echo "$UNAME_MACHINE"-pc-sco"$UNAME_REL"
        else
-               echo ${UNAME_MACHINE}-pc-sysv32
+               echo "$UNAME_MACHINE"-pc-sysv32
        fi
        exit ;;
     pc:*:*:*)
@@ -1073,7 +1125,7 @@ EOF
        # uname -m prints for DJGPP always 'pc', but it prints nothing about
        # the processor, so we play safe by assuming i586.
        # Note: whatever this is, it MUST be the same as what config.sub
-       # prints for the "djgpp" host, or else GDB configury will decide that
+       # prints for the "djgpp" host, or else GDB configure will decide that
        # this is a cross-build.
        echo i586-pc-msdosdjgpp
        exit ;;
@@ -1085,9 +1137,9 @@ EOF
        exit ;;
     i860:*:4.*:*) # i860-SVR4
        if grep Stardent /usr/include/sys/uadmin.h >/dev/null 2>&1 ; then
-         echo i860-stardent-sysv${UNAME_RELEASE} # Stardent Vistra i860-SVR4
+         echo i860-stardent-sysv"$UNAME_RELEASE" # Stardent Vistra i860-SVR4
        else # Add other i860-SVR4 vendors below as they are discovered.
-         echo i860-unknown-sysv${UNAME_RELEASE}  # Unknown i860-SVR4
+         echo i860-unknown-sysv"$UNAME_RELEASE"  # Unknown i860-SVR4
        fi
        exit ;;
     mini*:CTIX:SYS*5:*)
@@ -1107,9 +1159,9 @@ EOF
        test -r /etc/.relid \
        && OS_REL=.`sed -n 's/[^ ]* [^ ]* \([0-9][0-9]\).*/\1/p' < /etc/.relid`
        /bin/uname -p 2>/dev/null | grep 86 >/dev/null \
-         && { echo i486-ncr-sysv4.3${OS_REL}; exit; }
+         && { echo i486-ncr-sysv4.3"$OS_REL"; exit; }
        /bin/uname -p 2>/dev/null | /bin/grep entium >/dev/null \
-         && { echo i586-ncr-sysv4.3${OS_REL}; exit; } ;;
+         && { echo i586-ncr-sysv4.3"$OS_REL"; exit; } ;;
     3[34]??:*:4.0:* | 3[34]??,*:*:4.0:*)
        /bin/uname -p 2>/dev/null | grep 86 >/dev/null \
          && { echo i486-ncr-sysv4; exit; } ;;
@@ -1118,28 +1170,28 @@ EOF
        test -r /etc/.relid \
            && OS_REL=.`sed -n 's/[^ ]* [^ ]* \([0-9][0-9]\).*/\1/p' < /etc/.relid`
        /bin/uname -p 2>/dev/null | grep 86 >/dev/null \
-           && { echo i486-ncr-sysv4.3${OS_REL}; exit; }
+           && { echo i486-ncr-sysv4.3"$OS_REL"; exit; }
        /bin/uname -p 2>/dev/null | /bin/grep entium >/dev/null \
-           && { echo i586-ncr-sysv4.3${OS_REL}; exit; }
+           && { echo i586-ncr-sysv4.3"$OS_REL"; exit; }
        /bin/uname -p 2>/dev/null | /bin/grep pteron >/dev/null \
-           && { echo i586-ncr-sysv4.3${OS_REL}; exit; } ;;
+           && { echo i586-ncr-sysv4.3"$OS_REL"; exit; } ;;
     m68*:LynxOS:2.*:* | m68*:LynxOS:3.0*:*)
-       echo m68k-unknown-lynxos${UNAME_RELEASE}
+       echo m68k-unknown-lynxos"$UNAME_RELEASE"
        exit ;;
     mc68030:UNIX_System_V:4.*:*)
        echo m68k-atari-sysv4
        exit ;;
     TSUNAMI:LynxOS:2.*:*)
-       echo sparc-unknown-lynxos${UNAME_RELEASE}
+       echo sparc-unknown-lynxos"$UNAME_RELEASE"
        exit ;;
     rs6000:LynxOS:2.*:*)
-       echo rs6000-unknown-lynxos${UNAME_RELEASE}
+       echo rs6000-unknown-lynxos"$UNAME_RELEASE"
        exit ;;
     PowerPC:LynxOS:2.*:* | PowerPC:LynxOS:3.[01]*:* | PowerPC:LynxOS:4.[02]*:*)
-       echo powerpc-unknown-lynxos${UNAME_RELEASE}
+       echo powerpc-unknown-lynxos"$UNAME_RELEASE"
        exit ;;
     SM[BE]S:UNIX_SV:*:*)
-       echo mips-dde-sysv${UNAME_RELEASE}
+       echo mips-dde-sysv"$UNAME_RELEASE"
        exit ;;
     RM*:ReliantUNIX-*:*:*)
        echo mips-sni-sysv4
@@ -1150,7 +1202,7 @@ EOF
     *:SINIX-*:*:*)
        if uname -p 2>/dev/null >/dev/null ; then
                UNAME_MACHINE=`(uname -p) 2>/dev/null`
-               echo ${UNAME_MACHINE}-sni-sysv4
+               echo "$UNAME_MACHINE"-sni-sysv4
        else
                echo ns32k-sni-sysv
        fi
@@ -1170,23 +1222,23 @@ EOF
        exit ;;
     i*86:VOS:*:*)
        # From Paul.Green@stratus.com.
-       echo ${UNAME_MACHINE}-stratus-vos
+       echo "$UNAME_MACHINE"-stratus-vos
        exit ;;
     *:VOS:*:*)
        # From Paul.Green@stratus.com.
        echo hppa1.1-stratus-vos
        exit ;;
     mc68*:A/UX:*:*)
-       echo m68k-apple-aux${UNAME_RELEASE}
+       echo m68k-apple-aux"$UNAME_RELEASE"
        exit ;;
     news*:NEWS-OS:6*:*)
        echo mips-sony-newsos6
        exit ;;
     R[34]000:*System_V*:*:* | R4000:UNIX_SYSV:*:* | R*000:UNIX_SV:*:*)
        if [ -d /usr/nec ]; then
-               echo mips-nec-sysv${UNAME_RELEASE}
+               echo mips-nec-sysv"$UNAME_RELEASE"
        else
-               echo mips-unknown-sysv${UNAME_RELEASE}
+               echo mips-unknown-sysv"$UNAME_RELEASE"
        fi
        exit ;;
     BeBox:BeOS:*:*)    # BeOS running on hardware made by Be, PPC only.
@@ -1201,66 +1253,97 @@ 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}
+       echo sx4-nec-superux"$UNAME_RELEASE"
        exit ;;
     SX-5:SUPER-UX:*:*)
-       echo sx5-nec-superux${UNAME_RELEASE}
+       echo sx5-nec-superux"$UNAME_RELEASE"
        exit ;;
     SX-6:SUPER-UX:*:*)
-       echo sx6-nec-superux${UNAME_RELEASE}
+       echo sx6-nec-superux"$UNAME_RELEASE"
        exit ;;
     SX-7:SUPER-UX:*:*)
-       echo sx7-nec-superux${UNAME_RELEASE}
+       echo sx7-nec-superux"$UNAME_RELEASE"
        exit ;;
     SX-8:SUPER-UX:*:*)
-       echo sx8-nec-superux${UNAME_RELEASE}
+       echo sx8-nec-superux"$UNAME_RELEASE"
        exit ;;
     SX-8R:SUPER-UX:*:*)
-       echo sx8r-nec-superux${UNAME_RELEASE}
+       echo sx8r-nec-superux"$UNAME_RELEASE"
+       exit ;;
+    SX-ACE:SUPER-UX:*:*)
+       echo sxace-nec-superux"$UNAME_RELEASE"
        exit ;;
     Power*:Rhapsody:*:*)
-       echo powerpc-apple-rhapsody${UNAME_RELEASE}
+       echo powerpc-apple-rhapsody"$UNAME_RELEASE"
        exit ;;
     *:Rhapsody:*:*)
-       echo ${UNAME_MACHINE}-apple-rhapsody${UNAME_RELEASE}
+       echo "$UNAME_MACHINE"-apple-rhapsody"$UNAME_RELEASE"
        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
-       echo ${UNAME_PROCESSOR}-apple-darwin${UNAME_RELEASE}
+       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
+               # On 10.4-10.6 one might compile for PowerPC via gcc -arch ppc
+               if (echo '#ifdef __POWERPC__'; echo IS_PPC; echo '#endif') | \
+                      (CCOPTS="" $CC_FOR_BUILD -E - 2>/dev/null) | \
+                      grep IS_PPC >/dev/null
+               then
+                   UNAME_PROCESSOR=powerpc
+               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]*:*)
        UNAME_PROCESSOR=`uname -p`
-       if test "$UNAME_PROCESSOR" = "x86"; then
+       if test "$UNAME_PROCESSOR" = x86; then
                UNAME_PROCESSOR=i386
                UNAME_MACHINE=pc
        fi
-       echo ${UNAME_PROCESSOR}-${UNAME_MACHINE}-nto-qnx${UNAME_RELEASE}
+       echo "$UNAME_PROCESSOR"-"$UNAME_MACHINE"-nto-qnx"$UNAME_RELEASE"
        exit ;;
     *:QNX:*:4*)
        echo i386-pc-qnx
        exit ;;
-    NEO-?:NONSTOP_KERNEL:*:*)
-       echo neo-tandem-nsk${UNAME_RELEASE}
+    NEO-*:NONSTOP_KERNEL:*:*)
+       echo neo-tandem-nsk"$UNAME_RELEASE"
+       exit ;;
+    NSE-*:NONSTOP_KERNEL:*:*)
+       echo nse-tandem-nsk"$UNAME_RELEASE"
+       exit ;;
+    NSR-*:NONSTOP_KERNEL:*:*)
+       echo nsr-tandem-nsk"$UNAME_RELEASE"
        exit ;;
-    NSE-?:NONSTOP_KERNEL:*:*)
-       echo nse-tandem-nsk${UNAME_RELEASE}
+    NSV-*:NONSTOP_KERNEL:*:*)
+       echo nsv-tandem-nsk"$UNAME_RELEASE"
        exit ;;
-    NSR-?:NONSTOP_KERNEL:*:*)
-       echo nsr-tandem-nsk${UNAME_RELEASE}
+    NSX-*:NONSTOP_KERNEL:*:*)
+       echo nsx-tandem-nsk"$UNAME_RELEASE"
        exit ;;
     *:NonStop-UX:*:*)
        echo mips-compaq-nonstopux
@@ -1269,18 +1352,18 @@ EOF
        echo bs2000-siemens-sysv
        exit ;;
     DS/*:UNIX_System_V:*:*)
-       echo ${UNAME_MACHINE}-${UNAME_SYSTEM}-${UNAME_RELEASE}
+       echo "$UNAME_MACHINE"-"$UNAME_SYSTEM"-"$UNAME_RELEASE"
        exit ;;
     *:Plan9:*:*)
        # "uname -m" is not consistent, so use $cputype instead. 386
        # is converted to i386 for consistency with other x86
        # operating systems.
-       if test "$cputype" = "386"; then
+       if test "$cputype" = 386; then
            UNAME_MACHINE=i386
        else
            UNAME_MACHINE="$cputype"
        fi
-       echo ${UNAME_MACHINE}-unknown-plan9
+       echo "$UNAME_MACHINE"-unknown-plan9
        exit ;;
     *:TOPS-10:*:*)
        echo pdp10-unknown-tops10
@@ -1301,14 +1384,14 @@ EOF
        echo pdp10-unknown-its
        exit ;;
     SEI:*:*:SEIUX)
-       echo mips-sei-seiux${UNAME_RELEASE}
+       echo mips-sei-seiux"$UNAME_RELEASE"
        exit ;;
     *:DragonFly:*:*)
-       echo ${UNAME_MACHINE}-unknown-dragonfly`echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'`
+       echo "$UNAME_MACHINE"-unknown-dragonfly"`echo "$UNAME_RELEASE"|sed -e 's/[-(].*//'`"
        exit ;;
     *:*VMS:*:*)
        UNAME_MACHINE=`(uname -p) 2>/dev/null`
-       case "${UNAME_MACHINE}" in
+       case "$UNAME_MACHINE" in
            A*) echo alpha-dec-vms ; exit ;;
            I*) echo ia64-dec-vms ; exit ;;
            V*) echo vax-dec-vms ; exit ;;
@@ -1317,185 +1400,48 @@ EOF
        echo i386-pc-xenix
        exit ;;
     i*86:skyos:*:*)
-       echo ${UNAME_MACHINE}-pc-skyos`echo ${UNAME_RELEASE}` | sed -e 's/ .*$//'
+       echo "$UNAME_MACHINE"-pc-skyos"`echo "$UNAME_RELEASE" | sed -e 's/ .*$//'`"
        exit ;;
     i*86:rdos:*:*)
-       echo ${UNAME_MACHINE}-pc-rdos
+       echo "$UNAME_MACHINE"-pc-rdos
        exit ;;
     i*86:AROS:*:*)
-       echo ${UNAME_MACHINE}-pc-aros
+       echo "$UNAME_MACHINE"-pc-aros
        exit ;;
     x86_64:VMkernel:*:*)
-       echo ${UNAME_MACHINE}-unknown-esx
+       echo "$UNAME_MACHINE"-unknown-esx
+       exit ;;
+    amd64:Isilon\ OneFS:*:*)
+       echo x86_64-unknown-onefs
        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);
+echo "$0: unable to guess system type" >&2
 
-#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
+case "$UNAME_MACHINE:$UNAME_SYSTEM" in
+    mips:Linux | mips64:Linux)
+       # If we got here on MIPS GNU/Linux, output extra information.
+       cat >&2 <<EOF
 
-#if defined (alliant) && defined (i860)
-  printf ("i860-alliant-bsd\n"); exit (0);
-#endif
-
-  exit (1);
-}
+NOTE: MIPS GNU/Linux systems require a C compiler to fully recognize
+the system type. Please install a C compiler and try again.
 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
+       ;;
+esac
 
 cat >&2 <<EOF
-$0: unable to guess system type
 
-This script, last modified $timestamp, has failed to recognize
-the operating system you are using. It is advised that you
-download the most up to date version of the config scripts from
+This script (version $timestamp), has failed to recognize the
+operating system you are using. If your script is old, overwrite *all*
+copies of config.guess and config.sub with the latest versions from:
 
-  http://git.savannah.gnu.org/gitweb/?p=config.git;a=blob_plain;f=config.guess;hb=HEAD
+  https://git.savannah.gnu.org/gitweb/?p=config.git;a=blob_plain;f=config.guess
 and
-  http://git.savannah.gnu.org/gitweb/?p=config.git;a=blob_plain;f=config.sub;hb=HEAD
+  https://git.savannah.gnu.org/gitweb/?p=config.git;a=blob_plain;f=config.sub
 
-If the version you run ($0) is already up to date, please
-send the following data and any information you think might be
-pertinent to <config-patches@gnu.org> in order to provide the needed
-information to handle your system.
+If $0 has already been updated, send the following data and any
+information you think might be pertinent to config-patches@gnu.org to
+provide the necessary information to handle your system.
 
 config.guess timestamp = $timestamp
 
@@ -1514,16 +1460,16 @@ hostinfo               = `(hostinfo) 2>/dev/null`
 /usr/bin/oslevel       = `(/usr/bin/oslevel) 2>/dev/null`
 /usr/convex/getsysinfo = `(/usr/convex/getsysinfo) 2>/dev/null`
 
-UNAME_MACHINE = ${UNAME_MACHINE}
-UNAME_RELEASE = ${UNAME_RELEASE}
-UNAME_SYSTEM  = ${UNAME_SYSTEM}
-UNAME_VERSION = ${UNAME_VERSION}
+UNAME_MACHINE = "$UNAME_MACHINE"
+UNAME_RELEASE = "$UNAME_RELEASE"
+UNAME_SYSTEM  = "$UNAME_SYSTEM"
+UNAME_VERSION = "$UNAME_VERSION"
 EOF
 
 exit 1
 
 # Local variables:
-# eval: (add-hook 'write-file-hooks 'time-stamp)
+# eval: (add-hook 'before-save-hook 'time-stamp)
 # time-stamp-start: "timestamp='"
 # time-stamp-format: "%:y-%02m-%02d"
 # time-stamp-end: "'"
index 4bbb491..94db7bb 100644 (file)
@@ -1,10 +1,25 @@
-/* config.h.in.  Generated from configure.in by autoheader.  */
+/* config.h.in.  Generated from configure.ac by autoheader.  */
+
+/* Define to 1 if arpa/inet.h declares `ether_hostton' */
+#undef ARPA_INET_H_DECLARES_ETHER_HOSTTON
 
 /* Enable optimizer debugging */
 #undef BDEBUG
 
-/* define if you have a cloning BPF device */
-#undef HAVE_CLONING_BPF
+/* Define to 1 if remote packet capture is to be supported */
+#undef ENABLE_REMOTE
+
+/* define if we have the AIX getnetbyname_r() */
+#undef HAVE_AIX_GETNETBYNAME_R
+
+/* define if we have the AIX getprotobyname_r() */
+#undef HAVE_AIX_GETPROTOBYNAME_R
+
+/* Define to 1 if you have the `asprintf' function. */
+#undef HAVE_ASPRINTF
+
+/* Define to 1 if you have the <dagapi.h> header file. */
+#undef HAVE_DAGAPI_H
 
 /* define if you have the DAG API */
 #undef HAVE_DAG_API
 /* define if you have dag_get_stream_erf_types() */
 #undef HAVE_DAG_GET_STREAM_ERF_TYPES
 
-/* define if you have streams capable DAG API */
-#undef HAVE_DAG_STREAMS_API
+/* define if you have large streams capable DAG API */
+#undef HAVE_DAG_LARGE_STREAMS_API
 
 /* define if you have vdag_set_device_info() */
 #undef HAVE_DAG_VDAG
 
-/* Define to 1 if you have the declaration of `ether_hostton', and to 0 if you
-   don't. */
+/* Define to 1 if you have the declaration of `ether_hostton' */
 #undef HAVE_DECL_ETHER_HOSTTON
 
-/* define if you have a /dev/dlpi */
-#undef HAVE_DEV_DLPI
+/* Define to 1 if `dl_module_id_1' is a member of `dl_hp_ppa_info_t'. */
+#undef HAVE_DL_HP_PPA_INFO_T_DL_MODULE_ID_1
 
-/* if passive_req_t primitive exists */
-#undef HAVE_DLPI_PASSIVE
+/* Define to 1 if the system has the type `dl_passive_req_t'. */
+#undef HAVE_DL_PASSIVE_REQ_T
 
 /* Define to 1 if you have the `ether_hostton' function. */
 #undef HAVE_ETHER_HOSTTON
 
+/* Define to 1 if you have the `ffs' function. */
+#undef HAVE_FFS
+
 /* Define to 1 if fseeko (and presumably ftello) exists and is declared. */
 #undef HAVE_FSEEKO
 
+/* Define to 1 if you have the `getspnam' function. */
+#undef HAVE_GETSPNAM
+
+/* Define to 1 if you have a GNU-style `strerror_r' function. */
+#undef HAVE_GNU_STRERROR_R
+
 /* on HP-UX 10.20 or later */
 #undef HAVE_HPUX10_20_OR_LATER
 
 /* on HP-UX 9.x */
 #undef HAVE_HPUX9
 
-/* if ppa_info_t_dl_module_id exists */
-#undef HAVE_HP_PPA_INFO_T_DL_MODULE_ID_1
-
 /* Define to 1 if you have the <inttypes.h> header file. */
 #undef HAVE_INTTYPES_H
 
+/* Define to 1 if you have the `dag' library (-ldag). */
+#undef HAVE_LIBDAG
+
 /* if libdlpi exists */
 #undef HAVE_LIBDLPI
 
 /* 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_packet.h> header file. */
-#undef HAVE_LINUX_IF_PACKET_H
+/* define if we have the Linux getnetbyname_r() */
+#undef HAVE_LINUX_GETNETBYNAME_R
+
+/* define if we have the Linux getprotobyname_r() */
+#undef HAVE_LINUX_GETPROTOBYNAME_R
+
+/* 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/net_tstamp.h> header file. */
 #undef HAVE_LINUX_NET_TSTAMP_H
 
-/* if tp_vlan_tci exists */
-#undef HAVE_LINUX_TPACKET_AUXDATA_TP_VLAN_TCI
+/* Define to 1 if you have the <linux/socket.h> header file. */
+#undef HAVE_LINUX_SOCKET_H
 
-/* Define to 1 if you have the <linux/types.h> header file. */
-#undef HAVE_LINUX_TYPES_H
+/* Define to 1 if you have the <linux/sockios.h> header file. */
+#undef HAVE_LINUX_SOCKIOS_H
 
 /* Define to 1 if you have the <linux/usbdevice_fs.h> header file. */
 #undef HAVE_LINUX_USBDEVICE_FS_H
 /* Define to 1 if you have the <memory.h> header file. */
 #undef HAVE_MEMORY_H
 
-/* Define to 1 if you have the <netinet/ether.h> header file. */
-#undef HAVE_NETINET_ETHER_H
-
-/* Define to 1 if you have the <netinet/if_ether.h> header file. */
-#undef HAVE_NETINET_IF_ETHER_H
-
-/* Define to 1 if you have the <netpacket/if_packet.h> header file. */
-#undef HAVE_NETPACKET_IF_PACKET_H
-
 /* Define to 1 if you have the <netpacket/packet.h> header file. */
 #undef HAVE_NETPACKET_PACKET_H
 
+/* Define to 1 if you have the <net/bpf.h> header file. */
+#undef HAVE_NET_BPF_H
+
+/* Define to 1 if you have the <net/enet.h> header file. */
+#undef HAVE_NET_ENET_H
+
 /* Define to 1 if you have the <net/if_media.h> header file. */
 #undef HAVE_NET_IF_MEDIA_H
 
+/* Define to 1 if you have the <net/nit.h> header file. */
+#undef HAVE_NET_NIT_H
+
+/* Define to 1 if you have the <net/pfilt.h> header file. */
+#undef HAVE_NET_PFILT_H
+
 /* Define to 1 if you have the <net/pfvar.h> header file. */
 #undef HAVE_NET_PFVAR_H
 
+/* Define to 1 if you have the <net/raw.h> header file. */
+#undef HAVE_NET_RAW_H
+
 /* 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 to 1 if you have a POSIX-style `strerror_r' function. */
+#undef HAVE_POSIX_STRERROR_R
+
+/* 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. */
 #undef HAVE_SNPRINTF
 
-/* if struct sockaddr has the sa_len member */
-#undef HAVE_SOCKADDR_SA_LEN
-
-/* if struct sockaddr_storage exists */
-#undef HAVE_SOCKADDR_STORAGE
-
-/* define if socklen_t is defined */
+/* Define to 1 if the system has the type `socklen_t'. */
 #undef HAVE_SOCKLEN_T
 
 /* On solaris */
 #undef HAVE_SOLARIS
 
+/* define if we have the Solaris/IRIX getnetbyname_r() */
+#undef HAVE_SOLARIS_IRIX_GETNETBYNAME_R
+
+/* define if we have the Solaris/IRIX getprotobyname_r() */
+#undef HAVE_SOLARIS_IRIX_GETPROTOBYNAME_R
+
 /* Define to 1 if you have the <stdint.h> header file. */
 #undef HAVE_STDINT_H
 
 /* Define to 1 if you have the `strerror' function. */
 #undef HAVE_STRERROR
 
+/* Define to 1 if you have the `strerror_s' function. */
+#undef HAVE_STRERROR_S
+
 /* Define to 1 if you have the <strings.h> header file. */
 #undef HAVE_STRINGS_H
 
 /* Define to 1 if you have the <string.h> header file. */
 #undef HAVE_STRING_H
 
+/* Define to 1 if you have the `strlcat' function. */
+#undef HAVE_STRLCAT
+
 /* 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
 
 /* Define to 1 if the system has the type `struct ether_addr'. */
 #undef HAVE_STRUCT_ETHER_ADDR
 
-/* Define to 1 if you have the <sys/bitypes.h> header file. */
-#undef HAVE_SYS_BITYPES_H
+/* Define to 1 if `msg_control' is a member of `struct msghdr'. */
+#undef HAVE_STRUCT_MSGHDR_MSG_CONTROL
+
+/* Define to 1 if `msg_flags' is a member of `struct msghdr'. */
+#undef HAVE_STRUCT_MSGHDR_MSG_FLAGS
+
+/* Define to 1 if `hci_channel' is a member of `struct sockaddr_hci'. */
+#undef HAVE_STRUCT_SOCKADDR_HCI_HCI_CHANNEL
+
+/* Define to 1 if `sa_len' is a member of `struct sockaddr'. */
+#undef HAVE_STRUCT_SOCKADDR_SA_LEN
+
+/* Define to 1 if the system has the type `struct sockaddr_storage'. */
+#undef HAVE_STRUCT_SOCKADDR_STORAGE
+
+/* Define to 1 if `tp_vlan_tci' is a member of `struct tpacket_auxdata'. */
+#undef HAVE_STRUCT_TPACKET_AUXDATA_TP_VLAN_TCI
+
+/* Define to 1 if the system has the type `struct tpacket_stats'. */
+#undef HAVE_STRUCT_TPACKET_STATS
+
+/* Define to 1 if `bRequestType' is a member of `struct
+   usbdevfs_ctrltransfer'. */
+#undef HAVE_STRUCT_USBDEVFS_CTRLTRANSFER_BREQUESTTYPE
 
 /* Define to 1 if you have the <sys/bufmod.h> header file. */
 #undef HAVE_SYS_BUFMOD_H
 /* Define to 1 if you have the <sys/dlpi_ext.h> header file. */
 #undef HAVE_SYS_DLPI_EXT_H
 
+/* Define to 1 if you have the <sys/dlpi.h> header file. */
+#undef HAVE_SYS_DLPI_H
+
 /* 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/net/nit.h> header file. */
+#undef HAVE_SYS_NET_NIT_H
+
 /* Define to 1 if you have the <sys/sockio.h> header file. */
 #undef HAVE_SYS_SOCKIO_H
 
 /* Define to 1 if you have the <sys/types.h> header file. */
 #undef HAVE_SYS_TYPES_H
 
-/* if if_packet.h has tpacket_stats defined */
-#undef HAVE_TPACKET_STATS
+/* define if you have the TurboCap API */
+#undef HAVE_TC_API
 
 /* Define to 1 if you have the <unistd.h> header file. */
 #undef HAVE_UNISTD_H
 
-/* 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 `vasprintf' function. */
+#undef HAVE_VASPRINTF
 
 /* Define to 1 if you have the `vsnprintf' function. */
 #undef HAVE_VSNPRINTF
 
-/* define if the system supports zerocopy BPF */
-#undef HAVE_ZEROCOPY_BPF
-
-/* define if your compiler has __attribute__ */
-#undef HAVE___ATTRIBUTE__
+/* Define to 1 if you have the `vsyslog' function. */
+#undef HAVE_VSYSLOG
 
 /* IPv6 */
 #undef INET6
 /* 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
 
 /* Define to 1 if netinet/if_ether.h declares `ether_hostton' */
 #undef NETINET_IF_ETHER_H_DECLARES_ETHER_HOSTTON
 
+/* Define to 1 if net/ethernet.h declares `ether_hostton' */
+#undef NET_ETHERNET_H_DECLARES_ETHER_HOSTTON
+
 /* do not use protochain */
 #undef NO_PROTOCHAIN
 
 /* Define to the version of this package. */
 #undef PACKAGE_VERSION
 
-/* /dev/dlpi directory */
-#undef PCAP_DEV_PREFIX
-
 /* target host supports Bluetooth sniffing */
 #undef PCAP_SUPPORT_BT
 
 /* 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
 
+/* target host supports netmap */
+#undef PCAP_SUPPORT_NETMAP
+
+/* use packet ring capture support on Linux if available */
+#undef PCAP_SUPPORT_PACKET_RING
+
+/* target host supports RDMA sniffing */
+#undef PCAP_SUPPORT_RDMASNIFF
+
 /* target host supports USB sniffing */
 #undef PCAP_SUPPORT_USB
 
 /* include ACN support */
 #undef SITA
 
-/* if struct sockaddr_hci has hci_channel member */
-#undef SOCKADDR_HCI_HAS_HCI_CHANNEL
-
 /* Define to 1 if you have the ANSI C header files. */
 #undef STDC_HEADERS
 
+/* Define to 1 if strings.h declares `ffs' */
+#undef STRINGS_H_DECLARES_FFS
+
+/* Define to 1 if sys/ethernet.h declares `ether_hostton' */
+#undef SYS_ETHERNET_H_DECLARES_ETHER_HOSTTON
+
 /* 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
 /* define on AIX to get certain functions */
 #undef _SUN
 
-/* define if your compiler allows __attribute__((format)) without a warning */
-#undef __ATTRIBUTE___FORMAT_OK
-
 /* to handle Ultrix compilers that don't support const in prototypes */
 #undef const
 
 /* Define as token for inline if inlining supported */
 #undef inline
 
-/* Define to `short' if int16_t not defined. */
-#undef int16_t
-
-/* Define to `int' if int32_t not defined. */
-#undef int32_t
-
-/* Define to `long long' if int64_t not defined. */
-#undef int64_t
-
-/* Define to `signed char' if int8_t not defined. */
-#undef int8_t
-
 /* on sinix */
 #undef sinix
-
-/* Define to `unsigned short' if u_int16_t not defined. */
-#undef u_int16_t
-
-/* Define to `unsigned int' if u_int32_t not defined. */
-#undef u_int32_t
-
-/* Define to `unsigned long long' if u_int64_t not defined. */
-#undef u_int64_t
-
-/* Define to `unsigned char' if u_int8_t not defined. */
-#undef u_int8_t
index 59bb593..c95acc6 100755 (executable)
@@ -1,36 +1,31 @@
 #! /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-2018 Free Software Foundation, Inc.
 
-timestamp='2012-04-18'
+timestamp='2018-07-03'
 
-# 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/>.
+# along with this program; if not, see <https://www.gnu.org/licenses/>.
 #
 # 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.
@@ -38,7 +33,7 @@ timestamp='2012-04-18'
 # Otherwise, we print the canonical config type on stdout and succeed.
 
 # You can get the latest version of this script from:
-# http://git.savannah.gnu.org/gitweb/?p=config.git;a=blob_plain;f=config.sub;hb=HEAD
+# https://git.savannah.gnu.org/gitweb/?p=config.git;a=blob_plain;f=config.sub
 
 # This file is supposed to be the same for all GNU packages
 # and recognize all the CPU types, system types and aliases
@@ -58,12 +53,11 @@ timestamp='2012-04-18'
 me=`echo "$0" | sed -e 's,.*/,,'`
 
 usage="\
-Usage: $0 [OPTION] CPU-MFR-OPSYS
-       $0 [OPTION] ALIAS
+Usage: $0 [OPTION] CPU-MFR-OPSYS or ALIAS
 
 Canonicalize a configuration name.
 
-Operation modes:
+Options:
   -h, --help         print this help, then exit
   -t, --time-stamp   print date of last modification, then exit
   -v, --version      print version number, then exit
@@ -73,9 +67,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-2018 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."
@@ -102,7 +94,7 @@ while test $# -gt 0 ; do
 
     *local*)
        # First pass through any local machine types.
-       echo $1
+       echo "$1"
        exit ;;
 
     * )
@@ -118,134 +110,455 @@ case $# in
     exit 1;;
 esac
 
-# Separate what the user gave into CPU-COMPANY and OS or KERNEL-OS (if any).
-# Here we must recognize all the valid KERNEL-OS combinations.
-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* | \
-  kopensolaris*-gnu* | \
-  storm-chaos* | os2-emx* | rtmk-nova*)
-    os=-$maybe_os
-    basic_machine=`echo $1 | sed 's/^\(.*\)-\([^-]*-[^-]*\)$/\1/'`
-    ;;
-  android-linux)
-    os=-linux-android
-    basic_machine=`echo $1 | sed 's/^\(.*\)-\([^-]*-[^-]*\)$/\1/'`-unknown
-    ;;
-  *)
-    basic_machine=`echo $1 | sed 's/-[^-]*$//'`
-    if [ $basic_machine != $1 ]
-    then os=`echo $1 | sed 's/.*-/-/'`
-    else os=; fi
-    ;;
-esac
+# Split fields of configuration type
+IFS="-" read -r field1 field2 field3 field4 <<EOF
+$1
+EOF
 
-### Let's recognize common machines as not being operating systems so
-### that things like config.sub decstation-3100 work.  We also
-### recognize some manufacturers as not being operating systems, so we
-### can provide default operating systems below.
-case $os in
-       -sun*os*)
-               # Prevent following clause from handling this invalid input.
-               ;;
-       -dec* | -mips* | -sequent* | -encore* | -pc532* | -sgi* | -sony* | \
-       -att* | -7300* | -3300* | -delta* | -motorola* | -sun[234]* | \
-       -unicom* | -ibm* | -next | -hp | -isi* | -apollo | -altos* | \
-       -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)
-               os=
-               basic_machine=$1
-               ;;
-       -bluegene*)
-               os=-cnk
-               ;;
-       -sim | -cisco | -oki | -wec | -winbond)
-               os=
-               basic_machine=$1
-               ;;
-       -scout)
-               ;;
-       -wrs)
-               os=-vxworks
-               basic_machine=$1
-               ;;
-       -chorusos*)
-               os=-chorusos
-               basic_machine=$1
-               ;;
-       -chorusrdb)
-               os=-chorusrdb
-               basic_machine=$1
-               ;;
-       -hiux*)
-               os=-hiuxwe2
-               ;;
-       -sco6)
-               os=-sco5v6
-               basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'`
-               ;;
-       -sco5)
-               os=-sco3.2v5
-               basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'`
-               ;;
-       -sco4)
-               os=-sco3.2v4
-               basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'`
-               ;;
-       -sco3.2.[4-9]*)
-               os=`echo $os | sed -e 's/sco3.2./sco3.2v/'`
-               basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'`
-               ;;
-       -sco3.2v[4-9]*)
-               # Don't forget version if it is 3.2v4 or newer.
-               basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'`
-               ;;
-       -sco5v6*)
-               # Don't forget version if it is 3.2v4 or newer.
-               basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'`
-               ;;
-       -sco*)
-               os=-sco3.2v2
-               basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'`
-               ;;
-       -udk*)
-               basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'`
-               ;;
-       -isc)
-               os=-isc2.2
-               basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'`
-               ;;
-       -clix*)
-               basic_machine=clipper-intergraph
-               ;;
-       -isc*)
-               basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'`
-               ;;
-       -lynx*178)
-               os=-lynxos178
-               ;;
-       -lynx*5)
-               os=-lynxos5
-               ;;
-       -lynx*)
-               os=-lynxos
+# Separate into logical components for further validation
+case $1 in
+       *-*-*-*-*)
+               echo Invalid configuration \`"$1"\': more than four components >&2
+               exit 1
                ;;
-       -ptx*)
-               basic_machine=`echo $1 | sed -e 's/86-.*/86-sequent/'`
+       *-*-*-*)
+               basic_machine=$field1-$field2
+               os=$field3-$field4
                ;;
-       -windowsnt*)
-               os=`echo $os | sed -e 's/windowsnt/winnt/'`
+       *-*-*)
+               # Ambiguous whether COMPANY is present, or skipped and KERNEL-OS is two
+               # parts
+               maybe_os=$field2-$field3
+               case $maybe_os in
+                       nto-qnx* | linux-gnu* | linux-android* | linux-dietlibc \
+                       | linux-newlib* | linux-musl* | linux-uclibc* | uclinux-uclibc* \
+                       | uclinux-gnu* | kfreebsd*-gnu* | knetbsd*-gnu* | netbsd*-gnu* \
+                       | netbsd*-eabi* | kopensolaris*-gnu* | cloudabi*-eabi* \
+                       | storm-chaos* | os2-emx* | rtmk-nova*)
+                               basic_machine=$field1
+                               os=$maybe_os
+                               ;;
+                       android-linux)
+                               basic_machine=$field1-unknown
+                               os=linux-android
+                               ;;
+                       *)
+                               basic_machine=$field1-$field2
+                               os=$field3
+                               ;;
+               esac
                ;;
-       -psos*)
-               os=-psos
+       *-*)
+               # Second component is usually, but not always the OS
+               case $field2 in
+                       # Prevent following clause from handling this valid os
+                       sun*os*)
+                               basic_machine=$field1
+                               os=$field2
+                               ;;
+                       # Manufacturers
+                       dec* | mips* | sequent* | encore* | pc532* | sgi* | sony* \
+                       | att* | 7300* | 3300* | delta* | motorola* | sun[234]* \
+                       | unicom* | ibm* | next | hp | isi* | apollo | altos* \
+                       | 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* \
+                       | sim | cisco | oki | wec | wrs | winbond)
+                               basic_machine=$field1-$field2
+                               os=
+                               ;;
+                       *)
+                               basic_machine=$field1
+                               os=$field2
+                               ;;
+               esac
                ;;
-       -mint | -mint[0-9]*)
-               basic_machine=m68k-atari
-               os=-mint
+       *)
+               # Convert single-component short-hands not valid as part of
+               # multi-component configurations.
+               case $field1 in
+                       386bsd)
+                               basic_machine=i386-pc
+                               os=bsd
+                               ;;
+                       a29khif)
+                               basic_machine=a29k-amd
+                               os=udi
+                               ;;
+                       adobe68k)
+                               basic_machine=m68010-adobe
+                               os=scout
+                               ;;
+                       am29k)
+                               basic_machine=a29k-none
+                               os=bsd
+                               ;;
+                       amdahl)
+                               basic_machine=580-amdahl
+                               os=sysv
+                               ;;
+                       amigaos | amigados)
+                               basic_machine=m68k-unknown
+                               os=amigaos
+                               ;;
+                       amigaunix | amix)
+                               basic_machine=m68k-unknown
+                               os=sysv4
+                               ;;
+                       apollo68)
+                               basic_machine=m68k-apollo
+                               os=sysv
+                               ;;
+                       apollo68bsd)
+                               basic_machine=m68k-apollo
+                               os=bsd
+                               ;;
+                       aros)
+                               basic_machine=i386-pc
+                               os=aros
+                               ;;
+                       aux)
+                               basic_machine=m68k-apple
+                               os=aux
+                               ;;
+                       balance)
+                               basic_machine=ns32k-sequent
+                               os=dynix
+                               ;;
+                       blackfin)
+                               basic_machine=bfin-unknown
+                               os=linux
+                               ;;
+                       cegcc)
+                               basic_machine=arm-unknown
+                               os=cegcc
+                               ;;
+                       cray)
+                               basic_machine=j90-cray
+                               os=unicos
+                               ;;
+                       craynv)
+                               basic_machine=craynv-cray
+                               os=unicosmp
+                               ;;
+                       delta88)
+                               basic_machine=m88k-motorola
+                               os=sysv3
+                               ;;
+                       dicos)
+                               basic_machine=i686-pc
+                               os=dicos
+                               ;;
+                       djgpp)
+                               basic_machine=i586-pc
+                               os=msdosdjgpp
+                               ;;
+                       ebmon29k)
+                               basic_machine=a29k-amd
+                               os=ebmon
+                               ;;
+                       es1800 | OSE68k | ose68k | ose | OSE)
+                               basic_machine=m68k-ericsson
+                               os=ose
+                               ;;
+                       gmicro)
+                               basic_machine=tron-gmicro
+                               os=sysv
+                               ;;
+                       go32)
+                               basic_machine=i386-pc
+                               os=go32
+                               ;;
+                       h8300hms)
+                               basic_machine=h8300-hitachi
+                               os=hms
+                               ;;
+                       h8300xray)
+                               basic_machine=h8300-hitachi
+                               os=xray
+                               ;;
+                       h8500hms)
+                               basic_machine=h8500-hitachi
+                               os=hms
+                               ;;
+                       harris)
+                               basic_machine=m88k-harris
+                               os=sysv3
+                               ;;
+                       hp300bsd)
+                               basic_machine=m68k-hp
+                               os=bsd
+                               ;;
+                       hp300hpux)
+                               basic_machine=m68k-hp
+                               os=hpux
+                               ;;
+                       hppaosf)
+                               basic_machine=hppa1.1-hp
+                               os=osf
+                               ;;
+                       hppro)
+                               basic_machine=hppa1.1-hp
+                               os=proelf
+                               ;;
+                       i386mach)
+                               basic_machine=i386-mach
+                               os=mach
+                               ;;
+                       vsta)
+                               basic_machine=i386-unknown
+                               os=vsta
+                               ;;
+                       isi68 | isi)
+                               basic_machine=m68k-isi
+                               os=sysv
+                               ;;
+                       m68knommu)
+                               basic_machine=m68k-unknown
+                               os=linux
+                               ;;
+                       magnum | m3230)
+                               basic_machine=mips-mips
+                               os=sysv
+                               ;;
+                       merlin)
+                               basic_machine=ns32k-utek
+                               os=sysv
+                               ;;
+                       mingw64)
+                               basic_machine=x86_64-pc
+                               os=mingw64
+                               ;;
+                       mingw32)
+                               basic_machine=i686-pc
+                               os=mingw32
+                               ;;
+                       mingw32ce)
+                               basic_machine=arm-unknown
+                               os=mingw32ce
+                               ;;
+                       monitor)
+                               basic_machine=m68k-rom68k
+                               os=coff
+                               ;;
+                       morphos)
+                               basic_machine=powerpc-unknown
+                               os=morphos
+                               ;;
+                       moxiebox)
+                               basic_machine=moxie-unknown
+                               os=moxiebox
+                               ;;
+                       msdos)
+                               basic_machine=i386-pc
+                               os=msdos
+                               ;;
+                       msys)
+                               basic_machine=i686-pc
+                               os=msys
+                               ;;
+                       mvs)
+                               basic_machine=i370-ibm
+                               os=mvs
+                               ;;
+                       nacl)
+                               basic_machine=le32-unknown
+                               os=nacl
+                               ;;
+                       ncr3000)
+                               basic_machine=i486-ncr
+                               os=sysv4
+                               ;;
+                       netbsd386)
+                               basic_machine=i386-unknown
+                               os=netbsd
+                               ;;
+                       netwinder)
+                               basic_machine=armv4l-rebel
+                               os=linux
+                               ;;
+                       news | news700 | news800 | news900)
+                               basic_machine=m68k-sony
+                               os=newsos
+                               ;;
+                       news1000)
+                               basic_machine=m68030-sony
+                               os=newsos
+                               ;;
+                       necv70)
+                               basic_machine=v70-nec
+                               os=sysv
+                               ;;
+                       nh3000)
+                               basic_machine=m68k-harris
+                               os=cxux
+                               ;;
+                       nh[45]000)
+                               basic_machine=m88k-harris
+                               os=cxux
+                               ;;
+                       nindy960)
+                               basic_machine=i960-intel
+                               os=nindy
+                               ;;
+                       mon960)
+                               basic_machine=i960-intel
+                               os=mon960
+                               ;;
+                       nonstopux)
+                               basic_machine=mips-compaq
+                               os=nonstopux
+                               ;;
+                       os400)
+                               basic_machine=powerpc-ibm
+                               os=os400
+                               ;;
+                       OSE68000 | ose68000)
+                               basic_machine=m68000-ericsson
+                               os=ose
+                               ;;
+                       os68k)
+                               basic_machine=m68k-none
+                               os=os68k
+                               ;;
+                       paragon)
+                               basic_machine=i860-intel
+                               os=osf
+                               ;;
+                       parisc)
+                               basic_machine=hppa-unknown
+                               os=linux
+                               ;;
+                       pw32)
+                               basic_machine=i586-unknown
+                               os=pw32
+                               ;;
+                       rdos | rdos64)
+                               basic_machine=x86_64-pc
+                               os=rdos
+                               ;;
+                       rdos32)
+                               basic_machine=i386-pc
+                               os=rdos
+                               ;;
+                       rom68k)
+                               basic_machine=m68k-rom68k
+                               os=coff
+                               ;;
+                       sa29200)
+                               basic_machine=a29k-amd
+                               os=udi
+                               ;;
+                       sei)
+                               basic_machine=mips-sei
+                               os=seiux
+                               ;;
+                       sps7)
+                               basic_machine=m68k-bull
+                               os=sysv2
+                               ;;
+                       stratus)
+                               basic_machine=i860-stratus
+                               os=sysv4
+                               ;;
+                       sun2os3)
+                               basic_machine=m68000-sun
+                               os=sunos3
+                               ;;
+                       sun2os4)
+                               basic_machine=m68000-sun
+                               os=sunos4
+                               ;;
+                       sun3os3)
+                               basic_machine=m68k-sun
+                               os=sunos3
+                               ;;
+                       sun3os4)
+                               basic_machine=m68k-sun
+                               os=sunos4
+                               ;;
+                       sun4os3)
+                               basic_machine=sparc-sun
+                               os=sunos3
+                               ;;
+                       sun4os4)
+                               basic_machine=sparc-sun
+                               os=sunos4
+                               ;;
+                       sun4sol2)
+                               basic_machine=sparc-sun
+                               os=solaris2
+                               ;;
+                       sv1)
+                               basic_machine=sv1-cray
+                               os=unicos
+                               ;;
+                       symmetry)
+                               basic_machine=i386-sequent
+                               os=dynix
+                               ;;
+                       t3e)
+                               basic_machine=alphaev5-cray
+                               os=unicos
+                               ;;
+                       t90)
+                               basic_machine=t90-cray
+                               os=unicos
+                               ;;
+                       toad1)
+                               basic_machine=pdp10-xkl
+                               os=tops20
+                               ;;
+                       tpf)
+                               basic_machine=s390x-ibm
+                               os=tpf
+                               ;;
+                       udi29k)
+                               basic_machine=a29k-amd
+                               os=udi
+                               ;;
+                       ultra3)
+                               basic_machine=a29k-nyu
+                               os=sym1
+                               ;;
+                       v810 | necv810)
+                               basic_machine=v810-nec
+                               os=none
+                               ;;
+                       vaxv)
+                               basic_machine=vax-dec
+                               os=sysv
+                               ;;
+                       vms)
+                               basic_machine=vax-dec
+                               os=vms
+                               ;;
+                       vxworks960)
+                               basic_machine=i960-wrs
+                               os=vxworks
+                               ;;
+                       vxworks68)
+                               basic_machine=m68k-wrs
+                               os=vxworks
+                               ;;
+                       vxworks29k)
+                               basic_machine=a29k-wrs
+                               os=vxworks
+                               ;;
+                       xbox)
+                               basic_machine=i686-pc
+                               os=mingw32
+                               ;;
+                       ymp)
+                               basic_machine=ymp-cray
+                               os=unicos
+                               ;;
+                       *)
+                               basic_machine=$1
+                               os=
+                               ;;
+               esac
                ;;
 esac
 
@@ -259,21 +572,25 @@ 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] | armv6m | armv[78][arm] \
+       | avr | avr32 \
+       | ba \
+       | be32 | be64 \
        | bfin \
-       | c4x | clipper \
+       | c4x | c8051 | clipper | csky \
        | d10v | d30v | dlx | dsp16xx \
-       | epiphany \
-       | fido | fr30 | frv \
+       | e2k | epiphany \
+       | fido | fr30 | frv | ft32 \
        | h8300 | h8500 | hppa | hppa1.[01] | hppa2.0 | hppa2.0[nw] | hppa64 \
        | hexagon \
-       | i370 | i860 | i960 | ia64 \
+       | i370 | i860 | i960 | ia16 | 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,26 +604,31 @@ 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 \
+       | nfp \
+       | nios | nios2 | nios2eb | nios2el \
        | ns16k | ns32k \
-       | open8 \
-       | or32 \
-       | pdp10 | pdp11 | pj | pjl \
+       | open8 | or1k | or1knd | or32 \
+       | pdp10 | pj | pjl \
        | powerpc | powerpc64 | powerpc64le | powerpcle \
+       | pru \
        | pyramid \
+       | riscv | 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 \
+       | sh | sh[1234] | sh[24]a | sh[24]aeb | sh[23]e | sh[234]eb | sheb | shbe | shle | sh[1234]le | sh3ele \
        | sh64 | sh64le \
        | sparc | sparc64 | sparc64b | sparc64v | sparc86x | sparclet | sparclite \
        | sparcv8 | sparcv9 | sparcv9b | sparcv9v \
@@ -314,7 +636,8 @@ case $basic_machine in
        | tahoe | tic4x | tic54x | tic55x | tic6x | tic80 | tron \
        | ubicom32 \
        | v850 | v850e | v850e1 | v850e2 | v850es | v850e2v3 \
-       | we32k \
+       | visium \
+       | wasm32 \
        | x86 | xc16x | xstormy16 | xtensa \
        | z8k | z80)
                basic_machine=$basic_machine-unknown
@@ -328,22 +651,28 @@ 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
+               os=${os:-none}
+               ;;
+       m88110 | m680[12346]0 | m683?2 | m68360 | m5200 | v70 | w65)
                ;;
-       m88110 | m680[12346]0 | m683?2 | m68360 | m5200 | v70 | w65 | z8k)
+       m9s12z | m68hcs12z | hcs12z | s12z)
+               basic_machine=s12z-unknown
+               os=${os:-none}
                ;;
        ms1)
                basic_machine=mt-unknown
                ;;
-
        strongarm | thumb | xscale)
                basic_machine=arm-unknown
                ;;
        xgate)
                basic_machine=$basic_machine-unknown
-               os=-none
+               os=${os:-none}
                ;;
        xscaleeb)
                basic_machine=armeb-unknown
@@ -359,37 +688,35 @@ case $basic_machine in
        i*86 | x86_64)
          basic_machine=$basic_machine-pc
          ;;
-       # Object if more than one company name word.
-       *-*-*)
-               echo Invalid configuration \`$1\': machine \`$basic_machine\' not recognized 1>&2
-               exit 1
-               ;;
        # Recognize the basic CPU types with company name.
        580-* \
        | a29k-* \
        | 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-* \
+       | ba-* \
        | be32-* | be64-* \
        | bfin-* | bs2000-* \
        | c[123]* | c30-* | [cjt]90-* | c4x-* \
-       | clipper-* | craynv-* | cydra-* \
+       | c8051-* | clipper-* | craynv-* | csky-* | cydra-* \
        | d10v-* | d30v-* | dlx-* \
-       | elxsi-* \
+       | e2k-* | elxsi-* \
        | f30[01]-* | f700-* | fido-* | fr30-* | frv-* | fx80-* \
        | h8300-* | h8500-* \
        | hppa-* | hppa1.[01]-* | hppa2.0-* | hppa2.0[nw]-* | hppa64-* \
        | hexagon-* \
-       | i*86-* | i860-* | i960-* | ia64-* \
+       | i*86-* | i860-* | i960-* | ia16-* | 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,28 +730,35 @@ 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-* \
+       | nfp-* \
+       | nios-* | nios2-* | nios2eb-* | nios2el-* \
        | none-* | np1-* | ns16k-* | ns32k-* \
        | open8-* \
+       | or1k*-* \
        | orion-* \
        | pdp10-* | pdp11-* | pj-* | pjl-* | pn-* | power-* \
        | powerpc-* | powerpc64-* | powerpc64le-* | powerpcle-* \
+       | pru-* \
        | pyramid-* \
+       | riscv-* | riscv32-* | riscv64-* \
        | rl78-* | romp-* | rs6000-* | rx-* \
        | sh-* | sh[1234]-* | sh[24]a-* | sh[24]aeb-* | sh[23]e-* | sh[34]eb-* | sheb-* | shbe-* \
        | shle-* | sh[1234]le-* | sh3ele-* | sh64-* | sh64le-* \
        | sparc-* | sparc64-* | sparc64b-* | sparc64v-* | sparc86x-* | sparclet-* \
        | sparclite-* \
-       | sparcv8-* | sparcv9-* | sparcv9b-* | sparcv9v-* | sv1-* | sx?-* \
+       | sparcv8-* | sparcv9-* | sparcv9b-* | sparcv9v-* | sv1-* | sx*-* \
        | tahoe-* \
        | tic30-* | tic4x-* | tic54x-* | tic55x-* | tic6x-* | tic80-* \
        | tile*-* \
@@ -432,6 +766,8 @@ case $basic_machine in
        | ubicom32-* \
        | v850-* | v850e-* | v850e1-* | v850es-* | v850e2-* | v850e2v3-* \
        | vax-* \
+       | visium-* \
+       | wasm32-* \
        | we32k-* \
        | x86-* | x86_64-* | xc16x-* | xps100-* \
        | xstormy16-* | xtensa*-* \
@@ -444,138 +780,77 @@ case $basic_machine in
                ;;
        # Recognize the various machine names and aliases which stand
        # for a CPU type and a company and sometimes even an OS.
-       386bsd)
-               basic_machine=i386-unknown
-               os=-bsd
-               ;;
        3b1 | 7300 | 7300-att | att-7300 | pc7300 | safari | unixpc)
                basic_machine=m68000-att
                ;;
        3b*)
                basic_machine=we32k-att
                ;;
-       a29khif)
-               basic_machine=a29k-amd
-               os=-udi
-               ;;
        abacus)
                basic_machine=abacus-unknown
                ;;
-       adobe68k)
-               basic_machine=m68010-adobe
-               os=-scout
-               ;;
        alliant | fx80)
                basic_machine=fx80-alliant
                ;;
        altos | altos3068)
                basic_machine=m68k-altos
                ;;
-       am29k)
-               basic_machine=a29k-none
-               os=-bsd
-               ;;
        amd64)
                basic_machine=x86_64-pc
                ;;
        amd64-*)
-               basic_machine=x86_64-`echo $basic_machine | sed 's/^[^-]*-//'`
-               ;;
-       amdahl)
-               basic_machine=580-amdahl
-               os=-sysv
+               basic_machine=x86_64-`echo "$basic_machine" | sed 's/^[^-]*-//'`
                ;;
        amiga | amiga-*)
                basic_machine=m68k-unknown
                ;;
-       amigaos | amigados)
-               basic_machine=m68k-unknown
-               os=-amigaos
-               ;;
-       amigaunix | amix)
-               basic_machine=m68k-unknown
-               os=-sysv4
-               ;;
-       apollo68)
-               basic_machine=m68k-apollo
-               os=-sysv
-               ;;
-       apollo68bsd)
-               basic_machine=m68k-apollo
-               os=-bsd
-               ;;
-       aros)
-               basic_machine=i386-pc
-               os=-aros
-               ;;
-       aux)
-               basic_machine=m68k-apple
-               os=-aux
-               ;;
-       balance)
-               basic_machine=ns32k-sequent
-               os=-dynix
-               ;;
-       blackfin)
-               basic_machine=bfin-unknown
-               os=-linux
+       asmjs)
+               basic_machine=asmjs-unknown
                ;;
        blackfin-*)
-               basic_machine=bfin-`echo $basic_machine | sed 's/^[^-]*-//'`
-               os=-linux
+               basic_machine=bfin-`echo "$basic_machine" | sed 's/^[^-]*-//'`
+               os=linux
                ;;
        bluegene*)
                basic_machine=powerpc-ibm
-               os=-cnk
+               os=cnk
                ;;
        c54x-*)
-               basic_machine=tic54x-`echo $basic_machine | sed 's/^[^-]*-//'`
+               basic_machine=tic54x-`echo "$basic_machine" | sed 's/^[^-]*-//'`
                ;;
        c55x-*)
-               basic_machine=tic55x-`echo $basic_machine | sed 's/^[^-]*-//'`
+               basic_machine=tic55x-`echo "$basic_machine" | sed 's/^[^-]*-//'`
                ;;
        c6x-*)
-               basic_machine=tic6x-`echo $basic_machine | sed 's/^[^-]*-//'`
+               basic_machine=tic6x-`echo "$basic_machine" | sed 's/^[^-]*-//'`
                ;;
        c90)
                basic_machine=c90-cray
-               os=-unicos
-               ;;
-       cegcc)
-               basic_machine=arm-unknown
-               os=-cegcc
+               os=${os:-unicos}
                ;;
        convex-c1)
                basic_machine=c1-convex
-               os=-bsd
+               os=bsd
                ;;
        convex-c2)
                basic_machine=c2-convex
-               os=-bsd
+               os=bsd
                ;;
        convex-c32)
                basic_machine=c32-convex
-               os=-bsd
+               os=bsd
                ;;
        convex-c34)
                basic_machine=c34-convex
-               os=-bsd
+               os=bsd
                ;;
        convex-c38)
                basic_machine=c38-convex
-               os=-bsd
-               ;;
-       cray | j90)
-               basic_machine=j90-cray
-               os=-unicos
-               ;;
-       craynv)
-               basic_machine=craynv-cray
-               os=-unicosmp
+               os=bsd
                ;;
        cr16 | cr16-*)
                basic_machine=cr16-unknown
-               os=-elf
+               os=${os:-elf}
                ;;
        crds | unos)
                basic_machine=m68k-crds
@@ -588,7 +863,7 @@ case $basic_machine in
                ;;
        crx)
                basic_machine=crx-unknown
-               os=-elf
+               os=${os:-elf}
                ;;
        da30 | da30-*)
                basic_machine=m68k-da30
@@ -598,50 +873,38 @@ case $basic_machine in
                ;;
        decsystem10* | dec10*)
                basic_machine=pdp10-dec
-               os=-tops10
+               os=tops10
                ;;
        decsystem20* | dec20*)
                basic_machine=pdp10-dec
-               os=-tops20
+               os=tops20
                ;;
        delta | 3300 | motorola-3300 | motorola-delta \
              | 3300-motorola | delta-motorola)
                basic_machine=m68k-motorola
                ;;
-       delta88)
-               basic_machine=m88k-motorola
-               os=-sysv3
-               ;;
-       dicos)
-               basic_machine=i686-pc
-               os=-dicos
-               ;;
-       djgpp)
-               basic_machine=i586-pc
-               os=-msdosdjgpp
-               ;;
        dpx20 | dpx20-*)
                basic_machine=rs6000-bull
-               os=-bosx
+               os=${os:-bosx}
                ;;
-       dpx2* | dpx2*-bull)
+       dpx2*)
                basic_machine=m68k-bull
-               os=-sysv3
+               os=sysv3
                ;;
-       ebmon29k)
-               basic_machine=a29k-amd
-               os=-ebmon
+       e500v[12])
+               basic_machine=powerpc-unknown
+               os=$os"spe"
                ;;
-       elxsi)
-               basic_machine=elxsi-elxsi
-               os=-bsd
+       e500v[12]-*)
+               basic_machine=powerpc-`echo "$basic_machine" | sed 's/^[^-]*-//'`
+               os=$os"spe"
                ;;
        encore | umax | mmax)
                basic_machine=ns32k-encore
                ;;
-       es1800 | OSE68k | ose68k | ose | OSE)
-               basic_machine=m68k-ericsson
-               os=-ose
+       elxsi)
+               basic_machine=elxsi-elxsi
+               os=${os:-bsd}
                ;;
        fx2800)
                basic_machine=i860-alliant
@@ -649,45 +912,13 @@ case $basic_machine in
        genix)
                basic_machine=ns32k-ns
                ;;
-       gmicro)
-               basic_machine=tron-gmicro
-               os=-sysv
-               ;;
-       go32)
-               basic_machine=i386-pc
-               os=-go32
-               ;;
        h3050r* | hiux*)
                basic_machine=hppa1.1-hitachi
-               os=-hiuxwe2
-               ;;
-       h8300hms)
-               basic_machine=h8300-hitachi
-               os=-hms
-               ;;
-       h8300xray)
-               basic_machine=h8300-hitachi
-               os=-xray
-               ;;
-       h8500hms)
-               basic_machine=h8500-hitachi
-               os=-hms
-               ;;
-       harris)
-               basic_machine=m88k-harris
-               os=-sysv3
+               os=hiuxwe2
                ;;
        hp300-*)
                basic_machine=m68k-hp
                ;;
-       hp300bsd)
-               basic_machine=m68k-hp
-               os=-bsd
-               ;;
-       hp300hpux)
-               basic_machine=m68k-hp
-               os=-hpux
-               ;;
        hp3k9[0-9][0-9] | hp9[0-9][0-9])
                basic_machine=hppa1.0-hp
                ;;
@@ -717,189 +948,82 @@ case $basic_machine in
        hp9k8[0-9][0-9] | hp8[0-9][0-9])
                basic_machine=hppa1.0-hp
                ;;
-       hppa-next)
-               os=-nextstep3
-               ;;
-       hppaosf)
-               basic_machine=hppa1.1-hp
-               os=-osf
-               ;;
-       hppro)
-               basic_machine=hppa1.1-hp
-               os=-proelf
-               ;;
        i370-ibm* | ibm*)
                basic_machine=i370-ibm
                ;;
        i*86v32)
-               basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'`
-               os=-sysv32
+               basic_machine=`echo "$1" | sed -e 's/86.*/86-pc/'`
+               os=sysv32
                ;;
        i*86v4*)
-               basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'`
-               os=-sysv4
+               basic_machine=`echo "$1" | sed -e 's/86.*/86-pc/'`
+               os=sysv4
                ;;
        i*86v)
-               basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'`
-               os=-sysv
+               basic_machine=`echo "$1" | sed -e 's/86.*/86-pc/'`
+               os=sysv
                ;;
        i*86sol2)
-               basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'`
-               os=-solaris2
+               basic_machine=`echo "$1" | sed -e 's/86.*/86-pc/'`
+               os=solaris2
                ;;
-       i386mach)
-               basic_machine=i386-mach
-               os=-mach
-               ;;
-       i386-vsta | vsta)
-               basic_machine=i386-unknown
-               os=-vsta
+       j90 | j90-cray)
+               basic_machine=j90-cray
+               os=${os:-unicos}
                ;;
        iris | iris4d)
                basic_machine=mips-sgi
                case $os in
-                   -irix*)
+                   irix*)
                        ;;
                    *)
-                       os=-irix4
+                       os=irix4
                        ;;
                esac
                ;;
-       isi68 | isi)
-               basic_machine=m68k-isi
-               os=-sysv
-               ;;
-       m68knommu)
-               basic_machine=m68k-unknown
-               os=-linux
+       leon-*|leon[3-9]-*)
+               basic_machine=sparc-`echo "$basic_machine" | sed 's/-.*//'`
                ;;
        m68knommu-*)
-               basic_machine=m68k-`echo $basic_machine | sed 's/^[^-]*-//'`
-               os=-linux
-               ;;
-       m88k-omron*)
-               basic_machine=m88k-omron
-               ;;
-       magnum | m3230)
-               basic_machine=mips-mips
-               os=-sysv
-               ;;
-       merlin)
-               basic_machine=ns32k-utek
-               os=-sysv
+               basic_machine=m68k-`echo "$basic_machine" | sed 's/^[^-]*-//'`
+               os=linux
                ;;
-       microblaze)
+       microblaze*)
                basic_machine=microblaze-xilinx
                ;;
-       mingw32)
-               basic_machine=i386-pc
-               os=-mingw32
-               ;;
-       mingw32ce)
-               basic_machine=arm-unknown
-               os=-mingw32ce
-               ;;
        miniframe)
                basic_machine=m68000-convergent
                ;;
-       *mint | -mint[0-9]* | *MiNT | *MiNT[0-9]*)
+       *mint | mint[0-9]* | *MiNT | *MiNT[0-9]*)
                basic_machine=m68k-atari
-               os=-mint
+               os=mint
                ;;
        mips3*-*)
-               basic_machine=`echo $basic_machine | sed -e 's/mips3/mips64/'`
+               basic_machine=`echo "$basic_machine" | sed -e 's/mips3/mips64/'`
                ;;
        mips3*)
-               basic_machine=`echo $basic_machine | sed -e 's/mips3/mips64/'`-unknown
-               ;;
-       monitor)
-               basic_machine=m68k-rom68k
-               os=-coff
-               ;;
-       morphos)
-               basic_machine=powerpc-unknown
-               os=-morphos
-               ;;
-       msdos)
-               basic_machine=i386-pc
-               os=-msdos
+               basic_machine=`echo "$basic_machine" | sed -e 's/mips3/mips64/'`-unknown
                ;;
        ms1-*)
-               basic_machine=`echo $basic_machine | sed -e 's/ms1-/mt-/'`
-               ;;
-       msys)
-               basic_machine=i386-pc
-               os=-msys
-               ;;
-       mvs)
-               basic_machine=i370-ibm
-               os=-mvs
-               ;;
-       nacl)
-               basic_machine=le32-unknown
-               os=-nacl
-               ;;
-       ncr3000)
-               basic_machine=i486-ncr
-               os=-sysv4
-               ;;
-       netbsd386)
-               basic_machine=i386-unknown
-               os=-netbsd
-               ;;
-       netwinder)
-               basic_machine=armv4l-rebel
-               os=-linux
-               ;;
-       news | news700 | news800 | news900)
-               basic_machine=m68k-sony
-               os=-newsos
-               ;;
-       news1000)
-               basic_machine=m68030-sony
-               os=-newsos
+               basic_machine=`echo "$basic_machine" | sed -e 's/ms1-/mt-/'`
                ;;
        news-3600 | risc-news)
                basic_machine=mips-sony
-               os=-newsos
-               ;;
-       necv70)
-               basic_machine=v70-nec
-               os=-sysv
+               os=newsos
                ;;
-       next | m*-next )
+       next | m*-next)
                basic_machine=m68k-next
                case $os in
-                   -nextstep* )
+                   nextstep* )
                        ;;
-                   -ns2*)
-                     os=-nextstep2
+                   ns2*)
+                     os=nextstep2
                        ;;
                    *)
-                     os=-nextstep3
+                     os=nextstep3
                        ;;
                esac
                ;;
-       nh3000)
-               basic_machine=m68k-harris
-               os=-cxux
-               ;;
-       nh[45]000)
-               basic_machine=m88k-harris
-               os=-cxux
-               ;;
-       nindy960)
-               basic_machine=i960-intel
-               os=-nindy
-               ;;
-       mon960)
-               basic_machine=i960-intel
-               os=-mon960
-               ;;
-       nonstopux)
-               basic_machine=mips-compaq
-               os=-nonstopux
-               ;;
        np1)
                basic_machine=np1-gould
                ;;
@@ -912,40 +1036,26 @@ case $basic_machine in
        nsr-tandem)
                basic_machine=nsr-tandem
                ;;
+       nsv-tandem)
+               basic_machine=nsv-tandem
+               ;;
+       nsx-tandem)
+               basic_machine=nsx-tandem
+               ;;
        op50n-* | op60c-*)
                basic_machine=hppa1.1-oki
-               os=-proelf
+               os=proelf
                ;;
        openrisc | openrisc-*)
                basic_machine=or32-unknown
                ;;
-       os400)
-               basic_machine=powerpc-ibm
-               os=-os400
-               ;;
-       OSE68000 | ose68000)
-               basic_machine=m68000-ericsson
-               os=-ose
-               ;;
-       os68k)
-               basic_machine=m68k-none
-               os=-os68k
-               ;;
        pa-hitachi)
                basic_machine=hppa1.1-hitachi
-               os=-hiuxwe2
-               ;;
-       paragon)
-               basic_machine=i860-intel
-               os=-osf
-               ;;
-       parisc)
-               basic_machine=hppa-unknown
-               os=-linux
+               os=hiuxwe2
                ;;
        parisc-*)
-               basic_machine=hppa-`echo $basic_machine | sed 's/^[^-]*-//'`
-               os=-linux
+               basic_machine=hppa-`echo "$basic_machine" | sed 's/^[^-]*-//'`
+               os=linux
                ;;
        pbd)
                basic_machine=sparc-tti
@@ -960,7 +1070,7 @@ case $basic_machine in
                basic_machine=i386-pc
                ;;
        pc98-*)
-               basic_machine=i386-`echo $basic_machine | sed 's/^[^-]*-//'`
+               basic_machine=i386-`echo "$basic_machine" | sed 's/^[^-]*-//'`
                ;;
        pentium | p5 | k5 | k6 | nexgen | viac3)
                basic_machine=i586-pc
@@ -975,16 +1085,16 @@ case $basic_machine in
                basic_machine=i786-pc
                ;;
        pentium-* | p5-* | k5-* | k6-* | nexgen-* | viac3-*)
-               basic_machine=i586-`echo $basic_machine | sed 's/^[^-]*-//'`
+               basic_machine=i586-`echo "$basic_machine" | sed 's/^[^-]*-//'`
                ;;
        pentiumpro-* | p6-* | 6x86-* | athlon-*)
-               basic_machine=i686-`echo $basic_machine | sed 's/^[^-]*-//'`
+               basic_machine=i686-`echo "$basic_machine" | sed 's/^[^-]*-//'`
                ;;
        pentiumii-* | pentium2-* | pentiumiii-* | pentium3-*)
-               basic_machine=i686-`echo $basic_machine | sed 's/^[^-]*-//'`
+               basic_machine=i686-`echo "$basic_machine" | sed 's/^[^-]*-//'`
                ;;
        pentium4-*)
-               basic_machine=i786-`echo $basic_machine | sed 's/^[^-]*-//'`
+               basic_machine=i786-`echo "$basic_machine" | sed 's/^[^-]*-//'`
                ;;
        pn)
                basic_machine=pn-gould
@@ -994,39 +1104,27 @@ case $basic_machine in
        ppc | ppcbe)    basic_machine=powerpc-unknown
                ;;
        ppc-* | ppcbe-*)
-               basic_machine=powerpc-`echo $basic_machine | sed 's/^[^-]*-//'`
+               basic_machine=powerpc-`echo "$basic_machine" | sed 's/^[^-]*-//'`
                ;;
-       ppcle | powerpclittle | ppc-le | powerpc-little)
+       ppcle | powerpclittle)
                basic_machine=powerpcle-unknown
                ;;
        ppcle-* | powerpclittle-*)
-               basic_machine=powerpcle-`echo $basic_machine | sed 's/^[^-]*-//'`
+               basic_machine=powerpcle-`echo "$basic_machine" | sed 's/^[^-]*-//'`
                ;;
        ppc64)  basic_machine=powerpc64-unknown
                ;;
-       ppc64-*) basic_machine=powerpc64-`echo $basic_machine | sed 's/^[^-]*-//'`
+       ppc64-*) basic_machine=powerpc64-`echo "$basic_machine" | sed 's/^[^-]*-//'`
                ;;
-       ppc64le | powerpc64little | ppc64-le | powerpc64-little)
+       ppc64le | powerpc64little)
                basic_machine=powerpc64le-unknown
                ;;
        ppc64le-* | powerpc64little-*)
-               basic_machine=powerpc64le-`echo $basic_machine | sed 's/^[^-]*-//'`
+               basic_machine=powerpc64le-`echo "$basic_machine" | sed 's/^[^-]*-//'`
                ;;
        ps2)
                basic_machine=i386-ibm
                ;;
-       pw32)
-               basic_machine=i586-unknown
-               os=-pw32
-               ;;
-       rdos)
-               basic_machine=i386-pc
-               os=-rdos
-               ;;
-       rom68k)
-               basic_machine=m68k-rom68k
-               os=-coff
-               ;;
        rm[46]00)
                basic_machine=mips-siemens
                ;;
@@ -1039,10 +1137,6 @@ case $basic_machine in
        s390x | s390x-*)
                basic_machine=s390x-ibm
                ;;
-       sa29200)
-               basic_machine=a29k-amd
-               os=-udi
-               ;;
        sb1)
                basic_machine=mipsisa64sb1-unknown
                ;;
@@ -1051,32 +1145,17 @@ case $basic_machine in
                ;;
        sde)
                basic_machine=mipsisa32-sde
-               os=-elf
-               ;;
-       sei)
-               basic_machine=mips-sei
-               os=-seiux
+               os=${os:-elf}
                ;;
        sequent)
                basic_machine=i386-sequent
                ;;
-       sh)
-               basic_machine=sh-hitachi
-               os=-hms
-               ;;
        sh5el)
                basic_machine=sh5le-unknown
                ;;
-       sh64)
-               basic_machine=sh64-unknown
-               ;;
-       sparclite-wrs | simso-wrs)
+       simso-wrs)
                basic_machine=sparclite-wrs
-               os=-vxworks
-               ;;
-       sps7)
-               basic_machine=m68k-bull
-               os=-sysv2
+               os=vxworks
                ;;
        spur)
                basic_machine=spur-unknown
@@ -1084,44 +1163,12 @@ case $basic_machine in
        st2000)
                basic_machine=m68k-tandem
                ;;
-       stratus)
-               basic_machine=i860-stratus
-               os=-sysv4
-               ;;
        strongarm-* | thumb-*)
-               basic_machine=arm-`echo $basic_machine | sed 's/^[^-]*-//'`
+               basic_machine=arm-`echo "$basic_machine" | sed 's/^[^-]*-//'`
                ;;
        sun2)
                basic_machine=m68000-sun
                ;;
-       sun2os3)
-               basic_machine=m68000-sun
-               os=-sunos3
-               ;;
-       sun2os4)
-               basic_machine=m68000-sun
-               os=-sunos4
-               ;;
-       sun3os3)
-               basic_machine=m68k-sun
-               os=-sunos3
-               ;;
-       sun3os4)
-               basic_machine=m68k-sun
-               os=-sunos4
-               ;;
-       sun4os3)
-               basic_machine=sparc-sun
-               os=-sunos3
-               ;;
-       sun4os4)
-               basic_machine=sparc-sun
-               os=-sunos4
-               ;;
-       sun4sol2)
-               basic_machine=sparc-sun
-               os=-solaris2
-               ;;
        sun3 | sun3-*)
                basic_machine=m68k-sun
                ;;
@@ -1131,25 +1178,9 @@ case $basic_machine in
        sun386 | sun386i | roadrunner)
                basic_machine=i386-sun
                ;;
-       sv1)
-               basic_machine=sv1-cray
-               os=-unicos
-               ;;
-       symmetry)
-               basic_machine=i386-sequent
-               os=-dynix
-               ;;
-       t3e)
-               basic_machine=alphaev5-cray
-               os=-unicos
-               ;;
-       t90)
-               basic_machine=t90-cray
-               os=-unicos
-               ;;
        tile*)
                basic_machine=$basic_machine-unknown
-               os=-linux-gnu
+               os=linux-gnu
                ;;
        tx39)
                basic_machine=mipstx39-unknown
@@ -1157,85 +1188,32 @@ case $basic_machine in
        tx39el)
                basic_machine=mipstx39el-unknown
                ;;
-       toad1)
-               basic_machine=pdp10-xkl
-               os=-tops20
-               ;;
        tower | tower-32)
                basic_machine=m68k-ncr
                ;;
-       tpf)
-               basic_machine=s390x-ibm
-               os=-tpf
-               ;;
-       udi29k)
-               basic_machine=a29k-amd
-               os=-udi
-               ;;
-       ultra3)
-               basic_machine=a29k-nyu
-               os=-sym1
-               ;;
-       v810 | necv810)
-               basic_machine=v810-nec
-               os=-none
-               ;;
-       vaxv)
-               basic_machine=vax-dec
-               os=-sysv
-               ;;
-       vms)
-               basic_machine=vax-dec
-               os=-vms
-               ;;
        vpp*|vx|vx-*)
                basic_machine=f301-fujitsu
                ;;
-       vxworks960)
-               basic_machine=i960-wrs
-               os=-vxworks
-               ;;
-       vxworks68)
-               basic_machine=m68k-wrs
-               os=-vxworks
-               ;;
-       vxworks29k)
-               basic_machine=a29k-wrs
-               os=-vxworks
-               ;;
        w65*)
                basic_machine=w65-wdc
-               os=-none
+               os=none
                ;;
        w89k-*)
                basic_machine=hppa1.1-winbond
-               os=-proelf
+               os=proelf
                ;;
-       xbox)
-               basic_machine=i686-pc
-               os=-mingw32
+       x64)
+               basic_machine=x86_64-pc
                ;;
        xps | xps100)
                basic_machine=xps100-honeywell
                ;;
        xscale-* | xscalee[bl]-*)
-               basic_machine=`echo $basic_machine | sed 's/^xscale/arm/'`
-               ;;
-       ymp)
-               basic_machine=ymp-cray
-               os=-unicos
-               ;;
-       z8k-*-coff)
-               basic_machine=z8k-unknown
-               os=-sim
-               ;;
-       z80-*-coff)
-               basic_machine=z80-unknown
-               os=-sim
+               basic_machine=`echo "$basic_machine" | sed 's/^xscale/arm/'`
                ;;
        none)
                basic_machine=none-none
-               os=-none
+               os=${os:-none}
                ;;
 
 # Here we handle the default manufacturer of certain CPU types.  It is in
@@ -1261,10 +1239,6 @@ case $basic_machine in
        vax)
                basic_machine=vax-dec
                ;;
-       pdp10)
-               # there are many clones, so DEC is not a safe bet
-               basic_machine=pdp10-unknown
-               ;;
        pdp11)
                basic_machine=pdp11-dec
                ;;
@@ -1274,9 +1248,6 @@ case $basic_machine in
        sh[1234] | sh[24]a | sh[24]aeb | sh[34]eb | sh[1234]le | sh[23]ele)
                basic_machine=sh-unknown
                ;;
-       sparc | sparcv8 | sparcv9 | sparcv9b | sparcv9v)
-               basic_machine=sparc-sun
-               ;;
        cydra)
                basic_machine=cydra-cydrome
                ;;
@@ -1296,7 +1267,7 @@ case $basic_machine in
                # Make sure to match an already-canonicalized machine name.
                ;;
        *)
-               echo Invalid configuration \`$1\': machine \`$basic_machine\' not recognized 1>&2
+               echo Invalid configuration \`"$1"\': machine \`"$basic_machine"\' not recognized 1>&2
                exit 1
                ;;
 esac
@@ -1304,10 +1275,10 @@ esac
 # Here we canonicalize certain aliases for manufacturers.
 case $basic_machine in
        *-digital*)
-               basic_machine=`echo $basic_machine | sed 's/digital.*/dec/'`
+               basic_machine=`echo "$basic_machine" | sed 's/digital.*/dec/'`
                ;;
        *-commodore*)
-               basic_machine=`echo $basic_machine | sed 's/commodore.*/cbm/'`
+               basic_machine=`echo "$basic_machine" | sed 's/commodore.*/cbm/'`
                ;;
        *)
                ;;
@@ -1315,200 +1286,246 @@ esac
 
 # Decode manufacturer-specific aliases for certain operating systems.
 
-if [ x"$os" != x"" ]
+if [ x$os != x ]
 then
 case $os in
-       # First match some system type aliases
-       # that might get confused with valid system types.
-       # -solaris* is a basic system type, with this one exception.
-       -auroraux)
-               os=-auroraux
+       # First match some system type aliases that might get confused
+       # with valid system types.
+       # solaris* is a basic system type, with this one exception.
+       auroraux)
+               os=auroraux
                ;;
-       -solaris1 | -solaris1.*)
-               os=`echo $os | sed -e 's|solaris1|sunos4|'`
+       bluegene*)
+               os=cnk
                ;;
-       -solaris)
-               os=-solaris2
+       solaris1 | solaris1.*)
+               os=`echo $os | sed -e 's|solaris1|sunos4|'`
                ;;
-       -svr4*)
-               os=-sysv4
+       solaris)
+               os=solaris2
                ;;
-       -unixware*)
-               os=-sysv4.2uw
+       unixware*)
+               os=sysv4.2uw
                ;;
-       -gnu/linux*)
+       gnu/linux*)
                os=`echo $os | sed -e 's|gnu/linux|linux-gnu|'`
                ;;
-       # First accept the basic system types.
+       # es1800 is here to avoid being matched by es* (a different OS)
+       es1800*)
+               os=ose
+               ;;
+       # Some version numbers need modification
+       chorusos*)
+               os=chorusos
+               ;;
+       isc)
+               os=isc2.2
+               ;;
+       sco6)
+               os=sco5v6
+               ;;
+       sco5)
+               os=sco3.2v5
+               ;;
+       sco4)
+               os=sco3.2v4
+               ;;
+       sco3.2.[4-9]*)
+               os=`echo $os | sed -e 's/sco3.2./sco3.2v/'`
+               ;;
+       sco3.2v[4-9]* | sco5v6*)
+               # Don't forget version if it is 3.2v4 or newer.
+               ;;
+       scout)
+               # Don't match below
+               ;;
+       sco*)
+               os=sco3.2v2
+               ;;
+       psos*)
+               os=psos
+               ;;
+       # Now accept the basic system types.
        # The portable systems comes first.
-       # Each alternative MUST END IN A *, to match a version number.
-       # -sysv* is not here because it comes later, after sysvr4.
-       -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* \
-             | -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* \
-             | -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* \
-             | -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*)
+       # Each alternative MUST end in a * to match a version number.
+       # sysv* is not here because it comes later, after sysvr4.
+       gnu* | bsd* | mach* | minix* | genix* | ultrix* | irix* \
+            | *vms* | esix* | aix* | cnk* | sunos | sunos[34]*\
+            | hpux* | unos* | osf* | luna* | dgux* | auroraux* | solaris* \
+            | sym* | kopensolaris* | plan9* \
+            | amigaos* | amigados* | msdos* | newsos* | unicos* | aof* \
+            | aos* | aros* | cloudabi* | sortix* \
+            | nindy* | vxsim* | vxworks* | ebmon* | hms* | mvs* \
+            | clix* | riscos* | uniplus* | iris* | rtu* | xenix* \
+            | knetbsd* | mirbsd* | netbsd* \
+            | bitrig* | openbsd* | solidbsd* | libertybsd* \
+            | ekkobsd* | kfreebsd* | freebsd* | riscix* | lynxos* \
+            | bosx* | nextstep* | cxux* | aout* | elf* | oabi* \
+            | ptx* | coff* | ecoff* | winnt* | domain* | vsta* \
+            | udi* | eabi* | lites* | ieee* | go32* | aux* | hcos* \
+            | chorusrdb* | cegcc* | glidix* \
+            | cygwin* | msys* | pe* | moss* | proelf* | rtems* \
+            | midipix* | mingw32* | mingw64* | linux-gnu* | linux-android* \
+            | linux-newlib* | linux-musl* | linux-uclibc* \
+            | uxpv* | beos* | mpeix* | udk* | moxiebox* \
+            | interix* | uwin* | mks* | rhapsody* | darwin* \
+            | openstep* | oskit* | conix* | pw32* | nonstopux* \
+            | storm-chaos* | tops10* | tenex* | tops20* | its* \
+            | os2* | vos* | palmos* | uclinux* | nucleus* \
+            | morphos* | superux* | rtmk* | windiss* \
+            | powermax* | dnix* | nx6 | nx7 | sei* | dragonfly* \
+            | skyos* | haiku* | rdos* | toppers* | drops* | es* \
+            | onefs* | tirtos* | phoenix* | fuchsia* | redox* | bme* \
+            | midnightbsd*)
        # Remember, each alternative MUST END IN *, to match a version number.
                ;;
-       -qnx*)
+       qnx*)
                case $basic_machine in
                    x86-* | i*86-*)
                        ;;
                    *)
-                       os=-nto$os
+                       os=nto-$os
                        ;;
                esac
                ;;
-       -nto-qnx*)
+       hiux*)
+               os=hiuxwe2
                ;;
-       -nto*)
-               os=`echo $os | sed -e 's|nto|nto-qnx|'`
+       nto-qnx*)
                ;;
-       -sim | -es1800* | -hms* | -xray | -os68k* | -none* | -v88r* \
-             | -windows* | -osx | -abug | -netware* | -os9* | -beos* | -haiku* \
-             | -macos* | -mpw* | -magic* | -mmixware* | -mon960* | -lnews*)
+       nto*)
+               os=`echo $os | sed -e 's|nto|nto-qnx|'`
                ;;
-       -mac*)
-               os=`echo $os | sed -e 's|mac|macos|'`
+       sim | xray | os68k* | v88r* \
+           | windows* | osx | abug | netware* | os9* \
+           | macos* | mpw* | magic* | mmixware* | mon960* | lnews*)
                ;;
-       -linux-dietlibc)
-               os=-linux-dietlibc
+       linux-dietlibc)
+               os=linux-dietlibc
                ;;
-       -linux*)
+       linux*)
                os=`echo $os | sed -e 's|linux|linux-gnu|'`
                ;;
-       -sunos5*)
-               os=`echo $os | sed -e 's|sunos5|solaris2|'`
+       lynx*178)
+               os=lynxos178
                ;;
-       -sunos6*)
-               os=`echo $os | sed -e 's|sunos6|solaris3|'`
+       lynx*5)
+               os=lynxos5
                ;;
-       -opened*)
-               os=-openedition
+       lynx*)
+               os=lynxos
                ;;
-       -os400*)
-               os=-os400
+       mac*)
+               os=`echo "$os" | sed -e 's|mac|macos|'`
                ;;
-       -wince*)
-               os=-wince
+       opened*)
+               os=openedition
                ;;
-       -osfrose*)
-               os=-osfrose
+       os400*)
+               os=os400
                ;;
-       -osf*)
-               os=-osf
+       sunos5*)
+               os=`echo "$os" | sed -e 's|sunos5|solaris2|'`
                ;;
-       -utek*)
-               os=-bsd
+       sunos6*)
+               os=`echo "$os" | sed -e 's|sunos6|solaris3|'`
                ;;
-       -dynix*)
-               os=-bsd
+       wince*)
+               os=wince
                ;;
-       -acis*)
-               os=-aos
+       utek*)
+               os=bsd
                ;;
-       -atheos*)
-               os=-atheos
+       dynix*)
+               os=bsd
                ;;
-       -syllable*)
-               os=-syllable
+       acis*)
+               os=aos
                ;;
-       -386bsd)
-               os=-bsd
+       atheos*)
+               os=atheos
                ;;
-       -ctix* | -uts*)
-               os=-sysv
+       syllable*)
+               os=syllable
                ;;
-       -nova*)
-               os=-rtmk-nova
+       386bsd)
+               os=bsd
+               ;;
+       ctix* | uts*)
+               os=sysv
+               ;;
+       nova*)
+               os=rtmk-nova
                ;;
-       -ns2 )
-               os=-nextstep2
+       ns2)
+               os=nextstep2
                ;;
-       -nsk*)
-               os=-nsk
+       nsk*)
+               os=nsk
                ;;
        # Preserve the version number of sinix5.
-       -sinix5.*)
+       sinix5.*)
                os=`echo $os | sed -e 's|sinix|sysv|'`
                ;;
-       -sinix*)
-               os=-sysv4
+       sinix*)
+               os=sysv4
                ;;
-       -tpf*)
-               os=-tpf
+       tpf*)
+               os=tpf
                ;;
-       -triton*)
-               os=-sysv3
+       triton*)
+               os=sysv3
                ;;
-       -oss*)
-               os=-sysv3
+       oss*)
+               os=sysv3
                ;;
-       -svr4)
-               os=-sysv4
+       svr4*)
+               os=sysv4
                ;;
-       -svr3)
-               os=-sysv3
+       svr3)
+               os=sysv3
                ;;
-       -sysvr4)
-               os=-sysv4
+       sysvr4)
+               os=sysv4
                ;;
-       # This must come after -sysvr4.
-       -sysv*)
+       # This must come after sysvr4.
+       sysv*)
                ;;
-       -ose*)
-               os=-ose
+       ose*)
+               os=ose
                ;;
-       -es1800*)
-               os=-ose
+       *mint | mint[0-9]* | *MiNT | MiNT[0-9]*)
+               os=mint
                ;;
-       -xenix)
-               os=-xenix
+       zvmoe)
+               os=zvmoe
                ;;
-       -*mint | -mint[0-9]* | -*MiNT | -MiNT[0-9]*)
-               os=-mint
+       dicos*)
+               os=dicos
                ;;
-       -aros*)
-               os=-aros
-               ;;
-       -kaos*)
-               os=-kaos
+       pikeos*)
+               # Until real need of OS specific support for
+               # particular features comes up, bare metal
+               # configurations are quite functional.
+               case $basic_machine in
+                   arm*)
+                       os=eabi
+                       ;;
+                   *)
+                       os=elf
+                       ;;
+               esac
                ;;
-       -zvmoe)
-               os=-zvmoe
+       nacl*)
                ;;
-       -dicos*)
-               os=-dicos
+       ios)
                ;;
-       -nacl*)
+       none)
                ;;
-       -none)
+       *-eabi)
                ;;
        *)
-               # Get rid of the `-' at the beginning of $os.
-               os=`echo $os | sed 's/[^-]*-//'`
-               echo Invalid configuration \`$1\': system \`$os\' not recognized 1>&2
+               echo Invalid configuration \`"$1"\': system \`"$os"\' not recognized 1>&2
                exit 1
                ;;
 esac
@@ -1526,170 +1543,179 @@ else
 
 case $basic_machine in
        score-*)
-               os=-elf
+               os=elf
                ;;
        spu-*)
-               os=-elf
+               os=elf
                ;;
        *-acorn)
-               os=-riscix1.2
+               os=riscix1.2
                ;;
        arm*-rebel)
-               os=-linux
+               os=linux
                ;;
        arm*-semi)
-               os=-aout
+               os=aout
                ;;
        c4x-* | tic4x-*)
-               os=-coff
+               os=coff
+               ;;
+       c8051-*)
+               os=elf
+               ;;
+       clipper-intergraph)
+               os=clix
+               ;;
+       hexagon-*)
+               os=elf
                ;;
        tic54x-*)
-               os=-coff
+               os=coff
                ;;
        tic55x-*)
-               os=-coff
+               os=coff
                ;;
        tic6x-*)
-               os=-coff
+               os=coff
                ;;
        # This must come before the *-dec entry.
        pdp10-*)
-               os=-tops20
+               os=tops20
                ;;
        pdp11-*)
-               os=-none
+               os=none
                ;;
        *-dec | vax-*)
-               os=-ultrix4.2
+               os=ultrix4.2
                ;;
        m68*-apollo)
-               os=-domain
+               os=domain
                ;;
        i386-sun)
-               os=-sunos4.0.2
+               os=sunos4.0.2
                ;;
        m68000-sun)
-               os=-sunos3
+               os=sunos3
                ;;
        m68*-cisco)
-               os=-aout
+               os=aout
                ;;
        mep-*)
-               os=-elf
+               os=elf
                ;;
        mips*-cisco)
-               os=-elf
+               os=elf
                ;;
        mips*-*)
-               os=-elf
+               os=elf
                ;;
        or32-*)
-               os=-coff
+               os=coff
                ;;
        *-tti)  # must be before sparc entry or we get the wrong os.
-               os=-sysv3
+               os=sysv3
                ;;
        sparc-* | *-sun)
-               os=-sunos4.1.1
+               os=sunos4.1.1
                ;;
-       *-be)
-               os=-beos
+       pru-*)
+               os=elf
                ;;
-       *-haiku)
-               os=-haiku
+       *-be)
+               os=beos
                ;;
        *-ibm)
-               os=-aix
+               os=aix
                ;;
        *-knuth)
-               os=-mmixware
+               os=mmixware
                ;;
        *-wec)
-               os=-proelf
+               os=proelf
                ;;
        *-winbond)
-               os=-proelf
+               os=proelf
                ;;
        *-oki)
-               os=-proelf
+               os=proelf
                ;;
        *-hp)
-               os=-hpux
+               os=hpux
                ;;
        *-hitachi)
-               os=-hiux
+               os=hiux
                ;;
        i860-* | *-att | *-ncr | *-altos | *-motorola | *-convergent)
-               os=-sysv
+               os=sysv
                ;;
        *-cbm)
-               os=-amigaos
+               os=amigaos
                ;;
        *-dg)
-               os=-dgux
+               os=dgux
                ;;
        *-dolphin)
-               os=-sysv3
+               os=sysv3
                ;;
        m68k-ccur)
-               os=-rtu
+               os=rtu
                ;;
        m88k-omron*)
-               os=-luna
+               os=luna
                ;;
-       *-next )
-               os=-nextstep
+       *-next)
+               os=nextstep
                ;;
        *-sequent)
-               os=-ptx
+               os=ptx
                ;;
        *-crds)
-               os=-unos
+               os=unos
                ;;
        *-ns)
-               os=-genix
+               os=genix
                ;;
        i370-*)
-               os=-mvs
-               ;;
-       *-next)
-               os=-nextstep3
+               os=mvs
                ;;
        *-gould)
-               os=-sysv
+               os=sysv
                ;;
        *-highlevel)
-               os=-bsd
+               os=bsd
                ;;
        *-encore)
-               os=-bsd
+               os=bsd
                ;;
        *-sgi)
-               os=-irix
+               os=irix
                ;;
        *-siemens)
-               os=-sysv4
+               os=sysv4
                ;;
        *-masscomp)
-               os=-rtu
+               os=rtu
                ;;
        f30[01]-fujitsu | f700-fujitsu)
-               os=-uxpv
+               os=uxpv
                ;;
        *-rom68k)
-               os=-coff
+               os=coff
                ;;
        *-*bug)
-               os=-coff
+               os=coff
                ;;
        *-apple)
-               os=-macos
+               os=macos
                ;;
        *-atari*)
-               os=-mint
+               os=mint
+               ;;
+       *-wrs)
+               os=vxworks
                ;;
        *)
-               os=-none
+               os=none
                ;;
 esac
 fi
@@ -1700,79 +1726,82 @@ vendor=unknown
 case $basic_machine in
        *-unknown)
                case $os in
-                       -riscix*)
+                       riscix*)
                                vendor=acorn
                                ;;
-                       -sunos*)
+                       sunos*)
                                vendor=sun
                                ;;
-                       -cnk*|-aix*)
+                       cnk*|-aix*)
                                vendor=ibm
                                ;;
-                       -beos*)
+                       beos*)
                                vendor=be
                                ;;
-                       -hpux*)
+                       hpux*)
                                vendor=hp
                                ;;
-                       -mpeix*)
+                       mpeix*)
                                vendor=hp
                                ;;
-                       -hiux*)
+                       hiux*)
                                vendor=hitachi
                                ;;
-                       -unos*)
+                       unos*)
                                vendor=crds
                                ;;
-                       -dgux*)
+                       dgux*)
                                vendor=dg
                                ;;
-                       -luna*)
+                       luna*)
                                vendor=omron
                                ;;
-                       -genix*)
+                       genix*)
                                vendor=ns
                                ;;
-                       -mvs* | -opened*)
+                       clix*)
+                               vendor=intergraph
+                               ;;
+                       mvs* | opened*)
                                vendor=ibm
                                ;;
-                       -os400*)
+                       os400*)
                                vendor=ibm
                                ;;
-                       -ptx*)
+                       ptx*)
                                vendor=sequent
                                ;;
-                       -tpf*)
+                       tpf*)
                                vendor=ibm
                                ;;
-                       -vxsim* | -vxworks* | -windiss*)
+                       vxsim* | vxworks* | windiss*)
                                vendor=wrs
                                ;;
-                       -aux*)
+                       aux*)
                                vendor=apple
                                ;;
-                       -hms*)
+                       hms*)
                                vendor=hitachi
                                ;;
-                       -mpw* | -macos*)
+                       mpw* | macos*)
                                vendor=apple
                                ;;
-                       -*mint | -mint[0-9]* | -*MiNT | -MiNT[0-9]*)
+                       *mint | mint[0-9]* | *MiNT | MiNT[0-9]*)
                                vendor=atari
                                ;;
-                       -vos*)
+                       vos*)
                                vendor=stratus
                                ;;
                esac
-               basic_machine=`echo $basic_machine | sed "s/unknown/$vendor/"`
+               basic_machine=`echo "$basic_machine" | sed "s/unknown/$vendor/"`
                ;;
 esac
 
-echo $basic_machine$os
+echo "$basic_machine-$os"
 exit
 
 # Local variables:
-# eval: (add-hook 'write-file-hooks 'time-stamp)
+# eval: (add-hook 'before-save-hook 'time-stamp)
 # time-stamp-start: "timestamp='"
 # time-stamp-format: "%:y-%02m-%02d"
 # time-stamp-end: "'"
index e665cb9..fa15fc7 100755 (executable)
--- a/configure
+++ b/configure
@@ -1,6 +1,6 @@
 #! /bin/sh
 # Guess values for system-dependent variables and create Makefiles.
-# Generated by GNU Autoconf 2.69.
+# Generated by GNU Autoconf 2.69 for pcap 1.9.1.
 #
 #
 # Copyright (C) 1992-1996, 1998-2012 Free Software Foundation, Inc.
@@ -575,12 +575,12 @@ MFLAGS=
 MAKEFLAGS=
 
 # Identity of this package.
-PACKAGE_NAME=
-PACKAGE_TARNAME=
-PACKAGE_VERSION=
-PACKAGE_STRING=
-PACKAGE_BUGREPORT=
-PACKAGE_URL=
+PACKAGE_NAME='pcap'
+PACKAGE_TARNAME='pcap'
+PACKAGE_VERSION='1.9.1'
+PACKAGE_STRING='pcap 1.9.1'
+PACKAGE_BUGREPORT=''
+PACKAGE_URL=''
 
 ac_unique_file="pcap.c"
 # Factoring default headers for most tests.
@@ -623,43 +623,61 @@ ac_subst_vars='LTLIBOBJS
 INSTALL_DATA
 INSTALL_SCRIPT
 INSTALL_PROGRAM
+RDMA_SRC
+PCAP_SUPPORT_RDMASNIFF
 DBUS_SRC
 PCAP_SUPPORT_DBUS
 PKGCONFIG
-CAN_SRC
-PCAP_SUPPORT_CAN
-CANUSB_SRC
-PCAP_SUPPORT_CANUSB
 BT_MONITOR_SRC
 BT_SRC
 PCAP_SUPPORT_BT
+NETMAP_SRC
+PCAP_SUPPORT_NETMAP
 NETFILTER_SRC
 PCAP_SUPPORT_NETFILTER
 USB_SRC
 PCAP_SUPPORT_USB
+EXTRA_NETWORK_LIBS
+RPCAPD_LIBS
+INSTALL_RPCAPD
+BUILD_RPCAPD
+PTHREAD_LIBS
+MAN_ADMIN_COMMANDS
 MAN_MISC_INFO
 MAN_FILE_FORMATS
+MAN_DEVICES
 DYEXT
 SSRC
 ADDLARCHIVEOBJS
 ADDLOBJS
+V_YACC
 V_RPATH_OPT
 V_SONAME_OPT
 V_SHLIB_OPT
 V_SHLIB_CMD
+V_SHLIB_CCOPT
 V_PCAP
+V_LEX
 V_INCLS
 V_FINDALLDEVS
 V_DEFS
+V_PROG_LDFLAGS_FAT
+V_PROG_CCOPT_FAT
+V_LIB_LDFLAGS_FAT
+V_LIB_CCOPT_FAT
 V_CCOPT
 MKDEP
 DEPENDENCY_CFLAG
 LN_S
 AR
 RANLIB
-V_YACC
-V_LEX
-HAVE_LINUX_TPACKET_AUXDATA
+YFLAGS
+YACC
+LEXLIB
+LEX_OUTPUT_ROOT
+LEX
+PCAP_SUPPORT_PACKET_RING
+VALGRINDTEST_SRC
 LIBOBJS
 EGREP
 GREP
@@ -703,6 +721,7 @@ infodir
 docdir
 oldincludedir
 includedir
+runstatedir
 localstatedir
 sharedstatedir
 sysconfdir
@@ -731,9 +750,8 @@ enable_protochain
 with_sita
 with_pcap
 with_libnl
+enable_packet_ring
 enable_ipv6
-enable_optimizer_dbg
-enable_yydebug
 with_dag
 with_dag_includes
 with_dag_libraries
@@ -741,14 +759,17 @@ with_septel
 with_snf
 with_snf_includes
 with_snf_libraries
-with_flex
-with_bison
+with_turbocap
+enable_remote
+enable_optimizer_dbg
+enable_yydebug
 enable_universal
 enable_shared
+enable_usb
+enable_netmap
 enable_bluetooth
-enable_canusb
-enable_can
 enable_dbus
+enable_rdma
 '
       ac_precious_vars='build_alias
 host_alias
@@ -758,7 +779,9 @@ CFLAGS
 LDFLAGS
 LIBS
 CPPFLAGS
-CPP'
+CPP
+YACC
+YFLAGS'
 
 
 # Initialize some variables set by options.
@@ -797,9 +820,10 @@ datadir='${datarootdir}'
 sysconfdir='${prefix}/etc'
 sharedstatedir='${prefix}/com'
 localstatedir='${prefix}/var'
+runstatedir='${localstatedir}/run'
 includedir='${prefix}/include'
 oldincludedir='/usr/include'
-docdir='${datarootdir}/doc/${PACKAGE}'
+docdir='${datarootdir}/doc/${PACKAGE_TARNAME}'
 infodir='${datarootdir}/info'
 htmldir='${docdir}'
 dvidir='${docdir}'
@@ -1049,6 +1073,15 @@ do
   | -silent | --silent | --silen | --sile | --sil)
     silent=yes ;;
 
+  -runstatedir | --runstatedir | --runstatedi | --runstated \
+  | --runstate | --runstat | --runsta | --runst | --runs \
+  | --run | --ru | --r)
+    ac_prev=runstatedir ;;
+  -runstatedir=* | --runstatedir=* | --runstatedi=* | --runstated=* \
+  | --runstate=* | --runstat=* | --runsta=* | --runst=* | --runs=* \
+  | --run=* | --ru=* | --r=*)
+    runstatedir=$ac_optarg ;;
+
   -sbindir | --sbindir | --sbindi | --sbind | --sbin | --sbi | --sb)
     ac_prev=sbindir ;;
   -sbindir=* | --sbindir=* | --sbindi=* | --sbind=* | --sbin=* \
@@ -1186,7 +1219,7 @@ fi
 for ac_var in  exec_prefix prefix bindir sbindir libexecdir datarootdir \
                datadir sysconfdir sharedstatedir localstatedir includedir \
                oldincludedir docdir infodir htmldir dvidir pdfdir psdir \
-               libdir localedir mandir
+               libdir localedir mandir runstatedir
 do
   eval ac_val=\$$ac_var
   # Remove trailing slashes.
@@ -1299,7 +1332,7 @@ if test "$ac_init_help" = "long"; then
   # Omit some internal or obsolete options to make the list less imposing.
   # This message is too long to be a string in the A/UX 3.1 sh.
   cat <<_ACEOF
-\`configure' configures this package to adapt to many kinds of systems.
+\`configure' configures pcap 1.9.1 to adapt to many kinds of systems.
 
 Usage: $0 [OPTION]... [VAR=VALUE]...
 
@@ -1339,6 +1372,7 @@ Fine tuning of the installation directories:
   --sysconfdir=DIR        read-only single-machine data [PREFIX/etc]
   --sharedstatedir=DIR    modifiable architecture-independent data [PREFIX/com]
   --localstatedir=DIR     modifiable single-machine data [PREFIX/var]
+  --runstatedir=DIR       modifiable per-process data [LOCALSTATEDIR/run]
   --libdir=DIR            object code libraries [EPREFIX/lib]
   --includedir=DIR        C header files [PREFIX/include]
   --oldincludedir=DIR     C header files for non-gcc [/usr/include]
@@ -1347,7 +1381,7 @@ Fine tuning of the installation directories:
   --infodir=DIR           info documentation [DATAROOTDIR/info]
   --localedir=DIR         locale-dependent data [DATAROOTDIR/locale]
   --mandir=DIR            man documentation [DATAROOTDIR/man]
-  --docdir=DIR            documentation root [DATAROOTDIR/doc/PACKAGE]
+  --docdir=DIR            documentation root [DATAROOTDIR/doc/pcap]
   --htmldir=DIR           html documentation [DOCDIR]
   --dvidir=DIR            dvi documentation [DOCDIR]
   --pdfdir=DIR            pdf documentation [DOCDIR]
@@ -1364,7 +1398,9 @@ _ACEOF
 fi
 
 if test -n "$ac_init_help"; then
-
+  case $ac_init_help in
+     short | recursive ) echo "Configuration of pcap 1.9.1:";;
+   esac
   cat <<\_ACEOF
 
 Optional Features:
@@ -1373,21 +1409,25 @@ Optional Features:
   --enable-FEATURE[=ARG]  include FEATURE [ARG=yes]
   --disable-largefile     omit support for large files
   --disable-protochain    disable \"protochain\" insn
-  --enable-ipv6           build IPv6-capable version [default=yes, if
-                          getaddrinfo available]
+  --enable-packet-ring    enable packet ring support on Linux [default=yes]
+  --enable-ipv6           build IPv6-capable version [default=yes]
+  --enable-remote         enable remote packet capture [default=no]
+  --disable-remote        disable remote packet capture
   --enable-optimizer-dbg  build optimizer debugging code
   --enable-yydebug        build parser debugging code
-  --disable-universal     don't build universal on OS X
+  --disable-universal     don't build universal on macOS
   --enable-shared         build shared libraries [default=yes, if support
                           available]
-  --enable-bluetooth      enable Bluetooth support [default=yes, if support
+  --enable-usb            enable USB capture support [default=yes, if support
                           available]
-  --enable-canusb         enable canusb support [default=yes, if support
+  --enable-netmap         enable netmap 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-rdma           enable RDMA capture support [default=yes, if support
+                          available]
 
 Optional Packages:
   --with-PACKAGE[=ARG]    use PACKAGE [ARG=yes]
@@ -1397,20 +1437,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 +1464,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.
@@ -1488,7 +1537,7 @@ fi
 test -n "$ac_init_help" && exit $ac_status
 if $ac_init_version; then
   cat <<\_ACEOF
-configure
+pcap configure 1.9.1
 generated by GNU Autoconf 2.69
 
 Copyright (C) 2012 Free Software Foundation, Inc.
@@ -1540,6 +1589,52 @@ fi
 
 } # ac_fn_c_try_compile
 
+# ac_fn_c_try_link LINENO
+# -----------------------
+# Try to link conftest.$ac_ext, and return whether this succeeded.
+ac_fn_c_try_link ()
+{
+  as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack
+  rm -f conftest.$ac_objext conftest$ac_exeext
+  if { { ac_try="$ac_link"
+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 "$ac_link") 2>conftest.err
+  ac_status=$?
+  if test -s conftest.err; then
+    grep -v '^ *+' conftest.err >conftest.er1
+    cat conftest.er1 >&5
+    mv -f conftest.er1 conftest.err
+  fi
+  $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+  test $ac_status = 0; } && {
+        test -z "$ac_c_werror_flag" ||
+        test ! -s conftest.err
+       } && test -s conftest$ac_exeext && {
+        test "$cross_compiling" = yes ||
+        test -x conftest$ac_exeext
+       }; then :
+  ac_retval=0
+else
+  $as_echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+       ac_retval=1
+fi
+  # Delete the IPA/IPO (Inter Procedural Analysis/Optimization) information
+  # created by the PGI compiler (conftest_ipa8_conftest.oo), as it would
+  # interfere with the next link command; also delete a directory that is
+  # left behind by Apple's compiler.  We do this before executing the actions.
+  rm -rf conftest.dSYM conftest_ipa8_conftest.oo
+  eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno
+  as_fn_set_status $ac_retval
+
+} # ac_fn_c_try_link
+
 # ac_fn_c_try_cpp LINENO
 # ----------------------
 # Try to preprocess conftest.$ac_ext, and return whether this succeeded.
@@ -1737,106 +1832,6 @@ $as_echo "$ac_res" >&6; }
 
 } # ac_fn_c_check_header_compile
 
-# ac_fn_c_check_type LINENO TYPE VAR INCLUDES
-# -------------------------------------------
-# Tests whether TYPE exists after having included INCLUDES, setting cache
-# variable VAR accordingly.
-ac_fn_c_check_type ()
-{
-  as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack
-  { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $2" >&5
-$as_echo_n "checking for $2... " >&6; }
-if eval \${$3+:} false; then :
-  $as_echo_n "(cached) " >&6
-else
-  eval "$3=no"
-  cat confdefs.h - <<_ACEOF >conftest.$ac_ext
-/* end confdefs.h.  */
-$4
-int
-main ()
-{
-if (sizeof ($2))
-        return 0;
-  ;
-  return 0;
-}
-_ACEOF
-if ac_fn_c_try_compile "$LINENO"; then :
-  cat confdefs.h - <<_ACEOF >conftest.$ac_ext
-/* end confdefs.h.  */
-$4
-int
-main ()
-{
-if (sizeof (($2)))
-           return 0;
-  ;
-  return 0;
-}
-_ACEOF
-if ac_fn_c_try_compile "$LINENO"; then :
-
-else
-  eval "$3=yes"
-fi
-rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
-fi
-rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
-fi
-eval ac_res=\$$3
-              { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5
-$as_echo "$ac_res" >&6; }
-  eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno
-
-} # ac_fn_c_check_type
-
-# ac_fn_c_try_link LINENO
-# -----------------------
-# Try to link conftest.$ac_ext, and return whether this succeeded.
-ac_fn_c_try_link ()
-{
-  as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack
-  rm -f conftest.$ac_objext conftest$ac_exeext
-  if { { ac_try="$ac_link"
-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 "$ac_link") 2>conftest.err
-  ac_status=$?
-  if test -s conftest.err; then
-    grep -v '^ *+' conftest.err >conftest.er1
-    cat conftest.er1 >&5
-    mv -f conftest.er1 conftest.err
-  fi
-  $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
-  test $ac_status = 0; } && {
-        test -z "$ac_c_werror_flag" ||
-        test ! -s conftest.err
-       } && test -s conftest$ac_exeext && {
-        test "$cross_compiling" = yes ||
-        test -x conftest$ac_exeext
-       }; then :
-  ac_retval=0
-else
-  $as_echo "$as_me: failed program was:" >&5
-sed 's/^/| /' conftest.$ac_ext >&5
-
-       ac_retval=1
-fi
-  # Delete the IPA/IPO (Inter Procedural Analysis/Optimization) information
-  # created by the PGI compiler (conftest_ipa8_conftest.oo), as it would
-  # interfere with the next link command; also delete a directory that is
-  # left behind by Apple's compiler.  We do this before executing the actions.
-  rm -rf conftest.dSYM conftest_ipa8_conftest.oo
-  eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno
-  as_fn_set_status $ac_retval
-
-} # ac_fn_c_try_link
-
 # ac_fn_c_check_func LINENO FUNC VAR
 # ----------------------------------
 # Tests whether FUNC exists, setting the cache variable VAR accordingly
@@ -1949,11 +1944,122 @@ $as_echo "$ac_res" >&6; }
   eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno
 
 } # ac_fn_c_check_decl
+
+# ac_fn_c_check_type LINENO TYPE VAR INCLUDES
+# -------------------------------------------
+# Tests whether TYPE exists after having included INCLUDES, setting cache
+# variable VAR accordingly.
+ac_fn_c_check_type ()
+{
+  as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack
+  { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $2" >&5
+$as_echo_n "checking for $2... " >&6; }
+if eval \${$3+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  eval "$3=no"
+  cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+$4
+int
+main ()
+{
+if (sizeof ($2))
+        return 0;
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+  cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+$4
+int
+main ()
+{
+if (sizeof (($2)))
+           return 0;
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+
+else
+  eval "$3=yes"
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+fi
+eval ac_res=\$$3
+              { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5
+$as_echo "$ac_res" >&6; }
+  eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno
+
+} # ac_fn_c_check_type
+
+# ac_fn_c_check_member LINENO AGGR MEMBER VAR INCLUDES
+# ----------------------------------------------------
+# Tries to find if the field MEMBER exists in type AGGR, after including
+# INCLUDES, setting cache variable VAR accordingly.
+ac_fn_c_check_member ()
+{
+  as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack
+  { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $2.$3" >&5
+$as_echo_n "checking for $2.$3... " >&6; }
+if eval \${$4+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+$5
+int
+main ()
+{
+static $2 ac_aggr;
+if (ac_aggr.$3)
+return 0;
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+  eval "$4=yes"
+else
+  cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+$5
+int
+main ()
+{
+static $2 ac_aggr;
+if (sizeof ac_aggr.$3)
+return 0;
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+  eval "$4=yes"
+else
+  eval "$4=no"
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+fi
+eval ac_res=\$$4
+              { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5
+$as_echo "$ac_res" >&6; }
+  eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno
+
+} # ac_fn_c_check_member
 cat >config.log <<_ACEOF
 This file contains any messages produced by compilers while
 running configure, to aid debugging if configure makes a mistake.
 
-It was created by $as_me, which was
+It was created by pcap $as_me 1.9.1, which was
 generated by GNU Autoconf 2.69.  Invocation command line was
 
   $ $0 $@
@@ -2302,6 +2408,8 @@ ac_compiler_gnu=$ac_cv_c_compiler_gnu
 
 
 
+
+
 ac_aux_dir=
 for ac_dir in "$srcdir" "$srcdir/.." "$srcdir/../.."; do
   if test -f "$ac_dir/install-sh"; then
@@ -2515,6 +2623,10 @@ fi
            export CC
     fi
 
+#
+# Try to enable as many C99 features as we can.
+# At minimum, we want C++/C99-style // comments.
+#
 ac_ext=c
 ac_cpp='$CPP $CPPFLAGS'
 ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
@@ -3304,15 +3416,285 @@ ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
 ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
 ac_compiler_gnu=$ac_cv_c_compiler_gnu
 
+   { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $CC option to accept ISO C99" >&5
+$as_echo_n "checking for $CC option to accept ISO C99... " >&6; }
+if ${ac_cv_prog_cc_c99+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  ac_cv_prog_cc_c99=no
+ac_save_CC=$CC
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+#include <stdarg.h>
+#include <stdbool.h>
+#include <stdlib.h>
+#include <wchar.h>
+#include <stdio.h>
+
+// Check varargs macros.  These examples are taken from C99 6.10.3.5.
+#define debug(...) fprintf (stderr, __VA_ARGS__)
+#define showlist(...) puts (#__VA_ARGS__)
+#define report(test,...) ((test) ? puts (#test) : printf (__VA_ARGS__))
+static void
+test_varargs_macros (void)
+{
+  int x = 1234;
+  int y = 5678;
+  debug ("Flag");
+  debug ("X = %d\n", x);
+  showlist (The first, second, and third items.);
+  report (x>y, "x is %d but y is %d", x, y);
+}
+
+// Check long long types.
+#define BIG64 18446744073709551615ull
+#define BIG32 4294967295ul
+#define BIG_OK (BIG64 / BIG32 == 4294967297ull && BIG64 % BIG32 == 0)
+#if !BIG_OK
+  your preprocessor is broken;
+#endif
+#if BIG_OK
+#else
+  your preprocessor is broken;
+#endif
+static long long int bignum = -9223372036854775807LL;
+static unsigned long long int ubignum = BIG64;
+
+struct incomplete_array
+{
+  int datasize;
+  double data[];
+};
+
+struct named_init {
+  int number;
+  const wchar_t *name;
+  double average;
+};
+
+typedef const char *ccp;
+
+static inline int
+test_restrict (ccp restrict text)
+{
+  // See if C++-style comments work.
+  // Iterate through items via the restricted pointer.
+  // Also check for declarations in for loops.
+  for (unsigned int i = 0; *(text+i) != '\0'; ++i)
+    continue;
+  return 0;
+}
+
+// Check varargs and va_copy.
+static void
+test_varargs (const char *format, ...)
+{
+  va_list args;
+  va_start (args, format);
+  va_list args_copy;
+  va_copy (args_copy, args);
+
+  const char *str;
+  int number;
+  float fnumber;
+
+  while (*format)
+    {
+      switch (*format++)
+       {
+       case 's': // string
+         str = va_arg (args_copy, const char *);
+         break;
+       case 'd': // int
+         number = va_arg (args_copy, int);
+         break;
+       case 'f': // float
+         fnumber = va_arg (args_copy, double);
+         break;
+       default:
+         break;
+       }
+    }
+  va_end (args_copy);
+  va_end (args);
+}
+
+int
+main ()
+{
+
+  // Check bool.
+  _Bool success = false;
+
+  // Check restrict.
+  if (test_restrict ("String literal") == 0)
+    success = true;
+  char *restrict newvar = "Another string";
+
+  // Check varargs.
+  test_varargs ("s, d' f .", "string", 65, 34.234);
+  test_varargs_macros ();
+
+  // Check flexible array members.
+  struct incomplete_array *ia =
+    malloc (sizeof (struct incomplete_array) + (sizeof (double) * 10));
+  ia->datasize = 10;
+  for (int i = 0; i < ia->datasize; ++i)
+    ia->data[i] = i * 1.234;
+
+  // Check named initializers.
+  struct named_init ni = {
+    .number = 34,
+    .name = L"Test wide string",
+    .average = 543.34343,
+  };
+
+  ni.number = 58;
+
+  int dynamic_array[ni.number];
+  dynamic_array[ni.number - 1] = 543;
+
+  // work around unused variable warnings
+  return (!success || bignum == 0LL || ubignum == 0uLL || newvar[0] == 'x'
+         || dynamic_array[ni.number - 1] != 543);
+
+  ;
+  return 0;
+}
+_ACEOF
+for ac_arg in '' -std=gnu99 -std=c99 -c99 -AC99 -D_STDC_C99= -qlanglvl=extc99
+do
+  CC="$ac_save_CC $ac_arg"
+  if ac_fn_c_try_compile "$LINENO"; then :
+  ac_cv_prog_cc_c99=$ac_arg
+fi
+rm -f core conftest.err conftest.$ac_objext
+  test "x$ac_cv_prog_cc_c99" != "xno" && break
+done
+rm -f conftest.$ac_ext
+CC=$ac_save_CC
+
+fi
+# AC_CACHE_VAL
+case "x$ac_cv_prog_cc_c99" in
+  x)
+    { $as_echo "$as_me:${as_lineno-$LINENO}: result: none needed" >&5
+$as_echo "none needed" >&6; } ;;
+  xno)
+    { $as_echo "$as_me:${as_lineno-$LINENO}: result: unsupported" >&5
+$as_echo "unsupported" >&6; } ;;
+  *)
+    CC="$CC $ac_cv_prog_cc_c99"
+    { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_prog_cc_c99" >&5
+$as_echo "$ac_cv_prog_cc_c99" >&6; } ;;
+esac
+if test "x$ac_cv_prog_cc_c99" != xno; then :
+
+fi
+
+
+if test "$ac_cv_prog_cc_c99" = "no"; then
+       { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: The C compiler does not support C99; there may be compiler errors" >&5
+$as_echo "$as_me: WARNING: The C compiler does not support C99; there may be compiler errors" >&2;}
+fi
+
+
 
 
 
-
     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; }
+               can_add_to_cflags=yes
+               #
+               # The compile supports this; do we have some C code for
+               # which the warning should *not* appear?
+               # We test the fourth argument because the third argument
+               # could contain quotes, breaking the test.
+               #
+               if test "x" != "x"
+               then
+                   CFLAGS="$CFLAGS $ac_lbl_cc_force_warning_errors"
+                   { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether -fvisibility=hidden " >&5
+$as_echo_n "checking whether -fvisibility=hidden ... " >&6; }
+                   cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+
+                       #
+                       # Not a problem.
+                       #
+                       { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+
+else
+
+                       #
+                       # A problem.
+                       #
+                       { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
+$as_echo "yes" >&6; }
+                       can_add_to_cflags=no
+
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+               fi
+               CFLAGS="$save_CFLAGS"
+               if test x"$can_add_to_cflags" = "xyes"
+               then
+                   V_CCOPT="$V_CCOPT -fvisibility=hidden"
+               fi
+
+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 +3707,94 @@ 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; }
+               can_add_to_cflags=yes
+               #
+               # The compile supports this; do we have some C code for
+               # which the warning should *not* appear?
+               # We test the fourth argument because the third argument
+               # could contain quotes, breaking the test.
+               #
+               if test "x" != "x"
+               then
+                   CFLAGS="$CFLAGS $ac_lbl_cc_force_warning_errors"
+                   { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether -fvisibility=hidden " >&5
+$as_echo_n "checking whether -fvisibility=hidden ... " >&6; }
+                   cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+
+                       #
+                       # Not a problem.
+                       #
+                       { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+
+else
+
+                       #
+                       # A problem.
+                       #
+                       { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
+$as_echo "yes" >&6; }
+                       can_add_to_cflags=no
+
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+               fi
+               CFLAGS="$save_CFLAGS"
+               if test x"$can_add_to_cflags" = "xyes"
+               then
+                   V_CCOPT="$V_CCOPT -fvisibility=hidden"
+               fi
+
+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 +3869,94 @@ 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; }
+               can_add_to_cflags=yes
+               #
+               # The compile supports this; do we have some C code for
+               # which the warning should *not* appear?
+               # We test the fourth argument because the third argument
+               # could contain quotes, breaking the test.
+               #
+               if test "x" != "x"
+               then
+                   CFLAGS="$CFLAGS $ac_lbl_cc_force_warning_errors"
+                   { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether -xldscope=hidden " >&5
+$as_echo_n "checking whether -xldscope=hidden ... " >&6; }
+                   cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+
+                       #
+                       # Not a problem.
+                       #
+                       { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+
+else
+
+                       #
+                       # A problem.
+                       #
+                       { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
+$as_echo "yes" >&6; }
+                       can_add_to_cflags=no
+
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+               fi
+               CFLAGS="$save_CFLAGS"
+               if test x"$can_add_to_cflags" = "xyes"
+               then
+                   V_CCOPT="$V_CCOPT -xldscope=hidden"
+               fi
+
+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 +3965,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
@@ -3446,7 +4003,7 @@ $as_echo "#define const /**/" >>confdefs.h
            # On platforms where we build a shared library:
            #
            #   add options to generate position-independent code,
-           #   if necessary (it's the default in AIX and Darwin/OS X);
+           #   if necessary (it's the default in AIX and Darwin/macOS);
            #
            #   define option to set the soname of the shared library,
            #   if the OS supports that;
@@ -3461,7 +4018,7 @@ $as_echo "#define const /**/" >>confdefs.h
            aix*)
                    ;;
 
-           freebsd*|netbsd*|openbsd*|dragonfly*|linux*|osf*)
+           freebsd*|netbsd*|openbsd*|dragonfly*|linux*|osf*|midipix*)
                    #
                    # Platforms where the linker is the GNU linker
                    # or accepts command-line arguments like
@@ -3478,19 +4035,19 @@ $as_echo "#define const /**/" >>confdefs.h
                    sparc64*)
                        case "$host_os" in
 
-                       freebsd*|openbsd*)
+                       freebsd*|openbsd*|linux*)
                            PIC_OPT=-fPIC
                            ;;
                        esac
                        ;;
                    esac
-                   V_CCOPT="$V_CCOPT $PIC_OPT"
+                   V_SHLIB_CCOPT="$V_SHLIB_CCOPT $PIC_OPT"
                    V_SONAME_OPT="-Wl,-soname,"
                    V_RPATH_OPT="-Wl,-rpath,"
                    ;;
 
            hpux*)
-                   V_CCOPT="$V_CCOPT -fpic"
+                   V_SHLIB_CCOPT="$V_SHLIB_CCOPT -fpic"
                    #
                    # XXX - this assumes GCC is using the HP linker,
                    # rather than the GNU linker, and that the "+h"
@@ -3506,7 +4063,7 @@ $as_echo "#define const /**/" >>confdefs.h
                    ;;
 
            solaris*)
-                   V_CCOPT="$V_CCOPT -fpic"
+                   V_SHLIB_CCOPT="$V_SHLIB_CCOPT -fpic"
                    #
                    # XXX - this assumes GCC is using the Sun linker,
                    # rather than the GNU linker.
@@ -3521,7 +4078,7 @@ $as_echo "#define const /**/" >>confdefs.h
            # where we build a shared library:
            #
            #   add options to generate position-independent code,
-           #   if necessary (it's the default in Darwin/OS X);
+           #   if necessary (it's the default in Darwin/macOS);
            #
            #   if we generate ".so" shared libraries, define the
            #   appropriate options for building the shared library;
@@ -3547,7 +4104,7 @@ $as_echo "#define const /**/" >>confdefs.h
                    #
                    # "cc" is GCC.
                    #
-                   V_CCOPT="$V_CCOPT -fpic"
+                   V_SHLIB_CCOPT="$V_SHLIB_CCOPT -fpic"
                    V_SHLIB_CMD="\$(CC)"
                    V_SHLIB_OPT="-shared"
                    V_SONAME_OPT="-Wl,-soname,"
@@ -3555,7 +4112,7 @@ $as_echo "#define const /**/" >>confdefs.h
                    ;;
 
            hpux*)
-                   V_CCOPT="$V_CCOPT +z"
+                   V_SHLIB_CCOPT="$V_SHLIB_CCOPT +z"
                    V_SHLIB_CMD="\$(LD)"
                    V_SHLIB_OPT="-b"
                    V_SONAME_OPT="+h "
@@ -3578,7 +4135,7 @@ $as_echo "#define const /**/" >>confdefs.h
                    ;;
 
            solaris*)
-                   V_CCOPT="$V_CCOPT -Kpic"
+                   V_SHLIB_CCOPT="$V_SHLIB_CCOPT -Kpic"
                    V_SHLIB_CMD="\$(CC)"
                    V_SHLIB_OPT="-G"
                    V_SONAME_OPT="-h "
@@ -3650,183 +4207,320 @@ cat >>confdefs.h <<_ACEOF
 _ACEOF
 
 
-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for __attribute__" >&5
-$as_echo_n "checking for __attribute__... " >&6; }
-if ${ac_cv___attribute__+:} false; then :
-  $as_echo_n "(cached) " >&6
-else
-
-cat confdefs.h - <<_ACEOF >conftest.$ac_ext
-/* end confdefs.h.  */
-
-
-#include <stdlib.h>
-
-static void foo(void) __attribute__ ((noreturn));
+#
+# Try to arrange for large file support.
+#
+# Check whether --enable-largefile was given.
+if test "${enable_largefile+set}" = set; then :
+  enableval=$enable_largefile;
+fi
 
-static void
-foo(void)
-{
-  exit(1);
-}
+if test "$enable_largefile" != no; then
 
+  { $as_echo "$as_me:${as_lineno-$LINENO}: checking for special C compiler options needed for large files" >&5
+$as_echo_n "checking for special C compiler options needed for large files... " >&6; }
+if ${ac_cv_sys_largefile_CC+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  ac_cv_sys_largefile_CC=no
+     if test "$GCC" != yes; then
+       ac_save_CC=$CC
+       while :; do
+        # IRIX 6.2 and later do not support large files by default,
+        # so use the C compiler's -n32 option if that helps.
+        cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+#include <sys/types.h>
+ /* Check that off_t can represent 2**63 - 1 correctly.
+    We can't simply define LARGE_OFF_T to be 9223372036854775807,
+    since some C++ compilers masquerading as C compilers
+    incorrectly reject 9223372036854775807.  */
+#define LARGE_OFF_T ((((off_t) 1 << 31) << 31) - 1 + (((off_t) 1 << 31) << 31))
+  int off_t_is_large[(LARGE_OFF_T % 2147483629 == 721
+                      && LARGE_OFF_T % 2147483647 == 1)
+                     ? 1 : -1];
 int
-main(int argc, char **argv)
+main ()
 {
-  foo();
-}
 
+  ;
+  return 0;
+}
 _ACEOF
-if ac_fn_c_try_compile "$LINENO"; then :
-  ac_cv___attribute__=yes
-else
-  ac_cv___attribute__=no
+        if ac_fn_c_try_compile "$LINENO"; then :
+  break
 fi
-rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+rm -f core conftest.err conftest.$ac_objext
+        CC="$CC -n32"
+        if ac_fn_c_try_compile "$LINENO"; then :
+  ac_cv_sys_largefile_CC=' -n32'; break
 fi
-
-if test "$ac_cv___attribute__" = "yes"; then
-
-$as_echo "#define HAVE___ATTRIBUTE__ 1" >>confdefs.h
-
-else
-  #
-  # We can't use __attribute__, so we can't use __attribute__((unused)),
-  # so we define _U_ to an empty string.
-  #
-  V_DEFS="$V_DEFS -D_U_=\"\""
+rm -f core conftest.err conftest.$ac_objext
+        break
+       done
+       CC=$ac_save_CC
+       rm -f conftest.$ac_ext
+    fi
 fi
-{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv___attribute__" >&5
-$as_echo "$ac_cv___attribute__" >&6; }
-
-if test "$ac_cv___attribute__" = "yes"; then
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_sys_largefile_CC" >&5
+$as_echo "$ac_cv_sys_largefile_CC" >&6; }
+  if test "$ac_cv_sys_largefile_CC" != no; then
+    CC=$CC$ac_cv_sys_largefile_CC
+  fi
 
-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether __attribute__((unused)) can be used without warnings" >&5
-$as_echo_n "checking whether __attribute__((unused)) can be used without warnings... " >&6; }
-if ${ac_cv___attribute___unused+:} false; then :
+  { $as_echo "$as_me:${as_lineno-$LINENO}: checking for _FILE_OFFSET_BITS value needed for large files" >&5
+$as_echo_n "checking for _FILE_OFFSET_BITS value needed for large files... " >&6; }
+if ${ac_cv_sys_file_offset_bits+:} false; then :
   $as_echo_n "(cached) " >&6
 else
-
-save_CFLAGS="$CFLAGS"
-CFLAGS="$CFLAGS $ac_lbl_cc_force_warning_errors"
-cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+  while :; do
+  cat confdefs.h - <<_ACEOF >conftest.$ac_ext
 /* end confdefs.h.  */
-
-
-#include <stdlib.h>
-#include <stdio.h>
-
+#include <sys/types.h>
+ /* Check that off_t can represent 2**63 - 1 correctly.
+    We can't simply define LARGE_OFF_T to be 9223372036854775807,
+    since some C++ compilers masquerading as C compilers
+    incorrectly reject 9223372036854775807.  */
+#define LARGE_OFF_T ((((off_t) 1 << 31) << 31) - 1 + (((off_t) 1 << 31) << 31))
+  int off_t_is_large[(LARGE_OFF_T % 2147483629 == 721
+                      && LARGE_OFF_T % 2147483647 == 1)
+                     ? 1 : -1];
 int
-main(int argc  __attribute((unused)), char **argv __attribute((unused)))
+main ()
 {
-  printf("Hello, world!\n");
+
+  ;
   return 0;
 }
-
 _ACEOF
 if ac_fn_c_try_compile "$LINENO"; then :
-  ac_cv___attribute___unused=yes
-else
-  ac_cv___attribute___unused=no
+  ac_cv_sys_file_offset_bits=no; break
 fi
 rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
-fi
+  cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+#define _FILE_OFFSET_BITS 64
+#include <sys/types.h>
+ /* Check that off_t can represent 2**63 - 1 correctly.
+    We can't simply define LARGE_OFF_T to be 9223372036854775807,
+    since some C++ compilers masquerading as C compilers
+    incorrectly reject 9223372036854775807.  */
+#define LARGE_OFF_T ((((off_t) 1 << 31) << 31) - 1 + (((off_t) 1 << 31) << 31))
+  int off_t_is_large[(LARGE_OFF_T % 2147483629 == 721
+                      && LARGE_OFF_T % 2147483647 == 1)
+                     ? 1 : -1];
+int
+main ()
+{
 
-CFLAGS="$save_CFLAGS"
-if test "$ac_cv___attribute___unused" = "yes"; then
-  V_DEFS="$V_DEFS -D_U_=\"__attribute__((unused))\""
-else
-  V_DEFS="$V_DEFS -D_U_=\"\""
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+  ac_cv_sys_file_offset_bits=64; break
 fi
-{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv___attribute___unused" >&5
-$as_echo "$ac_cv___attribute___unused" >&6; }
-
-
-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether __attribute__((format)) can be used without warnings" >&5
-$as_echo_n "checking whether __attribute__((format)) can be used without warnings... " >&6; }
-if ${ac_cv___attribute___format+:} false; then :
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+  ac_cv_sys_file_offset_bits=unknown
+  break
+done
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_sys_file_offset_bits" >&5
+$as_echo "$ac_cv_sys_file_offset_bits" >&6; }
+case $ac_cv_sys_file_offset_bits in #(
+  no | unknown) ;;
+  *)
+cat >>confdefs.h <<_ACEOF
+#define _FILE_OFFSET_BITS $ac_cv_sys_file_offset_bits
+_ACEOF
+;;
+esac
+rm -rf conftest*
+  if test $ac_cv_sys_file_offset_bits = unknown; then
+    { $as_echo "$as_me:${as_lineno-$LINENO}: checking for _LARGE_FILES value needed for large files" >&5
+$as_echo_n "checking for _LARGE_FILES value needed for large files... " >&6; }
+if ${ac_cv_sys_large_files+:} false; then :
   $as_echo_n "(cached) " >&6
 else
-
-save_CFLAGS="$CFLAGS"
-CFLAGS="$CFLAGS $ac_lbl_cc_force_warning_errors"
-cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+  while :; do
+  cat confdefs.h - <<_ACEOF >conftest.$ac_ext
 /* end confdefs.h.  */
-
-
-#include <stdlib.h>
-
-extern int foo(const char *fmt, ...)
-                 __attribute__ ((format (printf, 1, 2)));
-
+#include <sys/types.h>
+ /* Check that off_t can represent 2**63 - 1 correctly.
+    We can't simply define LARGE_OFF_T to be 9223372036854775807,
+    since some C++ compilers masquerading as C compilers
+    incorrectly reject 9223372036854775807.  */
+#define LARGE_OFF_T ((((off_t) 1 << 31) << 31) - 1 + (((off_t) 1 << 31) << 31))
+  int off_t_is_large[(LARGE_OFF_T % 2147483629 == 721
+                      && LARGE_OFF_T % 2147483647 == 1)
+                     ? 1 : -1];
 int
-main(int argc, char **argv)
+main ()
 {
-  foo("%s", "test");
+
+  ;
+  return 0;
 }
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+  ac_cv_sys_large_files=no; break
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+  cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+#define _LARGE_FILES 1
+#include <sys/types.h>
+ /* Check that off_t can represent 2**63 - 1 correctly.
+    We can't simply define LARGE_OFF_T to be 9223372036854775807,
+    since some C++ compilers masquerading as C compilers
+    incorrectly reject 9223372036854775807.  */
+#define LARGE_OFF_T ((((off_t) 1 << 31) << 31) - 1 + (((off_t) 1 << 31) << 31))
+  int off_t_is_large[(LARGE_OFF_T % 2147483629 == 721
+                      && LARGE_OFF_T % 2147483647 == 1)
+                     ? 1 : -1];
+int
+main ()
+{
 
+  ;
+  return 0;
+}
 _ACEOF
 if ac_fn_c_try_compile "$LINENO"; then :
-  ac_cv___attribute___format=yes
-else
-  ac_cv___attribute___format=no
+  ac_cv_sys_large_files=1; break
 fi
 rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+  ac_cv_sys_large_files=unknown
+  break
+done
 fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_sys_large_files" >&5
+$as_echo "$ac_cv_sys_large_files" >&6; }
+case $ac_cv_sys_large_files in #(
+  no | unknown) ;;
+  *)
+cat >>confdefs.h <<_ACEOF
+#define _LARGE_FILES $ac_cv_sys_large_files
+_ACEOF
+;;
+esac
+rm -rf conftest*
+  fi
 
-CFLAGS="$save_CFLAGS"
-if test "$ac_cv___attribute___format" = "yes"; then
-
-$as_echo "#define __ATTRIBUTE___FORMAT_OK 1" >>confdefs.h
-
-fi
-{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv___attribute___format" >&5
-$as_echo "$ac_cv___attribute___format" >&6; }
 
 fi
 
-ac_ext=c
-ac_cpp='$CPP $CPPFLAGS'
-ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
-ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
-ac_compiler_gnu=$ac_cv_c_compiler_gnu
-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking how to run the C preprocessor" >&5
-$as_echo_n "checking how to run the C preprocessor... " >&6; }
-# On Suns, sometimes $CPP names a directory.
-if test -n "$CPP" && test -d "$CPP"; then
-  CPP=
-fi
-if test -z "$CPP"; then
-  if ${ac_cv_prog_CPP+:} false; then :
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for _LARGEFILE_SOURCE value needed for large files" >&5
+$as_echo_n "checking for _LARGEFILE_SOURCE value needed for large files... " >&6; }
+if ${ac_cv_sys_largefile_source+:} false; then :
   $as_echo_n "(cached) " >&6
 else
-      # Double quotes because CPP needs to be expanded
-    for CPP in "$CC -E" "$CC -E -traditional-cpp" "/lib/cpp"
-    do
-      ac_preproc_ok=false
-for ac_c_preproc_warn_flag in '' yes
-do
-  # Use a header file that comes with gcc, so configuring glibc
-  # with a fresh cross-compiler works.
-  # Prefer <limits.h> to <assert.h> if __STDC__ is defined, since
-  # <limits.h> exists even on freestanding compilers.
-  # On the NeXT, cc -E runs the code through the compiler's parser,
-  # not just through cpp. "Syntax error" is here to catch this case.
+  while :; do
   cat confdefs.h - <<_ACEOF >conftest.$ac_ext
 /* end confdefs.h.  */
-#ifdef __STDC__
-# include <limits.h>
-#else
-# include <assert.h>
-#endif
-                    Syntax error
+#include <sys/types.h> /* for off_t */
+     #include <stdio.h>
+int
+main ()
+{
+int (*fp) (FILE *, off_t, int) = fseeko;
+     return fseeko (stdin, 0, 0) && fp (stdin, 0, 0);
+  ;
+  return 0;
+}
 _ACEOF
-if ac_fn_c_try_cpp "$LINENO"; then :
-
-else
-  # Broken: fails on valid input.
-continue
-fi
+if ac_fn_c_try_link "$LINENO"; then :
+  ac_cv_sys_largefile_source=no; break
+fi
+rm -f core conftest.err conftest.$ac_objext \
+    conftest$ac_exeext conftest.$ac_ext
+  cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+#define _LARGEFILE_SOURCE 1
+#include <sys/types.h> /* for off_t */
+     #include <stdio.h>
+int
+main ()
+{
+int (*fp) (FILE *, off_t, int) = fseeko;
+     return fseeko (stdin, 0, 0) && fp (stdin, 0, 0);
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_c_try_link "$LINENO"; then :
+  ac_cv_sys_largefile_source=1; break
+fi
+rm -f core conftest.err conftest.$ac_objext \
+    conftest$ac_exeext conftest.$ac_ext
+  ac_cv_sys_largefile_source=unknown
+  break
+done
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_sys_largefile_source" >&5
+$as_echo "$ac_cv_sys_largefile_source" >&6; }
+case $ac_cv_sys_largefile_source in #(
+  no | unknown) ;;
+  *)
+cat >>confdefs.h <<_ACEOF
+#define _LARGEFILE_SOURCE $ac_cv_sys_largefile_source
+_ACEOF
+;;
+esac
+rm -rf conftest*
+
+# We used to try defining _XOPEN_SOURCE=500 too, to work around a bug
+# in glibc 2.1.3, but that breaks too many other things.
+# If you want fseeko and ftello with glibc, upgrade to a fixed glibc.
+if test $ac_cv_sys_largefile_source != unknown; then
+
+$as_echo "#define HAVE_FSEEKO 1" >>confdefs.h
+
+fi
+
+
+ac_ext=c
+ac_cpp='$CPP $CPPFLAGS'
+ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_c_compiler_gnu
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking how to run the C preprocessor" >&5
+$as_echo_n "checking how to run the C preprocessor... " >&6; }
+# On Suns, sometimes $CPP names a directory.
+if test -n "$CPP" && test -d "$CPP"; then
+  CPP=
+fi
+if test -z "$CPP"; then
+  if ${ac_cv_prog_CPP+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+      # Double quotes because CPP needs to be expanded
+    for CPP in "$CC -E" "$CC -E -traditional-cpp" "/lib/cpp"
+    do
+      ac_preproc_ok=false
+for ac_c_preproc_warn_flag in '' yes
+do
+  # Use a header file that comes with gcc, so configuring glibc
+  # with a fresh cross-compiler works.
+  # Prefer <limits.h> to <assert.h> if __STDC__ is defined, since
+  # <limits.h> exists even on freestanding compilers.
+  # On the NeXT, cc -E runs the code through the compiler's parser,
+  # not just through cpp. "Syntax error" is here to catch this case.
+  cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+#ifdef __STDC__
+# include <limits.h>
+#else
+# include <assert.h>
+#endif
+                    Syntax error
+_ACEOF
+if ac_fn_c_try_cpp "$LINENO"; then :
+
+else
+  # Broken: fails on valid input.
+continue
+fi
 rm -f conftest.err conftest.i conftest.$ac_ext
 
   # OK, works on sane cases.  Now check whether nonexistent headers
 done
 
 
-for ac_header in sys/bitypes.h
+for ac_header in sys/ioccom.h sys/sockio.h limits.h
 do :
-  ac_fn_c_check_header_mongrel "$LINENO" "sys/bitypes.h" "ac_cv_header_sys_bitypes_h" "$ac_includes_default"
-if test "x$ac_cv_header_sys_bitypes_h" = xyes; then :
+  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"
+if eval test \"x\$"$as_ac_Header"\" = x"yes"; then :
   cat >>confdefs.h <<_ACEOF
-#define HAVE_SYS_BITYPES_H 1
+#define `$as_echo "HAVE_$ac_header" | $as_tr_cpp` 1
 _ACEOF
 
 fi
 
 done
 
+for ac_header in netpacket/packet.h
+do :
+  ac_fn_c_check_header_mongrel "$LINENO" "netpacket/packet.h" "ac_cv_header_netpacket_packet_h" "$ac_includes_default"
+if test "x$ac_cv_header_netpacket_packet_h" = xyes; then :
+  cat >>confdefs.h <<_ACEOF
+#define HAVE_NETPACKET_PACKET_H 1
+_ACEOF
 
-ac_fn_c_check_type "$LINENO" "int8_t" "ac_cv_type_int8_t" "$ac_includes_default
-#ifdef HAVE_SYS_BITYPES_H
-#include <sys/bitypes.h>
-#endif
-"
-if test "x$ac_cv_type_int8_t" = xyes; then :
+fi
 
-else
+done
 
-$as_echo "#define int8_t signed char" >>confdefs.h
+for ac_header in net/pfvar.h
+do :
+  ac_fn_c_check_header_compile "$LINENO" "net/pfvar.h" "ac_cv_header_net_pfvar_h" "#include <sys/types.h>
+#include <sys/socket.h>
+#include <net/if.h>
+"
+if test "x$ac_cv_header_net_pfvar_h" = xyes; then :
+  cat >>confdefs.h <<_ACEOF
+#define HAVE_NET_PFVAR_H 1
+_ACEOF
 
 fi
 
-ac_fn_c_check_type "$LINENO" "u_int8_t" "ac_cv_type_u_int8_t" "$ac_includes_default
-#ifdef HAVE_SYS_BITYPES_H
-#include <sys/bitypes.h>
-#endif
-"
-if test "x$ac_cv_type_u_int8_t" = xyes; then :
+done
 
-else
+if test "$ac_cv_header_net_pfvar_h" = yes; then
+       #
+       # Check for various PF actions.
+       #
+       { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether net/pfvar.h defines PF_NAT through PF_NORDR" >&5
+$as_echo_n "checking whether net/pfvar.h defines PF_NAT through PF_NORDR... " >&6; }
+       cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+#include <sys/types.h>
+           #include <sys/socket.h>
+           #include <net/if.h>
+           #include <net/pfvar.h>
+int
+main ()
+{
+return PF_NAT+PF_NONAT+PF_BINAT+PF_NOBINAT+PF_RDR+PF_NORDR;
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
 
-$as_echo "#define u_int8_t unsigned char" >>confdefs.h
+               { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
+$as_echo "yes" >&6; }
 
-fi
+$as_echo "#define HAVE_PF_NAT_THROUGH_PF_NORDR 1" >>confdefs.h
 
-ac_fn_c_check_type "$LINENO" "int16_t" "ac_cv_type_int16_t" "$ac_includes_default"
-if test "x$ac_cv_type_int16_t" = xyes; then :
 
 else
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+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>
 
-$as_echo "#define int16_t short" >>confdefs.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
 
-       $ac_includes_default
-#ifdef HAVE_SYS_BITYPES_H
-#include <sys/bitypes.h>
-#endif
 fi
 
-ac_fn_c_check_type "$LINENO" "u_int16_t" "ac_cv_type_u_int16_t" "$ac_includes_default
-#ifdef HAVE_SYS_BITYPES_H
-#include <sys/bitypes.h>
-#endif
-"
-if test "x$ac_cv_type_u_int16_t" = xyes; then :
+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; }
+           if ${ac_cv_lbl_gcc_fixincludes+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+/*
+                    * This generates a "duplicate case value" when fixincludes
+                    * has not be run.
+                    */
+#              include <sys/types.h>
+#              include <sys/time.h>
+#              include <sys/ioctl.h>
+#              ifdef HAVE_SYS_IOCCOM_H
+#              include <sys/ioccom.h>
+#              endif
+int
+main ()
+{
+switch (0) {
+                   case _IO('A', 1):;
+                   case _IO('B', 1):;
+                   }
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+  ac_cv_lbl_gcc_fixincludes=yes
 else
+  ac_cv_lbl_gcc_fixincludes=no
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+fi
+
+           { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lbl_gcc_fixincludes" >&5
+$as_echo "$ac_cv_lbl_gcc_fixincludes" >&6; }
+           if test $ac_cv_lbl_gcc_fixincludes = no ; then
+                   # Don't cache failure
+                   unset ac_cv_lbl_gcc_fixincludes
+                   as_fn_error $? "see the INSTALL for more info" "$LINENO" 5
+           fi
+    fi
 
-$as_echo "#define u_int16_t unsigned short" >>confdefs.h
+for ac_func in strerror
+do :
+  ac_fn_c_check_func "$LINENO" "strerror" "ac_cv_func_strerror"
+if test "x$ac_cv_func_strerror" = xyes; then :
+  cat >>confdefs.h <<_ACEOF
+#define HAVE_STRERROR 1
+_ACEOF
 
 fi
+done
 
-ac_fn_c_check_type "$LINENO" "int32_t" "ac_cv_type_int32_t" "$ac_includes_default
-#ifdef HAVE_SYS_BITYPES_H
-#include <sys/bitypes.h>
-#endif
-"
-if test "x$ac_cv_type_int32_t" = xyes; then :
+ac_fn_c_check_func "$LINENO" "strerror_r" "ac_cv_func_strerror_r"
+if test "x$ac_cv_func_strerror_r" = xyes; then :
 
-else
+       #
+       # We have strerror_r; if we define _GNU_SOURCE, is it a
+       # POSIX-compliant strerror_r() or a GNU strerror_r()?
+       #
+       { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether strerror_r is GNU-style" >&5
+$as_echo_n "checking whether strerror_r is GNU-style... " >&6; }
+       cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
 
-$as_echo "#define int32_t int" >>confdefs.h
+               #define _GNU_SOURCE
+#include <string.h>
 
-fi
+/* Define it GNU-style; that will cause an error if it's not GNU-style */
+extern char *strerror_r(int, char *, size_t);
 
-ac_fn_c_check_type "$LINENO" "u_int32_t" "ac_cv_type_u_int32_t" "$ac_includes_default
-#ifdef HAVE_SYS_BITYPES_H
-#include <sys/bitypes.h>
-#endif
-"
-if test "x$ac_cv_type_u_int32_t" = xyes; then :
+int
+main(void)
+{
+       return 0;
+}
 
-else
 
-$as_echo "#define u_int32_t unsigned int" >>confdefs.h
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
 
-fi
+               # GNU-style
+               { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
+$as_echo "yes" >&6; }
+
+$as_echo "#define HAVE_GNU_STRERROR_R /**/" >>confdefs.h
 
-ac_fn_c_check_type "$LINENO" "int64_t" "ac_cv_type_int64_t" "$ac_includes_default
-#ifdef HAVE_SYS_BITYPES_H
-#include <sys/bitypes.h>
-#endif
-"
-if test "x$ac_cv_type_int64_t" = xyes; then :
 
 else
 
-$as_echo "#define int64_t long long" >>confdefs.h
+               { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
 
-fi
+$as_echo "#define HAVE_POSIX_STRERROR_R /**/" >>confdefs.h
 
-ac_fn_c_check_type "$LINENO" "u_int64_t" "ac_cv_type_u_int64_t" "$ac_includes_default
-#ifdef HAVE_SYS_BITYPES_H
-#include <sys/bitypes.h>
-#endif
-"
-if test "x$ac_cv_type_u_int64_t" = xyes; then :
+
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
 
 else
 
-$as_echo "#define u_int64_t unsigned long long" >>confdefs.h
+       #
+       # We don't have strerror_r; do we have strerror_s?
+       #
+       for ac_func in strerror_s
+do :
+  ac_fn_c_check_func "$LINENO" "strerror_s" "ac_cv_func_strerror_s"
+if test "x$ac_cv_func_strerror_s" = xyes; then :
+  cat >>confdefs.h <<_ACEOF
+#define HAVE_STRERROR_S 1
+_ACEOF
+
+fi
+done
+
 
 fi
 
 
 #
-# Try to arrange for large file support.
+# Thanks, IBM, for not providing vsyslog() in AIX!
 #
-# Check whether --enable-largefile was given.
-if test "${enable_largefile+set}" = set; then :
-  enableval=$enable_largefile;
+for ac_func in vsyslog
+do :
+  ac_fn_c_check_func "$LINENO" "vsyslog" "ac_cv_func_vsyslog"
+if test "x$ac_cv_func_vsyslog" = xyes; then :
+  cat >>confdefs.h <<_ACEOF
+#define HAVE_VSYSLOG 1
+_ACEOF
+
 fi
+done
 
-if test "$enable_largefile" != no; then
 
-  { $as_echo "$as_me:${as_lineno-$LINENO}: checking for special C compiler options needed for large files" >&5
-$as_echo_n "checking for special C compiler options needed for large files... " >&6; }
-if ${ac_cv_sys_largefile_CC+:} false; then :
-  $as_echo_n "(cached) " >&6
+#
+# Either:
+#
+#      we have snprintf() and vsnprintf(), and have asprintf() and
+#      vasprintf();
+#
+#      we have snprintf() and vsnprintf(), but don't have asprintf()
+#      or vasprintf();
+#
+#      we have neither snprintf() nor vsnprintf(), and don't have
+#      asprintf() or vasprintf(), either.
+#
+# We assume that if we have asprintf() we have vasprintf(), as well
+# as snprintf() and vsnprintf(), and that if we have snprintf() we
+# have vsnprintf().
+#
+# For the first case, we don't need any replacement routines.
+# For the second case, we need replacement asprintf()/vasprintf()
+# routines.
+# For the third case, we need replacement snprintf()/vsnprintf() and
+# asprintf()/vasprintf() routines.
+#
+needsnprintf=no
+for ac_func in vsnprintf snprintf
+do :
+  as_ac_var=`$as_echo "ac_cv_func_$ac_func" | $as_tr_sh`
+ac_fn_c_check_func "$LINENO" "$ac_func" "$as_ac_var"
+if eval test \"x\$"$as_ac_var"\" = x"yes"; then :
+  cat >>confdefs.h <<_ACEOF
+#define `$as_echo "HAVE_$ac_func" | $as_tr_cpp` 1
+_ACEOF
+
 else
-  ac_cv_sys_largefile_CC=no
-     if test "$GCC" != yes; then
-       ac_save_CC=$CC
-       while :; do
-        # IRIX 6.2 and later do not support large files by default,
-        # so use the C compiler's -n32 option if that helps.
-        cat confdefs.h - <<_ACEOF >conftest.$ac_ext
-/* end confdefs.h.  */
-#include <sys/types.h>
- /* Check that off_t can represent 2**63 - 1 correctly.
-    We can't simply define LARGE_OFF_T to be 9223372036854775807,
-    since some C++ compilers masquerading as C compilers
-    incorrectly reject 9223372036854775807.  */
-#define LARGE_OFF_T (((off_t) 1 << 62) - 1 + ((off_t) 1 << 62))
-  int off_t_is_large[(LARGE_OFF_T % 2147483629 == 721
-                      && LARGE_OFF_T % 2147483647 == 1)
-                     ? 1 : -1];
-int
-main ()
-{
+  needsnprintf=yes
+fi
+done
 
-  ;
-  return 0;
-}
+needasprintf=no
+for ac_func in vasprintf asprintf
+do :
+  as_ac_var=`$as_echo "ac_cv_func_$ac_func" | $as_tr_sh`
+ac_fn_c_check_func "$LINENO" "$ac_func" "$as_ac_var"
+if eval test \"x\$"$as_ac_var"\" = x"yes"; then :
+  cat >>confdefs.h <<_ACEOF
+#define `$as_echo "HAVE_$ac_func" | $as_tr_cpp` 1
 _ACEOF
-        if ac_fn_c_try_compile "$LINENO"; then :
-  break
+
+else
+  needasprintf=yes
 fi
-rm -f core conftest.err conftest.$ac_objext
-        CC="$CC -n32"
-        if ac_fn_c_try_compile "$LINENO"; then :
-  ac_cv_sys_largefile_CC=' -n32'; break
+done
+
+if test $needsnprintf = yes; then
+       #
+       # We assume we have none of them; missing/snprintf.c supplies
+       # all of them.
+       #
+       case " $LIBOBJS " in
+  *" snprintf.$ac_objext "* ) ;;
+  *) LIBOBJS="$LIBOBJS snprintf.$ac_objext"
+ ;;
+esac
+
+elif test $needasprintf = yes; then
+       #
+       # We assume we have snprintf()/vsnprintf() but lack
+       # asprintf()/vasprintf(); missing/asprintf.c supplies
+       # the latter (using vsnprintf()).
+       #
+       case " $LIBOBJS " in
+  *" asprintf.$ac_objext "* ) ;;
+  *) LIBOBJS="$LIBOBJS asprintf.$ac_objext"
+ ;;
+esac
+
 fi
-rm -f core conftest.err conftest.$ac_objext
-        break
-       done
-       CC=$ac_save_CC
-       rm -f conftest.$ac_ext
-    fi
+
+needstrlcat=no
+for ac_func in strlcat
+do :
+  ac_fn_c_check_func "$LINENO" "strlcat" "ac_cv_func_strlcat"
+if test "x$ac_cv_func_strlcat" = xyes; then :
+  cat >>confdefs.h <<_ACEOF
+#define HAVE_STRLCAT 1
+_ACEOF
+
+else
+  needstrlcat=yes
 fi
-{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_sys_largefile_CC" >&5
-$as_echo "$ac_cv_sys_largefile_CC" >&6; }
-  if test "$ac_cv_sys_largefile_CC" != no; then
-    CC=$CC$ac_cv_sys_largefile_CC
-  fi
+done
 
-  { $as_echo "$as_me:${as_lineno-$LINENO}: checking for _FILE_OFFSET_BITS value needed for large files" >&5
-$as_echo_n "checking for _FILE_OFFSET_BITS value needed for large files... " >&6; }
-if ${ac_cv_sys_file_offset_bits+:} false; then :
+if test $needstrlcat = yes; then
+       case " $LIBOBJS " in
+  *" strlcat.$ac_objext "* ) ;;
+  *) LIBOBJS="$LIBOBJS strlcat.$ac_objext"
+ ;;
+esac
+
+fi
+
+needstrlcpy=no
+for ac_func in strlcpy
+do :
+  ac_fn_c_check_func "$LINENO" "strlcpy" "ac_cv_func_strlcpy"
+if test "x$ac_cv_func_strlcpy" = xyes; then :
+  cat >>confdefs.h <<_ACEOF
+#define HAVE_STRLCPY 1
+_ACEOF
+
+else
+  needstrlcpy=yes
+fi
+done
+
+if test $needstrlcpy = yes; then
+       case " $LIBOBJS " in
+  *" strlcpy.$ac_objext "* ) ;;
+  *) LIBOBJS="$LIBOBJS strlcpy.$ac_objext"
+ ;;
+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 we have ffs(), and is it declared in <strings.h>?
+#
+for ac_func in ffs
+do :
+  ac_fn_c_check_func "$LINENO" "ffs" "ac_cv_func_ffs"
+if test "x$ac_cv_func_ffs" = xyes; then :
+  cat >>confdefs.h <<_ACEOF
+#define HAVE_FFS 1
+_ACEOF
+
+fi
+done
+
+if test "$ac_cv_func_ffs" = yes; then
+       #
+       # We have ffs(); is it declared in <strings.h>?
+       #
+       # This test fails if we don't have <strings.h> or if we do
+       # but it doesn't declare ffs().
+       #
+       ac_fn_c_check_decl "$LINENO" "ffs" "ac_cv_have_decl_ffs" "
+#include <strings.h>
+
+"
+if test "x$ac_cv_have_decl_ffs" = xyes; then :
+
+
+$as_echo "#define STRINGS_H_DECLARES_FFS /**/" >>confdefs.h
+
+
+fi
+
+fi
+
+#
+# Do this before checking for ether_hostton(), as it's a
+# "getaddrinfo()-ish function".
+#
+
+    #
+    # Most operating systems have getaddrinfo() in the default searched
+    # libraries (i.e. libc).  Check there first.
+    #
+    ac_fn_c_check_func "$LINENO" "getaddrinfo" "ac_cv_func_getaddrinfo"
+if test "x$ac_cv_func_getaddrinfo" = xyes; then :
+
+else
+
+       #
+       # Not found in the standard system libraries.
+       # Try libsocket, which requires libnsl.
+       #
+       { $as_echo "$as_me:${as_lineno-$LINENO}: checking for getaddrinfo in -lsocket" >&5
+$as_echo_n "checking for getaddrinfo in -lsocket... " >&6; }
+if ${ac_cv_lib_socket_getaddrinfo+:} false; then :
   $as_echo_n "(cached) " >&6
 else
-  while :; do
-  cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+  ac_check_lib_save_LIBS=$LIBS
+LIBS="-lsocket -lnsl $LIBS"
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
 /* end confdefs.h.  */
-#include <sys/types.h>
- /* Check that off_t can represent 2**63 - 1 correctly.
-    We can't simply define LARGE_OFF_T to be 9223372036854775807,
-    since some C++ compilers masquerading as C compilers
-    incorrectly reject 9223372036854775807.  */
-#define LARGE_OFF_T (((off_t) 1 << 62) - 1 + ((off_t) 1 << 62))
-  int off_t_is_large[(LARGE_OFF_T % 2147483629 == 721
-                      && LARGE_OFF_T % 2147483647 == 1)
-                     ? 1 : -1];
+
+/* 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 getaddrinfo ();
 int
 main ()
 {
-
+return getaddrinfo ();
   ;
   return 0;
 }
 _ACEOF
-if ac_fn_c_try_compile "$LINENO"; then :
-  ac_cv_sys_file_offset_bits=no; break
+if ac_fn_c_try_link "$LINENO"; then :
+  ac_cv_lib_socket_getaddrinfo=yes
+else
+  ac_cv_lib_socket_getaddrinfo=no
 fi
-rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
-  cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+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_socket_getaddrinfo" >&5
+$as_echo "$ac_cv_lib_socket_getaddrinfo" >&6; }
+if test "x$ac_cv_lib_socket_getaddrinfo" = xyes; then :
+
+           #
+           # OK, we found it in libsocket.
+           #
+           LIBS="-lsocket -lnsl $LIBS"
+
+else
+
+           #
+           # We didn't find it.
+           #
+           as_fn_error $? "getaddrinfo is required, but wasn't found" "$LINENO" 5
+
+fi
+
+
+       #
+       # OK, do we have recvmsg() in libxnet?
+       # We also link with libsocket and libnsl.
+       #
+       { $as_echo "$as_me:${as_lineno-$LINENO}: checking for recvmsg in -lxnet" >&5
+$as_echo_n "checking for recvmsg in -lxnet... " >&6; }
+if ${ac_cv_lib_xnet_recvmsg+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  ac_check_lib_save_LIBS=$LIBS
+LIBS="-lxnet -lsocket -lnsl $LIBS"
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
 /* end confdefs.h.  */
-#define _FILE_OFFSET_BITS 64
-#include <sys/types.h>
- /* Check that off_t can represent 2**63 - 1 correctly.
-    We can't simply define LARGE_OFF_T to be 9223372036854775807,
-    since some C++ compilers masquerading as C compilers
-    incorrectly reject 9223372036854775807.  */
-#define LARGE_OFF_T (((off_t) 1 << 62) - 1 + ((off_t) 1 << 62))
-  int off_t_is_large[(LARGE_OFF_T % 2147483629 == 721
-                      && LARGE_OFF_T % 2147483647 == 1)
-                     ? 1 : -1];
+
+/* 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 recvmsg ();
 int
 main ()
 {
-
+return recvmsg ();
   ;
   return 0;
 }
 _ACEOF
-if ac_fn_c_try_compile "$LINENO"; then :
-  ac_cv_sys_file_offset_bits=64; break
+if ac_fn_c_try_link "$LINENO"; then :
+  ac_cv_lib_xnet_recvmsg=yes
+else
+  ac_cv_lib_xnet_recvmsg=no
 fi
-rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
-  ac_cv_sys_file_offset_bits=unknown
-  break
-done
+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_sys_file_offset_bits" >&5
-$as_echo "$ac_cv_sys_file_offset_bits" >&6; }
-case $ac_cv_sys_file_offset_bits in #(
-  no | unknown) ;;
-  *)
-cat >>confdefs.h <<_ACEOF
-#define _FILE_OFFSET_BITS $ac_cv_sys_file_offset_bits
-_ACEOF
-;;
-esac
-rm -rf conftest*
-  if test $ac_cv_sys_file_offset_bits = unknown; then
-    { $as_echo "$as_me:${as_lineno-$LINENO}: checking for _LARGE_FILES value needed for large files" >&5
-$as_echo_n "checking for _LARGE_FILES value needed for large files... " >&6; }
-if ${ac_cv_sys_large_files+:} false; then :
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_xnet_recvmsg" >&5
+$as_echo "$ac_cv_lib_xnet_recvmsg" >&6; }
+if test "x$ac_cv_lib_xnet_recvmsg" = xyes; then :
+
+           #
+           # Yes - link with it as well.
+           #
+           LIBS="-lxnet $LIBS"
+
+fi
+
+
+fi
+
+    # DLPI needs putmsg under HPUX so test for -lstr while we're at it
+    { $as_echo "$as_me:${as_lineno-$LINENO}: checking for library containing putmsg" >&5
+$as_echo_n "checking for library containing putmsg... " >&6; }
+if ${ac_cv_search_putmsg+:} false; then :
   $as_echo_n "(cached) " >&6
 else
-  while :; do
-  cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+  ac_func_search_save_LIBS=$LIBS
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
 /* end confdefs.h.  */
-#include <sys/types.h>
- /* Check that off_t can represent 2**63 - 1 correctly.
-    We can't simply define LARGE_OFF_T to be 9223372036854775807,
-    since some C++ compilers masquerading as C compilers
-    incorrectly reject 9223372036854775807.  */
-#define LARGE_OFF_T (((off_t) 1 << 62) - 1 + ((off_t) 1 << 62))
-  int off_t_is_large[(LARGE_OFF_T % 2147483629 == 721
-                      && LARGE_OFF_T % 2147483647 == 1)
-                     ? 1 : -1];
+
+/* 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 putmsg ();
 int
 main ()
 {
+return putmsg ();
+  ;
+  return 0;
+}
+_ACEOF
+for ac_lib in '' str; do
+  if test -z "$ac_lib"; then
+    ac_res="none required"
+  else
+    ac_res=-l$ac_lib
+    LIBS="-l$ac_lib  $ac_func_search_save_LIBS"
+  fi
+  if ac_fn_c_try_link "$LINENO"; then :
+  ac_cv_search_putmsg=$ac_res
+fi
+rm -f core conftest.err conftest.$ac_objext \
+    conftest$ac_exeext
+  if ${ac_cv_search_putmsg+:} false; then :
+  break
+fi
+done
+if ${ac_cv_search_putmsg+:} false; then :
+
+else
+  ac_cv_search_putmsg=no
+fi
+rm conftest.$ac_ext
+LIBS=$ac_func_search_save_LIBS
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_search_putmsg" >&5
+$as_echo "$ac_cv_search_putmsg" >&6; }
+ac_res=$ac_cv_search_putmsg
+if test "$ac_res" != no; then :
+  test "$ac_res" = "none required" || LIBS="$ac_res $LIBS"
+
+fi
+
+
+
+#
+# Check for reentrant versions of getnetbyname_r(), as provided by
+# Linux (glibc), Solaris/IRIX, and AIX (with three different APIs!).
+# If we don't find one, we just use getnetbyname(), which uses
+# thread-specific data on many platforms, but doesn't use it on
+# NetBSD or OpenBSD, and may not use it on older versions of other
+# platforms.
+#
+# Only do the check if we have a declaration of getnetbyname_r();
+# without it, we can't check which API it has.  (We assume that
+# if there's a declaration, it has a prototype, so that the API
+# can be checked.)
+#
+ac_fn_c_check_decl "$LINENO" "getnetbyname_r" "ac_cv_have_decl_getnetbyname_r" "#include <netdb.h>
+"
+if test "x$ac_cv_have_decl_getnetbyname_r" = xyes; then :
+
+       { $as_echo "$as_me:${as_lineno-$LINENO}: checking for the Linux getnetbyname_r()" >&5
+$as_echo_n "checking for the Linux getnetbyname_r()... " >&6; }
+       cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+#include <netdb.h>
+int
+main ()
+{
+
+               struct netent netent_buf;
+               char buf[1024];
+               struct netent *resultp;
+               int h_errnoval;
+
+               return getnetbyname_r((const char *)0, &netent_buf, buf, sizeof buf, &resultp, &h_errnoval);
 
   ;
   return 0;
 }
 _ACEOF
-if ac_fn_c_try_compile "$LINENO"; then :
-  ac_cv_sys_large_files=no; break
+if ac_fn_c_try_link "$LINENO"; then :
+
+               { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
+$as_echo "yes" >&6; }
+
+$as_echo "#define HAVE_LINUX_GETNETBYNAME_R 1" >>confdefs.h
+
+
+else
+
+               { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+
+               { $as_echo "$as_me:${as_lineno-$LINENO}: checking for Solaris/IRIX getnetbyname_r()" >&5
+$as_echo_n "checking for Solaris/IRIX getnetbyname_r()... " >&6; }
+               cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+#include <netdb.h>
+int
+main ()
+{
+
+                       struct netent netent_buf;
+                       char buf[1024];
+
+                       return getnetbyname_r((const char *)0, &netent_buf, buf, (int)sizeof buf) != NULL;
+
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_c_try_link "$LINENO"; then :
+
+                       { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
+$as_echo "yes" >&6; }
+
+$as_echo "#define HAVE_SOLARIS_IRIX_GETNETBYNAME_R 1" >>confdefs.h
+
+
+else
+
+                       { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+
+                       { $as_echo "$as_me:${as_lineno-$LINENO}: checking for AIX getnetbyname_r()" >&5
+$as_echo_n "checking for AIX getnetbyname_r()... " >&6; }
+                       cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+#include <netdb.h>
+int
+main ()
+{
+
+                               struct netent netent_buf;
+                               struct netent_data net_data;
+
+                               return getnetbyname_r((const char *)0, &netent_buf, &net_data);
+
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_c_try_link "$LINENO"; then :
+
+                               { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
+$as_echo "yes" >&6; }
+
+$as_echo "#define HAVE_AIX_GETNETBYNAME_R 1" >>confdefs.h
+
+
+else
+
+                               { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+
 fi
-rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
-  cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+rm -f core conftest.err conftest.$ac_objext \
+    conftest$ac_exeext conftest.$ac_ext
+
+fi
+rm -f core conftest.err conftest.$ac_objext \
+    conftest$ac_exeext conftest.$ac_ext
+
+fi
+rm -f core conftest.err conftest.$ac_objext \
+    conftest$ac_exeext conftest.$ac_ext
+
+fi
+
+
+#
+# Check for reentrant versions of getprotobyname_r(), as provided by
+# Linux (glibc), Solaris/IRIX, and AIX (with three different APIs!).
+# If we don't find one, we just use getprotobyname(), which uses
+# thread-specific data on many platforms, but doesn't use it on
+# NetBSD or OpenBSD, and may not use it on older versions of other
+# platforms.
+#
+# Only do the check if we have a declaration of getprotobyname_r();
+# without it, we can't check which API it has.  (We assume that
+# if there's a declaration, it has a prototype, so that the API
+# can be checked.)
+#
+ac_fn_c_check_decl "$LINENO" "getprotobyname_r" "ac_cv_have_decl_getprotobyname_r" "#include <netdb.h>
+"
+if test "x$ac_cv_have_decl_getprotobyname_r" = xyes; then :
+
+       { $as_echo "$as_me:${as_lineno-$LINENO}: checking for the Linux getprotobyname_r()" >&5
+$as_echo_n "checking for the Linux getprotobyname_r()... " >&6; }
+       cat confdefs.h - <<_ACEOF >conftest.$ac_ext
 /* end confdefs.h.  */
-#define _LARGE_FILES 1
+#include <netdb.h>
+int
+main ()
+{
+
+               struct protoent protoent_buf;
+               char buf[1024];
+               struct protoent *resultp;
+
+               return getprotobyname_r((const char *)0, &protoent_buf, buf, sizeof buf, &resultp);
+
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_c_try_link "$LINENO"; then :
+
+               { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
+$as_echo "yes" >&6; }
+
+$as_echo "#define HAVE_LINUX_GETPROTOBYNAME_R 1" >>confdefs.h
+
+
+else
+
+               { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+
+               { $as_echo "$as_me:${as_lineno-$LINENO}: checking for Solaris/IRIX getprotobyname_r()" >&5
+$as_echo_n "checking for Solaris/IRIX getprotobyname_r()... " >&6; }
+               cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+#include <netdb.h>
+int
+main ()
+{
+
+                       struct protoent protoent_buf;
+                       char buf[1024];
+
+                       return getprotobyname_r((const char *)0, &protoent_buf, buf, (int)sizeof buf) != NULL;
+
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_c_try_link "$LINENO"; then :
+
+                       { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
+$as_echo "yes" >&6; }
+
+$as_echo "#define HAVE_SOLARIS_IRIX_GETPROTOBYNAME_R 1" >>confdefs.h
+
+
+else
+
+                       { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+
+                       { $as_echo "$as_me:${as_lineno-$LINENO}: checking for AIX getprotobyname_r()" >&5
+$as_echo_n "checking for AIX getprotobyname_r()... " >&6; }
+                       cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+#include <netdb.h>
+int
+main ()
+{
+
+                               struct protoent protoent_buf;
+                               struct protoent_data proto_data;
+
+                               return getprotobyname_r((const char *)0, &protoent_buf, &proto_data);
+
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_c_try_link "$LINENO"; then :
+
+                               { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
+$as_echo "yes" >&6; }
+
+$as_echo "#define HAVE_AIX_GETPROTOBYNAME_R 1" >>confdefs.h
+
+
+else
+
+                               { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+
+fi
+rm -f core conftest.err conftest.$ac_objext \
+    conftest$ac_exeext conftest.$ac_ext
+
+fi
+rm -f core conftest.err conftest.$ac_objext \
+    conftest$ac_exeext conftest.$ac_ext
+
+fi
+rm -f core conftest.err conftest.$ac_objext \
+    conftest$ac_exeext conftest.$ac_ext
+
+fi
+
+
+#
+# You are in a twisty little maze of UN*Xes, all different.
+# Some might not have ether_hostton().
+# Some might have it and declare it in <net/ethernet.h>.
+# Some might have it and declare it in <netinet/ether.h>
+# Some might have it and declare it in <sys/ethernet.h>.
+# Some might have it and declare it in <arpa/inet.h>.
+# Some might have it and declare it in <netinet/if_ether.h>.
+# Some might have it and not declare it in any header file.
+#
+# Before you is a C compiler.
+#
+for ac_func in ether_hostton
+do :
+  ac_fn_c_check_func "$LINENO" "ether_hostton" "ac_cv_func_ether_hostton"
+if test "x$ac_cv_func_ether_hostton" = xyes; then :
+  cat >>confdefs.h <<_ACEOF
+#define HAVE_ETHER_HOSTTON 1
+_ACEOF
+
+fi
+done
+
+if test "$ac_cv_func_ether_hostton" = yes; then
+       #
+       # OK, we have ether_hostton().  Is it declared in <net/ethernet.h>?
+       #
+       # This test fails if we don't have <net/ethernet.h> or if we do
+       # but it doesn't declare ether_hostton().
+       #
+       ac_fn_c_check_decl "$LINENO" "ether_hostton" "ac_cv_have_decl_ether_hostton" "
+#include <net/ethernet.h>
+
+"
+if test "x$ac_cv_have_decl_ether_hostton" = xyes; then :
+
+
+$as_echo "#define NET_ETHERNET_H_DECLARES_ETHER_HOSTTON /**/" >>confdefs.h
+
+
+fi
+
+       #
+       # Did that succeed?
+       #
+       if test "$ac_cv_have_decl_ether_hostton" != yes; then
+               #
+               # No, how about <netinet/ether.h>, as on Linux?
+               #
+               # This test fails if we don't have <netinet/ether.h>
+               # or if we do but it doesn't declare ether_hostton().
+               #
+               # Unset ac_cv_have_decl_ether_hostton so we don't
+               # treat the previous failure as a cached value and
+               # suppress the next test.
+               #
+               unset ac_cv_have_decl_ether_hostton
+               ac_fn_c_check_decl "$LINENO" "ether_hostton" "ac_cv_have_decl_ether_hostton" "
+#include <netinet/ether.h>
+
+"
+if test "x$ac_cv_have_decl_ether_hostton" = xyes; then :
+
+
+$as_echo "#define NETINET_ETHER_H_DECLARES_ETHER_HOSTTON /**/" >>confdefs.h
+
+
+fi
+
+       fi
+       #
+       # Did that succeed?
+       #
+       if test "$ac_cv_have_decl_ether_hostton" != yes; then
+               #
+               # No, how about <sys/ethernet.h>, as on Solaris 10
+               # and later?
+               #
+               # This test fails if we don't have <sys/ethernet.h>
+               # or if we do but it doesn't declare ether_hostton().
+               #
+               # Unset ac_cv_have_decl_ether_hostton so we don't
+               # treat the previous failure as a cached value and
+               # suppress the next test.
+               #
+               unset ac_cv_have_decl_ether_hostton
+               ac_fn_c_check_decl "$LINENO" "ether_hostton" "ac_cv_have_decl_ether_hostton" "
+#include <sys/ethernet.h>
+
+"
+if test "x$ac_cv_have_decl_ether_hostton" = xyes; then :
+
+
+$as_echo "#define SYS_ETHERNET_H_DECLARES_ETHER_HOSTTON /**/" >>confdefs.h
+
+
+fi
+
+       fi
+       #
+       # Did that succeed?
+       #
+       if test "$ac_cv_have_decl_ether_hostton" != yes; then
+               #
+               # No, how about <arpa/inet.h>, as in AIX?
+               #
+               # This test fails if we don't have <arpa/inet.h>
+               # (if we have ether_hostton(), we should have
+               # networking, and if we have networking, we should
+               # have <arapa/inet.h>) or if we do but it doesn't
+               # declare ether_hostton().
+               #
+               # Unset ac_cv_have_decl_ether_hostton so we don't
+               # treat the previous failure as a cached value and
+               # suppress the next test.
+               #
+               unset ac_cv_have_decl_ether_hostton
+               ac_fn_c_check_decl "$LINENO" "ether_hostton" "ac_cv_have_decl_ether_hostton" "
+#include <arpa/inet.h>
+
+"
+if test "x$ac_cv_have_decl_ether_hostton" = xyes; then :
+
+
+$as_echo "#define ARPA_INET_H_DECLARES_ETHER_HOSTTON /**/" >>confdefs.h
+
+
+fi
+
+       fi
+       #
+       # Did that succeed?
+       #
+       if test "$ac_cv_have_decl_ether_hostton" != yes; then
+               #
+               # No, how about <netinet/if_ether.h>?
+               # On some platforms, it requires <net/if.h> and
+               # <netinet/in.h>, and we always include it with
+               # both of them, so test it with both of them.
+               #
+               # This test fails if we don't have <netinet/if_ether.h>
+               # and the headers we include before it, or if we do but
+               # <netinet/if_ether.h> doesn't declare ether_hostton().
+               #
+               # Unset ac_cv_have_decl_ether_hostton so we don't
+               # treat the previous failure as a cached value and
+               # suppress the next test.
+               #
+               unset ac_cv_have_decl_ether_hostton
+               ac_fn_c_check_decl "$LINENO" "ether_hostton" "ac_cv_have_decl_ether_hostton" "
 #include <sys/types.h>
- /* Check that off_t can represent 2**63 - 1 correctly.
-    We can't simply define LARGE_OFF_T to be 9223372036854775807,
-    since some C++ compilers masquerading as C compilers
-    incorrectly reject 9223372036854775807.  */
-#define LARGE_OFF_T (((off_t) 1 << 62) - 1 + ((off_t) 1 << 62))
-  int off_t_is_large[(LARGE_OFF_T % 2147483629 == 721
-                      && LARGE_OFF_T % 2147483647 == 1)
-                     ? 1 : -1];
+#include <sys/socket.h>
+#include <net/if.h>
+#include <netinet/in.h>
+#include <netinet/if_ether.h>
+
+"
+if test "x$ac_cv_have_decl_ether_hostton" = xyes; then :
+
+
+$as_echo "#define NETINET_IF_ETHER_H_DECLARES_ETHER_HOSTTON /**/" >>confdefs.h
+
+
+fi
+
+       fi
+       #
+       # After all that, is ether_hostton() declared?
+       #
+       if test "$ac_cv_have_decl_ether_hostton" = yes; then
+               #
+               # Yes.
+               #
+
+$as_echo "#define HAVE_DECL_ETHER_HOSTTON 1" >>confdefs.h
+
+        else
+               #
+               # No, we'll have to declare it ourselves.
+               # Do we have "struct ether_addr" if we include
+               # <netinet/if_ether.h>?
+               #
+               ac_fn_c_check_type "$LINENO" "struct ether_addr" "ac_cv_type_struct_ether_addr" "
+                       #include <sys/types.h>
+                       #include <sys/socket.h>
+                       #include <net/if.h>
+                       #include <netinet/in.h>
+                       #include <netinet/if_ether.h>
+
+"
+if test "x$ac_cv_type_struct_ether_addr" = xyes; then :
+
+cat >>confdefs.h <<_ACEOF
+#define HAVE_STRUCT_ETHER_ADDR 1
+_ACEOF
+
+
+fi
+
+       fi
+fi
+
+#
+# For various things that might use pthreads.
+#
+ac_fn_c_check_header_mongrel "$LINENO" "pthread.h" "ac_cv_header_pthread_h" "$ac_includes_default"
+if test "x$ac_cv_header_pthread_h" = xyes; then :
+
+       #
+       # OK, we have pthread.h.  Do we have pthread_create in the
+       # system libraries?
+       #
+       ac_fn_c_check_func "$LINENO" "pthread_create" "ac_cv_func_pthread_create"
+if test "x$ac_cv_func_pthread_create" = xyes; then :
+
+               #
+               # Yes.
+               #
+               ac_lbl_have_pthreads="found"
+
+else
+
+               #
+               # No - do we have it in -lpthreads?
+               #
+               { $as_echo "$as_me:${as_lineno-$LINENO}: checking for pthread_create in -lpthreads" >&5
+$as_echo_n "checking for pthread_create in -lpthreads... " >&6; }
+if ${ac_cv_lib_pthreads_pthread_create+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  ac_check_lib_save_LIBS=$LIBS
+LIBS="-lpthreads  $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 pthread_create ();
 int
 main ()
 {
-
+return pthread_create ();
   ;
   return 0;
 }
 _ACEOF
-if ac_fn_c_try_compile "$LINENO"; then :
-  ac_cv_sys_large_files=1; break
+if ac_fn_c_try_link "$LINENO"; then :
+  ac_cv_lib_pthreads_pthread_create=yes
+else
+  ac_cv_lib_pthreads_pthread_create=no
 fi
-rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
-  ac_cv_sys_large_files=unknown
-  break
-done
+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_sys_large_files" >&5
-$as_echo "$ac_cv_sys_large_files" >&6; }
-case $ac_cv_sys_large_files in #(
-  no | unknown) ;;
-  *)
-cat >>confdefs.h <<_ACEOF
-#define _LARGE_FILES $ac_cv_sys_large_files
-_ACEOF
-;;
-esac
-rm -rf conftest*
-  fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_pthreads_pthread_create" >&5
+$as_echo "$ac_cv_lib_pthreads_pthread_create" >&6; }
+if test "x$ac_cv_lib_pthreads_pthread_create" = xyes; then :
 
+                       #
+                       # Yes - add -lpthreads.
+                       #
+                       ac_lbl_have_pthreads="found"
+                       PTHREAD_LIBS="$PTHREAD_LIBS -lpthreads"
 
-fi
+else
 
-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for _LARGEFILE_SOURCE value needed for large files" >&5
-$as_echo_n "checking for _LARGEFILE_SOURCE value needed for large files... " >&6; }
-if ${ac_cv_sys_largefile_source+:} false; then :
+                       #
+                       # No - do we have it in -lpthread?
+                       #
+                       { $as_echo "$as_me:${as_lineno-$LINENO}: checking for pthread_create in -lpthread" >&5
+$as_echo_n "checking for pthread_create in -lpthread... " >&6; }
+if ${ac_cv_lib_pthread_pthread_create+:} false; then :
   $as_echo_n "(cached) " >&6
 else
-  while :; do
-  cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+  ac_check_lib_save_LIBS=$LIBS
+LIBS="-lpthread  $LIBS"
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
 /* end confdefs.h.  */
-#include <sys/types.h> /* for off_t */
-     #include <stdio.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 pthread_create ();
 int
 main ()
 {
-int (*fp) (FILE *, off_t, int) = fseeko;
-     return fseeko (stdin, 0, 0) && fp (stdin, 0, 0);
+return pthread_create ();
   ;
   return 0;
 }
 _ACEOF
 if ac_fn_c_try_link "$LINENO"; then :
-  ac_cv_sys_largefile_source=no; break
+  ac_cv_lib_pthread_pthread_create=yes
+else
+  ac_cv_lib_pthread_pthread_create=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_pthread_pthread_create" >&5
+$as_echo "$ac_cv_lib_pthread_pthread_create" >&6; }
+if test "x$ac_cv_lib_pthread_pthread_create" = xyes; then :
+
+                               #
+                               # Yes - add -lpthread.
+                               #
+                                ac_lbl_have_pthreads="found"
+                               PTHREAD_LIBS="$PTHREAD_LIBS -lpthread"
+
+else
+
+                               #
+                               # No.
+                               #
+                               ac_lbl_have_pthreads="not found"
+
+fi
+
+
+fi
+
+
+fi
+
+
+else
+
+       #
+       # We didn't find pthread.h.
+       #
+       ac_lbl_have_pthreads="not found"
+
+
+fi
+
+
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking if --disable-protochain option is specified" >&5
+$as_echo_n "checking if --disable-protochain option is specified... " >&6; }
+# Check whether --enable-protochain was given.
+if test "${enable_protochain+set}" = set; then :
+  enableval=$enable_protochain;
+fi
+
+case "x$enable_protochain" in
+xyes)  enable_protochain=enabled       ;;
+xno)   enable_protochain=disabled      ;;
+x)     enable_protochain=enabled       ;;
+esac
+
+if test "$enable_protochain" = "disabled"; then
+
+$as_echo "#define NO_PROTOCHAIN 1" >>confdefs.h
+
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: ${enable_protochain}" >&5
+$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_SRC=
+
+#
+# SITA support is mutually exclusive with native capture support;
+# "--with-sita" selects SITA support.
+#
+
+# Check whether --with-sita was given.
+if test "${with_sita+set}" = set; then :
+  withval=$with_sita;
+       if test ! "x$withval" = "xno" ; then
+
+$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
+       fi
+
+else
+
+
+# Check whether --with-pcap was given.
+if test "${with_pcap+set}" = set; then :
+  withval=$with_pcap;
+fi
+
+if test ! -z "$with_pcap" ; then
+       V_PCAP="$withval"
+else
+       #
+       # Check for a bunch of headers for various packet
+       # capture mechanisms.
+       #
+       for ac_header in net/bpf.h
+do :
+  ac_fn_c_check_header_mongrel "$LINENO" "net/bpf.h" "ac_cv_header_net_bpf_h" "$ac_includes_default"
+if test "x$ac_cv_header_net_bpf_h" = xyes; then :
+  cat >>confdefs.h <<_ACEOF
+#define HAVE_NET_BPF_H 1
+_ACEOF
+
+fi
+
+done
+
+       if test "$ac_cv_header_net_bpf_h" = yes; then
+               #
+               # Does it define BIOCSETIF?
+               # I.e., is it a header for an LBL/BSD-style capture
+               # mechanism, or is it just a header for a BPF filter
+               # engine?  Some versions of Arch Linux, for example,
+               # have a net/bpf.h that doesn't define BIOCSETIF;
+               # as it's a Linux, it should use packet sockets,
+               # instead.
+               #
+               # We need:
+               #
+               #  sys/types.h, because FreeBSD 10's net/bpf.h
+               #  requires that various BSD-style integer types
+               #  be defined;
+               #
+               #  sys/time.h, because AIX 5.2 and 5.3's net/bpf.h
+               #  doesn't include it but does use struct timeval
+               #  in ioctl definitions;
+               #
+               #  sys/ioctl.h and, if we have it, sys/ioccom.h,
+               #  because net/bpf.h defines ioctls;
+               #
+               #  net/if.h, because it defines some structures
+               #  used in ioctls defined by net/bpf.h;
+               #
+               #  sys/socket.h, because OpenBSD 5.9's net/bpf.h
+               #  defines some structure fields as being
+               #  struct sockaddrs;
+               #
+               # and net/bpf.h doesn't necessarily include all
+               # of those headers itself.
+               #
+               { $as_echo "$as_me:${as_lineno-$LINENO}: checking if net/bpf.h defines BIOCSETIF" >&5
+$as_echo_n "checking if net/bpf.h defines BIOCSETIF... " >&6; }
+               if ${ac_cv_lbl_bpf_h_defines_biocsetif+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
   cat confdefs.h - <<_ACEOF >conftest.$ac_ext
 /* end confdefs.h.  */
-#define _LARGEFILE_SOURCE 1
-#include <sys/types.h> /* for off_t */
-     #include <stdio.h>
+
+#include <sys/types.h>
+#include <sys/time.h>
+#include <sys/ioctl.h>
+#include <sys/socket.h>
+#ifdef HAVE_SYS_IOCCOM_H
+#include <sys/ioccom.h>
+#endif
+#include <net/bpf.h>
+#include <net/if.h>
+
 int
 main ()
 {
-int (*fp) (FILE *, off_t, int) = fseeko;
-     return fseeko (stdin, 0, 0) && fp (stdin, 0, 0);
+u_int i = BIOCSETIF;
   ;
   return 0;
 }
 _ACEOF
-if ac_fn_c_try_link "$LINENO"; then :
-  ac_cv_sys_largefile_source=1; break
+if ac_fn_c_try_compile "$LINENO"; then :
+  ac_cv_lbl_bpf_h_defines_biocsetif=yes
+else
+  ac_cv_lbl_bpf_h_defines_biocsetif=no
 fi
-rm -f core conftest.err conftest.$ac_objext \
-    conftest$ac_exeext conftest.$ac_ext
-  ac_cv_sys_largefile_source=unknown
-  break
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+fi
+
+               { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lbl_bpf_h_defines_biocsetif" >&5
+$as_echo "$ac_cv_lbl_bpf_h_defines_biocsetif" >&6; }
+       fi
+       for ac_header in net/pfilt.h net/enet.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"
+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
+
+       for ac_header in net/nit.h sys/net/nit.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"
+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
-{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_sys_largefile_source" >&5
-$as_echo "$ac_cv_sys_largefile_source" >&6; }
-case $ac_cv_sys_largefile_source in #(
-  no | unknown) ;;
-  *)
-cat >>confdefs.h <<_ACEOF
-#define _LARGEFILE_SOURCE $ac_cv_sys_largefile_source
+
+done
+
+       for ac_header in linux/socket.h net/raw.h sys/dlpi.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"
+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
-;;
-esac
-rm -rf conftest*
 
-# We used to try defining _XOPEN_SOURCE=500 too, to work around a bug
-# in glibc 2.1.3, but that breaks too many other things.
-# If you want fseeko and ftello with glibc, upgrade to a fixed glibc.
-if test $ac_cv_sys_largefile_source != unknown; then
+fi
 
-$as_echo "#define HAVE_FSEEKO 1" >>confdefs.h
+done
+
+
+       if test "$ac_cv_lbl_bpf_h_defines_biocsetif" = yes; then
+               #
+               # BPF.
+               # Check this before DLPI, so that we pick BPF on
+               # Solaris 11 and later.
+               #
+               V_PCAP=bpf
+
+               #
+               # We have BPF, so build valgrindtest with "make test"
+               # on macOS and FreeBSD (add your OS once there's a
+               # valgrind for it).
+               #
+               case "$host_os" in
+
+               freebsd*|darwin*|linux*)
+                       VALGRINDTEST_SRC=valgrindtest.c
+                       ;;
+               esac
+       elif test "$ac_cv_header_linux_socket_h" = yes; then
+               #
+               # No prizes for guessing this one.
+               #
+               V_PCAP=linux
 
+               #
+               # XXX - this won't work with older kernels that have
+               # SOCK_PACKET sockets but not PF_PACKET sockets.
+               #
+               VALGRINDTEST_SRC=valgrindtest.c
+       elif test "$ac_cv_header_net_pfilt_h" = yes; then
+               #
+               # DEC OSF/1, Digital UNIX, Tru64 UNIX
+               #
+               V_PCAP=pf
+       elif test "$ac_cv_header_net_enet_h" = yes; then
+               #
+               # Stanford Enetfilter.
+               #
+               V_PCAP=enet
+       elif test "$ac_cv_header_net_nit_h" = yes; then
+               #
+               # SunOS 4.x STREAMS NIT.
+               #
+               V_PCAP=snit
+       elif test "$ac_cv_header_sys_net_nit_h" = yes; then
+               #
+               # Pre-SunOS 4.x non-STREAMS NIT.
+               #
+               V_PCAP=nit
+       elif test "$ac_cv_header_net_raw_h" = yes; then
+               #
+               # IRIX snoop.
+               #
+               V_PCAP=snoop
+       elif test "$ac_cv_header_sys_dlpi_h" = yes; then
+               #
+               # DLPI on pre-Solaris 11 SunOS 5, HP-UX, possibly others.
+               #
+               V_PCAP=dlpi
+       else
+               #
+               # Nothing we support.
+               #
+               V_PCAP=null
+               { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: cannot determine packet capture interface" >&5
+$as_echo "$as_me: WARNING: cannot determine packet capture interface" >&2;}
+               { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: (see the INSTALL doc for more info)" >&5
+$as_echo "$as_me: WARNING: (see the INSTALL doc for more info)" >&2;}
+       fi
 fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking packet capture type" >&5
+$as_echo_n "checking packet capture type... " >&6; }
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $V_PCAP" >&5
+$as_echo "$V_PCAP" >&6; }
 
 
-for ac_header in sys/ioccom.h sys/sockio.h limits.h paths.h
+#
+# Do capture-mechanism-dependent tests.
+#
+case "$V_PCAP" in
+dlpi)
+       #
+       # Needed for common functions used by pcap-[dlpi,libdlpi].c
+       #
+       SSRC="dlpisubs.c"
+
+       #
+       # Checks for some header files.
+       #
+       for ac_header in sys/bufmod.h sys/dlpi_ext.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"
 
 done
 
-for ac_header in linux/types.h
-do :
-  ac_fn_c_check_header_mongrel "$LINENO" "linux/types.h" "ac_cv_header_linux_types_h" "$ac_includes_default"
-if test "x$ac_cv_header_linux_types_h" = xyes; then :
-  cat >>confdefs.h <<_ACEOF
-#define HAVE_LINUX_TYPES_H 1
-_ACEOF
-
-fi
 
-done
+       #
+       # 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.
+       # 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].
+       # Also, due to the bug above applications that link to libpcap with
+       # libdlpi will have to add "-L/lib" option to "configure".
+       #
+       saved_ldflags=$LDFLAGS
+       LDFLAGS="$LIBS -L/lib"
+       { $as_echo "$as_me:${as_lineno-$LINENO}: checking for dlpi_walk in -ldlpi" >&5
+$as_echo_n "checking for dlpi_walk in -ldlpi... " >&6; }
+if ${ac_cv_lib_dlpi_dlpi_walk+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  ac_check_lib_save_LIBS=$LIBS
+LIBS="-ldlpi  $LIBS"
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
 
-for ac_header in linux/if_packet.h netpacket/packet.h netpacket/if_packet.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"
-if eval test \"x\$"$as_ac_Header"\" = x"yes"; then :
-  cat >>confdefs.h <<_ACEOF
-#define `$as_echo "HAVE_$ac_header" | $as_tr_cpp` 1
+/* 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 dlpi_walk ();
+int
+main ()
+{
+return dlpi_walk ();
+  ;
+  return 0;
+}
 _ACEOF
-
+if ac_fn_c_try_link "$LINENO"; then :
+  ac_cv_lib_dlpi_dlpi_walk=yes
+else
+  ac_cv_lib_dlpi_dlpi_walk=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_dlpi_dlpi_walk" >&5
+$as_echo "$ac_cv_lib_dlpi_dlpi_walk" >&6; }
+if test "x$ac_cv_lib_dlpi_dlpi_walk" = xyes; then :
 
-done
+                       LIBS="-ldlpi $LIBS"
+                       V_PCAP=libdlpi
 
-for ac_header in net/pfvar.h
-do :
-  ac_fn_c_check_header_compile "$LINENO" "net/pfvar.h" "ac_cv_header_net_pfvar_h" "#include <sys/types.h>
-#include <sys/socket.h>
-#include <net/if.h>
-"
-if test "x$ac_cv_header_net_pfvar_h" = xyes; then :
-  cat >>confdefs.h <<_ACEOF
-#define HAVE_NET_PFVAR_H 1
-_ACEOF
+$as_echo "#define HAVE_LIBDLPI 1" >>confdefs.h
 
+
+else
+  V_PCAP=dlpi
 fi
 
-done
+       LDFLAGS=$saved_ldflags
 
-if test "$ac_cv_header_net_pfvar_h" = yes; then
        #
-       # Check for various PF actions.
+       # Checks whether <sys/dlpi.h> is usable, to catch weird SCO
+       # versions of DLPI.
        #
-       { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether net/pfvar.h defines PF_NAT through PF_NORDR" >&5
-$as_echo_n "checking whether net/pfvar.h defines PF_NAT through PF_NORDR... " >&6; }
-       cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+       { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether <sys/dlpi.h> is usable" >&5
+$as_echo_n "checking whether <sys/dlpi.h> is usable... " >&6; }
+       if ${ac_cv_sys_dlpi_usable+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  cat confdefs.h - <<_ACEOF >conftest.$ac_ext
 /* end confdefs.h.  */
-#include <sys/types.h>
-           #include <sys/socket.h>
-           #include <net/if.h>
-           #include <net/pfvar.h>
+
+                       #include <sys/types.h>
+                       #include <sys/time.h>
+                       #include <sys/dlpi.h>
+
 int
 main ()
 {
-return PF_NAT+PF_NONAT+PF_BINAT+PF_NOBINAT+PF_RDR+PF_NORDR;
+int i = DL_PROMISC_PHYS;
   ;
   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; }
-
-$as_echo "#define HAVE_PF_NAT_THROUGH_PF_NORDR 1" >>confdefs.h
-
-
+  ac_cv_sys_dlpi_usable=yes
 else
-  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
-$as_echo "no" >&6; }
+  ac_cv_sys_dlpi_usable=no
 fi
 rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
 fi
-for ac_header in netinet/if_ether.h
-do :
-  ac_fn_c_check_header_compile "$LINENO" "netinet/if_ether.h" "ac_cv_header_netinet_if_ether_h" "#include <sys/types.h>
-#include <sys/socket.h>
+
+       { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_sys_dlpi_usable" >&5
+$as_echo "$ac_cv_sys_dlpi_usable" >&6; }
+       if test $ac_cv_sys_dlpi_usable = no ; then
+               as_fn_error $? "<sys/dlpi.h> is not usable on this system; it probably has a non-standard DLPI" "$LINENO" 5
+       fi
+
+       #
+       # Check to see if Solaris has the dl_passive_req_t struct defined
+       # in <sys/dlpi.h>.
+       # This check is for DLPI support for passive modes.
+       # See dlpi(7P) for more details.
+       #
+       ac_fn_c_check_type "$LINENO" "dl_passive_req_t" "ac_cv_type_dl_passive_req_t" "
+               #include <sys/types.h>
+               #include <sys/dlpi.h>
+
 "
-if test "x$ac_cv_header_netinet_if_ether_h" = xyes; then :
-  cat >>confdefs.h <<_ACEOF
-#define HAVE_NETINET_IF_ETHER_H 1
+if test "x$ac_cv_type_dl_passive_req_t" = xyes; then :
+
+cat >>confdefs.h <<_ACEOF
+#define HAVE_DL_PASSIVE_REQ_T 1
 _ACEOF
 
+
 fi
 
-done
+       ;;
 
-if test "$ac_cv_header_netinet_if_ether_h" != yes; then
+linux)
        #
-       # The simple test didn't work.
-       # Do we need to include <net/if.h> first?
-       # Unset ac_cv_header_netinet_if_ether_h so we don't
-       # treat the previous failure as a cached value and
-       # suppress the next test.
+       # Do we have the wireless extensions?
        #
-       { $as_echo "$as_me:${as_lineno-$LINENO}: Rechecking with some additional includes" >&5
-$as_echo "$as_me: Rechecking with some additional includes" >&6;}
-       unset ac_cv_header_netinet_if_ether_h
-       for ac_header in netinet/if_ether.h
+       for ac_header in linux/wireless.h
 do :
-  ac_fn_c_check_header_compile "$LINENO" "netinet/if_ether.h" "ac_cv_header_netinet_if_ether_h" "#include <sys/types.h>
+  ac_fn_c_check_header_compile "$LINENO" "linux/wireless.h" "ac_cv_header_linux_wireless_h" "
 #include <sys/socket.h>
-#include <netinet/in.h>
-struct mbuf;
-struct rtentry;
-#include <net/if.h>
+#include <linux/if.h>
+#include <linux/types.h>
+
 "
-if test "x$ac_cv_header_netinet_if_ether_h" = xyes; then :
+if test "x$ac_cv_header_linux_wireless_h" = xyes; then :
   cat >>confdefs.h <<_ACEOF
-#define HAVE_NETINET_IF_ETHER_H 1
+#define HAVE_LINUX_WIRELESS_H 1
 _ACEOF
 
 fi
 
 done
 
+
+       #
+       # Do we have libnl?
+       #
+
+# Check whether --with-libnl was given.
+if test "${with_libnl+set}" = set; then :
+  withval=$with_libnl; with_libnl=$withval
+else
+  with_libnl=if_available
 fi
 
-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; }
-           if ${ac_cv_lbl_gcc_fixincludes+:} false; then :
+
+       if test x$with_libnl != xno ; then
+               have_any_nl="no"
+
+                incdir=-I/usr/include/libnl3
+                libnldir=
+                case "$with_libnl" in
+
+                yes|if_available)
+                  ;;
+
+                *)
+                  if test -d $withval; then
+                    libnldir=-L${withval}/lib/.libs
+                    incdir=-I${withval}/include
+                  fi
+                  ;;
+                esac
+
+               #
+               # Try libnl 3.x first.
+               #
+               { $as_echo "$as_me:${as_lineno-$LINENO}: checking for nl_socket_alloc in -lnl-3" >&5
+$as_echo_n "checking for nl_socket_alloc in -lnl-3... " >&6; }
+if ${ac_cv_lib_nl_3_nl_socket_alloc+:} false; then :
   $as_echo_n "(cached) " >&6
 else
-  cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+  ac_check_lib_save_LIBS=$LIBS
+LIBS="-lnl-3 ${incdir} ${libnldir} -lnl-genl-3 -lnl-3  $LIBS"
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
 /* end confdefs.h.  */
-/*
-                    * This generates a "duplicate case value" when fixincludes
-                    * has not be run.
-                    */
-#              include <sys/types.h>
-#              include <sys/time.h>
-#              include <sys/ioctl.h>
-#              ifdef HAVE_SYS_IOCCOM_H
-#              include <sys/ioccom.h>
-#              endif
+
+/* 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 nl_socket_alloc ();
 int
 main ()
 {
-switch (0) {
-                   case _IO('A', 1):;
-                   case _IO('B', 1):;
-                   }
+return nl_socket_alloc ();
   ;
   return 0;
 }
 _ACEOF
-if ac_fn_c_try_compile "$LINENO"; then :
-  ac_cv_lbl_gcc_fixincludes=yes
+if ac_fn_c_try_link "$LINENO"; then :
+  ac_cv_lib_nl_3_nl_socket_alloc=yes
 else
-  ac_cv_lbl_gcc_fixincludes=no
+  ac_cv_lib_nl_3_nl_socket_alloc=no
 fi
-rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+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_nl_3_nl_socket_alloc" >&5
+$as_echo "$ac_cv_lib_nl_3_nl_socket_alloc" >&6; }
+if test "x$ac_cv_lib_nl_3_nl_socket_alloc" = xyes; then :
 
-           { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lbl_gcc_fixincludes" >&5
-$as_echo "$ac_cv_lbl_gcc_fixincludes" >&6; }
-           if test $ac_cv_lbl_gcc_fixincludes = no ; then
-                   # Don't cache failure
-                   unset ac_cv_lbl_gcc_fixincludes
-                   as_fn_error $? "see the INSTALL for more info" "$LINENO" 5
-           fi
-    fi
-
-for ac_func in strerror strlcpy
-do :
-  as_ac_var=`$as_echo "ac_cv_func_$ac_func" | $as_tr_sh`
-ac_fn_c_check_func "$LINENO" "$ac_func" "$as_ac_var"
-if eval test \"x\$"$as_ac_var"\" = x"yes"; then :
-  cat >>confdefs.h <<_ACEOF
-#define `$as_echo "HAVE_$ac_func" | $as_tr_cpp` 1
-_ACEOF
+                       #
+                       # Yes, we have libnl 3.x.
+                       #
+                       LIBS="${libnldir} -lnl-genl-3 -lnl-3 $LIBS"
 
-fi
-done
+$as_echo "#define HAVE_LIBNL 1" >>confdefs.h
 
 
-needsnprintf=no
-for ac_func in vsnprintf snprintf
-do :
-  as_ac_var=`$as_echo "ac_cv_func_$ac_func" | $as_tr_sh`
-ac_fn_c_check_func "$LINENO" "$ac_func" "$as_ac_var"
-if eval test \"x\$"$as_ac_var"\" = x"yes"; then :
-  cat >>confdefs.h <<_ACEOF
-#define `$as_echo "HAVE_$ac_func" | $as_tr_cpp` 1
-_ACEOF
+$as_echo "#define HAVE_LIBNL_3_x 1" >>confdefs.h
 
-else
-  needsnprintf=yes
-fi
-done
 
-if test $needsnprintf = yes; then
-       case " $LIBOBJS " in
-  *" snprintf.$ac_objext "* ) ;;
-  *) LIBOBJS="$LIBOBJS snprintf.$ac_objext"
- ;;
-esac
+$as_echo "#define HAVE_LIBNL_NLE 1" >>confdefs.h
+
+
+$as_echo "#define HAVE_LIBNL_SOCKETS 1" >>confdefs.h
+
+                       V_INCLS="$V_INCLS ${incdir}"
+                       have_any_nl="yes"
 
 fi
 
-#
-# Do this before checking for ether_hostton(), as it's a
-# "gethostbyname() -ish function".
-#
 
-    # Most operating systems have gethostbyname() in the default searched
-    # libraries (i.e. libc):
-    # Some OSes (eg. Solaris) place it in libnsl
-    # Some strange OSes (SINIX) have it in libsocket:
-    { $as_echo "$as_me:${as_lineno-$LINENO}: checking for library containing gethostbyname" >&5
-$as_echo_n "checking for library containing gethostbyname... " >&6; }
-if ${ac_cv_search_gethostbyname+:} false; then :
+               if test x$have_any_nl = xno ; then
+                       #
+                       # Try libnl 2.x
+                       #
+                       { $as_echo "$as_me:${as_lineno-$LINENO}: checking for nl_socket_alloc in -lnl" >&5
+$as_echo_n "checking for nl_socket_alloc in -lnl... " >&6; }
+if ${ac_cv_lib_nl_nl_socket_alloc+:} false; then :
   $as_echo_n "(cached) " >&6
 else
-  ac_func_search_save_LIBS=$LIBS
+  ac_check_lib_save_LIBS=$LIBS
+LIBS="-lnl  $LIBS"
 cat confdefs.h - <<_ACEOF >conftest.$ac_ext
 /* end confdefs.h.  */
 
@@ -4811,58 +6617,61 @@ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
 #ifdef __cplusplus
 extern "C"
 #endif
-char gethostbyname ();
+char nl_socket_alloc ();
 int
 main ()
 {
-return gethostbyname ();
+return nl_socket_alloc ();
   ;
   return 0;
 }
 _ACEOF
-for ac_lib in '' nsl socket resolv; do
-  if test -z "$ac_lib"; then
-    ac_res="none required"
-  else
-    ac_res=-l$ac_lib
-    LIBS="-l$ac_lib  $ac_func_search_save_LIBS"
-  fi
-  if ac_fn_c_try_link "$LINENO"; then :
-  ac_cv_search_gethostbyname=$ac_res
+if ac_fn_c_try_link "$LINENO"; then :
+  ac_cv_lib_nl_nl_socket_alloc=yes
+else
+  ac_cv_lib_nl_nl_socket_alloc=no
 fi
 rm -f core conftest.err conftest.$ac_objext \
-    conftest$ac_exeext
-  if ${ac_cv_search_gethostbyname+:} false; then :
-  break
+    conftest$ac_exeext conftest.$ac_ext
+LIBS=$ac_check_lib_save_LIBS
 fi
-done
-if ${ac_cv_search_gethostbyname+:} false; then :
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_nl_nl_socket_alloc" >&5
+$as_echo "$ac_cv_lib_nl_nl_socket_alloc" >&6; }
+if test "x$ac_cv_lib_nl_nl_socket_alloc" = xyes; then :
 
-else
-  ac_cv_search_gethostbyname=no
-fi
-rm conftest.$ac_ext
-LIBS=$ac_func_search_save_LIBS
-fi
-{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_search_gethostbyname" >&5
-$as_echo "$ac_cv_search_gethostbyname" >&6; }
-ac_res=$ac_cv_search_gethostbyname
-if test "$ac_res" != no; then :
-  test "$ac_res" = "none required" || LIBS="$ac_res $LIBS"
+                               #
+                               # Yes, we have libnl 2.x.
+                               #
+                               LIBS="${libnldir} -lnl-genl -lnl $LIBS"
+
+$as_echo "#define HAVE_LIBNL 1" >>confdefs.h
+
+
+$as_echo "#define HAVE_LIBNL_2_x 1" >>confdefs.h
+
+
+$as_echo "#define HAVE_LIBNL_NLE 1" >>confdefs.h
+
+
+$as_echo "#define HAVE_LIBNL_SOCKETS 1" >>confdefs.h
+
+                               have_any_nl="yes"
 
 fi
 
-    # Unfortunately libsocket sometimes depends on libnsl and
-    # AC_SEARCH_LIBS isn't up to the task of handling dependencies like this.
-    if test "$ac_cv_search_gethostbyname" = "no"
-    then
-       { $as_echo "$as_me:${as_lineno-$LINENO}: checking for gethostbyname in -lsocket" >&5
-$as_echo_n "checking for gethostbyname in -lsocket... " >&6; }
-if ${ac_cv_lib_socket_gethostbyname+:} false; then :
+               fi
+
+               if test x$have_any_nl = xno ; then
+                       #
+                       # No, we don't; do we have libnl 1.x?
+                       #
+                       { $as_echo "$as_me:${as_lineno-$LINENO}: checking for nl_handle_alloc in -lnl" >&5
+$as_echo_n "checking for nl_handle_alloc in -lnl... " >&6; }
+if ${ac_cv_lib_nl_nl_handle_alloc+:} false; then :
   $as_echo_n "(cached) " >&6
 else
   ac_check_lib_save_LIBS=$LIBS
-LIBS="-lsocket -lnsl $LIBS"
+LIBS="-lnl  $LIBS"
 cat confdefs.h - <<_ACEOF >conftest.$ac_ext
 /* end confdefs.h.  */
 
@@ -4872,433 +6681,440 @@ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
 #ifdef __cplusplus
 extern "C"
 #endif
-char gethostbyname ();
+char nl_handle_alloc ();
 int
 main ()
 {
-return gethostbyname ();
+return nl_handle_alloc ();
   ;
   return 0;
 }
 _ACEOF
 if ac_fn_c_try_link "$LINENO"; then :
-  ac_cv_lib_socket_gethostbyname=yes
+  ac_cv_lib_nl_nl_handle_alloc=yes
 else
-  ac_cv_lib_socket_gethostbyname=no
+  ac_cv_lib_nl_nl_handle_alloc=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_socket_gethostbyname" >&5
-$as_echo "$ac_cv_lib_socket_gethostbyname" >&6; }
-if test "x$ac_cv_lib_socket_gethostbyname" = xyes; then :
-  LIBS="-lsocket -lnsl $LIBS"
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_nl_nl_handle_alloc" >&5
+$as_echo "$ac_cv_lib_nl_nl_handle_alloc" >&6; }
+if test "x$ac_cv_lib_nl_nl_handle_alloc" = xyes; then :
+
+                               #
+                               # Yes.
+                               #
+                               LIBS="${libnldir} -lnl $LIBS"
+
+$as_echo "#define HAVE_LIBNL 1" >>confdefs.h
+
+                               have_any_nl="yes"
+
+fi
+
+               fi
+
+               if test x$have_any_nl = xno ; then
+                       #
+                       # No, we don't have libnl at all.
+                       #
+                       if test x$with_libnl = xyes ; then
+                               as_fn_error $? "libnl support requested but libnl not found" "$LINENO" 5
+                       fi
+               fi
+       fi
+
+       for ac_header in linux/ethtool.h
+do :
+  ac_fn_c_check_header_compile "$LINENO" "linux/ethtool.h" "ac_cv_header_linux_ethtool_h" "
+$ac_includes_default
+#include <linux/types.h>
+
+"
+if test "x$ac_cv_header_linux_ethtool_h" = xyes; then :
+  cat >>confdefs.h <<_ACEOF
+#define HAVE_LINUX_ETHTOOL_H 1
+_ACEOF
+
+fi
+
+done
+
+
+       #
+       # Check to see if struct tpacket_stats is defined in
+       # <linux/if_packet.h>.  If so, then pcap-linux.c can use this
+       # to report proper statistics.
+       #
+       # -Scott Barron
+       #
+       ac_fn_c_check_type "$LINENO" "struct tpacket_stats" "ac_cv_type_struct_tpacket_stats" "
+               #include <linux/if_packet.h>
+
+"
+if test "x$ac_cv_type_struct_tpacket_stats" = xyes; then :
+
+cat >>confdefs.h <<_ACEOF
+#define HAVE_STRUCT_TPACKET_STATS 1
+_ACEOF
+
+
+fi
+
+
+       #
+       # Check to see if the tpacket_auxdata struct has a tp_vlan_tci member.
+       #
+       # NOTE: any failure means we conclude that it doesn't have that
+       # member, so if we don't have tpacket_auxdata, we conclude it
+       # doesn't have that member (which is OK, as either we won't be
+       # using code that would use that member, or we wouldn't compile
+       # in any case).
+       ac_fn_c_check_member "$LINENO" "struct tpacket_auxdata" "tp_vlan_tci" "ac_cv_member_struct_tpacket_auxdata_tp_vlan_tci" "
+               #include <sys/types.h>
+               #include <linux/if_packet.h>
+
+"
+if test "x$ac_cv_member_struct_tpacket_auxdata_tp_vlan_tci" = xyes; then :
+
+cat >>confdefs.h <<_ACEOF
+#define HAVE_STRUCT_TPACKET_AUXDATA_TP_VLAN_TCI 1
+_ACEOF
+
+
+fi
+
+       ;;
+
+bpf)
+       #
+       # Check whether we have the *BSD-style ioctls.
+       #
+       for ac_header in net/if_media.h
+do :
+  ac_fn_c_check_header_mongrel "$LINENO" "net/if_media.h" "ac_cv_header_net_if_media_h" "$ac_includes_default"
+if test "x$ac_cv_header_net_if_media_h" = xyes; then :
+  cat >>confdefs.h <<_ACEOF
+#define HAVE_NET_IF_MEDIA_H 1
+_ACEOF
+
+fi
+
+done
+
+
+       #
+       # Check whether we have struct BPF_TIMEVAL.
+       #
+       ac_fn_c_check_type "$LINENO" "struct BPF_TIMEVAL" "ac_cv_type_struct_BPF_TIMEVAL" "
+               #include <sys/types.h>
+               #include <sys/ioctl.h>
+               #ifdef HAVE_SYS_IOCCOM_H
+               #include <sys/ioccom.h>
+               #endif
+               #include <net/bpf.h>
+
+"
+if test "x$ac_cv_type_struct_BPF_TIMEVAL" = xyes; then :
+
+cat >>confdefs.h <<_ACEOF
+#define HAVE_STRUCT_BPF_TIMEVAL 1
+_ACEOF
+
+
+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)
+       ;;
+
+*)
+       as_fn_error $? "$V_PCAP is not a valid pcap type" "$LINENO" 5
+       ;;
+esac
+
+if test "$V_PCAP" != null
+then
+       ac_fn_c_check_func "$LINENO" "getifaddrs" "ac_cv_func_getifaddrs"
+if test "x$ac_cv_func_getifaddrs" = xyes; then :
+
+               #
+               # We have "getifaddrs()"; make sure we have <ifaddrs.h>
+               # as well, just in case some platform is really weird.
+               #
+               ac_fn_c_check_header_mongrel "$LINENO" "ifaddrs.h" "ac_cv_header_ifaddrs_h" "$ac_includes_default"
+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=fad-getad.c
+
+else
+
+                   #
+                   # We don't have the header - give up.
+                   # XXX - we could also fall back on some other
+                   # mechanism, but, for now, this'll catch this
+                   # problem so that we can at least try to figure
+                   # out something to do on systems with "getifaddrs()"
+                   # but without "ifaddrs.h", if there is something
+                   # we can do on those systems.
+                   #
+                   as_fn_error $? "Your system has getifaddrs() but doesn't have a usable <ifaddrs.h>." "$LINENO" 5
+
 fi
 
-    fi
-    { $as_echo "$as_me:${as_lineno-$LINENO}: checking for library containing socket" >&5
-$as_echo_n "checking for library containing socket... " >&6; }
-if ${ac_cv_search_socket+:} false; then :
-  $as_echo_n "(cached) " >&6
-else
-  ac_func_search_save_LIBS=$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 socket ();
-int
-main ()
-{
-return socket ();
-  ;
-  return 0;
-}
-_ACEOF
-for ac_lib in '' socket; do
-  if test -z "$ac_lib"; then
-    ac_res="none required"
-  else
-    ac_res=-l$ac_lib
-    LIBS="-l$ac_lib  $ac_func_search_save_LIBS"
-  fi
-  if ac_fn_c_try_link "$LINENO"; then :
-  ac_cv_search_socket=$ac_res
-fi
-rm -f core conftest.err conftest.$ac_objext \
-    conftest$ac_exeext
-  if ${ac_cv_search_socket+:} false; then :
-  break
-fi
-done
-if ${ac_cv_search_socket+:} false; then :
 
 else
-  ac_cv_search_socket=no
-fi
-rm conftest.$ac_ext
-LIBS=$ac_func_search_save_LIBS
-fi
-{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_search_socket" >&5
-$as_echo "$ac_cv_search_socket" >&6; }
-ac_res=$ac_cv_search_socket
-if test "$ac_res" != no; then :
-  test "$ac_res" = "none required" || LIBS="$ac_res $LIBS"
 
-else
-  { $as_echo "$as_me:${as_lineno-$LINENO}: checking for socket in -lsocket" >&5
-$as_echo_n "checking for socket in -lsocket... " >&6; }
-if ${ac_cv_lib_socket_socket+:} false; then :
+               #
+               # Well, we don't have "getifaddrs()", at least not with the
+               # libraries with which we've decided we need to link
+               # libpcap with, so we have to use some other mechanism.
+               #
+               # Note that this may happen on Solaris, which has
+               # getifaddrs(), but in -lsocket, not in -lxnet, so we
+               # won't find it if we link with -lxnet, which we want
+               # to do for other reasons.
+               #
+               # For now, we use either the SIOCGIFCONF ioctl or the
+               # SIOCGLIFCONF ioctl, preferring the latter if we have
+               # it; the latter is a Solarisism that first appeared
+               # in Solaris 8.  (Solaris's getifaddrs() appears to
+               # be built atop SIOCGLIFCONF; using it directly
+               # avoids a not-all-that-useful middleman.)
+               #
+               { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether we have SIOCGLIFCONF" >&5
+$as_echo_n "checking whether we have SIOCGLIFCONF... " >&6; }
+               if ${ac_cv_lbl_have_siocglifconf+:} false; then :
   $as_echo_n "(cached) " >&6
 else
-  ac_check_lib_save_LIBS=$LIBS
-LIBS="-lsocket -lnsl $LIBS"
-cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+  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 socket ();
+#include <sys/param.h>
+                       #include <sys/file.h>
+                       #include <sys/ioctl.h>
+                       #include <sys/socket.h>
+                       #include <sys/sockio.h>
 int
 main ()
 {
-return socket ();
+ioctl(0, SIOCGLIFCONF, (char *)0);
   ;
   return 0;
 }
 _ACEOF
-if ac_fn_c_try_link "$LINENO"; then :
-  ac_cv_lib_socket_socket=yes
+if ac_fn_c_try_compile "$LINENO"; then :
+  ac_cv_lbl_have_siocglifconf=yes
 else
-  ac_cv_lib_socket_socket=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_socket_socket" >&5
-$as_echo "$ac_cv_lib_socket_socket" >&6; }
-if test "x$ac_cv_lib_socket_socket" = xyes; then :
-  LIBS="-lsocket -lnsl $LIBS"
+  ac_cv_lbl_have_siocglifconf=no
 fi
-
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
 fi
 
-    # DLPI needs putmsg under HPUX so test for -lstr while we're at it
-    { $as_echo "$as_me:${as_lineno-$LINENO}: checking for library containing putmsg" >&5
-$as_echo_n "checking for library containing putmsg... " >&6; }
-if ${ac_cv_search_putmsg+:} false; then :
-  $as_echo_n "(cached) " >&6
-else
-  ac_func_search_save_LIBS=$LIBS
-cat confdefs.h - <<_ACEOF >conftest.$ac_ext
-/* end confdefs.h.  */
+               { $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=fad-glifc.c
+               else
+                       V_FINDALLDEVS=fad-gifc.c
+               fi
 
-/* 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 putmsg ();
-int
-main ()
-{
-return putmsg ();
-  ;
-  return 0;
-}
-_ACEOF
-for ac_lib in '' str; do
-  if test -z "$ac_lib"; then
-    ac_res="none required"
-  else
-    ac_res=-l$ac_lib
-    LIBS="-l$ac_lib  $ac_func_search_save_LIBS"
-  fi
-  if ac_fn_c_try_link "$LINENO"; then :
-  ac_cv_search_putmsg=$ac_res
-fi
-rm -f core conftest.err conftest.$ac_objext \
-    conftest$ac_exeext
-  if ${ac_cv_search_putmsg+:} false; then :
-  break
 fi
-done
-if ${ac_cv_search_putmsg+:} false; then :
 
-else
-  ac_cv_search_putmsg=no
-fi
-rm conftest.$ac_ext
-LIBS=$ac_func_search_save_LIBS
 fi
-{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_search_putmsg" >&5
-$as_echo "$ac_cv_search_putmsg" >&6; }
-ac_res=$ac_cv_search_putmsg
-if test "$ac_res" != no; then :
-  test "$ac_res" = "none required" || LIBS="$ac_res $LIBS"
 
 fi
 
 
-
-#
-# You are in a twisty little maze of UN*Xes, all different.
-# Some might not have ether_hostton().
-# Some might have it, but not declare it in any header file.
-# Some might have it, but declare it in <netinet/if_ether.h>.
-# Some might have it, but declare it in <netinet/ether.h>
-# (And some might have it but document it as something declared in
-# <netinet/ethernet.h>, although <netinet/if_ether.h> appears to work.)
-#
-# Before you is a C compiler.
-#
-for ac_func in ether_hostton
+case "$host_os" in
+linux*)
+       for ac_header in linux/net_tstamp.h
 do :
-  ac_fn_c_check_func "$LINENO" "ether_hostton" "ac_cv_func_ether_hostton"
-if test "x$ac_cv_func_ether_hostton" = xyes; then :
+  ac_fn_c_check_header_mongrel "$LINENO" "linux/net_tstamp.h" "ac_cv_header_linux_net_tstamp_h" "$ac_includes_default"
+if test "x$ac_cv_header_linux_net_tstamp_h" = xyes; then :
   cat >>confdefs.h <<_ACEOF
-#define HAVE_ETHER_HOSTTON 1
+#define HAVE_LINUX_NET_TSTAMP_H 1
 _ACEOF
 
 fi
-done
 
-if test "$ac_cv_func_ether_hostton" = yes; then
-       #
-       # OK, we have ether_hostton().  Do we have <netinet/if_ether.h>?
-       #
-       if test "$ac_cv_header_netinet_if_ether_h" = yes; then
-               #
-               # Yes.  Does it declare ether_hostton()?
-               #
-               ac_fn_c_check_decl "$LINENO" "ether_hostton" "ac_cv_have_decl_ether_hostton" "
-#include <sys/types.h>
-#include <sys/socket.h>
-#include <netinet/in.h>
-#include <arpa/inet.h>
-struct mbuf;
-struct rtentry;
-#include <net/if.h>
-#include <netinet/if_ether.h>
+done
 
-"
-if test "x$ac_cv_have_decl_ether_hostton" = xyes; then :
+       ;;
+*)
+       { $as_echo "$as_me:${as_lineno-$LINENO}: no hardware timestamp support implemented for $host_os" >&5
+$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
 
-$as_echo "#define NETINET_IF_ETHER_H_DECLARES_ETHER_HOSTTON /**/" >>confdefs.h
 
+if test "x$enable_packet_ring" != "xno" ; then
 
-fi
+$as_echo "#define PCAP_SUPPORT_PACKET_RING 1" >>confdefs.h
 
-       fi
-       #
-       # Did that succeed?
-       #
-       if test "$ac_cv_have_decl_ether_hostton" != yes; then
-               #
-               # No, how about <netinet/ether.h>, as on Linux?
-               #
-               for ac_header in netinet/ether.h
-do :
-  ac_fn_c_check_header_mongrel "$LINENO" "netinet/ether.h" "ac_cv_header_netinet_ether_h" "$ac_includes_default"
-if test "x$ac_cv_header_netinet_ether_h" = xyes; then :
-  cat >>confdefs.h <<_ACEOF
-#define HAVE_NETINET_ETHER_H 1
-_ACEOF
 
 fi
 
-done
-
-               if test "$ac_cv_header_netinet_ether_h" = yes; then
-                       #
-                       # We have it - does it declare ether_hostton()?
-                       # Unset ac_cv_have_decl_ether_hostton so we don't
-                       # treat the previous failure as a cached value and
-                       # suppress the next test.
-                       #
-                       unset ac_cv_have_decl_ether_hostton
-                       ac_fn_c_check_decl "$LINENO" "ether_hostton" "ac_cv_have_decl_ether_hostton" "
-#include <netinet/ether.h>
+#
+# Check for socklen_t.
+#
+ac_fn_c_check_type "$LINENO" "socklen_t" "ac_cv_type_socklen_t" "
+       #include <sys/types.h>
+       #include <sys/socket.h>
 
 "
-if test "x$ac_cv_have_decl_ether_hostton" = xyes; then :
+if test "x$ac_cv_type_socklen_t" = xyes; then :
+
+cat >>confdefs.h <<_ACEOF
+#define HAVE_SOCKLEN_T 1
+_ACEOF
 
 
-$as_echo "#define NETINET_ETHER_H_DECLARES_ETHER_HOSTTON /**/" >>confdefs.h
+fi
 
 
+# Check whether --enable-ipv6 was given.
+if test "${enable_ipv6+set}" = set; then :
+  enableval=$enable_ipv6;
+else
+  enable_ipv6=yes
 fi
 
-               fi
-       fi
+if test "$enable_ipv6" != "no"; then
        #
-       # Is ether_hostton() declared?
+       # We've already made sure we have getaddrinfo above in
+       # AC_LBL_LIBRARY_NET.
        #
-       if test "$ac_cv_have_decl_ether_hostton" != yes; then
-               #
-               # No, we'll have to declare it ourselves.
-               # Do we have "struct ether_addr"?
-               #
-               ac_fn_c_check_type "$LINENO" "struct ether_addr" "ac_cv_type_struct_ether_addr" "
-#include <sys/types.h>
-#include <sys/socket.h>
-#include <netinet/in.h>
-#include <arpa/inet.h>
-struct mbuf;
-struct rtentry;
-#include <net/if.h>
-#include <netinet/if_ether.h>
-
-"
-if test "x$ac_cv_type_struct_ether_addr" = xyes; then :
-
-cat >>confdefs.h <<_ACEOF
-#define HAVE_STRUCT_ETHER_ADDR 1
-_ACEOF
 
+$as_echo "#define INET6 1" >>confdefs.h
 
 fi
 
+# Check for Endace DAG card support.
 
-$as_echo "#define HAVE_DECL_ETHER_HOSTTON 0" >>confdefs.h
-
+# Check whether --with-dag was given.
+if test "${with_dag+set}" = set; then :
+  withval=$with_dag;
+       if test "$withval" = no
+       then
+               # User doesn't want DAG support.
+               want_dag=no
+       elif test "$withval" = yes
+       then
+               # User wants DAG support but hasn't specified a directory.
+               want_dag=yes
        else
+               # User wants DAG support and has specified a directory, so use the provided value.
+               want_dag=yes
+               dag_root=$withval
+       fi
 
-$as_echo "#define HAVE_DECL_ETHER_HOSTTON 1" >>confdefs.h
+else
 
+       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
-
-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking if --disable-protochain option is specified" >&5
-$as_echo_n "checking if --disable-protochain option is specified... " >&6; }
-# Check whether --enable-protochain was given.
-if test "${enable_protochain+set}" = set; then :
-  enableval=$enable_protochain;
-fi
 
-case "x$enable_protochain" in
-xyes)  enable_protochain=enabled       ;;
-xno)   enable_protochain=disabled      ;;
-x)     enable_protochain=enabled       ;;
-esac
+fi
 
-if test "$enable_protochain" = "disabled"; then
 
-$as_echo "#define NO_PROTOCHAIN 1" >>confdefs.h
+
+# Check whether --with-dag-includes was given.
+if test "${with_dag_includes+set}" = set; then :
+  withval=$with_dag_includes;
+       # User wants DAG support and has specified a header directory, so use the provided value.
+       want_dag=yes
+       dag_include_dir=$withval
 
 fi
-{ $as_echo "$as_me:${as_lineno-$LINENO}: result: ${enable_protochain}" >&5
-$as_echo "${enable_protochain}" >&6; }
 
-#
-# SITA support is mutually exclusive with native capture support;
-# "--with-sita" selects SITA support.
-#
 
-# Check whether --with-sita was given.
-if test "${with_sita+set}" = set; then :
-  withval=$with_sita;
-       if test ! "x$withval" = "xno" ; then
 
-$as_echo "#define SITA 1" >>confdefs.h
+# Check whether --with-dag-libraries was given.
+if test "${with_dag_libraries+set}" = set; then :
+  withval=$with_dag_libraries;
+       # User wants DAG support and has specified a library directory, so use the provided value.
+       want_dag=yes
+       dag_lib_dir=$withval
 
-               { $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
+fi
 
-else
 
-if test -z "$with_pcap" && test "$cross_compiling" = yes; then
-       as_fn_error $? "pcap type not determined when cross-compiling; use --with-pcap=..." "$LINENO" 5
-fi
+if test "$want_dag" != no; then
 
-# Check whether --with-pcap was given.
-if test "${with_pcap+set}" = set; then :
-  withval=$with_pcap;
-fi
+       # If necessary, set default paths for DAG API headers and libraries.
+       if test -z "$dag_root"; then
+               dag_root=/usr/local
+       fi
 
-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking packet capture type" >&5
-$as_echo_n "checking packet capture type... " >&6; }
-if test ! -z "$with_pcap" ; then
-       V_PCAP="$withval"
-elif test -r /dev/bpf -o -h /dev/bpf ; then
-       #
-       # Cloning BPF device.
-       #
-       V_PCAP=bpf
-
-$as_echo "#define HAVE_CLONING_BPF 1" >>confdefs.h
-
-elif test -r /dev/bpf0 ; then
-       V_PCAP=bpf
-elif test -r /usr/include/net/pfilt.h ; then
-       V_PCAP=pf
-elif test -r /dev/enet ; then
-       V_PCAP=enet
-elif test -r /dev/nit ; then
-       V_PCAP=snit
-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
-elif test -r /usr/include/net/raw.h ; then
-       V_PCAP=snoop
-elif test -r /usr/include/odmi.h ; then
-       #
-       # On AIX, the BPF devices might not yet be present - they're
-       # created the first time libpcap runs after booting.
-       # We check for odmi.h instead.
-       #
-       V_PCAP=bpf
-elif test -c /dev/bpf0 ; then          # check again in case not readable
-       V_PCAP=bpf
-elif test -r /usr/include/sys/dlpi.h ; then
-       V_PCAP=dlpi
-elif test -c /dev/enet ; then          # check again in case not readable
-       V_PCAP=enet
-elif test -c /dev/nit ; then           # check again in case not readable
-       V_PCAP=snit
-else
-       V_PCAP=null
-fi
-{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $V_PCAP" >&5
-$as_echo "$V_PCAP" >&6; }
+       if test -z "$dag_include_dir"; then
+               dag_include_dir="$dag_root/include"
+       fi
 
-#
-# Do capture-mechanism-dependent tests.
-#
-case "$V_PCAP" in
-dlpi)
-       #
-       # Needed for common functions used by pcap-[dlpi,libdlpi].c
-       #
-       SSRC="dlpisubs.c"
+       if test -z "$dag_lib_dir"; then
+               dag_lib_dir="$dag_root/lib"
+       fi
 
-       #
-       # Checks for some header files.
-       #
-       for ac_header in sys/bufmod.h sys/dlpi_ext.h
+       V_INCLS="$V_INCLS -I$dag_include_dir"
+
+       for ac_header in dagapi.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"
-if eval test \"x\$"$as_ac_Header"\" = x"yes"; then :
+  ac_fn_c_check_header_mongrel "$LINENO" "dagapi.h" "ac_cv_header_dagapi_h" "$ac_includes_default"
+if test "x$ac_cv_header_dagapi_h" = xyes; then :
   cat >>confdefs.h <<_ACEOF
-#define `$as_echo "HAVE_$ac_header" | $as_tr_cpp` 1
+#define HAVE_DAGAPI_H 1
 _ACEOF
 
 fi
@@ -5306,26 +7122,24 @@ fi
 done
 
 
-       #
-       # 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.
-       # 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].
-       # Also, due to the bug above applications that link to libpcap with
-       # libdlpi will have to add "-L/lib" option to "configure".
-       #
-       saved_ldflags=$LDFLAGS
-       LDFLAGS="$LIBS -L/lib"
-       { $as_echo "$as_me:${as_lineno-$LINENO}: checking for dlpi_walk in -ldlpi" >&5
-$as_echo_n "checking for dlpi_walk in -ldlpi... " >&6; }
-if ${ac_cv_lib_dlpi_dlpi_walk+:} false; then :
+       if test "$ac_cv_header_dagapi_h" = yes; then
+
+               if test $V_PCAP != dag ; then
+                        SSRC="$SSRC pcap-dag.c"
+               fi
+
+               # Check for various DAG API functions.
+               # 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
 else
   ac_check_lib_save_LIBS=$LIBS
-LIBS="-ldlpi  $LIBS"
+LIBS="-ldag  $LIBS"
 cat confdefs.h - <<_ACEOF >conftest.$ac_ext
 /* end confdefs.h.  */
 
@@ -5335,193 +7149,129 @@ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
 #ifdef __cplusplus
 extern "C"
 #endif
-char dlpi_walk ();
+char dag_attach_stream ();
 int
 main ()
 {
-return dlpi_walk ();
+return dag_attach_stream ();
   ;
   return 0;
 }
 _ACEOF
 if ac_fn_c_try_link "$LINENO"; then :
-  ac_cv_lib_dlpi_dlpi_walk=yes
+  ac_cv_lib_dag_dag_attach_stream=yes
 else
-  ac_cv_lib_dlpi_dlpi_walk=no
+  ac_cv_lib_dag_dag_attach_stream=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_dlpi_dlpi_walk" >&5
-$as_echo "$ac_cv_lib_dlpi_dlpi_walk" >&6; }
-if test "x$ac_cv_lib_dlpi_dlpi_walk" = xyes; then :
-
-                       LIBS="-ldlpi $LIBS"
-                       V_PCAP=libdlpi
-
-$as_echo "#define HAVE_LIBDLPI 1" >>confdefs.h
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_dag_dag_attach_stream" >&5
+$as_echo "$ac_cv_lib_dag_dag_attach_stream" >&6; }
+if test "x$ac_cv_lib_dag_dag_attach_stream" = xyes; then :
+  cat >>confdefs.h <<_ACEOF
+#define HAVE_LIBDAG 1
+_ACEOF
 
+  LIBS="-ldag $LIBS"
 
 else
-  V_PCAP=dlpi
+  as_fn_error $? "DAG library lacks streams support" "$LINENO" 5
 fi
 
-       LDFLAGS=$saved_ldflags
-
-       #
-       # Checks whether <sys/dlpi.h> is usable, to catch weird SCO
-       # versions of DLPI.
-       #
-       { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether <sys/dlpi.h> is usable" >&5
-$as_echo_n "checking whether <sys/dlpi.h> is usable... " >&6; }
-       if ${ac_cv_sys_dlpi_usable+:} false; then :
+               { $as_echo "$as_me:${as_lineno-$LINENO}: checking for dag_attach_stream64 in -ldag" >&5
+$as_echo_n "checking for dag_attach_stream64 in -ldag... " >&6; }
+if ${ac_cv_lib_dag_dag_attach_stream64+:} false; then :
   $as_echo_n "(cached) " >&6
 else
-  cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+  ac_check_lib_save_LIBS=$LIBS
+LIBS="-ldag  $LIBS"
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
 /* end confdefs.h.  */
 
-                       #include <sys/types.h>
-                       #include <sys/time.h>
-                       #include <sys/dlpi.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 dag_attach_stream64 ();
 int
 main ()
 {
-int i = DL_PROMISC_PHYS;
+return dag_attach_stream64 ();
   ;
   return 0;
 }
 _ACEOF
-if ac_fn_c_try_compile "$LINENO"; then :
-  ac_cv_sys_dlpi_usable=yes
+if ac_fn_c_try_link "$LINENO"; then :
+  ac_cv_lib_dag_dag_attach_stream64=yes
 else
-  ac_cv_sys_dlpi_usable=no
+  ac_cv_lib_dag_dag_attach_stream64=no
 fi
-rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+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_dag_dag_attach_stream64" >&5
+$as_echo "$ac_cv_lib_dag_dag_attach_stream64" >&6; }
+if test "x$ac_cv_lib_dag_dag_attach_stream64" = xyes; then :
+  dag_large_streams="1"
+else
+  dag_large_streams="0"
 fi
 
-       { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_sys_dlpi_usable" >&5
-$as_echo "$ac_cv_sys_dlpi_usable" >&6; }
-       if test $ac_cv_sys_dlpi_usable = no ; then
-               as_fn_error $? "<sys/dlpi.h> is not usable on this system; it probably has a non-standard DLPI" "$LINENO" 5
-       fi
-
-       #
-       # Check whether we have a /dev/dlpi device or have multiple devices.
-       #
-       { $as_echo "$as_me:${as_lineno-$LINENO}: checking for /dev/dlpi device" >&5
-$as_echo_n "checking for /dev/dlpi device... " >&6; }
-       if test -c /dev/dlpi ; then
-               { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
-$as_echo "yes" >&6; }
-
-$as_echo "#define HAVE_DEV_DLPI 1" >>confdefs.h
-
-       else
-               { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
-$as_echo "no" >&6; }
-               dir="/dev/dlpi"
-               { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $dir directory" >&5
-$as_echo_n "checking for $dir directory... " >&6; }
-               if test -d $dir ; then
-                       { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
-$as_echo "yes" >&6; }
-
-cat >>confdefs.h <<_ACEOF
-#define PCAP_DEV_PREFIX "$dir"
-_ACEOF
-
-               else
-                       { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
-$as_echo "no" >&6; }
-               fi
-       fi
-
-       #
-       # This check is for Solaris with DLPI support for passive modes.
-       # See dlpi(7P) for more details.
-       #
-       { $as_echo "$as_me:${as_lineno-$LINENO}: checking if dl_passive_req_t struct exists" >&5
-$as_echo_n "checking if dl_passive_req_t struct exists... " >&6; }
-       if ${ac_cv_lbl_has_dl_passive_req_t+:} false; then :
+               { $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
 else
-  cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+  ac_check_lib_save_LIBS=$LIBS
+LIBS="-ldag  $LIBS"
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
 /* end confdefs.h.  */
 
-#       include <sys/types.h>
-#       include <sys/dlpi.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 dag_get_erf_types ();
 int
 main ()
 {
-u_int i = sizeof(dl_passive_req_t)
+return dag_get_erf_types ();
   ;
   return 0;
 }
 _ACEOF
-if ac_fn_c_try_compile "$LINENO"; then :
-  ac_cv_lbl_has_dl_passive_req_t=yes
+if ac_fn_c_try_link "$LINENO"; then :
+  ac_cv_lib_dag_dag_get_erf_types=yes
 else
-  ac_cv_lbl_has_dl_passive_req_t=no
-fi
-rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+  ac_cv_lib_dag_dag_get_erf_types=no
 fi
-
-    { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lbl_has_dl_passive_req_t" >&5
-$as_echo "$ac_cv_lbl_has_dl_passive_req_t" >&6; }
-    if test $ac_cv_lbl_has_dl_passive_req_t = yes ; then
-
-$as_echo "#define HAVE_DLPI_PASSIVE 1" >>confdefs.h
-
-    fi
-       ;;
-
-linux)
-       #
-       # Do we have the wireless extensions?
-       #
-       for ac_header in linux/wireless.h
-do :
-  ac_fn_c_check_header_compile "$LINENO" "linux/wireless.h" "ac_cv_header_linux_wireless_h" "
-#include <sys/socket.h>
-#include <linux/if.h>
-#include <linux/types.h>
-
-"
-if test "x$ac_cv_header_linux_wireless_h" = xyes; then :
-  cat >>confdefs.h <<_ACEOF
-#define HAVE_LINUX_WIRELESS_H 1
-_ACEOF
-
+rm -f core conftest.err conftest.$ac_objext \
+    conftest$ac_exeext conftest.$ac_ext
+LIBS=$ac_check_lib_save_LIBS
 fi
-
-done
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_dag_dag_get_erf_types" >&5
+$as_echo "$ac_cv_lib_dag_dag_get_erf_types" >&6; }
+if test "x$ac_cv_lib_dag_dag_get_erf_types" = xyes; then :
 
 
-       #
-       # Do we have libnl?
-       #
+$as_echo "#define HAVE_DAG_GET_ERF_TYPES 1" >>confdefs.h
 
-# Check whether --with-libnl was given.
-if test "${with_libnl+set}" = set; then :
-  withval=$with_libnl; with_libnl=$withval
 fi
 
-
-       if test x$with_libnl != xno ; then
-               have_any_nl="no"
-
-               #
-               # Try libnl 3.x first.
-               #
-               { $as_echo "$as_me:${as_lineno-$LINENO}: checking for nl_socket_alloc in -lnl-3" >&5
-$as_echo_n "checking for nl_socket_alloc in -lnl-3... " >&6; }
-if ${ac_cv_lib_nl_3_nl_socket_alloc+:} false; then :
+               { $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
 else
   ac_check_lib_save_LIBS=$LIBS
-LIBS="-lnl-3  $LIBS"
+LIBS="-ldag  $LIBS"
 cat confdefs.h - <<_ACEOF >conftest.$ac_ext
 /* end confdefs.h.  */
 
@@ -5531,61 +7281,55 @@ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
 #ifdef __cplusplus
 extern "C"
 #endif
-char nl_socket_alloc ();
+char dag_get_stream_erf_types ();
 int
 main ()
 {
-return nl_socket_alloc ();
+return dag_get_stream_erf_types ();
   ;
   return 0;
 }
 _ACEOF
 if ac_fn_c_try_link "$LINENO"; then :
-  ac_cv_lib_nl_3_nl_socket_alloc=yes
+  ac_cv_lib_dag_dag_get_stream_erf_types=yes
 else
-  ac_cv_lib_nl_3_nl_socket_alloc=no
+  ac_cv_lib_dag_dag_get_stream_erf_types=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_nl_3_nl_socket_alloc" >&5
-$as_echo "$ac_cv_lib_nl_3_nl_socket_alloc" >&6; }
-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"
-
-$as_echo "#define HAVE_LIBNL 1" >>confdefs.h
-
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_dag_dag_get_stream_erf_types" >&5
+$as_echo "$ac_cv_lib_dag_dag_get_stream_erf_types" >&6; }
+if test "x$ac_cv_lib_dag_dag_get_stream_erf_types" = xyes; then :
 
-$as_echo "#define HAVE_LIBNL_3_x 1" >>confdefs.h
 
+$as_echo "#define HAVE_DAG_GET_STREAM_ERF_TYPES 1" >>confdefs.h
 
-$as_echo "#define HAVE_LIBNL_NLE 1" >>confdefs.h
+fi
 
 
-$as_echo "#define HAVE_LIBNL_SOCKETS 1" >>confdefs.h
+               LDFLAGS=$saved_ldflags
 
-                       V_INCLS="$V_INCLS -I/usr/include/libnl3"
-                       have_any_nl="yes"
+               #
+               # We assume that if we have libdag we have libdagconf,
+               # as they're installed at the same time from the same
+               # package.
+               #
+               LIBS="$LIBS -ldag -ldagconf"
+               LDFLAGS="$LDFLAGS -L$dag_lib_dir"
 
-fi
+               if test "$dag_large_streams" = 1; then
 
+$as_echo "#define HAVE_DAG_LARGE_STREAMS_API 1" >>confdefs.h
 
-               if test x$have_any_nl = xno ; then
-                       #
-                       # Try libnl 2.x
-                       #
-                       { $as_echo "$as_me:${as_lineno-$LINENO}: checking for nl_socket_alloc in -lnl" >&5
-$as_echo_n "checking for nl_socket_alloc in -lnl... " >&6; }
-if ${ac_cv_lib_nl_nl_socket_alloc+:} false; then :
+                       { $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
 else
   ac_check_lib_save_LIBS=$LIBS
-LIBS="-lnl  $LIBS"
+LIBS="-lvdag  $LIBS"
 cat confdefs.h - <<_ACEOF >conftest.$ac_ext
 /* end confdefs.h.  */
 
@@ -5595,460 +7339,547 @@ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
 #ifdef __cplusplus
 extern "C"
 #endif
-char nl_socket_alloc ();
+char vdag_set_device_info ();
 int
 main ()
 {
-return nl_socket_alloc ();
+return vdag_set_device_info ();
   ;
   return 0;
 }
 _ACEOF
 if ac_fn_c_try_link "$LINENO"; then :
-  ac_cv_lib_nl_nl_socket_alloc=yes
+  ac_cv_lib_vdag_vdag_set_device_info=yes
 else
-  ac_cv_lib_nl_nl_socket_alloc=no
+  ac_cv_lib_vdag_vdag_set_device_info=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_nl_nl_socket_alloc" >&5
-$as_echo "$ac_cv_lib_nl_nl_socket_alloc" >&6; }
-if test "x$ac_cv_lib_nl_nl_socket_alloc" = xyes; then :
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_vdag_vdag_set_device_info" >&5
+$as_echo "$ac_cv_lib_vdag_vdag_set_device_info" >&6; }
+if test "x$ac_cv_lib_vdag_vdag_set_device_info" = xyes; then :
+  ac_dag_have_vdag="1"
+else
+  ac_dag_have_vdag="0"
+fi
 
-                               #
-                               # Yes, we have libnl 2.x.
-                               #
-                               LIBS="-lnl-genl -lnl $LIBS"
+                       if test "$ac_dag_have_vdag" = 1; then
 
-$as_echo "#define HAVE_LIBNL 1" >>confdefs.h
+$as_echo "#define HAVE_DAG_VDAG 1" >>confdefs.h
 
+                               if test "$ac_lbl_have_pthreads" != "found"; then
+                                       as_fn_error $? "DAG requires pthreads, but we didn't find them" "$LINENO" 5
+                               fi
+                               LIBS="$LIBS $PTHREAD_LIBS"
+                       fi
+               fi
 
-$as_echo "#define HAVE_LIBNL_2_x 1" >>confdefs.h
 
+$as_echo "#define HAVE_DAG_API 1" >>confdefs.h
 
-$as_echo "#define HAVE_LIBNL_NLE 1" >>confdefs.h
+       else
 
+               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
 
-$as_echo "#define HAVE_LIBNL_SOCKETS 1" >>confdefs.h
+               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
+fi
 
-                               have_any_nl="yes"
+
+# Check whether --with-septel was given.
+if test "${with_septel+set}" = set; then :
+  withval=$with_septel;
+       if test "$withval" = no
+       then
+               want_septel=no
+       elif test "$withval" = yes
+       then
+               want_septel=yes
+               septel_root=
+       else
+               want_septel=yes
+               septel_root=$withval
+       fi
+
+else
+
+       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
+if test "$with_septel" != no; then
+
+       { $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
+
+       septel_tools_dir="$septel_root"
+       septel_include_dir="$septel_root/INC"
+
+       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="$SSRC pcap-septel.c"
                fi
 
-               if test x$have_any_nl = xno ; then
-                       #
-                       # No, we don't; do we have libnl 1.x?
-                       #
-                       { $as_echo "$as_me:${as_lineno-$LINENO}: checking for nl_handle_alloc in -lnl" >&5
-$as_echo_n "checking for nl_handle_alloc in -lnl... " >&6; }
-if ${ac_cv_lib_nl_nl_handle_alloc+:} false; then :
-  $as_echo_n "(cached) " >&6
-else
-  ac_check_lib_save_LIBS=$LIBS
-LIBS="-lnl  $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 nl_handle_alloc ();
-int
-main ()
-{
-return nl_handle_alloc ();
-  ;
-  return 0;
-}
-_ACEOF
-if ac_fn_c_try_link "$LINENO"; then :
-  ac_cv_lib_nl_nl_handle_alloc=yes
+$as_echo "#define HAVE_SEPTEL_API 1" >>confdefs.h
+
+       else
+               { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+
+               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.
+
+# Check whether --with-snf was given.
+if test "${with_snf+set}" = set; then :
+  withval=$with_snf;
+       if test "$withval" = no
+       then
+               # User explicitly doesn't want SNF
+               want_snf=no
+       elif test "$withval" = yes
+       then
+               # User wants SNF support but hasn't specified a directory.
+               want_snf=yes
+       else
+               # User wants SNF support with a specified directory.
+               want_snf=yes
+               snf_root=$withval
+       fi
+
 else
-  ac_cv_lib_nl_nl_handle_alloc=no
+
+       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
-rm -f core conftest.err conftest.$ac_objext \
-    conftest$ac_exeext conftest.$ac_ext
-LIBS=$ac_check_lib_save_LIBS
+
+
+
+# Check whether --with-snf-includes was given.
+if test "${with_snf_includes+set}" = set; then :
+  withval=$with_snf_includes;
+       # User wants SNF with specific header directory
+       want_snf=yes
+       snf_include_dir=$withval
+
 fi
-{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_nl_nl_handle_alloc" >&5
-$as_echo "$ac_cv_lib_nl_nl_handle_alloc" >&6; }
-if test "x$ac_cv_lib_nl_nl_handle_alloc" = xyes; then :
 
-                               #
-                               # Yes.
-                               #
-                               LIBS="-lnl $LIBS"
 
-$as_echo "#define HAVE_LIBNL 1" >>confdefs.h
 
-                               have_any_nl="yes"
+# Check whether --with-snf-libraries was given.
+if test "${with_snf_libraries+set}" = set; then :
+  withval=$with_snf_libraries;
+       # User wants SNF with specific lib directory
+       want_snf=yes
+       snf_lib_dir=$withval
 
 fi
 
-               fi
 
-               if test x$have_any_nl = xno ; then
-                       #
-                       # No, we don't have libnl at all.
-                       #
-                       if test x$with_libnl = xyes ; then
-                               as_fn_error $? "libnl support requested but libnl not found" "$LINENO" 5
-                       fi
-               fi
-       fi
+ac_cv_lbl_snf_api=no
+if test "$with_snf" != no; then
 
-       for ac_header in linux/ethtool.h
-do :
-  ac_fn_c_check_header_compile "$LINENO" "linux/ethtool.h" "ac_cv_header_linux_ethtool_h" "
-$ac_includes_default
-#include <linux/types.h>
+       { $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 test "x$ac_cv_header_linux_ethtool_h" = xyes; then :
-  cat >>confdefs.h <<_ACEOF
-#define HAVE_LINUX_ETHTOOL_H 1
-_ACEOF
+       # If necessary, set default paths for Sniffer headers and libraries.
+       if test -z "$snf_root"; then
+               snf_root=/opt/snf
+       fi
 
-fi
+       if test -z "$snf_include_dir"; then
+               snf_include_dir="$snf_root/include"
+       fi
 
-done
+       if test -z "$snf_lib_dir"; then
+               snf_lib_dir="$snf_root/lib"
+       fi
 
-       { $as_echo "$as_me:${as_lineno-$LINENO}: checking if if_packet.h has tpacket_stats defined" >&5
-$as_echo_n "checking if if_packet.h has tpacket_stats defined... " >&6; }
-   if ${ac_cv_lbl_tpacket_stats+:} false; then :
+       if test -f "$snf_include_dir/snf.h"; then
+               # 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
+$as_echo_n "checking for snf_init in -lsnf... " >&6; }
+if ${ac_cv_lib_snf_snf_init+:} false; then :
   $as_echo_n "(cached) " >&6
 else
-  cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+  ac_check_lib_save_LIBS=$LIBS
+LIBS="-lsnf  $LIBS"
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
 /* end confdefs.h.  */
 
-#  include <linux/if_packet.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 snf_init ();
 int
 main ()
 {
-struct tpacket_stats stats
+return snf_init ();
   ;
   return 0;
 }
 _ACEOF
-if ac_fn_c_try_compile "$LINENO"; then :
-  ac_cv_lbl_tpacket_stats=yes
+if ac_fn_c_try_link "$LINENO"; then :
+  ac_cv_lib_snf_snf_init=yes
 else
-  ac_cv_lbl_tpacket_stats=no
+  ac_cv_lib_snf_snf_init=no
 fi
-rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+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_snf_snf_init" >&5
+$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"
 fi
 
-   { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lbl_tpacket_stats" >&5
-$as_echo "$ac_cv_lbl_tpacket_stats" >&6; }
-   if test $ac_cv_lbl_tpacket_stats = yes; then
+               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
 
-$as_echo "#define HAVE_TPACKET_STATS 1" >>confdefs.h
+       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; }
 
-   fi
-       { $as_echo "$as_me:${as_lineno-$LINENO}: checking if tpacket_auxdata struct has tp_vlan_tci member" >&5
-$as_echo_n "checking if tpacket_auxdata struct has tp_vlan_tci member... " >&6; }
-    if ${ac_cv_lbl_linux_tpacket_auxdata_tp_vlan_tci+:} false; then :
-  $as_echo_n "(cached) " >&6
-else
-  cat confdefs.h - <<_ACEOF >conftest.$ac_ext
-/* end confdefs.h.  */
+               V_INCLS="$V_INCLS -I$snf_include_dir"
+               LIBS="$LIBS -lsnf"
+               LDFLAGS="$LDFLAGS -L$snf_lib_dir"
 
-#      include <sys/types.h>
-#      include <linux/if_packet.h>
-int
-main ()
-{
-u_int i = sizeof(((struct tpacket_auxdata *)0)->tp_vlan_tci)
-  ;
-  return 0;
-}
-_ACEOF
-if ac_fn_c_try_compile "$LINENO"; then :
-  ac_cv_lbl_linux_tpacket_auxdata_tp_vlan_tci=yes
-else
-  ac_cv_lbl_linux_tpacket_auxdata_tp_vlan_tci=no
-fi
-rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
-fi
+               if test "$V_PCAP" != snf ; then
+                       SSRC="$SSRC pcap-snf.c"
+               fi
 
-    { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lbl_linux_tpacket_auxdata_tp_vlan_tci" >&5
-$as_echo "$ac_cv_lbl_linux_tpacket_auxdata_tp_vlan_tci" >&6; }
-    if test $ac_cv_lbl_linux_tpacket_auxdata_tp_vlan_tci = yes ; then
-           HAVE_LINUX_TPACKET_AUXDATA=tp_vlan_tci
 
+$as_echo "#define HAVE_SNF_API 1" >>confdefs.h
 
-$as_echo "#define HAVE_LINUX_TPACKET_AUXDATA_TP_VLAN_TCI 1" >>confdefs.h
+       else
+               { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
 
-    fi
-       ;;
+               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
 
-bpf)
-       #
-       # Check whether we have the *BSD-style ioctls.
-       #
-       for ac_header in net/if_media.h
-do :
-  ac_fn_c_check_header_mongrel "$LINENO" "net/if_media.h" "ac_cv_header_net_if_media_h" "$ac_includes_default"
-if test "x$ac_cv_header_net_if_media_h" = xyes; then :
-  cat >>confdefs.h <<_ACEOF
-#define HAVE_NET_IF_MEDIA_H 1
-_ACEOF
+               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
+
+# 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
 
-done
 
+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
 
-       { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether the system supports zerocopy BPF" >&5
-$as_echo_n "checking whether the system supports zerocopy BPF... " >&6; }
        cat confdefs.h - <<_ACEOF >conftest.$ac_ext
 /* end confdefs.h.  */
-#include <sys/socket.h>
-           #include <sys/ioctl.h>
-           #include <net/if.h>
-           #include <net/bpf.h>
+
+           #include <TcApi.h>
+
 int
 main ()
 {
-return (BIOCROTZBUF + BPF_BUFMODE_ZBUF);
+
+           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; }
 
-$as_echo "#define HAVE_ZEROCOPY_BPF 1" >>confdefs.h
-
-
-else
-  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
-$as_echo "no" >&6; }
-fi
-rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
-
-           #
-           # Check whether we have struct BPF_TIMEVAL.
-           #
-           ac_fn_c_check_type "$LINENO" "struct BPF_TIMEVAL" "ac_cv_type_struct_BPF_TIMEVAL" "
-#include <sys/types.h>
-#include <sys/ioctl.h>
-#ifdef HAVE_SYS_IOCCOM_H
-#include <sys/ioccom.h>
-#endif
-#include <net/bpf.h>
+               SSRC="$SSRC pcap-tc.c"
+               V_INCLS="$V_INCLS $TURBOCAP_CFLAGS"
+               LIBS="$LIBS $TURBOCAP_LIBS -lTcApi -lpthread -lstdc++"
 
-"
-if test "x$ac_cv_type_struct_BPF_TIMEVAL" = xyes; then :
 
-cat >>confdefs.h <<_ACEOF
-#define HAVE_STRUCT_BPF_TIMEVAL 1
-_ACEOF
+$as_echo "#define HAVE_TC_API 1" >>confdefs.h
 
+       else
+               { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
 
+               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
 
-       ;;
-
-dag)
-       V_DEFS="$V_DEFS -DDAG_ONLY"
-       ;;
-
-septel)
-       V_DEFS="$V_DEFS -DSEPTEL_ONLY"
-       ;;
-
-snf)
-       V_DEFS="$V_DEFS -DSNF_ONLY"
-       ;;
-
-null)
-       { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: cannot determine packet capture interface" >&5
-$as_echo "$as_me: WARNING: cannot determine packet capture interface" >&2;}
-       { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: (see the INSTALL doc for more info)" >&5
-$as_echo "$as_me: WARNING: (see the INSTALL doc for more info)" >&2;}
-       ;;
-esac
-
-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 :
-
-               #
-               # We have "getifaddrs()"; make sure we have <ifaddrs.h>
-               # as well, just in case some platform is really weird.
-               #
-               ac_fn_c_check_header_mongrel "$LINENO" "ifaddrs.h" "ac_cv_header_ifaddrs_h" "$ac_includes_default"
-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
-
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether to enable remote packet capture" >&5
+$as_echo_n "checking whether to enable remote packet capture... " >&6; }
+# Check whether --enable-remote was given.
+if test "${enable_remote+set}" = set; then :
+  enableval=$enable_remote;
 else
-
-                   #
-                   # We don't have the header - give up.
-                   # XXX - we could also fall back on some other
-                   # mechanism, but, for now, this'll catch this
-                   # problem so that we can at least try to figure
-                   # out something to do on systems with "getifaddrs()"
-                   # but without "ifaddrs.h", if there is something
-                   # we can do on those systems.
-                   #
-                   as_fn_error $? "Your system has getifaddrs() but doesn't have a usable <ifaddrs.h>." "$LINENO" 5
-
+  enableval=no
 fi
 
-
+case "$enableval" in
+yes)   { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
+$as_echo "yes" >&6; }
+       { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: Remote packet capture may expose libpcap-based applications" >&5
+$as_echo "$as_me: WARNING: Remote packet capture may expose libpcap-based applications" >&2;}
+       { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: to attacks by malicious remote capture servers!" >&5
+$as_echo "$as_me: WARNING: to attacks by malicious remote capture servers!" >&2;}
+       #
+       # rpcapd requires pthreads on UN*X.
+       #
+       if test "$ac_lbl_have_pthreads" != "found"; then
+               as_fn_error $? "rpcapd requires pthreads, but we didn't find them" "$LINENO" 5
+       fi
+       #
+       # It also requires crypt().
+       # Do we have it in the system libraries?
+       #
+       ac_fn_c_check_func "$LINENO" "crypt" "ac_cv_func_crypt"
+if test "x$ac_cv_func_crypt" = xyes; then :
 
 else
 
                #
-               # Well, we don't have "getifaddrs()", so we have to use
-               # some other mechanism; determine what that mechanism is.
-               #
-               # The first thing we use is the type of capture mechanism,
-               # which is somewhat of a proxy for the OS we're using.
+               # No.  Do we have it in -lcrypt?
                #
-               case "$V_PCAP" in
-
-               dlpi|libdlpi)
-                       #
-                       # This might be Solaris 8 or later, with
-                       # SIOCGLIFCONF, or it might be some other OS
-                       # or some older version of Solaris, with
-                       # just SIOCGIFCONF.
-                       #
-                       { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether we have SIOCGLIFCONF" >&5
-$as_echo_n "checking whether we have SIOCGLIFCONF... " >&6; }
-                       if ${ac_cv_lbl_have_siocglifconf+:} false; then :
+               { $as_echo "$as_me:${as_lineno-$LINENO}: checking for crypt in -lcrypt" >&5
+$as_echo_n "checking for crypt in -lcrypt... " >&6; }
+if ${ac_cv_lib_crypt_crypt+:} false; then :
   $as_echo_n "(cached) " >&6
 else
-  cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+  ac_check_lib_save_LIBS=$LIBS
+LIBS="-lcrypt  $LIBS"
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
 /* end confdefs.h.  */
-#include <sys/param.h>
-                               #include <sys/file.h>
-                               #include <sys/ioctl.h>
-                               #include <sys/socket.h>
-                               #include <sys/sockio.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 crypt ();
 int
 main ()
 {
-ioctl(0, SIOCGLIFCONF, (char *)0);
+return crypt ();
   ;
   return 0;
 }
 _ACEOF
-if ac_fn_c_try_compile "$LINENO"; then :
-  ac_cv_lbl_have_siocglifconf=yes
+if ac_fn_c_try_link "$LINENO"; then :
+  ac_cv_lib_crypt_crypt=yes
 else
-  ac_cv_lbl_have_siocglifconf=no
+  ac_cv_lib_crypt_crypt=no
 fi
-rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+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_crypt_crypt" >&5
+$as_echo "$ac_cv_lib_crypt_crypt" >&6; }
+if test "x$ac_cv_lib_crypt_crypt" = xyes; then :
 
-                       { $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
-                       else
-                               V_FINDALLDEVS=gifc
-                       fi
-                       ;;
-
-               *)
                        #
-                       # Assume we just have SIOCGIFCONF.
-                       # (XXX - on at least later Linux kernels, there's
-                       # another mechanism, and we should be using that
-                       # instead.)
+                       # Yes; add -lcrypt to the libraries for rpcapd.
                        #
-                       V_FINDALLDEVS=gifc
-                       ;;
-               esac
-fi
+                       RPCAPD_LIBS="$RPCAPD_LIBS -lcrypt"
 
-fi
+else
+
+                       as_fn_error $? "rpcapd requires crypt(), but we didn't find it" "$LINENO" 5
 
 fi
 
 
-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for socklen_t" >&5
-$as_echo_n "checking for socklen_t... " >&6; }
-cat confdefs.h - <<_ACEOF >conftest.$ac_ext
-/* end confdefs.h.  */
+fi
 
-       #include <sys/types.h>
-       #include <sys/socket.h>
 
-int
-main ()
-{
- socklen_t x;
-  ;
-  return 0;
-}
+       #
+       # OK, we have crypt().  Do we have getspnam()?
+       #
+       for ac_func in getspnam
+do :
+  ac_fn_c_check_func "$LINENO" "getspnam" "ac_cv_func_getspnam"
+if test "x$ac_cv_func_getspnam" = xyes; then :
+  cat >>confdefs.h <<_ACEOF
+#define HAVE_GETSPNAM 1
 _ACEOF
-if ac_fn_c_try_compile "$LINENO"; then :
-  have_socklen_t=yes
-else
-  have_socklen_t=no
+
 fi
-rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
-if test "x$have_socklen_t" = "xyes"; then
+done
+
+
+       #
+       # Check for various members of struct msghdr.
+       #
+       ac_fn_c_check_member "$LINENO" "struct msghdr" "msg_control" "ac_cv_member_struct_msghdr_msg_control" "
+               #include \"ftmacros.h\"
+               #include <sys/socket.h>
+
+"
+if test "x$ac_cv_member_struct_msghdr_msg_control" = xyes; then :
+
+cat >>confdefs.h <<_ACEOF
+#define HAVE_STRUCT_MSGHDR_MSG_CONTROL 1
+_ACEOF
 
-$as_echo "#define HAVE_SOCKLEN_T 1" >>confdefs.h
 
 fi
-{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $have_socklen_t" >&5
-$as_echo "$have_socklen_t" >&6; }
 
-# Check whether --enable-ipv6 was given.
-if test "${enable_ipv6+set}" = set; then :
-  enableval=$enable_ipv6;
-else
-  enable_ipv6=ifavailable
-fi
+       ac_fn_c_check_member "$LINENO" "struct msghdr" "msg_flags" "ac_cv_member_struct_msghdr_msg_flags" "
+               #include \"ftmacros.h\"
+               #include <sys/socket.h>
 
-if test "$enable_ipv6" != "no"; then
-       ac_fn_c_check_func "$LINENO" "getaddrinfo" "ac_cv_func_getaddrinfo"
-if test "x$ac_cv_func_getaddrinfo" = xyes; then :
+"
+if test "x$ac_cv_member_struct_msghdr_msg_flags" = xyes; then :
 
+cat >>confdefs.h <<_ACEOF
+#define HAVE_STRUCT_MSGHDR_MSG_FLAGS 1
+_ACEOF
 
-$as_echo "#define INET6 1" >>confdefs.h
 
+fi
 
-else
 
-               if test "$enable_ipv6" != "ifavailable"; then
-                       { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
-$as_echo "$as_me: error: in \`$ac_pwd':" >&2;}
-as_fn_error $? "--enable-ipv6 was given, but getaddrinfo isn't available
-See \`config.log' for more details" "$LINENO" 5; }
-               fi
 
-fi
+$as_echo "#define ENABLE_REMOTE /**/" >>confdefs.h
 
-fi
+       SSRC="$SSRC pcap-new.c pcap-rpcap.c rpcap-protocol.c sockutils.c"
+       BUILD_RPCAPD=build-rpcapd
+       INSTALL_RPCAPD=install-rpcapd
+       ;;
+*)     { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+       ;;
+esac
 
 { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether to build optimizer debugging code" >&5
 $as_echo_n "checking whether to build optimizer debugging code... " >&6; }
 { $as_echo "$as_me:${as_lineno-$LINENO}: result: ${enable_yydebug-no}" >&5
 $as_echo "${enable_yydebug-no}" >&6; }
 
-# Check for Endace DAG card support.
-
-# Check whether --with-dag was given.
-if test "${with_dag+set}" = set; then :
-  withval=$with_dag;
-       if test "$withval" = no
-       then
-               # User doesn't want DAG support.
-               want_dag=no
-       elif test "$withval" = yes
-       then
-               # User wants DAG support but hasn't specified a directory.
-               want_dag=yes
-       else
-               # User wants DAG support and has specified a directory, so use the provided value.
-               want_dag=yes
-               dag_root=$withval
-       fi
-
+#
+# 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_LEX+:} false; then :
+  $as_echo_n "(cached) " >&6
 else
-
-       #
-       # Use DAG API if present, otherwise don't
-       #
-       want_dag=ifpresent
+  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
+do
+  IFS=$as_save_IFS
+  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_LEX="$ac_prog"
+    $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+    break 2
+  fi
+done
+  done
+IFS=$as_save_IFS
 
 fi
-
-
-
-# Check whether --with-dag-includes was given.
-if test "${with_dag_includes+set}" = set; then :
-  withval=$with_dag_includes;
-       # User wants DAG support and has specified a header directory, so use the provided value.
-       want_dag=yes
-       dag_include_dir=$withval
-
 fi
-
-
-
-# Check whether --with-dag-libraries was given.
-if test "${with_dag_libraries+set}" = set; then :
-  withval=$with_dag_libraries;
-       # User wants DAG support and has specified a library directory, so use the provided value.
-       want_dag=yes
-       dag_lib_dir=$withval
-
+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
 
 
-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
-       ;;
+  test -n "$LEX" && break
+done
+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
 
-ac_cv_lbl_dag_api=no
-if test "$want_dag" != no; then
-
-       { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether we have DAG API headers" >&5
-$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
-       fi
-
-       if test -z "$dag_include_dir"; then
-               dag_include_dir="$dag_root/include"
-       fi
-
-       if test -z "$dag_lib_dir"; then
-           dag_lib_dir="$dag_root/lib"
-       fi
-
-       if test -z "$dag_tools_dir"; then
-           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; }
+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 $ac_cv_lbl_dag_api = yes; then
-       V_INCLS="$V_INCLS -I$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"
-       { $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 :
+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
-  ac_check_lib_save_LIBS=$LIBS
-LIBS="-ldag  $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 dag_attach_stream ();
-int
-main ()
-{
-return dag_attach_stream ();
-  ;
-  return 0;
-}
+    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_dag_dag_attach_stream=yes
-else
-  ac_cv_lib_dag_dag_attach_stream=no
+  ac_cv_lib_lex=$ac_lib
 fi
 rm -f core conftest.err conftest.$ac_objext \
     conftest$ac_exeext conftest.$ac_ext
-LIBS=$ac_check_lib_save_LIBS
+      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_dag_dag_attach_stream" >&5
-$as_echo "$ac_cv_lib_dag_dag_attach_stream" >&6; }
-if test "x$ac_cv_lib_dag_dag_attach_stream" = xyes; then :
-  dag_streams="1"
-else
-  dag_streams="0"
+{ $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}: 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 "$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
-  ac_check_lib_save_LIBS=$LIBS
-LIBS="-ldag  $LIBS"
+  # 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.  */
 
-/* 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 dag_get_erf_types ();
-int
-main ()
-{
-return dag_get_erf_types ();
-  ;
-  return 0;
-}
+  #define YYTEXT_POINTER 1
+`cat $LEX_OUTPUT_ROOT.c`
 _ACEOF
 if ac_fn_c_try_link "$LINENO"; then :
-  ac_cv_lib_dag_dag_get_erf_types=yes
-else
-  ac_cv_lib_dag_dag_get_erf_types=no
+  ac_cv_prog_lex_yytext_pointer=yes
 fi
 rm -f core conftest.err conftest.$ac_objext \
     conftest$ac_exeext conftest.$ac_ext
-LIBS=$ac_check_lib_save_LIBS
+LIBS=$ac_save_LIBS
+
 fi
-{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_dag_dag_get_erf_types" >&5
-$as_echo "$ac_cv_lib_dag_dag_get_erf_types" >&6; }
-if test "x$ac_cv_lib_dag_dag_get_erf_types" = xyes; then :
+{ $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
 
-$as_echo "#define HAVE_DAG_GET_ERF_TYPES 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
 
-       { $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 :
+#
+# 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
-  ac_check_lib_save_LIBS=$LIBS
-LIBS="-ldag  $LIBS"
-cat confdefs.h - <<_ACEOF >conftest.$ac_ext
-/* end confdefs.h.  */
+  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
 
-/* 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 dag_get_stream_erf_types ();
-int
-main ()
-{
-return dag_get_stream_erf_types ();
-  ;
-  return 0;
-}
-_ACEOF
-if ac_fn_c_try_link "$LINENO"; then :
-  ac_cv_lib_dag_dag_get_stream_erf_types=yes
+#
+# 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_YACC+:} false; then :
+  $as_echo_n "(cached) " >&6
 else
-  ac_cv_lib_dag_dag_get_stream_erf_types=no
+  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
+do
+  IFS=$as_save_IFS
+  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_YACC="$ac_prog"
+    $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+    break 2
+  fi
+done
+  done
+IFS=$as_save_IFS
+
 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_dag_dag_get_stream_erf_types" >&5
-$as_echo "$ac_cv_lib_dag_dag_get_stream_erf_types" >&6; }
-if test "x$ac_cv_lib_dag_dag_get_stream_erf_types" = xyes; then :
-
-
-$as_echo "#define HAVE_DAG_GET_STREAM_ERF_TYPES 1" >>confdefs.h
-
+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
 
 
-       LDFLAGS=$saved_ldflags
-
-       if test "$dag_streams" = 1; then
-
-$as_echo "#define HAVE_DAG_STREAMS_API 1" >>confdefs.h
+  test -n "$YACC" && break
+done
+test -n "$YACC" || YACC="yacc"
 
-               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_n "checking for vdag_set_device_info in -lvdag... " >&6; }
-if ${ac_cv_lib_vdag_vdag_set_device_info+:} 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
-  ac_check_lib_save_LIBS=$LIBS
-LIBS="-lvdag  $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 vdag_set_device_info ();
-int
-main ()
-{
-return vdag_set_device_info ();
-  ;
-  return 0;
-}
-_ACEOF
-if ac_fn_c_try_link "$LINENO"; then :
-  ac_cv_lib_vdag_vdag_set_device_info=yes
-else
-  ac_cv_lib_vdag_vdag_set_device_info=no
-fi
-rm -f core conftest.err conftest.$ac_objext \
-    conftest$ac_exeext conftest.$ac_ext
-LIBS=$ac_check_lib_save_LIBS
+  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: $ac_cv_lib_vdag_vdag_set_device_info" >&5
-$as_echo "$ac_cv_lib_vdag_vdag_set_device_info" >&6; }
-if test "x$ac_cv_lib_vdag_vdag_set_device_info" = xyes; then :
-  ac_dag_have_vdag="1"
-else
-  ac_dag_have_vdag="0"
+{ $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, a newer version of Berkeley YACC with support
+ for reentrant parsers, or another YACC compatible with them." "$LINENO" 5
 fi
 
-               if test "$ac_dag_have_vdag" = 1; then
+#
+# Do various checks for various OSes and versions of those OSes.
+#
+# Assume, by default, no support for shared libraries and V7/BSD
+# convention for man pages (devices in section 4, file formats in
+# section 5, miscellaneous info in section 7, administrative commands
+# and daemons in section 8).  Individual cases can override this.
+#
+DYEXT="none"
+MAN_DEVICES=4
+MAN_FILE_FORMATS=5
+MAN_MISC_INFO=7
+MAN_ADMIN_COMMANDS=8
+case "$host_os" in
 
-$as_echo "#define HAVE_DAG_VDAG 1" >>confdefs.h
+aix*)
 
-                       LIBS="$LIBS -lpthread"
-               fi
-       fi
+$as_echo "#define _SUN 1" >>confdefs.h
 
 
-$as_echo "#define HAVE_DAG_API 1" >>confdefs.h
+       #
+       # AIX makes it fun to build shared and static libraries,
+       # because they're *both* ".a" archive libraries.  We
+       # build the static library for the benefit of the traditional
+       # scheme of building libpcap and tcpdump in subdirectories of
+       # the same directory, with tcpdump statically linked with the
+       # libpcap in question, but we also build a shared library as
+       # "libpcap.shareda" and install *it*, rather than the static
+       # library, as "libpcap.a".
+       #
+       DYEXT="shareda"
 
-fi
+       case "$V_PCAP" in
 
-{ $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; }
+       dlpi)
+               #
+               # If we're using DLPI, applications will need to
+               # use /lib/pse.exp if present, as we use the
+               # STREAMS routines.
+               #
+               pseexe="/lib/pse.exp"
+               { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $pseexe" >&5
+$as_echo_n "checking for $pseexe... " >&6; }
+               if test -f $pseexe ; then
+                       { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
+$as_echo "yes" >&6; }
+                       LIBS="-I:$pseexe"
+               fi
+               ;;
 
-if test $ac_cv_lbl_dag_api = no; then
-       { $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
+       bpf)
+               #
+               # If we're using BPF, we need "-lodm" and "-lcfg", as
+               # we use them to load the BPF module.
+               #
+               LIBS="-lodm -lcfg"
+               ;;
+       esac
+       ;;
 
-       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
-       fi
-else
-       { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
-$as_echo "yes" >&6; }
+darwin*)
+       DYEXT="dylib"
+       V_CCOPT="$V_CCOPT -fno-common"
+       # Check whether --enable-universal was given.
+if test "${enable_universal+set}" = set; then :
+  enableval=$enable_universal;
 fi
 
+       if test "$enable_universal" != "no"; then
+               case "$host_os" in
 
-# Check whether --with-septel was given.
-if test "${with_septel+set}" = set; then :
-  withval=$with_septel;
-       if test "$withval" = no
-       then
-               want_septel=no
-       elif test "$withval" = yes
-       then
-               want_septel=yes
-               septel_root=
-       else
-               want_septel=yes
-               septel_root=$withval
-       fi
-
-else
+               darwin[0-7].*)
+                       #
+                       # Pre-Tiger.  Build only for 32-bit PowerPC; no
+                       # need for any special compiler or linker flags.
+                       #
+                       ;;
 
-       #
-       # Use Septel API if present, otherwise don't
-       #
-       want_septel=ifpresent
-       septel_root=./../septel
+               darwin8.[0123]|darwin8.[0123].*)
+                       #
+                       # Tiger, prior to Intel support.  Build
+                       # libraries and executables for 32-bit PowerPC
+                       # and 64-bit PowerPC, with 32-bit PowerPC first.
+                       # (I'm guessing that's what Apple does.)
+                       #
+                       # (The double brackets are needed because
+                       # autotools/m4 use brackets as a quoting
+                       # character; the double brackets turn into
+                       # single brackets in the generated configure
+                       # file.)
+                       #
+                       V_LIB_CCOPT_FAT="-arch ppc -arch ppc64"
+                       V_LIB_LDFLAGS_FAT="-arch ppc -arch ppc64"
+                       V_PROG_CCOPT_FAT="-arch ppc -arch ppc64"
+                       V_PROG_LDFLAGS_FAT="-arch ppc -arch ppc64"
+                       ;;
 
-fi
+               darwin8.[456]|darwin.[456].*)
+                       #
+                       # Tiger, subsequent to Intel support but prior
+                       # to x86-64 support.  Build libraries and
+                       # executables for 32-bit PowerPC, 64-bit
+                       # PowerPC, and 32-bit x86, with 32-bit PowerPC
+                       # first.  (I'm guessing that's what Apple does.)
+                       #
+                       # (The double brackets are needed because
+                       # autotools/m4 use brackets as a quoting
+                       # character; the double brackets turn into
+                       # single brackets in the generated configure
+                       # file.)
+                       #
+                       V_LIB_CCOPT_FAT="-arch ppc -arch ppc64 -arch i386"
+                       V_LIB_LDFLAGS_FAT="-arch ppc -arch ppc64 -arch i386"
+                       V_PROG_CCOPT_FAT="-arch ppc -arch ppc64 -arch i386"
+                       V_PROG_LDFLAGS_FAT="-arch ppc -arch ppc64 -arch i386"
+                       ;;
 
-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
+               darwin8.*)
+                       #
+                       # All other Tiger, so subsequent to x86-64
+                       # support.  Build libraries and executables for
+                       # 32-bit PowerPC, 64-bit PowerPC, 32-bit x86,
+                       # and x86-64, with 32-bit PowerPC first.  (I'm
+                       # guessing that's what Apple does.)
+                       #
+                       V_LIB_CCOPT_FAT="-arch ppc -arch ppc64 -arch i386 -arch x86_64"
+                       V_LIB_LDFLAGS_FAT="-arch ppc -arch ppc64 -arch i386 -arch x86_64"
+                       V_PROG_CCOPT_FAT="-arch ppc -arch ppc64 -arch i386 -arch x86_64"
+                       V_PROG_LDFLAGS_FAT="-arch ppc -arch ppc64 -arch i386 -arch x86_64"
+                       ;;
 
-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; }
+               darwin9.*)
+                       #
+                       # Leopard.  Build libraries for 32-bit PowerPC,
+                       # 64-bit PowerPC, 32-bit x86, and x86-64, with
+                       # 32-bit PowerPC first, and build executables
+                       # for 32-bit x86 and 32-bit PowerPC, with 32-bit
+                       # x86 first.  (That's what Apple does.)
+                       #
+                       V_LIB_CCOPT_FAT="-arch ppc -arch ppc64 -arch i386 -arch x86_64"
+                       V_LIB_LDFLAGS_FAT="-arch ppc -arch ppc64 -arch i386 -arch x86_64"
+                       V_PROG_CCOPT_FAT="-arch i386 -arch ppc"
+                       V_PROG_LDFLAGS_FAT="-arch i386 -arch ppc"
+                       ;;
 
-       if test -z "$septel_root"; then
-               septel_root=$srcdir/../septel
-       fi
+               darwin10.*)
+                       #
+                       # Snow Leopard.  Build libraries for x86-64,
+                       # 32-bit x86, and 32-bit PowerPC, with x86-64
+                       # first, and build executables for x86-64 and
+                       # 32-bit x86, with x86-64 first.  (That's what
+                       # Apple does, even though Snow Leopard doesn't
+                       # run on PPC, so PPC libpcap runs under Rosetta,
+                       # and Rosetta doesn't support BPF ioctls, so PPC
+                       # programs can't do live captures.)
+                       #
+                       V_LIB_CCOPT_FAT="-arch x86_64 -arch i386 -arch ppc"
+                       V_LIB_LDFLAGS_FAT="-arch x86_64 -arch i386 -arch ppc"
+                       V_PROG_CCOPT_FAT="-arch x86_64 -arch i386"
+                       V_PROG_LDFLAGS_FAT="-arch x86_64 -arch i386"
+                       ;;
 
-       septel_tools_dir="$septel_root"
-       septel_include_dir="$septel_root/INC"
+               darwin*)
+                       #
+                       # Post-Snow Leopard.  Build libraries for x86-64
+                       # and 32-bit x86, with x86-64 first, and build
+                       # executables only for x86-64.  (That's what
+                       # Apple does.)  This requires no special flags
+                       # for programs.
+                       # XXX - update if and when Apple drops support
+                       # for 32-bit x86 code and if and when Apple adds
+                       # ARM-based Macs.  (You're on your own for iOS
+                       # etc.)
+                       #
+                       # XXX - check whether we *can* build for
+                       # i386 and, if not, suggest that the user
+                       # install the /usr/include headers if they
+                       # want to build fat.
+                       #
+                       { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether building for 32-bit x86 is supported" >&5
+$as_echo_n "checking whether building for 32-bit x86 is supported... " >&6; }
+                       save_CFLAGS="$CFLAGS"
+                       CFLAGS="$CFLAGS -arch i386"
+                       cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
 
-       ac_cv_lbl_septel_api=no
-       if test -r "$septel_include_dir/msg.h"; then
-               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"
+int
+main ()
+{
+return 0;
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
 
-               if test "$V_PCAP" != septel ; then
-                        SSRC="pcap-septel.c"
-               fi
-               ac_cv_lbl_septel_api=yes
-       fi
+                               { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
+$as_echo "yes" >&6; }
+                               V_LIB_CCOPT_FAT="-arch x86_64 -arch i386"
+                               V_LIB_LDFLAGS_FAT="-arch x86_64 -arch i386"
 
-       { $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
+else
 
-$as_echo "#define HAVE_SEPTEL_API 1" >>confdefs.h
+                               { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+                               V_LIB_CCOPT_FAT="-arch x86_64"
+                               V_LIB_LDFLAGS_FAT="-arch x86_64"
+                               case "$host_os" in
+
+                               darwin18.*)
+                                       #
+                                       # Mojave; you need to install the
+                                       # /usr/include headers to get
+                                       # 32-bit x86 builds to work.
+                                       #
+                                       { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: Compiling for 32-bit x86 gives an error; try installing the command-line tools and, after that, installing the /usr/include headers from the /Library/Developer/CommandLineTools/Packages/macOS_SDK_headers_for_macOS_10.14.pkg package" >&5
+$as_echo "$as_me: WARNING: Compiling for 32-bit x86 gives an error; try installing the command-line tools and, after that, installing the /usr/include headers from the /Library/Developer/CommandLineTools/Packages/macOS_SDK_headers_for_macOS_10.14.pkg package" >&2;}
+                                       ;;
+
+                               *)
+                                       #
+                                       # Pre-Mojave; the command-line
+                                       # tools should be sufficient to
+                                       # enable 32-bit x86 builds.
+                                       #
+                                       { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: Compiling for 32-bit x86 gives an error; try installing the command-line tools" >&5
+$as_echo "$as_me: WARNING: Compiling for 32-bit x86 gives an error; try installing the command-line tools" >&2;}
+                                       ;;
+                               esac
 
-       fi
 fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+                       CFLAGS="$save_CFLAGS"
+                       ;;
+               esac
+       fi
+       ;;
 
-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
-fi
+hpux9*)
 
-# Check for Myricom SNF support.
+$as_echo "#define HAVE_HPUX9 1" >>confdefs.h
 
-# Check whether --with-snf was given.
-if test "${with_snf+set}" = set; then :
-  withval=$with_snf;
-       if test "$withval" = no
-       then
-               # User explicitly doesn't want SNF
-               want_snf=no
-       elif test "$withval" = yes
-       then
-               # User wants SNF support but hasn't specific a directory.
-               want_snf=yes
-       else
-               # User wants SNF support with a specified directory.
-               want_snf=yes
-               snf_root=$withval
-       fi
 
-else
+       #
+       # Use System V conventions for man pages.
+       #
+       MAN_ADMIN_COMMANDS=1m
+       MAN_FILE_FORMATS=4
+       MAN_MISC_INFO=5
+       ;;
+
+hpux10.0*)
 
        #
-       # Use Sniffer API if present, otherwise don't
+       # Use System V conventions for man pages.
        #
-       want_snf=ifpresent
-
-fi
-
-
-
-# Check whether --with-snf-includes was given.
-if test "${with_snf_includes+set}" = set; then :
-  withval=$with_snf_includes;
-       # User wants SNF with specific header directory
-       want_snf=yes
-       snf_include_dir=$withval
+       MAN_ADMIN_COMMANDS=1m
+       MAN_FILE_FORMATS=4
+       MAN_MISC_INFO=5
+       ;;
 
-fi
+hpux10.1*)
 
+       #
+       # Use System V conventions for man pages.
+       #
+       MAN_ADMIN_COMMANDS=1m
+       MAN_FILE_FORMATS=4
+       MAN_MISC_INFO=5
+       ;;
 
+hpux*)
 
-# Check whether --with-snf-libraries was given.
-if test "${with_snf_libraries+set}" = set; then :
-  withval=$with_snf_libraries;
-       # User wants SNF with specific lib directory
-       want_snf=yes
-       snf_lib_dir=$withval
+$as_echo "#define HAVE_HPUX10_20_OR_LATER 1" >>confdefs.h
 
-fi
+       if test "`uname -m`" = "ia64"; then
+               DYEXT="so"
+       else
+               DYEXT="sl"
+       fi
 
+       #
+       # "-b" builds a shared library; "+h" sets the soname.
+       #
+       SHLIB_OPT="-b"
+       SONAME_OPT="+h"
 
-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.
+       # Use System V conventions for man pages.
        #
+       MAN_FILE_FORMATS=4
+       MAN_MISC_INFO=5
        ;;
-*)
-       #
-       # If the user explicitly requested Sniffer, tell them it's not
-       # supported.
+
+irix*)
        #
-       # If they expressed no preference, don't include it.
+       # Use IRIX conventions for man pages; they're the same as the
+       # System V conventions, except that they use section 8 for
+       # administrative commands and daemons.
        #
-       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
+       MAN_FILE_FORMATS=4
+       MAN_MISC_INFO=5
        ;;
-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 test -z "$snf_root"; then
-               snf_root=/opt/snf
-       fi
+linux*|freebsd*|netbsd*|openbsd*|dragonfly*|kfreebsd*|gnu*|midipix*)
+       DYEXT="so"
 
-       if test -z "$snf_include_dir"; then
-               snf_include_dir="$snf_root/include"
+       #
+       # Compiler assumed to be GCC; run-time linker may require a -R
+       # flag.
+       #
+       if test "$libdir" != "/usr/lib"; then
+               V_RFLAGS=-Wl,-R$libdir
        fi
+       ;;
 
-       if test -z "$snf_lib_dir"; then
-               snf_lib_dir="$snf_root/lib"
-       fi
+osf*)
+       DYEXT="so"
 
-       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; }
+       #
+       # DEC OSF/1, a/k/a Digial UNIX, a/k/a Tru64 UNIX.
+       # Use Tru64 UNIX conventions for man pages; they're the same as
+       # the System V conventions except that they use section 8 for
+       # administrative commands and daemons.
+       #
+       MAN_FILE_FORMATS=4
+       MAN_MISC_INFO=5
+       MAN_DEVICES=7
+       ;;
 
-       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
-               saved_ldflags=$LDFLAGS
-               LDFLAGS="$LDFLAGS -L$snf_lib_dir"
-               { $as_echo "$as_me:${as_lineno-$LINENO}: checking for snf_init in -lsnf" >&5
-$as_echo_n "checking for snf_init in -lsnf... " >&6; }
-if ${ac_cv_lib_snf_snf_init+:} false; then :
+sinix*)
+       { $as_echo "$as_me:${as_lineno-$LINENO}: checking if SINIX compiler defines sinix" >&5
+$as_echo_n "checking if SINIX compiler defines sinix... " >&6; }
+       if ${ac_cv_cc_sinix_defined+:} false; then :
   $as_echo_n "(cached) " >&6
 else
-  ac_check_lib_save_LIBS=$LIBS
-LIBS="-lsnf  $LIBS"
-cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+  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 snf_init ();
 int
 main ()
 {
-return snf_init ();
+int i = sinix;
   ;
   return 0;
 }
 _ACEOF
-if ac_fn_c_try_link "$LINENO"; then :
-  ac_cv_lib_snf_snf_init=yes
+if ac_fn_c_try_compile "$LINENO"; then :
+  ac_cv_cc_sinix_defined=yes
 else
-  ac_cv_lib_snf_snf_init=no
-fi
-rm -f core conftest.err conftest.$ac_objext \
-    conftest$ac_exeext conftest.$ac_ext
-LIBS=$ac_check_lib_save_LIBS
+  ac_cv_cc_sinix_defined=no
 fi
-{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_snf_snf_init" >&5
-$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"
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
 fi
 
-               LDFLAGS="$saved_ldflags"
+           { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_cc_sinix_defined" >&5
+$as_echo "$ac_cv_cc_sinix_defined" >&6; }
+           if test $ac_cv_cc_sinix_defined = no ; then
 
-               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 sinix 1" >>confdefs.h
 
-$as_echo "#define HAVE_SNF_API 1" >>confdefs.h
+           fi
+       ;;
 
-               fi
-       fi
+solaris*)
+
+$as_echo "#define HAVE_SOLARIS 1" >>confdefs.h
+
+
+       DYEXT="so"
+
+       #
+       # Make sure errno is thread-safe, in case we're called in
+       # a multithreaded program.  We don't guarantee that two
+       # threads can use the *same* pcap_t safely, but the
+       # current version does guarantee that you can use different
+       # pcap_t's in different threads, and even that pcap_compile()
+       # is thread-safe (it wasn't thread-safe in some older versions).
+       #
+       V_CCOPT="$V_CCOPT -D_TS_ERRNO"
+
+       case "`uname -r`" in
+
+       5.12)
+               ;;
+
+       *)
+               #
+               # Use System V conventions for man pages.
+               #
+               MAN_ADMIN_COMMANDS=1m
+               MAN_FILE_FORMATS=4
+               MAN_MISC_INFO=5
+               MAN_DEVICES=7D
+       esac
+       ;;
+esac
+
+# Check whether --enable-shared was given.
+if test "${enable_shared+set}" = set; then :
+  enableval=$enable_shared;
 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
+test "x$enable_shared" = "xno" && DYEXT="none"
+
+if test -n "$ac_tool_prefix"; then
+  # Extract the first word of "${ac_tool_prefix}ranlib", so it can be a program name with args.
+set dummy ${ac_tool_prefix}ranlib; 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_RANLIB+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  if test -n "$RANLIB"; then
+  ac_cv_prog_RANLIB="$RANLIB" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  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_RANLIB="${ac_tool_prefix}ranlib"
+    $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+    break 2
+  fi
+done
+  done
+IFS=$as_save_IFS
+
+fi
+fi
+RANLIB=$ac_cv_prog_RANLIB
+if test -n "$RANLIB"; then
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: $RANLIB" >&5
+$as_echo "$RANLIB" >&6; }
+else
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
 fi
 
 
-# Check whether --with-flex was given.
-if test "${with_flex+set}" = set; then :
-  withval=$with_flex;
 fi
+if test -z "$ac_cv_prog_RANLIB"; then
+  ac_ct_RANLIB=$RANLIB
+  # Extract the first word of "ranlib", so it can be a program name with args.
+set dummy ranlib; 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_ac_ct_RANLIB+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  if test -n "$ac_ct_RANLIB"; then
+  ac_cv_prog_ac_ct_RANLIB="$ac_ct_RANLIB" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  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_ac_ct_RANLIB="ranlib"
+    $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+    break 2
+  fi
+done
+  done
+IFS=$as_save_IFS
 
+fi
+fi
+ac_ct_RANLIB=$ac_cv_prog_ac_ct_RANLIB
+if test -n "$ac_ct_RANLIB"; then
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_RANLIB" >&5
+$as_echo "$ac_ct_RANLIB" >&6; }
+else
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
 
-# Check whether --with-bison was given.
-if test "${with_bison+set}" = set; then :
-  withval=$with_bison;
+  if test "x$ac_ct_RANLIB" = x; then
+    RANLIB=":"
+  else
+    case $cross_compiling:$ac_tool_warned in
+yes:)
+{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5
+$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;}
+ac_tool_warned=yes ;;
+esac
+    RANLIB=$ac_ct_RANLIB
+  fi
+else
+  RANLIB="$ac_cv_prog_RANLIB"
 fi
 
-    if test "$with_flex" = no ; then
-           V_LEX=lex
-    else
-           for ac_prog in flex
-do
-  # Extract the first word of "$ac_prog", so it can be a program name with args.
-set dummy $ac_prog; ac_word=$2
+if test -n "$ac_tool_prefix"; then
+  # Extract the first word of "${ac_tool_prefix}ar", so it can be a program name with args.
+set dummy ${ac_tool_prefix}ar; 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_AR+:} 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 "$AR"; then
+  ac_cv_prog_AR="$AR" # Let the user override the test.
 else
 as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
 for as_dir in $PATH
@@ -6702,7 +8684,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_AR="${ac_tool_prefix}ar"
     $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
     break 2
   fi
@@ -6712,58 +8694,28 @@ 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; }
+AR=$ac_cv_prog_AR
+if test -n "$AR"; then
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: $AR" >&5
+$as_echo "$AR" >&6; }
 else
   { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
 $as_echo "no" >&6; }
 fi
 
 
-  test -n "$V_LEX" && break
-done
-test -n "$V_LEX" || V_LEX="lex"
-
-    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 :
-  $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
 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
-do
-  # Extract the first word of "$ac_prog", so it can be a program name with args.
-set dummy $ac_prog; ac_word=$2
+if test -z "$ac_cv_prog_AR"; then
+  ac_ct_AR=$AR
+  # Extract the first word of "ar", so it can be a program name with args.
+set dummy ar; 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_ac_ct_AR+:} 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 "$ac_ct_AR"; then
+  ac_cv_prog_ac_ct_AR="$ac_ct_AR" # Let the user override the test.
 else
 as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
 for as_dir in $PATH
@@ -6772,7 +8724,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_ac_ct_AR="ar"
     $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
     break 2
   fi
@@ -6782,556 +8734,1007 @@ 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; }
+ac_ct_AR=$ac_cv_prog_ac_ct_AR
+if test -n "$ac_ct_AR"; then
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_AR" >&5
+$as_echo "$ac_ct_AR" >&6; }
 else
   { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
 $as_echo "no" >&6; }
 fi
 
+  if test "x$ac_ct_AR" = x; then
+    AR=""
+  else
+    case $cross_compiling:$ac_tool_warned in
+yes:)
+{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5
+$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;}
+ac_tool_warned=yes ;;
+esac
+    AR=$ac_ct_AR
+  fi
+else
+  AR="$ac_cv_prog_AR"
+fi
 
-  test -n "$V_YACC" && break
-done
-test -n "$V_YACC" || V_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 "$as_me:${as_lineno-$LINENO}: checking whether ln -s works" >&5
+$as_echo_n "checking whether ln -s works... " >&6; }
+LN_S=$as_ln_s
+if test "$LN_S" = "ln -s"; then
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
+$as_echo "yes" >&6; }
+else
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no, using $LN_S" >&5
+$as_echo "no, using $LN_S" >&6; }
+fi
 
-$as_echo "#define NEED_YYPARSE_WRAPPER 1" >>confdefs.h
 
+
+rm -f os-proto.h
+    if test "${LBL_CFLAGS+set}" = set; then
+           V_CCOPT="$V_CCOPT ${LBL_CFLAGS}"
     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 :
-  $as_echo_n "(cached) " >&6
+    if test -f .devel ; then
+           #
+           # Skip all the warning option stuff on some compilers.
+           #
+           if test "$ac_lbl_cc_dont_try_gcc_dashW" != yes; then
+
+       { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether the compiler fails when given an unknown warning option" >&5
+$as_echo_n "checking whether the compiler fails when given an unknown warning option... " >&6; }
+       save_CFLAGS="$CFLAGS"
+       CFLAGS="$CFLAGS -Wxyzzy-this-will-never-succeed-xyzzy"
+       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: no" >&5
+$as_echo "no" >&6; }
+               #
+               # We're assuming this is clang, where
+               # -Werror=unknown-warning-option is the appropriate
+               # option to force the compiler to fail.
+               #
+               ac_lbl_unknown_warning_option_error="-Werror=unknown-warning-option"
+
 else
-  if lex -t scanner.l > /dev/null 2>&1; then
-                       tcpdump_cv_capable_lex=yes
-               else
-                       tcpdump_cv_capable_lex=insufficient
+
+               { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
+$as_echo "yes" >&6; }
+
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+       CFLAGS="$save_CFLAGS"
+
+
+       { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether the compiler supports the -W option" >&5
+$as_echo_n "checking whether the compiler supports the -W option... " >&6; }
+       save_CFLAGS="$CFLAGS"
+       if expr "x-W" : "x-W.*" >/dev/null
+       then
+           CFLAGS="$CFLAGS $ac_lbl_unknown_warning_option_error -W"
+       elif expr "x-W" : "x-f.*" >/dev/null
+       then
+           CFLAGS="$CFLAGS -Werror -W"
+       elif expr "x-W" : "x-m.*" >/dev/null
+       then
+           CFLAGS="$CFLAGS -Werror -W"
+       else
+           CFLAGS="$CFLAGS -W"
+       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; }
+               can_add_to_cflags=yes
+               #
+               # The compile supports this; do we have some C code for
+               # which the warning should *not* appear?
+               # We test the fourth argument because the third argument
+               # could contain quotes, breaking the test.
+               #
+               if test "x" != "x"
+               then
+                   CFLAGS="$CFLAGS $ac_lbl_cc_force_warning_errors"
+                   { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether -W " >&5
+$as_echo_n "checking whether -W ... " >&6; }
+                   cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+
+                       #
+                       # Not a problem.
+                       #
+                       { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+
+else
+
+                       #
+                       # A problem.
+                       #
+                       { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
+$as_echo "yes" >&6; }
+                       can_add_to_cflags=no
+
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+               fi
+               CFLAGS="$save_CFLAGS"
+               if test x"$can_add_to_cflags" = "xyes"
+               then
+                   V_CCOPT="$V_CCOPT -W"
                fi
+
+else
+
+               { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+               CFLAGS="$save_CFLAGS"
+
 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
+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"
+       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.  */
+
+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; }
+               can_add_to_cflags=yes
+               #
+               # The compile supports this; do we have some C code for
+               # which the warning should *not* appear?
+               # We test the fourth argument because the third argument
+               # could contain quotes, breaking the test.
+               #
+               if test "x" != "x"
+               then
+                   CFLAGS="$CFLAGS $ac_lbl_cc_force_warning_errors"
+                   { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether -Wall " >&5
+$as_echo_n "checking whether -Wall ... " >&6; }
+                   cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+
+                       #
+                       # Not a problem.
+                       #
+                       { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+
+else
+
+                       #
+                       # A problem.
+                       #
+                       { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
+$as_echo "yes" >&6; }
+                       can_add_to_cflags=no
+
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+               fi
+               CFLAGS="$save_CFLAGS"
+               if test x"$can_add_to_cflags" = "xyes"
+               then
+                   V_CCOPT="$V_CCOPT -Wall"
+               fi
+
+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 -Wcomma option" >&5
+$as_echo_n "checking whether the compiler supports the -Wcomma option... " >&6; }
+       save_CFLAGS="$CFLAGS"
+       if expr "x-Wcomma" : "x-W.*" >/dev/null
+       then
+           CFLAGS="$CFLAGS $ac_lbl_unknown_warning_option_error -Wcomma"
+       elif expr "x-Wcomma" : "x-f.*" >/dev/null
+       then
+           CFLAGS="$CFLAGS -Werror -Wcomma"
+       elif expr "x-Wcomma" : "x-m.*" >/dev/null
+       then
+           CFLAGS="$CFLAGS -Werror -Wcomma"
+       else
+           CFLAGS="$CFLAGS -Wcomma"
        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; }
+               can_add_to_cflags=yes
+               #
+               # The compile supports this; do we have some C code for
+               # which the warning should *not* appear?
+               # We test the fourth argument because the third argument
+               # could contain quotes, breaking the test.
+               #
+               if test "x" != "x"
+               then
+                   CFLAGS="$CFLAGS $ac_lbl_cc_force_warning_errors"
+                   { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether -Wcomma " >&5
+$as_echo_n "checking whether -Wcomma ... " >&6; }
+                   cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+
+                       #
+                       # Not a problem.
+                       #
+                       { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+
+else
+
+                       #
+                       # A problem.
+                       #
+                       { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
+$as_echo "yes" >&6; }
+                       can_add_to_cflags=no
+
 fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+               fi
+               CFLAGS="$save_CFLAGS"
+               if test x"$can_add_to_cflags" = "xyes"
+               then
+                   V_CCOPT="$V_CCOPT -Wcomma"
+               fi
 
-#
-# Assume, by default, no support for shared libraries and V7/BSD convention
-# for man pages (file formats in section 5, miscellaneous info in section 7).
-# Individual cases can override this.
-#
-DYEXT="none"
-MAN_FILE_FORMATS=5
-MAN_MISC_INFO=7
-case "$host_os" in
+else
 
-aix*)
+               { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+               CFLAGS="$save_CFLAGS"
 
-$as_echo "#define _SUN 1" >>confdefs.h
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
 
 
-       #
-       # AIX makes it fun to build shared and static libraries,
-       # because they're *both* ".a" archive libraries.  We
-       # build the static library for the benefit of the traditional
-       # scheme of building libpcap and tcpdump in subdirectories of
-       # the same directory, with tcpdump statically linked with the
-       # libpcap in question, but we also build a shared library as
-       # "libpcap.shareda" and install *it*, rather than the static
-       # library, as "libpcap.a".
-       #
-       DYEXT="shareda"
+       { $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.  */
 
-       case "$V_PCAP" in
+int
+main ()
+{
+return 0
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
 
-       dlpi)
+               { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
+$as_echo "yes" >&6; }
+               can_add_to_cflags=yes
                #
-               # If we're using DLPI, applications will need to
-               # use /lib/pse.exp if present, as we use the
-               # STREAMS routines.
+               # The compile supports this; do we have some C code for
+               # which the warning should *not* appear?
+               # We test the fourth argument because the third argument
+               # could contain quotes, breaking the test.
                #
-               pseexe="/lib/pse.exp"
-               { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $pseexe" >&5
-$as_echo_n "checking for $pseexe... " >&6; }
-               if test -f $pseexe ; then
+               if test "x" != "x"
+               then
+                   CFLAGS="$CFLAGS $ac_lbl_cc_force_warning_errors"
+                   { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether -Wdeclaration-after-statement " >&5
+$as_echo_n "checking whether -Wdeclaration-after-statement ... " >&6; }
+                   cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+
+                       #
+                       # Not a problem.
+                       #
+                       { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+
+else
+
+                       #
+                       # A problem.
+                       #
                        { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
 $as_echo "yes" >&6; }
-                       LIBS="-I:$pseexe"
+                       can_add_to_cflags=no
+
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+               fi
+               CFLAGS="$save_CFLAGS"
+               if test x"$can_add_to_cflags" = "xyes"
+               then
+                   V_CCOPT="$V_CCOPT -Wdeclaration-after-statement"
                fi
-               ;;
 
-       bpf)
-               #
-               # If we're using BPF, we need "-lodm" and "-lcfg", as
-               # we use them to load the BPF module.
-               #
-               LIBS="-lodm -lcfg"
-               ;;
-       esac
-       ;;
+else
+
+               { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+               CFLAGS="$save_CFLAGS"
 
-darwin*)
-       DYEXT="dylib"
-       V_CCOPT="$V_CCOPT -fno-common"
-       # Check whether --enable-universal was given.
-if test "${enable_universal+set}" = set; then :
-  enableval=$enable_universal;
 fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
 
-       if test "$enable_universal" != "no"; then
-               case "$host_os" in
 
-               darwin0-7.*)
-                       #
-                       # Pre-Tiger.  Build only for 32-bit PowerPC; no
-                       # need for any special compiler or linker flags.
-                       #
-                       ;;
+       { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether the compiler supports the -Wdocumentation option" >&5
+$as_echo_n "checking whether the compiler supports the -Wdocumentation option... " >&6; }
+       save_CFLAGS="$CFLAGS"
+       if expr "x-Wdocumentation" : "x-W.*" >/dev/null
+       then
+           CFLAGS="$CFLAGS $ac_lbl_unknown_warning_option_error -Wdocumentation"
+       elif expr "x-Wdocumentation" : "x-f.*" >/dev/null
+       then
+           CFLAGS="$CFLAGS -Werror -Wdocumentation"
+       elif expr "x-Wdocumentation" : "x-m.*" >/dev/null
+       then
+           CFLAGS="$CFLAGS -Werror -Wdocumentation"
+       else
+           CFLAGS="$CFLAGS -Wdocumentation"
+       fi
+       cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
 
-               darwin8.0123*)
-                       #
-                       # Tiger, prior to Intel support.  Build for 32-bit
-                       # PowerPC and 64-bit PowerPC, with 32-bit PowerPC
-                       # first.  (I'm guessing that's what Apple does.)
-                       #
-                       V_CCOPT="$V_CCOPT -arch ppc -arch ppc64"
-                       LDFLAGS="$LDFLAGS -arch ppc -arch ppc64"
-                       ;;
+int
+main ()
+{
+return 0
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
 
-               darwin8.456*)
-                       #
-                       # Tiger, subsequent to Intel support but prior to
-                       # x86-64 support.  Build for 32-bit PowerPC, 64-bit
-                       # PowerPC, and x86, with 32-bit PowerPC first.
-                       # (I'm guessing that's what Apple does.)
-                       #
-                       V_CCOPT="$V_CCOPT -arch ppc -arch ppc64 -arch i386"
-                       LDFLAGS="$LDFLAGS -arch ppc -arch ppc64 -arch i386"
-                       ;;
+               { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
+$as_echo "yes" >&6; }
+               can_add_to_cflags=yes
+               #
+               # The compile supports this; do we have some C code for
+               # which the warning should *not* appear?
+               # We test the fourth argument because the third argument
+               # could contain quotes, breaking the test.
+               #
+               if test "x" != "x"
+               then
+                   CFLAGS="$CFLAGS $ac_lbl_cc_force_warning_errors"
+                   { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether -Wdocumentation " >&5
+$as_echo_n "checking whether -Wdocumentation ... " >&6; }
+                   cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
 
-               darwin8.*)
-                       #
-                       # All other Tiger, so subsequent to x86-64
-                       # support. Build for 32-bit PowerPC, 64-bit
-                       # PowerPC, x86, and x86-64, and with 32-bit PowerPC
-                       # first.  (I'm guessing that's what Apple does.)
-                       #
-                       V_CCOPT="$V_CCOPT -arch ppc -arch ppc64 -arch i386 -arch x86_64"
-                       LDFLAGS="$LDFLAGS -arch ppc -arch ppc64 -arch i386 -arch x86_64"
-                       ;;
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
 
-               darwin9.*)
                        #
-                       # Leopard.  Build for 32-bit PowerPC, 64-bit
-                       # PowerPC, x86, and x86-64, with 32-bit PowerPC
-                       # first.  (That's what Apple does.)
+                       # Not a problem.
                        #
-                       V_CCOPT="$V_CCOPT -arch ppc -arch ppc64 -arch i386 -arch x86_64"
-                       LDFLAGS="$LDFLAGS -arch ppc -arch ppc64 -arch i386 -arch x86_64"
-                       ;;
+                       { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
 
-               darwin10.*)
-                       #
-                       # Snow Leopard.  Build for x86-64, x86, and
-                       # 32-bit PowerPC, with x86-64 first.  (That's
-                       # what Apple does, even though Snow Leopard
-                       # doesn't run on PPC, so PPC libpcap runs under
-                       # Rosetta, and Rosetta doesn't support BPF
-                       # ioctls, so PPC programs can't do live
-                       # captures.)
-                       #
-                       V_CCOPT="$V_CCOPT -arch x86_64 -arch i386 -arch ppc"
-                       LDFLAGS="$LDFLAGS -arch x86_64 -arch i386 -arch ppc"
-                       ;;
+else
 
-               darwin*)
                        #
-                       # Post-Snow Leopard.  Build for x86-64 and
-                       # x86, with x86-64 first.  (That's probably what
-                       # Apple does, given that Rosetta is gone.)
-                       # XXX - update if and when Apple drops support
-                       # for 32-bit x86 code.
+                       # A problem.
                        #
-                       V_CCOPT="$V_CCOPT -arch x86_64 -arch i386"
-                       LDFLAGS="$LDFLAGS -arch x86_64 -arch i386"
-                       ;;
-               esac
-       fi
-       ;;
-
-hpux9*)
+                       { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
+$as_echo "yes" >&6; }
+                       can_add_to_cflags=no
 
-$as_echo "#define HAVE_HPUX9 1" >>confdefs.h
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+               fi
+               CFLAGS="$save_CFLAGS"
+               if test x"$can_add_to_cflags" = "xyes"
+               then
+                   V_CCOPT="$V_CCOPT -Wdocumentation"
+               fi
 
+else
 
-       #
-       # Use System V conventions for man pages.
-       #
-       MAN_FILE_FORMATS=4
-       MAN_MISC_INFO=5
-       ;;
+               { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+               CFLAGS="$save_CFLAGS"
 
-hpux10.0*)
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
 
-       #
-       # Use System V conventions for man pages.
-       #
-       MAN_FILE_FORMATS=4
-       MAN_MISC_INFO=5
-       ;;
 
-hpux10.1*)
+       { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether the compiler supports the -Wformat-nonliteral option" >&5
+$as_echo_n "checking whether the compiler supports the -Wformat-nonliteral option... " >&6; }
+       save_CFLAGS="$CFLAGS"
+       if expr "x-Wformat-nonliteral" : "x-W.*" >/dev/null
+       then
+           CFLAGS="$CFLAGS $ac_lbl_unknown_warning_option_error -Wformat-nonliteral"
+       elif expr "x-Wformat-nonliteral" : "x-f.*" >/dev/null
+       then
+           CFLAGS="$CFLAGS -Werror -Wformat-nonliteral"
+       elif expr "x-Wformat-nonliteral" : "x-m.*" >/dev/null
+       then
+           CFLAGS="$CFLAGS -Werror -Wformat-nonliteral"
+       else
+           CFLAGS="$CFLAGS -Wformat-nonliteral"
+       fi
+       cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
 
-       #
-       # Use System V conventions for man pages.
-       #
-       MAN_FILE_FORMATS=4
-       MAN_MISC_INFO=5
-       ;;
+int
+main ()
+{
+return 0
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
 
-hpux*)
+               { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
+$as_echo "yes" >&6; }
+               can_add_to_cflags=yes
+               #
+               # The compile supports this; do we have some C code for
+               # which the warning should *not* appear?
+               # We test the fourth argument because the third argument
+               # could contain quotes, breaking the test.
+               #
+               if test "x" != "x"
+               then
+                   CFLAGS="$CFLAGS $ac_lbl_cc_force_warning_errors"
+                   { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether -Wformat-nonliteral " >&5
+$as_echo_n "checking whether -Wformat-nonliteral ... " >&6; }
+                   cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
 
-$as_echo "#define HAVE_HPUX10_20_OR_LATER 1" >>confdefs.h
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
 
-       if test "`uname -m`" = "ia64"; then
-               DYEXT="so"
-       else
-               DYEXT="sl"
-       fi
+                       #
+                       # Not a problem.
+                       #
+                       { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
 
-       #
-       # "-b" builds a shared library; "+h" sets the soname.
-       #
-       SHLIB_OPT="-b"
-       SONAME_OPT="+h"
+else
 
-       #
-       # Use System V conventions for man pages.
-       #
-       MAN_FILE_FORMATS=4
-       MAN_MISC_INFO=5
-       ;;
+                       #
+                       # A problem.
+                       #
+                       { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
+$as_echo "yes" >&6; }
+                       can_add_to_cflags=no
 
-irix*)
-       #
-       # Use System V conventions for man pages.
-       #
-       MAN_FILE_FORMATS=4
-       MAN_MISC_INFO=5
-       ;;
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+               fi
+               CFLAGS="$save_CFLAGS"
+               if test x"$can_add_to_cflags" = "xyes"
+               then
+                   V_CCOPT="$V_CCOPT -Wformat-nonliteral"
+               fi
 
-linux*|freebsd*|netbsd*|openbsd*|dragonfly*|kfreebsd*|gnu*)
-       DYEXT="so"
+else
 
-       #
-       # Compiler assumed to be GCC; run-time linker may require a -R
-       # flag.
-       #
-       if test "$libdir" != "/usr/lib"; then
-               V_RFLAGS=-Wl,-R$libdir
-       fi
-       ;;
+               { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+               CFLAGS="$save_CFLAGS"
 
-osf*)
-       DYEXT="so"
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
 
-       #
-       # Use System V conventions for man pages.
-       #
-       MAN_FILE_FORMATS=4
-       MAN_MISC_INFO=5
-       ;;
 
-sinix*)
-       { $as_echo "$as_me:${as_lineno-$LINENO}: checking if SINIX compiler defines sinix" >&5
-$as_echo_n "checking if SINIX compiler defines sinix... " >&6; }
-       if ${ac_cv_cc_sinix_defined+:} false; then :
-  $as_echo_n "(cached) " >&6
-else
-  cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+       { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether the compiler supports the -Wmissing-noreturn option" >&5
+$as_echo_n "checking whether the compiler supports the -Wmissing-noreturn option... " >&6; }
+       save_CFLAGS="$CFLAGS"
+       if expr "x-Wmissing-noreturn" : "x-W.*" >/dev/null
+       then
+           CFLAGS="$CFLAGS $ac_lbl_unknown_warning_option_error -Wmissing-noreturn"
+       elif expr "x-Wmissing-noreturn" : "x-f.*" >/dev/null
+       then
+           CFLAGS="$CFLAGS -Werror -Wmissing-noreturn"
+       elif expr "x-Wmissing-noreturn" : "x-m.*" >/dev/null
+       then
+           CFLAGS="$CFLAGS -Werror -Wmissing-noreturn"
+       else
+           CFLAGS="$CFLAGS -Wmissing-noreturn"
+       fi
+       cat confdefs.h - <<_ACEOF >conftest.$ac_ext
 /* end confdefs.h.  */
 
 int
 main ()
 {
-int i = sinix;
+return 0
   ;
   return 0;
 }
 _ACEOF
 if ac_fn_c_try_compile "$LINENO"; then :
-  ac_cv_cc_sinix_defined=yes
+
+               { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
+$as_echo "yes" >&6; }
+               can_add_to_cflags=yes
+               #
+               # The compile supports this; do we have some C code for
+               # which the warning should *not* appear?
+               # We test the fourth argument because the third argument
+               # could contain quotes, breaking the test.
+               #
+               if test "x" != "x"
+               then
+                   CFLAGS="$CFLAGS $ac_lbl_cc_force_warning_errors"
+                   { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether -Wmissing-noreturn " >&5
+$as_echo_n "checking whether -Wmissing-noreturn ... " >&6; }
+                   cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+
+                       #
+                       # Not a problem.
+                       #
+                       { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+
 else
-  ac_cv_cc_sinix_defined=no
+
+                       #
+                       # A problem.
+                       #
+                       { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
+$as_echo "yes" >&6; }
+                       can_add_to_cflags=no
+
 fi
 rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
-fi
+               fi
+               CFLAGS="$save_CFLAGS"
+               if test x"$can_add_to_cflags" = "xyes"
+               then
+                   V_CCOPT="$V_CCOPT -Wmissing-noreturn"
+               fi
 
-           { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_cc_sinix_defined" >&5
-$as_echo "$ac_cv_cc_sinix_defined" >&6; }
-           if test $ac_cv_cc_sinix_defined = no ; then
+else
 
-$as_echo "#define sinix 1" >>confdefs.h
+               { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+               CFLAGS="$save_CFLAGS"
 
-           fi
-       ;;
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
 
-solaris*)
 
-$as_echo "#define HAVE_SOLARIS 1" >>confdefs.h
+       { $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"
+       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.  */
 
+int
+main ()
+{
+return 0
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
 
-       DYEXT="so"
-       #
-       # Use System V conventions for man pages.
-       #
-       MAN_FILE_FORMATS=4
-       MAN_MISC_INFO=5
-       ;;
-esac
+               { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
+$as_echo "yes" >&6; }
+               can_add_to_cflags=yes
+               #
+               # The compile supports this; do we have some C code for
+               # which the warning should *not* appear?
+               # We test the fourth argument because the third argument
+               # could contain quotes, breaking the test.
+               #
+               if test "x" != "x"
+               then
+                   CFLAGS="$CFLAGS $ac_lbl_cc_force_warning_errors"
+                   { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether -Wmissing-prototypes " >&5
+$as_echo_n "checking whether -Wmissing-prototypes ... " >&6; }
+                   cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
 
-# Check whether --enable-shared was given.
-if test "${enable_shared+set}" = set; then :
-  enableval=$enable_shared;
-fi
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
 
-test "x$enable_shared" = "xno" && DYEXT="none"
+                       #
+                       # Not a problem.
+                       #
+                       { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
 
-if test -n "$ac_tool_prefix"; then
-  # Extract the first word of "${ac_tool_prefix}ranlib", so it can be a program name with args.
-set dummy ${ac_tool_prefix}ranlib; 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_RANLIB+:} false; then :
-  $as_echo_n "(cached) " >&6
-else
-  if test -n "$RANLIB"; then
-  ac_cv_prog_RANLIB="$RANLIB" # Let the user override the test.
 else
-as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
-for as_dir in $PATH
-do
-  IFS=$as_save_IFS
-  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_RANLIB="${ac_tool_prefix}ranlib"
-    $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
-    break 2
-  fi
-done
-  done
-IFS=$as_save_IFS
+
+                       #
+                       # A problem.
+                       #
+                       { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
+$as_echo "yes" >&6; }
+                       can_add_to_cflags=no
 
 fi
-fi
-RANLIB=$ac_cv_prog_RANLIB
-if test -n "$RANLIB"; then
-  { $as_echo "$as_me:${as_lineno-$LINENO}: result: $RANLIB" >&5
-$as_echo "$RANLIB" >&6; }
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+               fi
+               CFLAGS="$save_CFLAGS"
+               if test x"$can_add_to_cflags" = "xyes"
+               then
+                   V_CCOPT="$V_CCOPT -Wmissing-prototypes"
+               fi
+
 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; }
+               CFLAGS="$save_CFLAGS"
+
 fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
 
 
-fi
-if test -z "$ac_cv_prog_RANLIB"; then
-  ac_ct_RANLIB=$RANLIB
-  # Extract the first word of "ranlib", so it can be a program name with args.
-set dummy ranlib; 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_ac_ct_RANLIB+:} false; then :
-  $as_echo_n "(cached) " >&6
-else
-  if test -n "$ac_ct_RANLIB"; then
-  ac_cv_prog_ac_ct_RANLIB="$ac_ct_RANLIB" # Let the user override the test.
-else
-as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
-for as_dir in $PATH
-do
-  IFS=$as_save_IFS
-  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_ac_ct_RANLIB="ranlib"
-    $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
-    break 2
-  fi
-done
-  done
-IFS=$as_save_IFS
+       { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether the compiler supports the -Wmissing-variable-declarations option" >&5
+$as_echo_n "checking whether the compiler supports the -Wmissing-variable-declarations option... " >&6; }
+       save_CFLAGS="$CFLAGS"
+       if expr "x-Wmissing-variable-declarations" : "x-W.*" >/dev/null
+       then
+           CFLAGS="$CFLAGS $ac_lbl_unknown_warning_option_error -Wmissing-variable-declarations"
+       elif expr "x-Wmissing-variable-declarations" : "x-f.*" >/dev/null
+       then
+           CFLAGS="$CFLAGS -Werror -Wmissing-variable-declarations"
+       elif expr "x-Wmissing-variable-declarations" : "x-m.*" >/dev/null
+       then
+           CFLAGS="$CFLAGS -Werror -Wmissing-variable-declarations"
+       else
+           CFLAGS="$CFLAGS -Wmissing-variable-declarations"
+       fi
+       cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
 
-fi
-fi
-ac_ct_RANLIB=$ac_cv_prog_ac_ct_RANLIB
-if test -n "$ac_ct_RANLIB"; then
-  { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_RANLIB" >&5
-$as_echo "$ac_ct_RANLIB" >&6; }
-else
-  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
-$as_echo "no" >&6; }
-fi
+int
+main ()
+{
+return 0
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
 
-  if test "x$ac_ct_RANLIB" = x; then
-    RANLIB=":"
-  else
-    case $cross_compiling:$ac_tool_warned in
-yes:)
-{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5
-$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;}
-ac_tool_warned=yes ;;
-esac
-    RANLIB=$ac_ct_RANLIB
-  fi
-else
-  RANLIB="$ac_cv_prog_RANLIB"
-fi
+               { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
+$as_echo "yes" >&6; }
+               can_add_to_cflags=yes
+               #
+               # The compile supports this; do we have some C code for
+               # which the warning should *not* appear?
+               # We test the fourth argument because the third argument
+               # could contain quotes, breaking the test.
+               #
+               if test "x" != "x"
+               then
+                   CFLAGS="$CFLAGS $ac_lbl_cc_force_warning_errors"
+                   { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether -Wmissing-variable-declarations " >&5
+$as_echo_n "checking whether -Wmissing-variable-declarations ... " >&6; }
+                   cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+
+                       #
+                       # Not a problem.
+                       #
+                       { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
 
-if test -n "$ac_tool_prefix"; then
-  # Extract the first word of "${ac_tool_prefix}ar", so it can be a program name with args.
-set dummy ${ac_tool_prefix}ar; 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_AR+:} false; then :
-  $as_echo_n "(cached) " >&6
-else
-  if test -n "$AR"; then
-  ac_cv_prog_AR="$AR" # Let the user override the test.
 else
-as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
-for as_dir in $PATH
-do
-  IFS=$as_save_IFS
-  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_AR="${ac_tool_prefix}ar"
-    $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
-    break 2
-  fi
-done
-  done
-IFS=$as_save_IFS
+
+                       #
+                       # A problem.
+                       #
+                       { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
+$as_echo "yes" >&6; }
+                       can_add_to_cflags=no
 
 fi
-fi
-AR=$ac_cv_prog_AR
-if test -n "$AR"; then
-  { $as_echo "$as_me:${as_lineno-$LINENO}: result: $AR" >&5
-$as_echo "$AR" >&6; }
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+               fi
+               CFLAGS="$save_CFLAGS"
+               if test x"$can_add_to_cflags" = "xyes"
+               then
+                   V_CCOPT="$V_CCOPT -Wmissing-variable-declarations"
+               fi
+
 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; }
+               CFLAGS="$save_CFLAGS"
+
 fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
 
 
-fi
-if test -z "$ac_cv_prog_AR"; then
-  ac_ct_AR=$AR
-  # Extract the first word of "ar", so it can be a program name with args.
-set dummy ar; 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_ac_ct_AR+:} false; then :
-  $as_echo_n "(cached) " >&6
-else
-  if test -n "$ac_ct_AR"; then
-  ac_cv_prog_ac_ct_AR="$ac_ct_AR" # Let the user override the test.
+       { $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; }
+               can_add_to_cflags=yes
+               #
+               # The compile supports this; do we have some C code for
+               # which the warning should *not* appear?
+               # We test the fourth argument because the third argument
+               # could contain quotes, breaking the test.
+               #
+               if test "x" != "x"
+               then
+                   CFLAGS="$CFLAGS $ac_lbl_cc_force_warning_errors"
+                   { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether -Wshadow " >&5
+$as_echo_n "checking whether -Wshadow ... " >&6; }
+                   cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+
+                       #
+                       # Not a problem.
+                       #
+                       { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+
 else
-as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
-for as_dir in $PATH
-do
-  IFS=$as_save_IFS
-  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_ac_ct_AR="ar"
-    $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
-    break 2
-  fi
-done
-  done
-IFS=$as_save_IFS
+
+                       #
+                       # A problem.
+                       #
+                       { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
+$as_echo "yes" >&6; }
+                       can_add_to_cflags=no
 
 fi
-fi
-ac_ct_AR=$ac_cv_prog_ac_ct_AR
-if test -n "$ac_ct_AR"; then
-  { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_AR" >&5
-$as_echo "$ac_ct_AR" >&6; }
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+               fi
+               CFLAGS="$save_CFLAGS"
+               if test x"$can_add_to_cflags" = "xyes"
+               then
+                   V_CCOPT="$V_CCOPT -Wshadow"
+               fi
+
 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; }
-fi
+               CFLAGS="$save_CFLAGS"
 
-  if test "x$ac_ct_AR" = x; then
-    AR=""
-  else
-    case $cross_compiling:$ac_tool_warned in
-yes:)
-{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5
-$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;}
-ac_tool_warned=yes ;;
-esac
-    AR=$ac_ct_AR
-  fi
-else
-  AR="$ac_cv_prog_AR"
 fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
 
 
-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether ln -s works" >&5
-$as_echo_n "checking whether ln -s works... " >&6; }
-LN_S=$as_ln_s
-if test "$LN_S" = "ln -s"; then
-  { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
+       { $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; }
+               can_add_to_cflags=yes
+               #
+               # The compile supports this; do we have some C code for
+               # which the warning should *not* appear?
+               # We test the fourth argument because the third argument
+               # could contain quotes, breaking the test.
+               #
+               if test "x" != "x"
+               then
+                   CFLAGS="$CFLAGS $ac_lbl_cc_force_warning_errors"
+                   { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether -Wsign-compare " >&5
+$as_echo_n "checking whether -Wsign-compare ... " >&6; }
+                   cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+
+                       #
+                       # Not a problem.
+                       #
+                       { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+
 else
-  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no, using $LN_S" >&5
-$as_echo "no, using $LN_S" >&6; }
+
+                       #
+                       # A problem.
+                       #
+                       { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
+$as_echo "yes" >&6; }
+                       can_add_to_cflags=no
+
 fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+               fi
+               CFLAGS="$save_CFLAGS"
+               if test x"$can_add_to_cflags" = "xyes"
+               then
+                   V_CCOPT="$V_CCOPT -Wsign-compare"
+               fi
 
+else
 
+               { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+               CFLAGS="$save_CFLAGS"
 
-rm -f os-proto.h
-    if test "${LBL_CFLAGS+set}" = set; then
-           V_CCOPT="$V_CCOPT ${LBL_CFLAGS}"
-    fi
-    if test -f .devel ; then
-           #
-           # Skip all the warning option stuff on some compilers.
-           #
-           if test "$ac_lbl_cc_dont_try_gcc_dashW" != yes; then
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
 
-       { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether the compiler fails when given an unknown warning option" >&5
-$as_echo_n "checking whether the compiler fails when given an unknown warning option... " >&6; }
+
+       { $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 -Wxyzzy-this-will-never-succeed-xyzzy"
+       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.  */
 
@@ -7345,29 +9748,75 @@ return 0
 _ACEOF
 if ac_fn_c_try_compile "$LINENO"; then :
 
-               { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
-$as_echo "no" >&6; }
+               { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
+$as_echo "yes" >&6; }
+               can_add_to_cflags=yes
                #
-               # We're assuming this is clang, where
-               # -Werror=unknown-warning-option is the appropriate
-               # option to force the compiler to fail.
+               # The compile supports this; do we have some C code for
+               # which the warning should *not* appear?
+               # We test the fourth argument because the third argument
+               # could contain quotes, breaking the test.
                #
-               ac_lbl_unknown_warning_option_error="-Werror=unknown-warning-option"
+               if test "x" != "x"
+               then
+                   CFLAGS="$CFLAGS $ac_lbl_cc_force_warning_errors"
+                   { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether -Wstrict-prototypes " >&5
+$as_echo_n "checking whether -Wstrict-prototypes ... " >&6; }
+                   cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+
+                       #
+                       # Not a problem.
+                       #
+                       { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
 
 else
 
-               { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
+                       #
+                       # A problem.
+                       #
+                       { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
 $as_echo "yes" >&6; }
+                       can_add_to_cflags=no
 
 fi
 rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
-       CFLAGS="$save_CFLAGS"
+               fi
+               CFLAGS="$save_CFLAGS"
+               if test x"$can_add_to_cflags" = "xyes"
+               then
+                   V_CCOPT="$V_CCOPT -Wstrict-prototypes"
+               fi
 
+else
 
-       { $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; }
+               { $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 -Wunused-parameter option" >&5
+$as_echo_n "checking whether the compiler supports the -Wunused-parameter option... " >&6; }
        save_CFLAGS="$CFLAGS"
-       CFLAGS="$CFLAGS $ac_lbl_unknown_warning_option_error -Wall"
+       if expr "x-Wunused-parameter" : "x-W.*" >/dev/null
+       then
+           CFLAGS="$CFLAGS $ac_lbl_unknown_warning_option_error -Wunused-parameter"
+       elif expr "x-Wunused-parameter" : "x-f.*" >/dev/null
+       then
+           CFLAGS="$CFLAGS -Werror -Wunused-parameter"
+       elif expr "x-Wunused-parameter" : "x-m.*" >/dev/null
+       then
+           CFLAGS="$CFLAGS -Werror -Wunused-parameter"
+       else
+           CFLAGS="$CFLAGS -Wunused-parameter"
+       fi
        cat confdefs.h - <<_ACEOF >conftest.$ac_ext
 /* end confdefs.h.  */
 
@@ -7383,8 +9832,47 @@ if ac_fn_c_try_compile "$LINENO"; then :
 
                { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
 $as_echo "yes" >&6; }
+               can_add_to_cflags=yes
+               #
+               # The compile supports this; do we have some C code for
+               # which the warning should *not* appear?
+               # We test the fourth argument because the third argument
+               # could contain quotes, breaking the test.
+               #
+               if test "x" != "x"
+               then
+                   CFLAGS="$CFLAGS $ac_lbl_cc_force_warning_errors"
+                   { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether -Wunused-parameter " >&5
+$as_echo_n "checking whether -Wunused-parameter ... " >&6; }
+                   cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+
+                       #
+                       # Not a problem.
+                       #
+                       { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+
+else
+
+                       #
+                       # A problem.
+                       #
+                       { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
+$as_echo "yes" >&6; }
+                       can_add_to_cflags=no
+
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+               fi
                CFLAGS="$save_CFLAGS"
-               V_CCOPT="$V_CCOPT -Wall"
+               if test x"$can_add_to_cflags" = "xyes"
+               then
+                   V_CCOPT="$V_CCOPT -Wunused-parameter"
+               fi
 
 else
 
@@ -7396,10 +9884,21 @@ 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; }
+       { $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"
-       CFLAGS="$CFLAGS $ac_lbl_unknown_warning_option_error -Wmissing-prototypes"
+       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.  */
 
@@ -7415,8 +9914,47 @@ if ac_fn_c_try_compile "$LINENO"; then :
 
                { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
 $as_echo "yes" >&6; }
+               can_add_to_cflags=yes
+               #
+               # The compile supports this; do we have some C code for
+               # which the warning should *not* appear?
+               # We test the fourth argument because the third argument
+               # could contain quotes, breaking the test.
+               #
+               if test "x" != "x"
+               then
+                   CFLAGS="$CFLAGS $ac_lbl_cc_force_warning_errors"
+                   { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether -Wused-but-marked-unused " >&5
+$as_echo_n "checking whether -Wused-but-marked-unused ... " >&6; }
+                   cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+
+                       #
+                       # Not a problem.
+                       #
+                       { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+
+else
+
+                       #
+                       # A problem.
+                       #
+                       { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
+$as_echo "yes" >&6; }
+                       can_add_to_cflags=no
+
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+               fi
                CFLAGS="$save_CFLAGS"
-               V_CCOPT="$V_CCOPT -Wmissing-prototypes"
+               if test x"$can_add_to_cflags" = "xyes"
+               then
+                   V_CCOPT="$V_CCOPT -Wused-but-marked-unused"
+               fi
 
 else
 
@@ -7427,11 +9965,49 @@ $as_echo "no" >&6; }
 fi
 rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
 
+                   # Warns about safeguards added in case the enums are
+                   # extended
+                   # AC_LBL_CHECK_COMPILER_OPT(V_CCOPT, -Wcovered-switch-default)
+                   #
+                   # This can cause problems with ntohs(), ntohl(),
+                   # htons(), and htonl() on some platforms, such
+                   # as OpenBSD 6.3 with Clang 5.0.1.  I guess the
+                   # problem is that the macro that ultimately does
+                   # the byte-swapping involves a conditional
+                   # expression that tests whether the value being
+                   # swapped is a compile-time constant or not,
+                   # using __builtin_constant_p(), and, depending
+                   # on whether it is, does a compile-time swap or
+                   # a run-time swap; perhaps the compiler always
+                   # considers one of the two results of the
+                   # conditional expressin is never evaluated,
+                   # because the conditional check is done at
+                   # compile time, and thus always says "that
+                   # expression is never executed".
+                   #
+                   # (Perhaps there should be a way of flagging
+                   # an expression that you *want* evaluated at
+                   # compile time, so that the compiler 1) warns
+                   # if it *can't* be evaluated at compile time
+                   # and 2) *doesn't* warn that the true or false
+                   # branch will never be reached.)
+                   #
 
-       { $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; }
+       { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether the compiler supports the -Wunreachable-code option" >&5
+$as_echo_n "checking whether the compiler supports the -Wunreachable-code option... " >&6; }
        save_CFLAGS="$CFLAGS"
-       CFLAGS="$CFLAGS $ac_lbl_unknown_warning_option_error -Wstrict-prototypes"
+       if expr "x-Wunreachable-code" : "x-W.*" >/dev/null
+       then
+           CFLAGS="$CFLAGS $ac_lbl_unknown_warning_option_error -Wunreachable-code"
+       elif expr "x-Wunreachable-code" : "x-f.*" >/dev/null
+       then
+           CFLAGS="$CFLAGS -Werror -Wunreachable-code"
+       elif expr "x-Wunreachable-code" : "x-m.*" >/dev/null
+       then
+           CFLAGS="$CFLAGS -Werror -Wunreachable-code"
+       else
+           CFLAGS="$CFLAGS -Wunreachable-code"
+       fi
        cat confdefs.h - <<_ACEOF >conftest.$ac_ext
 /* end confdefs.h.  */
 
@@ -7447,8 +10023,54 @@ if ac_fn_c_try_compile "$LINENO"; then :
 
                { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
 $as_echo "yes" >&6; }
+               can_add_to_cflags=yes
+               #
+               # The compile supports this; do we have some C code for
+               # which the warning should *not* appear?
+               # We test the fourth argument because the third argument
+               # could contain quotes, breaking the test.
+               #
+               if test "xgenerates warnings from ntohs()" != "x"
+               then
+                   CFLAGS="$CFLAGS $ac_lbl_cc_force_warning_errors"
+                   { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether -Wunreachable-code generates warnings from ntohs()" >&5
+$as_echo_n "checking whether -Wunreachable-code generates warnings from ntohs()... " >&6; }
+                   cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+#include <arpa/inet.h>
+
+unsigned short
+testme(unsigned short a)
+{
+       return ntohs(a);
+}
+
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+
+                       #
+                       # Not a problem.
+                       #
+                       { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+
+else
+
+                       #
+                       # A problem.
+                       #
+                       { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
+$as_echo "yes" >&6; }
+                       can_add_to_cflags=no
+
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+               fi
                CFLAGS="$save_CFLAGS"
-               V_CCOPT="$V_CCOPT -Wstrict-prototypes"
+               if test x"$can_add_to_cflags" = "xyes"
+               then
+                   V_CCOPT="$V_CCOPT -Wunreachable-code"
+               fi
 
 else
 
@@ -7531,8 +10153,11 @@ $as_echo_n "checking whether the compiler supports generating dependencies... "
 /* end confdefs.h.  */
 int main(void) { return 0; }
 _ACEOF
-               echo "$CC" $ac_lbl_dependency_flag conftest.c >&5
-               if "$CC" $ac_lbl_dependency_flag conftest.c >/dev/null 2>&1; then
+               if { { $as_echo "$as_me:${as_lineno-$LINENO}: eval \"\$CC \$ac_lbl_dependency_flag conftest.c >/dev/null 2>&1\""; } >&5
+  (eval "$CC $ac_lbl_dependency_flag conftest.c >/dev/null 2>&1") 2>&5
+  ac_status=$?
+  $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+  test $ac_status = 0; }; then
                        { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes, with $ac_lbl_dependency_flag" >&5
 $as_echo "yes, with $ac_lbl_dependency_flag" >&6; }
                        DEPENDENCY_CFLAG="$ac_lbl_dependency_flag"
@@ -7544,7 +10169,7 @@ $as_echo "no" >&6; }
                        # We can't run mkdep, so have "make depend" do
                        # nothing.
                        #
-                       MKDEP=:
+                       MKDEP='${srcdir}/nomkdep'
                fi
                rm -rf conftest*
        else
@@ -7554,7 +10179,7 @@ $as_echo "no" >&6; }
                # We can't run mkdep, so have "make depend" do
                # nothing.
                #
-               MKDEP=:
+               MKDEP='${srcdir}/nomkdep'
        fi
 
 
@@ -7580,108 +10205,68 @@ $as_echo "$as_me: WARNING: can't find $name" >&2;}
            fi
     fi
 
-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking if sockaddr struct has the sa_len member" >&5
-$as_echo_n "checking if sockaddr struct has the sa_len member... " >&6; }
-    if ${ac_cv_lbl_sockaddr_has_sa_len+:} false; then :
-  $as_echo_n "(cached) " >&6
-else
-  cat confdefs.h - <<_ACEOF >conftest.$ac_ext
-/* end confdefs.h.  */
+#
+# Check to see if the sockaddr struct has the 4.4 BSD sa_len member.
+#
+ac_fn_c_check_member "$LINENO" "struct sockaddr" "sa_len" "ac_cv_member_struct_sockaddr_sa_len" "
+       #include <sys/types.h>
+       #include <sys/socket.h>
 
-#      include <sys/types.h>
-#      include <sys/socket.h>
-int
-main ()
-{
-u_int i = sizeof(((struct sockaddr *)0)->sa_len)
-  ;
-  return 0;
-}
+"
+if test "x$ac_cv_member_struct_sockaddr_sa_len" = xyes; then :
+
+cat >>confdefs.h <<_ACEOF
+#define HAVE_STRUCT_SOCKADDR_SA_LEN 1
 _ACEOF
-if ac_fn_c_try_compile "$LINENO"; then :
-  ac_cv_lbl_sockaddr_has_sa_len=yes
-else
-  ac_cv_lbl_sockaddr_has_sa_len=no
-fi
-rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
-fi
 
-    { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lbl_sockaddr_has_sa_len" >&5
-$as_echo "$ac_cv_lbl_sockaddr_has_sa_len" >&6; }
-    if test $ac_cv_lbl_sockaddr_has_sa_len = yes ; then
 
-$as_echo "#define HAVE_SOCKADDR_SA_LEN 1" >>confdefs.h
+fi
 
-    fi
 
-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking if sockaddr_storage struct exists" >&5
-$as_echo_n "checking if sockaddr_storage struct exists... " >&6; }
-    if ${ac_cv_lbl_has_sockaddr_storage+:} false; then :
-  $as_echo_n "(cached) " >&6
-else
-  cat confdefs.h - <<_ACEOF >conftest.$ac_ext
-/* end confdefs.h.  */
+#
+# Check to see if there's a sockaddr_storage structure.
+#
+ac_fn_c_check_type "$LINENO" "struct sockaddr_storage" "ac_cv_type_struct_sockaddr_storage" "
+       #include <sys/types.h>
+       #include <sys/socket.h>
 
-#      include <sys/types.h>
-#      include <sys/socket.h>
-int
-main ()
-{
-u_int i = sizeof (struct sockaddr_storage)
-  ;
-  return 0;
-}
+"
+if test "x$ac_cv_type_struct_sockaddr_storage" = xyes; then :
+
+cat >>confdefs.h <<_ACEOF
+#define HAVE_STRUCT_SOCKADDR_STORAGE 1
 _ACEOF
-if ac_fn_c_try_compile "$LINENO"; then :
-  ac_cv_lbl_has_sockaddr_storage=yes
-else
-  ac_cv_lbl_has_sockaddr_storage=no
-fi
-rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
-fi
 
-    { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lbl_has_sockaddr_storage" >&5
-$as_echo "$ac_cv_lbl_has_sockaddr_storage" >&6; }
-    if test $ac_cv_lbl_has_sockaddr_storage = yes ; then
 
-$as_echo "#define HAVE_SOCKADDR_STORAGE 1" >>confdefs.h
+fi
 
-    fi
 
-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking if dl_hp_ppa_info_t struct has dl_module_id_1 member" >&5
-$as_echo_n "checking if dl_hp_ppa_info_t struct has dl_module_id_1 member... " >&6; }
-    if ${ac_cv_lbl_dl_hp_ppa_info_t_has_dl_module_id_1+:} false; then :
-  $as_echo_n "(cached) " >&6
-else
-  cat confdefs.h - <<_ACEOF >conftest.$ac_ext
-/* end confdefs.h.  */
+#
+# Check to see if the dl_hp_ppa_info_t struct has the HP-UX 11.00
+# dl_module_id_1 member.
+#
+# NOTE: any failure means we conclude that it doesn't have that member,
+# so if we don't have DLPI, don't have a <sys/dlpi_ext.h> header, or
+# have one that doesn't declare a dl_hp_ppa_info_t type, we conclude
+# it doesn't have that member (which is OK, as either we won't be
+# using code that would use that member, or we wouldn't compile in
+# any case).
+#
+ac_fn_c_check_member "$LINENO" "dl_hp_ppa_info_t" "dl_module_id_1" "ac_cv_member_dl_hp_ppa_info_t_dl_module_id_1" "
+       #include <sys/types.h>
+       #include <sys/dlpi.h>
+       #include <sys/dlpi_ext.h>
 
-#      include <sys/types.h>
-#      include <sys/dlpi.h>
-#      include <sys/dlpi_ext.h>
-int
-main ()
-{
-u_int i = sizeof(((dl_hp_ppa_info_t *)0)->dl_module_id_1)
-  ;
-  return 0;
-}
+"
+if test "x$ac_cv_member_dl_hp_ppa_info_t_dl_module_id_1" = xyes; then :
+
+cat >>confdefs.h <<_ACEOF
+#define HAVE_DL_HP_PPA_INFO_T_DL_MODULE_ID_1 1
 _ACEOF
-if ac_fn_c_try_compile "$LINENO"; then :
-  ac_cv_lbl_dl_hp_ppa_info_t_has_dl_module_id_1=yes
-else
-  ac_cv_lbl_dl_hp_ppa_info_t_has_dl_module_id_1=no
-fi
-rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
-fi
 
-    { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lbl_dl_hp_ppa_info_t_has_dl_module_id_1" >&5
-$as_echo "$ac_cv_lbl_dl_hp_ppa_info_t_has_dl_module_id_1" >&6; }
-    if test $ac_cv_lbl_dl_hp_ppa_info_t_has_dl_module_id_1 = yes ; then
 
-$as_echo "#define HAVE_HP_PPA_INFO_T_DL_MODULE_ID_1 1" >>confdefs.h
+fi
 
-    fi
 
 { $as_echo "$as_me:${as_lineno-$LINENO}: checking if unaligned accesses fail" >&5
 $as_echo_n "checking if unaligned accesses fail... " >&6; }
@@ -7778,16 +10363,9 @@ $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.
-#
 
-$as_echo "#define HAVE_VERSION_H 1" >>confdefs.h
 
 
-rm -f net
-ln -s ${srcdir}/bpf/net net
 
 
 
@@ -7807,10 +10385,33 @@ ln -s ${srcdir}/bpf/net net
 
 
 
-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for USB sniffing support" >&5
+
+
+
+
+
+
+
+
+# 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
+
+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
 
@@ -7882,87 +10483,136 @@ done
          # "value", rather than "bRequestType", "bRequest", and
          # "wValue".
          #
-         { $as_echo "$as_me:${as_lineno-$LINENO}: checking if usbdevfs_ctrltransfer struct has bRequestType member" >&5
-$as_echo_n "checking if usbdevfs_ctrltransfer struct has bRequestType member... " >&6; }
-         if ${ac_cv_usbdevfs_ctrltransfer_has_bRequestType+:} false; then :
+         ac_fn_c_check_member "$LINENO" "struct usbdevfs_ctrltransfer" "bRequestType" "ac_cv_member_struct_usbdevfs_ctrltransfer_bRequestType" "
+                 $ac_includes_default
+                 #ifdef HAVE_LINUX_COMPILER_H
+                 #include <linux/compiler.h>
+                 #endif
+                 #include <linux/usbdevice_fs.h>
+
+"
+if test "x$ac_cv_member_struct_usbdevfs_ctrltransfer_bRequestType" = xyes; then :
+
+cat >>confdefs.h <<_ACEOF
+#define HAVE_STRUCT_USBDEVFS_CTRLTRANSFER_BREQUESTTYPE 1
+_ACEOF
+
+
+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
+
+
+
+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
+$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
+$as_echo_n "checking whether we can compile the netfilter support... " >&6; }
+               if ${ac_cv_netfilter_can_compile+:} false; then :
   $as_echo_n "(cached) " >&6
 else
   cat confdefs.h - <<_ACEOF >conftest.$ac_ext
 /* end confdefs.h.  */
 
 $ac_includes_default
-#ifdef HAVE_SYS_BITYPES_H
-#include <sys/bitypes.h>
-#endif
-#ifdef HAVE_LINUX_COMPILER_H
-#include <linux/compiler.h>
-#endif
-#include <linux/usbdevice_fs.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <linux/types.h>
+
+#include <linux/netlink.h>
+#include <linux/netfilter.h>
+#include <linux/netfilter/nfnetlink.h>
+#include <linux/netfilter/nfnetlink_log.h>
+#include <linux/netfilter/nfnetlink_queue.h>
 int
 main ()
 {
-u_int i = sizeof(((struct usbdevfs_ctrltransfer *)0)->bRequestType)
+
   ;
   return 0;
 }
 _ACEOF
 if ac_fn_c_try_compile "$LINENO"; then :
-  ac_cv_usbdevfs_ctrltransfer_has_bRequestType=yes
+  ac_cv_netfilter_can_compile=yes
 else
-  ac_cv_usbdevfs_ctrltransfer_has_bRequestType=no
+  ac_cv_netfilter_can_compile=no
 fi
 rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
 fi
 
-           { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_usbdevfs_ctrltransfer_has_bRequestType" >&5
-$as_echo "$ac_cv_usbdevfs_ctrltransfer_has_bRequestType" >&6; }
-           if test $ac_cv_usbdevfs_ctrltransfer_has_bRequestType = yes ; then
+               { $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
 
-$as_echo "#define HAVE_USBDEVFS_CTRLTRANSFER_BREQUESTTYPE 1" >>confdefs.h
+$as_echo "#define PCAP_SUPPORT_NETFILTER 1" >>confdefs.h
 
-           fi
-       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
 
 
 
-{ $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
-$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 --enable-netmap was given.
+if test "${enable_netmap+set}" = set; then :
+  enableval=$enable_netmap;
+else
+  enable_netmap=yes
+fi
+
+
+if test "x$enable_netmap" != "xno" ; then
        #
-       # Check whether the includes Just Work.  If not, don't turn on
-       # netfilter support.
+       # Check whether net/netmap_user.h is usable if NETMAP_WITH_LIBS is
+       # defined; it's not usable on DragonFly BSD 4.6 if NETMAP_WITH_LIBS
+       # is defined, for example, as it includes a non-existent malloc.h
+       # header.
        #
-       { $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 :
+       { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether we can compile the netmap support" >&5
+$as_echo_n "checking whether we can compile the netmap support... " >&6; }
+       if ${ac_cv_net_netmap_user_can_compile+:} false; then :
   $as_echo_n "(cached) " >&6
 else
   cat confdefs.h - <<_ACEOF >conftest.$ac_ext
 /* end confdefs.h.  */
 
 $ac_includes_default
-#include <sys/socket.h>
-#include <netinet/in.h>
-#include <linux/types.h>
-
-#include <linux/netlink.h>
-#include <linux/netfilter.h>
-#include <linux/netfilter/nfnetlink.h>
-#include <linux/netfilter/nfnetlink_log.h>
-#include <linux/netfilter/nfnetlink_queue.h>
+#define NETMAP_WITH_LIBS
+#include <net/netmap_user.h>
 int
 main ()
 {
@@ -7972,29 +10622,25 @@ main ()
 }
 _ACEOF
 if ac_fn_c_try_compile "$LINENO"; then :
-  ac_cv_netfilter_can_compile=yes
+  ac_cv_net_netmap_user_can_compile=yes
 else
-  ac_cv_netfilter_can_compile=no
+  ac_cv_net_netmap_user_can_compile=no
 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 "$ac_cv_netfilter_can_compile" >&6; }
-       if test $ac_cv_netfilter_can_compile = yes ; then
+       { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_net_netmap_user_can_compile" >&5
+$as_echo "$ac_cv_net_netmap_user_can_compile" >&6; }
+       if test $ac_cv_net_netmap_user_can_compile = yes ; then
 
-$as_echo "#define PCAP_SUPPORT_NETFILTER 1" >>confdefs.h
+$as_echo "#define PCAP_SUPPORT_NETMAP 1" >>confdefs.h
 
-         NETFILTER_SRC=pcap-netfilter-linux.c
+           NETMAP_SRC=pcap-netmap.c
        fi
-       ;;
-*)
-       { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
-$as_echo "no" >&6; }
-       ;;
-esac
 
 
+fi
+
 
 # Check whether --enable-bluetooth was given.
 if test "${enable_bluetooth+set}" = set; then :
@@ -8004,269 +10650,120 @@ 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*)
                ac_fn_c_check_header_mongrel "$LINENO" "bluetooth/bluetooth.h" "ac_cv_header_bluetooth_bluetooth_h" "$ac_includes_default"
 if test "x$ac_cv_header_bluetooth_bluetooth_h" = xyes; then :
 
+                       #
+                       # We have bluetooth.h, so we support Bluetooth
+                       # sniffing.
+                       #
 
 $as_echo "#define PCAP_SUPPORT_BT 1" >>confdefs.h
 
-                 BT_SRC=pcap-bt-linux.c
-                 { $as_echo "$as_me:${as_lineno-$LINENO}: Bluetooth sniffing is supported" >&5
+                       BT_SRC=pcap-bt-linux.c
+                       { $as_echo "$as_me:${as_lineno-$LINENO}: Bluetooth sniffing is supported" >&5
 $as_echo "$as_me: Bluetooth sniffing is supported" >&6;}
+                       ac_lbl_bluetooth_available=yes
 
-                 #
-                 # OK, does struct sockaddr_hci have an hci_channel
-                 # member?
-                 #
-                 { $as_echo "$as_me:${as_lineno-$LINENO}: checking if struct sockaddr_hci has hci_channel member" >&5
-$as_echo_n "checking if struct sockaddr_hci has hci_channel member... " >&6; }
-                 if ${ac_cv_lbl_sockaddr_hci_has_hci_channel+:} false; then :
-  $as_echo_n "(cached) " >&6
-else
-  cat confdefs.h - <<_ACEOF >conftest.$ac_ext
-/* end confdefs.h.  */
+                       #
+                       # OK, does struct sockaddr_hci have an hci_channel
+                       # member?
+                       #
+                       ac_fn_c_check_member "$LINENO" "struct sockaddr_hci" "hci_channel" "ac_cv_member_struct_sockaddr_hci_hci_channel" "
+                               #include <bluetooth/bluetooth.h>
+                               #include <bluetooth/hci.h>
 
-#include <bluetooth/bluetooth.h>
-#include <bluetooth/hci.h>
+"
+if test "x$ac_cv_member_struct_sockaddr_hci_hci_channel" = xyes; then :
 
-int
-main ()
-{
-u_int i = sizeof(((struct sockaddr_hci *)0)->hci_channel)
-  ;
-  return 0;
-}
+cat >>confdefs.h <<_ACEOF
+#define HAVE_STRUCT_SOCKADDR_HCI_HCI_CHANNEL 1
 _ACEOF
-if ac_fn_c_try_compile "$LINENO"; then :
-  ac_cv_lbl_sockaddr_hci_has_hci_channel=yes
-else
-  ac_cv_lbl_sockaddr_hci_has_hci_channel=no
-fi
-rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
-fi
-
-                   { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lbl_sockaddr_hci_has_hci_channel" >&5
-$as_echo "$ac_cv_lbl_sockaddr_hci_has_hci_channel" >&6; }
-                   if test $ac_cv_lbl_sockaddr_hci_has_hci_channel = yes ; then
-
-$as_echo "#define SOCKADDR_HCI_HAS_HCI_CHANNEL /**/" >>confdefs.h
 
 
-                     #
-                     # OK, is HCI_CHANNEL_MONITOR defined?
-                     #
-                     { $as_echo "$as_me:${as_lineno-$LINENO}: checking if HCI_CHANNEL_MONITOR is defined" >&5
+                               #
+                               # Yes; is HCI_CHANNEL_MONITOR defined?
+                               #
+                               { $as_echo "$as_me:${as_lineno-$LINENO}: checking if HCI_CHANNEL_MONITOR is defined" >&5
 $as_echo_n "checking if HCI_CHANNEL_MONITOR is defined... " >&6; }
-                     if ${ac_cv_lbl_hci_channel_monitor_is_defined+:} false; then :
+                               if ${ac_cv_lbl_hci_channel_monitor_is_defined+:} false; then :
   $as_echo_n "(cached) " >&6
 else
   cat confdefs.h - <<_ACEOF >conftest.$ac_ext
 /* end confdefs.h.  */
 
-#include <bluetooth/bluetooth.h>
-#include <bluetooth/hci.h>
+                                           #include <bluetooth/bluetooth.h>
+                                           #include <bluetooth/hci.h>
 
 int
 main ()
 {
-u_int i = HCI_CHANNEL_MONITOR
+
+                                           u_int i = HCI_CHANNEL_MONITOR;
+
   ;
   return 0;
 }
 _ACEOF
 if ac_fn_c_try_compile "$LINENO"; then :
-  ac_cv_lbl_hci_channel_monitor_is_defined=yes
-else
-  ac_cv_lbl_hci_channel_monitor_is_defined=no
-fi
-rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
-fi
 
-                     { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lbl_hci_channel_monitor_is_defined" >&5
-$as_echo "$ac_cv_lbl_hci_channel_monitor_is_defined" >&6; }
-                     if test $ac_cv_lbl_hci_channel_monitor_is_defined = yes ; then
+                                           { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
+$as_echo "yes" >&6; }
 
 $as_echo "#define PCAP_SUPPORT_BT_MONITOR /**/" >>confdefs.h
 
-                       BT_MONITOR_SRC=pcap-bt-monitor-linux.c
-                     fi
-                   fi
-                   ac_lbl_bluetooth_available=yes
+                                           BT_MONITOR_SRC=pcap-bt-monitor-linux.c
 
 else
-  ac_lbl_bluetooth_available=no
-
-fi
-
-
-               if test "x$ac_lbl_bluetooth_available" == "xno" ; then
-                   if test "x$enable_bluetooth" = "xyes" ; then
-                       as_fn_error $? "Bluetooth sniffing is not supported; install bluez-lib devel to enable it" "$LINENO" 5
-                   else
-                       { $as_echo "$as_me:${as_lineno-$LINENO}: Bluetooth sniffing is not supported; install bluez-lib devel to enable it" >&5
-$as_echo "$as_me: Bluetooth sniffing is not supported; install bluez-lib devel to enable it" >&6;}
-                   fi
-               fi
-               ;;
-       *)
-               if test "x$enable_bluetooth" = "xyes" ; then
-                   as_fn_error $? "no Bluetooth sniffing support implemented for $host_os" "$LINENO" 5
-               else
-                   { $as_echo "$as_me:${as_lineno-$LINENO}: no Bluetooth sniffing support implemented for $host_os" >&5
-$as_echo "$as_me: no Bluetooth sniffing support implemented for $host_os" >&6;}
-               fi
-               ;;
-       esac
-
 
+                                           { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
 
 fi
-
-# Check whether --enable-canusb was given.
-if test "${enable_canusb+set}" = set; then :
-  enableval=$enable_canusb;
-else
-  enable_canusb=ifsupportavailable
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
 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
+                       #
+                       # We don't have bluetooth.h, so we don't support
+                       # Bluetooth sniffing.
+                       #
+                       if test "x$enable_bluetooth" = "xyes" ; then
+                               as_fn_error $? "Bluetooth sniffing is not supported; install bluez-lib devel to enable it" "$LINENO" 5
+                       else
+                               { $as_echo "$as_me:${as_lineno-$LINENO}: Bluetooth sniffing is not supported; install bluez-lib devel to enable it" >&5
+$as_echo "$as_me: Bluetooth sniffing is not supported; install bluez-lib devel to enable it" >&6;}
+                       fi
 
 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
+               if test "x$enable_bluetooth" = "xyes" ; then
+                       as_fn_error $? "no Bluetooth sniffing 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;}
+                       { $as_echo "$as_me:${as_lineno-$LINENO}: no Bluetooth sniffing support implemented for $host_os" >&5
+$as_echo "$as_me: no Bluetooth sniffing 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
 
@@ -8278,28 +10775,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 macOS; see
+                       #
                        # https://bugs.freedesktop.org/show_bug.cgi?id=74029
                        #
-                       as_fn_error $? "Due to freedesktop.org bug 74029, D-Bus capture support is not available on OS X" "$LINENO" 5
-                       ;;
+                       # The user requested it, so fail.
+                       #
+                       as_fn_error $? "Due to freedesktop.org bug 74029, D-Bus capture support is not available on macOS" "$LINENO" 5
                esac
        else
                case "$host_os" in
 
                darwin*)
                        #
+                       # We don't support D-Bus sniffing on macOS; 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 +10852,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,62 +10884,153 @@ 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
 
 
 fi
 
-case "$host_os" in
-linux*)
-       for ac_header in linux/net_tstamp.h
-do :
-  ac_fn_c_check_header_mongrel "$LINENO" "linux/net_tstamp.h" "ac_cv_header_linux_net_tstamp_h" "$ac_includes_default"
-if test "x$ac_cv_header_linux_net_tstamp_h" = xyes; then :
-  cat >>confdefs.h <<_ACEOF
-#define HAVE_LINUX_NET_TSTAMP_H 1
+# Check whether --enable-rdma was given.
+if test "${enable_rdma+set}" = set; then :
+  enableval=$enable_rdma;
+else
+  enable_rdma=ifavailable
+fi
+
+
+if test "xxx_only" = yes; then
+       # User requested something-else-only pcap, so they don't
+       # want RDMA support.
+       enable_rdma=no
+fi
+
+if test "x$enable_rdma" != "xno"; then
+       { $as_echo "$as_me:${as_lineno-$LINENO}: checking for ibv_get_device_list in -libverbs" >&5
+$as_echo_n "checking for ibv_get_device_list in -libverbs... " >&6; }
+if ${ac_cv_lib_ibverbs_ibv_get_device_list+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  ac_check_lib_save_LIBS=$LIBS
+LIBS="-libverbs  $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 ibv_get_device_list ();
+int
+main ()
+{
+return ibv_get_device_list ();
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_c_try_link "$LINENO"; then :
+  ac_cv_lib_ibverbs_ibv_get_device_list=yes
+else
+  ac_cv_lib_ibverbs_ibv_get_device_list=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_ibverbs_ibv_get_device_list" >&5
+$as_echo "$ac_cv_lib_ibverbs_ibv_get_device_list" >&6; }
+if test "x$ac_cv_lib_ibverbs_ibv_get_device_list" = xyes; then :
+
+               ac_fn_c_check_header_mongrel "$LINENO" "infiniband/verbs.h" "ac_cv_header_infiniband_verbs_h" "$ac_includes_default"
+if test "x$ac_cv_header_infiniband_verbs_h" = xyes; then :
+
+                       #
+                       # ibv_create_flow may be defined as a static inline
+                       # function in infiniband/verbs.h, so we can't
+                       # use AC_CHECK_LIB.
+                       #
+                       # Too bad autoconf has no AC_SYMBOL_EXISTS()
+                       # macro that works like CMake's check_symbol_exists()
+                       # function, to check do a compile check like
+                       # this (they do a clever trick to avoid having
+                       # to know the function's signature).
+                       #
+                       { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether libibverbs defines ibv_create_flow" >&5
+$as_echo_n "checking whether libibverbs defines ibv_create_flow... " >&6; }
+                       cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+
+                                       #include <infiniband/verbs.h>
+
+int
+main ()
+{
+
+                                       (void) ibv_create_flow((struct ibv_qp *) NULL,
+                                                              (struct ibv_flow_attr *) NULL);
+
+  ;
+  return 0;
+}
 _ACEOF
+if ac_fn_c_try_link "$LINENO"; then :
+
+                                       { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
+$as_echo "yes" >&6; }
+
+$as_echo "#define PCAP_SUPPORT_RDMASNIFF /**/" >>confdefs.h
+
+                                       RDMA_SRC=pcap-rdmasniff.c
+                                       LIBS="-libverbs $LIBS"
+
+else
+
+                                       { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+
+
+fi
+rm -f core conftest.err conftest.$ac_objext \
+    conftest$ac_exeext conftest.$ac_ext
 
 fi
 
-done
 
-       ;;
-*)
-       { $as_echo "$as_me:${as_lineno-$LINENO}: no hardware timestamp support implemented for $host_os" >&5
-$as_echo "$as_me: no hardware timestamp support implemented for $host_os" >&6;}
-       ;;
-esac
+
+fi
+
+
+
+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
@@ -8525,7 +11131,7 @@ ac_config_headers="$ac_config_headers config.h"
 
 ac_config_commands="$ac_config_commands default-1"
 
-ac_config_files="$ac_config_files Makefile pcap-filter.manmisc pcap-linktype.manmisc pcap-tstamp.manmisc pcap-savefile.manfile pcap.3pcap pcap_compile.3pcap pcap_datalink.3pcap pcap_dump_open.3pcap pcap_get_tstamp_precision.3pcap pcap_list_datalinks.3pcap pcap_list_tstamp_types.3pcap pcap_open_dead.3pcap pcap_open_offline.3pcap pcap_set_tstamp_precision.3pcap pcap_set_tstamp_type.3pcap"
+ac_config_files="$ac_config_files Makefile pcap-filter.manmisc pcap-linktype.manmisc pcap-tstamp.manmisc pcap-savefile.manfile pcap.3pcap pcap_compile.3pcap pcap_datalink.3pcap pcap_dump_open.3pcap pcap_get_tstamp_precision.3pcap pcap_list_datalinks.3pcap pcap_list_tstamp_types.3pcap pcap_open_dead.3pcap pcap_open_offline.3pcap pcap_set_immediate_mode.3pcap pcap_set_tstamp_precision.3pcap pcap_set_tstamp_type.3pcap rpcapd/Makefile rpcapd/rpcapd.manadmin rpcapd/rpcapd-config.manfile testprogs/Makefile"
 
 cat >confcache <<\_ACEOF
 # This file is a shell script that caches the results of configure
@@ -9033,7 +11639,7 @@ cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1
 # report actual input values of CONFIG_FILES etc. instead of their
 # values after options handling.
 ac_log="
-This file was extended by $as_me, which was
+This file was extended by pcap $as_me 1.9.1, which was
 generated by GNU Autoconf 2.69.  Invocation command line was
 
   CONFIG_FILES    = $CONFIG_FILES
@@ -9099,7 +11705,7 @@ _ACEOF
 cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
 ac_cs_config="`$as_echo "$ac_configure_args" | sed 's/^ //; s/[\\""\`\$]/\\\\&/g'`"
 ac_cs_version="\\
-config.status
+pcap config.status 1.9.1
 configured by $0, generated by GNU Autoconf 2.69,
   with options \\"\$ac_cs_config\\"
 
@@ -9242,8 +11848,13 @@ do
     "pcap_list_tstamp_types.3pcap") CONFIG_FILES="$CONFIG_FILES pcap_list_tstamp_types.3pcap" ;;
     "pcap_open_dead.3pcap") CONFIG_FILES="$CONFIG_FILES pcap_open_dead.3pcap" ;;
     "pcap_open_offline.3pcap") CONFIG_FILES="$CONFIG_FILES pcap_open_offline.3pcap" ;;
+    "pcap_set_immediate_mode.3pcap") CONFIG_FILES="$CONFIG_FILES pcap_set_immediate_mode.3pcap" ;;
     "pcap_set_tstamp_precision.3pcap") CONFIG_FILES="$CONFIG_FILES pcap_set_tstamp_precision.3pcap" ;;
     "pcap_set_tstamp_type.3pcap") CONFIG_FILES="$CONFIG_FILES pcap_set_tstamp_type.3pcap" ;;
+    "rpcapd/Makefile") CONFIG_FILES="$CONFIG_FILES rpcapd/Makefile" ;;
+    "rpcapd/rpcapd.manadmin") CONFIG_FILES="$CONFIG_FILES rpcapd/rpcapd.manadmin" ;;
+    "rpcapd/rpcapd-config.manfile") CONFIG_FILES="$CONFIG_FILES rpcapd/rpcapd-config.manfile" ;;
+    "testprogs/Makefile") CONFIG_FILES="$CONFIG_FILES testprogs/Makefile" ;;
 
   *) as_fn_error $? "invalid argument: \`$ac_config_target'" "$LINENO" 5;;
   esac
@@ -9801,7 +12412,7 @@ $as_echo "$as_me: executing $ac_file commands" >&6;}
   case $ac_file$ac_mode in
     "default-1":C) if test -f .devel; then
        echo timestamp > stamp-h
-       cat Makefile-devel-adds >> Makefile
+       cat $srcdir/Makefile-devel-adds >> Makefile
        make depend
 fi ;;
 
diff --git a/configure.ac b/configure.ac
new file mode 100644 (file)
index 0000000..eba2723
--- /dev/null
@@ -0,0 +1,2465 @@
+dnl
+dnl Copyright (c) 1994, 1995, 1996, 1997
+dnl    The Regents of the University of California.  All rights reserved.
+dnl
+dnl Process this file with autoconf to produce a configure script.
+dnl
+
+#
+# See
+#
+#      http://ftp.gnu.org/gnu/config/README
+#
+# for the URLs to use to fetch new versions of config.guess and
+# config.sub.
+#
+
+AC_PREREQ(2.64)
+
+AC_INIT(pcap, m4_esyscmd_s([cat VERSION]))
+AC_CONFIG_SRCDIR(pcap.c)
+AC_SUBST(PACKAGE_NAME)
+
+AC_CANONICAL_SYSTEM
+
+AC_LBL_C_INIT_BEFORE_CC(V_CCOPT, V_INCLS)
+#
+# Try to enable as many C99 features as we can.
+# At minimum, we want C++/C99-style // comments.
+#
+AC_PROG_CC_C99
+if test "$ac_cv_prog_cc_c99" = "no"; then
+       AC_MSG_WARN([The C compiler does not support C99; there may be compiler errors])
+fi
+AC_LBL_C_INIT(V_CCOPT, V_INCLS)
+AC_LBL_SHLIBS_INIT
+AC_LBL_C_INLINE
+
+#
+# Try to arrange for large file support.
+#
+AC_SYS_LARGEFILE
+AC_FUNC_FSEEKO
+
+dnl
+dnl Even if <net/bpf.h> were, on all OSes that support BPF, fixed to
+dnl include <sys/ioccom.h>, and we were to drop support for older
+dnl releases without that fix, so that pcap-bpf.c doesn't need to
+dnl include <sys/ioccom.h>, the test program in "AC_LBL_FIXINCLUDES"
+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)
+AC_CHECK_HEADERS(netpacket/packet.h)
+AC_CHECK_HEADERS(net/pfvar.h, , , [#include <sys/types.h>
+#include <sys/socket.h>
+#include <net/if.h>])
+if test "$ac_cv_header_net_pfvar_h" = yes; then
+       #
+       # Check for various PF actions.
+       #
+       AC_MSG_CHECKING(whether net/pfvar.h defines PF_NAT through PF_NORDR)
+       AC_TRY_COMPILE(
+           [#include <sys/types.h>
+           #include <sys/socket.h>
+           #include <net/if.h>
+           #include <net/pfvar.h>],
+           [return PF_NAT+PF_NONAT+PF_BINAT+PF_NOBINAT+PF_RDR+PF_NORDR;],
+           [
+               AC_MSG_RESULT(yes)
+               AC_DEFINE(HAVE_PF_NAT_THROUGH_PF_NORDR, 1,
+                   [define if net/pfvar.h defines PF_NAT through PF_NORDR])
+           ],
+           AC_MSG_RESULT(no))
+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)
+AC_CHECK_FUNC(strerror_r,
+    [
+       #
+       # We have strerror_r; if we define _GNU_SOURCE, is it a
+       # POSIX-compliant strerror_r() or a GNU strerror_r()?
+       #
+       AC_MSG_CHECKING(whether strerror_r is GNU-style)
+       AC_COMPILE_IFELSE(
+           [
+               AC_LANG_SOURCE(
+#define _GNU_SOURCE
+#include <string.h>
+
+/* Define it GNU-style; that will cause an error if it's not GNU-style */
+extern char *strerror_r(int, char *, size_t);
+
+int
+main(void)
+{
+       return 0;
+}
+)
+           ],
+           [
+               # GNU-style
+               AC_MSG_RESULT(yes)
+               AC_DEFINE(HAVE_GNU_STRERROR_R,,
+                   [Define to 1 if you have a GNU-style `strerror_r' function.])
+           ],
+           [
+               AC_MSG_RESULT(no)
+               AC_DEFINE(HAVE_POSIX_STRERROR_R,,
+                   [Define to 1 if you have a POSIX-style `strerror_r' function.])
+           ])
+    ],
+    [
+       #
+       # We don't have strerror_r; do we have strerror_s?
+       #
+       AC_CHECK_FUNCS(strerror_s)
+    ])
+
+#
+# Thanks, IBM, for not providing vsyslog() in AIX!
+#
+AC_CHECK_FUNCS(vsyslog)
+
+#
+# Either:
+#
+#      we have snprintf() and vsnprintf(), and have asprintf() and
+#      vasprintf();
+#
+#      we have snprintf() and vsnprintf(), but don't have asprintf()
+#      or vasprintf();
+#
+#      we have neither snprintf() nor vsnprintf(), and don't have
+#      asprintf() or vasprintf(), either.
+#
+# We assume that if we have asprintf() we have vasprintf(), as well
+# as snprintf() and vsnprintf(), and that if we have snprintf() we
+# have vsnprintf().
+#
+# For the first case, we don't need any replacement routines.
+# For the second case, we need replacement asprintf()/vasprintf()
+# routines.
+# For the third case, we need replacement snprintf()/vsnprintf() and
+# asprintf()/vasprintf() routines.
+#
+needsnprintf=no
+AC_CHECK_FUNCS(vsnprintf snprintf,,
+       [needsnprintf=yes])
+needasprintf=no
+AC_CHECK_FUNCS(vasprintf asprintf,,
+       [needasprintf=yes])
+if test $needsnprintf = yes; then
+       #
+       # We assume we have none of them; missing/snprintf.c supplies
+       # all of them.
+       #
+       AC_LIBOBJ([snprintf])
+elif test $needasprintf = yes; then
+       #
+       # We assume we have snprintf()/vsnprintf() but lack
+       # asprintf()/vasprintf(); missing/asprintf.c supplies
+       # the latter (using vsnprintf()).
+       #
+       AC_LIBOBJ([asprintf])
+fi
+
+needstrlcat=no
+AC_CHECK_FUNCS(strlcat,,
+       [needstrlcat=yes])
+if test $needstrlcat = yes; then
+       AC_LIBOBJ([strlcat])
+fi
+
+needstrlcpy=no
+AC_CHECK_FUNCS(strlcpy,,
+       [needstrlcpy=yes])
+if test $needstrlcpy = yes; then
+       AC_LIBOBJ([strlcpy])
+fi
+
+needstrtok_r=no
+AC_CHECK_FUNCS(strtok_r,,
+       [needstrtok_r=yes])
+if test $needstrtok_r = yes; then
+       AC_LIBOBJ([strtok_r])
+fi
+
+#
+# Do we have ffs(), and is it declared in <strings.h>?
+#
+AC_CHECK_FUNCS(ffs)
+if test "$ac_cv_func_ffs" = yes; then
+       #
+       # We have ffs(); is it declared in <strings.h>?
+       #
+       # This test fails if we don't have <strings.h> or if we do
+       # but it doesn't declare ffs().
+       #
+       AC_CHECK_DECL(ffs,
+           [
+               AC_DEFINE(STRINGS_H_DECLARES_FFS,,
+                   [Define to 1 if strings.h declares `ffs'])
+           ],,
+           [
+#include <strings.h>
+           ])
+fi
+
+#
+# Do this before checking for ether_hostton(), as it's a
+# "getaddrinfo()-ish function".
+#
+AC_LBL_LIBRARY_NET
+
+#
+# Check for reentrant versions of getnetbyname_r(), as provided by
+# Linux (glibc), Solaris/IRIX, and AIX (with three different APIs!).
+# If we don't find one, we just use getnetbyname(), which uses
+# thread-specific data on many platforms, but doesn't use it on
+# NetBSD or OpenBSD, and may not use it on older versions of other
+# platforms.
+#
+# Only do the check if we have a declaration of getnetbyname_r();
+# without it, we can't check which API it has.  (We assume that
+# if there's a declaration, it has a prototype, so that the API
+# can be checked.)
+#
+AC_CHECK_DECL(getnetbyname_r,
+    [
+       AC_MSG_CHECKING([for the Linux getnetbyname_r()])
+       AC_TRY_LINK(
+           [#include <netdb.h>],
+           [
+               struct netent netent_buf;
+               char buf[1024];
+               struct netent *resultp;
+               int h_errnoval;
+
+               return getnetbyname_r((const char *)0, &netent_buf, buf, sizeof buf, &resultp, &h_errnoval);
+           ],
+           [
+               AC_MSG_RESULT(yes)
+               AC_DEFINE(HAVE_LINUX_GETNETBYNAME_R, 1,
+                   [define if we have the Linux getnetbyname_r()])
+           ],
+           [
+               AC_MSG_RESULT(no)
+
+               AC_MSG_CHECKING([for Solaris/IRIX getnetbyname_r()])
+               AC_TRY_LINK(
+                   [#include <netdb.h>],
+                   [
+                       struct netent netent_buf;
+                       char buf[1024];
+
+                       return getnetbyname_r((const char *)0, &netent_buf, buf, (int)sizeof buf) != NULL;
+                   ],
+                   [
+                       AC_MSG_RESULT(yes)
+                       AC_DEFINE(HAVE_SOLARIS_IRIX_GETNETBYNAME_R, 1,
+                           [define if we have the Solaris/IRIX getnetbyname_r()])
+                   ],
+                   [
+                       AC_MSG_RESULT(no)
+
+                       AC_MSG_CHECKING([for AIX getnetbyname_r()])
+                       AC_TRY_LINK(
+                           [#include <netdb.h>],
+                           [
+                               struct netent netent_buf;
+                               struct netent_data net_data;
+
+                               return getnetbyname_r((const char *)0, &netent_buf, &net_data);
+                           ],
+                           [
+                               AC_MSG_RESULT(yes)
+                               AC_DEFINE(HAVE_AIX_GETNETBYNAME_R, 1,
+                                   [define if we have the AIX getnetbyname_r()])
+                           ],
+                           [
+                               AC_MSG_RESULT(no)
+                           ])
+                   ])
+           ])
+    ],,[#include <netdb.h>])
+
+#
+# Check for reentrant versions of getprotobyname_r(), as provided by
+# Linux (glibc), Solaris/IRIX, and AIX (with three different APIs!).
+# If we don't find one, we just use getprotobyname(), which uses
+# thread-specific data on many platforms, but doesn't use it on
+# NetBSD or OpenBSD, and may not use it on older versions of other
+# platforms.
+#
+# Only do the check if we have a declaration of getprotobyname_r();
+# without it, we can't check which API it has.  (We assume that
+# if there's a declaration, it has a prototype, so that the API
+# can be checked.)
+#
+AC_CHECK_DECL(getprotobyname_r,
+    [
+       AC_MSG_CHECKING([for the Linux getprotobyname_r()])
+       AC_TRY_LINK(
+           [#include <netdb.h>],
+           [
+               struct protoent protoent_buf;
+               char buf[1024];
+               struct protoent *resultp;
+
+               return getprotobyname_r((const char *)0, &protoent_buf, buf, sizeof buf, &resultp);
+           ],
+           [
+               AC_MSG_RESULT(yes)
+               AC_DEFINE(HAVE_LINUX_GETPROTOBYNAME_R, 1,
+                   [define if we have the Linux getprotobyname_r()])
+           ],
+           [
+               AC_MSG_RESULT(no)
+
+               AC_MSG_CHECKING([for Solaris/IRIX getprotobyname_r()])
+               AC_TRY_LINK(
+                   [#include <netdb.h>],
+                   [
+                       struct protoent protoent_buf;
+                       char buf[1024];
+
+                       return getprotobyname_r((const char *)0, &protoent_buf, buf, (int)sizeof buf) != NULL;
+                   ],
+                   [
+                       AC_MSG_RESULT(yes)
+                       AC_DEFINE(HAVE_SOLARIS_IRIX_GETPROTOBYNAME_R, 1,
+                           [define if we have the Solaris/IRIX getprotobyname_r()])
+                   ],
+                   [
+                       AC_MSG_RESULT(no)
+
+                       AC_MSG_CHECKING([for AIX getprotobyname_r()])
+                       AC_TRY_LINK(
+                           [#include <netdb.h>],
+                           [
+                               struct protoent protoent_buf;
+                               struct protoent_data proto_data;
+
+                               return getprotobyname_r((const char *)0, &protoent_buf, &proto_data);
+                           ],
+                           [
+                               AC_MSG_RESULT(yes)
+                               AC_DEFINE(HAVE_AIX_GETPROTOBYNAME_R, 1,
+                                   [define if we have the AIX getprotobyname_r()])
+                           ],
+                           [
+                               AC_MSG_RESULT(no)
+                           ])
+                   ])
+           ])
+    ],,[#include <netdb.h>])
+
+#
+# You are in a twisty little maze of UN*Xes, all different.
+# Some might not have ether_hostton().
+# Some might have it and declare it in <net/ethernet.h>.
+# Some might have it and declare it in <netinet/ether.h>
+# Some might have it and declare it in <sys/ethernet.h>.
+# Some might have it and declare it in <arpa/inet.h>.
+# Some might have it and declare it in <netinet/if_ether.h>.
+# Some might have it and not declare it in any header file.
+#
+# Before you is a C compiler.
+#
+AC_CHECK_FUNCS(ether_hostton)
+if test "$ac_cv_func_ether_hostton" = yes; then
+       #
+       # OK, we have ether_hostton().  Is it declared in <net/ethernet.h>?
+       #
+       # This test fails if we don't have <net/ethernet.h> or if we do
+       # but it doesn't declare ether_hostton().
+       #
+       AC_CHECK_DECL(ether_hostton,
+           [
+               AC_DEFINE(NET_ETHERNET_H_DECLARES_ETHER_HOSTTON,,
+                   [Define to 1 if net/ethernet.h declares `ether_hostton'])
+           ],,
+           [
+#include <net/ethernet.h>
+           ])
+       #
+       # Did that succeed?
+       #
+       if test "$ac_cv_have_decl_ether_hostton" != yes; then
+               #
+               # No, how about <netinet/ether.h>, as on Linux?
+               #
+               # This test fails if we don't have <netinet/ether.h>
+               # or if we do but it doesn't declare ether_hostton().
+               #
+               # Unset ac_cv_have_decl_ether_hostton so we don't
+               # treat the previous failure as a cached value and
+               # suppress the next test.
+               #
+               unset ac_cv_have_decl_ether_hostton
+               AC_CHECK_DECL(ether_hostton,
+                   [
+                       AC_DEFINE(NETINET_ETHER_H_DECLARES_ETHER_HOSTTON,,
+                           [Define to 1 if netinet/ether.h declares `ether_hostton'])
+                   ],,
+                   [
+#include <netinet/ether.h>
+                   ])
+       fi
+       #
+       # Did that succeed?
+       #
+       if test "$ac_cv_have_decl_ether_hostton" != yes; then
+               #
+               # No, how about <sys/ethernet.h>, as on Solaris 10
+               # and later?
+               #
+               # This test fails if we don't have <sys/ethernet.h>
+               # or if we do but it doesn't declare ether_hostton().
+               #
+               # Unset ac_cv_have_decl_ether_hostton so we don't
+               # treat the previous failure as a cached value and
+               # suppress the next test.
+               #
+               unset ac_cv_have_decl_ether_hostton
+               AC_CHECK_DECL(ether_hostton,
+                   [
+                       AC_DEFINE(SYS_ETHERNET_H_DECLARES_ETHER_HOSTTON,,
+                           [Define to 1 if sys/ethernet.h declares `ether_hostton'])
+                   ],,
+                   [
+#include <sys/ethernet.h>
+                   ])
+       fi
+       #
+       # Did that succeed?
+       #
+       if test "$ac_cv_have_decl_ether_hostton" != yes; then
+               #
+               # No, how about <arpa/inet.h>, as in AIX?
+               #
+               # This test fails if we don't have <arpa/inet.h>
+               # (if we have ether_hostton(), we should have
+               # networking, and if we have networking, we should
+               # have <arapa/inet.h>) or if we do but it doesn't
+               # declare ether_hostton().
+               #
+               # Unset ac_cv_have_decl_ether_hostton so we don't
+               # treat the previous failure as a cached value and
+               # suppress the next test.
+               #
+               unset ac_cv_have_decl_ether_hostton
+               AC_CHECK_DECL(ether_hostton,
+                   [
+                       AC_DEFINE(ARPA_INET_H_DECLARES_ETHER_HOSTTON,,
+                           [Define to 1 if arpa/inet.h declares `ether_hostton'])
+                   ],,
+                   [
+#include <arpa/inet.h>
+                   ])
+       fi
+       #
+       # Did that succeed?
+       #
+       if test "$ac_cv_have_decl_ether_hostton" != yes; then
+               #
+               # No, how about <netinet/if_ether.h>?
+               # On some platforms, it requires <net/if.h> and
+               # <netinet/in.h>, and we always include it with
+               # both of them, so test it with both of them.
+               #
+               # This test fails if we don't have <netinet/if_ether.h>
+               # and the headers we include before it, or if we do but
+               # <netinet/if_ether.h> doesn't declare ether_hostton().
+               #
+               # Unset ac_cv_have_decl_ether_hostton so we don't
+               # treat the previous failure as a cached value and
+               # suppress the next test.
+               #
+               unset ac_cv_have_decl_ether_hostton
+               AC_CHECK_DECL(ether_hostton,
+                   [
+                       AC_DEFINE(NETINET_IF_ETHER_H_DECLARES_ETHER_HOSTTON,,
+                           [Define to 1 if netinet/if_ether.h declares `ether_hostton'])
+                   ],,
+                   [
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <net/if.h>
+#include <netinet/in.h>
+#include <netinet/if_ether.h>
+                   ])
+       fi
+       #
+       # After all that, is ether_hostton() declared?
+       #
+       if test "$ac_cv_have_decl_ether_hostton" = yes; then
+               #
+               # Yes.
+               #
+               AC_DEFINE(HAVE_DECL_ETHER_HOSTTON, 1,
+                   [Define to 1 if you have the declaration of `ether_hostton'])
+        else
+               #
+               # No, we'll have to declare it ourselves.
+               # Do we have "struct ether_addr" if we include
+               # <netinet/if_ether.h>?
+               #
+               AC_CHECK_TYPES(struct ether_addr,,,
+                   [
+                       #include <sys/types.h>
+                       #include <sys/socket.h>
+                       #include <net/if.h>
+                       #include <netinet/in.h>
+                       #include <netinet/if_ether.h>
+                   ])
+       fi
+fi
+
+#
+# For various things that might use pthreads.
+#
+AC_CHECK_HEADER(pthread.h,
+    [
+       #
+       # OK, we have pthread.h.  Do we have pthread_create in the
+       # system libraries?
+       #
+       AC_CHECK_FUNC(pthread_create,
+           [
+               #
+               # Yes.
+               #
+               ac_lbl_have_pthreads="found"
+           ],
+           [
+               #
+               # No - do we have it in -lpthreads?
+               #
+               AC_CHECK_LIB(pthreads, pthread_create,
+                   [
+                       #
+                       # Yes - add -lpthreads.
+                       #
+                       ac_lbl_have_pthreads="found"
+                       PTHREAD_LIBS="$PTHREAD_LIBS -lpthreads"
+                   ],
+                   [
+                       #
+                       # No - do we have it in -lpthread?
+                       #
+                       AC_CHECK_LIB(pthread, pthread_create,
+                           [
+                               #
+                               # Yes - add -lpthread.
+                               #
+                                ac_lbl_have_pthreads="found"
+                               PTHREAD_LIBS="$PTHREAD_LIBS -lpthread"
+                           ],
+                           [
+                               #
+                               # No.
+                               #
+                               ac_lbl_have_pthreads="not found"
+                           ])
+                   ])
+           ])
+    ],
+    [
+       #
+       # We didn't find pthread.h.
+       #
+       ac_lbl_have_pthreads="not found"
+    ]
+)
+
+dnl to pacify those who hate protochain insn
+AC_MSG_CHECKING(if --disable-protochain option is specified)
+AC_ARG_ENABLE(protochain,
+AC_HELP_STRING([--disable-protochain],[disable \"protochain\" insn]))
+case "x$enable_protochain" in
+xyes)  enable_protochain=enabled       ;;
+xno)   enable_protochain=disabled      ;;
+x)     enable_protochain=enabled       ;;
+esac
+
+if test "$enable_protochain" = "disabled"; then
+       AC_DEFINE(NO_PROTOCHAIN,1,[do not use protochain])
+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_SRC=
+
+#
+# SITA support is mutually exclusive with native capture support;
+# "--with-sita" selects SITA support.
+#
+AC_ARG_WITH(sita,
+AC_HELP_STRING([--with-sita],[include SITA support]),
+[
+       if test ! "x$withval" = "xno" ; then
+               AC_DEFINE(SITA,1,[include ACN support])
+               AC_MSG_NOTICE(Enabling SITA ACN support)
+               V_PCAP=sita
+       fi
+],
+[
+AC_ARG_WITH(pcap,
+AC_HELP_STRING([--with-pcap=TYPE],[use packet capture TYPE]))
+if test ! -z "$with_pcap" ; then
+       V_PCAP="$withval"
+else
+       #
+       # Check for a bunch of headers for various packet
+       # capture mechanisms.
+       #
+       AC_CHECK_HEADERS(net/bpf.h)
+       if test "$ac_cv_header_net_bpf_h" = yes; then
+               #
+               # Does it define BIOCSETIF?
+               # I.e., is it a header for an LBL/BSD-style capture
+               # mechanism, or is it just a header for a BPF filter
+               # engine?  Some versions of Arch Linux, for example,
+               # have a net/bpf.h that doesn't define BIOCSETIF;
+               # as it's a Linux, it should use packet sockets,
+               # instead.
+               #
+               # We need:
+               #
+               #  sys/types.h, because FreeBSD 10's net/bpf.h
+               #  requires that various BSD-style integer types
+               #  be defined;
+               #
+               #  sys/time.h, because AIX 5.2 and 5.3's net/bpf.h
+               #  doesn't include it but does use struct timeval
+               #  in ioctl definitions;
+               #
+               #  sys/ioctl.h and, if we have it, sys/ioccom.h,
+               #  because net/bpf.h defines ioctls;
+               #
+               #  net/if.h, because it defines some structures
+               #  used in ioctls defined by net/bpf.h;
+               #
+               #  sys/socket.h, because OpenBSD 5.9's net/bpf.h
+               #  defines some structure fields as being
+               #  struct sockaddrs;
+               #
+               # and net/bpf.h doesn't necessarily include all
+               # of those headers itself.
+               #
+               AC_MSG_CHECKING(if net/bpf.h defines BIOCSETIF)
+               AC_CACHE_VAL(ac_cv_lbl_bpf_h_defines_biocsetif,
+                       AC_TRY_COMPILE(
+[
+#include <sys/types.h>
+#include <sys/time.h>
+#include <sys/ioctl.h>
+#include <sys/socket.h>
+#ifdef HAVE_SYS_IOCCOM_H
+#include <sys/ioccom.h>
+#endif
+#include <net/bpf.h>
+#include <net/if.h>
+],
+                       [u_int i = BIOCSETIF;],
+                       ac_cv_lbl_bpf_h_defines_biocsetif=yes,
+                       ac_cv_lbl_bpf_h_defines_biocsetif=no))
+               AC_MSG_RESULT($ac_cv_lbl_bpf_h_defines_biocsetif)
+       fi
+       AC_CHECK_HEADERS(net/pfilt.h net/enet.h)
+       AC_CHECK_HEADERS(net/nit.h sys/net/nit.h)
+       AC_CHECK_HEADERS(linux/socket.h net/raw.h sys/dlpi.h)
+
+       if test "$ac_cv_lbl_bpf_h_defines_biocsetif" = yes; then
+               #
+               # BPF.
+               # Check this before DLPI, so that we pick BPF on
+               # Solaris 11 and later.
+               #
+               V_PCAP=bpf
+
+               #
+               # We have BPF, so build valgrindtest with "make test"
+               # on macOS and FreeBSD (add your OS once there's a
+               # valgrind for it).
+               #
+               case "$host_os" in
+
+               freebsd*|darwin*|linux*)
+                       VALGRINDTEST_SRC=valgrindtest.c
+                       ;;
+               esac
+       elif test "$ac_cv_header_linux_socket_h" = yes; then
+               #
+               # No prizes for guessing this one.
+               #
+               V_PCAP=linux
+
+               #
+               # XXX - this won't work with older kernels that have
+               # SOCK_PACKET sockets but not PF_PACKET sockets.
+               #
+               VALGRINDTEST_SRC=valgrindtest.c
+       elif test "$ac_cv_header_net_pfilt_h" = yes; then
+               #
+               # DEC OSF/1, Digital UNIX, Tru64 UNIX
+               #
+               V_PCAP=pf
+       elif test "$ac_cv_header_net_enet_h" = yes; then
+               #
+               # Stanford Enetfilter.
+               #
+               V_PCAP=enet
+       elif test "$ac_cv_header_net_nit_h" = yes; then
+               #
+               # SunOS 4.x STREAMS NIT.
+               #
+               V_PCAP=snit
+       elif test "$ac_cv_header_sys_net_nit_h" = yes; then
+               #
+               # Pre-SunOS 4.x non-STREAMS NIT.
+               #
+               V_PCAP=nit
+       elif test "$ac_cv_header_net_raw_h" = yes; then
+               #
+               # IRIX snoop.
+               #
+               V_PCAP=snoop
+       elif test "$ac_cv_header_sys_dlpi_h" = yes; then
+               #
+               # DLPI on pre-Solaris 11 SunOS 5, HP-UX, possibly others.
+               #
+               V_PCAP=dlpi
+       else
+               #
+               # Nothing we support.
+               #
+               V_PCAP=null
+               AC_MSG_WARN(cannot determine packet capture interface)
+               AC_MSG_WARN((see the INSTALL doc for more info))
+       fi
+fi
+AC_MSG_CHECKING(packet capture type)
+AC_MSG_RESULT($V_PCAP)
+AC_SUBST(VALGRINDTEST_SRC)
+
+#
+# Do capture-mechanism-dependent tests.
+#
+case "$V_PCAP" in
+dlpi)
+       #
+       # Needed for common functions used by pcap-[dlpi,libdlpi].c
+       #
+       SSRC="dlpisubs.c"
+
+       #
+       # Checks for some header files.
+       #
+       AC_CHECK_HEADERS(sys/bufmod.h sys/dlpi_ext.h)
+
+       #
+       # 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.
+       # 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].
+       # Also, due to the bug above applications that link to libpcap with
+       # libdlpi will have to add "-L/lib" option to "configure".
+       #
+       saved_ldflags=$LDFLAGS
+       LDFLAGS="$LIBS -L/lib"
+       AC_CHECK_LIB(dlpi, dlpi_walk,
+               [
+                       LIBS="-ldlpi $LIBS"
+                       V_PCAP=libdlpi
+                       AC_DEFINE(HAVE_LIBDLPI,1,[if libdlpi exists])
+               ],
+               V_PCAP=dlpi)
+       LDFLAGS=$saved_ldflags
+
+       #
+       # Checks whether <sys/dlpi.h> is usable, to catch weird SCO
+       # versions of DLPI.
+       #
+       AC_MSG_CHECKING(whether <sys/dlpi.h> is usable)
+       AC_CACHE_VAL(ac_cv_sys_dlpi_usable,
+               AC_TRY_COMPILE(
+                   [
+                       #include <sys/types.h>
+                       #include <sys/time.h>
+                       #include <sys/dlpi.h>
+                   ],
+                   [int i = DL_PROMISC_PHYS;],
+                   ac_cv_sys_dlpi_usable=yes,
+                   ac_cv_sys_dlpi_usable=no))
+       AC_MSG_RESULT($ac_cv_sys_dlpi_usable)
+       if test $ac_cv_sys_dlpi_usable = no ; then
+               AC_MSG_ERROR(<sys/dlpi.h> is not usable on this system; it probably has a non-standard DLPI)
+       fi
+
+       #
+       # Check to see if Solaris has the dl_passive_req_t struct defined
+       # in <sys/dlpi.h>.
+       # This check is for DLPI support for passive modes.
+       # See dlpi(7P) for more details.
+       #
+       AC_CHECK_TYPES(dl_passive_req_t,,,
+           [
+               #include <sys/types.h>
+               #include <sys/dlpi.h>
+           ])
+       ;;
+
+linux)
+       #
+       # Do we have the wireless extensions?
+       #
+       AC_CHECK_HEADERS(linux/wireless.h, [], [],
+       [
+#include <sys/socket.h>
+#include <linux/if.h>
+#include <linux/types.h>
+       ])
+
+       #
+       # Do we have libnl?
+       #
+       AC_ARG_WITH(libnl,
+       AC_HELP_STRING([--without-libnl],[disable libnl support @<:@default=yes, on Linux, if present@:>@]),
+               with_libnl=$withval,with_libnl=if_available)
+
+       if test x$with_libnl != xno ; then
+               have_any_nl="no"
+
+                incdir=-I/usr/include/libnl3
+                libnldir=
+                case "$with_libnl" in
+
+                yes|if_available)
+                  ;;
+
+                *)
+                  if test -d $withval; then
+                    libnldir=-L${withval}/lib/.libs
+                    incdir=-I${withval}/include
+                  fi
+                  ;;
+                esac
+
+               #
+               # Try libnl 3.x first.
+               #
+               AC_CHECK_LIB(nl-3, nl_socket_alloc,
+               [
+                       #
+                       # Yes, we have libnl 3.x.
+                       #
+                       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 ${incdir}"
+                       have_any_nl="yes"
+               ],[], ${incdir} ${libnldir} -lnl-genl-3 -lnl-3 )
+
+               if test x$have_any_nl = xno ; then
+                       #
+                       # Try libnl 2.x
+                       #
+                       AC_CHECK_LIB(nl, nl_socket_alloc,
+                       [
+                               #
+                               # Yes, we have libnl 2.x.
+                               #
+                               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])
+                               AC_DEFINE(HAVE_LIBNL_SOCKETS,1,[libnl has new-style socket api])
+                               have_any_nl="yes"
+                       ])
+               fi
+
+               if test x$have_any_nl = xno ; then
+                       #
+                       # No, we don't; do we have libnl 1.x?
+                       #
+                       AC_CHECK_LIB(nl, nl_handle_alloc,
+                       [
+                               #
+                               # Yes.
+                               #
+                               LIBS="${libnldir} -lnl $LIBS"
+                               AC_DEFINE(HAVE_LIBNL,1,[if libnl exists])
+                               have_any_nl="yes"
+                       ])
+               fi
+
+               if test x$have_any_nl = xno ; then
+                       #
+                       # No, we don't have libnl at all.
+                       #
+                       if test x$with_libnl = xyes ; then
+                               AC_MSG_ERROR([libnl support requested but libnl not found])
+                       fi
+               fi
+       fi
+
+       AC_CHECK_HEADERS(linux/ethtool.h,,,
+           [
+AC_INCLUDES_DEFAULT
+#include <linux/types.h>
+           ])
+
+       #
+       # Check to see if struct tpacket_stats is defined in
+       # <linux/if_packet.h>.  If so, then pcap-linux.c can use this
+       # to report proper statistics.
+       #
+       # -Scott Barron
+       #
+       AC_CHECK_TYPES(struct tpacket_stats,,,
+           [
+               #include <linux/if_packet.h>
+           ])
+
+       #
+       # Check to see if the tpacket_auxdata struct has a tp_vlan_tci member.
+       #
+       # NOTE: any failure means we conclude that it doesn't have that
+       # member, so if we don't have tpacket_auxdata, we conclude it
+       # doesn't have that member (which is OK, as either we won't be
+       # using code that would use that member, or we wouldn't compile
+       # in any case).
+       AC_CHECK_MEMBERS([struct tpacket_auxdata.tp_vlan_tci],,,
+           [
+               #include <sys/types.h>
+               #include <linux/if_packet.h>
+           ])
+       ;;
+
+bpf)
+       #
+       # Check whether we have the *BSD-style ioctls.
+       #
+       AC_CHECK_HEADERS(net/if_media.h)
+
+       #
+       # Check whether we have struct BPF_TIMEVAL.
+       #
+       AC_CHECK_TYPES(struct BPF_TIMEVAL,,,
+           [
+               #include <sys/types.h>
+               #include <sys/ioctl.h>
+               #ifdef HAVE_SYS_IOCCOM_H
+               #include <sys/ioccom.h>
+               #endif
+               #include <net/bpf.h>
+           ])
+       ;;
+
+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)
+       ;;
+
+*)
+       AC_MSG_ERROR($V_PCAP is not a valid pcap type)
+       ;;
+esac
+
+dnl
+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
+then
+       AC_CHECK_FUNC(getifaddrs,[
+               #
+               # We have "getifaddrs()"; make sure we have <ifaddrs.h>
+               # as well, just in case some platform is really weird.
+               #
+               AC_CHECK_HEADER(ifaddrs.h,[
+                   #
+                   # We have the header, so we use "getifaddrs()" to
+                   # get the list of interfaces.
+                   #
+                   V_FINDALLDEVS=fad-getad.c
+               ],[
+                   #
+                   # We don't have the header - give up.
+                   # XXX - we could also fall back on some other
+                   # mechanism, but, for now, this'll catch this
+                   # problem so that we can at least try to figure
+                   # out something to do on systems with "getifaddrs()"
+                   # but without "ifaddrs.h", if there is something
+                   # we can do on those systems.
+                   #
+                   AC_MSG_ERROR([Your system has getifaddrs() but doesn't have a usable <ifaddrs.h>.])
+               ])
+       ],[
+               #
+               # Well, we don't have "getifaddrs()", at least not with the
+               # libraries with which we've decided we need to link
+               # libpcap with, so we have to use some other mechanism.
+               #
+               # Note that this may happen on Solaris, which has
+               # getifaddrs(), but in -lsocket, not in -lxnet, so we
+               # won't find it if we link with -lxnet, which we want
+               # to do for other reasons.
+               #
+               # For now, we use either the SIOCGIFCONF ioctl or the
+               # SIOCGLIFCONF ioctl, preferring the latter if we have
+               # it; the latter is a Solarisism that first appeared
+               # in Solaris 8.  (Solaris's getifaddrs() appears to
+               # be built atop SIOCGLIFCONF; using it directly
+               # avoids a not-all-that-useful middleman.)
+               #
+               AC_MSG_CHECKING(whether we have SIOCGLIFCONF)
+               AC_CACHE_VAL(ac_cv_lbl_have_siocglifconf,
+                   AC_TRY_COMPILE(
+                       [#include <sys/param.h>
+                       #include <sys/file.h>
+                       #include <sys/ioctl.h>
+                       #include <sys/socket.h>
+                       #include <sys/sockio.h>],
+                       [ioctl(0, SIOCGLIFCONF, (char *)0);],
+                       ac_cv_lbl_have_siocglifconf=yes,
+                       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=fad-glifc.c
+               else
+                       V_FINDALLDEVS=fad-gifc.c
+               fi
+       ])
+fi
+])
+
+dnl check for hardware timestamp support
+case "$host_os" in
+linux*)
+       AC_CHECK_HEADERS([linux/net_tstamp.h])
+       ;;
+*)
+       AC_MSG_NOTICE(no hardware timestamp support implemented for $host_os)
+       ;;
+esac
+
+AC_ARG_ENABLE([packet-ring],
+[AC_HELP_STRING([--enable-packet-ring],[enable packet ring support on Linux @<:@default=yes@:>@])],
+,enable_packet_ring=yes)
+
+if test "x$enable_packet_ring" != "xno" ; then
+       AC_DEFINE(PCAP_SUPPORT_PACKET_RING, 1, [use packet ring capture support on Linux if available])
+       AC_SUBST(PCAP_SUPPORT_PACKET_RING)
+fi
+
+#
+# Check for socklen_t.
+#
+AC_CHECK_TYPES(socklen_t,,,
+    [
+       #include <sys/types.h>
+       #include <sys/socket.h>
+    ])
+
+AC_ARG_ENABLE(ipv6,
+AC_HELP_STRING([--enable-ipv6],[build IPv6-capable version @<:@default=yes@:>@]),
+    [],
+    [enable_ipv6=yes])
+if test "$enable_ipv6" != "no"; then
+       #
+       # We've already made sure we have getaddrinfo above in
+       # AC_LBL_LIBRARY_NET.
+       #
+       AC_DEFINE(INET6,1,[IPv6])
+fi
+
+# Check for Endace DAG card support.
+AC_ARG_WITH([dag],
+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
+               # User doesn't want DAG support.
+               want_dag=no
+       elif test "$withval" = yes
+       then
+               # User wants DAG support but hasn't specified a directory.
+               want_dag=yes
+       else
+               # User wants DAG support and has specified a directory, so use the provided value.
+               want_dag=yes
+               dag_root=$withval
+       fi
+],[
+       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=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
+       dag_include_dir=$withval
+],[])
+
+AC_ARG_WITH([dag-libraries],
+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
+],[])
+
+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
+       fi
+
+       if test -z "$dag_include_dir"; then
+               dag_include_dir="$dag_root/include"
+       fi
+
+       if test -z "$dag_lib_dir"; then
+               dag_lib_dir="$dag_root/lib"
+       fi
+
+       V_INCLS="$V_INCLS -I$dag_include_dir"
+
+       AC_CHECK_HEADERS([dagapi.h])
+
+       if test "$ac_cv_header_dagapi_h" = yes; then
+
+               if test $V_PCAP != dag ; then
+                        SSRC="$SSRC pcap-dag.c"
+               fi
+
+               # Check for various DAG API functions.
+               # 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],
+                   [],
+                   [AC_MSG_ERROR(DAG library lacks streams support)])
+               AC_CHECK_LIB([dag], [dag_attach_stream64], [dag_large_streams="1"], [dag_large_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
+
+               #
+               # We assume that if we have libdag we have libdagconf,
+               # as they're installed at the same time from the same
+               # package.
+               #
+               LIBS="$LIBS -ldag -ldagconf"
+               LDFLAGS="$LDFLAGS -L$dag_lib_dir"
+
+               if test "$dag_large_streams" = 1; then
+                       AC_DEFINE(HAVE_DAG_LARGE_STREAMS_API, 1, [define if you have large streams capable DAG API])
+                       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()])
+                               if test "$ac_lbl_have_pthreads" != "found"; then
+                                       AC_MSG_ERROR([DAG requires pthreads, but we didn't find them])
+                               fi
+                               LIBS="$LIBS $PTHREAD_LIBS"
+                       fi
+               fi
+
+               AC_DEFINE(HAVE_DAG_API, 1, [define if you have the DAG API])
+       else
+
+               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 "$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
+fi
+
+AC_ARG_WITH(septel,
+AC_HELP_STRING([--with-septel@<:@=DIR@:>@],[include Septel support (located in directory DIR, if supplied).  @<:@default=yes, if present@:>@]),
+[
+       if test "$withval" = no
+       then
+               want_septel=no
+       elif test "$withval" = yes
+       then
+               want_septel=yes
+               septel_root=
+       else
+               want_septel=yes
+               septel_root=$withval
+       fi
+],[
+       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
+])
+
+ac_cv_lbl_septel_api=no
+if test "$with_septel" != no; then
+
+       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
+
+       septel_tools_dir="$septel_root"
+       septel_include_dir="$septel_root/INC"
+
+       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="$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
+
+               if test "$want_septel" = yes; then
+                       # 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
+       fi
+fi
+
+# Check for Myricom SNF support.
+AC_ARG_WITH([snf],
+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
+               # User explicitly doesn't want SNF
+               want_snf=no
+       elif test "$withval" = yes
+       then
+               # User wants SNF support but hasn't specified a directory.
+               want_snf=yes
+       else
+               # User wants SNF support with a specified directory.
+               want_snf=yes
+               snf_root=$withval
+       fi
+],[
+       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=IDIR],[Myricom SNF include directory, if not DIR/include]),
+[
+       # User wants SNF with specific header directory
+       want_snf=yes
+       snf_include_dir=$withval
+],[])
+
+AC_ARG_WITH([snf-libraries],
+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
+],[])
+
+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
+
+       if test -z "$snf_include_dir"; then
+               snf_include_dir="$snf_root/include"
+       fi
+
+       if test -z "$snf_lib_dir"; then
+               snf_lib_dir="$snf_root/lib"
+       fi
+
+       if test -f "$snf_include_dir/snf.h"; then
+               # 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
+
+       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([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
+               # 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
+])
+
+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
+
+dnl
+dnl Allow the user to enable remote capture.
+dnl It's off by default, as that increases the attack surface of
+dnl libpcap, exposing it to malicious servers.
+dnl
+AC_MSG_CHECKING([whether to enable remote packet capture])
+AC_ARG_ENABLE(remote,
+[  --enable-remote         enable remote packet capture @<:@default=no@:>@
+  --disable-remote        disable remote packet capture],,
+   enableval=no)
+case "$enableval" in
+yes)   AC_MSG_RESULT(yes)
+       AC_WARN([Remote packet capture may expose libpcap-based applications])
+       AC_WARN([to attacks by malicious remote capture servers!])
+       #
+       # rpcapd requires pthreads on UN*X.
+       #
+       if test "$ac_lbl_have_pthreads" != "found"; then
+               AC_MSG_ERROR([rpcapd requires pthreads, but we didn't find them])
+       fi
+       #
+       # It also requires crypt().
+       # Do we have it in the system libraries?
+       #
+       AC_CHECK_FUNC(crypt,,
+           [
+               #
+               # No.  Do we have it in -lcrypt?
+               #
+               AC_CHECK_LIB(crypt, crypt,
+                   [
+                       #
+                       # Yes; add -lcrypt to the libraries for rpcapd.
+                       #
+                       RPCAPD_LIBS="$RPCAPD_LIBS -lcrypt"
+                   ],
+                   [
+                       AC_MSG_ERROR([rpcapd requires crypt(), but we didn't find it])
+                   ])
+           ])
+
+       #
+       # OK, we have crypt().  Do we have getspnam()?
+       #
+       AC_CHECK_FUNCS(getspnam)
+
+       #
+       # Check for various members of struct msghdr.
+       #
+       AC_CHECK_MEMBERS([struct msghdr.msg_control],,,
+           [
+               #include "ftmacros.h"
+               #include <sys/socket.h>
+           ])
+       AC_CHECK_MEMBERS([struct msghdr.msg_flags],,,
+           [
+               #include "ftmacros.h"
+               #include <sys/socket.h>
+           ])
+
+       AC_DEFINE(ENABLE_REMOTE,,
+           [Define to 1 if remote packet capture is to be supported])
+       SSRC="$SSRC pcap-new.c pcap-rpcap.c rpcap-protocol.c sockutils.c"
+       BUILD_RPCAPD=build-rpcapd
+       INSTALL_RPCAPD=install-rpcapd
+       ;;
+*)     AC_MSG_RESULT(no)
+       ;;
+esac
+
+AC_MSG_CHECKING(whether to build optimizer debugging code)
+AC_ARG_ENABLE(optimizer-dbg,
+AC_HELP_STRING([--enable-optimizer-dbg],[build optimizer debugging code]))
+if test "$enable_optimizer_dbg" = "yes"; then
+       AC_DEFINE(BDEBUG,1,[Enable optimizer debugging])
+fi
+AC_MSG_RESULT(${enable_optimizer_dbg-no})
+
+AC_MSG_CHECKING(whether to build parser debugging code)
+AC_ARG_ENABLE(yydebug,
+AC_HELP_STRING([--enable-yydebug],[build parser debugging code]))
+if test "$enable_yydebug" = "yes"; then
+       AC_DEFINE(YYDEBUG,1,[Enable parser debugging])
+fi
+AC_MSG_RESULT(${enable_yydebug-no})
+
+#
+# Look for {f}lex.
+#
+AC_PROG_LEX
+if test "$LEX" = ":"; then
+       AC_MSG_ERROR([Neither flex nor lex was found.])
+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, a newer version of Berkeley YACC with support
+ for reentrant parsers, or another YACC compatible with them.])
+fi
+
+#
+# Do various checks for various OSes and versions of those OSes.
+#
+# Assume, by default, no support for shared libraries and V7/BSD
+# convention for man pages (devices in section 4, file formats in
+# section 5, miscellaneous info in section 7, administrative commands
+# and daemons in section 8).  Individual cases can override this.
+#
+DYEXT="none"
+MAN_DEVICES=4
+MAN_FILE_FORMATS=5
+MAN_MISC_INFO=7
+MAN_ADMIN_COMMANDS=8
+case "$host_os" in
+
+aix*)
+       dnl Workaround to enable certain features
+       AC_DEFINE(_SUN,1,[define on AIX to get certain functions])
+
+       #
+       # AIX makes it fun to build shared and static libraries,
+       # because they're *both* ".a" archive libraries.  We
+       # build the static library for the benefit of the traditional
+       # scheme of building libpcap and tcpdump in subdirectories of
+       # the same directory, with tcpdump statically linked with the
+       # libpcap in question, but we also build a shared library as
+       # "libpcap.shareda" and install *it*, rather than the static
+       # library, as "libpcap.a".
+       #
+       DYEXT="shareda"
+
+       case "$V_PCAP" in
+
+       dlpi)
+               #
+               # If we're using DLPI, applications will need to
+               # use /lib/pse.exp if present, as we use the
+               # STREAMS routines.
+               #
+               pseexe="/lib/pse.exp"
+               AC_MSG_CHECKING(for $pseexe)
+               if test -f $pseexe ; then
+                       AC_MSG_RESULT(yes)
+                       LIBS="-I:$pseexe"
+               fi
+               ;;
+
+       bpf)
+               #
+               # If we're using BPF, we need "-lodm" and "-lcfg", as
+               # we use them to load the BPF module.
+               #
+               LIBS="-lodm -lcfg"
+               ;;
+       esac
+       ;;
+
+darwin*)
+       DYEXT="dylib"
+       V_CCOPT="$V_CCOPT -fno-common"
+       AC_ARG_ENABLE(universal,
+       AC_HELP_STRING([--disable-universal],[don't build universal on macOS]))
+       if test "$enable_universal" != "no"; then
+               case "$host_os" in
+
+               darwin[[0-7]].*)
+                       #
+                       # Pre-Tiger.  Build only for 32-bit PowerPC; no
+                       # need for any special compiler or linker flags.
+                       #
+                       ;;
+
+               darwin8.[[0123]]|darwin8.[[0123]].*)
+                       #
+                       # Tiger, prior to Intel support.  Build
+                       # libraries and executables for 32-bit PowerPC
+                       # and 64-bit PowerPC, with 32-bit PowerPC first.
+                       # (I'm guessing that's what Apple does.)
+                       #
+                       # (The double brackets are needed because
+                       # autotools/m4 use brackets as a quoting
+                       # character; the double brackets turn into
+                       # single brackets in the generated configure
+                       # file.)
+                       #
+                       V_LIB_CCOPT_FAT="-arch ppc -arch ppc64"
+                       V_LIB_LDFLAGS_FAT="-arch ppc -arch ppc64"
+                       V_PROG_CCOPT_FAT="-arch ppc -arch ppc64"
+                       V_PROG_LDFLAGS_FAT="-arch ppc -arch ppc64"
+                       ;;
+
+               darwin8.[[456]]|darwin.[[456]].*)
+                       #
+                       # Tiger, subsequent to Intel support but prior
+                       # to x86-64 support.  Build libraries and
+                       # executables for 32-bit PowerPC, 64-bit
+                       # PowerPC, and 32-bit x86, with 32-bit PowerPC
+                       # first.  (I'm guessing that's what Apple does.)
+                       #
+                       # (The double brackets are needed because
+                       # autotools/m4 use brackets as a quoting
+                       # character; the double brackets turn into
+                       # single brackets in the generated configure
+                       # file.)
+                       #
+                       V_LIB_CCOPT_FAT="-arch ppc -arch ppc64 -arch i386"
+                       V_LIB_LDFLAGS_FAT="-arch ppc -arch ppc64 -arch i386"
+                       V_PROG_CCOPT_FAT="-arch ppc -arch ppc64 -arch i386"
+                       V_PROG_LDFLAGS_FAT="-arch ppc -arch ppc64 -arch i386"
+                       ;;
+
+               darwin8.*)
+                       #
+                       # All other Tiger, so subsequent to x86-64
+                       # support.  Build libraries and executables for
+                       # 32-bit PowerPC, 64-bit PowerPC, 32-bit x86,
+                       # and x86-64, with 32-bit PowerPC first.  (I'm
+                       # guessing that's what Apple does.)
+                       #
+                       V_LIB_CCOPT_FAT="-arch ppc -arch ppc64 -arch i386 -arch x86_64"
+                       V_LIB_LDFLAGS_FAT="-arch ppc -arch ppc64 -arch i386 -arch x86_64"
+                       V_PROG_CCOPT_FAT="-arch ppc -arch ppc64 -arch i386 -arch x86_64"
+                       V_PROG_LDFLAGS_FAT="-arch ppc -arch ppc64 -arch i386 -arch x86_64"
+                       ;;
+
+               darwin9.*)
+                       #
+                       # Leopard.  Build libraries for 32-bit PowerPC,
+                       # 64-bit PowerPC, 32-bit x86, and x86-64, with
+                       # 32-bit PowerPC first, and build executables
+                       # for 32-bit x86 and 32-bit PowerPC, with 32-bit
+                       # x86 first.  (That's what Apple does.)
+                       #
+                       V_LIB_CCOPT_FAT="-arch ppc -arch ppc64 -arch i386 -arch x86_64"
+                       V_LIB_LDFLAGS_FAT="-arch ppc -arch ppc64 -arch i386 -arch x86_64"
+                       V_PROG_CCOPT_FAT="-arch i386 -arch ppc"
+                       V_PROG_LDFLAGS_FAT="-arch i386 -arch ppc"
+                       ;;
+
+               darwin10.*)
+                       #
+                       # Snow Leopard.  Build libraries for x86-64,
+                       # 32-bit x86, and 32-bit PowerPC, with x86-64
+                       # first, and build executables for x86-64 and
+                       # 32-bit x86, with x86-64 first.  (That's what
+                       # Apple does, even though Snow Leopard doesn't
+                       # run on PPC, so PPC libpcap runs under Rosetta,
+                       # and Rosetta doesn't support BPF ioctls, so PPC
+                       # programs can't do live captures.)
+                       #
+                       V_LIB_CCOPT_FAT="-arch x86_64 -arch i386 -arch ppc"
+                       V_LIB_LDFLAGS_FAT="-arch x86_64 -arch i386 -arch ppc"
+                       V_PROG_CCOPT_FAT="-arch x86_64 -arch i386"
+                       V_PROG_LDFLAGS_FAT="-arch x86_64 -arch i386"
+                       ;;
+
+               darwin*)
+                       #
+                       # Post-Snow Leopard.  Build libraries for x86-64
+                       # and 32-bit x86, with x86-64 first, and build
+                       # executables only for x86-64.  (That's what
+                       # Apple does.)  This requires no special flags
+                       # for programs.
+                       # XXX - update if and when Apple drops support
+                       # for 32-bit x86 code and if and when Apple adds
+                       # ARM-based Macs.  (You're on your own for iOS
+                       # etc.)
+                       #
+                       # XXX - check whether we *can* build for
+                       # i386 and, if not, suggest that the user
+                       # install the /usr/include headers if they
+                       # want to build fat.
+                       #
+                       AC_MSG_CHECKING(whether building for 32-bit x86 is supported)
+                       save_CFLAGS="$CFLAGS"
+                       CFLAGS="$CFLAGS -arch i386"
+                       AC_TRY_COMPILE(
+                           [],
+                           [return 0;],
+                           [
+                               AC_MSG_RESULT(yes)
+                               V_LIB_CCOPT_FAT="-arch x86_64 -arch i386"
+                               V_LIB_LDFLAGS_FAT="-arch x86_64 -arch i386"
+                           ],
+                           [
+                               AC_MSG_RESULT(no)
+                               V_LIB_CCOPT_FAT="-arch x86_64"
+                               V_LIB_LDFLAGS_FAT="-arch x86_64"
+                               case "$host_os" in
+
+                               darwin18.*)
+                                       #
+                                       # Mojave; you need to install the
+                                       # /usr/include headers to get
+                                       # 32-bit x86 builds to work.
+                                       #
+                                       AC_MSG_WARN([Compiling for 32-bit x86 gives an error; try installing the command-line tools and, after that, installing the /usr/include headers from the /Library/Developer/CommandLineTools/Packages/macOS_SDK_headers_for_macOS_10.14.pkg package])
+                                       ;;
+
+                               *)
+                                       #
+                                       # Pre-Mojave; the command-line
+                                       # tools should be sufficient to
+                                       # enable 32-bit x86 builds.
+                                       #
+                                       AC_MSG_WARN([Compiling for 32-bit x86 gives an error; try installing the command-line tools])
+                                       ;;
+                               esac
+                           ])
+                       CFLAGS="$save_CFLAGS"
+                       ;;
+               esac
+       fi
+       ;;
+
+hpux9*)
+       AC_DEFINE(HAVE_HPUX9,1,[on HP-UX 9.x])
+
+       #
+       # Use System V conventions for man pages.
+       #
+       MAN_ADMIN_COMMANDS=1m
+       MAN_FILE_FORMATS=4
+       MAN_MISC_INFO=5
+       ;;
+
+hpux10.0*)
+
+       #
+       # Use System V conventions for man pages.
+       #
+       MAN_ADMIN_COMMANDS=1m
+       MAN_FILE_FORMATS=4
+       MAN_MISC_INFO=5
+       ;;
+
+hpux10.1*)
+
+       #
+       # Use System V conventions for man pages.
+       #
+       MAN_ADMIN_COMMANDS=1m
+       MAN_FILE_FORMATS=4
+       MAN_MISC_INFO=5
+       ;;
+
+hpux*)
+       dnl HPUX 10.20 and above is similar to HPUX 9, but
+       dnl not the same....
+       dnl
+       dnl XXX - DYEXT should be set to "sl" if this is building
+       dnl for 32-bit PA-RISC, but should be left as "so" for
+       dnl 64-bit PA-RISC or, I suspect, IA-64.
+       AC_DEFINE(HAVE_HPUX10_20_OR_LATER,1,[on HP-UX 10.20 or later])
+       if test "`uname -m`" = "ia64"; then
+               DYEXT="so"
+       else
+               DYEXT="sl"
+       fi
+
+       #
+       # "-b" builds a shared library; "+h" sets the soname.
+       #
+       SHLIB_OPT="-b"
+       SONAME_OPT="+h"
+
+       #
+       # Use System V conventions for man pages.
+       #
+       MAN_FILE_FORMATS=4
+       MAN_MISC_INFO=5
+       ;;
+
+irix*)
+       #
+       # Use IRIX conventions for man pages; they're the same as the
+       # System V conventions, except that they use section 8 for
+       # administrative commands and daemons.
+       #
+       MAN_FILE_FORMATS=4
+       MAN_MISC_INFO=5
+       ;;
+
+linux*|freebsd*|netbsd*|openbsd*|dragonfly*|kfreebsd*|gnu*|midipix*)
+       DYEXT="so"
+
+       #
+       # Compiler assumed to be GCC; run-time linker may require a -R
+       # flag.
+       #
+       if test "$libdir" != "/usr/lib"; then
+               V_RFLAGS=-Wl,-R$libdir
+       fi
+       ;;
+
+osf*)
+       DYEXT="so"
+
+       #
+       # DEC OSF/1, a/k/a Digial UNIX, a/k/a Tru64 UNIX.
+       # Use Tru64 UNIX conventions for man pages; they're the same as
+       # the System V conventions except that they use section 8 for
+       # administrative commands and daemons.
+       #
+       MAN_FILE_FORMATS=4
+       MAN_MISC_INFO=5
+       MAN_DEVICES=7
+       ;;
+
+sinix*)
+       AC_MSG_CHECKING(if SINIX compiler defines sinix)
+       AC_CACHE_VAL(ac_cv_cc_sinix_defined,
+               AC_TRY_COMPILE(
+                   [],
+                   [int i = sinix;],
+                   ac_cv_cc_sinix_defined=yes,
+                   ac_cv_cc_sinix_defined=no))
+           AC_MSG_RESULT($ac_cv_cc_sinix_defined)
+           if test $ac_cv_cc_sinix_defined = no ; then
+                   AC_DEFINE(sinix,1,[on sinix])
+           fi
+       ;;
+
+solaris*)
+       AC_DEFINE(HAVE_SOLARIS,1,[On solaris])
+
+       DYEXT="so"
+
+       #
+       # Make sure errno is thread-safe, in case we're called in
+       # a multithreaded program.  We don't guarantee that two
+       # threads can use the *same* pcap_t safely, but the
+       # current version does guarantee that you can use different
+       # pcap_t's in different threads, and even that pcap_compile()
+       # is thread-safe (it wasn't thread-safe in some older versions).
+       #
+       V_CCOPT="$V_CCOPT -D_TS_ERRNO"
+
+       case "`uname -r`" in
+
+       5.12)
+               ;;
+
+       *)
+               #
+               # Use System V conventions for man pages.
+               #
+               MAN_ADMIN_COMMANDS=1m
+               MAN_FILE_FORMATS=4
+               MAN_MISC_INFO=5
+               MAN_DEVICES=7D
+       esac
+       ;;
+esac
+
+AC_ARG_ENABLE(shared,
+AC_HELP_STRING([--enable-shared],[build shared libraries @<:@default=yes, if support available@:>@]))
+test "x$enable_shared" = "xno" && DYEXT="none"
+
+AC_PROG_RANLIB
+AC_CHECK_TOOL([AR], [ar])
+
+AC_PROG_LN_S
+AC_SUBST(LN_S)
+
+AC_LBL_DEVEL(V_CCOPT)
+
+#
+# Check to see if the sockaddr struct has the 4.4 BSD sa_len member.
+#
+AC_CHECK_MEMBERS([struct sockaddr.sa_len],,,
+    [
+       #include <sys/types.h>
+       #include <sys/socket.h>
+    ])
+
+#
+# Check to see if there's a sockaddr_storage structure.
+#
+AC_CHECK_TYPES(struct sockaddr_storage,,,
+    [
+       #include <sys/types.h>
+       #include <sys/socket.h>
+    ])
+
+#
+# Check to see if the dl_hp_ppa_info_t struct has the HP-UX 11.00
+# dl_module_id_1 member.
+#
+# NOTE: any failure means we conclude that it doesn't have that member,
+# so if we don't have DLPI, don't have a <sys/dlpi_ext.h> header, or
+# have one that doesn't declare a dl_hp_ppa_info_t type, we conclude
+# it doesn't have that member (which is OK, as either we won't be
+# using code that would use that member, or we wouldn't compile in
+# any case).
+#
+AC_CHECK_MEMBERS([dl_hp_ppa_info_t.dl_module_id_1],,,
+    [
+       #include <sys/types.h>
+       #include <sys/dlpi.h>
+       #include <sys/dlpi_ext.h>
+    ])
+
+AC_LBL_UNALIGNED_ACCESS
+
+AC_SUBST(V_CCOPT)
+AC_SUBST(V_LIB_CCOPT_FAT)
+AC_SUBST(V_LIB_LDFLAGS_FAT)
+AC_SUBST(V_PROG_CCOPT_FAT)
+AC_SUBST(V_PROG_LDFLAGS_FAT)
+AC_SUBST(V_DEFS)
+AC_SUBST(V_FINDALLDEVS)
+AC_SUBST(V_INCLS)
+AC_SUBST(V_LEX)
+AC_SUBST(V_PCAP)
+AC_SUBST(V_SHLIB_CCOPT)
+AC_SUBST(V_SHLIB_CMD)
+AC_SUBST(V_SHLIB_OPT)
+AC_SUBST(V_SONAME_OPT)
+AC_SUBST(V_RPATH_OPT)
+AC_SUBST(V_YACC)
+AC_SUBST(ADDLOBJS)
+AC_SUBST(ADDLARCHIVEOBJS)
+AC_SUBST(SSRC)
+AC_SUBST(DYEXT)
+AC_SUBST(MAN_DEVICES)
+AC_SUBST(MAN_FILE_FORMATS)
+AC_SUBST(MAN_MISC_INFO)
+AC_SUBST(MAN_ADMIN_COMMANDS)
+AC_SUBST(PTHREAD_LIBS)
+AC_SUBST(BUILD_RPCAPD)
+AC_SUBST(INSTALL_RPCAPD)
+AC_SUBST(RPCAPD_LIBS)
+AC_SUBST(EXTRA_NETWORK_LIBS)
+
+AC_ARG_ENABLE([usb],
+[AC_HELP_STRING([--enable-usb],[enable USB capture 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)
+       ac_usb_dev_name=`udevinfo -q name -p /sys/class/usb_device/usbmon 2>/dev/null`
+       if test $? -ne 0 ; then
+         ac_usb_dev_name="usbmon"
+       fi
+       AC_DEFINE_UNQUOTED(LINUX_USB_MON_DEV, "/dev/$ac_usb_dev_name", [path for device for USB sniffing])
+       AC_MSG_NOTICE(Device for USB sniffing is /dev/$ac_usb_dev_name)
+       #
+       # Do we have a version of <linux/compiler.h> available?
+       # If so, we might need it for <linux/usbdevice_fs.h>.
+       #
+       AC_CHECK_HEADERS(linux/compiler.h)
+       if test "$ac_cv_header_linux_compiler_h" = yes; then
+         #
+         # Yes - include it when testing for <linux/usbdevice_fs.h>.
+         #
+         AC_CHECK_HEADERS(linux/usbdevice_fs.h,,,[#include <linux/compiler.h>])
+       else
+         AC_CHECK_HEADERS(linux/usbdevice_fs.h)
+       fi
+       if test "$ac_cv_header_linux_usbdevice_fs_h" = yes; then
+         #
+         # OK, does it define bRequestType?  Older versions of the kernel
+         # define fields with names like "requesttype, "request", and
+         # "value", rather than "bRequestType", "bRequest", and
+         # "wValue".
+         #
+         AC_CHECK_MEMBERS([struct usbdevfs_ctrltransfer.bRequestType],,,
+             [
+                 AC_INCLUDES_DEFAULT
+                 #ifdef HAVE_LINUX_COMPILER_H
+                 #include <linux/compiler.h>
+                 #endif
+                 #include <linux/usbdevice_fs.h>
+             ])
+       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
+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>
+#include <linux/types.h>
+
+#include <linux/netlink.h>
+#include <linux/netfilter.h>
+#include <linux/netfilter/nfnetlink.h>
+#include <linux/netfilter/nfnetlink_log.h>
+#include <linux/netfilter/nfnetlink_queue.h>],
+                   [],
+                   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
+fi
+AC_SUBST(PCAP_SUPPORT_NETFILTER)
+AC_SUBST(NETFILTER_SRC)
+
+AC_ARG_ENABLE([netmap],
+[AC_HELP_STRING([--enable-netmap],[enable netmap support @<:@default=yes, if support available@:>@])],
+    [],
+    [enable_netmap=yes])
+
+if test "x$enable_netmap" != "xno" ; then
+       #
+       # Check whether net/netmap_user.h is usable if NETMAP_WITH_LIBS is
+       # defined; it's not usable on DragonFly BSD 4.6 if NETMAP_WITH_LIBS
+       # is defined, for example, as it includes a non-existent malloc.h
+       # header.
+       #
+       AC_MSG_CHECKING(whether we can compile the netmap support)
+       AC_CACHE_VAL(ac_cv_net_netmap_user_can_compile,
+         AC_TRY_COMPILE([
+AC_INCLUDES_DEFAULT
+#define NETMAP_WITH_LIBS
+#include <net/netmap_user.h>],
+           [],
+           ac_cv_net_netmap_user_can_compile=yes,
+           ac_cv_net_netmap_user_can_compile=no))
+       AC_MSG_RESULT($ac_cv_net_netmap_user_can_compile)
+       if test $ac_cv_net_netmap_user_can_compile = yes ; then
+         AC_DEFINE(PCAP_SUPPORT_NETMAP, 1,
+           [target host supports netmap])
+           NETMAP_SRC=pcap-netmap.c
+       fi
+       AC_SUBST(PCAP_SUPPORT_NETMAP)
+       AC_SUBST(NETMAP_SRC)
+fi
+
+
+AC_ARG_ENABLE([bluetooth],
+[AC_HELP_STRING([--enable-bluetooth],[enable Bluetooth support @<:@default=yes, if support available@:>@])],
+    [],
+    [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
+       linux*)
+               AC_CHECK_HEADER(bluetooth/bluetooth.h,
+                   [
+                       #
+                       # We have bluetooth.h, so we support Bluetooth
+                       # sniffing.
+                       #
+                       AC_DEFINE(PCAP_SUPPORT_BT, 1, [target host supports Bluetooth sniffing])
+                       BT_SRC=pcap-bt-linux.c
+                       AC_MSG_NOTICE(Bluetooth sniffing is supported)
+                       ac_lbl_bluetooth_available=yes
+
+                       #
+                       # OK, does struct sockaddr_hci have an hci_channel
+                       # member?
+                       #
+                       AC_CHECK_MEMBERS([struct sockaddr_hci.hci_channel],
+                           [
+                               #
+                               # Yes; is HCI_CHANNEL_MONITOR defined?
+                               #
+                               AC_MSG_CHECKING(if HCI_CHANNEL_MONITOR is defined)
+                               AC_CACHE_VAL(ac_cv_lbl_hci_channel_monitor_is_defined,
+                                   AC_TRY_COMPILE(
+                                       [
+                                           #include <bluetooth/bluetooth.h>
+                                           #include <bluetooth/hci.h>
+                                       ],
+                                       [
+                                           u_int i = HCI_CHANNEL_MONITOR;
+                                       ],
+                                       [
+                                           AC_MSG_RESULT(yes)
+                                           AC_DEFINE(PCAP_SUPPORT_BT_MONITOR,,
+                                             [target host supports Bluetooth Monitor])
+                                           BT_MONITOR_SRC=pcap-bt-monitor-linux.c
+                                       ],
+                                       [
+                                           AC_MSG_RESULT(no)
+                                       ]))
+                           ],,
+                           [
+                               #include <bluetooth/bluetooth.h>
+                               #include <bluetooth/hci.h>
+                           ])
+                   ],
+                   [
+                       #
+                       # We don't have bluetooth.h, so we don't support
+                       # Bluetooth sniffing.
+                       #
+                       if test "x$enable_bluetooth" = "xyes" ; then
+                               AC_MSG_ERROR(Bluetooth sniffing is not supported; install bluez-lib devel to enable it)
+                       else
+                               AC_MSG_NOTICE(Bluetooth sniffing is not supported; install bluez-lib devel to enable it)
+                       fi
+                   ])
+               ;;
+       *)
+               if test "x$enable_bluetooth" = "xyes" ; then
+                       AC_MSG_ERROR(no Bluetooth sniffing support implemented for $host_os)
+               else
+                       AC_MSG_NOTICE(no Bluetooth sniffing support implemented for $host_os)
+               fi
+               ;;
+       esac
+       AC_SUBST(PCAP_SUPPORT_BT)
+       AC_SUBST(BT_SRC)
+       AC_SUBST(BT_MONITOR_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 macOS; 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 macOS])
+               esac
+       else
+               case "$host_os" in
+
+               darwin*)
+                       #
+                       # We don't support D-Bus sniffing on macOS; 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
+
+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
+               fi
+       fi
+       AC_SUBST(PCAP_SUPPORT_DBUS)
+       AC_SUBST(DBUS_SRC)
+fi
+
+AC_ARG_ENABLE([rdma],
+[AC_HELP_STRING([--enable-rdma],[enable RDMA capture support @<:@default=yes, if support available@:>@])],
+    [],
+    [enable_rdma=ifavailable])
+
+if test "xxx_only" = yes; then
+       # User requested something-else-only pcap, so they don't
+       # want RDMA support.
+       enable_rdma=no
+fi
+
+if test "x$enable_rdma" != "xno"; then
+       AC_CHECK_LIB(ibverbs, ibv_get_device_list, [
+               AC_CHECK_HEADER(infiniband/verbs.h, [
+                       #
+                       # ibv_create_flow may be defined as a static inline
+                       # function in infiniband/verbs.h, so we can't
+                       # use AC_CHECK_LIB.
+                       #
+                       # Too bad autoconf has no AC_SYMBOL_EXISTS()
+                       # macro that works like CMake's check_symbol_exists()
+                       # function, to check do a compile check like
+                       # this (they do a clever trick to avoid having
+                       # to know the function's signature).
+                       #
+                       AC_MSG_CHECKING(whether libibverbs defines ibv_create_flow)
+                       AC_TRY_LINK(
+                               [
+                                       #include <infiniband/verbs.h>
+                               ],
+                               [
+                                       (void) ibv_create_flow((struct ibv_qp *) NULL,
+                                                              (struct ibv_flow_attr *) NULL);
+                               ],
+                               [
+                                       AC_MSG_RESULT([yes])
+                                       AC_DEFINE(PCAP_SUPPORT_RDMASNIFF, , [target host supports RDMA sniffing])
+                                       RDMA_SRC=pcap-rdmasniff.c
+                                       LIBS="-libverbs $LIBS"
+                               ],
+                               [
+                                       AC_MSG_RESULT([no])
+                               ]
+                       )
+               ])
+       ])
+       AC_SUBST(PCAP_SUPPORT_RDMASNIFF)
+       AC_SUBST(RDMA_SRC)
+fi
+
+AC_PROG_INSTALL
+
+AC_CONFIG_HEADER(config.h)
+
+AC_OUTPUT_COMMANDS([if test -f .devel; then
+       echo timestamp > stamp-h
+       cat $srcdir/Makefile-devel-adds >> Makefile
+       make depend
+fi])
+AC_OUTPUT(Makefile pcap-filter.manmisc pcap-linktype.manmisc
+       pcap-tstamp.manmisc pcap-savefile.manfile pcap.3pcap
+       pcap_compile.3pcap pcap_datalink.3pcap pcap_dump_open.3pcap
+       pcap_get_tstamp_precision.3pcap pcap_list_datalinks.3pcap
+       pcap_list_tstamp_types.3pcap pcap_open_dead.3pcap
+       pcap_open_offline.3pcap pcap_set_immediate_mode.3pcap
+       pcap_set_tstamp_precision.3pcap pcap_set_tstamp_type.3pcap
+       rpcapd/Makefile rpcapd/rpcapd.manadmin rpcapd/rpcapd-config.manfile
+       testprogs/Makefile)
+exit 0
diff --git a/configure.in b/configure.in
deleted file mode 100644 (file)
index 4530aed..0000000
+++ /dev/null
@@ -1,1716 +0,0 @@
-dnl
-dnl Copyright (c) 1994, 1995, 1996, 1997
-dnl    The Regents of the University of California.  All rights reserved.
-dnl
-dnl Process this file with autoconf to produce a configure script.
-dnl
-
-#
-# See
-#
-#      http://ftp.gnu.org/gnu/config/README
-#
-# for the URLs to use to fetch new versions of config.guess and
-# config.sub.
-#
-
-AC_PREREQ(2.61)
-AC_INIT(pcap.c)
-
-AC_CANONICAL_SYSTEM
-
-AC_LBL_C_INIT_BEFORE_CC(V_CCOPT, V_INCLS)
-AC_PROG_CC
-AC_LBL_C_INIT(V_CCOPT, V_INCLS)
-AC_LBL_SHLIBS_INIT
-AC_LBL_C_INLINE
-AC_C___ATTRIBUTE__
-if test "$ac_cv___attribute__" = "yes"; then
-       AC_C___ATTRIBUTE___UNUSED
-       AC_C___ATTRIBUTE___FORMAT
-fi
-
-AC_CHECK_HEADERS(sys/bitypes.h)
-
-AC_CHECK_TYPE([int8_t], ,
-       [AC_DEFINE([int8_t], [signed char],
-       [Define to `signed char' if int8_t not defined.])],
-       [AC_INCLUDES_DEFAULT
-#ifdef HAVE_SYS_BITYPES_H
-#include <sys/bitypes.h>
-#endif])
-AC_CHECK_TYPE([u_int8_t], ,
-       [AC_DEFINE([u_int8_t], [unsigned char],
-       [Define to `unsigned char' if u_int8_t not defined.])],
-       [AC_INCLUDES_DEFAULT
-#ifdef HAVE_SYS_BITYPES_H
-#include <sys/bitypes.h>
-#endif])
-AC_CHECK_TYPE([int16_t], ,
-       [AC_DEFINE([int16_t], [short],
-       [Define to `short' if int16_t not defined.])]
-       [AC_INCLUDES_DEFAULT
-#ifdef HAVE_SYS_BITYPES_H
-#include <sys/bitypes.h>
-#endif])
-AC_CHECK_TYPE([u_int16_t], ,
-       [AC_DEFINE([u_int16_t], [unsigned short],
-       [Define to `unsigned short' if u_int16_t not defined.])],
-       [AC_INCLUDES_DEFAULT
-#ifdef HAVE_SYS_BITYPES_H
-#include <sys/bitypes.h>
-#endif])
-AC_CHECK_TYPE([int32_t], ,
-       [AC_DEFINE([int32_t], [int],
-       [Define to `int' if int32_t not defined.])],
-       [AC_INCLUDES_DEFAULT
-#ifdef HAVE_SYS_BITYPES_H
-#include <sys/bitypes.h>
-#endif])
-AC_CHECK_TYPE([u_int32_t], ,
-       [AC_DEFINE([u_int32_t], [unsigned int],
-       [Define to `unsigned int' if u_int32_t not defined.])],
-       [AC_INCLUDES_DEFAULT
-#ifdef HAVE_SYS_BITYPES_H
-#include <sys/bitypes.h>
-#endif])
-AC_CHECK_TYPE([int64_t], ,
-       [AC_DEFINE([int64_t], [long long],
-       [Define to `long long' if int64_t not defined.])],
-       [AC_INCLUDES_DEFAULT
-#ifdef HAVE_SYS_BITYPES_H
-#include <sys/bitypes.h>
-#endif])
-AC_CHECK_TYPE([u_int64_t], ,
-       [AC_DEFINE([u_int64_t], [unsigned long long],
-       [Define to `unsigned long long' if u_int64_t not defined.])],
-       [AC_INCLUDES_DEFAULT
-#ifdef HAVE_SYS_BITYPES_H
-#include <sys/bitypes.h>
-#endif])
-
-#
-# Try to arrange for large file support.
-#
-AC_SYS_LARGEFILE
-AC_FUNC_FSEEKO
-
-dnl
-dnl Even if <net/bpf.h> were, on all OSes that support BPF, fixed to
-dnl include <sys/ioccom.h>, and we were to drop support for older
-dnl releases without that fix, so that pcap-bpf.c doesn't need to
-dnl include <sys/ioccom.h>, the test program in "AC_LBL_FIXINCLUDES"
-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(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>
-#include <sys/socket.h>
-#include <net/if.h>])
-if test "$ac_cv_header_net_pfvar_h" = yes; then
-       #
-       # Check for various PF actions.
-       #
-       AC_MSG_CHECKING(whether net/pfvar.h defines PF_NAT through PF_NORDR)
-       AC_TRY_COMPILE(
-           [#include <sys/types.h>
-           #include <sys/socket.h>
-           #include <net/if.h>
-           #include <net/pfvar.h>],
-           [return PF_NAT+PF_NONAT+PF_BINAT+PF_NOBINAT+PF_RDR+PF_NORDR;],
-           [
-               AC_MSG_RESULT(yes)
-               AC_DEFINE(HAVE_PF_NAT_THROUGH_PF_NORDR, 1,
-                   [define if net/pfvar.h defines PF_NAT through PF_NORDR])
-           ],
-           AC_MSG_RESULT(no))
-fi
-AC_CHECK_HEADERS(netinet/if_ether.h, , , [#include <sys/types.h>
-#include <sys/socket.h>])
-if test "$ac_cv_header_netinet_if_ether_h" != yes; then
-       #
-       # The simple test didn't work.
-       # Do we need to include <net/if.h> first?
-       # Unset ac_cv_header_netinet_if_ether_h so we don't
-       # treat the previous failure as a cached value and
-       # suppress the next test.
-       #
-       AC_MSG_NOTICE([Rechecking with some additional includes])
-       unset ac_cv_header_netinet_if_ether_h
-       AC_CHECK_HEADERS(netinet/if_ether.h, , , [#include <sys/types.h>
-#include <sys/socket.h>
-#include <netinet/in.h>
-struct mbuf;
-struct rtentry;
-#include <net/if.h>])
-fi
-
-AC_LBL_FIXINCLUDES
-
-AC_CHECK_FUNCS(strerror strlcpy)
-
-needsnprintf=no
-AC_CHECK_FUNCS(vsnprintf snprintf,,
-       [needsnprintf=yes])
-if test $needsnprintf = yes; then
-       AC_LIBOBJ([snprintf])
-fi
-
-#
-# Do this before checking for ether_hostton(), as it's a
-# "gethostbyname() -ish function".
-#
-AC_LBL_LIBRARY_NET
-
-#
-# You are in a twisty little maze of UN*Xes, all different.
-# Some might not have ether_hostton().
-# Some might have it, but not declare it in any header file.
-# Some might have it, but declare it in <netinet/if_ether.h>.
-# Some might have it, but declare it in <netinet/ether.h>
-# (And some might have it but document it as something declared in
-# <netinet/ethernet.h>, although <netinet/if_ether.h> appears to work.)
-#
-# Before you is a C compiler.
-#
-AC_CHECK_FUNCS(ether_hostton)
-if test "$ac_cv_func_ether_hostton" = yes; then
-       #
-       # OK, we have ether_hostton().  Do we have <netinet/if_ether.h>?
-       #
-       if test "$ac_cv_header_netinet_if_ether_h" = yes; then
-               #
-               # Yes.  Does it declare ether_hostton()?
-               #
-               AC_CHECK_DECL(ether_hostton,
-                   [
-                       AC_DEFINE(NETINET_IF_ETHER_H_DECLARES_ETHER_HOSTTON,,
-                           [Define to 1 if netinet/if_ether.h declares `ether_hostton'])
-                   ],,
-                   [
-#include <sys/types.h>
-#include <sys/socket.h>
-#include <netinet/in.h>
-#include <arpa/inet.h>
-struct mbuf;
-struct rtentry;
-#include <net/if.h>
-#include <netinet/if_ether.h>
-                   ])
-       fi
-       #
-       # Did that succeed?
-       #
-       if test "$ac_cv_have_decl_ether_hostton" != yes; then
-               #
-               # No, how about <netinet/ether.h>, as on Linux?
-               #
-               AC_CHECK_HEADERS(netinet/ether.h)
-               if test "$ac_cv_header_netinet_ether_h" = yes; then
-                       #
-                       # We have it - does it declare ether_hostton()?
-                       # Unset ac_cv_have_decl_ether_hostton so we don't
-                       # treat the previous failure as a cached value and
-                       # suppress the next test.
-                       #
-                       unset ac_cv_have_decl_ether_hostton
-                       AC_CHECK_DECL(ether_hostton,
-                           [
-                               AC_DEFINE(NETINET_ETHER_H_DECLARES_ETHER_HOSTTON,,
-                                   [Define to 1 if netinet/ether.h declares `ether_hostton'])
-                           ],,
-                           [
-#include <netinet/ether.h>
-                           ])
-               fi
-       fi
-       #
-       # Is ether_hostton() declared?
-       #
-       if test "$ac_cv_have_decl_ether_hostton" != yes; then
-               #
-               # No, we'll have to declare it ourselves.
-               # Do we have "struct ether_addr"?
-               #
-               AC_CHECK_TYPES(struct ether_addr,,,
-                   [
-#include <sys/types.h>
-#include <sys/socket.h>
-#include <netinet/in.h>
-#include <arpa/inet.h>
-struct mbuf;
-struct rtentry;
-#include <net/if.h>
-#include <netinet/if_ether.h>
-                   ])
-               AC_DEFINE(HAVE_DECL_ETHER_HOSTTON, 0,
-                   [Define to 1 if you have the declaration of `ether_hostton', and to 0 if you
-don't.])
-       else
-               AC_DEFINE(HAVE_DECL_ETHER_HOSTTON, 1,
-                   [Define to 1 if you have the declaration of `ether_hostton', and to 0 if you
-don't.])
-       fi
-fi
-
-dnl to pacify those who hate protochain insn
-AC_MSG_CHECKING(if --disable-protochain option is specified)
-AC_ARG_ENABLE(protochain,
-AC_HELP_STRING([--disable-protochain],[disable \"protochain\" insn]))
-case "x$enable_protochain" in
-xyes)  enable_protochain=enabled       ;;
-xno)   enable_protochain=disabled      ;;
-x)     enable_protochain=enabled       ;;
-esac
-
-if test "$enable_protochain" = "disabled"; then
-       AC_DEFINE(NO_PROTOCHAIN,1,[do not use protochain])
-fi
-AC_MSG_RESULT(${enable_protochain})
-
-#
-# SITA support is mutually exclusive with native capture support;
-# "--with-sita" selects SITA support.
-#
-AC_ARG_WITH(sita,
-AC_HELP_STRING([--with-sita],[include SITA support]),
-[
-       if test ! "x$withval" = "xno" ; then
-               AC_DEFINE(SITA,1,[include ACN support])
-               AC_MSG_NOTICE(Enabling SITA ACN support)
-               V_PCAP=sita
-               V_FINDALLDEVS=sita
-       fi
-],
-[
-dnl
-dnl Not all versions of test support -c (character special) but it's a
-dnl better way of testing since the device might be protected. So we
-dnl check in our normal order using -r and then check the for the /dev
-dnl guys again using -c.
-dnl
-dnl XXX This could be done for cross-compiling, but for now it's not.
-dnl
-if test -z "$with_pcap" && test "$cross_compiling" = yes; then
-       AC_MSG_ERROR(pcap type not determined when cross-compiling; use --with-pcap=...)
-fi
-AC_ARG_WITH(pcap,
-AC_HELP_STRING([--with-pcap=TYPE],[use packet capture TYPE]))
-AC_MSG_CHECKING(packet capture type)
-if test ! -z "$with_pcap" ; then
-       V_PCAP="$withval"
-elif test -r /dev/bpf -o -h /dev/bpf ; then
-       #
-       # Cloning BPF device.
-       #
-       V_PCAP=bpf
-       AC_DEFINE(HAVE_CLONING_BPF,1,[define if you have a cloning BPF device])
-elif test -r /dev/bpf0 ; then
-       V_PCAP=bpf
-elif test -r /usr/include/net/pfilt.h ; then
-       V_PCAP=pf
-elif test -r /dev/enet ; then
-       V_PCAP=enet
-elif test -r /dev/nit ; then
-       V_PCAP=snit
-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
-elif test -r /usr/include/net/raw.h ; then
-       V_PCAP=snoop
-elif test -r /usr/include/odmi.h ; then
-       #
-       # On AIX, the BPF devices might not yet be present - they're
-       # created the first time libpcap runs after booting.
-       # We check for odmi.h instead.
-       #
-       V_PCAP=bpf
-elif test -c /dev/bpf0 ; then          # check again in case not readable
-       V_PCAP=bpf
-elif test -r /usr/include/sys/dlpi.h ; then
-       V_PCAP=dlpi
-elif test -c /dev/enet ; then          # check again in case not readable
-       V_PCAP=enet
-elif test -c /dev/nit ; then           # check again in case not readable
-       V_PCAP=snit
-else
-       V_PCAP=null
-fi
-AC_MSG_RESULT($V_PCAP)
-
-#
-# Do capture-mechanism-dependent tests.
-#
-case "$V_PCAP" in
-dlpi)
-       #
-       # Needed for common functions used by pcap-[dlpi,libdlpi].c
-       #
-       SSRC="dlpisubs.c"
-
-       #
-       # Checks for some header files.
-       #
-       AC_CHECK_HEADERS(sys/bufmod.h sys/dlpi_ext.h)
-
-       #
-       # 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. 
-       # 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]. 
-       # Also, due to the bug above applications that link to libpcap with
-       # libdlpi will have to add "-L/lib" option to "configure".
-       #
-       saved_ldflags=$LDFLAGS
-       LDFLAGS="$LIBS -L/lib"
-       AC_CHECK_LIB(dlpi, dlpi_walk,
-               [
-                       LIBS="-ldlpi $LIBS"
-                       V_PCAP=libdlpi
-                       AC_DEFINE(HAVE_LIBDLPI,1,[if libdlpi exists])
-               ],
-               V_PCAP=dlpi)
-       LDFLAGS=$saved_ldflags
-
-       #
-       # Checks whether <sys/dlpi.h> is usable, to catch weird SCO
-       # versions of DLPI.
-       #
-       AC_MSG_CHECKING(whether <sys/dlpi.h> is usable)
-       AC_CACHE_VAL(ac_cv_sys_dlpi_usable,
-               AC_TRY_COMPILE(
-                   [
-                       #include <sys/types.h>
-                       #include <sys/time.h>
-                       #include <sys/dlpi.h>
-                   ],
-                   [int i = DL_PROMISC_PHYS;],
-                   ac_cv_sys_dlpi_usable=yes,
-                   ac_cv_sys_dlpi_usable=no))
-       AC_MSG_RESULT($ac_cv_sys_dlpi_usable)
-       if test $ac_cv_sys_dlpi_usable = no ; then
-               AC_MSG_ERROR(<sys/dlpi.h> is not usable on this system; it probably has a non-standard DLPI)
-       fi
-
-       #
-       # Check whether we have a /dev/dlpi device or have multiple devices.
-       #
-       AC_MSG_CHECKING(for /dev/dlpi device)
-       if test -c /dev/dlpi ; then
-               AC_MSG_RESULT(yes)
-               AC_DEFINE(HAVE_DEV_DLPI, 1, [define if you have a /dev/dlpi])
-       else
-               AC_MSG_RESULT(no)
-               dir="/dev/dlpi"
-               AC_MSG_CHECKING(for $dir directory)
-               if test -d $dir ; then
-                       AC_MSG_RESULT(yes)
-                       AC_DEFINE_UNQUOTED(PCAP_DEV_PREFIX, "$dir", [/dev/dlpi directory])
-               else
-                       AC_MSG_RESULT(no)
-               fi
-       fi
-
-       #
-       # This check is for Solaris with DLPI support for passive modes.
-       # See dlpi(7P) for more details.
-       #
-       AC_LBL_DL_PASSIVE_REQ_T
-       ;;
-
-linux)
-       #
-       # Do we have the wireless extensions?
-       #
-       AC_CHECK_HEADERS(linux/wireless.h, [], [],
-       [
-#include <sys/socket.h>
-#include <linux/if.h>
-#include <linux/types.h>
-       ])
-
-       #
-       # Do we have libnl?
-       #
-       AC_ARG_WITH(libnl,
-       AC_HELP_STRING([--without-libnl],[disable libnl support @<:@default=yes, on Linux, if present@:>@]),
-               with_libnl=$withval,,)
-
-       if test x$with_libnl != xno ; then
-               have_any_nl="no"
-
-               #
-               # Try libnl 3.x first.
-               #
-               AC_CHECK_LIB(nl-3, nl_socket_alloc,
-               [
-                       #
-                       # Yes, we have libnl 3.x.
-                       #
-                       LIBS="-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"
-                       have_any_nl="yes"
-               ])
-
-               if test x$have_any_nl = xno ; then
-                       #
-                       # Try libnl 2.x
-                       #
-                       AC_CHECK_LIB(nl, nl_socket_alloc,
-                       [
-                               #
-                               # Yes, we have libnl 2.x.
-                               #
-                               LIBS="-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])
-                               AC_DEFINE(HAVE_LIBNL_SOCKETS,1,[libnl has new-style socket api])
-                               have_any_nl="yes"
-                       ])
-               fi
-
-               if test x$have_any_nl = xno ; then
-                       #
-                       # No, we don't; do we have libnl 1.x?
-                       #
-                       AC_CHECK_LIB(nl, nl_handle_alloc,
-                       [
-                               #
-                               # Yes.
-                               #
-                               LIBS="-lnl $LIBS"
-                               AC_DEFINE(HAVE_LIBNL,1,[if libnl exists])
-                               have_any_nl="yes"
-                       ])
-               fi
-
-               if test x$have_any_nl = xno ; then
-                       #
-                       # No, we don't have libnl at all.
-                       #
-                       if test x$with_libnl = xyes ; then
-                               AC_MSG_ERROR([libnl support requested but libnl not found])
-                       fi
-               fi
-       fi
-
-       AC_CHECK_HEADERS(linux/ethtool.h,,,
-           [
-AC_INCLUDES_DEFAULT
-#include <linux/types.h>
-           ])
-       AC_LBL_TPACKET_STATS
-       AC_LBL_LINUX_TPACKET_AUXDATA_TP_VLAN_TCI
-       ;;
-
-bpf)
-       #
-       # Check whether we have the *BSD-style ioctls.
-       #
-       AC_CHECK_HEADERS(net/if_media.h)
-
-       AC_MSG_CHECKING(whether the system supports zerocopy BPF)
-       AC_TRY_COMPILE(
-           [#include <sys/socket.h>
-           #include <sys/ioctl.h>
-           #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])
-           ],
-           AC_MSG_RESULT(no))
-
-           #
-           # Check whether we have struct BPF_TIMEVAL.
-           #
-           AC_CHECK_TYPES(struct BPF_TIMEVAL,,,
-               [
-#include <sys/types.h>
-#include <sys/ioctl.h>
-#ifdef HAVE_SYS_IOCCOM_H
-#include <sys/ioccom.h>
-#endif
-#include <net/bpf.h>
-                   ])
-       ;;
-
-dag)
-       V_DEFS="$V_DEFS -DDAG_ONLY"
-       ;;
-
-septel)
-       V_DEFS="$V_DEFS -DSEPTEL_ONLY"
-       ;;
-
-snf)
-       V_DEFS="$V_DEFS -DSNF_ONLY"
-       ;;
-
-null)
-       AC_MSG_WARN(cannot determine packet capture interface)
-       AC_MSG_WARN((see the INSTALL doc for more info))
-       ;;
-esac
-
-dnl
-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
-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>
-               # as well, just in case some platform is really weird.
-               #
-               AC_CHECK_HEADER(ifaddrs.h,[
-                   #
-                   # We have the header, so we use "getifaddrs()" to
-                   # get the list of interfaces.
-                   #
-                   V_FINDALLDEVS=getad
-               ],[
-                   #
-                   # We don't have the header - give up.
-                   # XXX - we could also fall back on some other
-                   # mechanism, but, for now, this'll catch this
-                   # problem so that we can at least try to figure
-                   # out something to do on systems with "getifaddrs()"
-                   # but without "ifaddrs.h", if there is something
-                   # we can do on those systems.
-                   #
-                   AC_MSG_ERROR([Your system has getifaddrs() but doesn't have a usable <ifaddrs.h>.])
-               ])
-       ],[
-               #
-               # Well, we don't have "getifaddrs()", so we have to use
-               # some other mechanism; determine what that mechanism is.
-               #
-               # The first thing we use is the type of capture mechanism,
-               # which is somewhat of a proxy for the OS we're using.
-               #
-               case "$V_PCAP" in
-
-               dlpi|libdlpi)
-                       #
-                       # This might be Solaris 8 or later, with
-                       # SIOCGLIFCONF, or it might be some other OS
-                       # or some older version of Solaris, with
-                       # just SIOCGIFCONF.
-                       #
-                       AC_MSG_CHECKING(whether we have SIOCGLIFCONF)
-                       AC_CACHE_VAL(ac_cv_lbl_have_siocglifconf,
-                           AC_TRY_COMPILE(
-                               [#include <sys/param.h>
-                               #include <sys/file.h>
-                               #include <sys/ioctl.h>
-                               #include <sys/socket.h>
-                               #include <sys/sockio.h>],
-                               [ioctl(0, SIOCGLIFCONF, (char *)0);],
-                               ac_cv_lbl_have_siocglifconf=yes,
-                               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
-                       else
-                               V_FINDALLDEVS=gifc
-                       fi
-                       ;;
-
-               *)
-                       #
-                       # Assume we just have SIOCGIFCONF.
-                       # (XXX - on at least later Linux kernels, there's
-                       # another mechanism, and we should be using that
-                       # instead.)
-                       #
-                       V_FINDALLDEVS=gifc
-                       ;;
-               esac])
-fi
-])
-
-AC_MSG_CHECKING(for socklen_t)
-AC_TRY_COMPILE([
-       #include <sys/types.h>
-       #include <sys/socket.h>
-       ],
-       [ socklen_t x; ],
-       have_socklen_t=yes,
-       have_socklen_t=no)
-if test "x$have_socklen_t" = "xyes"; then
-       AC_DEFINE(HAVE_SOCKLEN_T, 1, [define if socklen_t is defined])
-fi
-AC_MSG_RESULT($have_socklen_t)
-
-AC_ARG_ENABLE(ipv6,
-AC_HELP_STRING([--enable-ipv6],[build IPv6-capable version @<:@default=yes, if getaddrinfo available@:>@]),
-    [],
-    [enable_ipv6=ifavailable])
-if test "$enable_ipv6" != "no"; then
-       AC_CHECK_FUNC(getaddrinfo,
-           [
-               AC_DEFINE(INET6,1,[IPv6])
-           ],
-           [
-               if test "$enable_ipv6" != "ifavailable"; then
-                       AC_MSG_FAILURE([--enable-ipv6 was given, but getaddrinfo isn't available])
-               fi
-           ])
-fi
-
-AC_MSG_CHECKING(whether to build optimizer debugging code)
-AC_ARG_ENABLE(optimizer-dbg,
-AC_HELP_STRING([--enable-optimizer-dbg],[build optimizer debugging code]))
-if test "$enable_optimizer_dbg" = "yes"; then
-       AC_DEFINE(BDEBUG,1,[Enable optimizer debugging])
-fi
-AC_MSG_RESULT(${enable_optimizer_dbg-no})
-
-AC_MSG_CHECKING(whether to build parser debugging code)
-AC_ARG_ENABLE(yydebug,
-AC_HELP_STRING([--enable-yydebug],[build parser debugging code]))
-if test "$enable_yydebug" = "yes"; then
-       AC_DEFINE(YYDEBUG,1,[Enable parser debugging])
-fi
-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@:>@]),
-[
-       if test "$withval" = no
-       then
-               # User doesn't want DAG support.
-               want_dag=no
-       elif test "$withval" = yes
-       then
-               # User wants DAG support but hasn't specified a directory.
-               want_dag=yes
-       else
-               # User wants DAG support and has specified a directory, so use the provided value.
-               want_dag=yes
-               dag_root=$withval
-       fi
-],[
-       #
-       # Use DAG API if present, otherwise don't
-       #
-       want_dag=ifpresent
-])
-
-AC_ARG_WITH([dag-includes],
-AC_HELP_STRING([--with-dag-includes=DIR],[Endace DAG include directory]),
-[
-       # User wants DAG support and has specified a header directory, so use the provided value.
-       want_dag=yes
-       dag_include_dir=$withval
-],[])
-
-AC_ARG_WITH([dag-libraries],
-AC_HELP_STRING([--with-dag-libraries=DIR],[Endace DAG library directory]),
-[
-       # 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
-
-       AC_MSG_CHECKING([whether we have DAG API headers])
-
-       # If necessary, set default paths for DAG API headers and libraries.
-       if test -z "$dag_root"; then
-           dag_root=/usr/local
-       fi
-
-       if test -z "$dag_include_dir"; then
-               dag_include_dir="$dag_root/include"
-       fi
-
-       if test -z "$dag_lib_dir"; then
-           dag_lib_dir="$dag_root/lib"
-       fi
-       
-       if test -z "$dag_tools_dir"; then
-           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 $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
-
-       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_DEFINE(HAVE_DAG_API, 1, [define if you have the DAG API])
-fi
-
-AC_MSG_CHECKING(whether we have the DAG API)
-
-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 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.)])
-       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@:>@]),
-[
-       if test "$withval" = no
-       then
-               want_septel=no
-       elif test "$withval" = yes
-       then
-               want_septel=yes
-               septel_root=
-       else
-               want_septel=yes
-               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
-               want_septel=no
-       fi
-       ;;
-esac
-
-if test "$with_septel" != no; then
-       AC_MSG_CHECKING(whether we have Septel API)
-
-       if test -z "$septel_root"; then
-               septel_root=$srcdir/../septel
-       fi
-
-       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
-               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"
-               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)
-               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@:>@]),
-[
-       if test "$withval" = no
-       then
-               # User explicitly doesn't want SNF
-               want_snf=no
-       elif test "$withval" = yes
-       then
-               # User wants SNF support but hasn't specific a directory.
-               want_snf=yes
-       else
-               # User wants SNF support with a specified directory.
-               want_snf=yes
-               snf_root=$withval
-       fi
-],[
-       #
-       # Use Sniffer API if present, otherwise don't
-       #
-       want_snf=ifpresent
-])
-
-AC_ARG_WITH([snf-includes],
-AC_HELP_STRING([--with-snf-includes=DIR],[Myricom SNF include directory]),
-[
-       # User wants SNF with specific header directory
-       want_snf=yes
-       snf_include_dir=$withval
-],[])
-
-AC_ARG_WITH([snf-libraries],
-AC_HELP_STRING([--with-snf-libraries=DIR],[Myricom SNF library directory]),
-[
-       # 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 test -z "$snf_root"; then
-               snf_root=/opt/snf
-       fi
-
-       if test -z "$snf_include_dir"; then
-               snf_include_dir="$snf_root/include"
-       fi
-
-       if test -z "$snf_lib_dir"; then
-               snf_lib_dir="$snf_root/lib"
-       fi
-
-       if test -f "$snf_include_dir/snf.h"; then
-               ac_cv_lbl_snf_api=yes
-       fi
-       AC_MSG_RESULT([$ac_cv_lbl_snf_api ($snf_root)])
-
-       if test $ac_cv_lbl_snf_api = no; then
-               if test "$want_snf" = yes; then
-                       AC_MSG_ERROR(SNF API headers not found under $snf_include_dir; use --without-snf)
-               fi
-       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"
-
-               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])
-               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)
-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
-fi
-
-#
-# Assume, by default, no support for shared libraries and V7/BSD convention
-# for man pages (file formats in section 5, miscellaneous info in section 7).
-# Individual cases can override this.
-#
-DYEXT="none"
-MAN_FILE_FORMATS=5
-MAN_MISC_INFO=7
-case "$host_os" in
-
-aix*)
-       dnl Workaround to enable certain features
-       AC_DEFINE(_SUN,1,[define on AIX to get certain functions])
-
-       #
-       # AIX makes it fun to build shared and static libraries,
-       # because they're *both* ".a" archive libraries.  We
-       # build the static library for the benefit of the traditional
-       # scheme of building libpcap and tcpdump in subdirectories of
-       # the same directory, with tcpdump statically linked with the
-       # libpcap in question, but we also build a shared library as
-       # "libpcap.shareda" and install *it*, rather than the static
-       # library, as "libpcap.a".
-       #
-       DYEXT="shareda"
-
-       case "$V_PCAP" in
-
-       dlpi)
-               #
-               # If we're using DLPI, applications will need to
-               # use /lib/pse.exp if present, as we use the
-               # STREAMS routines.
-               #
-               pseexe="/lib/pse.exp"
-               AC_MSG_CHECKING(for $pseexe)
-               if test -f $pseexe ; then
-                       AC_MSG_RESULT(yes)
-                       LIBS="-I:$pseexe"
-               fi
-               ;;
-
-       bpf)
-               #
-               # If we're using BPF, we need "-lodm" and "-lcfg", as
-               # we use them to load the BPF module.
-               #
-               LIBS="-lodm -lcfg"
-               ;;
-       esac
-       ;;
-
-darwin*)
-       DYEXT="dylib"
-       V_CCOPT="$V_CCOPT -fno-common"
-       AC_ARG_ENABLE(universal,
-       AC_HELP_STRING([--disable-universal],[don't build universal on OS X]))
-       if test "$enable_universal" != "no"; then
-               case "$host_os" in
-
-               darwin[0-7].*)
-                       #
-                       # Pre-Tiger.  Build only for 32-bit PowerPC; no
-                       # need for any special compiler or linker flags.
-                       #
-                       ;;
-
-               darwin8.[0123]*)
-                       #
-                       # Tiger, prior to Intel support.  Build for 32-bit
-                       # PowerPC and 64-bit PowerPC, with 32-bit PowerPC
-                       # first.  (I'm guessing that's what Apple does.)
-                       #
-                       V_CCOPT="$V_CCOPT -arch ppc -arch ppc64"
-                       LDFLAGS="$LDFLAGS -arch ppc -arch ppc64"
-                       ;;
-
-               darwin8.[456]*)
-                       #
-                       # Tiger, subsequent to Intel support but prior to
-                       # x86-64 support.  Build for 32-bit PowerPC, 64-bit
-                       # PowerPC, and x86, with 32-bit PowerPC first.
-                       # (I'm guessing that's what Apple does.)
-                       #
-                       V_CCOPT="$V_CCOPT -arch ppc -arch ppc64 -arch i386"
-                       LDFLAGS="$LDFLAGS -arch ppc -arch ppc64 -arch i386"
-                       ;;
-
-               darwin8.*)
-                       #
-                       # All other Tiger, so subsequent to x86-64
-                       # support. Build for 32-bit PowerPC, 64-bit
-                       # PowerPC, x86, and x86-64, and with 32-bit PowerPC
-                       # first.  (I'm guessing that's what Apple does.)
-                       #
-                       V_CCOPT="$V_CCOPT -arch ppc -arch ppc64 -arch i386 -arch x86_64"
-                       LDFLAGS="$LDFLAGS -arch ppc -arch ppc64 -arch i386 -arch x86_64"
-                       ;;
-
-               darwin9.*)
-                       #
-                       # Leopard.  Build for 32-bit PowerPC, 64-bit
-                       # PowerPC, x86, and x86-64, with 32-bit PowerPC
-                       # first.  (That's what Apple does.)
-                       #
-                       V_CCOPT="$V_CCOPT -arch ppc -arch ppc64 -arch i386 -arch x86_64"
-                       LDFLAGS="$LDFLAGS -arch ppc -arch ppc64 -arch i386 -arch x86_64"
-                       ;;
-
-               darwin10.*)
-                       #
-                       # Snow Leopard.  Build for x86-64, x86, and
-                       # 32-bit PowerPC, with x86-64 first.  (That's
-                       # what Apple does, even though Snow Leopard
-                       # doesn't run on PPC, so PPC libpcap runs under
-                       # Rosetta, and Rosetta doesn't support BPF
-                       # ioctls, so PPC programs can't do live
-                       # captures.)
-                       #
-                       V_CCOPT="$V_CCOPT -arch x86_64 -arch i386 -arch ppc"
-                       LDFLAGS="$LDFLAGS -arch x86_64 -arch i386 -arch ppc"
-                       ;;
-
-               darwin*)
-                       #
-                       # Post-Snow Leopard.  Build for x86-64 and
-                       # x86, with x86-64 first.  (That's probably what
-                       # Apple does, given that Rosetta is gone.)
-                       # XXX - update if and when Apple drops support
-                       # for 32-bit x86 code.
-                       #
-                       V_CCOPT="$V_CCOPT -arch x86_64 -arch i386"
-                       LDFLAGS="$LDFLAGS -arch x86_64 -arch i386"
-                       ;;
-               esac
-       fi
-       ;;
-
-hpux9*)
-       AC_DEFINE(HAVE_HPUX9,1,[on HP-UX 9.x])
-
-       #
-       # Use System V conventions for man pages.
-       #
-       MAN_FILE_FORMATS=4
-       MAN_MISC_INFO=5
-       ;;
-
-hpux10.0*)
-
-       #
-       # Use System V conventions for man pages.
-       #
-       MAN_FILE_FORMATS=4
-       MAN_MISC_INFO=5
-       ;;
-
-hpux10.1*)
-
-       #
-       # Use System V conventions for man pages.
-       #
-       MAN_FILE_FORMATS=4
-       MAN_MISC_INFO=5
-       ;;
-
-hpux*)
-       dnl HPUX 10.20 and above is similar to HPUX 9, but
-       dnl not the same....
-       dnl
-       dnl XXX - DYEXT should be set to "sl" if this is building
-       dnl for 32-bit PA-RISC, but should be left as "so" for
-       dnl 64-bit PA-RISC or, I suspect, IA-64.
-       AC_DEFINE(HAVE_HPUX10_20_OR_LATER,1,[on HP-UX 10.20 or later])
-       if test "`uname -m`" = "ia64"; then
-               DYEXT="so"
-       else
-               DYEXT="sl"
-       fi
-
-       #
-       # "-b" builds a shared library; "+h" sets the soname.
-       #
-       SHLIB_OPT="-b"
-       SONAME_OPT="+h"
-
-       #
-       # Use System V conventions for man pages.
-       #
-       MAN_FILE_FORMATS=4
-       MAN_MISC_INFO=5
-       ;;
-
-irix*)
-       #
-       # Use System V conventions for man pages.
-       #
-       MAN_FILE_FORMATS=4
-       MAN_MISC_INFO=5
-       ;;
-
-linux*|freebsd*|netbsd*|openbsd*|dragonfly*|kfreebsd*|gnu*)
-       DYEXT="so"
-
-       #
-       # Compiler assumed to be GCC; run-time linker may require a -R
-       # flag.
-       #
-       if test "$libdir" != "/usr/lib"; then
-               V_RFLAGS=-Wl,-R$libdir
-       fi
-       ;;
-
-osf*)
-       DYEXT="so"
-
-       #
-       # Use System V conventions for man pages.
-       #
-       MAN_FILE_FORMATS=4
-       MAN_MISC_INFO=5
-       ;;
-
-sinix*)
-       AC_MSG_CHECKING(if SINIX compiler defines sinix)
-       AC_CACHE_VAL(ac_cv_cc_sinix_defined,
-               AC_TRY_COMPILE(
-                   [],
-                   [int i = sinix;],
-                   ac_cv_cc_sinix_defined=yes,
-                   ac_cv_cc_sinix_defined=no))
-           AC_MSG_RESULT($ac_cv_cc_sinix_defined)
-           if test $ac_cv_cc_sinix_defined = no ; then
-                   AC_DEFINE(sinix,1,[on sinix])
-           fi
-       ;;
-
-solaris*)
-       AC_DEFINE(HAVE_SOLARIS,1,[On solaris])
-
-       DYEXT="so"
-       #
-       # Use System V conventions for man pages.
-       #
-       MAN_FILE_FORMATS=4
-       MAN_MISC_INFO=5
-       ;;
-esac
-
-AC_ARG_ENABLE(shared,
-AC_HELP_STRING([--enable-shared],[build shared libraries @<:@default=yes, if support available@:>@]))
-test "x$enable_shared" = "xno" && DYEXT="none"
-
-AC_PROG_RANLIB
-AC_CHECK_TOOL([AR], [ar])
-
-AC_PROG_LN_S
-AC_SUBST(LN_S)
-
-AC_LBL_DEVEL(V_CCOPT)
-
-AC_LBL_SOCKADDR_SA_LEN
-
-AC_LBL_SOCKADDR_STORAGE
-
-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
-
-AC_SUBST(V_CCOPT)
-AC_SUBST(V_DEFS)
-AC_SUBST(V_FINDALLDEVS)
-AC_SUBST(V_INCLS)
-AC_SUBST(V_LEX)
-AC_SUBST(V_PCAP)
-AC_SUBST(V_SHLIB_CMD)
-AC_SUBST(V_SHLIB_OPT)
-AC_SUBST(V_SONAME_OPT)
-AC_SUBST(V_RPATH_OPT)
-AC_SUBST(V_YACC)
-AC_SUBST(ADDLOBJS)
-AC_SUBST(ADDLARCHIVEOBJS)
-AC_SUBST(SSRC)
-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_DEFINE(PCAP_SUPPORT_USB, 1, [target host supports USB sniffing])
-       USB_SRC=pcap-usb-linux.c
-       AC_MSG_RESULT(yes)
-       ac_usb_dev_name=`udevinfo -q name -p /sys/class/usb_device/usbmon 2>/dev/null`
-       if test $? -ne 0 ; then
-         ac_usb_dev_name="usbmon"
-       fi
-       AC_DEFINE_UNQUOTED(LINUX_USB_MON_DEV, "/dev/$ac_usb_dev_name", [path for device for USB sniffing])
-       AC_MSG_NOTICE(Device for USB sniffing is /dev/$ac_usb_dev_name)
-       #
-       # Do we have a version of <linux/compiler.h> available?
-       # If so, we might need it for <linux/usbdevice_fs.h>.
-       #
-       AC_CHECK_HEADERS(linux/compiler.h)
-       if test "$ac_cv_header_linux_compiler_h" = yes; then
-         #
-         # Yes - include it when testing for <linux/usbdevice_fs.h>.
-         #
-         AC_CHECK_HEADERS(linux/usbdevice_fs.h,,,[#include <linux/compiler.h>])
-       else
-         AC_CHECK_HEADERS(linux/usbdevice_fs.h)
-       fi
-       if test "$ac_cv_header_linux_usbdevice_fs_h" = yes; then
-         #
-         # OK, does it define bRequestType?  Older versions of the kernel
-         # define fields with names like "requesttype, "request", and
-         # "value", rather than "bRequestType", "bRequest", and
-         # "wValue".
-         #
-         AC_MSG_CHECKING(if usbdevfs_ctrltransfer struct has bRequestType member)
-         AC_CACHE_VAL(ac_cv_usbdevfs_ctrltransfer_has_bRequestType,
-           AC_TRY_COMPILE([
-AC_INCLUDES_DEFAULT
-#ifdef HAVE_SYS_BITYPES_H
-#include <sys/bitypes.h>
-#endif
-#ifdef HAVE_LINUX_COMPILER_H
-#include <linux/compiler.h>
-#endif
-#include <linux/usbdevice_fs.h>],
-             [u_int i = sizeof(((struct usbdevfs_ctrltransfer *)0)->bRequestType)],
-             ac_cv_usbdevfs_ctrltransfer_has_bRequestType=yes,
-             ac_cv_usbdevfs_ctrltransfer_has_bRequestType=no))
-           AC_MSG_RESULT($ac_cv_usbdevfs_ctrltransfer_has_bRequestType)
-           if test $ac_cv_usbdevfs_ctrltransfer_has_bRequestType = yes ; then
-             AC_DEFINE(HAVE_USBDEVFS_CTRLTRANSFER_BREQUESTTYPE,1,
-               [if struct usbdevfs_ctrltransfer has bRequestType])
-           fi
-       fi
-       ;;
-*)
-       AC_MSG_RESULT(no)
-       ;;
-esac
-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([
-AC_INCLUDES_DEFAULT
-#include <sys/socket.h>
-#include <netinet/in.h>
-#include <linux/types.h>
-
-#include <linux/netlink.h>
-#include <linux/netfilter.h>
-#include <linux/netfilter/nfnetlink.h>
-#include <linux/netfilter/nfnetlink_log.h>
-#include <linux/netfilter/nfnetlink_queue.h>],
-           [],
-           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_SUBST(PCAP_SUPPORT_NETFILTER)
-AC_SUBST(NETFILTER_SRC)
-
-AC_ARG_ENABLE([bluetooth],
-[AC_HELP_STRING([--enable-bluetooth],[enable Bluetooth support @<:@default=yes, if support available@:>@])],
-    [],
-    [enable_bluetooth=ifsupportavailable])
-
-if test "x$enable_bluetooth" != "xno" ; then
-       dnl check for Bluetooth sniffing support
-       case "$host_os" in
-       linux*)
-               AC_CHECK_HEADER(bluetooth/bluetooth.h,
-               [
-                 AC_DEFINE(PCAP_SUPPORT_BT, 1, [target host supports Bluetooth sniffing])
-                 BT_SRC=pcap-bt-linux.c
-                 AC_MSG_NOTICE(Bluetooth sniffing is supported)
-
-                 #
-                 # OK, does struct sockaddr_hci have an hci_channel
-                 # member?
-                 #
-                 AC_MSG_CHECKING(if struct sockaddr_hci has hci_channel member)
-                 AC_CACHE_VAL(ac_cv_lbl_sockaddr_hci_has_hci_channel,
-                   AC_TRY_COMPILE(
-[
-#include <bluetooth/bluetooth.h>
-#include <bluetooth/hci.h>
-],
-                     [u_int i = sizeof(((struct sockaddr_hci *)0)->hci_channel)],
-                     ac_cv_lbl_sockaddr_hci_has_hci_channel=yes,
-                     ac_cv_lbl_sockaddr_hci_has_hci_channel=no))
-                   AC_MSG_RESULT($ac_cv_lbl_sockaddr_hci_has_hci_channel)
-                   if test $ac_cv_lbl_sockaddr_hci_has_hci_channel = yes ; then
-                     AC_DEFINE(SOCKADDR_HCI_HAS_HCI_CHANNEL,,
-                       [if struct sockaddr_hci has hci_channel member])
-
-                     #
-                     # OK, is HCI_CHANNEL_MONITOR defined?
-                     #
-                     AC_MSG_CHECKING(if HCI_CHANNEL_MONITOR is defined)
-                     AC_CACHE_VAL(ac_cv_lbl_hci_channel_monitor_is_defined,
-                     AC_TRY_COMPILE(
-[
-#include <bluetooth/bluetooth.h>
-#include <bluetooth/hci.h>
-],
-                       [u_int i = HCI_CHANNEL_MONITOR],
-                       ac_cv_lbl_hci_channel_monitor_is_defined=yes,
-                       ac_cv_lbl_hci_channel_monitor_is_defined=no))
-                     AC_MSG_RESULT($ac_cv_lbl_hci_channel_monitor_is_defined)
-                     if test $ac_cv_lbl_hci_channel_monitor_is_defined = yes ; then
-                       AC_DEFINE(PCAP_SUPPORT_BT_MONITOR,,
-                         [target host supports Bluetooth Monitor])
-                       BT_MONITOR_SRC=pcap-bt-monitor-linux.c
-                     fi
-                   fi
-                   ac_lbl_bluetooth_available=yes
-               ],
-               ac_lbl_bluetooth_available=no
-               )
-               if test "x$ac_lbl_bluetooth_available" == "xno" ; then
-                   if test "x$enable_bluetooth" = "xyes" ; then
-                       AC_MSG_ERROR(Bluetooth sniffing is not supported; install bluez-lib devel to enable it)
-                   else
-                       AC_MSG_NOTICE(Bluetooth sniffing is not supported; install bluez-lib devel to enable it)
-                   fi
-               fi
-               ;;
-       *)
-               if test "x$enable_bluetooth" = "xyes" ; then
-                   AC_MSG_ERROR(no Bluetooth sniffing support implemented for $host_os)
-               else
-                   AC_MSG_NOTICE(no Bluetooth sniffing support implemented for $host_os)
-               fi
-               ;;
-       esac
-       AC_SUBST(PCAP_SUPPORT_BT)
-       AC_SUBST(BT_SRC)
-       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 "x$enable_dbus" != "xno"; then
-       if test "x$enable_dbus" = "xyes"; then
-               case "$host_os" in
-
-               darwin*)
-                       #
-                       # https://bugs.freedesktop.org/show_bug.cgi?id=74029
-                       #
-                       AC_MSG_ERROR([Due to freedesktop.org bug 74029, D-Bus capture support is not available on OS X])
-                       ;;
-               esac
-       else            
-               case "$host_os" in
-
-               darwin*)
-                       #
-                       # https://bugs.freedesktop.org/show_bug.cgi?id=74029
-                       #
-                       ;;
-
-               *)
-                       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
-                               fi
-                       fi
-                       ;;      
-               esac
-       fi
-       AC_SUBST(PCAP_SUPPORT_DBUS)
-       AC_SUBST(DBUS_SRC)
-fi
-
-dnl check for hardware timestamp support
-case "$host_os" in
-linux*)
-       AC_CHECK_HEADERS([linux/net_tstamp.h])
-       ;;
-*)
-       AC_MSG_NOTICE(no hardware timestamp support implemented for $host_os)
-       ;;
-esac
-
-AC_PROG_INSTALL
-
-AC_CONFIG_HEADER(config.h)
-
-AC_OUTPUT_COMMANDS([if test -f .devel; then
-       echo timestamp > stamp-h
-       cat Makefile-devel-adds >> Makefile
-       make depend
-fi])
-AC_OUTPUT(Makefile pcap-filter.manmisc pcap-linktype.manmisc
-       pcap-tstamp.manmisc pcap-savefile.manfile pcap.3pcap
-       pcap_compile.3pcap pcap_datalink.3pcap pcap_dump_open.3pcap
-       pcap_get_tstamp_precision.3pcap pcap_list_datalinks.3pcap
-       pcap_list_tstamp_types.3pcap pcap_open_dead.3pcap
-       pcap_open_offline.3pcap pcap_set_tstamp_precision.3pcap
-       pcap_set_tstamp_type.3pcap)
-exit 0
diff --git a/diag-control.h b/diag-control.h
new file mode 100644 (file)
index 0000000..cfc581b
--- /dev/null
@@ -0,0 +1,219 @@
+/* -*- 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 _diag_control_h
+#define _diag_control_h
+
+#include "pcap/compiler-tests.h"
+
+#ifndef _MSC_VER
+  /*
+   * Clang and GCC both support this way of putting pragmas into #defines.
+   * We don't use it unless we have a compiler that supports it; the
+   * warning-suppressing pragmas differ between Clang and GCC, so we test
+   * for both of those separately.
+   */
+  #define PCAP_DO_PRAGMA(x) _Pragma (#x)
+#endif
+
+/*
+ * Suppress Flex warnings.
+ */
+#if defined(_MSC_VER)
+  /*
+   * This is Microsoft Visual Studio; we can use __pragma(warning(disable:XXXX))
+   * and __pragma(warning(push/pop)).
+   *
+   * Suppress signed-vs-unsigned comparison, narrowing, and unreachable
+   * code warnings.
+   */
+  #define DIAG_OFF_FLEX \
+    __pragma(warning(push)) \
+    __pragma(warning(disable:4127)) \
+    __pragma(warning(disable:4242)) \
+    __pragma(warning(disable:4244)) \
+    __pragma(warning(disable:4702))
+  #define DIAG_ON_FLEX  __pragma(warning(pop))
+#elif PCAP_IS_AT_LEAST_CLANG_VERSION(2,8)
+  /*
+   * This is Clang 2.8 or later; we can use "clang diagnostic
+   * ignored -Wxxx" and "clang diagnostic push/pop".
+   *
+   * Suppress -Wdocumentation warnings; GCC doesn't support -Wdocumentation,
+   * at least according to the GCC 7.3 documentation.  Apparently, Flex
+   * generates code that upsets at least some versions of Clang's
+   * -Wdocumentation.
+   */
+  #define DIAG_OFF_FLEX \
+    PCAP_DO_PRAGMA(clang diagnostic push) \
+    PCAP_DO_PRAGMA(clang diagnostic ignored "-Wsign-compare") \
+    PCAP_DO_PRAGMA(clang diagnostic ignored "-Wdocumentation") \
+    PCAP_DO_PRAGMA(clang diagnostic ignored "-Wmissing-noreturn") \
+    PCAP_DO_PRAGMA(clang diagnostic ignored "-Wunused-parameter") \
+    PCAP_DO_PRAGMA(clang diagnostic ignored "-Wunreachable-code")
+  #define DIAG_ON_FLEX \
+    PCAP_DO_PRAGMA(clang diagnostic pop)
+#elif PCAP_IS_AT_LEAST_GNUC_VERSION(4,6)
+  /*
+   * This is GCC 4.6 or later, or a compiler claiming to be that.
+   * We can use "GCC diagnostic ignored -Wxxx" (introduced in 4.2)
+   * and "GCC diagnostic push/pop" (introduced in 4.6).
+   */
+  #define DIAG_OFF_FLEX \
+    PCAP_DO_PRAGMA(GCC diagnostic push) \
+    PCAP_DO_PRAGMA(GCC diagnostic ignored "-Wsign-compare") \
+    PCAP_DO_PRAGMA(GCC diagnostic ignored "-Wunused-parameter") \
+    PCAP_DO_PRAGMA(GCC diagnostic ignored "-Wunreachable-code")
+  #define DIAG_ON_FLEX \
+    PCAP_DO_PRAGMA(GCC diagnostic pop)
+#else
+  /*
+   * Neither Visual Studio, nor Clang 2.8 or later, nor GCC 4.6 or later
+   * or a compiler claiming to be that; there's nothing we know of that
+   * we can do.
+   */
+  #define DIAG_OFF_FLEX
+  #define DIAG_ON_FLEX
+#endif
+
+#ifdef YYBYACC
+  /*
+   * Berkeley YACC.
+   *
+   * It generates a global declaration of yylval, or the appropriately
+   * prefixed version of yylval, in grammar.h, *even though it's been
+   * told to generate a pure parser, meaning it doesn't have any global
+   * variables*.  Bison doesn't do this.
+   *
+   * That causes a warning due to the local declaration in the parser
+   * shadowing the global declaration.
+   *
+   * So, if the compiler warns about that, we turn off -Wshadow warnings.
+   *
+   * In addition, the generated code may have functions with unreachable
+   * code, so suppress warnings about those.
+   */
+  #if defined(_MSC_VER)
+    /*
+     * This is Microsoft Visual Studio; we can use
+     * __pragma(warning(disable:XXXX)) and __pragma(warning(push/pop)).
+     */
+    #define DIAG_OFF_BISON_BYACC \
+      __pragma(warning(push)) \
+      __pragma(warning(disable:4702))
+    #define DIAG_ON_BISON_BYACC  __pragma(warning(pop))
+  #elif PCAP_IS_AT_LEAST_CLANG_VERSION(2,8)
+    /*
+     * This is Clang 2.8 or later; we can use "clang diagnostic
+     * ignored -Wxxx" and "clang diagnostic push/pop".
+     */
+    #define DIAG_OFF_BISON_BYACC \
+      PCAP_DO_PRAGMA(clang diagnostic push) \
+      PCAP_DO_PRAGMA(clang diagnostic ignored "-Wshadow") \
+      PCAP_DO_PRAGMA(clang diagnostic ignored "-Wunreachable-code")
+    #define DIAG_ON_BISON_BYACC \
+      PCAP_DO_PRAGMA(clang diagnostic pop)
+  #elif PCAP_IS_AT_LEAST_GNUC_VERSION(4,6)
+    /*
+     * This is GCC 4.6 or later, or a compiler claiming to be that.
+     * We can use "GCC diagnostic ignored -Wxxx" (introduced in 4.2)
+     * and "GCC diagnostic push/pop" (introduced in 4.6).
+     */
+    #define DIAG_OFF_BISON_BYACC \
+      PCAP_DO_PRAGMA(GCC diagnostic push) \
+      PCAP_DO_PRAGMA(GCC diagnostic ignored "-Wshadow") \
+      PCAP_DO_PRAGMA(GCC diagnostic ignored "-Wunreachable-code")
+    #define DIAG_ON_BISON_BYACC \
+      PCAP_DO_PRAGMA(GCC diagnostic pop)
+  #else
+    /*
+     * Neither Clang 2.8 or later nor GCC 4.6 or later or a compiler
+     * claiming to be that; there's nothing we know of that we can do.
+     */
+    #define DIAG_OFF_BISON_BYACC
+    #define DIAG_ON_BISON_BYACC
+  #endif
+#else
+  /*
+   * Bison.
+   *
+   * The generated code may have functions with unreachable code, so
+   * suppress warnings about those.
+   */
+  #if defined(_MSC_VER)
+    /*
+     * This is Microsoft Visual Studio; we can use
+     * __pragma(warning(disable:XXXX)) and __pragma(warning(push/pop)).
+     *
+     * Suppress some /Wall warnings.
+     */
+    #define DIAG_OFF_BISON_BYACC \
+      __pragma(warning(push)) \
+      __pragma(warning(disable:4127)) \
+      __pragma(warning(disable:4242)) \
+      __pragma(warning(disable:4244)) \
+      __pragma(warning(disable:4702))
+    #define DIAG_ON_BISON_BYACC  __pragma(warning(pop))
+  #elif PCAP_IS_AT_LEAST_CLANG_VERSION(2,8)
+    /*
+     * This is Clang 2.8 or later; we can use "clang diagnostic
+     * ignored -Wxxx" and "clang diagnostic push/pop".
+     */
+    #define DIAG_OFF_BISON_BYACC \
+      PCAP_DO_PRAGMA(clang diagnostic push) \
+      PCAP_DO_PRAGMA(clang diagnostic ignored "-Wunreachable-code")
+    #define DIAG_ON_BISON_BYACC \
+      PCAP_DO_PRAGMA(clang diagnostic pop)
+  #elif PCAP_IS_AT_LEAST_GNUC_VERSION(4,6)
+    /*
+     * This is GCC 4.6 or later, or a compiler claiming to be that.
+     * We can use "GCC diagnostic ignored -Wxxx" (introduced in 4.2)
+     * and "GCC diagnostic push/pop" (introduced in 4.6).
+     */
+    #define DIAG_OFF_BISON_BYACC \
+      PCAP_DO_PRAGMA(GCC diagnostic push) \
+      PCAP_DO_PRAGMA(GCC diagnostic ignored "-Wunreachable-code")
+    #define DIAG_ON_BISON_BYACC \
+      PCAP_DO_PRAGMA(GCC diagnostic pop)
+  #else
+    /*
+     * Neither Clang 2.8 or later nor GCC 4.6 or later or a compiler
+     * claiming to be that; there's nothing we know of that we can do.
+     */
+    #define DIAG_OFF_BISON_BYACC
+    #define DIAG_ON_BISON_BYACC
+  #endif
+#endif
+
+#endif /* _diag_control_h */
index 131fa27..5f6e41a 100644 (file)
@@ -12,7 +12,7 @@
  */
 
 #ifdef HAVE_CONFIG_H
-#include "config.h"
+#include <config.h>
 #endif
 
 #ifndef DL_IPATM
@@ -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,38 @@ 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:
+               /*
+                * XXX - DL_IPNET devices default to "raw IP" rather than
+                * "IPNET header"; see
+                *
+                *    http://seclists.org/tcpdump/2009/q1/202
+                *
+                * We'd have to do DL_IOC_IPNET_INFO to enable getting
+                * the IPNET header.
+                */
+               p->linktype = DLT_RAW;
+               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,9 +356,10 @@ 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);
+               pcap_fmt_errmsg_for_errno(p->errbuf, PCAP_ERRBUF_SIZE,
+                   errno, "malloc");
                return (-1);
        }
 
@@ -362,6 +393,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_fmt_errmsg_for_errno(errbuf, PCAP_ERRBUF_SIZE, err, "%s", func);
 }
 #endif
diff --git a/doc/DLT_ALLOCATE_HOWTO.md b/doc/DLT_ALLOCATE_HOWTO.md
new file mode 100644 (file)
index 0000000..ff77128
--- /dev/null
@@ -0,0 +1,29 @@
+DLT and LINKTYPE allocation
+===========================
+
+DLT_ types live in pcap/dlt.h.  They can be requested by the community on a
+First-Come First-Served basis [i.e. https://tools.ietf.org/html/rfc8126#section-4.4 ]
+(Although libpcap is not at this time an IETF specification, there have been
+some as yet-incomplete efforts to do this).
+
+The Tcpdump Group prefers to link to an open specification on the new DLT_
+type,  but they are available for closed, proprietary projects as well.
+In that case, a stable email address suffices so that someone who finds
+an unknown DLT_ type can investigate.
+We prefer to give out unambiguous numbers, and we try to do it as quickly
+as possible, but DLT_USERx is available while you wait.
+
+Note that DLT_ types are, in theory, private to the capture mechanism and can
+in some cases be operating system specific, and so a second set of values,
+LINKTYPE_ is allocated for actually writing to pcap files.  As much as
+possible going forward, the DLT_ and LINKTYPE_ value are identical, however,
+this was not always the case.  See pcap-common.c.
+
+The LINKTYPE_ values are not exported, but are in pcap-common.c only.
+
+DEVELOPER NOTES
+---------------
+
+When allocating a new DLT_ value, a corresponding value needs to be
+added to pcap-common.c.
+It is not necessary to copy the comments from dlt.h to pcap-common.c.
diff --git a/doc/README.Win32.md b/doc/README.Win32.md
new file mode 100644 (file)
index 0000000..8de25c8
--- /dev/null
@@ -0,0 +1,3 @@
+Win32 used to build with Visual Studio 6, but we now use cmake.
+
+This file needs to be adopted by a windows expert developer.
similarity index 99%
rename from README.aix
rename to doc/README.aix
index f457df3..92e513f 100644 (file)
@@ -76,8 +76,8 @@ If you use DLPI:
     Then you need to type:
 
            strload -f /etc/dlpi.conf
-    Check again with strload -q -d dlpi that the dlpi driver is loaded.  
+
+    Check again with strload -q -d dlpi that the dlpi driver is loaded.
 
     Alternatively, you can uncomment the lines for DLPI in
     /etc/pse.conf and reboot the machine; this way DLPI will always
similarity index 97%
rename from README.dag
rename to doc/README.dag
index accae7c..7ea2504 100644 (file)
@@ -5,7 +5,7 @@ Endace (http://www.endace.com, see below for further contact details).
 
 1) Install and build the DAG software distribution by following the
 instructions supplied with that package. Current Endace customers can download
-the DAG software distibution from https://www.endace.com
+the DAG software distribution from https://www.endace.com
 
 2) Configure libcap. To allow the 'configure' script to locate the DAG
 software distribution use the '--with-dag' option:
@@ -88,7 +88,7 @@ as separate interfaces, e.g. dag0:0, dag0:2, dag0:4 etc. dag0:0 is the same
 as dag0. These are visible via pcap_findalldevs().
 
 libpcap now does NOT set the card's hardware snaplen (slen). This must now be
-set using the appropriate DAG coniguration program, e.g. dagthree, dagfour,
+set using the appropriate DAG configuration program, e.g. dagthree, dagfour,
 dagsix, dagconfig. This is because the snaplen is currently shared between
 all of the streams. In future this may change if per-stream slen is
 implemented.
similarity index 96%
rename from README.hpux
rename to doc/README.hpux
index 88c27f8..65ecff9 100644 (file)
@@ -5,14 +5,14 @@ HP-UX and cannot upgrade, please continue reading.
 HP-UX patches to fix packet capture problems
 
 Note that packet-capture programs such as tcpdump may, on HP-UX, not be
-able to see packets sent from the machine on which they're running. 
+able to see packets sent from the machine on which they're running.
 Some articles on groups.google.com discussing this are:
 
        http://groups.google.com/groups?selm=82ld3v%2480i%241%40mamenchi.zrz.TU-Berlin.DE
 
 which says:
 
-  Newsgroups: comp.sys.hp.hpux 
+  Newsgroups: comp.sys.hp.hpux
   Subject:  Re: Did someone made tcpdump working on 10.20 ?
   Date: 12/08/1999
   From: Lutz Jaenicke <jaenicke@emserv1.ee.TU-Berlin.DE>
@@ -27,14 +27,14 @@ which says:
    >must me "patched" (poked) in order to see outbound data in promiscuous mode.
    >Many things to do .... So the question is : did someone has already this
    >"ready to use" PHNE_**** patch ?
-  
+
    Two things:
    1. You do need a late "LAN products cumulative patch" (e.g.  PHNE_18173
   for   s700/10.20).
    2. You must use
 echo 'lanc_outbound_promisc_flag/W1' | /usr/bin/adb -w /stand/vmunix /dev/kmem
      You can insert this e.g. into /sbin/init.d/lan
-  
+
    Best regards,
    Lutz
 
@@ -44,7 +44,7 @@ and
 
 which says:
 
-  Newsgroups: comp.sys.hp.hpux 
+  Newsgroups: comp.sys.hp.hpux
   Subject: Re: tcpdump only shows incoming packets
   Date: 02/15/2000
   From: Rick Jones <foo@bar.baz.invalid>
@@ -56,12 +56,12 @@ which says:
   > outgoing. I have tried tcpflow-0.12 which also uses libpcap and the
   > same thing happens.  Could someone please give me a hint on how to
   > get this right?
-  
+
   Search/Read the archives ?-)
-  
+
   What you are seeing is expected, un-patched, behaviour for an HP-UX
   system.  On 11.00, you need to install the latest lancommon/DLPI
-  patches, and then the latest driver patch for the interface(s) in use. 
+  patches, and then the latest driver patch for the interface(s) in use.
   At that point, a miracle happens and you should start seeing outbound
   traffic.
 
@@ -79,7 +79,7 @@ which says:
   From: Harald Skotnes <harald@cc.uit.no>
 
   Rick Jones wrote:
-  
+
        ...
 
   > What you are seeing is expected, un-patched, behaviour for an HP-UX
@@ -87,7 +87,7 @@ which says:
   > patches, and then the latest driver patch for the interface(s) in
   > use. At that point, a miracle happens and you should start seeing
   > outbound traffic.
-  
+
   Thanks a lot.  I have this problem on several machines running HPUX
   10.20 and 11.00.  The machines where patched up before y2k so did not
   know what to think.  Anyway I have now installed PHNE_19766,
@@ -101,7 +101,7 @@ And another message to tcpdump-workers@tcpdump.org, from Rick Jones:
 
   Date: Mon, 29 Apr 2002 15:59:55 -0700
   From: Rick Jones
-  To: tcpdump-workers@tcpdump.org 
+  To: tcpdump-workers@tcpdump.org
   Subject: Re: [tcpdump-workers] I Can't Capture the Outbound Traffic
 
        ...
@@ -130,21 +130,21 @@ captures on HP-UX 9.x:
 
   Dave Barr (barr@cis.ohio-state.edu) wrote:
   : Has anyone ported tcpdump (or something similar) to HP/UX 9.x?
-  
+
   I'm reasonably confident that any port of tcpdump to 9.X would require
   the (then optional) STREAMS product.  This would bring DLPI, which is
   what one uses to access interfaces in promiscuous mode.
-  
+
   I'm not sure that HP even sells the 9.X STREAMS product any longer,
   since HP-UX 9.X is off the pricelist (well, maybe 9.10 for the old 68K
-  devices). 
-  
+  devices).
+
   Your best bet is to be up on 10.20 or better if that is at all
-  possible.  If your hardware is supported by it, I'd go with HP-UX 11. 
+  possible.  If your hardware is supported by it, I'd go with HP-UX 11.
   If you want to see the system's own outbound traffic, you'll never get
   that functionality on 9.X, but it might happen at some point for 10.20
-  and 11.X. 
-  
+  and 11.X.
+
   rick jones
 
 (as per other messages cited here, the ability to see the system's own
@@ -178,12 +178,12 @@ An additional note, from Jost Martin, for HP-UX 10.20:
        (thanks to hildeb@www.stahl.bau.tu-bs.de (Ralf Hildebrandt) who
        posted the security-part some time ago)
 
-                <<hack_ip_stack>> 
+                <<hack_ip_stack>>
 
                (Don't switch IP-forwarding off, if you need it !)
                Install the hack as /sbin/init.d/hacl_ip_stack (adjust
        permissions !) and make a sequencing-symlink
-       /sbin/rc2.d/S350hack_ip_stack pointing to this script. 
+       /sbin/rc2.d/S350hack_ip_stack pointing to this script.
                Now all this is done on every reboot.
 
 According to Rick Jones, the global promiscuous switch also has to be
similarity index 97%
rename from README.linux
rename to doc/README.linux.md
index f92cd22..ddca4fe 100644 (file)
@@ -19,13 +19,13 @@ the 2.0[.x] kernel:
          The Packet protocol is used by applications which communicate
          directly with network devices without an intermediate network
          protocol implemented in the kernel, e.g. tcpdump. If you want them
-         to work, choose Y. 
+         to work, choose Y.
 
          This driver is also available as a module called af_packet.o ( =
          code which can be inserted in and removed from the running kernel
          whenever you want). If you want to compile it as a module, say M
          here and read Documentation/modules.txt; if you use modprobe or
-         kmod, you may also want to add "alias net-pf-17 af_packet" to 
+         kmod, you may also want to add "alias net-pf-17 af_packet" to
          /etc/modules.conf.
 
 and the note for the 2.2[.x] kernel says:
@@ -47,7 +47,7 @@ In addition, there is an option that, in 2.2 and later kernels, will
 allow packet capture filters specified to programs such as tcpdump to be
 executed in the kernel, so that packets that don't pass the filter won't
 be copied from the kernel to the program, rather than having all packets
-copied to the program and libpcap doing the filtering in user mode. 
+copied to the program and libpcap doing the filtering in user mode.
 
 Copying packets from the kernel to the program consumes a significant
 amount of CPU, so filtering in the kernel can reduce the overhead of
@@ -97,9 +97,9 @@ reported by pcap_stats on Linux are as follows:
 2.2.x
 =====
 ps_recv   Number of packets that were accepted by the pcap filter
-ps_drop   Always 0, this statistic is not gatherd on this platform
+ps_drop   Always 0, this statistic is not gathered on this platform
 
-2.4.x
+2.4.x and later
 =====
 ps_recv   Number of packets that were accepted by the pcap filter
 ps_drop   Number of packets that had passed filtering but were not
similarity index 86%
rename from README.macosx
rename to doc/README.macos
index 3dc9211..3cceb23 100644 (file)
@@ -1,5 +1,5 @@
-As with other systems using BPF, Mac OS X allows users with read access
-to the BPF devices to capture packets with libpcap and allows users with
+As with other systems using BPF, macOS allows users with read access to
+the BPF devices to capture packets with libpcap and allows users with
 write access to the BPF devices to send packets with libpcap.
 
 On some systems that use BPF, the BPF devices live on the root file
@@ -12,16 +12,16 @@ can be configured to set the permissions and/or ownership of those
 devices to give users other than root permission to read or write those
 devices.
 
-On Mac OS X, the BPF devices live on devfs, but the OS X version of
-devfs is based on an older (non-default) FreeBSD devfs, and that version
-of devfs cannot be configured to set the permissions and/or ownership of
+On macOS, the BPF devices live on devfs, but the macOS version of devfs
+is based on an older (non-default) FreeBSD devfs, and that version of
+devfs cannot be configured to set the permissions and/or ownership of
 those devices.
 
 Therefore, we supply:
 
-       a "startup item" for older versions of Mac OS X;
+       a "startup item" for older versions of macOS;
 
-       a launchd daemon for Tiger and later versions of Mac OS X;
+       a launchd daemon for Tiger and later versions of macOS;
 
 Both of them will change the ownership of the BPF devices so that the
 "admin" group owns them, and will change the permission of the BPF
similarity index 95%
rename from README.septel
rename to doc/README.septel
index fbc88df..fa2c0c9 100644 (file)
@@ -14,7 +14,7 @@ where DIR is the root of the Septel software distribution, for example
 /var/src/septel.
 
 By default (if you write only ./configure --with-septel) it takes
-./../septel as argument for DIR. 
+./../septel as argument for DIR.
 
 If the Septel software is correctly detected 'configure' will
 report:
@@ -40,7 +40,7 @@ cards and will not capture from the native OS packet stream.
 
 Note: As mentioned in pcap-septel.c we should first edit the system.txt
 file to change the user part example (UPE) module id to 0xdd instead of
-0x2d for technical reason.  So this change in system.txt is crutial and
+0x2d for technical reason.  So this change in system.txt is crucial and
 things will go wrong if it's not done.  System.txt along with config.txt
 are configuration files that are edited by the user before running the
 gctload program that uses these files for initialising modules and
similarity index 94%
rename from README.sita
rename to doc/README.sita
index ee7a426..5a65822 100644 (file)
@@ -1,5 +1,5 @@
 The following instructions apply if you have a Linux platform and want
-libpcap to support the 'ACN' WAN/LAN router product from from SITA
+libpcap to support the 'ACN' WAN/LAN router product from SITA
 (http://www.sita.aero)
 
 This might also work on non-Linux Unix-compatible platforms, but that
@@ -12,7 +12,7 @@ These additions/extensions have been made to PCAP to allow it to
 capture packets from a SITA ACN device (and potentially others).
 
 To enable its support you need to ensure that the distribution has
-a correct configure.in file; that can be created if neccessay by
+a correct configure.ac file; that can be created if neccessay by
 using the normal autoconf procedure of:
 
 aclocal
similarity index 96%
rename from README.tru64
rename to doc/README.tru64
index 7fe1ef0..2420d9e 100644 (file)
@@ -1,4 +1,4 @@
-The following instructions are applicable to Tru64 UNIX 
+The following instructions are applicable to Tru64 UNIX
 (formerly Digital UNIX (formerly DEC OSF/1)) version 4.0, and
 probably to later versions as well; at least some options apply to
 Digital UNIX 3.2 - perhaps all do.
index 707fd9d..5f49961 100644 (file)
  */
 
 #ifdef HAVE_CONFIG_H
-#include "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>
-#endif
-#include <sys/types.h>
-#endif /* WIN32 */
+#include <pcap-types.h>
 
 #include <ctype.h>
 #include <memory.h>
 #include "os-proto.h"
 #endif
 
-static inline int xdtoi(int);
 static inline int skip_space(FILE *);
 static inline int skip_line(FILE *);
 
 /* Hex digit to integer. */
-static inline int
-xdtoi(c)
-       register int c;
+static inline u_char
+xdtoi(u_char c)
 {
        if (isdigit(c))
-               return c - '0';
+               return (u_char)(c - '0');
        else if (islower(c))
-               return c - 'a' + 10;
+               return (u_char)(c - 'a' + 10);
        else
-               return c - 'A' + 10;
+               return (u_char)(c - 'A' + 10);
 }
 
 static inline int
-skip_space(f)
-       FILE *f;
+skip_space(FILE *f)
 {
        int c;
 
@@ -81,8 +66,7 @@ skip_space(f)
 }
 
 static inline int
-skip_line(f)
-       FILE *f;
+skip_line(FILE *f)
 {
        int c;
 
@@ -96,47 +80,61 @@ skip_line(f)
 struct pcap_etherent *
 pcap_next_etherent(FILE *fp)
 {
-       register int c, d, i;
+       register int c, i;
+       u_char d;
        char *bp;
+       size_t namesize;
        static struct pcap_etherent e;
 
        memset((char *)&e, 0, sizeof(e));
-       do {
+       for (;;) {
                /* Find addr */
                c = skip_space(fp);
+               if (c == EOF)
+                       return (NULL);
                if (c == '\n')
                        continue;
 
                /* If this is a comment, or first thing on line
-                  cannot be etehrnet address, skip the line. */
+                  cannot be Ethernet address, skip the line. */
                if (!isxdigit(c)) {
                        c = skip_line(fp);
+                       if (c == EOF)
+                               return (NULL);
                        continue;
                }
 
                /* must be the start of an address */
                for (i = 0; i < 6; i += 1) {
-                       d = xdtoi(c);
+                       d = xdtoi((u_char)c);
                        c = getc(fp);
+                       if (c == EOF)
+                               return (NULL);
                        if (isxdigit(c)) {
                                d <<= 4;
-                               d |= xdtoi(c);
+                               d |= xdtoi((u_char)c);
                                c = getc(fp);
+                               if (c == EOF)
+                                       return (NULL);
                        }
                        e.addr[i] = d;
                        if (c != ':')
                                break;
                        c = getc(fp);
+                       if (c == EOF)
+                               return (NULL);
                }
-               if (c == EOF)
-                       break;
 
                /* Must be whitespace */
                if (!isspace(c)) {
                        c = skip_line(fp);
+                       if (c == EOF)
+                               return (NULL);
                        continue;
                }
                c = skip_space(fp);
+               if (c == EOF)
+                       return (NULL);
 
                /* hit end of line... */
                if (c == '\n')
@@ -144,17 +142,21 @@ pcap_next_etherent(FILE *fp)
 
                if (c == '#') {
                        c = skip_line(fp);
+                       if (c == EOF)
+                               return (NULL);
                        continue;
                }
 
                /* pick up name */
                bp = e.name;
-               /* Use 'd' to prevent buffer overflow. */
-               d = sizeof(e.name) - 1;
+               /* Use 'namesize' to prevent buffer overflow. */
+               namesize = sizeof(e.name) - 1;
                do {
-                       *bp++ = c;
+                       *bp++ = (u_char)c;
                        c = getc(fp);
-               } while (!isspace(c) && c != EOF && --d > 0);
+                       if (c == EOF)
+                               return (NULL);
+               } while (!isspace(c) && --namesize != 0);
                *bp = '\0';
 
                /* Eat trailing junk */
@@ -162,8 +164,5 @@ pcap_next_etherent(FILE *fp)
                        (void)skip_line(fp);
 
                return &e;
-
-       } while (c != EOF);
-
-       return (NULL);
+       }
 }
index 8bab881..51f6308 100644 (file)
 #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/extract.h b/extract.h
new file mode 100644 (file)
index 0000000..aa3ff99
--- /dev/null
+++ b/extract.h
@@ -0,0 +1,225 @@
+/*
+ * 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
+
+#include <pcap/pcap-inttypes.h>
+#include <pcap/compiler-tests.h>
+
+/*
+ * Macros to extract possibly-unaligned big-endian integral values.
+ */
+#ifdef LBL_ALIGN
+/*
+ * The processor doesn't natively handle unaligned loads.
+ */
+#if PCAP_IS_AT_LEAST_GNUC_VERSION(2,0) && \
+    (defined(__alpha) || defined(__alpha__) || \
+     defined(__mips) || defined(__mips__))
+/*
+ * This is MIPS or Alpha, which don't natively handle unaligned loads,
+ * but which have instructions that can help when doing unaligned
+ * loads, and this is GCC 2.0 or later or a compiler that claims to
+ * be GCC 2.0 or later, which we assume that mean we have
+ * __attribute__((packed)), which we can use to convince the compiler
+ * to generate those instructions.
+ *
+ * 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)))
index 6fd3360..5236fbb 100644 (file)
@@ -33,7 +33,7 @@
  */
 
 #ifdef HAVE_CONFIG_H
-#include "config.h"
+#include <config.h>
 #endif
 
 #include <sys/types.h>
  * all those systems we have "struct sockaddr_storage".
  */
 #ifndef SA_LEN
-#ifdef HAVE_SOCKADDR_SA_LEN
+#ifdef HAVE_STRUCT_SOCKADDR_SA_LEN
 #define SA_LEN(addr)   ((addr)->sa_len)
-#else /* HAVE_SOCKADDR_SA_LEN */
-#ifdef HAVE_SOCKADDR_STORAGE
+#else /* HAVE_STRUCT_SOCKADDR_SA_LEN */
+#ifdef HAVE_STRUCT_SOCKADDR_STORAGE
 static size_t
 get_sa_len(struct sockaddr *addr)
 {
@@ -131,10 +131,10 @@ get_sa_len(struct sockaddr *addr)
        }
 }
 #define SA_LEN(addr)   (get_sa_len(addr))
-#else /* HAVE_SOCKADDR_STORAGE */
+#else /* HAVE_STRUCT_SOCKADDR_STORAGE */
 #define SA_LEN(addr)   (sizeof (struct sockaddr))
-#endif /* HAVE_SOCKADDR_STORAGE */
-#endif /* HAVE_SOCKADDR_SA_LEN */
+#endif /* HAVE_STRUCT_SOCKADDR_STORAGE */
+#endif /* HAVE_STRUCT_SOCKADDR_SA_LEN */
 #endif /* SA_LEN */
 
 /*
@@ -144,9 +144,9 @@ get_sa_len(struct sockaddr *addr)
  * could be opened.
  */
 int
-pcap_findalldevs_interfaces(pcap_if_t **alldevsp, char *errbuf)
+pcap_findalldevs_interfaces(pcap_if_list_t *devlistp, char *errbuf,
+    int (*check_usable)(const char *), get_if_flags_func get_flags_func)
 {
-       pcap_if_t *devlist = NULL;
        struct ifaddrs *ifap, *ifa;
        struct sockaddr *addr, *netmask, *broadaddr, *dstaddr;
        size_t addr_size, broadaddr_size, dstaddr_size;
@@ -168,12 +168,51 @@ pcap_findalldevs_interfaces(pcap_if_t **alldevsp, char *errbuf)
         * those.
         */
        if (getifaddrs(&ifap) != 0) {
-               (void)snprintf(errbuf, PCAP_ERRBUF_SIZE,
-                   "getifaddrs: %s", pcap_strerror(errno));
+               pcap_fmt_errmsg_for_errno(errbuf, PCAP_ERRBUF_SIZE,
+                   errno, "getifaddrs");
                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
@@ -193,7 +232,7 @@ pcap_findalldevs_interfaces(pcap_if_t **alldevsp, char *errbuf)
                /*
                 * Note that, on some platforms, ifa_broadaddr and
                 * ifa_dstaddr could be the same field (true on at
-                * least some versions of *BSD and OS X), so we
+                * least some versions of *BSD and macOS), so we
                 * can't just check whether the broadcast address
                 * is null and add it if so and check whether the
                 * destination address is null and add it if so.
@@ -223,39 +262,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 (add_addr_to_if(devlistp, ifa->ifa_name, ifa->ifa_flags,
+                   get_flags_func,
+                   addr, addr_size, netmask, addr_size,
                    broadaddr, broadaddr_size, dstaddr, dstaddr_size,
                    errbuf) < 0) {
                        ret = -1;
@@ -265,16 +276,5 @@ pcap_findalldevs_interfaces(pcap_if_t **alldevsp, char *errbuf)
 
        freeifaddrs(ifap);
 
-       if (ret == -1) {
-               /*
-                * We had an error; free the list we've been constructing.
-                */
-               if (devlist != NULL) {
-                       pcap_freealldevs(devlist);
-                       devlist = NULL;
-               }
-       }
-
-       *alldevsp = devlist;
        return (ret);
 }
index 5c3357c..6b16127 100644 (file)
@@ -33,7 +33,7 @@
  */
 
 #ifdef HAVE_CONFIG_H
-#include "config.h"
+#include <config.h>
 #endif
 
 #include <sys/param.h>
@@ -57,6 +57,12 @@ struct rtentry;              /* declarations in <net/if.h> */
 #include <string.h>
 #include <unistd.h>
 
+#ifdef HAVE_LIMITS_H
+#include <limits.h>
+#else
+#define INT_MAX                2147483647
+#endif
+
 #include "pcap-int.h"
 
 #ifdef HAVE_OS_PROTO_H
@@ -89,11 +95,11 @@ struct rtentry;             /* declarations in <net/if.h> */
  * address in an entry returned by SIOCGIFCONF.
  */
 #ifndef SA_LEN
-#ifdef HAVE_SOCKADDR_SA_LEN
+#ifdef HAVE_STRUCT_SOCKADDR_SA_LEN
 #define SA_LEN(addr)   ((addr)->sa_len)
-#else /* HAVE_SOCKADDR_SA_LEN */
+#else /* HAVE_STRUCT_SOCKADDR_SA_LEN */
 #define SA_LEN(addr)   (sizeof (struct sockaddr))
-#endif /* HAVE_SOCKADDR_SA_LEN */
+#endif /* HAVE_STRUCT_SOCKADDR_SA_LEN */
 #endif /* SA_LEN */
 
 /*
@@ -132,12 +138,12 @@ 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_list_t *devlistp, char *errbuf,
+    int (*check_usable)(const char *), get_if_flags_func get_flags_func)
 {
-       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,8 +160,8 @@ 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,
-                   "socket: %s", pcap_strerror(errno));
+               pcap_fmt_errmsg_for_errno(errbuf, PCAP_ERRBUF_SIZE,
+                   errno, "socket");
                return (-1);
        }
 
@@ -168,10 +174,20 @@ pcap_findalldevs_interfaces(pcap_if_t **alldevsp, char *errbuf)
         */
        buf_size = 8192;
        for (;;) {
+               /*
+                * Don't let the buffer size get bigger than INT_MAX.
+                */
+               if (buf_size > INT_MAX) {
+                       (void)pcap_snprintf(errbuf, PCAP_ERRBUF_SIZE,
+                           "interface information requires more than %u bytes",
+                           INT_MAX);
+                       (void)close(fd);
+                       return (-1);
+               }
                buf = malloc(buf_size);
                if (buf == NULL) {
-                       (void)snprintf(errbuf, PCAP_ERRBUF_SIZE,
-                           "malloc: %s", pcap_strerror(errno));
+                       pcap_fmt_errmsg_for_errno(errbuf, PCAP_ERRBUF_SIZE,
+                           errno, "malloc");
                        (void)close(fd);
                        return (-1);
                }
@@ -181,13 +197,13 @@ 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,
-                           "SIOCGIFCONF: %s", pcap_strerror(errno));
+                       pcap_fmt_errmsg_for_errno(errbuf, PCAP_ERRBUF_SIZE,
+                           errno, "SIOCGIFCONF");
                        (void)close(fd);
                        free(buf);
                        return (-1);
                }
-               if (ifc.ifc_len < buf_size &&
+               if (ifc.ifc_len < (int)buf_size &&
                    (buf_size - ifc.ifc_len) > sizeof(ifrp->ifr_name) + MAX_SA_LEN)
                        break;
                free(buf);
@@ -217,12 +233,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 +253,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,11 +270,10 @@ 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,
-                           "SIOCGIFFLAGS: %.*s: %s",
+                       pcap_fmt_errmsg_for_errno(errbuf, PCAP_ERRBUF_SIZE,
+                           errno, "SIOCGIFFLAGS: %.*s",
                            (int)sizeof(ifrflags.ifr_name),
-                           ifrflags.ifr_name,
-                           pcap_strerror(errno));
+                           ifrflags.ifr_name);
                        ret = -1;
                        break;
                }
@@ -268,11 +293,11 @@ pcap_findalldevs_interfaces(pcap_if_t **alldevsp, char *errbuf)
                                netmask = NULL;
                                netmask_size = 0;
                        } else {
-                               (void)snprintf(errbuf, PCAP_ERRBUF_SIZE,
-                                   "SIOCGIFNETMASK: %.*s: %s",
+                               pcap_fmt_errmsg_for_errno(errbuf,
+                                   PCAP_ERRBUF_SIZE, errno,
+                                   "SIOCGIFNETMASK: %.*s",
                                    (int)sizeof(ifrnetmask.ifr_name),
-                                   ifrnetmask.ifr_name,
-                                   pcap_strerror(errno));
+                                   ifrnetmask.ifr_name);
                                ret = -1;
                                break;
                        }
@@ -299,11 +324,11 @@ pcap_findalldevs_interfaces(pcap_if_t **alldevsp, char *errbuf)
                                        broadaddr = NULL;
                                        broadaddr_size = 0;
                                } else {
-                                       (void)snprintf(errbuf, PCAP_ERRBUF_SIZE,
-                                           "SIOCGIFBRDADDR: %.*s: %s",
+                                       pcap_fmt_errmsg_for_errno(errbuf,
+                                           PCAP_ERRBUF_SIZE, errno,
+                                           "SIOCGIFBRDADDR: %.*s",
                                            (int)sizeof(ifrbroadaddr.ifr_name),
-                                           ifrbroadaddr.ifr_name,
-                                           pcap_strerror(errno));
+                                           ifrbroadaddr.ifr_name);
                                        ret = -1;
                                        break;
                                }
@@ -338,11 +363,11 @@ pcap_findalldevs_interfaces(pcap_if_t **alldevsp, char *errbuf)
                                        dstaddr = NULL;
                                        dstaddr_size = 0;
                                } else {
-                                       (void)snprintf(errbuf, PCAP_ERRBUF_SIZE,
-                                           "SIOCGIFDSTADDR: %.*s: %s",
+                                       pcap_fmt_errmsg_for_errno(errbuf,
+                                           PCAP_ERRBUF_SIZE, errno,
+                                           "SIOCGIFDSTADDR: %.*s",
                                            (int)sizeof(ifrdstaddr.ifr_name),
-                                           ifrdstaddr.ifr_name,
-                                           pcap_strerror(errno));
+                                           ifrdstaddr.ifr_name);
                                        ret = -1;
                                        break;
                                }
@@ -390,11 +415,11 @@ 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 (add_addr_to_if(devlistp, ifrp->ifr_name,
+                   ifrflags.ifr_flags, get_flags_func,
+                   &ifrp->ifr_addr, SA_LEN(&ifrp->ifr_addr),
+                   netmask, netmask_size, broadaddr, broadaddr_size,
+                   dstaddr, dstaddr_size, errbuf) < 0) {
                        ret = -1;
                        break;
                }
@@ -402,16 +427,5 @@ pcap_findalldevs_interfaces(pcap_if_t **alldevsp, char *errbuf)
        free(buf);
        (void)close(fd);
 
-       if (ret == -1) {
-               /*
-                * We had an error; free the list we've been constructing.
-                */
-               if (devlist != NULL) {
-                       pcap_freealldevs(devlist);
-                       devlist = NULL;
-               }
-       }
-
-       *alldevsp = devlist;
        return (ret);
 }
index 1a820ad..f22f56d 100644 (file)
@@ -33,7 +33,7 @@
  */
 
 #ifdef HAVE_CONFIG_H
-#include "config.h"
+#include <config.h>
 #endif
 
 #include <sys/param.h>
@@ -75,9 +75,9 @@ 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_list_t *devlistp, char *errbuf,
+    int (*check_usable)(const char *), get_if_flags_func get_flags_func)
 {
-       pcap_if_t *devlist = NULL;
        register int fd4, fd6, fd;
        register struct lifreq *ifrp, *ifend;
        struct lifnum ifn;
@@ -97,8 +97,8 @@ 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,
-                   "socket: %s", pcap_strerror(errno));
+               pcap_fmt_errmsg_for_errno(errbuf, PCAP_ERRBUF_SIZE,
+                   errno, "socket: AF_INET");
                return (-1);
        }
 
@@ -107,8 +107,8 @@ 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,
-                   "socket: %s", pcap_strerror(errno));
+               pcap_fmt_errmsg_for_errno(errbuf, PCAP_ERRBUF_SIZE,
+                   errno, "socket: AF_INET6");
                (void)close(fd4);
                return (-1);
        }
@@ -120,8 +120,8 @@ 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,
-                   "SIOCGLIFNUM: %s", pcap_strerror(errno));
+               pcap_fmt_errmsg_for_errno(errbuf, PCAP_ERRBUF_SIZE,
+                   errno, "SIOCGLIFNUM");
                (void)close(fd6);
                (void)close(fd4);
                return (-1);
@@ -133,8 +133,8 @@ 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,
-                   "malloc: %s", pcap_strerror(errno));
+               pcap_fmt_errmsg_for_errno(errbuf, PCAP_ERRBUF_SIZE,
+                   errno, "malloc");
                (void)close(fd6);
                (void)close(fd4);
                return (-1);
@@ -149,8 +149,8 @@ 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,
-                   "SIOCGLIFCONF: %s", pcap_strerror(errno));
+               pcap_fmt_errmsg_for_errno(errbuf, PCAP_ERRBUF_SIZE,
+                   errno, "SIOCGLIFCONF");
                (void)close(fd6);
                (void)close(fd4);
                free(buf);
@@ -165,14 +165,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 +172,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,11 +198,10 @@ 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,
-                           "SIOCGLIFFLAGS: %.*s: %s",
+                       pcap_fmt_errmsg_for_errno(errbuf, PCAP_ERRBUF_SIZE,
+                           errno, "SIOCGLIFFLAGS: %.*s",
                            (int)sizeof(ifrflags.lifr_name),
-                           ifrflags.lifr_name,
-                           pcap_strerror(errno));
+                           ifrflags.lifr_name);
                        ret = -1;
                        break;
                }
@@ -233,11 +220,11 @@ pcap_findalldevs_interfaces(pcap_if_t **alldevsp, char *errbuf)
                                 */
                                netmask = NULL;
                        } else {
-                               (void)snprintf(errbuf, PCAP_ERRBUF_SIZE,
-                                   "SIOCGLIFNETMASK: %.*s: %s",
+                               pcap_fmt_errmsg_for_errno(errbuf,
+                                   PCAP_ERRBUF_SIZE, errno,
+                                   "SIOCGLIFNETMASK: %.*s",
                                    (int)sizeof(ifrnetmask.lifr_name),
-                                   ifrnetmask.lifr_name,
-                                   pcap_strerror(errno));
+                                   ifrnetmask.lifr_name);
                                ret = -1;
                                break;
                        }
@@ -261,11 +248,11 @@ pcap_findalldevs_interfaces(pcap_if_t **alldevsp, char *errbuf)
                                         */
                                        broadaddr = NULL;
                                } else {
-                                       (void)snprintf(errbuf, PCAP_ERRBUF_SIZE,
-                                           "SIOCGLIFBRDADDR: %.*s: %s",
+                                       pcap_fmt_errmsg_for_errno(errbuf,
+                                           PCAP_ERRBUF_SIZE, errno,
+                                           "SIOCGLIFBRDADDR: %.*s",
                                            (int)sizeof(ifrbroadaddr.lifr_name),
-                                           ifrbroadaddr.lifr_name,
-                                           pcap_strerror(errno));
+                                           ifrbroadaddr.lifr_name);
                                        ret = -1;
                                        break;
                                }
@@ -296,11 +283,11 @@ pcap_findalldevs_interfaces(pcap_if_t **alldevsp, char *errbuf)
                                         */
                                        dstaddr = NULL;
                                } else {
-                                       (void)snprintf(errbuf, PCAP_ERRBUF_SIZE,
-                                           "SIOCGLIFDSTADDR: %.*s: %s",
+                                       pcap_fmt_errmsg_for_errno(errbuf,
+                                           PCAP_ERRBUF_SIZE, errno,
+                                           "SIOCGLIFDSTADDR: %.*s",
                                            (int)sizeof(ifrdstaddr.lifr_name),
-                                           ifrdstaddr.lifr_name,
-                                           pcap_strerror(errno));
+                                           ifrdstaddr.lifr_name);
                                        ret = -1;
                                        break;
                                }
@@ -340,8 +327,9 @@ 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 (add_addr_to_if(devlistp, ifrp->lifr_name,
+                   ifrflags.lifr_flags, get_flags_func,
+                   (struct sockaddr *)&ifrp->lifr_addr,
                    sizeof (struct sockaddr_storage),
                    netmask, sizeof (struct sockaddr_storage),
                    broadaddr, sizeof (struct sockaddr_storage),
@@ -354,16 +342,5 @@ pcap_findalldevs_interfaces(pcap_if_t **alldevsp, char *errbuf)
        (void)close(fd6);
        (void)close(fd4);
 
-       if (ret == -1) {
-               /*
-                * We had an error; free the list we've been constructing.
-                */
-               if (devlist != NULL) {
-                       pcap_freealldevs(devlist);
-                       devlist = NULL;
-               }
-       }
-
-       *alldevsp = devlist;
        return (ret);
 }
diff --git a/fad-sita.c b/fad-sita.c
deleted file mode 100644 (file)
index 34ddf1d..0000000
+++ /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/fad-win32.c b/fad-win32.c
deleted file mode 100644 (file)
index 0de893e..0000000
+++ /dev/null
@@ -1,248 +0,0 @@
-/*
- * Copyright (c) 2002 - 2005 NetGroup, Politecnico di Torino (Italy)
- * Copyright (c) 2005 - 2006 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.h>
-#include <pcap-int.h>
-#include <Packet32.h>
-
-#include <errno.h>
-
-static int
-pcap_add_if_win32(pcap_if_t **devlist, char *name, const char *desc,
-    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, 0, desc, 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);
-}
-
-
-/*
- * Get a list of all interfaces that are up and that we can open.
- * Returns -1 on error, 0 otherwise.
- * The list, as returned through "alldevsp", may be null if no interfaces
- * were up and could be opened.
- *
- * Win32 implementation, based on WinPcap
- */
-int
-pcap_findalldevs_interfaces(pcap_if_t **alldevsp, char *errbuf)
-{
-       pcap_if_t *devlist = NULL;
-       int ret = 0;
-       const char *desc;
-       char *AdaptersName;
-       ULONG NameLength;
-       char *name;
-       
-       /*
-        * Find out how big a buffer we need.
-        *
-        * This call should always return FALSE; if the error is
-        * ERROR_INSUFFICIENT_BUFFER, NameLength will be set to
-        * the size of the buffer we need, otherwise there's a
-        * problem, and NameLength should be set to 0.
-        *
-        * It shouldn't require NameLength to be set, but,
-        * at least as of WinPcap 4.1.3, it checks whether
-        * NameLength is big enough before it checks for a
-        * NULL buffer argument, so, while it'll still do
-        * the right thing if NameLength is uninitialized and
-        * whatever junk happens to be there is big enough
-        * (because the pointer argument will be null), it's
-        * still reading an uninitialized variable.
-        */
-       NameLength = 0;
-       if (!PacketGetAdapterNames(NULL, &NameLength))
-       {
-               DWORD last_error = GetLastError();
-
-               if (last_error != ERROR_INSUFFICIENT_BUFFER)
-               {
-                       snprintf(errbuf, PCAP_ERRBUF_SIZE,
-                               "PacketGetAdapterNames: %s",
-                               pcap_win32strerror());
-                       return (-1);
-               }
-       }
-
-       if (NameLength > 0)
-               AdaptersName = (char*) malloc(NameLength);
-       else
-       {
-               *alldevsp = NULL;
-               return 0;
-       }
-       if (AdaptersName == NULL)
-       {
-               snprintf(errbuf, PCAP_ERRBUF_SIZE, "Cannot allocate enough memory to list the adapters.");
-               return (-1);
-       }                       
-
-       if (!PacketGetAdapterNames(AdaptersName, &NameLength)) {
-               snprintf(errbuf, PCAP_ERRBUF_SIZE,
-                       "PacketGetAdapterNames: %s",
-                       pcap_win32strerror());
-               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') {
-               /*
-                * Add an entry for this interface.
-                */
-               if (pcap_add_if_win32(&devlist, name, desc, errbuf) == -1) {
-                       /*
-                        * Failure.
-                        */
-                       ret = -1;
-                       break;
-               }
-               name += strlen(name) + 1;
-               desc += strlen(desc) + 1;
-       }
-
-       if (ret != -1) {
-               /*
-                * We haven't had any errors yet; do any platform-specific
-                * operations to add devices.
-                */
-               if (pcap_platform_finddevs(&devlist, errbuf) < 0)
-                       ret = -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/fmtutils.c b/fmtutils.c
new file mode 100644 (file)
index 0000000..091e0d3
--- /dev/null
@@ -0,0 +1,214 @@
+/*
+ * Copyright (c) 1993, 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.
+ */
+
+/*
+ * Utilities for message formatting used both by libpcap and rpcapd.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include "ftmacros.h"
+
+#include <stddef.h>
+#include <stdarg.h>
+#include <stdio.h>
+#include <string.h>
+#include <errno.h>
+
+#include <pcap/pcap.h>
+
+#include "portability.h"
+
+#include "fmtutils.h"
+
+/*
+ * Generate an error message based on a format, arguments, and an
+ * errno, with a message for the errno after the formatted output.
+ */
+void
+pcap_fmt_errmsg_for_errno(char *errbuf, size_t errbuflen, int errnum,
+    const char *fmt, ...)
+{
+       va_list ap;
+       size_t msglen;
+       char *p;
+       size_t errbuflen_remaining;
+
+       va_start(ap, fmt);
+       pcap_vsnprintf(errbuf, errbuflen, fmt, ap);
+       va_end(ap);
+       msglen = strlen(errbuf);
+
+       /*
+        * Do we have enough space to append ": "?
+        * Including the terminating '\0', that's 3 bytes.
+        */
+       if (msglen + 3 > errbuflen) {
+               /* No - just give them what we've produced. */
+               return;
+       }
+       p = errbuf + msglen;
+       errbuflen_remaining = errbuflen - msglen;
+       *p++ = ':';
+       *p++ = ' ';
+       *p = '\0';
+       msglen += 2;
+       errbuflen_remaining -= 2;
+
+       /*
+        * Now append the string for the error code.
+        */
+#if defined(HAVE_STRERROR_S)
+       /*
+        * We have a Windows-style strerror_s().
+        */
+       errno_t err = strerror_s(p, errbuflen_remaining, errnum);
+       if (err != 0) {
+               /*
+                * It doesn't appear to be documented anywhere obvious
+                * what the error returns from strerror_s().
+                */
+               pcap_snprintf(p, errbuflen_remaining, "Error %d", errnum);
+       }
+#elif defined(HAVE_GNU_STRERROR_R)
+       /*
+        * We have a GNU-style strerror_r(), which is *not* guaranteed to
+        * do anything to the buffer handed to it, and which returns a
+        * pointer to the error string, which may or may not be in
+        * the buffer.
+        *
+        * It is, however, guaranteed to succeed.
+        */
+       char strerror_buf[PCAP_ERRBUF_SIZE];
+       char *errstring = strerror_r(errnum, strerror_buf, PCAP_ERRBUF_SIZE);
+       pcap_snprintf(p, errbuflen_remaining, "%s", errstring);
+#elif defined(HAVE_POSIX_STRERROR_R)
+       /*
+        * We have a POSIX-style strerror_r(), which is guaranteed to fill
+        * in the buffer, but is not guaranteed to succeed.
+        */
+       int err = strerror_r(errnum, p, errbuflen_remaining);
+       if (err == EINVAL) {
+               /*
+                * UNIX 03 says this isn't guaranteed to produce a
+                * fallback error message.
+                */
+               pcap_snprintf(p, errbuflen_remaining, "Unknown error: %d",
+                   errnum);
+       } else if (err == ERANGE) {
+               /*
+                * UNIX 03 says this isn't guaranteed to produce a
+                * fallback error message.
+                */
+               pcap_snprintf(p, errbuflen_remaining,
+                   "Message for error %d is too long", errnum);
+       }
+#else
+       /*
+        * We have neither strerror_s() nor strerror_r(), so we're
+        * stuck with using pcap_strerror().
+        */
+       pcap_snprintf(p, errbuflen_remaining, "%s", pcap_strerror(errnum));
+#endif
+}
+
+#ifdef _WIN32
+/*
+ * Generate an error message based on a format, arguments, and a
+ * Win32 error, with a message for the Win32 error after the formatted output.
+ */
+void
+pcap_fmt_errmsg_for_win32_err(char *errbuf, size_t errbuflen, DWORD errnum,
+    const char *fmt, ...)
+{
+       va_list ap;
+       size_t msglen;
+       char *p;
+       size_t errbuflen_remaining;
+       DWORD retval;
+       char win32_errbuf[PCAP_ERRBUF_SIZE+1];
+
+       va_start(ap, fmt);
+       pcap_vsnprintf(errbuf, errbuflen, fmt, ap);
+       va_end(ap);
+       msglen = strlen(errbuf);
+
+       /*
+        * Do we have enough space to append ": "?
+        * Including the terminating '\0', that's 3 bytes.
+        */
+       if (msglen + 3 > errbuflen) {
+               /* No - just give them what we've produced. */
+               return;
+       }
+       p = errbuf + msglen;
+       errbuflen_remaining = errbuflen - msglen;
+       *p++ = ':';
+       *p++ = ' ';
+       *p = '\0';
+       msglen += 2;
+       errbuflen_remaining -= 2;
+
+       /*
+        * Now append the string for the error code.
+        *
+        * XXX - what language ID to use?
+        *
+        * For UN*Xes, pcap_strerror() may or may not return localized
+        * strings.
+        *
+        * We currently don't have localized messages for libpcap, but
+        * we might want to do so.  On the other hand, if most of these
+        * messages are going to be read by libpcap developers and
+        * perhaps by developers of libpcap-based applications, English
+        * might be a better choice, so the developer doesn't have to
+        * get the message translated if it's in a language they don't
+        * happen to understand.
+        */
+       retval = FormatMessageA(FORMAT_MESSAGE_FROM_SYSTEM|FORMAT_MESSAGE_IGNORE_INSERTS|FORMAT_MESSAGE_MAX_WIDTH_MASK,
+           NULL, errnum, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
+           win32_errbuf, PCAP_ERRBUF_SIZE, NULL);
+       if (retval == 0) {
+               /*
+                * Failed.
+                */
+               pcap_snprintf(p, errbuflen_remaining,
+                   "Couldn't get error message for error (%lu)", errnum);
+               return;
+       }
+
+       pcap_snprintf(p, errbuflen_remaining, "%s (%lu)", win32_errbuf, errnum);
+}
+#endif
similarity index 56%
rename from Win32/Src/inet_aton.c
rename to fmtutils.h
index cbd4361..838948b 100644 (file)
@@ -1,32 +1,27 @@
 /*
- * Copyright (c) 1995, 1996, 1997 Kungliga Tekniska Högskolan
- * (Royal Institute of Technology, Stockholm, Sweden).
- * All rights reserved.
- * 
+ * 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 Kungliga Tekniska
- *      Högskolan and its contributors.
- * 
- * 4. Neither the name of the Institute 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 INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
+ *     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 INSTITUTE OR CONTRIBUTORS BE LIABLE
+ * 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)
  * SUCH DAMAGE.
  */
 
-#include <sys/types.h>
-#include <pcap-stdinc.h>
+#ifndef fmtutils_h
+#define        fmtutils_h
 
-/* Minimal implementation of inet_aton.
- * Cannot distinguish between failure and a local broadcast address. */
+#include "pcap/funcattrs.h"
 
-#ifndef INADDR_NONE
-#define INADDR_NONE 0xffffffff
+#ifdef __cplusplus
+extern "C" {
 #endif
 
-int
-inet_aton(const char *cp, struct in_addr *addr)
-{
-  addr->s_addr = inet_addr(cp);
-  return (addr->s_addr == INADDR_NONE) ? 0 : 1;
+void   pcap_fmt_errmsg_for_errno(char *, size_t, int,
+    PCAP_FORMAT_STRING(const char *), ...) PCAP_PRINTFLIKE(4, 5);
+
+#ifdef _WIN32
+void   pcap_fmt_errmsg_for_win32_err(char *, size_t, DWORD,
+    PCAP_FORMAT_STRING(const char *), ...) PCAP_PRINTFLIKE(4, 5);
+#endif
+
+#ifdef __cplusplus
 }
+#endif
+
+#endif
diff --git a/ftmacros.h b/ftmacros.h
new file mode 100644 (file)
index 0000000..cd3daeb
--- /dev/null
@@ -0,0 +1,109 @@
+/*
+ * 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 ftmacros_h
+#define        ftmacros_h
+
+/*
+ * Define some feature test macros to make sure that everything we want
+ * to be declared gets declared.
+ *
+ * On some UN*Xes we need to force strtok_r() to be declared.
+ * We do *NOT* want to define _POSIX_C_SOURCE, as that tends
+ * to make non-POSIX APIs that we use unavailable.
+ * XXX - is there no portable way to say "please pollute the
+ * namespace to the maximum extent possible"?
+ */
+#if defined(sun) || defined(__sun)
+  #define __EXTENSIONS__
+
+  /*
+   * We also need to define _XPG4_2 in order to get
+   * the Single UNIX Specification version of
+   * recvmsg().
+   */
+  #define _XPG4_2
+#elif defined(_hpux) || defined(hpux) || defined(__hpux)
+  #define _REENTRANT
+
+  /*
+   * We need this to get the versions of socket functions that
+   * use socklen_t.  Define it only if it's not already defined,
+   * so we don't get redefiniton warnings.
+   */
+  #ifndef _XOPEN_SOURCE_EXTENDED
+    #define _XOPEN_SOURCE_EXTENDED
+  #endif
+
+  /*
+   * XXX - the list of PA-RISC options for GCC makes it sound as if
+   * building code that uses a particular vintage of UNIX API/ABI
+   * is complicated:
+   *
+   *    https://gcc.gnu.org/onlinedocs/gcc/HPPA-Options.html
+   *
+   * See the description of the -munix flag.
+   *
+   * We probably want libpcap to work with programs built for any
+   * UN*X standard.  I'm not sure whether that's possible and, if
+   * it is, what sort of stuff it'd have to do.
+   *
+   * It might also be a requirement that we build with a special
+   * flag to allow the library to be used with threaded code, at
+   * least with HP's C compiler; hopefully doing so won't make it
+   * *not* work with *un*-threaded code.
+   */
+#elif defined(__linux__) || defined(linux) || defined(__linux)
+  /*
+   * Turn on _GNU_SOURCE to get everything GNU libc has to offer,
+   * including asprintf().
+   *
+   * Unfortunately, one thing it has to offer is a strerror_r()
+   * that's not POSIX-compliant, but we deal with that in
+   * pcap_fmt_errmsg_for_errno().
+   */
+  #define _GNU_SOURCE
+
+  /*
+   * We turn on both _DEFAULT_SOURCE and _BSD_SOURCE to try to get
+   * the BSD u_XXX types, such as u_int and u_short, defined.  We
+   * define _DEFAULT_SOURCE first, so that newer versions of GNU libc
+   * don't whine about _BSD_SOURCE being deprecated; we still have
+   * to define _BSD_SOURCE to handle older versions of GNU libc that
+   * don't support _DEFAULT_SOURCE.
+   */
+  #define _DEFAULT_SOURCE
+  #define _BSD_SOURCE
+#endif
+
+#endif
index 7be05df..e3425cd 100644 (file)
--- a/gencode.c
+++ b/gencode.c
  */
 
 #ifdef HAVE_CONFIG_H
-#include "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>
-#endif
-#include <sys/types.h>
-#include <sys/socket.h>
-#endif /* WIN32 */
-
-/*
- * XXX - why was this included even on UNIX?
- */
-#ifdef __MINGW32__
-#include "ip6_misc.h"
-#endif
-
-#ifndef WIN32
-
-#ifdef __NetBSD__
-#include <sys/param.h>
-#endif
+#include <pcap-types.h>
+#ifdef _WIN32
+  #include <ws2tcpip.h>
+#else
+  #include <sys/socket.h>
 
-#include <netinet/in.h>
-#include <arpa/inet.h>
+  #ifdef __NetBSD__
+    #include <sys/param.h>
+  #endif
 
-#endif /* WIN32 */
+  #include <netinet/in.h>
+  #include <arpa/inet.h>
+#endif /* _WIN32 */
 
 #include <stdlib.h>
 #include <string.h>
@@ -69,6 +50,8 @@
 
 #include "pcap-int.h"
 
+#include "extract.h"
+
 #include "ethertype.h"
 #include "nlpid.h"
 #include "llc.h"
 #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
-#include <netdb.h>     /* for "struct addrinfo" */
-#endif /* WIN32 */
-#endif /*INET6*/
+
+#ifdef _WIN32
+  #ifdef INET6
+    #if defined(__MINGW32__) && defined(DEFINE_ADDITIONAL_IPV6_STUFF)
+/* IPv6 address */
+struct in6_addr
+  {
+    union
+      {
+       uint8_t         u6_addr8[16];
+       uint16_t        u6_addr16[8];
+       uint32_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_);
+    uint16_t sin6_port;                /* Transport layer port # */
+    uint32_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) */
+  #endif /* INET6 */
+#else /* _WIN32 */
+  #include <netdb.h>   /* for "struct addrinfo" */
+#endif /* _WIN32 */
 #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
 #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
@@ -198,100 +239,352 @@ 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;
+
+       /*
+        * 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;
+
+       /*
+        * Another thing that's allocated is the result of pcap_ether_aton();
+        * it must be freed with free().  This variable points to any
+        * address that would need to be freed.
+        */
+       u_char *e;
+
+       /*
+        * 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;
+
+       /*
+        * TRUE if we need variable length part of VLAN offset
+        */
+       int is_vlan_vloffset;
+
+       /*
+        * 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;
+};
+
+/*
+ * For use by routines outside this file.
+ */
+/* VARARGS */
+void
+bpf_set_error(compiler_state_t *cstate, const char *fmt, ...)
+{
+       va_list ap;
+
+       va_start(ap, fmt);
+       (void)pcap_vsnprintf(cstate->bpf_pcap->errbuf, PCAP_ERRBUF_SIZE,
+           fmt, ap);
+       va_end(ap);
+}
+
+/*
+ * For use *ONLY* in routines in this file.
+ */
+static void PCAP_NORETURN bpf_error(compiler_state_t *, const char *, ...)
+    PCAP_PRINTFLIKE(2, 3);
+
+/* VARARGS */
+static void PCAP_NORETURN
+bpf_error(compiler_state_t *cstate, const char *fmt, ...)
+{
+       va_list ap;
+
+       va_start(ap, fmt);
+       (void)pcap_vsnprintf(cstate->bpf_pcap->errbuf, PCAP_ERRBUF_SIZE,
+           fmt, ap);
+       va_end(ap);
+       longjmp(cstate->top_ctx, 1);
+       /*NOTREACHED*/
+}
+
+static int 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 *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);
+static void initchunks(compiler_state_t *cstate);
+static void *newchunk_nolongjmp(compiler_state_t *cstate, size_t);
+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);
+static struct block *gen_gateway(compiler_state_t *, const u_char *,
+    struct addrinfo *, 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_atmfield_code_internal(compiler_state_t *, int,
+    bpf_int32, bpf_u_int32, int);
+static struct block *gen_atmtype_llc(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_nolongjmp(compiler_state_t *cstate, size_t n)
 {
        struct chunk *cp;
        int k;
@@ -305,58 +598,78 @@ 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;
-               if (k >= NCHUNKS)
-                       bpf_error("out of memory");
+               ++cp;
+               k = ++cstate->cur_chunk;
+               if (k >= NCHUNKS) {
+                       bpf_set_error(cstate, "out of memory");
+                       return (NULL);
+               }
                size = CHUNK0SIZE << k;
                cp->m = (void *)malloc(size);
-               if (cp->m == NULL)
-                       bpf_error("out of memory");
+               if (cp->m == NULL) {
+                       bpf_set_error(cstate, "out of memory");
+                       return (NULL);
+               }
                memset((char *)cp->m, 0, size);
                cp->n_left = size;
-               if (n > size)
-                       bpf_error("out of memory");
+               if (n > size) {
+                       bpf_set_error(cstate, "out of memory");
+                       return (NULL);
+               }
        }
        cp->n_left -= n;
        return (void *)((char *)cp->m + cp->n_left);
 }
 
+static void *
+newchunk(compiler_state_t *cstate, size_t n)
+{
+       void *p;
+
+       p = newchunk_nolongjmp(cstate, n);
+       if (p == NULL) {
+               longjmp(cstate->top_ctx, 1);
+               /*NOTREACHED*/
+       }
+       return (p);
+}
+
 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.
+ * This is used by the lexical analyzer, so it can't longjmp; it just
+ * returns NULL on an allocation error, and the callers must check
+ * for it.
  */
 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_nolongjmp(cstate, n);
 
-       strlcpy(cp, s, n);
+       if (cp == NULL)
+               return (NULL);
+       pcap_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;
 
@@ -364,129 +677,178 @@ 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()
+static inline PCAP_NORETURN_DEF void
+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;
+#ifdef _WIN32
+       static int done = 0;
+#endif
+       compiler_state_t cstate;
        const char * volatile xbuf = buf;
+       yyscan_t scanner = NULL;
+       volatile 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.
+        * If this pcap_t hasn't been activated, it doesn't have a
+        * link-layer type, so we can't use it.
         */
-#ifdef WIN32
-       extern int wsockinit (void);
-       static int done = 0;
+       if (!p->activated) {
+               pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
+                   "not-yet-activated pcap_t passed to pcap_compile");
+               return (-1);
+       }
 
+#ifdef _WIN32
        if (!done)
-               wsockinit();
+               pcap_wsockinit();
        done = 1;
-       EnterCriticalSection(&g_PcapCompileCriticalSection);
 #endif
 
+#ifdef ENABLE_REMOTE
        /*
-        * If this pcap_t hasn't been activated, it doesn't have a
-        * link-layer type, so we can't use it.
+        * If the device on which we're capturing need to be notified
+        * that a new filter is being compiled, do so.
+        *
+        * This allows them to save a copy of it, in case, for example,
+        * they're implementing a form of remote packet capture, and
+        * want the remote machine to filter out the packets in which
+        * it's sending the packets it's captured.
+        *
+        * XXX - the fact that we happen to be compiling a filter
+        * doesn't necessarily mean we'll be installing it as the
+        * filter for this pcap_t; we might be running it from userland
+        * on captured packets to do packet classification.  We really
+        * need a better way of handling this, but this is all that
+        * the WinPcap remote capture code did.
         */
-       if (!p->activated) {
-               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 (p->save_current_filter_op != NULL)
+               (p->save_current_filter_op)(p, buf);
+#endif
 
-       if (setjmp(top_ctx)) {
+       initchunks(&cstate);
+       cstate.no_optimize = 0;
 #ifdef INET6
-               if (ai != NULL) {
-                       freeaddrinfo(ai);
-                       ai = NULL;
-               }
+       cstate.ai = NULL;
 #endif
-               lex_cleanup();
-               freechunks();
-               rc = -1;
-               goto quit;
-       }
+       cstate.e = NULL;
+       cstate.ic.root = NULL;
+       cstate.ic.cur_mark = 0;
+       cstate.bpf_pcap = p;
+       init_regs(&cstate);
 
-       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)
+               pcap_fmt_errmsg_for_errno(p->errbuf, PCAP_ERRBUF_SIZE,
+                   errno, "can't initialize scanner");
+       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();
+       if (init_linktype(&cstate, p) == -1) {
+               rc = -1;
+               goto quit;
+       }
+       if (pcap_parse(scanner, &cstate) != 0) {
+#ifdef INET6
+               if (cstate.ai != NULL)
+                       freeaddrinfo(cstate.ai);
+#endif
+               if (cstate.e != NULL)
+                       free(cstate.e);
+               rc = -1;
+               goto quit;
+       }
 
-       if (root == NULL)
-               root = gen_retblk(snaplen);
+       if (cstate.ic.root == NULL) {
+               /*
+                * Catch errors reported by gen_retblk().
+                */
+               if (setjmp(cstate.top_ctx)) {
+                       rc = -1;
+                       goto quit;
+               }
+               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) {
+               if (bpf_optimize(&cstate.ic, p->errbuf) == -1) {
+                       /* Failure */
+                       rc = -1;
+                       goto quit;
+               }
+               if (cstate.ic.root == NULL ||
+                   (cstate.ic.root->s.code == (BPF_RET|BPF_K) && cstate.ic.root->s.k == 0)) {
+                       (void)pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
+                           "expression rejects all packets");
+                       rc = -1;
+                       goto quit;
+               }
+       }
+       program->bf_insns = icode_to_fcode(&cstate.ic,
+           cstate.ic.root, &len, p->errbuf);
+       if (program->bf_insns == NULL) {
+               /* Failure */
+               rc = -1;
+               goto quit;
        }
-       program->bf_insns = icode_to_fcode(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);
 }
@@ -532,8 +894,7 @@ pcap_freecode(struct bpf_program *program)
  * in each block is already resolved.
  */
 static void
-backpatch(list, target)
-       struct block *list, *target;
+backpatch(struct block *list, struct block *target)
 {
        struct block *next;
 
@@ -554,8 +915,7 @@ backpatch(list, target)
  * which of jt and jf is the link.
  */
 static void
-merge(b0, b1)
-       struct block *b0, *b1;
+merge(struct block *b0, struct block *b1)
 {
        register struct block **p = &b0;
 
@@ -567,13 +927,19 @@ merge(b0, b1)
        *p = b1;
 }
 
-void
-finish_parse(p)
-       struct block *p;
+int
+finish_parse(compiler_state_t *cstate, struct block *p)
 {
        struct block *ppi_dlt_check;
 
        /*
+        * Catch errors reported by us and routines below us, and return -1
+        * on an error.
+        */
+       if (setjmp(cstate->top_ctx))
+               return (-1);
+
+       /*
         * Insert before the statements of the first (root) block any
         * statements needed to load the lengths of any variable-length
         * headers into registers.
@@ -592,25 +958,34 @@ 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;
+       return (0);
 }
 
 void
-gen_and(b0, b1)
-       struct block *b0, *b1;
+gen_and(struct block *b0, struct block *b1)
 {
        backpatch(b0, b1->head);
        b0->sense = !b0->sense;
@@ -621,8 +996,7 @@ gen_and(b0, b1)
 }
 
 void
-gen_or(b0, b1)
-       struct block *b0, *b1;
+gen_or(struct block *b0, struct block *b1)
 {
        b0->sense = !b0->sense;
        backpatch(b0, b1->head);
@@ -632,82 +1006,75 @@ gen_or(b0, b1)
 }
 
 void
-gen_not(b)
-       struct block *b;
+gen_not(struct block *b)
 {
        b->sense = !b->sense;
 }
 
 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;
 
+       /*
+        * XXX - the actual *instructions* do unsigned comparisons on
+        * most platforms, and the load instructions don't do sign
+        * extension, so gen_cmp() should really take an unsigned
+        * value argument.
+        *
+        * As the load instructons also don't do sign-extension, we
+        * fetch the values from the byte array as unsigned.  We don't
+        * want to use the signed versions of the extract calls.
+        */
        b = NULL;
        while (size >= 4) {
                register const u_char *p = &v[size - 4];
-               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,
+                   (bpf_int32)EXTRACT_32BITS(p));
                if (b != NULL)
                        gen_and(b, tmp);
                b = tmp;
@@ -715,16 +1082,16 @@ gen_bcmp(offrel, offset, size, v)
        }
        while (size >= 2) {
                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,
+                   (bpf_int32)EXTRACT_16BITS(p));
                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;
@@ -739,24 +1106,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))
@@ -764,294 +1129,157 @@ 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.
- */
+static int
+init_linktype(compiler_state_t *cstate, pcap_t *p)
+{
+       cstate->pcap_fddipad = p->fddipad;
 
-/*
- * 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;
+       /*
+        * 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;
 
-/*
- * 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;
+       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 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;
+       cstate->linktype = cstate->outermostlinktype;
+       cstate->off_linkhdr.constant_part = 0;
+       cstate->off_linkhdr.is_variable = 0;
+       cstate->off_linkhdr.reg = -1;
 
-/*
- * 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;
-
-/*
- * These are offsets for the MTP2 fields.
- */
-static u_int off_li;
-static u_int off_li_hsl;
-
-/*
- * These are offsets for the MTP3 fields.
- */
-static u_int off_sio;
-static u_int off_opc;
-static u_int off_dpc;
-static 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.
- */
-static u_int off_payload;
-
-/*
- * 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 = OFFSET_NOT_SET;
+       cstate->off_vci = OFFSET_NOT_SET;
+       cstate->off_proto = OFFSET_NOT_SET;
+       cstate->off_payload = OFFSET_NOT_SET;
 
        /*
-        * And that we're not doing PPPoE.
+        * And not Geneve.
         */
-       is_pppoes = 0;
+       cstate->is_geneve = 0;
 
        /*
-        * And assume we're not doing SS7.
+        * No variable length VLAN offset by default
         */
-       off_li = -1;
-       off_li_hsl = -1;
-       off_sio = -1;
-       off_opc = -1;
-       off_dpc = -1;
-       off_sls = -1;
+       cstate->is_vlan_vloffset = 0;
 
        /*
-        * Also assume it's not 802.11.
+        * And assume we're not doing SS7.
         */
-       off_ll = 0;
-       off_macpl = 0;
-       off_macpl_is_variable = 0;
+       cstate->off_li = OFFSET_NOT_SET;
+       cstate->off_li_hsl = OFFSET_NOT_SET;
+       cstate->off_sio = OFFSET_NOT_SET;
+       cstate->off_opc = OFFSET_NOT_SET;
+       cstate->off_dpc = OFFSET_NOT_SET;
+       cstate->off_sls = OFFSET_NOT_SET;
 
-       orig_linktype = -1;
-       orig_nl = -1;
-        label_stack_depth = 0;
+       cstate->label_stack_depth = 0;
+       cstate->vlan_stack_depth = 0;
 
-       reg_off_ll = -1;
-       reg_off_macpl = -1;
-
-       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:
                /*
@@ -1062,13 +1290,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:
                /*
@@ -1094,19 +1322,25 @@ 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. */
+               /* FALLTHROUGH */
+
+       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.
@@ -1121,12 +1355,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:
                /*
@@ -1138,12 +1372,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 */
@@ -1158,44 +1393,50 @@ 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;
-
-       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 = 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 v1 */
+               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_LINUX_SLL2:    /* fake header for Linux cooked socket v2 */
+               cstate->off_linktype.constant_part = 0;
+               cstate->off_linkpl.constant_part = 20;
+               cstate->off_nl = 0;
+               cstate->off_nl_nosnap = 0;      /* no 802.2 LLC */
+               break;
 
        case DLT_LTALK:
                /*
@@ -1203,11 +1444,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:
                /*
@@ -1220,22 +1461,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;
@@ -1243,33 +1484,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:
@@ -1278,324 +1519,305 @@ 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 = OFFSET_NOT_SET; /* 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 = OFFSET_NOT_SET; /* 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 = OFFSET_NOT_SET; /* 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 = OFFSET_NOT_SET;        /* not really a network layer but raw IP addresses */
+               cstate->off_nl_nosnap = OFFSET_NOT_SET; /* 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 = OFFSET_NOT_SET; /* 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 = OFFSET_NOT_SET;
+               cstate->off_nl_nosnap = OFFSET_NOT_SET;
+               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 = OFFSET_NOT_SET;        /* L3 proto location dep. on cookie type */
+               cstate->off_nl_nosnap = OFFSET_NOT_SET; /* 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 = OFFSET_NOT_SET;
+               cstate->off_nl_nosnap = OFFSET_NOT_SET;
+               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 = OFFSET_NOT_SET;
+               cstate->off_nl_nosnap = OFFSET_NOT_SET;
+               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 = OFFSET_NOT_SET;
+               cstate->off_nl_nosnap = OFFSET_NOT_SET;
+               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 = OFFSET_NOT_SET;
+               cstate->off_nl_nosnap = OFFSET_NOT_SET;
+               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 = OFFSET_NOT_SET;
+               cstate->off_nl_nosnap = OFFSET_NOT_SET;
+               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 = OFFSET_NOT_SET;
+               cstate->off_nl_nosnap = OFFSET_NOT_SET;
+               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 = OFFSET_NOT_SET;
+               cstate->off_nl_nosnap = OFFSET_NOT_SET;
+               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 = OFFSET_NOT_SET;        /* variable, min 16, max 71 steps of 7 */
+               cstate->off_nl_nosnap = OFFSET_NOT_SET; /* 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 = OFFSET_NOT_SET;
+               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 = OFFSET_NOT_SET;
+                       cstate->off_nl_nosnap = OFFSET_NOT_SET;
+               } else {
+                       bpf_set_error(cstate, "unknown data link type %d", cstate->linktype);
+                       return (-1);
                }
-
+               break;
        }
-       bpf_error("unknown data link type %d", linktype);
-       /* NOTREACHED */
+
+       cstate->off_outermostlinkhdr = cstate->off_prevlinkhdr = cstate->off_linkhdr;
+       return (0);
 }
 
 /*
- * 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.
+ * Load a value relative to the specified absolute offset.
  */
 static struct slist *
-gen_load_llrel(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_llprefixlen();
+       s = gen_abs_offset_varpart(cstate, abs_offset);
 
        /*
         * 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.
+        * 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 length of the prefix preceding the link-layer
-        * header is "off_ll".
+        * Otherwise, we can do an absolute load with an offset of
+        * abs_offset->constant_part + offset.
         */
        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.
+                * "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 {
                /*
-                * 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.
+                * 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 = offset + off_ll;
+               s = new_stmt(cstate, BPF_LD|BPF_ABS|size);
+               s->s.k = abs_offset->constant_part + offset;
        }
        return s;
 }
 
 /*
- * Load a value relative to the beginning of the MAC-layer payload.
+ * Load a value relative to the beginning of the specified header.
  */
 static struct slist *
-gen_load_macplrel(offset, size)
-       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;
 
-       s = gen_off_macpl();
-
        /*
-        * 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.
+        * Squelch warnings from compilers that *don't* assume that
+        * offrel always has a valid enum value and therefore don't
+        * assume that we'll always go through one of the case arms.
         *
-        * Otherwise, the offset of the MAC-layer payload is constant,
-        * and is in off_macpl.
+        * If we have a default case, compilers that *do* assume that
+        * will then complain about the default case code being
+        * unreachable.
+        *
+        * Damned if you do, damned if you don't.
         */
-       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.
-                */
-               s2 = new_stmt(BPF_LD|BPF_IND|size);
-               s2->s.k = 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.
-                */
-               s = new_stmt(BPF_LD|BPF_ABS|size);
-               s->s.k = off_macpl + offset;
-       }
-       return s;
-}
-
-/*
- * 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;
-{
-       struct slist *s, *s2;
+       s = NULL;
 
        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_PREVLINKHDR:
+               s = gen_load_absoffsetrel(cstate, &cstate->off_prevlinkhdr, offset, size);
                break;
 
-       case OR_MACPL:
-               s = gen_load_macplrel(offset, size);
+       case OR_LLC:
+               s = gen_load_absoffsetrel(cstate, &cstate->off_linkpl, offset, size);
                break;
 
-       case OR_NET:
-               s = gen_load_macplrel(off_nl + offset, size);
+       case OR_PREVMPLSHDR:
+               s = gen_load_absoffsetrel(cstate, &cstate->off_linkpl, cstate->off_nl - 4 + offset, size);
                break;
 
-       case OR_NET_NOSNAP:
-               s = gen_load_macplrel(off_nl_nosnap + offset, size);
+       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:
@@ -1605,117 +1827,115 @@ 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:
-               abort();
-               return NULL;
        }
        return s;
 }
 
 /*
  * 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);
 }
 
 /*
@@ -1736,8 +1956,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;
 
@@ -1758,9 +1977,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;
@@ -1798,22 +2017,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);
 
                /*
@@ -1829,8 +2048,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;
 
@@ -1846,7 +2064,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);
 
                /*
@@ -1861,9 +2079,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);
 
                /*
@@ -1871,7 +2089,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;
@@ -1886,10 +2104,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 {
@@ -1902,37 +2119,70 @@ 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);
-               /* NOTREACHED */
+               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 */
+               /*NOTREACHED*/
 
        default:
                break;
        }
 
-       return gen_false();
+       return gen_false(cstate);
 }
 
 /*
@@ -1944,8 +2194,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;
 
@@ -1966,8 +2215,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;
@@ -1998,17 +2247,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);
 
                /*
@@ -2016,8 +2265,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;
 
@@ -2033,7 +2281,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
@@ -2047,9 +2295,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);
 
                /*
@@ -2057,7 +2305,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;
@@ -2071,9 +2319,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;
@@ -2087,14 +2334,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;
@@ -2105,7 +2351,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
@@ -2126,24 +2372,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);
 
@@ -2154,7 +2400,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;
@@ -2167,7 +2413,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);
 
@@ -2177,7 +2423,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;
@@ -2187,15 +2433,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);
@@ -2204,7 +2450,7 @@ gen_load_prism_llprefixlen()
 }
 
 static struct slist *
-gen_load_avs_llprefixlen()
+gen_load_avs_llprefixlen(compiler_state_t *cstate)
 {
        struct slist *s1, *s2;
 
@@ -2215,27 +2461,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);
@@ -2244,7 +2490,7 @@ gen_load_avs_llprefixlen()
 }
 
 static struct slist *
-gen_load_radiotap_llprefixlen()
+gen_load_radiotap_llprefixlen(compiler_state_t *cstate)
 {
        struct slist *s1, *s2;
 
@@ -2255,7 +2501,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
@@ -2267,36 +2513,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);
@@ -2314,7 +2560,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;
 
@@ -2323,7 +2569,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
@@ -2335,36 +2581,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);
@@ -2380,21 +2626,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.
                 */
@@ -2406,7 +2653,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
@@ -2414,7 +2661,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) {
                /*
@@ -2423,30 +2670,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);
 
@@ -2455,7 +2702,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);
 
@@ -2463,7 +2710,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;
@@ -2474,24 +2721,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);
 
        /*
@@ -2503,32 +2750,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
@@ -2539,11 +2808,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);
 
@@ -2555,11 +2825,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);
 
@@ -2570,17 +2841,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;
@@ -2594,33 +2865,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:
@@ -2630,21 +2914,43 @@ 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;
        }
 
        /*
+        * If there there is no initialization yet and we need variable
+        * length offsets for VLAN, initialize them to zero
+        */
+       if (s == NULL && cstate->is_vlan_vloffset) {
+               struct slist *s2;
+
+               if (cstate->off_linkpl.reg == -1)
+                       cstate->off_linkpl.reg = alloc_reg(cstate);
+               if (cstate->off_linktype.reg == -1)
+                       cstate->off_linktype.reg = alloc_reg(cstate);
+
+               s = new_stmt(cstate, BPF_LD|BPF_W|BPF_IMM);
+               s->s.k = 0;
+               s2 = new_stmt(cstate, BPF_ST);
+               s2->s.k = cstate->off_linkpl.reg;
+               sappend(s, s2);
+               s2 = new_stmt(cstate, BPF_ST);
+               s2->s.k = cstate->off_linktype.reg;
+               sappend(s, s2);
+       }
+
+       /*
         * If we have any offset-loading code, append all the
         * existing statements in the block to those statements,
         * and make the resulting list the list of statements
@@ -2657,19 +2963,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);
@@ -2682,181 +2988,65 @@ gen_ppi_dlt_check(void)
        return b;
 }
 
+/*
+ * 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_prism_llprefixlen(void)
+gen_abs_offset_varpart(compiler_state_t *cstate, bpf_abs_offset *off)
 {
        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 (off->is_variable) {
+               if (off->reg == -1) {
+                       /*
+                        * We haven't yet assigned a register for the
+                        * variable part of the offset of the link-layer
+                        * header; allocate one.
+                        */
+                       off->reg = alloc_reg(cstate);
+               }
 
-       if (reg_off_ll == -1) {
                /*
-                * We haven't yet assigned a register for the length
-                * of the AVS header; allocate one.
+                * Load the register containing the variable part of the
+                * offset of the link-layer header into the X register.
                 */
-               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) {
+               s = new_stmt(cstate, BPF_LDX|BPF_MEM);
+               s->s.k = off->reg;
+               return s;
+       } else {
                /*
-                * We haven't yet assigned a register for the length
-                * of the radiotap header; allocate one.
+                * That offset isn't variable, there's no variable part,
+                * so we don't need to generate any code.
                 */
-               reg_off_ll = alloc_reg();
+               return NULL;
        }
-
-       /*
-        * 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.
+ * Map an Ethernet type to the equivalent PPP type.
  */
-static struct slist *
-gen_ppi_llprefixlen(void)
+static int
+ethertype_to_ppptype(int proto)
 {
-       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();
-       }
+       switch (proto) {
 
-       /*
-        * 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;
-}
+       case ETHERTYPE_IP:
+               proto = PPP_IP;
+               break;
 
-/*
- * 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.
- */
-static struct slist *
-gen_off_macpl(void)
-{
-       struct slist *s;
-
-       if (off_macpl_is_variable) {
-               if (reg_off_macpl == -1) {
-                       /*
-                        * We haven't yet assigned a register for the offset
-                        * of the MAC-layer payload; allocate one.
-                        */
-                       reg_off_macpl = alloc_reg();
-               }
-
-               /*
-                * Load the register containing the offset of the MAC-layer
-                * payload into the X register.
-                */
-               s = new_stmt(BPF_LDX|BPF_MEM);
-               s->s.k = reg_off_macpl;
-               return s;
-       } else {
-               /*
-                * That offset isn't variable, so we don't need to
-                * generate any code.
-                */
-               return NULL;
-       }
-}
-
-/*
- * Map an Ethernet type to the equivalent PPP type.
- */
-static int
-ethertype_to_ppptype(proto)
-       int proto;
-{
-       switch (proto) {
-
-       case ETHERTYPE_IP:
-               proto = PPP_IP;
-               break;
-
-       case ETHERTYPE_IPV6:
-               proto = PPP_IPV6;
-               break;
+       case ETHERTYPE_IPV6:
+               proto = PPP_IPV6;
+               break;
 
        case ETHERTYPE_DN:
                proto = PPP_DECNET;
@@ -2891,6 +3081,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      /* macOS, 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.
  *
@@ -2898,57 +3133,47 @@ 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");
-                       /* NOTREACHED */
+                       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;
 
        case DLT_C_HDLC:
                switch (proto) {
@@ -2958,12 +3183,9 @@ 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;
                }
-               break;
 
        case DLT_IEEE802_11:
        case DLT_PRISM_HEADER:
@@ -2973,81 +3195,53 @@ 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*/
-               break;
 
        case DLT_FDDI:
                /*
                 * XXX - check for LLC frames.
                 */
-               return gen_llc_linktype(proto);
+               return gen_llc_linktype(cstate, proto);
                /*NOTREACHED*/
-               break;
 
        case DLT_IEEE802:
                /*
                 * 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_internal(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;
 
        case DLT_SLIP:
        case DLT_SLIP_BSDOS:
@@ -3063,41 +3257,38 @@ 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;
 
        case DLT_IPV4:
                /*
                 * 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;
 
        case DLT_IPV6:
                /*
                 * 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;
 
        case DLT_PPP:
        case DLT_PPP_PPPD:
@@ -3108,9 +3299,8 @@ 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;
 
        case DLT_PPP_BSDOS:
                /*
@@ -3124,57 +3314,88 @@ 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*/
-               break;
 
        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:
                        /*
@@ -3182,27 +3403,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:
@@ -3211,15 +3413,14 @@ 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 */
 
        case DLT_ARCNET:
@@ -3231,48 +3432,46 @@ 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*/
-               break;
 
        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;
 
        case DLT_FRELAY:
                /*
@@ -3285,13 +3484,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:
                        /*
@@ -3305,21 +3504,20 @@ 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:
@@ -3351,93 +3549,101 @@ 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");
+       case DLT_IPMB_KONTRON:
+       case DLT_IPMB_LINUX:
+               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");
-       }
-
-       /*
-        * All the types that have no encapsulation should either be
-        * handled as DLT_SLIP, DLT_SLIP_BSDOS, and DLT_RAW are, if
-        * all packets are IP packets, or should be handled in some
-        * special case, if none of them are (if some are and some
-        * aren't, the lack of encapsulation is a problem, as we'd
-        * have to find some other way of determining the packet type).
-        *
-        * Therefore, if "off_linktype" is -1, there's an error.
-        */
-       if (off_linktype == (u_int)-1)
-               abort();
+               bpf_error(cstate, "NFLOG link-layer type filtering not implemented");
 
-       /*
-        * Any type not handled above should always have an Ethernet
-        * type at an offset of "off_linktype".
-        */
-       return gen_cmp(OR_LINK, off_linktype, BPF_H, (bpf_int32)proto);
+       default:
+               /*
+                * Does this link-layer header type have a field
+                * indicating the type of the next protocol?  If
+                * so, off_linktype.constant_part will be the offset of that
+                * field in the packet; if not, it will be OFFSET_NOT_SET.
+                */
+               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(cstate, OR_LINKTYPE, 0, BPF_H, (bpf_int32)proto);
+                       /*NOTREACHED */
+               } else {
+                       /*
+                        * No; report an error.
+                        */
+                       description = pcap_datalink_val_to_description_or_dlt(cstate->linktype);
+                       bpf_error(cstate, "%s link-layer type filtering not implemented",
+                           description);
+                       /*NOTREACHED */
+               }
+       }
 }
 
 /*
@@ -3448,46 +3654,44 @@ 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];
 
-       snapblock[0] = LLCSAP_SNAP;     /* DSAP = SNAP */
-       snapblock[1] = LLCSAP_SNAP;     /* SSAP = SNAP */
-       snapblock[2] = 0x03;            /* control = UI */
-       snapblock[3] = (orgcode >> 16); /* upper 8 bits of organization code */
-       snapblock[4] = (orgcode >> 8);  /* middle 8 bits of organization code */
-       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);
+       snapblock[0] = LLCSAP_SNAP;             /* DSAP = SNAP */
+       snapblock[1] = LLCSAP_SNAP;             /* SSAP = SNAP */
+       snapblock[2] = 0x03;                    /* control = UI */
+       snapblock[3] = (u_char)(orgcode >> 16); /* upper 8 bits of organization code */
+       snapblock[4] = (u_char)(orgcode >> 8);  /* middle 8 bits of organization code */
+       snapblock[5] = (u_char)(orgcode >> 0);  /* lower 8 bits of organization code */
+       snapblock[6] = (u_char)(ptype >> 8);    /* upper 8 bits of protocol type */
+       snapblock[7] = (u_char)(ptype >> 0);    /* lower 8 bits of protocol type */
+       return gen_bcmp(cstate, OR_LLC, 0, 8, snapblock);
 }
 
 /*
  * Generate code to match frames with an LLC header.
  */
-struct block *
-gen_llc(void)
+static struct block *
+gen_llc_internal(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;
@@ -3496,20 +3700,20 @@ gen_llc(void)
                /*
                 * We check for LLC traffic.
                 */
-               b0 = gen_atmtype_abbrev(A_LLC);
+               b0 = gen_atmtype_llc(cstate);
                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:
                /*
@@ -3520,7 +3724,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:
@@ -3530,32 +3734,53 @@ 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);
-               /* NOTREACHED */
+               bpf_error(cstate, "'llc' not supported for %s",
+                         pcap_datalink_val_to_description_or_dlt(cstate->linktype));
+               /*NOTREACHED*/
        }
 }
 
 struct block *
-gen_llc_i(void)
+gen_llc(compiler_state_t *cstate)
+{
+       /*
+        * Catch errors reported by us and routines below us, and return NULL
+        * on an error.
+        */
+       if (setjmp(cstate->top_ctx))
+               return (NULL);
+
+       return gen_llc_internal(cstate);
+}
+
+struct block *
+gen_llc_i(compiler_state_t *cstate)
 {
        struct block *b0, *b1;
        struct slist *s;
 
        /*
+        * Catch errors reported by us and routines below us, and return NULL
+        * on an error.
+        */
+       if (setjmp(cstate->top_ctx))
+               return (NULL);
+
+       /*
         * Check whether this is an LLC frame.
         */
-       b0 = gen_llc();
+       b0 = gen_llc_internal(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);
@@ -3564,75 +3789,103 @@ gen_llc_i(void)
 }
 
 struct block *
-gen_llc_s(void)
+gen_llc_s(compiler_state_t *cstate)
 {
        struct block *b0, *b1;
 
        /*
+        * Catch errors reported by us and routines below us, and return NULL
+        * on an error.
+        */
+       if (setjmp(cstate->top_ctx))
+               return (NULL);
+
+       /*
         * Check whether this is an LLC frame.
         */
-       b0 = gen_llc();
+       b0 = gen_llc_internal(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;
 
        /*
+        * Catch errors reported by us and routines below us, and return NULL
+        * on an error.
+        */
+       if (setjmp(cstate->top_ctx))
+               return (NULL);
+
+       /*
         * Check whether this is an LLC frame.
         */
-       b0 = gen_llc();
+       b0 = gen_llc_internal(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;
 
        /*
+        * Catch errors reported by us and routines below us, and return NULL
+        * on an error.
+        */
+       if (setjmp(cstate->top_ctx))
+               return (NULL);
+
+       /*
         * Check whether this is an LLC frame.
         */
-       b0 = gen_llc();
+       b0 = gen_llc_internal(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;
 
        /*
+        * Catch errors reported by us and routines below us, and return NULL
+        * on an error.
+        */
+       if (setjmp(cstate->top_ctx))
+               return (NULL);
+
+       /*
         * Check whether this is an LLC frame.
         */
-       b0 = gen_llc();
+       b0 = gen_llc_internal(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;
 }
@@ -3650,8 +3903,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.
@@ -3664,10 +3916,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:
@@ -3675,7 +3926,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:
@@ -3688,7 +3939,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:
                /*
@@ -3700,7 +3951,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
@@ -3715,23 +3966,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;
@@ -3747,38 +3995,60 @@ 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);
+       case Q_OR:
+               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;
 
+       case Q_ADDR1:
+               bpf_error(cstate, "'addr1' and 'address1' are not valid qualifiers for addresses other than 802.11 MAC addresses");
+               /*NOTREACHED*/
+
+       case Q_ADDR2:
+               bpf_error(cstate, "'addr2' and 'address2' are not valid qualifiers for addresses other than 802.11 MAC addresses");
+               /*NOTREACHED*/
+
+       case Q_ADDR3:
+               bpf_error(cstate, "'addr3' and 'address3' are not valid qualifiers for addresses other than 802.11 MAC addresses");
+               /*NOTREACHED*/
+
+       case Q_ADDR4:
+               bpf_error(cstate, "'addr4' and 'address4' are not valid qualifiers for addresses other than 802.11 MAC addresses");
+               /*NOTREACHED*/
+
+       case Q_RA:
+               bpf_error(cstate, "'ra' is not a valid qualifier for addresses other than 802.11 MAC addresses");
+               /*NOTREACHED*/
+
+       case Q_TA:
+               bpf_error(cstate, "'ta' is not a valid qualifier for addresses other than 802.11 MAC addresses");
+               /*NOTREACHED*/
+
        default:
                abort();
+               /*NOTREACHED*/
        }
-       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;
-       u_int32_t *a, *m;
+       uint32_t *a, *m;
 
        switch (dir) {
 
@@ -3791,206 +4061,225 @@ 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);
+       case Q_OR:
+               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;
 
+       case Q_ADDR1:
+               bpf_error(cstate, "'addr1' and 'address1' are not valid qualifiers for addresses other than 802.11 MAC addresses");
+               /*NOTREACHED*/
+
+       case Q_ADDR2:
+               bpf_error(cstate, "'addr2' and 'address2' are not valid qualifiers for addresses other than 802.11 MAC addresses");
+               /*NOTREACHED*/
+
+       case Q_ADDR3:
+               bpf_error(cstate, "'addr3' and 'address3' are not valid qualifiers for addresses other than 802.11 MAC addresses");
+               /*NOTREACHED*/
+
+       case Q_ADDR4:
+               bpf_error(cstate, "'addr4' and 'address4' are not valid qualifiers for addresses other than 802.11 MAC addresses");
+               /*NOTREACHED*/
+
+       case Q_RA:
+               bpf_error(cstate, "'ra' is not a valid qualifier for addresses other than 802.11 MAC addresses");
+               /*NOTREACHED*/
+
+       case Q_TA:
+               bpf_error(cstate, "'ta' is not a valid qualifier for addresses other than 802.11 MAC addresses");
+               /*NOTREACHED*/
+
        default:
                abort();
+               /*NOTREACHED*/
        }
        /* 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]));
+       a = (uint32_t *)addr;
+       m = (uint32_t *)mask;
+       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");
-               break;
+               bpf_error(cstate, "'addr1' and 'address1' are only supported on 802.11 with 802.11 headers");
+               /*NOTREACHED*/
 
        case Q_ADDR2:
-               bpf_error("'addr2' is only supported on 802.11 with 802.11 headers");
-               break;
+               bpf_error(cstate, "'addr2' and 'address2' are only supported on 802.11 with 802.11 headers");
+               /*NOTREACHED*/
 
        case Q_ADDR3:
-               bpf_error("'addr3' is only supported on 802.11 with 802.11 headers");
-               break;
+               bpf_error(cstate, "'addr3' and 'address3' are only supported on 802.11 with 802.11 headers");
+               /*NOTREACHED*/
 
        case Q_ADDR4:
-               bpf_error("'addr4' is only supported on 802.11 with 802.11 headers");
-               break;
+               bpf_error(cstate, "'addr4' and 'address4' are only supported on 802.11 with 802.11 headers");
+               /*NOTREACHED*/
 
        case Q_RA:
-               bpf_error("'ra' is only supported on 802.11 with 802.11 headers");
-               break;
+               bpf_error(cstate, "'ra' is only supported on 802.11 with 802.11 headers");
+               /*NOTREACHED*/
 
        case Q_TA:
-               bpf_error("'ta' is only supported on 802.11 with 802.11 headers");
-               break;
+               bpf_error(cstate, "'ta' is only supported on 802.11 with 802.11 headers");
+               /*NOTREACHED*/
        }
        abort();
-       /* NOTREACHED */
+       /*NOTREACHED*/
 }
 
 /*
  * 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");
-               break;
+               bpf_error(cstate, "'addr1' and 'address1' are only supported on 802.11");
+               /*NOTREACHED*/
 
        case Q_ADDR2:
-               bpf_error("'addr2' is only supported on 802.11");
-               break;
+               bpf_error(cstate, "'addr2' and 'address2' are only supported on 802.11");
+               /*NOTREACHED*/
 
        case Q_ADDR3:
-               bpf_error("'addr3' is only supported on 802.11");
-               break;
+               bpf_error(cstate, "'addr3' and 'address3' are only supported on 802.11");
+               /*NOTREACHED*/
 
        case Q_ADDR4:
-               bpf_error("'addr4' is only supported on 802.11");
-               break;
+               bpf_error(cstate, "'addr4' and 'address4' are only supported on 802.11");
+               /*NOTREACHED*/
 
        case Q_RA:
-               bpf_error("'ra' is only supported on 802.11");
-               break;
+               bpf_error(cstate, "'ra' is only supported on 802.11");
+               /*NOTREACHED*/
 
        case Q_TA:
-               bpf_error("'ta' is only supported on 802.11");
-               break;
+               bpf_error(cstate, "'ta' is only supported on 802.11");
+               /*NOTREACHED*/
        }
        abort();
-       /* NOTREACHED */
+       /*NOTREACHED*/
 }
 
 /*
  * 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");
-               break;
+               bpf_error(cstate, "'addr1' and 'address1' are only supported on 802.11");
+               /*NOTREACHED*/
 
        case Q_ADDR2:
-               bpf_error("'addr2' is only supported on 802.11");
-               break;
+               bpf_error(cstate, "'addr2' and 'address2' are only supported on 802.11");
+               /*NOTREACHED*/
 
        case Q_ADDR3:
-               bpf_error("'addr3' is only supported on 802.11");
-               break;
+               bpf_error(cstate, "'addr3' and 'address3' are only supported on 802.11");
+               /*NOTREACHED*/
 
        case Q_ADDR4:
-               bpf_error("'addr4' is only supported on 802.11");
-               break;
+               bpf_error(cstate, "'addr4' and 'address4' are only supported on 802.11");
+               /*NOTREACHED*/
 
        case Q_RA:
-               bpf_error("'ra' is only supported on 802.11");
-               break;
+               bpf_error(cstate, "'ra' is only supported on 802.11");
+               /*NOTREACHED*/
 
        case Q_TA:
-               bpf_error("'ta' is only supported on 802.11");
-               break;
+               bpf_error(cstate, "'ta' is only supported on 802.11");
+               /*NOTREACHED*/
        }
        abort();
-       /* NOTREACHED */
+       /*NOTREACHED*/
 }
 
 /*
@@ -3998,9 +4287,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;
@@ -4012,7 +4299,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) {
@@ -4042,23 +4329,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);
@@ -4066,7 +4353,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);
 
                /*
@@ -4080,8 +4367,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);
@@ -4089,8 +4376,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);
@@ -4098,7 +4385,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);
 
                /*
@@ -4112,8 +4399,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;
 
@@ -4127,8 +4414,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);
@@ -4136,7 +4423,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);
 
                /*
@@ -4154,8 +4441,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);
@@ -4189,23 +4476,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);
@@ -4213,7 +4500,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);
 
                /*
@@ -4226,8 +4513,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;
 
@@ -4241,8 +4528,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);
@@ -4250,7 +4537,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);
 
                /*
@@ -4268,8 +4555,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);
@@ -4281,6 +4568,68 @@ gen_wlanhostop(eaddr, dir)
                gen_and(b1, b0);
                return b0;
 
+       case Q_AND:
+               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(cstate, eaddr, Q_SRC);
+               b1 = gen_wlanhostop(cstate, eaddr, Q_DST);
+               gen_or(b0, b1);
+               return b1;
+
+       /*
+        * XXX - add BSSID keyword?
+        */
+       case Q_ADDR1:
+               return (gen_bcmp(cstate, OR_LINKHDR, 4, 6, eaddr));
+
+       case Q_ADDR2:
+               /*
+                * Not present in CTS or ACK control frames.
+                */
+               b0 = gen_mcmp(cstate, OR_LINKHDR, 0, BPF_B, IEEE80211_FC0_TYPE_CTL,
+                       IEEE80211_FC0_TYPE_MASK);
+               gen_not(b0);
+               b1 = gen_mcmp(cstate, OR_LINKHDR, 0, BPF_B, IEEE80211_FC0_SUBTYPE_CTS,
+                       IEEE80211_FC0_SUBTYPE_MASK);
+               gen_not(b1);
+               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(cstate, OR_LINKHDR, 10, 6, eaddr);
+               gen_and(b2, b1);
+               return b1;
+
+       case Q_ADDR3:
+               /*
+                * Not present in control frames.
+                */
+               b0 = gen_mcmp(cstate, OR_LINKHDR, 0, BPF_B, IEEE80211_FC0_TYPE_CTL,
+                       IEEE80211_FC0_TYPE_MASK);
+               gen_not(b0);
+               b1 = gen_bcmp(cstate, OR_LINKHDR, 16, 6, eaddr);
+               gen_and(b0, b1);
+               return b1;
+
+       case Q_ADDR4:
+               /*
+                * Present only if the direction mask has both "From DS"
+                * and "To DS" set.  Neither control frames nor management
+                * frames should have both of those set, so we don't
+                * check the frame type.
+                */
+               b0 = gen_mcmp(cstate, OR_LINKHDR, 1, BPF_B,
+                       IEEE80211_FC1_DIR_DSTODS, IEEE80211_FC1_DIR_MASK);
+               b1 = gen_bcmp(cstate, OR_LINKHDR, 24, 6, eaddr);
+               gen_and(b0, b1);
+               return b1;
+
        case Q_RA:
                /*
                 * Not present in management frames; addr1 in other
@@ -4292,15 +4641,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.
@@ -4317,13 +4666,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);
@@ -4334,8 +4683,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;
 
@@ -4348,74 +4697,12 @@ gen_wlanhostop(eaddr, dir)
                /*
                 * Check addr2.
                 */
-               b1 = gen_bcmp(OR_LINK, 10, 6, eaddr);
-               gen_and(b2, b1);
-               return b1;
-
-       /*
-        * XXX - add BSSID keyword?
-        */
-       case Q_ADDR1:
-               return (gen_bcmp(OR_LINK, 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,
-                       IEEE80211_FC0_TYPE_MASK);
-               gen_not(b0);
-               b1 = gen_mcmp(OR_LINK, 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,
-                       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;
-
-       case Q_ADDR3:
-               /*
-                * Not present in control frames.
-                */
-               b0 = gen_mcmp(OR_LINK, 0, BPF_B, IEEE80211_FC0_TYPE_CTL,
-                       IEEE80211_FC0_TYPE_MASK);
-               gen_not(b0);
-               b1 = gen_bcmp(OR_LINK, 16, 6, eaddr);
-               gen_and(b0, b1);
-               return b1;
-
-       case Q_ADDR4:
-               /*
-                * Present only if the direction mask has both "From DS"
-                * and "To DS" set.  Neither control frames nor management
-                * frames should have both of those set, so we don't
-                * check the frame type.
-                */
-               b0 = gen_mcmp(OR_LINK, 1, BPF_B,
-                       IEEE80211_FC1_DIR_DSTODS, IEEE80211_FC1_DIR_MASK);
-               b1 = gen_bcmp(OR_LINK, 24, 6, eaddr);
-               gen_and(b0, b1);
-               return b1;
-
-       case Q_AND:
-               b0 = gen_wlanhostop(eaddr, Q_SRC);
-               b1 = gen_wlanhostop(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);
-               gen_or(b0, b1);
-               return b1;
        }
        abort();
-       /* NOTREACHED */
+       /*NOTREACHED*/
 }
 
 /*
@@ -4424,58 +4711,56 @@ 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");
-               break;
+               bpf_error(cstate, "'addr1' and 'address1' are only supported on 802.11");
+               /*NOTREACHED*/
 
        case Q_ADDR2:
-               bpf_error("'addr2' is only supported on 802.11");
-               break;
+               bpf_error(cstate, "'addr2' and 'address2' are only supported on 802.11");
+               /*NOTREACHED*/
 
        case Q_ADDR3:
-               bpf_error("'addr3' is only supported on 802.11");
-               break;
+               bpf_error(cstate, "'addr3' and 'address3' are only supported on 802.11");
+               /*NOTREACHED*/
 
        case Q_ADDR4:
-               bpf_error("'addr4' is only supported on 802.11");
-               break;
+               bpf_error(cstate, "'addr4' and 'address4' are only supported on 802.11");
+               /*NOTREACHED*/
 
        case Q_RA:
-               bpf_error("'ra' is only supported on 802.11");
-               break;
+               bpf_error(cstate, "'ra' is only supported on 802.11");
+               /*NOTREACHED*/
 
        case Q_TA:
-               bpf_error("'ta' is only supported on 802.11");
-               break;
+               bpf_error(cstate, "'ta' is only supported on 802.11");
+               /*NOTREACHED*/
        }
        abort();
-       /* NOTREACHED */
+       /*NOTREACHED*/
 }
 
 /*
@@ -4497,9 +4782,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 */
@@ -4519,50 +4802,72 @@ 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:
+       case Q_OR:
                /* 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");
+       case Q_ADDR1:
+               bpf_error(cstate, "'addr1' and 'address1' are not valid qualifiers for addresses other than 802.11 MAC addresses");
+               /*NOTREACHED*/
+
+       case Q_ADDR2:
+               bpf_error(cstate, "'addr2' and 'address2' are not valid qualifiers for addresses other than 802.11 MAC addresses");
+               /*NOTREACHED*/
+
+       case Q_ADDR3:
+               bpf_error(cstate, "'addr3' and 'address3' are not valid qualifiers for addresses other than 802.11 MAC addresses");
+               /*NOTREACHED*/
+
+       case Q_ADDR4:
+               bpf_error(cstate, "'addr4' and 'address4' are not valid qualifiers for addresses other than 802.11 MAC addresses");
+               /*NOTREACHED*/
+
+       case Q_RA:
+               bpf_error(cstate, "'ra' is not a valid qualifier for addresses other than 802.11 MAC addresses");
+               /*NOTREACHED*/
+
+       case Q_TA:
+               bpf_error(cstate, "'ta' is not a valid qualifier for addresses other than 802.11 MAC addresses");
+               /*NOTREACHED*/
 
        default:
                abort();
+               /*NOTREACHED*/
        }
-       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;
 }
@@ -4573,8 +4878,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;
 
@@ -4582,17 +4886,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, (u_int)-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, (u_int)-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;
 
@@ -4602,12 +4906,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;
@@ -4620,126 +4920,146 @@ 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_LINK:
+               bpf_error(cstate, "link-layer modifier applied to %s", typestr);
+
        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);
-
-       case Q_TCP:
-               bpf_error("'tcp' modifier applied to %s", typestr);
+               return gen_hostop(cstate, addr, mask, dir, ETHERTYPE_ARP, 14, 24);
 
        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(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);
-
-       case Q_PIM:
-               bpf_error("'pim' modifier applied to %s", typestr);
-
-       case Q_VRRP:
-               bpf_error("'vrrp' modifier applied to %s", typestr);
-
-       case Q_CARP:
-               bpf_error("'carp' modifier applied to %s", typestr);
+               bpf_error(cstate, "'igrp' modifier applied to %s", typestr);
 
        case Q_ATALK:
-               bpf_error("ATALK host filtering not implemented");
-
-       case Q_AARP:
-               bpf_error("AARP host filtering not implemented");
+               bpf_error(cstate, "AppleTalk host filtering not implemented");
 
        case Q_DECNET:
-               return gen_dnhostop(addr, dir);
-
-       case Q_SCA:
-               bpf_error("SCA host filtering not implemented");
+               return gen_dnhostop(cstate, addr, dir);
 
        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");
+       case Q_SCA:
+               bpf_error(cstate, "SCA host filtering not implemented");
 
        case Q_MOPRC:
-               bpf_error("MOPRC host filtering not implemented");
+               bpf_error(cstate, "MOPRC host filtering not implemented");
+
+       case Q_MOPDL:
+               bpf_error(cstate, "MOPDL 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_PIM:
+               bpf_error(cstate, "'pim' modifier applied to %s", typestr);
+
+       case Q_VRRP:
+               bpf_error(cstate, "'vrrp' modifier applied to %s", typestr);
+
+       case Q_AARP:
+               bpf_error(cstate, "AARP host filtering not implemented");
 
        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_ISIS_L1:
+               bpf_error(cstate, "'l1' modifier applied to %s", typestr);
+
+       case Q_ISIS_L2:
+               bpf_error(cstate, "'l2' modifier applied to %s", typestr);
+
+       case Q_ISIS_IIH:
+               bpf_error(cstate, "'iih' modifier applied to %s", typestr);
+
+       case Q_ISIS_SNP:
+               bpf_error(cstate, "'snp' modifier applied to %s", typestr);
+
+       case Q_ISIS_CSNP:
+               bpf_error(cstate, "'csnp' modifier applied to %s", typestr);
+
+       case Q_ISIS_PSNP:
+               bpf_error(cstate, "'psnp' modifier applied to %s", typestr);
+
+       case Q_ISIS_LSP:
+               bpf_error(cstate, "'lsp' 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);
+
+       case Q_CARP:
+               bpf_error(cstate, "'carp' modifier applied to %s", typestr);
 
        default:
                abort();
        }
-       /* NOTREACHED */
+       /*NOTREACHED*/
 }
 
 #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;
 
@@ -4751,193 +5071,241 @@ 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 ip6 %s", typestr);
 
        case Q_TCP:
-               bpf_error("'tcp' modifier applied to %s", typestr);
+               bpf_error(cstate, "'tcp' modifier applied to ip6 %s", typestr);
 
        case Q_UDP:
-               bpf_error("'udp' modifier applied to %s", typestr);
+               bpf_error(cstate, "'udp' modifier applied to ip6 %s", typestr);
 
        case Q_ICMP:
-               bpf_error("'icmp' modifier applied to %s", typestr);
+               bpf_error(cstate, "'icmp' modifier applied to ip6 %s", typestr);
 
        case Q_IGMP:
-               bpf_error("'igmp' modifier applied to %s", typestr);
+               bpf_error(cstate, "'igmp' modifier applied to ip6 %s", typestr);
 
        case Q_IGRP:
-               bpf_error("'igrp' modifier applied to %s", typestr);
-
-       case Q_PIM:
-               bpf_error("'pim' modifier applied to %s", typestr);
-
-       case Q_VRRP:
-               bpf_error("'vrrp' modifier applied to %s", typestr);
-
-       case Q_CARP:
-               bpf_error("'carp' modifier applied to %s", typestr);
+               bpf_error(cstate, "'igrp' modifier applied to ip6 %s", typestr);
 
        case Q_ATALK:
-               bpf_error("ATALK host filtering not implemented");
-
-       case Q_AARP:
-               bpf_error("AARP host filtering not implemented");
+               bpf_error(cstate, "AppleTalk modifier applied to ip6 %s", typestr);
 
        case Q_DECNET:
-               bpf_error("'decnet' modifier applied to ip6 %s", typestr);
-
-       case Q_SCA:
-               bpf_error("SCA host filtering not implemented");
+               bpf_error(cstate, "'decnet' modifier applied to ip6 %s", typestr);
 
        case Q_LAT:
-               bpf_error("LAT host filtering not implemented");
+               bpf_error(cstate, "'lat' modifier applied to ip6 %s", typestr);
 
-       case Q_MOPDL:
-               bpf_error("MOPDL host filtering not implemented");
+       case Q_SCA:
+               bpf_error(cstate, "'sca' modifier applied to ip6 %s", typestr);
 
        case Q_MOPRC:
-               bpf_error("MOPRC host filtering not implemented");
+               bpf_error(cstate, "'moprc' modifier applied to ip6 %s", typestr);
+
+       case Q_MOPDL:
+               bpf_error(cstate, "'mopdl' modifier applied to ip6 %s", typestr);
 
        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 ip6 %s", typestr);
 
        case Q_AH:
-               bpf_error("'ah' modifier applied to %s", typestr);
+               bpf_error(cstate, "'ah' modifier applied to ip6 %s", typestr);
 
        case Q_ESP:
-               bpf_error("'esp' modifier applied to %s", typestr);
+               bpf_error(cstate, "'esp' modifier applied to ip6 %s", typestr);
+
+       case Q_PIM:
+               bpf_error(cstate, "'pim' modifier applied to ip6 %s", typestr);
+
+       case Q_VRRP:
+               bpf_error(cstate, "'vrrp' modifier applied to ip6 %s", typestr);
+
+       case Q_AARP:
+               bpf_error(cstate, "'aarp' modifier applied to ip6 %s", typestr);
 
        case Q_ISO:
-               bpf_error("ISO host filtering not implemented");
+               bpf_error(cstate, "'iso' modifier applied to ip6 %s", typestr);
 
        case Q_ESIS:
-               bpf_error("'esis' modifier applied to %s", typestr);
+               bpf_error(cstate, "'esis' modifier applied to ip6 %s", typestr);
 
        case Q_ISIS:
-               bpf_error("'isis' modifier applied to %s", typestr);
+               bpf_error(cstate, "'isis' modifier applied to ip6 %s", typestr);
 
        case Q_CLNP:
-               bpf_error("'clnp' modifier applied to %s", typestr);
+               bpf_error(cstate, "'clnp' modifier applied to ip6 %s", typestr);
 
        case Q_STP:
-               bpf_error("'stp' modifier applied to %s", typestr);
+               bpf_error(cstate, "'stp' modifier applied to ip6 %s", typestr);
 
        case Q_IPX:
-               bpf_error("IPX host filtering not implemented");
+               bpf_error(cstate, "'ipx' modifier applied to ip6 %s", typestr);
 
        case Q_NETBEUI:
-               bpf_error("'netbeui' modifier applied to %s", typestr);
+               bpf_error(cstate, "'netbeui' modifier applied to ip6 %s", typestr);
+
+       case Q_ISIS_L1:
+               bpf_error(cstate, "'l1' modifier applied to ip6 %s", typestr);
+
+       case Q_ISIS_L2:
+               bpf_error(cstate, "'l2' modifier applied to ip6 %s", typestr);
+
+       case Q_ISIS_IIH:
+               bpf_error(cstate, "'iih' modifier applied to ip6 %s", typestr);
+
+       case Q_ISIS_SNP:
+               bpf_error(cstate, "'snp' modifier applied to ip6 %s", typestr);
+
+       case Q_ISIS_CSNP:
+               bpf_error(cstate, "'csnp' modifier applied to ip6 %s", typestr);
+
+       case Q_ISIS_PSNP:
+               bpf_error(cstate, "'psnp' modifier applied to ip6 %s", typestr);
+
+       case Q_ISIS_LSP:
+               bpf_error(cstate, "'lsp' modifier applied to ip6 %s", typestr);
 
        case Q_RADIO:
-               bpf_error("'radio' modifier applied to %s", typestr);
+               bpf_error(cstate, "'radio' modifier applied to ip6 %s", typestr);
+
+       case Q_CARP:
+               bpf_error(cstate, "'carp' modifier applied to ip6 %s", typestr);
 
        default:
                abort();
        }
-       /* NOTREACHED */
+       /*NOTREACHED*/
 }
 #endif
 
 #ifndef INET6
 static struct block *
-gen_gateway(eaddr, alist, proto, dir)
-       const u_char *eaddr;
-       bpf_u_int32 **alist;
-       int proto;
-       int dir;
+gen_gateway(compiler_state_t *cstate, const u_char *eaddr,
+    struct addrinfo *alist, int proto, int dir)
 {
        struct block *b0, *b1, *tmp;
+       struct addrinfo *ai;
+       struct sockaddr_in *sin;
 
        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);
-               while (*alist) {
-                       tmp = gen_host(**alist++, 0xffffffff, proto, Q_OR,
-                           Q_HOST);
-                       gen_or(b1, tmp);
-                       b1 = tmp;
-               }
-               gen_not(b1);
-               gen_and(b0, b1);
+               b1 = NULL;
+               for (ai = alist; ai != NULL; ai = ai->ai_next) {
+                       /*
+                        * Does it have an address?
+                        */
+                       if (ai->ai_addr != NULL) {
+                               /*
+                                * Yes.  Is it an IPv4 address?
+                                */
+                               if (ai->ai_addr->sa_family == AF_INET) {
+                                       /*
+                                        * Generate an entry for it.
+                                        */
+                                       sin = (struct sockaddr_in *)ai->ai_addr;
+                                       tmp = gen_host(cstate,
+                                           ntohl(sin->sin_addr.s_addr),
+                                           0xffffffff, proto, Q_OR, Q_HOST);
+                                       /*
+                                        * Is it the *first* IPv4 address?
+                                        */
+                                       if (b1 == NULL) {
+                                               /*
+                                                * Yes, so start with it.
+                                                */
+                                               b1 = tmp;
+                                       } else {
+                                               /*
+                                                * No, so OR it into the
+                                                * existing set of
+                                                * addresses.
+                                                */
+                                               gen_or(b1, tmp);
+                                               b1 = tmp;
+                                       }
+                               }
+                       }
+               }
+               if (b1 == NULL) {
+                       /*
+                        * No IPv4 addresses found.
+                        */
+                       return (NULL);
+               }
+               gen_not(b1);
+               gen_and(b0, b1);
                return b1;
        }
-       bpf_error("illegal modifier of 'gateway'");
-       /* NOTREACHED */
+       bpf_error(cstate, "illegal modifier of 'gateway'");
+       /*NOTREACHED*/
 }
 #endif
 
-struct block *
-gen_proto_abbrev(proto)
-       int proto;
+static struct block *
+gen_proto_abbrev_internal(compiler_state_t *cstate, int proto)
 {
        struct block *b0;
        struct block *b1;
@@ -4945,25 +5313,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
@@ -4971,14 +5339,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
@@ -4986,8 +5354,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;
 
@@ -4996,7 +5364,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
@@ -5004,69 +5372,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;
 
@@ -5074,101 +5442,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();
@@ -5176,15 +5544,28 @@ gen_proto_abbrev(proto)
        return b1;
 }
 
+struct block *
+gen_proto_abbrev(compiler_state_t *cstate, int proto)
+{
+       /*
+        * Catch errors reported by us and routines below us, and return NULL
+        * on an error.
+        */
+       if (setjmp(cstate->top_ctx))
+               return (NULL);
+
+       return gen_proto_abbrev_internal(cstate, 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);
@@ -5202,56 +5583,76 @@ 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_AND:
+               tmp = gen_portatom(cstate, 0, (bpf_int32)port);
+               b1 = gen_portatom(cstate, 2, (bpf_int32)port);
+               gen_and(tmp, b1);
                break;
 
-       case Q_OR:
        case Q_DEFAULT:
-               tmp = gen_portatom(0, (bpf_int32)port);
-               b1 = gen_portatom(2, (bpf_int32)port);
+       case Q_OR:
+               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);
-               gen_and(tmp, b1);
-               break;
+       case Q_ADDR1:
+               bpf_error(cstate, "'addr1' and 'address1' are not valid qualifiers for ports");
+               /*NOTREACHED*/
+
+       case Q_ADDR2:
+               bpf_error(cstate, "'addr2' and 'address2' are not valid qualifiers for ports");
+               /*NOTREACHED*/
+
+       case Q_ADDR3:
+               bpf_error(cstate, "'addr3' and 'address3' are not valid qualifiers for ports");
+               /*NOTREACHED*/
+
+       case Q_ADDR4:
+               bpf_error(cstate, "'addr4' and 'address4' are not valid qualifiers for ports");
+               /*NOTREACHED*/
+
+       case Q_RA:
+               bpf_error(cstate, "'ra' is not a valid qualifier for ports");
+               /*NOTREACHED*/
+
+       case Q_TA:
+               bpf_error(cstate, "'ta' is not a valid qualifier for ports");
+               /*NOTREACHED*/
 
        default:
                abort();
+               /*NOTREACHED*/
        }
        gen_and(b0, b1);
 
@@ -5259,10 +5660,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;
 
@@ -5283,20 +5681,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;
 
@@ -5308,37 +5706,36 @@ 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);
-               break;
-
-       case Q_OR:
-       case Q_DEFAULT:
-               tmp = gen_portatom6(0, (bpf_int32)port);
-               b1 = gen_portatom6(2, (bpf_int32)port);
-               gen_or(tmp, b1);
+               b1 = gen_portatom6(cstate, 2, (bpf_int32)port);
                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;
 
+       case Q_DEFAULT:
+       case Q_OR:
+               tmp = gen_portatom6(cstate, 0, (bpf_int32)port);
+               b1 = gen_portatom6(cstate, 2, (bpf_int32)port);
+               gen_or(tmp, b1);
+               break;
+
        default:
                abort();
        }
@@ -5348,28 +5745,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;
 
@@ -5382,9 +5776,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;
 
@@ -5399,8 +5792,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);
 
@@ -5408,42 +5801,65 @@ 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_AND:
+               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;
 
-       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);
+       case Q_OR:
+               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);
-               gen_and(tmp, b1);
-               break;
+       case Q_ADDR1:
+               bpf_error(cstate, "'addr1' and 'address1' are not valid qualifiers for port ranges");
+               /*NOTREACHED*/
+
+       case Q_ADDR2:
+               bpf_error(cstate, "'addr2' and 'address2' are not valid qualifiers for port ranges");
+               /*NOTREACHED*/
+
+       case Q_ADDR3:
+               bpf_error(cstate, "'addr3' and 'address3' are not valid qualifiers for port ranges");
+               /*NOTREACHED*/
+
+       case Q_ADDR4:
+               bpf_error(cstate, "'addr4' and 'address4' are not valid qualifiers for port ranges");
+               /*NOTREACHED*/
+
+       case Q_RA:
+               bpf_error(cstate, "'ra' is not a valid qualifier for port ranges");
+               /*NOTREACHED*/
+
+       case Q_TA:
+               bpf_error(cstate, "'ta' is not a valid qualifier for port ranges");
+               /*NOTREACHED*/
 
        default:
                abort();
+               /*NOTREACHED*/
        }
        gen_and(b0, b1);
 
@@ -5451,28 +5867,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;
 
@@ -5484,9 +5898,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;
 
@@ -5501,8 +5914,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);
 
@@ -5510,39 +5923,37 @@ 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);
-               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);
-               gen_or(tmp, b1);
+               b1 = gen_portrangeatom6(cstate, 2, (bpf_int32)port1, (bpf_int32)port2);
                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;
 
+       case Q_DEFAULT:
+       case Q_OR:
+               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;
+
        default:
                abort();
        }
@@ -5552,28 +5963,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;
 
@@ -5585,9 +5994,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;
 
@@ -5598,16 +6005,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;
 
@@ -5619,7 +6026,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:
@@ -5631,44 +6038,39 @@ lookup_proto(name, proto)
 
 #if 0
 struct stmt *
-gen_joinsp(s, n)
-       struct stmt **s;
-       int n;
+gen_joinsp(struct stmt **s, int n)
 {
        return NULL;
 }
 #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*/
        }
 
@@ -5683,17 +6085,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 optimizer yet */
 
        /*
         * s[0] is a dummy entry to protect other BPF insn from damage
@@ -5701,44 +6096,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*/
@@ -5749,7 +6144,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;
@@ -5762,26 +6157,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;
@@ -5798,39 +6193,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++;
@@ -5840,7 +6235,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++;
@@ -5849,7 +6244,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;
@@ -5864,54 +6259,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];
@@ -5929,11 +6324,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;
@@ -5941,7 +6336,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;
@@ -5950,13 +6345,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);
@@ -5976,10 +6371,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
@@ -5987,15 +6379,18 @@ 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;
 
+       case Q_LINK:
+               return gen_linktype(cstate, v);
+
        case Q_IP:
                /*
                 * For FDDI, RFC 1188 says that SNAP encapsulation is used,
@@ -6012,22 +6407,120 @@ 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(cstate, OR_LINKPL, 9, BPF_B, (bpf_int32)v);
+#else
+               b1 = gen_protochain(cstate, v, Q_IP);
+#endif
+               gen_and(b0, b1);
+               return b1;
+
+       case Q_ARP:
+               bpf_error(cstate, "arp does not encapsulate another protocol");
+               /*NOTREACHED*/
+
+       case Q_RARP:
+               bpf_error(cstate, "rarp does not encapsulate another protocol");
+               /*NOTREACHED*/
+
+       case Q_SCTP:
+               bpf_error(cstate, "'sctp proto' is bogus");
+               /*NOTREACHED*/
+
+       case Q_TCP:
+               bpf_error(cstate, "'tcp proto' is bogus");
+               /*NOTREACHED*/
+
+       case Q_UDP:
+               bpf_error(cstate, "'udp proto' is bogus");
+               /*NOTREACHED*/
+
+       case Q_ICMP:
+               bpf_error(cstate, "'icmp proto' is bogus");
+               /*NOTREACHED*/
+
+       case Q_IGMP:
+               bpf_error(cstate, "'igmp proto' is bogus");
+               /*NOTREACHED*/
+
+       case Q_IGRP:
+               bpf_error(cstate, "'igrp proto' is bogus");
+               /*NOTREACHED*/
+
+       case Q_ATALK:
+               bpf_error(cstate, "AppleTalk encapsulation is not specifiable");
+               /*NOTREACHED*/
+
+       case Q_DECNET:
+               bpf_error(cstate, "DECNET encapsulation is not specifiable");
+               /*NOTREACHED*/
+
+       case Q_LAT:
+               bpf_error(cstate, "LAT does not encapsulate another protocol");
+               /*NOTREACHED*/
+
+       case Q_SCA:
+               bpf_error(cstate, "SCA does not encapsulate another protocol");
+               /*NOTREACHED*/
+
+       case Q_MOPRC:
+               bpf_error(cstate, "MOPRC does not encapsulate another protocol");
+               /*NOTREACHED*/
+
+       case Q_MOPDL:
+               bpf_error(cstate, "MOPDL does not encapsulate another protocol");
+               /*NOTREACHED*/
+
+       case Q_IPV6:
+               b0 = gen_linktype(cstate, ETHERTYPE_IPV6);
 #ifndef CHASE_CHAIN
-               b1 = gen_cmp(OR_NET, 9, BPF_B, (bpf_int32)v);
+               /*
+                * Also check for a fragment header before the final
+                * header.
+                */
+               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(cstate, OR_LINKPL, 6, BPF_B, (bpf_int32)v);
+               gen_or(b2, b1);
 #else
-               b1 = gen_protochain(v, Q_IP);
+               b1 = gen_protochain(cstate, v, Q_IPV6);
 #endif
                gen_and(b0, b1);
                return b1;
 
+       case Q_ICMPV6:
+               bpf_error(cstate, "'icmp6 proto' is bogus");
+               /*NOTREACHED*/
+
+       case Q_AH:
+               bpf_error(cstate, "'ah proto' is bogus");
+               /*NOTREACHED*/
+
+       case Q_ESP:
+               bpf_error(cstate, "'ah proto' is bogus");
+               /*NOTREACHED*/
+
+       case Q_PIM:
+               bpf_error(cstate, "'pim proto' is bogus");
+               /*NOTREACHED*/
+
+       case Q_VRRP:
+               bpf_error(cstate, "'vrrp proto' is bogus");
+               /*NOTREACHED*/
+
+       case Q_AARP:
+               bpf_error(cstate, "'aarp proto' is bogus");
+               /*NOTREACHED*/
+
        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
@@ -6043,223 +6536,174 @@ 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;
 
                case DLT_C_HDLC:
                        /*
                         * 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_ESIS:
+               bpf_error(cstate, "'esis proto' is bogus");
+               /*NOTREACHED*/
+
        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");
-               /* NOTREACHED */
-
-       case Q_RARP:
-               bpf_error("rarp does not encapsulate another protocol");
-               /* NOTREACHED */
-
-       case Q_ATALK:
-               bpf_error("atalk encapsulation is not specifiable");
-               /* NOTREACHED */
-
-       case Q_DECNET:
-               bpf_error("decnet encapsulation is not specifiable");
-               /* NOTREACHED */
-
-       case Q_SCA:
-               bpf_error("sca does not encapsulate another protocol");
-               /* NOTREACHED */
-
-       case Q_LAT:
-               bpf_error("lat does not encapsulate another protocol");
-               /* NOTREACHED */
+       case Q_CLNP:
+               bpf_error(cstate, "'clnp proto' is not supported");
+               /*NOTREACHED*/
 
-       case Q_MOPRC:
-               bpf_error("moprc does not encapsulate another protocol");
-               /* NOTREACHED */
+       case Q_STP:
+               bpf_error(cstate, "'stp proto' is bogus");
+               /*NOTREACHED*/
 
-       case Q_MOPDL:
-               bpf_error("mopdl does not encapsulate another protocol");
-               /* NOTREACHED */
+       case Q_IPX:
+               bpf_error(cstate, "'ipx proto' is bogus");
+               /*NOTREACHED*/
 
-       case Q_LINK:
-               return gen_linktype(v);
+       case Q_NETBEUI:
+               bpf_error(cstate, "'netbeui proto' is bogus");
+               /*NOTREACHED*/
 
-       case Q_UDP:
-               bpf_error("'udp proto' is bogus");
-               /* NOTREACHED */
+       case Q_ISIS_L1:
+               bpf_error(cstate, "'l1 proto' is bogus");
+               /*NOTREACHED*/
 
-       case Q_TCP:
-               bpf_error("'tcp proto' is bogus");
-               /* NOTREACHED */
+       case Q_ISIS_L2:
+               bpf_error(cstate, "'l2 proto' is bogus");
+               /*NOTREACHED*/
 
-       case Q_SCTP:
-               bpf_error("'sctp proto' is bogus");
-               /* NOTREACHED */
+       case Q_ISIS_IIH:
+               bpf_error(cstate, "'iih proto' is bogus");
+               /*NOTREACHED*/
 
-       case Q_ICMP:
-               bpf_error("'icmp proto' is bogus");
-               /* NOTREACHED */
+       case Q_ISIS_SNP:
+               bpf_error(cstate, "'snp proto' is bogus");
+               /*NOTREACHED*/
 
-       case Q_IGMP:
-               bpf_error("'igmp proto' is bogus");
-               /* NOTREACHED */
+       case Q_ISIS_CSNP:
+               bpf_error(cstate, "'csnp proto' is bogus");
+               /*NOTREACHED*/
 
-       case Q_IGRP:
-               bpf_error("'igrp proto' is bogus");
-               /* NOTREACHED */
+       case Q_ISIS_PSNP:
+               bpf_error(cstate, "'psnp proto' is bogus");
+               /*NOTREACHED*/
 
-       case Q_PIM:
-               bpf_error("'pim proto' is bogus");
-               /* NOTREACHED */
+       case Q_ISIS_LSP:
+               bpf_error(cstate, "'lsp proto' is bogus");
+               /*NOTREACHED*/
 
-       case Q_VRRP:
-               bpf_error("'vrrp proto' is bogus");
-               /* NOTREACHED */
+       case Q_RADIO:
+               bpf_error(cstate, "'radio proto' is bogus");
+               /*NOTREACHED*/
 
        case Q_CARP:
-               bpf_error("'carp proto' is bogus");
-               /* NOTREACHED */
-
-       case Q_IPV6:
-               b0 = gen_linktype(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);
-               gen_and(b2, b1);
-               b2 = gen_cmp(OR_NET, 6, BPF_B, (bpf_int32)v);
-               gen_or(b2, b1);
-#else
-               b1 = gen_protochain(v, Q_IPV6);
-#endif
-               gen_and(b0, b1);
-               return b1;
-
-       case Q_ICMPV6:
-               bpf_error("'icmp6 proto' is bogus");
-
-       case Q_AH:
-               bpf_error("'ah proto' is bogus");
-
-       case Q_ESP:
-               bpf_error("'ah proto' is bogus");
-
-       case Q_STP:
-               bpf_error("'stp proto' is bogus");
-
-       case Q_IPX:
-               bpf_error("'ipx proto' is bogus");
-
-       case Q_NETBEUI:
-               bpf_error("'netbeui proto' is bogus");
-
-       case Q_RADIO:
-               bpf_error("'radio proto' is bogus");
+               bpf_error(cstate, "'carp proto' is bogus");
+               /*NOTREACHED*/
 
        default:
                abort();
-               /* NOTREACHED */
+               /*NOTREACHED*/
        }
-       /* NOTREACHED */
+       /*NOTREACHED*/
 }
 
 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;
        int tproto;
        u_char *eaddr;
        bpf_u_int32 mask, addr;
-#ifndef INET6
-       bpf_u_int32 **alist;
-#else
-       int tproto6;
+       struct addrinfo *res, *res0;
        struct sockaddr_in *sin4;
+#ifdef INET6
+       int tproto6;
        struct sockaddr_in6 *sin6;
-       struct addrinfo *res, *res0;
        struct in6_addr mask128;
 #endif /*INET6*/
        struct block *b, *tmp;
        int port, real_proto;
        int port1, port2;
 
+       /*
+        * Catch errors reported by us and routines below us, and return NULL
+        * on an error.
+        */
+       if (setjmp(cstate->top_ctx))
+               return (NULL);
+
        switch (q.addr) {
 
        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;
 
@@ -6270,100 +6714,83 @@ 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);
-                       tproto = proto;
-                       if (off_linktype == (u_int)-1 && tproto == Q_DEFAULT)
-                               tproto = Q_IP;
-                       b = gen_host(**alist++, 0xffffffff, tproto, dir, q.addr);
-                       while (*alist) {
-                               tmp = gen_host(**alist++, 0xffffffff,
-                                              tproto, dir, q.addr);
-                               gen_or(b, tmp);
-                               b = tmp;
-                       }
-                       return b;
-#else
+#ifdef INET6
                        memset(&mask128, 0xff, sizeof(mask128));
+#endif
                        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) {
+                       tproto = proto;
+#ifdef INET6
+                       tproto6 = proto;
+#endif
+                       if (cstate->off_linktype.constant_part == OFFSET_NOT_SET &&
+                           tproto == Q_DEFAULT) {
                                tproto = Q_IP;
+#ifdef INET6
                                tproto6 = Q_IPV6;
+#endif
                        }
                        for (res = res0; res; res = res->ai_next) {
                                switch (res->ai_family) {
                                case AF_INET:
+#ifdef INET6
                                        if (tproto == Q_IPV6)
                                                continue;
+#endif
 
                                        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;
+#ifdef INET6
                                case AF_INET6:
                                        if (tproto6 == Q_IP)
                                                continue;
 
                                        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;
+#endif
                                default:
                                        continue;
                                }
@@ -6371,154 +6798,162 @@ 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");
                        }
                        return b;
-#endif /*INET6*/
                }
 
        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);
-
-               alist = pcap_nametoaddr(name);
-               if (alist == NULL || *alist == NULL)
-                       bpf_error("unknown host '%s'", name);
-               b = gen_gateway(eaddr, alist, proto, dir);
-               free(eaddr);
+                       bpf_error(cstate, "unknown ether host: %s", name);
+
+               res = pcap_nametoaddrinfo(name);
+               cstate->ai = res;
+               if (res == NULL)
+                       bpf_error(cstate, "unknown host '%s'", name);
+               b = gen_gateway(cstate, eaddr, res, proto, dir);
+               cstate->ai = NULL;
+               freeaddrinfo(res);
+               if (b == NULL)
+                       bpf_error(cstate, "unknown host '%s'", name);
                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();
-               /* NOTREACHED */
+               syntax(cstate);
+               /*NOTREACHED*/
        }
        abort();
-       /* NOTREACHED */
+       /*NOTREACHED*/
 }
 
 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;
 
+       /*
+        * Catch errors reported by us and routines below us, and return NULL
+        * on an error.
+        */
+       if (setjmp(cstate->top_ctx))
+               return (NULL);
+
        nlen = __pcap_atoin(s1, &n);
        /* Promote short ipaddr */
        n <<= 32 - nlen;
@@ -6528,12 +6963,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
@@ -6543,39 +6978,46 @@ 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");
-               /* NOTREACHED */
+               bpf_error(cstate, "Mask syntax for networks only");
+               /*NOTREACHED*/
        }
-       /* NOTREACHED */
-       return NULL;
+       /*NOTREACHED*/
 }
 
 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;
-       int dir = q.dir;
+       int proto;
+       int dir;
        register int vlen;
 
+       /*
+        * Catch errors reported by us and routines below us, and return NULL
+        * on an error.
+        */
+       if (setjmp(cstate->top_ctx))
+               return (NULL);
+
+       proto = q.proto;
+       dir = q.dir;
        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) {
@@ -6584,9 +7026,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) {
@@ -6598,9 +7040,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:
@@ -6613,15 +7055,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;
            }
 
@@ -6635,65 +7077,70 @@ 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");
-               /* NOTREACHED */
+               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();
-               /* NOTREACHED */
+               syntax(cstate);
+               /*NOTREACHED*/
 
        default:
                abort();
-               /* NOTREACHED */
+               /*NOTREACHED*/
        }
-       /* NOTREACHED */
+       /*NOTREACHED*/
 }
 
 #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;
        struct in6_addr mask;
        struct block *b;
-       u_int32_t *a, *m;
+       uint32_t *a, *m;
+
+       /*
+        * Catch errors reported by us and routines below us, and return NULL
+        * on an error.
+        */
+       if (setjmp(cstate->top_ctx))
+               return (NULL);
 
        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) {
@@ -6701,11 +7148,11 @@ gen_mcode6(s1, s2, masklen, q)
                        (0xff << (8 - masklen % 8)) & 0xff;
        }
 
-       a = (u_int32_t *)addr;
-       m = (u_int32_t *)&mask;
+       a = (uint32_t *)addr;
+       m = (uint32_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) {
@@ -6713,80 +7160,79 @@ 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");
-               /* NOTREACHED */
+               bpf_error(cstate, "invalid qualifier against IPv6 address");
+               /*NOTREACHED*/
        }
-       return NULL;
 }
 #endif /*INET6*/
 
 struct block *
-gen_ecode(eaddr, q)
-       register const u_char *eaddr;
-       struct qual q;
+gen_ecode(compiler_state_t *cstate, const char *s, struct qual q)
 {
        struct block *b, *tmp;
 
+       /*
+        * Catch errors reported by us and routines below us, and return NULL
+        * on an error.
+        */
+       if (setjmp(cstate->top_ctx))
+               return (NULL);
+
        if ((q.addr == Q_HOST || q.addr == Q_DEFAULT) && q.proto == Q_LINK) {
-               switch (linktype) {
+               cstate->e = pcap_ether_aton(s);
+               if (cstate->e == NULL)
+                       bpf_error(cstate, "malloc");
+               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, cstate->e, (int)q.dir);
+                       if (tmp != NULL)
+                               gen_and(tmp, b);
+                       break;
                case DLT_FDDI:
-                       return gen_fhostop(eaddr, (int)q.dir);
+                       b = gen_fhostop(cstate, cstate->e, (int)q.dir);
+                       break;
                case DLT_IEEE802:
-                       return gen_thostop(eaddr, (int)q.dir);
+                       b = gen_thostop(cstate, cstate->e, (int)q.dir);
+                       break;
                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;
-                       }
+                       b = gen_wlanhostop(cstate, cstate->e, (int)q.dir);
                        break;
                case DLT_IP_OVER_FC:
-                       return gen_ipfchostop(eaddr, (int)q.dir);
-               default:
-                       bpf_error("ethernet addresses supported only on ethernet/FDDI/token ring/802.11/ATM LANE/Fibre Channel");
+                       b = gen_ipfchostop(cstate, cstate->e, (int)q.dir);
                        break;
+               default:
+                       free(cstate->e);
+                       cstate->e = NULL;
+                       bpf_error(cstate, "ethernet addresses supported only on ethernet/FDDI/token ring/802.11/ATM LANE/Fibre Channel");
+                       /*NOTREACHED*/
                }
+               free(cstate->e);
+               cstate->e = NULL;
+               return (b);
        }
-       bpf_error("ethernet address used in non-ether expression");
-       /* NOTREACHED */
-       return NULL;
+       bpf_error(cstate, "ethernet address used in non-ether expression");
+       /*NOTREACHED*/
 }
 
 void
-sappend(s0, s1)
-       struct slist *s0, *s1;
+sappend(struct slist *s0, struct slist *s1)
 {
        /*
         * This is definitely not the best way to do this, but the
@@ -6798,23 +7244,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;
 }
@@ -6826,21 +7270,18 @@ xfer_to_a(a)
  * (1, 2, or 4) at that offset into that register, making it the register
  * for "index".
  */
-struct arth *
-gen_load(proto, inst, size)
-       int proto;
-       struct arth *inst;
-       int size;
+static struct arth *
+gen_load_internal(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;
@@ -6856,7 +7297,7 @@ gen_load(proto, inst, size)
        }
        switch (proto) {
        default:
-               bpf_error("unsupported index operation");
+               bpf_error(cstate, "unsupported index operation");
 
        case Q_RADIO:
                /*
@@ -6864,21 +7305,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;
@@ -6895,7 +7336,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
@@ -6907,11 +7348,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
@@ -6920,8 +7361,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;
@@ -6940,40 +7381,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);
 
@@ -6981,7 +7417,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_internal(cstate, proto);
                if (inst->b)
                        gen_and(inst->b, b);
                inst->b = b;
@@ -7005,34 +7441,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);
 
                /*
@@ -7041,42 +7475,103 @@ 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_internal(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_internal(cstate, Q_IP), b);
                inst->b = b;
                break;
        case Q_ICMPV6:
-               bpf_error("IPv6 upper-layer protocol is not supported by proto[x]");
-               /*NOTREACHED*/
+        /*
+        * Do the computation only if the packet contains
+        * the protocol in question.
+        */
+        b = gen_proto_abbrev_internal(cstate, Q_IPV6);
+        if (inst->b) {
+            gen_and(inst->b, b);
+        }
+        inst->b = b;
+
+        /*
+        * Check if we have an icmp6 next header
+        */
+        b = gen_cmp(cstate, OR_LINKPL, 6, BPF_B, 58);
+        if (inst->b) {
+            gen_and(inst->b, b);
+        }
+        inst->b = b;
+
+
+        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 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(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(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 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 + 40;
+
+        sappend(s, tmp);
+        sappend(inst->s, s);
+
+        break;
        }
        inst->regno = regno;
-       s = new_stmt(BPF_ST);
+       s = new_stmt(cstate, BPF_ST);
        s->s.k = regno;
        sappend(inst->s, s);
 
        return inst;
 }
 
-struct block *
-gen_relation(code, a0, a1, reversed)
-       int code;
-       struct arth *a0, *a1;
-       int reversed;
+struct arth *
+gen_load(compiler_state_t *cstate, int proto, struct arth *inst, int size)
+{
+       /*
+        * Catch errors reported by us and routines below us, and return NULL
+        * on an error.
+        */
+       if (setjmp(cstate->top_ctx))
+               return (NULL);
+
+       return gen_load_internal(cstate, proto, inst, size);
+}
+
+static struct block *
+gen_relation_internal(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);
 
@@ -7086,8 +7581,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) {
@@ -7105,15 +7600,38 @@ gen_relation(code, a0, a1, reversed)
        return b;
 }
 
+struct block *
+gen_relation(compiler_state_t *cstate, int code, struct arth *a0,
+    struct arth *a1, int reversed)
+{
+       /*
+        * Catch errors reported by us and routines below us, and return NULL
+        * on an error.
+        */
+       if (setjmp(cstate->top_ctx))
+               return (NULL);
+
+       return gen_relation_internal(cstate, 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;
+       struct arth *a;
        struct slist *s;
 
-       s = new_stmt(BPF_LD|BPF_LEN);
-       s->next = new_stmt(BPF_ST);
+       /*
+        * Catch errors reported by us and routines below us, and return NULL
+        * on an error.
+        */
+       if (setjmp(cstate->top_ctx))
+               return (NULL);
+
+       regno = alloc_reg(cstate);
+       a = (struct arth *)newchunk(cstate, sizeof(*a));
+       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;
@@ -7121,21 +7639,20 @@ gen_loadlen()
        return a;
 }
 
-struct arth *
-gen_loadi(val)
-       int val;
+static struct arth *
+gen_loadi_internal(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;
@@ -7144,85 +7661,137 @@ gen_loadi(val)
 }
 
 struct arth *
-gen_neg(a)
-       struct arth *a;
+gen_loadi(compiler_state_t *cstate, int val)
+{
+       /*
+        * Catch errors reported by us and routines below us, and return NULL
+        * on an error.
+        */
+       if (setjmp(cstate->top_ctx))
+               return (NULL);
+
+       return gen_loadi_internal(cstate, val);
+}
+
+/*
+ * The a_arg dance is to avoid annoying whining by compilers that
+ * a might be clobbered by longjmp - yeah, it might, but *WHO CARES*?
+ * It's not *used* after setjmp returns.
+ */
+struct arth *
+gen_neg(compiler_state_t *cstate, struct arth *a_arg)
 {
+       struct arth *a = a_arg;
        struct slist *s;
 
-       s = xfer_to_a(a);
+       /*
+        * Catch errors reported by us and routines below us, and return NULL
+        * on an error.
+        */
+       if (setjmp(cstate->top_ctx))
+               return (NULL);
+
+       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);
 
        return a;
 }
 
+/*
+ * The a0_arg dance is to avoid annoying whining by compilers that
+ * a0 might be clobbered by longjmp - yeah, it might, but *WHO CARES*?
+ * It's not *used* after setjmp returns.
+ */
 struct arth *
-gen_arth(code, a0, a1)
-       int code;
-       struct arth *a0, *a1;
+gen_arth(compiler_state_t *cstate, int code, struct arth *a0_arg,
+    struct arth *a1)
 {
+       struct arth *a0 = a0_arg;
        struct slist *s0, *s1, *s2;
 
-       s0 = xfer_to_x(a1);
-       s1 = xfer_to_a(a0);
-       s2 = new_stmt(BPF_ALU|BPF_X|code);
+       /*
+        * Catch errors reported by us and routines below us, and return NULL
+        * on an error.
+        */
+       if (setjmp(cstate->top_ctx))
+               return (NULL);
+
+       /*
+        * Disallow division by, or modulus by, zero; we do this here
+        * so that it gets done even if the optimizer is disabled.
+        *
+        * Also disallow shifts by a value greater than 31; we do this
+        * here, for the same reason.
+        */
+       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");
+       } else if (code == BPF_LSH || code == BPF_RSH) {
+               /*
+                * XXX - we need to make up our minds as to what integers
+                * are signed and what integers are unsigned in BPF programs
+                * and in our IR.
+                */
+               if (a1->s->s.code == (BPF_LD|BPF_IMM) &&
+                   (a1->s->s.k < 0 || a1->s->s.k > 31))
+                       bpf_error(cstate, "shift by more than 31 bits");
+       }
+       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");
-       /* NOTREACHED */
-       return 0;
+       bpf_error(cstate, "too many registers needed to evaluate expression");
+       /*NOTREACHED*/
 }
 
 /*
@@ -7230,21 +7799,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;
 
@@ -7252,22 +7819,34 @@ 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);
+       /*
+        * Catch errors reported by us and routines below us, and return NULL
+        * on an error.
+        */
+       if (setjmp(cstate->top_ctx))
+               return (NULL);
+
+       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);
+       /*
+        * Catch errors reported by us and routines below us, and return NULL
+        * on an error.
+        */
+       if (setjmp(cstate->top_ctx))
+               return (NULL);
+
+       b = gen_len(cstate, BPF_JGT, n);
        gen_not(b);
 
        return b;
@@ -7284,100 +7863,97 @@ 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;
 
+       /*
+        * Catch errors reported by us and routines below us, and return NULL
+        * on an error.
+        */
+       if (setjmp(cstate->top_ctx))
+               return (NULL);
+
        switch (op) {
        default:
                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 };
+
+       /*
+        * Catch errors reported by us and routines below us, and return NULL
+        * on an error.
+        */
+       if (setjmp(cstate->top_ctx))
+               return (NULL);
 
        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;
+               /*NOTREACHED*/
 
        case Q_IP:
                /*
@@ -7385,20 +7961,19 @@ 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");
-       /* NOTREACHED */
-       return NULL;
+       bpf_error(cstate, "only link-layer/IP broadcast filters supported");
+       /*NOTREACHED*/
 }
 
 /*
@@ -7406,41 +7981,50 @@ 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;
 
+       /*
+        * Catch errors reported by us and routines below us, and return NULL
+        * on an error.
+        */
+       if (setjmp(cstate->top_ctx))
+               return (NULL);
+
        switch (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
@@ -7448,10 +8032,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:
@@ -7478,23 +8062,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);
@@ -7502,7 +8086,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);
 
                        /*
@@ -7515,8 +8099,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;
 
@@ -7530,8 +8114,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);
@@ -7539,7 +8123,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);
 
                        /*
@@ -7557,8 +8141,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);
@@ -7570,25 +8154,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;
                }
@@ -7596,20 +8163,19 @@ 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");
-       /* NOTREACHED */
-       return NULL;
+       bpf_error(cstate, "link-layer multicast filters supported only on ethernet/FDDI/token ring/ARCNET/802.11/ATM LANE/Fibre Channel");
+       /*NOTREACHED*/
 }
 
 /*
@@ -7622,35 +8188,50 @@ 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;
 
        /*
+        * Catch errors reported by us and routines below us, and return NULL
+        * on an error.
+        */
+       if (setjmp(cstate->top_ctx))
+               return (NULL);
+
+       /*
         * 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_internal(cstate, BPF_JEQ,
+                         gen_load_internal(cstate, Q_LINK, gen_loadi_internal(cstate, 0), 1),
+                         gen_loadi_internal(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);
+               }
+               break;
+
+       case DLT_LINUX_SLL2:
+               /* match outgoing packets */
+               b0 = gen_cmp(cstate, OR_LINKHDR, 10, BPF_B, LINUX_SLL_OUTGOING);
                if (!dir) {
                        /* to filter on inbound traffic, invert the match */
                        gen_not(b0);
@@ -7659,7 +8240,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
@@ -7667,10 +8248,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;
 
@@ -7701,18 +8282,28 @@ 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;
 
        default:
                /*
                 * If we have packet meta-data indicating a direction,
-                * check it, otherwise give up as this link-layer type
-                * has nothing in the packet data.
+                * and that metadata can be checked by BPF code, check
+                * it.  Otherwise, give up, as this link-layer type has
+                * nothing in the packet data.
+                *
+                * Currently, the only platform where a BPF filter can
+                * check that metadata is Linux with the in-kernel
+                * BPF interpreter.  If other packet capture mechanisms
+                * and BPF filters also supported this, it would be
+                * nice.  It would be even better if they made that
+                * metadata available so that we could provide it
+                * with newer capture APIs, allowing it to be saved
+                * in pcapng files.
                 */
 #if defined(linux) && defined(PF_PACKET) && defined(SO_ATTACH_FILTER)
                /*
@@ -7721,25 +8312,24 @@ 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 %s when reading savefiles",
+                           pcap_datalink_val_to_description_or_dlt(cstate->linktype));
                        b0 = NULL;
-                       /* NOTREACHED */
+                       /*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);
-               b0 = NULL;
-               /* NOTREACHED */
+               bpf_error(cstate, "inbound/outbound not supported on %s",
+                   pcap_datalink_val_to_description_or_dlt(cstate->linktype));
+               /*NOTREACHED*/
 #endif /* defined(linux) && defined(PF_PACKET) && defined(SO_ATTACH_FILTER) */
        }
        return (b0);
@@ -7748,191 +8338,284 @@ 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");
-               /* NOTREACHED */
+       /*
+        * Catch errors reported by us and routines below us, and return NULL
+        * on an error.
+        */
+       if (setjmp(cstate->top_ctx))
+               return (NULL);
+
+       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 */
+               /*NOTREACHED*/
        }
-       b0 = gen_bcmp(OR_LINK, off, strlen(ifname), (const u_char *)ifname);
+       b0 = gen_bcmp(cstate, OR_LINKHDR, off, (u_int)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");
-               /* NOTREACHED */
+       /*
+        * Catch errors reported by us and routines below us, and return NULL
+        * on an error.
+        */
+       if (setjmp(cstate->top_ctx))
+               return (NULL);
+
+       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 */
+               /*NOTREACHED*/
        }
 
-       b0 = gen_bcmp(OR_LINK, offsetof(struct pfloghdr, ruleset),
-           strlen(ruleset), (const u_char *)ruleset);
+       b0 = gen_bcmp(cstate, OR_LINKHDR, offsetof(struct pfloghdr, ruleset),
+           (u_int)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");
-               /* NOTREACHED */
+       /*
+        * Catch errors reported by us and routines below us, and return NULL
+        * on an error.
+        */
+       if (setjmp(cstate->top_ctx))
+               return (NULL);
+
+       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");
-               /* NOTREACHED */
-       }
-
-       b0 = gen_cmp(OR_LINK, offsetof(struct pfloghdr, subrulenr), BPF_W,
+       /*
+        * Catch errors reported by us and routines below us, and return NULL
+        * on an error.
+        */
+       if (setjmp(cstate->top_ctx))
+               return (NULL);
+
+       if (cstate->linktype != DLT_PFLOG) {
+               bpf_error(cstate, "srnr supported only on PF linktype");
+               /*NOTREACHED*/
+       }
+
+       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");
-               /* NOTREACHED */
+       /*
+        * Catch errors reported by us and routines below us, and return NULL
+        * on an error.
+        */
+       if (setjmp(cstate->top_ctx))
+               return (NULL);
+
+       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");
-               /* NOTREACHED */
+       /*
+        * Catch errors reported by us and routines below us, and return NULL
+        * on an error.
+        */
+       if (setjmp(cstate->top_ctx))
+               return (NULL);
+
+       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 _U_)
 {
-       bpf_error("libpcap was compiled without pf support");
-       /* NOTREACHED */
-       return (NULL);
+       /*
+        * Catch errors reported by us and routines below us, and return NULL
+        * on an error.
+        */
+       if (setjmp(cstate->top_ctx))
+               return (NULL);
+
+       bpf_error(cstate, "libpcap was compiled without pf support");
+       /*NOTREACHED*/
 }
 
 struct block *
-gen_pf_ruleset(char *ruleset)
+gen_pf_ruleset(compiler_state_t *cstate, char *ruleset _U_)
 {
-       bpf_error("libpcap was compiled on a machine without pf support");
-       /* NOTREACHED */
-       return (NULL);
+       /*
+        * Catch errors reported by us and routines below us, and return NULL
+        * on an error.
+        */
+       if (setjmp(cstate->top_ctx))
+               return (NULL);
+
+       bpf_error(cstate, "libpcap was compiled on a machine without pf support");
+       /*NOTREACHED*/
 }
 
 struct block *
-gen_pf_rnr(int rnr)
+gen_pf_rnr(compiler_state_t *cstate, int rnr _U_)
 {
-       bpf_error("libpcap was compiled on a machine without pf support");
-       /* NOTREACHED */
-       return (NULL);
+       /*
+        * Catch errors reported by us and routines below us, and return NULL
+        * on an error.
+        */
+       if (setjmp(cstate->top_ctx))
+               return (NULL);
+
+       bpf_error(cstate, "libpcap was compiled on a machine without pf support");
+       /*NOTREACHED*/
 }
 
 struct block *
-gen_pf_srnr(int srnr)
+gen_pf_srnr(compiler_state_t *cstate, int srnr _U_)
 {
-       bpf_error("libpcap was compiled on a machine without pf support");
-       /* NOTREACHED */
-       return (NULL);
+       /*
+        * Catch errors reported by us and routines below us, and return NULL
+        * on an error.
+        */
+       if (setjmp(cstate->top_ctx))
+               return (NULL);
+
+       bpf_error(cstate, "libpcap was compiled on a machine without pf support");
+       /*NOTREACHED*/
 }
 
 struct block *
-gen_pf_reason(int reason)
+gen_pf_reason(compiler_state_t *cstate, int reason _U_)
 {
-       bpf_error("libpcap was compiled on a machine without pf support");
-       /* NOTREACHED */
-       return (NULL);
+       /*
+        * Catch errors reported by us and routines below us, and return NULL
+        * on an error.
+        */
+       if (setjmp(cstate->top_ctx))
+               return (NULL);
+
+       bpf_error(cstate, "libpcap was compiled on a machine without pf support");
+       /*NOTREACHED*/
 }
 
 struct block *
-gen_pf_action(int action)
+gen_pf_action(compiler_state_t *cstate, int action _U_)
 {
-       bpf_error("libpcap was compiled on a machine without pf support");
-       /* NOTREACHED */
-       return (NULL);
+       /*
+        * Catch errors reported by us and routines below us, and return NULL
+        * on an error.
+        */
+       if (setjmp(cstate->top_ctx))
+               return (NULL);
+
+       bpf_error(cstate, "libpcap was compiled on a machine without pf support");
+       /*NOTREACHED*/
 }
 #endif /* HAVE_NET_PFVAR_H */
 
 /* 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) {
+       /*
+        * Catch errors reported by us and routines below us, and return NULL
+        * on an error.
+        */
+       if (setjmp(cstate->top_ctx))
+               return (NULL);
+
+       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");
-               /* NOTREACHED */
+               bpf_error(cstate, "802.11 link-layer types supported only on 802.11");
+               /*NOTREACHED*/
        }
 
        return (b0);
 }
 
 struct block *
-gen_p80211_fcdir(int fcdir)
+gen_p80211_fcdir(compiler_state_t *cstate, int fcdir)
 {
        struct block *b0;
 
-       switch (linktype) {
+       /*
+        * Catch errors reported by us and routines below us, and return NULL
+        * on an error.
+        */
+       if (setjmp(cstate->top_ctx))
+               return (NULL);
+
+       switch (cstate->linktype) {
 
        case DLT_IEEE802_11:
        case DLT_PRISM_HEADER:
@@ -7941,111 +8624,308 @@ gen_p80211_fcdir(int fcdir)
                break;
 
        default:
-               bpf_error("frame direction supported only with 802.11 headers");
-               /* NOTREACHED */
+               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 char *s, struct qual q)
 {
-       switch (linktype) {
+       struct block *b;
+
+       /*
+        * Catch errors reported by us and routines below us, and return NULL
+        * on an error.
+        */
+       if (setjmp(cstate->top_ctx))
+               return (NULL);
+
+       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));
-               else {
-                       bpf_error("ARCnet address used in non-arc expression");
-                       /* NOTREACHED */
-               }
-               break;
+                   q.proto == Q_LINK) {
+                       cstate->e = pcap_ether_aton(s);
+                       if (cstate->e == NULL)
+                               bpf_error(cstate, "malloc");
+                       b = gen_ahostop(cstate, cstate->e, (int)q.dir);
+                       free(cstate->e);
+                       cstate->e = NULL;
+                       return (b);
+               } else
+                       bpf_error(cstate, "ARCnet address used in non-arc expression");
+               /*NOTREACHED*/
 
        default:
-               bpf_error("aid supported only on ARCnet");
-               /* NOTREACHED */
+               bpf_error(cstate, "aid supported only on ARCnet");
+               /*NOTREACHED*/
        }
-       bpf_error("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");
-               break;
+               bpf_error(cstate, "'addr1' and 'address1' are only supported on 802.11");
+               /*NOTREACHED*/
 
        case Q_ADDR2:
-               bpf_error("'addr2' is only supported on 802.11");
-               break;
+               bpf_error(cstate, "'addr2' and 'address2' are only supported on 802.11");
+               /*NOTREACHED*/
 
        case Q_ADDR3:
-               bpf_error("'addr3' is only supported on 802.11");
-               break;
+               bpf_error(cstate, "'addr3' and 'address3' are only supported on 802.11");
+               /*NOTREACHED*/
 
        case Q_ADDR4:
-               bpf_error("'addr4' is only supported on 802.11");
-               break;
+               bpf_error(cstate, "'addr4' and 'address4' are only supported on 802.11");
+               /*NOTREACHED*/
 
        case Q_RA:
-               bpf_error("'ra' is only supported on 802.11");
-               break;
+               bpf_error(cstate, "'ra' is only supported on 802.11");
+               /*NOTREACHED*/
 
        case Q_TA:
-               bpf_error("'ta' is only supported on 802.11");
-               break;
+               bpf_error(cstate, "'ta' is only supported on 802.11");
+               /*NOTREACHED*/
        }
        abort();
-       /* NOTREACHED */
+       /*NOTREACHED*/
+}
+
+static struct block *
+gen_vlan_tpid_test(compiler_state_t *cstate)
+{
+       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);
+
+       return b1;
 }
 
+static struct block *
+gen_vlan_vid_test(compiler_state_t *cstate, bpf_u_int32 vlan_num)
+{
+       if (vlan_num > 0x0fff) {
+               bpf_error(cstate, "VLAN tag %u greater than maximum %u",
+                   vlan_num, 0x0fff);
+       }
+       return gen_mcmp(cstate, OR_LINKPL, 0, BPF_H, (bpf_int32)vlan_num, 0x0fff);
+}
+
+static struct block *
+gen_vlan_no_bpf_extensions(compiler_state_t *cstate, bpf_u_int32 vlan_num,
+    int has_vlan_tag)
+{
+       struct block *b0, *b1;
+
+       b0 = gen_vlan_tpid_test(cstate);
+
+       if (has_vlan_tag) {
+               b1 = gen_vlan_vid_test(cstate, vlan_num);
+               gen_and(b0, b1);
+               b0 = b1;
+       }
+
+       /*
+        * Both payload and link header type follow the VLAN tags so that
+        * both need to be updated.
+        */
+       cstate->off_linkpl.constant_part += 4;
+       cstate->off_linktype.constant_part += 4;
+
+       return b0;
+}
+
+#if defined(SKF_AD_VLAN_TAG_PRESENT)
+/* add v to variable part of off */
+static void
+gen_vlan_vloffset_add(compiler_state_t *cstate, bpf_abs_offset *off, int v, struct slist *s)
+{
+       struct slist *s2;
+
+       if (!off->is_variable)
+               off->is_variable = 1;
+       if (off->reg == -1)
+               off->reg = alloc_reg(cstate);
+
+       s2 = new_stmt(cstate, BPF_LD|BPF_MEM);
+       s2->s.k = off->reg;
+       sappend(s, s2);
+       s2 = new_stmt(cstate, BPF_ALU|BPF_ADD|BPF_IMM);
+       s2->s.k = v;
+       sappend(s, s2);
+       s2 = new_stmt(cstate, BPF_ST);
+       s2->s.k = off->reg;
+       sappend(s, s2);
+}
+
+/*
+ * patch block b_tpid (VLAN TPID test) to update variable parts of link payload
+ * and link type offsets first
+ */
+static void
+gen_vlan_patch_tpid_test(compiler_state_t *cstate, struct block *b_tpid)
+{
+       struct slist s;
+
+       /* offset determined at run time, shift variable part */
+       s.next = NULL;
+       cstate->is_vlan_vloffset = 1;
+       gen_vlan_vloffset_add(cstate, &cstate->off_linkpl, 4, &s);
+       gen_vlan_vloffset_add(cstate, &cstate->off_linktype, 4, &s);
+
+       /* we get a pointer to a chain of or-ed blocks, patch first of them */
+       sappend(s.next, b_tpid->head->stmts);
+       b_tpid->head->stmts = s.next;
+}
+
+/*
+ * patch block b_vid (VLAN id test) to load VID value either from packet
+ * metadata (using BPF extensions) if SKF_AD_VLAN_TAG_PRESENT is true
+ */
+static void
+gen_vlan_patch_vid_test(compiler_state_t *cstate, struct block *b_vid)
+{
+       struct slist *s, *s2, *sjeq;
+       unsigned cnt;
+
+       s = new_stmt(cstate, BPF_LD|BPF_B|BPF_ABS);
+       s->s.k = SKF_AD_OFF + SKF_AD_VLAN_TAG_PRESENT;
+
+       /* true -> next instructions, false -> beginning of b_vid */
+       sjeq = new_stmt(cstate, JMP(BPF_JEQ));
+       sjeq->s.k = 1;
+       sjeq->s.jf = b_vid->stmts;
+       sappend(s, sjeq);
+
+       s2 = new_stmt(cstate, BPF_LD|BPF_B|BPF_ABS);
+       s2->s.k = SKF_AD_OFF + SKF_AD_VLAN_TAG;
+       sappend(s, s2);
+       sjeq->s.jt = s2;
+
+       /* Jump to the test in b_vid. We need to jump one instruction before
+        * the end of the b_vid block so that we only skip loading the TCI
+        * from packet data and not the 'and' instruction extractging VID.
+        */
+       cnt = 0;
+       for (s2 = b_vid->stmts; s2; s2 = s2->next)
+               cnt++;
+       s2 = new_stmt(cstate, JMP(BPF_JA));
+       s2->s.k = cnt - 1;
+       sappend(s, s2);
+
+       /* insert our statements at the beginning of b_vid */
+       sappend(s, b_vid->stmts);
+       b_vid->stmts = s;
+}
+
+/*
+ * Generate check for "vlan" or "vlan <id>" on systems with support for BPF
+ * extensions.  Even if kernel supports VLAN BPF extensions, (outermost) VLAN
+ * tag can be either in metadata or in packet data; therefore if the
+ * SKF_AD_VLAN_TAG_PRESENT test is negative, we need to check link
+ * header for VLAN tag. As the decision is done at run time, we need
+ * update variable part of the offsets
+ */
+static struct block *
+gen_vlan_bpf_extensions(compiler_state_t *cstate, bpf_u_int32 vlan_num,
+    int has_vlan_tag)
+{
+        struct block *b0, *b_tpid, *b_vid = NULL;
+        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;
+
+       /*
+        * This is tricky. We need to insert the statements updating variable
+        * parts of offsets before the the traditional TPID and VID tests so
+        * that they are called whenever SKF_AD_VLAN_TAG_PRESENT fails but
+        * we do not want this update to affect those checks. That's why we
+        * generate both test blocks first and insert the statements updating
+        * variable parts of both offsets after that. This wouldn't work if
+        * there already were variable length link header when entering this
+        * function but gen_vlan_bpf_extensions() isn't called in that case.
+        */
+       b_tpid = gen_vlan_tpid_test(cstate);
+       if (has_vlan_tag)
+               b_vid = gen_vlan_vid_test(cstate, vlan_num);
+
+       gen_vlan_patch_tpid_test(cstate, b_tpid);
+       gen_or(b0, b_tpid);
+       b0 = b_tpid;
+
+       if (has_vlan_tag) {
+               gen_vlan_patch_vid_test(cstate, b_vid);
+               gen_and(b0, b_vid);
+               b0 = b_vid;
+       }
+
+        return b0;
+}
+#endif
+
 /*
  * support IEEE 802.1Q VLAN trunk over ethernet
  */
 struct block *
-gen_vlan(vlan_num)
-       int vlan_num;
+gen_vlan(compiler_state_t *cstate, bpf_u_int32 vlan_num, int has_vlan_tag)
 {
-       struct  block   *b0, *b1;
+       struct  block   *b0;
+
+       /*
+        * Catch errors reported by us and routines below us, and return NULL
+        * on an error.
+        */
+       if (setjmp(cstate->top_ctx))
+               return (NULL);
 
        /* 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
@@ -8078,87 +8958,90 @@ 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_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,
+                                   has_vlan_tag);
+                       else
+                               b0 = gen_vlan_no_bpf_extensions(cstate,
+                                   vlan_num, has_vlan_tag);
+               } else
 #endif
+                       b0 = gen_vlan_no_bpf_extensions(cstate, vlan_num,
+                           has_vlan_tag);
+                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, has_vlan_tag);
                break;
 
        default:
-               bpf_error("no VLAN support for data link type %d",
-                     linktype);
+               bpf_error(cstate, "no VLAN support for %s",
+                     pcap_datalink_val_to_description_or_dlt(cstate->linktype));
                /*NOTREACHED*/
        }
 
+        cstate->vlan_stack_depth++;
+
        return (b0);
 }
 
 /*
  * support for MPLS
+ *
+ * The label_num_arg dance is to avoid annoying whining by compilers that
+ * label_num might be clobbered by longjmp - yeah, it might, but *WHO CARES*?
+ * It's not *used* after setjmp returns.
  */
 struct block *
-gen_mpls(label_num)
-       int label_num;
+gen_mpls(compiler_state_t *cstate, bpf_u_int32 label_num_arg,
+    int has_label_num)
 {
-       struct  block   *b0,*b1;
+       volatile bpf_u_int32 label_num = label_num_arg;
+       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().
+        * Catch errors reported by us and routines below us, and return NULL
+        * on an error.
         */
-        orig_nl = off_nl;
+       if (setjmp(cstate->top_ctx))
+               return (NULL);
 
-        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 ...
@@ -8166,26 +9049,42 @@ gen_mpls(label_num)
                      * leave it for now */
 
             default:
-                    bpf_error("no MPLS support for data link type %d",
-                          linktype);
-                    b0 = NULL;
+                    bpf_error(cstate, "no MPLS support for %s",
+                          pcap_datalink_val_to_description_or_dlt(cstate->linktype));
                     /*NOTREACHED*/
-                    break;
             }
         }
 
        /* If a specific MPLS label is requested, check it */
-       if (label_num >= 0) {
+       if (has_label_num) {
+               if (label_num > 0xFFFFF) {
+                       bpf_error(cstate, "MPLS label %u greater than maximum %u",
+                           label_num, 0xFFFFF);
+               }
                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);
 }
 
@@ -8193,65 +9092,56 @@ gen_mpls(label_num)
  * Support PPPOE discovery and session.
  */
 struct block *
-gen_pppoed()
+gen_pppoed(compiler_state_t *cstate)
 {
+       /*
+        * Catch errors reported by us and routines below us, and return NULL
+        * on an error.
+        */
+       if (setjmp(cstate->top_ctx))
+               return (NULL);
+
        /* 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, bpf_u_int32 sess_num, int has_sess_num)
 {
        struct block *b0, *b1;
 
        /*
-        * Test against the PPPoE session link-layer type.
+        * Catch errors reported by us and routines below us, and return NULL
+        * on an error.
         */
-       b0 = gen_linktype((bpf_int32)ETHERTYPE_PPPOES);
+       if (setjmp(cstate->top_ctx))
+               return (NULL);
 
        /*
-        * Change the offsets to point to the type and data fields within
-        * the PPP packet, and note that this is PPPoE rather than
-        * raw PPP.
-        *
-        * XXX - this is a bit of a kludge.  If we were to split the
-        * compiler into a parser that parses an expression and
-        * generates an expression tree, and a code generator that
-        * takes an expression tree (which could come from our
-        * parser or from some other parser) and generates BPF code,
-        * we could perhaps make the offsets parameters of routines
-        * and, in the handler for an "AND" node, pass to subnodes
-        * other than the PPPoE node the adjusted offsets.
-        *
-        * This would mean that "pppoes" would, instead of changing the
-        * behavior of *all* tests after it, change only the behavior
-        * of tests ANDed with it.  That would change the documented
-        * semantics of "pppoes", which might break some expressions.
-        * However, it would mean that "(pppoes and ip) or ip" would check
-        * both for VLAN-encapsulated IP and IP-over-Ethernet, rather than
-        * checking only for VLAN-encapsulated IP, so that could still
-        * be considered worth doing; it wouldn't break expressions
-        * that are of the form "pppoes and ..." which I suspect are the
-        * most common expressions involving "pppoes".  "pppoes or ..."
-        * doesn't necessarily do what the user would really want, now,
-        * 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...".
+        * Test against the PPPoE session link-layer type.
         */
-       orig_linktype = off_linktype;   /* save original values */
-       orig_nl = off_nl;
-       is_pppoes = 1;
+       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(OR_MACPL, orig_nl, BPF_W,
+       if (has_sess_num) {
+               if (sess_num > 0x0000ffff) {
+                       bpf_error(cstate, "PPPoE session number %u greater than maximum %u",
+                           sess_num, 0x0000ffff);
+               }
+               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
+        * the PPP packet, and note that this is PPPoE rather than
+        * raw PPP.
+        *
+        * XXX - this is a bit of a kludge.  See the comments in
+        * gen_vlan().
+        *
         * The "network-layer" protocol is PPPoE, which has a 6-byte
         * PPPoE header, followed by a PPP packet.
         *
@@ -8260,70 +9150,373 @@ 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);
+
+       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, bpf_u_int32 vni, int has_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 (has_vni) {
+               if (vni > 0xffffff) {
+                       bpf_error(cstate, "Geneve VNI %u greater than maximum %u",
+                           vni, 0xffffff);
+               }
+               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, bpf_u_int32 vni, int has_vni)
+{
+       struct block *b0, *b1;
+       struct slist *s, *s1;
+
+       b0 = gen_geneve_check(cstate, gen_port, OR_TRAN_IPV4, vni, has_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, bpf_u_int32 vni, int has_vni)
+{
+       struct block *b0, *b1;
+       struct slist *s, *s1;
+
+       b0 = gen_geneve_check(cstate, gen_port6, OR_TRAN_IPV6, vni, has_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, bpf_u_int32 vni, int has_vni)
+{
+       struct block *b0, *b1;
+       struct slist *s;
 
        /*
-        * 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.
+        * Catch errors reported by us and routines below us, and return NULL
+        * on an error.
         */
-       off_nl = 6+2;
-       off_nl_nosnap = 6+2;
+       if (setjmp(cstate->top_ctx))
+               return (NULL);
+
+       b0 = gen_geneve4(cstate, vni, has_vni);
+       b1 = gen_geneve6(cstate, vni, has_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;
+static struct block *
+gen_atmfield_code_internal(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 == OFFSET_NOT_SET)
                        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 == OFFSET_NOT_SET)
                        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 == OFFSET_NOT_SET)
                        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 == OFFSET_NOT_SET)
                        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 == OFFSET_NOT_SET)
                        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;
 
@@ -8333,73 +9526,122 @@ gen_atmfield_code(atmfield, jvalue, jtype, reverse)
        return b0;
 }
 
+static struct block *
+gen_atmtype_metac(compiler_state_t *cstate)
+{
+       struct block *b0, *b1;
+
+       b0 = gen_atmfield_code_internal(cstate, A_VPI, 0, BPF_JEQ, 0);
+       b1 = gen_atmfield_code_internal(cstate, A_VCI, 1, BPF_JEQ, 0);
+       gen_and(b0, b1);
+       return b1;
+}
+
+static struct block *
+gen_atmtype_sc(compiler_state_t *cstate)
+{
+       struct block *b0, *b1;
+
+       b0 = gen_atmfield_code_internal(cstate, A_VPI, 0, BPF_JEQ, 0);
+       b1 = gen_atmfield_code_internal(cstate, A_VCI, 5, BPF_JEQ, 0);
+       gen_and(b0, b1);
+       return b1;
+}
+
+static struct block *
+gen_atmtype_llc(compiler_state_t *cstate)
+{
+       struct block *b0;
+
+       b0 = gen_atmfield_code_internal(cstate, A_PROTOTYPE, PT_LLC, BPF_JEQ, 0);
+       cstate->linktype = cstate->prevlinktype;
+       return b0;
+}
+
+struct block *
+gen_atmfield_code(compiler_state_t *cstate, int atmfield,
+    bpf_int32 jvalue, bpf_u_int32 jtype, int reverse)
+{
+       /*
+        * Catch errors reported by us and routines below us, and return NULL
+        * on an error.
+        */
+       if (setjmp(cstate->top_ctx))
+               return (NULL);
+
+       return gen_atmfield_code_internal(cstate, 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;
 
+       /*
+        * Catch errors reported by us and routines below us, and return NULL
+        * on an error.
+        */
+       if (setjmp(cstate->top_ctx))
+               return (NULL);
+
        switch (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);
-               gen_and(b0, b1);
+               if (!cstate->is_atm)
+                       bpf_error(cstate, "'metac' supported only on raw ATM");
+               b1 = gen_atmtype_metac(cstate);
                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_internal(cstate, A_VPI, 0, BPF_JEQ, 0);
+               b1 = gen_atmfield_code_internal(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_internal(cstate, A_VPI, 0, BPF_JEQ, 0);
+               b1 = gen_atmfield_code_internal(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_internal(cstate, A_VPI, 0, BPF_JEQ, 0);
+               b1 = gen_atmfield_code_internal(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);
-               gen_and(b0, b1);
+               if (!cstate->is_atm)
+                       bpf_error(cstate, "'sc' supported only on raw ATM");
+               b1 = gen_atmtype_sc(cstate);
                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_internal(cstate, A_VPI, 0, BPF_JEQ, 0);
+               b1 = gen_atmfield_code_internal(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_internal(cstate, A_PROTOTYPE, PT_LANE, BPF_JEQ, 0);
 
                /*
                 * Arrange that all subsequent tests assume LANE
@@ -8407,26 +9649,22 @@ 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_atmtype_llc(cstate);
                break;
 
        default:
@@ -8443,65 +9681,71 @@ 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;
 
+       /*
+        * Catch errors reported by us and routines below us, and return NULL
+        * on an error.
+        */
+       if (setjmp(cstate->top_ctx))
+               return (NULL);
+
        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:
@@ -8510,20 +9754,34 @@ gen_mtp2type_abbrev(type)
        return b0;
 }
 
+/*
+ * The jvalue_arg dance is to avoid annoying whining by compilers that
+ * jvalue might be clobbered by longjmp - yeah, it might, but *WHO CARES*?
+ * It's not *used* after setjmp returns.
+ */
 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_arg, bpf_u_int32 jtype, int reverse)
 {
+       volatile bpf_u_int32 jvalue = jvalue_arg;
        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;
+       u_int newoff_opc;
+       u_int newoff_dpc;
+       u_int newoff_sls;
 
+       /*
+        * Catch errors reported by us and routines below us, and return NULL
+        * on an error.
+        */
+       if (setjmp(cstate->top_ctx))
+               return (NULL);
+
+       newoff_sio = cstate->off_sio;
+       newoff_opc = cstate->off_opc;
+       newoff_dpc = cstate->off_dpc;
+       newoff_sls = cstate->off_sls;
        switch (mtp3field) {
 
        case MH_SIO:
@@ -8531,24 +9789,26 @@ 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 == OFFSET_NOT_SET)
+                       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;
+               newoff_opc += 3;
+
+               /* FALLTHROUGH */
         case M_OPC:
-               if (off_opc == (u_int)-1)
-                       bpf_error("'opc' supported only on SS7");
+               if (cstate->off_opc == OFFSET_NOT_SET)
+                       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*/
@@ -8559,7 +9819,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;
 
@@ -8568,11 +9828,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 == OFFSET_NOT_SET)
+                       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*/
@@ -8581,23 +9841,25 @@ 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;
+               newoff_sls += 3;
+               /* FALLTHROUGH */
+
        case M_SLS:
-               if (off_sls == (u_int)-1)
-                       bpf_error("'sls' supported only on SS7");
+               if (cstate->off_sls == OFFSET_NOT_SET)
+                       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;
 
@@ -8608,8 +9870,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;
 
@@ -8620,27 +9881,27 @@ gen_msg_abbrev(type)
        switch (type) {
 
        case A_SETUP:
-               b1 = gen_atmfield_code(A_MSGTYPE, SETUP, BPF_JEQ, 0);
+               b1 = gen_atmfield_code_internal(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_internal(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_internal(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_internal(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_internal(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_internal(cstate, A_MSGTYPE, RELEASE_DONE, BPF_JEQ, 0);
                break;
 
        default:
@@ -8650,27 +9911,38 @@ 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;
 
+       /*
+        * Catch errors reported by us and routines below us, and return NULL
+        * on an error.
+        */
+       if (setjmp(cstate->top_ctx))
+               return (NULL);
+
        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");
+               /* OAM F4 type */
+               b0 = gen_atmfield_code_internal(cstate, A_VCI, 3, BPF_JEQ, 0);
+               b1 = gen_atmfield_code_internal(cstate, A_VCI, 4, BPF_JEQ, 0);
+               gen_or(b0, b1);
+               b0 = gen_atmfield_code_internal(cstate, A_VPI, 0, BPF_JEQ, 0);
+               gen_and(b0, b1);
                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_internal(cstate, A_VCI, 3, BPF_JEQ, 0);
+               b1 = gen_atmfield_code_internal(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_internal(cstate, A_VPI, 0, BPF_JEQ, 0);
                gen_and(b0, b1);
                break;
 
@@ -8679,36 +9951,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_sc(cstate);
                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_metac(cstate);
                gen_and(b0, b1);
                break;
 
index e6b3a71..cc21e04 100644 (file)
--- a/gencode.h
+++ b/gencode.h
@@ -19,6 +19,8 @@
  * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
  */
 
+#include "pcap/funcattrs.h"
+
 /*
  * ATM support:
  *
  * POSSIBILITY OF SUCH DAMAGE.
  */
 
-#ifndef HAVE___ATTRIBUTE__
-#define __attribute__(x)
-#endif /* HAVE___ATTRIBUTE__ */
-
 /* Address qualifiers. */
 
 #define Q_HOST         1
 #define Q_ISIS_L2       32
 /* PDU types */
 #define Q_ISIS_IIH      33
-#define Q_ISIS_LAN_IIH  34
-#define Q_ISIS_PTP_IIH  35
-#define Q_ISIS_SNP      36
-#define Q_ISIS_CSNP     37
-#define Q_ISIS_PSNP     38
-#define Q_ISIS_LSP      39
+#define Q_ISIS_SNP      34
+#define Q_ISIS_CSNP     35
+#define Q_ISIS_PSNP     36
+#define Q_ISIS_LSP      37
 
-#define Q_RADIO                40
+#define Q_RADIO                38
 
-#define Q_CARP         41
+#define Q_CARP         39
 
 /* Directional qualifiers. */
 
 #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
@@ -268,6 +264,11 @@ struct block {
        int val[N_ATOMS];
 };
 
+/*
+ * A value of 0 for val[i] means the value is unknown.
+ */
+#define VAL_UNKNOWN    0
+
 struct arth {
        struct block *b;        /* protocol checks */
        struct slist *s;        /* stmt list */
@@ -281,83 +282,107 @@ 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 char *, struct qual);
+struct block *gen_acode(compiler_state_t *, const 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 *, ...)
-    __attribute__((noreturn))
-#ifdef __ATTRIBUTE___FORMAT_OK
-    __attribute__((format (printf, 1, 2)))
-#endif /* __ATTRIBUTE___FORMAT_OK */
-    ;
-
-void finish_parse(struct block *);
-char *sdup(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 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 *, bpf_u_int32, int);
+struct block *gen_mpls(compiler_state_t *, bpf_u_int32, int);
+
+struct block *gen_pppoed(compiler_state_t *);
+struct block *gen_pppoes(compiler_state_t *, bpf_u_int32, int);
+
+struct block *gen_geneve(compiler_state_t *, bpf_u_int32, 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;
+};
+
+int bpf_optimize(struct icode *, char *);
+void bpf_set_error(compiler_state_t *, const char *, ...)
+    PCAP_PRINTFLIKE(2, 3);
+
+int finish_parse(compiler_state_t *, struct block *);
+char *sdup(compiler_state_t *, const char *);
+
+struct bpf_insn *icode_to_fcode(struct icode *, struct block *, u_int *,
+    char *);
 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;
index b269d27..32cb19c 100644 (file)
--- a/grammar.y
+++ b/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
  */
 
 #ifdef HAVE_CONFIG_H
-#include "config.h"
+#include <config.h>
 #endif
 
-#ifdef WIN32
-#include <pcap-stdinc.h>
-#else /* WIN32 */
+#include <stdlib.h>
+
+#ifndef _WIN32
 #include <sys/types.h>
 #include <sys/socket.h>
-#endif /* WIN32 */
-
-#include <stdlib.h>
 
-#ifndef WIN32
 #if __STDC__
 struct mbuf;
 struct rtentry;
@@ -42,13 +63,18 @@ struct rtentry;
 
 #include <netinet/in.h>
 #include <arpa/inet.h>
-#endif /* WIN32 */
+#endif /* _WIN32 */
 
 #include <stdio.h>
 
+#include "diag-control.h"
+
 #include "pcap-int.h"
 
 #include "gencode.h"
+#include "grammar.h"
+#include "scanner.h"
+
 #ifdef HAVE_NET_PFVAR_H
 #include <net/if.h>
 #include <net/pfvar.h>
@@ -62,9 +88,30 @@ struct rtentry;
 #include "os-proto.h"
 #endif
 
-#define QSET(q, p, d, a) (q).proto = (p),\
-                        (q).dir = (d),\
-                        (q).addr = (a)
+#ifdef YYBYACC
+/*
+ * Both Berkeley YACC and Bison define yydebug (under whatever name
+ * it has) as a global, but Bison does so only if YYDEBUG is defined.
+ * Berkeley YACC define it even if YYDEBUG isn't defined; declare it
+ * here to suppress a warning.
+ */
+#if !defined(YYDEBUG)
+extern int yydebug;
+#endif
+
+/*
+ * In Berkeley YACC, yynerrs (under whatever name it has) is global,
+ * even if it's building a reentrant parser.  In Bison, it's local
+ * in reentrant parsers.
+ *
+ * Declare it to squelch a warning.
+ */
+extern int yynerrs;
+#endif
+
+#define QSET(q, p, d, a) (q).proto = (unsigned char)(p),\
+                        (q).dir = (unsigned char)(d),\
+                        (q).addr = (unsigned char)(a)
 
 struct tok {
        int v;                  /* value */
@@ -169,31 +216,17 @@ 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 const struct qual qerr = { Q_UNDEF, Q_UNDEF, Q_UNDEF, Q_UNDEF };
 
 static void
-yyerror(const char *msg)
+yyerror(void *yyscanner _U_, compiler_state_t *cstate, const char *msg)
 {
-       ++n_errors;
-       bpf_error("%s", msg);
-       /* NOTREACHED */
+       bpf_set_error(cstate, "can't parse filter expression: %s", msg);
 }
 
-#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;
@@ -202,12 +235,12 @@ pfreason_to_num(const char *reason)
                if (pcap_strcasecmp(reason, reasons[i]) == 0)
                        return (i);
        }
-       bpf_error("unknown PF reason");
-       /*NOTREACHED*/
+       bpf_set_error(cstate, "unknown PF reason");
+       return (-1);
 }
 
 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)
@@ -226,37 +259,38 @@ pfaction_to_num(const char *action)
                return (PF_NORDR);
 #endif
        else {
-               bpf_error("unknown PF action");
-               /*NOTREACHED*/
+               bpf_set_error(cstate, "unknown PF action");
+               return (-1);
        }
 }
 #else /* !HAVE_NET_PFVAR_H */
 static int
-pfreason_to_num(const char *reason)
+pfreason_to_num(compiler_state_t *cstate, const char *reason _U_)
 {
-       bpf_error("libpcap was compiled on a machine without pf support");
-       /*NOTREACHED*/
-
-       /* this is to make the VC compiler happy */
-       return -1;
+       bpf_set_error(cstate, "libpcap was compiled on a machine without pf support");
+       return (-1);
 }
 
 static int
-pfaction_to_num(const char *action)
+pfaction_to_num(compiler_state_t *cstate, const char *action _U_)
 {
-       bpf_error("libpcap was compiled on a machine without pf support");
-       /*NOTREACHED*/
-
-       /* this is to make the VC compiler happy */
-       return -1;
+       bpf_set_error(cstate, "libpcap was compiled on a machine without pf support");
+       return (-1);
 }
 #endif /* HAVE_NET_PFVAR_H */
+
+/*
+ * For calls that might return an "an error occurred" value.
+ */
+#define CHECK_INT_VAL(val)     if (val == -1) YYABORT
+#define CHECK_PTR_VAL(val)     if (val == NULL) YYABORT
+
+DIAG_OFF_BISON_BYACC
 %}
 
 %union {
        int i;
        bpf_u_int32 h;
-       u_char *e;
        char *s;
        struct stmt *stmt;
        struct arth *a;
@@ -299,8 +333,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
@@ -310,11 +344,9 @@ pfaction_to_num(const char *action)
 %token RADIO
 %token FISU LSSU MSU HFISU HLSSU HMSU
 %token SIO OPC DPC SLS HSIO HOPC HDPC HSLS
+%token LEX_ERROR
 
-%type  <s> ID
-%type  <e> EID
-%type  <e> AID
+%type  <s> ID EID AID
 %type  <s> HID HID6
 %type  <i> NUM action reason type subtype type_subtype dir
 
@@ -329,7 +361,7 @@ pfaction_to_num(const char *action)
 %%
 prog:    null expr
 {
-       finish_parse($2.b);
+       CHECK_INT_VAL(finish_parse(cstate, $2.b));
 }
        | null
        ;
@@ -346,64 +378,58 @@ and:        AND                   { $$ = $<blk>0; }
 or:      OR                    { $$ = $<blk>0; }
        ;
 id:      nid
-       | pnum                  { $$.b = gen_ncode(NULL, (bpf_u_int32)$1,
-                                                  $$.q = $<blk>0.q); }
+       | pnum                  { CHECK_PTR_VAL(($$.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,
-                                   $$.q = $<blk>0.q); }
-       | HID NETMASK HID       { $$.b = gen_mcode($1, $3, 0,
-                                   $$.q = $<blk>0.q); }
+nid:     ID                    { CHECK_PTR_VAL($1); CHECK_PTR_VAL(($$.b = gen_scode(cstate, $1, $$.q = $<blk>0.q))); }
+       | HID '/' NUM           { CHECK_PTR_VAL($1); CHECK_PTR_VAL(($$.b = gen_mcode(cstate, $1, NULL, $3,
+                                   $$.q = $<blk>0.q))); }
+       | HID NETMASK HID       { CHECK_PTR_VAL($1); CHECK_PTR_VAL(($$.b = gen_mcode(cstate, $1, $3, 0,
+                                   $$.q = $<blk>0.q))); }
        | HID                   {
+                                 CHECK_PTR_VAL($1);
                                  /* 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");
-                                 else if ($$.q.addr == Q_PORTRANGE)
-                                       bpf_error("'portrange' modifier applied to ip host");
-                                 else if ($$.q.addr == Q_PROTO)
-                                       bpf_error("'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);
+                                 if ($$.q.addr == Q_PORT) {
+                                       bpf_set_error(cstate, "'port' modifier applied to ip host");
+                                       YYABORT;
+                                 } else if ($$.q.addr == Q_PORTRANGE) {
+                                       bpf_set_error(cstate, "'portrange' modifier applied to ip host");
+                                       YYABORT;
+                                 } else if ($$.q.addr == Q_PROTO) {
+                                       bpf_set_error(cstate, "'proto' modifier applied to ip host");
+                                       YYABORT;
+                                 } else if ($$.q.addr == Q_PROTOCHAIN) {
+                                       bpf_set_error(cstate, "'protochain' modifier applied to ip host");
+                                       YYABORT;
+                                 }
+                                 CHECK_PTR_VAL(($$.b = gen_ncode(cstate, $1, 0, $$.q)));
                                }
        | HID6 '/' NUM          {
+                                 CHECK_PTR_VAL($1);
 #ifdef INET6
-                                 $$.b = gen_mcode6($1, NULL, $3,
-                                   $$.q = $<blk>0.q);
+                                 CHECK_PTR_VAL(($$.b = gen_mcode6(cstate, $1, NULL, $3,
+                                   $$.q = $<blk>0.q)));
 #else
-                                 bpf_error("'ip6addr/prefixlen' not supported "
+                                 bpf_set_error(cstate, "'ip6addr/prefixlen' not supported "
                                        "in this configuration");
+                                 YYABORT;
 #endif /*INET6*/
                                }
        | HID6                  {
+                                 CHECK_PTR_VAL($1);
 #ifdef INET6
-                                 $$.b = gen_mcode6($1, 0, 128,
-                                   $$.q = $<blk>0.q);
+                                 CHECK_PTR_VAL(($$.b = gen_mcode6(cstate, $1, 0, 128,
+                                   $$.q = $<blk>0.q)));
 #else
-                                 bpf_error("'ip6addr' not supported "
+                                 bpf_set_error(cstate, "'ip6addr' not supported "
                                        "in this configuration");
+                                 YYABORT;
 #endif /*INET6*/
                                }
-       | EID                   { 
-                                 $$.b = gen_ecode($1, $$.q = $<blk>0.q);
-                                 /*
-                                  * $1 was allocated by "pcap_ether_aton()",
-                                  * so we must free it now that we're done
-                                  * with it.
-                                  */
-                                 free($1);
-                               }
-       | AID                   {
-                                 $$.b = gen_acode($1, $$.q = $<blk>0.q);
-                                 /*
-                                  * $1 was allocated by "pcap_ether_aton()",
-                                  * so we must free it now that we're done
-                                  * with it.
-                                  */
-                                 free($1);
-                               }
+       | EID                   { CHECK_PTR_VAL($1); CHECK_PTR_VAL(($$.b = gen_ecode(cstate, $1, $$.q = $<blk>0.q))); }
+       | AID                   { CHECK_PTR_VAL($1); CHECK_PTR_VAL(($$.b = gen_acode(cstate, $1, $$.q = $<blk>0.q))); }
        | not id                { gen_not($2.b); $$ = $2; }
        ;
 not:     '!'                   { $$ = $<blk>0; }
@@ -414,8 +440,8 @@ 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,
-                                                  $$.q = $<blk>0.q); }
+qid:     pnum                  { CHECK_PTR_VAL(($$.b = gen_ncode(cstate, NULL, (bpf_u_int32)$1,
+                                                  $$.q = $<blk>0.q))); }
        | pid
        ;
 term:    rterm
@@ -425,21 +451,28 @@ head:       pqual dqual aqual     { QSET($$.q, $1, $2, $3); }
        | pqual dqual           { QSET($$.q, $1, $2, Q_DEFAULT); }
        | pqual aqual           { QSET($$.q, $1, Q_DEFAULT, $2); }
        | pqual PROTO           { QSET($$.q, $1, Q_DEFAULT, Q_PROTO); }
-       | pqual PROTOCHAIN      { QSET($$.q, $1, Q_DEFAULT, Q_PROTOCHAIN); }
+       | pqual PROTOCHAIN      {
+#ifdef NO_PROTOCHAIN
+                                 bpf_set_error(cstate, "protochain not supported");
+                                 YYABORT;
+#else
+                                 QSET($$.q, $1, Q_DEFAULT, Q_PROTOCHAIN);
+#endif
+                               }
        | pqual ndaqual         { QSET($$.q, $1, Q_DEFAULT, $2); }
        ;
 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                 { CHECK_PTR_VAL(($$.b = gen_proto_abbrev(cstate, $1))); $$.q = qerr; }
+       | arth relop arth       { CHECK_PTR_VAL(($$.b = gen_relation(cstate, $2, $1, $3, 0)));
                                  $$.q = qerr; }
-       | arth irelop arth      { $$.b = gen_relation($2, $1, $3, 1);
+       | arth irelop arth      { CHECK_PTR_VAL(($$.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               { CHECK_PTR_VAL(($$.b = gen_atmtype_abbrev(cstate, $1))); $$.q = qerr; }
+       | atmmultitype          { CHECK_PTR_VAL(($$.b = gen_atmmulti_abbrev(cstate, $1))); $$.q = qerr; }
        | atmfield atmvalue     { $$.b = $2.b; $$.q = qerr; }
-       | mtp2type              { $$.b = gen_mtp2type_abbrev($1); $$.q = qerr; }
+       | mtp2type              { CHECK_PTR_VAL(($$.b = gen_mtp2type_abbrev(cstate, $1))); $$.q = qerr; }
        | mtp3field mtp3value   { $$.b = $2.b; $$.q = qerr; }
        ;
 /* protocol level qualifiers */
@@ -509,63 +542,69 @@ 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    { CHECK_PTR_VAL(($$ = gen_broadcast(cstate, $1))); }
+       | pqual TK_MULTICAST    { CHECK_PTR_VAL(($$ = gen_multicast(cstate, $1))); }
+       | LESS NUM              { CHECK_PTR_VAL(($$ = gen_less(cstate, $2))); }
+       | GREATER NUM           { CHECK_PTR_VAL(($$ = gen_greater(cstate, $2))); }
+       | CBYTE NUM byteop NUM  { CHECK_PTR_VAL(($$ = gen_byteop(cstate, $3, $2, $4))); }
+       | INBOUND               { CHECK_PTR_VAL(($$ = gen_inbound(cstate, 0))); }
+       | OUTBOUND              { CHECK_PTR_VAL(($$ = gen_inbound(cstate, 1))); }
+       | VLAN pnum             { CHECK_PTR_VAL(($$ = gen_vlan(cstate, (bpf_u_int32)$2, 1))); }
+       | VLAN                  { CHECK_PTR_VAL(($$ = gen_vlan(cstate, 0, 0))); }
+       | MPLS pnum             { CHECK_PTR_VAL(($$ = gen_mpls(cstate, (bpf_u_int32)$2, 1))); }
+       | MPLS                  { CHECK_PTR_VAL(($$ = gen_mpls(cstate, 0, 0))); }
+       | PPPOED                { CHECK_PTR_VAL(($$ = gen_pppoed(cstate))); }
+       | PPPOES pnum           { CHECK_PTR_VAL(($$ = gen_pppoes(cstate, (bpf_u_int32)$2, 1))); }
+       | PPPOES                { CHECK_PTR_VAL(($$ = gen_pppoes(cstate, 0, 0))); }
+       | GENEVE pnum           { CHECK_PTR_VAL(($$ = gen_geneve(cstate, (bpf_u_int32)$2, 1))); }
+       | GENEVE                { CHECK_PTR_VAL(($$ = gen_geneve(cstate, 0, 0))); }
        | 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          { CHECK_PTR_VAL($2); CHECK_PTR_VAL(($$ = gen_pf_ifname(cstate, $2))); }
+       | PF_RSET ID            { CHECK_PTR_VAL($2); CHECK_PTR_VAL(($$ = gen_pf_ruleset(cstate, $2))); }
+       | PF_RNR NUM            { CHECK_PTR_VAL(($$ = gen_pf_rnr(cstate, $2))); }
+       | PF_SRNR NUM           { CHECK_PTR_VAL(($$ = gen_pf_srnr(cstate, $2))); }
+       | PF_REASON reason      { CHECK_PTR_VAL(($$ = gen_pf_reason(cstate, $2))); }
+       | PF_ACTION action      { CHECK_PTR_VAL(($$ = gen_pf_action(cstate, $2))); }
        ;
 
 p80211:   TYPE type SUBTYPE subtype
-                               { $$ = gen_p80211_type($2 | $4,
+                               { CHECK_PTR_VAL(($$ = gen_p80211_type(cstate, $2 | $4,
                                        IEEE80211_FC0_TYPE_MASK |
-                                       IEEE80211_FC0_SUBTYPE_MASK);
+                                       IEEE80211_FC0_SUBTYPE_MASK)));
                                }
-       | TYPE type             { $$ = gen_p80211_type($2,
-                                       IEEE80211_FC0_TYPE_MASK);
+       | TYPE type             { CHECK_PTR_VAL(($$ = gen_p80211_type(cstate, $2,
+                                       IEEE80211_FC0_TYPE_MASK)));
                                }
-       | SUBTYPE type_subtype  { $$ = gen_p80211_type($2,
+       | SUBTYPE type_subtype  { CHECK_PTR_VAL(($$ = gen_p80211_type(cstate, $2,
                                        IEEE80211_FC0_TYPE_MASK |
-                                       IEEE80211_FC0_SUBTYPE_MASK);
+                                       IEEE80211_FC0_SUBTYPE_MASK)));
                                }
-       | DIR dir               { $$ = gen_p80211_fcdir($2); }
+       | DIR dir               { CHECK_PTR_VAL(($$ = gen_p80211_fcdir(cstate, $2))); }
        ;
 
 type:    NUM
-       | ID                    { $$ = str2tok($1, ieee80211_types);
-                                 if ($$ == -1)
-                                       bpf_error("unknown 802.11 type name");
+       | ID                    { CHECK_PTR_VAL($1);
+                                 $$ = str2tok($1, ieee80211_types);
+                                 if ($$ == -1) {
+                                       bpf_set_error(cstate, "unknown 802.11 type name");
+                                       YYABORT;
+                                 }
                                }
        ;
 
 subtype:  NUM
        | ID                    { const struct tok *types = NULL;
                                  int i;
+                                 CHECK_PTR_VAL($1);
                                  for (i = 0;; i++) {
                                        if (ieee80211_type_subtypes[i].tok == NULL) {
                                                /* Ran out of types */
-                                               bpf_error("unknown 802.11 type");
-                                               break;
+                                               bpf_set_error(cstate, "unknown 802.11 type");
+                                               YYABORT;
                                        }
                                        if ($<i>-1 == ieee80211_type_subtypes[i].type) {
                                                types = ieee80211_type_subtypes[i].tok;
@@ -574,17 +613,20 @@ subtype:  NUM
                                  }
 
                                  $$ = str2tok($1, types);
-                                 if ($$ == -1)
-                                       bpf_error("unknown 802.11 subtype name");
+                                 if ($$ == -1) {
+                                       bpf_set_error(cstate, "unknown 802.11 subtype name");
+                                       YYABORT;
+                                 }
                                }
        ;
 
 type_subtype:  ID              { int i;
+                                 CHECK_PTR_VAL($1);
                                  for (i = 0;; i++) {
                                        if (ieee80211_type_subtypes[i].tok == NULL) {
                                                /* Ran out of types */
-                                               bpf_error("unknown 802.11 type name");
-                                               break;
+                                               bpf_set_error(cstate, "unknown 802.11 type name");
+                                               YYABORT;
                                        }
                                        $$ = str2tok($1, ieee80211_type_subtypes[i].tok);
                                        if ($$ != -1) {
@@ -595,33 +637,37 @@ type_subtype:     ID              { int i;
                                }
                ;
 
-pllc:  LLC                     { $$ = gen_llc(); }
-       | LLC ID                { if (pcap_strcasecmp($2, "i") == 0)
-                                       $$ = gen_llc_i();
-                                 else if (pcap_strcasecmp($2, "s") == 0)
-                                       $$ = gen_llc_s();
-                                 else if (pcap_strcasecmp($2, "u") == 0)
-                                       $$ = gen_llc_u();
-                                 else {
-                                       u_int subtype;
+pllc:  LLC                     { CHECK_PTR_VAL(($$ = gen_llc(cstate))); }
+       | LLC ID                { CHECK_PTR_VAL($2);
+                                 if (pcap_strcasecmp($2, "i") == 0) {
+                                       CHECK_PTR_VAL(($$ = gen_llc_i(cstate)));
+                                 } else if (pcap_strcasecmp($2, "s") == 0) {
+                                       CHECK_PTR_VAL(($$ = gen_llc_s(cstate)));
+                                 } else if (pcap_strcasecmp($2, "u") == 0) {
+                                       CHECK_PTR_VAL(($$ = gen_llc_u(cstate)));
+                                 } else {
+                                       int subtype;
 
                                        subtype = str2tok($2, llc_s_subtypes);
-                                       if (subtype != -1)
-                                               $$ = gen_llc_s_subtype(subtype);
-                                       else {
+                                       if (subtype != -1) {
+                                               CHECK_PTR_VAL(($$ = 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);
+                                               if (subtype == -1) {
+                                                       bpf_set_error(cstate, "unknown LLC type name \"%s\"", $2);
+                                                       YYABORT;
+                                               }
+                                               CHECK_PTR_VAL(($$ = 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            { CHECK_PTR_VAL(($$ = gen_llc_s_subtype(cstate, LLC_RNR))); }
        ;
 
 dir:     NUM
-       | ID                    { if (pcap_strcasecmp($1, "nods") == 0)
+       | ID                    { CHECK_PTR_VAL($1);
+                                 if (pcap_strcasecmp($1, "nods") == 0)
                                        $$ = IEEE80211_FC1_DIR_NODS;
                                  else if (pcap_strcasecmp($1, "tods") == 0)
                                        $$ = IEEE80211_FC1_DIR_TODS;
@@ -629,16 +675,18 @@ dir:        NUM
                                        $$ = IEEE80211_FC1_DIR_FROMDS;
                                  else if (pcap_strcasecmp($1, "dstods") == 0)
                                        $$ = IEEE80211_FC1_DIR_DSTODS;
-                                 else
-                                       bpf_error("unknown 802.11 direction");
+                                 else {
+                                       bpf_set_error(cstate, "unknown 802.11 direction");
+                                       YYABORT;
+                                 }
                                }
        ;
 
 reason:          NUM                   { $$ = $1; }
-       | ID                    { $$ = pfreason_to_num($1); }
+       | ID                    { CHECK_PTR_VAL($1); CHECK_INT_VAL(($$ = pfreason_to_num(cstate, $1))); }
        ;
 
-action:          ID                    { $$ = pfaction_to_num($1); }
+action:          ID                    { CHECK_PTR_VAL($1); CHECK_INT_VAL(($$ = pfaction_to_num(cstate, $1))); }
        ;
 
 relop:   '>'                   { $$ = BPF_JGT; }
@@ -649,24 +697,24 @@ irelop:     LEQ                   { $$ = BPF_JGT; }
        | '<'                   { $$ = BPF_JGE; }
        | NEQ                   { $$ = BPF_JEQ; }
        ;
-arth:    pnum                  { $$ = gen_loadi($1); }
+arth:    pnum                  { CHECK_PTR_VAL(($$ = 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 ']'            { CHECK_PTR_VAL(($$ = gen_load(cstate, $1, $3, 1))); }
+       | pname '[' arth ':' NUM ']'    { CHECK_PTR_VAL(($$ = gen_load(cstate, $1, $3, $5))); }
+       | arth '+' arth                 { CHECK_PTR_VAL(($$ = gen_arth(cstate, BPF_ADD, $1, $3))); }
+       | arth '-' arth                 { CHECK_PTR_VAL(($$ = gen_arth(cstate, BPF_SUB, $1, $3))); }
+       | arth '*' arth                 { CHECK_PTR_VAL(($$ = gen_arth(cstate, BPF_MUL, $1, $3))); }
+       | arth '/' arth                 { CHECK_PTR_VAL(($$ = gen_arth(cstate, BPF_DIV, $1, $3))); }
+       | arth '%' arth                 { CHECK_PTR_VAL(($$ = gen_arth(cstate, BPF_MOD, $1, $3))); }
+       | arth '&' arth                 { CHECK_PTR_VAL(($$ = gen_arth(cstate, BPF_AND, $1, $3))); }
+       | arth '|' arth                 { CHECK_PTR_VAL(($$ = gen_arth(cstate, BPF_OR, $1, $3))); }
+       | arth '^' arth                 { CHECK_PTR_VAL(($$ = gen_arth(cstate, BPF_XOR, $1, $3))); }
+       | arth LSH arth                 { CHECK_PTR_VAL(($$ = gen_arth(cstate, BPF_LSH, $1, $3))); }
+       | arth RSH arth                 { CHECK_PTR_VAL(($$ = gen_arth(cstate, BPF_RSH, $1, $3))); }
+       | '-' arth %prec UMINUS         { CHECK_PTR_VAL(($$ = gen_neg(cstate, $2))); }
        | paren narth ')'               { $$ = $2; }
-       | LEN                           { $$ = gen_loadlen(); }
+       | LEN                           { CHECK_PTR_VAL(($$ = gen_loadlen(cstate))); }
        ;
 byteop:          '&'                   { $$ = '&'; }
        | '|'                   { $$ = '|'; }
@@ -695,15 +743,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             { CHECK_PTR_VAL(($$.b = gen_atmfield_code(cstate, $<blk>0.atmfieldtype, (bpf_int32)$2, (bpf_u_int32)$1, 0))); }
+       | irelop NUM            { CHECK_PTR_VAL(($$.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);
+               CHECK_PTR_VAL(($$.b = gen_atmfield_code(cstate, $$.atmfieldtype, (bpf_int32) $1, BPF_JEQ, 0)));
        }
        ;
 atmlistvalue: atmfieldvalue
@@ -728,8 +776,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             { CHECK_PTR_VAL(($$.b = gen_mtp3field_code(cstate, $<blk>0.mtp3fieldtype, (u_int)$2, (u_int)$1, 0))); }
+       | irelop NUM            { CHECK_PTR_VAL(($$.b = gen_mtp3field_code(cstate, $<blk>0.mtp3fieldtype, (u_int)$2, (u_int)$1, 1))); }
        | paren mtp3listvalue ')' { $$.b = $2.b; $$.q = qerr; }
        ;
 mtp3fieldvalue: NUM {
@@ -742,7 +790,7 @@ mtp3fieldvalue: NUM {
            $$.mtp3fieldtype == MH_OPC ||
            $$.mtp3fieldtype == MH_DPC ||
            $$.mtp3fieldtype == MH_SLS)
-               $$.b = gen_mtp3field_code($$.mtp3fieldtype, (u_int) $1, BPF_JEQ, 0);
+               CHECK_PTR_VAL(($$.b = gen_mtp3field_code(cstate, $$.mtp3fieldtype, (u_int) $1, BPF_JEQ, 0)));
        }
        ;
 mtp3listvalue: mtp3fieldvalue
diff --git a/inet.c b/inet.c
deleted file mode 100644 (file)
index 036b2db..0000000
--- a/inet.c
+++ /dev/null
@@ -1,1082 +0,0 @@
-/* -*- 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
-
-/* 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)
-
-/*
- * 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.
- */
-char *
-pcap_lookupdev(errbuf)
-       register char *errbuf;
-{
-       pcap_if_t *alldevs;
-/* for old BSD systems, including bsdi3 */
-#ifndef IF_NAMESIZE
-#define IF_NAMESIZE IFNAMSIZ
-#endif
-       static char device[IF_NAMESIZE + 1];
-       char *ret;
-
-       if (pcap_findalldevs(&alldevs, errbuf) == -1)
-               return (NULL);
-
-       if (alldevs == NULL || (alldevs->flags & PCAP_IF_LOOPBACK)) {
-               /*
-                * There are no devices on the list, or the first device
-                * on the list is a loopback device, which means there
-                * are no non-loopback devices on the list.  This means
-                * we can't return any device.
-                *
-                * XXX - why not return a loopback device?  If we can't
-                * capture on it, it won't be on the list, and if it's
-                * on the list, there aren't any non-loopback devices,
-                * so why not just supply it as the default device?
-                */
-               (void)strlcpy(errbuf, "no suitable device found",
-                   PCAP_ERRBUF_SIZE);
-               ret = NULL;
-       } else {
-               /*
-                * Return the name of the first device on the list.
-                */
-               (void)strlcpy(device, alldevs->name, sizeof(device));
-               ret = device;
-       }
-
-       pcap_freealldevs(alldevs);
-       return (ret);
-}
-
-int
-pcap_lookupnet(device, netp, maskp, errbuf)
-       register const char *device;
-       register bpf_u_int32 *netp, *maskp;
-       register char *errbuf;
-{
-       register int fd;
-       register struct sockaddr_in *sin4;
-       struct ifreq ifr;
-
-       /*
-        * The pseudo-device "any" listens on all interfaces and therefore
-        * has the network address and -mask "0.0.0.0" therefore catching
-        * all traffic. Using NULL for the interface is the same as "any".
-        */
-       if (!device || strcmp(device, "any") == 0
-#ifdef HAVE_DAG_API
-           || strstr(device, "dag") != NULL
-#endif
-#ifdef HAVE_SEPTEL_API
-           || strstr(device, "septel") != NULL
-#endif
-#ifdef PCAP_SUPPORT_BT
-           || strstr(device, "bluetooth") != NULL
-#endif
-#ifdef PCAP_SUPPORT_USB
-           || strstr(device, "usbmon") != NULL
-#endif
-#ifdef HAVE_SNF_API
-           || strstr(device, "snf") != NULL
-#endif
-           ) {
-               *netp = *maskp = 0;
-               return 0;
-       }
-
-       fd = socket(AF_INET, SOCK_DGRAM, 0);
-       if (fd < 0) {
-               (void)snprintf(errbuf, PCAP_ERRBUF_SIZE, "socket: %s",
-                   pcap_strerror(errno));
-               return (-1);
-       }
-       memset(&ifr, 0, sizeof(ifr));
-#ifdef linux
-       /* XXX Work around Linux kernel bug */
-       ifr.ifr_addr.sa_family = AF_INET;
-#endif
-       (void)strncpy(ifr.ifr_name, device, sizeof(ifr.ifr_name));
-       if (ioctl(fd, SIOCGIFADDR, (char *)&ifr) < 0) {
-               if (errno == EADDRNOTAVAIL) {
-                       (void)snprintf(errbuf, PCAP_ERRBUF_SIZE,
-                           "%s: no IPv4 address assigned", device);
-               } else {
-                       (void)snprintf(errbuf, PCAP_ERRBUF_SIZE,
-                           "SIOCGIFADDR: %s: %s",
-                           device, pcap_strerror(errno));
-               }
-               (void)close(fd);
-               return (-1);
-       }
-       sin4 = (struct sockaddr_in *)&ifr.ifr_addr;
-       *netp = sin4->sin_addr.s_addr;
-       memset(&ifr, 0, sizeof(ifr));
-#ifdef linux
-       /* XXX Work around Linux kernel bug */
-       ifr.ifr_addr.sa_family = AF_INET;
-#endif
-       (void)strncpy(ifr.ifr_name, device, sizeof(ifr.ifr_name));
-       if (ioctl(fd, SIOCGIFNETMASK, (char *)&ifr) < 0) {
-               (void)snprintf(errbuf, PCAP_ERRBUF_SIZE,
-                   "SIOCGIFNETMASK: %s: %s", device, pcap_strerror(errno));
-               (void)close(fd);
-               return (-1);
-       }
-       (void)close(fd);
-       *maskp = sin4->sin_addr.s_addr;
-       if (*maskp == 0) {
-               if (IN_CLASSA(*netp))
-                       *maskp = IN_CLASSA_NET;
-               else if (IN_CLASSB(*netp))
-                       *maskp = IN_CLASSB_NET;
-               else if (IN_CLASSC(*netp))
-                       *maskp = IN_CLASSC_NET;
-               else {
-                       (void)snprintf(errbuf, PCAP_ERRBUF_SIZE,
-                           "inet class for 0x%x unknown", *netp);
-                       return (-1);
-               }
-       }
-       *netp &= *maskp;
-       return (0);
-}
-
-#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.
- */
-char *
-pcap_lookupdev(errbuf)
-       register char *errbuf;
-{
-       DWORD dwVersion;
-       DWORD dwWindowsMajorVersion;
-       dwVersion = GetVersion();       /* get the OS version */
-       dwWindowsMajorVersion = (DWORD)(LOBYTE(LOWORD(dwVersion)));
-
-       if (dwVersion >= 0x80000000 && dwWindowsMajorVersion >= 4) {
-               /*
-                * Windows 95, 98, ME.
-                */
-               ULONG NameLength = 8192;
-               static char AdaptersName[8192];
-
-               if (PacketGetAdapterNames(AdaptersName,&NameLength) )
-                       return (AdaptersName);
-               else
-                       return NULL;
-       } else {
-               /*
-                * Windows NT (NT 4.0, W2K, WXP). Convert the names to UNICODE for backward compatibility
-                */
-               ULONG NameLength = 8192;
-               static WCHAR AdaptersName[8192];
-               char *tAstr;
-               WCHAR *tUstr;
-               WCHAR *TAdaptersName = (WCHAR*)malloc(8192 * sizeof(WCHAR));
-               int NAdapts = 0;
-
-               if(TAdaptersName == NULL)
-               {
-                       (void)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());
-                       free(TAdaptersName);
-                       return NULL;
-               }
-
-
-               tAstr = (char*)TAdaptersName;
-               tUstr = (WCHAR*)AdaptersName;
-
-               /*
-                * Convert and copy the device names
-                */
-               while(sscanf(tAstr, "%S", tUstr) > 0)
-               {
-                       tAstr += strlen(tAstr) + 1;
-                       tUstr += wcslen(tUstr) + 1;
-                       NAdapts ++;
-               }
-
-               tAstr++;
-               *tUstr = 0;
-               tUstr++;
-
-               /*
-                * Copy the descriptions
-                */
-               while(NAdapts--)
-               {
-                       char* tmp = (char*)tUstr;
-                       strcpy(tmp, tAstr);
-                       tmp += strlen(tAstr) + 1;
-                       tUstr = (WCHAR*)tmp;
-                       tAstr += strlen(tAstr) + 1;
-               }
-
-               free(TAdaptersName);
-               return (char *)(AdaptersName);
-       }
-}
-
-
-int
-pcap_lookupnet(device, netp, maskp, errbuf)
-       register const char *device;
-       register bpf_u_int32 *netp, *maskp;
-       register char *errbuf;
-{
-       /*
-        * We need only the first IPv4 address, so we must scan the array returned by PacketGetNetInfo()
-        * in order to skip non IPv4 (i.e. IPv6 addresses)
-        */
-       npf_if_addr if_addrs[MAX_NETWORK_ADDRESSES];
-       LONG if_addr_size = 1;
-       struct sockaddr_in *t_addr;
-       unsigned int i;
-
-       if (!PacketGetNetInfoEx((void *)device, if_addrs, &if_addr_size)) {
-               *netp = *maskp = 0;
-               return (0);
-       }
-
-       for(i=0; i<MAX_NETWORK_ADDRESSES; i++)
-       {
-               if(if_addrs[i].IPAddress.ss_family == AF_INET)
-               {
-                       t_addr = (struct sockaddr_in *) &(if_addrs[i].IPAddress);
-                       *netp = t_addr->sin_addr.S_un.S_addr;
-                       t_addr = (struct sockaddr_in *) &(if_addrs[i].SubnetMask);
-                       *maskp = t_addr->sin_addr.S_un.S_addr;
-
-                       *netp &= *maskp;
-                       return (0);
-               }
-
-       }
-
-       *netp = *maskp = 0;
-       return (0);
-}
-
-#endif /* !WIN32 && !MSDOS */
index ebc6691..b44de09 100755 (executable)
@@ -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/lbl/os-aix7.h b/lbl/os-aix7.h
new file mode 100644 (file)
index 0000000..93b12f2
--- /dev/null
@@ -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);
index 6b87bc0..055eb80 100644 (file)
@@ -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);
-   
+
index 4c73c69..5422f18 100644 (file)
 
 /*
  * 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);
-   
+
index 22948b4..a555f5e 100644 (file)
@@ -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 *, ...);
index b735857..6353fb0 100644 (file)
@@ -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 *);
index fa1f770..21e5702 100644 (file)
@@ -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/libpcap.pc.in b/libpcap.pc.in
new file mode 100644 (file)
index 0000000..d74cbc5
--- /dev/null
@@ -0,0 +1,18 @@
+#
+# pkg-config file for libpcap.
+#
+# These variables come from the configure script, so includedir and
+# libdir may be defined in terms of prefix and exec_prefix, so the
+# latter must be defined as well.
+#
+prefix="@prefix@"
+exec_prefix="@exec_prefix@"
+includedir="@includedir@"
+libdir="@libdir@"
+
+Name: libpcap
+Description: Platform-independent network traffic capture library
+Version: @PACKAGE_VERSION@
+Libs: -L${libdir} -l@PACKAGE_NAME@
+Libs.private: @LIBS@
+Cflags: -I${includedir}
diff --git a/missing/asprintf.c b/missing/asprintf.c
new file mode 100644 (file)
index 0000000..3aa55ed
--- /dev/null
@@ -0,0 +1,101 @@
+#include <stdio.h>
+#include <stdlib.h>
+#include <stdarg.h>
+
+#include "portability.h"
+
+/*
+ * vasprintf() and asprintf() for platforms with a C99-compliant
+ * snprintf() - so that, if you format into a 1-byte buffer, it
+ * will return how many characters it would have produced had
+ * it been given an infinite-sized buffer.
+ */
+int
+pcap_vasprintf(char **strp, const char *format, va_list args)
+{
+       char buf;
+       int len;
+       size_t str_size;
+       char *str;
+       int ret;
+
+       /*
+        * XXX - the C99 standard says, in section 7.19.6.5 "Thes
+        * nprintf function":
+        *
+        *    The snprintf function is equivalent to fprintf, except that
+        *    the output is written into an array (specified by argument s)
+        *    rather than to a stream.  If n is zero, nothing is written,
+        *    and s may be a null pointer.  Otherwise, output characters
+        *    beyond the n-1st are discarded rather than being written
+        *    to the array, and a null character is written at the end
+        *    of the characters actually written into the array.
+        *
+        *        ...
+        *
+        *    The snprintf function returns the number of characters that
+        *    would have been written had n been sufficiently large, not
+        *    counting the terminating null character, or a negative value
+        *    if an encoding error occurred. Thus, the null-terminated
+        *    output has been completely written if and only if the returned
+        *    value is nonnegative and less than n.
+        *
+        * That doesn't make it entirely clear whether, if a null buffer
+        * pointer and a zero count are passed, it will return the number
+        * of characters that would have been written had a buffer been
+        * passed.
+        *
+        * And, even if C99 *does*, in fact, say it has to work, it
+        * doesn't work in Solaris 8, for example - it returns -1 for
+        * NULL/0, but returns the correct character count for a 1-byte
+        * buffer.
+        *
+        * So we pass a one-character pointer in order to find out how
+        * many characters this format and those arguments will need
+        * without actually generating any more of those characters
+        * than we need.
+        *
+        * (The fact that it might happen to work with GNU libc or with
+        * various BSD libcs is completely uninteresting, as those tend
+        * to have asprintf() already and thus don't even *need* this
+        * code; this is for use in those UN*Xes that *don't* have
+        * asprintf().)
+        */
+       len = vsnprintf(&buf, sizeof buf, format, args);
+       if (len == -1) {
+               *strp = NULL;
+               return (-1);
+       }
+       str_size = len + 1;
+       str = malloc(str_size);
+       if (str == NULL) {
+               *strp = NULL;
+               return (-1);
+       }
+       ret = vsnprintf(str, str_size, format, args);
+       if (ret == -1) {
+               free(str);
+               *strp = NULL;
+               return (-1);
+       }
+       *strp = str;
+       /*
+        * vsnprintf() shouldn't truncate the string, as we have
+        * allocated a buffer large enough to hold the string, so its
+        * return value should be the number of characters written.
+        */
+       return (ret);
+}
+
+int
+pcap_asprintf(char **strp, const char *format, ...)
+{
+       va_list args;
+       int ret;
+
+       va_start(args, format);
+       ret = pcap_vasprintf(strp, format, args);
+       va_end(args);
+       return (ret);
+}
+
similarity index 93%
rename from Win32/Src/getopt.c
rename to missing/getopt.c
index 03c2086..7c897c6 100644 (file)
@@ -39,6 +39,8 @@ static char sccsid[] = "@(#)getopt.c  8.3 (Berkeley) 4/27/95";
 #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 */
@@ -54,19 +56,19 @@ char        *optarg;                /* argument associated with option */
  *     Parse argc/argv argument vector.
  */
 int
-getopt(nargc, nargv, ostr)
-       int nargc;
-       char * const *nargv;
-       const char *ostr;
+getopt(int nargc, char * const *nargv, const char *ostr)
 {
-#ifdef WIN32
-       char *__progname="windump";
-#else
-       extern char *__progname;
-#endif
+       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]) != '-') {
diff --git a/missing/getopt.h b/missing/getopt.h
new file mode 100644 (file)
index 0000000..fc83c94
--- /dev/null
@@ -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, optreset, optopt;
+
+extern int getopt(int nargc, char * const *nargv, const char *ostr);
index 9b63f8b..672aeb8 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1995-1999 Kungliga Tekniska Högskolan
+ * Copyright (c) 1995-1999 Kungliga Tekniska Högskolan
  * (Royal Institute of Technology, Stockholm, Sweden).
  * All rights reserved.
  *
  * SUCH DAMAGE.
  */
 
+/*
+ * We use this for platforms that don't have snprintf() at all.
+ */
+
 #ifdef HAVE_CONFIG_H
 #include <config.h>
 #endif
@@ -42,7 +46,7 @@
 #include <ctype.h>
 #include <sys/types.h>
 
-#include <pcap-int.h>
+#include "portability.h"
 
 enum format_flags {
     minus_flag     =  1,
@@ -456,13 +460,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 +477,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 +522,14 @@ 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);
+  va_end(args);
 
 #ifdef PARANOIA
   {
@@ -534,30 +539,31 @@ asnprintf (char **ret, size_t max_sz, const char *format, ...)
     if (tmp == NULL)
       abort ();
 
-    ret2 = vsprintf (tmp, format, args);
+    va_start(args, format);
+    ret2 = pcap_vsprintf (tmp, format, args);
+    va_end(args);
     if (val != ret2 || strcmp(*ret, tmp))
       abort ();
     free (tmp);
   }
 #endif
 
-  va_end(args);
   return val;
 }
 #endif
 
 #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 +606,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/missing/strlcat.c b/missing/strlcat.c
new file mode 100644 (file)
index 0000000..bb78a3d
--- /dev/null
@@ -0,0 +1,61 @@
+/*     $OpenBSD: pcap_strlcat.c,v 1.15 2015/03/02 21:41:08 millert Exp $       */
+
+/*
+ * Copyright (c) 1998, 2015 Todd C. Miller <Todd.Miller@courtesan.com>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <stddef.h>
+#include <string.h>
+
+#include "portability.h"
+
+/*
+ * Appends src to string dst of size dsize (unlike strncat, dsize is the
+ * full size of dst, not space left).  At most dsize-1 characters
+ * will be copied.  Always NUL terminates (unless dsize <= strlen(dst)).
+ * Returns strlen(src) + MIN(dsize, strlen(initial dst)).
+ * If retval >= dsize, truncation occurred.
+ */
+size_t
+pcap_strlcat(char * restrict dst, const char * restrict src, size_t dsize)
+{
+       const char *odst = dst;
+       const char *osrc = src;
+       size_t n = dsize;
+       size_t dlen;
+
+       /* Find the end of dst and adjust bytes left but don't go past end. */
+       while (n-- != 0 && *dst != '\0')
+               dst++;
+       dlen = dst - odst;
+       n = dsize - dlen;
+
+       if (n-- == 0)
+               return(dlen + strlen(src));
+       while (*src != '\0') {
+               if (n != 0) {
+                       *dst++ = *src;
+                       n--;
+               }
+               src++;
+       }
+       *dst = '\0';
+
+       return(dlen + (src - osrc));    /* count does not include NUL */
+}
diff --git a/missing/strlcpy.c b/missing/strlcpy.c
new file mode 100644 (file)
index 0000000..c552e0d
--- /dev/null
@@ -0,0 +1,56 @@
+/*     $OpenBSD: pcap_strlcpy.c,v 1.12 2015/01/15 03:54:12 millert Exp $       */
+
+/*
+ * Copyright (c) 1998, 2015 Todd C. Miller <Todd.Miller@courtesan.com>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <stddef.h>
+#include <string.h>
+
+#include "portability.h"
+
+/*
+ * Copy string src to buffer dst of size dsize.  At most dsize-1
+ * chars will be copied.  Always NUL terminates (unless dsize == 0).
+ * Returns strlen(src); if retval >= dsize, truncation occurred.
+ */
+size_t
+pcap_strlcpy(char * restrict dst, const char * restrict src, size_t dsize)
+{
+       const char *osrc = src;
+       size_t nleft = dsize;
+
+       /* Copy as many bytes as will fit. */
+       if (nleft != 0) {
+               while (--nleft != 0) {
+                       if ((*dst++ = *src++) == '\0')
+                               break;
+               }
+       }
+
+       /* Not enough room in dst, add NUL and traverse rest of src. */
+       if (nleft == 0) {
+               if (dsize != 0)
+                       *dst = '\0';            /* NUL-terminate dst */
+               while (*src++)
+                       ;
+       }
+
+       return(src - osrc - 1); /* count does not include NUL */
+}
diff --git a/missing/strtok_r.c b/missing/strtok_r.c
new file mode 100644 (file)
index 0000000..5fca2f3
--- /dev/null
@@ -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/missing/win_asprintf.c b/missing/win_asprintf.c
new file mode 100644 (file)
index 0000000..cce6296
--- /dev/null
@@ -0,0 +1,51 @@
+#include <stdio.h>
+#include <stdlib.h>
+#include <stdarg.h>
+
+#include "portability.h"
+
+int
+pcap_vasprintf(char **strp, const char *format, va_list args)
+{
+       int len;
+       size_t str_size;
+       char *str;
+       int ret;
+
+       len = _vscprintf(format, args);
+       if (len == -1) {
+               *strp = NULL;
+               return (-1);
+       }
+       str_size = len + 1;
+       str = malloc(str_size);
+       if (str == NULL) {
+               *strp = NULL;
+               return (-1);
+       }
+       ret = pcap_vsnprintf(str, str_size, format, args);
+       if (ret == -1) {
+               free(str);
+               *strp = NULL;
+               return (-1);
+       }
+       *strp = str;
+       /*
+        * pcap_vsnprintf() shouldn't truncate the string, as we have
+        * allocated a buffer large enough to hold the string, so its
+        * return value should be the number of characters printed.
+        */
+       return (ret);
+}
+
+int
+pcap_asprintf(char **strp, const char *format, ...)
+{
+       va_list args;
+       int ret;
+
+       va_start(args, format);
+       ret = pcap_vasprintf(strp, format, args);
+       va_end(args);
+       return (ret);
+}
diff --git a/missing/win_snprintf.c b/missing/win_snprintf.c
new file mode 100644 (file)
index 0000000..f422403
--- /dev/null
@@ -0,0 +1,43 @@
+#include <stdio.h>
+#include <stdarg.h>
+
+#include "portability.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.
+        *
+        * We don't, however, offer C99 behavior for the return
+        * value; _vsnprintf_s() returns -1, not the number of
+        * characters that would have been put into the buffer
+        * had it been large enough, if the string is truncated.
+        * The only way to get that value is to use _vscprintf();
+        * getting that count isn't worth the re-formatting.
+        *
+        * XXX - does _vsnprintf_s() return -1 on a formatting
+        * error?
+        */
+       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/mkdep b/mkdep
index bfe4a26..1486b18 100755 (executable)
--- a/mkdep
+++ b/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
index d82056e..26d9008 100644 (file)
@@ -1,43 +1,43 @@
-#include <stdio.h>\r
-#include <stdlib.h>\r
-#include <stdarg.h>\r
-#include <time.h>\r
-\r
-static void Abort (char *fmt,...)\r
-{\r
-  va_list args;\r
-  va_start (args, fmt);\r
-  vfprintf (stderr, fmt, args);\r
-  va_end (args);\r
-  exit (1);\r
-}\r
-\r
-int main (int argc, char **argv)\r
-{\r
-  FILE  *inFile;\r
-  FILE  *outFile = stdout;\r
-  time_t now     = time (NULL);\r
-  int    ch, i;\r
-\r
-  if (argc != 2)\r
-     Abort ("Usage: %s bin-file [> result]", argv[0]);\r
-\r
-  if ((inFile = fopen(argv[1],"rb")) == NULL)\r
-     Abort ("Cannot open %s\n", argv[1]);\r
-\r
-  fprintf (outFile,\r
-           "/* data statements for file %s at %.24s */\n"\r
-           "/* Generated by BIN2C, G.Vanem 1995 */\n",\r
-           argv[1], ctime(&now));\r
-\r
-  i = 0;\r
-  while ((ch = fgetc(inFile)) != EOF)\r
-  {\r
-    if (i++ % 12 == 0)\r
-       fputs ("\n  ", outFile);\r
-    fprintf (outFile, "0x%02X,", ch);\r
-  }\r
-  fputc ('\n', outFile);\r
-  fclose (inFile);\r
-  return (0);\r
-}\r
+#include <stdio.h>
+#include <stdlib.h>
+#include <stdarg.h>
+#include <time.h>
+
+static void Abort (const char *fmt,...)
+{
+  va_list args;
+  va_start (args, fmt);
+  vfprintf (stderr, fmt, args);
+  va_end (args);
+  exit (1);
+}
+
+int main (int argc, char **argv)
+{
+  FILE  *inFile;
+  FILE  *outFile = stdout;
+  time_t now     = time (NULL);
+  int    ch, i;
+
+  if (argc != 2)
+     Abort ("Usage: %s bin-file [> result]", argv[0]);
+
+  if ((inFile = fopen(argv[1],"rb")) == NULL)
+     Abort ("Cannot open %s\n", argv[1]);
+
+  fprintf (outFile,
+           "/* data statements for file %s at %.24s */\n"
+           "/* Generated by BIN2C, G. Vanem 1995 */\n",
+           argv[1], ctime(&now));
+
+  i = 0;
+  while ((ch = fgetc(inFile)) != EOF)
+  {
+    if (i++ % 12 == 0)
+       fputs ("\n  ", outFile);
+    fprintf (outFile, "0x%02X,", ch);
+  }
+  fputc ('\n', outFile);
+  fclose (inFile);
+  return (0);
+}
diff --git a/msdos/common.dj b/msdos/common.dj
deleted file mode 100644 (file)
index ec0ce02..0000000
+++ /dev/null
@@ -1,79 +0,0 @@
-#
-# Common defines for libpcap and 16/32-bit network drivers (djgpp)
-#
-
-.SUFFIXES: .exe .wlm .dxe .l .y
-.PHONY:    check_gcclib
-
-default: check_gcclib all
-
-GCCLIB   = /djgpp/lib/gcc-lib/djgpp/3.31
-MAKEFILE = Makefile.dj
-
-#
-# DLX 2.91+ lib. Change path to suite.
-# Not used anymore. Uses DXE3 now.
-#
-# DLX_LIB  = $(DJDIR)/contrib/dlx.291/libdlx.a
-# DLX_LINK = $(DJDIR)/bin/dlxgen.exe
-
-WATT32_ROOT = $(subst \,/,$(WATT_ROOT))
-
-
-ifeq ($(wildcard $(GCCLIB)/libgcc.a),)
-check_gcclib:
-       @echo libgcc.a not found. Set \"$(GCCLIB)\" to \"/djgpp/lib/gcc-lib/djgpp/3.X\"
-endif
-
-
-#
-# Include 32-bit driver support
-#
-USE_32BIT_DRIVERS = 0
-
-#
-# Use loadable driver modules instead of statically linking
-# all drivers.
-#
-USE_32BIT_MODULES = 0
-
-#
-# Put interrupt sensitive code/data in locked sections
-# Do `make clean' in all affected directories after changing this.
-#
-USE_SECTION_LOCKING = 0
-
-#
-# Set to 1 to use exception handler lib (only for me)
-#
-USE_EXCEPT = 0
-
-CC   = gcc.exe
-LD   = ld.exe
-ASM  = nasm.exe -fbin -dDEBUG
-YACC = bison.exe
-LEX  = flex.exe
-
-CFLAGS = -g -gcoff -O2 -Wall -I. -I$(WATT32_ROOT)/inc
-
-ifeq ($(USE_EXCEPT),1)
-  CFLAGS += -DUSE_EXCEPT
-  EXC_LIB = d:/prog/mw/except/lib/libexc.a
-endif
-
-ifeq ($(USE_SECTION_LOCKING),1)
-  CFLAGS += -DUSE_SECTION_LOCKING
-endif
-
-ifeq ($(USE_32BIT_DRIVERS),1)
-  CFLAGS += -DUSE_32BIT_DRIVERS
-endif
-
-%.o: %.c
-       $(CC) -c $(CFLAGS) $<
-       @echo
-
-%.o: %.s
-       $(CC) -c $(CFLAGS) -x assembler-with-cpp -o $@ $<
-       @echo
-
index cdb4e7c..599a619 100644 (file)
-#\r
-#  Makefile for dos-libpcap. NB. This makefile requires a Borland\r
-#  compatible make tool.\r
-#\r
-#  Targets:\r
-#    Borland C 4.0+      (DOS large model)\r
-#    Metaware HighC 3.3+ (PharLap 386|DosX)\r
-#\r
-\r
-.AUTODEPEND\r
-.SWAP\r
-\r
-!if "$(WATT_ROOT)" == ""\r
-!error Environment variable "WATT_ROOT" not set.\r
-!endif\r
-\r
-WATT_INC = $(WATT_ROOT)\inc\r
-\r
-DEFS   = -DMSDOS -DDEBUG -DNDIS_DEBUG -D_U_= -Dinline= \\r
-         -DHAVE_STRERROR -DHAVE_LIMITS_H\r
-\r
-ASM    = tasm.exe -t -l -mx -m2 -DDEBUG\r
-\r
-SOURCE = grammar.c  scanner.c bpf_filt.c bpf_imag.c bpf_dump.c \\r
-         etherent.c gencode.c nametoad.c pcap-dos.c optimize.c \\r
-         savefile.c pcap.c inet.c msdos\ndis2.c msdos\pktdrvr.c \\r
-         missing\snprintf.c\r
-\r
-BORLAND_OBJ = $(SOURCE:.c=.obj) msdos\pkt_rx0.obj msdos\ndis_0.obj\r
-\r
-HIGHC_OBJ   = $(SOURCE:.c=.o32) msdos\pkt_rx0.o32\r
-\r
-all:\r
-            @echo Usage: make pcap_bc.lib or pcap_hc.lib\r
-\r
-\r
-pcap_bc.lib: bcc.arg $(BORLAND_OBJ) pcap_bc\r
-\r
-\r
-pcap_hc.lib: hc386.arg $(HIGHC_OBJ)\r
-            386lib $< @&&|\r
-               -nowarn -nobackup -twocase -replace $(HIGHC_OBJ)\r
-|\r
-\r
-pcap_bc:    $(BORLAND_OBJ)\r
-            @tlib pcap_bc.lib /C @&&|\r
-               -+$(**:.obj=-+)\r
-|\r
-\r
-.c.obj:\r
-            bcc.exe @bcc.arg -o$*.obj $*.c\r
-\r
-.c.o32:\r
-            hc386.exe @hc386.arg -o $*.o32 $*.c\r
-\r
-.asm.obj:\r
-            $(ASM) $*.asm, $*.obj\r
-\r
-.asm.o32:\r
-            $(ASM) -DDOSX=1 $*.asm, $*.o32\r
-\r
-scanner.c: scanner.l\r
-            flex -Ppcap_ -7 -oscanner.c scanner.l\r
-\r
-grammar.c tokdefs.h: grammar.y\r
-            bison --name-prefix=pcap_ --yacc --defines grammar.y\r
-            - @del grammar.c\r
-            - @del tokdefs.h\r
-            ren y_tab.c grammar.c\r
-            ren y_tab.h tokdefs.h\r
-\r
-bcc.arg:    msdos\Makefile\r
-            @copy &&|\r
-              $(DEFS) -ml -c -v -3 -O2 -po -RT- -w-\r
-              -I$(WATT_INC) -I. -I.\msdos\pm_drvr -H=$(TEMP)\bcc.sym\r
-| $<\r
-\r
-hc386.arg:  msdos\Makefile\r
-            @copy &&|\r
-            # -DUSE_32BIT_DRIVERS\r
-              $(DEFS) -DDOSX=1 -w3 -c -g -O5\r
-              -I$(WATT_INC) -I. -I.\msdos\pm_drvr\r
-              -Hsuffix=.o32\r
-              -Hnocopyr\r
-              -Hpragma=Offwarn(491,553,572)\r
-              -Hon=Recognize_library  # make memcpy/strlen etc. inline\r
-              -Hoff=Behaved           # turn off some optimiser warnings\r
-| $<\r
-\r
-clean:\r
-            @del *.obj\r
-            @del *.o32\r
-            @del *.lst\r
-            @del *.map\r
-            @del bcc.arg\r
-            @del hc386.arg\r
-            @del grammar.c\r
-            @del tokdefs.h\r
-            @del scanner.c\r
-            @echo Cleaned\r
-\r
-#\r
-# dependencies\r
-#             \r
-pkt_rx0.obj:  msdos\pkt_rx0.asm\r
-\r
-bpf_filt.obj: bpf_filt.c pcap-int.h pcap.h pcap-bpf.h gnuc.h\r
-\r
-bpf_imag.obj: bpf_imag.c pcap-int.h pcap.h pcap-bpf.h\r
-\r
-bpf_dump.obj: bpf_dump.c pcap.h pcap-bpf.h\r
-\r
-etherent.obj: etherent.c pcap-int.h pcap.h pcap-bpf.h pcap-namedb.h\r
-\r
-optimize.obj: optimize.c pcap-int.h pcap.h pcap-bpf.h gencode.h\r
-\r
-savefile.obj: savefile.c pcap-int.h pcap.h pcap-bpf.h\r
-\r
-pcap.obj: pcap.c pcap-dos.h pcap-int.h pcap.h pcap-bpf.h\r
-\r
-inet.obj: inet.c pcap-int.h pcap.h pcap-bpf.h\r
-\r
-grammar.obj: grammar.c pcap-int.h pcap.h pcap-bpf.h gencode.h \\r
-  pf.h pcap-namedb.h\r
-\r
-scanner.obj: scanner.c pcap-int.h pcap.h pcap-bpf.h gencode.h \\r
-  pcap-namedb.h tokdefs.h\r
-\r
-gencode.obj: gencode.c pcap-dos.h pcap-int.h pcap.h pcap-bpf.h \\r
-  ethertype.h nlpid.h llc.h gencode.h atmuni31.h sunatmpos.h ppp.h sll.h \\r
-  arcnet.h pf.h pcap-namedb.h\r
-\r
-nametoad.obj: nametoad.c pcap-int.h pcap.h pcap-bpf.h gencode.h \\r
-  pcap-namedb.h ethertype.h\r
-\r
-pcap-dos.obj: pcap-dos.c pcap.h pcap-bpf.h pcap-dos.h pcap-int.h \\r
-  msdos\pktdrvr.h\r
-\r
-pktdrvr.obj: msdos\pktdrvr.c gnuc.h pcap-dos.h pcap-int.h \\r
-  pcap.h pcap-bpf.h msdos\pktdrvr.h msdos\pkt_stub.inc\r
-\r
-ndis2.obj: msdos\ndis2.c pcap-dos.h pcap-int.h pcap.h pcap-bpf.h \\r
-  msdos\ndis2.h\r
-\r
-pkt_rx0.o32:  msdos\pkt_rx0.asm\r
-\r
-bpf_filt.o32: bpf_filt.c pcap-int.h pcap.h pcap-bpf.h gnuc.h\r
-\r
-bpf_imag.o32: bpf_imag.c pcap-int.h pcap.h pcap-bpf.h\r
-\r
-bpf_dump.o32: bpf_dump.c pcap.h pcap-bpf.h\r
-\r
-etherent.o32: etherent.c pcap-int.h pcap.h pcap-bpf.h pcap-namedb.h\r
-\r
-optimize.o32: optimize.c pcap-int.h pcap.h pcap-bpf.h gencode.h\r
-\r
-savefile.o32: savefile.c pcap-int.h pcap.h pcap-bpf.h\r
-\r
-pcap.o32: pcap.c pcap-dos.h pcap-int.h pcap.h pcap-bpf.h\r
-\r
-inet.o32: inet.c pcap-int.h pcap.h pcap-bpf.h\r
-\r
-grammar.o32: grammar.c pcap-int.h pcap.h pcap-bpf.h gencode.h \\r
-  pf.h pcap-namedb.h\r
-\r
-scanner.o32: scanner.c pcap-int.h pcap.h pcap-bpf.h gencode.h \\r
-  pcap-namedb.h tokdefs.h\r
-\r
-gencode.o32: gencode.c pcap-dos.h pcap-int.h pcap.h pcap-bpf.h \\r
-  ethertype.h nlpid.h llc.h gencode.h atmuni31.h sunatmpos.h ppp.h sll.h \\r
-  arcnet.h pf.h pcap-namedb.h\r
-\r
-nametoad.o32: nametoad.c pcap-int.h pcap.h pcap-bpf.h gencode.h \\r
-  pcap-namedb.h ethertype.h\r
-\r
-pcap-dos.o32: pcap-dos.c pcap.h pcap-bpf.h pcap-dos.h pcap-int.h \\r
-  msdos\pktdrvr.h\r
-\r
-pktdrvr.o32: msdos\pktdrvr.c gnuc.h pcap-dos.h pcap-int.h \\r
-  pcap.h pcap-bpf.h msdos\pktdrvr.h msdos\pkt_stub.inc\r
-\r
-ndis2.o32: msdos\ndis2.c pcap-dos.h pcap-int.h pcap.h pcap-bpf.h \\r
-  msdos\ndis2.h\r
-\r
+#
+#  Makefile for dos-libpcap. NB. This makefile requires a Borland
+#  compatible make tool.
+#
+#  Targets:
+#    Borland C 4.0+      (DOS large model)
+#    Metaware HighC 3.3+ (PharLap 386|DosX)
+#
+
+.AUTODEPEND
+.SWAP
+
+!if "$(WATT_ROOT)" == ""
+!error Environment variable "WATT_ROOT" not set.
+!endif
+
+WATT_INC = $(WATT_ROOT)\inc
+
+DEFS   = -DMSDOS -DDEBUG -DNDIS_DEBUG -D_U_= -Dinline= \
+         -DHAVE_STRERROR -DHAVE_LIMITS_H
+
+ASM    = tasm.exe -t -l -mx -m2 -DDEBUG
+
+SOURCE = grammar.c  scanner.c bpf_filt.c bpf_imag.c bpf_dump.c \
+         etherent.c gencode.c nametoad.c pcap-dos.c optimize.c \
+         savefile.c pcap.c msdos\ndis2.c msdos\pktdrvr.c \
+         missing\snprintf.c
+
+BORLAND_OBJ = $(SOURCE:.c=.obj) msdos\pkt_rx0.obj msdos\ndis_0.obj
+
+HIGHC_OBJ   = $(SOURCE:.c=.o32) msdos\pkt_rx0.o32
+
+all:
+            @echo Usage: make pcap_bc.lib or pcap_hc.lib
+
+
+pcap_bc.lib: bcc.arg $(BORLAND_OBJ) pcap_bc
+
+
+pcap_hc.lib: hc386.arg $(HIGHC_OBJ)
+            386lib $< @&&|
+               -nowarn -nobackup -twocase -replace $(HIGHC_OBJ)
+|
+
+pcap_bc:    $(BORLAND_OBJ)
+            @tlib pcap_bc.lib /C @&&|
+               -+$(**:.obj=-+)
+|
+
+.c.obj:
+            bcc.exe @bcc.arg -o$*.obj $*.c
+
+.c.o32:
+            hc386.exe @hc386.arg -o $*.o32 $*.c
+
+.asm.obj:
+            $(ASM) $*.asm, $*.obj
+
+.asm.o32:
+            $(ASM) -DDOSX=1 $*.asm, $*.o32
+
+scanner.c: scanner.l
+            flex -Ppcap_ -7 -oscanner.c scanner.l
+
+grammar.c tokdefs.h: grammar.y
+            bison --name-prefix=pcap_ --yacc --defines grammar.y
+            - @del grammar.c
+            - @del tokdefs.h
+            ren y_tab.c grammar.c
+            ren y_tab.h tokdefs.h
+
+bcc.arg:    msdos\Makefile
+            @copy &&|
+              $(DEFS) -ml -c -v -3 -O2 -po -RT- -w-
+              -I$(WATT_INC) -I. -I.\msdos\pm_drvr -H=$(TEMP)\bcc.sym
+| $<
+
+hc386.arg:  msdos\Makefile
+            @copy &&|
+            # -DUSE_32BIT_DRIVERS
+              $(DEFS) -DDOSX=1 -w3 -c -g -O5
+              -I$(WATT_INC) -I. -I.\msdos\pm_drvr
+              -Hsuffix=.o32
+              -Hnocopyr
+              -Hpragma=Offwarn(491,553,572)
+              -Hon=Recognize_library  # make memcpy/strlen etc. inline
+              -Hoff=Behaved           # turn off some optimiser warnings
+| $<
+
+clean:
+            @del *.obj
+            @del *.o32
+            @del *.lst
+            @del *.map
+            @del bcc.arg
+            @del hc386.arg
+            @del grammar.c
+            @del tokdefs.h
+            @del scanner.c
+            @echo Cleaned
+
+#
+# dependencies
+#
+pkt_rx0.obj:  msdos\pkt_rx0.asm
+
+bpf_filt.obj: bpf_filt.c pcap-int.h pcap.h pcap-bpf.h gnuc.h
+
+bpf_imag.obj: bpf_imag.c pcap-int.h pcap.h pcap-bpf.h
+
+bpf_dump.obj: bpf_dump.c pcap.h pcap-bpf.h
+
+etherent.obj: etherent.c pcap-int.h pcap.h pcap-bpf.h pcap-namedb.h
+
+optimize.obj: optimize.c pcap-int.h pcap.h pcap-bpf.h gencode.h
+
+savefile.obj: savefile.c pcap-int.h pcap.h pcap-bpf.h
+
+pcap.obj: pcap.c pcap-dos.h pcap-int.h pcap.h pcap-bpf.h
+
+grammar.obj: grammar.c pcap-int.h pcap.h pcap-bpf.h gencode.h \
+  pf.h pcap-namedb.h
+
+scanner.obj: scanner.c pcap-int.h pcap.h pcap-bpf.h gencode.h \
+  pcap-namedb.h tokdefs.h
+
+gencode.obj: gencode.c pcap-dos.h pcap-int.h pcap.h pcap-bpf.h \
+  ethertype.h nlpid.h llc.h gencode.h atmuni31.h sunatmpos.h ppp.h sll.h \
+  arcnet.h pf.h pcap-namedb.h
+
+nametoad.obj: nametoad.c pcap-int.h pcap.h pcap-bpf.h gencode.h \
+  pcap-namedb.h ethertype.h
+
+pcap-dos.obj: pcap-dos.c pcap.h pcap-bpf.h pcap-dos.h pcap-int.h \
+  msdos\pktdrvr.h
+
+pktdrvr.obj: msdos\pktdrvr.c gnuc.h pcap-dos.h pcap-int.h \
+  pcap.h pcap-bpf.h msdos\pktdrvr.h msdos\pkt_stub.inc
+
+ndis2.obj: msdos\ndis2.c pcap-dos.h pcap-int.h pcap.h pcap-bpf.h \
+  msdos\ndis2.h
+
+pkt_rx0.o32:  msdos\pkt_rx0.asm
+
+bpf_filt.o32: bpf_filt.c pcap-int.h pcap.h pcap-bpf.h gnuc.h
+
+bpf_imag.o32: bpf_imag.c pcap-int.h pcap.h pcap-bpf.h
+
+bpf_dump.o32: bpf_dump.c pcap.h pcap-bpf.h
+
+etherent.o32: etherent.c pcap-int.h pcap.h pcap-bpf.h pcap-namedb.h
+
+optimize.o32: optimize.c pcap-int.h pcap.h pcap-bpf.h gencode.h
+
+savefile.o32: savefile.c pcap-int.h pcap.h pcap-bpf.h
+
+pcap.o32: pcap.c pcap-dos.h pcap-int.h pcap.h pcap-bpf.h
+
+grammar.o32: grammar.c pcap-int.h pcap.h pcap-bpf.h gencode.h \
+  pf.h pcap-namedb.h
+
+scanner.o32: scanner.c pcap-int.h pcap.h pcap-bpf.h gencode.h \
+  pcap-namedb.h tokdefs.h
+
+gencode.o32: gencode.c pcap-dos.h pcap-int.h pcap.h pcap-bpf.h \
+  ethertype.h nlpid.h llc.h gencode.h atmuni31.h sunatmpos.h ppp.h sll.h \
+  arcnet.h pf.h pcap-namedb.h
+
+nametoad.o32: nametoad.c pcap-int.h pcap.h pcap-bpf.h gencode.h \
+  pcap-namedb.h ethertype.h
+
+pcap-dos.o32: pcap-dos.c pcap.h pcap-bpf.h pcap-dos.h pcap-int.h \
+  msdos\pktdrvr.h
+
+pktdrvr.o32: msdos\pktdrvr.c gnuc.h pcap-dos.h pcap-int.h \
+  pcap.h pcap-bpf.h msdos\pktdrvr.h msdos\pkt_stub.inc
+
+ndis2.o32: msdos\ndis2.c pcap-dos.h pcap-int.h pcap.h pcap-bpf.h \
+  msdos\ndis2.h
+
index 28e3f2d..190db00 100644 (file)
@@ -6,43 +6,49 @@
 #
 #  c:\net\pcap> make -f msdos/makefile.dj
 #
+# Note: you should do a "set LFN=y" before running this makefile.
+#
 
-VPATH = missing msdos
+VPATH = missing msdos bpf/net
 
 PREREQUISITES = scanner.c grammar.c tokdefs.h version.h msdos/pkt_stub.inc
 
-include msdos/common.dj
+include ./msdos/common.dj
 
 DRIVER_DIR = ./msdos/pm_drvr
 
-CFLAGS += -DDEBUG -DNDIS_DEBUG -DHAVE_LIMITS_H -DHAVE_STRERROR \
-          -D_U_='__attribute__((unused))' -DHAVE_VERSION_H
+CFLAGS += -DDEBUG -DNDIS_DEBUG -DHAVE_LIMITS_H -DHAVE_STRERROR -DHAVE_SNPRINTF -DHAVE_VSNPRINTF\
+          -D_U_='__attribute__((unused))'
 
-# CFLAGS += -Dyylval=pcap_lval -DBDEBUG -DNDEBUG
+CFLAGS += -Dyylval=pcap_lval # -DBDEBUG -DNDEBUG
 
-SOURCES = grammar.c scanner.c bpf_filt.c bpf_imag.c bpf_dump.c   \
-          etherent.c gencode.c nametoad.c pcap-dos.c optimize.c  \
-          savefile.c pcap.c inet.c msdos\pktdrvr.c msdos/ndis2.c \
-          missing/snprintf.c
+SOURCES = grammar.c scanner.c bpf/net/bpf_filter.c bpf_image.c bpf_dump.c \
+          etherent.c gencode.c nametoaddr.c pcap-common.c pcap-dos.c optimize.c \
+          savefile.c pcap.c sf-pcap.c sf-pcapng.c \
+          msdos/pktdrvr.c msdos/ndis2.c # missing/snprintf.c
 
-OBJECTS = $(notdir $(SOURCES:.c=.o))
+OBJECTS = $(addprefix $(OBJ_DIR)/, $(notdir $(SOURCES:.c=.o)))
 TEMPBIN = tmp.bin
 
 ifeq ($(USE_32BIT_DRIVERS),1)
-  PM_OBJECTS = $(addprefix $(DRIVER_DIR)/, \
+  PM_OBJECTS = $(addprefix $(OBJ_DIR)/, \
                  printk.o pci.o pci-scan.o bios32.o dma.o irq.o intwrap.o \
                  lock.o kmalloc.o quirks.o timer.o net_init.o)
   #
   # Static link of drivers
   #
   ifeq ($(USE_32BIT_MODULES),0)
-    PM_OBJECTS += $(addprefix $(DRIVER_DIR)/, \
+    PM_OBJECTS += $(addprefix $(OBJ_DIR)/, \
                     accton.o 8390.o 3c503.o 3c509.o 3c59x.o 3c515.o \
                     3c575_cb.o 3c90x.o ne.o wd.o cs89x0.o rtl8139.o)
   endif
 endif
 
-all: libpcap.a
+TARGETS = msdos/bin2c.exe libpcap.a filtertest.exe findalldevstest.exe \
+          nonblocktest.exe opentest.exe
+
+all: $(TARGETS)
+       @echo 'Welcome to libpcap/djgpp with samples.'
 
 ifeq ($(USE_32BIT_DRIVERS),1)
 $(PM_OBJECTS):
@@ -53,6 +59,22 @@ libpcap.a: version.h $(OBJECTS) $(PM_OBJECTS)
        rm -f $@
        ar rs $@ $^
 
+filtertest.exe: tests/filtertest.c libpcap.a
+       $(CC) $(CFLAGS) -Din_addr_t=u_long -o $@ $^ $(WATT32_ROOT)/lib/libwatt.a
+       @echo
+
+findalldevstest.exe: tests/findalldevstest.c libpcap.a
+       $(CC) $(CFLAGS) -o $@ $^ $(WATT32_ROOT)/lib/libwatt.a
+       @echo
+
+nonblocktest.exe: tests/nonblocktest.c libpcap.a
+       $(CC) $(CFLAGS) -o $@ $^ $(WATT32_ROOT)/lib/libwatt.a
+       @echo
+
+opentest.exe: tests/opentest.c libpcap.a
+       $(CC) $(CFLAGS) -o $@ $^ $(WATT32_ROOT)/lib/libwatt.a
+       @echo
+
 msdos/pkt_stub.inc: msdos/bin2c.exe msdos/pkt_rx1.S
        $(ASM) -o $(TEMPBIN) -lmsdos/pkt_rx1.lst msdos/pkt_rx1.S
        ./msdos/bin2c $(TEMPBIN) > $@
@@ -61,8 +83,8 @@ msdos/pkt_stub.inc: msdos/bin2c.exe msdos/pkt_rx1.S
 grammar.c tokdefs.h: grammar.y
        rm -f grammar.c tokdefs.h
        $(YACC) --name-prefix=pcap_ --yacc --defines grammar.y
-       mv -f y_tab.c grammar.c
-       mv -f y_tab.h tokdefs.h
+       mv -f y.tab.c grammar.c
+       mv -f y.tab.h tokdefs.h
 
 version.h: ./VERSION
        @echo '/* Generated from VERSION. Do not edit */' > $@
@@ -76,76 +98,30 @@ msdos/bin2c.exe: msdos/bin2c.c
        $(CC) $*.c -o $*.exe
 
 clean:
-       $(MAKE) -f Makefile.dj -C $(DRIVER_DIR) clean
-       $(MAKE) -f Makefile.dj -C libcpcap clean
-       rm -f $(OBJECTS) msdos/pkt_rx1.lst Makefile.bak $(PREREQUISITES)
+       rm -f $(OBJECTS) msdos/pkt_rx1.lst Makefile.bak .depend.dj $(PREREQUISITES)
+#      $(MAKE) -f Makefile.dj -C $(DRIVER_DIR) clean
 
 vclean: clean
-       rm -f libpcap.a msdos/bin2c.exe
-
-#
-# Generated dependencies; Due to some hacks in gcc 2.95 and djgpp 2.03
-# we must prevent "$(DJDIR)/bin/../include/sys/version.h" from beeing
-# included in dependency output (or else this makefile cannot be used on
-# another machine). We therefore use a special 'specs' file during
-# pre-processing.
-#
-MM_SPECS = specs.tmp
-MAKEFILE = msdos/Makefile.dj
-
-depend: $(PREREQUISITES)
-       @echo Generating dependencies..
-       @cp $(MAKEFILE) Makefile.bak
-       @echo "*cpp: %(cpp_cpu) %{posix:-D_POSIX_SOURCE} -remap" > $(MM_SPECS)
-       sed -e "/^# DO NOT DELETE THIS LINE/,$$d" < Makefile.bak > $(MAKEFILE)
-       echo "# DO NOT DELETE THIS LINE"                        >> $(MAKEFILE)
-       $(CC) -MM -specs=$(MM_SPECS) $(CFLAGS) $(SOURCES)       >> $(MAKEFILE)
-       rm -f $(MM_SPECS)
+       rm -f $(TARGETS)
+       -rmdir $(OBJ_DIR)
 
 #
 # Manually generated dependencies
-#             
+#
 msdos/pktdrvr.c: msdos/pkt_stub.inc
 scanner.c: scanner.l
 grammar.c tokdefs.h: grammar.y
 grammar.h: grammar.y
-scanner.l: pcap-int.h pcap-namedb.h gencode.h grammar.h gnuc.h
-grammar.y: pcap-int.h gencode.h pcap-namedb.h gnuc.h
+scanner.l: pcap-int.h pcap-namedb.h gencode.h grammar.h
+grammar.y: pcap-int.h gencode.h pcap-namedb.h
 
 #
-# Automatically generated dependencies
+# Generate dependencies.
 #
-# DO NOT DELETE THIS LINE
-grammar.o: grammar.c pcap-int.h pcap.h pcap-bpf.h gencode.h pf.h \
-  pcap-namedb.h
-scanner.o: scanner.c pcap-int.h pcap.h pcap-bpf.h gencode.h pcap-namedb.h \
-  tokdefs.h
-bpf_filt.o: bpf_filt.c pcap-int.h pcap.h pcap-bpf.h gnuc.h
-bpf_imag.o: bpf_imag.c pcap-int.h pcap.h pcap-bpf.h
-bpf_dump.o: bpf_dump.c pcap.h pcap-bpf.h
-etherent.o: etherent.c pcap-int.h pcap.h pcap-bpf.h pcap-namedb.h
-gencode.o: gencode.c pcap-dos.h msdos/pm_drvr/lock.h pcap-int.h pcap.h \
-  pcap-bpf.h ethertype.h nlpid.h llc.h gencode.h atmuni31.h sunatmpos.h \
-  ppp.h sll.h arcnet.h pf.h pcap-namedb.h
-nametoad.o: nametoad.c pcap-int.h pcap.h pcap-bpf.h gencode.h \
-  pcap-namedb.h ethertype.h
-pcap-dos.o: pcap-dos.c msdos/pm_drvr/pmdrvr.h msdos/pm_drvr/iface.h \
-  msdos/pm_drvr/lock.h msdos/pm_drvr/ioport.h pcap-dos.h pcap-int.h \
-  pcap.h pcap-bpf.h msdos/pm_drvr/kmalloc.h msdos/pm_drvr/bitops.h \
-  msdos/pm_drvr/timer.h msdos/pm_drvr/dma.h msdos/pm_drvr/irq.h \
-  msdos/pm_drvr/printk.h msdos/pm_drvr/pci.h msdos/pm_drvr/bios32.h \
-  msdos/pm_drvr/module.h msdos/pm_drvr/3c501.h msdos/pm_drvr/3c503.h \
-  msdos/pm_drvr/3c509.h msdos/pm_drvr/3c59x.h msdos/pm_drvr/3c515.h \
-  msdos/pm_drvr/3c90x.h msdos/pm_drvr/3c575_cb.h msdos/pm_drvr/ne.h \
-  msdos/pm_drvr/wd.h msdos/pm_drvr/accton.h msdos/pm_drvr/cs89x0.h \
-  msdos/pm_drvr/rtl8139.h msdos/pm_drvr/ne2k-pci.h msdos/pktdrvr.h
-optimize.o: optimize.c pcap-int.h pcap.h pcap-bpf.h gencode.h
-savefile.o: savefile.c pcap-int.h pcap.h pcap-bpf.h
-pcap.o: pcap.c pcap-dos.h msdos/pm_drvr/lock.h pcap-int.h pcap.h \
-  pcap-bpf.h
-inet.o: inet.c pcap-int.h pcap.h pcap-bpf.h
-pktdrvr.o: msdos/pktdrvr.c gnuc.h pcap-dos.h msdos/pm_drvr/lock.h \
-  pcap-int.h pcap.h pcap-bpf.h msdos/pktdrvr.h msdos/pkt_stub.inc
-ndis2.o: msdos/ndis2.c pcap-dos.h msdos/pm_drvr/lock.h pcap-int.h pcap.h \
-  pcap-bpf.h msdos/ndis2.h
-snprintf.o: missing/snprintf.c pcap-int.h pcap.h pcap-bpf.h
+REPLACE = sed -e 's/\(.*\)\.o: /\n$$(OBJ_DIR)\/\1.o: /'
+
+depend: $(PREREQUISITES)
+       $(CC) -MM $(CFLAGS) $(SOURCES) | $(REPLACE) > .depend.dj
+
+-include .depend.dj
+
index e0d5672..0246012 100644 (file)
-#\r
-#  Watcom Makefile for dos-libpcap.\r
-#\r
-# Specify MODEL = `3r' or `3s'\r
-# Specify TARGET = `pharlap' or `dos4g'\r
-#\r
-# Use this makefile from the libpcap root directory.\r
-# E.g. like this:\r
-#\r
-#  c:\net\pcap> wmake -f msdos\makefile.wc\r
-#\r
-\r
-MODEL  = 3s\r
-TARGET = dos4g\r
-\r
-OBJDIR = msdos\$(TARGET).w$(MODEL)\r
-LIB    = $(OBJDIR)\pcap.lib\r
-\r
-.EXTENSIONS: .l .y\r
-\r
-DEFS = -dDEBUG -dNDIS_DEBUG -d_U_= -dHAVE_LIMITS_H -dHAVE_STRERROR &\r
-       -dHAVE_SNPRINTF -dHAVE_VSNPRINTF\r
-\r
-CC  = wcc386.exe\r
-ASM = wasm.exe -$(MODEL) $(DEFS) -dDOSX -dDOS4GW -zq -bt=dos -fr=nul -d3 -s\r
-\r
-OBJS = $(OBJDIR)\grammar.obj  $(OBJDIR)\scanner.obj  $(OBJDIR)\pcap.obj     &\r
-       $(OBJDIR)\bpf_filt.obj $(OBJDIR)\bpf_imag.obj $(OBJDIR)\bpf_dump.obj &\r
-       $(OBJDIR)\etherent.obj $(OBJDIR)\gencode.obj  $(OBJDIR)\nametoad.obj &\r
-       $(OBJDIR)\pcap-dos.obj $(OBJDIR)\pktdrvr.obj  $(OBJDIR)\optimize.obj &\r
-       $(OBJDIR)\savefile.obj $(OBJDIR)\inet.obj     $(OBJDIR)\ndis2.obj\r
-\r
-CFLAGS = $(DEFS) $(YYDEFS) -I. -I$(%watt_root)\inc -I.\msdos\pm_drvr &\r
-         -$(MODEL) -mf -zff -zgf -zq -bt=dos -fr=nul -w6 -fpi        &\r
-         -oilrtf -zm\r
-\r
-TEMPBIN = tmp.bin\r
-\r
-all: $(OBJDIR) $(OBJDIR)\pcap.lib\r
-\r
-$(OBJDIR):\r
-          - mkdir $(OBJDIR)\r
-\r
-$(OBJDIR)\pcap.lib: $(OBJS) wlib.arg\r
-          wlib -q -b -c $(OBJDIR)\pcap.lib @wlib.arg\r
-\r
-wlib.arg: msdos\makefile.wc\r
-          %create $^@\r
-          for %f in ($(OBJS)) do %append $^@ +- %f\r
-\r
-$(OBJDIR)\pktdrvr.obj: msdos\pkt_stub.inc msdos\pktdrvr.c gnuc.h &\r
-  pcap-dos.h pcap-int.h pcap.h msdos\pktdrvr.h\r
-          *$(CC) $(CFLAGS) msdos\pktdrvr.c -fo=$@\r
-\r
-$(OBJDIR)\ndis2.obj: msdos\ndis2.c\r
-          *$(CC) $(CFLAGS) msdos\ndis2.c -fo=$@\r
-\r
-.ERASE\r
-.c{$(OBJDIR)}.obj:\r
-          *$(CC) $(CFLAGS) $[@ -fo=$@\r
-\r
-grammar.c tokdefs.h: grammar.y \r
-          bison --name-prefix=pcap_ --yacc --defines $[@\r
-          - @del grammar.c\r
-          - @del tokdefs.h\r
-          ren y_tab.c grammar.c\r
-          ren y_tab.h tokdefs.h\r
-\r
-scanner.c: scanner.l\r
-          flex -Ppcap_ -7 -o$@ $[@\r
-\r
-msdos\pkt_stub.inc: bin2c.exe msdos\pkt_rx1.S\r
-          nasm -fbin -dDEBUG -o $(TEMPBIN) -lmsdos\pkt_rx1.lst msdos\pkt_rx1.S\r
-          bin2c.exe  $(TEMPBIN) > $@\r
-          @del $(TEMPBIN)\r
-\r
-bin2c.exe: msdos\bin2c.c\r
-          wcl $[@\r
-\r
-clean realclean vclean: .SYMBOLIC\r
-          for %f in (dos4g.w3r dos4g.w3s pharlap.w3r pharlap.w3s) do &\r
-            @del %f\*.obj\r
-          @del grammar.c\r
-          @del tokdefs.h\r
-          @del scanner.c\r
-          @del bin2c.exe\r
-          @del bin2c.obj\r
-          @del msdos\pkt_stub.inc\r
-          @echo Cleaned\r
-\r
-#\r
-# dependencies\r
-#                     \r
-$(OBJDIR)\bpf_filt.obj: bpf_filt.c pcap-int.h pcap.h pcap-bpf.h gnuc.h\r
-\r
-$(OBJDIR)\bpf_imag.obj: bpf_imag.c pcap-int.h pcap.h pcap-bpf.h\r
-\r
-$(OBJDIR)\bpf_dump.obj: bpf_dump.c pcap.h pcap-bpf.h\r
-\r
-$(OBJDIR)\etherent.obj: etherent.c pcap-int.h pcap.h pcap-bpf.h pcap-nam.h\r
-\r
-$(OBJDIR)\optimize.obj: optimize.c pcap-int.h pcap.h pcap-bpf.h gencode.h\r
-\r
-$(OBJDIR)\savefile.obj: savefile.c pcap-int.h pcap.h pcap-bpf.h\r
-\r
-$(OBJDIR)\pcap.obj: pcap.c pcap-dos.h pcap-int.h pcap.h pcap-bpf.h\r
-\r
-$(OBJDIR)\inet.obj: inet.c pcap-int.h pcap.h pcap-bpf.h\r
-\r
-$(OBJDIR)\grammar.obj: grammar.c pcap-int.h pcap.h pcap-bpf.h gencode.h &\r
-  pf.h pcap-nam.h\r
-\r
-$(OBJDIR)\scanner.obj: scanner.c pcap-int.h pcap.h pcap-bpf.h gencode.h &\r
-  pcap-nam.h tokdefs.h\r
-\r
-$(OBJDIR)\gencode.obj: gencode.c pcap-dos.h pcap-int.h pcap.h pcap-bpf.h &\r
-  ethertyp.h nlpid.h llc.h gencode.h atmuni31.h sunatmpo.h ppp.h sll.h &\r
-  arcnet.h pf.h pcap-nam.h\r
-\r
-$(OBJDIR)\nametoad.obj: nametoad.c pcap-int.h pcap.h pcap-bpf.h gencode.h &\r
-  pcap-nam.h ethertyp.h\r
-\r
-$(OBJDIR)\pcap-dos.obj: pcap-dos.c pcap.h pcap-bpf.h pcap-dos.h pcap-int.h &\r
-  msdos\pktdrvr.h\r
-\r
-$(OBJDIR)\pktdrvr.obj: msdos\pktdrvr.c gnuc.h pcap-dos.h pcap-int.h &\r
-  pcap.h pcap-bpf.h msdos\pktdrvr.h msdos\pkt_stub.inc\r
-\r
-$(OBJDIR)\ndis2.obj: msdos\ndis2.c pcap-dos.h pcap-int.h pcap.h pcap-bpf.h &\r
-  msdos\ndis2.h\r
-\r
+#
+#  Watcom Makefile for dos-libpcap.
+#
+# Specify MODEL = `3r' or `3s'
+# Specify TARGET = `pharlap' or `dos4g'
+#
+# Use this makefile from the libpcap root directory.
+# E.g. like this:
+#
+#  c:\net\pcap> wmake -f msdos\makefile.wc
+#
+
+MODEL  = 3s
+TARGET = dos4g
+
+OBJDIR = msdos\$(TARGET).w$(MODEL)
+LIB    = $(OBJDIR)\pcap.lib
+
+.EXTENSIONS: .l .y
+
+DEFS = -dDEBUG -dNDIS_DEBUG -d_U_= -dHAVE_LIMITS_H -dHAVE_STRERROR &
+       -dHAVE_SNPRINTF -dHAVE_VSNPRINTF
+
+CC  = wcc386.exe
+ASM = wasm.exe -$(MODEL) $(DEFS) -dDOSX -dDOS4GW -zq -bt=dos -fr=nul -d3 -s
+
+OBJS = $(OBJDIR)\grammar.obj    $(OBJDIR)\scanner.obj  $(OBJDIR)\pcap.obj     &
+       $(OBJDIR)\bpf_filter.obj $(OBJDIR)\bpf_imag.obj $(OBJDIR)\bpf_dump.obj &
+       $(OBJDIR)\etherent.obj   $(OBJDIR)\gencode.obj  $(OBJDIR)\nametoad.obj &
+       $(OBJDIR)\pcap-dos.obj   $(OBJDIR)\pktdrvr.obj  $(OBJDIR)\optimize.obj &
+       $(OBJDIR)\savefile.obj   $(OBJDIR)\ndis2.obj
+
+CFLAGS = $(DEFS) $(YYDEFS) -I. -I$(%watt_root)\inc -I.\msdos\pm_drvr &
+         -$(MODEL) -mf -zff -zgf -zq -bt=dos -fr=nul -w6 -fpi        &
+         -oilrtf -zm
+
+TEMPBIN = tmp.bin
+
+all: $(OBJDIR) $(OBJDIR)\pcap.lib
+
+$(OBJDIR):
+          - mkdir $(OBJDIR)
+
+$(OBJDIR)\pcap.lib: $(OBJS) wlib.arg
+          wlib -q -b -c $(OBJDIR)\pcap.lib @wlib.arg
+
+wlib.arg: msdos\makefile.wc
+          %create $^@
+          for %f in ($(OBJS)) do %append $^@ +- %f
+
+$(OBJDIR)\pktdrvr.obj: msdos\pkt_stub.inc msdos\pktdrvr.c &
+  pcap-dos.h pcap-int.h pcap.h msdos\pktdrvr.h
+          *$(CC) $(CFLAGS) msdos\pktdrvr.c -fo=$@
+
+$(OBJDIR)\bpf_filter.obj: bpf\net\bpf_filter.c
+          *$(CC) $(CFLAGS) bpf\net\bpf_filter.c -fo=$@
+
+$(OBJDIR)\ndis2.obj: msdos\ndis2.c
+          *$(CC) $(CFLAGS) msdos\ndis2.c -fo=$@
+
+.ERASE
+.c{$(OBJDIR)}.obj:
+          *$(CC) $(CFLAGS) $[@ -fo=$@
+
+grammar.c tokdefs.h: grammar.y
+          bison --name-prefix=pcap_ --yacc --defines $[@
+          - @del grammar.c
+          - @del tokdefs.h
+          ren y_tab.c grammar.c
+          ren y_tab.h tokdefs.h
+
+scanner.c: scanner.l
+          flex -Ppcap_ -7 -o$@ $[@
+
+msdos\pkt_stub.inc: bin2c.exe msdos\pkt_rx1.S
+          nasm -fbin -dDEBUG -o $(TEMPBIN) -lmsdos\pkt_rx1.lst msdos\pkt_rx1.S
+          bin2c.exe  $(TEMPBIN) > $@
+          @del $(TEMPBIN)
+
+bin2c.exe: msdos\bin2c.c
+          wcl $[@
+
+clean realclean vclean: .SYMBOLIC
+          for %f in (dos4g.w3r dos4g.w3s pharlap.w3r pharlap.w3s) do &
+            @del %f\*.obj
+          @del grammar.c
+          @del tokdefs.h
+          @del scanner.c
+          @del bin2c.exe
+          @del bin2c.obj
+          @del msdos\pkt_stub.inc
+          @echo Cleaned
+
+#
+# dependencies
+#
+$(OBJDIR)\bpf_filter.obj: bpf\net\bpf_filter.c pcap-int.h pcap.h pcap-bpf.h
+
+$(OBJDIR)\bpf_imag.obj: bpf_imag.c pcap-int.h pcap.h pcap-bpf.h
+
+$(OBJDIR)\bpf_dump.obj: bpf_dump.c pcap.h pcap-bpf.h
+
+$(OBJDIR)\etherent.obj: etherent.c pcap-int.h pcap.h pcap-bpf.h pcap-namedb.h
+
+$(OBJDIR)\optimize.obj: optimize.c pcap-int.h pcap.h pcap-bpf.h gencode.h
+
+$(OBJDIR)\savefile.obj: savefile.c pcap-int.h pcap.h pcap-bpf.h
+
+$(OBJDIR)\pcap.obj: pcap.c pcap-dos.h pcap-int.h pcap.h pcap-bpf.h
+
+$(OBJDIR)\grammar.obj: grammar.c pcap-int.h pcap.h pcap-bpf.h gencode.h &
+  pcap-namedb.h
+
+$(OBJDIR)\scanner.obj: scanner.c pcap-int.h pcap.h pcap-bpf.h gencode.h &
+  pcap-namedb.h tokdefs.h
+
+$(OBJDIR)\gencode.obj: gencode.c pcap-dos.h pcap-int.h pcap.h pcap-bpf.h &
+  ethertyp.h nlpid.h llc.h gencode.h atmuni31.h sunatmpo.h ppp.h sll.h &
+  arcnet.h pcap-namedb.h
+
+$(OBJDIR)\nametoad.obj: nametoad.c pcap-int.h pcap.h pcap-bpf.h gencode.h &
+  pcap-namedb.h ethertyp.h
+
+$(OBJDIR)\pcap-dos.obj: pcap-dos.c pcap.h pcap-bpf.h pcap-dos.h pcap-int.h &
+  msdos\pktdrvr.h
+
+$(OBJDIR)\pktdrvr.obj: msdos\pktdrvr.c pcap-dos.h pcap-int.h &
+  pcap.h pcap-bpf.h msdos\pktdrvr.h msdos\pkt_stub.inc
+
+$(OBJDIR)\ndis2.obj: msdos\ndis2.c pcap-dos.h pcap-int.h pcap.h pcap-bpf.h &
+  msdos\ndis2.h
+
diff --git a/msdos/ndis2.c b/msdos/ndis2.c
deleted file mode 100644 (file)
index 0a5ea2a..0000000
+++ /dev/null
@@ -1,860 +0,0 @@
-/* \r
- * Copyright (c) 1993,1994\r
- *      Texas A&M University.  All rights reserved.\r
- *\r
- * Redistribution and use in source and binary forms, with or without\r
- * modification, are permitted provided that the following conditions\r
- * are met:\r
- * 1. Redistributions of source code must retain the above copyright\r
- *    notice, this list of conditions and the following disclaimer.\r
- * 2. Redistributions in binary form must reproduce the above copyright\r
- *    notice, this list of conditions and the following disclaimer in the\r
- *    documentation and/or other materials provided with the distribution.\r
- * 3. All advertising materials mentioning features or use of this software\r
- *    must display the following acknowledgement:\r
- *      This product includes software developed by Texas A&M University\r
- *      and its contributors.\r
- * 4. Neither the name of the University nor the names of its contributors\r
- *    may be used to endorse or promote products derived from this software\r
- *    without specific prior written permission.\r
- *\r
- * THIS SOFTWARE IS PROVIDED BY THE UNIVERSITY AND CONTRIBUTORS ``AS IS'' AND\r
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE\r
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE\r
- * ARE DISCLAIMED.  IN NO EVENT SHALL THE UNIVERSITY OR CONTRIBUTORS BE LIABLE\r
- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL\r
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS\r
- * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)\r
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT\r
- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY\r
- * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF\r
- * SUCH DAMAGE.\r
- *\r
- * Developers:\r
- *             David K. Hess, Douglas Lee Schales, David R. Safford\r
- *\r
- * Heavily modified for Metaware HighC + GNU C 2.8+\r
- *             Gisle Vanem 1998\r
- */\r
-\r
-#include <stdio.h>\r
-#include <stdlib.h>\r
-#include <dos.h>\r
-#include <io.h>\r
-#include <fcntl.h>\r
-#include <malloc.h>\r
-#include <string.h>\r
-\r
-#include "pcap-dos.h"\r
-#include "pcap-int.h"\r
-#include "msdos/ndis2.h"\r
-\r
-#if defined(USE_NDIS2)\r
-\r
-/*\r
- *  Packet buffer handling\r
- */\r
-extern int     FreePktBuf  (PktBuf *buf);\r
-extern int     EnquePktBuf (PktBuf *buf);\r
-extern PktBuf* AllocPktBuf (void);\r
-\r
-/*\r
- *  Various defines\r
- */\r
-#define MAX_NUM_DEBUG_STRINGS 90\r
-#define DEBUG_STRING_LENGTH   80\r
-#define STACK_POOL_SIZE       6\r
-#define STACK_SIZE            256\r
-\r
-#define MEDIA_FDDI            1\r
-#define MEDIA_ETHERNET        2\r
-#define MEDIA_TOKEN           3\r
-\r
-static int     startDebug     = 0;\r
-static int     stopDebug      = 0;\r
-\r
-static DWORD   droppedPackets = 0L;\r
-static WORD    frameSize      = 0;\r
-static WORD    headerSize     = 0;\r
-static int     mediaType      = 0;\r
-static char   *lastErr        = NULL;\r
-\r
-static BYTE    debugStrings [MAX_NUM_DEBUG_STRINGS][DEBUG_STRING_LENGTH];\r
-static BYTE   *freeStacks   [STACK_POOL_SIZE];\r
-static int     freeStackPtr = STACK_POOL_SIZE - 1;\r
-\r
-static ProtMan protManEntry = NULL;\r
-static WORD    protManDS    = 0;\r
-static volatile int xmitPending;\r
-\r
-static struct _PktBuf        *txBufPending;\r
-static struct _CardHandle    *handle;\r
-static struct _CommonChars    common;\r
-static struct _ProtocolChars  protChars;\r
-static struct _ProtDispatch   lowerTable;\r
-\r
-static struct _FailingModules failingModules;\r
-static struct _BindingsList   bindings;\r
-\r
-static struct {\r
-         WORD  err_num;\r
-         char *err_text;\r
-       } ndis_errlist[] = {\r
-\r
-  { ERR_SUCCESS,\r
-    "The function completed successfully.\n"  },\r
-\r
-  { ERR_WAIT_FOR_RELEASE,\r
-    "The ReceiveChain completed successfully but the protocol has\n"\r
-    "retained control of the buffer.\n"  },\r
-\r
-  { ERR_REQUEST_QUEUED,\r
-    "The current request has been queued.\n"  },\r
-\r
-  { ERR_FRAME_NOT_RECOGNIZED,\r
-    "Frame not recognized.\n"  },\r
-\r
-  { ERR_FRAME_REJECTED,\r
-    "Frame was discarded.\n"  },\r
-\r
-  { ERR_FORWARD_FRAME,\r
-    "Protocol wishes to forward frame to another protocol.\n"  },\r
-\r
-  { ERR_OUT_OF_RESOURCE,\r
-    "Out of resource.\n"  },\r
-\r
-  { ERR_INVALID_PARAMETER,\r
-    "Invalid parameter.\n"  },\r
-\r
-  { ERR_INVALID_FUNCTION,\r
-    "Invalid function.\n"  },\r
-\r
-  { ERR_NOT_SUPPORTED,\r
-    "Not supported.\n"  },\r
-\r
-  { ERR_HARDWARE_ERROR,\r
-    "Hardware error.\n"  },\r
-\r
-  { ERR_TRANSMIT_ERROR,\r
-    "The packet was not transmitted due to an error.\n"  },\r
-\r
-  { ERR_NO_SUCH_DESTINATION,\r
-    "Token ring packet was not recognized when transmitted.\n"  },\r
-\r
-  { ERR_BUFFER_TOO_SMALL,\r
-    "Provided buffer was too small.\n"  },\r
-\r
-  { ERR_ALREADY_STARTED,\r
-    "Network drivers already started.\n"  },\r
-\r
-  { ERR_INCOMPLETE_BINDING,\r
-    "Protocol driver could not complete its bindings.\n"  },\r
-\r
-  { ERR_DRIVER_NOT_INITIALIZED,\r
-    "MAC did not initialize properly.\n"  },\r
-\r
-  { ERR_HARDWARE_NOT_FOUND,\r
-    "Hardware not found.\n"  },\r
-\r
-  { ERR_HARDWARE_FAILURE,\r
-    "Hardware failure.\n"  },\r
-\r
-  { ERR_CONFIGURATION_FAILURE,\r
-    "Configuration failure.\n"  },\r
-\r
-  { ERR_INTERRUPT_CONFLICT,\r
-    "Interrupt conflict.\n"  },\r
-\r
-  { ERR_INCOMPATIBLE_MAC,\r
-    "The MAC is not compatible with the protocol.\n"  },\r
-\r
-  { ERR_INITIALIZATION_FAILED,\r
-    "Initialization failed.\n"  },\r
-\r
-  { ERR_NO_BINDING,\r
-    "Binding did not occur.\n"  },\r
-\r
-  { ERR_NETWORK_MAY_NOT_BE_CONNECTED,\r
-    "The network may not be connected to the adapter.\n"  },\r
-\r
-  { ERR_INCOMPATIBLE_OS_VERSION,\r
-    "The version of the operating system is incompatible with the protocol.\n"  },\r
-\r
-  { ERR_ALREADY_REGISTERED,\r
-    "The protocol is already registered.\n"  },\r
-\r
-  { ERR_PATH_NOT_FOUND,\r
-    "PROTMAN.EXE could not be found.\n"  },\r
-\r
-  { ERR_INSUFFICIENT_MEMORY,\r
-    "Insufficient memory.\n"  },\r
-\r
-  { ERR_INFO_NOT_FOUND,\r
-    "Protocol Mananger info structure is lost or corrupted.\n"  },\r
-\r
-  { ERR_GENERAL_FAILURE,\r
-    "General failure.\n"  }\r
-};\r
-\r
-/*\r
- *  Some handy macros\r
- */       \r
-#define PERROR(str)    printf("%s (%d): %s\n", __FILE__,__LINE__,str)\r
-#define DEBUG_RING()   (debugStrings[stopDebug+1 == MAX_NUM_DEBUG_STRINGS ? \\r
-                        stopDebug = 0 : ++stopDebug])\r
-\r
-/*\r
- * needs rewrite for DOSX\r
- */\r
-#define MAC_DISPATCH(hnd)  ((struct _MacUpperDispatch*)(hnd)->common->upperDispatchTable)\r
-#define MAC_STATUS(hnd)    ((struct _MacStatusTable*)  (hnd)->common->serviceStatus)\r
-#define MAC_CHAR(hnd)      ((struct _MacChars*)        (hnd)->common->serviceChars)\r
-\r
-#ifdef NDIS_DEBUG\r
-  #define DEBUG0(str)      printf (str)\r
-  #define DEBUG1(fmt,a)    printf (fmt,a)\r
-  #define DEBUG2(fmt,a,b)  printf (fmt,a,b)\r
-  #define TRACE0(str)      sprintf (DEBUG_RING(),str)\r
-  #define TRACE1(fmt,a)    sprintf (DEBUG_RING(),fmt,a)\r
-#else\r
-  #define DEBUG0(str)      ((void)0)\r
-  #define DEBUG1(fmt,a)    ((void)0)\r
-  #define DEBUG2(fmt,a,b)  ((void)0)\r
-  #define TRACE0(str)      ((void)0)\r
-  #define TRACE1(fmt,a)    ((void)0)\r
-#endif\r
-\r
-/*\r
- * This routine is called from both threads\r
- */\r
-void NdisFreeStack (BYTE *aStack)\r
-{\r
-  GUARD();\r
-\r
-  if (freeStackPtr == STACK_POOL_SIZE - 1)\r
-     PERROR ("tried to free too many stacks");\r
-\r
-  freeStacks[++freeStackPtr] = aStack;\r
-\r
-  if (freeStackPtr == 0)\r
-     TRACE0 ("freeStackPtr went positive\n");\r
-\r
-  UNGUARD();\r
-}\r
-\r
-/*\r
- * This routine is called from callbacks to allocate local data\r
- */\r
-BYTE *NdisAllocStack (void)\r
-{\r
-  BYTE *stack;\r
-\r
-  GUARD();\r
-\r
-  if (freeStackPtr < 0)\r
-  {\r
-    /* Ran out of stack buffers. Return NULL which will start\r
-     * dropping packets\r
-     */\r
-    TRACE0 ("freeStackPtr went negative\n");\r
-    stack = 0;\r
-  }\r
-  else\r
-    stack = freeStacks[freeStackPtr--];\r
-\r
-  UNGUARD();\r
-  return (stack);\r
-}\r
-\r
-CALLBACK (NdisSystemRequest (DWORD param1, DWORD param2, WORD param3,\r
-                             WORD opcode, WORD targetDS))\r
-{\r
-  static int            bindEntry = 0;\r
-  struct _CommonChars  *macCommon;\r
-  volatile WORD result;\r
-\r
-  switch (opcode)\r
-  {\r
-    case REQ_INITIATE_BIND:\r
-         macCommon = (struct _CommonChars*) param2;\r
-         if (macCommon == NULL)\r
-        {\r
-           printf ("There is an NDIS misconfiguration.\n");\r
-           result = ERR_GENERAL_FAILURE;\r
-          break;\r
-        }\r
-         DEBUG2 ("module name %s\n"\r
-                 "module type %s\n",\r
-                 macCommon->moduleName,\r
-                 ((MacChars*) macCommon->serviceChars)->macName);\r
-\r
-         /* Binding to the MAC */\r
-         result = macCommon->systemRequest ((DWORD)&common, (DWORD)&macCommon,\r
-                                            0, REQ_BIND,\r
-                                            macCommon->moduleDS);\r
-\r
-         if (!strcmp(bindings.moduleName[bindEntry], handle->moduleName))\r
-              handle->common = macCommon;\r
-         else PERROR ("unknown module");\r
-         ++bindEntry;\r
-        break;\r
-\r
-    case REQ_INITIATE_UNBIND:\r
-         macCommon = (struct _CommonChars*) param2;\r
-         result = macCommon->systemRequest ((DWORD)&common, 0,\r
-                                            0, REQ_UNBIND,\r
-                                            macCommon->moduleDS);\r
-         break;\r
-\r
-    default:\r
-         result = ERR_GENERAL_FAILURE;\r
-        break;\r
-  }\r
-  ARGSUSED (param1);\r
-  ARGSUSED (param3);\r
-  ARGSUSED (targetDS);\r
-  return (result);\r
-}\r
-\r
-CALLBACK (NdisRequestConfirm (WORD protId, WORD macId,   WORD reqHandle,\r
-                              WORD status, WORD request, WORD protDS))\r
-{\r
-  ARGSUSED (protId);    ARGSUSED (macId);\r
-  ARGSUSED (reqHandle); ARGSUSED (status);\r
-  ARGSUSED (request);   ARGSUSED (protDS);\r
-  return (ERR_SUCCESS);\r
-}\r
-\r
-CALLBACK (NdisTransmitConfirm (WORD protId, WORD macId, WORD reqHandle,\r
-                               WORD status, WORD protDS))\r
-{\r
-  xmitPending--;\r
-  FreePktBuf (txBufPending);  /* Add passed ECB back to the free list */\r
-\r
-  ARGSUSED (reqHandle);\r
-  ARGSUSED (status);\r
-  ARGSUSED (protDS);\r
-  return (ERR_SUCCESS);\r
-}\r
-\r
-\r
-/*\r
- * The primary function for receiving packets\r
- */\r
-CALLBACK (NdisReceiveLookahead (WORD  macId,      WORD  frameSize,\r
-                                WORD  bytesAvail, BYTE *buffer,\r
-                                BYTE *indicate,   WORD  protDS))\r
-{\r
-  int     result;\r
-  PktBuf *pktBuf;\r
-  WORD    bytesCopied;\r
-  struct _TDBufDescr tDBufDescr;\r
-\r
-#if 0\r
-  TRACE1 ("lookahead length = %d, ", bytesAvail);\r
-  TRACE1 ("ecb = %08lX, ",          *ecb);\r
-  TRACE1 ("count = %08lX\n",         count);\r
-  TRACE1 ("offset = %08lX, ",        offset);\r
-  TRACE1 ("timesAllowed = %d, ",     timesAllowed);\r
-  TRACE1 ("packet size = %d\n",      look->dataLookAheadLen);\r
-#endif\r
-\r
-  /* Allocate a buffer for the packet\r
-   */\r
-  if ((pktBuf = AllocPktBuf()) == NULL)\r
-  {\r
-    droppedPackets++;\r
-    return (ERR_FRAME_REJECTED);\r
-  }\r
-\r
-  /*\r
-   * Now kludge things. Note we will have to undo this later. This will\r
-   * make the packet contiguous after the MLID has done the requested copy.\r
-   */\r
-\r
-  tDBufDescr.tDDataCount = 1;\r
-  tDBufDescr.tDBufDescrRec[0].tDPtrType = NDIS_PTR_PHYSICAL;\r
-  tDBufDescr.tDBufDescrRec[0].tDDataPtr = pktBuf->buffer;\r
-  tDBufDescr.tDBufDescrRec[0].tDDataLen = pktBuf->length;\r
-  tDBufDescr.tDBufDescrRec[0].dummy     = 0;\r
-\r
-  result = MAC_DISPATCH(handle)->transferData (&bytesCopied, 0, &tDBufDescr,\r
-                                               handle->common->moduleDS);\r
-  pktBuf->packetLength = bytesCopied;\r
-\r
-  if (result == ERR_SUCCESS)\r
-       EnquePktBuf(pktBuf);\r
-  else FreePktBuf (pktBuf);\r
-\r
-  ARGSUSED (frameSize);\r
-  ARGSUSED (bytesAvail);\r
-  ARGSUSED (indicate);\r
-  ARGSUSED (protDS);\r
-\r
-  return (ERR_SUCCESS);\r
-}\r
-\r
-CALLBACK (NdisIndicationComplete (WORD macId, WORD protDS))\r
-{\r
-  ARGSUSED (macId);\r
-  ARGSUSED (protDS);\r
-\r
-  /* We don't give a hoot about these. Just return\r
-   */\r
-  return (ERR_SUCCESS);\r
-}\r
-\r
-/*\r
- * This is the OTHER way we may receive packets\r
- */\r
-CALLBACK (NdisReceiveChain (WORD macId, WORD frameSize, WORD reqHandle,\r
-                            struct _RxBufDescr *rxBufDescr,\r
-                            BYTE *indicate, WORD protDS))\r
-{\r
-  struct _PktBuf *pktBuf;\r
-  int     i;\r
-\r
-  /*\r
-   * For now we copy the entire packet over to a PktBuf structure. This may be\r
-   * a performance hit but this routine probably isn't called very much, and\r
-   * it is a lot of work to do it otherwise. Also if it is a filter protocol\r
-   * packet we could end up sucking up MAC buffes.\r
-   */\r
-\r
-  if ((pktBuf = AllocPktBuf()) == NULL)\r
-  {\r
-    droppedPackets++;\r
-    return (ERR_FRAME_REJECTED);\r
-  }\r
-  pktBuf->packetLength = 0;\r
-\r
-  /* Copy the packet to the buffer\r
-   */\r
-  for (i = 0; i < rxBufDescr->rxDataCount; ++i)\r
-  {\r
-    struct _RxBufDescrRec *rxDescr = &rxBufDescr->rxBufDescrRec[i];\r
-\r
-    memcpy (pktBuf->buffer + pktBuf->packetLength,\r
-            rxDescr->rxDataPtr, rxDescr->rxDataLen);\r
-    pktBuf->packetLength += rxDescr->rxDataLen;\r
-  }\r
-\r
-  EnquePktBuf (pktBuf);\r
-\r
-  ARGSUSED (frameSize);\r
-  ARGSUSED (reqHandle);\r
-  ARGSUSED (indicate);\r
-  ARGSUSED (protDS);   \r
-\r
-  /* This frees up the buffer for the MAC to use\r
-   */\r
-  return (ERR_SUCCESS);\r
-}\r
-\r
-CALLBACK (NdisStatusProc (WORD macId,  WORD param1, BYTE *indicate,\r
-                          WORD opcode, WORD protDS))\r
-{\r
-  switch (opcode)\r
-  {\r
-    case STATUS_RING_STATUS:\r
-        break;\r
-    case STATUS_ADAPTER_CHECK:\r
-        break;\r
-    case STATUS_START_RESET:\r
-        break;\r
-    case STATUS_INTERRUPT:\r
-        break;\r
-    case STATUS_END_RESET:\r
-        break;\r
-    default:\r
-        break;\r
-  }\r
-  ARGSUSED (macId);\r
-  ARGSUSED (param1);\r
-  ARGSUSED (indicate);\r
-  ARGSUSED (opcode);\r
-  ARGSUSED (protDS);\r
-\r
-  /* We don't need to do anything about this stuff yet\r
-   */\r
-  return (ERR_SUCCESS);\r
-}\r
-\r
-/*\r
- * Tell the NDIS driver to start the delivery of the packet\r
- */\r
-int NdisSendPacket (struct _PktBuf *pktBuf, int macId)\r
-{ \r
-  struct _TxBufDescr txBufDescr;\r
-  int     result;\r
-\r
-  xmitPending++;\r
-  txBufPending = pktBuf;    /* we only have 1 pending Tx at a time */\r
-\r
-  txBufDescr.txImmedLen  = 0;\r
-  txBufDescr.txImmedPtr  = NULL;\r
-  txBufDescr.txDataCount = 1;\r
-  txBufDescr.txBufDescrRec[0].txPtrType = NDIS_PTR_PHYSICAL;\r
-  txBufDescr.txBufDescrRec[0].dummy     = 0;\r
-  txBufDescr.txBufDescrRec[0].txDataLen = pktBuf->packetLength;\r
-  txBufDescr.txBufDescrRec[0].txDataPtr = pktBuf->buffer;\r
-\r
-  result = MAC_DISPATCH(handle)->transmitChain (common.moduleId,\r
-                                                pktBuf->handle,\r
-                                                &txBufDescr,\r
-                                                handle->common->moduleDS);\r
-  switch (result)\r
-  {\r
-    case ERR_OUT_OF_RESOURCE:\r
-         /* Note that this should not happen but if it does there is not\r
-          * much we can do about it\r
-          */\r
-         printf ("ERROR: transmit queue overflowed\n");\r
-         return (0);\r
-\r
-    case ERR_SUCCESS:\r
-         /* Everything was hunky dory and synchronous. Free up the \r
-          * packet buffer\r
-          */\r
-         xmitPending--;\r
-         FreePktBuf (pktBuf);\r
-         return (1);\r
-\r
-    case ERR_REQUEST_QUEUED:\r
-         /* Everything was hunky dory and asynchronous. Do nothing\r
-          */\r
-         return (1);\r
-\r
-    default:\r
-         printf ("Tx fail, code = %04X\n", result);\r
-         return (0);\r
-  }\r
-}\r
-\r
-\r
-\r
-static int ndis_nerr = sizeof(ndis_errlist) / sizeof(ndis_errlist[0]);\r
-\r
-static char *Ndis_strerror (WORD errorCode)\r
-{\r
-  static char buf[30];\r
-  int    i;\r
-\r
-  for (i = 0; i < ndis_nerr; i++)\r
-      if (errorCode == ndis_errlist[i].err_num)\r
-         return (ndis_errlist[i].err_text);\r
-\r
-  sprintf (buf,"unknown error %d",errorCode);\r
-  return (buf);\r
-}\r
-\r
-\r
-char *NdisLastError (void)\r
-{\r
-  char *errStr = lastErr;\r
-  lastErr = NULL;\r
-  return (errStr);\r
-}\r
-\r
-int NdisOpen (void)\r
-{\r
-  struct _ReqBlock reqBlock;\r
-  int     result;\r
-  int     ndisFd = open (NDIS_PATH, O_RDONLY);\r
-\r
-  if (ndisFd < 0)\r
-  {\r
-    printf ("Could not open NDIS Protocol Manager device.\n");\r
-    return (0);\r
-  }\r
-\r
-  memset (&reqBlock, 0, sizeof(ReqBlock));\r
-\r
-  reqBlock.opcode = PM_GET_PROTOCOL_MANAGER_LINKAGE;\r
-\r
-  result = NdisGetLinkage (ndisFd, (char*)&reqBlock, sizeof(ReqBlock));\r
-  if (result != 0)\r
-  {\r
-    printf ("Could not get Protocol Manager linkage.\n");\r
-    close (ndisFd);\r
-    return (0);\r
-  }\r
-\r
-  close (ndisFd);\r
-  protManEntry = (ProtMan) reqBlock.pointer1;\r
-  protManDS    = reqBlock.word1;\r
-\r
-  DEBUG2 ("Entry Point = %04X:%04X\n", FP_SEG(protManEntry),FP_OFF(protManEntry));\r
-  DEBUG1 ("ProtMan DS  = %04X\n", protManDS);\r
-  return (1);\r
-}\r
-\r
-\r
-int NdisRegisterAndBind (int promis)\r
-{\r
-  struct _ReqBlock reqBlock;\r
-  WORD    result;\r
-\r
-  memset (&common,0,sizeof(common));\r
-\r
-  common.tableSize = sizeof (common);\r
-\r
-  common.majorNdisVersion   = 2;\r
-  common.minorNdisVersion   = 0;\r
-  common.majorModuleVersion = 2;\r
-  common.minorModuleVersion = 0;\r
-\r
-  /* Indicates binding from below and dynamically loaded\r
-   */\r
-  common.moduleFlags = 0x00000006L;\r
-\r
-  strcpy (common.moduleName, "PCAP");\r
-\r
-  common.protocolLevelUpper = 0xFF;\r
-  common.protocolLevelLower = 1;\r
-  common.interfaceLower     = 1;\r
-#ifdef __DJGPP__\r
-  common.moduleDS           = _dos_ds; /* the callback data segment */\r
-#else\r
-  common.moduleDS           = _DS;\r
-#endif\r
-\r
-  common.systemRequest      = (SystemRequest) systemRequestGlue;\r
-  common.serviceChars       = (BYTE*) &protChars;\r
-  common.serviceStatus      = NULL;\r
-  common.upperDispatchTable = NULL;\r
-  common.lowerDispatchTable = (BYTE*) &lowerTable;\r
-\r
-  protChars.length  = sizeof (protChars);\r
-  protChars.name[0] = 0;\r
-  protChars.type    = 0;\r
-\r
-  lowerTable.backPointer        = &common;\r
-  lowerTable.requestConfirm     = requestConfirmGlue;\r
-  lowerTable.transmitConfirm    = transmitConfirmGlue;\r
-  lowerTable.receiveLookahead   = receiveLookaheadGlue;\r
-  lowerTable.indicationComplete = indicationCompleteGlue;\r
-  lowerTable.receiveChain       = receiveChainGlue;\r
-  lowerTable.status             = statusGlue;\r
-  lowerTable.flags              = 3;\r
-  if (promis)\r
-     lowerTable.flags |= 4;   /* promiscous mode (receive everything) */\r
-\r
-  bindings.numBindings = 1;\r
-  strcpy (bindings.moduleName[0], handle->moduleName);\r
-\r
-  /* Register ourselves with NDIS\r
-   */\r
-  reqBlock.opcode   = PM_REGISTER_MODULE;\r
-  reqBlock.pointer1 = (BYTE FAR*) &common;\r
-  reqBlock.pointer2 = (BYTE FAR*) &bindings;\r
-\r
-  result = (*protManEntry) (&reqBlock, protManDS);\r
-  if (result)\r
-  {\r
-    printf ("Protman registering failed: %s\n", Ndis_strerror(result));\r
-    return (0);\r
-  }\r
-\r
-  /* Start the binding process\r
-   */\r
-  reqBlock.opcode   = PM_BIND_AND_START;\r
-  reqBlock.pointer1 = (BYTE FAR*) &failingModules;\r
-\r
-  result = (*protManEntry) (&reqBlock, protManDS);\r
-  if (result)\r
-  {\r
-    printf ("Start binding failed: %s\n", Ndis_strerror(result));\r
-    return (0);\r
-  }\r
-  return (1);\r
-}\r
-\r
-static int CheckMacFeatures (CardHandle *card)\r
-{\r
-  DWORD      serviceFlags;\r
-  BYTE _far *mediaString;\r
-  BYTE _far *mac_addr;\r
-\r
-  DEBUG2 ("checking card features\n"\r
-          "common table address = %08lX, macId = %d\n",\r
-          card->common, card->common->moduleId);\r
-\r
-  serviceFlags = MAC_CHAR (handle)->serviceFlags;\r
-\r
-  if ((serviceFlags & SF_PROMISCUOUS) == 0)\r
-  {\r
-    printf ("The MAC %s does not support promiscuous mode.\n",\r
-            card->moduleName);\r
-    return (0);\r
-  }\r
-\r
-  mediaString = MAC_CHAR (handle)->macName;\r
-\r
-  DEBUG1 ("media type = %s\n",mediaString);\r
-\r
-  /* Get the media type. And set the header size\r
-   */\r
-  if (!strncmp(mediaString,"802.3",5) ||\r
-      !strncmp(mediaString,"DIX",3)   ||\r
-      !strncmp(mediaString,"DIX+802.3",9))\r
-       headerSize = sizeof (EthernetIIHeader);\r
-\r
-  else if (!strncmp(mediaString,"FDDI",4))\r
-       headerSize = sizeof (FddiHeader) +\r
-                    sizeof (Ieee802Dot2SnapHeader);\r
-  else\r
-  {\r
-    printf ("Unsupported MAC type: `%s'\n", mediaString);\r
-    return (0);\r
-  }\r
-\r
-  frameSize = MAC_CHAR (handle)->maxFrameSize;\r
-  mac_addr  = MAC_CHAR (handle)->currentAddress;\r
-\r
-  printf ("Hardware address: %02X:%02X:%02X:%02X:%02X:%02X\n",\r
-          mac_addr[0], mac_addr[1], mac_addr[2],\r
-          mac_addr[3], mac_addr[4], mac_addr[5]);\r
-  return (1);\r
-}\r
-\r
-static int NdisStartMac (CardHandle *card)\r
-{\r
-  WORD result;\r
-\r
-  /* Set the lookahead length\r
-   */\r
-  result = MAC_DISPATCH(handle)->request (common.moduleId, 0,\r
-                                          headerSize, 0,\r
-                                          REQ_SET_LOOKAHEAD,\r
-                                          card->common->moduleDS);\r
-\r
-  /* We assume that if we got INVALID PARAMETER then either this\r
-   * is not supported or will work anyway. NE2000 does this.\r
-   */\r
-  if (result != ERR_SUCCESS && result != ERR_INVALID_PARAMETER)\r
-  {\r
-    DEBUG1 ("Set lookahead failed: %s\n", Ndis_strerror(result));\r
-    return (0);\r
-  }\r
-\r
-  /* Set the packet filter. Note that for some medias and drivers we\r
-   * must specify all three flags or the card(s) will not operate correctly.\r
-   */\r
-  result = MAC_DISPATCH(handle)->request (common.moduleId, 0,\r
-                      /* all packets */   FILTER_PROMISCUOUS |\r
-                      /* packets to us */ FILTER_DIRECTED    |\r
-                      /* broadcasts */    FILTER_BROADCAST,\r
-                                          0, REQ_SET_PACKET_FILTER,\r
-                                          card->common->moduleDS);\r
-  if (result != ERR_SUCCESS)\r
-  {\r
-    DEBUG1 ("Set packet filter failed: %s\n", Ndis_strerror(result));\r
-    return (0);\r
-  }\r
-\r
-  /* If OPEN/CLOSE supported then open the adapter\r
-   */\r
-  if (MAC_CHAR(handle)->serviceFlags & SF_OPEN_CLOSE)\r
-  {\r
-    result = MAC_DISPATCH(handle)->request (common.moduleId, 0, 0, NULL,\r
-                                            REQ_OPEN_ADAPTER,\r
-                                            card->common->moduleDS);\r
-    if (result != ERR_SUCCESS)\r
-    {\r
-      DEBUG1 ("Opening the MAC failed: %s\n", Ndis_strerror(result));\r
-      return (0);\r
-    }\r
-  }\r
-  return (1);\r
-}\r
-\r
-void NdisShutdown (void)\r
-{\r
-  struct _ReqBlock reqBlock;\r
-  int     result, i;\r
-\r
-  if (!handle)\r
-     return;\r
-\r
-  /* If the adapters support open and are open then close them\r
-   */\r
-  if ((MAC_CHAR(handle)->serviceFlags & SF_OPEN_CLOSE) &&\r
-      (MAC_STATUS(handle)->macStatus & MAC_OPEN))\r
-  {\r
-    result = MAC_DISPATCH(handle)->request (common.moduleId, 0, 0, 0,\r
-                                            REQ_CLOSE_ADAPTER,\r
-                                            handle->common->moduleDS);\r
-    if (result != ERR_SUCCESS)\r
-    {\r
-      printf ("Closing the MAC failed: %s\n", Ndis_strerror(result));\r
-      return;\r
-    }\r
-  }\r
-\r
-  /* Tell the Protocol Manager to unbind and stop\r
-   */\r
-  reqBlock.opcode   = PM_UNBIND_AND_STOP;\r
-  reqBlock.pointer1 = (BYTE FAR*) &failingModules;\r
-  reqBlock.pointer2 = NULL;\r
-\r
-  result = (*protManEntry) (&reqBlock, protManDS);\r
-  if (result)\r
-     printf ("Unbind failed: %s\n",  Ndis_strerror(result));\r
-\r
-  for (i = 0; i < STACK_POOL_SIZE; ++i)\r
-     free (freeStacks[i] - STACK_SIZE);\r
-\r
-  handle = NULL;\r
-}\r
-\r
-int NdisInit (int promis)\r
-{\r
-  int i, result;\r
-\r
-  /* Allocate the real mode stacks used for NDIS callbacks\r
-   */\r
-  for (i = 0; i < STACK_POOL_SIZE; ++i)\r
-  {\r
-    freeStacks[i] = malloc (STACK_SIZE);\r
-    if (!freeStacks[i])\r
-       return (0);\r
-    freeStacks[i] += STACK_SIZE;\r
-  }\r
-\r
-  if (!NdisOpen())\r
-     return (0);\r
-\r
-  if (!NdisRegisterAndBind(promis))\r
-     return (0);\r
-\r
-  DEBUG1 ("My module id: %d\n", common.moduleId);\r
-  DEBUG1 ("Handle id;    %d\n", handle->common->moduleId);\r
-  DEBUG1 ("MAC card:     %-16s - ", handle->moduleName);\r
-\r
-  atexit (NdisShutdown);\r
-\r
-  if (!CheckMacFeatures(&handle))\r
-     return (0);\r
-\r
-  switch (mediaType)\r
-  {\r
-    case MEDIA_FDDI:\r
-         DEBUG0 ("Media type: FDDI");\r
-        break;\r
-    case MEDIA_ETHERNET:\r
-         DEBUG0 ("Media type: ETHERNET");\r
-        break;\r
-    default:\r
-         DEBUG0 ("Unsupported media.\n");\r
-         return (0);\r
-  }\r
-\r
-  DEBUG1 (" - Frame size: %d\n", frameSize);\r
-\r
-  if (!NdisStartMac(&handle))\r
-     return (0);\r
-  return (1);\r
-}\r
-#endif  /* USE_NDIS2 */\r
-\r
diff --git a/msdos/ndis2.h b/msdos/ndis2.h
deleted file mode 100644 (file)
index dc72f4c..0000000
+++ /dev/null
@@ -1,559 +0,0 @@
-/* \r
- * Copyright (c) 1993,1994\r
- *      Texas A&M University.  All rights reserved.\r
- *\r
- * Redistribution and use in source and binary forms, with or without\r
- * modification, are permitted provided that the following conditions\r
- * are met:\r
- * 1. Redistributions of source code must retain the above copyright\r
- *    notice, this list of conditions and the following disclaimer.\r
- * 2. Redistributions in binary form must reproduce the above copyright\r
- *    notice, this list of conditions and the following disclaimer in the\r
- *    documentation and/or other materials provided with the distribution.\r
- * 3. All advertising materials mentioning features or use of this software\r
- *    must display the following acknowledgement:\r
- *      This product includes software developed by Texas A&M University\r
- *      and its contributors.\r
- * 4. Neither the name of the University nor the names of its contributors\r
- *    may be used to endorse or promote products derived from this software\r
- *    without specific prior written permission.\r
- *\r
- * THIS SOFTWARE IS PROVIDED BY THE UNIVERSITY AND CONTRIBUTORS ``AS IS'' AND\r
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE\r
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE\r
- * ARE DISCLAIMED.  IN NO EVENT SHALL THE UNIVERSITY OR CONTRIBUTORS BE LIABLE\r
- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL\r
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS\r
- * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)\r
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT\r
- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY\r
- * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF\r
- * SUCH DAMAGE.\r
- *\r
- * Developers:\r
- *             David K. Hess, Douglas Lee Schales, David R. Safford\r
- *\r
- * Heavily modified for Metaware HighC + GNU C 2.8+\r
- *             Gisle Vanem 1998\r
- */\r
-\r
-#ifndef __PCAP_NDIS_H\r
-#define __PCAP_NDIS_H\r
-\r
-#if defined (__HIGHC__)\r
-  #define pascal          _CC(_CALLEE_POPS_STACK & ~_REVERSE_PARMS) /* calling convention */\r
-  #define CALLBACK(foo)   pascal WORD foo\r
-  #define PAS_PTR(x,arg)  typedef FAR WORD pascal (*x) arg\r
-  #define GUARD()         _inline (0x9C,0xFA)   /* pushfd, cli */\r
-  #define UNGUARD()       _inline (0x9D)        /* popfd */\r
-  #define FAR             _far\r
-\r
-#elif defined(__GNUC__)\r
-  #define CALLBACK(foo)   WORD foo __attribute__((stdcall))\r
-  #define PAS_PTR(x,arg)  typedef WORD (*x) arg __attribute__((stdcall))\r
-  #define GUARD()         __asm__ __volatile__ ("pushfd; cli")\r
-  #define UNGUARD()       __asm__ __volatile__ ("popfd")\r
-  #define FAR\r
-\r
-#elif defined (__TURBOC__)\r
-  #define CALLBACK(foo)   WORD pascal foo\r
-  #define PAS_PTR(x,arg)  typedef WORD pascal (_far *x) arg\r
-  #define GUARD()         _asm { pushf; cli }\r
-  #define UNGUARD()       _asm { popf }\r
-  #define FAR             _far\r
-\r
-#elif defined (__WATCOMC__)\r
-  #define CALLBACK(foo)   WORD pascal foo\r
-  #define PAS_PTR(x,arg)  typedef WORD pascal (_far *x) arg\r
-  #define GUARD()         _disable()\r
-  #define UNGUARD()       _enable()\r
-  #define FAR             _far\r
-\r
-#else\r
-  #error Unsupported compiler\r
-#endif\r
-\r
-\r
-/*\r
- *  Forwards\r
- */\r
-struct _ReqBlock;\r
-struct _TxBufDescr;\r
-struct _TDBufDescr;\r
-\r
-/*\r
- * Protocol Manager API\r
- */\r
-PAS_PTR (ProtMan, (struct _ReqBlock FAR*, WORD));\r
-\r
-/*\r
- * System request\r
- */\r
-PAS_PTR (SystemRequest, (DWORD, DWORD, WORD, WORD, WORD));\r
-\r
-/*\r
- * MAC API\r
- */\r
-PAS_PTR (TransmitChain, (WORD, WORD, struct _TxBufDescr FAR*, WORD));\r
-PAS_PTR (TransferData,  (WORD*,WORD, struct _TDBufDescr FAR*, WORD));\r
-PAS_PTR (Request,       (WORD, WORD, WORD, DWORD, WORD, WORD));\r
-PAS_PTR (ReceiveRelease,(WORD, WORD));\r
-PAS_PTR (IndicationOn,  (WORD));\r
-PAS_PTR (IndicationOff, (WORD));\r
-\r
-\r
-typedef enum {\r
-        HARDWARE_NOT_INSTALLED  = 0,\r
-        HARDWARE_FAILED_DIAG    = 1,\r
-        HARDWARE_FAILED_CONFIG  = 2,\r
-        HARDWARE_HARD_FAULT     = 3,\r
-        HARDWARE_SOFT_FAULT     = 4,\r
-        HARDWARE_OK             = 7,\r
-        HARDWARE_MASK           = 0x0007,\r
-        MAC_BOUND               = 0x0008,\r
-        MAC_OPEN                = 0x0010,\r
-        DIAG_IN_PROGRESS        = 0x0020\r
-      } NdisMacStatus;\r
-\r
-typedef enum {\r
-        STATUS_RING_STATUS      = 1,\r
-        STATUS_ADAPTER_CHECK    = 2,\r
-        STATUS_START_RESET      = 3,\r
-        STATUS_INTERRUPT        = 4,\r
-        STATUS_END_RESET        = 5\r
-      } NdisStatus;\r
-\r
-typedef enum {\r
-        FILTER_DIRECTED         = 1,\r
-        FILTER_BROADCAST        = 2,\r
-        FILTER_PROMISCUOUS      = 4,\r
-        FILTER_SOURCE_ROUTE     = 8\r
-      } NdisPacketFilter;\r
-\r
-typedef enum {\r
-        REQ_INITIATE_DIAGNOSTICS     = 1,\r
-        REQ_READ_ERROR_LOG           = 2,\r
-        REQ_SET_STATION_ADDRESS      = 3,\r
-        REQ_OPEN_ADAPTER             = 4,\r
-        REQ_CLOSE_ADAPTER            = 5,\r
-        REQ_RESET_MAC                = 6,\r
-        REQ_SET_PACKET_FILTER        = 7,\r
-        REQ_ADD_MULTICAST_ADDRESS    = 8,\r
-        REQ_DELETE_MULTICAST_ADDRESS = 9,\r
-        REQ_UPDATE_STATISTICS        = 10,\r
-        REQ_CLEAR_STATISTICS         = 11,\r
-        REQ_INTERRUPT_REQUEST        = 12,\r
-        REQ_SET_FUNCTIONAL_ADDRESS   = 13,\r
-        REQ_SET_LOOKAHEAD            = 14\r
-      } NdisGeneralRequest;\r
-\r
-typedef enum {\r
-        SF_BROADCAST             = 0x00000001L,\r
-        SF_MULTICAST             = 0x00000002L,\r
-        SF_FUNCTIONAL            = 0x00000004L,\r
-        SF_PROMISCUOUS           = 0x00000008L,\r
-        SF_SOFT_ADDRESS          = 0x00000010L,\r
-        SF_STATS_CURRENT         = 0x00000020L,\r
-        SF_INITIATE_DIAGS        = 0x00000040L,\r
-        SF_LOOPBACK              = 0x00000080L,\r
-        SF_RECEIVE_CHAIN         = 0x00000100L,\r
-        SF_SOURCE_ROUTING        = 0x00000200L,\r
-        SF_RESET_MAC             = 0x00000400L,\r
-        SF_OPEN_CLOSE            = 0x00000800L,\r
-        SF_INTERRUPT_REQUEST     = 0x00001000L,\r
-        SF_SOURCE_ROUTING_BRIDGE = 0x00002000L,\r
-        SF_VIRTUAL_ADDRESSES     = 0x00004000L\r
-      } NdisMacServiceFlags;\r
-\r
-typedef enum {\r
-        REQ_INITIATE_BIND        = 1,\r
-        REQ_BIND                 = 2,\r
-        REQ_INITIATE_PREBIND     = 3,\r
-        REQ_INITIATE_UNBIND      = 4,\r
-        REQ_UNBIND               = 5\r
-      } NdisSysRequest;\r
-\r
-typedef enum  {\r
-        PM_GET_PROTOCOL_MANAGER_INFO      = 1,\r
-        PM_REGISTER_MODULE                = 2,\r
-        PM_BIND_AND_START                 = 3,\r
-        PM_GET_PROTOCOL_MANAGER_LINKAGE   = 4,\r
-        PM_GET_PROTOCOL_INI_PATH          = 5,\r
-        PM_REGISTER_PROTOCOL_MANAGER_INFO = 6,\r
-        PM_INIT_AND_REGISTER              = 7,\r
-        PM_UNBIND_AND_STOP                = 8,\r
-        PM_BIND_STATUS                    = 9,\r
-        PM_REGISTER_STATUS                = 10\r
-      } NdisProtManager;\r
-\r
-\r
-typedef enum {\r
-        ERR_SUCCESS                      = 0x00,\r
-        ERR_WAIT_FOR_RELEASE             = 0x01,\r
-        ERR_REQUEST_QUEUED               = 0x02,\r
-        ERR_FRAME_NOT_RECOGNIZED         = 0x03,\r
-        ERR_FRAME_REJECTED               = 0x04,\r
-        ERR_FORWARD_FRAME                = 0x05,\r
-        ERR_OUT_OF_RESOURCE              = 0x06,\r
-        ERR_INVALID_PARAMETER            = 0x07,\r
-        ERR_INVALID_FUNCTION             = 0x08,\r
-        ERR_NOT_SUPPORTED                = 0x09,\r
-        ERR_HARDWARE_ERROR               = 0x0A,\r
-        ERR_TRANSMIT_ERROR               = 0x0B,\r
-        ERR_NO_SUCH_DESTINATION          = 0x0C,\r
-        ERR_BUFFER_TOO_SMALL             = 0x0D,\r
-        ERR_ALREADY_STARTED              = 0x20,\r
-        ERR_INCOMPLETE_BINDING           = 0x21,\r
-        ERR_DRIVER_NOT_INITIALIZED       = 0x22,\r
-        ERR_HARDWARE_NOT_FOUND           = 0x23,\r
-        ERR_HARDWARE_FAILURE             = 0x24,\r
-        ERR_CONFIGURATION_FAILURE        = 0x25,\r
-        ERR_INTERRUPT_CONFLICT           = 0x26,\r
-        ERR_INCOMPATIBLE_MAC             = 0x27,\r
-        ERR_INITIALIZATION_FAILED        = 0x28,\r
-        ERR_NO_BINDING                   = 0x29,\r
-        ERR_NETWORK_MAY_NOT_BE_CONNECTED = 0x2A,\r
-        ERR_INCOMPATIBLE_OS_VERSION      = 0x2B,\r
-        ERR_ALREADY_REGISTERED           = 0x2C,\r
-        ERR_PATH_NOT_FOUND               = 0x2D,\r
-        ERR_INSUFFICIENT_MEMORY          = 0x2E,\r
-        ERR_INFO_NOT_FOUND               = 0x2F,\r
-        ERR_GENERAL_FAILURE              = 0xFF\r
-      } NdisError;\r
-\r
-#define NDIS_PARAM_INTEGER   0\r
-#define NDIS_PARAM_STRING    1\r
-\r
-#define NDIS_TX_BUF_LENGTH   8\r
-#define NDIS_TD_BUF_LENGTH   1\r
-#define NDIS_RX_BUF_LENGTH   8\r
-\r
-#define NDIS_PTR_PHYSICAL    0\r
-#define NDIS_PTR_VIRTUAL     2\r
-\r
-#define NDIS_PATH    "PROTMAN$"\r
-\r
-\r
-typedef struct _CommonChars {\r
-        WORD  tableSize;\r
-        BYTE  majorNdisVersion;        /* 2 - Latest version */\r
-        BYTE  minorNdisVersion;        /* 0                  */\r
-        WORD  reserved1;\r
-        BYTE  majorModuleVersion;\r
-        BYTE  minorModuleVersion;\r
-        DWORD moduleFlags;\r
-        /* 0 - Binding at upper boundary supported\r
-         * 1 - Binding at lower boundary supported\r
-         * 2 - Dynamically bound.\r
-         * 3-31 - Reserved, must be zero.\r
-         */\r
-        BYTE  moduleName[16];\r
-        BYTE  protocolLevelUpper;\r
-        /* 1 - MAC\r
-         * 2 - Data Link\r
-         * 3 - Network\r
-         * 4 - Transport\r
-         * 5 - Session\r
-         * -1 - Not specified\r
-         */\r
-        BYTE  interfaceUpper;\r
-        BYTE  protocolLevelLower;\r
-        /* 0 - Physical\r
-         * 1 - MAC\r
-         * 2 - Data Link\r
-         * 3 - Network\r
-         * 4 - Transport\r
-         * 5 - Session\r
-         * -1 - Not specified\r
-         */\r
-        BYTE  interfaceLower;\r
-        WORD  moduleId;\r
-        WORD  moduleDS;\r
-        SystemRequest systemRequest;\r
-        BYTE *serviceChars;\r
-        BYTE *serviceStatus;\r
-        BYTE *upperDispatchTable;\r
-        BYTE *lowerDispatchTable;\r
-        BYTE *reserved2;            /* Must be NULL */\r
-        BYTE *reserved3;            /* Must be NULL */\r
-      } CommonChars;\r
-\r
-\r
-typedef struct _MulticastList {\r
-        WORD   maxMulticastAddresses;\r
-        WORD   numberMulticastAddresses;\r
-        BYTE   multicastAddress[16][16];\r
-      } MulticastList;\r
-\r
-\r
-typedef struct _MacChars {\r
-        WORD   tableSize;\r
-        BYTE   macName[16];\r
-        WORD   addressLength;\r
-        BYTE   permanentAddress[16];\r
-        BYTE   currentAddress[16];\r
-        DWORD  currentFunctionalAddress;\r
-        MulticastList *multicastList;\r
-        DWORD  linkSpeed;\r
-        DWORD  serviceFlags;\r
-        WORD   maxFrameSize;\r
-        DWORD  txBufferSize;\r
-        WORD   txBufferAllocSize;\r
-        DWORD  rxBufferSize;\r
-        WORD   rxBufferAllocSize;\r
-        BYTE   ieeeVendor[3];\r
-        BYTE   vendorAdapter;\r
-        BYTE  *vendorAdapterDescription;\r
-        WORD   interruptLevel;\r
-        WORD   txQueueDepth;\r
-        WORD   maxDataBlocks;\r
-      } MacChars;\r
-\r
-\r
-typedef struct _ProtocolChars {\r
-        WORD   length;\r
-        BYTE   name[16];\r
-        WORD   type;\r
-      } ProtocolChars;\r
-\r
-\r
-typedef struct _MacUpperDispatch {\r
-        CommonChars      *backPointer;\r
-        Request           request;\r
-        TransmitChain     transmitChain;\r
-        TransferData      transferData;\r
-        ReceiveRelease    receiveRelease;\r
-        IndicationOn      indicationOn;\r
-        IndicationOff     indicationOff;\r
-      } MacUpperDispatch;\r
-\r
-\r
-typedef struct _MacStatusTable {\r
-        WORD   tableSize;\r
-        DWORD  lastDiag;\r
-        DWORD  macStatus;\r
-        WORD   packetFilter;\r
-        BYTE  *mediaSpecificStats;\r
-        DWORD  lastClear;\r
-        DWORD  totalFramesRx;\r
-        DWORD  totalFramesCrc;\r
-        DWORD  totalBytesRx;\r
-        DWORD  totalDiscardBufSpaceRx;\r
-        DWORD  totalMulticastRx;\r
-        DWORD  totalBroadcastRx;\r
-        DWORD  obsolete1[5];\r
-        DWORD  totalDiscardHwErrorRx;\r
-        DWORD  totalFramesTx;\r
-        DWORD  totalBytesTx;\r
-        DWORD  totalMulticastTx;\r
-        DWORD  totalBroadcastTx;\r
-        DWORD  obsolete2[2];\r
-        DWORD  totalDiscardTimeoutTx;\r
-        DWORD  totalDiscardHwErrorTx;\r
-      } MacStatusTable;\r
-\r
-\r
-typedef struct _ProtDispatch {\r
-        CommonChars *backPointer;\r
-        DWORD        flags;\r
-        /* 0 - handles non-LLC frames\r
-         * 1 - handles specific-LSAP LLC frames\r
-         * 2 - handles specific-LSAP LLC frames\r
-         * 3-31 - reserved must be 0\r
-         */\r
-        void  (*requestConfirm) (void);\r
-        void  (*transmitConfirm) (void);\r
-        void  (*receiveLookahead) (void);\r
-        void  (*indicationComplete) (void);\r
-        void  (*receiveChain) (void);\r
-        void  (*status) (void);\r
-      } ProtDispatch;\r
-\r
-\r
-typedef struct _ReqBlock {\r
-        WORD      opcode;\r
-        WORD      status;\r
-        BYTE FAR *pointer1;\r
-        BYTE FAR *pointer2;\r
-        WORD      word1;\r
-      } ReqBlock;\r
-\r
-\r
-typedef struct _TxBufDescrRec {\r
-        BYTE   txPtrType;\r
-        BYTE   dummy;\r
-        WORD   txDataLen;\r
-        BYTE  *txDataPtr;\r
-      } TxBufDescrRec;\r
-\r
-\r
-typedef struct _TxBufDescr {\r
-        WORD          txImmedLen;\r
-        BYTE         *txImmedPtr;\r
-        WORD          txDataCount;\r
-        TxBufDescrRec txBufDescrRec[NDIS_TX_BUF_LENGTH];\r
-      } TxBufDescr;\r
-\r
-\r
-typedef struct _TDBufDescrRec {\r
-        BYTE   tDPtrType;\r
-        BYTE   dummy;\r
-        WORD   tDDataLen;\r
-        BYTE  *tDDataPtr;\r
-      } TDBufDescrRec;\r
-\r
-\r
-typedef struct _TDBufDescr {\r
-        WORD          tDDataCount;\r
-        TDBufDescrRec tDBufDescrRec[NDIS_TD_BUF_LENGTH];\r
-      } TDBufDescr;\r
-\r
-\r
-typedef struct _RxBufDescrRec {\r
-        WORD   rxDataLen;\r
-        BYTE  *rxDataPtr;\r
-      } RxBufDescrRec;\r
-\r
-\r
-typedef struct _RxBufDescr {\r
-        WORD          rxDataCount;\r
-        RxBufDescrRec rxBufDescrRec[NDIS_RX_BUF_LENGTH];\r
-      } RxBufDescr;\r
-\r
-\r
-typedef struct _PktBuf {\r
-       struct _PktBuf *nextLink;\r
-       struct _PktBuf *prevLink;\r
-        int    handle;\r
-        int    length;\r
-        int    packetLength;\r
-        DWORD  sequence;\r
-        BYTE  *buffer;\r
-      } PktBuf;\r
-\r
-\r
-typedef struct _CardHandle {\r
-        BYTE         moduleName[16];\r
-        CommonChars *common;\r
-      } CardHandle;\r
-\r
-\r
-typedef struct _BindingsList {\r
-        WORD  numBindings;\r
-        BYTE  moduleName[2][16];\r
-      } BindingsList;\r
-\r
-\r
-typedef struct _FailingModules {\r
-        BYTE  upperModuleName[16];\r
-        BYTE  lowerModuleName[16];\r
-      } FailingModules;\r
-\r
-\r
-typedef union _HardwareAddress {\r
-        BYTE  bytes[6];\r
-        WORD  words[3];\r
-        struct {\r
-          BYTE bytes[6];\r
-        } addr;\r
-      } HardwareAddress;\r
-\r
-\r
-typedef struct _FddiHeader {\r
-        BYTE             frameControl;\r
-        HardwareAddress  etherDestHost;\r
-        HardwareAddress  etherSrcHost;\r
-      } FddiHeader;\r
-\r
-\r
-typedef struct _EthernetIIHeader {\r
-        HardwareAddress  etherDestHost;\r
-        HardwareAddress  etherSrcHost;\r
-        WORD             etherType;\r
-      } EthernetIIHeader;\r
-\r
-\r
-typedef struct _Ieee802Dot5Header {\r
-        HardwareAddress  etherDestHost;\r
-        HardwareAddress  etherSrcHost;\r
-        BYTE             routeInfo[30];\r
-      } Ieee802Dot5Header;\r
-\r
-\r
-typedef struct _Ieee802Dot2SnapHeader {\r
-        BYTE  dsap;                      /* 0xAA */\r
-        BYTE  ssap;                      /* 0xAA */\r
-        BYTE  control;                   /* 3    */\r
-        BYTE protocolId[5];\r
-      } Ieee802Dot2SnapHeader;\r
-\r
-\r
-/*\r
- *  Prototypes\r
- */\r
-extern char *NdisLastError        (void);\r
-extern int   NdisOpen             (void);\r
-extern int   NdisInit             (int promis);\r
-extern int   NdisRegisterAndBind  (int promis);\r
-extern void  NdisShutdown         (void);\r
-extern void  NdisCheckMacFeatures (struct _CardHandle *card);\r
-extern int   NdisSendPacket       (struct _PktBuf *pktBuf, int macId);\r
-\r
-/*\r
- *  Assembly "glue" functions\r
- */\r
-extern int systemRequestGlue();\r
-extern int requestConfirmGlue();\r
-extern int transmitConfirmGlue();\r
-extern int receiveLookaheadGlue();\r
-extern int indicationCompleteGlue();\r
-extern int receiveChainGlue();\r
-extern int statusGlue();\r
-\r
-/*\r
- *  IOCTL function\r
- */\r
-#ifdef __SMALL__\r
-extern int _far NdisGetLinkage (int handle, char *data, int size);\r
-#else\r
-extern int NdisGetLinkage (int handle, char *data, int size);\r
-#endif\r
-\r
-/*\r
- *  NDIS callback handlers\r
- */\r
-CALLBACK (NdisSystemRequest     (DWORD,DWORD, WORD, WORD, WORD));\r
-CALLBACK (NdisRequestConfirm    ( WORD, WORD, WORD, WORD, WORD,WORD));\r
-CALLBACK (NdisTransmitConfirm   ( WORD, WORD, WORD, WORD, WORD));\r
-CALLBACK (NdisReceiveLookahead  ( WORD, WORD, WORD, BYTE*, BYTE*, WORD));\r
-CALLBACK (NdisReceiveChain      ( WORD, WORD, WORD, struct _RxBufDescr*, BYTE*, WORD));\r
-CALLBACK (NdisStatusProc        ( WORD, WORD, BYTE*, WORD,WORD));\r
-CALLBACK (NdisIndicationComplete( WORD, WORD));\r
-\r
-BYTE *NdisAllocStack (void);\r
-void  NdisFreeStack  (BYTE*);\r
-\r
-#ifdef __HIGHC__\r
-  #define RENAME_ASM_SYM(x) pragma Alias(x,"@" #x "")  /* prepend `@' */\r
-  #define RENAME_C_SYM(x)   pragma Alias(x,"_" #x "")  /* prepend `_' */\r
-\r
-  RENAME_ASM_SYM (systemRequestGlue);\r
-  RENAME_ASM_SYM (requestConfirmGlue);\r
-  RENAME_ASM_SYM (transmitConfirmGlue);\r
-  RENAME_ASM_SYM (receiveLookaheadGlue);\r
-  RENAME_ASM_SYM (indicationCompleteGlue);\r
-  RENAME_ASM_SYM (receiveChainGlue);\r
-  RENAME_ASM_SYM (statusGlue);\r
-  RENAME_ASM_SYM (NdisGetLinkage);\r
-  RENAME_C_SYM   (NdisSystemRequest);\r
-  RENAME_C_SYM   (NdisRequestConfirm);\r
-  RENAME_C_SYM   (NdisTransmitConfirm);\r
-  RENAME_C_SYM   (NdisReceiveLookahead);\r
-  RENAME_C_SYM   (NdisIndicationComplete);\r
-  RENAME_C_SYM   (NdisReceiveChain);\r
-  RENAME_C_SYM   (NdisStatusProc);\r
-  RENAME_C_SYM   (NdisAllocStack);\r
-  RENAME_C_SYM   (NdisFreeStack);\r
-#endif\r
-\r
-#endif\r
diff --git a/msdos/ndis_0.asm b/msdos/ndis_0.asm
deleted file mode 100644 (file)
index 2990985..0000000
+++ /dev/null
@@ -1,188 +0,0 @@
-PAGE 60,132\r
-NAME NDIS_0\r
-\r
-ifdef DOSX\r
-  .386\r
-  _TEXT   SEGMENT PUBLIC DWORD USE16 'CODE'\r
-  _TEXT   ENDS\r
-  _DATA   SEGMENT PUBLIC DWORD USE16 'CODE'\r
-  _DATA   ENDS\r
-  _TEXT32 SEGMENT PUBLIC BYTE  USE32 'CODE'\r
-  _TEXT32 ENDS\r
-  CB_DSEG EQU <CS>                          ; DOSX is tiny-model\r
-  D_SEG   EQU <_TEXT SEGMENT>\r
-  D_END   EQU <_TEXT ENDS>\r
-  ASSUME  CS:_TEXT,DS:_TEXT\r
-\r
-  PUSHREGS equ <pushad>\r
-  POPREGS  equ <popad>\r
-\r
-  PUBPROC macro name\r
-          align 4\r
-          public @&name\r
-          @&name label near\r
-          endm\r
-else\r
-  .286\r
-  _TEXT   SEGMENT PUBLIC DWORD 'CODE'\r
-  _TEXT   ENDS\r
-  _DATA   SEGMENT PUBLIC DWORD 'DATA'\r
-  _DATA   ENDS\r
-  CB_DSEG EQU <SEG _DATA>                   ; 16bit is small/large model\r
-  D_SEG   EQU <_DATA SEGMENT>\r
-  D_END   EQU <_DATA ENDS>\r
-  ASSUME  CS:_TEXT,DS:_DATA\r
-\r
-  PUSHREGS equ <pusha>\r
-  POPREGS  equ <popa>\r
-\r
-  PUBPROC  macro name\r
-           public _&name\r
-           _&name label far\r
-           endm\r
-endif\r
-\r
-;-------------------------------------------\r
-\r
-D_SEG\r
-\r
-D_END\r
-\r
-\r
-_TEXT SEGMENT\r
-\r
-EXTRN _NdisSystemRequest      : near\r
-EXTRN _NdisRequestConfirm     : near\r
-EXTRN _NdisTransmitConfirm    : near\r
-EXTRN _NdisReceiveLookahead   : near\r
-EXTRN _NdisIndicationComplete : near\r
-EXTRN _NdisReceiveChain       : near\r
-EXTRN _NdisStatusProc         : near\r
-EXTRN _NdisAllocStack         : near\r
-EXTRN _NdisFreeStack          : near\r
-\r
-;\r
-; *ALL* interrupt threads come through this macro.\r
-;\r
-CALLBACK macro callbackProc, argsSize\r
-\r
-     pushf\r
-     PUSHREGS                ;; Save the registers\r
-\r
-     push es\r
-     push ds\r
-     mov  ax,CB_DSEG         ;; Load DS\r
-     mov  ds,ax\r
-     call _NdisAllocStack    ;; Get and install a stack.\r
-\r
-     mov  bx,ss              ;; Save off the old stack in other regs\r
-     mov  cx,sp\r
-     mov  ss,dx              ;; Install the new one\r
-     mov  sp,ax\r
-     push bx                 ;; Save the old one on to the new stack\r
-     push cx\r
-     sub  sp,&argsSize       ;; Allocate space for arguments on the stack\r
-\r
-     mov  ax,ss              ;; Set up the destination for the move\r
-     mov  es,ax\r
-     mov  di,sp\r
-     mov  ds,bx              ;; Set up the source for the move.\r
-     mov  si,cx\r
-     add  si,4+6+32\r
-\r
-     mov  cx,&argsSize       ;; Move the arguments to the stack.\r
-     shr  cx,1\r
-     cld\r
-     rep  movsw\r
-\r
-     mov  ax,CB_DSEG         ;; Set my data segment again.\r
-     mov  ds,ax\r
-\r
-     call &callbackProc      ;; Call the real callback.\r
-     pop  di                 ;; Pop off the old stack\r
-     pop  si\r
-     mov  bx,ss              ;; Save off the current allocated stack.\r
-     mov  cx,sp\r
-     mov  ss,si              ;; Restore the old stack\r
-     mov  sp,di\r
-     push ax                 ;; Save the return code\r
-     push bx                 ;; Free the stack. Push the pointer to it\r
-     push cx\r
-     call _NdisFreeStack\r
-     add  sp,4\r
-     pop  ax                 ;; Get the return code back\r
-     add  di,32              ;; Get a pointer to ax on the stack\r
-     mov  word ptr ss:[di],ax\r
-     pop  ds\r
-     pop  es\r
-\r
-     POPREGS\r
-     popf\r
-endm\r
-\r
-;\r
-; Define all of the callbacks for the NDIS procs.\r
-;\r
-\r
-PUBPROC systemRequestGlue\r
-CALLBACK _NdisSystemRequest,14\r
-RETF\r
-\r
-PUBPROC requestConfirmGlue\r
-CALLBACK _NdisRequestConfirm,12\r
-RETF\r
-\r
-PUBPROC transmitConfirmGlue\r
-CALLBACK _NdisTransmitConfirm,10\r
-RETF\r
-\r
-PUBPROC receiveLookaheadGlue\r
-CALLBACK _NdisReceiveLookahead,16\r
-RETF\r
-\r
-PUBPROC indicationCompleteGlue\r
-CALLBACK _NdisIndicationComplete,4\r
-RETF\r
-\r
-PUBPROC receiveChainGlue\r
-CALLBACK _NdisReceiveChain,16\r
-RETF\r
-\r
-PUBPROC statusGlue\r
-CALLBACK _NdisStatusProc,12\r
-RETF\r
-\r
-;\r
-; int FAR NdisGetLinkage (int handle, char *data, int size);\r
-;\r
-\r
-ifdef DOSX\r
-  PUBPROC NdisGetLinkage\r
-          push ebx\r
-          mov ebx, [esp+8]              ; device handle\r
-          mov eax, 4402h                ; IOCTRL read function\r
-          mov edx, [esp+12]             ; DS:EDX -> result data\r
-          mov ecx, [esp+16]             ; ECX = length\r
-          int 21h\r
-          pop ebx\r
-          jc  @fail\r
-          xor eax, eax\r
-  @fail:  ret\r
-\r
-else\r
-  PUBPROC NdisGetLinkage\r
-          enter 0, 0\r
-          mov bx, [bp+6]\r
-          mov ax, 4402h\r
-          mov dx, [bp+8]\r
-          mov cx, [bp+12]\r
-          int 21h\r
-          jc  @fail\r
-          xor ax, ax\r
-  @fail:  leave\r
-          retf\r
-endif\r
-\r
-ENDS\r
-\r
-END\r
index 94f3d09..d604fa1 100644 (file)
-PAGE 60,132\r
-NAME PKT_RX\r
-\r
-ifdef ??version        ; using TASM\r
-  masm\r
-  jumps\r
-endif\r
-\r
-PUBLIC _pktDrop, _pktRxBuf, _pktTxBuf,    _pktTemp\r
-PUBLIC _rxOutOfs, _rxInOfs, _PktReceiver, _pktRxEnd\r
-\r
-;\r
-; these sizes MUST be equal to the sizes in PKTDRVR.H\r
-;\r
-\r
-RX_BUF_SIZE = 1500      ; max message size on Ethernet\r
-TX_BUF_SIZE = 1500\r
-\r
-ifdef DOSX\r
- .386\r
-  NUM_RX_BUF = 32       ; # of RX element buffers\r
-  _TEXT   SEGMENT PUBLIC DWORD USE16 'CODE'\r
-  _TEXT   ENDS\r
-  _DATA   SEGMENT PUBLIC DWORD USE16 'CODE'\r
-  _DATA   ENDS\r
-  D_SEG   EQU <_TEXT SEGMENT>\r
-  D_END   EQU <_TEXT ENDS>\r
-  ASSUME  CS:_TEXT,DS:_TEXT\r
-else\r
- .286\r
-  NUM_RX_BUF = 10\r
-  _TEXT   SEGMENT PUBLIC DWORD 'CODE'\r
-  _TEXT   ENDS\r
-  _DATA   SEGMENT PUBLIC DWORD 'DATA'\r
-  _DATA   ENDS\r
-  D_SEG   EQU <_DATA SEGMENT>\r
-  D_END   EQU <_DATA ENDS>\r
-  ASSUME  CS:_TEXT,DS:_DATA\r
-endif\r
-\r
-;-------------------------------------------\r
-\r
-D_SEG\r
-\r
-RX_ELEMENT     STRUC\r
-   firstCount  dw  0                          ; # of bytes on 1st call\r
-   secondCount dw  0                          ; # of bytes on 2nd call\r
-   handle      dw  0                          ; handle for upcall\r
-   destinAdr   db  6           dup (0)        ; packet destination address\r
-   sourceAdr   db  6           dup (0)        ; packet source address\r
-   protocol    dw  0                          ; packet protocol number\r
-   rxBuffer    db  RX_BUF_SIZE dup (0)        ; RX buffer\r
-ENDS\r
-               align 4\r
-_rxOutOfs      dw  offset _pktRxBuf           ; ring buffer offsets\r
-_rxInOfs       dw  offset _pktRxBuf           ; into _pktRxBuf\r
-_pktDrop       dw  0,0                        ; packet drop counter\r
-_pktTemp       db  20                dup (0)  ; temp work area\r
-_pktTxBuf      db  (TX_BUF_SIZE+14)  dup (0)  ; TX buffer\r
-_pktRxBuf      RX_ELEMENT NUM_RX_BUF dup (<>) ; RX structures\r
- LAST_OFS      = offset $\r
-\r
- screenSeg     dw  0B800h\r
- newInOffset   dw  0\r
-\r
- fanChars      db  '-\|/'\r
- fanIndex      dw  0\r
-\r
-D_END\r
-\r
-_TEXT SEGMENT\r
-\r
-\r
-SHOW_RX  MACRO\r
-         push es\r
-         push bx\r
-         mov bx, screenSeg\r
-         mov es, bx                    ;; r-mode segment of colour screen\r
-         mov di, 158                   ;; upper right corner - 1\r
-         mov bx, fanIndex\r
-         mov al, fanChars[bx]          ;; get write char\r
-         mov ah, 15                    ;;  and white colour\r
-         stosw                         ;; write to screen at ES:EDI\r
-         inc fanIndex                  ;; update next index\r
-         and fanIndex, 3\r
-         pop bx\r
-         pop es\r
-ENDM\r
-\r
-;------------------------------------------------------------------------\r
-;\r
-; This macro return ES:DI to tail of Rx queue\r
-\r
-ENQUEUE  MACRO\r
-         LOCAL @noWrap\r
-         mov ax, _rxInOfs              ;; DI = current in-offset\r
-         add ax, SIZE RX_ELEMENT       ;; point to next _pktRxBuf buffer\r
-         cmp ax, LAST_OFS              ;; pointing past last ?\r
-         jb  @noWrap                   ;; no - jump\r
-         lea ax, _pktRxBuf             ;; yes, point to 1st buffer\r
-         align 4\r
-@noWrap: cmp ax, _rxOutOfs             ;; in-ofs = out-ofs ?\r
-         je  @dump                     ;; yes, queue is full\r
-         mov di, _rxInOfs              ;; ES:DI -> buffer at queue input\r
-         mov newInOffset, ax           ;; remember new input offset\r
-\r
-   ;; NOTE. rxInOfs is updated after the packet has been copied\r
-   ;; to ES:DI (= DS:SI on 2nd call) by the packet driver\r
-\r
-ENDM\r
-\r
-;------------------------------------------------------------------------\r
-;\r
-; This routine gets called by the packet driver twice:\r
-;   1st time (AX=0) it requests an address where to put the packet\r
-;\r
-;   2nd time (AX=1) the packet has been copied to this location (DS:SI)\r
-;   BX has client handle (stored in RX_ELEMENT.handle).\r
-;   CX has # of bytes in packet on both call. They should be equal.\r
-;\r
-; A test for equality is done by putting CX in _pktRxBuf [n].firstCount\r
-; and _pktRxBuf[n].secondCount, and CL on first call in\r
-; _pktRxBuf[n].rxBuffer[CX]. These values are checked in "PktReceive"\r
-; (PKTDRVR.C)\r
-;\r
-;---------------------------------------------------------------------\r
-\r
-_PktReceiver:\r
-         pushf\r
-         cli                         ; no distraction wanted !\r
-         push ds\r
-         push bx\r
-ifdef DOSX\r
-         mov bx, cs\r
-else\r
-         mov bx, SEG _DATA\r
-endif\r
-         mov ds, bx\r
-         mov es, bx                  ; ES = DS = CS or seg _DATA\r
-         pop bx                      ; restore handle\r
-\r
-         cmp ax, 0                   ; first call? (AX=0)\r
-         jne @post                   ; AX=1: second call, do post process\r
-\r
-ifdef DEBUG\r
-         SHOW_RX                     ; show that a packet is received\r
-endif\r
-         cmp cx, RX_BUF_SIZE+14      ; size OK ?\r
-         ja  @skip                   ; no, packet to large for us\r
-\r
-         ENQUEUE                     ; ES:DI -> _pktRxBuf[n]\r
-\r
-         mov [di].firstCount, cx     ; remember the first count.\r
-         mov [di].handle, bx         ; remember the handle.\r
-         add di, 6                   ; ES:DI -> _pktRxBuf[n].destinAdr\r
-         pop ds\r
-         popf\r
-         retf                        ; far return to driver with ES:DI\r
-\r
-         align 4\r
-@dump:   inc _pktDrop[0]             ; discard the packet on 1st call\r
-         adc _pktDrop[2], 0          ; increment packets lost\r
-\r
-@skip:   xor di, di                  ; return ES:DI = NIL pointer\r
-         xor ax, ax\r
-         mov es, ax\r
-         pop ds\r
-         popf\r
-         retf\r
-\r
-         align 4\r
-@post:   or si, si                   ; DS:SI->_pktRxBuf[n][n].destinAdr\r
-         jz @discard                 ; make sure we don't use NULL-pointer\r
-\r
-         sub si, 6                   ; DS:SI -> _pktRxBuf[n].destinAdr\r
-       ;\r
-       ; push si\r
-       ; push [si].firstCount\r
-       ; call bpf_filter_match       ; run the filter here some day?\r
-       ; add sp, 4\r
-       ; cmp ax, 0\r
-       ; je  @discard\r
-\r
-         mov [si].secondCount, cx\r
-         mov ax, newInOffset\r
-         mov _rxInOfs, ax            ; update _pktRxBuf input offset\r
-\r
-         align 4\r
-@discard:pop ds\r
-         popf\r
-         retf\r
-\r
-_pktRxEnd  db 0                      ; marker for end of r-mode code/data\r
-\r
-_TEXT ENDS\r
-\r
-END\r
+PAGE 60,132
+NAME PKT_RX
+
+ifdef ??version        ; using TASM
+  masm
+  jumps
+endif
+
+PUBLIC _pktDrop, _pktRxBuf, _pktTxBuf,    _pktTemp
+PUBLIC _rxOutOfs, _rxInOfs, _PktReceiver, _pktRxEnd
+
+;
+; these sizes MUST be equal to the sizes in PKTDRVR.H
+;
+
+RX_BUF_SIZE = 1500      ; max message size on Ethernet
+TX_BUF_SIZE = 1500
+
+ifdef DOSX
+ .386
+  NUM_RX_BUF = 32       ; # of RX element buffers
+  _TEXT   SEGMENT PUBLIC DWORD USE16 'CODE'
+  _TEXT   ENDS
+  _DATA   SEGMENT PUBLIC DWORD USE16 'CODE'
+  _DATA   ENDS
+  D_SEG   EQU <_TEXT SEGMENT>
+  D_END   EQU <_TEXT ENDS>
+  ASSUME  CS:_TEXT,DS:_TEXT
+else
+ .286
+  NUM_RX_BUF = 10
+  _TEXT   SEGMENT PUBLIC DWORD 'CODE'
+  _TEXT   ENDS
+  _DATA   SEGMENT PUBLIC DWORD 'DATA'
+  _DATA   ENDS
+  D_SEG   EQU <_DATA SEGMENT>
+  D_END   EQU <_DATA ENDS>
+  ASSUME  CS:_TEXT,DS:_DATA
+endif
+
+;-------------------------------------------
+
+D_SEG
+
+RX_ELEMENT     STRUC
+   firstCount  dw  0                          ; # of bytes on 1st call
+   secondCount dw  0                          ; # of bytes on 2nd call
+   handle      dw  0                          ; handle for upcall
+   destinAdr   db  6           dup (0)        ; packet destination address
+   sourceAdr   db  6           dup (0)        ; packet source address
+   protocol    dw  0                          ; packet protocol number
+   rxBuffer    db  RX_BUF_SIZE dup (0)        ; RX buffer
+ENDS
+               align 4
+_rxOutOfs      dw  offset _pktRxBuf           ; ring buffer offsets
+_rxInOfs       dw  offset _pktRxBuf           ; into _pktRxBuf
+_pktDrop       dw  0,0                        ; packet drop counter
+_pktTemp       db  20                dup (0)  ; temp work area
+_pktTxBuf      db  (TX_BUF_SIZE+14)  dup (0)  ; TX buffer
+_pktRxBuf      RX_ELEMENT NUM_RX_BUF dup (<>) ; RX structures
+ LAST_OFS      = offset $
+
+ screenSeg     dw  0B800h
+ newInOffset   dw  0
+
+ fanChars      db  '-\|/'
+ fanIndex      dw  0
+
+D_END
+
+_TEXT SEGMENT
+
+
+SHOW_RX  MACRO
+         push es
+         push bx
+         mov bx, screenSeg
+         mov es, bx                    ;; r-mode segment of colour screen
+         mov di, 158                   ;; upper right corner - 1
+         mov bx, fanIndex
+         mov al, fanChars[bx]          ;; get write char
+         mov ah, 15                    ;;  and white colour
+         stosw                         ;; write to screen at ES:EDI
+         inc fanIndex                  ;; update next index
+         and fanIndex, 3
+         pop bx
+         pop es
+ENDM
+
+;------------------------------------------------------------------------
+;
+; This macro return ES:DI to tail of Rx queue
+
+ENQUEUE  MACRO
+         LOCAL @noWrap
+         mov ax, _rxInOfs              ;; DI = current in-offset
+         add ax, SIZE RX_ELEMENT       ;; point to next _pktRxBuf buffer
+         cmp ax, LAST_OFS              ;; pointing past last ?
+         jb  @noWrap                   ;; no - jump
+         lea ax, _pktRxBuf             ;; yes, point to 1st buffer
+         align 4
+@noWrap: cmp ax, _rxOutOfs             ;; in-ofs = out-ofs ?
+         je  @dump                     ;; yes, queue is full
+         mov di, _rxInOfs              ;; ES:DI -> buffer at queue input
+         mov newInOffset, ax           ;; remember new input offset
+
+   ;; NOTE. rxInOfs is updated after the packet has been copied
+   ;; to ES:DI (= DS:SI on 2nd call) by the packet driver
+
+ENDM
+
+;------------------------------------------------------------------------
+;
+; This routine gets called by the packet driver twice:
+;   1st time (AX=0) it requests an address where to put the packet
+;
+;   2nd time (AX=1) the packet has been copied to this location (DS:SI)
+;   BX has client handle (stored in RX_ELEMENT.handle).
+;   CX has # of bytes in packet on both call. They should be equal.
+;
+; A test for equality is done by putting CX in _pktRxBuf [n].firstCount
+; and _pktRxBuf[n].secondCount, and CL on first call in
+; _pktRxBuf[n].rxBuffer[CX]. These values are checked in "PktReceive"
+; (PKTDRVR.C)
+;
+;---------------------------------------------------------------------
+
+_PktReceiver:
+         pushf
+         cli                         ; no distraction wanted !
+         push ds
+         push bx
+ifdef DOSX
+         mov bx, cs
+else
+         mov bx, SEG _DATA
+endif
+         mov ds, bx
+         mov es, bx                  ; ES = DS = CS or seg _DATA
+         pop bx                      ; restore handle
+
+         cmp ax, 0                   ; first call? (AX=0)
+         jne @post                   ; AX=1: second call, do post process
+
+ifdef DEBUG
+         SHOW_RX                     ; show that a packet is received
+endif
+         cmp cx, RX_BUF_SIZE+14      ; size OK ?
+         ja  @skip                   ; no, packet to large for us
+
+         ENQUEUE                     ; ES:DI -> _pktRxBuf[n]
+
+         mov [di].firstCount, cx     ; remember the first count.
+         mov [di].handle, bx         ; remember the handle.
+         add di, 6                   ; ES:DI -> _pktRxBuf[n].destinAdr
+         pop ds
+         popf
+         retf                        ; far return to driver with ES:DI
+
+         align 4
+@dump:   inc _pktDrop[0]             ; discard the packet on 1st call
+         adc _pktDrop[2], 0          ; increment packets lost
+
+@skip:   xor di, di                  ; return ES:DI = NIL pointer
+         xor ax, ax
+         mov es, ax
+         pop ds
+         popf
+         retf
+
+         align 4
+@post:   or si, si                   ; DS:SI->_pktRxBuf[n][n].destinAdr
+         jz @discard                 ; make sure we don't use NULL-pointer
+
+         sub si, 6                   ; DS:SI -> _pktRxBuf[n].destinAdr
+       ;
+       ; push si
+       ; push [si].firstCount
+       ; call bpf_filter_match       ; run the filter here some day?
+       ; add sp, 4
+       ; cmp ax, 0
+       ; je  @discard
+
+         mov [si].secondCount, cx
+         mov ax, newInOffset
+         mov _rxInOfs, ax            ; update _pktRxBuf input offset
+
+         align 4
+@discard:pop ds
+         popf
+         retf
+
+_pktRxEnd  db 0                      ; marker for end of r-mode code/data
+
+_TEXT ENDS
+
+END
index b294a36..654e657 100644 (file)
-;\r
-; This file requires NASM 0.97+ to assemble\r
-;\r
-; Currently used only for djgpp + DOS4GW targets\r
-;\r
-; these sizes MUST be equal to the sizes in PKTDRVR.H\r
-;\r
-%define  ETH_MTU     1500                  ; max data size on Ethernet\r
-%define  ETH_MIN     60                    ; min/max total frame size\r
-%define  ETH_MAX     (ETH_MTU+2*6+2)\r
-%define  NUM_RX_BUF  32                    ; # of RX element buffers\r
-%define  RX_SIZE     (ETH_MAX+6)           ; sizeof(RX_ELEMENT) = 1514+6\r
-%idefine offset\r
-\r
-struc RX_ELEMENT\r
-      .firstCount  resw 1                  ; # of bytes on 1st call\r
-      .secondCount resw 1                  ; # of bytes on 2nd call\r
-      .handle      resw 1                  ; handle for upcall\r
-    ; .timeStamp   resw 4                  ; 64-bit RDTSC value\r
-      .destinAdr   resb 6                  ; packet destination address\r
-      .sourceAdr   resb 6                  ; packet source address\r
-      .protocol    resw 1                  ; packet protocol number\r
-      .rxBuffer    resb ETH_MTU            ; RX buffer\r
-endstruc\r
-\r
-;-------------------------------------------\r
-\r
-[org 0]  ; assemble to .bin file\r
-\r
-_rxOutOfs   dw   offset _pktRxBuf          ; ring buffer offsets\r
-_rxInOfs    dw   offset _pktRxBuf          ; into _pktRxBuf\r
-_pktDrop    dw   0,0                       ; packet drop counter\r
-_pktTemp    resb 20                        ; temp work area\r
-_pktTxBuf   resb (ETH_MAX)                 ; TX buffer\r
-_pktRxBuf   resb (RX_SIZE*NUM_RX_BUF)      ; RX structures\r
- LAST_OFS   equ  $\r
-\r
-screenSeg   dw  0B800h\r
-newInOffset dw  0\r
-\r
-fanChars    db  '-\|/'\r
-fanIndex    dw  0\r
-\r
-%macro SHOW_RX 0\r
-       push es\r
-       push bx\r
-       mov bx, [screenSeg]\r
-       mov es, bx                    ;; r-mode segment of colour screen\r
-       mov di, 158                   ;; upper right corner - 1\r
-       mov bx, [fanIndex]\r
-       mov al, [fanChars+bx]         ;; get write char\r
-       mov ah, 15                    ;;  and white colour\r
-       cld                           ;; Needed?\r
-       stosw                         ;; write to screen at ES:EDI\r
-       inc word [fanIndex]           ;; update next index\r
-       and word [fanIndex], 3\r
-       pop bx\r
-       pop es\r
-%endmacro\r
-\r
-;PutTimeStamp\r
-;       rdtsc\r
-;       mov [si].timeStamp, eax\r
-;       mov [si+4].timeStamp, edx\r
-;       ret\r
-\r
-\r
-;------------------------------------------------------------------------\r
-;\r
-; This routine gets called by the packet driver twice:\r
-;   1st time (AX=0) it requests an address where to put the packet\r
-;\r
-;   2nd time (AX=1) the packet has been copied to this location (DS:SI)\r
-;   BX has client handle (stored in RX_ELEMENT.handle).\r
-;   CX has # of bytes in packet on both call. They should be equal.\r
-; A test for equality is done by putting CX in _pktRxBuf [n].firstCount\r
-; and _pktRxBuf[n].secondCount, and CL on first call in\r
-; _pktRxBuf[n].rxBuffer[CX]. These values are checked in "PktReceive"\r
-; (PKTDRVR.C)\r
-;\r
-;---------------------------------------------------------------------\r
-\r
-_PktReceiver:\r
-         pushf\r
-         cli                         ; no distraction wanted !\r
-         push ds\r
-         push bx\r
-         mov bx, cs\r
-         mov ds, bx\r
-         mov es, bx                  ; ES = DS = CS or seg _DATA\r
-         pop bx                      ; restore handle\r
-\r
-         cmp ax, 0                   ; first call? (AX=0)\r
-         jne @post                   ; AX=1: second call, do post process\r
-\r
-%ifdef DEBUG\r
-         SHOW_RX                     ; show that a packet is received\r
-%endif\r
-\r
-         cmp cx, ETH_MAX             ; size OK ?\r
-         ja  @skip                   ; no, too big\r
-\r
-         mov ax, [_rxInOfs]\r
-         add ax, RX_SIZE\r
-         cmp ax, LAST_OFS\r
-         jb  @noWrap\r
-         mov ax, offset _pktRxBuf\r
-@noWrap:\r
-         cmp ax, [_rxOutOfs]\r
-         je  @dump\r
-         mov di, [_rxInOfs]          ; ES:DI -> _pktRxBuf[n]\r
-         mov [newInOffset], ax\r
-\r
-         mov [di], cx                ; remember firstCount.\r
-         mov [di+4], bx              ; remember handle.\r
-         add di, 6                   ; ES:DI -> _pktRxBuf[n].destinAdr\r
-         pop ds\r
-         popf\r
-         retf                        ; far return to driver with ES:DI\r
-\r
-@dump:   add word [_pktDrop+0], 1    ; discard the packet on 1st call\r
-         adc word [_pktDrop+2], 0    ; increment packets lost\r
-\r
-@skip:   xor di, di                  ; return ES:DI = NIL pointer\r
-         xor ax, ax\r
-         mov es, ax\r
-         pop ds\r
-         popf\r
-         retf\r
-\r
-@post:   or si, si                   ; DS:SI->_pktRxBuf[n][n].destinAdr\r
-         jz @discard                 ; make sure we don't use NULL-pointer\r
-\r
-       ;\r
-       ; push si\r
-       ; call bpf_filter_match       ; run the filter here some day\r
-       ; pop si\r
-       ; cmp ax, 0\r
-       ; je  @discard\r
-\r
-         mov [si-6+2], cx            ; store _pktRxBuf[n].secondCount\r
-         mov ax, [newInOffset]\r
-         mov [_rxInOfs], ax          ; update _pktRxBuf input offset\r
-\r
-       ; call PutTimeStamp\r
-\r
-@discard:\r
-         pop ds\r
-         popf\r
-         retf\r
-\r
-_pktRxEnd  db 0                      ; marker for end of r-mode code/data\r
-\r
-END\r
-\r
+;
+; This file requires NASM 0.97+ to assemble
+;
+; Currently used only for djgpp + DOS4GW targets
+;
+; these sizes MUST be equal to the sizes in PKTDRVR.H
+;
+%define  ETH_MTU     1500                  ; max data size on Ethernet
+%define  ETH_MIN     60                    ; min/max total frame size
+%define  ETH_MAX     (ETH_MTU+2*6+2)       ; =1514
+%define  NUM_RX_BUF  32                    ; # of RX element buffers
+%define  RX_SIZE     (ETH_MAX+6)           ; sizeof(RX_ELEMENT) = 1514+6
+%idefine offset
+
+struc RX_ELEMENT
+      .firstCount  resw 1                  ; # of bytes on 1st call
+      .secondCount resw 1                  ; # of bytes on 2nd call
+      .handle      resw 1                  ; handle for upcall
+    ; .timeStamp   resw 4                  ; 64-bit RDTSC value
+      .destinAdr   resb 6                  ; packet destination address
+      .sourceAdr   resb 6                  ; packet source address
+      .protocol    resw 1                  ; packet protocol number
+      .rxBuffer    resb ETH_MTU            ; RX buffer
+endstruc
+
+;-------------------------------------------
+
+[org 0]  ; assemble to .bin file
+
+_rxOutOfs   dw   offset _pktRxBuf          ; ring buffer offsets
+_rxInOfs    dw   offset _pktRxBuf          ; into _pktRxBuf
+_pktDrop    dw   0,0                       ; packet drop counter
+_pktTemp    resb 20                        ; temp work area
+_pktTxBuf   resb (ETH_MAX)                 ; TX buffer
+_pktRxBuf   resb (RX_SIZE*NUM_RX_BUF)      ; RX structures
+ LAST_OFS   equ  $
+
+screenSeg   dw  0B800h
+newInOffset dw  0
+
+fanChars    db  '-\|/'
+fanIndex    dw  0
+
+%macro SHOW_RX 0
+       push es
+       push bx
+       mov bx, [screenSeg]
+       mov es, bx                    ;; r-mode segment of colour screen
+       mov di, 158                   ;; upper right corner - 1
+       mov bx, [fanIndex]
+       mov al, [fanChars+bx]         ;; get write char
+       mov ah, 15                    ;;  and white colour
+       cld                           ;; Needed?
+       stosw                         ;; write to screen at ES:EDI
+       inc word [fanIndex]           ;; update next index
+       and word [fanIndex], 3
+       pop bx
+       pop es
+%endmacro
+
+;PutTimeStamp
+;       rdtsc
+;       mov [si].timeStamp, eax
+;       mov [si+4].timeStamp, edx
+;       ret
+
+
+;------------------------------------------------------------------------
+;
+; This routine gets called by the packet driver twice:
+;   1st time (AX=0) it requests an address where to put the packet
+;
+;   2nd time (AX=1) the packet has been copied to this location (DS:SI)
+;   BX has client handle (stored in RX_ELEMENT.handle).
+;   CX has # of bytes in packet on both call. They should be equal.
+; A test for equality is done by putting CX in _pktRxBuf [n].firstCount
+; and _pktRxBuf[n].secondCount, and CL on first call in
+; _pktRxBuf[n].rxBuffer[CX]. These values are checked in "PktReceive"
+; (PKTDRVR.C)
+;
+;---------------------------------------------------------------------
+
+_PktReceiver:
+         pushf
+         cli                         ; no distraction wanted !
+         push ds
+         push bx
+         mov bx, cs
+         mov ds, bx
+         mov es, bx                  ; ES = DS = CS or seg _DATA
+         pop bx                      ; restore handle
+
+         cmp ax, 0                   ; first call? (AX=0)
+         jne @post                   ; AX=1: second call, do post process
+
+%ifdef DEBUG
+         SHOW_RX                     ; show that a packet is received
+%endif
+
+         cmp cx, ETH_MAX             ; size OK ?
+         ja  @skip                   ; no, too big
+
+         mov ax, [_rxInOfs]
+         add ax, RX_SIZE
+         cmp ax, LAST_OFS
+         jb  @noWrap
+         mov ax, offset _pktRxBuf
+@noWrap:
+         cmp ax, [_rxOutOfs]
+         je  @dump
+         mov di, [_rxInOfs]          ; ES:DI -> _pktRxBuf[n]
+         mov [newInOffset], ax
+
+         mov [di], cx                ; remember firstCount.
+         mov [di+4], bx              ; remember handle.
+         add di, 6                   ; ES:DI -> _pktRxBuf[n].destinAdr
+         pop ds
+         popf
+         retf                        ; far return to driver with ES:DI
+
+@dump:   add word [_pktDrop+0], 1    ; discard the packet on 1st call
+         adc word [_pktDrop+2], 0    ; increment packets lost
+
+@skip:   xor di, di                  ; return ES:DI = NIL pointer
+         xor ax, ax
+         mov es, ax
+         pop ds
+         popf
+         retf
+
+@post:   or si, si                   ; DS:SI->_pktRxBuf[n][n].destinAdr
+         jz @discard                 ; make sure we don't use NULL-pointer
+
+       ;
+       ; push si
+       ; call bpf_filter_match       ; run the filter here some day
+       ; pop si
+       ; cmp ax, 0
+       ; je  @discard
+
+         mov [si-6+2], cx            ; store _pktRxBuf[n].secondCount
+         mov ax, [newInOffset]
+         mov [_rxInOfs], ax          ; update _pktRxBuf input offset
+
+       ; call PutTimeStamp
+
+@discard:
+         pop ds
+         popf
+         retf
+
+_pktRxEnd  db 0                      ; marker for end of r-mode code/data
+
+END
+
index cd22ee6..37fc8a4 100644 (file)
-/*\r
- *  File.........: pktdrvr.c\r
- *\r
- *  Responsible..: Gisle Vanem,  giva@bgnett.no\r
- *\r
- *  Created......: 26.Sept 1995\r
- *\r
- *  Description..: Packet-driver interface for 16/32-bit C :\r
- *                 Borland C/C++ 3.0+ small/large model\r
- *                 Watcom C/C++ 11+, DOS4GW flat model\r
- *                 Metaware HighC 3.1+ and PharLap 386|DosX\r
- *                 GNU C/C++ 2.7+ and djgpp 2.x extender\r
- *\r
- *  References...: PC/TCP Packet driver Specification. rev 1.09\r
- *                 FTP Software Inc.\r
- *\r
- */\r
-\r
-#include <stdio.h>\r
-#include <stdlib.h>\r
-#include <string.h>\r
-#include <dos.h>\r
-\r
-#include "pcap-dos.h"\r
-#include "pcap-int.h"\r
-#include "msdos/pktdrvr.h"\r
-\r
-#if (DOSX)\r
-#define NUM_RX_BUF  32      /* # of buffers in Rx FIFO queue */\r
-#else\r
-#define NUM_RX_BUF  10\r
-#endif\r
-\r
-#define DIM(x)   (sizeof((x)) / sizeof(x[0]))\r
-#define PUTS(s)  do {                                           \\r
-                   if (!pktInfo.quiet)                          \\r
-                      pktInfo.error ?                           \\r
-                        printf ("%s: %s\n", s, pktInfo.error) : \\r
-                        printf ("%s\n", pktInfo.error = s);     \\r
-                 } while (0)\r
-\r
-#if defined(__HIGHC__)\r
-  extern UINT _mwenv;\r
-\r
-#elif defined(__DJGPP__)\r
-  #include <stddef.h>\r
-  #include <dpmi.h>\r
-  #include <go32.h>\r
-  #include <pc.h>\r
-  #include <sys/farptr.h>\r
-\r
-#elif defined(__WATCOMC__)\r
-  #include <i86.h>\r
-  #include <stddef.h>\r
-  extern char _Extender;\r
-\r
-#else\r
-  extern void far PktReceiver (void);\r
-#endif\r
-\r
-\r
-#if (DOSX & (DJGPP|DOS4GW))\r
-  #include <sys/pack_on.h>\r
-\r
-  struct DPMI_regs {\r
-         DWORD  r_di;\r
-         DWORD  r_si;\r
-         DWORD  r_bp;\r
-         DWORD  reserved;\r
-         DWORD  r_bx;\r
-         DWORD  r_dx;\r
-         DWORD  r_cx;\r
-         DWORD  r_ax;\r
-         WORD   r_flags;\r
-         WORD   r_es, r_ds, r_fs, r_gs;\r
-         WORD   r_ip, r_cs, r_sp, r_ss;\r
-       };\r
-\r
-  /* Data located in a real-mode segment. This becomes far at runtime\r
-   */\r
-  typedef struct  {          /* must match data/code in pkt_rx1.s */\r
-          WORD       _rxOutOfs;\r
-          WORD       _rxInOfs;\r
-          DWORD      _pktDrop;\r
-          BYTE       _pktTemp [20];\r
-          TX_ELEMENT _pktTxBuf[1];\r
-          RX_ELEMENT _pktRxBuf[NUM_RX_BUF];\r
-          WORD       _dummy[2];        /* screenSeg,newInOffset */\r
-          BYTE       _fanChars[4];\r
-          WORD       _fanIndex;\r
-          BYTE       _PktReceiver[15]; /* starts on a paragraph (16byte) */\r
-        } PktRealStub;\r
-  #include <sys/pack_off.h>\r
-\r
-  static BYTE real_stub_array [] = {\r
-         #include "pkt_stub.inc"       /* generated opcode array */\r
-       };\r
-\r
-  #define rxOutOfs      offsetof (PktRealStub,_rxOutOfs)\r
-  #define rxInOfs       offsetof (PktRealStub,_rxInOfs)\r
-  #define PktReceiver   offsetof (PktRealStub,_PktReceiver [para_skip])\r
-  #define pktDrop       offsetof (PktRealStub,_pktDrop)\r
-  #define pktTemp       offsetof (PktRealStub,_pktTemp)\r
-  #define pktTxBuf      offsetof (PktRealStub,_pktTxBuf)\r
-  #define FIRST_RX_BUF  offsetof (PktRealStub,_pktRxBuf [0])\r
-  #define LAST_RX_BUF   offsetof (PktRealStub,_pktRxBuf [NUM_RX_BUF-1])\r
-\r
-#else\r
-  extern WORD       rxOutOfs;    /* offsets into pktRxBuf FIFO queue   */\r
-  extern WORD       rxInOfs;\r
-  extern DWORD      pktDrop;     /* # packets dropped in PktReceiver() */\r
-  extern BYTE       pktRxEnd;    /* marks the end of r-mode code/data  */\r
-\r
-  extern RX_ELEMENT pktRxBuf [NUM_RX_BUF];       /* PktDrvr Rx buffers */\r
-  extern TX_ELEMENT pktTxBuf;                    /* PktDrvr Tx buffer  */\r
-  extern char       pktTemp[20];                 /* PktDrvr temp area  */\r
-\r
-  #define FIRST_RX_BUF (WORD) &pktRxBuf [0]\r
-  #define LAST_RX_BUF  (WORD) &pktRxBuf [NUM_RX_BUF-1]\r
-#endif\r
-\r
-\r
-#ifdef __BORLANDC__           /* Use Borland's inline functions */\r
-  #define memcpy  __memcpy__\r
-  #define memcmp  __memcmp__\r
-  #define memset  __memset__\r
-#endif\r
-\r
-\r
-#if (DOSX & PHARLAP)\r
-  extern void PktReceiver (void);     /* in pkt_rx0.asm */\r
-  static int  RealCopy    (ULONG, ULONG, REALPTR*, FARPTR*, USHORT*);\r
-\r
-  #undef  FP_SEG\r
-  #undef  FP_OFF\r
-  #define FP_OFF(x)     ((WORD)(x))\r
-  #define FP_SEG(x)     ((WORD)(realBase >> 16))\r
-  #define DOS_ADDR(s,o) (((DWORD)(s) << 16) + (WORD)(o))\r
-  #define r_ax          eax\r
-  #define r_bx          ebx\r
-  #define r_dx          edx\r
-  #define r_cx          ecx\r
-  #define r_si          esi\r
-  #define r_di          edi\r
-  #define r_ds          ds\r
-  #define r_es          es\r
-  LOCAL FARPTR          protBase;\r
-  LOCAL REALPTR         realBase;\r
-  LOCAL WORD            realSeg;   /* DOS para-address of allocated area */\r
-  LOCAL SWI_REGS        reg;\r
-\r
-  static WORD _far *rxOutOfsFp, *rxInOfsFp;\r
-\r
-#elif (DOSX & DJGPP)\r
-  static _go32_dpmi_seginfo rm_mem;\r
-  static __dpmi_regs        reg;\r
-  static DWORD              realBase;\r
-  static int                para_skip = 0;\r
-\r
-  #define DOS_ADDR(s,o)     (((WORD)(s) << 4) + (o))\r
-  #define r_ax              x.ax\r
-  #define r_bx              x.bx\r
-  #define r_dx              x.dx\r
-  #define r_cx              x.cx\r
-  #define r_si              x.si\r
-  #define r_di              x.di\r
-  #define r_ds              x.ds\r
-  #define r_es              x.es\r
-\r
-#elif (DOSX & DOS4GW)\r
-  LOCAL struct DPMI_regs    reg;\r
-  LOCAL WORD                rm_base_seg, rm_base_sel;\r
-  LOCAL DWORD               realBase;\r
-  LOCAL int                 para_skip = 0;\r
-\r
-  LOCAL DWORD dpmi_get_real_vector (int intr);\r
-  LOCAL WORD  dpmi_real_malloc     (int size, WORD *selector);\r
-  LOCAL void  dpmi_real_free       (WORD selector);\r
-  #define DOS_ADDR(s,o) (((DWORD)(s) << 4) + (WORD)(o))\r
-\r
-#else              /* real-mode Borland etc. */\r
-  static struct  {\r
-         WORD r_ax, r_bx, r_cx, r_dx, r_bp;\r
-         WORD r_si, r_di, r_ds, r_es, r_flags;\r
-       } reg;\r
-#endif\r
-\r
-#ifdef __HIGHC__\r
-  #pragma Alias (pktDrop,    "_pktDrop")\r
-  #pragma Alias (pktRxBuf,   "_pktRxBuf")\r
-  #pragma Alias (pktTxBuf,   "_pktTxBuf")\r
-  #pragma Alias (pktTemp,    "_pktTemp")\r
-  #pragma Alias (rxOutOfs,   "_rxOutOfs")\r
-  #pragma Alias (rxInOfs,    "_rxInOfs")\r
-  #pragma Alias (pktRxEnd,   "_pktRxEnd")\r
-  #pragma Alias (PktReceiver,"_PktReceiver")\r
-#endif\r
-\r
-\r
-PUBLIC PKT_STAT    pktStat;    /* statistics for packets    */\r
-PUBLIC PKT_INFO    pktInfo;    /* packet-driver information */\r
-\r
-PUBLIC PKT_RX_MODE receiveMode  = PDRX_DIRECT;\r
-PUBLIC ETHER       myAddress    = {   0,  0,  0,  0,  0,  0 };\r
-PUBLIC ETHER       ethBroadcast = { 255,255,255,255,255,255 };\r
-\r
-LOCAL  struct {             /* internal statistics */\r
-       DWORD  tooSmall;     /* size < ETH_MIN */\r
-       DWORD  tooLarge;     /* size > ETH_MAX */\r
-       DWORD  badSync;      /* count_1 != count_2 */\r
-       DWORD  wrongHandle;  /* upcall to wrong handle */\r
-     } intStat;  \r
-\r
-/***************************************************************************/\r
-\r
-PUBLIC const char *PktGetErrorStr (int errNum)\r
-{\r
-  static const char *errStr[] = {\r
-                    "",\r
-                    "Invalid handle number",\r
-                    "No interfaces of specified class found",\r
-                    "No interfaces of specified type found",\r
-                    "No interfaces of specified number found",\r
-                    "Bad packet type specified",\r
-                    "Interface does not support multicast",\r
-                    "Packet driver cannot terminate",\r
-                    "Invalid receiver mode specified",\r
-                    "Insufficient memory space",\r
-                    "Type previously accessed, and not released",\r
-                    "Command out of range, or not implemented",\r
-                    "Cannot send packet (usually hardware error)",\r
-                    "Cannot change hardware address ( > 1 handle open)",\r
-                    "Hardware address has bad length or format",\r
-                    "Cannot reset interface (more than 1 handle open)",\r
-                    "Bad Check-sum",\r
-                    "Bad size",\r
-                    "Bad sync" ,\r
-                    "Source hit"\r
-                  };\r
-\r
-  if (errNum < 0 || errNum >= DIM(errStr))\r
-     return ("Unknown driver error.");\r
-  return (errStr [errNum]);\r
-}\r
-\r
-/**************************************************************************/\r
-\r
-PUBLIC const char *PktGetClassName (WORD class)\r
-{\r
-  switch (class)\r
-  { \r
-    case PD_ETHER:\r
-         return ("DIX-Ether");\r
-    case PD_PRONET10:\r
-         return ("ProNET-10");\r
-    case PD_IEEE8025:\r
-         return ("IEEE 802.5");\r
-    case PD_OMNINET:\r
-         return ("OmniNet");\r
-    case PD_APPLETALK:\r
-         return ("AppleTalk");\r
-    case PD_SLIP:\r
-         return ("SLIP");\r
-    case PD_STARTLAN:\r
-         return ("StartLAN");\r
-    case PD_ARCNET:\r
-         return ("ArcNet");\r
-    case PD_AX25:\r
-         return ("AX.25");\r
-    case PD_KISS:\r
-         return ("KISS");\r
-    case PD_IEEE8023_2:\r
-         return ("IEEE 802.3 w/802.2 hdr");\r
-    case PD_FDDI8022:\r
-         return ("FDDI w/802.2 hdr");\r
-    case PD_X25:\r
-         return ("X.25");\r
-    case PD_LANstar:\r
-         return ("LANstar");\r
-    case PD_PPP:\r
-         return ("PPP");\r
-    default:\r
-         return ("unknown");\r
-  }\r
-}\r
-\r
-/**************************************************************************/\r
-\r
-PUBLIC char const *PktRXmodeStr (PKT_RX_MODE mode)\r
-{\r
-  static const char *modeStr [] = {\r
-                    "Receiver turned off",\r
-                    "Receive only directly addressed packets",\r
-                    "Receive direct & broadcast packets",\r
-                    "Receive direct,broadcast and limited multicast packets",\r
-                    "Receive direct,broadcast and all multicast packets",\r
-                    "Receive all packets (promiscuouos mode)"\r
-                  };\r
-\r
-  if (mode > DIM(modeStr))\r
-     return ("??");\r
-  return (modeStr [mode-1]);\r
-}\r
-\r
-/**************************************************************************/\r
-\r
-LOCAL __inline BOOL PktInterrupt (void)\r
-{\r
-  BOOL okay;\r
-\r
-#if (DOSX & PHARLAP)\r
-  _dx_real_int ((UINT)pktInfo.intr, &reg);\r
-  okay = ((reg.flags & 1) == 0);  /* OK if carry clear */\r
-\r
-#elif (DOSX & DJGPP)\r
-  __dpmi_int ((int)pktInfo.intr, &reg);\r
-  okay = ((reg.x.flags & 1) == 0);\r
-\r
-#elif (DOSX & DOS4GW)\r
-  union  REGS  r;\r
-  struct SREGS s;\r
-\r
-  memset (&r, 0, sizeof(r));\r
-  segread (&s);\r
-  r.w.ax  = 0x300;\r
-  r.x.ebx = pktInfo.intr;\r
-  r.w.cx  = 0;\r
-  s.es    = FP_SEG (&reg);\r
-  r.x.edi = FP_OFF (&reg);\r
-  reg.r_flags = 0;\r
-  reg.r_ss = reg.r_sp = 0;     /* DPMI host provides stack */\r
-\r
-  int386x (0x31, &r, &r, &s);\r
-  okay = (!r.w.cflag);\r
-\r
-#else\r
-  reg.r_flags = 0;\r
-  intr (pktInfo.intr, (struct REGPACK*)&reg);\r
-  okay = ((reg.r_flags & 1) == 0);\r
-#endif\r
-\r
-  if (okay)\r
-       pktInfo.error = NULL;\r
-  else pktInfo.error = PktGetErrorStr (reg.r_dx >> 8);\r
-  return (okay);\r
-}\r
-\r
-/**************************************************************************/\r
-\r
-/*\r
- * Search for packet driver at interrupt 60h through 80h. If ASCIIZ\r
- * string "PKT DRVR" found at offset 3 in the interrupt handler, return\r
- * interrupt number, else return zero in pktInfo.intr\r
- */\r
-PUBLIC BOOL PktSearchDriver (void)\r
-{\r
-  BYTE intr  = 0x20;\r
-  BOOL found = FALSE;\r
-\r
-  while (!found && intr < 0xFF)\r
-  {\r
-    static char str[12];                 /* 3 + strlen("PKT DRVR") */\r
-    static char pktStr[9] = "PKT DRVR";  /* ASCIIZ string at ofs 3 */\r
-    DWORD  rp;                           /* in interrupt  routine  */\r
-\r
-#if (DOSX & PHARLAP)\r
-    _dx_rmiv_get (intr, &rp);\r
-    ReadRealMem (&str, (REALPTR)rp, sizeof(str));\r
-\r
-#elif (DOSX & DJGPP)\r
-    __dpmi_raddr realAdr;\r
-    __dpmi_get_real_mode_interrupt_vector (intr, &realAdr);\r
-    rp = (realAdr.segment << 4) + realAdr.offset16;\r
-    dosmemget (rp, sizeof(str), &str);\r
-\r
-#elif (DOSX & DOS4GW)\r
-    rp = dpmi_get_real_vector (intr);\r
-    memcpy (&str, (void*)rp, sizeof(str));\r
-\r
-#else\r
-    _fmemcpy (&str, getvect(intr), sizeof(str));\r
-#endif\r
-\r
-    found = memcmp (&str[3],&pktStr,sizeof(pktStr)) == 0;\r
-    intr++;\r
-  }\r
-  pktInfo.intr = (found ? intr-1 : 0);\r
-  return (found);\r
-}\r
-\r
-\r
-/**************************************************************************/\r
-\r
-static BOOL PktSetAccess (void)\r
-{\r
-  reg.r_ax = 0x0200 + pktInfo.class;\r
-  reg.r_bx = 0xFFFF;\r
-  reg.r_dx = 0;\r
-  reg.r_cx = 0;\r
-\r
-#if (DOSX & PHARLAP)\r
-  reg.ds  = 0;\r
-  reg.esi = 0;\r
-  reg.es  = RP_SEG (realBase);\r
-  reg.edi = (WORD) &PktReceiver;\r
-\r
-#elif (DOSX & DJGPP)\r
-  reg.x.ds = 0;\r
-  reg.x.si = 0;\r
-  reg.x.es = rm_mem.rm_segment;\r
-  reg.x.di = PktReceiver;\r
-\r
-#elif (DOSX & DOS4GW)\r
-  reg.r_ds = 0;\r
-  reg.r_si = 0;\r
-  reg.r_es = rm_base_seg;\r
-  reg.r_di = PktReceiver;\r
-\r
-#else\r
-  reg.r_ds = 0;\r
-  reg.r_si = 0;\r
-  reg.r_es = FP_SEG (&PktReceiver);\r
-  reg.r_di = FP_OFF (&PktReceiver);\r
-#endif\r
-\r
-  if (!PktInterrupt())\r
-     return (FALSE);\r
-\r
-  pktInfo.handle = reg.r_ax;\r
-  return (TRUE);\r
-}\r
-\r
-/**************************************************************************/\r
-\r
-PUBLIC BOOL PktReleaseHandle (WORD handle)\r
-{\r
-  reg.r_ax = 0x0300;\r
-  reg.r_bx = handle;\r
-  return PktInterrupt();\r
-}\r
-\r
-/**************************************************************************/\r
-\r
-PUBLIC BOOL PktTransmit (const void *eth, int len)\r
-{\r
-  if (len > ETH_MTU)\r
-     return (FALSE);\r
-\r
-  reg.r_ax = 0x0400;             /* Function 4, send pkt */\r
-  reg.r_cx = len;                /* total size of frame  */\r
-\r
-#if (DOSX & DJGPP)\r
-  dosmemput (eth, len, realBase+pktTxBuf);\r
-  reg.x.ds = rm_mem.rm_segment;  /* DOS data segment and */\r
-  reg.x.si = pktTxBuf;           /* DOS offset to buffer */\r
-\r
-#elif (DOSX & DOS4GW)\r
-  memcpy ((void*)(realBase+pktTxBuf), eth, len);\r
-  reg.r_ds = rm_base_seg;\r
-  reg.r_si = pktTxBuf;\r
-\r
-#elif (DOSX & PHARLAP)\r
-  memcpy (&pktTxBuf, eth, len);\r
-  reg.r_ds = FP_SEG (&pktTxBuf);\r
-  reg.r_si = FP_OFF (&pktTxBuf);\r
-\r
-#else\r
-  reg.r_ds = FP_SEG (eth);\r
-  reg.r_si = FP_OFF (eth);\r
-#endif\r
-\r
-  return PktInterrupt();\r
-}\r
-\r
-/**************************************************************************/\r
-\r
-#if (DOSX & (DJGPP|DOS4GW))\r
-LOCAL __inline BOOL CheckElement (RX_ELEMENT *rx)\r
-#else\r
-LOCAL __inline BOOL CheckElement (RX_ELEMENT _far *rx)\r
-#endif\r
-{\r
-  WORD count_1, count_2;\r
-\r
-  /*\r
-   * We got an upcall to the same RMCB with wrong handle.\r
-   * This can happen if we failed to release handle at program exit\r
-   */\r
-  if (rx->handle != pktInfo.handle)\r
-  {\r
-    pktInfo.error = "Wrong handle";\r
-    intStat.wrongHandle++;\r
-    PktReleaseHandle (rx->handle);\r
-    return (FALSE);\r
-  }\r
-  count_1 = rx->firstCount;\r
-  count_2 = rx->secondCount;\r
-\r
-  if (count_1 != count_2)\r
-  {\r
-    pktInfo.error = "Bad sync";\r
-    intStat.badSync++;\r
-    return (FALSE);\r
-  }\r
-  if (count_1 > ETH_MAX)\r
-  {\r
-    pktInfo.error = "Large esize";\r
-    intStat.tooLarge++;\r
-    return (FALSE);\r
-  }\r
-#if 0\r
-  if (count_1 < ETH_MIN)\r
-  {\r
-    pktInfo.error = "Small esize";\r
-    intStat.tooSmall++;\r
-    return (FALSE);\r
-  }\r
-#endif\r
-  return (TRUE);\r
-}\r
-\r
-/**************************************************************************/\r
-\r
-PUBLIC BOOL PktTerminHandle (WORD handle)\r
-{\r
-  reg.r_ax = 0x0500;\r
-  reg.r_bx = handle;\r
-  return PktInterrupt();\r
-}\r
-\r
-/**************************************************************************/\r
-\r
-PUBLIC BOOL PktResetInterface (WORD handle)\r
-{\r
-  reg.r_ax = 0x0700;\r
-  reg.r_bx = handle;\r
-  return PktInterrupt();\r
-}\r
-\r
-/**************************************************************************/\r
-\r
-PUBLIC BOOL PktSetReceiverMode (PKT_RX_MODE mode)\r
-{\r
-  if (pktInfo.class == PD_SLIP || pktInfo.class == PD_PPP)\r
-     return (TRUE);\r
-\r
-  reg.r_ax = 0x1400;\r
-  reg.r_bx = pktInfo.handle;\r
-  reg.r_cx = (WORD)mode;\r
-\r
-  if (!PktInterrupt())\r
-     return (FALSE);\r
-\r
-  receiveMode = mode;\r
-  return (TRUE);\r
-}\r
-\r
-/**************************************************************************/\r
-\r
-PUBLIC BOOL PktGetReceiverMode (PKT_RX_MODE *mode)\r
-{\r
-  reg.r_ax = 0x1500;\r
-  reg.r_bx = pktInfo.handle;\r
-\r
-  if (!PktInterrupt())\r
-     return (FALSE);\r
-\r
-  *mode = reg.r_ax;\r
-  return (TRUE);\r
-}\r
-\r
-/**************************************************************************/\r
-\r
-static PKT_STAT initialStat;         /* statistics at startup */\r
-static BOOL     resetStat = FALSE;   /* statistics reset ? */\r
-\r
-PUBLIC BOOL PktGetStatistics (WORD handle)\r
-{\r
-  reg.r_ax = 0x1800;\r
-  reg.r_bx = handle;\r
-\r
-  if (!PktInterrupt())\r
-     return (FALSE);\r
-\r
-#if (DOSX & PHARLAP)\r
-  ReadRealMem (&pktStat, DOS_ADDR(reg.ds,reg.esi), sizeof(pktStat));\r
-\r
-#elif (DOSX & DJGPP)\r
-  dosmemget (DOS_ADDR(reg.x.ds,reg.x.si), sizeof(pktStat), &pktStat);\r
-\r
-#elif (DOSX & DOS4GW)\r
-  memcpy (&pktStat, (void*)DOS_ADDR(reg.r_ds,reg.r_si), sizeof(pktStat));\r
-\r
-#else\r
-  _fmemcpy (&pktStat, MK_FP(reg.r_ds,reg.r_si), sizeof(pktStat));\r
-#endif\r
-\r
-  return (TRUE);\r
-}\r
-\r
-/**************************************************************************/\r
-\r
-PUBLIC BOOL PktSessStatistics (WORD handle)\r
-{\r
-  if (!PktGetStatistics(pktInfo.handle))\r
-     return (FALSE);\r
-\r
-  if (resetStat)\r
-  {\r
-    pktStat.inPackets  -= initialStat.inPackets;\r
-    pktStat.outPackets -= initialStat.outPackets;\r
-    pktStat.inBytes    -= initialStat.inBytes;\r
-    pktStat.outBytes   -= initialStat.outBytes;\r
-    pktStat.inErrors   -= initialStat.inErrors;\r
-    pktStat.outErrors  -= initialStat.outErrors;\r
-    pktStat.outErrors  -= initialStat.outErrors;\r
-    pktStat.lost       -= initialStat.lost;\r
-  }\r
-  return (TRUE);\r
-}\r
-\r
-/**************************************************************************/\r
-\r
-PUBLIC BOOL PktResetStatistics (WORD handle)\r
-{\r
-  if (!PktGetStatistics(pktInfo.handle))\r
-     return (FALSE);\r
-\r
-  memcpy (&initialStat, &pktStat, sizeof(initialStat));\r
-  resetStat = TRUE;\r
-  return (TRUE);\r
-}\r
-\r
-/**************************************************************************/\r
-\r
-PUBLIC BOOL PktGetAddress (ETHER *addr)\r
-{\r
-  reg.r_ax = 0x0600;\r
-  reg.r_bx = pktInfo.handle;\r
-  reg.r_cx = sizeof (*addr);\r
-\r
-#if (DOSX & DJGPP)\r
-  reg.x.es = rm_mem.rm_segment;\r
-  reg.x.di = pktTemp;\r
-#elif (DOSX & DOS4GW)\r
-  reg.r_es = rm_base_seg;\r
-  reg.r_di = pktTemp;\r
-#else\r
-  reg.r_es = FP_SEG (&pktTemp);\r
-  reg.r_di = FP_OFF (&pktTemp);  /* ES:DI = address for result */\r
-#endif\r
-\r
-  if (!PktInterrupt())\r
-     return (FALSE);\r
-\r
-#if (DOSX & PHARLAP)\r
-  ReadRealMem (addr, realBase + (WORD)&pktTemp, sizeof(*addr));\r
-\r
-#elif (DOSX & DJGPP)\r
-  dosmemget (realBase+pktTemp, sizeof(*addr), addr);\r
-\r
-#elif (DOSX & DOS4GW)\r
-  memcpy (addr, (void*)(realBase+pktTemp), sizeof(*addr));\r
-\r
-#else\r
-  memcpy ((void*)addr, &pktTemp, sizeof(*addr));\r
-#endif\r
-\r
-  return (TRUE);\r
-}\r
-\r
-/**************************************************************************/\r
-\r
-PUBLIC BOOL PktSetAddress (const ETHER *addr)\r
-{\r
-  /* copy addr to real-mode scrath area */\r
-\r
-#if (DOSX & PHARLAP)\r
-  WriteRealMem (realBase + (WORD)&pktTemp, (void*)addr, sizeof(*addr));\r
-\r
-#elif (DOSX & DJGPP)\r
-  dosmemput (addr, sizeof(*addr), realBase+pktTemp);\r
-\r
-#elif (DOSX & DOS4GW)\r
-  memcpy ((void*)(realBase+pktTemp), addr, sizeof(*addr));\r
-\r
-#else\r
-  memcpy (&pktTemp, (void*)addr, sizeof(*addr));\r
-#endif\r
-\r
-  reg.r_ax = 0x1900;\r
-  reg.r_cx = sizeof (*addr);      /* address length       */\r
-\r
-#if (DOSX & DJGPP)\r
-  reg.x.es = rm_mem.rm_segment;   /* DOS offset to param  */\r
-  reg.x.di = pktTemp;             /* DOS segment to param */\r
-#elif (DOSX & DOS4GW)\r
-  reg.r_es = rm_base_seg;\r
-  reg.r_di = pktTemp;\r
-#else\r
-  reg.r_es = FP_SEG (&pktTemp);\r
-  reg.r_di = FP_OFF (&pktTemp);\r
-#endif\r
-\r
-  return PktInterrupt();\r
-}\r
-\r
-/**************************************************************************/\r
-\r
-PUBLIC BOOL PktGetDriverInfo (void)\r
-{\r
-  pktInfo.majVer = 0;\r
-  pktInfo.minVer = 0;\r
-  memset (&pktInfo.name, 0, sizeof(pktInfo.name));\r
-  reg.r_ax = 0x01FF;\r
-  reg.r_bx = 0;\r
-\r
-  if (!PktInterrupt())\r
-     return (FALSE);\r
-\r
-  pktInfo.number = reg.r_cx & 0xFF;\r
-  pktInfo.class  = reg.r_cx >> 8;\r
-#if 0\r
-  pktInfo.minVer = reg.r_bx % 10;\r
-  pktInfo.majVer = reg.r_bx / 10;\r
-#else\r
-  pktInfo.majVer = reg.r_bx;  // !!\r
-#endif\r
-  pktInfo.funcs  = reg.r_ax & 0xFF;\r
-  pktInfo.type   = reg.r_dx & 0xFF;\r
-\r
-#if (DOSX & PHARLAP)\r
-  ReadRealMem (&pktInfo.name, DOS_ADDR(reg.ds,reg.esi), sizeof(pktInfo.name));\r
-\r
-#elif (DOSX & DJGPP)\r
-  dosmemget (DOS_ADDR(reg.x.ds,reg.x.si), sizeof(pktInfo.name), &pktInfo.name);\r
-\r
-#elif (DOSX & DOS4GW)\r
-  memcpy (&pktInfo.name, (void*)DOS_ADDR(reg.r_ds,reg.r_si), sizeof(pktInfo.name));\r
-\r
-#else\r
-  _fmemcpy (&pktInfo.name, MK_FP(reg.r_ds,reg.r_si), sizeof(pktInfo.name));\r
-#endif\r
-  return (TRUE);\r
-}\r
-\r
-/**************************************************************************/\r
-\r
-PUBLIC BOOL PktGetDriverParam (void)\r
-{\r
-  reg.r_ax = 0x0A00;\r
-\r
-  if (!PktInterrupt())\r
-     return (FALSE);\r
-\r
-#if (DOSX & PHARLAP)\r
-  ReadRealMem (&pktInfo.majVer, DOS_ADDR(reg.es,reg.edi), PKT_PARAM_SIZE);\r
-\r
-#elif (DOSX & DJGPP)\r
-  dosmemget (DOS_ADDR(reg.x.es,reg.x.di), PKT_PARAM_SIZE, &pktInfo.majVer);\r
-\r
-#elif (DOSX & DOS4GW)\r
-  memcpy (&pktInfo.majVer, (void*)DOS_ADDR(reg.r_es,reg.r_di), PKT_PARAM_SIZE);\r
-\r
-#else\r
-  _fmemcpy (&pktInfo.majVer, MK_FP(reg.r_es,reg.r_di), PKT_PARAM_SIZE);\r
-#endif\r
-  return (TRUE);\r
-}\r
-\r
-/**************************************************************************/\r
-\r
-#if (DOSX & PHARLAP)\r
-  PUBLIC int PktReceive (BYTE *buf, int max)\r
-  {\r
-    WORD inOfs  = *rxInOfsFp;\r
-    WORD outOfs = *rxOutOfsFp;\r
-\r
-    if (outOfs != inOfs)\r
-    {\r
-      RX_ELEMENT _far *head = (RX_ELEMENT _far*)(protBase+outOfs);\r
-      int size, len = max;\r
-\r
-      if (CheckElement(head))\r
-      {\r
-        size = min (head->firstCount, sizeof(RX_ELEMENT));\r
-        len  = min (size, max);\r
-        _fmemcpy (buf, &head->destin, len);\r
-      }\r
-      else\r
-        size = -1;\r
-\r
-      outOfs += sizeof (RX_ELEMENT);\r
-      if (outOfs > LAST_RX_BUF)\r
-          outOfs = FIRST_RX_BUF;\r
-      *rxOutOfsFp = outOfs;\r
-      return (size);\r
-    }\r
-    return (0);\r
-  }\r
-\r
-  PUBLIC void PktQueueBusy (BOOL busy)\r
-  {\r
-    *rxOutOfsFp = busy ? (*rxInOfsFp + sizeof(RX_ELEMENT)) : *rxInOfsFp;\r
-    if (*rxOutOfsFp > LAST_RX_BUF)\r
-        *rxOutOfsFp = FIRST_RX_BUF;\r
-    *(DWORD _far*)(protBase + (WORD)&pktDrop) = 0;\r
-  }\r
-\r
-  PUBLIC WORD PktBuffersUsed (void)\r
-  {\r
-    WORD inOfs  = *rxInOfsFp;\r
-    WORD outOfs = *rxOutOfsFp;\r
-\r
-    if (inOfs >= outOfs)\r
-       return (inOfs - outOfs) / sizeof(RX_ELEMENT);\r
-    return (NUM_RX_BUF - (outOfs - inOfs) / sizeof(RX_ELEMENT));\r
-  }\r
-\r
-  PUBLIC DWORD PktRxDropped (void)\r
-  {\r
-    return (*(DWORD _far*)(protBase + (WORD)&pktDrop));\r
-  }\r
-\r
-#elif (DOSX & DJGPP)\r
-  PUBLIC int PktReceive (BYTE *buf, int max)\r
-  {\r
-    WORD ofs = _farpeekw (_dos_ds, realBase+rxOutOfs);\r
-\r
-    if (ofs != _farpeekw (_dos_ds, realBase+rxInOfs))\r
-    {\r
-      RX_ELEMENT head;\r
-      int  size, len = max;\r
-\r
-      head.firstCount  = _farpeekw (_dos_ds, realBase+ofs);\r
-      head.secondCount = _farpeekw (_dos_ds, realBase+ofs+2);\r
-      head.handle      = _farpeekw (_dos_ds, realBase+ofs+4);\r
-\r
-      if (CheckElement(&head))\r
-      {\r
-        size = min (head.firstCount, sizeof(RX_ELEMENT));\r
-        len  = min (size, max);\r
-        dosmemget (realBase+ofs+6, len, buf);\r
-      }\r
-      else\r
-        size = -1;\r
-\r
-      ofs += sizeof (RX_ELEMENT);\r
-      if (ofs > LAST_RX_BUF)\r
-           _farpokew (_dos_ds, realBase+rxOutOfs, FIRST_RX_BUF);\r
-      else _farpokew (_dos_ds, realBase+rxOutOfs, ofs);\r
-      return (size);\r
-    }\r
-    return (0);\r
-  }\r
-\r
-  PUBLIC void PktQueueBusy (BOOL busy)\r
-  {\r
-    WORD ofs;\r
-\r
-    disable();\r
-    ofs = _farpeekw (_dos_ds, realBase+rxInOfs);\r
-    if (busy)\r
-       ofs += sizeof (RX_ELEMENT);\r
-\r
-    if (ofs > LAST_RX_BUF)\r
-         _farpokew (_dos_ds, realBase+rxOutOfs, FIRST_RX_BUF);\r
-    else _farpokew (_dos_ds, realBase+rxOutOfs, ofs);\r
-    _farpokel (_dos_ds, realBase+pktDrop, 0UL);\r
-    enable();\r
-  }\r
-\r
-  PUBLIC WORD PktBuffersUsed (void)\r
-  {\r
-    WORD inOfs, outOfs;\r
-\r
-    disable();\r
-    inOfs  = _farpeekw (_dos_ds, realBase+rxInOfs);\r
-    outOfs = _farpeekw (_dos_ds, realBase+rxOutOfs);\r
-    enable();\r
-    if (inOfs >= outOfs)\r
-       return (inOfs - outOfs) / sizeof(RX_ELEMENT);\r
-    return (NUM_RX_BUF - (outOfs - inOfs) / sizeof(RX_ELEMENT));\r
-  }\r
-\r
-  PUBLIC DWORD PktRxDropped (void)\r
-  {\r
-    return _farpeekl (_dos_ds, realBase+pktDrop);\r
-  }\r
-\r
-#elif (DOSX & DOS4GW)\r
-  PUBLIC int PktReceive (BYTE *buf, int max)\r
-  {\r
-    WORD ofs = *(WORD*) (realBase+rxOutOfs);\r
-\r
-    if (ofs != *(WORD*) (realBase+rxInOfs))\r
-    {\r
-      RX_ELEMENT head;\r
-      int  size, len = max;\r
-\r
-      head.firstCount  = *(WORD*) (realBase+ofs);\r
-      head.secondCount = *(WORD*) (realBase+ofs+2);\r
-      head.handle      = *(WORD*) (realBase+ofs+4);\r
-\r
-      if (CheckElement(&head))\r
-      {\r
-        size = min (head.firstCount, sizeof(RX_ELEMENT));\r
-        len  = min (size, max);\r
-        memcpy (buf, (const void*)(realBase+ofs+6), len);\r
-      }\r
-      else\r
-        size = -1;\r
-\r
-      ofs += sizeof (RX_ELEMENT);\r
-      if (ofs > LAST_RX_BUF)\r
-           *(WORD*) (realBase+rxOutOfs) = FIRST_RX_BUF;\r
-      else *(WORD*) (realBase+rxOutOfs) = ofs;\r
-      return (size);\r
-    }\r
-    return (0);\r
-  }\r
-\r
-  PUBLIC void PktQueueBusy (BOOL busy)\r
-  {\r
-    WORD ofs;\r
-\r
-    _disable();\r
-    ofs = *(WORD*) (realBase+rxInOfs);\r
-    if (busy)\r
-       ofs += sizeof (RX_ELEMENT);\r
-\r
-    if (ofs > LAST_RX_BUF)\r
-         *(WORD*) (realBase+rxOutOfs) = FIRST_RX_BUF;\r
-    else *(WORD*) (realBase+rxOutOfs) = ofs;\r
-    *(DWORD*) (realBase+pktDrop) = 0UL;\r
-    _enable();\r
-  }\r
-\r
-  PUBLIC WORD PktBuffersUsed (void)\r
-  {\r
-    WORD inOfs, outOfs;\r
-\r
-    _disable();\r
-    inOfs  = *(WORD*) (realBase+rxInOfs);\r
-    outOfs = *(WORD*) (realBase+rxOutOfs);\r
-    _enable();\r
-    if (inOfs >= outOfs)\r
-       return (inOfs - outOfs) / sizeof(RX_ELEMENT);\r
-    return (NUM_RX_BUF - (outOfs - inOfs) / sizeof(RX_ELEMENT));\r
-  }\r
-\r
-  PUBLIC DWORD PktRxDropped (void)\r
-  {\r
-    return *(DWORD*) (realBase+pktDrop);\r
-  }\r
-\r
-#else     /* real-mode small/large model */\r
-\r
-  PUBLIC int PktReceive (BYTE *buf, int max)\r
-  {\r
-    if (rxOutOfs != rxInOfs)\r
-    {\r
-      RX_ELEMENT far *head = (RX_ELEMENT far*) MK_FP (_DS,rxOutOfs);\r
-      int  size, len = max;\r
-\r
-      if (CheckElement(head))\r
-      {\r
-        size = min (head->firstCount, sizeof(RX_ELEMENT));\r
-        len  = min (size, max);\r
-        _fmemcpy (buf, &head->destin, len);\r
-      }\r
-      else\r
-        size = -1;\r
-\r
-      rxOutOfs += sizeof (RX_ELEMENT);\r
-      if (rxOutOfs > LAST_RX_BUF)\r
-          rxOutOfs = FIRST_RX_BUF;\r
-      return (size);\r
-    }\r
-    return (0);\r
-  }\r
-\r
-  PUBLIC void PktQueueBusy (BOOL busy)\r
-  {\r
-    rxOutOfs = busy ? (rxInOfs + sizeof(RX_ELEMENT)) : rxInOfs;\r
-    if (rxOutOfs > LAST_RX_BUF)\r
-        rxOutOfs = FIRST_RX_BUF;\r
-    pktDrop = 0L;\r
-  }\r
-\r
-  PUBLIC WORD PktBuffersUsed (void)\r
-  {\r
-    WORD inOfs  = rxInOfs;\r
-    WORD outOfs = rxOutOfs;\r
-\r
-    if (inOfs >= outOfs)\r
-       return ((inOfs - outOfs) / sizeof(RX_ELEMENT));\r
-    return (NUM_RX_BUF - (outOfs - inOfs) / sizeof(RX_ELEMENT));\r
-  }\r
-\r
-  PUBLIC DWORD PktRxDropped (void)\r
-  {\r
-    return (pktDrop);\r
-  }\r
-#endif\r
-\r
-/**************************************************************************/\r
-\r
-LOCAL __inline void PktFreeMem (void)\r
-{\r
-#if (DOSX & PHARLAP)\r
-  if (realSeg)\r
-  {\r
-    _dx_real_free (realSeg);\r
-    realSeg = 0;\r
-  }\r
-#elif (DOSX & DJGPP)\r
-  if (rm_mem.rm_segment)\r
-  {\r
-    unsigned ofs;  /* clear the DOS-mem to prevent further upcalls */\r
-\r
-    for (ofs = 0; ofs < 16 * rm_mem.size / 4; ofs += 4)\r
-       _farpokel (_dos_ds, realBase + ofs, 0);\r
-    _go32_dpmi_free_dos_memory (&rm_mem);\r
-    rm_mem.rm_segment = 0;\r
-  }\r
-#elif (DOSX & DOS4GW)\r
-  if (rm_base_sel)\r
-  {\r
-    dpmi_real_free (rm_base_sel);\r
-    rm_base_sel = 0;\r
-  }\r
-#endif\r
-}\r
-\r
-/**************************************************************************/\r
-\r
-PUBLIC BOOL PktExitDriver (void)\r
-{           \r
-  if (pktInfo.handle)\r
-  {\r
-    if (!PktSetReceiverMode(PDRX_BROADCAST))\r
-       PUTS ("Error restoring receiver mode.");\r
-\r
-    if (!PktReleaseHandle(pktInfo.handle))\r
-       PUTS ("Error releasing PKT-DRVR handle.");\r
-\r
-    PktFreeMem();\r
-    pktInfo.handle = 0;\r
-  }\r
-\r
-  if (pcap_pkt_debug >= 1)\r
-     printf ("Internal stats: too-small %lu, too-large %lu, bad-sync %lu, "\r
-             "wrong-handle %lu\n",\r
-             intStat.tooSmall, intStat.tooLarge,\r
-             intStat.badSync, intStat.wrongHandle);\r
-  return (TRUE);\r
-}\r
-\r
-#if (DOSX & (DJGPP|DOS4GW))\r
-static void dump_pkt_stub (void)\r
-{\r
-  int i;\r
-\r
-  fprintf (stderr, "PktReceiver %lu, pkt_stub[PktReceiver] =\n",\r
-           PktReceiver);\r
-  for (i = 0; i < 15; i++)\r
-      fprintf (stderr, "%02X, ", real_stub_array[i+PktReceiver]);\r
-  fputs ("\n", stderr);\r
-}\r
-#endif\r
-\r
-/*\r
- * Front end initialization routine\r
- */\r
-PUBLIC BOOL PktInitDriver (PKT_RX_MODE mode)\r
-{\r
-  PKT_RX_MODE rxMode;\r
-  BOOL   writeInfo = (pcap_pkt_debug >= 3);\r
-\r
-  pktInfo.quiet = (pcap_pkt_debug < 3);\r
-\r
-#if (DOSX & PHARLAP) && defined(__HIGHC__)\r
-  if (_mwenv != 2)\r
-  {\r
-    fprintf (stderr, "Only Pharlap DOS extender supported.\n");\r
-    return (FALSE);\r
-  }\r
-#endif\r
-\r
-#if (DOSX & PHARLAP) && defined(__WATCOMC__)\r
-  if (_Extender != 1)\r
-  {\r
-    fprintf (stderr, "Only DOS4GW style extenders supported.\n");\r
-    return (FALSE);\r
-  }\r
-#endif\r
-\r
-  if (!PktSearchDriver())\r
-  {\r
-    PUTS ("Packet driver not found.");\r
-    PktFreeMem();\r
-    return (FALSE);\r
-  }\r
-\r
-  if (!PktGetDriverInfo())\r
-  {\r
-    PUTS ("Error getting pkt-drvr information.");\r
-    PktFreeMem();\r
-    return (FALSE);\r
-  }\r
-\r
-#if (DOSX & PHARLAP)\r
-  if (RealCopy((ULONG)&rxOutOfs, (ULONG)&pktRxEnd,\r
-               &realBase, &protBase, (USHORT*)&realSeg))\r
-  {\r
-    rxOutOfsFp  = (WORD _far *) (protBase + (WORD) &rxOutOfs);\r
-    rxInOfsFp   = (WORD _far *) (protBase + (WORD) &rxInOfs);\r
-    *rxOutOfsFp = FIRST_RX_BUF;\r
-    *rxInOfsFp  = FIRST_RX_BUF;\r
-  }\r
-  else\r
-  {\r
-    PUTS ("Cannot allocate real-mode stub.");\r
-    return (FALSE);\r
-  }\r
-\r
-#elif (DOSX & (DJGPP|DOS4GW))\r
-  if (sizeof(real_stub_array) > 0xFFFF)\r
-  {\r
-    fprintf (stderr, "`real_stub_array[]' too big.\n");\r
-    return (FALSE);\r
-  }\r
-#if (DOSX & DJGPP)\r
-  rm_mem.size = (sizeof(real_stub_array) + 15) / 16;\r
-\r
-  if (_go32_dpmi_allocate_dos_memory(&rm_mem) || rm_mem.rm_offset != 0)\r
-  {\r
-    PUTS ("real-mode init failed.");\r
-    return (FALSE);\r
-  }\r
-  realBase = (rm_mem.rm_segment << 4);\r
-  dosmemput (&real_stub_array, sizeof(real_stub_array), realBase);\r
-  _farpokel (_dos_ds, realBase+rxOutOfs, FIRST_RX_BUF);\r
-  _farpokel (_dos_ds, realBase+rxInOfs,  FIRST_RX_BUF);\r
-\r
-#elif (DOSX & DOS4GW)\r
-  rm_base_seg = dpmi_real_malloc (sizeof(real_stub_array), &rm_base_sel);\r
-  if (!rm_base_seg)\r
-  {\r
-    PUTS ("real-mode init failed.");\r
-    return (FALSE);\r
-  }\r
-  realBase = (rm_base_seg << 4);\r
-  memcpy ((void*)realBase, &real_stub_array, sizeof(real_stub_array));\r
-  *(WORD*) (realBase+rxOutOfs) = FIRST_RX_BUF;\r
-  *(WORD*) (realBase+rxInOfs)  = FIRST_RX_BUF;\r
-\r
-#endif\r
-  {\r
-    int pushf = PktReceiver;\r
-\r
-    while (real_stub_array[pushf++] != 0x9C &&    /* pushf */\r
-           real_stub_array[pushf]   != 0xFA)      /* cli   */\r
-    {\r
-      if (++para_skip > 16)\r
-      {\r
-        fprintf (stderr, "Something wrong with `pkt_stub.inc'.\n");\r
-        para_skip = 0;\r
-        dump_pkt_stub();\r
-        return (FALSE);\r
-      }\r
-    }\r
-    if (*(WORD*)(real_stub_array + offsetof(PktRealStub,_dummy)) != 0xB800)\r
-    {\r
-      fprintf (stderr, "`real_stub_array[]' is misaligned.\n");\r
-      return (FALSE);\r
-    }\r
-  }\r
-\r
-  if (pcap_pkt_debug > 2)\r
-      dump_pkt_stub();\r
-\r
-#else\r
-  rxOutOfs = FIRST_RX_BUF;\r
-  rxInOfs  = FIRST_RX_BUF;\r
-#endif\r
-\r
-  if (!PktSetAccess())\r
-  {\r
-    PUTS ("Error setting pkt-drvr access.");\r
-    PktFreeMem();\r
-    return (FALSE);\r
-  }\r
-\r
-  if (!PktGetAddress(&myAddress))\r
-  {\r
-    PUTS ("Error fetching adapter address.");\r
-    PktFreeMem();\r
-    return (FALSE);\r
-  }\r
-\r
-  if (!PktSetReceiverMode(mode))\r
-  {\r
-    PUTS ("Error setting receiver mode.");\r
-    PktFreeMem();\r
-    return (FALSE);\r
-  }\r
-\r
-  if (!PktGetReceiverMode(&rxMode))\r
-  {\r
-    PUTS ("Error getting receiver mode.");\r
-    PktFreeMem();\r
-    return (FALSE);\r
-  }\r
-\r
-  if (writeInfo)\r
-     printf ("Pkt-driver information:\n"\r
-             "  Version  : %d.%d\n"\r
-             "  Name     : %.15s\n"\r
-             "  Class    : %u (%s)\n"\r
-             "  Type     : %u\n"\r
-             "  Number   : %u\n"\r
-             "  Funcs    : %u\n"\r
-             "  Intr     : %Xh\n"\r
-             "  Handle   : %u\n"\r
-             "  Extended : %s\n"\r
-             "  Hi-perf  : %s\n"\r
-             "  RX mode  : %s\n"\r
-             "  Eth-addr : %02X:%02X:%02X:%02X:%02X:%02X\n",\r
-\r
-             pktInfo.majVer, pktInfo.minVer, pktInfo.name,\r
-             pktInfo.class,  PktGetClassName(pktInfo.class),\r
-             pktInfo.type,   pktInfo.number,\r
-             pktInfo.funcs,  pktInfo.intr,   pktInfo.handle,\r
-             pktInfo.funcs == 2 || pktInfo.funcs == 6 ? "Yes" : "No",\r
-             pktInfo.funcs == 5 || pktInfo.funcs == 6 ? "Yes" : "No",\r
-             PktRXmodeStr(rxMode),\r
-             myAddress[0], myAddress[1], myAddress[2],\r
-             myAddress[3], myAddress[4], myAddress[5]);\r
-\r
-#if defined(DEBUG) && (DOSX & PHARLAP)\r
-  if (writeInfo)\r
-  {\r
-    DWORD    rAdr = realBase + (WORD)&PktReceiver;\r
-    unsigned sel, ofs;\r
-\r
-    printf ("\nReceiver at   %04X:%04X\n", RP_SEG(rAdr),    RP_OFF(rAdr));\r
-    printf ("Realbase    = %04X:%04X\n",   RP_SEG(realBase),RP_OFF(realBase));\r
-\r
-    sel = _FP_SEG (protBase);\r
-    ofs = _FP_OFF (protBase);\r
-    printf ("Protbase    = %04X:%08X\n", sel,ofs);\r
-    printf ("RealSeg     = %04X\n", realSeg);\r
-\r
-    sel = _FP_SEG (rxOutOfsFp);\r
-    ofs = _FP_OFF (rxOutOfsFp);\r
-    printf ("rxOutOfsFp  = %04X:%08X\n", sel,ofs);\r
-\r
-    sel = _FP_SEG (rxInOfsFp);\r
-    ofs = _FP_OFF (rxInOfsFp);\r
-    printf ("rxInOfsFp   = %04X:%08X\n", sel,ofs);\r
-\r
-    printf ("Ready: *rxOutOfsFp = %04X *rxInOfsFp = %04X\n",\r
-            *rxOutOfsFp, *rxInOfsFp);\r
-\r
-    PktQueueBusy (TRUE);\r
-    printf ("Busy:  *rxOutOfsFp = %04X *rxInOfsFp = %04X\n",\r
-            *rxOutOfsFp, *rxInOfsFp);\r
-  }\r
-#endif\r
-\r
-  memset (&pktStat, 0, sizeof(pktStat));  /* clear statistics */\r
-  PktQueueBusy (TRUE);\r
-  return (TRUE);\r
-}\r
-\r
-\r
-/*\r
- * DPMI functions only for Watcom + DOS4GW extenders\r
- */\r
-#if (DOSX & DOS4GW)\r
-LOCAL DWORD dpmi_get_real_vector (int intr)\r
-{\r
-  union REGS r;\r
-\r
-  r.x.eax = 0x200;\r
-  r.x.ebx = (DWORD) intr;\r
-  int386 (0x31, &r, &r);\r
-  return ((r.w.cx << 4) + r.w.dx);\r
-}\r
-\r
-LOCAL WORD dpmi_real_malloc (int size, WORD *selector)\r
-{\r
-  union REGS r;\r
-\r
-  r.x.eax = 0x0100;             /* DPMI allocate DOS memory */\r
-  r.x.ebx = (size + 15) / 16;   /* Number of paragraphs requested */\r
-  int386 (0x31, &r, &r);\r
-  if (r.w.cflag & 1)\r
-     return (0);\r
-\r
-  *selector = r.w.dx;\r
-  return (r.w.ax);              /* Return segment address */\r
-}\r
-\r
-LOCAL void dpmi_real_free (WORD selector)\r
-{\r
-  union REGS r;\r
-\r
-  r.x.eax = 0x101;              /* DPMI free DOS memory */\r
-  r.x.ebx = selector;           /* Selector to free */\r
-  int386 (0x31, &r, &r);\r
-}\r
-#endif\r
-\r
-\r
-#if defined(DOSX) && (DOSX & PHARLAP)\r
-/*\r
- * Description:\r
- *     This routine allocates conventional memory for the specified block\r
- *     of code (which must be within the first 64K of the protected mode\r
- *     program segment) and copies the code to it.\r
- *\r
- *     The caller should free up the conventional memory block when it\r
- *     is done with the conventional memory.\r
- *\r
- *     NOTE THIS ROUTINE REQUIRES 386|DOS-EXTENDER 3.0 OR LATER.\r
- *\r
- * Calling arguments:\r
- *     start_offs      start of real mode code in program segment\r
- *     end_offs        1 byte past end of real mode code in program segment\r
- *     real_basep      returned;  real mode ptr to use as a base for the\r
- *                        real mode code (eg, to get the real mode FAR\r
- *                        addr of a function foo(), take\r
- *                        real_basep + (ULONG) foo).\r
- *                        This pointer is constructed such that\r
- *                        offsets within the real mode segment are\r
- *                        the same as the link-time offsets in the\r
- *                        protected mode program segment\r
- *     prot_basep      returned;  prot mode ptr to use as a base for getting\r
- *                        to the conventional memory, also constructed\r
- *                        so that adding the prot mode offset of a\r
- *                        function or variable to the base gets you a\r
- *                        ptr to the function or variable in the\r
- *                        conventional memory block.\r
- *     rmem_adrp       returned;  real mode para addr of allocated\r
- *                        conventional memory block, to be used to free\r
- *                        up the conventional memory when done.  DO NOT\r
- *                        USE THIS TO CONSTRUCT A REAL MODE PTR, USE\r
- *                        REAL_BASEP INSTEAD SO THAT OFFSETS WORK OUT\r
- *                        CORRECTLY.\r
- *\r
- * Returned values:\r
- *     0      if error\r
- *     1      if success\r
- */\r
-int RealCopy (ULONG    start_offs,\r
-              ULONG    end_offs,\r
-              REALPTR *real_basep,\r
-              FARPTR  *prot_basep,\r
-              USHORT  *rmem_adrp)\r
-{\r
-  ULONG   rm_base;    /* base real mode para addr for accessing */\r
-                      /* allocated conventional memory          */\r
-  UCHAR  *source;     /* source pointer for copy                */\r
-  FARPTR  destin;     /* destination pointer for copy           */\r
-  ULONG   len;        /* number of bytes to copy                */\r
-  ULONG   temp;\r
-  USHORT  stemp;\r
-\r
-  /* First check for valid inputs\r
-   */\r
-  if (start_offs >= end_offs || end_offs > 0x10000)\r
-     return (FALSE);\r
-\r
-  /* Round start_offs down to a paragraph (16-byte) boundary so we can set up\r
-   * the real mode pointer easily. Round up end_offs to make sure we allocate\r
-   * enough paragraphs\r
-   */\r
-  start_offs &= ~15;\r
-  end_offs = (15 + (end_offs << 4)) >> 4;\r
-\r
-  /* Allocate the conventional memory for our real mode code.  Remember to\r
-   * round byte count UP to 16-byte paragraph size.  We alloc it\r
-   * above the DOS data buffer so both the DOS data buffer and the appl\r
-   * conventional mem block can still be resized.\r
-   *\r
-   * First just try to alloc it;  if we can't get it, shrink the appl mem\r
-   * block down to the minimum, try to alloc the memory again, then grow the\r
-   * appl mem block back to the maximum.  (Don't try to shrink the DOS data\r
-   * buffer to free conventional memory;  it wouldn't be good for this routine\r
-   * to have the possible side effect of making file I/O run slower.)\r
-   */\r
-  len = ((end_offs - start_offs) + 15) >> 4;\r
-  if (_dx_real_above(len, rmem_adrp, &stemp) != _DOSE_NONE)\r
-  {\r
-    if (_dx_cmem_usage(0, 0, &temp, &temp) != _DOSE_NONE)\r
-       return (FALSE);\r
-\r
-    if (_dx_real_above(len, rmem_adrp, &stemp) != _DOSE_NONE)\r
-       *rmem_adrp = 0;\r
-\r
-    if (_dx_cmem_usage(0, 1, &temp, &temp) != _DOSE_NONE)\r
-    {\r
-      if (*rmem_adrp != 0)\r
-         _dx_real_free (*rmem_adrp);\r
-      return (FALSE);\r
-    }\r
-\r
-    if (*rmem_adrp == 0)\r
-       return (FALSE);\r
-  }\r
-\r
-  /* Construct real mode & protected mode pointers to access the allocated\r
-   * memory.  Note we know start_offs is aligned on a paragraph (16-byte)\r
-   * boundary, because we rounded it down.\r
-   *\r
-   * We make the offsets come out rights by backing off the real mode selector\r
-   * by start_offs.\r
-   */\r
-  rm_base = ((ULONG) *rmem_adrp) - (start_offs >> 4);\r
-  RP_SET (*real_basep, 0, rm_base);\r
-  FP_SET (*prot_basep, rm_base << 4, SS_DOSMEM);\r
-\r
-  /* Copy the real mode code/data to the allocated memory\r
-   */\r
-  source = (UCHAR *) start_offs;\r
-  destin = *prot_basep;\r
-  FP_SET (destin, FP_OFF(*prot_basep) + start_offs, FP_SEL(*prot_basep));\r
-  len = end_offs - start_offs;\r
-  WriteFarMem (destin, source, len);\r
-\r
-  return (TRUE);\r
-}\r
-#endif /* DOSX && (DOSX & PHARLAP) */\r
+/*
+ *  File.........: pktdrvr.c
+ *
+ *  Responsible..: Gisle Vanem,  giva@bgnett.no
+ *
+ *  Created......: 26.Sept 1995
+ *
+ *  Description..: Packet-driver interface for 16/32-bit C :
+ *                 Borland C/C++ 3.0+ small/large model
+ *                 Watcom C/C++ 11+, DOS4GW flat model
+ *                 Metaware HighC 3.1+ and PharLap 386|DosX
+ *                 GNU C/C++ 2.7+ and djgpp 2.x extender
+ *
+ *  References...: PC/TCP Packet driver Specification. rev 1.09
+ *                 FTP Software Inc.
+ *
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <dos.h>
+
+#include "pcap-dos.h"
+#include "pcap-int.h"
+#include "msdos/pktdrvr.h"
+
+#if (DOSX)
+#define NUM_RX_BUF  32      /* # of buffers in Rx FIFO queue */
+#else
+#define NUM_RX_BUF  10
+#endif
+
+#define DIM(x)   (sizeof((x)) / sizeof(x[0]))
+#define PUTS(s)  do {                                           \
+                   if (!pktInfo.quiet)                          \
+                      pktInfo.error ?                           \
+                        printf ("%s: %s\n", s, pktInfo.error) : \
+                        printf ("%s\n", pktInfo.error = s);     \
+                 } while (0)
+
+#if defined(__HIGHC__)
+  extern UINT _mwenv;
+
+#elif defined(__DJGPP__)
+  #include <stddef.h>
+  #include <dpmi.h>
+  #include <go32.h>
+  #include <pc.h>
+  #include <sys/farptr.h>
+
+#elif defined(__WATCOMC__)
+  #include <i86.h>
+  #include <stddef.h>
+  extern char _Extender;
+
+#else
+  extern void far PktReceiver (void);
+#endif
+
+
+#if (DOSX & (DJGPP|DOS4GW))
+  #include <sys/pack_on.h>
+
+  struct DPMI_regs {
+         DWORD  r_di;
+         DWORD  r_si;
+         DWORD  r_bp;
+         DWORD  reserved;
+         DWORD  r_bx;
+         DWORD  r_dx;
+         DWORD  r_cx;
+         DWORD  r_ax;
+         WORD   r_flags;
+         WORD   r_es, r_ds, r_fs, r_gs;
+         WORD   r_ip, r_cs, r_sp, r_ss;
+       };
+
+  /* Data located in a real-mode segment. This becomes far at runtime
+   */
+  typedef struct  {          /* must match data/code in pkt_rx1.s */
+          WORD       _rxOutOfs;
+          WORD       _rxInOfs;
+          DWORD      _pktDrop;
+          BYTE       _pktTemp [20];
+          TX_ELEMENT _pktTxBuf[1];
+          RX_ELEMENT _pktRxBuf[NUM_RX_BUF];
+          WORD       _dummy[2];        /* screenSeg,newInOffset */
+          BYTE       _fanChars[4];
+          WORD       _fanIndex;
+          BYTE       _PktReceiver[15]; /* starts on a paragraph (16byte) */
+        } PktRealStub;
+  #include <sys/pack_off.h>
+
+  static BYTE real_stub_array [] = {
+         #include "pkt_stub.inc"       /* generated opcode array */
+       };
+
+  #define rxOutOfs      offsetof (PktRealStub,_rxOutOfs)
+  #define rxInOfs       offsetof (PktRealStub,_rxInOfs)
+  #define PktReceiver   offsetof (PktRealStub,_PktReceiver [para_skip])
+  #define pktDrop       offsetof (PktRealStub,_pktDrop)
+  #define pktTemp       offsetof (PktRealStub,_pktTemp)
+  #define pktTxBuf      offsetof (PktRealStub,_pktTxBuf)
+  #define FIRST_RX_BUF  offsetof (PktRealStub,_pktRxBuf [0])
+  #define LAST_RX_BUF   offsetof (PktRealStub,_pktRxBuf [NUM_RX_BUF-1])
+
+#else
+  extern WORD       rxOutOfs;    /* offsets into pktRxBuf FIFO queue   */
+  extern WORD       rxInOfs;
+  extern DWORD      pktDrop;     /* # packets dropped in PktReceiver() */
+  extern BYTE       pktRxEnd;    /* marks the end of r-mode code/data  */
+
+  extern RX_ELEMENT pktRxBuf [NUM_RX_BUF];       /* PktDrvr Rx buffers */
+  extern TX_ELEMENT pktTxBuf;                    /* PktDrvr Tx buffer  */
+  extern char       pktTemp[20];                 /* PktDrvr temp area  */
+
+  #define FIRST_RX_BUF (WORD) &pktRxBuf [0]
+  #define LAST_RX_BUF  (WORD) &pktRxBuf [NUM_RX_BUF-1]
+#endif
+
+
+#ifdef __BORLANDC__           /* Use Borland's inline functions */
+  #define memcpy  __memcpy__
+  #define memcmp  __memcmp__
+  #define memset  __memset__
+#endif
+
+
+#if (DOSX & PHARLAP)
+  extern void PktReceiver (void);     /* in pkt_rx0.asm */
+  static int  RealCopy    (ULONG, ULONG, REALPTR*, FARPTR*, USHORT*);
+
+  #undef  FP_SEG
+  #undef  FP_OFF
+  #define FP_OFF(x)     ((WORD)(x))
+  #define FP_SEG(x)     ((WORD)(realBase >> 16))
+  #define DOS_ADDR(s,o) (((DWORD)(s) << 16) + (WORD)(o))
+  #define r_ax          eax
+  #define r_bx          ebx
+  #define r_dx          edx
+  #define r_cx          ecx
+  #define r_si          esi
+  #define r_di          edi
+  #define r_ds          ds
+  #define r_es          es
+  LOCAL FARPTR          protBase;
+  LOCAL REALPTR         realBase;
+  LOCAL WORD            realSeg;   /* DOS para-address of allocated area */
+  LOCAL SWI_REGS        reg;
+
+  static WORD _far *rxOutOfsFp, *rxInOfsFp;
+
+#elif (DOSX & DJGPP)
+  static _go32_dpmi_seginfo rm_mem;
+  static __dpmi_regs        reg;
+  static DWORD              realBase;
+  static int                para_skip = 0;
+
+  #define DOS_ADDR(s,o)     (((WORD)(s) << 4) + (o))
+  #define r_ax              x.ax
+  #define r_bx              x.bx
+  #define r_dx              x.dx
+  #define r_cx              x.cx
+  #define r_si              x.si
+  #define r_di              x.di
+  #define r_ds              x.ds
+  #define r_es              x.es
+
+#elif (DOSX & DOS4GW)
+  LOCAL struct DPMI_regs    reg;
+  LOCAL WORD                rm_base_seg, rm_base_sel;
+  LOCAL DWORD               realBase;
+  LOCAL int                 para_skip = 0;
+
+  LOCAL DWORD dpmi_get_real_vector (int intr);
+  LOCAL WORD  dpmi_real_malloc     (int size, WORD *selector);
+  LOCAL void  dpmi_real_free       (WORD selector);
+  #define DOS_ADDR(s,o) (((DWORD)(s) << 4) + (WORD)(o))
+
+#else              /* real-mode Borland etc. */
+  static struct  {
+         WORD r_ax, r_bx, r_cx, r_dx, r_bp;
+         WORD r_si, r_di, r_ds, r_es, r_flags;
+       } reg;
+#endif
+
+#ifdef __HIGHC__
+  #pragma Alias (pktDrop,    "_pktDrop")
+  #pragma Alias (pktRxBuf,   "_pktRxBuf")
+  #pragma Alias (pktTxBuf,   "_pktTxBuf")
+  #pragma Alias (pktTemp,    "_pktTemp")
+  #pragma Alias (rxOutOfs,   "_rxOutOfs")
+  #pragma Alias (rxInOfs,    "_rxInOfs")
+  #pragma Alias (pktRxEnd,   "_pktRxEnd")
+  #pragma Alias (PktReceiver,"_PktReceiver")
+#endif
+
+
+PUBLIC PKT_STAT    pktStat;    /* statistics for packets    */
+PUBLIC PKT_INFO    pktInfo;    /* packet-driver information */
+
+PUBLIC PKT_RX_MODE receiveMode  = PDRX_DIRECT;
+PUBLIC ETHER       myAddress    = {   0,  0,  0,  0,  0,  0 };
+PUBLIC ETHER       ethBroadcast = { 255,255,255,255,255,255 };
+
+LOCAL  struct {             /* internal statistics */
+       DWORD  tooSmall;     /* size < ETH_MIN */
+       DWORD  tooLarge;     /* size > ETH_MAX */
+       DWORD  badSync;      /* count_1 != count_2 */
+       DWORD  wrongHandle;  /* upcall to wrong handle */
+     } intStat;
+
+/***************************************************************************/
+
+PUBLIC const char *PktGetErrorStr (int errNum)
+{
+  static const char *errStr[] = {
+                    "",
+                    "Invalid handle number",
+                    "No interfaces of specified class found",
+                    "No interfaces of specified type found",
+                    "No interfaces of specified number found",
+                    "Bad packet type specified",
+                    "Interface does not support multicast",
+                    "Packet driver cannot terminate",
+                    "Invalid receiver mode specified",
+                    "Insufficient memory space",
+                    "Type previously accessed, and not released",
+                    "Command out of range, or not implemented",
+                    "Cannot send packet (usually hardware error)",
+                    "Cannot change hardware address ( > 1 handle open)",
+                    "Hardware address has bad length or format",
+                    "Cannot reset interface (more than 1 handle open)",
+                    "Bad Check-sum",
+                    "Bad size",
+                    "Bad sync" ,
+                    "Source hit"
+                  };
+
+  if (errNum < 0 || errNum >= DIM(errStr))
+     return ("Unknown driver error.");
+  return (errStr [errNum]);
+}
+
+/**************************************************************************/
+
+PUBLIC const char *PktGetClassName (WORD class)
+{
+  switch (class)
+  {
+    case PD_ETHER:
+         return ("DIX-Ether");
+    case PD_PRONET10:
+         return ("ProNET-10");
+    case PD_IEEE8025:
+         return ("IEEE 802.5");
+    case PD_OMNINET:
+         return ("OmniNet");
+    case PD_APPLETALK:
+         return ("AppleTalk");
+    case PD_SLIP:
+         return ("SLIP");
+    case PD_STARTLAN:
+         return ("StartLAN");
+    case PD_ARCNET:
+         return ("ArcNet");
+    case PD_AX25:
+         return ("AX.25");
+    case PD_KISS:
+         return ("KISS");
+    case PD_IEEE8023_2:
+         return ("IEEE 802.3 w/802.2 hdr");
+    case PD_FDDI8022:
+         return ("FDDI w/802.2 hdr");
+    case PD_X25:
+         return ("X.25");
+    case PD_LANstar:
+         return ("LANstar");
+    case PD_PPP:
+         return ("PPP");
+    default:
+         return ("unknown");
+  }
+}
+
+/**************************************************************************/
+
+PUBLIC char const *PktRXmodeStr (PKT_RX_MODE mode)
+{
+  static const char *modeStr [] = {
+                    "Receiver turned off",
+                    "Receive only directly addressed packets",
+                    "Receive direct & broadcast packets",
+                    "Receive direct,broadcast and limited multicast packets",
+                    "Receive direct,broadcast and all multicast packets",
+                    "Receive all packets (promiscuouos mode)"
+                  };
+
+  if (mode > DIM(modeStr))
+     return ("??");
+  return (modeStr [mode-1]);
+}
+
+/**************************************************************************/
+
+LOCAL __inline BOOL PktInterrupt (void)
+{
+  BOOL okay;
+
+#if (DOSX & PHARLAP)
+  _dx_real_int ((UINT)pktInfo.intr, &reg);
+  okay = ((reg.flags & 1) == 0);  /* OK if carry clear */
+
+#elif (DOSX & DJGPP)
+  __dpmi_int ((int)pktInfo.intr, &reg);
+  okay = ((reg.x.flags & 1) == 0);
+
+#elif (DOSX & DOS4GW)
+  union  REGS  r;
+  struct SREGS s;
+
+  memset (&r, 0, sizeof(r));
+  segread (&s);
+  r.w.ax  = 0x300;
+  r.x.ebx = pktInfo.intr;
+  r.w.cx  = 0;
+  s.es    = FP_SEG (&reg);
+  r.x.edi = FP_OFF (&reg);
+  reg.r_flags = 0;
+  reg.r_ss = reg.r_sp = 0;     /* DPMI host provides stack */
+
+  int386x (0x31, &r, &r, &s);
+  okay = (!r.w.cflag);
+
+#else
+  reg.r_flags = 0;
+  intr (pktInfo.intr, (struct REGPACK*)&reg);
+  okay = ((reg.r_flags & 1) == 0);
+#endif
+
+  if (okay)
+       pktInfo.error = NULL;
+  else pktInfo.error = PktGetErrorStr (reg.r_dx >> 8);
+  return (okay);
+}
+
+/**************************************************************************/
+
+/*
+ * Search for packet driver at interrupt 60h through 80h. If ASCIIZ
+ * string "PKT DRVR" found at offset 3 in the interrupt handler, return
+ * interrupt number, else return zero in pktInfo.intr
+ */
+PUBLIC BOOL PktSearchDriver (void)
+{
+  BYTE intr  = 0x20;
+  BOOL found = FALSE;
+
+  while (!found && intr < 0xFF)
+  {
+    static char str[12];                 /* 3 + strlen("PKT DRVR") */
+    static char pktStr[9] = "PKT DRVR";  /* ASCIIZ string at ofs 3 */
+    DWORD  rp;                           /* in interrupt  routine  */
+
+#if (DOSX & PHARLAP)
+    _dx_rmiv_get (intr, &rp);
+    ReadRealMem (&str, (REALPTR)rp, sizeof(str));
+
+#elif (DOSX & DJGPP)
+    __dpmi_raddr realAdr;
+    __dpmi_get_real_mode_interrupt_vector (intr, &realAdr);
+    rp = (realAdr.segment << 4) + realAdr.offset16;
+    dosmemget (rp, sizeof(str), &str);
+
+#elif (DOSX & DOS4GW)
+    rp = dpmi_get_real_vector (intr);
+    memcpy (&str, (void*)rp, sizeof(str));
+
+#else
+    _fmemcpy (&str, getvect(intr), sizeof(str));
+#endif
+
+    found = memcmp (&str[3],&pktStr,sizeof(pktStr)) == 0;
+    intr++;
+  }
+  pktInfo.intr = (found ? intr-1 : 0);
+  return (found);
+}
+
+
+/**************************************************************************/
+
+static BOOL PktSetAccess (void)
+{
+  reg.r_ax = 0x0200 + pktInfo.class;
+  reg.r_bx = 0xFFFF;
+  reg.r_dx = 0;
+  reg.r_cx = 0;
+
+#if (DOSX & PHARLAP)
+  reg.ds  = 0;
+  reg.esi = 0;
+  reg.es  = RP_SEG (realBase);
+  reg.edi = (WORD) &PktReceiver;
+
+#elif (DOSX & DJGPP)
+  reg.x.ds = 0;
+  reg.x.si = 0;
+  reg.x.es = rm_mem.rm_segment;
+  reg.x.di = PktReceiver;
+
+#elif (DOSX & DOS4GW)
+  reg.r_ds = 0;
+  reg.r_si = 0;
+  reg.r_es = rm_base_seg;
+  reg.r_di = PktReceiver;
+
+#else
+  reg.r_ds = 0;
+  reg.r_si = 0;
+  reg.r_es = FP_SEG (&PktReceiver);
+  reg.r_di = FP_OFF (&PktReceiver);
+#endif
+
+  if (!PktInterrupt())
+     return (FALSE);
+
+  pktInfo.handle = reg.r_ax;
+  return (TRUE);
+}
+
+/**************************************************************************/
+
+PUBLIC BOOL PktReleaseHandle (WORD handle)
+{
+  reg.r_ax = 0x0300;
+  reg.r_bx = handle;
+  return PktInterrupt();
+}
+
+/**************************************************************************/
+
+PUBLIC BOOL PktTransmit (const void *eth, int len)
+{
+  if (len > ETH_MTU)
+     return (FALSE);
+
+  reg.r_ax = 0x0400;             /* Function 4, send pkt */
+  reg.r_cx = len;                /* total size of frame  */
+
+#if (DOSX & DJGPP)
+  dosmemput (eth, len, realBase+pktTxBuf);
+  reg.x.ds = rm_mem.rm_segment;  /* DOS data segment and */
+  reg.x.si = pktTxBuf;           /* DOS offset to buffer */
+
+#elif (DOSX & DOS4GW)
+  memcpy ((void*)(realBase+pktTxBuf), eth, len);
+  reg.r_ds = rm_base_seg;
+  reg.r_si = pktTxBuf;
+
+#elif (DOSX & PHARLAP)
+  memcpy (&pktTxBuf, eth, len);
+  reg.r_ds = FP_SEG (&pktTxBuf);
+  reg.r_si = FP_OFF (&pktTxBuf);
+
+#else
+  reg.r_ds = FP_SEG (eth);
+  reg.r_si = FP_OFF (eth);
+#endif
+
+  return PktInterrupt();
+}
+
+/**************************************************************************/
+
+#if (DOSX & (DJGPP|DOS4GW))
+LOCAL __inline BOOL CheckElement (RX_ELEMENT *rx)
+#else
+LOCAL __inline BOOL CheckElement (RX_ELEMENT _far *rx)
+#endif
+{
+  WORD count_1, count_2;
+
+  /*
+   * We got an upcall to the same RMCB with wrong handle.
+   * This can happen if we failed to release handle at program exit
+   */
+  if (rx->handle != pktInfo.handle)
+  {
+    pktInfo.error = "Wrong handle";
+    intStat.wrongHandle++;
+    PktReleaseHandle (rx->handle);
+    return (FALSE);
+  }
+  count_1 = rx->firstCount;
+  count_2 = rx->secondCount;
+
+  if (count_1 != count_2)
+  {
+    pktInfo.error = "Bad sync";
+    intStat.badSync++;
+    return (FALSE);
+  }
+  if (count_1 > ETH_MAX)
+  {
+    pktInfo.error = "Large esize";
+    intStat.tooLarge++;
+    return (FALSE);
+  }
+#if 0
+  if (count_1 < ETH_MIN)
+  {
+    pktInfo.error = "Small esize";
+    intStat.tooSmall++;
+    return (FALSE);
+  }
+#endif
+  return (TRUE);
+}
+
+/**************************************************************************/
+
+PUBLIC BOOL PktTerminHandle (WORD handle)
+{
+  reg.r_ax = 0x0500;
+  reg.r_bx = handle;
+  return PktInterrupt();
+}
+
+/**************************************************************************/
+
+PUBLIC BOOL PktResetInterface (WORD handle)
+{
+  reg.r_ax = 0x0700;
+  reg.r_bx = handle;
+  return PktInterrupt();
+}
+
+/**************************************************************************/
+
+PUBLIC BOOL PktSetReceiverMode (PKT_RX_MODE mode)
+{
+  if (pktInfo.class == PD_SLIP || pktInfo.class == PD_PPP)
+     return (TRUE);
+
+  reg.r_ax = 0x1400;
+  reg.r_bx = pktInfo.handle;
+  reg.r_cx = (WORD)mode;
+
+  if (!PktInterrupt())
+     return (FALSE);
+
+  receiveMode = mode;
+  return (TRUE);
+}
+
+/**************************************************************************/
+
+PUBLIC BOOL PktGetReceiverMode (PKT_RX_MODE *mode)
+{
+  reg.r_ax = 0x1500;
+  reg.r_bx = pktInfo.handle;
+
+  if (!PktInterrupt())
+     return (FALSE);
+
+  *mode = reg.r_ax;
+  return (TRUE);
+}
+
+/**************************************************************************/
+
+static PKT_STAT initialStat;         /* statistics at startup */
+static BOOL     resetStat = FALSE;   /* statistics reset ? */
+
+PUBLIC BOOL PktGetStatistics (WORD handle)
+{
+  reg.r_ax = 0x1800;
+  reg.r_bx = handle;
+
+  if (!PktInterrupt())
+     return (FALSE);
+
+#if (DOSX & PHARLAP)
+  ReadRealMem (&pktStat, DOS_ADDR(reg.ds,reg.esi), sizeof(pktStat));
+
+#elif (DOSX & DJGPP)
+  dosmemget (DOS_ADDR(reg.x.ds,reg.x.si), sizeof(pktStat), &pktStat);
+
+#elif (DOSX & DOS4GW)
+  memcpy (&pktStat, (void*)DOS_ADDR(reg.r_ds,reg.r_si), sizeof(pktStat));
+
+#else
+  _fmemcpy (&pktStat, MK_FP(reg.r_ds,reg.r_si), sizeof(pktStat));
+#endif
+
+  return (TRUE);
+}
+
+/**************************************************************************/
+
+PUBLIC BOOL PktSessStatistics (WORD handle)
+{
+  if (!PktGetStatistics(pktInfo.handle))
+     return (FALSE);
+
+  if (resetStat)
+  {
+    pktStat.inPackets  -= initialStat.inPackets;
+    pktStat.outPackets -= initialStat.outPackets;
+    pktStat.inBytes    -= initialStat.inBytes;
+    pktStat.outBytes   -= initialStat.outBytes;
+    pktStat.inErrors   -= initialStat.inErrors;
+    pktStat.outErrors  -= initialStat.outErrors;
+    pktStat.outErrors  -= initialStat.outErrors;
+    pktStat.lost       -= initialStat.lost;
+  }
+  return (TRUE);
+}
+
+/**************************************************************************/
+
+PUBLIC BOOL PktResetStatistics (WORD handle)
+{
+  if (!PktGetStatistics(pktInfo.handle))
+     return (FALSE);
+
+  memcpy (&initialStat, &pktStat, sizeof(initialStat));
+  resetStat = TRUE;
+  return (TRUE);
+}
+
+/**************************************************************************/
+
+PUBLIC BOOL PktGetAddress (ETHER *addr)
+{
+  reg.r_ax = 0x0600;
+  reg.r_bx = pktInfo.handle;
+  reg.r_cx = sizeof (*addr);
+
+#if (DOSX & DJGPP)
+  reg.x.es = rm_mem.rm_segment;
+  reg.x.di = pktTemp;
+#elif (DOSX & DOS4GW)
+  reg.r_es = rm_base_seg;
+  reg.r_di = pktTemp;
+#else
+  reg.r_es = FP_SEG (&pktTemp);
+  reg.r_di = FP_OFF (&pktTemp);  /* ES:DI = address for result */
+#endif
+
+  if (!PktInterrupt())
+     return (FALSE);
+
+#if (DOSX & PHARLAP)
+  ReadRealMem (addr, realBase + (WORD)&pktTemp, sizeof(*addr));
+
+#elif (DOSX & DJGPP)
+  dosmemget (realBase+pktTemp, sizeof(*addr), addr);
+
+#elif (DOSX & DOS4GW)
+  memcpy (addr, (void*)(realBase+pktTemp), sizeof(*addr));
+
+#else
+  memcpy ((void*)addr, &pktTemp, sizeof(*addr));
+#endif
+
+  return (TRUE);
+}
+
+/**************************************************************************/
+
+PUBLIC BOOL PktSetAddress (const ETHER *addr)
+{
+  /* copy addr to real-mode scrath area */
+
+#if (DOSX & PHARLAP)
+  WriteRealMem (realBase + (WORD)&pktTemp, (void*)addr, sizeof(*addr));
+
+#elif (DOSX & DJGPP)
+  dosmemput (addr, sizeof(*addr), realBase+pktTemp);
+
+#elif (DOSX & DOS4GW)
+  memcpy ((void*)(realBase+pktTemp), addr, sizeof(*addr));
+
+#else
+  memcpy (&pktTemp, (void*)addr, sizeof(*addr));
+#endif
+
+  reg.r_ax = 0x1900;
+  reg.r_cx = sizeof (*addr);      /* address length       */
+
+#if (DOSX & DJGPP)
+  reg.x.es = rm_mem.rm_segment;   /* DOS offset to param  */
+  reg.x.di = pktTemp;             /* DOS segment to param */
+#elif (DOSX & DOS4GW)
+  reg.r_es = rm_base_seg;
+  reg.r_di = pktTemp;
+#else
+  reg.r_es = FP_SEG (&pktTemp);
+  reg.r_di = FP_OFF (&pktTemp);
+#endif
+
+  return PktInterrupt();
+}
+
+/**************************************************************************/
+
+PUBLIC BOOL PktGetDriverInfo (void)
+{
+  pktInfo.majVer = 0;
+  pktInfo.minVer = 0;
+  memset (&pktInfo.name, 0, sizeof(pktInfo.name));
+  reg.r_ax = 0x01FF;
+  reg.r_bx = 0;
+
+  if (!PktInterrupt())
+     return (FALSE);
+
+  pktInfo.number = reg.r_cx & 0xFF;
+  pktInfo.class  = reg.r_cx >> 8;
+#if 0
+  pktInfo.minVer = reg.r_bx % 10;
+  pktInfo.majVer = reg.r_bx / 10;
+#else
+  pktInfo.majVer = reg.r_bx;  // !!
+#endif
+  pktInfo.funcs  = reg.r_ax & 0xFF;
+  pktInfo.type   = reg.r_dx & 0xFF;
+
+#if (DOSX & PHARLAP)
+  ReadRealMem (&pktInfo.name, DOS_ADDR(reg.ds,reg.esi), sizeof(pktInfo.name));
+
+#elif (DOSX & DJGPP)
+  dosmemget (DOS_ADDR(reg.x.ds,reg.x.si), sizeof(pktInfo.name), &pktInfo.name);
+
+#elif (DOSX & DOS4GW)
+  memcpy (&pktInfo.name, (void*)DOS_ADDR(reg.r_ds,reg.r_si), sizeof(pktInfo.name));
+
+#else
+  _fmemcpy (&pktInfo.name, MK_FP(reg.r_ds,reg.r_si), sizeof(pktInfo.name));
+#endif
+  return (TRUE);
+}
+
+/**************************************************************************/
+
+PUBLIC BOOL PktGetDriverParam (void)
+{
+  reg.r_ax = 0x0A00;
+
+  if (!PktInterrupt())
+     return (FALSE);
+
+#if (DOSX & PHARLAP)
+  ReadRealMem (&pktInfo.majVer, DOS_ADDR(reg.es,reg.edi), PKT_PARAM_SIZE);
+
+#elif (DOSX & DJGPP)
+  dosmemget (DOS_ADDR(reg.x.es,reg.x.di), PKT_PARAM_SIZE, &pktInfo.majVer);
+
+#elif (DOSX & DOS4GW)
+  memcpy (&pktInfo.majVer, (void*)DOS_ADDR(reg.r_es,reg.r_di), PKT_PARAM_SIZE);
+
+#else
+  _fmemcpy (&pktInfo.majVer, MK_FP(reg.r_es,reg.r_di), PKT_PARAM_SIZE);
+#endif
+  return (TRUE);
+}
+
+/**************************************************************************/
+
+#if (DOSX & PHARLAP)
+  PUBLIC int PktReceive (BYTE *buf, int max)
+  {
+    WORD inOfs  = *rxInOfsFp;
+    WORD outOfs = *rxOutOfsFp;
+
+    if (outOfs != inOfs)
+    {
+      RX_ELEMENT _far *head = (RX_ELEMENT _far*)(protBase+outOfs);
+      int size, len = max;
+
+      if (CheckElement(head))
+      {
+        size = min (head->firstCount, sizeof(RX_ELEMENT));
+        len  = min (size, max);
+        _fmemcpy (buf, &head->destin, len);
+      }
+      else
+        size = -1;
+
+      outOfs += sizeof (RX_ELEMENT);
+      if (outOfs > LAST_RX_BUF)
+          outOfs = FIRST_RX_BUF;
+      *rxOutOfsFp = outOfs;
+      return (size);
+    }
+    return (0);
+  }
+
+  PUBLIC void PktQueueBusy (BOOL busy)
+  {
+    *rxOutOfsFp = busy ? (*rxInOfsFp + sizeof(RX_ELEMENT)) : *rxInOfsFp;
+    if (*rxOutOfsFp > LAST_RX_BUF)
+        *rxOutOfsFp = FIRST_RX_BUF;
+    *(DWORD _far*)(protBase + (WORD)&pktDrop) = 0;
+  }
+
+  PUBLIC WORD PktBuffersUsed (void)
+  {
+    WORD inOfs  = *rxInOfsFp;
+    WORD outOfs = *rxOutOfsFp;
+
+    if (inOfs >= outOfs)
+       return (inOfs - outOfs) / sizeof(RX_ELEMENT);
+    return (NUM_RX_BUF - (outOfs - inOfs) / sizeof(RX_ELEMENT));
+  }
+
+  PUBLIC DWORD PktRxDropped (void)
+  {
+    return (*(DWORD _far*)(protBase + (WORD)&pktDrop));
+  }
+
+#elif (DOSX & DJGPP)
+  PUBLIC int PktReceive (BYTE *buf, int max)
+  {
+    WORD ofs = _farpeekw (_dos_ds, realBase+rxOutOfs);
+
+    if (ofs != _farpeekw (_dos_ds, realBase+rxInOfs))
+    {
+      RX_ELEMENT head;
+      int  size, len = max;
+
+      head.firstCount  = _farpeekw (_dos_ds, realBase+ofs);
+      head.secondCount = _farpeekw (_dos_ds, realBase+ofs+2);
+      head.handle      = _farpeekw (_dos_ds, realBase+ofs+4);
+
+      if (CheckElement(&head))
+      {
+        size = min (head.firstCount, sizeof(RX_ELEMENT));
+        len  = min (size, max);
+        dosmemget (realBase+ofs+6, len, buf);
+      }
+      else
+        size = -1;
+
+      ofs += sizeof (RX_ELEMENT);
+      if (ofs > LAST_RX_BUF)
+           _farpokew (_dos_ds, realBase+rxOutOfs, FIRST_RX_BUF);
+      else _farpokew (_dos_ds, realBase+rxOutOfs, ofs);
+      return (size);
+    }
+    return (0);
+  }
+
+  PUBLIC void PktQueueBusy (BOOL busy)
+  {
+    WORD ofs;
+
+    disable();
+    ofs = _farpeekw (_dos_ds, realBase+rxInOfs);
+    if (busy)
+       ofs += sizeof (RX_ELEMENT);
+
+    if (ofs > LAST_RX_BUF)
+         _farpokew (_dos_ds, realBase+rxOutOfs, FIRST_RX_BUF);
+    else _farpokew (_dos_ds, realBase+rxOutOfs, ofs);
+    _farpokel (_dos_ds, realBase+pktDrop, 0UL);
+    enable();
+  }
+
+  PUBLIC WORD PktBuffersUsed (void)
+  {
+    WORD inOfs, outOfs;
+
+    disable();
+    inOfs  = _farpeekw (_dos_ds, realBase+rxInOfs);
+    outOfs = _farpeekw (_dos_ds, realBase+rxOutOfs);
+    enable();
+    if (inOfs >= outOfs)
+       return (inOfs - outOfs) / sizeof(RX_ELEMENT);
+    return (NUM_RX_BUF - (outOfs - inOfs) / sizeof(RX_ELEMENT));
+  }
+
+  PUBLIC DWORD PktRxDropped (void)
+  {
+    return _farpeekl (_dos_ds, realBase+pktDrop);
+  }
+
+#elif (DOSX & DOS4GW)
+  PUBLIC int PktReceive (BYTE *buf, int max)
+  {
+    WORD ofs = *(WORD*) (realBase+rxOutOfs);
+
+    if (ofs != *(WORD*) (realBase+rxInOfs))
+    {
+      RX_ELEMENT head;
+      int  size, len = max;
+
+      head.firstCount  = *(WORD*) (realBase+ofs);
+      head.secondCount = *(WORD*) (realBase+ofs+2);
+      head.handle      = *(WORD*) (realBase+ofs+4);
+
+      if (CheckElement(&head))
+      {
+        size = min (head.firstCount, sizeof(RX_ELEMENT));
+        len  = min (size, max);
+        memcpy (buf, (const void*)(realBase+ofs+6), len);
+      }
+      else
+        size = -1;
+
+      ofs += sizeof (RX_ELEMENT);
+      if (ofs > LAST_RX_BUF)
+           *(WORD*) (realBase+rxOutOfs) = FIRST_RX_BUF;
+      else *(WORD*) (realBase+rxOutOfs) = ofs;
+      return (size);
+    }
+    return (0);
+  }
+
+  PUBLIC void PktQueueBusy (BOOL busy)
+  {
+    WORD ofs;
+
+    _disable();
+    ofs = *(WORD*) (realBase+rxInOfs);
+    if (busy)
+       ofs += sizeof (RX_ELEMENT);
+
+    if (ofs > LAST_RX_BUF)
+         *(WORD*) (realBase+rxOutOfs) = FIRST_RX_BUF;
+    else *(WORD*) (realBase+rxOutOfs) = ofs;
+    *(DWORD*) (realBase+pktDrop) = 0UL;
+    _enable();
+  }
+
+  PUBLIC WORD PktBuffersUsed (void)
+  {
+    WORD inOfs, outOfs;
+
+    _disable();
+    inOfs  = *(WORD*) (realBase+rxInOfs);
+    outOfs = *(WORD*) (realBase+rxOutOfs);
+    _enable();
+    if (inOfs >= outOfs)
+       return (inOfs - outOfs) / sizeof(RX_ELEMENT);
+    return (NUM_RX_BUF - (outOfs - inOfs) / sizeof(RX_ELEMENT));
+  }
+
+  PUBLIC DWORD PktRxDropped (void)
+  {
+    return *(DWORD*) (realBase+pktDrop);
+  }
+
+#else     /* real-mode small/large model */
+
+  PUBLIC int PktReceive (BYTE *buf, int max)
+  {
+    if (rxOutOfs != rxInOfs)
+    {
+      RX_ELEMENT far *head = (RX_ELEMENT far*) MK_FP (_DS,rxOutOfs);
+      int  size, len = max;
+
+      if (CheckElement(head))
+      {
+        size = min (head->firstCount, sizeof(RX_ELEMENT));
+        len  = min (size, max);
+        _fmemcpy (buf, &head->destin, len);
+      }
+      else
+        size = -1;
+
+      rxOutOfs += sizeof (RX_ELEMENT);
+      if (rxOutOfs > LAST_RX_BUF)
+          rxOutOfs = FIRST_RX_BUF;
+      return (size);
+    }
+    return (0);
+  }
+
+  PUBLIC void PktQueueBusy (BOOL busy)
+  {
+    rxOutOfs = busy ? (rxInOfs + sizeof(RX_ELEMENT)) : rxInOfs;
+    if (rxOutOfs > LAST_RX_BUF)
+        rxOutOfs = FIRST_RX_BUF;
+    pktDrop = 0L;
+  }
+
+  PUBLIC WORD PktBuffersUsed (void)
+  {
+    WORD inOfs  = rxInOfs;
+    WORD outOfs = rxOutOfs;
+
+    if (inOfs >= outOfs)
+       return ((inOfs - outOfs) / sizeof(RX_ELEMENT));
+    return (NUM_RX_BUF - (outOfs - inOfs) / sizeof(RX_ELEMENT));
+  }
+
+  PUBLIC DWORD PktRxDropped (void)
+  {
+    return (pktDrop);
+  }
+#endif
+
+/**************************************************************************/
+
+LOCAL __inline void PktFreeMem (void)
+{
+#if (DOSX & PHARLAP)
+  if (realSeg)
+  {
+    _dx_real_free (realSeg);
+    realSeg = 0;
+  }
+#elif (DOSX & DJGPP)
+  if (rm_mem.rm_segment)
+  {
+    unsigned ofs;  /* clear the DOS-mem to prevent further upcalls */
+
+    for (ofs = 0; ofs < 16 * rm_mem.size / 4; ofs += 4)
+       _farpokel (_dos_ds, realBase + ofs, 0);
+    _go32_dpmi_free_dos_memory (&rm_mem);
+    rm_mem.rm_segment = 0;
+  }
+#elif (DOSX & DOS4GW)
+  if (rm_base_sel)
+  {
+    dpmi_real_free (rm_base_sel);
+    rm_base_sel = 0;
+  }
+#endif
+}
+
+/**************************************************************************/
+
+PUBLIC BOOL PktExitDriver (void)
+{
+  if (pktInfo.handle)
+  {
+    if (!PktSetReceiverMode(PDRX_BROADCAST))
+       PUTS ("Error restoring receiver mode.");
+
+    if (!PktReleaseHandle(pktInfo.handle))
+       PUTS ("Error releasing PKT-DRVR handle.");
+
+    PktFreeMem();
+    pktInfo.handle = 0;
+  }
+
+  if (pcap_pkt_debug >= 1)
+     printf ("Internal stats: too-small %lu, too-large %lu, bad-sync %lu, "
+             "wrong-handle %lu\n",
+             intStat.tooSmall, intStat.tooLarge,
+             intStat.badSync, intStat.wrongHandle);
+  return (TRUE);
+}
+
+#if (DOSX & (DJGPP|DOS4GW))
+static void dump_pkt_stub (void)
+{
+  int i;
+
+  fprintf (stderr, "PktReceiver %lu, pkt_stub[PktReceiver] =\n",
+           PktReceiver);
+  for (i = 0; i < 15; i++)
+      fprintf (stderr, "%02X, ", real_stub_array[i+PktReceiver]);
+  fputs ("\n", stderr);
+}
+#endif
+
+/*
+ * Front end initialization routine
+ */
+PUBLIC BOOL PktInitDriver (PKT_RX_MODE mode)
+{
+  PKT_RX_MODE rxMode;
+  BOOL   writeInfo = (pcap_pkt_debug >= 3);
+
+  pktInfo.quiet = (pcap_pkt_debug < 3);
+
+#if (DOSX & PHARLAP) && defined(__HIGHC__)
+  if (_mwenv != 2)
+  {
+    fprintf (stderr, "Only Pharlap DOS extender supported.\n");
+    return (FALSE);
+  }
+#endif
+
+#if (DOSX & PHARLAP) && defined(__WATCOMC__)
+  if (_Extender != 1)
+  {
+    fprintf (stderr, "Only DOS4GW style extenders supported.\n");
+    return (FALSE);
+  }
+#endif
+
+  if (!PktSearchDriver())
+  {
+    PUTS ("Packet driver not found.");
+    PktFreeMem();
+    return (FALSE);
+  }
+
+  if (!PktGetDriverInfo())
+  {
+    PUTS ("Error getting pkt-drvr information.");
+    PktFreeMem();
+    return (FALSE);
+  }
+
+#if (DOSX & PHARLAP)
+  if (RealCopy((ULONG)&rxOutOfs, (ULONG)&pktRxEnd,
+               &realBase, &protBase, (USHORT*)&realSeg))
+  {
+    rxOutOfsFp  = (WORD _far *) (protBase + (WORD) &rxOutOfs);
+    rxInOfsFp   = (WORD _far *) (protBase + (WORD) &rxInOfs);
+    *rxOutOfsFp = FIRST_RX_BUF;
+    *rxInOfsFp  = FIRST_RX_BUF;
+  }
+  else
+  {
+    PUTS ("Cannot allocate real-mode stub.");
+    return (FALSE);
+  }
+
+#elif (DOSX & (DJGPP|DOS4GW))
+  if (sizeof(real_stub_array) > 0xFFFF)
+  {
+    fprintf (stderr, "`real_stub_array[]' too big.\n");
+    return (FALSE);
+  }
+#if (DOSX & DJGPP)
+  rm_mem.size = (sizeof(real_stub_array) + 15) / 16;
+
+  if (_go32_dpmi_allocate_dos_memory(&rm_mem) || rm_mem.rm_offset != 0)
+  {
+    PUTS ("real-mode init failed.");
+    return (FALSE);
+  }
+  realBase = (rm_mem.rm_segment << 4);
+  dosmemput (&real_stub_array, sizeof(real_stub_array), realBase);
+  _farpokel (_dos_ds, realBase+rxOutOfs, FIRST_RX_BUF);
+  _farpokel (_dos_ds, realBase+rxInOfs,  FIRST_RX_BUF);
+
+#elif (DOSX & DOS4GW)
+  rm_base_seg = dpmi_real_malloc (sizeof(real_stub_array), &rm_base_sel);
+  if (!rm_base_seg)
+  {
+    PUTS ("real-mode init failed.");
+    return (FALSE);
+  }
+  realBase = (rm_base_seg << 4);
+  memcpy ((void*)realBase, &real_stub_array, sizeof(real_stub_array));
+  *(WORD*) (realBase+rxOutOfs) = FIRST_RX_BUF;
+  *(WORD*) (realBase+rxInOfs)  = FIRST_RX_BUF;
+
+#endif
+  {
+    int pushf = PktReceiver;
+
+    while (real_stub_array[pushf++] != 0x9C &&    /* pushf */
+           real_stub_array[pushf]   != 0xFA)      /* cli   */
+    {
+      if (++para_skip > 16)
+      {
+        fprintf (stderr, "Something wrong with `pkt_stub.inc'.\n");
+        para_skip = 0;
+        dump_pkt_stub();
+        return (FALSE);
+      }
+    }
+    if (*(WORD*)(real_stub_array + offsetof(PktRealStub,_dummy)) != 0xB800)
+    {
+      fprintf (stderr, "`real_stub_array[]' is misaligned.\n");
+      return (FALSE);
+    }
+  }
+
+  if (pcap_pkt_debug > 2)
+      dump_pkt_stub();
+
+#else
+  rxOutOfs = FIRST_RX_BUF;
+  rxInOfs  = FIRST_RX_BUF;
+#endif
+
+  if (!PktSetAccess())
+  {
+    PUTS ("Error setting pkt-drvr access.");
+    PktFreeMem();
+    return (FALSE);
+  }
+
+  if (!PktGetAddress(&myAddress))
+  {
+    PUTS ("Error fetching adapter address.");
+    PktFreeMem();
+    return (FALSE);
+  }
+
+  if (!PktSetReceiverMode(mode))
+  {
+    PUTS ("Error setting receiver mode.");
+    PktFreeMem();
+    return (FALSE);
+  }
+
+  if (!PktGetReceiverMode(&rxMode))
+  {
+    PUTS ("Error getting receiver mode.");
+    PktFreeMem();
+    return (FALSE);
+  }
+
+  if (writeInfo)
+     printf ("Pkt-driver information:\n"
+             "  Version  : %d.%d\n"
+             "  Name     : %.15s\n"
+             "  Class    : %u (%s)\n"
+             "  Type     : %u\n"
+             "  Number   : %u\n"
+             "  Funcs    : %u\n"
+             "  Intr     : %Xh\n"
+             "  Handle   : %u\n"
+             "  Extended : %s\n"
+             "  Hi-perf  : %s\n"
+             "  RX mode  : %s\n"
+             "  Eth-addr : %02X:%02X:%02X:%02X:%02X:%02X\n",
+
+             pktInfo.majVer, pktInfo.minVer, pktInfo.name,
+             pktInfo.class,  PktGetClassName(pktInfo.class),
+             pktInfo.type,   pktInfo.number,
+             pktInfo.funcs,  pktInfo.intr,   pktInfo.handle,
+             pktInfo.funcs == 2 || pktInfo.funcs == 6 ? "Yes" : "No",
+             pktInfo.funcs == 5 || pktInfo.funcs == 6 ? "Yes" : "No",
+             PktRXmodeStr(rxMode),
+             myAddress[0], myAddress[1], myAddress[2],
+             myAddress[3], myAddress[4], myAddress[5]);
+
+#if defined(DEBUG) && (DOSX & PHARLAP)
+  if (writeInfo)
+  {
+    DWORD    rAdr = realBase + (WORD)&PktReceiver;
+    unsigned sel, ofs;
+
+    printf ("\nReceiver at   %04X:%04X\n", RP_SEG(rAdr),    RP_OFF(rAdr));
+    printf ("Realbase    = %04X:%04X\n",   RP_SEG(realBase),RP_OFF(realBase));
+
+    sel = _FP_SEG (protBase);
+    ofs = _FP_OFF (protBase);
+    printf ("Protbase    = %04X:%08X\n", sel,ofs);
+    printf ("RealSeg     = %04X\n", realSeg);
+
+    sel = _FP_SEG (rxOutOfsFp);
+    ofs = _FP_OFF (rxOutOfsFp);
+    printf ("rxOutOfsFp  = %04X:%08X\n", sel,ofs);
+
+    sel = _FP_SEG (rxInOfsFp);
+    ofs = _FP_OFF (rxInOfsFp);
+    printf ("rxInOfsFp   = %04X:%08X\n", sel,ofs);
+
+    printf ("Ready: *rxOutOfsFp = %04X *rxInOfsFp = %04X\n",
+            *rxOutOfsFp, *rxInOfsFp);
+
+    PktQueueBusy (TRUE);
+    printf ("Busy:  *rxOutOfsFp = %04X *rxInOfsFp = %04X\n",
+            *rxOutOfsFp, *rxInOfsFp);
+  }
+#endif
+
+  memset (&pktStat, 0, sizeof(pktStat));  /* clear statistics */
+  PktQueueBusy (TRUE);
+  return (TRUE);
+}
+
+
+/*
+ * DPMI functions only for Watcom + DOS4GW extenders
+ */
+#if (DOSX & DOS4GW)
+LOCAL DWORD dpmi_get_real_vector (int intr)
+{
+  union REGS r;
+
+  r.x.eax = 0x200;
+  r.x.ebx = (DWORD) intr;
+  int386 (0x31, &r, &r);
+  return ((r.w.cx << 4) + r.w.dx);
+}
+
+LOCAL WORD dpmi_real_malloc (int size, WORD *selector)
+{
+  union REGS r;
+
+  r.x.eax = 0x0100;             /* DPMI allocate DOS memory */
+  r.x.ebx = (size + 15) / 16;   /* Number of paragraphs requested */
+  int386 (0x31, &r, &r);
+  if (r.w.cflag & 1)
+     return (0);
+
+  *selector = r.w.dx;
+  return (r.w.ax);              /* Return segment address */
+}
+
+LOCAL void dpmi_real_free (WORD selector)
+{
+  union REGS r;
+
+  r.x.eax = 0x101;              /* DPMI free DOS memory */
+  r.x.ebx = selector;           /* Selector to free */
+  int386 (0x31, &r, &r);
+}
+#endif
+
+
+#if defined(DOSX) && (DOSX & PHARLAP)
+/*
+ * Description:
+ *     This routine allocates conventional memory for the specified block
+ *     of code (which must be within the first 64K of the protected mode
+ *     program segment) and copies the code to it.
+ *
+ *     The caller should free up the conventional memory block when it
+ *     is done with the conventional memory.
+ *
+ *     NOTE THIS ROUTINE REQUIRES 386|DOS-EXTENDER 3.0 OR LATER.
+ *
+ * Calling arguments:
+ *     start_offs      start of real mode code in program segment
+ *     end_offs        1 byte past end of real mode code in program segment
+ *     real_basep      returned;  real mode ptr to use as a base for the
+ *                        real mode code (eg, to get the real mode FAR
+ *                        addr of a function foo(), take
+ *                        real_basep + (ULONG) foo).
+ *                        This pointer is constructed such that
+ *                        offsets within the real mode segment are
+ *                        the same as the link-time offsets in the
+ *                        protected mode program segment
+ *     prot_basep      returned;  prot mode ptr to use as a base for getting
+ *                        to the conventional memory, also constructed
+ *                        so that adding the prot mode offset of a
+ *                        function or variable to the base gets you a
+ *                        ptr to the function or variable in the
+ *                        conventional memory block.
+ *     rmem_adrp       returned;  real mode para addr of allocated
+ *                        conventional memory block, to be used to free
+ *                        up the conventional memory when done.  DO NOT
+ *                        USE THIS TO CONSTRUCT A REAL MODE PTR, USE
+ *                        REAL_BASEP INSTEAD SO THAT OFFSETS WORK OUT
+ *                        CORRECTLY.
+ *
+ * Returned values:
+ *     0      if error
+ *     1      if success
+ */
+int RealCopy (ULONG    start_offs,
+              ULONG    end_offs,
+              REALPTR *real_basep,
+              FARPTR  *prot_basep,
+              USHORT  *rmem_adrp)
+{
+  ULONG   rm_base;    /* base real mode para addr for accessing */
+                      /* allocated conventional memory          */
+  UCHAR  *source;     /* source pointer for copy                */
+  FARPTR  destin;     /* destination pointer for copy           */
+  ULONG   len;        /* number of bytes to copy                */
+  ULONG   temp;
+  USHORT  stemp;
+
+  /* First check for valid inputs
+   */
+  if (start_offs >= end_offs || end_offs > 0x10000)
+     return (FALSE);
+
+  /* Round start_offs down to a paragraph (16-byte) boundary so we can set up
+   * the real mode pointer easily. Round up end_offs to make sure we allocate
+   * enough paragraphs
+   */
+  start_offs &= ~15;
+  end_offs = (15 + (end_offs << 4)) >> 4;
+
+  /* Allocate the conventional memory for our real mode code.  Remember to
+   * round byte count UP to 16-byte paragraph size.  We alloc it
+   * above the DOS data buffer so both the DOS data buffer and the appl
+   * conventional mem block can still be resized.
+   *
+   * First just try to alloc it;  if we can't get it, shrink the appl mem
+   * block down to the minimum, try to alloc the memory again, then grow the
+   * appl mem block back to the maximum.  (Don't try to shrink the DOS data
+   * buffer to free conventional memory;  it wouldn't be good for this routine
+   * to have the possible side effect of making file I/O run slower.)
+   */
+  len = ((end_offs - start_offs) + 15) >> 4;
+  if (_dx_real_above(len, rmem_adrp, &stemp) != _DOSE_NONE)
+  {
+    if (_dx_cmem_usage(0, 0, &temp, &temp) != _DOSE_NONE)
+       return (FALSE);
+
+    if (_dx_real_above(len, rmem_adrp, &stemp) != _DOSE_NONE)
+       *rmem_adrp = 0;
+
+    if (_dx_cmem_usage(0, 1, &temp, &temp) != _DOSE_NONE)
+    {
+      if (*rmem_adrp != 0)
+         _dx_real_free (*rmem_adrp);
+      return (FALSE);
+    }
+
+    if (*rmem_adrp == 0)
+       return (FALSE);
+  }
+
+  /* Construct real mode & protected mode pointers to access the allocated
+   * memory.  Note we know start_offs is aligned on a paragraph (16-byte)
+   * boundary, because we rounded it down.
+   *
+   * We make the offsets come out rights by backing off the real mode selector
+   * by start_offs.
+   */
+  rm_base = ((ULONG) *rmem_adrp) - (start_offs >> 4);
+  RP_SET (*real_basep, 0, rm_base);
+  FP_SET (*prot_basep, rm_base << 4, SS_DOSMEM);
+
+  /* Copy the real mode code/data to the allocated memory
+   */
+  source = (UCHAR *) start_offs;
+  destin = *prot_basep;
+  FP_SET (destin, FP_OFF(*prot_basep) + start_offs, FP_SEL(*prot_basep));
+  len = end_offs - start_offs;
+  WriteFarMem (destin, source, len);
+
+  return (TRUE);
+}
+#endif /* DOSX && (DOSX & PHARLAP) */
index 08898ae..3e0cfe0 100644 (file)
-#ifndef __PKTDRVR_H\r
-#define __PKTDRVR_H\r
-\r
-#define PUBLIC\r
-#define LOCAL        static\r
-\r
-#define RX_BUF_SIZE  ETH_MTU   /* buffer size variables. NB !! */\r
-#define TX_BUF_SIZE  ETH_MTU   /* must be same as in pkt_rx*.* */\r
-\r
-#ifdef __HIGHC__\r
-#pragma Off(Align_members)\r
-#else\r
-#pragma pack(1)\r
-#endif\r
-\r
-typedef enum  {                /* Packet-driver classes */\r
-        PD_ETHER      = 1,\r
-        PD_PRONET10   = 2,\r
-        PD_IEEE8025   = 3,\r
-        PD_OMNINET    = 4,\r
-        PD_APPLETALK  = 5,\r
-        PD_SLIP       = 6,\r
-        PD_STARTLAN   = 7,\r
-        PD_ARCNET     = 8,\r
-        PD_AX25       = 9,\r
-        PD_KISS       = 10,\r
-        PD_IEEE8023_2 = 11,\r
-        PD_FDDI8022   = 12,\r
-        PD_X25        = 13,\r
-        PD_LANstar    = 14,\r
-        PD_PPP        = 18\r
-      } PKT_CLASS;\r
-\r
-typedef enum  {             /* Packet-driver receive modes    */\r
-        PDRX_OFF    = 1,    /* turn off receiver              */\r
-        PDRX_DIRECT,        /* receive only to this interface */\r
-        PDRX_BROADCAST,     /* DIRECT + broadcast packets     */\r
-        PDRX_MULTICAST1,    /* BROADCAST + limited multicast  */\r
-        PDRX_MULTICAST2,    /* BROADCAST + all multicast      */\r
-        PDRX_ALL_PACKETS,   /* receive all packets on network */\r
-      } PKT_RX_MODE;\r
-\r
-typedef struct {\r
-        char type[8];\r
-        char len;\r
-      } PKT_FRAME;\r
-\r
-\r
-typedef struct {\r
-        BYTE  class;        /* = 1 for DEC/Interl/Xerox Ethernet */\r
-        BYTE  number;       /* = 0 for single LAN adapter        */\r
-        WORD  type;         /* = 13 for 3C523                    */\r
-        BYTE  funcs;        /* Basic/Extended/HiPerf functions   */\r
-        WORD  intr;         /* user interrupt vector number      */\r
-        WORD  handle;       /* Handle associated with session    */\r
-        BYTE  name [15];    /* Name of adapter interface,ie.3C523*/\r
-        BOOL  quiet;        /* (don't) print errors to stdout    */\r
-        const char *error;  /* address of error string           */\r
-        BYTE  majVer;       /* Major driver implementation ver.  */\r
-        BYTE  minVer;       /* Minor driver implementation ver.  */\r
-        BYTE  dummyLen;     /* length of following data          */\r
-        WORD  MAClength;    /* HiPerformance data, N/A           */\r
-        WORD  MTU;          /* HiPerformance data, N/A           */\r
-        WORD  multicast;    /* HiPerformance data, N/A           */\r
-        WORD  rcvrBuffers;  /* valid for                         */\r
-        WORD  UMTbufs;      /*   High Performance drivers only   */\r
-        WORD  postEOIintr;  /*                  Usage ??         */\r
-      } PKT_INFO;\r
-\r
-#define PKT_PARAM_SIZE  14    /* members majVer - postEOIintr */\r
-\r
-\r
-typedef struct {\r
-        DWORD inPackets;          /* # of packets received    */\r
-        DWORD outPackets;         /* # of packets transmitted */\r
-        DWORD inBytes;            /* # of bytes received      */\r
-        DWORD outBytes;           /* # of bytes transmitted   */\r
-        DWORD inErrors;           /* # of reception errors    */\r
-        DWORD outErrors;          /* # of transmission errors */\r
-        DWORD lost;               /* # of packets lost (RX)   */\r
-      } PKT_STAT;\r
-                   \r
-\r
-typedef struct {\r
-        ETHER destin;\r
-        ETHER source;\r
-        WORD  proto;\r
-        BYTE  data [TX_BUF_SIZE];\r
-      } TX_ELEMENT;\r
-\r
-typedef struct {\r
-        WORD  firstCount;         /* # of bytes on 1st         */\r
-        WORD  secondCount;        /* and 2nd upcall            */\r
-        WORD  handle;             /* instance that upcalled    */\r
-        ETHER destin;             /* E-net destination address */\r
-        ETHER source;             /* E-net source address      */\r
-        WORD  proto;              /* protocol number           */\r
-        BYTE  data [RX_BUF_SIZE];\r
-      } RX_ELEMENT;\r
-\r
-\r
-#ifdef __HIGHC__\r
-#pragma pop(Align_members)\r
-#else\r
-#pragma pack()\r
-#endif\r
-\r
-\r
-/*\r
- * Prototypes for publics\r
- */\r
-\r
-#ifdef __cplusplus\r
-extern "C" {\r
-#endif\r
-\r
-extern PKT_STAT    pktStat;     /* statistics for packets */\r
-extern PKT_INFO    pktInfo;     /* packet-driver information */\r
-\r
-extern PKT_RX_MODE receiveMode;\r
-extern ETHER       myAddress, ethBroadcast;\r
-\r
-extern BOOL  PktInitDriver (PKT_RX_MODE mode);\r
-extern BOOL  PktExitDriver (void);\r
-\r
-extern const char *PktGetErrorStr    (int errNum);\r
-extern const char *PktGetClassName   (WORD class);\r
-extern const char *PktRXmodeStr      (PKT_RX_MODE mode);\r
-extern BOOL        PktSearchDriver   (void);\r
-extern int         PktReceive        (BYTE *buf, int max);\r
-extern BOOL        PktTransmit       (const void *eth, int len);\r
-extern DWORD       PktRxDropped      (void);\r
-extern BOOL        PktReleaseHandle  (WORD handle);\r
-extern BOOL        PktTerminHandle   (WORD handle);\r
-extern BOOL        PktResetInterface (WORD handle);\r
-extern BOOL        PktSetReceiverMode(PKT_RX_MODE  mode);\r
-extern BOOL        PktGetReceiverMode(PKT_RX_MODE *mode);\r
-extern BOOL        PktGetStatistics  (WORD handle);\r
-extern BOOL        PktSessStatistics (WORD handle);\r
-extern BOOL        PktResetStatistics(WORD handle);\r
-extern BOOL        PktGetAddress     (ETHER *addr);\r
-extern BOOL        PktSetAddress     (const ETHER *addr);\r
-extern BOOL        PktGetDriverInfo  (void);\r
-extern BOOL        PktGetDriverParam (void);\r
-extern void        PktQueueBusy      (BOOL busy);\r
-extern WORD        PktBuffersUsed    (void);\r
-\r
-#ifdef __cplusplus\r
-}\r
-#endif\r
-\r
-#endif /* __PKTDRVR_H */\r
-\r
+#ifndef __PKTDRVR_H
+#define __PKTDRVR_H
+
+#define PUBLIC
+#define LOCAL        static
+
+#define RX_BUF_SIZE  ETH_MTU   /* buffer size variables. NB !! */
+#define TX_BUF_SIZE  ETH_MTU   /* must be same as in pkt_rx*.* */
+
+#ifdef __HIGHC__
+#pragma Off(Align_members)
+#else
+#pragma pack(1)
+#endif
+
+typedef enum  {                /* Packet-driver classes */
+        PD_ETHER      = 1,
+        PD_PRONET10   = 2,
+        PD_IEEE8025   = 3,
+        PD_OMNINET    = 4,
+        PD_APPLETALK  = 5,
+        PD_SLIP       = 6,
+        PD_STARTLAN   = 7,
+        PD_ARCNET     = 8,
+        PD_AX25       = 9,
+        PD_KISS       = 10,
+        PD_IEEE8023_2 = 11,
+        PD_FDDI8022   = 12,
+        PD_X25        = 13,
+        PD_LANstar    = 14,
+        PD_PPP        = 18
+      } PKT_CLASS;
+
+typedef enum  {             /* Packet-driver receive modes    */
+        PDRX_OFF    = 1,    /* turn off receiver              */
+        PDRX_DIRECT,        /* receive only to this interface */
+        PDRX_BROADCAST,     /* DIRECT + broadcast packets     */
+        PDRX_MULTICAST1,    /* BROADCAST + limited multicast  */
+        PDRX_MULTICAST2,    /* BROADCAST + all multicast      */
+        PDRX_ALL_PACKETS,   /* receive all packets on network */
+      } PKT_RX_MODE;
+
+typedef struct {
+        char type[8];
+        char len;
+      } PKT_FRAME;
+
+
+typedef struct {
+        BYTE  class;        /* = 1 for DEC/Interl/Xerox Ethernet */
+        BYTE  number;       /* = 0 for single LAN adapter        */
+        WORD  type;         /* = 13 for 3C523                    */
+        BYTE  funcs;        /* Basic/Extended/HiPerf functions   */
+        WORD  intr;         /* user interrupt vector number      */
+        WORD  handle;       /* Handle associated with session    */
+        BYTE  name [15];    /* Name of adapter interface,ie.3C523*/
+        BOOL  quiet;        /* (don't) print errors to stdout    */
+        const char *error;  /* address of error string           */
+        BYTE  majVer;       /* Major driver implementation ver.  */
+        BYTE  minVer;       /* Minor driver implementation ver.  */
+        BYTE  dummyLen;     /* length of following data          */
+        WORD  MAClength;    /* HiPerformance data, N/A           */
+        WORD  MTU;          /* HiPerformance data, N/A           */
+        WORD  multicast;    /* HiPerformance data, N/A           */
+        WORD  rcvrBuffers;  /* valid for                         */
+        WORD  UMTbufs;      /*   High Performance drivers only   */
+        WORD  postEOIintr;  /*                  Usage ??         */
+      } PKT_INFO;
+
+#define PKT_PARAM_SIZE  14    /* members majVer - postEOIintr */
+
+
+typedef struct {
+        DWORD inPackets;          /* # of packets received    */
+        DWORD outPackets;         /* # of packets transmitted */
+        DWORD inBytes;            /* # of bytes received      */
+        DWORD outBytes;           /* # of bytes transmitted   */
+        DWORD inErrors;           /* # of reception errors    */
+        DWORD outErrors;          /* # of transmission errors */
+        DWORD lost;               /* # of packets lost (RX)   */
+      } PKT_STAT;
+
+
+typedef struct {
+        ETHER destin;
+        ETHER source;
+        WORD  proto;
+        BYTE  data [TX_BUF_SIZE];
+      } TX_ELEMENT;
+
+typedef struct {
+        WORD  firstCount;         /* # of bytes on 1st         */
+        WORD  secondCount;        /* and 2nd upcall            */
+        WORD  handle;             /* instance that upcalled    */
+        ETHER destin;             /* E-net destination address */
+        ETHER source;             /* E-net source address      */
+        WORD  proto;              /* protocol number           */
+        BYTE  data [RX_BUF_SIZE];
+      } RX_ELEMENT;
+
+
+#ifdef __HIGHC__
+#pragma pop(Align_members)
+#else
+#pragma pack()
+#endif
+
+
+/*
+ * Prototypes for publics
+ */
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+extern PKT_STAT    pktStat;     /* statistics for packets */
+extern PKT_INFO    pktInfo;     /* packet-driver information */
+
+extern PKT_RX_MODE receiveMode;
+extern ETHER       myAddress, ethBroadcast;
+
+extern BOOL  PktInitDriver (PKT_RX_MODE mode);
+extern BOOL  PktExitDriver (void);
+
+extern const char *PktGetErrorStr    (int errNum);
+extern const char *PktGetClassName   (WORD class);
+extern const char *PktRXmodeStr      (PKT_RX_MODE mode);
+extern BOOL        PktSearchDriver   (void);
+extern int         PktReceive        (BYTE *buf, int max);
+extern BOOL        PktTransmit       (const void *eth, int len);
+extern DWORD       PktRxDropped      (void);
+extern BOOL        PktReleaseHandle  (WORD handle);
+extern BOOL        PktTerminHandle   (WORD handle);
+extern BOOL        PktResetInterface (WORD handle);
+extern BOOL        PktSetReceiverMode(PKT_RX_MODE  mode);
+extern BOOL        PktGetReceiverMode(PKT_RX_MODE *mode);
+extern BOOL        PktGetStatistics  (WORD handle);
+extern BOOL        PktSessStatistics (WORD handle);
+extern BOOL        PktResetStatistics(WORD handle);
+extern BOOL        PktGetAddress     (ETHER *addr);
+extern BOOL        PktSetAddress     (const ETHER *addr);
+extern BOOL        PktGetDriverInfo  (void);
+extern BOOL        PktGetDriverParam (void);
+extern void        PktQueueBusy      (BOOL busy);
+extern WORD        PktBuffersUsed    (void);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __PKTDRVR_H */
+
index 913c4e6..b95483f 100644 (file)
@@ -10,19 +10,21 @@ supported:
  - GNU C 2.7+ with djgpp 2.01+ DOS extender
  - Watcom C 11.x with DOS4GW extender
 
-Note: the files in the libpcap.zip contains short trucated filenames.
+Note: the files in the libpcap.zip contains short truncated filenames.
   So for djgpp to work with these, disable the use of long file names by
-  setting "LFN=n" in the environment.
+  setting "LFN=n" in the environment. On the other hand, if you get libpcap
+  from Github or the official libpcap.tar.gz, some filenames are beyond 8+3.
+  In this case set "LFN=y".
 
 Files specific to DOS are pcap-dos.[ch] and the assembly and C files in
-the MSDOS sub-directory. Remember to built lipcap libraries from the top
+the MSDOS sub-directory. Remember to built the libpcap library from the top
 install directory. And not from the MSDOS sub-directory.
 
 Note for djgpp users:
   If you got the libpcap from the official site www.tcpdump, then that
   distribution does NOT contain any sources for building 32-bit drivers.
   Instead get the full version at
-     http://www.bgnett.no/~giva/pcap/libpcap.zip
+     http://www.watt-32.net/pcap/libpcap.zip
 
   and set "USE_32BIT_DRIVERS = 1" in msdos\common.dj.
 
@@ -49,30 +51,28 @@ The following packages and tools must be present for all targets.
    receive network data. It's mostly used to access the 'hosts'
    file and other <netdb.h> features. Get 'watt32s*.zip' at:
 
-     http://www.bgnett.no/~giva/
+     http://www.watt-32.net
 
 2. Exception handler and disassember library (libexc.a) is needed if
    "USE_EXCEPT = 1" in common.dj. Available at:
 
-     http://www.bgnett.no/~giva/misc/exc_dx07.zip
+     http://www.watt-32.net/misc/exc_dx07.zip
 
 3. Flex & Bison is used to generate parser for the filter handler
    pcap_compile:
-
-     ftp://ftp.simtel.net/pub/simtelnet/gnu/djgpp/v2gnu/flx254b.zip
-     ftp://ftp.simtel.net/pub/simtelnet/gnu/djgpp/v2gnu/bsn128b.zip
+     ftp://ftp.delorie.com/pub/djgpp/current/v2gnu/flx254b.zip
+     ftp://ftp.delorie.com/pub/djgpp/current/v2gnu/bsn241b.zip
 
 4. NASM assembler v 0.98 or later is required when building djgpp and
    Watcom targets:
-
-     ftp://ftp.simtel.net/pub/simtelnet/gnu/djgpp/v2tk/nasm098p.zip
+     http://www.nasm.us/
 
 5. sed (Stream Editor) is required for doing `make depend'.
-   It's available at
-     ftp://ftp.simtel.net/pub/simtelnet/gnu/djgpp/v2gnu/sed*.zip
+   It's available at:
+     ftp://ftp.delorie.com/pub/djgpp/current/v2gnu/sed422b.zip
 
-   A touch tool to update the time-stamp of a file. E.g.
-     ftp://ftp.simtel.net/pub/simtelnet/gnu/djgpp/v2gnu/grep*.zip
+   A touch tool to update the time-stamp of a file. E.g.:
+     ftp://ftp.delorie.com/pub/djgpp/current/v2gnu/grep29b.zip
 
 6. For djgpp rm.exe and cp.exe are required. These should already be
    part of your djgpp installation. Also required (experimental at the
@@ -121,10 +121,17 @@ Follow these steps in building libpcap:
 
    Note: Code in `USE_NDIS2' does not work at the moment.
 
-4. The resulting libraries are put in current directory. There's no
-   test-program for `libpcap'. Linking the library with `tcpdump' is
-   the ultimate test anyway.
+4. The resulting library is put in current directory. There's some
+   test-program for `libpcap': `filtertest.exe', `findalldevstest.exe',
+     `nonblocktest.exe' and `opentest.exe'.
+
+   But linking the library with `tcpdump' is the ultimate test. DOS/djgpp
+   should now hopefully be a supported target. Get the sources at:
+     https://www.tcpdump.org/
+   or
+     https://github.com/the-tcpdump-group/tcpdump/
 
+   (click on the 'Download ZIP' on the right side of that page.)
 
 
 Extensions to libpcap
@@ -132,14 +139,14 @@ Extensions to libpcap
 
 I've included some extra functions to DOS-libpcap:
 
-  `pcap_config_hook (const char *name, const char *value)' 
+  `pcap_config_hook (const char *keyword, const char *value)' :
 
     Allows an application to set values of internal libpcap variables.
-    `name' is typically a left-side keyword with an associated `value'
-    that is called from application's configure process (see tcpdump's
-    config.c file). libpcap keeps a set of tables that are searched for
-    a name/value match. Currently only used to set debug-levels and
-    parameters for the 32-bit network drivers.
+    `keyword' and an associated `value' should be present in the `debug_tab[]'
+    array in pcap-dos.c (currently only used to set debug-levels and parameters
+    for the 32-bit network drivers.) Thus an application using DOS-libpcap can
+    override the default value during it's configure process (see tcpdump's
+    msdos/config.c file for an extended example).
 
   `pcap_set_wait (pcap_t *, void (*)(void), int)' :
 
@@ -153,8 +160,7 @@ I've included some extra functions to DOS-libpcap:
 Happy sniffing !
 
 
-Gisle Vanem <giva@bgnett.no>
-            <gvanem@broadpark.no>
+Gisle Vanem <gvanem@yahoo.no>
 
-October 1999, 2004
+October 1999, 2004, 2006, 2013
 
index e6483a3..7c48bd3 100644 (file)
@@ -23,7 +23,7 @@
  */
 
 #ifdef HAVE_CONFIG_H
-#include "config.h"
+#include <config.h>
 #endif
 
 #ifdef DECNETLIB
 #include <netdnet/dnetdb.h>
 #endif
 
-#ifdef WIN32
-#include <pcap-stdinc.h>
-
-#else /* WIN32 */
-
-#include <sys/param.h>
-#include <sys/types.h>                         /* concession to AIX */
-#include <sys/socket.h>
-#include <sys/time.h>
-
-#include <netinet/in.h>
-#endif /* WIN32 */
-
-#ifndef WIN32
-#ifdef HAVE_ETHER_HOSTTON
-/*
- * XXX - do we need any of this if <netinet/if_ether.h> doesn't declare
- * ether_hostton()?
- */
-#ifdef HAVE_NETINET_IF_ETHER_H
-struct mbuf;           /* Squelch compiler warnings on some platforms for */
-struct rtentry;                /* declarations in <net/if.h> */
-#include <net/if.h>    /* for "struct ifnet" in "struct arpcom" on Solaris */
-#include <netinet/if_ether.h>
-#endif /* HAVE_NETINET_IF_ETHER_H */
-#ifdef NETINET_ETHER_H_DECLARES_ETHER_HOSTTON
-#include <netinet/ether.h>
-#endif /* NETINET_ETHER_H_DECLARES_ETHER_HOSTTON */
-#endif /* HAVE_ETHER_HOSTTON */
-#include <arpa/inet.h>
-#include <netdb.h>
-#endif /* WIN32 */
+#ifdef _WIN32
+  #include <winsock2.h>
+  #include <ws2tcpip.h>
+
+  #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.
+     */
+    #include <wspiapi.h>
+  #endif /* INET6 */
+#else /* _WIN32 */
+  #include <sys/param.h>
+  #include <sys/types.h>
+  #include <sys/socket.h>
+  #include <sys/time.h>
+
+  #include <netinet/in.h>
+
+  #ifdef HAVE_ETHER_HOSTTON
+    #if defined(NET_ETHERNET_H_DECLARES_ETHER_HOSTTON)
+      /*
+       * OK, just include <net/ethernet.h>.
+       */
+      #include <net/ethernet.h>
+    #elif defined(NETINET_ETHER_H_DECLARES_ETHER_HOSTTON)
+      /*
+       * OK, just include <netinet/ether.h>
+       */
+      #include <netinet/ether.h>
+    #elif defined(SYS_ETHERNET_H_DECLARES_ETHER_HOSTTON)
+      /*
+       * OK, just include <sys/ethernet.h>
+       */
+      #include <sys/ethernet.h>
+    #elif defined(ARPA_INET_H_DECLARES_ETHER_HOSTTON)
+      /*
+       * OK, just include <arpa/inet.h>
+       */
+      #include <arpa/inet.h>
+    #elif defined(NETINET_IF_ETHER_H_DECLARES_ETHER_HOSTTON)
+      /*
+       * OK, include <netinet/if_ether.h>, after all the other stuff we
+       * need to include or define for its benefit.
+       */
+      #define NEED_NETINET_IF_ETHER_H
+    #else
+      /*
+       * We'll have to declare it ourselves.
+       * If <netinet/if_ether.h> defines struct ether_addr, include
+       * it.  Otherwise, define it ourselves.
+       */
+      #ifdef HAVE_STRUCT_ETHER_ADDR
+        #define NEED_NETINET_IF_ETHER_H
+      #else /* HAVE_STRUCT_ETHER_ADDR */
+       struct ether_addr {
+               unsigned char ether_addr_octet[6];
+       };
+      #endif /* HAVE_STRUCT_ETHER_ADDR */
+    #endif /* what declares ether_hostton() */
+
+    #ifdef NEED_NETINET_IF_ETHER_H
+      #include <net/if.h>      /* Needed on some platforms */
+      #include <netinet/in.h>  /* Needed on some platforms */
+      #include <netinet/if_ether.h>
+    #endif /* NEED_NETINET_IF_ETHER_H */
+
+    #ifndef HAVE_DECL_ETHER_HOSTTON
+      /*
+       * No header declares it, so declare it ourselves.
+       */
+      extern int ether_hostton(const char *, struct ether_addr *);
+    #endif /* !defined(HAVE_DECL_ETHER_HOSTTON) */
+  #endif /* HAVE_ETHER_HOSTTON */
+
+  #include <arpa/inet.h>
+  #include <netdb.h>
+#endif /* _WIN32 */
 
 #include <ctype.h>
 #include <errno.h>
@@ -74,6 +137,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"
@@ -84,11 +148,10 @@ struct rtentry;            /* declarations in <net/if.h> */
 #define NTOHS(x) (x) = ntohs(x)
 #endif
 
-static inline int xdtoi(int);
-
 /*
  *  Convert host name to internet address.
  *  Return 0 upon failure.
+ *  XXX - not thread-safe; don't use it inside libpcap.
  */
 bpf_u_int32 **
 pcap_nametoaddr(const char *name)
@@ -114,7 +177,6 @@ pcap_nametoaddr(const char *name)
                return 0;
 }
 
-#ifdef INET6
 struct addrinfo *
 pcap_nametoaddrinfo(const char *name)
 {
@@ -131,28 +193,105 @@ pcap_nametoaddrinfo(const char *name)
        else
                return res;
 }
-#endif /*INET6*/
 
 /*
  *  Convert net name to internet address.
  *  Return 0 upon failure.
+ *  XXX - not guaranteed to be thread-safe!  See below for platforms
+ *  on which it is thread-safe and on which it isn't.
  */
 bpf_u_int32
 pcap_nametonetaddr(const char *name)
 {
-#ifndef WIN32
+#ifdef _WIN32
+       /*
+        * 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;
+#else
+       /*
+        * UN*X.
+        */
        struct netent *np;
+  #if defined(HAVE_LINUX_GETNETBYNAME_R)
+       /*
+        * We have Linux's reentrant getnetbyname_r().
+        */
+       struct netent result_buf;
+       char buf[1024]; /* arbitrary size */
+       int h_errnoval;
+       int err;
 
-       if ((np = getnetbyname(name)) != NULL)
-               return np->n_net;
-       else
+       /*
+        * Apparently, the man page at
+        *
+        *    http://man7.org/linux/man-pages/man3/getnetbyname_r.3.html
+        *
+        * lies when it says
+        *
+        *    If the function call successfully obtains a network record,
+        *    then *result is set pointing to result_buf; otherwise, *result
+        *    is set to NULL.
+        *
+        * and, in fact, at least in some versions of GNU libc, it does
+        * *not* always get set if getnetbyname_r() succeeds.
+        */
+       np = NULL;
+       err = getnetbyname_r(name, &result_buf, buf, sizeof buf, &np,
+           &h_errnoval);
+       if (err != 0) {
+               /*
+                * XXX - dynamically allocate the buffer, and make it
+                * bigger if we get ERANGE back?
+                */
                return 0;
-#else
+       }
+  #elif defined(HAVE_SOLARIS_IRIX_GETNETBYNAME_R)
        /*
-        * There's no "getnetbyname()" on Windows.
+        * We have Solaris's and IRIX's reentrant getnetbyname_r().
         */
-       return 0;
-#endif
+       struct netent result_buf;
+       char buf[1024]; /* arbitrary size */
+
+       np = getnetbyname_r(name, &result_buf, buf, (int)sizeof buf);
+  #elif defined(HAVE_AIX_GETNETBYNAME_R)
+       /*
+        * We have AIX's reentrant getnetbyname_r().
+        */
+       struct netent result_buf;
+       struct netent_data net_data;
+
+       if (getnetbyname_r(name, &result_buf, &net_data) == -1)
+               np = NULL;
+       else
+               np = &result_buf;
+  #else
+       /*
+        * We don't have any getnetbyname_r(); either we have a
+        * getnetbyname() that uses thread-specific data, in which
+        * case we're thread-safe (sufficiently recent FreeBSD,
+        * sufficiently recent Darwin-based OS, sufficiently recent
+        * HP-UX, sufficiently recent Tru64 UNIX), or we have the
+        * traditional getnetbyname() (everything else, including
+        * current NetBSD and OpenBSD), in which case we're not
+        * thread-safe.
+        */
+       np = getnetbyname(name);
+  #endif
+       if (np != NULL)
+               return np->n_net;
+       else
+               return 0;
+#endif /* _WIN32 */
 }
 
 /*
@@ -163,20 +302,113 @@ pcap_nametonetaddr(const char *name)
 int
 pcap_nametoport(const char *name, int *port, int *proto)
 {
-       struct servent *sp;
+       struct addrinfo hints, *res, *ai;
+       int error;
+       struct sockaddr_in *in4;
+#ifdef INET6
+       struct sockaddr_in6 *in6;
+#endif
        int tcp_port = -1;
        int udp_port = -1;
 
        /*
+        * We check for both TCP and UDP in case there are
+        * ambiguous entries.
+        */
+       memset(&hints, 0, sizeof(hints));
+       hints.ai_family = PF_UNSPEC;
+       hints.ai_socktype = SOCK_STREAM;
+       hints.ai_protocol = IPPROTO_TCP;
+       error = getaddrinfo(NULL, name, &hints, &res);
+       if (error != 0) {
+               if (error != EAI_NONAME &&
+                   error != EAI_SERVICE) {
+                       /*
+                        * This is a real error, not just "there's
+                        * no such service name".
+                        * XXX - this doesn't return an error string.
+                        */
+                       return 0;
+               }
+       } else {
+               /*
+                * OK, we found it.  Did it find anything?
+                */
+               for (ai = res; ai != NULL; ai = ai->ai_next) {
+                       /*
+                        * Does it have an address?
+                        */
+                       if (ai->ai_addr != NULL) {
+                               /*
+                                * Yes.  Get a port number; we're done.
+                                */
+                               if (ai->ai_addr->sa_family == AF_INET) {
+                                       in4 = (struct sockaddr_in *)ai->ai_addr;
+                                       tcp_port = ntohs(in4->sin_port);
+                                       break;
+                               }
+#ifdef INET6
+                               if (ai->ai_addr->sa_family == AF_INET6) {
+                                       in6 = (struct sockaddr_in6 *)ai->ai_addr;
+                                       tcp_port = ntohs(in6->sin6_port);
+                                       break;
+                               }
+#endif
+                       }
+               }
+               freeaddrinfo(res);
+       }
+
+       memset(&hints, 0, sizeof(hints));
+       hints.ai_family = PF_UNSPEC;
+       hints.ai_socktype = SOCK_DGRAM;
+       hints.ai_protocol = IPPROTO_UDP;
+       error = getaddrinfo(NULL, name, &hints, &res);
+       if (error != 0) {
+               if (error != EAI_NONAME &&
+                   error != EAI_SERVICE) {
+                       /*
+                        * This is a real error, not just "there's
+                        * no such service name".
+                        * XXX - this doesn't return an error string.
+                        */
+                       return 0;
+               }
+       } else {
+               /*
+                * OK, we found it.  Did it find anything?
+                */
+               for (ai = res; ai != NULL; ai = ai->ai_next) {
+                       /*
+                        * Does it have an address?
+                        */
+                       if (ai->ai_addr != NULL) {
+                               /*
+                                * Yes.  Get a port number; we're done.
+                                */
+                               if (ai->ai_addr->sa_family == AF_INET) {
+                                       in4 = (struct sockaddr_in *)ai->ai_addr;
+                                       udp_port = ntohs(in4->sin_port);
+                                       break;
+                               }
+#ifdef INET6
+                               if (ai->ai_addr->sa_family == AF_INET6) {
+                                       in6 = (struct sockaddr_in6 *)ai->ai_addr;
+                                       udp_port = ntohs(in6->sin6_port);
+                                       break;
+                               }
+#endif
+                       }
+               }
+               freeaddrinfo(res);
+       }
+
+       /*
         * We need to check /etc/services for ambiguous entries.
-        * If we find the ambiguous entry, and it has the
+        * If we find an ambiguous entry, and it has the
         * same port number, change the proto to PROTO_UNDEF
         * so both TCP and UDP will be checked.
         */
-       sp = getservbyname(name, "tcp");
-       if (sp != NULL) tcp_port = ntohs(sp->s_port);
-       sp = getservbyname(name, "udp");
-       if (sp != NULL) udp_port = ntohs(sp->s_port);
        if (tcp_port >= 0) {
                *port = tcp_port;
                *proto = IPPROTO_TCP;
@@ -255,12 +487,62 @@ pcap_nametoportrange(const char *name, int *port1, int *port2, int *proto)
        return 1;
 }
 
+/*
+ * XXX - not guaranteed to be thread-safe!  See below for platforms
+ * on which it is thread-safe and on which it isn't.
+ */
 int
 pcap_nametoproto(const char *str)
 {
        struct protoent *p;
+  #if defined(HAVE_LINUX_GETNETBYNAME_R)
+       /*
+        * We have Linux's reentrant getprotobyname_r().
+        */
+       struct protoent result_buf;
+       char buf[1024]; /* arbitrary size */
+       int err;
+
+       err = getprotobyname_r(str, &result_buf, buf, sizeof buf, &p);
+       if (err != 0) {
+               /*
+                * XXX - dynamically allocate the buffer, and make it
+                * bigger if we get ERANGE back?
+                */
+               return 0;
+       }
+  #elif defined(HAVE_SOLARIS_IRIX_GETNETBYNAME_R)
+       /*
+        * We have Solaris's and IRIX's reentrant getprotobyname_r().
+        */
+       struct protoent result_buf;
+       char buf[1024]; /* arbitrary size */
 
+       p = getprotobyname_r(str, &result_buf, buf, (int)sizeof buf);
+  #elif defined(HAVE_AIX_GETNETBYNAME_R)
+       /*
+        * We have AIX's reentrant getprotobyname_r().
+        */
+       struct protoent result_buf;
+       struct protoent_data proto_data;
+
+       if (getprotobyname_r(str, &result_buf, &proto_data) == -1)
+               p = NULL;
+       else
+               p = &result_buf;
+  #else
+       /*
+        * We don't have any getprotobyname_r(); either we have a
+        * getprotobyname() that uses thread-specific data, in which
+        * case we're thread-safe (sufficiently recent FreeBSD,
+        * sufficiently recent Darwin-based OS, sufficiently recent
+        * HP-UX, sufficiently recent Tru64 UNIX, Windows), or we have
+        * the traditional getprotobyname() (everything else, including
+        * current NetBSD and OpenBSD), in which case we're not
+        * thread-safe.
+        */
        p = getprotobyname(str);
+  #endif
        if (p != 0)
                return p->p_proto;
        else
@@ -274,8 +556,19 @@ 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.)
+ *
+ * We declare it here, right before defining it, to squelch any
+ * warnings we might get from compilers about the lack of a
+ * declaration.
+ */
+PCAP_API struct eproto eproto_db[];
+PCAP_API_DEF struct eproto eproto_db[] = {
        { "pup", ETHERTYPE_PUP },
        { "xns", ETHERTYPE_NS },
        { "ip", ETHERTYPE_IP },
@@ -338,17 +631,16 @@ pcap_nametollc(const char *s)
        return PROTO_UNDEF;
 }
 
-/* Hex digit to integer. */
-static inline int
-xdtoi(c)
-       register int c;
+/* Hex digit to 8-bit unsigned integer. */
+static inline u_char
+xdtoi(u_char c)
 {
        if (isdigit(c))
-               return c - '0';
+               return (u_char)(c - '0');
        else if (islower(c))
-               return c - 'a' + 10;
+               return (u_char)(c - 'a' + 10);
        else
-               return c - 'A' + 10;
+               return (u_char)(c - 'A' + 10);
 }
 
 int
@@ -359,7 +651,7 @@ __pcap_atoin(const char *s, bpf_u_int32 *addr)
 
        *addr = 0;
        len = 0;
-       while (1) {
+       for (;;) {
                n = 0;
                while (*s && *s != '.')
                        n = n * 10 + *s++ - '0';
@@ -383,7 +675,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);
@@ -407,7 +699,7 @@ u_char *
 pcap_ether_aton(const char *s)
 {
        register u_char *ep, *e;
-       register u_int d;
+       register u_char d;
 
        e = ep = (u_char *)malloc(6);
        if (e == NULL)
@@ -428,7 +720,11 @@ pcap_ether_aton(const char *s)
 }
 
 #ifndef HAVE_ETHER_HOSTTON
-/* Roll our own */
+/*
+ * Roll our own.
+ * XXX - not thread-safe, because pcap_next_etherent() isn't thread-
+ * safe!  Needs a mutex or a thread-safe pcap_next_etherent().
+ */
 u_char *
 pcap_ether_hostton(const char *name)
 {
@@ -460,17 +756,10 @@ pcap_ether_hostton(const char *name)
        return (NULL);
 }
 #else
-
-#if !defined(HAVE_DECL_ETHER_HOSTTON) || !HAVE_DECL_ETHER_HOSTTON
-#ifndef HAVE_STRUCT_ETHER_ADDR
-struct ether_addr {
-       unsigned char ether_addr_octet[6];
-};
-#endif
-extern int ether_hostton(const char *, struct ether_addr *);
-#endif
-
-/* Use the os supplied routines */
+/*
+ * Use the OS-supplied routine.
+ * This *should* be thread-safe; the API doesn't have a static buffer.
+ */
 u_char *
 pcap_ether_hostton(const char *name)
 {
@@ -487,23 +776,25 @@ pcap_ether_hostton(const char *name)
 }
 #endif
 
-u_short
-__pcap_nametodnaddr(const char *name)
-{
+/*
+ * XXX - not guaranteed to be thread-safe!
+ */
+int
 #ifdef DECNETLIB
+__pcap_nametodnaddr(const char *name, u_short *res)
+{
        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);
+__pcap_nametodnaddr(const char *name _U_, u_short *res _U_)
+{
        return(0);
 #endif
 }
similarity index 54%
rename from Win32/Src/inet_pton.c
rename to nametoaddr.h
index fe89bb5..fd6b7e1 100644 (file)
@@ -1,32 +1,27 @@
 /*
- * Copyright (c) 1999 Kungliga Tekniska Högskolan
- * (Royal Institute of Technology, Stockholm, Sweden).
- * All rights reserved.
- * 
+ * 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 Kungliga Tekniska
- *      Högskolan and its contributors.
- * 
- * 4. Neither the name of the Institute 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 INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
+ *     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 INSTITUTE OR CONTRIBUTORS BE LIABLE
+ * 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)
  * SUCH DAMAGE.
  */
 
-#include <errno.h>
-
-#ifdef WIN32
-#ifndef EAFNOSUPPORT
-#define        EAFNOSUPPORT    97      /* not present in errno.h provided with VC */
-#endif
+#ifdef __cplusplus
+extern "C" {
 #endif
 
-#ifdef __MINGW32__
-int* _errno();
-#define errno (*_errno())
-#endif /* __MINGW32__ */
-
-#include <pcap-stdinc.h>
-
-int inet_aton(const char *cp, struct in_addr *addr);
+/*
+ * 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 *);
 
-int
-inet_pton(int af, const char *src, void *dst)
-{
-    if (af != AF_INET) {
-       errno = EAFNOSUPPORT;
-       return -1;
-    }
-    return inet_aton (src, dst);
+#ifdef __cplusplus
 }
+#endif
diff --git a/nomkdep b/nomkdep
new file mode 100755 (executable)
index 0000000..bed7366
--- /dev/null
+++ b/nomkdep
@@ -0,0 +1,6 @@
+#!/bin/sh -
+#
+# Does nothing; used if we don't have a command-line flag to the compiler
+# to get it to generate dependencies.
+#
+exit 0
index feaf201..448452d 100644 (file)
  * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
  * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
  *
- *  Optimization module for tcpdump intermediate representation.
+ *  Optimization module for BPF code intermediate representation.
  */
 
 #ifdef HAVE_CONFIG_H
-#include "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>
-#endif
-#include <sys/types.h>
-#endif /* WIN32 */
+#include <pcap-types.h>
 
 #include <stdio.h>
 #include <stdlib.h>
 #include <memory.h>
+#include <setjmp.h>
 #include <string.h>
 
 #include <errno.h>
 #include "pcap-int.h"
 
 #include "gencode.h"
+#include "optimize.h"
 
 #ifdef HAVE_OS_PROTO_H
 #include "os-proto.h"
 #endif
 
 #ifdef BDEBUG
-extern int dflag;
+/*
+ * 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.
+ */
+static int pcap_optimizer_debug;
+
+/*
+ * Routine to set that flag.
+ *
+ * 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)
+{
+       pcap_optimizer_debug = value;
+}
+
+/*
+ * The internal "print dot graph" 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.
+ */
+static int pcap_print_dot_graph;
+
+/*
+ * Routine to set that flag.
+ *
+ * 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_print_dot_graph(int value);
+
+PCAP_API_DEF void
+pcap_set_print_dot_graph(int value)
+{
+       pcap_print_dot_graph = value;
+}
+
 #endif
 
-#if defined(MSDOS) && !defined(__DJGPP__)
-extern int _w32_ffs (int mask);
-#define ffs _w32_ffs
+/*
+ * lowest_set_bit().
+ *
+ * Takes a 32-bit integer as an argument.
+ *
+ * If handed a non-zero value, returns the index of the lowest set bit,
+ * counting upwards fro zero.
+ *
+ * If handed zero, the results are platform- and compiler-dependent.
+ * Keep it out of the light, don't give it any water, don't feed it
+ * after midnight, and don't pass zero to it.
+ *
+ * This is the same as the count of trailing zeroes in the word.
+ */
+#if PCAP_IS_AT_LEAST_GNUC_VERSION(3,4)
+  /*
+   * GCC 3.4 and later; we have __builtin_ctz().
+   */
+  #define lowest_set_bit(mask) __builtin_ctz(mask)
+#elif defined(_MSC_VER)
+  /*
+   * Visual Studio; we support only 2005 and later, so use
+   * _BitScanForward().
+   */
+#include <intrin.h>
+
+#ifndef __clang__
+#pragma intrinsic(_BitScanForward)
 #endif
 
-#if defined(WIN32) && defined (_MSC_VER)
-int ffs(int mask);
+static __forceinline int
+lowest_set_bit(int mask)
+{
+       unsigned long bit;
+
+       /*
+        * Don't sign-extend mask if long is longer than int.
+        * (It's currently not, in MSVC, even on 64-bit platforms, but....)
+        */
+       if (_BitScanForward(&bit, (unsigned int)mask) == 0)
+               return -1;      /* mask is zero */
+       return (int)bit;
+}
+#elif defined(MSDOS) && defined(__DJGPP__)
+  /*
+   * MS-DOS with DJGPP, which declares ffs() in <string.h>, which
+   * we've already included.
+   */
+  #define lowest_set_bit(mask) (ffs((mask)) - 1)
+#elif (defined(MSDOS) && defined(__WATCOMC__)) || defined(STRINGS_H_DECLARES_FFS)
+  /*
+   * MS-DOS with Watcom C, which has <strings.h> and declares ffs() there,
+   * or some other platform (UN*X conforming to a sufficient recent version
+   * of the Single UNIX Specification).
+   */
+  #include <strings.h>
+  #define lowest_set_bit(mask) (ffs((mask)) - 1)
+#else
+/*
+ * None of the above.
+ * Use a perfect-hash-function-based function.
+ */
+static int
+lowest_set_bit(int mask)
+{
+       unsigned int v = (unsigned int)mask;
+
+       static const int MultiplyDeBruijnBitPosition[32] = {
+               0, 1, 28, 2, 29, 14, 24, 3, 30, 22, 20, 15, 25, 17, 4, 8,
+               31, 27, 13, 23, 21, 19, 16, 7, 26, 12, 18, 6, 11, 5, 10, 9
+       };
+
+       /*
+        * We strip off all but the lowermost set bit (v & ~v),
+        * and perform a minimal perfect hash on it to look up the
+        * number of low-order zero bits in a table.
+        *
+        * See:
+        *
+        *      http://7ooo.mooo.com/text/ComputingTrailingZerosHOWTO.pdf
+        *
+        *      http://supertech.csail.mit.edu/papers/debruijn.pdf
+        */
+       return (MultiplyDeBruijnBitPosition[((v & -v) * 0x077CB531U) >> 27]);
+}
 #endif
 
 /*
@@ -89,63 +206,76 @@ 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 *);
+typedef struct {
+       /*
+        * Place to longjmp to on an error.
+        */
+       jmp_buf top_ctx;
 
-static void find_inedges(struct block *);
-#ifdef BDEBUG
-static void opt_dump(struct block *);
-#endif
+       /*
+        * The buffer into which to put error message.
+        */
+       char *errbuf;
 
-static int n_blocks;
-struct block **blocks;
-static int n_edges;
-struct edge **edges;
+       /*
+        * A flag to indicate that further optimization is needed.
+        * Iterative passes are continued until a given pass yields no
+        * branch movement.
+        */
+       int done;
+
+       int n_blocks;
+       struct block **blocks;
+       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}
  */
 #define SET_MEMBER(p, a) \
-((p)[(unsigned)(a) / BITS_PER_WORD] & (1 << ((unsigned)(a) % BITS_PER_WORD)))
+((p)[(unsigned)(a) / BITS_PER_WORD] & ((bpf_u_int32)1 << ((unsigned)(a) % BITS_PER_WORD)))
 
 /*
  * Add 'a' to uset p.
  */
 #define SET_INSERT(p, a) \
-(p)[(unsigned)(a) / BITS_PER_WORD] |= (1 << ((unsigned)(a) % BITS_PER_WORD))
+(p)[(unsigned)(a) / BITS_PER_WORD] |= ((bpf_u_int32)1 << ((unsigned)(a) % BITS_PER_WORD))
 
 /*
  * Delete 'a' from uset p.
  */
 #define SET_DELETE(p, a) \
-(p)[(unsigned)(a) / BITS_PER_WORD] &= ~(1 << ((unsigned)(a) % BITS_PER_WORD))
+(p)[(unsigned)(a) / BITS_PER_WORD] &= ~((bpf_u_int32)1 << ((unsigned)(a) % BITS_PER_WORD))
 
 /*
  * a := a intersect b
@@ -177,48 +307,91 @@ 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;
+} opt_state_t;
+
+typedef struct {
+       /*
+        * Place to longjmp to on an error.
+        */
+       jmp_buf top_ctx;
+
+       /*
+        * The buffer into which to put error message.
+        */
+       char *errbuf;
+
+       /*
+        * 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(opt_state_t *, struct icode *);
+static void opt_cleanup(opt_state_t *);
+static void PCAP_NORETURN opt_error(opt_state_t *, const char *, ...)
+    PCAP_PRINTFLIKE(2, 3);
+
+static void intern_blocks(opt_state_t *, struct icode *);
+
+static void find_inedges(opt_state_t *, struct block *);
+#ifdef BDEBUG
+static void opt_dump(opt_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 +399,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 +408,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;
+               *x++ = 0xFFFFFFFFU;
        /* 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 +443,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[i] = ~0;
+       x = opt_state->all_edge_sets;
+       for (i = opt_state->n_edges * opt_state->edgewords; --i >= 0; )
+               x[i] = 0xFFFFFFFFU;
 
        /* 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 +472,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 +480,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 +586,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 +610,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 +636,7 @@ compute_local_ud(struct block *b)
        }
 
        b->def = def;
-       b->kill = kill;
+       b->kill = killed;
        b->in_use = use;
 }
 
@@ -471,7 +644,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,86 +655,55 @@ 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;
        struct valnode *p;
 
-       hash = (u_int)code ^ (v0 << 4) ^ (v1 << 8);
+       hash = (u_int)code ^ ((u_int)v0 << 4) ^ ((u_int)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;
 }
@@ -569,7 +711,7 @@ F(int code, int v0, int v1)
 static inline void
 vstore(struct stmt *s, int *valp, int newval, int alter)
 {
-       if (alter && *valp == newval)
+       if (alter && newval != VAL_UNKNOWN && *valp == newval)
                s->code = NOP;
        else
                *valp = newval;
@@ -580,12 +722,12 @@ 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(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 +744,13 @@ fold_op(struct stmt *s, int v0, int v1)
 
        case BPF_DIV:
                if (b == 0)
-                       bpf_error("division by zero");
+                       opt_error(opt_state, "division by zero");
                a /= b;
                break;
 
        case BPF_MOD:
                if (b == 0)
-                       bpf_error("modulus by zero");
+                       opt_error(opt_state, "modulus by zero");
                a %= b;
                break;
 
@@ -625,11 +767,39 @@ fold_op(struct stmt *s, int v0, int v1)
                break;
 
        case BPF_LSH:
-               a <<= b;
+               /*
+                * A left shift of more than the width of the type
+                * is undefined in C; we'll just treat it as shifting
+                * all the bits out.
+                *
+                * XXX - the BPF interpreter doesn't check for this,
+                * so its behavior is dependent on the behavior of
+                * the processor on which it's running.  There are
+                * processors on which it shifts all the bits out
+                * and processors on which it does no shift.
+                */
+               if (b < 32)
+                       a <<= b;
+               else
+                       a = 0;
                break;
 
        case BPF_RSH:
-               a >>= b;
+               /*
+                * A right shift of more than the width of the type
+                * is undefined in C; we'll just treat it as shifting
+                * all the bits out.
+                *
+                * XXX - the BPF interpreter doesn't check for this,
+                * so its behavior is dependent on the behavior of
+                * the processor on which it's running.  There are
+                * processors on which it shifts all the bits out
+                * and processors on which it does no shift.
+                */
+               if (b < 32)
+                       a >>= b;
+               else
+                       a = 0;
                break;
 
        default:
@@ -637,7 +807,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 +828,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 +863,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 +874,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 +953,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 +971,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 +981,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 +996,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 +1008,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 +1022,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 +1033,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 +1042,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 +1052,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 +1061,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 +1076,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 +1091,7 @@ 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(opt_state_t *opt_state, struct stmt *s, int val[], int alter)
 {
        int op;
        int v;
@@ -931,7 +1101,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 +1109,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 +1136,34 @@ 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;
+                       /*
+                        * Do this negation as unsigned arithmetic; that's
+                        * what modern BPF engines do, and it guarantees
+                        * that all possible values can be negated.  (Yeah,
+                        * negating 0x80000000, the minimum signed 32-bit
+                        * two's-complement value, results in 0x80000000,
+                        * so it's still negative, but we *should* be doing
+                        * all unsigned arithmetic here, to match what
+                        * modern BPF engines do.)
+                        *
+                        * Express it as 0U - (unsigned value) so that we
+                        * don't get compiler warnings about negating an
+                        * unsigned value and don't get UBSan warnings
+                        * about the result of negating 0x80000000 being
+                        * undefined.
+                        */
+                       s->k = 0U - (bpf_u_int32)(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:
@@ -993,9 +1179,17 @@ opt_stmt(struct stmt *s, int val[], int alter)
                op = BPF_OP(s->code);
                if (alter) {
                        if (s->k == 0) {
-                               /* don't optimize away "sub #0"
+                               /*
+                                * Optimize operations where the constant
+                                * is zero.
+                                *
+                                * Don't optimize away "sub #0"
                                 * as it may be needed later to
-                                * fixup the generated math code */
+                                * fixup the generated math code.
+                                *
+                                * Fail if we're dividing by zero or taking
+                                * a modulus by zero.
+                                */
                                if (op == BPF_ADD ||
                                    op == BPF_LSH || op == BPF_RSH ||
                                    op == BPF_OR || op == BPF_XOR) {
@@ -1007,14 +1201,20 @@ opt_stmt(struct stmt *s, int val[], int alter)
                                        val[A_ATOM] = K(s->k);
                                        break;
                                }
+                               if (op == BPF_DIV)
+                                       opt_error(opt_state,
+                                           "division by zero");
+                               if (op == BPF_MOD)
+                                       opt_error(opt_state,
+                                           "modulus by zero");
                        }
-                       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(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 +1228,27 @@ 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(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;
+                               /*
+                                * XXX - we need to make up our minds
+                                * as to what integers are signed and
+                                * what integers are unsigned in BPF
+                                * programs and in our IR.
+                                */
+                               if ((op == BPF_LSH || op == BPF_RSH) &&
+                                   (s->k < 0 || s->k > 31))
+                                       opt_error(opt_state,
+                                           "shift by more than 31 bits");
+                               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 +1259,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 +1278,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 +1287,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 +1301,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 +1320,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 +1336,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 +1344,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 +1353,18 @@ 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(opt_state_t *opt_state, struct block *b, int do_stmts)
 {
        struct slist *s;
        struct edge *p;
@@ -1204,7 +1414,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(opt_state, &s->s, b->val, do_stmts);
 
        /*
         * This is a special case: if we don't use anything from this
@@ -1230,16 +1440,17 @@ opt_blk(struct block *b, int do_stmts)
         * block, can we eliminate it?
         */
        if (do_stmts &&
-           ((b->out_use == 0 && aval != 0 && b->val[A_ATOM] == aval &&
-             xval != 0 && b->val[X_ATOM] == xval) ||
+           ((b->out_use == 0 &&
+             aval != VAL_UNKNOWN && b->val[A_ATOM] == aval &&
+             xval != VAL_UNKNOWN && b->val[X_ATOM] == xval) ||
             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 +1537,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 +1551,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,21 +1563,21 @@ 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) {
-                       k = ffs(x) - 1;
-                       x &=~ (1 << k);
+                       k = lowest_set_bit(x);
+                       x &=~ ((bpf_u_int32)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 +1592,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;
@@ -1407,7 +1618,7 @@ or_pullup(struct block *b)
                diffp = &JF(b->in_edges->pred);
 
        at_top = 1;
-       while (1) {
+       for (;;) {
                if (*diffp == 0)
                        return;
 
@@ -1424,7 +1635,7 @@ or_pullup(struct block *b)
                at_top = 0;
        }
        samep = &JF(*diffp);
-       while (1) {
+       for (;;) {
                if (*samep == 0)
                        return;
 
@@ -1469,11 +1680,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;
@@ -1498,7 +1709,7 @@ and_pullup(struct block *b)
                diffp = &JF(b->in_edges->pred);
 
        at_top = 1;
-       while (1) {
+       for (;;) {
                if (*diffp == 0)
                        return;
 
@@ -1515,7 +1726,7 @@ and_pullup(struct block *b)
                at_top = 0;
        }
        samep = &JT(*diffp);
-       while (1) {
+       for (;;) {
                if (*samep == 0)
                        return;
 
@@ -1560,22 +1771,22 @@ 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(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(opt_state, p, do_stmts);
 
        if (do_stmts)
                /*
@@ -1585,17 +1796,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 +1819,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 +1864,89 @@ opt_root(struct block **b)
 }
 
 static void
-opt_loop(struct block *root, int do_stmts)
+opt_loop(opt_state_t *opt_state, struct icode *ic, int do_stmts)
 {
 
 #ifdef BDEBUG
-       if (dflag > 1) {
+       if (pcap_optimizer_debug > 1 || pcap_print_dot_graph) {
                printf("opt_loop(root, %d) begin\n", do_stmts);
-               opt_dump(root);
+               opt_dump(opt_state, 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(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 || pcap_print_dot_graph) {
+                       printf("opt_loop(root, %d) bottom, done=%d\n", do_stmts, opt_state->done);
+                       opt_dump(opt_state, ic);
                }
 #endif
-       } while (!done);
+       } while (!opt_state->done);
 }
 
 /*
  * Optimize the filter code in its dag representation.
+ * Return 0 on success, -1 on error.
  */
-void
-bpf_optimize(struct block **rootp)
+int
+bpf_optimize(struct icode *ic, char *errbuf)
 {
-       struct block *root;
-
-       root = *rootp;
+       opt_state_t opt_state;
 
-       opt_init(root);
-       opt_loop(root, 0);
-       opt_loop(root, 1);
-       intern_blocks(root);
+       memset(&opt_state, 0, sizeof(opt_state));
+       opt_state.errbuf = errbuf;
+       if (setjmp(opt_state.top_ctx)) {
+               opt_cleanup(&opt_state);
+               return -1;
+       }
+       opt_init(&opt_state, ic);
+       opt_loop(&opt_state, ic, 0);
+       opt_loop(&opt_state, ic, 1);
+       intern_blocks(&opt_state, ic);
 #ifdef BDEBUG
-       if (dflag > 1) {
+       if (pcap_optimizer_debug > 1 || pcap_print_dot_graph) {
                printf("after intern_blocks()\n");
-               opt_dump(root);
+               opt_dump(&opt_state, ic);
        }
 #endif
-       opt_root(rootp);
+       opt_root(&ic->root);
 #ifdef BDEBUG
-       if (dflag > 1) {
+       if (pcap_optimizer_debug > 1 || pcap_print_dot_graph) {
                printf("after opt_root()\n");
-               opt_dump(root);
+               opt_dump(&opt_state, ic);
        }
 #endif
-       opt_cleanup();
+       opt_cleanup(&opt_state);
+       return 0;
 }
 
 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);
 }
 
 /*
@@ -1739,7 +1956,7 @@ mark_code(struct block *p)
 static int
 eq_slist(struct slist *x, struct slist *y)
 {
-       while (1) {
+       for (;;) {
                while (x && x->s.code == NOP)
                        x = x->next;
                while (y && y->s.code == NOP)
@@ -1767,33 +1984,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 +2027,32 @@ intern_blocks(struct block *root)
 }
 
 static void
-opt_cleanup(void)
+opt_cleanup(opt_state_t *opt_state)
+{
+       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);
+}
+
+/*
+ * For optimizer errors.
+ */
+static void PCAP_NORETURN
+opt_error(opt_state_t *opt_state, const char *fmt, ...)
 {
-       free((void *)vnode_base);
-       free((void *)vmap);
-       free((void *)edges);
-       free((void *)space);
-       free((void *)levels);
-       free((void *)blocks);
+       va_list ap;
+
+       if (opt_state->errbuf != NULL) {
+               va_start(ap, fmt);
+               (void)pcap_vsnprintf(opt_state->errbuf,
+                   PCAP_ERRBUF_SIZE, fmt, ap);
+               va_end(ap);
+       }
+       longjmp(opt_state->top_ctx, 1);
+       /* NOTREACHED */
 }
 
 /*
@@ -1839,12 +2074,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 +2087,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 +2122,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 +2139,7 @@ count_stmts(struct block *p)
  * from the total number of blocks and/or statements.
  */
 static void
-opt_init(struct block *root)
+opt_init(opt_state_t *opt_state, struct icode *ic)
 {
        bpf_u_int32 *p;
        int i, n, max_stmts;
@@ -1913,88 +2148,95 @@ 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)
+               opt_error(opt_state, "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) {
+               opt_error(opt_state, "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) {
+               opt_error(opt_state, "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) {
+               opt_error(opt_state, "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));
+       if (opt_state->vmap == NULL) {
+               opt_error(opt_state, "malloc");
+       }
+       opt_state->vnode_base = (struct valnode *)calloc(opt_state->maxval, sizeof(*opt_state->vnode_base));
+       if (opt_state->vnode_base == NULL) {
+               opt_error(opt_state, "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];
+int bids[NBIDS];
 #endif
 
+static void PCAP_NORETURN conv_error(conv_state_t *, const char *, ...)
+    PCAP_PRINTFLIKE(2, 3);
+
 /*
  * Returns true if successful.  Returns false if a branch has
  * an offset that is too large.  If so, we have marked that
@@ -2002,35 +2244,35 @@ int bids[1000];
  * properly.
  */
 static int
-convert_code_r(struct block *p)
+convert_code_r(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 */
+       u_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(conv_state, ic, JF(p)) == 0)
                return (0);
-       if (convert_code_r(JT(p)) == 0)
+       if (convert_code_r(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");
+                       conv_error(conv_state, "not enough core");
                        /*NOTREACHED*/
                }
        }
@@ -2054,7 +2296,8 @@ 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");
+                               free(offset);
+                               conv_error(conv_state, "illegal jmp destination");
                                /*NOTREACHED*/
                        }
 #endif
@@ -2064,9 +2307,9 @@ 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";
+               const char ljerr[] = "%s for block-local relative jump: off=%d";
 
 #if 0
                printf("code=%x off=%d %x %x\n", src->s.code,
@@ -2074,7 +2317,8 @@ convert_code_r(struct block *p)
 #endif
 
                if (!src->s.jt || !src->s.jf) {
-                       bpf_error(ljerr, "no jmp destination", off);
+                       free(offset);
+                       conv_error(conv_state, ljerr, "no jmp destination", off);
                        /*NOTREACHED*/
                }
 
@@ -2082,24 +2326,37 @@ 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);
+                                       free(offset);
+                                       conv_error(conv_state, ljerr, "multiple matches", off);
                                        /*NOTREACHED*/
                                }
 
-                               dst->jt = i - off - 1;
+                               if (i - off - 1 >= 256) {
+                                       free(offset);
+                                       conv_error(conv_state, ljerr, "out-of-range jump", off);
+                                       /*NOTREACHED*/
+                               }
+                               dst->jt = (u_char)(i - off - 1);
                                jt++;
                        }
                        if (offset[i] == src->s.jf) {
                                if (jf) {
-                                       bpf_error(ljerr, "multiple matches", off);
+                                       free(offset);
+                                       conv_error(conv_state, ljerr, "multiple matches", off);
+                                       /*NOTREACHED*/
+                               }
+                               if (i - off - 1 >= 256) {
+                                       free(offset);
+                                       conv_error(conv_state, ljerr, "out-of-range jump", off);
                                        /*NOTREACHED*/
                                }
-                               dst->jf = i - off - 1;
+                               dst->jf = (u_char)(i - off - 1);
                                jf++;
                        }
                }
                if (!jt || !jf) {
-                       bpf_error(ljerr, "no destination found", off);
+                       free(offset);
+                       conv_error(conv_state, ljerr, "no destination found", off);
                        /*NOTREACHED*/
                }
            }
@@ -2111,7 +2368,8 @@ filled:
                free(offset);
 
 #ifdef BDEBUG
-       bids[dst - fstart] = p->id + 1;
+       if (dst - conv_state->fstart < NBIDS)
+               bids[dst - conv_state->fstart] = p->id + 1;
 #endif
        dst->code = (u_short)p->s.code;
        dst->k = p->s.k;
@@ -2126,13 +2384,17 @@ filled:
                        return(0);
                    }
                    /* branch if T to following jump */
-                   dst->jt = extrajmps;
+                   if (extrajmps >= 256) {
+                       conv_error(conv_state, "too many extra jumps");
+                       /*NOTREACHED*/
+                   }
+                   dst->jt = (u_char)extrajmps;
                    extrajmps++;
                    dst[extrajmps].code = BPF_JMP|BPF_JA;
                    dst[extrajmps].k = off - extrajmps;
                }
                else
-                   dst->jt = off;
+                   dst->jt = (u_char)off;
                off = JF(p)->offset - (p->offset + slen) - 1;
                if (off >= 256) {
                    /* offset too large for branch, must add a jump */
@@ -2143,13 +2405,17 @@ filled:
                    }
                    /* branch if F to following jump */
                    /* if two jumps are inserted, F goes to second one */
-                   dst->jf = extrajmps;
+                   if (extrajmps >= 256) {
+                       conv_error(conv_state, "too many extra jumps");
+                       /*NOTREACHED*/
+                   }
+                   dst->jf = (u_char)extrajmps;
                    extrajmps++;
                    dst[extrajmps].code = BPF_JMP|BPF_JA;
                    dst[extrajmps].k = off - extrajmps;
                }
                else
-                   dst->jf = off;
+                   dst->jf = (u_char)off;
        }
        return (1);
 }
@@ -2174,28 +2440,41 @@ 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(struct icode *ic, struct block *root, u_int *lenp, 
+    char *errbuf)
 {
        u_int n;
        struct bpf_insn *fp;
+       conv_state_t conv_state;
+
+       conv_state.fstart = NULL;
+       conv_state.errbuf = errbuf;
+       if (setjmp(conv_state.top_ctx) != 0) {
+               free(conv_state.fstart);
+               return NULL;
+       }
 
        /*
         * Loop doing convert_code_r() until no branches remain
         * with too-large offsets.
         */
-       while (1) {
-           unMarkAll();
-           n = *lenp = count_stmts(root);
+       for (;;) {
+           unMarkAll(ic);
+           n = *lenp = count_stmts(ic, root);
 
            fp = (struct bpf_insn *)malloc(sizeof(*fp) * n);
-           if (fp == NULL)
-                   bpf_error("malloc");
+           if (fp == NULL) {
+               (void)pcap_snprintf(errbuf, PCAP_ERRBUF_SIZE,
+                   "malloc");
+               free(fp);
+               return NULL;
+           }
            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(&conv_state, ic, root))
                break;
            free(fp);
        }
@@ -2204,6 +2483,22 @@ icode_to_fcode(struct block *root, u_int *lenp)
 }
 
 /*
+ * For iconv_to_fconv() errors.
+ */
+static void PCAP_NORETURN
+conv_error(conv_state_t *conv_state, const char *fmt, ...)
+{
+       va_list ap;
+
+       va_start(ap, fmt);
+       (void)pcap_vsnprintf(conv_state->errbuf,
+           PCAP_ERRBUF_SIZE, fmt, ap);
+       va_end(ap);
+       longjmp(conv_state->top_ctx, 1);
+       /* NOTREACHED */
+}
+
+/*
  * Make a copy of a BPF program and put it in the "fcode" member of
  * a "pcap_t".
  *
@@ -2220,7 +2515,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,8 +2529,8 @@ 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),
-                        "malloc: %s", pcap_strerror(errno));
+               pcap_fmt_errmsg_for_errno(p->errbuf, sizeof(p->errbuf),
+                   errno, "malloc");
                return (-1);
        }
        memcpy(p->fcode.bf_insns, fp->bf_insns, prog_size);
@@ -2244,14 +2539,126 @@ 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] != VAL_UNKNOWN)
+                       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 int
+dot_dump(struct icode *ic, char *errbuf)
+{
+       struct bpf_program f;
+       FILE *out = stdout;
+
+       memset(bids, 0, sizeof bids);
+       f.bf_insns = icode_to_fcode(ic, ic->root, &f.bf_len, errbuf);
+       if (f.bf_insns == NULL)
+               return -1;
+
+       fprintf(out, "digraph BPF {\n");
+       unMarkAll(ic);
+       dot_dump_node(ic, ic->root, &f, out);
+       unMarkAll(ic);
+       dot_dump_edge(ic, ic->root, out);
+       fprintf(out, "}\n");
+
+       free((char *)f.bf_insns);
+       return 0;
+}
+
+static int
+plain_dump(struct icode *ic, char *errbuf)
 {
        struct bpf_program f;
 
        memset(bids, 0, sizeof bids);
-       f.bf_insns = icode_to_fcode(root, &f.bf_len);
+       f.bf_insns = icode_to_fcode(ic, ic->root, &f.bf_len, errbuf);
+       if (f.bf_insns == NULL)
+               return -1;
        bpf_dump(&f, 1);
        putchar('\n');
        free((char *)f.bf_insns);
+       return 0;
+}
+
+static void
+opt_dump(opt_state_t *opt_state, struct icode *ic)
+{
+       int status;
+       char errbuf[PCAP_ERRBUF_SIZE];
+
+       /*
+        * If the CFG, in DOT format, is requested, output it rather than
+        * the code that would be generated from that graph.
+        */
+       if (pcap_print_dot_graph)
+               status = dot_dump(ic, errbuf);
+       else
+               status = plain_dump(ic, errbuf);
+       if (status == -1)
+               opt_error(opt_state, "opt_dump: icode_to_fcode failed: %s", errbuf);
 }
 #endif
diff --git a/optimize.h b/optimize.h
new file mode 100644 (file)
index 0000000..56b31f4
--- /dev/null
@@ -0,0 +1,28 @@
+/*
+ * Copyright (c) 1990, 1991, 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.
+ */
+
+/*
+ * Some stuff for use when debugging the optimizer.
+ */
+#ifdef BDEBUG
+#define NBIDS  1000
+extern int bids[NBIDS];
+#endif
diff --git a/packaging/pcap.spec.in b/packaging/pcap.spec.in
deleted file mode 100644 (file)
index ff7b996..0000000
+++ /dev/null
@@ -1,77 +0,0 @@
-%define prefix   /usr
-%define version @VERSION@
-
-Summary: A system-independent interface for user-level packet capture
-Name: libpcap
-Version: %version
-Release: 1
-Group: Development/Libraries
-License: BSD with advertising
-Source: @NAME@.tar.gz
-BuildRoot: /tmp/%{name}-buildroot
-URL: http://www.tcpdump.org
-
-Source: http://www.tcpdump.org/release/%{name}-%{version}.tar.gz
-
-%description
-Libpcap provides a portable framework for low-level network
-monitoring.  Libpcap can provide network statistics collection,
-security monitoring and network debugging.  Since almost every system
-vendor provides a different interface for packet capture, the libpcap
-authors created this system-independent API to ease in porting and to
-alleviate the need for several system-dependent packet capture modules
-in each application.
-
-Install libpcap if you need to do low-level network traffic monitoring
-on your network.
-
-%package devel
-Summary: Libraries and header files for the libpcap library
-Group: Development/Libraries
-
-%description devel
-Libpcap provides a portable framework for low-level network
-monitoring.  Libpcap can provide network statistics collection,
-security monitoring and network debugging.  Since almost every system
-vendor provides a different interface for packet capture, the libpcap
-authors created this system-independent API to ease in porting and to
-alleviate the need for several system-dependent packet capture modules
-in each application.
-
-This package provides the libraries, include files, and other 
-resources needed for developing libpcap applications.
-%prep
-%setup -q
-
-%build
-export CFLAGS="$RPM_OPT_FLAGS -fno-strict-aliasing"
-%configure
-make %{?_smp_mflags}
-
-%install
-rm -rf $RPM_BUILD_ROOT
-
-make DESTDIR=$RPM_BUILD_ROOT install
-
-%clean
-rm -rf $RPM_BUILD_ROOT
-
-%files
-%defattr(-,root,root)
-%doc LICENSE README CHANGES INSTALL.txt README.linux TODO VERSION CREDITS packaging/pcap.spec
-%{_libdir}/libpcap.so.*
-%{_mandir}/man7/pcap*.7*
-
-%files devel
-%defattr(-,root,root)
-%{_bindir}/pcap-config
-%{_includedir}/pcap/*.h
-%{_includedir}/pcap.h
-%{_includedir}/pcap-bpf.h
-%{_includedir}/pcap-namedb.h
-%{_libdir}/libpcap.so
-%{_libdir}/libpcap.a
-%{_mandir}/man1/pcap-config.1*
-%{_mandir}/man3/pcap*.3*
-%{_mandir}/man5/pcap*.5*
index 9a994c4..4f1a0af 100644 (file)
  */
 
 #ifdef HAVE_CONFIG_H
-#include "config.h"
+#include <config.h>
 #endif
 
 #include <sys/param.h>                 /* optionally get BSD define */
-#ifdef HAVE_ZEROCOPY_BPF
-#include <sys/mman.h>
-#endif
 #include <sys/socket.h>
 #include <time.h>
 /*
  * <net/bpf.h> defines ioctls, but doesn't include <sys/ioccom.h>.
  *
  * We include <sys/ioctl.h> as it might be necessary to declare ioctl();
- * at least on *BSD and Mac OS X, it also defines various SIOC ioctls -
+ * at least on *BSD and macOS, it also defines various SIOC ioctls -
  * we could include <sys/sockio.h>, but if we're already including
  * <sys/ioctl.h>, which includes <sys/sockio.h> on those platforms,
  * there's not much point in doing so.
 #endif
 #include <sys/utsname.h>
 
-#ifdef HAVE_ZEROCOPY_BPF
-#include <machine/atomic.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
 
 #include <net/if.h>
 #include <net/bpf.h>
 #define _AIX
 
+/*
+ * If both BIOCROTZBUF and BPF_BUFMODE_ZBUF are defined, we have
+ * zero-copy BPF.
+ */
+#if defined(BIOCROTZBUF) && defined(BPF_BUFMODE_ZBUF)
+  #define HAVE_ZEROCOPY_BPF
+  #include <sys/mman.h>
+  #include <machine/atomic.h>
+#endif
+
 #include <net/if_types.h>              /* for IFT_ values */
 #include <sys/sysconfig.h>
 #include <sys/device.h>
@@ -112,7 +124,7 @@ static int bpf_load(char *errbuf);
 #include <string.h>
 #include <unistd.h>
 
-#ifdef HAVE_NET_IF_MEDIA_H
+#ifdef SIOCGIFMEDIA
 # include <net/if_media.h>
 #endif
 
@@ -134,10 +146,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
@@ -171,10 +179,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)
@@ -185,7 +206,7 @@ static int monitor_mode(pcap_t *, int);
 #  endif
 
 #  if defined(__APPLE__)
-static void remove_en(pcap_t *);
+static void remove_non_802_11(pcap_t *);
 static void remove_802_11(pcap_t *);
 #  endif
 
@@ -206,8 +227,9 @@ static void remove_802_11(pcap_t *);
 #endif
 
 /*
- * On OS X, we don't even get any of the 802.11-plus-radio-header DLT_'s
- * defined, even though some of them are used by various Airport drivers.
+ * In some versions of macOS, we might not even get any of the
+ * 802.11-plus-radio-header DLT_'s defined, even though some
+ * of them are used by various Airport drivers in those versions.
  */
 #ifndef DLT_PRISM_HEADER
 #define DLT_PRISM_HEADER       119
@@ -234,20 +256,20 @@ static int pcap_set_datalink_bpf(pcap_t *p, int dlt);
  * blocking mode.
  */
 static int
-pcap_getnonblock_bpf(pcap_t *p, char *errbuf)
-{ 
+pcap_getnonblock_bpf(pcap_t *p)
+{
 #ifdef HAVE_ZEROCOPY_BPF
        struct pcap_bpf *pb = p->priv;
 
        if (pb->zerocopy)
                return (pb->nonblock);
 #endif
-       return (pcap_getnonblock_fd(p, errbuf));
+       return (pcap_getnonblock_fd(p));
 }
 
 static int
-pcap_setnonblock_bpf(pcap_t *p, int nonblock, char *errbuf)
-{   
+pcap_setnonblock_bpf(pcap_t *p, int nonblock)
+{
 #ifdef HAVE_ZEROCOPY_BPF
        struct pcap_bpf *pb = p->priv;
 
@@ -256,7 +278,7 @@ pcap_setnonblock_bpf(pcap_t *p, int nonblock, char *errbuf)
                return (0);
        }
 #endif
-       return (pcap_setnonblock_fd(p, nonblock, errbuf));
+       return (pcap_setnonblock_fd(p, nonblock));
 }
 
 #ifdef HAVE_ZEROCOPY_BPF
@@ -347,8 +369,8 @@ 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,
-                                   "BIOCROTZBUF: %s", strerror(errno));
+                               pcap_fmt_errmsg_for_errno(p->errbuf,
+                                   PCAP_ERRBUF_SIZE, errno, "BIOCROTZBUF");
                                return (PCAP_ERROR);
                        }
                        return (pcap_next_zbuf_shm(p, cc));
@@ -375,8 +397,8 @@ pcap_next_zbuf(pcap_t *p, int *cc)
                        }
                        return (0);
                } else if (r < 0) {
-                       (void) snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
-                           "select: %s", strerror(errno));
+                       pcap_fmt_errmsg_for_errno(p->errbuf, PCAP_ERRBUF_SIZE,
+                           errno, "select");
                        return (PCAP_ERROR);
                }
        }
@@ -394,8 +416,8 @@ pcap_next_zbuf(pcap_t *p, int *cc)
         * data.
         */
        if (ioctl(p->fd, BIOCROTZBUF, &bz) < 0) {
-               (void) snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
-                   "BIOCROTZBUF: %s", strerror(errno));
+               pcap_fmt_errmsg_for_errno(p->errbuf, PCAP_ERRBUF_SIZE,
+                   errno, "BIOCROTZBUF");
                return (PCAP_ERROR);
        }
        return (pcap_next_zbuf_shm(p, cc));
@@ -419,16 +441,32 @@ 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);
 
        p->activate_op = pcap_activate_bpf;
        p->can_set_rfmon_op = pcap_can_set_rfmon_bpf;
+#ifdef BIOCSTSTAMP
+       /*
+        * We claim that 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_fmt_errmsg_for_errno(ebuf, PCAP_ERRBUF_SIZE, errno,
+                   "malloc");
+               free(p);
+               return (NULL);
+       }
+       p->tstamp_precision_list[0] = PCAP_TSTAMP_PRECISION_MICRO;
+       p->tstamp_precision_list[1] = PCAP_TSTAMP_PRECISION_NANO;
+#endif /* BIOCSTSTAMP */
        return (p);
 }
 
@@ -437,15 +475,13 @@ 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
-       static const char device[] = "/dev/bpf";
-#else
+       int fd = -1;
+       static const char cloning_device[] = "/dev/bpf";
        int n = 0;
        char device[sizeof "/dev/bpf0000000000"];
-#endif
+       static int no_cloning_bpf = 0;
 
 #ifdef _AIX
        /*
@@ -453,44 +489,59 @@ 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
 
-#ifdef HAVE_CLONING_BPF
-       if ((fd = open(device, O_RDWR)) == -1 &&
-           (errno != EACCES || (fd = open(device, O_RDONLY)) == -1)) {
-               if (errno == EACCES)
-                       fd = PCAP_ERROR_PERM_DENIED;
-               else
-                       fd = PCAP_ERROR;
-               snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
-                 "(cannot open device) %s: %s", device, pcap_strerror(errno));
-       }
-#else
        /*
-        * Go through all the minors and find one that isn't in use.
+        * First, unless we've already tried opening /dev/bpf and
+        * gotten ENOENT, try opening /dev/bpf.
+        * If it fails with ENOENT, remember that, so we don't try
+        * again, and try /dev/bpfN.
         */
-       do {
-               (void)snprintf(device, sizeof(device), "/dev/bpf%d", n++);
+       if (!no_cloning_bpf &&
+           (fd = open(cloning_device, O_RDWR)) == -1 &&
+           ((errno != EACCES && errno != ENOENT) ||
+            (fd = open(cloning_device, O_RDONLY)) == -1)) {
+               if (errno != ENOENT) {
+                       if (errno == EACCES)
+                               fd = PCAP_ERROR_PERM_DENIED;
+                       else
+                               fd = PCAP_ERROR;
+                       pcap_fmt_errmsg_for_errno(errbuf, PCAP_ERRBUF_SIZE,
+                           errno, "(cannot open device) %s", cloning_device);
+                       return (fd);
+               }
+               no_cloning_bpf = 1;
+       }
+
+       if (no_cloning_bpf) {
                /*
-                * Initially try a read/write open (to allow the inject
-                * method to work).  If that fails due to permission
-                * issues, fall back to read-only.  This allows a
-                * non-root user to be granted specific access to pcap
-                * capabilities via file permissions.
-                *
-                * XXX - we should have an API that has a flag that
-                * controls whether to open read-only or read-write,
-                * so that denial of permission to send (or inability
-                * to send, if sending packets isn't supported on
-                * the device in question) can be indicated at open
-                * time.
+                * We don't have /dev/bpf.
+                * Go through all the /dev/bpfN minors and find one
+                * that isn't in use.
                 */
-               fd = open(device, O_RDWR);
-               if (fd == -1 && errno == EACCES)
-                       fd = open(device, O_RDONLY);
-       } while (fd < 0 && errno == EBUSY);
+               do {
+                       (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
+                        * issues, fall back to read-only.  This allows a
+                        * non-root user to be granted specific access to pcap
+                        * capabilities via file permissions.
+                        *
+                        * XXX - we should have an API that has a flag that
+                        * controls whether to open read-only or read-write,
+                        * so that denial of permission to send (or inability
+                        * to send, if sending packets isn't supported on
+                        * the device in question) can be indicated at open
+                        * time.
+                        */
+                       fd = open(device, O_RDWR);
+                       if (fd == -1 && errno == EACCES)
+                               fd = open(device, O_RDONLY);
+               } while (fd < 0 && errno == EBUSY);
+       }
 
        /*
         * XXX better message for all minors used
@@ -506,7 +557,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 {
                                /*
@@ -515,7 +566,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;
@@ -527,9 +578,8 @@ bpf_open(pcap_t *p)
                         * if any.
                         */
                        fd = PCAP_ERROR_PERM_DENIED;
-                       snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
-                           "(cannot open BPF device) %s: %s", device,
-                           pcap_strerror(errno));
+                       pcap_fmt_errmsg_for_errno(errbuf, PCAP_ERRBUF_SIZE,
+                           errno, "(cannot open BPF device) %s", device);
                        break;
 
                default:
@@ -537,17 +587,75 @@ bpf_open(pcap_t *p)
                         * Some other problem.
                         */
                        fd = PCAP_ERROR;
-                       snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
-                           "(cannot open BPF device) %s: %s", device,
-                           pcap_strerror(errno));
+                       pcap_fmt_errmsg_for_errno(errbuf, PCAP_ERRBUF_SIZE,
+                           errno, "(cannot open BPF device) %s", device);
                        break;
                }
        }
-#endif
 
        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_fmt_errmsg_for_errno(errbuf, PCAP_ERRBUF_SIZE,
+                           errno, "BIOCSETIF: %s", name);
+                       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)
@@ -559,14 +667,14 @@ 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",
-                           pcap_strerror(errno));
+                       pcap_fmt_errmsg_for_errno(ebuf, PCAP_ERRBUF_SIZE,
+                           errno, "malloc");
                        return (PCAP_ERROR);
                }
 
                if (ioctl(fd, BIOCGDLTLIST, (caddr_t)bdlp) < 0) {
-                       (void)snprintf(ebuf, PCAP_ERRBUF_SIZE,
-                           "BIOCGDLTLIST: %s", pcap_strerror(errno));
+                       pcap_fmt_errmsg_for_errno(ebuf, PCAP_ERRBUF_SIZE,
+                           errno, "BIOCGDLTLIST");
                        free(bdlp->bfl_list);
                        return (PCAP_ERROR);
                }
@@ -620,8 +728,8 @@ 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,
-                           "BIOCGDLTLIST: %s", pcap_strerror(errno));
+                       pcap_fmt_errmsg_for_errno(ebuf, PCAP_ERRBUF_SIZE,
+                           errno, "BIOCGDLTLIST");
                        return (PCAP_ERROR);
                }
        }
@@ -629,10 +737,10 @@ get_dlt_list(int fd, int v, struct bpf_dltlist *bdlp, char *ebuf)
 }
 #endif
 
+#if defined(__APPLE__)
 static int
 pcap_can_set_rfmon_bpf(pcap_t *p)
 {
-#if defined(__APPLE__)
        struct utsname osinfo;
        struct ifreq ifr;
        int fd;
@@ -641,7 +749,7 @@ pcap_can_set_rfmon_bpf(pcap_t *p)
 #endif
 
        /*
-        * The joys of monitor mode on OS X.
+        * The joys of monitor mode on Mac OS X/OS X/macOS.
         *
         * Prior to 10.4, it's not supported at all.
         *
@@ -679,7 +787,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.
                         */
@@ -687,12 +795,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,
-                           "socket: %s", pcap_strerror(errno));
+                       pcap_fmt_errmsg_for_errno(p->errbuf, PCAP_ERRBUF_SIZE,
+                           errno, "socket");
                        return (PCAP_ERROR);
                }
-               strlcpy(ifr.ifr_name, "wlt", sizeof(ifr.ifr_name));
-               strlcat(ifr.ifr_name, p->opt.source + 2, sizeof(ifr.ifr_name));
+               pcap_strlcpy(ifr.ifr_name, "wlt", sizeof(ifr.ifr_name));
+               pcap_strlcat(ifr.ifr_name, p->opt.device + 2, sizeof(ifr.ifr_name));
                if (ioctl(fd, SIOCGIFFLAGS, (char *)&ifr) < 0) {
                        /*
                         * No such device?
@@ -712,14 +820,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) {
 
@@ -742,9 +850,8 @@ pcap_can_set_rfmon_bpf(pcap_t *p)
                        return (PCAP_ERROR_IFACE_NOT_UP);
 
                default:
-                       snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
-                           "BIOCSETIF: %s: %s",
-                           p->opt.source, pcap_strerror(errno));
+                       pcap_fmt_errmsg_for_errno(p->errbuf, PCAP_ERRBUF_SIZE,
+                           errno, "BIOCSETIF: %s", p->opt.device);
                        close(fd);
                        return (PCAP_ERROR);
                }
@@ -770,9 +877,14 @@ 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)
+static int
+pcap_can_set_rfmon_bpf(pcap_t *p)
+{
        int ret;
 
        ret = monitor_mode(p, 0);
@@ -781,10 +893,14 @@ pcap_can_set_rfmon_bpf(pcap_t *p)
        if (ret == 0)
                return (1);     /* success */
        return (ret);
+}
 #else
+static int
+pcap_can_set_rfmon_bpf(pcap_t *p _U_)
+{
        return (0);
-#endif
 }
+#endif
 
 static int
 pcap_stats_bpf(pcap_t *p, struct pcap_stat *ps)
@@ -805,8 +921,8 @@ 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_strerror(errno));
+               pcap_fmt_errmsg_for_errno(p->errbuf, PCAP_ERRBUF_SIZE,
+                   errno, "BIOCGSTATS");
                return (PCAP_ERROR);
        }
 
@@ -825,7 +941,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;
@@ -866,7 +982,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 */
@@ -904,18 +1020,21 @@ pcap_read_bpf(pcap_t *p, int cnt, pcap_handler callback, u_char *user)
                        case EWOULDBLOCK:
                                return (0);
 
-                       case ENXIO:
+                       case ENXIO:     /* FreeBSD, DragonFly BSD, and Darwin */
+                       case EIO:       /* OpenBSD */
+                                       /* NetBSD appears not to return an error in this case */
                                /*
                                 * 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 retur that.
+                                * an appropriate error for that,
+                                * but pcap_dispatch() etc. aren't
+                                * documented as having error returns
+                                * other than PCAP_ERROR or PCAP_ERROR_BREAK.
                                 */
-                               snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
-                                   "The interface went down");
+                               pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
+                                   "The interface disappeared");
                                return (PCAP_ERROR);
 
 #if defined(sun) && !defined(BSD) && !defined(__svr4__) && !defined(__SVR4)
@@ -933,24 +1052,28 @@ 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_strerror(errno));
+                       pcap_fmt_errmsg_for_errno(p->errbuf, PCAP_ERRBUF_SIZE,
+                           errno, "read");
                        return (PCAP_ERROR);
                }
-               bp = p->buffer;
+               bp = (u_char *)p->buffer;
        } else
                bp = p->bp;
 
        /*
         * Loop through each packet.
         */
+#ifdef BIOCSTSTAMP
+#define bhp ((struct bpf_xhdr *)bp)
+#else
 #define bhp ((struct bpf_hdr *)bp)
+#endif
        ep = bp + cc;
 #ifdef PCAP_FDDIPAD
        pad = p->fddipad;
 #endif
        while (bp < ep) {
-               register int caplen, hdrlen;
+               register u_int caplen, hdrlen;
 
                /*
                 * Has "pcap_breakloop()" been called?
@@ -1006,7 +1129,25 @@ pcap_read_bpf(pcap_t *p, int cnt, pcap_handler callback, u_char *user)
                if (pb->filtering_in_kernel ||
                    bpf_filter(p->fcode.bf_insns, datap, bhp->bh_datalen, caplen)) {
                        struct pcap_pkthdr pkthdr;
+#ifdef BIOCSTSTAMP
+                       struct bintime bt;
+
+                       bt.sec = bhp->bh_tstamp.bt_sec;
+                       bt.frac = bhp->bh_tstamp.bt_frac;
+                       if (p->opt.tstamp_precision == PCAP_TSTAMP_PRECISION_NANO) {
+                               struct timespec ts;
 
+                               bintime2timespec(&bt, &ts);
+                               pkthdr.ts.tv_sec = ts.tv_sec;
+                               pkthdr.ts.tv_usec = ts.tv_nsec;
+                       } else {
+                               struct timeval tv;
+
+                               bintime2timeval(&bt, &tv);
+                               pkthdr.ts.tv_sec = tv.tv_sec;
+                               pkthdr.ts.tv_usec = tv.tv_usec;
+                       }
+#else
                        pkthdr.ts.tv_sec = bhp->bh_tstamp.tv_sec;
 #ifdef _AIX
                        /*
@@ -1017,6 +1158,7 @@ pcap_read_bpf(pcap_t *p, int cnt, pcap_handler callback, u_char *user)
 #else
                        pkthdr.ts.tv_usec = bhp->bh_tstamp.tv_usec;
 #endif
+#endif /* BIOCSTSTAMP */
 #ifdef PCAP_FDDIPAD
                        if (caplen > pad)
                                pkthdr.caplen = caplen - pad;
@@ -1064,13 +1206,13 @@ pcap_inject_bpf(pcap_t *p, const void *buf, size_t size)
 #ifdef __APPLE__
        if (ret == -1 && errno == EAFNOSUPPORT) {
                /*
-                * In Mac OS X, there's a bug wherein setting the
-                * BIOCSHDRCMPLT flag causes writes to fail; see,
-                * for example:
+                * In some versions of macOS, there's a bug wherein setting
+                * the BIOCSHDRCMPLT flag causes writes to fail; see, for
+                * example:
                 *
                 *      http://cerberus.sourcefire.com/~jeff/archives/patches/macosx/BIOCSHDRCMPLT-10.3.3.patch
                 *
-                * So, if, on OS X, we get EAFNOSUPPORT from the write, we
+                * So, if, on macOS, we get EAFNOSUPPORT from the write, we
                 * assume it's due to that bug, and turn off that flag
                 * and try again.  If we succeed, it either means that
                 * somebody applied the fix from that URL, or other patches
@@ -1079,14 +1221,13 @@ pcap_inject_bpf(pcap_t *p, const void *buf, size_t size)
                 *      http://cerberus.sourcefire.com/~jeff/archives/patches/macosx/
                 *
                 * and are running a Darwin kernel with those fixes, or
-                * that Apple fixed the problem in some OS X release.
+                * that Apple fixed the problem in some macOS release.
                 */
                u_int spoof_eth_src = 0;
 
                if (ioctl(p->fd, BIOCSHDRCMPLT, &spoof_eth_src) == -1) {
-                       (void)snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
-                           "send: can't turn off BIOCSHDRCMPLT: %s",
-                           pcap_strerror(errno));
+                       pcap_fmt_errmsg_for_errno(p->errbuf, PCAP_ERRBUF_SIZE,
+                           errno, "send: can't turn off BIOCSHDRCMPLT");
                        return (PCAP_ERROR);
                }
 
@@ -1097,8 +1238,8 @@ 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_strerror(errno));
+               pcap_fmt_errmsg_for_errno(p->errbuf, PCAP_ERRBUF_SIZE,
+                   errno, "send");
                return (PCAP_ERROR);
        }
        return (ret);
@@ -1113,7 +1254,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);
@@ -1122,7 +1263,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();
@@ -1141,7 +1282,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);
                }
@@ -1152,7 +1293,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);
                }
@@ -1186,8 +1327,8 @@ bpf_load(char *errbuf)
 
        major = genmajor(BPF_NAME);
        if (major == -1) {
-               snprintf(errbuf, PCAP_ERRBUF_SIZE,
-                   "bpf_load: genmajor failed: %s", pcap_strerror(errno));
+               pcap_fmt_errmsg_for_errno(errbuf, PCAP_ERRBUF_SIZE,
+                   errno, "bpf_load: genmajor failed");
                (void)bpf_odmcleanup(NULL);
                return (PCAP_ERROR);
        }
@@ -1196,9 +1337,8 @@ bpf_load(char *errbuf)
        if (!minors) {
                minors = genminor("bpf", major, 0, BPF_MINORS, 1, 1);
                if (!minors) {
-                       snprintf(errbuf, PCAP_ERRBUF_SIZE,
-                           "bpf_load: genminor failed: %s",
-                           pcap_strerror(errno));
+                       pcap_fmt_errmsg_for_errno(errbuf, PCAP_ERRBUF_SIZE,
+                           errno, "bpf_load: genminor failed");
                        (void)bpf_odmcleanup(NULL);
                        return (PCAP_ERROR);
                }
@@ -1209,20 +1349,19 @@ bpf_load(char *errbuf)
 
        rc = stat(BPF_NODE "0", &sbuf);
        if (rc == -1 && errno != ENOENT) {
-               snprintf(errbuf, PCAP_ERRBUF_SIZE,
-                   "bpf_load: can't stat %s: %s",
-                   BPF_NODE "0", pcap_strerror(errno));
+               pcap_fmt_errmsg_for_errno(errbuf, PCAP_ERRBUF_SIZE,
+                   errno, "bpf_load: can't stat %s", BPF_NODE "0");
                return (PCAP_ERROR);
        }
 
        if (rc == -1 || getmajor(sbuf.st_rdev) != major) {
                for (i = 0; i < BPF_MINORS; i++) {
-                       sprintf(buf, "%s%d", BPF_NODE, i);
+                       pcap_snprintf(buf, sizeof(buf), "%s%d", BPF_NODE, i);
                        unlink(buf);
                        if (mknod(buf, S_IRUSR | S_IFCHR, domakedev(major, i)) == -1) {
-                               snprintf(errbuf, PCAP_ERRBUF_SIZE,
-                                   "bpf_load: can't mknod %s: %s",
-                                   buf, pcap_strerror(errno));
+                               pcap_fmt_errmsg_for_errno(errbuf,
+                                   PCAP_ERRBUF_SIZE, errno,
+                                   "bpf_load: can't mknod %s", buf);
                                return (PCAP_ERROR);
                        }
                }
@@ -1230,15 +1369,14 @@ bpf_load(char *errbuf)
 
        /* Check if the driver is loaded */
        memset(&cfg_ld, 0x0, sizeof(cfg_ld));
+       pcap_snprintf(buf, sizeof(buf), "%s/%s", DRIVER_PATH, BPF_NAME);
        cfg_ld.path = buf;
-       sprintf(cfg_ld.path, "%s/%s", DRIVER_PATH, BPF_NAME);
        if ((sysconfig(SYS_QUERYLOAD, (void *)&cfg_ld, sizeof(cfg_ld)) == -1) ||
            (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,
-                           "bpf_load: could not load driver: %s",
-                           strerror(errno));
+                       pcap_fmt_errmsg_for_errno(errbuf, PCAP_ERRBUF_SIZE,
+                           errno, "bpf_load: could not load driver");
                        return (PCAP_ERROR);
                }
        }
@@ -1251,9 +1389,8 @@ 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,
-                           "bpf_load: could not configure driver: %s",
-                           strerror(errno));
+                       pcap_fmt_errmsg_for_errno(errbuf, PCAP_ERRBUF_SIZE,
+                           errno, "bpf_load: could not configure driver");
                        return (PCAP_ERROR);
                }
        }
@@ -1265,7 +1402,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)
@@ -1333,6 +1470,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) {
+                                       pcap_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.
@@ -1378,7 +1533,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
@@ -1388,9 +1543,9 @@ check_setif_failure(pcap_t *p, int error)
                         */
                        fd = socket(AF_INET, SOCK_DGRAM, 0);
                        if (fd != -1) {
-                               strlcpy(ifr.ifr_name, "en",
+                               pcap_strlcpy(ifr.ifr_name, "en",
                                    sizeof(ifr.ifr_name));
-                               strlcat(ifr.ifr_name, p->opt.source + 3,
+                               pcap_strlcat(ifr.ifr_name, p->opt.device + 3,
                                    sizeof(ifr.ifr_name));
                                if (ioctl(fd, SIOCGIFFLAGS, (char *)&ifr) < 0) {
                                        /*
@@ -1399,9 +1554,10 @@ check_setif_failure(pcap_t *p, int error)
                                         * exist.
                                         */
                                        err = PCAP_ERROR_NO_SUCH_DEVICE;
-                                       snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
-                                           "SIOCGIFFLAGS on %s failed: %s",
-                                           ifr.ifr_name, pcap_strerror(errno));
+                                       pcap_fmt_errmsg_for_errno(p->errbuf,
+                                           PCAP_ERRBUF_SIZE, errno,
+                                           "SIOCGIFFLAGS on %s failed",
+                                           ifr.ifr_name);
                                } else {
                                        /*
                                         * The underlying "enN" device
@@ -1423,9 +1579,9 @@ 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,
-                                   "socket() failed: %s",
-                                   pcap_strerror(errno));
+                               pcap_fmt_errmsg_for_errno(p->errbuf,
+                                   errno, PCAP_ERRBUF_SIZE,
+                                   "socket() failed");
                        }
                        return (err);
                }
@@ -1433,8 +1589,8 @@ check_setif_failure(pcap_t *p, int error)
                /*
                 * No such device.
                 */
-               snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "BIOCSETIF failed: %s",
-                   pcap_strerror(errno));
+               pcap_fmt_errmsg_for_errno(p->errbuf, PCAP_ERRBUF_SIZE,
+                   errno, "BIOCSETIF failed");
                return (PCAP_ERROR_NO_SUCH_DEVICE);
        } else if (errno == ENETDOWN) {
                /*
@@ -1450,8 +1606,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_fmt_errmsg_for_errno(p->errbuf, PCAP_ERRBUF_SIZE,
+                   errno, "BIOCSETIF: %s", p->opt.device);
                return (PCAP_ERROR);
        }
 }
@@ -1514,7 +1670,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;
@@ -1523,46 +1679,83 @@ 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_strerror(errno));
+               pcap_fmt_errmsg_for_errno(p->errbuf, PCAP_ERRBUF_SIZE,
+                   errno, "BIOCVERSION");
                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;
        }
 
+       /*
+        * Turn a negative snapshot value (invalid), a snapshot value of
+        * 0 (unspecified), or a value bigger than the normal maximum
+        * value, into the maximum allowed value.
+        *
+        * If some application really *needs* a bigger snapshot
+        * length, we should just increase MAXIMUM_SNAPLEN.
+        */
+       if (p->snapshot <= 0 || p->snapshot > MAXIMUM_SNAPLEN)
+               p->snapshot = MAXIMUM_SNAPLEN;
+
 #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_fmt_errmsg_for_errno(p->errbuf, PCAP_ERRBUF_SIZE,
+                   errno, "getzoneid()");
+               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) pcap_strlcpy(path_zname, p->opt.device, znamelen + 1);
+               ifr.lifr_zoneid = getzoneidbyname(path_zname);
+               if (ifr.lifr_zoneid == -1) {
+                       pcap_fmt_errmsg_for_errno(p->errbuf, PCAP_ERRBUF_SIZE,
+                           errno, "getzoneidbyname(%s)", path_zname);
+                       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_fmt_errmsg_for_errno(p->errbuf, PCAP_ERRBUF_SIZE,
+                           errno, "strdup");
+                       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_strerror(errno));
+               pcap_fmt_errmsg_for_errno(p->errbuf, PCAP_ERRBUF_SIZE,
+                   errno, "strdup");
                status = PCAP_ERROR;
                goto bad;
        }
@@ -1597,15 +1790,15 @@ 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.
                                         */
                                        sockfd = socket(AF_INET, SOCK_DGRAM, 0);
                                        if (sockfd != -1) {
-                                               strlcpy(ifrname,
-                                                   p->opt.source, ifnamsiz);
+                                               pcap_strlcpy(ifrname,
+                                                   p->opt.device, ifnamsiz);
                                                if (ioctl(sockfd, SIOCGIFFLAGS,
                                                    (char *)&ifr) < 0) {
                                                        /*
@@ -1616,10 +1809,10 @@ pcap_activate_bpf(pcap_t *p)
                                                         * exist.
                                                         */
                                                        status = PCAP_ERROR_NO_SUCH_DEVICE;
-                                                       snprintf(p->errbuf,
+                                                       pcap_fmt_errmsg_for_errno(p->errbuf,
                                                            PCAP_ERRBUF_SIZE,
-                                                           "SIOCGIFFLAGS failed: %s",
-                                                           pcap_strerror(errno));
+                                                           errno,
+                                                           "SIOCGIFFLAGS failed");
                                                } else
                                                        status = PCAP_ERROR_RFMON_NOTSUP;
                                                close(sockfd);
@@ -1630,25 +1823,24 @@ pcap_activate_bpf(pcap_t *p)
                                                 * report "no such device".
                                                 */
                                                status = PCAP_ERROR_NO_SUCH_DEVICE;
-                                               snprintf(p->errbuf,
-                                                   PCAP_ERRBUF_SIZE,
-                                                   "socket() failed: %s",
-                                                   pcap_strerror(errno));
+                                               pcap_fmt_errmsg_for_errno(p->errbuf,
+                                                   PCAP_ERRBUF_SIZE, errno,
+                                                   "socket() failed");
                                        }
                                        goto bad;
                                }
-                               wltdev = malloc(strlen(p->opt.source) + 2);
+                               wltdev = malloc(strlen(p->opt.device) + 2);
                                if (wltdev == NULL) {
-                                       (void)snprintf(p->errbuf,
-                                           PCAP_ERRBUF_SIZE, "malloc: %s",
-                                           pcap_strerror(errno));
+                                       pcap_fmt_errmsg_for_errno(p->errbuf,
+                                           PCAP_ERRBUF_SIZE, errno,
+                                           "malloc");
                                        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,
@@ -1657,6 +1849,86 @@ 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_fmt_errmsg_for_errno(p->errbuf,
+                                   PCAP_ERRBUF_SIZE, errno,
+                                   "Can't open socket");
+                               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.
+                        */
+                       pcap_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_fmt_errmsg_for_errno(p->errbuf,
+                                           PCAP_ERRBUF_SIZE, errno,
+                                           "Can't create interface for %s",
+                                           p->opt.device);
+                               }
+                               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
@@ -1680,8 +1952,8 @@ pcap_activate_bpf(pcap_t *p)
                 * size.
                 */
                if (ioctl(fd, BIOCGETZMAX, (caddr_t)&zbufmax) < 0) {
-                       snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "BIOCGETZMAX: %s",
-                           pcap_strerror(errno));
+                       pcap_fmt_errmsg_for_errno(p->errbuf, PCAP_ERRBUF_SIZE,
+                           errno, "BIOCGETZMAX");
                        status = PCAP_ERROR;
                        goto bad;
                }
@@ -1707,8 +1979,8 @@ 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_strerror(errno));
+                       pcap_fmt_errmsg_for_errno(p->errbuf, PCAP_ERRBUF_SIZE,
+                           errno, "mmap");
                        status = PCAP_ERROR;
                        goto bad;
                }
@@ -1717,15 +1989,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_strerror(errno));
+                       pcap_fmt_errmsg_for_errno(p->errbuf, PCAP_ERRBUF_SIZE,
+                           errno, "BIOCSETZBUF");
                        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_fmt_errmsg_for_errno(p->errbuf, PCAP_ERRBUF_SIZE,
+                           errno, "BIOCSETIF: %s", p->opt.device);
                        status = PCAP_ERROR;
                        goto bad;
                }
@@ -1743,9 +2015,9 @@ 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_strerror(errno));
+                               pcap_fmt_errmsg_for_errno(p->errbuf,
+                                   PCAP_ERRBUF_SIZE, errno,
+                                   "BIOCSBLEN: %s", p->opt.device);
                                status = PCAP_ERROR;
                                goto bad;
                        }
@@ -1753,7 +2025,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
@@ -1786,7 +2058,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
@@ -1801,9 +2073,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;
                        }
@@ -1812,8 +2084,8 @@ 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_strerror(errno));
+               pcap_fmt_errmsg_for_errno(p->errbuf, PCAP_ERRBUF_SIZE,
+                   errno, "BIOCGDLT");
                status = PCAP_ERROR;
                goto bad;
        }
@@ -1845,7 +2117,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;
@@ -1926,14 +2198,14 @@ pcap_activate_bpf(pcap_t *p)
                                         * of link-layer types, as selecting
                                         * it will keep monitor mode off.
                                         */
-                                       remove_en(p);
+                                       remove_non_802_11(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) {
                                                        /*
@@ -2005,7 +2277,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
@@ -2057,8 +2329,8 @@ 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,
-                   "BIOCSHDRCMPLT: %s", pcap_strerror(errno));
+               pcap_fmt_errmsg_for_errno(p->errbuf, PCAP_ERRBUF_SIZE,
+                   errno, "BIOCSHDRCMPLT");
                status = PCAP_ERROR;
                goto bad;
        }
@@ -2099,8 +2371,8 @@ 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,
-                                   "BIOCSRTIMEOUT: %s", pcap_strerror(errno));
+                               pcap_fmt_errmsg_for_errno(p->errbuf,
+                                   errno, PCAP_ERRBUF_SIZE, "BIOCSRTIMEOUT");
                                status = PCAP_ERROR;
                                goto bad;
                        }
@@ -2109,8 +2381,8 @@ 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,
-                                   "BIOCSRTIMEOUT: %s", pcap_strerror(errno));
+                               pcap_fmt_errmsg_for_errno(p->errbuf,
+                                   errno, PCAP_ERRBUF_SIZE, "BIOCSRTIMEOUT");
                                status = PCAP_ERROR;
                                goto bad;
                        }
@@ -2144,8 +2416,8 @@ pcap_activate_bpf(pcap_t *p)
 #endif /* _AIX */
                v = 1;
                if (ioctl(p->fd, BIOCIMMEDIATE, &v) < 0) {
-                       snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
-                           "BIOCIMMEDIATE: %s", pcap_strerror(errno));
+                       pcap_fmt_errmsg_for_errno(p->errbuf, PCAP_ERRBUF_SIZE,
+                           errno, "BIOCIMMEDIATE");
                        status = PCAP_ERROR;
                        goto bad;
                }
@@ -2157,7 +2429,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;
        }
@@ -2166,15 +2438,25 @@ 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_strerror(errno));
+                       pcap_fmt_errmsg_for_errno(p->errbuf, PCAP_ERRBUF_SIZE,
+                           errno, "BIOCPROMISC");
                        status = PCAP_WARNING_PROMISC_NOTSUP;
                }
        }
 
+#ifdef BIOCSTSTAMP
+       v = BPF_T_BINTIME;
+       if (ioctl(p->fd, BIOCSTSTAMP, &v) < 0) {
+               pcap_fmt_errmsg_for_errno(p->errbuf, PCAP_ERRBUF_SIZE,
+                   errno, "BIOCSTSTAMP");
+               status = PCAP_ERROR;
+               goto bad;
+       }
+#endif /* BIOCSTSTAMP */
+
        if (ioctl(fd, BIOCGBLEN, (caddr_t)&v) < 0) {
-               snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "BIOCGBLEN: %s",
-                   pcap_strerror(errno));
+               pcap_fmt_errmsg_for_errno(p->errbuf, PCAP_ERRBUF_SIZE,
+                   errno, "BIOCGBLEN");
                status = PCAP_ERROR;
                goto bad;
        }
@@ -2182,10 +2464,10 @@ 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_strerror(errno));
+               pcap_fmt_errmsg_for_errno(p->errbuf, PCAP_ERRBUF_SIZE,
+                   errno, "malloc");
                status = PCAP_ERROR;
                goto bad;
        }
@@ -2215,8 +2497,8 @@ 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_strerror(errno));
+               pcap_fmt_errmsg_for_errno(p->errbuf, PCAP_ERRBUF_SIZE,
+                   errno, "BIOCSETF");
                status = PCAP_ERROR;
                goto bad;
        }
@@ -2285,9 +2567,299 @@ 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];
+
+       /*
+        * On macOS, we don't do this check if the device name begins
+        * with "wlt"; at least some versions of macOS (actually, it
+        * was called "Mac OS X" then...) 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) {
+                       pcap_fmt_errmsg_for_errno(errbuf, PCAP_ERRBUF_SIZE,
+                           errno, "malloc");
+                       return (-1);
+               }
+               strcpy(en_name, "en");
+               strcat(en_name, name + 3);
+               fd = bpf_open_and_bind(en_name, errbuf);
+               free(en_name);
+       } else
+#endif /* __APPLE */
+       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
+get_usb_if_flags(const char *name _U_, bpf_u_int32 *flags _U_, char *errbuf _U_)
+{
+       /*
+        * XXX - if there's a way to determine whether there's something
+        * plugged into a given USB bus, use that to determine whether
+        * this device is "connected" or not.
+        */
+       return (0);
+}
+
+static int
+finddevs_usb(pcap_if_list_t *devlistp, 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;
+
+               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';
+               /*
+                * There's an entry in this directory for every USB device,
+                * not for every bus; if there's more than one device on
+                * the bus, there'll be more than one entry for that bus,
+                * so we need to avoid adding multiple capture devices
+                * for each bus.
+                */
+               if (find_or_add_dev(devlistp, name, PCAP_IF_UP,
+                   get_usb_if_flags, NULL, errbuf) == NULL) {
+                       free(name);
+                       closedir(usbdir);
+                       return (PCAP_ERROR);
+               }
+       }
+       free(name);
+       closedir(usbdir);
+       return (0);
+}
+#endif
+
+/*
+ * Get additional flags for a device, using SIOCGIFMEDIA.
+ */
+#ifdef SIOCGIFMEDIA
+static int
+get_if_flags(const char *name, bpf_u_int32 *flags, char *errbuf)
+{
+       int sock;
+       struct ifmediareq req;
+
+       sock = socket(AF_INET, SOCK_DGRAM, 0);
+       if (sock == -1) {
+               pcap_fmt_errmsg_for_errno(errbuf, PCAP_ERRBUF_SIZE, errno,
+                   "Can't create socket to get media information for %s",
+                   name);
+               return (-1);
+       }
+       memset(&req, 0, sizeof(req));
+       strncpy(req.ifm_name, name, sizeof(req.ifm_name));
+       if (ioctl(sock, SIOCGIFMEDIA, &req) < 0) {
+               if (errno == EOPNOTSUPP || errno == EINVAL || errno == ENOTTY ||
+                   errno == ENODEV || errno == EPERM) {
+                       /*
+                        * Not supported, so we can't provide any
+                        * additional information.  Assume that
+                        * this means that "connected" vs.
+                        * "disconnected" doesn't apply.
+                        *
+                        * The ioctl routine for Apple's pktap devices,
+                        * annoyingly, checks for "are you root?" before
+                        * checking whether the ioctl is valid, so it
+                        * returns EPERM, rather than ENOTSUP, for the
+                        * invalid SIOCGIFMEDIA, unless you're root.
+                        * So, just as we do for some ethtool ioctls
+                        * on Linux, which makes the same mistake, we
+                        * also treat EPERM as meaning "not supported".
+                        */
+                       *flags |= PCAP_IF_CONNECTION_STATUS_NOT_APPLICABLE;
+                       close(sock);
+                       return (0);
+               }
+               pcap_fmt_errmsg_for_errno(errbuf, PCAP_ERRBUF_SIZE, errno,
+                   "SIOCGIFMEDIA on %s failed", name);
+               close(sock);
+               return (-1);
+       }
+       close(sock);
+
+       /*
+        * OK, what type of network is this?
+        */
+       switch (IFM_TYPE(req.ifm_active)) {
+
+       case IFM_IEEE80211:
+               /*
+                * Wireless.
+                */
+               *flags |= PCAP_IF_WIRELESS;
+               break;
+       }
+
+       /*
+        * Do we know whether it's connected?
+        */
+       if (req.ifm_status & IFM_AVALID) {
+               /*
+                * Yes.
+                */
+               if (req.ifm_status & IFM_ACTIVE) {
+                       /*
+                        * It's connected.
+                        */
+                       *flags |= PCAP_IF_CONNECTION_STATUS_CONNECTED;
+               } else {
+                       /*
+                        * It's disconnected.
+                        */
+                       *flags |= PCAP_IF_CONNECTION_STATUS_DISCONNECTED;
+               }
+       }
+       return (0);
+}
+#else
+static int
+get_if_flags(const char *name _U_, bpf_u_int32 *flags _U_, char *errbuf _U_)
+{
+       /*
+        * Nothing we can do other than mark loopback devices as "the
+        * connected/disconnected status doesn't apply".
+        *
+        * XXX - on Solaris, can we do what the dladm command does,
+        * i.e. get a connected/disconnected indication from a kstat?
+        * (Note that you can also get the link speed, and possibly
+        * other information, from a kstat as well.)
+        */
+       if (*flags & PCAP_IF_LOOPBACK) {
+               /*
+                * Loopback devices aren't wireless, and "connected"/
+                * "disconnected" doesn't apply to them.
+                */
+               *flags |= PCAP_IF_CONNECTION_STATUS_NOT_APPLICABLE;
+               return (0);
+       }
+       return (0);
+}
+#endif
+
 int
-pcap_platform_finddevs(pcap_if_t **alldevsp, char *errbuf)
+pcap_platform_finddevs(pcap_if_list_t *devlistp, char *errbuf)
 {
+       /*
+        * Get the list of regular interfaces first.
+        */
+       if (pcap_findalldevs_interfaces(devlistp, errbuf, check_bpf_bindable,
+           get_if_flags) == -1)
+               return (-1);    /* failure */
+
+#if defined(__FreeBSD__) && defined(SIOCIFCREATE2)
+       if (finddevs_usb(devlistp, errbuf) == -1)
+               return (-1);
+#endif
+
        return (0);
 }
 
@@ -2298,20 +2870,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_strerror(errno));
+               pcap_fmt_errmsg_for_errno(p->errbuf, PCAP_ERRBUF_SIZE,
+                   errno, "can't open socket");
                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.
@@ -2337,8 +2909,8 @@ monitor_mode(pcap_t *p, int set)
                        return (PCAP_ERROR_RFMON_NOTSUP);
 
                default:
-                       snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
-                           "SIOCGIFMEDIA 1: %s", pcap_strerror(errno));
+                       pcap_fmt_errmsg_for_errno(p->errbuf, PCAP_ERRBUF_SIZE,
+                           errno, "SIOCGIFMEDIA");
                        close(sock);
                        return (PCAP_ERROR);
                }
@@ -2355,17 +2927,17 @@ 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_strerror(errno));
+               pcap_fmt_errmsg_for_errno(p->errbuf, PCAP_ERRBUF_SIZE,
+                   errno, "malloc");
                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_strerror(errno));
+               pcap_fmt_errmsg_for_errno(p->errbuf, PCAP_ERRBUF_SIZE,
+                   errno, "SIOCGIFMEDIA");
                free(media_list);
                close(sock);
                return (PCAP_ERROR);
@@ -2417,18 +2989,16 @@ 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,
-                                    "SIOCSIFMEDIA: %s", pcap_strerror(errno));
+                               pcap_fmt_errmsg_for_errno(p->errbuf,
+                                   PCAP_ERRBUF_SIZE, errno, "SIOCSIFMEDIA");
                                close(sock);
                                return (PCAP_ERROR);
                        }
@@ -2460,7 +3030,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,
@@ -2482,8 +3052,12 @@ find_802_11(struct bpf_dltlist *bdlp)
                                new_dlt = bdlp->bfl_list[i];
                        break;
 
+#ifdef DLT_PRISM_HEADER
                case DLT_PRISM_HEADER:
+#endif
+#ifdef DLT_AIRONET_HEADER
                case DLT_AIRONET_HEADER:
+#endif
                case DLT_IEEE802_11_RADIO_AVS:
                        /*
                         * 802.11 with radio, but not radiotap.
@@ -2518,24 +3092,25 @@ find_802_11(struct bpf_dltlist *bdlp)
 
 #if defined(__APPLE__) && defined(BIOCGDLTLIST)
 /*
- * Remove DLT_EN10MB from the list of DLT_ values, as we're in monitor mode,
- * and DLT_EN10MB isn't supported in monitor mode.
+ * Remove non-802.11 header types from the list of DLT_ values, as we're in
+ * monitor mode, and those header types aren't supported in monitor mode.
  */
 static void
-remove_en(pcap_t *p)
+remove_non_802_11(pcap_t *p)
 {
        int i, j;
 
        /*
-        * Scan the list of DLT_ values and discard DLT_EN10MB.
+        * Scan the list of DLT_ values and discard non-802.11 ones.
         */
        j = 0;
        for (i = 0; i < p->dlt_count; i++) {
                switch (p->dlt_list[i]) {
 
                case DLT_EN10MB:
+               case DLT_RAW:
                        /*
-                        * Don't offer this one.
+                        * Not 802.11.  Don't offer this one.
                         */
                        continue;
 
@@ -2577,10 +3152,17 @@ remove_802_11(pcap_t *p)
                switch (p->dlt_list[i]) {
 
                case DLT_IEEE802_11:
+#ifdef DLT_PRISM_HEADER
                case DLT_PRISM_HEADER:
+#endif
+#ifdef DLT_AIRONET_HEADER
                case DLT_AIRONET_HEADER:
+#endif
                case DLT_IEEE802_11_RADIO:
                case DLT_IEEE802_11_RADIO_AVS:
+#ifdef DLT_PPI
+               case DLT_PPI:
+#endif
                        /*
                         * 802.11.  Don't offer this one.
                         */
@@ -2652,8 +3234,8 @@ pcap_setfilter_bpf(pcap_t *p, struct bpf_program *fp)
         * some kernels.
         */
        if (errno != EINVAL) {
-               snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "BIOCSETF: %s",
-                   pcap_strerror(errno));
+               pcap_fmt_errmsg_for_errno(p->errbuf, PCAP_ERRBUF_SIZE,
+                   errno, "BIOCSETF");
                return (-1);
        }
 
@@ -2672,60 +3254,85 @@ pcap_setfilter_bpf(pcap_t *p, struct bpf_program *fp)
  * Set direction flag: Which packets do we accept on a forwarding
  * single device? IN, OUT or both?
  */
+#if defined(BIOCSDIRECTION)
 static int
 pcap_setdirection_bpf(pcap_t *p, pcap_direction_t d)
 {
-#if defined(BIOCSDIRECTION)
        u_int direction;
 
        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),
-                   "Cannot set direction to %s: %s",
+               pcap_fmt_errmsg_for_errno(p->errbuf, sizeof(p->errbuf),
+                   errno, "Cannot set direction to %s",
                        (d == PCAP_D_IN) ? "PCAP_D_IN" :
-                       ((d == PCAP_D_OUT) ? "PCAP_D_OUT" : "PCAP_D_INOUT"),
-                       strerror(errno));
+                       ((d == PCAP_D_OUT) ? "PCAP_D_OUT" : "PCAP_D_INOUT"));
                return (-1);
        }
        return (0);
+}
 #elif defined(BIOCSSEESENT)
+static int
+pcap_setdirection_bpf(pcap_t *p, pcap_direction_t d)
+{
        u_int seesent;
 
        /*
         * 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),
-                   "Cannot set direction to %s: %s",
-                       (d == PCAP_D_INOUT) ? "PCAP_D_INOUT" : "PCAP_D_IN",
-                       strerror(errno));
+               pcap_fmt_errmsg_for_errno(p->errbuf, sizeof(p->errbuf),
+                   errno, "Cannot set direction to %s",
+                   (d == PCAP_D_INOUT) ? "PCAP_D_INOUT" : "PCAP_D_IN");
                return (-1);
        }
        return (0);
+}
 #else
-       (void) snprintf(p->errbuf, sizeof(p->errbuf),
+static int
+pcap_setdirection_bpf(pcap_t *p, pcap_direction_t d _U_)
+{
+       (void) pcap_snprintf(p->errbuf, sizeof(p->errbuf),
            "This system doesn't support BIOCSSEESENT, so the direction can't be set");
        return (-1);
-#endif
 }
+#endif
 
+#ifdef BIOCSDLT
 static int
 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),
-                   "Cannot set DLT %d: %s", dlt, strerror(errno));
+               pcap_fmt_errmsg_for_errno(p->errbuf, sizeof(p->errbuf),
+                   errno, "Cannot set DLT %d", dlt);
                return (-1);
        }
-#endif
        return (0);
 }
+#else
+static int
+pcap_set_datalink_bpf(pcap_t *p _U_, int dlt _U_)
+{
+       return (0);
+}
+#endif
+
+/*
+ * Platform-specific information.
+ */
+const char *
+pcap_lib_version(void)
+{
+#ifdef HAVE_ZEROCOPY_BPF
+       return (PCAP_VERSION_STRING " (with zerocopy support)");
+#else
+       return (PCAP_VERSION_STRING);
+#endif
+}
index 9374522..ebb64c3 100644 (file)
@@ -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
index a32691d..9c8712e 100644 (file)
@@ -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
  * By Paolo Abeni <paolo.abeni@email.it>
  *
  */
+
 #ifdef HAVE_CONFIG_H
-#include "config.h"
+#include <config.h>
 #endif
 
 #include "pcap-int.h"
 #include "pcap-bt-linux.h"
 #include "pcap/bluetooth.h"
 
-#ifdef NEED_STRERROR_H
-#include "strerror.h"
-#endif
-
 #include <errno.h>
 #include <stdlib.h>
 #include <unistd.h>
@@ -73,29 +69,30 @@ struct pcap_bt {
        int dev_id;             /* device ID of device we're bound to */
 };
 
-int 
-bt_findalldevs(pcap_if_t **alldevsp, char *err_str)
+int
+bt_findalldevs(pcap_if_list_t *devlistp, char *err_str)
 {
        struct hci_dev_list_req *dev_list;
        struct hci_dev_req *dev_req;
-       int i, sock;
+       int sock;
+       unsigned i;
        int ret = 0;
 
        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 is not fatal*/
                if (errno == EAFNOSUPPORT)
                        return 0;
-               snprintf(err_str, PCAP_ERRBUF_SIZE,
-                   "Can't open raw Bluetooth socket: %s", strerror(errno));
+               pcap_fmt_errmsg_for_errno(err_str, PCAP_ERRBUF_SIZE,
+                   errno, "Can't open raw Bluetooth socket");
                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,29 +100,34 @@ 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,
-                   "Can't get Bluetooth device list via ioctl: %s",
-                   strerror(errno));
+               pcap_fmt_errmsg_for_errno(err_str, PCAP_ERRBUF_SIZE,
+                   errno, "Can't get Bluetooth device list via ioctl");
                ret = -1;
                goto free;
        }
 
        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, 
-                      dev_descr, err_str) < 0)
+               char dev_name[20], dev_descr[40];
+
+               pcap_snprintf(dev_name, sizeof(dev_name), BT_IFACE"%u", dev_req->dev_id);
+               pcap_snprintf(dev_descr, sizeof(dev_descr), "Bluetooth adapter number %u", i);
+
+               /*
+                * Bluetooth is a wireless technology.
+                * XXX - if there's the notion of associating with a
+                * network, and we can determine whether the interface
+                * is associated with a network, check that and set
+                * the status to PCAP_IF_CONNECTION_STATUS_CONNECTED
+                * or PCAP_IF_CONNECTION_STATUS_DISCONNECTED.
+                */
+               if (add_dev(devlistp, dev_name, PCAP_IF_WIRELESS, dev_descr, err_str)  == NULL)
                {
                        ret = -1;
                        break;
                }
-
        }
 
 free:
@@ -171,7 +173,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 +192,27 @@ 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;
        }
 
+       /*
+        * Turn a negative snapshot value (invalid), a snapshot value of
+        * 0 (unspecified), or a value bigger than the normal maximum
+        * value, into the maximum allowed value.
+        *
+        * If some application really *needs* a bigger snapshot
+        * length, we should just increase MAXIMUM_SNAPLEN.
+        */
+       if (handle->snapshot <= 0 || handle->snapshot > MAXIMUM_SNAPLEN)
+               handle->snapshot = MAXIMUM_SNAPLEN;
+
        /* 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,44 +224,44 @@ 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,
-                   "Can't create raw socket: %s", strerror(errno));
+               pcap_fmt_errmsg_for_errno(handle->errbuf, PCAP_ERRBUF_SIZE,
+                   errno, "Can't create raw socket");
                return PCAP_ERROR;
        }
 
        handle->buffer = malloc(handle->bufsize);
        if (!handle->buffer) {
-               snprintf(handle->errbuf, PCAP_ERRBUF_SIZE, "Can't allocate dump buffer: %s",
-                       pcap_strerror(errno));
+               pcap_fmt_errmsg_for_errno(handle->errbuf, PCAP_ERRBUF_SIZE,
+                   errno, "Can't allocate dump buffer");
                goto close_fail;
        }
 
        opt = 1;
        if (setsockopt(handle->fd, SOL_HCI, HCI_DATA_DIR, &opt, sizeof(opt)) < 0) {
-               snprintf(handle->errbuf, PCAP_ERRBUF_SIZE,
-                   "Can't enable data direction info: %s", strerror(errno));
+               pcap_fmt_errmsg_for_errno(handle->errbuf, PCAP_ERRBUF_SIZE,
+                   errno, "Can't enable data direction info");
                goto close_fail;
        }
 
        opt = 1;
        if (setsockopt(handle->fd, SOL_HCI, HCI_TIME_STAMP, &opt, sizeof(opt)) < 0) {
-               snprintf(handle->errbuf, PCAP_ERRBUF_SIZE,
-                   "Can't enable time stamp: %s", strerror(errno));
+               pcap_fmt_errmsg_for_errno(handle->errbuf, PCAP_ERRBUF_SIZE,
+                   errno, "Can't enable time stamp");
                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,
-                   "Can't set filter: %s", strerror(errno));
+               pcap_fmt_errmsg_for_errno(handle->errbuf, PCAP_ERRBUF_SIZE,
+                   errno, "Can't set filter");
                goto close_fail;
        }
 
@@ -257,13 +269,12 @@ bt_activate(pcap_t* handle)
        /* Bind socket to the HCI device */
        addr.hci_family = AF_BLUETOOTH;
        addr.hci_dev = handlep->dev_id;
-#ifdef SOCKADDR_HCI_HAS_HCI_CHANNEL
+#ifdef HAVE_STRUCT_SOCKADDR_HCI_HCI_CHANNEL
        addr.hci_channel = HCI_CHANNEL_RAW;
 #endif
        if (bind(handle->fd, (struct sockaddr *) &addr, sizeof(addr)) < 0) {
-               snprintf(handle->errbuf, PCAP_ERRBUF_SIZE,
-                   "Can't attach to device %d: %s", handlep->dev_id,
-                   strerror(errno));
+               pcap_fmt_errmsg_for_errno(handle->errbuf, PCAP_ERRBUF_SIZE,
+                   errno, "Can't attach to device %d", handlep->dev_id);
                goto close_fail;
        }
 
@@ -282,8 +293,8 @@ 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,
-                                "SO_RCVBUF: %s", pcap_strerror(errno));
+                       pcap_fmt_errmsg_for_errno(handle->errbuf,
+                           errno, PCAP_ERRBUF_SIZE, "SO_RCVBUF");
                        goto close_fail;
                }
        }
@@ -297,7 +308,7 @@ close_fail:
 }
 
 static int
-bt_read_linux(pcap_t *handle, int max_packets, pcap_handler callback, u_char *user)
+bt_read_linux(pcap_t *handle, int max_packets _U_, pcap_handler callback, u_char *user)
 {
        struct cmsghdr *cmsg;
        struct msghdr msg;
@@ -305,16 +316,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 +341,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,
-                   "Can't receive packet: %s", strerror(errno));
+               pcap_fmt_errmsg_for_errno(handle->errbuf, PCAP_ERRBUF_SIZE,
+                   errno, "Can't receive packet");
                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 +362,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,24 +370,23 @@ 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 */
 }
 
 static int
-bt_inject_linux(pcap_t *handle, const void *buf, size_t size)
+bt_inject_linux(pcap_t *handle, const void *buf _U_, size_t size _U_)
 {
-       snprintf(handle->errbuf, PCAP_ERRBUF_SIZE, "inject not supported on "
-               "bluetooth devices");
+       pcap_snprintf(handle->errbuf, PCAP_ERRBUF_SIZE,
+           "Packet injection is 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 +394,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,
-                   "Can't get stats via ioctl: %s", strerror(errno));
+               pcap_fmt_errmsg_for_errno(handle->errbuf, PCAP_ERRBUF_SIZE,
+                   errno, "Can't get stats via ioctl");
                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;
index cacbd2f..163bd34 100644 (file)
@@ -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
@@ -34,5 +34,5 @@
 /*
  * Prototypes for Bluetooth-related functions
  */
-int bt_findalldevs(pcap_if_t **alldevsp, char *err_str);
+int bt_findalldevs(pcap_if_list_t *devlistp, char *err_str);
 pcap_t *bt_create(const char *device, char *ebuf, int *is_ours);
index 76c9ee3..a693949 100644 (file)
  */
 
 #ifdef HAVE_CONFIG_H
-#include "config.h"
+#include <config.h>
 #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)
+bt_monitor_findalldevs(pcap_if_list_t *devlistp, char *err_str)
 {
     int         ret = 0;
 
-    if (pcap_add_if(alldevsp, INTERFACE_NAME, 0,
-               "Bluetooth Linux Monitor", err_str) < 0)
+    /*
+     * Bluetooth is a wireless technology.
+     *
+     * This is a device to monitor all Bluetooth interfaces, so
+     * there's no notion of "connected" or "disconnected", any
+     * more than there's a notion of "connected" or "disconnected"
+     * for the "any" device.
+     */
+    if (add_dev(devlistp, INTERFACE_NAME,
+                PCAP_IF_WIRELESS|PCAP_IF_CONNECTION_STATUS_NOT_APPLICABLE,
+                "Bluetooth Linux Monitor", err_str) == NULL)
     {
         ret = -1;
     }
@@ -70,14 +91,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 +107,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 +119,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,
-            "Can't receive packet: %s", strerror(errno));
+        pcap_fmt_errmsg_for_errno(handle->errbuf, PCAP_ERRBUF_SIZE,
+            errno, "Can't receive packet");
         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 +139,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 +149,8 @@ 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,
+        "Packet injection is not supported yet on Bluetooth monitor devices");
     return -1;
 }
 
@@ -161,8 +183,18 @@ 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;
+    /*
+     * Turn a negative snapshot value (invalid), a snapshot value of
+     * 0 (unspecified), or a value bigger than the normal maximum
+     * value, into the maximum allowed value.
+     *
+     * If some application really *needs* a bigger snapshot
+     * length, we should just increase MAXIMUM_SNAPLEN.
+     */
+    if (handle->snapshot <= 0 || handle->snapshot > MAXIMUM_SNAPLEN)
+        handle->snapshot = MAXIMUM_SNAPLEN;
+
+    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,15 +208,15 @@ 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,
-            "Can't create raw socket: %s", strerror(errno));
+        pcap_fmt_errmsg_for_errno(handle->errbuf, PCAP_ERRBUF_SIZE,
+            errno, "Can't create raw socket");
         return PCAP_ERROR;
     }
 
     handle->buffer = malloc(handle->bufsize);
     if (!handle->buffer) {
-        snprintf(handle->errbuf, PCAP_ERRBUF_SIZE, "Can't allocate dump buffer: %s",
-            pcap_strerror(errno));
+        pcap_fmt_errmsg_for_errno(handle->errbuf, PCAP_ERRBUF_SIZE,
+            errno, "Can't allocate dump buffer");
         goto close_fail;
     }
 
@@ -194,15 +226,15 @@ 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,
-            "Can't attach to interface: %s", strerror(errno));
+        pcap_fmt_errmsg_for_errno(handle->errbuf, PCAP_ERRBUF_SIZE,
+            errno, "Can't attach to interface");
         goto close_fail;
     }
 
     opt = 1;
     if (setsockopt(handle->fd, SOL_SOCKET, SO_TIMESTAMP, &opt, sizeof(opt)) < 0) {
-        snprintf(handle->errbuf, PCAP_ERRBUF_SIZE,
-            "Can't enable time stamp: %s", strerror(errno));
+        pcap_fmt_errmsg_for_errno(handle->errbuf, PCAP_ERRBUF_SIZE,
+            errno, "Can't enable time stamp");
         goto close_fail;
     }
 
@@ -231,7 +263,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;
 
index aada2bc..8133710 100644 (file)
@@ -28,5 +28,5 @@
  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  */
 
-int bt_monitor_findalldevs(pcap_if_t **alldevsp, char *err_str);
+int bt_monitor_findalldevs(pcap_if_list_t *devlistp, char *err_str);
 pcap_t *bt_monitor_create(const char *device, char *ebuf, int *is_ours);
diff --git a/pcap-can-linux.c b/pcap-can-linux.c
deleted file mode 100644 (file)
index 3a9e8cb..0000000
+++ /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/pcap-canusb-linux.c b/pcap-canusb-linux.c
deleted file mode 100644 (file)
index a72f469..0000000
+++ /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 */
index a68e032..2a745f0 100644 (file)
  * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
  * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
  *
- * pcap-common.c - common code for pcap and pcap-ng files
+ * pcap-common.c - common code for pcap and pcapng files
  */
 
 #ifdef HAVE_CONFIG_H
-#include "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>
-#endif
-#include <sys/types.h>
-#endif /* WIN32 */
+#include <pcap-types.h>
 
 #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"
 
 
 #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
 
 /*
  * 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
 
 /*
  * 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)
  */
 #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
 
 /*
  * 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).
  */
 
 /*
  * IEEE 802.15.4, exactly as it appears in the spec (no padding, no
- * nothing); requested by Mikko Saarnivala <mikko.saarnivala@sensinode.com>.
+ * nothing), and with the FCS at the end of the frame; requested by
+ * Mikko Saarnivala <mikko.saarnivala@sensinode.com>.
+ *
+ * This should only be used if the FCS is present at the end of the
+ * frame; if the frame has no FCS, DLT_IEEE802_15_4_NOFCS should be
+ * used.
  */
-#define LINKTYPE_IEEE802_15_4  195
+#define LINKTYPE_IEEE802_15_4_WITHFCS  195
 
 /*
  * Various link-layer types, with a pseudo-header, for SITA
 #define LINKTYPE_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>.
+ * IPMB packet for IPMI, beginning with a 2-byte header, followed by
+ * the I2C slave address, followed by the netFn and LUN, etc..
+ * Requested by Chanthy Toeung <chanthy.toeung@ca.kontron.com>.
+ *
+ * XXX - its DLT_ value used to be called DLT_IPMB, back when we got the
+ * impression from the email thread requesting it that the packet
+ * had no extra 2-byte header.  We've renamed it; if anybody used
+ * DLT_IPMB and assumed no 2-byte header, this will cause the compile
+ * to fail, at which point we'll have to figure out what to do about
+ * the two header types using the same DLT_/LINKTYPE_ value.  If that
+ * doesn't happen, we'll assume nobody used it and that the redefinition
+ * is safe.
  */
-#define LINKTYPE_IPMB          199
+#define LINKTYPE_IPMB_KONTRON  199
 
 /*
  * 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
  */
 #define LINKTYPE_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>.
+ * PPP, 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 LINKTYPE_PPP_WITH_DIR  204     /* Don't confuse with LINKTYPE_PPP_PPPD */
+
+/*
+ * Cisco HDLC, 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 LINKTYPE_PPP_WITH_DIR  204     /* PPP */
 #define LINKTYPE_C_HDLC_WITH_DIR 205   /* Cisco HDLC */
+
+/*
+ * Frame Relay, with a one-byte direction pseudo-header prepended - zero
+ * means "received by this host" (DCE -> DTE), non-zero (any non-zero
+ * value) means "sent by this host" (DTE -> DCE) - as per Will Barker
+ * <w.barker@zen.co.uk>.
+ */
 #define LINKTYPE_FRELAY_WITH_DIR 206   /* Frame Relay */
+
+/*
+ * LAPB, with a one-byte direction pseudo-header prepended - zero means
+ * "received by this host" (DCE -> DTE), non-zero (any non-zero value)
+ * means "sent by this host" (DTE -> DCE)- as per Will Barker
+ * <w.barker@zen.co.uk>.
+ */
 #define LINKTYPE_LAPB_WITH_DIR 207     /* LAPB */
 
 /*
  */
 #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
 
  * 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;
+ *     uint8_t   dli_version;
+ *     uint8_t   dli_family;
+ *     uint16_t  dli_htype;
+ *     uint32_t  dli_pktlen;
+ *     uint32_t  dli_ifindex;
+ *     uint32_t  dli_grifindex;
+ *     uint32_t  dli_zsrc;
+ *     uint32_t  dli_zdst;
  * };
  *
  * dli_version is 2 for the current version of the pseudo-header.
 
 /*
  * 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>.
  */
 
 /*
  * 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
 
 /*
  * 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>
 
 /*
  * pfsync output; DLT_PFSYNC is 18, which collides with DLT_CIP in
- * SuSE 6.3, on OpenBSD, NetBSD, DragonFly BSD, and Mac OS X, and
+ * SuSE 6.3, on OpenBSD, NetBSD, DragonFly BSD, and macOS, and
  * is 121, which collides with DLT_HHDLC, in FreeBSD.  We pick a
  * shiny new link-layer header type value that doesn't collide with
  * anything, in the hopes that future pfsync savefiles, if any,
 
 /*
  * 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
  */
 #define LINKTYPE_PROFIBUS_DL           257
 
-
 /*
  * Apple's DLT_PKTAP headers.
  *
  * 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
+ * will be 258 *even on macOS*; 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
  */
 #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
+
+/*
+ * USB packets, beginning with a Darwin (macOS, etc.) header.
+ */
+#define LINKTYPE_USB_DARWIN    266
+
+/*
+ * OpenBSD DLT_OPENFLOW.
+ */
+#define LINKTYPE_OPENFLOW      267
+
+/*
+ * SDLC frames containing SNA PDUs.
+ */
+#define LINKTYPE_SDLC          268
+
+/*
+ * per "Selvig, Bjorn" <b.selvig@ti.com> used for
+ * TI protocol sniffer.
+ */
+#define LINKTYPE_TI_LLN_SNIFFER        269
+
+/*
+ * per: Erik de Jong <erikdejong at gmail.com> for
+ *   https://github.com/eriknl/LoRaTap/releases/tag/v0.1
+ */
+#define LINKTYPE_LORATAP        270
+
+/*
+ * per: Stefanha at gmail.com for
+ *   http://lists.sandelman.ca/pipermail/tcpdump-workers/2017-May/000772.html
+ * and: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/tree/include/uapi/linux/vsockmon.h
+ * for: http://qemu-project.org/Features/VirtioVsock
+ */
+#define LINKTYPE_VSOCK          271
+
+/*
+ * Nordic Semiconductor Bluetooth LE sniffer.
+ */
+#define LINKTYPE_NORDIC_BLE    272
+
+/*
+ * Excentis DOCSIS 3.1 RF sniffer (XRA-31)
+ *   per: bruno.verstuyft at excentis.com
+ *        http://www.xra31.com/xra-header
+ */
+#define LINKTYPE_DOCSIS31_XRA31        273
+
+/*
+ * mPackets, as specified by IEEE 802.3br Figure 99-4, starting
+ * with the preamble and always ending with a CRC field.
+ */
+#define LINKTYPE_ETHERNET_MPACKET      274
+
+/*
+ * DisplayPort AUX channel monitoring data as specified by VESA
+ * DisplayPort(DP) Standard preceeded by a pseudo-header.
+ *    per dirk.eibach at gdsys.cc
+ */
+#define LINKTYPE_DISPLAYPORT_AUX       275
+
+/*
+ * Linux cooked sockets v2.
+ */
+#define LINKTYPE_LINUX_SLL2    276
+
+#define LINKTYPE_MATCHING_MAX  276             /* highest value in the "matching" range */
+
+/*
+ * The DLT_ and LINKTYPE_ values in the "matching" range should be the
+ * same, so DLT_MATCHING_MAX and LINKTYPE_MATCHING_MAX should be the
+ * same.
+ */
+#if LINKTYPE_MATCHING_MAX != DLT_MATCHING_MAX
+#error The LINKTYPE_ matching range does not match the DLT_ matching range
+#endif
 
 static struct linktype_map {
        int     dlt;
@@ -1142,6 +1272,75 @@ linktype_to_dlt(int linktype)
 }
 
 /*
+ * Return the maximum snapshot length for a given DLT_ value.
+ *
+ * For most link-layer types, we use MAXIMUM_SNAPLEN.
+ *
+ * For DLT_DBUS, the maximum is 128MiB, as per
+ *
+ *    https://dbus.freedesktop.org/doc/dbus-specification.html#message-protocol-messages
+ *
+ * For DLT_USBPCAP, the maximum is 1MiB, as per
+ *
+ *    https://bugs.wireshark.org/bugzilla/show_bug.cgi?id=15985
+ */
+u_int
+max_snaplen_for_dlt(int dlt)
+{
+       switch (dlt) {
+
+       case DLT_DBUS:
+               return 128*1024*1024;
+
+       case DLT_USBPCAP:
+               return 1024*1024;
+
+       default:
+               return MAXIMUM_SNAPLEN;
+       }
+}
+
+/*
+ * 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;
+       uint16_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
  * memory-mapped buffer shared by the kernel).
@@ -1156,8 +1355,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 +1363,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 +1418,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 +1457,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;
+                       uint32_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++;
+                       }
                }
        }
 }
@@ -1297,14 +1507,15 @@ swap_nflog_header(const struct pcap_pkthdr *hdr, u_char *buf)
        nflog_tlv_t *tlv;
        u_int caplen = hdr->caplen;
        u_int length = hdr->len;
-       u_int16_t size;
+       uint16_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 +1565,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;
index 6ac5bcd..8795a82 100644 (file)
@@ -1,3 +1,25 @@
+/*
+ * 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.
+ *
+ * pcap-common.h - common code for pcap and pcapng files
+ */
 
 /*
  * We use the "receiver-makes-right" approach to byte order,
  * machine (if the file was written in little-end order).
  */
 #define        SWAPLONG(y) \
-((((y)&0xff)<<24) | (((y)&0xff00)<<8) | (((y)&0xff0000)>>8) | (((y)>>24)&0xff))
+    (((((u_int)(y))&0xff)<<24) | \
+     ((((u_int)(y))&0xff00)<<8) | \
+     ((((u_int)(y))&0xff0000)>>8) | \
+     ((((u_int)(y))>>24)&0xff))
 #define        SWAPSHORT(y) \
-       ( (((y)&0xff)<<8) | ((u_short)((y)&0xff00)>>8) )
+     ((u_short)(((((u_int)(y))&0xff)<<8) | \
+                ((((u_int)(y))&0xff00)>>8)))
 
 extern int dlt_to_linktype(int dlt);
 
@@ -23,3 +49,5 @@ extern int linktype_to_dlt(int linktype);
 
 extern void swap_pseudo_headers(int linktype, struct pcap_pkthdr *hdr,
     u_char *data);
+
+extern u_int max_snaplen_for_dlt(int dlt);
index 2a2272b..0388d0f 100644 (file)
@@ -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
index 206be3b..54ca42f 100644 (file)
@@ -4,12 +4,17 @@
 # Script to give the appropriate compiler flags and linker flags
 # to use when building code that uses libpcap.
 #
+# These variables come from the configure script, so includedir and
+# libdir may be defined in terms of prefix and exec_prefix, so the
+# latter must be defined as well.
+#
 prefix="@prefix@"
 exec_prefix="@exec_prefix@"
 includedir="@includedir@"
 libdir="@libdir@"
 V_RPATH_OPT="@V_RPATH_OPT@"
 LIBS="@LIBS@"
+PACKAGE_NAME="@PACKAGE_NAME@"
 
 static=0
 show_cflags=0
@@ -75,7 +80,7 @@ else
        #
        if [ "$show_cflags" = 1 -a "$show_libs" = 1 ]
        then
-               echo "-I$includedir -L$libdir $RPATH -lpcap"
+               echo "-I$includedir -L$libdir $RPATH -l$PACKAGE_NAME"
        elif [ "$show_cflags" = 1 -a "$show_additional_libs" = 1 ]
        then
                echo "-I$includedir"
@@ -84,6 +89,6 @@ else
                echo "-I$includedir"
        elif [ "$show_libs" = 1 ]
        then
-               echo "-L$libdir $RPATH -lpcap"
+               echo "-L$libdir $RPATH -l$PACKAGE_NAME"
        fi
 fi
index aaa3fae..e076676 100644 (file)
@@ -1,22 +1,14 @@
 /*
- * pcap-dag.c: Packet capture interface for Endace DAG card.
- *
- * The functionality of this code attempts to mimic that of pcap-linux as much
- * as possible.  This code is compiled in several different ways depending on
- * whether DAG_ONLY and HAVE_DAG_API are defined.  If HAVE_DAG_API is not
- * defined it should not get compiled in, otherwise if DAG_ONLY is defined then
- * the 'dag_' function calls are renamed to 'pcap_' equivalents.  If DAG_ONLY
- * is not defined then nothing is altered - the dag_ functions will be
- * called as required from their pcap-linux/bpf equivalents.
+ * pcap-dag.c: Packet capture interface for Endace DAG cards.
  *
  * 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@endace.com>
  */
 
 #ifdef HAVE_CONFIG_H
-#include "config.h"
+#include <config.h>
 #endif
 
 #include <sys/param.h>                 /* optionally get BSD define */
@@ -40,6 +32,8 @@ struct rtentry;               /* declarations in <net/if.h> */
 
 #include "dagnew.h"
 #include "dagapi.h"
+#include "dagpci.h"
+#include "dag_config_api.h"
 
 #include "pcap-dag.h"
 
@@ -52,6 +46,103 @@ struct rtentry;             /* declarations in <net/if.h> */
 #define DAG_MAX_BOARDS 32
 #endif
 
+
+#ifndef ERF_TYPE_AAL5
+#define ERF_TYPE_AAL5               4
+#endif
+
+#ifndef ERF_TYPE_MC_HDLC
+#define ERF_TYPE_MC_HDLC            5
+#endif
+
+#ifndef ERF_TYPE_MC_RAW
+#define ERF_TYPE_MC_RAW             6
+#endif
+
+#ifndef ERF_TYPE_MC_ATM
+#define ERF_TYPE_MC_ATM             7
+#endif
+
+#ifndef ERF_TYPE_MC_RAW_CHANNEL
+#define ERF_TYPE_MC_RAW_CHANNEL     8
+#endif
+
+#ifndef ERF_TYPE_MC_AAL5
+#define ERF_TYPE_MC_AAL5            9
+#endif
+
+#ifndef ERF_TYPE_COLOR_HDLC_POS
+#define ERF_TYPE_COLOR_HDLC_POS     10
+#endif
+
+#ifndef ERF_TYPE_COLOR_ETH
+#define ERF_TYPE_COLOR_ETH          11
+#endif
+
+#ifndef ERF_TYPE_MC_AAL2
+#define ERF_TYPE_MC_AAL2            12
+#endif
+
+#ifndef ERF_TYPE_IP_COUNTER
+#define ERF_TYPE_IP_COUNTER         13
+#endif
+
+#ifndef ERF_TYPE_TCP_FLOW_COUNTER
+#define ERF_TYPE_TCP_FLOW_COUNTER   14
+#endif
+
+#ifndef ERF_TYPE_DSM_COLOR_HDLC_POS
+#define ERF_TYPE_DSM_COLOR_HDLC_POS 15
+#endif
+
+#ifndef ERF_TYPE_DSM_COLOR_ETH
+#define ERF_TYPE_DSM_COLOR_ETH      16
+#endif
+
+#ifndef ERF_TYPE_COLOR_MC_HDLC_POS
+#define ERF_TYPE_COLOR_MC_HDLC_POS  17
+#endif
+
+#ifndef ERF_TYPE_AAL2
+#define ERF_TYPE_AAL2               18
+#endif
+
+#ifndef ERF_TYPE_COLOR_HASH_POS
+#define ERF_TYPE_COLOR_HASH_POS     19
+#endif
+
+#ifndef ERF_TYPE_COLOR_HASH_ETH
+#define ERF_TYPE_COLOR_HASH_ETH     20
+#endif
+
+#ifndef ERF_TYPE_INFINIBAND
+#define ERF_TYPE_INFINIBAND         21
+#endif
+
+#ifndef ERF_TYPE_IPV4
+#define ERF_TYPE_IPV4               22
+#endif
+
+#ifndef ERF_TYPE_IPV6
+#define ERF_TYPE_IPV6               23
+#endif
+
+#ifndef ERF_TYPE_RAW_LINK
+#define ERF_TYPE_RAW_LINK           24
+#endif
+
+#ifndef ERF_TYPE_INFINIBAND_LINK
+#define ERF_TYPE_INFINIBAND_LINK    25
+#endif
+
+#ifndef ERF_TYPE_META
+#define ERF_TYPE_META               27
+#endif
+
+#ifndef ERF_TYPE_PAD
+#define ERF_TYPE_PAD                48
+#endif
+
 #define ATM_CELL_SIZE          52
 #define ATM_HDR_SIZE           4
 
@@ -79,20 +170,19 @@ struct sunatm_hdr {
  */
 struct pcap_dag {
        struct pcap_stat stat;
-#ifdef HAVE_DAG_STREAMS_API
        u_char  *dag_mem_bottom;        /* DAG card current memory bottom pointer */
        u_char  *dag_mem_top;   /* DAG card current memory top pointer */
-#else /* HAVE_DAG_STREAMS_API */
-       void    *dag_mem_base;  /* DAG card memory base address */
-       u_int   dag_mem_bottom; /* DAG card current memory bottom offset */
-       u_int   dag_mem_top;    /* DAG card current memory top offset */
-#endif /* HAVE_DAG_STREAMS_API */
        int     dag_fcs_bits;   /* Number of checksum bits from link layer */
-       int     dag_offset_flags; /* Flags to pass to dag_offset(). */
+       int     dag_flags;      /* Flags */
        int     dag_stream;     /* DAG stream number */
        int     dag_timeout;    /* timeout specified to pcap_open_live.
                                 * Same as in linux above, introduce
                                 * generally? */
+       dag_card_ref_t dag_ref; /* DAG Configuration/Status API card reference */
+       dag_component_t dag_root;       /* DAG CSAPI Root component */
+       attr_uuid_t drop_attr;  /* DAG Stream Drop Attribute handle, if available */
+       struct timeval required_select_timeout;
+                               /* Timeout caller must use in event loops */
 };
 
 typedef struct pcap_dag_node {
@@ -111,11 +201,18 @@ static const unsigned short endian_test_word = 0x0100;
 
 static unsigned char TempPkt[MAX_DAG_PACKET];
 
+#ifndef HAVE_DAG_LARGE_STREAMS_API
+#define dag_attach_stream64(a, b, c, d) dag_attach_stream(a, b, c, d)
+#define dag_get_stream_poll64(a, b, c, d, e) dag_get_stream_poll(a, b, c, d, e)
+#define dag_set_stream_poll64(a, b, c, d, e) dag_set_stream_poll(a, b, c, d, e)
+#define dag_size_t uint32_t
+#endif
+
 static int dag_setfilter(pcap_t *p, struct bpf_program *fp);
 static int dag_stats(pcap_t *p, struct pcap_stat *ps);
 static int dag_set_datalink(pcap_t *p, int dlt);
 static int dag_get_datalink(pcap_t *p);
-static int dag_setnonblock(pcap_t *p, int nonblock, char *errbuf);
+static int dag_setnonblock(pcap_t *p, int nonblock);
 
 static void
 delete_pcap_dag(pcap_t *p)
@@ -143,29 +240,28 @@ delete_pcap_dag(pcap_t *p)
 static void
 dag_platform_cleanup(pcap_t *p)
 {
-       struct pcap_dag *pd;
-
-       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));
-#else
-               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);
+       struct pcap_dag *pd = p->priv;
+
+       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(pd->dag_ref != NULL) {
+               dag_config_dispose(pd->dag_ref);
+               /*
+                * Note: we don't need to call close(p->fd) or
+                * dag_close(p->fd), as dag_config_dispose(pd->dag_ref)
+                * does this.
+                *
+                * Set p->fd to -1 to make sure that's not done.
+                */
+               p->fd = -1;
+               pd->dag_ref = NULL;
        }
-       /* Note: don't need to call close(p->fd) here as dag_close(p->fd) does this. */
+       delete_pcap_dag(p);
+       pcap_cleanup_live_common(p);
 }
 
 static void
@@ -173,7 +269,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 +318,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;
@@ -245,13 +342,13 @@ dag_read(pcap_t *p, int cnt, pcap_handler callback, u_char *user)
 {
        struct pcap_dag *pd = p->priv;
        unsigned int processed = 0;
-       int flags = pd->dag_offset_flags;
-       unsigned int nonblocking = flags & DAGF_NONBLOCK;
+       unsigned int nonblocking = pd->dag_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?
                 */
@@ -265,7 +362,6 @@ dag_read(pcap_t *p, int cnt, pcap_handler callback, u_char *user)
                        return -2;
                }
 
-#ifdef HAVE_DAG_STREAMS_API
                /* dag_advance_stream() will block (unless nonblock is called)
                 * until 64kB of data has accumulated.
                 * If to_ms is set, it will timeout before 64kB has accumulated.
@@ -280,17 +376,13 @@ dag_read(pcap_t *p, int cnt, pcap_handler callback, u_char *user)
                if ( NULL == (pd->dag_mem_top = dag_advance_stream(p->fd, pd->dag_stream, &(pd->dag_mem_bottom))) ) {
                     return -1;
                }
-#else
-               /* dag_offset does not support timeouts */
-               pd->dag_mem_top = dag_offset(p->fd, &(pd->dag_mem_bottom), flags);
-#endif /* HAVE_DAG_STREAMS_API */
 
                if (nonblocking && (pd->dag_mem_top - pd->dag_mem_bottom < dag_record_size))
                {
                        /* Pcap is configured to process only available packets, and there aren't any, return immediately. */
                        return 0;
                }
-               
+
                if(!nonblocking &&
                   pd->dag_timeout &&
                   (pd->dag_mem_top - pd->dag_mem_bottom < dag_record_size))
@@ -300,23 +392,19 @@ 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
-               dag_record_t *header = (dag_record_t *)(pd->dag_mem_base + pd->dag_mem_bottom);
-#endif /* HAVE_DAG_STREAMS_API */
 
                u_char *dp = ((u_char *)header); /* + dag_record_size; */
                unsigned short rlen;
+
                /*
                 * Has "pcap_breakloop()" been called?
                 */
@@ -329,7 +417,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)
                {
@@ -341,39 +429,35 @@ dag_read(pcap_t *p, int cnt, pcap_handler callback, u_char *user)
                /* Count lost packets. */
                switch((header->type & 0x7f)) {
                        /* in these types the color value overwrites the lctr */
-               case TYPE_COLOR_HDLC_POS:
-               case TYPE_COLOR_ETH:
-               case TYPE_DSM_COLOR_HDLC_POS:
-               case TYPE_DSM_COLOR_ETH:
-               case TYPE_COLOR_MC_HDLC_POS:
-               case TYPE_COLOR_HASH_ETH:
-               case TYPE_COLOR_HASH_POS:
+               case ERF_TYPE_COLOR_HDLC_POS:
+               case ERF_TYPE_COLOR_ETH:
+               case ERF_TYPE_DSM_COLOR_HDLC_POS:
+               case ERF_TYPE_DSM_COLOR_ETH:
+               case ERF_TYPE_COLOR_MC_HDLC_POS:
+               case ERF_TYPE_COLOR_HASH_ETH:
+               case ERF_TYPE_COLOR_HASH_POS:
                        break;
 
                default:
-                       if (header->lctr) {
-                               if (pd->stat.ps_drop > (UINT_MAX - ntohs(header->lctr))) {
-                                       pd->stat.ps_drop = UINT_MAX;
-                               } else {
-                                       pd->stat.ps_drop += ntohs(header->lctr);
-                               }
+                       if ( (pd->drop_attr == kNullAttributeUuid) && (header->lctr) ) {
+                               pd->stat.ps_drop += ntohs(header->lctr);
                        }
                }
-               
-               if ((header->type & 0x7f) == TYPE_PAD) {
+
+               if ((header->type & 0x7f) == ERF_TYPE_PAD) {
                        continue;
                }
 
                num_ext_hdr = dag_erf_ext_header_count(dp, rlen);
 
                /* ERF encapsulation */
-               /* The Extensible Record Format is not dropped for this kind of encapsulation, 
+               /* 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).
                 *
@@ -384,20 +468,20 @@ dag_read(pcap_t *p, int cnt, pcap_handler callback, u_char *user)
                        packet_len = ntohs(header->wlen) + dag_record_size;
                        caplen = rlen;
                        switch ((header->type & 0x7f)) {
-                       case TYPE_MC_AAL5:
-                       case TYPE_MC_ATM:
-                       case TYPE_MC_HDLC:
-                       case TYPE_MC_RAW_CHANNEL:
-                       case TYPE_MC_RAW:
-                       case TYPE_MC_AAL2:
-                       case TYPE_COLOR_MC_HDLC_POS:
+                       case ERF_TYPE_MC_AAL5:
+                       case ERF_TYPE_MC_ATM:
+                       case ERF_TYPE_MC_HDLC:
+                       case ERF_TYPE_MC_RAW_CHANNEL:
+                       case ERF_TYPE_MC_RAW:
+                       case ERF_TYPE_MC_AAL2:
+                       case ERF_TYPE_COLOR_MC_HDLC_POS:
                                packet_len += 4; /* MC header */
                                break;
 
-                       case TYPE_COLOR_HASH_ETH:
-                       case TYPE_DSM_COLOR_ETH:
-                       case TYPE_COLOR_ETH:
-                       case TYPE_ETH:
+                       case ERF_TYPE_COLOR_HASH_ETH:
+                       case ERF_TYPE_DSM_COLOR_ETH:
+                       case ERF_TYPE_COLOR_ETH:
+                       case ERF_TYPE_ETH:
                                packet_len += 2; /* ETH header */
                                break;
                        } /* switch type */
@@ -415,79 +499,103 @@ 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:
-                               if (header->type == TYPE_AAL5) {
+                       case ERF_TYPE_ATM:
+                       case ERF_TYPE_AAL5:
+                               if ((header->type & 0x7f) == ERF_TYPE_AAL5) {
                                        packet_len = ntohs(header->wlen);
                                        caplen = rlen - dag_record_size;
                                }
-                       case TYPE_MC_ATM:
-                               if (header->type == TYPE_MC_ATM) {
+                       case ERF_TYPE_MC_ATM:
+                               if ((header->type & 0x7f) == ERF_TYPE_MC_ATM) {
                                        caplen = packet_len = ATM_CELL_SIZE;
                                        dp+=4;
                                }
-                       case TYPE_MC_AAL5:
-                               if (header->type == TYPE_MC_AAL5) {
+                       case ERF_TYPE_MC_AAL5:
+                               if ((header->type & 0x7f) == ERF_TYPE_MC_AAL5) {
                                        packet_len = ntohs(header->wlen);
                                        caplen = rlen - dag_record_size - 4;
                                        dp+=4;
                                }
-                               if (header->type == TYPE_ATM) {
+                               /* Skip over extension headers */
+                               caplen -= (8 * num_ext_hdr);
+
+                               if ((header->type & 0x7f) == ERF_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)));
 
-                               } else {
+                               } else if (p->linktype == DLT_ATM_RFC1483) {
                                        packet_len -= ATM_HDR_SIZE;
                                        caplen -= ATM_HDR_SIZE;
                                        dp += ATM_HDR_SIZE;
-                               }
+                               } else
+                                       continue;
                                break;
 
-                       case TYPE_COLOR_HASH_ETH:
-                       case TYPE_DSM_COLOR_ETH:
-                       case TYPE_COLOR_ETH:
-                       case TYPE_ETH:
+                       case ERF_TYPE_COLOR_HASH_ETH:
+                       case ERF_TYPE_DSM_COLOR_ETH:
+                       case ERF_TYPE_COLOR_ETH:
+                       case ERF_TYPE_ETH:
+                               if ((p->linktype != DLT_EN10MB) &&
+                                   (p->linktype != DLT_DOCSIS))
+                                       continue;
                                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;
                                }
                                dp += 2;
                                break;
 
-                       case TYPE_COLOR_HASH_POS:
-                       case TYPE_DSM_COLOR_HDLC_POS:
-                       case TYPE_COLOR_HDLC_POS:
-                       case TYPE_HDLC_POS:
+                       case ERF_TYPE_COLOR_HASH_POS:
+                       case ERF_TYPE_DSM_COLOR_HDLC_POS:
+                       case ERF_TYPE_COLOR_HDLC_POS:
+                       case ERF_TYPE_HDLC_POS:
+                               if ((p->linktype != DLT_CHDLC) &&
+                                   (p->linktype != DLT_PPP_SERIAL) &&
+                                   (p->linktype != DLT_FRELAY))
+                                       continue;
                                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;
                                }
                                break;
 
-                       case TYPE_COLOR_MC_HDLC_POS:
-                       case TYPE_MC_HDLC:
+                       case ERF_TYPE_COLOR_MC_HDLC_POS:
+                       case ERF_TYPE_MC_HDLC:
+                               if ((p->linktype != DLT_CHDLC) &&
+                                   (p->linktype != DLT_PPP_SERIAL) &&
+                                   (p->linktype != DLT_FRELAY) &&
+                                   (p->linktype != DLT_MTP2) &&
+                                   (p->linktype != DLT_MTP2_WITH_PHDR) &&
+                                   (p->linktype != DLT_LAPD))
+                                       continue;
                                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 +606,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);
@@ -509,23 +617,40 @@ dag_read(pcap_t *p, int cnt, pcap_handler callback, u_char *user)
 #endif
                                break;
 
-                       case TYPE_IPV4:
-                       case TYPE_IPV6:
+                       case ERF_TYPE_IPV4:
+                               if ((p->linktype != DLT_RAW) &&
+                                   (p->linktype != DLT_IPV4))
+                                       continue;
                                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;
+                               }
+                               break;
+
+                       case ERF_TYPE_IPV6:
+                               if ((p->linktype != DLT_RAW) &&
+                                   (p->linktype != DLT_IPV6))
+                                       continue;
+                               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;
                                }
                                break;
 
                        /* These types have no matching 'native' DLT, but can be used with DLT_ERF above */
-                       case TYPE_MC_RAW:
-                       case TYPE_MC_RAW_CHANNEL:
-                       case TYPE_IP_COUNTER:
-                       case TYPE_TCP_FLOW_COUNTER:
-                       case TYPE_INFINIBAND:
-                       case TYPE_RAW_LINK:
-                       case TYPE_INFINIBAND_LINK:
+                       case ERF_TYPE_MC_RAW:
+                       case ERF_TYPE_MC_RAW_CHANNEL:
+                       case ERF_TYPE_IP_COUNTER:
+                       case ERF_TYPE_TCP_FLOW_COUNTER:
+                       case ERF_TYPE_INFINIBAND:
+                       case ERF_TYPE_RAW_LINK:
+                       case ERF_TYPE_INFINIBAND_LINK:
                        default:
                                /* Unhandled ERF type.
                                 * Ignore rather than generating error
@@ -533,45 +658,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))
@@ -588,7 +720,7 @@ dag_read(pcap_t *p, int cnt, pcap_handler callback, u_char *user)
 static int
 dag_inject(pcap_t *p, const void *buf _U_, size_t size _U_)
 {
-       strlcpy(p->errbuf, "Sending packets isn't supported on DAG cards",
+       pcap_strlcpy(p->errbuf, "Sending packets isn't supported on DAG cards",
            PCAP_ERRBUF_SIZE);
        return (-1);
 }
@@ -598,92 +730,134 @@ 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().
  *
  *  See also pcap(3).
  */
-static int dag_activate(pcap_t* handle)
+static int dag_activate(pcap_t* p)
 {
-       struct pcap_dag *handlep = handle->priv;
-#if 0
-       char conf[30]; /* dag configure string */
-#endif
+       struct pcap_dag *pd = p->priv;
        char *s;
        int n;
        daginf_t* daginf;
        char * newDev = NULL;
-       char * device = handle->opt.source;
-#ifdef HAVE_DAG_STREAMS_API
-       uint32_t mindata;
+       char * device = p->opt.device;
+       int ret;
+       dag_size_t mindata;
        struct timeval maxwait;
        struct timeval poll;
-#endif
 
        if (device == NULL) {
-               snprintf(handle->errbuf, PCAP_ERRBUF_SIZE, "device is NULL: %s", pcap_strerror(errno));
-               return -1;
+               pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "device is NULL");
+               return PCAP_ERROR;
        }
 
        /* Initialize some components of the pcap structure. */
-
-#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));
+               ret = PCAP_ERROR;
+               pcap_fmt_errmsg_for_errno(p->errbuf, PCAP_ERRBUF_SIZE,
+                   errno, "Can't allocate string for device name");
                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));
+       if (dag_parse_name(device, newDev, strlen(device) + 16, &pd->dag_stream) < 0) {
+               /*
+                * XXX - it'd be nice if this indicated what was wrong
+                * with the name.  Does this reliably set errno?
+                * Should this return PCAP_ERROR_NO_SUCH_DEVICE in some
+                * cases?
+                */
+               ret = PCAP_ERROR;
+               pcap_fmt_errmsg_for_errno(p->errbuf, PCAP_ERRBUF_SIZE,
+                   errno, "dag_parse_name");
                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");
+       if (pd->dag_stream%2) {
+               ret = PCAP_ERROR;
+               pcap_snprintf(p->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));
-                       goto fail;
-               }
-               strcpy(newDev, "/dev/");
-               strcat(newDev, device);
-               device = newDev;
-       }
-#endif /* HAVE_DAG_STREAMS_API */
 
        /* 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));
+       if((pd->dag_ref = dag_config_init((char *)device)) == NULL) {
+               /*
+                * XXX - does this reliably set errno?
+                */
+               if (errno == ENOENT)
+                       ret = PCAP_ERROR_NO_SUCH_DEVICE;
+               else if (errno == EPERM || errno == EACCES)
+                       ret = PCAP_ERROR_PERM_DENIED;
+               else
+                       ret = PCAP_ERROR;
+               pcap_fmt_errmsg_for_errno(p->errbuf, PCAP_ERRBUF_SIZE,
+                   errno, "dag_config_init %s", device);
                goto fail;
        }
 
-#ifdef HAVE_DAG_STREAMS_API
+       if((p->fd = dag_config_get_card_fd(pd->dag_ref)) < 0) {
+               /*
+                * XXX - does this reliably set errno?
+                */
+               ret = PCAP_ERROR;
+               pcap_fmt_errmsg_for_errno(p->errbuf, PCAP_ERRBUF_SIZE,
+                   errno, "dag_config_get_card_fd %s", device);
+               goto failclose;
+       }
+
        /* 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));
+       if (dag_attach_stream64(p->fd, pd->dag_stream, 0, 0) < 0) {
+               ret = PCAP_ERROR;
+               pcap_fmt_errmsg_for_errno(p->errbuf, PCAP_ERRBUF_SIZE,
+                   errno, "dag_attach_stream");
                goto failclose;
        }
 
+       /* Try to find Stream Drop attribute */
+       pd->drop_attr = kNullAttributeUuid;
+       pd->dag_root = dag_config_get_root_component(pd->dag_ref);
+       if ( dag_component_get_subcomponent(pd->dag_root, kComponentStreamFeatures, 0) )
+       {
+               pd->drop_attr = dag_config_get_indexed_attribute_uuid(pd->dag_ref, kUint32AttributeStreamDropCount, pd->dag_stream/2);
+       }
+
        /* Set up default poll parameters for stream
         * Can be overridden by pcap_set_nonblock()
         */
-       if (dag_get_stream_poll(handle->fd, handlep->dag_stream,
+       if (dag_get_stream_poll64(p->fd, pd->dag_stream,
                                &mindata, &maxwait, &poll) < 0) {
-               snprintf(handle->errbuf, PCAP_ERRBUF_SIZE, "dag_get_stream_poll: %s\n", pcap_strerror(errno));
+               ret = PCAP_ERROR;
+               pcap_fmt_errmsg_for_errno(p->errbuf, PCAP_ERRBUF_SIZE,
+                   errno, "dag_get_stream_poll");
                goto faildetach;
        }
-       
-       if (handle->opt.immediate) {
+
+       /* Use the poll time as the required select timeout for callers
+        * who are using select()/etc. in an event loop waiting for
+        * packets to arrive.
+        */
+       pd->required_select_timeout = poll;
+       p->required_select_timeout = &pd->required_select_timeout;
+
+       /*
+        * Turn a negative snapshot value (invalid), a snapshot value of
+        * 0 (unspecified), or a value bigger than the normal maximum
+        * value, into the maximum allowed value.
+        *
+        * If some application really *needs* a bigger snapshot
+        * length, we should just increase MAXIMUM_SNAPLEN.
+        */
+       if (p->snapshot <= 0 || p->snapshot > MAXIMUM_SNAPLEN)
+               p->snapshot = MAXIMUM_SNAPLEN;
+
+       if (p->opt.immediate) {
                /* Call callback immediately.
-                * XXX - is this the right way to handle this?
+                * XXX - is this the right way to p this?
                 */
                mindata = 0;
        } else {
@@ -697,22 +871,16 @@ static int dag_activate(pcap_t* handle)
        /* Obey opt.timeout (was to_ms) if supplied. This is a good idea!
         * Recommend 10-100ms. Calls will time out even if no data arrived.
         */
-       maxwait.tv_sec = handle->opt.timeout/1000;
-       maxwait.tv_usec = (handle->opt.timeout%1000) * 1000;
+       maxwait.tv_sec = p->opt.timeout/1000;
+       maxwait.tv_usec = (p->opt.timeout%1000) * 1000;
 
-       if (dag_set_stream_poll(handle->fd, handlep->dag_stream,
+       if (dag_set_stream_poll64(p->fd, pd->dag_stream,
                                mindata, &maxwait, &poll) < 0) {
-               snprintf(handle->errbuf, PCAP_ERRBUF_SIZE, "dag_set_stream_poll: %s\n", pcap_strerror(errno));
+               ret = PCAP_ERROR;
+               pcap_fmt_errmsg_for_errno(p->errbuf, PCAP_ERRBUF_SIZE,
+                   errno, "dag_set_stream_poll");
                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));
-               goto failclose;
-       }
-
-#endif /* HAVE_DAG_STREAMS_API */
 
         /* XXX Not calling dag_configure() to set slen; this is unsafe in
         * multi-stream environments as the gpp config is global.
@@ -722,64 +890,54 @@ static int dag_activate(pcap_t* handle)
        /* set the card snap length to the specified snaplen parameter */
        /* This is a really bad idea, as different cards have different
         * valid slen ranges. Should fix in Config API. */
-       if (handle->snapshot == 0 || handle->snapshot > MAX_DAG_SNAPLEN) {
-               handle->snapshot = MAX_DAG_SNAPLEN;
+       if (p->snapshot == 0 || p->snapshot > MAX_DAG_SNAPLEN) {
+               p->snapshot = MAX_DAG_SNAPLEN;
        } else if (snaplen < MIN_DAG_SNAPLEN) {
-               handle->snapshot = MIN_DAG_SNAPLEN;
+               p->snapshot = MIN_DAG_SNAPLEN;
        }
        /* snap len has to be a multiple of 4 */
-       snprintf(conf, 30, "varlen slen=%d", (snaplen + 3) & ~3); 
+#endif
 
-       if(dag_configure(handle->fd, conf) < 0) {
-               snprintf(handle->errbuf, PCAP_ERRBUF_SIZE,"dag_configure %s: %s\n", device, pcap_strerror(errno));
-               goto faildetach;
-       }
-#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));
+       if(dag_start_stream(p->fd, pd->dag_stream) < 0) {
+               ret = PCAP_ERROR;
+               pcap_fmt_errmsg_for_errno(p->errbuf, PCAP_ERRBUF_SIZE,
+                   errno, "dag_start_stream %s", device);
                goto faildetach;
        }
-#else
-       if(dag_start(handle->fd) < 0) {
-               snprintf(handle->errbuf, PCAP_ERRBUF_SIZE, "dag_start %s: %s\n", device, pcap_strerror(errno));
-               goto failclose;
-       }
-#endif /* HAVE_DAG_STREAMS_API */
 
        /*
         * Important! You have to ensure bottom is properly
         * initialized to zero on startup, it won't give you
         * a compiler warning if you make this mistake!
         */
-       handlep->dag_mem_bottom = 0;
-       handlep->dag_mem_top = 0;
+       pd->dag_mem_bottom = 0;
+       pd->dag_mem_top = 0;
 
        /*
         * Find out how many FCS bits we should strip.
         * First, query the card to see if it strips the FCS.
         */
-       daginf = dag_info(handle->fd);
+       daginf = dag_info(p->fd);
        if ((0x4200 == daginf->device_code) || (0x4230 == daginf->device_code)) {
                /* DAG 4.2S and 4.23S already strip the FCS.  Stripping the final word again truncates the packet. */
-               handlep->dag_fcs_bits = 0;
+               pd->dag_fcs_bits = 0;
 
                /* Note that no FCS will be supplied. */
-               handle->linktype_ext = LT_FCS_DATALINK_EXT(0);
+               p->linktype_ext = LT_FCS_DATALINK_EXT(0);
        } else {
                /*
                 * Start out assuming it's 32 bits.
                 */
-               handlep->dag_fcs_bits = 32;
+               pd->dag_fcs_bits = 32;
 
                /* Allow an environment variable to override. */
                if ((s = getenv("ERF_FCS_BITS")) != NULL) {
                        if ((n = atoi(s)) == 0 || n == 16 || n == 32) {
-                               handlep->dag_fcs_bits = n;
+                               pd->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);
+                               ret = PCAP_ERROR;
+                               pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
+                                       "pcap_activate %s: bad ERF_FCS_BITS value (%d) in environment", device, n);
                                goto failstop;
                        }
                }
@@ -790,76 +948,81 @@ static int dag_activate(pcap_t* handle)
                if ((s = getenv("ERF_DONT_STRIP_FCS")) != NULL) {
                        /* Yes.  Note the number of bytes that will be
                           supplied. */
-                       handle->linktype_ext = LT_FCS_DATALINK_EXT(handlep->dag_fcs_bits/16);
+                       p->linktype_ext = LT_FCS_DATALINK_EXT(pd->dag_fcs_bits/16);
 
                        /* And don't strip them. */
-                       handlep->dag_fcs_bits = 0;
+                       pd->dag_fcs_bits = 0;
                }
        }
 
-       handlep->dag_timeout    = handle->opt.timeout;
+       pd->dag_timeout = p->opt.timeout;
 
-       handle->linktype = -1;
-       if (dag_get_datalink(handle) < 0)
+       p->linktype = -1;
+       if (dag_get_datalink(p) < 0) {
+               ret = PCAP_ERROR;
                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));
+       p->bufsize = 0;
+
+       if (new_pcap_dag(p) < 0) {
+               ret = PCAP_ERROR;
+               pcap_fmt_errmsg_for_errno(p->errbuf, PCAP_ERRBUF_SIZE,
+                   errno, "new_pcap_dag %s", device);
                goto failstop;
        }
 
        /*
         * "select()" and "poll()" don't work on DAG device descriptors.
         */
-       handle->selectable_fd = -1;
+       p->selectable_fd = -1;
 
        if (newDev != NULL) {
                free((char *)newDev);
        }
 
-       handle->read_op = dag_read;
-       handle->inject_op = dag_inject;
-       handle->setfilter_op = dag_setfilter;
-       handle->setdirection_op = NULL; /* Not implemented.*/
-       handle->set_datalink_op = dag_set_datalink;
-       handle->getnonblock_op = pcap_getnonblock_fd;
-       handle->setnonblock_op = dag_setnonblock;
-       handle->stats_op = dag_stats;
-       handle->cleanup_op = dag_platform_cleanup;
-       handlep->stat.ps_drop = 0;
-       handlep->stat.ps_recv = 0;
-       handlep->stat.ps_ifdrop = 0;
+       p->read_op = dag_read;
+       p->inject_op = dag_inject;
+       p->setfilter_op = dag_setfilter;
+       p->setdirection_op = NULL; /* Not implemented.*/
+       p->set_datalink_op = dag_set_datalink;
+       p->getnonblock_op = pcap_getnonblock_fd;
+       p->setnonblock_op = dag_setnonblock;
+       p->stats_op = dag_stats;
+       p->cleanup_op = dag_platform_cleanup;
+       pd->stat.ps_drop = 0;
+       pd->stat.ps_recv = 0;
+       pd->stat.ps_ifdrop = 0;
        return 0;
 
-#ifdef HAVE_DAG_STREAMS_API 
 failstop:
-       if (dag_stop_stream(handle->fd, handlep->dag_stream) < 0) {
+       if (dag_stop_stream(p->fd, pd->dag_stream) < 0) {
                fprintf(stderr,"dag_stop_stream: %s\n", strerror(errno));
        }
-       
+
 faildetach:
-       if (dag_detach_stream(handle->fd, handlep->dag_stream) < 0)
+       if (dag_detach_stream(p->fd, pd->dag_stream) < 0)
                fprintf(stderr,"dag_detach_stream: %s\n", strerror(errno));
-#else
-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));
-       delete_pcap_dag(handle);
+       dag_config_dispose(pd->dag_ref);
+       /*
+        * Note: we don't need to call close(p->fd) or dag_close(p->fd),
+        * as dag_config_dispose(pd->dag_ref) does this.
+        *
+        * Set p->fd to -1 to make sure that's not done.
+        */
+       p->fd = -1;
+       pd->dag_ref = NULL;
+       delete_pcap_dag(p);
 
 fail:
-       pcap_cleanup_live_common(handle);
+       pcap_cleanup_live_common(p);
        if (newDev != NULL) {
                free((char *)newDev);
        }
 
-       return PCAP_ERROR;
+       return ret;
 }
 
 pcap_t *dag_create(const char *device, char *ebuf, int *is_ours)
@@ -868,9 +1031,7 @@ pcap_t *dag_create(const char *device, char *ebuf, int *is_ours)
        char *cpend;
        long devnum;
        pcap_t *p;
-#ifdef HAVE_DAG_STREAMS_API
        long stream = 0;
-#endif
 
        /* Does this look like a DAG device? */
        cp = strrchr(device, '/');
@@ -885,118 +1046,156 @@ pcap_t *dag_create(const char *device, char *ebuf, int *is_ours)
        /* Yes - is "dag" followed by a number from 0 to DAG_MAX_BOARDS-1 */
        cp += 3;
        devnum = strtol(cp, &cpend, 10);
-#ifdef HAVE_DAG_STREAMS_API
        if (*cpend == ':') {
                /* Followed by a stream number. */
                stream = strtol(++cpend, &cpend, 10);
        }
-#endif
+
        if (cpend == cp || *cpend != '\0') {
                /* Not followed by a number. */
                *is_ours = 0;
                return NULL;
        }
+
        if (devnum < 0 || devnum >= DAG_MAX_BOARDS) {
                /* Followed by a non-valid number. */
                *is_ours = 0;
                return NULL;
        }
-#ifdef HAVE_DAG_STREAMS_API
+
        if (stream <0 || stream >= DAG_STREAM_MAX) {
                /* Followed by a non-valid stream number. */
                *is_ours = 0;
                return NULL;
        }
-#endif
 
        /* 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_fmt_errmsg_for_errno(ebuf, PCAP_ERRBUF_SIZE,
+                   errno, "malloc");
+               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;
 }
 
 static int
 dag_stats(pcap_t *p, struct pcap_stat *ps) {
        struct pcap_dag *pd = p->priv;
+       uint32_t stream_drop;
+       dag_err_t dag_error;
+
+       /*
+        * Packet records received (ps_recv) are counted in dag_read().
+        * Packet records dropped (ps_drop) are read from Stream Drop attribute if present,
+        * otherwise integrate the ERF Header lctr counts (if available) in dag_read().
+        * We are reporting that no records are dropped by the card/driver (ps_ifdrop).
+        */
+
+       if(pd->drop_attr != kNullAttributeUuid) {
+               /* Note this counter is cleared at start of capture and will wrap at UINT_MAX.
+                * The application is responsible for polling ps_drop frequently enough
+                * to detect each wrap and integrate total drop with a wider counter */
+               if ((dag_error = dag_config_get_uint32_attribute_ex(pd->dag_ref, pd->drop_attr, &stream_drop) == kDagErrNone)) {
+                       pd->stat.ps_drop = stream_drop;
+               } else {
+                       pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "reading stream drop attribute: %s",
+                                dag_config_strerror(dag_error));
+                       return -1;
+               }
+       }
 
-       /* This needs to be filled out correctly.  Hopefully a dagapi call will
-                provide all necessary information.
-       */
-       /*pd->stat.ps_recv = 0;*/
-       /*pd->stat.ps_drop = 0;*/
-       
        *ps = pd->stat;
+
        return 0;
 }
 
 /*
- * Previously we just generated a list of all possible names and let
- * pcap_add_if() attempt to open each one, but with streams this adds up
- * to 81 possibilities which is inefficient.
- *
- * Since we know more about the devices we can prune the tree here.
- * pcap_add_if() will still retest each device but the total number of
- * open attempts will still be much less than the naive approach.
+ * Add all DAG devices.
  */
 int
-dag_findalldevs(pcap_if_t **devlistp, char *errbuf)
+dag_findalldevs(pcap_if_list_t *devlistp, char *errbuf)
 {
        char name[12];  /* XXX - pick a size */
-       int ret = 0;
        int c;
        char dagname[DAGNAME_BUFSIZE];
        int dagstream;
        int dagfd;
+       dag_card_inf_t *inf;
+       char *description;
+       int stream, rxstreams;
 
        /* 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;
+                       (void) pcap_snprintf(errbuf, PCAP_ERRBUF_SIZE,
+                           "dag: device name %s can't be parsed", name);
+                       return (-1);
                }
                if ( (dagfd = dag_open(dagname)) >= 0 ) {
-                       if (pcap_add_if(devlistp, name, 0, NULL, errbuf) == -1) {
+                       description = NULL;
+                       if ((inf = dag_pciinfo(dagfd)))
+                               description = dag_device_name(inf->device_code, 1);
+                       /*
+                        * XXX - is there a way to determine whether
+                        * the card is plugged into a network or not?
+                        * If so, we should check that and set
+                        * PCAP_IF_CONNECTION_STATUS_CONNECTED or
+                        * PCAP_IF_CONNECTION_STATUS_DISCONNECTED.
+                        *
+                        * Also, are there notions of "up" and "running"?
+                        */
+                       if (add_dev(devlistp, name, 0, description, errbuf) == NULL) {
                                /*
                                 * Failure.
                                 */
-                               ret = -1;
+                               return (-1);
                        }
-#ifdef HAVE_DAG_STREAMS_API
-                       {
-                               int stream, rxstreams;
-                               rxstreams = dag_rx_get_stream_count(dagfd);
-                               for(stream=0;stream<DAG_STREAM_MAX;stream+=2) {
-                                       if (0 == dag_attach_stream(dagfd, stream, 0, 0)) {
-                                               dag_detach_stream(dagfd, stream);
-
-                                               snprintf(name,  10, "dag%d:%d", c, stream);
-                                               if (pcap_add_if(devlistp, name, 0, NULL, errbuf) == -1) {
-                                                       /*
-                                                        * Failure.
-                                                        */
-                                                       ret = -1;
-                                               }
-                                               
-                                               rxstreams--;
-                                               if(rxstreams <= 0) {
-                                                       break;
-                                               }
+                       rxstreams = dag_rx_get_stream_count(dagfd);
+                       for(stream=0;stream<DAG_STREAM_MAX;stream+=2) {
+                               if (0 == dag_attach_stream64(dagfd, stream, 0, 0)) {
+                                       dag_detach_stream(dagfd, stream);
+
+                                       pcap_snprintf(name,  10, "dag%d:%d", c, stream);
+                                       if (add_dev(devlistp, name, 0, description, errbuf) == NULL) {
+                                               /*
+                                                * Failure.
+                                                */
+                                               return (-1);
                                        }
-                               }                               
+
+                                       rxstreams--;
+                                       if(rxstreams <= 0) {
+                                               break;
+                                       }
+                               }
                        }
-#endif  /* HAVE_DAG_STREAMS_API */
                        dag_close(dagfd);
                }
 
        }
-       return (ret);
+       return (0);
 }
 
 /*
@@ -1032,54 +1231,53 @@ dag_set_datalink(pcap_t *p, int dlt)
 }
 
 static int
-dag_setnonblock(pcap_t *p, int nonblock, char *errbuf)
+dag_setnonblock(pcap_t *p, int nonblock)
 {
        struct pcap_dag *pd = p->priv;
+       dag_size_t mindata;
+       struct timeval maxwait;
+       struct timeval poll;
 
        /*
         * Set non-blocking mode on the FD.
         * XXX - is that necessary?  If not, don't bother calling it,
         * and have a "dag_getnonblock()" function that looks at
-        * "pd->dag_offset_flags".
+        * "pd->dag_flags".
         */
-       if (pcap_setnonblock_fd(p, nonblock, errbuf) < 0)
+       if (pcap_setnonblock_fd(p, nonblock) < 0)
                return (-1);
-#ifdef HAVE_DAG_STREAMS_API
-       {
-               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));
-                       return -1;
-               }
-               
-               /* Amount of data to collect in Bytes before calling callbacks.
-                * Important for efficiency, but can introduce latency
-                * at low packet rates if to_ms not set!
-                */
-               if(nonblock)
-                       mindata = 0;
-               else
-                       mindata = 65536;
-               
-               if (dag_set_stream_poll(p->fd, pd->dag_stream,
-                                       mindata, &maxwait, &poll) < 0) {
-                       snprintf(errbuf, PCAP_ERRBUF_SIZE, "dag_set_stream_poll: %s\n", pcap_strerror(errno));
-                       return -1;
-               }
+
+       if (dag_get_stream_poll64(p->fd, pd->dag_stream,
+                               &mindata, &maxwait, &poll) < 0) {
+               pcap_fmt_errmsg_for_errno(p->errbuf, PCAP_ERRBUF_SIZE,
+                   errno, "dag_get_stream_poll");
+               return -1;
        }
-#endif /* HAVE_DAG_STREAMS_API */
+
+       /* Amount of data to collect in Bytes before calling callbacks.
+        * Important for efficiency, but can introduce latency
+        * at low packet rates if to_ms not set!
+        */
+       if(nonblock)
+               mindata = 0;
+       else
+               mindata = 65536;
+
+       if (dag_set_stream_poll64(p->fd, pd->dag_stream,
+                               mindata, &maxwait, &poll) < 0) {
+               pcap_fmt_errmsg_for_errno(p->errbuf, PCAP_ERRBUF_SIZE,
+                   errno, "dag_set_stream_poll");
+               return -1;
+       }
+
        if (nonblock) {
-               pd->dag_offset_flags |= DAGF_NONBLOCK;
+               pd->dag_flags |= DAGF_NONBLOCK;
        } else {
-               pd->dag_offset_flags &= ~DAGF_NONBLOCK;
+               pd->dag_flags &= ~DAGF_NONBLOCK;
        }
        return (0);
 }
-               
+
 static int
 dag_get_datalink(pcap_t *p)
 {
@@ -1090,7 +1288,8 @@ 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));
+               pcap_fmt_errmsg_for_errno(p->errbuf, sizeof(p->errbuf),
+                   errno, "malloc");
                return (-1);
        }
 
@@ -1099,19 +1298,21 @@ 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_fmt_errmsg_for_errno(p->errbuf, sizeof(p->errbuf),
+                   errno, "dag_get_stream_erf_types");
+               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_fmt_errmsg_for_errno(p->errbuf, sizeof(p->errbuf),
+                   errno, "dag_get_erf_types");
+               return (-1);
        }
-       
+
        while (types[index]) {
 #else
        /* Check the type through a dagapi call. */
@@ -1121,10 +1322,10 @@ dag_get_datalink(pcap_t *p)
 #endif
                switch((types[index] & 0x7f)) {
 
-               case TYPE_HDLC_POS:
-               case TYPE_COLOR_HDLC_POS:
-               case TYPE_DSM_COLOR_HDLC_POS:
-               case TYPE_COLOR_HASH_POS:
+               case ERF_TYPE_HDLC_POS:
+               case ERF_TYPE_COLOR_HDLC_POS:
+               case ERF_TYPE_DSM_COLOR_HDLC_POS:
+               case ERF_TYPE_COLOR_HASH_POS:
 
                        if (p->dlt_list != NULL) {
                                p->dlt_list[dlt_index++] = DLT_CHDLC;
@@ -1135,10 +1336,10 @@ dag_get_datalink(pcap_t *p)
                                p->linktype = DLT_CHDLC;
                        break;
 
-               case TYPE_ETH:
-               case TYPE_COLOR_ETH:
-               case TYPE_DSM_COLOR_ETH:
-               case TYPE_COLOR_HASH_ETH:
+               case ERF_TYPE_ETH:
+               case ERF_TYPE_COLOR_ETH:
+               case ERF_TYPE_DSM_COLOR_ETH:
+               case ERF_TYPE_COLOR_HASH_ETH:
                        /*
                         * This is (presumably) a real Ethernet capture; give it a
                         * link-layer-type list with DLT_EN10MB and DLT_DOCSIS, so
@@ -1157,10 +1358,10 @@ dag_get_datalink(pcap_t *p)
                                p->linktype = DLT_EN10MB;
                        break;
 
-               case TYPE_ATM: 
-               case TYPE_AAL5:
-               case TYPE_MC_ATM:
-               case TYPE_MC_AAL5:
+               case ERF_TYPE_ATM:
+               case ERF_TYPE_AAL5:
+               case ERF_TYPE_MC_ATM:
+               case ERF_TYPE_MC_AAL5:
                        if (p->dlt_list != NULL) {
                                p->dlt_list[dlt_index++] = DLT_ATM_RFC1483;
                                p->dlt_list[dlt_index++] = DLT_SUNATM;
@@ -1169,8 +1370,8 @@ dag_get_datalink(pcap_t *p)
                                p->linktype = DLT_ATM_RFC1483;
                        break;
 
-               case TYPE_COLOR_MC_HDLC_POS:
-               case TYPE_MC_HDLC:
+               case ERF_TYPE_COLOR_MC_HDLC_POS:
+               case ERF_TYPE_MC_HDLC:
                        if (p->dlt_list != NULL) {
                                p->dlt_list[dlt_index++] = DLT_CHDLC;
                                p->dlt_list[dlt_index++] = DLT_PPP_SERIAL;
@@ -1183,20 +1384,33 @@ dag_get_datalink(pcap_t *p)
                                p->linktype = DLT_CHDLC;
                        break;
 
-               case TYPE_IPV4:
-               case TYPE_IPV6:
+               case ERF_TYPE_IPV4:
+                       if (p->dlt_list != NULL) {
+                               p->dlt_list[dlt_index++] = DLT_RAW;
+                               p->dlt_list[dlt_index++] = DLT_IPV4;
+                       }
+                       if(!p->linktype)
+                               p->linktype = DLT_RAW;
+                       break;
+
+               case ERF_TYPE_IPV6:
+                       if (p->dlt_list != NULL) {
+                               p->dlt_list[dlt_index++] = DLT_RAW;
+                               p->dlt_list[dlt_index++] = DLT_IPV6;
+                       }
                        if(!p->linktype)
                                p->linktype = DLT_RAW;
                        break;
 
-               case TYPE_LEGACY:
-               case TYPE_MC_RAW:
-               case TYPE_MC_RAW_CHANNEL:
-               case TYPE_IP_COUNTER:
-               case TYPE_TCP_FLOW_COUNTER:
-               case TYPE_INFINIBAND:
-               case TYPE_RAW_LINK:
-               case TYPE_INFINIBAND_LINK:
+               case ERF_TYPE_LEGACY:
+               case ERF_TYPE_MC_RAW:
+               case ERF_TYPE_MC_RAW_CHANNEL:
+               case ERF_TYPE_IP_COUNTER:
+               case ERF_TYPE_TCP_FLOW_COUNTER:
+               case ERF_TYPE_INFINIBAND:
+               case ERF_TYPE_RAW_LINK:
+               case ERF_TYPE_INFINIBAND_LINK:
+               case ERF_TYPE_META:
                default:
                        /* Libpcap cannot deal with these types yet */
                        /* Add no 'native' DLTs, but still covered by DLT_ERF */
@@ -1215,3 +1429,39 @@ 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_list_t *devlistp _U_, char *errbuf)
+{
+       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;
+}
+
+/*
+ * Libpcap version string.
+ */
+const char *
+pcap_lib_version(void)
+{
+       return (PCAP_VERSION_STRING " (DAG-only)");
+}
+#endif
index 68520dc..67361af 100644 (file)
@@ -9,98 +9,4 @@
  */
 
 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
+int dag_findalldevs(pcap_if_list_t *devlistp, char *errbuf);
index c878353..1252975 100644 (file)
@@ -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
@@ -29,7 +29,7 @@
  */
 
 #ifdef HAVE_CONFIG_H
-#include "config.h"
+#include <config.h>
 #endif
 
 #include <string.h>
@@ -51,7 +51,7 @@ struct pcap_dbus {
 };
 
 static int
-dbus_read(pcap_t *handle, int max_packets, pcap_handler callback, u_char *user)
+dbus_read(pcap_t *handle, int max_packets _U_, pcap_handler callback, u_char *user)
 {
        struct pcap_dbus *handlep = handle->priv;
 
@@ -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)
@@ -145,6 +145,28 @@ dbus_cleanup(pcap_t *handle)
        pcap_cleanup_live_common(handle);
 }
 
+/*
+ * We don't support non-blocking mode.  I'm not sure what we'd
+ * do to support it and, given that we don't support select()/
+ * poll()/epoll_wait()/kevent() etc., it probably doesn't
+ * matter.
+ */
+static int
+dbus_getnonblock(pcap_t *p)
+{
+       pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
+           "Non-blocking mode isn't supported for capturing on D-Bus");
+       return (-1);
+}
+
+static int
+dbus_setnonblock(pcap_t *p, int nonblock _U_)
+{
+       pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
+           "Non-blocking mode isn't supported for capturing on D-Bus");
+       return (-1);
+}
+
 static int
 dbus_activate(pcap_t *handle)
 {
@@ -160,21 +182,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 +205,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;
        }
 
@@ -208,11 +230,36 @@ dbus_activate(pcap_t *handle)
        handle->setfilter_op = install_bpf_program; /* XXX, later add support for dbus_bus_add_match() */
        handle->setdirection_op = NULL;
        handle->set_datalink_op = NULL;      /* can't change data link type */
-       handle->getnonblock_op = pcap_getnonblock_fd;
-       handle->setnonblock_op = pcap_setnonblock_fd;
+       handle->getnonblock_op = dbus_getnonblock;
+       handle->setnonblock_op = dbus_setnonblock;
        handle->stats_op = dbus_stats;
-
+       handle->cleanup_op = dbus_cleanup;
+
+#ifndef _WIN32
+       /*
+        * Unfortunately, trying to do a select()/poll()/epoll_wait()/
+        * kevent()/etc. on a D-Bus connection isn't a simple
+        * case of "give me an FD on which to wait".
+        *
+        * Apparently, you have to register "add watch", "remove watch",
+        * and "toggle watch" functions with
+        * dbus_connection_set_watch_functions(),
+        * keep a *set* of FDs, add to that set in the "add watch"
+        * function, subtract from it in the "remove watch" function,
+        * and either add to or subtract from that set in the "toggle
+        * watch" function, and do the wait on *all* of the FDs in the
+        * set.  (Yes, you need the "toggle watch" function, so that
+        * the main loop doesn't itself need to check for whether
+        * a given watch is enabled or disabled - most libpcap programs
+        * know nothing about D-Bus and shouldn't *have* to know anything
+        * about D-Bus other than how to decode D-Bus messages.)
+        *
+        * Implementing that would require considerable changes in
+        * the way libpcap exports "selectable FDs" to its client.
+        * Until that's done, we just say "you can't do that".
+        */
        handle->selectable_fd = handle->fd = -1;
+#endif
 
        if (handle->opt.rfmon) {
                /*
@@ -222,6 +269,14 @@ dbus_activate(pcap_t *handle)
                return PCAP_ERROR_RFMON_NOTSUP;
        }
 
+       /*
+        * Turn a negative snapshot value (invalid), a snapshot value of
+        * 0 (unspecified), or a value bigger than the normal maximum
+        * value, into the maximum message length for D-Bus (128MB).
+        */
+       if (handle->snapshot <= 0 || handle->snapshot > 134217728)
+               handle->snapshot = 134217728;
+
        /* dbus_connection_set_max_message_size(handlep->conn, handle->snapshot); */
        if (handle->opt.buffer_size != 0)
                dbus_connection_set_max_received_size(handlep->conn, handle->opt.buffer_size);
@@ -234,7 +289,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 +305,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,20 +314,37 @@ 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);
 
        p->activate_op = dbus_activate;
+       /*
+        * Set these up front, so that, even if our client tries
+        * to set non-blocking mode before we're activated, or
+        * query the state of non-blocking mode, they get an error,
+        * rather than having the non-blocking mode option set
+        * for use later.
+        */
+       p->getnonblock_op = dbus_getnonblock;
+       p->setnonblock_op = dbus_setnonblock;
        return (p);
 }
 
-int 
-dbus_findalldevs(pcap_if_t **alldevsp, char *err_str)
+int
+dbus_findalldevs(pcap_if_list_t *devlistp, char *err_str)
 {
-       if (pcap_add_if(alldevsp, "dbus-system", 0, "D-Bus system bus", err_str) < 0)
+       /*
+        * The notion of "connected" vs. "disconnected" doesn't apply.
+        * XXX - what about the notions of "up" and "running"?
+        */
+       if (add_dev(devlistp, "dbus-system",
+           PCAP_IF_CONNECTION_STATUS_NOT_APPLICABLE, "D-Bus system bus",
+           err_str) == NULL)
                return -1;
-       if (pcap_add_if(alldevsp, "dbus-session", 0, "D-Bus session bus", err_str) < 0)
+       if (add_dev(devlistp, "dbus-session",
+           PCAP_IF_CONNECTION_STATUS_NOT_APPLICABLE, "D-Bus session bus",
+           err_str) == NULL)
                return -1;
        return 0;
 }
index 67493cc..c97f2e1 100644 (file)
@@ -1,2 +1,2 @@
 pcap_t *dbus_create(const char *, char *, int *);
-int dbus_findalldevs(pcap_if_t **devlistp, char *errbuf);
+int dbus_findalldevs(pcap_if_list_t *devlistp, char *errbuf);
diff --git a/pcap-dll.rc b/pcap-dll.rc
new file mode 100644 (file)
index 0000000..fc4f42b
--- /dev/null
@@ -0,0 +1,36 @@
+#include "config.h"
+#include <winver.h>
+
+  VS_VERSION_INFO VERSIONINFO
+    FILEVERSION    PACKAGE_VERSION_DLL
+    PRODUCTVERSION PACKAGE_VERSION_DLL
+    FILEFLAGSMASK  0x3fL
+    FILEOS         VOS__WINDOWS32
+    FILETYPE       VFT_DLL
+#ifdef _DEBUG
+    FILEFLAGS 0x1L
+#else
+    FILEFLAGS 0x0L
+#endif
+  BEGIN
+    BLOCK "StringFileInfo"
+    BEGIN
+      BLOCK "040904b0"
+      BEGIN
+        VALUE "Comments",         "https://github.com/the-tcpdump-group/libpcap/"
+        VALUE "CompanyName",      "The TCPdump Group"
+        VALUE "FileDescription",  "System-Independent Interface for User-Level Packet Capture"
+        VALUE "FileVersion",      "PACKAGE_VERSION_DLL"
+        VALUE "InternalName",     PACKAGE_NAME
+        VALUE "LegalCopyright",   "Copyright (c) The TCPdump Group"
+        VALUE "LegalTrademarks",  ""
+        VALUE "OriginalFilename", "wpcap.dll"
+        VALUE "ProductName",      PACKAGE_NAME
+        VALUE "ProductVersion",   PACKAGE_VERSION
+      END
+    END
+  BLOCK "VarFileInfo"
+  BEGIN
+    VALUE "Translation", 0x0, 1200
+  END
+  END
index 4598600..3ed8fa7 100644 (file)
@@ -69,7 +69,7 @@
  */
 
 #ifdef HAVE_CONFIG_H
-#include "config.h"
+#include <config.h>
 #endif
 
 #include <sys/types.h>
 #include "os-proto.h"
 #endif
 
-#ifndef PCAP_DEV_PREFIX
-#ifdef _AIX
-#define PCAP_DEV_PREFIX "/dev/dlpi"
-#else
-#define PCAP_DEV_PREFIX "/dev"
-#endif
+#if defined(__hpux)
+  /*
+   * HP-UX has a /dev/dlpi device; you open it and set the PPA of the actual
+   * network device you want.
+   */
+  #define HAVE_DEV_DLPI
+#elif defined(_AIX)
+  /*
+   * AIX has a /dev/dlpi directory, with devices named after the interfaces
+   * underneath it.
+   */
+  #define PCAP_DEV_PREFIX "/dev/dlpi"
+#elif defined(HAVE_SOLARIS)
+  /*
+   * Solaris has devices named after the interfaces underneath /dev.
+   */
+  #define PCAP_DEV_PREFIX "/dev"
 #endif
 
 #define        MAXDLBUF        8192
 
 /* Forwards */
-static char *split_dname(char *, int *, char *);
+static char *split_dname(char *, u_int *, char *);
 static int dl_doattach(int, int, char *);
 #ifdef DL_HP_RAWDLS
 static int dl_dohpuxbind(int, char *);
@@ -145,7 +156,7 @@ static int dlokack(int, const char *, char *, char *);
 static int dlinforeq(int, char *);
 static int dlinfoack(int, char *, char *);
 
-#ifdef HAVE_DLPI_PASSIVE
+#ifdef HAVE_DL_PASSIVE_REQ_T
 static void dlpassive(int, char *);
 #endif
 
@@ -153,27 +164,21 @@ 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
 static int dlpi_kread(int, off_t, void *, u_int, char *);
 #endif
 #ifdef HAVE_DEV_DLPI
-static int get_dlpi_ppa(int, const char *, int, char *);
+static int get_dlpi_ppa(int, const char *, u_int, u_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 +191,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 +224,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) {
@@ -224,13 +238,13 @@ pcap_read_dlpi(pcap_t *p, int cnt, pcap_handler callback, u_char *user)
                                case EAGAIN:
                                        return (0);
                                }
-                               strlcpy(p->errbuf, pcap_strerror(errno),
-                                   sizeof(p->errbuf));
+                               pcap_fmt_errmsg_for_errno(p->errbuf,
+                                   sizeof(p->errbuf), errno, "getmsg");
                                return (-1);
                        }
                        cc = data.len;
                } while (cc == 0);
-               bp = p->buffer + p->offset;
+               bp = (u_char *)p->buffer + p->offset;
        } else
                bp = p->bp;
 
@@ -248,20 +262,20 @@ 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_strerror(errno));
+               pcap_fmt_errmsg_for_errno(p->errbuf, PCAP_ERRBUF_SIZE,
+                   errno, "send");
                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_strerror(errno));
+               pcap_fmt_errmsg_for_errno(p->errbuf, PCAP_ERRBUF_SIZE,
+                   errno, "send");
                return (-1);
        }
        /*
@@ -293,12 +307,12 @@ pcap_inject_dlpi(pcap_t *p, const void *buf, size_t size)
         * it should check "p->linktype" and reject the send request if
         * it's anything other than DLT_EN10MB.
         */
-       strlcpy(p->errbuf, "send: Not supported on this version of this OS",
+       pcap_strlcpy(p->errbuf, "send: Not supported on this version of this OS",
            PCAP_ERRBUF_SIZE);
        ret = -1;
 #endif /* raw mode */
        return (ret);
-}   
+}
 
 #ifndef DL_IPATM
 #define DL_IPATM       0x12    /* ATM Classical IP interface */
@@ -331,29 +345,15 @@ pcap_cleanup_dlpi(pcap_t *p)
 }
 
 static int
-pcap_activate_dlpi(pcap_t *p)
+open_dlpi_device(const char *name, u_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];
-#ifndef HAVE_DEV_DLPI
+       char *cp;
+       int fd;
+#ifdef HAVE_DEV_DLPI
+       u_int unit;
+#else
        char dname2[100];
 #endif
 
@@ -361,21 +361,19 @@ 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));
+               pcap_strlcpy(dname, name, sizeof(dname));
        else
-               strlcpy(dname, cp + 1, sizeof(dname));
+               pcap_strlcpy(dname, cp + 1, sizeof(dname));
 
        /*
         * 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, &unit, errbuf);
+       if (cp == NULL)
+               return (PCAP_ERROR_NO_SUCH_DEVICE);
        *cp = '\0';
 
        /*
@@ -390,39 +388,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,
-                   "%s: %s", cp, pcap_strerror(errno));
-               goto bad;
+               pcap_fmt_errmsg_for_errno(errbuf, PCAP_ERRBUF_SIZE,
+                   errno, "%s", cp);
+               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;
+       status = get_dlpi_ppa(fd, dname, unit, ppa, errbuf);
+       if (status < 0) {
+               close(fd);
+               return (status);
        }
 #else
        /*
@@ -431,43 +414,41 @@ 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 == '/')
+               pcap_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
         * number from the device pathname.
         */
-       strlcpy(dname2, dname, sizeof(dname));
+       pcap_strlcpy(dname2, dname, sizeof(dname));
        *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_strerror(errno));
-                       goto bad;
+                       pcap_fmt_errmsg_for_errno(errbuf, PCAP_ERRBUF_SIZE,
+                           errno, "%s", dname);
+                       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,31 +463,78 @@ 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",
-                                   dname2, pcap_strerror(errno));
+                               pcap_fmt_errmsg_for_errno(errbuf,
+                                   PCAP_ERRBUF_SIZE, errno, "%s", dname2);
                        }
-                       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;
+       u_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
 
        /*
@@ -548,7 +576,7 @@ pcap_activate_dlpi(pcap_t *p)
                goto bad;
        }
 
-#ifdef HAVE_DLPI_PASSIVE
+#ifdef HAVE_DL_PASSIVE_REQ_T
        /*
         * Enable Passive mode to be able to capture on aggregated link.
         * Not supported in all Solaris versions.
@@ -617,6 +645,17 @@ pcap_activate_dlpi(pcap_t *p)
 #endif /* AIX vs. HP-UX vs. other */
 #endif /* !HP-UX 9 and !HP-UX 10.20 or later and !SINIX */
 
+       /*
+        * Turn a negative snapshot value (invalid), a snapshot value of
+        * 0 (unspecified), or a value bigger than the normal maximum
+        * value, into the maximum allowed value.
+        *
+        * If some application really *needs* a bigger snapshot
+        * length, we should just increase MAXIMUM_SNAPLEN.
+        */
+       if (p->snapshot <= 0 || p->snapshot > MAXIMUM_SNAPLEN)
+               p->snapshot = MAXIMUM_SNAPLEN;
+
 #ifdef HAVE_SOLARIS
        if (isatm) {
                /*
@@ -627,8 +666,8 @@ 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,
-                           "A_PROMISCON_REQ: %s", pcap_strerror(errno));
+                       pcap_fmt_errmsg_for_errno(p->errbuf, PCAP_ERRBUF_SIZE,
+                           errno, "A_PROMISCON_REQ");
                        goto bad;
                }
        } else
@@ -745,8 +784,8 @@ 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_strerror(errno));
+               pcap_fmt_errmsg_for_errno(p->errbuf, PCAP_ERRBUF_SIZE,
+                   errno, "DLIOCRAW");
                goto bad;
        }
 #endif
@@ -763,10 +802,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,8 +825,8 @@ 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_strerror(errno));
+               pcap_fmt_errmsg_for_errno(p->errbuf, PCAP_ERRBUF_SIZE,
+                   errno, "FLUSHR");
                goto bad;
        }
 
@@ -830,7 +869,7 @@ bad:
  * Returns NULL on error, and fills "ebuf" with an error message.
  */
 static char *
-split_dname(char *device, int *unitp, char *ebuf)
+split_dname(char *device, u_int *unitp, char *ebuf)
 {
        char *cp;
        char *eos;
@@ -841,7 +880,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,20 +892,20 @@ 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);
        }
-       *unitp = (int)unit;
+       *unitp = (u_int)unit;
        return (cp);
 }
 
@@ -929,7 +968,7 @@ dl_dohpuxbind(int fd, char *ebuf)
                *ebuf = '\0';
                hpsap++;
                if (hpsap > 100) {
-                       strlcpy(ebuf,
+                       pcap_strlcpy(ebuf,
                            "All SAPs from 22 through 100 are in use",
                            PCAP_ERRBUF_SIZE);
                        return (-1);
@@ -960,8 +999,81 @@ 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;
+       u_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);
+}
+
+static int
+get_if_flags(const char *name _U_, bpf_u_int32 *flags _U_, char *errbuf _U_)
+{
+       /*
+        * Nothing we can do other than mark loopback devices as "the
+        * connected/disconnected status doesn't apply".
+        *
+        * XXX - on Solaris, can we do what the dladm command does,
+        * i.e. get a connected/disconnected indication from a kstat?
+        * (Note that you can also get the link speed, and possibly
+        * other information, from a kstat as well.)
+        */
+       if (*flags & PCAP_IF_LOOPBACK) {
+               /*
+                * Loopback devices aren't wireless, and "connected"/
+                * "disconnected" doesn't apply to them.
+                */
+               *flags |= PCAP_IF_CONNECTION_STATUS_NOT_APPLICABLE;
+               return (0);
+       }
+       return (0);
+}
+
 int
-pcap_platform_finddevs(pcap_if_t **alldevsp, char *errbuf)
+pcap_platform_finddevs(pcap_if_list_t *devlistp, char *errbuf)
 {
 #ifdef HAVE_SOLARIS
        int fd;
@@ -972,7 +1084,16 @@ 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(devlistp, errbuf, is_dlpi_interface,
+           get_if_flags) == -1)
+               return (-1);    /* failure */
 
+#ifdef HAVE_SOLARIS
        /*
         * We may have to do special magic to get ATM devices.
         */
@@ -989,13 +1110,18 @@ 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_strerror(errno));
+               pcap_fmt_errmsg_for_errno(errbuf, PCAP_ERRBUF_SIZE,
+                   errno, "A_GET_UNITS");
                return (-1);
        }
        for (i = 0; i < buf.nunits; i++) {
-               snprintf(baname, sizeof baname, "ba%u", i);
-               if (pcap_add_if(alldevsp, baname, 0, NULL, errbuf) < 0)
+               pcap_snprintf(baname, sizeof baname, "ba%u", i);
+               /*
+                * XXX - is there a notion of "up" and "running"?
+                * And is there a way to determine whether the
+                * interface is plugged into a network?
+                */
+               if (add_dev(devlistp, baname, 0, NULL, errbuf) == NULL)
                        return (-1);
        }
 #endif
@@ -1015,9 +1141,8 @@ 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,
-                   "send_request: putmsg \"%s\": %s",
-                   what, pcap_strerror(errno));
+               pcap_fmt_errmsg_for_errno(ebuf, PCAP_ERRBUF_SIZE,
+                   errno, "send_request: putmsg \"%s\"", what);
                return (-1);
        }
        return (0);
@@ -1029,6 +1154,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,8 +1170,8 @@ 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",
-                   what, pcap_strerror(errno));
+               pcap_fmt_errmsg_for_errno(ebuf, PCAP_ERRBUF_SIZE,
+                   errno, "recv_ack: %s getmsg", what);
                return (PCAP_ERROR);
        }
 
@@ -1066,17 +1193,18 @@ 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,
-                           "recv_ack: %s: UNIX error - %s",
-                           what, pcap_strerror(dlp->error_ack.dl_unix_errno));
+                       pcap_fmt_errmsg_for_errno(ebuf, PCAP_ERRBUF_SIZE,
+                           dlp->error_ack.dl_unix_errno,
+                           "recv_ack: %s: UNIX error", what);
                        if (dlp->error_ack.dl_unix_errno == EPERM ||
                            dlp->error_ack.dl_unix_errno == EACCES)
                                return (PCAP_ERROR_PERM_DENIED);
                        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 +1214,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 +1230,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 +1332,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 +1424,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);
        }
 }
@@ -1357,7 +1482,7 @@ dlinfoack(int fd, char *bufp, char *ebuf)
        return (recv_ack(fd, DL_INFO_ACK_SIZE, "info", bufp, ebuf, NULL));
 }
 
-#ifdef HAVE_DLPI_PASSIVE
+#ifdef HAVE_DL_PASSIVE_REQ_T
 /*
  * Enable DLPI passive mode. We do not care if this request fails, as this
  * indicates the underlying DLPI device does not support link aggregation.
@@ -1412,28 +1537,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) {
+               pcap_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
 
@@ -1478,12 +1604,12 @@ echo 'lanc_outbound_promisc_flag/W1' | /usr/bin/adb -w /stand/vmunix /dev/kmem
  * Setting the variable is not necessary on HP-UX 11.x.
  */
 static int
-get_dlpi_ppa(register int fd, register const char *device, register int unit,
-    register char *ebuf)
+get_dlpi_ppa(register int fd, register const char *device, register u_int unit,
+    u_int *ppa, register char *ebuf)
 {
        register dl_hp_ppa_ack_t *ap;
        register dl_hp_ppa_info_t *ipstart, *ip;
-       register int i;
+       register u_int i;
        char dname[100];
        register u_long majdev;
        struct stat statbuf;
@@ -1493,7 +1619,6 @@ get_dlpi_ppa(register int fd, register const char *device, register int unit,
        dl_hp_ppa_ack_t *dlp;
        struct strbuf ctl;
        int flags;
-       int ppa;
 
        memset((char *)&req, 0, sizeof(req));
        req.dl_primitive = DL_HP_PPA_REQ;
@@ -1521,21 +1646,26 @@ 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,
-                   "get_dlpi_ppa: hpppa getmsg: %s", pcap_strerror(errno));
+               pcap_fmt_errmsg_for_errno(ebuf, PCAP_ERRBUF_SIZE,
+                   errno, "get_dlpi_ppa: hpppa getmsg");
+               return (PCAP_ERROR);
+       }
+       if (ctl.len == -1) {
+               pcap_snprintf(ebuf, PCAP_ERRBUF_SIZE,
+                   "get_dlpi_ppa: hpppa getmsg: control buffer has no data");
                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,
+       if ((size_t)ctl.len < DL_HP_PPA_ACK_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,8 +1673,8 @@ 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,
-                   "get_dlpi_ppa: hpppa malloc: %s", pcap_strerror(errno));
+               pcap_fmt_errmsg_for_errno(ebuf, PCAP_ERRBUF_SIZE,
+                   errno, "get_dlpi_ppa: hpppa malloc");
                return (PCAP_ERROR);
        }
        ctl.maxlen = dlp->dl_length;
@@ -1552,13 +1682,18 @@ 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,
-                   "get_dlpi_ppa: hpppa getmsg: %s", pcap_strerror(errno));
+               pcap_fmt_errmsg_for_errno(ebuf, PCAP_ERRBUF_SIZE,
+                   errno, "get_dlpi_ppa: hpppa getmsg");
                free(ppa_data_buf);
                return (PCAP_ERROR);
        }
-       if (ctl.len < dlp->dl_length) {
-               snprintf(ebuf, PCAP_ERRBUF_SIZE,
+       if (ctl.len == -1) {
+               pcap_snprintf(ebuf, PCAP_ERRBUF_SIZE,
+                   "get_dlpi_ppa: hpppa getmsg: control buffer has no data");
+               return (PCAP_ERROR);
+       }
+       if ((u_int)ctl.len < dlp->dl_length) {
+               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);
@@ -1569,7 +1704,7 @@ get_dlpi_ppa(register int fd, register const char *device, register int unit,
        ipstart = (dl_hp_ppa_info_t *)ppa_data_buf;
        ip = ipstart;
 
-#ifdef HAVE_HP_PPA_INFO_T_DL_MODULE_ID_1
+#ifdef HAVE_DL_HP_PPA_INFO_T_DL_MODULE_ID_1
        /*
         * The "dl_hp_ppa_info_t" structure has a "dl_module_id_1"
         * member that should, in theory, contain the part of the
@@ -1615,10 +1750,10 @@ 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%u", device, unit);
                if (stat(dname, &statbuf) < 0) {
-                       snprintf(ebuf, PCAP_ERRBUF_SIZE, "stat: %s: %s",
-                           dname, pcap_strerror(errno));
+                       pcap_fmt_errmsg_for_errno(ebuf, PCAP_ERRBUF_SIZE,
+                           errno, "stat: %s", dname);
                        return (PCAP_ERROR);
                }
                majdev = major(statbuf.st_rdev);
@@ -1634,19 +1769,19 @@ get_dlpi_ppa(register int fd, register const char *device, register int unit,
                }
        }
        if (i == ap->dl_count) {
-               snprintf(ebuf, PCAP_ERRBUF_SIZE,
-                   "can't find /dev/dlpi PPA for %s%d", device, unit);
+               pcap_snprintf(ebuf, PCAP_ERRBUF_SIZE,
+                   "can't find /dev/dlpi PPA for %s%u", 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);
        }
-       ppa = ip->dl_ppa;
+       *ppa = ip->dl_ppa;
        free(ppa_data_buf);
-       return (ppa);
+       return (0);
 }
 #endif
 
@@ -1665,8 +1800,8 @@ static char path_vmunix[] = "/hp-ux";
 
 /* Determine ppa number that specifies ifname */
 static int
-get_dlpi_ppa(register int fd, register const char *ifname, register int unit,
-    register char *ebuf)
+get_dlpi_ppa(register int fd, register const char *ifname, register u_int unit,
+    u_int *ppa, register char *ebuf)
 {
        register const char *cp;
        register int kd;
@@ -1678,26 +1813,26 @@ 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);
+               return (PCAP_ERROR);
        }
        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);
+               return (PCAP_ERROR);
        }
        kd = open("/dev/kmem", O_RDONLY);
        if (kd < 0) {
-               snprintf(ebuf, PCAP_ERRBUF_SIZE, "kmem open: %s",
-                   pcap_strerror(errno));
-               return (-1);
+               pcap_fmt_errmsg_for_errno(ebuf, PCAP_ERRBUF_SIZE,
+                   errno, "kmem open");
+               return (PCAP_ERROR);
        }
        if (dlpi_kread(kd, nl[NL_IFNET].n_value,
            &addr, sizeof(addr), ebuf) < 0) {
                close(kd);
-               return (-1);
+               return (PCAP_ERROR);
        }
        for (; addr != NULL; addr = ifnet.if_next) {
                if (dlpi_kread(kd, (off_t)addr,
@@ -1705,15 +1840,17 @@ get_dlpi_ppa(register int fd, register const char *ifname, register int unit,
                    dlpi_kread(kd, (off_t)ifnet.if_name,
                    if_name, sizeof(ifnet.if_name), ebuf) < 0) {
                        (void)close(kd);
-                       return (-1);
+                       return (PCAP_ERROR);
                }
                if_name[sizeof(ifnet.if_name)] = '\0';
-               if (strcmp(if_name, ifname) == 0 && ifnet.if_unit == unit)
-                       return (ifnet.if_index);
+               if (strcmp(if_name, ifname) == 0 && ifnet.if_unit == unit) {
+                       *ppa = ifnet.if_index;
+                       return (0);
+               }
        }
 
-       snprintf(ebuf, PCAP_ERRBUF_SIZE, "Can't find %s", ifname);
-       return (-1);
+       pcap_snprintf(ebuf, PCAP_ERRBUF_SIZE, "Can't find %s", ifname);
+       return (PCAP_ERROR_NO_SUCH_DEVICE);
 }
 
 static int
@@ -1723,17 +1860,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_strerror(errno));
+               pcap_fmt_errmsg_for_errno(ebuf, PCAP_ERRBUF_SIZE,
+                   errno, "lseek");
                return (-1);
        }
        cc = read(fd, buf, len);
        if (cc < 0) {
-               snprintf(ebuf, PCAP_ERRBUF_SIZE, "read: %s",
-                   pcap_strerror(errno));
+               pcap_fmt_errmsg_for_errno(ebuf, PCAP_ERRBUF_SIZE,
+                   errno, "read");
                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 +1879,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);
 
@@ -1761,3 +1898,12 @@ pcap_create_interface(const char *device, char *ebuf)
        p->activate_op = pcap_activate_dlpi;
        return (p);
 }
+
+/*
+ * Libpcap version string.
+ */
+const char *
+pcap_lib_version(void)
+{
+       return (PCAP_VERSION_STRING);
+}
index 43f50c7..c159b55 100644 (file)
@@ -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.
@@ -176,6 +174,17 @@ static int pcap_activate_dos (pcap_t *pcap)
     return (PCAP_ERROR_RFMON_NOTSUP);
   }
 
+  /*
+   * Turn a negative snapshot value (invalid), a snapshot value of
+   * 0 (unspecified), or a value bigger than the normal maximum
+   * value, into the maximum allowed value.
+   *
+   * If some application really *needs* a bigger snapshot
+   * length, we should just increase MAXIMUM_SNAPLEN.
+   */
+  if (pcap->snapshot <= 0 || pcap->snapshot > MAXIMUM_SNAPLEN)
+    pcap->snapshot = MAXIMUM_SNAPLEN;
+
   if (pcap->snapshot < ETH_MIN+8)
       pcap->snapshot = ETH_MIN+8;
 
@@ -188,23 +197,28 @@ 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))
     {
+      /* XXX - free pcap->buffer? */
       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);
+    /* XXX - free pcap->buffer? */
     return (PCAP_ERROR);
   }
   handle_to_device [pcap->fd-1] = active_dev;
@@ -221,7 +235,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 +266,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 +283,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 +291,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 +307,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 +334,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 +353,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))
@@ -391,17 +413,17 @@ int pcap_stats_ex (pcap_t *p, struct pcap_stat_ex *se)
 
   if (!dev || !dev->get_stats)
   {
-    strlcpy (p->errbuf, "detailed device statistics not available",
+    pcap_strlcpy (p->errbuf, "detailed device statistics not available",
              PCAP_ERRBUF_SIZE);
     return (-1);
   }
 
   if (!strnicmp(dev->name,"pkt",3))
   {
-    strlcpy (p->errbuf, "pktdrvr doesn't have detailed statistics",
+    pcap_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 +464,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)
@@ -458,6 +480,7 @@ static void pcap_cleanup_dos (pcap_t *p)
        return;
   }
   close_driver();
+  /* XXX - call pcap_cleanup_live_common? */
 }
 
 /*
@@ -495,6 +518,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 +527,44 @@ 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
- * were up and could be opened.
+ * The list may be NULL epty if no interfaces were up and could be opened.
  */
-int pcap_findalldevs (pcap_if_t **alldevsp, char *errbuf)
+int pcap_platform_finddevs  (pcap_if_list_t *devlistp, char *errbuf)
 {
   struct device     *dev;
-  struct sockaddr_ll sa_ll_1, sa_ll_2;
+  pcap_if_t *curdev;
+#if 0   /* Pkt drivers should have no addresses */
+  struct sockaddr_in sa_ll_1, sa_ll_2;
   struct sockaddr   *addr, *netmask, *broadaddr, *dstaddr;
-  pcap_if_t *devlist = NULL;
+#endif
   int       ret = 0;
-  size_t    addr_size = sizeof(struct sockaddr_ll);
+  int       found = 0;
 
   for (dev = (struct device*)dev_base; dev; dev = dev->next)
   {
@@ -548,42 +577,45 @@ int pcap_findalldevs (pcap_if_t **alldevsp, char *errbuf)
     FLUSHK();
     (*dev->close) (dev);
 
+    /*
+     * XXX - find out whether it's up or running?  Does that apply here?
+     * Can we find out if anything's plugged into the adapter, if it's
+     * a wired device, and set PCAP_IF_CONNECTION_STATUS_CONNECTED
+     * or PCAP_IF_CONNECTION_STATUS_DISCONNECTED?
+     */
+    if ((curdev = add_dev(devlistp, dev->name, 0,
+                dev->long_name, errbuf)) == NULL)
+    {
+      ret = -1;
+      break;
+    }
+    found = 1;
+#if 0   /* Pkt drivers should have no addresses */
     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)
-    {
-      ret = -1;
-      break;
-    }
-    if (add_addr_to_iflist(&devlist,dev->name, dev->flags, addr, addr_size,
-                           netmask, addr_size, broadaddr, addr_size,
-                           dstaddr, addr_size, errbuf) < 0)
+    if (add_addr_to_dev(curdev, addr, sizeof(*addr),
+                        netmask, sizeof(*netmask),
+                        broadaddr, sizeof(*broadaddr),
+                        dstaddr, sizeof(*dstaddr), errbuf) < 0)
     {
       ret = -1;
       break;
     }
+#endif
   }
 
-  if (devlist && ret < 0)
-  {
-    pcap_freealldevs (devlist);
-    devlist = NULL;
-  }
-  else
-  if (!devlist)
+  if (ret == 0 && !found)
      strcpy (errbuf, "No drivers found");
 
-  *alldevsp = devlist;
   return (ret);
 }
 
@@ -605,12 +637,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 +667,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 +689,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 +711,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 +788,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 +965,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 +992,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 +1005,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 +1085,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 +1124,7 @@ static int pkt_open (struct device *dev)
 
   if (!PktInitDriver(mode))
      return (0);
+
   PktResetStatistics (pktInfo.handle);
   PktQueueBusy (FALSE);
   return (1);
@@ -1290,7 +1322,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.
@@ -1494,3 +1526,11 @@ static void pktq_clear (struct rx_ringbuf *q)
 
 #endif /* USE_32BIT_DRIVERS */
 
+/*
+ * Libpcap version string.
+ */
+const char *
+pcap_lib_version(void)
+{
+  return ("DOS-" PCAP_VERSION_STRING);
+}
index 8f92252..bf47fb5 100644 (file)
@@ -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)) \
index 777d3e3..cd8cdbb 100644 (file)
@@ -8,7 +8,7 @@
  */
 
 #ifdef HAVE_CONFIG_H
-#include "config.h"
+#include <config.h>
 #endif
 
 #include <sys/types.h>
index f65a6a9..777e735 100644 (file)
@@ -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@ "5 November 2017"
 .SH NAME
 pcap-filter \- packet filter syntax
 .br
@@ -29,11 +29,11 @@ pcap-filter \- packet filter syntax
 is used to compile a string into a filter program.
 The resulting filter program can then be applied to
 some stream of packets to determine which packets will be supplied to
-.BR pcap_loop() ,
-.BR pcap_dispatch() ,
-.BR pcap_next() ,
+.BR pcap_loop(3PCAP) ,
+.BR pcap_dispatch(3PCAP) ,
+.BR pcap_next(3PCAP) ,
 or
-.BR pcap_next_ex() .
+.BR pcap_next_ex(3PCAP) .
 .LP
 The \fIfilter expression\fP consists of one or more
 .IR primitives .
@@ -86,12 +86,6 @@ The
 and
 .B addr4
 qualifiers are only valid for IEEE 802.11 Wireless LAN link layers.
-For some link layers, such as SLIP and the ``cooked'' Linux capture mode
-used for the ``any'' device and for some other device types, the
-.B inbound
-and
-.B outbound
-qualifiers can be used to specify a desired direction.
 .IP \fIproto\fP
 .I proto
 qualifiers restrict the match to a particular protocol.
@@ -181,9 +175,10 @@ be checked for a match.
 .IP "\fBether dst \fIehost\fP"
 True if the Ethernet destination address is \fIehost\fP.
 \fIEhost\fP
-may be either a name from /etc/ethers or a number (see
-.IR ethers (3N)
-for numeric format).
+may be either a name from /etc/ethers or a numerical MAC address of the
+form "xx:xx:xx:xx:xx:xx", "xx.xx.xx.xx.xx.xx", "xx-xx-xx-xx-xx-xx",
+"xxxx.xxxx.xxxx", "xxxxxxxxxxxx", or various mixes of ':', '.', and '-',
+where each "x" is a hex digit (0-9, a-f, or A-F).
 .IP "\fBether src \fIehost\fP"
 True if the Ethernet source address is \fIehost\fP.
 .IP "\fBether host \fIehost\fP"
@@ -298,7 +293,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 +367,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.
@@ -465,8 +460,6 @@ Token Ring packets (no check is done for LLC frames);
 FDDI packets (no check is done for LLC frames);
 .IP
 LLC-encapsulated ATM packets, for SunATM on Solaris.
-.IP
-
 .IP "\fBllc\fP \Fitype\fR"
 True if the packet has an 802.2 LLC header and has the specified
 .IR type .
@@ -513,6 +506,16 @@ Exchange Identification (XID) U PDUs
 \fBfrmr\fR
 Frame Reject (FRMR) U PDUs
 .RE
+.IP \fBinbound\fP
+Packet was received by the host performing the capture rather than being
+sent by that host.  This is only supported for certain link-layer types,
+such as SLIP and the ``cooked'' Linux capture mode
+used for the ``any'' device and for some other device types.
+.IP \fBoutbound\fP
+Packet was sent by the host performing the capture rather than being
+received by that host.  This is only supported for certain link-layer types,
+such as SLIP and the ``cooked'' Linux capture mode
+used for the ``any'' device and for some other device types.
 .IP "\fBifname \fIinterface\fR"
 True if the packet was logged as coming from the specified interface (applies
 only to packets logged by OpenBSD's or FreeBSD's
@@ -566,7 +569,7 @@ are:
 and
 .B block
 and, with later versions of
-.BR pf (4)),
+.BR pf (4),
 .BR nat ,
 .BR rdr ,
 .B binat
@@ -697,7 +700,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 +736,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
@@ -847,8 +866,9 @@ intervening fragment.
 Some offsets and field values may be expressed as names rather than
 as numeric values.
 The following protocol header field offsets are
-available: \fBicmptype\fP (ICMP type field), \fBicmpcode\fP (ICMP
-code field), and \fBtcpflags\fP (TCP flags field).
+available: \fBicmptype\fP (ICMP type field), \fBicmp6type (ICMP v6 type field)
+\fBicmpcode\fP (ICMP code field), \fBicmp6code\fP (ICMP v6 code field), and
+\fBtcpflags\fP (TCP flags field).
 
 The following ICMP type field values are available: \fBicmp-echoreply\fP,
 \fBicmp-unreach\fP, \fBicmp-sourcequench\fP, \fBicmp-redirect\fP,
@@ -857,14 +877,28 @@ The following ICMP type field values are available: \fBicmp-echoreply\fP,
 \fBicmp-tstampreply\fP, \fBicmp-ireq\fP, \fBicmp-ireqreply\fP,
 \fBicmp-maskreq\fP, \fBicmp-maskreply\fP.
 
+The following ICMPv6 type fields are available: \fBicmp6-echo\fP,
+\fBicmp6-echoreply\fP, \fBicmp6-multicastlistenerquery\fP,
+\fBicmp6-multicastlistenerreportv1\fP, \fBicmp6-multicastlistenerdone\fP,
+\fBicmp6-routersolicit\fP, \fBicmp6-routeradvert\fP,
+\fBicmp6-neighborsolicit\fP, \fBicmp6-neighboradvert\fP, \fBicmp6-redirect\fP,
+\fBicmp6-routerrenum\fP, \fBicmp6-nodeinformationquery\fP,
+\fBicmp6-nodeinformationresponse\fP, \fBicmp6-ineighbordiscoverysolicit\fP,
+\fBicmp6-ineighbordiscoveryadvert\fP, \fBicmp6-multicastlistenerreportv2\fP,
+\fBicmp6-homeagentdiscoveryrequest\fP, \fBicmp6-homeagentdiscoveryreply\fP,
+\fBicmp6-mobileprefixsolicit\fP, \fBicmp6-mobileprefixadvert\fP,
+\fBicmp6-certpathsolicit\fP, \fBicmp6-certpathadvert\fP,
+\fBicmp6-multicastrouteradvert\fP, \fBicmp6-multicastroutersolicit\fP,
+\fBicmp6-multicastrouterterm\fP.
+
 The following TCP flags field values are available: \fBtcp-fin\fP,
 \fBtcp-syn\fP, \fBtcp-rst\fP, \fBtcp-push\fP,
-\fBtcp-ack\fP, \fBtcp-urg\fP.
+\fBtcp-ack\fP, \fBtcp-urg\fP, \fBtcp-ece\fP,
+\fBtcp-cwr\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
@@ -995,11 +1029,12 @@ icmp[icmptype] != icmp-echo and icmp[icmptype] != icmp-echoreply
 .SH "SEE ALSO"
 pcap(3PCAP)
 .SH BUGS
-Please send problems, bugs, questions, desirable enhancements, etc. to:
+To report a security issue please send an e-mail to security@tcpdump.org.
 .LP
-.RS
-tcpdump-workers@lists.tcpdump.org
-.RE
+To report bugs and other problems, contribute patches, request a
+feature, provide generic feedback etc please see the file
+.I CONTRIBUTING
+in the libpcap source tree root.
 .LP
 Filter expressions on fields other than those in Token Ring headers will
 not correctly handle source-routed Token Ring packets.
index 5a20444..5295f8f 100644 (file)
 #ifndef pcap_int_h
 #define        pcap_int_h
 
+#include <signal.h>
+
 #include <pcap/pcap.h>
 
+#include "varattrs.h"
+#include "fmtutils.h"
+
+/*
+ * Version string.
+ * Uses PACKAGE_VERSION from config.h.
+ */
+#define PCAP_VERSION_STRING "libpcap version " PACKAGE_VERSION
+
 #ifdef __cplusplus
 extern "C" {
 #endif
 
-#ifdef WIN32
-#include <Packet32.h>
-extern CRITICAL_SECTION g_PcapCompileCriticalSection;
-#endif /* WIN32 */
-
 #ifdef MSDOS
-#include <fcntl.h>
-#include <io.h>
+  #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*/
-
-/*
- * Swap byte ordering of unsigned long long timestamp on a big endian
- * machine.
- */
-#define SWAPLL(ull)  ((ull & 0xff00000000000000) >> 56) | \
-                      ((ull & 0x00ff000000000000) >> 40) | \
-                      ((ull & 0x0000ff0000000000) >> 24) | \
-                      ((ull & 0x000000ff00000000) >> 8)  | \
-                      ((ull & 0x00000000ff000000) << 8)  | \
-                      ((ull & 0x0000000000ff0000) << 24) | \
-                      ((ull & 0x000000000000ff00) << 40) | \
-                      ((ull & 0x00000000000000ff) << 56)
-
-#else /* A recent Visual studio compiler or not VC */
-
 /*
  * Swap byte ordering of unsigned long long timestamp on a big endian
  * machine.
  */
-#define SWAPLL(ull)  ((ull & 0xff00000000000000LL) >> 56) | \
-                      ((ull & 0x00ff000000000000LL) >> 40) | \
-                      ((ull & 0x0000ff0000000000LL) >> 24) | \
-                      ((ull & 0x000000ff00000000LL) >> 8)  | \
-                      ((ull & 0x00000000ff000000LL) << 8)  | \
-                      ((ull & 0x0000000000ff0000LL) << 24) | \
-                      ((ull & 0x000000000000ff00LL) << 40) | \
-                      ((ull & 0x00000000000000ffLL) << 56)
-
-#endif /* _MSC_VER */
+#define SWAPLL(ull)  ((ull & 0xff00000000000000ULL) >> 56) | \
+                      ((ull & 0x00ff000000000000ULL) >> 40) | \
+                      ((ull & 0x0000ff0000000000ULL) >> 24) | \
+                      ((ull & 0x000000ff00000000ULL) >> 8)  | \
+                      ((ull & 0x00000000ff000000ULL) << 8)  | \
+                      ((ull & 0x0000000000ff0000ULL) << 24) | \
+                      ((ull & 0x000000000000ff00ULL) << 40) | \
+                      ((ull & 0x00000000000000ffULL) << 56)
 
 /*
  * Maximum snapshot length.
@@ -99,38 +86,64 @@ extern CRITICAL_SECTION g_PcapCompileCriticalSection;
  *    2) small enough not to cause attempts to allocate huge amounts of
  *       memory; some applications might use the snapshot length in a
  *       savefile header to control the size of the buffer they allocate,
- *       so a size of, say, 2^31-1 might not work well.
+ *       so a size of, say, 2^31-1 might not work well.  (libpcap uses it
+ *       as a hint, but doesn't start out allocating a buffer bigger than
+ *       2 KiB, and grows the buffer as necessary, but not beyond the
+ *       per-linktype maximum snapshot length.  Other code might naively
+ *       use it; we want to avoid writing a too-large snapshot length,
+ *       in order not to cause that code problems.)
  *
  * We don't enforce this in pcap_set_snaplen(), but we use it internally.
  */
 #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 */
+       int     nonblock;       /* non-blocking mode - don't wait for packets to be delivered, return "no packets available" */
        int     tstamp_type;
        int     tstamp_precision;
+
+       /*
+        * Platform-dependent options.
+        */
+#ifdef __linux__
+       int     protocol;       /* protocol to use when creating PF_PACKET socket */
+#endif
+#ifdef _WIN32
+       int     nocapture_local;/* disable NPF loopback */
+#endif
 };
 
 typedef int    (*activate_op_t)(pcap_t *);
 typedef int    (*can_set_rfmon_op_t)(pcap_t *);
 typedef int    (*read_op_t)(pcap_t *, int cnt, pcap_handler, u_char *);
+typedef int    (*next_packet_op_t)(pcap_t *, struct pcap_pkthdr *, u_char **);
 typedef int    (*inject_op_t)(pcap_t *, const void *, size_t);
+typedef void   (*save_current_filter_op_t)(pcap_t *, const char *);
 typedef int    (*setfilter_op_t)(pcap_t *, struct bpf_program *);
 typedef int    (*setdirection_op_t)(pcap_t *, pcap_direction_t);
 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    (*getnonblock_op_t)(pcap_t *);
+typedef int    (*setnonblock_op_t)(pcap_t *, int);
 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,34 +158,35 @@ struct pcap {
        read_op_t read_op;
 
        /*
-        * Method to call to read to read packets from a savefile.
+        * Method to call to read the next packet from a savefile.
         */
-       int (*next_packet_op)(pcap_t *, struct pcap_pkthdr *, u_char **);
+       next_packet_op_t next_packet_op;
 
-#ifdef WIN32
-       ADAPTER *adapter;
-       LPPACKET Packet;
-       int nonblock;
+#ifdef _WIN32
+       HANDLE handle;
 #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;
 
-       int break_loop;         /* flag set to force break from packet-reading loop */
+       sig_atomic_t break_loop; /* flag set to force break from packet-reading loop */
 
        void *priv;             /* private data for methods */
 
+#ifdef ENABLE_REMOTE
+       struct pcap_samp rmt_samp;      /* parameters related to the sampling process. */
+#endif
+
        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 +213,36 @@ 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;
+
+#if !defined(_WIN32) && !defined(MSDOS)
+       int selectable_fd;      /* FD on which select()/poll()/epoll_wait()/kevent()/etc. can be done */
+
+       /*
+        * In case there either is no selectable FD, or there is but
+        * it doesn't necessarily work (e.g., if it doesn't get notified
+        * if the packet capture timeout expires before the buffer
+        * fills up), this points to a timeout that should be used
+        * in select()/poll()/epoll_wait()/kevent() call.  The pcap_t should
+        * be put into non-blocking mode, and, if the timeout expires on
+        * the call, an attempt should be made to read packets from all
+        * pcap_t's with a required timeout, and the code must be
+        * prepared not to see any packets from the attempt.
+        */
+       struct timeval *required_select_timeout;
+#endif
+
+       /*
         * Placeholder for filter code if bpf not in kernel.
         */
        struct bpf_program fcode;
@@ -223,6 +263,7 @@ struct pcap {
        activate_op_t activate_op;
        can_set_rfmon_op_t can_set_rfmon_op;
        inject_op_t inject_op;
+       save_current_filter_op_t save_current_filter_op;
        setfilter_op_t setfilter_op;
        setdirection_op_t setdirection_op;
        set_datalink_op_t set_datalink_op;
@@ -235,20 +276,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 +382,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,9 +401,9 @@ 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)
-int    pcap_getnonblock_fd(pcap_t *, char *);
-int    pcap_setnonblock_fd(pcap_t *p, int, char *);
+#if !defined(_WIN32) && !defined(MSDOS)
+int    pcap_getnonblock_fd(pcap_t *);
+int    pcap_setnonblock_fd(pcap_t *p, int);
 #endif
 
 /*
@@ -383,38 +418,58 @@ 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.).
+ * A pcap_if_list_t * is a reference to a list of devices.
+ *
+ * A get_if_flags_func is a platform-dependent function called to get
+ * additional interface flags.
+ *
+ * "pcap_platform_finddevs()" is the platform-dependent routine to
+ * find local network interfaces.
+ *
+ * "pcap_findalldevs_interfaces()" is a helper to find those 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.
+ * "add_dev()" adds an entry to a pcap_if_list_t.
  *
- * "pcap_add_if()" adds an interface to the list of interfaces, for
- * use by various "find interfaces" routines.
+ * "find_dev()" tries to find a device, by name, in a pcap_if_list_t.
+ *
+ * "find_or_add_dev()" checks whether a device is already in a pcap_if_list_t
+ * and, if not, adds an entry for it.
  */
-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 *);
+struct pcap_if_list;
+typedef struct pcap_if_list pcap_if_list_t;
+typedef int (*get_if_flags_func)(const char *, bpf_u_int32 *, char *);
+int    pcap_platform_finddevs(pcap_if_list_t *, char *);
+#if !defined(_WIN32) && !defined(MSDOS)
+int    pcap_findalldevs_interfaces(pcap_if_list_t *, char *,
+           int (*)(const char *), get_if_flags_func);
+#endif
+pcap_if_t *find_or_add_dev(pcap_if_list_t *, const char *, bpf_u_int32,
+           get_if_flags_func, const char *, char *);
+pcap_if_t *find_dev(pcap_if_list_t *, const char *);
+pcap_if_t *add_dev(pcap_if_list_t *, const char *, bpf_u_int32, const char *,
+           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,
-           const char *, char *);
+#ifndef _WIN32
+pcap_if_t *find_or_add_if(pcap_if_list_t *, const char *, bpf_u_int32,
+           get_if_flags_func, char *);
+int    add_addr_to_if(pcap_if_list_t *, const char *, bpf_u_int32,
+           get_if_flags_func,
+           struct sockaddr *, size_t, struct sockaddr *, size_t,
+           struct sockaddr *, size_t, struct sockaddr *, size_t, char *);
+#endif
 
 /*
  * Internal interfaces for "pcap_open_offline()".
@@ -422,14 +477,39 @@ int       add_or_find_if(pcap_if_t **, pcap_if_t **, const char *, u_int,
  * "pcap_open_offline_common()" allocates and fills in a pcap_t, for use
  * by pcap_open_offline routines.
  *
+ * "pcap_adjust_snapshot()" adjusts the snapshot to be non-zero and
+ * fit within an int.
+ *
  * "sf_cleanup()" closes the file handle associated with a pcap_t, if
  * appropriate, and frees all data common to all modules for handling
  * savefile types.
  */
 pcap_t *pcap_open_offline_common(char *ebuf, size_t size);
+bpf_u_int32 pcap_adjust_snapshot(bpf_u_int32 linktype, bpf_u_int32 snaplen);
 void   sf_cleanup(pcap_t *p);
 
 /*
+ * Internal interfaces for doing user-mode filtering of packets and
+ * validating filter programs.
+ */
+/*
+ * 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;
+};
+
+/*
+ * Filtering routine that takes the auxiliary data as an additional
+ * argument.
+ */
+u_int  bpf_filter_with_aux_data(const struct bpf_insn *,
+    const u_char *, u_int, u_int, const struct bpf_aux_data *);
+
+/*
  * Internal interfaces for both "pcap_create()" and routines that
  * open savefiles.
  *
@@ -438,14 +518,14 @@ void      sf_cleanup(pcap_t *p);
  */
 void   pcap_oneshot(u_char *, const struct pcap_pkthdr *, const u_char *);
 
-#ifdef WIN32
-char   *pcap_win32strerror(void);
-#endif
-
 int    install_bpf_program(pcap_t *, struct bpf_program *);
 
 int    pcap_strcasecmp(const char *, const char *);
 
+#ifdef YYDEBUG
+extern int pcap_debug;
+#endif
+
 #ifdef __cplusplus
 }
 #endif
index 333e532..a38da8b 100644 (file)
@@ -25,7 +25,7 @@
  */
 
 #ifdef HAVE_CONFIG_H
-#include "config.h"
+#include <config.h>
 #endif
 
 #include <sys/types.h>
@@ -80,7 +80,7 @@ list_interfaces(const char *linkname, void *arg)
                lwp->lw_err = ENOMEM;
                return (B_TRUE);
        }
-       (void) strlcpy(entry->linkname, linkname, DLPI_LINKNAME_MAX);
+       (void) pcap_strlcpy(entry->linkname, linkname, DLPI_LINKNAME_MAX);
 
        if (lwp->lw_list == NULL) {
                lwp->lw_list = entry;
@@ -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,10 +133,21 @@ 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;
        }
 
+       /*
+        * Turn a negative snapshot value (invalid), a snapshot value of
+        * 0 (unspecified), or a value bigger than the normal maximum
+        * value, into the maximum allowed value.
+        *
+        * If some application really *needs* a bigger snapshot
+        * length, we should just increase MAXIMUM_SNAPLEN.
+        */
+       if (p->snapshot <= 0 || p->snapshot > MAXIMUM_SNAPLEN)
+               p->snapshot = MAXIMUM_SNAPLEN;
+
        /* Enable promiscuous mode. */
        if (p->opt.promisc) {
                retv = dlpromiscon(p, DL_PROMISC_PHYS);
@@ -187,7 +198,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,8 +220,8 @@ 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_strerror(errno));
+               pcap_fmt_errmsg_for_errno(p->errbuf, PCAP_ERRBUF_SIZE,
+                   errno, "FLUSHR");
                goto bad;
        }
 
@@ -258,7 +269,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,12 +277,46 @@ 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);
+}
+
+static int
+get_if_flags(const char *name _U_, bpf_u_int32 *flags _U_, char *errbuf _U_)
+{
+       /*
+        * Nothing we can do other than mark loopback devices as "the
+        * connected/disconnected status doesn't apply".
+        *
+        * XXX - on Solaris, can we do what the dladm command does,
+        * i.e. get a connected/disconnected indication from a kstat?
+        * (Note that you can also get the link speed, and possibly
+        * other information, from a kstat as well.)
+        */
+       if (*flags & PCAP_IF_LOOPBACK) {
+               /*
+                * Loopback devices aren't wireless, and "connected"/
+                * "disconnected" doesn't apply to them.
+                */
+               *flags |= PCAP_IF_CONNECTION_STATUS_NOT_APPLICABLE;
+               return (0);
+       }
+       return (0);
+}
+
+/*
  * 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.
  */
 int
-pcap_platform_finddevs(pcap_if_t **alldevsp, char *errbuf)
+pcap_platform_finddevs(pcap_if_list_t *devlistp, char *errbuf)
 {
        int retv = 0;
 
@@ -279,20 +324,39 @@ 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(devlistp, errbuf,
+           is_dlpi_interface, get_if_flags) == -1)
+               return (-1);    /* failure */
+
        /* dlpi_walk() for loopback will be added here. */
 
+       /*
+        * Find all DLPI devices in the current zone.
+        *
+        * XXX - will pcap_findalldevs_interfaces() find any devices
+        * outside the current zone?  If not, the only reason to call
+        * it would be to get the interface addresses.
+        */
        dlpi_walk(list_interfaces, &lw, 0);
 
        if (lw.lw_err != 0) {
-               snprintf(errbuf, PCAP_ERRBUF_SIZE,
-                   "dlpi_walk: %s", pcap_strerror(lw.lw_err));
+               pcap_fmt_errmsg_for_errno(errbuf, PCAP_ERRBUF_SIZE,
+                   lw.lw_err, "dlpi_walk");
                retv = -1;
                goto done;
        }
 
        /* Add linkname if it does not exist on the list. */
        for (entry = lw.lw_list; entry != NULL; entry = entry->lnl_next) {
-               if (pcap_add_if(alldevsp, entry->linkname, 0, NULL, errbuf) < 0)
+               /*
+                * If it isn't already in the list of devices, try to
+                * add it.
+                */
+               if (find_or_add_dev(devlistp, entry->linkname, 0, get_if_flags,
+                   NULL, errbuf) == NULL)
                        retv = -1;
        }
 done:
@@ -337,7 +401,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,19 +468,28 @@ 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);
 
        p->activate_op = pcap_activate_libdlpi;
        return (p);
 }
+
+/*
+ * Libpcap version string.
+ */
+const char *
+pcap_lib_version(void)
+{
+       return (PCAP_VERSION_STRING);
+}
index e42c5b3..777e9dc 100644 (file)
@@ -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
@@ -43,6 +43,6 @@ The names for those values begin with
 .BR LINKTYPE_ .
 .PP
 The link-layer header types supported by libpcap are described at
-http://www.tcpdump.org/linktypes.html.
+https://www.tcpdump.org/linktypes.html.
 .SH SEE ALSO
-pcap_datalink(3PCAP)
+pcap(3PCAP)
index 48749c1..70334b3 100644 (file)
  *  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.
  *
  * 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.
 #define _GNU_SOURCE
 
 #ifdef HAVE_CONFIG_H
-#include "config.h"
+#include <config.h>
 #endif
 
 #include <errno.h>
 # 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
 #   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
 #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,10 +336,9 @@ struct pcap_linux {
 /*
  * Prototypes for internal functions and methods.
  */
-static void map_arphrd_to_dlt(pcap_t *, int, const char *, int);
-#ifdef HAVE_PF_PACKET_SOCKETS
-static short int map_packet_type_to_sll_type(short int);
-#endif
+static int get_if_flags(const char *, bpf_u_int32 *, char *);
+static int is_wifi(int, const char *);
+static void map_arphrd_to_dlt(pcap_t *, int, int, const char *, int);
 static int pcap_activate_linux(pcap_t *);
 static int activate_old(pcap_t *);
 static int activate_new(pcap_t *);
@@ -334,8 +353,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 +387,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
@@ -360,13 +403,59 @@ static int pcap_read_linux_mmap_v2(pcap_t *, int, pcap_handler , u_char *);
 static int pcap_read_linux_mmap_v3(pcap_t *, int, pcap_handler , u_char *);
 #endif
 static int pcap_setfilter_linux_mmap(pcap_t *, struct bpf_program *);
-static int pcap_setnonblock_mmap(pcap_t *p, int nonblock, char *errbuf);
-static int pcap_getnonblock_mmap(pcap_t *p, char *errbuf);
+static int pcap_setnonblock_mmap(pcap_t *p, int nonblock);
+static int pcap_getnonblock_mmap(pcap_t *p);
 static void pcap_oneshot_mmap(u_char *user, const struct pcap_pkthdr *h,
     const u_char *bytes);
 #endif
 
 /*
+ * In pre-3.0 kernels, the tp_vlan_tci field is set to whatever the
+ * vlan_tci field in the skbuff is.  0 can either mean "not on a VLAN"
+ * or "on VLAN 0".  There is no flag set in the tp_status field to
+ * distinguish between them.
+ *
+ * In 3.0 and later kernels, if there's a VLAN tag present, the tp_vlan_tci
+ * field is set to the VLAN tag, and the TP_STATUS_VLAN_VALID flag is set
+ * in the tp_status field, otherwise the tp_vlan_tci field is set to 0 and
+ * the TP_STATUS_VLAN_VALID flag isn't set in the tp_status field.
+ *
+ * With a pre-3.0 kernel, we cannot distinguish between packets with no
+ * VLAN tag and packets on VLAN 0, so we will mishandle some packets, and
+ * there's nothing we can do about that.
+ *
+ * So, on those systems, which never set the TP_STATUS_VLAN_VALID flag, we
+ * continue the behavior of earlier libpcaps, wherein we treated packets
+ * with a VLAN tag of 0 as being packets without a VLAN tag rather than packets
+ * on VLAN 0.  We do this by treating packets with a tp_vlan_tci of 0 and
+ * with the TP_STATUS_VLAN_VALID flag not set in tp_status as not having
+ * VLAN tags.  This does the right thing on 3.0 and later kernels, and
+ * continues the old unfixably-imperfect behavior on pre-3.0 kernels.
+ *
+ * If TP_STATUS_VLAN_VALID isn't defined, we test it as the 0x10 bit; it
+ * has that value in 3.0 and later kernels.
+ */
+#ifdef TP_STATUS_VLAN_VALID
+  #define VLAN_VALID(hdr, hv)  ((hv)->tp_vlan_tci != 0 || ((hdr)->tp_status & TP_STATUS_VLAN_VALID))
+#else
+  /*
+   * This is being compiled on a system that lacks TP_STATUS_VLAN_VALID,
+   * so we testwith the value it has in the 3.0 and later kernels, so
+   * we can test it if we're running on a system that has it.  (If we're
+   * running on a system that doesn't have it, it won't be set in the
+   * tp_status field, so the tests of it will always fail; that means
+   * we behave the way we did before we introduced this macro.)
+   */
+  #define VLAN_VALID(hdr, hv)  ((hv)->tp_vlan_tci != 0 || ((hdr)->tp_status & 0x10))
+#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
  */
 #ifdef HAVE_PF_PACKET_SOCKETS
@@ -375,20 +464,26 @@ static int        iface_get_id(int fd, const char *device, char *ebuf);
 static int     iface_get_mtu(int fd, const char *device, char *ebuf);
 static int     iface_get_arptype(int fd, const char *device, char *ebuf);
 #ifdef HAVE_PF_PACKET_SOCKETS
-static int     iface_bind(int fd, int ifindex, char *ebuf);
+static int     iface_bind(int fd, int ifindex, char *ebuf, int protocol);
 #ifdef IW_MODE_MONITOR
 static int     has_wext(int sock_fd, const char *device, char *ebuf);
 #endif /* IW_MODE_MONITOR */
 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
 static int     fix_program(pcap_t *handle, struct sock_fprog *fcode,
     int is_mapped);
-static int     fix_offset(struct bpf_insn *p);
+static int     fix_offset(pcap_t *handle, struct bpf_insn *p);
 static int     set_kernel_filter(pcap_t *handle, struct sock_fprog *fcode);
 static int     reset_kernel_filter(pcap_t *handle);
 
@@ -403,34 +498,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 +527,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_strerror(errno));
-               if (handle->tstamp_type_list != NULL)
-                       free(handle->tstamp_type_list);
-               free(handle);
+               pcap_fmt_errmsg_for_errno(ebuf, PCAP_ERRBUF_SIZE,
+                   errno, "malloc");
+               pcap_close(handle);
                return NULL;
        }
        handle->tstamp_precision_list[0] = PCAP_TSTAMP_PRECISION_MICRO;
@@ -501,7 +581,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 +599,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,9 +614,8 @@ get_mac80211_phydev(pcap_t *handle, const char *device, char *phydev_path,
                        free(pathstr);
                        return 0;
                }
-               snprintf(handle->errbuf, PCAP_ERRBUF_SIZE,
-                   "%s: Can't readlink %s: %s", device, pathstr,
-                   strerror(errno));
+               pcap_fmt_errmsg_for_errno(handle->errbuf, PCAP_ERRBUF_SIZE,
+                   errno, "%s: Can't readlink %s", device, pathstr);
                free(pathstr);
                return PCAP_ERROR;
        }
@@ -591,20 +670,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 +691,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 +714,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 +732,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 +764,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 +792,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 +804,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_fmt_errmsg_for_errno(handle->errbuf, PCAP_ERRBUF_SIZE,
+                   errno, "strdup");
+               /*
+                * 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 +842,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 +853,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 +861,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 +875,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 +920,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 +939,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,18 +964,21 @@ 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;
        }
 
        /*
         * Now configure the monitor interface up.
         */
        memset(&ifr, 0, sizeof(ifr));
-       strlcpy(ifr.ifr_name, handlep->mondevice, sizeof(ifr.ifr_name));
+       pcap_strlcpy(ifr.ifr_name, handlep->mondevice, sizeof(ifr.ifr_name));
        if (ioctl(sock_fd, SIOCGIFFLAGS, &ifr) == -1) {
-               snprintf(handle->errbuf, PCAP_ERRBUF_SIZE,
-                   "%s: Can't get flags for %s: %s", device,
-                   handlep->mondevice, strerror(errno));
+               pcap_fmt_errmsg_for_errno(handle->errbuf, PCAP_ERRBUF_SIZE,
+                   errno, "%s: Can't get flags for %s", device,
+                   handlep->mondevice);
                del_mon_if(handle, sock_fd, &nlstate, device,
                    handlep->mondevice);
                nl80211_cleanup(&nlstate);
@@ -882,9 +986,9 @@ added:
        }
        ifr.ifr_flags |= IFF_UP|IFF_RUNNING;
        if (ioctl(sock_fd, SIOCSIFFLAGS, &ifr) == -1) {
-               snprintf(handle->errbuf, PCAP_ERRBUF_SIZE,
-                   "%s: Can't set flags for %s: %s", device,
-                   handlep->mondevice, strerror(errno));
+               pcap_fmt_errmsg_for_errno(handle->errbuf, PCAP_ERRBUF_SIZE,
+                   errno, "%s: Can't set flags for %s", device,
+                   handlep->mondevice);
                del_mon_if(handle, sock_fd, &nlstate, device,
                    handlep->mondevice);
                nl80211_cleanup(&nlstate);
@@ -911,6 +1015,48 @@ 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);
+       pcap_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_protocol(pcap_t *handle)
+{
+       int protocol;
+
+       protocol = handle->opt.protocol;
+       if (protocol == 0)
+               protocol = ETH_P_ALL;
+
+       return htons(protocol);
+}
+
 static int
 pcap_can_set_rfmon_linux(pcap_t *handle)
 {
@@ -923,7 +1069,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 +1089,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 */
@@ -962,17 +1108,23 @@ pcap_can_set_rfmon_linux(pcap_t *handle)
         * (We assume that if we have Wireless Extensions support
         * we also have PF_PACKET support.)
         */
-       sock_fd = socket(PF_PACKET, SOCK_RAW, htons(ETH_P_ALL));
+       sock_fd = socket(PF_PACKET, SOCK_RAW, pcap_protocol(handle));
        if (sock_fd == -1) {
-               (void)snprintf(handle->errbuf, PCAP_ERRBUF_SIZE,
-                   "socket: %s", pcap_strerror(errno));
+               pcap_fmt_errmsg_for_errno(handle->errbuf, PCAP_ERRBUF_SIZE,
+                   errno, "socket");
                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,
+       pcap_strlcpy(ireq.ifr_ifrn.ifrn_name, handle->opt.device,
            sizeof ireq.ifr_ifrn.ifrn_name);
        if (ioctl(sock_fd, SIOCGIWMODE, &ireq) != -1) {
                /*
@@ -983,8 +1135,8 @@ pcap_can_set_rfmon_linux(pcap_t *handle)
        }
        if (errno == ENODEV) {
                /* The device doesn't even exist. */
-               (void)snprintf(handle->errbuf, PCAP_ERRBUF_SIZE,
-                   "SIOCGIWMODE failed: %s", pcap_strerror(errno));
+               pcap_fmt_errmsg_for_errno(handle->errbuf, PCAP_ERRBUF_SIZE,
+                   errno, "SIOCGIWMODE failed");
                close(sock_fd);
                return PCAP_ERROR_NO_SUCH_DEVICE;
        }
@@ -1005,16 +1157,16 @@ static long int
 linux_if_drops(const char * if_name)
 {
        char buffer[512];
-       char * bufptr;
-       FILE * file;
-       int field_to_convert = 3, if_name_sz = strlen(if_name);
+       FILE *file;
+       char *bufptr, *nameptr, *colonptr;
+       int field_to_convert = 3;
        long int dropped_pkts = 0;
-       
+
        file = fopen("/proc/net/dev", "r");
        if (!file)
                return 0;
 
-       while (!dropped_pkts && fgets( buffer, sizeof(buffer), file ))
+       while (fgets(buffer, sizeof(buffer), file) != NULL)
        {
                /*      search for 'bytes' -- if its in there, then
                        that means we need to grab the fourth field. otherwise
@@ -1024,34 +1176,79 @@ 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) == ' ') &&
-                       *(bufptr + if_name_sz) == ':')
+
+               /*
+                * See whether this line corresponds to this device.
+                * The line should have zero or more leading blanks,
+                * followed by a device name, followed by a colon,
+                * followed by the statistics.
+                */
+               bufptr = buffer;
+               /* Skip leading blanks */
+               while (*bufptr == ' ')
+                       bufptr++;
+               nameptr = bufptr;
+               /* Look for the colon */
+               colonptr = strchr(nameptr, ':');
+               if (colonptr == NULL)
+               {
+                       /*
+                        * Not found; this could, for example, be the
+                        * header line.
+                        */
+                       continue;
+               }
+               /* Null-terminate the interface name. */
+               *colonptr = '\0';
+               if (strcmp(if_name, nameptr) == 0)
                {
-                       bufptr = bufptr + if_name_sz + 1;
+                       /*
+                        * OK, this line has the statistics for the interface.
+                        * Skip past the interface name.
+                        */
+                       bufptr = colonptr + 1;
 
                        /* grab the nth field from it */
-                       while--field_to_convert && *bufptr != '\0')
+                       while (--field_to_convert && *bufptr != '\0')
                        {
-                               while (*bufptr != '\0' && *(bufptr++) == ' ');
-                               while (*bufptr != '\0' && *(bufptr++) != ' ');
+                               /*
+                                * This isn't the field we want.
+                                * First, skip any leading blanks before
+                                * the field.
+                                */
+                               while (*bufptr == ' ')
+                                       bufptr++;
+
+                               /*
+                                * Now skip the non-blank characters of
+                                * the field.
+                                */
+                               while (*bufptr != '\0' && *bufptr != ' ')
+                                       bufptr++;
                        }
-                       
-                       /* get rid of any final spaces */
-                       while (*bufptr != '\0' && *bufptr == ' ') bufptr++;
-                       
-                       if (*bufptr != '\0')
-                               dropped_pkts = strtol(bufptr, NULL, 10);
 
+                       if (field_to_convert == 0)
+                       {
+                               /*
+                                * We've found the field we want.
+                                * Skip any leading blanks before it.
+                                */
+                               while (*bufptr == ' ')
+                                       bufptr++;
+
+                               /*
+                                * Now extract the value, if we have one.
+                                */
+                               if (*bufptr != '\0')
+                                       dropped_pkts = strtol(bufptr, NULL, 10);
+                       }
                        break;
                }
        }
-       
+
        fclose(file);
        return dropped_pkts;
-} 
+}
 
 
 /*
@@ -1095,7 +1292,7 @@ static void       pcap_cleanup_linux( pcap_t *handle )
                         * in 2.0[.x] kernels.
                         */
                        memset(&ifr, 0, sizeof(ifr));
-                       strlcpy(ifr.ifr_name, handlep->device,
+                       pcap_strlcpy(ifr.ifr_name, handlep->device,
                            sizeof(ifr.ifr_name));
                        if (ioctl(handle->fd, SIOCGIFFLAGS, &ifr) == -1) {
                                fprintf(stderr,
@@ -1159,7 +1356,7 @@ static void       pcap_cleanup_linux( pcap_t *handle )
                         */
                        oldflags = 0;
                        memset(&ifr, 0, sizeof(ifr));
-                       strlcpy(ifr.ifr_name, handlep->device,
+                       pcap_strlcpy(ifr.ifr_name, handlep->device,
                            sizeof(ifr.ifr_name));
                        if (ioctl(handle->fd, SIOCGIFFLAGS, &ifr) != -1) {
                                if (ifr.ifr_flags & IFF_UP) {
@@ -1173,7 +1370,7 @@ static void       pcap_cleanup_linux( pcap_t *handle )
                        /*
                         * Now restore the mode.
                         */
-                       strlcpy(ireq.ifr_ifrn.ifrn_name, handlep->device,
+                       pcap_strlcpy(ireq.ifr_ifrn.ifrn_name, handlep->device,
                            sizeof ireq.ifr_ifrn.ifrn_name);
                        ireq.u.mode = handlep->oldmode;
                        if (ioctl(handle->fd, SIOCSIWMODE, &ireq) == -1) {
@@ -1221,6 +1418,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 +1522,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
@@ -1255,6 +1540,17 @@ pcap_activate_linux(pcap_t *handle)
                goto fail;
        }
 
+       /*
+        * Turn a negative snapshot value (invalid), a snapshot value of
+        * 0 (unspecified), or a value bigger than the normal maximum
+        * value, into the maximum allowed value.
+        *
+        * If some application really *needs* a bigger snapshot
+        * length, we should just increase MAXIMUM_SNAPLEN.
+        */
+       if (handle->snapshot <= 0 || handle->snapshot > MAXIMUM_SNAPLEN)
+               handle->snapshot = MAXIMUM_SNAPLEN;
+
        handle->inject_op = pcap_inject_linux;
        handle->setfilter_op = pcap_setfilter_linux;
        handle->setdirection_op = pcap_setdirection_linux;
@@ -1274,7 +1570,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 +1578,17 @@ pcap_activate_linux(pcap_t *handle)
 
        handlep->device = strdup(device);
        if (handlep->device == NULL) {
-               snprintf(handle->errbuf, PCAP_ERRBUF_SIZE, "strdup: %s",
-                        pcap_strerror(errno) );
-               return PCAP_ERROR;
+               pcap_fmt_errmsg_for_errno(handle->errbuf, PCAP_ERRBUF_SIZE,
+                   errno, "strdup");
+               status = PCAP_ERROR;
+               goto fail;
        }
-       
+
        /* 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 +1627,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:
@@ -1344,11 +1645,10 @@ pcap_activate_linux(pcap_t *handle)
                        /*
                         * We failed to set up to use it, or the kernel
                         * supports it, but we failed to enable it.
-                        * ret has been set to the error status to
+                        * status has been set to the error status to
                         * return and, if it's PCAP_ERROR, handle->errbuf
                         * contains the error message.
                         */
-                       status = ret;
                        goto fail;
                }
        }
@@ -1375,8 +1675,8 @@ 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,
-                                "SO_RCVBUF: %s", pcap_strerror(errno));
+                       pcap_fmt_errmsg_for_errno(handle->errbuf,
+                           PCAP_ERRBUF_SIZE, errno, "SO_RCVBUF");
                        status = PCAP_ERROR;
                        goto fail;
                }
@@ -1386,8 +1686,8 @@ pcap_activate_linux(pcap_t *handle)
 
        handle->buffer   = malloc(handle->bufsize + handle->offset);
        if (!handle->buffer) {
-               snprintf(handle->errbuf, PCAP_ERRBUF_SIZE,
-                        "malloc: %s", pcap_strerror(errno));
+               pcap_fmt_errmsg_for_errno(handle->errbuf, PCAP_ERRBUF_SIZE,
+                   errno, "malloc");
                status = PCAP_ERROR;
                goto fail;
        }
@@ -1411,7 +1711,7 @@ fail:
  *  error occured.
  */
 static int
-pcap_read_linux(pcap_t *handle, int max_packets, pcap_handler callback, u_char *user)
+pcap_read_linux(pcap_t *handle, int max_packets _U_, pcap_handler callback, u_char *user)
 {
        /*
         * Currently, on Linux only one packet is delivered per read,
@@ -1448,6 +1748,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)
@@ -1476,11 +1792,10 @@ pcap_read_packet(pcap_t *handle, pcap_handler callback, u_char *userdata)
        int                     offset;
 #ifdef HAVE_PF_PACKET_SOCKETS
        struct sockaddr_ll      from;
-       struct sll_header       *hdrp;
 #else
        struct sockaddr         from;
 #endif
-#if defined(HAVE_PACKET_AUXDATA) && defined(HAVE_LINUX_TPACKET_AUXDATA_TP_VLAN_TCI)
+#if defined(HAVE_PACKET_AUXDATA) && defined(HAVE_STRUCT_TPACKET_AUXDATA_TP_VLAN_TCI)
        struct iovec            iov;
        struct msghdr           msg;
        struct cmsghdr          *cmsg;
@@ -1488,20 +1803,24 @@ pcap_read_packet(pcap_t *handle, pcap_handler callback, u_char *userdata)
                struct cmsghdr  cmsg;
                char            buf[CMSG_SPACE(sizeof(struct tpacket_auxdata))];
        } cmsg_buf;
-#else /* defined(HAVE_PACKET_AUXDATA) && defined(HAVE_LINUX_TPACKET_AUXDATA_TP_VLAN_TCI) */
+#else /* defined(HAVE_PACKET_AUXDATA) && defined(HAVE_STRUCT_TPACKET_AUXDATA_TP_VLAN_TCI) */
        socklen_t               fromlen;
-#endif /* defined(HAVE_PACKET_AUXDATA) && defined(HAVE_LINUX_TPACKET_AUXDATA_TP_VLAN_TCI) */
+#endif /* defined(HAVE_PACKET_AUXDATA) && defined(HAVE_STRUCT_TPACKET_AUXDATA_TP_VLAN_TCI) */
        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
         * fake packet header.
         */
-       if (handlep->cooked)
-               offset = SLL_HDR_LEN;
-       else
+       if (handlep->cooked) {
+               if (handle->linktype == DLT_LINUX_SLL2)
+                       offset = SLL2_HDR_LEN;
+               else
+                       offset = SLL_HDR_LEN;
+       } else
                offset = 0;
 #else
        /*
@@ -1526,9 +1845,9 @@ 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)
+#if defined(HAVE_PACKET_AUXDATA) && defined(HAVE_STRUCT_TPACKET_AUXDATA_TP_VLAN_TCI)
        msg.msg_name            = &from;
        msg.msg_namelen         = sizeof(from);
        msg.msg_iov             = &iov;
@@ -1539,7 +1858,7 @@ pcap_read_packet(pcap_t *handle, pcap_handler callback, u_char *userdata)
 
        iov.iov_len             = handle->bufsize - offset;
        iov.iov_base            = bp + offset;
-#endif /* defined(HAVE_PACKET_AUXDATA) && defined(HAVE_LINUX_TPACKET_AUXDATA_TP_VLAN_TCI) */
+#endif /* defined(HAVE_PACKET_AUXDATA) && defined(HAVE_STRUCT_TPACKET_AUXDATA_TP_VLAN_TCI) */
 
        do {
                /*
@@ -1555,15 +1874,15 @@ pcap_read_packet(pcap_t *handle, pcap_handler callback, u_char *userdata)
                        return PCAP_ERROR_BREAK;
                }
 
-#if defined(HAVE_PACKET_AUXDATA) && defined(HAVE_LINUX_TPACKET_AUXDATA_TP_VLAN_TCI)
+#if defined(HAVE_PACKET_AUXDATA) && defined(HAVE_STRUCT_TPACKET_AUXDATA_TP_VLAN_TCI)
                packet_len = recvmsg(handle->fd, &msg, MSG_TRUNC);
-#else /* defined(HAVE_PACKET_AUXDATA) && defined(HAVE_LINUX_TPACKET_AUXDATA_TP_VLAN_TCI) */
+#else /* defined(HAVE_PACKET_AUXDATA) && defined(HAVE_STRUCT_TPACKET_AUXDATA_TP_VLAN_TCI) */
                fromlen = sizeof(from);
                packet_len = recvfrom(
                        handle->fd, bp + offset,
                        handle->bufsize - offset, MSG_TRUNC,
                        (struct sockaddr *) &from, &fromlen);
-#endif /* defined(HAVE_PACKET_AUXDATA) && defined(HAVE_LINUX_TPACKET_AUXDATA_TP_VLAN_TCI) */
+#endif /* defined(HAVE_PACKET_AUXDATA) && defined(HAVE_STRUCT_TPACKET_AUXDATA_TP_VLAN_TCI) */
        } while (packet_len == -1 && errno == EINTR);
 
        /* Check if an error occured */
@@ -1582,13 +1901,13 @@ 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,
-                                "recvfrom: %s", pcap_strerror(errno));
+                       pcap_fmt_errmsg_for_errno(handle->errbuf,
+                           PCAP_ERRBUF_SIZE, errno, "recvfrom");
                        return PCAP_ERROR;
                }
        }
@@ -1631,20 +1950,45 @@ pcap_read_packet(pcap_t *handle, pcap_handler callback, u_char *userdata)
                 * Add the length of the fake header to the length
                 * of packet data we read.
                 */
-               packet_len += SLL_HDR_LEN;
-
-               hdrp = (struct sll_header *)bp;
-               hdrp->sll_pkttype = map_packet_type_to_sll_type(from.sll_pkttype);
-               hdrp->sll_hatype = htons(from.sll_hatype);
-               hdrp->sll_halen = htons(from.sll_halen);
-               memcpy(hdrp->sll_addr, from.sll_addr,
-                   (from.sll_halen > SLL_ADDRLEN) ?
-                     SLL_ADDRLEN :
-                     from.sll_halen);
-               hdrp->sll_protocol = from.sll_protocol;
+               if (handle->linktype == DLT_LINUX_SLL2) {
+                       struct sll2_header      *hdrp;
+
+                       packet_len += SLL2_HDR_LEN;
+
+                       hdrp = (struct sll2_header *)bp;
+                       hdrp->sll2_protocol = from.sll_protocol;
+                       hdrp->sll2_reserved_mbz = 0;
+                       hdrp->sll2_if_index = htonl(from.sll_ifindex);
+                       hdrp->sll2_hatype = htons(from.sll_hatype);
+                       hdrp->sll2_pkttype = from.sll_pkttype;
+                       hdrp->sll2_halen = from.sll_halen;
+                       memcpy(hdrp->sll2_addr, from.sll_addr,
+                           (from.sll_halen > SLL_ADDRLEN) ?
+                             SLL_ADDRLEN :
+                             from.sll_halen);
+               } else {
+                       struct sll_header       *hdrp;
+
+                       packet_len += SLL_HDR_LEN;
+
+                       hdrp = (struct sll_header *)bp;
+                       hdrp->sll_pkttype = htons(from.sll_pkttype);
+                       hdrp->sll_hatype = htons(from.sll_hatype);
+                       hdrp->sll_halen = htons(from.sll_halen);
+                       memcpy(hdrp->sll_addr, from.sll_addr,
+                           (from.sll_halen > SLL_ADDRLEN) ?
+                             SLL_ADDRLEN :
+                             from.sll_halen);
+                       hdrp->sll_protocol = from.sll_protocol;
+               }
        }
 
-#if defined(HAVE_PACKET_AUXDATA) && defined(HAVE_LINUX_TPACKET_AUXDATA_TP_VLAN_TCI)
+       /*
+        * Start out with no VLAN information.
+        */
+       aux_data.vlan_tag_present = 0;
+       aux_data.vlan_tag = 0;
+#if defined(HAVE_PACKET_AUXDATA) && defined(HAVE_STRUCT_TPACKET_AUXDATA_TP_VLAN_TCI)
        if (handlep->vlan_offset != -1) {
                for (cmsg = CMSG_FIRSTHDR(&msg); cmsg; cmsg = CMSG_NXTHDR(&msg, cmsg)) {
                        struct tpacket_auxdata *aux;
@@ -1653,34 +1997,59 @@ pcap_read_packet(pcap_t *handle, pcap_handler callback, u_char *userdata)
 
                        if (cmsg->cmsg_len < CMSG_LEN(sizeof(struct tpacket_auxdata)) ||
                            cmsg->cmsg_level != SOL_PACKET ||
-                           cmsg->cmsg_type != PACKET_AUXDATA)
+                           cmsg->cmsg_type != PACKET_AUXDATA) {
+                               /*
+                                * This isn't a PACKET_AUXDATA auxiliary
+                                * data item.
+                                */
                                continue;
+                       }
 
                        aux = (struct tpacket_auxdata *)CMSG_DATA(cmsg);
-#if defined(TP_STATUS_VLAN_VALID)
-                       if ((aux->tp_vlan_tci == 0) && !(aux->tp_status & TP_STATUS_VLAN_VALID))
-#else
-                       if (aux->tp_vlan_tci == 0) /* this is ambigious but without the
-                                               TP_STATUS_VLAN_VALID flag, there is
-                                               nothing that we can do */
-#endif
+                       if (!VLAN_VALID(aux, aux)) {
+                               /*
+                                * There is no VLAN information in the
+                                * auxiliary data.
+                                */
                                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);
 
+                       /*
+                        * Save a flag indicating that we have a VLAN tag,
+                        * and the VLAN TCI, to bpf_aux_data struct for
+                        * use by the BPF filter if we're doing the
+                        * filtering in userland.
+                        */
+                       aux_data.vlan_tag_present = 1;
+                       aux_data.vlan_tag = htons(aux->tp_vlan_tci) & 0x0fff;
+
+                       /*
+                        * Add the tag to the packet lengths.
+                        */
                        packet_len += VLAN_TAG_LEN;
                }
        }
-#endif /* defined(HAVE_PACKET_AUXDATA) && defined(HAVE_LINUX_TPACKET_AUXDATA_TP_VLAN_TCI) */
+#endif /* defined(HAVE_PACKET_AUXDATA) && defined(HAVE_STRUCT_TPACKET_AUXDATA_TP_VLAN_TCI) */
 #endif /* HAVE_PF_PACKET_SOCKETS */
 
        /*
@@ -1721,9 +2090,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,16 +2103,16 @@ 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,
-                                       "SIOCGSTAMPNS: %s", pcap_strerror(errno));
+                       pcap_fmt_errmsg_for_errno(handle->errbuf,
+                           PCAP_ERRBUF_SIZE, errno, "SIOCGSTAMPNS");
                        return PCAP_ERROR;
                }
         } else
 #endif
        {
                if (ioctl(handle->fd, SIOCGSTAMP, &pcap_header.ts) == -1) {
-                       snprintf(handle->errbuf, PCAP_ERRBUF_SIZE,
-                                       "SIOCGSTAMP: %s", pcap_strerror(errno));
+                       pcap_fmt_errmsg_for_errno(handle->errbuf,
+                           PCAP_ERRBUF_SIZE, errno, "SIOCGSTAMP");
                        return PCAP_ERROR;
                }
         }
@@ -1773,7 +2141,7 @@ pcap_read_packet(pcap_t *handle, pcap_handler callback, u_char *userdata)
         * We count them here even if we can get the packet count
         * from the kernel, as we can only determine at run time
         * whether we'll be able to get it from the kernel (if
-        * HAVE_TPACKET_STATS isn't defined, we can't get it from
+        * HAVE_STRUCT_TPACKET_STATS isn't defined, we can't get it from
         * the kernel, but if it is defined, the library might
         * have been built with a 2.4 or later kernel, but we
         * might be running on a 2.2[.x] kernel without Alexey
@@ -1817,7 +2185,7 @@ pcap_inject_linux(pcap_t *handle, const void *buf, size_t size)
                        /*
                         * We don't support sending on the "any" device.
                         */
-                       strlcpy(handle->errbuf,
+                       pcap_strlcpy(handle->errbuf,
                            "Sending packets isn't supported on the \"any\" device",
                            PCAP_ERRBUF_SIZE);
                        return (-1);
@@ -1825,13 +2193,13 @@ pcap_inject_linux(pcap_t *handle, const void *buf, size_t size)
 
                if (handlep->cooked) {
                        /*
-                        * We don't support sending on the "any" device.
+                        * We don't support sending on cooked-mode sockets.
                         *
                         * XXX - how do you send on a bound cooked-mode
                         * socket?
                         * Is a "sendto()" required there?
                         */
-                       strlcpy(handle->errbuf,
+                       pcap_strlcpy(handle->errbuf,
                            "Sending packets isn't supported in cooked mode",
                            PCAP_ERRBUF_SIZE);
                        return (-1);
@@ -1841,12 +2209,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_strerror(errno));
+               pcap_fmt_errmsg_for_errno(handle->errbuf, PCAP_ERRBUF_SIZE,
+                   errno, "send");
                return (-1);
        }
        return (ret);
-}                           
+}
 
 /*
  *  Get the statistics for the given packet capture handle.
@@ -1860,7 +2228,7 @@ static int
 pcap_stats_linux(pcap_t *handle, struct pcap_stat *stats)
 {
        struct pcap_linux *handlep = handle->priv;
-#ifdef HAVE_TPACKET_STATS
+#ifdef HAVE_STRUCT_TPACKET_STATS
 #ifdef HAVE_TPACKET3
        /*
         * For sockets using TPACKET_V1 or TPACKET_V2, the extra
@@ -1881,11 +2249,11 @@ pcap_stats_linux(pcap_t *handle, struct pcap_stat *stats)
        struct tpacket_stats kstats;
 #endif /* HAVE_TPACKET3 */
        socklen_t len = sizeof (struct tpacket_stats);
-#endif /* HAVE_TPACKET_STATS */
+#endif /* HAVE_STRUCT_TPACKET_STATS */
 
        long if_dropped = 0;
-       
-       /* 
+
+       /*
         *      To fill in ps_ifdrop, we parse /proc/net/dev for the number
         */
        if (handle->opt.promisc)
@@ -1895,7 +2263,7 @@ pcap_stats_linux(pcap_t *handle, struct pcap_stat *stats)
                handlep->stat.ps_ifdrop += (handlep->proc_dropped - if_dropped);
        }
 
-#ifdef HAVE_TPACKET_STATS
+#ifdef HAVE_STRUCT_TPACKET_STATS
        /*
         * Try to get the packet counts from the kernel.
         */
@@ -1915,7 +2283,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 +2312,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,8 +2331,8 @@ 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_stats: %s", pcap_strerror(errno));
+                       pcap_fmt_errmsg_for_errno(handle->errbuf,
+                           PCAP_ERRBUF_SIZE, errno, "pcap_stats");
                        return -1;
                }
        }
@@ -1990,10 +2358,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;
@@ -2001,7 +2369,7 @@ pcap_stats_linux(pcap_t *handle, struct pcap_stat *stats)
 }
 
 static int
-add_linux_if(pcap_if_t **devlistp, const char *ifname, int fd, char *errbuf)
+add_linux_if(pcap_if_list_t *devlistp, const char *ifname, int fd, char *errbuf)
 {
        const char *p;
        char name[512]; /* XXX - pick a size */
@@ -2045,23 +2413,23 @@ add_linux_if(pcap_if_t **devlistp, const char *ifname, int fd, char *errbuf)
        /*
         * Get the flags for this interface.
         */
-       strlcpy(ifrflags.ifr_name, name, sizeof(ifrflags.ifr_name));
+       pcap_strlcpy(ifrflags.ifr_name, name, sizeof(ifrflags.ifr_name));
        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,
-                   "SIOCGIFFLAGS: %.*s: %s",
+               pcap_fmt_errmsg_for_errno(errbuf, PCAP_ERRBUF_SIZE,
+                   errno, "SIOCGIFFLAGS: %.*s",
                    (int)sizeof(ifrflags.ifr_name),
-                   ifrflags.ifr_name,
-                   pcap_strerror(errno));
+                   ifrflags.ifr_name);
                return (-1);
        }
 
        /*
-        * Add an entry for this interface, with no addresses.
+        * Add an entry for this interface, with no addresses, if it's
+        * not already in the list.
         */
-       if (pcap_add_if(devlistp, name, ifrflags.ifr_flags, NULL,
-           errbuf) == -1) {
+       if (find_or_add_if(devlistp, name, ifrflags.ifr_flags,
+           get_if_flags, errbuf) == NULL) {
                /*
                 * Failure.
                 */
@@ -2088,7 +2456,7 @@ add_linux_if(pcap_if_t **devlistp, const char *ifname, int fd, char *errbuf)
  * Otherwise, we return 1 if we don't get an error and -1 if we do.
  */
 static int
-scan_sys_class_net(pcap_if_t **devlistp, char *errbuf)
+scan_sys_class_net(pcap_if_list_t *devlistp, char *errbuf)
 {
        DIR *sys_class_net_d;
        int fd;
@@ -2108,18 +2476,18 @@ scan_sys_class_net(pcap_if_t **devlistp, char *errbuf)
                /*
                 * Fail if we got some other error.
                 */
-               (void)snprintf(errbuf, PCAP_ERRBUF_SIZE,
-                   "Can't open /sys/class/net: %s", pcap_strerror(errno));
+               pcap_fmt_errmsg_for_errno(errbuf, PCAP_ERRBUF_SIZE,
+                   errno, "Can't open /sys/class/net");
                return (-1);
        }
 
        /*
         * 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,
-                   "socket: %s", pcap_strerror(errno));
+               pcap_fmt_errmsg_for_errno(errbuf, PCAP_ERRBUF_SIZE,
+                   errno, "socket");
                (void)closedir(sys_class_net_d);
                return (-1);
        }
@@ -2155,7 +2523,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,9 +2554,8 @@ 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,
-                           "Error reading /sys/class/net: %s",
-                           pcap_strerror(errno));
+                       pcap_fmt_errmsg_for_errno(errbuf, PCAP_ERRBUF_SIZE,
+                           errno, "Error reading /sys/class/net");
                        ret = -1;
                }
        }
@@ -2206,7 +2573,7 @@ scan_sys_class_net(pcap_if_t **devlistp, char *errbuf)
  * See comments from scan_sys_class_net().
  */
 static int
-scan_proc_net_dev(pcap_if_t **devlistp, char *errbuf)
+scan_proc_net_dev(pcap_if_list_t *devlistp, char *errbuf)
 {
        FILE *proc_net_f;
        int fd;
@@ -2226,18 +2593,18 @@ scan_proc_net_dev(pcap_if_t **devlistp, char *errbuf)
                /*
                 * Fail if we got some other error.
                 */
-               (void)snprintf(errbuf, PCAP_ERRBUF_SIZE,
-                   "Can't open /proc/net/dev: %s", pcap_strerror(errno));
+               pcap_fmt_errmsg_for_errno(errbuf, PCAP_ERRBUF_SIZE,
+                   errno, "Can't open /proc/net/dev");
                return (-1);
        }
 
        /*
         * 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,
-                   "socket: %s", pcap_strerror(errno));
+               pcap_fmt_errmsg_for_errno(errbuf, PCAP_ERRBUF_SIZE,
+                   errno, "socket");
                (void)fclose(proc_net_f);
                return (-1);
        }
@@ -2275,9 +2642,8 @@ 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,
-                           "Error reading /proc/net/dev: %s",
-                           pcap_strerror(errno));
+                       pcap_fmt_errmsg_for_errno(errbuf, PCAP_ERRBUF_SIZE,
+                           errno, "Error reading /proc/net/dev");
                        ret = -1;
                }
        }
@@ -2292,90 +2658,281 @@ scan_proc_net_dev(pcap_if_t **devlistp, char *errbuf)
  */
 static const char any_descr[] = "Pseudo-device that captures on all interfaces";
 
-int
-pcap_platform_finddevs(pcap_if_t **alldevsp, char *errbuf)
+/*
+ * A SOCK_PACKET or PF_PACKET socket can be bound to any network interface.
+ */
+static int
+can_be_bound(const char *name _U_)
 {
-       int ret;
-
-       /*
-        * 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,
-        * and even getifaddrs() won't return information about
-        * interfaces with no addresses, so you need to read "/sys/class/net"
-        * to get the names of the rest of the interfaces.
-        */
-       ret = scan_sys_class_net(alldevsp, errbuf);
-       if (ret == -1)
-               return (-1);    /* failed */
-       if (ret == 0) {
-               /*
-                * No /sys/class/net; try reading /proc/net/dev instead.
-                */
-               if (scan_proc_net_dev(alldevsp, errbuf) == -1)
-                       return (-1);
-       }
-
-       /*
-        * Add the "any" device.
-        */
-       if (pcap_add_if(alldevsp, "any", IFF_UP|IFF_RUNNING,
-           any_descr, errbuf) < 0)
-               return (-1);
-
-       return (0);
+       return (1);
 }
 
 /*
- *  Attach the given BPF code to the packet capture device.
+ * Get additional flags for a device, using SIOCGIFMEDIA.
  */
 static int
-pcap_setfilter_linux_common(pcap_t *handle, struct bpf_program *filter,
-    int is_mmapped)
+get_if_flags(const char *name, bpf_u_int32 *flags, char *errbuf)
 {
-       struct pcap_linux *handlep;
-#ifdef SO_ATTACH_FILTER
-       struct sock_fprog       fcode;
-       int                     can_filter_in_kernel;
-       int                     err = 0;
-#endif
+       int sock;
+       FILE *fh;
+       unsigned int arptype;
+       struct ifreq ifr;
+       struct ethtool_value info;
 
-       if (!handle)
-               return -1;
-       if (!filter) {
-               strlcpy(handle->errbuf, "setfilter: No filter specified",
-                       PCAP_ERRBUF_SIZE);
-               return -1;
+       if (*flags & PCAP_IF_LOOPBACK) {
+               /*
+                * Loopback devices aren't wireless, and "connected"/
+                * "disconnected" doesn't apply to them.
+                */
+               *flags |= PCAP_IF_CONNECTION_STATUS_NOT_APPLICABLE;
+               return 0;
        }
 
-       handlep = handle->priv;
-
-       /* Make our private copy of the filter */
-
-       if (install_bpf_program(handle, filter) < 0)
-               /* install_bpf_program() filled in errbuf */
+       sock = socket(AF_INET, SOCK_DGRAM, 0);
+       if (sock == -1) {
+               pcap_fmt_errmsg_for_errno(errbuf, PCAP_ERRBUF_SIZE, errno,
+                   "Can't create socket to get ethtool information for %s",
+                   name);
                return -1;
+       }
 
        /*
-        * Run user level packet filter by default. Will be overriden if
-        * installing a kernel filter succeeds.
+        * OK, what type of network is this?
+        * In particular, is it wired or wireless?
         */
-       handlep->filter_in_userland = 1;
-
-       /* Install kernel level filter if possible */
-
-#ifdef SO_ATTACH_FILTER
-#ifdef USHRT_MAX
-       if (handle->fcode.bf_len > USHRT_MAX) {
+       if (is_wifi(sock, name)) {
                /*
-                * fcode.len is an unsigned short for current kernel.
-                * I have yet to see BPF-Code with that much
-                * instructions but still it is possible. So for the
-                * sake of correctness I added this check.
+                * Wi-Fi, hence wireless.
                 */
-               fprintf(stderr, "Warning: Filter too complex for kernel\n");
-               fcode.len = 0;
-               fcode.filter = NULL;
+               *flags |= PCAP_IF_WIRELESS;
+       } else {
+               /*
+                * OK, what does /sys/class/net/{if}/type contain?
+                * (We don't use that for Wi-Fi, as it'll report
+                * "Ethernet", i.e. ARPHRD_ETHER, for non-monitor-
+                * mode devices.)
+                */
+               char *pathstr;
+
+               if (asprintf(&pathstr, "/sys/class/net/%s/type", name) == -1) {
+                       pcap_snprintf(errbuf, PCAP_ERRBUF_SIZE,
+                           "%s: Can't generate path name string for /sys/class/net device",
+                           name);
+                       close(sock);
+                       return -1;
+               }
+               fh = fopen(pathstr, "r");
+               if (fh != NULL) {
+                       if (fscanf(fh, "%u", &arptype) == 1) {
+                               /*
+                                * OK, we got an ARPHRD_ type; what is it?
+                                */
+                               switch (arptype) {
+
+#ifdef ARPHRD_LOOPBACK
+                               case ARPHRD_LOOPBACK:
+                                       /*
+                                        * These are types to which
+                                        * "connected" and "disconnected"
+                                        * don't apply, so don't bother
+                                        * asking about it.
+                                        *
+                                        * XXX - add other types?
+                                        */
+                                       close(sock);
+                                       fclose(fh);
+                                       free(pathstr);
+                                       return 0;
+#endif
+
+                               case ARPHRD_IRDA:
+                               case ARPHRD_IEEE80211:
+                               case ARPHRD_IEEE80211_PRISM:
+                               case ARPHRD_IEEE80211_RADIOTAP:
+#ifdef ARPHRD_IEEE802154
+                               case ARPHRD_IEEE802154:
+#endif
+#ifdef ARPHRD_IEEE802154_MONITOR
+                               case ARPHRD_IEEE802154_MONITOR:
+#endif
+#ifdef ARPHRD_6LOWPAN
+                               case ARPHRD_6LOWPAN:
+#endif
+                                       /*
+                                        * Various wireless types.
+                                        */
+                                       *flags |= PCAP_IF_WIRELESS;
+                                       break;
+                               }
+                       }
+                       fclose(fh);
+                       free(pathstr);
+               }
+       }
+
+#ifdef ETHTOOL_GLINK
+       memset(&ifr, 0, sizeof(ifr));
+       pcap_strlcpy(ifr.ifr_name, name, sizeof(ifr.ifr_name));
+       info.cmd = ETHTOOL_GLINK;
+       ifr.ifr_data = (caddr_t)&info;
+       if (ioctl(sock, SIOCETHTOOL, &ifr) == -1) {
+               int save_errno = errno;
+
+               switch (save_errno) {
+
+               case EOPNOTSUPP:
+               case EINVAL:
+                       /*
+                        * OK, this OS version or driver doesn't support
+                        * asking for this information.
+                        * XXX - distinguish between "this doesn't
+                        * support ethtool at all because it's not
+                        * that type of device" vs. "this doesn't
+                        * support ethtool even though it's that
+                        * type of device", and return "unknown".
+                        */
+                       *flags |= PCAP_IF_CONNECTION_STATUS_NOT_APPLICABLE;
+                       close(sock);
+                       return 0;
+
+               case ENODEV:
+                       /*
+                        * OK, no such device.
+                        * The user will find that out when they try to
+                        * activate the device; just say "OK" and
+                        * don't set anything.
+                        */
+                       close(sock);
+                       return 0;
+
+               default:
+                       /*
+                        * Other error.
+                        */
+                       pcap_fmt_errmsg_for_errno(errbuf, PCAP_ERRBUF_SIZE,
+                           save_errno,
+                           "%s: SIOCETHTOOL(ETHTOOL_GLINK) ioctl failed",
+                           name);
+                       close(sock);
+                       return -1;
+               }
+       }
+
+       /*
+        * Is it connected?
+        */
+       if (info.data) {
+               /*
+                * It's connected.
+                */
+               *flags |= PCAP_IF_CONNECTION_STATUS_CONNECTED;
+       } else {
+               /*
+                * It's disconnected.
+                */
+               *flags |= PCAP_IF_CONNECTION_STATUS_DISCONNECTED;
+       }
+#endif
+
+       close(sock);
+       return 0;
+}
+
+int
+pcap_platform_finddevs(pcap_if_list_t *devlistp, char *errbuf)
+{
+       int ret;
+
+       /*
+        * Get the list of regular interfaces first.
+        */
+       if (pcap_findalldevs_interfaces(devlistp, errbuf, can_be_bound,
+           get_if_flags) == -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,
+        * and even getifaddrs() won't return information about
+        * interfaces with no addresses, so you need to read "/sys/class/net"
+        * to get the names of the rest of the interfaces.
+        */
+       ret = scan_sys_class_net(devlistp, errbuf);
+       if (ret == -1)
+               return (-1);    /* failed */
+       if (ret == 0) {
+               /*
+                * No /sys/class/net; try reading /proc/net/dev instead.
+                */
+               if (scan_proc_net_dev(devlistp, errbuf) == -1)
+                       return (-1);
+       }
+
+       /*
+        * Add the "any" device.
+        * As it refers to all network devices, not to any particular
+        * network device, the notion of "connected" vs. "disconnected"
+        * doesn't apply.
+        */
+       if (add_dev(devlistp, "any",
+           PCAP_IF_UP|PCAP_IF_RUNNING|PCAP_IF_CONNECTION_STATUS_NOT_APPLICABLE,
+           any_descr, errbuf) == NULL)
+               return (-1);
+
+       return (0);
+}
+
+/*
+ *  Attach the given BPF code to the packet capture device.
+ */
+static int
+pcap_setfilter_linux_common(pcap_t *handle, struct bpf_program *filter,
+    int is_mmapped)
+{
+       struct pcap_linux *handlep;
+#ifdef SO_ATTACH_FILTER
+       struct sock_fprog       fcode;
+       int                     can_filter_in_kernel;
+       int                     err = 0;
+#endif
+
+       if (!handle)
+               return -1;
+       if (!filter) {
+               pcap_strlcpy(handle->errbuf, "setfilter: No filter specified",
+                       PCAP_ERRBUF_SIZE);
+               return -1;
+       }
+
+       handlep = handle->priv;
+
+       /* Make our private copy of the filter */
+
+       if (install_bpf_program(handle, filter) < 0)
+               /* install_bpf_program() filled in errbuf */
+               return -1;
+
+       /*
+        * Run user level packet filter by default. Will be overriden if
+        * installing a kernel filter succeeds.
+        */
+       handlep->filter_in_userland = 1;
+
+       /* Install kernel level filter if possible */
+
+#ifdef SO_ATTACH_FILTER
+#ifdef USHRT_MAX
+       if (handle->fcode.bf_len > USHRT_MAX) {
+               /*
+                * fcode.len is an unsigned short for current kernel.
+                * I have yet to see BPF-Code with that much
+                * instructions but still it is possible. So for the
+                * sake of correctness I added this check.
+                */
+               fprintf(stderr, "Warning: Filter too complex for kernel\n");
+               fcode.len = 0;
+               fcode.filter = NULL;
                can_filter_in_kernel = 0;
        } else
 #endif /* USHRT_MAX */
@@ -2478,8 +3035,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_fmt_errmsg_for_errno(handle->errbuf,
+                           PCAP_ERRBUF_SIZE, errno,
+                           "can't remove kernel filter");
+                       err = -2;       /* fatal error */
+               }
+       }
 
        /*
         * Free up the copy of the filter that was made by "fix_program()".
@@ -2521,45 +3084,55 @@ 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;
 }
 
-#ifdef HAVE_PF_PACKET_SOCKETS
-/*
- * Map the PACKET_ value to a LINUX_SLL_ value; we
- * want the same numerical value to be used in
- * the link-layer header even if the numerical values
- * for the PACKET_ #defines change, so that programs
- * that look at the packet type field will always be
- * able to handle DLT_LINUX_SLL captures.
- */
-static short int
-map_packet_type_to_sll_type(short int sll_pkttype)
+static int
+is_wifi(int sock_fd
+#ifndef IW_MODE_MONITOR
+_U_
+#endif
+, const char *device)
 {
-       switch (sll_pkttype) {
-
-       case PACKET_HOST:
-               return htons(LINUX_SLL_HOST);
-
-       case PACKET_BROADCAST:
-               return htons(LINUX_SLL_BROADCAST);
-
-       case PACKET_MULTICAST:
-               return  htons(LINUX_SLL_MULTICAST);
-
-       case PACKET_OTHERHOST:
-               return htons(LINUX_SLL_OTHERHOST);
+       char *pathstr;
+       struct stat statb;
+#ifdef IW_MODE_MONITOR
+       char errbuf[PCAP_ERRBUF_SIZE];
+#endif
 
-       case PACKET_OUTGOING:
-               return htons(LINUX_SLL_OUTGOING);
+       /*
+        * 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);
 
-       default:
-               return -1;
+#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
@@ -2579,8 +3152,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 +3164,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 +3176,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 +3187,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 +3236,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
@@ -2917,7 +3503,7 @@ static void map_arphrd_to_dlt(pcap_t *handle, int arptype, const char *device,
                 * IP-over-FC on which somebody wants to capture
                 * packets.
                 */
-               handle->dlt_list = (u_int *) malloc(sizeof(u_int) * 2);
+               handle->dlt_list = (u_int *) malloc(sizeof(u_int) * 3);
                /*
                 * If that fails, just leave the list empty.
                 */
@@ -2940,7 +3526,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 +3569,14 @@ 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;
+
+#ifndef ARPHRD_VSOCKMON
+#define ARPHRD_VSOCKMON        826
+#endif
+       case ARPHRD_VSOCKMON:
+               handle->linktype = DLT_VSOCK;
                break;
 
        default:
@@ -2994,6 +3587,45 @@ static void map_arphrd_to_dlt(pcap_t *handle, int arptype, const char *device,
 
 /* ===== Functions to interface to the newer kernels ================== */
 
+#ifdef PACKET_RESERVE
+static void
+set_dlt_list_cooked(pcap_t *handle, int sock_fd)
+{
+       socklen_t               len;
+       unsigned int            tp_reserve;
+
+       /*
+        * If we can't do PACKET_RESERVE, we can't reserve extra space
+        * for a DLL_LINUX_SLL2 header, so we can't support DLT_LINUX_SLL2.
+        */
+       len = sizeof(tp_reserve);
+       if (getsockopt(sock_fd, SOL_PACKET, PACKET_RESERVE, &tp_reserve,
+           &len) == 0) {
+               /*
+                * Yes, we can do DLL_LINUX_SLL2.
+                */
+               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_LINUX_SLL;
+                       handle->dlt_list[1] = DLT_LINUX_SLL2;
+                       handle->dlt_count = 2;
+               }
+       }
+}
+#else
+/*
+ * The build environment doesn't define PACKET_RESERVE, so we can't reserve
+ * extra space for a DLL_LINUX_SLL2 header, so we can't support DLT_LINUX_SLL2.
+ */
+static void
+set_dlt_list_cooked(pcap_t *handle _U_, int sock_fd _U_)
+{
+}
+#endif
+
 /*
  * Try to open a packet socket using the new kernel PF_PACKET interface.
  * Returns 1 on success, 0 on an error that means the new interface isn't
@@ -3006,14 +3638,19 @@ 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;
+       int                     protocol = pcap_protocol(handle);
+       int                     sock_fd = -1, arptype, ret;
 #ifdef HAVE_PACKET_AUXDATA
        int                     val;
 #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
@@ -3022,8 +3659,8 @@ activate_new(pcap_t *handle)
         * try a SOCK_RAW socket for the raw interface.
         */
        sock_fd = is_any_device ?
-               socket(PF_PACKET, SOCK_DGRAM, htons(ETH_P_ALL)) :
-               socket(PF_PACKET, SOCK_RAW, htons(ETH_P_ALL));
+               socket(PF_PACKET, SOCK_DGRAM, protocol) :
+               socket(PF_PACKET, SOCK_RAW, protocol);
 
        if (sock_fd == -1) {
                if (errno == EINVAL || errno == EAFNOSUPPORT) {
@@ -3033,21 +3670,21 @@ activate_new(pcap_t *handle)
                         */
                        return 0;
                }
-
-               snprintf(handle->errbuf, PCAP_ERRBUF_SIZE, "socket: %s",
-                        pcap_strerror(errno) );
                if (errno == EPERM || errno == EACCES) {
                        /*
                         * You don't have permission to open the
                         * socket.
                         */
-                       return PCAP_ERROR_PERM_DENIED;
+                       ret = PCAP_ERROR_PERM_DENIED;
                } else {
                        /*
                         * Other error.
                         */
-                       return PCAP_ERROR;
+                       ret = PCAP_ERROR;
                }
+               pcap_fmt_errmsg_for_errno(handle->errbuf, PCAP_ERRBUF_SIZE,
+                   errno, "socket");
+               return ret;
        }
 
        /* It seems the kernel supports the new interface. */
@@ -3117,7 +3754,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,27 +3773,27 @@ activate_new(pcap_t *handle)
                         * kernels) - reopen in cooked mode.
                         */
                        if (close(sock_fd) == -1) {
-                               snprintf(handle->errbuf, PCAP_ERRBUF_SIZE,
-                                        "close: %s", pcap_strerror(errno));
+                               pcap_fmt_errmsg_for_errno(handle->errbuf,
+                                   PCAP_ERRBUF_SIZE, errno, "close");
                                return PCAP_ERROR;
                        }
-                       sock_fd = socket(PF_PACKET, SOCK_DGRAM,
-                           htons(ETH_P_ALL));
+                       sock_fd = socket(PF_PACKET, SOCK_DGRAM, protocol);
                        if (sock_fd == -1) {
-                               snprintf(handle->errbuf, PCAP_ERRBUF_SIZE,
-                                   "socket: %s", pcap_strerror(errno));
                                if (errno == EPERM || errno == EACCES) {
                                        /*
                                         * You don't have permission to
                                         * open the socket.
                                         */
-                                       return PCAP_ERROR_PERM_DENIED;
+                                       ret = PCAP_ERROR_PERM_DENIED;
                                } else {
                                        /*
                                         * Other error.
                                         */
-                                       return PCAP_ERROR;
+                                       ret = PCAP_ERROR;
                                }
+                               pcap_fmt_errmsg_for_errno(handle->errbuf,
+                                   PCAP_ERRBUF_SIZE, errno, "socket");
+                               return ret;
                        }
                        handlep->cooked = 1;
 
@@ -3169,6 +3806,7 @@ activate_new(pcap_t *handle)
                                free(handle->dlt_list);
                                handle->dlt_list = NULL;
                                handle->dlt_count = 0;
+                               set_dlt_list_cooked(handle, sock_fd);
                        }
 
                        if (handle->linktype == -1) {
@@ -3178,7 +3816,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 "
@@ -3205,7 +3843,7 @@ activate_new(pcap_t *handle)
                }
 
                if ((err = iface_bind(sock_fd, handlep->ifindex,
-                   handle->errbuf)) != 1) {
+                   handle->errbuf, protocol)) != 1) {
                        close(sock_fd);
                        if (err < 0)
                                return err;
@@ -3229,6 +3867,9 @@ activate_new(pcap_t *handle)
                 */
                handlep->cooked = 1;
                handle->linktype = DLT_LINUX_SLL;
+               handle->dlt_list = NULL;
+               handle->dlt_count = 0;
+               set_dlt_list_cooked(handle, sock_fd);
 
                /*
                 * We're not bound to a device.
@@ -3268,8 +3909,8 @@ 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,
-                               "setsockopt: %s", pcap_strerror(errno));
+                       pcap_fmt_errmsg_for_errno(handle->errbuf,
+                           PCAP_ERRBUF_SIZE, errno, "setsockopt (PACKET_ADD_MEMBERSHIP)");
                        close(sock_fd);
                        return PCAP_ERROR;
                }
@@ -3281,8 +3922,8 @@ 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,
-                        "setsockopt: %s", pcap_strerror(errno));
+               pcap_fmt_errmsg_for_errno(handle->errbuf, PCAP_ERRBUF_SIZE,
+                   errno, "setsockopt (PACKET_AUXDATA)");
                close(sock_fd);
                return PCAP_ERROR;
        }
@@ -3302,24 +3943,37 @@ activate_new(pcap_t *handle)
         * large enough to hold a "cooked mode" header plus
         * 1 byte of packet data (so we don't pass a byte
         * count of 0 to "recvfrom()").
+        * XXX - we don't know whether this will be DLT_LINUX_SLL
+        * or DLT_LINUX_SLL2, so make sure it's big enough for
+        * a DLT_LINUX_SLL2 "cooked mode" header; a snapshot length
+        * that small is silly anyway.
         */
        if (handlep->cooked) {
-               if (handle->snapshot < SLL_HDR_LEN + 1)
-                       handle->snapshot = SLL_HDR_LEN + 1;
+               if (handle->snapshot < SLL2_HDR_LEN + 1)
+                       handle->snapshot = SLL2_HDR_LEN + 1;
        }
        handle->bufsize = handle->snapshot;
 
        /*
         * 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 +3986,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,9 +3998,26 @@ 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,
+       pcap_strlcpy(ebuf,
                "New packet capturing interface not supported by build "
                "environment", PCAP_ERRBUF_SIZE);
        return 0;
@@ -3366,7 +4037,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,9 +4049,8 @@ activate_mmap(pcap_t *handle, int *status)
         */
        handlep->oneshot_buffer = malloc(handle->snapshot);
        if (handlep->oneshot_buffer == NULL) {
-               snprintf(handle->errbuf, PCAP_ERRBUF_SIZE,
-                        "can't allocate oneshot buffer: %s",
-                        pcap_strerror(errno));
+               pcap_fmt_errmsg_for_errno(handle->errbuf, PCAP_ERRBUF_SIZE,
+                   errno, "can't allocate oneshot buffer");
                *status = PCAP_ERROR;
                return -1;
        }
@@ -3427,6 +4097,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 +4120,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,16 +4144,28 @@ 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.
+        *
+        * This socket option was introduced in 2.6.27, which was
+        * also the first release with TPACKET_V2 support.
+        */
        if (getsockopt(handle->fd, SOL_PACKET, PACKET_HDRLEN, &val, &len) < 0) {
-               if (errno == ENOPROTOOPT || errno == EINVAL)
+               if (errno == ENOPROTOOPT || errno == EINVAL) {
+                       /*
+                        * ENOPROTOOPT means the kernel is too old to
+                        * support PACKET_HDRLEN at all, which means
+                        * it either doesn't support TPACKET at all
+                        * or supports  only TPACKET_V1.
+                        */
                        return 1;       /* no */
+               }
 
                /* Failed to even find out; this is a fatal error. */
-               snprintf(handle->errbuf, PCAP_ERRBUF_SIZE,
-                       "can't get %s header len on packet socket: %s",
-                       version_str,
-                       pcap_strerror(errno));
+               pcap_fmt_errmsg_for_errno(handle->errbuf, PCAP_ERRBUF_SIZE,
+                   errno, "can't get %s header len on packet socket",
+                   version_str);
                return -1;
        }
        handlep->tp_hdrlen = val;
@@ -3488,21 +4173,21 @@ 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,
-                       "can't activate %s on packet socket: %s",
-                       version_str,
-                       pcap_strerror(errno));
+               pcap_fmt_errmsg_for_errno(handle->errbuf, PCAP_ERRBUF_SIZE,
+                   errno, "can't activate %s on packet socket", version_str);
                return -1;
        }
        handlep->tp_version = version;
 
-       /* Reserve space for VLAN tag reconstruction */
+       /*
+        * Reserve space for VLAN tag reconstruction.
+        * This option was also introduced in 2.6.27.
+        */
        val = VLAN_TAG_LEN;
        if (setsockopt(handle->fd, SOL_PACKET, PACKET_RESERVE, &val,
                           sizeof(val)) < 0) {
-               snprintf(handle->errbuf, PCAP_ERRBUF_SIZE,
-                       "can't set up reserve on packet socket: %s",
-                       pcap_strerror(errno));
+               pcap_fmt_errmsg_for_errno(handle->errbuf, PCAP_ERRBUF_SIZE,
+                   errno, "can't set up reserve on packet socket");
                return -1;
        }
 
@@ -3511,6 +4196,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 +4242,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,32 +4254,96 @@ 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 either that's all the kernel
+        * supports or it doesn't support TPACKET at all.  In the latter
+        * case, create_ring() will fail, and we'll fall back on non-
+        * memory-mapped capture.
+        */
+       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_fmt_errmsg_for_errno(handle->errbuf,
+                           PCAP_ERRBUF_SIZE, errno, "uname failed");
+                       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;
 }
 
+#define MAX(a,b) ((a)>(b)?(a):(b))
+
 /*
  * Attempt to set up memory-mapped access.
  *
@@ -3605,13 +4383,14 @@ 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
-               /* Note that with large snapshot length (say 64K, which is
-                * the default for recent versions of tcpdump, the value that
-                * "-s 0" has given for a long time with tcpdump, and the
-                * default in Wireshark/TShark/dumpcap), if we use the snapshot
+               /* Note that with large snapshot length (say 256K, which is
+                * the default for recent versions of tcpdump, Wireshark,
+                * TShark, dumpcap or 64K, the value that "-s 0" has given for
+                * a long time with tcpdump), if we use the snapshot
                 * length to calculate the frame length, only a few frames
                 * will be available in the ring even with pretty
                 * large ring size (and a lot of memory will be unused).
@@ -3635,29 +4414,35 @@ create_ring(pcap_t *handle, int *status)
                 * based on the MTU, so that the MTU limits the maximum size
                 * of packets that we can receive.)
                 *
-                * We don't do that if segmentation/fragmentation or receive
-                * offload are enabled, so we don't get rudely surprised by
-                * "packets" bigger than the MTU. */
+                * If segmentation/fragmentation or receive offload are
+                * enabled, we can get reassembled/aggregated packets larger
+                * than MTU, but bounded to 65535 plus the Ethernet overhead,
+                * due to kernel and protocol constraints */
                frame_size = handle->snapshot;
                if (handle->linktype == DLT_EN10MB) {
+                       unsigned int max_frame_len;
                        int mtu;
                        int offload;
 
+                       mtu = iface_get_mtu(handle->fd, handle->opt.device,
+                           handle->errbuf);
+                       if (mtu == -1) {
+                               *status = PCAP_ERROR;
+                               return -1;
+                       }
                        offload = iface_get_offload(handle);
                        if (offload == -1) {
                                *status = PCAP_ERROR;
                                return -1;
                        }
-                       if (!offload) {
-                               mtu = iface_get_mtu(handle->fd, handle->opt.source,
-                                   handle->errbuf);
-                               if (mtu == -1) {
-                                       *status = PCAP_ERROR;
-                                       return -1;
-                               }
-                               if (frame_size > mtu + 18)
-                                       frame_size = mtu + 18;
-                       }
+                       if (offload)
+                               max_frame_len = MAX(mtu, 65535);
+                       else
+                               max_frame_len = mtu;
+                       max_frame_len += 18;
+
+                       if (frame_size > max_frame_len)
+                               frame_size = max_frame_len;
                }
 
                /* NOTE: calculus matching those in tpacket_rcv()
@@ -3666,8 +4451,8 @@ 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,
-                           "getsockopt: %s", pcap_strerror(errno));
+                       pcap_fmt_errmsg_for_errno(handle->errbuf,
+                           PCAP_ERRBUF_SIZE, errno, "getsockopt (SO_TYPE)");
                        *status = PCAP_ERROR;
                        return -1;
                }
@@ -3681,15 +4466,51 @@ 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,
-                                   "getsockopt: %s", pcap_strerror(errno));
+                               pcap_fmt_errmsg_for_errno(handle->errbuf,
+                                   PCAP_ERRBUF_SIZE, errno,
+                                   "getsockopt (PACKET_RESERVE)");
+                               *status = PCAP_ERROR;
+                               return -1;
+                       }
+                       /*
+                        * Older kernel, so we can't use PACKET_RESERVE;
+                        * this means we can't reserver extra space
+                        * for a DLT_LINUX_SLL2 header.
+                        */
+                       tp_reserve = 0;
+               } else {
+                       /*
+                        * We can reserve extra space for a DLT_LINUX_SLL2
+                        * header.  Do so.
+                        *
+                        * XXX - we assume that the kernel is still adding
+                        * 16 bytes of extra space; that happens to
+                        * correspond to SLL_HDR_LEN (whether intentionally
+                        * or not - the kernel code has a raw "16" in
+                        * the expression), so we subtract SLL_HDR_LEN
+                        * from SLL2_HDR_LEN to get the additional space
+                        * needed.
+                        *
+                        * XXX - should we use TPACKET_ALIGN(SLL2_HDR_LEN - SLL_HDR_LEN)?
+                        */
+                       tp_reserve += SLL2_HDR_LEN - SLL_HDR_LEN;
+                       len = sizeof(tp_reserve);
+                       if (setsockopt(handle->fd, SOL_PACKET, PACKET_RESERVE,
+                           &tp_reserve, len) < 0) {
+                               pcap_fmt_errmsg_for_errno(handle->errbuf,
+                                   PCAP_ERRBUF_SIZE, errno,
+                                   "setsockopt (PACKET_RESERVE)");
                                *status = PCAP_ERROR;
                                return -1;
                        }
-                       tp_reserve = 0; /* older kernel, reserve not supported */
                }
 #else
-               tp_reserve = 0; /* older kernel, reserve not supported */
+               /*
+                * Build environment for an older kernel, so we can't
+                * use PACKET_RESERVE; this means we can't reserve
+                * extra space for a DLT_LINUX_SLL2 header.
+                */
+               tp_reserve = 0;
 #endif
                maclen = (sk_type == SOCK_DGRAM) ? 0 : MAX_LINKHEADER_SIZE;
                        /* XXX: in the kernel maclen is calculated from
@@ -3721,29 +4542,92 @@ create_ring(pcap_t *handle, int *status)
                         */
                macoff = netoff - maclen;
                req.tp_frame_size = TPACKET_ALIGN(macoff + frame_size);
-               req.tp_frame_nr = handle->opt.buffer_size/req.tp_frame_size;
+               /*
+                * Round the buffer size up to a multiple of the
+                * frame size (rather than rounding down, which
+                * would give a buffer smaller than our caller asked
+                * for, and possibly give zero frames if the requested
+                * buffer size is too small for one frame).
+                */
+               req.tp_frame_nr = (handle->opt.buffer_size + req.tp_frame_size - 1)/req.tp_frame_size;
                break;
 
 #ifdef HAVE_TPACKET3
        case TPACKET_V3:
+               /*
+                * If we have TPACKET_V3, we have PACKET_RESERVE.
+                */
+               len = sizeof(tp_reserve);
+               if (getsockopt(handle->fd, SOL_PACKET, PACKET_RESERVE,
+                   &tp_reserve, &len) < 0) {
+                       /*
+                        * Even ENOPROTOOPT is an error - we wouldn't
+                        * be here if the kernel didn't support
+                        * TPACKET_V3, which means it supports
+                        * PACKET_RESERVE.
+                        */
+                       pcap_fmt_errmsg_for_errno(handle->errbuf,
+                           PCAP_ERRBUF_SIZE, errno,
+                           "getsockopt (PACKET_RESERVE)");
+                       *status = PCAP_ERROR;
+                       return -1;
+               }
+               /*
+                * We can reserve extra space for a DLT_LINUX_SLL2
+                * header.  Do so.
+                *
+                * XXX - we assume that the kernel is still adding
+                * 16 bytes of extra space; that happens to
+                * correspond to SLL_HDR_LEN (whether intentionally
+                * or not - the kernel code has a raw "16" in
+                * the expression), so we subtract SLL_HDR_LEN
+                * from SLL2_HDR_LEN to get the additional space
+                * needed.
+                *
+                * XXX - should we use TPACKET_ALIGN(SLL2_HDR_LEN - SLL_HDR_LEN)?
+                */
+               tp_reserve += SLL2_HDR_LEN - SLL_HDR_LEN;
+               len = sizeof(tp_reserve);
+               if (setsockopt(handle->fd, SOL_PACKET, PACKET_RESERVE,
+                    &tp_reserve, len) < 0) {
+                       pcap_fmt_errmsg_for_errno(handle->errbuf,
+                           PCAP_ERRBUF_SIZE, errno,
+                           "setsockopt (PACKET_RESERVE)");
+                       *status = PCAP_ERROR;
+                       return -1;
+               }
+
                /* The "frames" for this are actually buffers that
                 * contain multiple variable-sized frames.
                 *
-                * We pick a "frame" size of 128K to leave enough
-                * room for at least one reasonably-sized packet
+                * We pick a "frame" size of MAXIMUM_SNAPLEN to leave
+                * enough room for at least one reasonably-sized packet
                 * in the "frame". */
                req.tp_frame_size = MAXIMUM_SNAPLEN;
-               req.tp_frame_nr = handle->opt.buffer_size/req.tp_frame_size;
+               /*
+                * Round the buffer size up to a multiple of the
+                * "frame" size (rather than rounding down, which
+                * would give a buffer smaller than our caller asked
+                * for, and possibly give zero "frames" if the requested
+                * buffer size is too small for one "frame").
+                */
+               req.tp_frame_nr = (handle->opt.buffer_size + req.tp_frame_size - 1)/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 +4668,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));
+               pcap_strlcpy(ifr.ifr_name, handle->opt.device, sizeof(ifr.ifr_name));
                ifr.ifr_data = (void *)&hwconfig;
 
                if (ioctl(handle->fd, SIOCSHWTSTAMP, &ifr) < 0) {
@@ -3802,20 +4686,28 @@ 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,
-                                       "SIOCSHWTSTAMP failed: %s",
-                                       pcap_strerror(errno));
+                               pcap_fmt_errmsg_for_errno(handle->errbuf,
+                                   PCAP_ERRBUF_SIZE, errno,
+                                   "SIOCSHWTSTAMP failed");
                                *status = PCAP_ERROR;
                                return -1;
                        }
@@ -3841,9 +4733,9 @@ 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_strerror(errno));
+                               pcap_fmt_errmsg_for_errno(handle->errbuf,
+                                   PCAP_ERRBUF_SIZE, errno,
+                                   "can't set PACKET_TIMESTAMP");
                                *status = PCAP_ERROR;
                                return -1;
                        }
@@ -3857,10 +4749,29 @@ 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;
+       if (handlep->timeout > 0) {
+               /* Use the user specified timeout as the block timeout */
+               req.tp_retire_blk_tov = handlep->timeout;
+       } else if (handlep->timeout == 0) {
+               /*
+                * In pcap, this means "infinite timeout"; TPACKET_V3
+                * doesn't support that, so just set it to UINT_MAX
+                * milliseconds.  In the TPACKET_V3 loop, if the
+                * timeout is 0, and we haven't yet seen any packets,
+                * and we block and still don't have any packets, we
+                * keep blocking until we do.
+                */
+               req.tp_retire_blk_tov = UINT_MAX;
+       } else {
+               /*
+                * XXX - this is not valid; use 0, meaning "have the
+                * kernel pick a default", for now.
+                */
+               req.tp_retire_blk_tov = 0;
+       }
        /* private data not used */
        req.tp_sizeof_priv = 0;
        /* Rx ring - feature request bits - none (rxhash will not be filled) */
@@ -3891,9 +4802,8 @@ retry:
                         */
                        return 0;
                }
-               snprintf(handle->errbuf, PCAP_ERRBUF_SIZE,
-                   "can't create rx ring on packet socket: %s",
-                   pcap_strerror(errno));
+               pcap_fmt_errmsg_for_errno(handle->errbuf, PCAP_ERRBUF_SIZE,
+                   errno, "can't create rx ring on packet socket");
                *status = PCAP_ERROR;
                return -1;
        }
@@ -3903,8 +4813,8 @@ 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,
-                   "can't mmap rx ring: %s", pcap_strerror(errno));
+               pcap_fmt_errmsg_for_errno(handle->errbuf, PCAP_ERRBUF_SIZE,
+                   errno, "can't mmap rx ring");
 
                /* clear the allocated ring on error*/
                destroy_ring(handle);
@@ -3916,9 +4826,8 @@ retry:
        handle->cc = req.tp_frame_nr;
        handle->buffer = malloc(handle->cc * sizeof(union thdr *));
        if (!handle->buffer) {
-               snprintf(handle->errbuf, PCAP_ERRBUF_SIZE,
-                   "can't allocate ring of frame headers: %s",
-                   pcap_strerror(errno));
+               pcap_fmt_errmsg_for_errno(handle->errbuf, PCAP_ERRBUF_SIZE,
+                   errno, "can't allocate ring of frame headers");
 
                destroy_ring(handle);
                *status = PCAP_ERROR;
@@ -3930,7 +4839,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 +4858,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 +4899,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 )
 {
@@ -4005,18 +4915,25 @@ pcap_cleanup_linux_mmap( pcap_t *handle )
 
 
 static int
-pcap_getnonblock_mmap(pcap_t *p, char *errbuf)
+pcap_getnonblock_mmap(pcap_t *handle)
 {
-       struct pcap_linux *handlep = p->priv;
+       struct pcap_linux *handlep = handle->priv;
 
        /* use negative value of timeout to indicate non blocking ops */
        return (handlep->timeout<0);
 }
 
 static int
-pcap_setnonblock_mmap(pcap_t *p, int nonblock, char *errbuf)
+pcap_setnonblock_mmap(pcap_t *handle, int nonblock)
 {
-       struct pcap_linux *handlep = p->priv;
+       struct pcap_linux *handlep = handle->priv;
+
+       /*
+        * Set the file descriptor to non-blocking mode, as we use
+        * it for sending packets.
+        */
+       if (pcap_setnonblock_fd(handle, nonblock) == -1)
+               return -1;
 
        /*
         * Map each value to their corresponding negation to
@@ -4035,151 +4952,130 @@ 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_fmt_errmsg_for_errno(handle->errbuf,
+                           PCAP_ERRBUF_SIZE, errno,
+                           "can't poll on packet socket");
+                       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_fmt_errmsg_for_errno(handle->errbuf,
+                                           PCAP_ERRBUF_SIZE, errno,
+                                           "Error condition on packet socket");
                                }
+                               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;
 }
 
@@ -4195,19 +5091,35 @@ 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;
        struct sockaddr_ll *sll;
        struct pcap_pkthdr pcaphdr;
+       unsigned int snaplen = tp_snaplen;
+       struct utsname utsname;
 
        /* perform sanity check on internal offset. */
        if (tp_mac + tp_snaplen > handle->bufsize) {
-               snprintf(handle->errbuf, PCAP_ERRBUF_SIZE,
-                       "corrupted frame on kernel ring mac "
-                       "offset %d + caplen %d > frame len %d",
-                       tp_mac, tp_snaplen, handle->bufsize);
+               /*
+                * Report some system information as a debugging aid.
+                */
+               if (uname(&utsname) != -1) {
+                       pcap_snprintf(handle->errbuf, PCAP_ERRBUF_SIZE,
+                               "corrupted frame on kernel ring mac "
+                               "offset %u + caplen %u > frame len %d "
+                               "(kernel %.32s version %s, machine %.16s)",
+                               tp_mac, tp_snaplen, handle->bufsize,
+                               utsname.release, utsname.version,
+                               utsname.machine);
+               } else {
+                       pcap_snprintf(handle->errbuf, PCAP_ERRBUF_SIZE,
+                               "corrupted frame on kernel ring mac "
+                               "offset %u + caplen %u > frame len %d",
+                               tp_mac, tp_snaplen, handle->bufsize);
+               }
                return -1;
        }
 
@@ -4221,12 +5133,105 @@ 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;
 
+       /* if required build in place the sll header*/
        sll = (void *)frame + TPACKET_ALIGN(handlep->tp_hdrlen);
+       if (handlep->cooked) {
+               if (handle->linktype == DLT_LINUX_SLL2) {
+                       struct sll2_header *hdrp;
+
+                       /*
+                        * The kernel should have left us with enough
+                        * space for an sll header; back up the packet
+                        * data pointer into that space, as that'll be
+                        * the beginning of the packet we pass to the
+                        * callback.
+                        */
+                       bp -= SLL2_HDR_LEN;
+
+                       /*
+                        * Let's make sure that's past the end of
+                        * the tpacket header, i.e. >=
+                        * ((u_char *)thdr + TPACKET_HDRLEN), so we
+                        * don't step on the header when we construct
+                        * the sll header.
+                        */
+                       if (bp < (u_char *)frame +
+                                          TPACKET_ALIGN(handlep->tp_hdrlen) +
+                                          sizeof(struct sockaddr_ll)) {
+                               pcap_snprintf(handle->errbuf, PCAP_ERRBUF_SIZE,
+                                       "cooked-mode frame doesn't have room for sll header");
+                               return -1;
+                       }
+
+                       /*
+                        * OK, that worked; construct the sll header.
+                        */
+                       hdrp = (struct sll2_header *)bp;
+                       hdrp->sll2_protocol = sll->sll_protocol;
+                       hdrp->sll2_reserved_mbz = 0;
+                       hdrp->sll2_if_index = htonl(sll->sll_ifindex);
+                       hdrp->sll2_hatype = htons(sll->sll_hatype);
+                       hdrp->sll2_pkttype = sll->sll_pkttype;
+                       hdrp->sll2_halen = sll->sll_halen;
+                       memcpy(hdrp->sll2_addr, sll->sll_addr, SLL_ADDRLEN);
+
+                       snaplen += sizeof(struct sll2_header);
+               } else {
+                       struct sll_header *hdrp;
+
+                       /*
+                        * The kernel should have left us with enough
+                        * space for an sll header; back up the packet
+                        * data pointer into that space, as that'll be
+                        * the beginning of the packet we pass to the
+                        * callback.
+                        */
+                       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
+                        * don't step on the header when we construct
+                        * the sll header.
+                        */
+                       if (bp < (u_char *)frame +
+                                          TPACKET_ALIGN(handlep->tp_hdrlen) +
+                                          sizeof(struct sockaddr_ll)) {
+                               pcap_snprintf(handle->errbuf, PCAP_ERRBUF_SIZE,
+                                       "cooked-mode frame doesn't have room for sll header");
+                               return -1;
+                       }
+
+                       /*
+                        * OK, that worked; construct the sll header.
+                        */
+                       hdrp = (struct sll_header *)bp;
+                       hdrp->sll_pkttype = htons(sll->sll_pkttype);
+                       hdrp->sll_hatype = htons(sll->sll_hatype);
+                       hdrp->sll_halen = htons(sll->sll_halen);
+                       memcpy(hdrp->sll_addr, sll->sll_addr, SLL_ADDRLEN);
+                       hdrp->sll_protocol = sll->sll_protocol;
+
+                       snaplen += sizeof(struct sll_header);
+               }
+       }
+
+       if (handlep->filter_in_userland && handle->fcode.bf_insns) {
+               struct bpf_aux_data aux_data;
+
+               aux_data.vlan_tag_present = tp_vlan_tci_valid;
+               aux_data.vlan_tag = tp_vlan_tci & 0x0fff;
+
+               if (bpf_filter_with_aux_data(handle->fcode.bf_insns,
+                                            bp,
+                                            tp_len,
+                                            snaplen,
+                                            &aux_data) == 0)
+                       return 0;
+       }
+
        if (!linux_check_direction(handle, sll))
                return 0;
 
@@ -4238,46 +5243,14 @@ static int pcap_handle_packet_mmap(
 
        /* if required build in place the sll header*/
        if (handlep->cooked) {
-               struct sll_header *hdrp;
-
-               /*
-                * The kernel should have left us with enough
-                * space for an sll header; back up the packet
-                * data pointer into that space, as that'll be
-                * the beginning of the packet we pass to the
-                * callback.
-                */
-               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
-                * don't step on the header when we construct
-                * the sll header.
-                */
-               if (bp < (u_char *)frame +
-                                  TPACKET_ALIGN(handlep->tp_hdrlen) +
-                                  sizeof(struct sockaddr_ll)) {
-                       snprintf(handle->errbuf, PCAP_ERRBUF_SIZE,
-                               "cooked-mode frame doesn't have room for sll header");
-                       return -1;
-               }
-
-               /*
-                * OK, that worked; construct the sll header.
-                */
-               hdrp = (struct sll_header *)bp;
-               hdrp->sll_pkttype = map_packet_type_to_sll_type(
-                                               sll->sll_pkttype);
-               hdrp->sll_hatype = htons(sll->sll_hatype);
-               hdrp->sll_halen = htons(sll->sll_halen);
-               memcpy(hdrp->sll_addr, sll->sll_addr, SLL_ADDRLEN);
-               hdrp->sll_protocol = sll->sll_protocol;
-
                /* update packet len */
-               pcaphdr.caplen += SLL_HDR_LEN;
-               pcaphdr.len += SLL_HDR_LEN;
+               if (handle->linktype == DLT_LINUX_SLL2) {
+                       pcaphdr.caplen += SLL2_HDR_LEN;
+                       pcaphdr.len += SLL2_HDR_LEN;
+               } else {
+                       pcaphdr.caplen += SLL_HDR_LEN;
+                       pcaphdr.len += SLL_HDR_LEN;
+               }
        }
 
 #if defined(HAVE_TPACKET2) || defined(HAVE_TPACKET3)
@@ -4287,13 +5260,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;
        }
@@ -4308,36 +5292,130 @@ 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 */
-       callback(user, &pcaphdr, bp);
+       /* pass the packet to the user */
+       callback(user, &pcaphdr, bp);
+
+       return 1;
+}
+
+static int
+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.*/
+       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)) {
+               /*
+                * 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(
+                               handle,
+                               callback,
+                               user,
+                               h.raw,
+                               h.h1->tp_len,
+                               h.h1->tp_mac,
+                               h.h1->tp_snaplen,
+                               h.h1->tp_sec,
+                               h.h1->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->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;
 
-       return 1;
+               /* check for break loop condition*/
+               if (handle->break_loop) {
+                       handle->break_loop = 0;
+                       return PCAP_ERROR_BREAK;
+               }
+       }
+       return pkts;
 }
 
 static int
-pcap_read_linux_mmap_v1(pcap_t *handle, int max_packets, pcap_handler callback,
+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.*/
-       ret = pcap_wait_for_frames_mmap(handle);
-       if (ret) {
-               return ret;
+       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)) {
-               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_64->tp_status == TP_STATUS_KERNEL)
                        break;
 
                ret = pcap_handle_packet_mmap(
@@ -4345,11 +5423,12 @@ pcap_read_linux_mmap_v1(pcap_t *handle, int max_packets, pcap_handler callback,
                                callback,
                                user,
                                h.raw,
-                               h.h1->tp_len,
-                               h.h1->tp_mac,
-                               h.h1->tp_snaplen,
-                               h.h1->tp_sec,
-                               h.h1->tp_usec,
+                               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) {
@@ -4365,7 +5444,7 @@ pcap_read_linux_mmap_v1(pcap_t *handle, int max_packets, pcap_handler callback,
                 * after having been filtered by the kernel, count
                 * the one we've just processed.
                 */
-               h.h1->tp_status = TP_STATUS_KERNEL;
+               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) {
@@ -4396,22 +5475,32 @@ 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(
@@ -4424,12 +5513,9 @@ pcap_read_linux_mmap_v2(pcap_t *handle, int max_packets, pcap_handler callback,
                                h.h2->tp_snaplen,
                                h.h2->tp_sec,
                                handle->opt.tstamp_precision == PCAP_TSTAMP_PRECISION_NANO ? h.h2->tp_nsec : h.h2->tp_nsec / 1000,
-#if defined(TP_STATUS_VLAN_VALID)
-                               (h.h2->tp_vlan_tci || (h.h2->tp_status & TP_STATUS_VLAN_VALID)),
-#else
-                               h.h2->tp_vlan_tci != 0,
-#endif
-                               h.h2->tp_vlan_tci);
+                               VLAN_VALID(h.h2, h.h2),
+                               h.h2->tp_vlan_tci,
+                               VLAN_TPID(h.h2, h.h2));
                if (ret == 1) {
                        pkts++;
                        handlep->packets_read++;
@@ -4482,13 +5568,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;
@@ -4499,21 +5592,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,
@@ -4525,12 +5627,9 @@ again:
                                        tp3_hdr->tp_snaplen,
                                        tp3_hdr->tp_sec,
                                        handle->opt.tstamp_precision == PCAP_TSTAMP_PRECISION_NANO ? tp3_hdr->tp_nsec : tp3_hdr->tp_nsec / 1000,
-#if defined(TP_STATUS_VLAN_VALID)
-                                       (tp3_hdr->hv1.tp_vlan_tci || (tp3_hdr->tp_status & TP_STATUS_VLAN_VALID)),
-#else
-                                       tp3_hdr->hv1.tp_vlan_tci != 0,
-#endif
-                                       tp3_hdr->hv1.tp_vlan_tci);
+                                       VLAN_VALID(tp3_hdr, &tp3_hdr->hv1),
+                                       tp3_hdr->hv1.tp_vlan_tci,
+                                       VLAN_TPID(tp3_hdr, &tp3_hdr->hv1));
                        if (ret == 1) {
                                pkts++;
                                handlep->packets_read++;
@@ -4583,7 +5682,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;
@@ -4617,12 +5716,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;
        }
 
@@ -4643,9 +5742,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
@@ -4676,11 +5772,11 @@ iface_get_id(int fd, const char *device, char *ebuf)
        struct ifreq    ifr;
 
        memset(&ifr, 0, sizeof(ifr));
-       strlcpy(ifr.ifr_name, device, sizeof(ifr.ifr_name));
+       pcap_strlcpy(ifr.ifr_name, device, sizeof(ifr.ifr_name));
 
        if (ioctl(fd, SIOCGIFINDEX, &ifr) == -1) {
-               snprintf(ebuf, PCAP_ERRBUF_SIZE,
-                        "SIOCGIFINDEX: %s", pcap_strerror(errno));
+               pcap_fmt_errmsg_for_errno(ebuf, PCAP_ERRBUF_SIZE,
+                   errno, "SIOCGIFINDEX");
                return -1;
        }
 
@@ -4693,7 +5789,7 @@ iface_get_id(int fd, const char *device, char *ebuf)
  *  or a PCAP_ERROR_ value on a hard error.
  */
 static int
-iface_bind(int fd, int ifindex, char *ebuf)
+iface_bind(int fd, int ifindex, char *ebuf, int protocol)
 {
        struct sockaddr_ll      sll;
        int                     err;
@@ -4702,7 +5798,7 @@ iface_bind(int fd, int ifindex, char *ebuf)
        memset(&sll, 0, sizeof(sll));
        sll.sll_family          = AF_PACKET;
        sll.sll_ifindex         = ifindex;
-       sll.sll_protocol        = htons(ETH_P_ALL);
+       sll.sll_protocol        = protocol;
 
        if (bind(fd, (struct sockaddr *) &sll, sizeof(sll)) == -1) {
                if (errno == ENETDOWN) {
@@ -4715,8 +5811,8 @@ iface_bind(int fd, int ifindex, char *ebuf)
                         */
                        return PCAP_ERROR_IFACE_NOT_UP;
                } else {
-                       snprintf(ebuf, PCAP_ERRBUF_SIZE,
-                                "bind: %s", pcap_strerror(errno));
+                       pcap_fmt_errmsg_for_errno(ebuf, PCAP_ERRBUF_SIZE,
+                           errno, "bind");
                        return PCAP_ERROR;
                }
        }
@@ -4724,8 +5820,8 @@ 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,
-                       "getsockopt: %s", pcap_strerror(errno));
+               pcap_fmt_errmsg_for_errno(ebuf, PCAP_ERRBUF_SIZE,
+                   errno, "getsockopt (SO_ERROR)");
                return 0;
        }
 
@@ -4739,8 +5835,8 @@ iface_bind(int fd, int ifindex, char *ebuf)
                 */
                return PCAP_ERROR_IFACE_NOT_UP;
        } else if (err > 0) {
-               snprintf(ebuf, PCAP_ERRBUF_SIZE,
-                       "bind: %s", pcap_strerror(err));
+               pcap_fmt_errmsg_for_errno(ebuf, PCAP_ERRBUF_SIZE,
+                   err, "bind");
                return 0;
        }
 
@@ -4757,16 +5853,22 @@ static int
 has_wext(int sock_fd, const char *device, char *ebuf)
 {
        struct iwreq ireq;
+       int ret;
+
+       if (is_bonding_device(sock_fd, device))
+               return 0;       /* bonding device, so don't even try */
 
-       strlcpy(ireq.ifr_ifrn.ifrn_name, device,
+       pcap_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));
        if (errno == ENODEV)
-               return PCAP_ERROR_NO_SUCH_DEVICE;
-       return 0;
+               ret = PCAP_ERROR_NO_SUCH_DEVICE;
+       else
+               ret = 0;
+       pcap_fmt_errmsg_for_errno(ebuf, PCAP_ERRBUF_SIZE, errno,
+           "%s: SIOCGIWNAME", device);
+       return ret;
 }
 
 /*
@@ -4895,13 +5997,13 @@ enter_rfmon_mode_wext(pcap_t *handle, int sock_fd, const char *device)
         * return EOPNOTSUPP.
         */
        memset(&ireq, 0, sizeof ireq);
-       strlcpy(ireq.ifr_ifrn.ifrn_name, device,
+       pcap_strlcpy(ireq.ifr_ifrn.ifrn_name, device,
            sizeof ireq.ifr_ifrn.ifrn_name);
        ireq.u.data.pointer = (void *)args;
        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;
@@ -4914,9 +6016,8 @@ enter_rfmon_mode_wext(pcap_t *handle, int sock_fd, const char *device)
                        /*
                         * Failed.
                         */
-                       snprintf(handle->errbuf, PCAP_ERRBUF_SIZE,
-                           "%s: SIOCGIWPRIV: %s", device,
-                           pcap_strerror(errno));
+                       pcap_fmt_errmsg_for_errno(handle->errbuf,
+                           PCAP_ERRBUF_SIZE, errno, "%s: SIOCGIWPRIV", device);
                        return PCAP_ERROR;
                }
 
@@ -4925,15 +6026,14 @@ 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,
-                           "malloc: %s", pcap_strerror(errno));
+                       pcap_fmt_errmsg_for_errno(handle->errbuf,
+                           PCAP_ERRBUF_SIZE, errno, "malloc");
                        return PCAP_ERROR;
                }
                ireq.u.data.pointer = (void *)priv;
                if (ioctl(sock_fd, SIOCGIWPRIV, &ireq) == -1) {
-                       snprintf(handle->errbuf, PCAP_ERRBUF_SIZE,
-                           "%s: SIOCGIWPRIV: %s", device,
-                           pcap_strerror(errno));
+                       pcap_fmt_errmsg_for_errno(handle->errbuf,
+                           PCAP_ERRBUF_SIZE, errno, "%s: SIOCGIWPRIV", device);
                        free(priv);
                        return PCAP_ERROR;
                }
@@ -5097,7 +6197,7 @@ enter_rfmon_mode_wext(pcap_t *handle, int sock_fd, const char *device)
        /*
         * Get the old mode.
         */
-       strlcpy(ireq.ifr_ifrn.ifrn_name, device,
+       pcap_strlcpy(ireq.ifr_ifrn.ifrn_name, device,
            sizeof ireq.ifr_ifrn.ifrn_name);
        if (ioctl(sock_fd, SIOCGIWMODE, &ireq) == -1) {
                /*
@@ -5153,7 +6253,7 @@ enter_rfmon_mode_wext(pcap_t *handle, int sock_fd, const char *device)
                 * If it fails, just fall back on SIOCSIWMODE.
                 */
                memset(&ireq, 0, sizeof ireq);
-               strlcpy(ireq.ifr_ifrn.ifrn_name, device,
+               pcap_strlcpy(ireq.ifr_ifrn.ifrn_name, device,
                    sizeof ireq.ifr_ifrn.ifrn_name);
                ireq.u.data.length = 1; /* 1 argument */
                args[0] = 3;    /* request Prism header */
@@ -5185,10 +6285,10 @@ enter_rfmon_mode_wext(pcap_t *handle, int sock_fd, const char *device)
         * might get EBUSY.
         */
        memset(&ifr, 0, sizeof(ifr));
-       strlcpy(ifr.ifr_name, device, sizeof(ifr.ifr_name));
+       pcap_strlcpy(ifr.ifr_name, device, sizeof(ifr.ifr_name));
        if (ioctl(sock_fd, SIOCGIFFLAGS, &ifr) == -1) {
-               snprintf(handle->errbuf, PCAP_ERRBUF_SIZE,
-                   "%s: Can't get flags: %s", device, strerror(errno));
+               pcap_fmt_errmsg_for_errno(handle->errbuf, PCAP_ERRBUF_SIZE,
+                   errno, "%s: Can't get flags", device);
                return PCAP_ERROR;
        }
        oldflags = 0;
@@ -5196,8 +6296,9 @@ 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,
-                           "%s: Can't set flags: %s", device, strerror(errno));
+                       pcap_fmt_errmsg_for_errno(handle->errbuf,
+                           PCAP_ERRBUF_SIZE, errno, "%s: Can't set flags",
+                           device);
                        return PCAP_ERROR;
                }
        }
@@ -5205,7 +6306,7 @@ enter_rfmon_mode_wext(pcap_t *handle, int sock_fd, const char *device)
        /*
         * Then turn monitor mode on.
         */
-       strlcpy(ireq.ifr_ifrn.ifrn_name, device,
+       pcap_strlcpy(ireq.ifr_ifrn.ifrn_name, device,
            sizeof ireq.ifr_ifrn.ifrn_name);
        ireq.u.mode = IW_MODE_MONITOR;
        if (ioctl(sock_fd, SIOCSIWMODE, &ireq) == -1) {
@@ -5215,8 +6316,9 @@ 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,
-                           "%s: Can't set flags: %s", device, strerror(errno));
+                       pcap_fmt_errmsg_for_errno(handle->errbuf,
+                           PCAP_ERRBUF_SIZE, errno, "%s: Can't set flags",
+                           device);
                        return PCAP_ERROR;
                }
                return PCAP_ERROR_RFMON_NOTSUP;
@@ -5244,7 +6346,7 @@ enter_rfmon_mode_wext(pcap_t *handle, int sock_fd, const char *device)
                 * Try to select the radiotap header.
                 */
                memset(&ireq, 0, sizeof ireq);
-               strlcpy(ireq.ifr_ifrn.ifrn_name, device,
+               pcap_strlcpy(ireq.ifr_ifrn.ifrn_name, device,
                    sizeof ireq.ifr_ifrn.ifrn_name);
                args[0] = 3;    /* request radiotap header */
                memcpy(ireq.u.name, args, sizeof (int));
@@ -5255,7 +6357,7 @@ enter_rfmon_mode_wext(pcap_t *handle, int sock_fd, const char *device)
                 * That failed.  Try to select the AVS header.
                 */
                memset(&ireq, 0, sizeof ireq);
-               strlcpy(ireq.ifr_ifrn.ifrn_name, device,
+               pcap_strlcpy(ireq.ifr_ifrn.ifrn_name, device,
                    sizeof ireq.ifr_ifrn.ifrn_name);
                args[0] = 2;    /* request AVS header */
                memcpy(ireq.u.name, args, sizeof (int));
@@ -5266,7 +6368,7 @@ enter_rfmon_mode_wext(pcap_t *handle, int sock_fd, const char *device)
                 * That failed.  Try to select the Prism header.
                 */
                memset(&ireq, 0, sizeof ireq);
-               strlcpy(ireq.ifr_ifrn.ifrn_name, device,
+               pcap_strlcpy(ireq.ifr_ifrn.ifrn_name, device,
                    sizeof ireq.ifr_ifrn.ifrn_name);
                args[0] = 1;    /* request Prism header */
                memcpy(ireq.u.name, args, sizeof (int));
@@ -5284,7 +6386,7 @@ enter_rfmon_mode_wext(pcap_t *handle, int sock_fd, const char *device)
                 * Select the Prism header.
                 */
                memset(&ireq, 0, sizeof ireq);
-               strlcpy(ireq.ifr_ifrn.ifrn_name, device,
+               pcap_strlcpy(ireq.ifr_ifrn.ifrn_name, device,
                    sizeof ireq.ifr_ifrn.ifrn_name);
                args[0] = 3;    /* request Prism header */
                memcpy(ireq.u.name, args, sizeof (int));
@@ -5296,12 +6398,11 @@ enter_rfmon_mode_wext(pcap_t *handle, int sock_fd, const char *device)
                 * Get the current channel.
                 */
                memset(&ireq, 0, sizeof ireq);
-               strlcpy(ireq.ifr_ifrn.ifrn_name, device,
+               pcap_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,
-                           "%s: SIOCGIWFREQ: %s", device,
-                           pcap_strerror(errno));
+                       pcap_fmt_errmsg_for_errno(handle->errbuf,
+                           PCAP_ERRBUF_SIZE, errno, "%s: SIOCGIWFREQ", device);
                        return PCAP_ERROR;
                }
                channel = ireq.u.freq.m;
@@ -5311,7 +6412,7 @@ enter_rfmon_mode_wext(pcap_t *handle, int sock_fd, const char *device)
                 * current value.
                 */
                memset(&ireq, 0, sizeof ireq);
-               strlcpy(ireq.ifr_ifrn.ifrn_name, device,
+               pcap_strlcpy(ireq.ifr_ifrn.ifrn_name, device,
                    sizeof ireq.ifr_ifrn.ifrn_name);
                args[0] = 1;            /* request Prism header */
                args[1] = channel;      /* set channel */
@@ -5325,7 +6426,7 @@ enter_rfmon_mode_wext(pcap_t *handle, int sock_fd, const char *device)
                 * Prism header.
                 */
                memset(&ireq, 0, sizeof ireq);
-               strlcpy(ireq.ifr_ifrn.ifrn_name, device,
+               pcap_strlcpy(ireq.ifr_ifrn.ifrn_name, device,
                    sizeof ireq.ifr_ifrn.ifrn_name);
                args[0] = 0;    /* disallow transmitting */
                memcpy(ireq.u.name, args, sizeof (int));
@@ -5337,7 +6438,7 @@ enter_rfmon_mode_wext(pcap_t *handle, int sock_fd, const char *device)
                 * Force the Prism header.
                 */
                memset(&ireq, 0, sizeof ireq);
-               strlcpy(ireq.ifr_ifrn.ifrn_name, device,
+               pcap_strlcpy(ireq.ifr_ifrn.ifrn_name, device,
                    sizeof ireq.ifr_ifrn.ifrn_name);
                args[0] = 1;    /* request Prism header */
                memcpy(ireq.u.name, args, sizeof (int));
@@ -5349,7 +6450,7 @@ enter_rfmon_mode_wext(pcap_t *handle, int sock_fd, const char *device)
                 * Force the Prism header.
                 */
                memset(&ireq, 0, sizeof ireq);
-               strlcpy(ireq.ifr_ifrn.ifrn_name, device,
+               pcap_strlcpy(ireq.ifr_ifrn.ifrn_name, device,
                    sizeof ireq.ifr_ifrn.ifrn_name);
                ireq.u.data.length = 1; /* 1 argument */
                ireq.u.data.pointer = "1";
@@ -5362,7 +6463,7 @@ enter_rfmon_mode_wext(pcap_t *handle, int sock_fd, const char *device)
                 * Force the Prism header.
                 */
                memset(&ireq, 0, sizeof ireq);
-               strlcpy(ireq.ifr_ifrn.ifrn_name, device,
+               pcap_strlcpy(ireq.ifr_ifrn.ifrn_name, device,
                    sizeof ireq.ifr_ifrn.ifrn_name);
                args[0] = 1;    /* request Prism header */
                memcpy(ireq.u.name, args, sizeof (int));
@@ -5376,8 +6477,9 @@ 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,
-                           "%s: Can't set flags: %s", device, strerror(errno));
+                       pcap_fmt_errmsg_for_errno(handle->errbuf,
+                           PCAP_ERRBUF_SIZE, errno, "%s: Can't set flags",
+                           device);
 
                        /*
                         * At least try to restore the old mode on the
@@ -5445,6 +6547,177 @@ 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) {
+               pcap_fmt_errmsg_for_errno(ebuf, PCAP_ERRBUF_SIZE,
+                   errno, "socket for SIOCETHTOOL(ETHTOOL_GET_TS_INFO)");
+               return -1;
+       }
+
+       memset(&ifr, 0, sizeof(ifr));
+       pcap_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_fmt_errmsg_for_errno(ebuf, PCAP_ERRBUF_SIZE,
+                           save_errno,
+                           "%s: SIOCETHTOOL(ETHTOOL_GET_TS_INFO) ioctl failed",
+                           device);
+                       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.
  *
@@ -5452,21 +6725,35 @@ enter_rfmon_mode(pcap_t *handle, int sock_fd, const char *device)
  * if SIOCETHTOOL isn't defined, or we don't have any #defines for any
  * of the types of offloading, there's nothing we can do to check, so
  * we just say "no, we don't".
+ *
+ * We treat EOPNOTSUPP, EINVAL and, if eperm_ok is true, EPERM as
+ * indications that the operation isn't supported.  We do EPERM
+ * weirdly because the SIOCETHTOOL code in later kernels 1) doesn't
+ * support ETHTOOL_GUFO, 2) also doesn't include it in the list
+ * of ethtool operations that don't require CAP_NET_ADMIN privileges,
+ * and 3) does the "is this permitted" check before doing the "is
+ * this even supported" check, so it fails with "this is not permitted"
+ * rather than "this is not even supported".  To work around this
+ * annoyance, we only treat EPERM as an error for the first feature,
+ * and assume that they all do the same permission checks, so if the
+ * first one is allowed all the others are allowed if supported.
  */
 #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,
+    int eperm_ok)
 {
        struct ifreq    ifr;
        struct ethtool_value eval;
 
        memset(&ifr, 0, sizeof(ifr));
-       strlcpy(ifr.ifr_name, handle->opt.source, sizeof(ifr.ifr_name));
+       pcap_strlcpy(ifr.ifr_name, handle->opt.device, sizeof(ifr.ifr_name));
        eval.cmd = cmd;
        eval.data = 0;
        ifr.ifr_data = (caddr_t)&eval;
        if (ioctl(handle->fd, SIOCETHTOOL, &ifr) == -1) {
-               if (errno == EOPNOTSUPP || errno == EINVAL) {
+               if (errno == EOPNOTSUPP || errno == EINVAL ||
+                   (errno == EPERM && eperm_ok)) {
                        /*
                         * OK, let's just return 0, which, in our
                         * case, either means "no, what we're asking
@@ -5475,42 +6762,49 @@ 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,
-                   cmdname, strerror(errno));
+               pcap_fmt_errmsg_for_errno(handle->errbuf, PCAP_ERRBUF_SIZE,
+                   errno, "%s: SIOCETHTOOL(%s) ioctl failed",
+                   handle->opt.device, cmdname);
                return -1;
        }
-       return eval.data;       
+       return eval.data;
 }
 
+/*
+ * XXX - it's annoying that we have to check for offloading at all, but,
+ * given that we have to, it's still annoying that we have to check for
+ * particular types of offloading, especially that shiny new types of
+ * offloading may be added - and, worse, may not be checkable with
+ * a particular ETHTOOL_ operation; ETHTOOL_GFEATURES would, in
+ * theory, give those to you, but the actual flags being used are
+ * opaque (defined in a non-uapi header), and there doesn't seem to
+ * be any obvious way to ask the kernel what all the offloading flags
+ * are - at best, you can ask for a set of strings(!) to get *names*
+ * for various flags.  (That whole mechanism appears to have been
+ * designed for the sole purpose of letting ethtool report flags
+ * by name and set flags by name, with the names having no semantics
+ * ethtool understands.)
+ */
 static int
 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", 0);
        if (ret == -1)
                return -1;
        if (ret)
                return 1;       /* TCP segmentation offloading on */
 #endif
 
-#ifdef ETHTOOL_GUFO
-       ret = iface_ethtool_ioctl(handle, ETHTOOL_GUFO, "ETHTOOL_GUFO");
-       if (ret == -1)
-               return -1;
-       if (ret)
-               return 1;       /* UDP fragmentation offloading on */
-#endif
-
 #ifdef ETHTOOL_GGSO
        /*
         * XXX - will this cause large unsegmented packets to be
         * 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", 0);
        if (ret == -1)
                return -1;
        if (ret)
@@ -5518,7 +6812,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", 0);
        if (ret == -1)
                return -1;
        if (ret & ETH_FLAG_LRO)
@@ -5531,13 +6825,27 @@ 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", 0);
        if (ret == -1)
                return -1;
        if (ret)
                return 1;       /* generic (large) receive offloading on */
 #endif
 
+#ifdef ETHTOOL_GUFO
+       /*
+        * Do this one last, as support for it was removed in later
+        * kernels, and it fails with EPERM on those kernels rather
+        * than with EOPNOTSUPP (see explanation in comment for
+        * iface_ethtool_flag_ioctl()).
+        */
+       ret = iface_ethtool_flag_ioctl(handle, ETHTOOL_GUFO, "ETHTOOL_GUFO", 1);
+       if (ret == -1)
+               return -1;
+       if (ret)
+               return 1;       /* UDP fragmentation offloading on */
+#endif
+
        return 0;
 }
 #else /* SIOCETHTOOL */
@@ -5552,6 +6860,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 ================== */
@@ -5564,19 +6874,30 @@ static int
 activate_old(pcap_t *handle)
 {
        struct pcap_linux *handlep = handle->priv;
+       int             err;
        int             arptype;
        struct ifreq    ifr;
-       const char      *device = handle->opt.source;
+       const char      *device = handle->opt.device;
        struct utsname  utsname;
        int             mtu;
 
-       /* Open the socket */
+       /*
+        * PF_INET/SOCK_PACKET sockets must be bound to a device, so we
+        * can't support the "any" device.
+        */
+       if (strcmp(device, "any") == 0) {
+               pcap_strlcpy(handle->errbuf, "pcap_activate: The \"any\" device isn't supported on 2.0[.x]-kernel systems",
+                       PCAP_ERRBUF_SIZE);
+               return PCAP_ERROR;
+       }
 
+       /* Open the socket */
        handle->fd = socket(PF_INET, SOCK_PACKET, htons(ETH_P_ALL));
        if (handle->fd == -1) {
-               snprintf(handle->errbuf, PCAP_ERRBUF_SIZE,
-                        "socket: %s", pcap_strerror(errno));
-               if (errno == EPERM || errno == EACCES) {
+               err = errno;
+               pcap_fmt_errmsg_for_errno(handle->errbuf, PCAP_ERRBUF_SIZE,
+                   err, "socket");
+               if (err == EPERM || err == EACCES) {
                        /*
                         * You don't have permission to open the
                         * socket.
@@ -5597,12 +6918,6 @@ activate_old(pcap_t *handle)
        handlep->cooked = 0;
 
        /* Bind to the given device */
-
-       if (strcmp(device, "any") == 0) {
-               strlcpy(handle->errbuf, "pcap_activate: The \"any\" device isn't supported on 2.0[.x]-kernel systems",
-                       PCAP_ERRBUF_SIZE);
-               return PCAP_ERROR;
-       }
        if (iface_bind_old(handle->fd, device, handle->errbuf) == -1)
                return PCAP_ERROR;
 
@@ -5617,9 +6932,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;
        }
@@ -5628,10 +6943,10 @@ activate_old(pcap_t *handle)
 
        if (handle->opt.promisc) {
                memset(&ifr, 0, sizeof(ifr));
-               strlcpy(ifr.ifr_name, device, sizeof(ifr.ifr_name));
+               pcap_strlcpy(ifr.ifr_name, device, sizeof(ifr.ifr_name));
                if (ioctl(handle->fd, SIOCGIFFLAGS, &ifr) == -1) {
-                       snprintf(handle->errbuf, PCAP_ERRBUF_SIZE,
-                                "SIOCGIFFLAGS: %s", pcap_strerror(errno));
+                       pcap_fmt_errmsg_for_errno(handle->errbuf,
+                           PCAP_ERRBUF_SIZE, errno, "SIOCGIFFLAGS");
                        return PCAP_ERROR;
                }
                if ((ifr.ifr_flags & IFF_PROMISC) == 0) {
@@ -5658,9 +6973,8 @@ activate_old(pcap_t *handle)
 
                        ifr.ifr_flags |= IFF_PROMISC;
                        if (ioctl(handle->fd, SIOCSIFFLAGS, &ifr) == -1) {
-                               snprintf(handle->errbuf, PCAP_ERRBUF_SIZE,
-                                        "SIOCSIFFLAGS: %s",
-                                        pcap_strerror(errno));
+                               pcap_fmt_errmsg_for_errno(handle->errbuf,
+                                   PCAP_ERRBUF_SIZE, errno, "SIOCSIFFLAGS");
                                return PCAP_ERROR;
                        }
                        handlep->must_do_on_close |= MUST_CLEAR_PROMISC;
@@ -5727,16 +7041,27 @@ 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.
                 *
                 * We can safely pass "recvfrom()" a byte count
                 * based on the snapshot length.
+                *
+                * XXX - this "should not happen", as 2.2[.x]
+                * kernels all have PF_PACKET sockets, and there's
+                * no configuration option to disable them without
+                * disabling SOCK_PACKET sockets, because
+                * SOCK_PACKET sockets are implemented in the same
+                * source file, net/packet/af_packet.c.  There *is*
+                * an option to disable SOCK_PACKET sockets so that
+                * you only have PF_PACKET sockets, and the kernel
+                * will log warning messages for code that uses
+                * "obsolete (PF_INET,SOCK_PACKET)".
                 */
-               handle->bufsize = handle->snapshot;
+               handle->bufsize = (u_int)handle->snapshot;
        }
 
        /*
@@ -5766,24 +7091,24 @@ iface_bind_old(int fd, const char *device, char *ebuf)
        socklen_t       errlen = sizeof(err);
 
        memset(&saddr, 0, sizeof(saddr));
-       strlcpy(saddr.sa_data, device, sizeof(saddr.sa_data));
+       pcap_strlcpy(saddr.sa_data, device, sizeof(saddr.sa_data));
        if (bind(fd, &saddr, sizeof(saddr)) == -1) {
-               snprintf(ebuf, PCAP_ERRBUF_SIZE,
-                        "bind: %s", pcap_strerror(errno));
+               pcap_fmt_errmsg_for_errno(ebuf, PCAP_ERRBUF_SIZE,
+                   errno, "bind");
                return -1;
        }
 
        /* Any pending errors, e.g., network is down? */
 
        if (getsockopt(fd, SOL_SOCKET, SO_ERROR, &err, &errlen) == -1) {
-               snprintf(ebuf, PCAP_ERRBUF_SIZE,
-                       "getsockopt: %s", pcap_strerror(errno));
+               pcap_fmt_errmsg_for_errno(ebuf, PCAP_ERRBUF_SIZE,
+                   errno, "getsockopt (SO_ERROR)");
                return -1;
        }
 
        if (err > 0) {
-               snprintf(ebuf, PCAP_ERRBUF_SIZE,
-                       "bind: %s", pcap_strerror(err));
+               pcap_fmt_errmsg_for_errno(ebuf, PCAP_ERRBUF_SIZE,
+                   err, "bind");
                return -1;
        }
 
@@ -5805,11 +7130,11 @@ iface_get_mtu(int fd, const char *device, char *ebuf)
                return BIGGER_THAN_ALL_MTUS;
 
        memset(&ifr, 0, sizeof(ifr));
-       strlcpy(ifr.ifr_name, device, sizeof(ifr.ifr_name));
+       pcap_strlcpy(ifr.ifr_name, device, sizeof(ifr.ifr_name));
 
        if (ioctl(fd, SIOCGIFMTU, &ifr) == -1) {
-               snprintf(ebuf, PCAP_ERRBUF_SIZE,
-                        "SIOCGIFMTU: %s", pcap_strerror(errno));
+               pcap_fmt_errmsg_for_errno(ebuf, PCAP_ERRBUF_SIZE,
+                   errno, "SIOCGIFMTU");
                return -1;
        }
 
@@ -5823,20 +7148,22 @@ static int
 iface_get_arptype(int fd, const char *device, char *ebuf)
 {
        struct ifreq    ifr;
+       int             ret;
 
        memset(&ifr, 0, sizeof(ifr));
-       strlcpy(ifr.ifr_name, device, sizeof(ifr.ifr_name));
+       pcap_strlcpy(ifr.ifr_name, device, sizeof(ifr.ifr_name));
 
        if (ioctl(fd, SIOCGIFHWADDR, &ifr) == -1) {
-               snprintf(ebuf, PCAP_ERRBUF_SIZE,
-                        "SIOCGIFHWADDR: %s", pcap_strerror(errno));
                if (errno == ENODEV) {
                        /*
                         * No such device.
                         */
-                       return PCAP_ERROR_NO_SUCH_DEVICE;
-               }
-               return PCAP_ERROR;
+                       ret = PCAP_ERROR_NO_SUCH_DEVICE;
+               } else
+                       ret = PCAP_ERROR;
+               pcap_fmt_errmsg_for_errno(ebuf, PCAP_ERRBUF_SIZE,
+                   errno, "SIOCGIFHWADDR");
+               return ret;
        }
 
        return ifr.ifr_hwaddr.sa_family;
@@ -5861,8 +7188,8 @@ 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,
-                        "malloc: %s", pcap_strerror(errno));
+               pcap_fmt_errmsg_for_errno(handle->errbuf, PCAP_ERRBUF_SIZE,
+                   errno, "malloc");
                return -1;
        }
        memcpy(f, handle->fcode.bf_insns, prog_size);
@@ -5928,7 +7255,7 @@ fix_program(pcap_t *handle, struct sock_fprog *fcode, int is_mmapped)
                                         * Yes, so we need to fix this
                                         * instruction.
                                         */
-                                       if (fix_offset(p) < 0) {
+                                       if (fix_offset(handle, p) < 0) {
                                                /*
                                                 * We failed to do so.
                                                 * Return 0, so our caller
@@ -5946,38 +7273,80 @@ fix_program(pcap_t *handle, struct sock_fprog *fcode, int is_mmapped)
 }
 
 static int
-fix_offset(struct bpf_insn *p)
+fix_offset(pcap_t *handle, struct bpf_insn *p)
 {
        /*
-        * What's the offset?
+        * Existing references to auxiliary data shouldn't be adjusted.
+        *
+        * Note that SKF_AD_OFF is negative, but p->k is unsigned, so
+        * we use >= and cast SKF_AD_OFF to unsigned.
         */
-       if (p->k >= SLL_HDR_LEN) {
-               /*
-                * It's within the link-layer payload; that starts at an
-                * offset of 0, as far as the kernel packet filter is
-                * concerned, so subtract the length of the link-layer
-                * header.
-                */
-               p->k -= SLL_HDR_LEN;
-       } else if (p->k == 0) {
-               /*
-                * It's the packet type field; map it to the special magic
-                * kernel offset for that field.
-                */
-               p->k = SKF_AD_OFF + SKF_AD_PKTTYPE;
-       } else if (p->k == 14) {
+       if (p->k >= (bpf_u_int32)SKF_AD_OFF)
+               return 0;
+       if (handle->linktype == DLT_LINUX_SLL2) {
                /*
-                * It's the protocol field; map it to the special magic
-                * kernel offset for that field.
+                * What's the offset?
                 */
-               p->k = SKF_AD_OFF + SKF_AD_PROTOCOL;
-       } else if ((bpf_int32)(p->k) > 0) {
+               if (p->k >= SLL2_HDR_LEN) {
+                       /*
+                        * It's within the link-layer payload; that starts
+                        * at an offset of 0, as far as the kernel packet
+                        * filter is concerned, so subtract the length of
+                        * the link-layer header.
+                        */
+                       p->k -= SLL2_HDR_LEN;
+               } else if (p->k == 0) {
+                       /*
+                        * It's the protocol field; map it to the
+                        * special magic kernel offset for that field.
+                        */
+                       p->k = SKF_AD_OFF + SKF_AD_PROTOCOL;
+               } else if (p->k == 10) {
+                       /*
+                        * It's the packet type field; map it to the
+                        * special magic kernel offset for that field.
+                        */
+                       p->k = SKF_AD_OFF + SKF_AD_PKTTYPE;
+               } else if ((bpf_int32)(p->k) > 0) {
+                       /*
+                        * It's within the header, but it's not one of
+                        * those fields; we can't do that in the kernel,
+                        * so punt to userland.
+                        */
+                       return -1;
+               }
+       } else {
                /*
-                * It's within the header, but it's not one of those
-                * fields; we can't do that in the kernel, so punt
-                * to userland.
+                * What's the offset?
                 */
-               return -1;
+               if (p->k >= SLL_HDR_LEN) {
+                       /*
+                        * It's within the link-layer payload; that starts
+                        * at an offset of 0, as far as the kernel packet
+                        * filter is concerned, so subtract the length of
+                        * the link-layer header.
+                        */
+                       p->k -= SLL_HDR_LEN;
+               } else if (p->k == 0) {
+                       /*
+                        * It's the packet type field; map it to the
+                        * special magic kernel offset for that field.
+                        */
+                       p->k = SKF_AD_OFF + SKF_AD_PKTTYPE;
+               } else if (p->k == 14) {
+                       /*
+                        * It's the protocol field; map it to the
+                        * special magic kernel offset for that field.
+                        */
+                       p->k = SKF_AD_OFF + SKF_AD_PROTOCOL;
+               } else if ((bpf_int32)(p->k) > 0) {
+                       /*
+                        * It's within the header, but it's not one of
+                        * those fields; we can't do that in the kernel,
+                        * so punt to userland.
+                        */
+                       return -1;
+               }
        }
        return 0;
 }
@@ -6037,20 +7406,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_fmt_errmsg_for_errno(handle->errbuf,
+                           PCAP_ERRBUF_SIZE, errno,
+                           "can't get FD flags when changing filter");
+                       return -2;
+               }
+               if (fcntl(handle->fd, F_SETFL, save_mode | O_NONBLOCK) < 0) {
+                       pcap_fmt_errmsg_for_errno(handle->errbuf,
+                           PCAP_ERRBUF_SIZE, errno,
+                           "can't set nonblocking mode when changing filter");
+                       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_fmt_errmsg_for_errno(handle->errbuf,
+                           PCAP_ERRBUF_SIZE, save_errno,
+                           "recv failed when changing filter");
+                       return -2;
+               }
+               if (fcntl(handle->fd, F_SETFL, save_mode) == -1) {
+                       pcap_fmt_errmsg_for_errno(handle->errbuf,
+                           PCAP_ERRBUF_SIZE, errno,
+                           "can't restore FD flags when changing filter");
+                       return -2;
                }
        }
 
@@ -6073,11 +7462,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_fmt_errmsg_for_errno(handle->errbuf,
+                           PCAP_ERRBUF_SIZE, errno,
+                           "can't remove kernel total filter");
+                       return -2;      /* fatal error */
+               }
 
                errno = save_errno;
        }
@@ -6087,6 +7481,7 @@ set_kernel_filter(pcap_t *handle, struct sock_fprog *fcode)
 static int
 reset_kernel_filter(pcap_t *handle)
 {
+       int ret;
        /*
         * setsockopt() barfs unless it get a dummy parameter.
         * valgrind whines unless the value is initialized,
@@ -6095,7 +7490,45 @@ reset_kernel_filter(pcap_t *handle)
         */
        int dummy = 0;
 
-       return setsockopt(handle->fd, SOL_SOCKET, SO_DETACH_FILTER,
+       ret = setsockopt(handle->fd, SOL_SOCKET, SO_DETACH_FILTER,
                                   &dummy, sizeof(dummy));
+       /*
+        * Ignore ENOENT - it means "we don't have a filter", so there
+        * was no filter to remove, and there's still no filter.
+        *
+        * Also ignore ENONET, as a lot of kernel versions had a
+        * typo where ENONET, rather than ENOENT, was returned.
+        */
+       if (ret == -1 && errno != ENOENT && errno != ENONET)
+               return -1;
+       return 0;
+}
+#endif
+
+int
+pcap_set_protocol_linux(pcap_t *p, int protocol)
+{
+       if (pcap_check_activated(p))
+               return (PCAP_ERROR_ACTIVATED);
+       p->opt.protocol = protocol;
+       return (0);
 }
+
+/*
+ * Libpcap version string.
+ */
+const char *
+pcap_lib_version(void)
+{
+#ifdef HAVE_PACKET_RING
+ #if defined(HAVE_TPACKET3)
+       return (PCAP_VERSION_STRING " (with TPACKET_V3)");
+ #elif defined(HAVE_TPACKET2)
+       return (PCAP_VERSION_STRING " (with TPACKET_V2)");
+ #else
+       return (PCAP_VERSION_STRING " (with TPACKET_V1)");
+ #endif
+#else
+       return (PCAP_VERSION_STRING " (without TPACKET)");
 #endif
+}
index 2a5812b..91bad37 100644 (file)
@@ -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
@@ -29,7 +29,7 @@
  */
 
 #ifdef HAVE_CONFIG_H
-#include "config.h"
+#include <config.h>
 #endif
 
 #include "pcap-int.h"
 #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,47 +79,103 @@ 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 nfqueue_send_verdict(const pcap_t *handle, uint16_t group_id, u_int32_t id, u_int32_t verdict);
+
 
 static int
 netfilter_read_linux(pcap_t *handle, int max_packets, pcap_handler callback, u_char *user)
 {
        struct pcap_netfilter *handlep = handle->priv;
-       const unsigned char *buf;
+       register u_char *bp, *ep;
        int count = 0;
        int len;
 
-       /* ignore interrupt system call error */
-       do {
-               len = recv(handle->fd, handle->buffer, handle->bufsize, 0);
-               if (handle->break_loop) {
-                       handle->break_loop = 0;
-                       return -2;
-               }
-       } while ((len == -1) && (errno == EINTR));
-
-       if (len < 0) {
-               snprintf(handle->errbuf, PCAP_ERRBUF_SIZE, "Can't receive packet %d:%s", errno, pcap_strerror(errno));
-               return -1;
+       /*
+        * Has "pcap_breakloop()" been called?
+        */
+       if (handle->break_loop) {
+               /*
+                * Yes - clear the flag that indicates that it
+                * has, and return PCAP_ERROR_BREAK to indicate
+                * that we were told to break out of the loop.
+                */
+               handle->break_loop = 0;
+               return PCAP_ERROR_BREAK;
        }
+       len = handle->cc;
+       if (len == 0) {
+               /*
+                * The buffer is empty; refill it.
+                *
+                * We ignore EINTR, as that might just be due to a signal
+                * being delivered - if the signal should interrupt the
+                * loop, the signal handler should call pcap_breakloop()
+                * to set handle->break_loop (we ignore it on other
+                * platforms as well).
+                */
+               do {
+                       len = recv(handle->fd, handle->buffer, handle->bufsize, 0);
+                       if (handle->break_loop) {
+                               handle->break_loop = 0;
+                               return PCAP_ERROR_BREAK;
+                       }
+                       if (errno == ENOBUFS)
+                               handlep->packets_nobufs++;
+               } while ((len == -1) && (errno == EINTR || errno == ENOBUFS));
+
+               if (len < 0) {
+                       pcap_fmt_errmsg_for_errno(handle->errbuf,
+                           PCAP_ERRBUF_SIZE, errno, "Can't receive packet");
+                       return PCAP_ERROR;
+               }
 
-       buf = handle->buffer;
-       while (len >= NLMSG_SPACE(0)) {
-               const struct nlmsghdr *nlh = (const struct nlmsghdr *) buf;
-               u_int32_t msg_len;
+               bp = (unsigned char *)handle->buffer;
+       } else
+               bp = handle->bp;
+       ep = bp + len;
+       while (bp < ep) {
+               const struct nlmsghdr *nlh = (const struct nlmsghdr *) bp;
+               uint32_t msg_len;
                nftype_t type = OTHER;
+               /*
+                * Has "pcap_breakloop()" been called?
+                * If so, return immediately - if we haven't read any
+                * packets, clear the flag and return PCAP_ERROR_BREAK
+                * 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 (handle->break_loop) {
+                       handle->bp = bp;
+                       handle->cc = ep - bp;
+                       if (count == 0) {
+                               handle->break_loop = 0;
+                               return PCAP_ERROR_BREAK;
+                       } else
+                               return count;
+               }
+               if (ep - bp < NLMSG_SPACE(0)) {
+                       /*
+                        * There's less than one netlink message left
+                        * in the buffer.  Give up.
+                        */
+                       break;
+               }
 
-               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 +183,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 +240,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,17 +250,33 @@ 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;
-
-               len -= msg_len;
-               buf += msg_len;
+               /*
+                * If the message length would run past the end of the
+                * buffer, truncate it to the remaining space in the
+                * buffer.
+                */
+               if (msg_len > ep - bp)
+                       msg_len = ep - bp;
+
+               bp += msg_len;
+               if (count >= max_packets && !PACKET_COUNT_IS_UNLIMITED(max_packets)) {
+                       handle->bp = bp;
+                       handle->cc = ep - bp;
+                       if (handle->cc < 0)
+                               handle->cc = 0;
+                       return count;
+               }
        }
+
+       handle->cc = 0;
        return count;
 }
 
@@ -221,35 +293,37 @@ 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;
 }
 
 static int
-netfilter_inject_linux(pcap_t *handle, const void *buf, size_t size)
+netfilter_inject_linux(pcap_t *handle, const void *buf _U_, size_t size _U_)
 {
-       snprintf(handle->errbuf, PCAP_ERRBUF_SIZE, "inject not supported on netfilter devices");
+       pcap_snprintf(handle->errbuf, PCAP_ERRBUF_SIZE,
+           "Packet injection is not supported on netfilter devices");
        return (-1);
-}                           
+}
 
 struct my_nfattr {
-       u_int16_t nfa_len;
-       u_int16_t nfa_type;
+       uint16_t nfa_len;
+       uint16_t nfa_type;
        void *data;
 };
 
 static int
-netfilter_send_config_msg(const pcap_t *handle, u_int16_t msg_type, int ack, u_int8_t family, u_int16_t res_id, const struct my_nfattr *mynfa)
+netfilter_send_config_msg(const pcap_t *handle, uint16_t msg_type, int ack, u_int8_t family, u_int16_t res_id, const struct my_nfattr *mynfa)
 {
        char buf[1024] __attribute__ ((aligned));
+       memset(buf, 0, sizeof(buf));
 
        struct nlmsghdr *nlh = (struct nlmsghdr *) buf;
        struct nfgenmsg *nfg = (struct nfgenmsg *) (buf + sizeof(struct nlmsghdr));
 
        struct sockaddr_nl snl;
        static unsigned int seq_id;
-       
+
        if (!seq_id)
                seq_id = time(NULL);
        ++seq_id;
@@ -304,7 +378,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, (u_int)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;
@@ -321,13 +395,13 @@ netfilter_send_config_msg(const pcap_t *handle, u_int16_t msg_type, int ack, u_i
 }
 
 static int
-nflog_send_config_msg(const pcap_t *handle, u_int8_t family, u_int16_t group_id, const struct my_nfattr *mynfa)
+nflog_send_config_msg(const pcap_t *handle, uint8_t family, u_int16_t group_id, const struct my_nfattr *mynfa)
 {
        return netfilter_send_config_msg(handle, (NFNL_SUBSYS_ULOG << 8) | NFULNL_MSG_CONFIG, 1, family, group_id, mynfa);
 }
 
 static int
-nflog_send_config_cmd(const pcap_t *handle, u_int16_t group_id, u_int8_t cmd, u_int8_t family)
+nflog_send_config_cmd(const pcap_t *handle, uint16_t group_id, u_int8_t cmd, u_int8_t family)
 {
        struct nfulnl_msg_config_cmd msg;
        struct my_nfattr nfa;
@@ -341,8 +415,8 @@ 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 
-nflog_send_config_mode(const pcap_t *handle, u_int16_t group_id, u_int8_t copy_mode, u_int32_t copy_range)
+static int
+nflog_send_config_mode(const pcap_t *handle, uint16_t group_id, u_int8_t copy_mode, u_int32_t copy_range)
 {
        struct nfulnl_msg_config_mode msg;
        struct my_nfattr nfa;
@@ -358,7 +432,7 @@ nflog_send_config_mode(const pcap_t *handle, u_int16_t group_id, u_int8_t copy_m
 }
 
 static int
-nfqueue_send_verdict(const pcap_t *handle, u_int16_t group_id, u_int32_t id, u_int32_t verdict)
+nfqueue_send_verdict(const pcap_t *handle, uint16_t group_id, u_int32_t id, u_int32_t verdict)
 {
        struct nfqnl_msg_verdict_hdr msg;
        struct my_nfattr nfa;
@@ -374,13 +448,13 @@ nfqueue_send_verdict(const pcap_t *handle, u_int16_t group_id, u_int32_t id, u_i
 }
 
 static int
-nfqueue_send_config_msg(const pcap_t *handle, u_int8_t family, u_int16_t group_id, const struct my_nfattr *mynfa)
+nfqueue_send_config_msg(const pcap_t *handle, uint8_t family, u_int16_t group_id, const struct my_nfattr *mynfa)
 {
        return netfilter_send_config_msg(handle, (NFNL_SUBSYS_QUEUE << 8) | NFQNL_MSG_CONFIG, 1, family, group_id, mynfa);
 }
 
 static int
-nfqueue_send_config_cmd(const pcap_t *handle, u_int16_t group_id, u_int8_t cmd, u_int16_t pf)
+nfqueue_send_config_cmd(const pcap_t *handle, uint16_t group_id, u_int8_t cmd, u_int16_t pf)
 {
        struct nfqnl_msg_config_cmd msg;
        struct my_nfattr nfa;
@@ -395,8 +469,8 @@ 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 
-nfqueue_send_config_mode(const pcap_t *handle, u_int16_t group_id, u_int8_t copy_mode, u_int32_t copy_range)
+static int
+nfqueue_send_config_mode(const pcap_t *handle, uint16_t group_id, u_int8_t copy_mode, u_int32_t copy_range)
 {
        struct nfqnl_msg_config_params msg;
        struct my_nfattr nfa;
@@ -414,7 +488,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 +502,7 @@ netfilter_activate(pcap_t* handle)
                dev += strlen(NFQUEUE_IFACE);
                type = NFQUEUE;
        }
+
        if (type != OTHER && *dev == ':') {
                dev++;
                while (*dev) {
@@ -436,16 +510,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 +535,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;
        }
 
@@ -473,6 +547,17 @@ netfilter_activate(pcap_t* handle)
                group_count = 1;
        }
 
+       /*
+        * Turn a negative snapshot value (invalid), a snapshot value of
+        * 0 (unspecified), or a value bigger than the normal maximum
+        * value, into the maximum allowed value.
+        *
+        * If some application really *needs* a bigger snapshot
+        * length, we should just increase MAXIMUM_SNAPLEN.
+        */
+       if (handle->snapshot <= 0 || handle->snapshot > MAXIMUM_SNAPLEN)
+               handle->snapshot = MAXIMUM_SNAPLEN;
+
        /* Initialize some components of the pcap structure. */
        handle->bufsize = 128 + handle->snapshot;
        handle->offset = 0;
@@ -488,7 +573,8 @@ 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_fmt_errmsg_for_errno(handle->errbuf, PCAP_ERRBUF_SIZE,
+                   errno, "Can't create raw socket");
                return PCAP_ERROR;
        }
 
@@ -506,54 +592,68 @@ 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_fmt_errmsg_for_errno(handle->errbuf, PCAP_ERRBUF_SIZE,
+                   errno, "Can't allocate dump buffer");
                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_fmt_errmsg_for_errno(handle->errbuf,
+                           PCAP_ERRBUF_SIZE, errno,
+                           "NFULNL_CFG_CMD_PF_UNBIND");
                        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_fmt_errmsg_for_errno(handle->errbuf,
+                           PCAP_ERRBUF_SIZE, errno, "NFULNL_CFG_CMD_PF_BIND");
                        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_fmt_errmsg_for_errno(handle->errbuf,
+                                   PCAP_ERRBUF_SIZE, errno,
+                                   "Can't listen on group group index");
                                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_fmt_errmsg_for_errno(handle->errbuf,
+                                   PCAP_ERRBUF_SIZE, errno,
+                                   "NFULNL_COPY_PACKET");
                                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_fmt_errmsg_for_errno(handle->errbuf,
+                           PCAP_ERRBUF_SIZE, errno, "NFQNL_CFG_CMD_PF_UNBIND");
                        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_fmt_errmsg_for_errno(handle->errbuf,
+                           PCAP_ERRBUF_SIZE, errno, "NFQNL_CFG_CMD_PF_BIND");
                        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_fmt_errmsg_for_errno(handle->errbuf,
+                                   PCAP_ERRBUF_SIZE, errno,
+                                   "Can't listen on group group index");
                                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_fmt_errmsg_for_errno(handle->errbuf,
+                                   PCAP_ERRBUF_SIZE, errno,
+                                   "NFQNL_COPY_PACKET");
                                goto close_fail;
                        }
                }
@@ -572,7 +672,8 @@ 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_fmt_errmsg_for_errno(handle->errbuf,
+                           PCAP_ERRBUF_SIZE, errno, "SO_RCVBUF");
                        goto close_fail;
                }
        }
@@ -599,7 +700,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 +721,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,25 +729,33 @@ netfilter_create(const char *device, char *ebuf, int *is_ours)
        return (p);
 }
 
-int 
-netfilter_findalldevs(pcap_if_t **alldevsp, char *err_str)
+int
+netfilter_findalldevs(pcap_if_list_t *devlistp, 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",
-                       errno, pcap_strerror(errno));
+               pcap_fmt_errmsg_for_errno(err_str, PCAP_ERRBUF_SIZE,
+                   errno, "Can't open netlink socket");
                return -1;
        }
        close(sock);
 
-       if (pcap_add_if(alldevsp, NFLOG_IFACE, 0, "Linux netfilter log (NFLOG) interface", err_str) < 0)
+       /*
+        * The notion of "connected" vs. "disconnected" doesn't apply.
+        * XXX - what about "up" and "running"?
+        */
+       if (add_dev(devlistp, NFLOG_IFACE,
+           PCAP_IF_CONNECTION_STATUS_NOT_APPLICABLE,
+           "Linux netfilter log (NFLOG) interface", err_str) == NULL)
                return -1;
-       if (pcap_add_if(alldevsp, NFQUEUE_IFACE, 0, "Linux netfilter queue (NFQUEUE) interface", err_str) < 0)
+       if (add_dev(devlistp, NFQUEUE_IFACE,
+           PCAP_IF_CONNECTION_STATUS_NOT_APPLICABLE,
+           "Linux netfilter queue (NFQUEUE) interface", err_str) == NULL)
                return -1;
        return 0;
 }
index 882a402..97b7310 100644 (file)
@@ -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,5 +31,5 @@
 /*
  * Prototypes for netlink-related functions
  */
-int netfilter_findalldevs(pcap_if_t **alldevsp, char *err_str);
+int netfilter_findalldevs(pcap_if_list_t *devlistp, char *err_str);
 pcap_t *netfilter_create(const char *device, char *ebuf, int *is_ours);
diff --git a/pcap-netmap.c b/pcap-netmap.c
new file mode 100644 (file)
index 0000000..b2301a7
--- /dev/null
@@ -0,0 +1,306 @@
+/*
+ * Copyright (C) 2014 Luigi Rizzo. 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR 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 AUTHOR 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 <poll.h>
+#include <ctype.h>
+#include <errno.h>
+#include <netdb.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+#define NETMAP_WITH_LIBS
+#include <net/netmap_user.h>
+
+#include "pcap-int.h"
+#include "pcap-netmap.h"
+
+#ifndef __FreeBSD__
+  /*
+   * On FreeBSD we use IFF_PPROMISC which is in ifr_flagshigh.
+   * Remap to IFF_PROMISC on other platforms.
+   *
+   * XXX - DragonFly BSD?
+   */
+  #define IFF_PPROMISC IFF_PROMISC
+#endif /* __FreeBSD__ */
+
+struct pcap_netmap {
+       struct nm_desc *d;      /* pointer returned by nm_open() */
+       pcap_handler cb;        /* callback and argument */
+       u_char *cb_arg;
+       int must_clear_promisc; /* flag */
+       uint64_t rx_pkts;       /* # of pkts received before the filter */
+};
+
+
+static int
+pcap_netmap_stats(pcap_t *p, struct pcap_stat *ps)
+{
+       struct pcap_netmap *pn = p->priv;
+
+       ps->ps_recv = (u_int)pn->rx_pkts;
+       ps->ps_drop = 0;
+       ps->ps_ifdrop = 0;
+       return 0;
+}
+
+
+static void
+pcap_netmap_filter(u_char *arg, struct pcap_pkthdr *h, const u_char *buf)
+{
+       pcap_t *p = (pcap_t *)arg;
+       struct pcap_netmap *pn = p->priv;
+       const struct bpf_insn *pc = p->fcode.bf_insns;
+
+       ++pn->rx_pkts;
+       if (pc == NULL || bpf_filter(pc, buf, h->len, h->caplen))
+               pn->cb(pn->cb_arg, h, buf);
+}
+
+
+static int
+pcap_netmap_dispatch(pcap_t *p, int cnt, pcap_handler cb, u_char *user)
+{
+       int ret;
+       struct pcap_netmap *pn = p->priv;
+       struct nm_desc *d = pn->d;
+       struct pollfd pfd = { .fd = p->fd, .events = POLLIN, .revents = 0 };
+
+       pn->cb = cb;
+       pn->cb_arg = user;
+
+       for (;;) {
+               if (p->break_loop) {
+                       p->break_loop = 0;
+                       return PCAP_ERROR_BREAK;
+               }
+               /* nm_dispatch won't run forever */
+
+               ret = nm_dispatch((void *)d, cnt, (void *)pcap_netmap_filter, (void *)p);
+               if (ret != 0)
+                       break;
+               errno = 0;
+               ret = poll(&pfd, 1, p->opt.timeout);
+       }
+       return ret;
+}
+
+
+/* XXX need to check the NIOCTXSYNC/poll */
+static int
+pcap_netmap_inject(pcap_t *p, const void *buf, size_t size)
+{
+       struct pcap_netmap *pn = p->priv;
+       struct nm_desc *d = pn->d;
+
+       return nm_inject(d, buf, size);
+}
+
+
+static int
+pcap_netmap_ioctl(pcap_t *p, u_long what, uint32_t *if_flags)
+{
+       struct pcap_netmap *pn = p->priv;
+       struct nm_desc *d = pn->d;
+       struct ifreq ifr;
+       int error, fd = d->fd;
+
+#ifdef linux
+       fd = socket(AF_INET, SOCK_DGRAM, 0);
+       if (fd < 0) {
+               fprintf(stderr, "Error: cannot get device control socket.\n");
+               return -1;
+       }
+#endif /* linux */
+       bzero(&ifr, sizeof(ifr));
+       strncpy(ifr.ifr_name, d->req.nr_name, sizeof(ifr.ifr_name));
+       switch (what) {
+       case SIOCSIFFLAGS:
+               /*
+                * The flags we pass in are 32-bit and unsigned.
+                *
+                * On most if not all UN*Xes, ifr_flags is 16-bit and
+                * signed, and the result of assigning a longer
+                * unsigned value to a shorter signed value is
+                * implementation-defined (even if, in practice, it'll
+                * do what's intended on all platforms we support
+                * result of assigning a 32-bit unsigned value).
+                * So we mask out the upper 16 bits.
+                */
+               ifr.ifr_flags = *if_flags & 0xffff;
+#ifdef __FreeBSD__
+               /*
+                * In FreeBSD, we need to set the high-order flags,
+                * as we're using IFF_PPROMISC, which is in those bits.
+                *
+                * XXX - DragonFly BSD?
+                */
+               ifr.ifr_flagshigh = *if_flags >> 16;
+#endif /* __FreeBSD__ */
+               break;
+       }
+       error = ioctl(fd, what, &ifr);
+       if (!error) {
+               switch (what) {
+               case SIOCGIFFLAGS:
+                       /*
+                        * The flags we return are 32-bit.
+                        *
+                        * On most if not all UN*Xes, ifr_flags is
+                        * 16-bit and signed, and will get sign-
+                        * extended, so that the upper 16 bits of
+                        * those flags will be forced on.  So we
+                        * mask out the upper 16 bits of the
+                        * sign-extended value.
+                        */
+                       *if_flags = ifr.ifr_flags & 0xffff;
+#ifdef __FreeBSD__
+                       /*
+                        * In FreeBSD, we need to return the
+                        * high-order flags, as we're using
+                        * IFF_PPROMISC, which is in those bits.
+                        *
+                        * XXX - DragonFly BSD?
+                        */
+                       *if_flags |= (ifr.ifr_flagshigh << 16);
+#endif /* __FreeBSD__ */
+               }
+       }
+#ifdef linux
+       close(fd);
+#endif /* linux */
+       return error ? -1 : 0;
+}
+
+
+static void
+pcap_netmap_close(pcap_t *p)
+{
+       struct pcap_netmap *pn = p->priv;
+       struct nm_desc *d = pn->d;
+       uint32_t if_flags = 0;
+
+       if (pn->must_clear_promisc) {
+               pcap_netmap_ioctl(p, SIOCGIFFLAGS, &if_flags); /* fetch flags */
+               if (if_flags & IFF_PPROMISC) {
+                       if_flags &= ~IFF_PPROMISC;
+                       pcap_netmap_ioctl(p, SIOCSIFFLAGS, &if_flags);
+               }
+       }
+       nm_close(d);
+       pcap_cleanup_live_common(p);
+}
+
+
+static int
+pcap_netmap_activate(pcap_t *p)
+{
+       struct pcap_netmap *pn = p->priv;
+       struct nm_desc *d;
+       uint32_t if_flags = 0;
+
+       d = nm_open(p->opt.device, NULL, 0, NULL);
+       if (d == NULL) {
+               pcap_fmt_errmsg_for_errno(p->errbuf, PCAP_ERRBUF_SIZE,
+                   errno, "netmap open: cannot access %s",
+                   p->opt.device);
+               pcap_cleanup_live_common(p);
+               return (PCAP_ERROR);
+       }
+#if 0
+       fprintf(stderr, "%s device %s priv %p fd %d ports %d..%d\n",
+           __FUNCTION__, p->opt.device, d, d->fd,
+           d->first_rx_ring, d->last_rx_ring);
+#endif
+       pn->d = d;
+       p->fd = d->fd;
+
+       /*
+        * Turn a negative snapshot value (invalid), a snapshot value of
+        * 0 (unspecified), or a value bigger than the normal maximum
+        * value, into the maximum allowed value.
+        *
+        * If some application really *needs* a bigger snapshot
+        * length, we should just increase MAXIMUM_SNAPLEN.
+        */
+       if (p->snapshot <= 0 || p->snapshot > MAXIMUM_SNAPLEN)
+               p->snapshot = MAXIMUM_SNAPLEN;
+
+       if (p->opt.promisc && !(d->req.nr_ringid & NETMAP_SW_RING)) {
+               pcap_netmap_ioctl(p, SIOCGIFFLAGS, &if_flags); /* fetch flags */
+               if (!(if_flags & IFF_PPROMISC)) {
+                       pn->must_clear_promisc = 1;
+                       if_flags |= IFF_PPROMISC;
+                       pcap_netmap_ioctl(p, SIOCSIFFLAGS, &if_flags);
+               }
+       }
+       p->linktype = DLT_EN10MB;
+       p->selectable_fd = p->fd;
+       p->read_op = pcap_netmap_dispatch;
+       p->inject_op = pcap_netmap_inject;
+       p->setfilter_op = install_bpf_program;
+       p->setdirection_op = NULL;
+       p->set_datalink_op = NULL;
+       p->getnonblock_op = pcap_getnonblock_fd;
+       p->setnonblock_op = pcap_setnonblock_fd;
+       p->stats_op = pcap_netmap_stats;
+       p->cleanup_op = pcap_netmap_close;
+
+       return (0);
+}
+
+
+pcap_t *
+pcap_netmap_create(const char *device, char *ebuf, int *is_ours)
+{
+       pcap_t *p;
+
+       *is_ours = (!strncmp(device, "netmap:", 7) || !strncmp(device, "vale", 4));
+       if (! *is_ours)
+               return NULL;
+       p = pcap_create_common(ebuf, sizeof (struct pcap_netmap));
+       if (p == NULL)
+               return (NULL);
+       p->activate_op = pcap_netmap_activate;
+       return (p);
+}
+
+/*
+ * The "device name" for netmap devices isn't a name for a device, it's
+ * an expression that indicates how the device should be set up, so
+ * there's no way to enumerate them.
+ */
+int
+pcap_netmap_findalldevs(pcap_if_list_t *devlistp _U_, char *err_str _U_)
+{
+       return 0;
+}
diff --git a/pcap-netmap.h b/pcap-netmap.h
new file mode 100644 (file)
index 0000000..6a414fc
--- /dev/null
@@ -0,0 +1,2 @@
+pcap_t *pcap_netmap_create(const char *, char *, int *);
+int pcap_netmap_findalldevs(pcap_if_list_t *devlistp, char *errbuf);
diff --git a/pcap-new.c b/pcap-new.c
new file mode 100644 (file)
index 0000000..e61cf6a
--- /dev/null
@@ -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.
+ *
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include "ftmacros.h"
+
+/*
+ * sockutils.h may include <crtdbg.h> on Windows, and pcap-int.h will
+ * include portability.h, and portability.h, on Windows, expects that
+ * <crtdbg.h> has already been included, so include sockutils.h first.
+ */
+#include "sockutils.h"
+#include "pcap-int.h"  // for the details of the pcap_t structure
+#include "pcap-rpcap.h"
+#include "rpcap-protocol.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
+
+/* String identifier to be used in the pcap_findalldevs_ex() */
+#define PCAP_TEXT_SOURCE_FILE "File"
+#define PCAP_TEXT_SOURCE_FILE_LEN (sizeof PCAP_TEXT_SOURCE_FILE - 1)
+/* String identifier to be used in the pcap_findalldevs_ex() */
+#define PCAP_TEXT_SOURCE_ADAPTER "Network adapter"
+#define PCAP_TEXT_SOURCE_ADAPTER_LEN (sizeof "Network adapter" - 1)
+
+/* String identifier to be used in the pcap_findalldevs_ex() */
+#define PCAP_TEXT_SOURCE_ON_LOCAL_HOST "on local host"
+#define PCAP_TEXT_SOURCE_ON_LOCAL_HOST_LEN (sizeof PCAP_TEXT_SOURCE_ON_LOCAL_HOST + 1)
+
+/****************************************************
+ *                                                  *
+ * Function bodies                                  *
+ *                                                  *
+ ****************************************************/
+
+int pcap_findalldevs_ex(const char *source, struct pcap_rmtauth *auth, pcap_if_t **alldevs, char *errbuf)
+{
+       int type;
+       char name[PCAP_BUF_SIZE], path[PCAP_BUF_SIZE], filename[PCAP_BUF_SIZE];
+       size_t pathlen;
+       size_t stringlen;
+       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 *lastdev;     /* Last device in the pcap_if_t list */
+       pcap_if_t *dev;         /* Device we're adding to the pcap_if_t list */
+
+       /* List starts out empty. */
+       (*alldevs) = NULL;
+       lastdev = NULL;
+
+       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;
+
+       switch (type)
+       {
+       case PCAP_SRC_IFLOCAL:
+               if (pcap_parsesrcstr(source, &type, NULL, 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)
+               {
+                       pcap_snprintf(errbuf, PCAP_ERRBUF_SIZE,
+                               "No interfaces found! Make sure libpcap/Npcap 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)
+               {
+                       char *localdesc, *desc;
+
+                       /* 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_fmt_errmsg_for_errno(errbuf,
+                                   PCAP_ERRBUF_SIZE, errno,
+                                   "malloc() failed");
+                               pcap_freealldevs(*alldevs);
+                               return -1;
+                       }
+
+                       /*
+                        * Create the description.
+                        */
+                       if ((dev->description == NULL) || (dev->description[0] == 0))
+                               localdesc = dev->name;
+                       else
+                               localdesc = dev->description;
+                       if (pcap_asprintf(&desc, "%s '%s' %s",
+                           PCAP_TEXT_SOURCE_ADAPTER, localdesc,
+                           PCAP_TEXT_SOURCE_ON_LOCAL_HOST) == -1)
+                       {
+                               pcap_fmt_errmsg_for_errno(errbuf,
+                                   PCAP_ERRBUF_SIZE, errno,
+                                   "malloc() failed");
+                               pcap_freealldevs(*alldevs);
+                               return -1;
+                       }
+
+                       /* Now overwrite the description */
+                       free(dev->description);
+                       dev->description = desc;
+
+                       dev = dev->next;
+               }
+
+               return 0;
+
+       case PCAP_SRC_FILE:
+       {
+#ifdef _WIN32
+               WIN32_FIND_DATA filedata;
+               HANDLE filehandle;
+#else
+               struct dirent *filedata;
+               DIR *unixdir;
+#endif
+
+               if (pcap_parsesrcstr(source, &type, NULL, NULL, 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);
+               pathlen = strlen(path);
+
+#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
+
+               /* Add all files we find to the list. */
+               do
+               {
+#ifdef _WIN32
+                       /* Skip the file if the pathname won't fit in the buffer */
+                       if (pathlen + strlen(filedata.cFileName) >= sizeof(filename))
+                               continue;
+                       pcap_snprintf(filename, sizeof(filename), "%s%s", path, filedata.cFileName);
+#else
+                       if (pathlen + strlen(filedata->d_name) >= sizeof(filename))
+                               continue;
+                       pcap_snprintf(filename, sizeof(filename), "%s%s", path, filedata->d_name);
+#endif
+
+                       fp = pcap_open_offline(filename, errbuf);
+
+                       if (fp)
+                       {
+                               /* allocate the main structure */
+                               dev = (pcap_if_t *)malloc(sizeof(pcap_if_t));
+                               if (dev == NULL)
+                               {
+                                       pcap_fmt_errmsg_for_errno(errbuf,
+                                           PCAP_ERRBUF_SIZE, errno,
+                                           "malloc() failed");
+                                       pcap_freealldevs(*alldevs);
+                                       return -1;
+                               }
+
+                               /* Initialize the structure to 'zero' */
+                               memset(dev, 0, sizeof(pcap_if_t));
+
+                               /* Append it to the list. */
+                               if (lastdev == NULL)
+                               {
+                                       /*
+                                        * List is empty, so it's also
+                                        * the first device.
+                                        */
+                                       *alldevs = dev;
+                               }
+                               else
+                               {
+                                       /*
+                                        * Append after the last device.
+                                        */
+                                       lastdev->next = dev;
+                               }
+                               /* It's now the last device. */
+                               lastdev = dev;
+
+                               /* Create the new source identifier */
+                               if (pcap_createsrcstr(tmpstring, PCAP_SRC_FILE, NULL, NULL, filename, errbuf) == -1)
+                               {
+                                       pcap_freealldevs(*alldevs);
+                                       return -1;
+                               }
+
+                               dev->name = strdup(tmpstring);
+                               if (dev->name == NULL)
+                               {
+                                       pcap_fmt_errmsg_for_errno(errbuf,
+                                           PCAP_ERRBUF_SIZE, errno,
+                                           "malloc() failed");
+                                       pcap_freealldevs(*alldevs);
+                                       return -1;
+                               }
+
+                               /*
+                                * Create the description.
+                                */
+                               if (pcap_asprintf(&dev->description,
+                                   "%s '%s' %s", PCAP_TEXT_SOURCE_FILE,
+                                   filename, PCAP_TEXT_SOURCE_ON_LOCAL_HOST) == -1)
+                               {
+                                       pcap_fmt_errmsg_for_errno(errbuf,
+                                           PCAP_ERRBUF_SIZE, errno,
+                                           "malloc() failed");
+                                       pcap_freealldevs(*alldevs);
+                                       return -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;
+       }
+
+       case PCAP_SRC_IFREMOTE:
+               return pcap_findalldevs_ex_remote(source, auth, alldevs, errbuf);
+
+       default:
+               pcap_strlcpy(errbuf, "Source type not supported", PCAP_ERRBUF_SIZE);
+               return -1;
+       }
+}
+
+pcap_t *pcap_open(const char *source, int snaplen, int flags, int read_timeout, struct pcap_rmtauth *auth, char *errbuf)
+{
+       char name[PCAP_BUF_SIZE];
+       int type;
+       pcap_t *fp;
+       int status;
+
+       /*
+        * 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 (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) and,
+        * if it's file or local, the name of the file or capture device.
+        */
+       if (pcap_parsesrcstr(source, &type, NULL, NULL, name, errbuf) == -1)
+               return NULL;
+
+       switch (type)
+       {
+       case PCAP_SRC_FILE:
+               return pcap_open_offline(name, errbuf);
+
+       case PCAP_SRC_IFLOCAL:
+               fp = pcap_create(name, errbuf);
+               break;
+
+       case PCAP_SRC_IFREMOTE:
+               /*
+                * Although we already have host, port and iface, we prefer
+                * to pass only 'source' to pcap_open_rpcap(), so that it
+                * has to call pcap_parsesrcstr() again.
+                * This is less optimized, but much clearer.
+                */
+               return pcap_open_rpcap(source, snaplen, flags, read_timeout, auth, errbuf);
+
+       default:
+               pcap_strlcpy(errbuf, "Source type not supported", PCAP_ERRBUF_SIZE);
+               return NULL;
+       }
+
+       if (fp == NULL)
+               return (NULL);
+       status = pcap_set_snaplen(fp, snaplen);
+       if (status < 0)
+               goto fail;
+       if (flags & PCAP_OPENFLAG_PROMISCUOUS)
+       {
+               status = pcap_set_promisc(fp, 1);
+               if (status < 0)
+                       goto fail;
+       }
+       if (flags & PCAP_OPENFLAG_MAX_RESPONSIVENESS)
+       {
+               status = pcap_set_immediate_mode(fp, 1);
+               if (status < 0)
+                       goto fail;
+       }
+#ifdef _WIN32
+       /*
+        * This flag is supported on Windows only.
+        * XXX - is there a way to support it with
+        * the capture mechanisms on UN*X?  It's not
+        * exactly a "set direction" operation; I
+        * think it means "do not capture packets
+        * injected with pcap_sendpacket() or
+        * pcap_inject()".
+        */
+       /* disable loopback capture if requested */
+       if (flags & PCAP_OPENFLAG_NOCAPTURE_LOCAL)
+               fp->opt.nocapture_local = 1;
+#endif /* _WIN32 */
+       status = pcap_set_timeout(fp, read_timeout);
+       if (status < 0)
+               goto fail;
+       status = pcap_activate(fp);
+       if (status < 0)
+               goto fail;
+       return fp;
+
+fail:
+       if (status == PCAP_ERROR)
+               pcap_snprintf(errbuf, PCAP_ERRBUF_SIZE, "%s: %s",
+                   name, fp->errbuf);
+       else if (status == PCAP_ERROR_NO_SUCH_DEVICE ||
+           status == PCAP_ERROR_PERM_DENIED ||
+           status == PCAP_ERROR_PROMISC_PERM_DENIED)
+               pcap_snprintf(errbuf, PCAP_ERRBUF_SIZE, "%s: %s (%s)",
+                   name, pcap_statustostr(status), fp->errbuf);
+       else
+               pcap_snprintf(errbuf, PCAP_ERRBUF_SIZE, "%s: %s",
+                   name, pcap_statustostr(status));
+       pcap_close(fp);
+       return NULL;
+}
+
+struct pcap_samp *pcap_setsampling(pcap_t *p)
+{
+       return &p->rmt_samp;
+}
index ea81eb5..6a1a77c 100644 (file)
@@ -20,7 +20,7 @@
  */
 
 #ifdef HAVE_CONFIG_H
-#include "config.h"
+#include <config.h>
 #endif
 
 #include <sys/types.h>
@@ -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_strerror(errno));
+                       pcap_fmt_errmsg_for_errno(p->errbuf, sizeof(p->errbuf),
+                           errno, "pcap_read");
                        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_strerror(errno));
+               pcap_fmt_errmsg_for_errno(p->errbuf, PCAP_ERRBUF_SIZE,
+                   errno, "send");
                return (-1);
        }
        return (ret);
-}                           
+}
 
 static int
 nit_setflags(pcap_t *p)
@@ -249,8 +249,8 @@ 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_strerror(errno));
+               pcap_fmt_errmsg_for_errno(p->errbuf, PCAP_ERRBUF_SIZE,
+                   errno, "SIOCSNIT");
                return (-1);
        }
        return (0);
@@ -271,6 +271,17 @@ pcap_activate_nit(pcap_t *p)
                return (PCAP_ERROR_RFMON_NOTSUP);
        }
 
+       /*
+        * Turn a negative snapshot value (invalid), a snapshot value of
+        * 0 (unspecified), or a value bigger than the normal maximum
+        * value, into the maximum allowed value.
+        *
+        * If some application really *needs* a bigger snapshot
+        * length, we should just increase MAXIMUM_SNAPLEN.
+        */
+       if (p->snapshot <= 0 || p->snapshot > MAXIMUM_SNAPLEN)
+               p->snapshot = MAXIMUM_SNAPLEN;
+
        if (p->snapshot < 96)
                /*
                 * NIT requires a snapshot length of at least 96.
@@ -280,16 +291,23 @@ 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,
-                   "socket: %s", pcap_strerror(errno));
+               pcap_fmt_errmsg_for_errno(p->errbuf, PCAP_ERRBUF_SIZE,
+                   errno, "socket");
                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,
-                   "bind: %s: %s", snit.snit_ifname, pcap_strerror(errno));
+               /*
+                * 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_fmt_errmsg_for_errno(p->errbuf, PCAP_ERRBUF_SIZE,
+                   errno, "bind: %s", snit.snit_ifname);
                goto bad;
        }
        if (nit_setflags(p) < 0)
@@ -301,9 +319,10 @@ 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);
+               pcap_fmt_errmsg_for_errno(p->errbuf, PCAP_ERRBUF_SIZE,
+                   errno, "malloc");
                goto bad;
        }
 
@@ -348,11 +367,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 +379,39 @@ pcap_create_interface(const char *device, char *ebuf)
        return (p);
 }
 
-int
-pcap_platform_finddevs(pcap_if_t **alldevsp, char *errbuf)
+/*
+ * 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);
+}
+
+static int
+get_if_flags(const char *name _U_, bpf_u_int32 *flags _U_, char *errbuf _U_)
 {
+       /*
+        * Nothing we can do.
+        * XXX - is there a way to find out whether an adapter has
+        * something plugged into it?
+        */
        return (0);
 }
+
+int
+pcap_platform_finddevs(pcap_if_list_t *devlistp, char *errbuf)
+{
+       return (pcap_findalldevs_interfaces(devlistp, errbuf, can_be_bound,
+           get_if_flags));
+}
+
+/*
+ * Libpcap version string.
+ */
+const char *
+pcap_lib_version(void)
+{
+       return (PCAP_VERSION_STRING);
+}
diff --git a/pcap-npf.c b/pcap-npf.c
new file mode 100644 (file)
index 0000000..da4641f
--- /dev/null
@@ -0,0 +1,2114 @@
+/*
+ * Copyright (c) 1999 - 2005 NetGroup, Politecnico di Torino (Italy)
+ * Copyright (c) 2005 - 2010 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 <errno.h>
+#define PCAP_DONT_INCLUDE_PCAP_BPF_H
+#include <Packet32.h>
+#include <pcap-int.h>
+#include <pcap/dlt.h>
+
+/* Old-school MinGW have these headers in a different place.
+ */
+#if defined(__MINGW32__) && !defined(__MINGW64_VERSION_MAJOR)
+  #include <ddk/ntddndis.h>
+  #include <ddk/ndis.h>
+#else
+  #include <ntddndis.h>  /* MSVC/TDM-MinGW/MinGW64 */
+#endif
+
+#ifdef HAVE_DAG_API
+  #include <dagnew.h>
+  #include <dagapi.h>
+#endif /* HAVE_DAG_API */
+
+static int pcap_setfilter_npf(pcap_t *, struct bpf_program *);
+static int pcap_setfilter_win32_dag(pcap_t *, struct bpf_program *);
+static int pcap_getnonblock_npf(pcap_t *);
+static int pcap_setnonblock_npf(pcap_t *, int);
+
+/*dimension of the buffer in the pcap_t structure*/
+#define        WIN32_DEFAULT_USER_BUFFER_SIZE 256000
+
+/*dimension of the buffer in the kernel driver NPF */
+#define        WIN32_DEFAULT_KERNEL_BUFFER_SIZE 1000000
+
+/* Equivalent to ntohs(), but a lot faster under Windows */
+#define SWAPS(_X) ((_X & 0xff) << 8) | (_X >> 8)
+
+/*
+ * Private data for capturing on WinPcap/Npcap devices.
+ */
+struct pcap_win {
+       ADAPTER *adapter;               /* the packet32 ADAPTER for the device */
+       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
+
+#ifdef ENABLE_REMOTE
+       int samp_npkt;                  /* parameter needed for sampling, with '1 out of N' method has been requested */
+       struct timeval samp_time;       /* parameter needed for sampling, with '1 every N ms' method has been requested */
+#endif
+};
+
+/*
+ * 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);
+}
+
+static int
+PacketGetMonitorMode(PCHAR AdapterName _U_)
+{
+       /*
+        * This should fail, so that pcap_activate_npf() returns
+        * PCAP_ERROR_RFMON_NOTSUP if our caller requested monitor
+        * mode.
+        */
+       return (-1);
+}
+#endif
+
+/*
+ * Sigh.  PacketRequest() will have made a DeviceIoControl()
+ * call to the NPF driver to perform the OID request, with a
+ * BIOCQUERYOID ioctl.  The kernel code should get back one
+ * of NDIS_STATUS_INVALID_OID, NDIS_STATUS_NOT_SUPPORTED,
+ * or NDIS_STATUS_NOT_RECOGNIZED if the OID request isn't
+ * supported by the OS or the driver, but that doesn't seem
+ * to make it to the caller of PacketRequest() in a
+ * reliable fashion.
+ */
+#define NDIS_STATUS_INVALID_OID                0xc0010017
+#define NDIS_STATUS_NOT_SUPPORTED      0xc00000bb      /* STATUS_NOT_SUPPORTED */
+#define NDIS_STATUS_NOT_RECOGNIZED     0x00010001
+
+static int
+oid_get_request(ADAPTER *adapter, bpf_u_int32 oid, void *data, size_t *lenp,
+    char *errbuf)
+{
+       PACKET_OID_DATA *oid_data_arg;
+
+       /*
+        * 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(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(adapter, FALSE, oid_data_arg)) {
+               pcap_fmt_errmsg_for_win32_err(errbuf, PCAP_ERRBUF_SIZE,
+                   GetLastError(), "Error calling PacketRequest");
+               free(oid_data_arg);
+               return (-1);
+       }
+
+       /*
+        * 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_stats_npf(pcap_t *p, struct pcap_stat *ps)
+{
+       struct pcap_win *pw = p->priv;
+       struct bpf_stat bstats;
+
+       /*
+        * 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(pw->adapter, &bstats)) {
+               pcap_fmt_errmsg_for_win32_err(p->errbuf, PCAP_ERRBUF_SIZE,
+                   GetLastError(), "PacketGetStats error");
+               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);
+}
+
+/*
+ * 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_npf(pcap_t *p, int *pcap_stat_size)
+{
+       struct pcap_win *pw = p->priv;
+       struct bpf_stat bstats;
+
+       *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(pw->adapter, &bstats)) {
+               pcap_fmt_errmsg_for_win32_err(p->errbuf, PCAP_ERRBUF_SIZE,
+                   GetLastError(), "PacketGetStatsEx error");
+               return (NULL);
+       }
+       p->stat.ps_recv = bstats.bs_recv;
+       p->stat.ps_drop = bstats.bs_drop;
+       p->stat.ps_ifdrop = bstats.ps_ifdrop;
+#ifdef ENABLE_REMOTE
+       p->stat.ps_capt = bstats.bs_capt;
+#endif
+       return (&p->stat);
+}
+
+/* Set the dimension of the kernel-level capture buffer */
+static int
+pcap_setbuff_npf(pcap_t *p, int dim)
+{
+       struct pcap_win *pw = p->priv;
+
+       if(PacketSetBuff(pw->adapter,dim)==FALSE)
+       {
+               pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "driver error: not enough memory to allocate the kernel buffer");
+               return (-1);
+       }
+       return (0);
+}
+
+/* Set the driver working mode */
+static int
+pcap_setmode_npf(pcap_t *p, int mode)
+{
+       struct pcap_win *pw = p->priv;
+
+       if(PacketSetMode(pw->adapter,mode)==FALSE)
+       {
+               pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "driver error: working mode not recognized");
+               return (-1);
+       }
+
+       return (0);
+}
+
+/*set the minimum amount of data that will release a read call*/
+static int
+pcap_setmintocopy_npf(pcap_t *p, int size)
+{
+       struct pcap_win *pw = p->priv;
+
+       if(PacketSetMinToCopy(pw->adapter, size)==FALSE)
+       {
+               pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "driver error: unable to set the requested mintocopy size");
+               return (-1);
+       }
+       return (0);
+}
+
+static HANDLE
+pcap_getevent_npf(pcap_t *p)
+{
+       struct pcap_win *pw = p->priv;
+
+       return (PacketGetReadEvent(pw->adapter));
+}
+
+static int
+pcap_oid_get_request_npf(pcap_t *p, bpf_u_int32 oid, void *data, size_t *lenp)
+{
+       struct pcap_win *pw = p->priv;
+
+       return (oid_get_request(pw->adapter, oid, data, lenp, p->errbuf));
+}
+
+static int
+pcap_oid_set_request_npf(pcap_t *p, bpf_u_int32 oid, const void *data,
+    size_t *lenp)
+{
+       struct pcap_win *pw = p->priv;
+       PACKET_OID_DATA *oid_data_arg;
+
+       /*
+        * 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(pw->adapter, TRUE, oid_data_arg)) {
+               pcap_fmt_errmsg_for_win32_err(p->errbuf, PCAP_ERRBUF_SIZE,
+                   GetLastError(), "Error calling PacketRequest");
+               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_npf(pcap_t *p, pcap_send_queue *queue, int sync)
+{
+       struct pcap_win *pw = p->priv;
+       u_int res;
+
+       if (pw->adapter==NULL) {
+               pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
+                   "Cannot transmit a queue to an offline capture or to a TurboCap port");
+               return (0);
+       }
+
+       res = PacketSendPackets(pw->adapter,
+               queue->buffer,
+               queue->len,
+               (BOOLEAN)sync);
+
+       if(res != queue->len){
+               pcap_fmt_errmsg_for_win32_err(p->errbuf, PCAP_ERRBUF_SIZE,
+                   GetLastError(), "Error opening adapter");
+       }
+
+       return (res);
+}
+
+static int
+pcap_setuserbuffer_npf(pcap_t *p, int size)
+{
+       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_npf(pcap_t *p, char *filename, int maxsize, int maxpacks)
+{
+       struct pcap_win *pw = p->priv;
+       BOOLEAN res;
+
+       /* Set the packet driver in dump mode */
+       res = PacketSetMode(pw->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(pw->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(pw->adapter, maxsize, maxpacks);
+       if(res == FALSE) {
+               pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
+                               "Error setting dump limit");
+               return (-1);
+       }
+
+       return (0);
+}
+
+static int
+pcap_live_dump_ended_npf(pcap_t *p, int sync)
+{
+       struct pcap_win *pw = p->priv;
+
+       return (PacketIsDumpEnded(pw->adapter, (BOOLEAN)sync));
+}
+
+static PAirpcapHandle
+pcap_get_airpcap_handle_npf(pcap_t *p)
+{
+#ifdef HAVE_AIRPCAP_API
+       struct pcap_win *pw = p->priv;
+
+       return (PacketGetAirPcapHandle(pw->adapter));
+#else
+       return (NULL);
+#endif /* HAVE_AIRPCAP_API */
+}
+
+static int
+pcap_read_npf(pcap_t *p, int cnt, pcap_handler callback, u_char *user)
+{
+       PACKET Packet;
+       int cc;
+       int n = 0;
+       register u_char *bp, *ep;
+       u_char *datap;
+       struct pcap_win *pw = p->priv;
+
+       cc = p->cc;
+       if (p->cc == 0) {
+               /*
+                * Has "pcap_breakloop()" been called?
+                */
+               if (p->break_loop) {
+                       /*
+                        * Yes - clear the flag that indicates that it
+                        * has, and return PCAP_ERROR_BREAK to indicate
+                        * that we were told to break out of the loop.
+                        */
+                       p->break_loop = 0;
+                       return (PCAP_ERROR_BREAK);
+               }
+
+               /*
+                * 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(pw->adapter, &Packet, TRUE)) {
+                       /*
+                        * Did the device go away?
+                        * If so, the error we get is ERROR_GEN_FAILURE.
+                        */
+                       DWORD errcode = GetLastError();
+
+                       if (errcode == ERROR_GEN_FAILURE) {
+                               /*
+                                * The device on which we're capturing
+                                * went away, or it became unusable
+                                * by NPF due to a suspend/resume.
+                                *
+                                * XXX - hopefully no other error
+                                * conditions are indicated by this.
+                                *
+                                * XXX - we really should return an
+                                * appropriate error for that, but
+                                * pcap_dispatch() etc. aren't
+                                * documented as having error returns
+                                * other than PCAP_ERROR or PCAP_ERROR_BREAK.
+                                */
+                               pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
+                                   "The interface disappeared");
+                       } else {
+                               pcap_fmt_errmsg_for_win32_err(p->errbuf,
+                                   PCAP_ERRBUF_SIZE, errcode,
+                                   "PacketReceivePacket error");
+                       }
+                       return (PCAP_ERROR);
+               }
+
+               cc = Packet.ulBytesReceived;
+
+               bp = p->buffer;
+       }
+       else
+               bp = p->bp;
+
+       /*
+        * Loop through each packet.
+        */
+#define bhp ((struct bpf_hdr *)bp)
+       ep = bp + cc;
+       for (;;) {
+               register int caplen, hdrlen;
+
+               /*
+                * Has "pcap_breakloop()" been called?
+                * If so, return immediately - if we haven't read any
+                * packets, clear the flag and return PCAP_ERROR_BREAK
+                * 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 (PCAP_ERROR_BREAK);
+                       } else {
+                               p->bp = bp;
+                               p->cc = (int) (ep - bp);
+                               return (n);
+                       }
+               }
+               if (bp >= ep)
+                       break;
+
+               caplen = bhp->bh_caplen;
+               hdrlen = bhp->bh_hdrlen;
+               datap = bp + hdrlen;
+
+               /*
+                * Short-circuit evaluation: if using BPF filter
+                * in kernel, no need to do it now - we already know
+                * the packet passed the filter.
+                *
+                * XXX - bpf_filter() should always return TRUE if
+                * handed a null pointer for the program, but it might
+                * just try to "run" the filter, so we check here.
+                */
+               if (pw->filtering_in_kernel ||
+                   p->fcode.bf_insns == NULL ||
+                   bpf_filter(p->fcode.bf_insns, datap, bhp->bh_datalen, caplen)) {
+#ifdef ENABLE_REMOTE
+                       switch (p->rmt_samp.method) {
+
+                       case PCAP_SAMP_1_EVERY_N:
+                               pw->samp_npkt = (pw->samp_npkt + 1) % p->rmt_samp.value;
+
+                               /* Discard all packets that are not '1 out of N' */
+                               if (pw->samp_npkt != 0) {
+                                       bp += Packet_WORDALIGN(caplen + hdrlen);
+                                       continue;
+                               }
+                               break;
+
+                       case PCAP_SAMP_FIRST_AFTER_N_MS:
+                           {
+                               struct pcap_pkthdr *pkt_header = (struct pcap_pkthdr*) bp;
+
+                               /*
+                                * Check if the timestamp of the arrived
+                                * packet is smaller than our target time.
+                                */
+                               if (pkt_header->ts.tv_sec < pw->samp_time.tv_sec ||
+                                  (pkt_header->ts.tv_sec == pw->samp_time.tv_sec && pkt_header->ts.tv_usec < pw->samp_time.tv_usec)) {
+                                       bp += Packet_WORDALIGN(caplen + hdrlen);
+                                       continue;
+                               }
+
+                               /*
+                                * The arrived packet is suitable for being
+                                * delivered to our caller, so let's update
+                                * the target time.
+                                */
+                               pw->samp_time.tv_usec = pkt_header->ts.tv_usec + p->rmt_samp.value * 1000;
+                               if (pw->samp_time.tv_usec > 1000000) {
+                                       pw->samp_time.tv_sec = pkt_header->ts.tv_sec + pw->samp_time.tv_usec / 1000000;
+                                       pw->samp_time.tv_usec = pw->samp_time.tv_usec % 1000000;
+                               }
+                           }
+                       }
+#endif /* ENABLE_REMOTE */
+
+                       /*
+                        * XXX A bpf_hdr matches a pcap_pkthdr.
+                        */
+                       (*callback)(user, (struct pcap_pkthdr*)bp, datap);
+                       bp += Packet_WORDALIGN(caplen + hdrlen);
+                       if (++n >= cnt && !PACKET_COUNT_IS_UNLIMITED(cnt)) {
+                               p->bp = bp;
+                               p->cc = (int) (ep - bp);
+                               return (n);
+                       }
+               } else {
+                       /*
+                        * Skip this packet.
+                        */
+                       bp += Packet_WORDALIGN(caplen + hdrlen);
+               }
+       }
+#undef bhp
+       p->cc = 0;
+       return (n);
+}
+
+#ifdef HAVE_DAG_API
+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;
+       u_char *endofbuf;
+       int n = 0;
+       dag_record_t *header;
+       unsigned erf_record_len;
+       ULONGLONG ts;
+       int cc;
+       unsigned swt;
+       unsigned dfp = pw->adapter->DagFastProcess;
+
+       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.
+                *
+                * 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(pw->adapter, &Packet, TRUE)) {
+                       pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "read error: PacketReceivePacket failed");
+                       return (-1);
+               }
+
+               cc = Packet.ulBytesReceived;
+               if(cc == 0)
+                       /* The timeout has expired but we no packets arrived */
+                       return (0);
+               header = (dag_record_t*)pw->adapter->DagBuffer;
+       }
+       else
+               header = (dag_record_t*)p->bp;
+
+       endofbuf = (char*)header + cc;
+
+       /*
+        * Cycle through the packets
+        */
+       do
+       {
+               erf_record_len = SWAPS(header->rlen);
+               if((char*)header + erf_record_len > endofbuf)
+                       break;
+
+               /* Increase the number of captured packets */
+               p->stat.ps_recv++;
+
+               /* Find the beginning of the packet */
+               dp = ((u_char *)header) + dag_record_size;
+
+               /* Determine actual packet len */
+               switch(header->type)
+               {
+               case TYPE_ATM:
+                       packet_len = ATM_SNAPLEN;
+                       caplen = ATM_SNAPLEN;
+                       dp += 4;
+
+                       break;
+
+               case TYPE_ETH:
+                       swt = SWAPS(header->wlen);
+                       packet_len = swt - (pw->dag_fcs_bits);
+                       caplen = erf_record_len - dag_record_size - 2;
+                       if (caplen > packet_len)
+                       {
+                               caplen = packet_len;
+                       }
+                       dp += 2;
+
+                       break;
+
+               case TYPE_HDLC_POS:
+                       swt = SWAPS(header->wlen);
+                       packet_len = swt - (pw->dag_fcs_bits);
+                       caplen = erf_record_len - dag_record_size;
+                       if (caplen > packet_len)
+                       {
+                               caplen = packet_len;
+                       }
+
+                       break;
+               }
+
+               if(caplen > p->snapshot)
+                       caplen = p->snapshot;
+
+               /*
+                * 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
+                       {
+                               p->bp = (char*)header;
+                               p->cc = endofbuf - (char*)header;
+                               return (n);
+                       }
+               }
+
+               if(!dfp)
+               {
+                       /* convert between timestamp formats */
+                       ts = header->ts;
+                       pcap_header.ts.tv_sec = (int)(ts >> 32);
+                       ts = (ts & 0xffffffffi64) * 1000000;
+                       ts += 0x80000000; /* rounding */
+                       pcap_header.ts.tv_usec = (int)(ts >> 32);
+                       if (pcap_header.ts.tv_usec >= 1000000) {
+                               pcap_header.ts.tv_usec -= 1000000;
+                               pcap_header.ts.tv_sec++;
+                       }
+               }
+
+               /* No underlaying filtering system. We need to filter on our own */
+               if (p->fcode.bf_insns)
+               {
+                       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))
+               {
+                       p->bp = (char*)header;
+                       p->cc = endofbuf - (char*)header;
+                       return (n);
+               }
+       }
+       while((u_char*)header < endofbuf);
+
+       return (1);
+}
+#endif /* HAVE_DAG_API */
+
+/* Send a packet to the network */
+static int
+pcap_inject_npf(pcap_t *p, const void *buf, size_t size)
+{
+       struct pcap_win *pw = p->priv;
+       PACKET pkt;
+
+       PacketInitPacket(&pkt, (PVOID)buf, size);
+       if(PacketSendPacket(pw->adapter,&pkt,TRUE) == FALSE) {
+               pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "send error: PacketSendPacket failed");
+               return (-1);
+       }
+
+       /*
+        * We assume it all got sent if "PacketSendPacket()" succeeded.
+        * "pcap_inject()" is expected to return the number of bytes
+        * sent.
+        */
+       return ((int)size);
+}
+
+static void
+pcap_cleanup_npf(pcap_t *p)
+{
+       struct pcap_win *pw = p->priv;
+
+       if (pw->adapter != NULL) {
+               PacketCloseAdapter(pw->adapter);
+               pw->adapter = NULL;
+       }
+       if (pw->rfmon_selfstart)
+       {
+               PacketSetMonitorMode(p->opt.device, 0);
+       }
+       pcap_cleanup_live_common(p);
+}
+
+static int
+pcap_activate_npf(pcap_t *p)
+{
+       struct pcap_win *pw = p->priv;
+       NetType type;
+       int res;
+       int status = 0;
+
+       if (p->opt.rfmon) {
+               /*
+                * Monitor mode is supported on Windows Vista and later.
+                */
+               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 */
+       pcap_wsockinit();
+
+       pw->adapter = PacketOpenAdapter(p->opt.device);
+
+       if (pw->adapter == NULL)
+       {
+               DWORD errcode = GetLastError();
+
+               /*
+                * What error did we get when trying to open the adapter?
+                */
+               if (errcode == ERROR_BAD_UNIT) {
+                       /*
+                        * There's no such device.
+                        */
+                       return (PCAP_ERROR_NO_SUCH_DEVICE);
+               } else {
+                       /*
+                        * Unknown - report details.
+                        */
+                       pcap_fmt_errmsg_for_win32_err(p->errbuf, PCAP_ERRBUF_SIZE,
+                           errcode, "Error opening adapter");
+                       if (pw->rfmon_selfstart)
+                       {
+                               PacketSetMonitorMode(p->opt.device, 0);
+                       }
+                       return (PCAP_ERROR);
+               }
+       }
+
+       /*get network type*/
+       if(PacketGetNetType (pw->adapter,&type) == FALSE)
+       {
+               pcap_fmt_errmsg_for_win32_err(p->errbuf, PCAP_ERRBUF_SIZE,
+                   GetLastError(), "Cannot determine the network type");
+               goto bad;
+       }
+
+       /*Set the linktype*/
+       switch (type.LinkType)
+       {
+       case NdisMediumWan:
+               p->linktype = DLT_EN10MB;
+               break;
+
+       case NdisMedium802_3:
+               p->linktype = DLT_EN10MB;
+               /*
+                * This is (presumably) a real Ethernet capture; give it a
+                * link-layer-type list with DLT_EN10MB and DLT_DOCSIS, so
+                * that an application can let you choose it, in case you're
+                * capturing DOCSIS traffic that a Cisco Cable Modem
+                * Termination System is putting out onto an Ethernet (it
+                * doesn't put an Ethernet header onto the wire, it puts raw
+                * DOCSIS frames out on the wire inside the low-level
+                * Ethernet framing).
+                */
+               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_DOCSIS;
+                       p->dlt_count = 2;
+               }
+               break;
+
+       case NdisMediumFddi:
+               p->linktype = DLT_FDDI;
+               break;
+
+       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;
+
+       case NdisMediumPPPSerial:
+               p->linktype = DLT_PPP_SERIAL;
+               break;
+
+       case NdisMediumNull:
+               p->linktype = DLT_NULL;
+               break;
+
+       case NdisMediumBare80211:
+               p->linktype = DLT_IEEE802_11;
+               break;
+
+       case NdisMediumRadio80211:
+               p->linktype = DLT_IEEE802_11_RADIO;
+               break;
+
+       case NdisMediumPpi:
+               p->linktype = DLT_PPI;
+               break;
+
+#ifdef NdisMediumWirelessWan
+       case NdisMediumWirelessWan:
+               p->linktype = DLT_RAW;
+               break;
+#endif
+
+       default:
+               /*
+                * An unknown medium type is assumed to supply Ethernet
+                * headers; if not, the user will have to report it,
+                * so that the medium type and link-layer header type
+                * can be determined.  If we were to fail here, we
+                * might get the link-layer type in the error, but
+                * the user wouldn't get a capture, so we wouldn't
+                * be able to determine the link-layer type; we report
+                * a warning with the link-layer type, so at least
+                * some programs will report the warning.
+                */
+               p->linktype = DLT_EN10MB;
+               pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
+                   "Unknown NdisMedium value %d, defaulting to DLT_EN10MB",
+                   type.LinkType);
+               status = PCAP_WARNING;
+               break;
+       }
+
+       /*
+        * Turn a negative snapshot value (invalid), a snapshot value of
+        * 0 (unspecified), or a value bigger than the normal maximum
+        * value, into the maximum allowed value.
+        *
+        * If some application really *needs* a bigger snapshot
+        * length, we should just increase MAXIMUM_SNAPLEN.
+        */
+       if (p->snapshot <= 0 || p->snapshot > MAXIMUM_SNAPLEN)
+               p->snapshot = MAXIMUM_SNAPLEN;
+
+       /* Set promiscuous mode */
+       if (p->opt.promisc)
+       {
+
+               if (PacketSetHwFilter(pw->adapter,NDIS_PACKET_TYPE_PROMISCUOUS) == FALSE)
+               {
+                       pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "failed to set hardware filter to promiscuous mode");
+                       goto bad;
+               }
+       }
+       else
+       {
+               /* NDIS_PACKET_TYPE_ALL_LOCAL selects "All packets sent by installed
+                * protocols and all packets indicated by the NIC" but if no protocol
+                * drivers (like TCP/IP) are installed, NDIS_PACKET_TYPE_DIRECTED,
+                * NDIS_PACKET_TYPE_BROADCAST, and NDIS_PACKET_TYPE_MULTICAST are needed to
+                * capture incoming frames.
+                */
+               if (PacketSetHwFilter(pw->adapter,
+                       NDIS_PACKET_TYPE_ALL_LOCAL |
+                       NDIS_PACKET_TYPE_DIRECTED |
+                       NDIS_PACKET_TYPE_BROADCAST |
+                       NDIS_PACKET_TYPE_MULTICAST) == FALSE)
+               {
+                       pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "failed to set hardware filter to non-promiscuous mode");
+                       goto bad;
+               }
+       }
+
+       /* Set the buffer size */
+       p->bufsize = WIN32_DEFAULT_USER_BUFFER_SIZE;
+
+       if(!(pw->adapter->Flags & INFO_FLAG_DAG_CARD))
+       {
+       /*
+        * Traditional Adapter
+        */
+               /*
+                * If the buffer size wasn't explicitly set, default to
+                * WIN32_DEFAULT_KERNEL_BUFFER_SIZE.
+                */
+               if (p->opt.buffer_size == 0)
+                       p->opt.buffer_size = WIN32_DEFAULT_KERNEL_BUFFER_SIZE;
+
+               if(PacketSetBuff(pw->adapter,p->opt.buffer_size)==FALSE)
+               {
+                       pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "driver error: not enough memory to allocate the kernel buffer");
+                       goto bad;
+               }
+
+               p->buffer = malloc(p->bufsize);
+               if (p->buffer == NULL)
+               {
+                       pcap_fmt_errmsg_for_errno(p->errbuf, PCAP_ERRBUF_SIZE,
+                           errno, "malloc");
+                       goto bad;
+               }
+
+               if (p->opt.immediate)
+               {
+                       /* tell the driver to copy the buffer as soon as data arrives */
+                       if(PacketSetMinToCopy(pw->adapter,0)==FALSE)
+                       {
+                               pcap_fmt_errmsg_for_win32_err(p->errbuf,
+                                   PCAP_ERRBUF_SIZE, GetLastError(),
+                                   "Error calling PacketSetMinToCopy");
+                               goto bad;
+                       }
+               }
+               else
+               {
+                       /* tell the driver to copy the buffer only if it contains at least 16K */
+                       if(PacketSetMinToCopy(pw->adapter,16000)==FALSE)
+                       {
+                               pcap_fmt_errmsg_for_win32_err(p->errbuf,
+                                   PCAP_ERRBUF_SIZE, GetLastError(),
+                                   "Error calling PacketSetMinToCopy");
+                               goto bad;
+                       }
+               }
+       } else {
+               /*
+                * Dag Card
+                */
+#ifdef HAVE_DAG_API
+               /*
+                * We have DAG support.
+                */
+               LONG    status;
+               HKEY    dagkey;
+               DWORD   lptype;
+               DWORD   lpcbdata;
+               int             postype = 0;
+               char    keyname[512];
+
+               pcap_snprintf(keyname, sizeof(keyname), "%s\\CardParams\\%s",
+                       "SYSTEM\\CurrentControlSet\\Services\\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(pw->adapter, p->snapshot);
+
+               /* Set the length of the FCS associated to any packet. This value
+                * will be subtracted to the packet length */
+               pw->dag_fcs_bits = pw->adapter->DagFcsLen;
+#else /* HAVE_DAG_API */
+               /*
+                * No DAG support.
+                */
+               goto bad;
+#endif /* HAVE_DAG_API */
+       }
+
+       PacketSetReadTimeout(pw->adapter, p->opt.timeout);
+
+       /* disable loopback capture if requested */
+       if (p->opt.nocapture_local)
+       {
+               if (!PacketSetLoopbackBehavior(pw->adapter, NPF_DISABLE_LOOPBACK))
+               {
+                       pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
+                           "Unable to disable the capture of loopback packets.");
+                       goto bad;
+               }
+       }
+
+#ifdef HAVE_DAG_API
+       if(pw->adapter->Flags & INFO_FLAG_DAG_CARD)
+       {
+               /* install dag specific handlers for read and setfilter */
+               p->read_op = pcap_read_win32_dag;
+               p->setfilter_op = pcap_setfilter_win32_dag;
+       }
+       else
+       {
+#endif /* HAVE_DAG_API */
+               /* install traditional npf handlers for read and setfilter */
+               p->read_op = pcap_read_npf;
+               p->setfilter_op = pcap_setfilter_npf;
+#ifdef HAVE_DAG_API
+       }
+#endif /* HAVE_DAG_API */
+       p->setdirection_op = NULL;      /* Not implemented. */
+           /* XXX - can this be implemented on some versions of Windows? */
+       p->inject_op = pcap_inject_npf;
+       p->set_datalink_op = NULL;      /* can't change data link type */
+       p->getnonblock_op = pcap_getnonblock_npf;
+       p->setnonblock_op = pcap_setnonblock_npf;
+       p->stats_op = pcap_stats_npf;
+       p->stats_ex_op = pcap_stats_ex_npf;
+       p->setbuff_op = pcap_setbuff_npf;
+       p->setmode_op = pcap_setmode_npf;
+       p->setmintocopy_op = pcap_setmintocopy_npf;
+       p->getevent_op = pcap_getevent_npf;
+       p->oid_get_request_op = pcap_oid_get_request_npf;
+       p->oid_set_request_op = pcap_oid_set_request_npf;
+       p->sendqueue_transmit_op = pcap_sendqueue_transmit_npf;
+       p->setuserbuffer_op = pcap_setuserbuffer_npf;
+       p->live_dump_op = pcap_live_dump_npf;
+       p->live_dump_ended_op = pcap_live_dump_ended_npf;
+       p->get_airpcap_handle_op = pcap_get_airpcap_handle_npf;
+       p->cleanup_op = pcap_cleanup_npf;
+
+       /*
+        * XXX - this is only done because WinPcap supported
+        * pcap_fileno() returning the hFile HANDLE from the
+        * ADAPTER structure.  We make no general guarantees
+        * that the caller can do anything useful with it.
+        *
+        * (Not that we make any general guarantee of that
+        * sort on UN*X, either, any more, given that not
+        * all capture devices are regular OS network
+        * interfaces.)
+        */
+       p->handle = pw->adapter->hFile;
+
+       return (status);
+bad:
+       pcap_cleanup_npf(p);
+       return (PCAP_ERROR);
+}
+
+/*
+* Check if rfmon mode is supported on the pcap_t for Windows systems.
+*/
+static int
+pcap_can_set_rfmon_npf(pcap_t *p)
+{
+       return (PacketIsMonitorModeSupported(p->opt.device) == 1);
+}
+
+pcap_t *
+pcap_create_interface(const char *device _U_, char *ebuf)
+{
+       pcap_t *p;
+
+       p = pcap_create_common(ebuf, sizeof(struct pcap_win));
+       if (p == NULL)
+               return (NULL);
+
+       p->activate_op = pcap_activate_npf;
+       p->can_set_rfmon_op = pcap_can_set_rfmon_npf;
+       return (p);
+}
+
+static int
+pcap_setfilter_npf(pcap_t *p, struct bpf_program *fp)
+{
+       struct pcap_win *pw = p->priv;
+
+       if(PacketSetBpf(pw->adapter,fp)==FALSE){
+               /*
+                * Kernel filter not installed.
+                *
+                * XXX - we don't know whether this failed because:
+                *
+                *  the kernel rejected the filter program as invalid,
+                *  in which case we should fall back on userland
+                *  filtering;
+                *
+                *  the kernel rejected the filter program as too big,
+                *  in which case we should again fall back on
+                *  userland filtering;
+                *
+                *  there was some other problem, in which case we
+                *  should probably report an error.
+                *
+                * For NPF devices, the Win32 status will be
+                * STATUS_INVALID_DEVICE_REQUEST for invalid
+                * filters, but I don't know what it'd be for
+                * other problems, and for some other devices
+                * it might not be set at all.
+                *
+                * So we just fall back on userland filtering in
+                * all cases.
+                */
+
+               /*
+                * install_bpf_program() validates the program.
+                *
+                * XXX - what if we already have a filter in the kernel?
+                */
+               if (install_bpf_program(p, fp) < 0)
+                       return (-1);
+               pw->filtering_in_kernel = 0;    /* filtering in userland */
+               return (0);
+       }
+
+       /*
+        * It worked.
+        */
+       pw->filtering_in_kernel = 1;    /* filtering in the kernel */
+
+       /*
+        * Discard any previously-received packets, as they might have
+        * passed whatever filter was formerly in effect, but might
+        * not pass this filter (BIOCSETF discards packets buffered
+        * in the kernel, so you can lose packets in any case).
+        */
+       p->cc = 0;
+       return (0);
+}
+
+/*
+ * We filter at user level, since the kernel driver does't process the packets
+ */
+static int
+pcap_setfilter_win32_dag(pcap_t *p, struct bpf_program *fp) {
+
+       if(!fp)
+       {
+               pcap_strlcpy(p->errbuf, "setfilter: No filter specified", sizeof(p->errbuf));
+               return (-1);
+       }
+
+       /* Install a user level filter */
+       if (install_bpf_program(p, fp) < 0)
+               return (-1);
+
+       return (0);
+}
+
+static int
+pcap_getnonblock_npf(pcap_t *p)
+{
+       struct pcap_win *pw = p->priv;
+
+       /*
+        * XXX - if there were a PacketGetReadTimeout() call, we
+        * would use it, and return 1 if the timeout is -1
+        * and 0 otherwise.
+        */
+       return (pw->nonblock);
+}
+
+static int
+pcap_setnonblock_npf(pcap_t *p, int nonblock)
+{
+       struct pcap_win *pw = p->priv;
+       int newtimeout;
+
+       if (nonblock) {
+               /*
+                * Set the packet buffer timeout to -1 for non-blocking
+                * mode.
+                */
+               newtimeout = -1;
+       } else {
+               /*
+                * 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.  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(pw->adapter, newtimeout)) {
+               pcap_fmt_errmsg_for_win32_err(p->errbuf, PCAP_ERRBUF_SIZE,
+                   GetLastError(), "PacketSetReadTimeout");
+               return (-1);
+       }
+       pw->nonblock = (newtimeout == -1);
+       return (0);
+}
+
+static int
+pcap_add_if_npf(pcap_if_list_t *devlistp, 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.
+        */
+       curdev = add_dev(devlistp, name, flags, description, errbuf);
+       if (curdev == NULL) {
+               /*
+                * 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.
+                */
+               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);
+}
+
+static int
+get_if_flags(const char *name, bpf_u_int32 *flags, char *errbuf)
+{
+       char *name_copy;
+       ADAPTER *adapter;
+       int status;
+       size_t len;
+       NDIS_HARDWARE_STATUS hardware_status;
+#ifdef OID_GEN_PHYSICAL_MEDIUM
+       NDIS_PHYSICAL_MEDIUM phys_medium;
+       bpf_u_int32 gen_physical_medium_oids[] = {
+  #ifdef OID_GEN_PHYSICAL_MEDIUM_EX
+               OID_GEN_PHYSICAL_MEDIUM_EX,
+  #endif
+               OID_GEN_PHYSICAL_MEDIUM
+       };
+#define N_GEN_PHYSICAL_MEDIUM_OIDS     (sizeof gen_physical_medium_oids / sizeof gen_physical_medium_oids[0])
+       size_t i;
+#endif /* OID_GEN_PHYSICAL_MEDIUM */
+#ifdef OID_GEN_LINK_STATE
+       NDIS_LINK_STATE link_state;
+#endif
+       int connect_status;
+
+       if (*flags & PCAP_IF_LOOPBACK) {
+               /*
+                * Loopback interface, so the connection status doesn't
+                * apply. and it's not wireless (or wired, for that
+                * matter...).  We presume it's up and running.
+                */
+               *flags |= PCAP_IF_UP | PCAP_IF_RUNNING | PCAP_IF_CONNECTION_STATUS_NOT_APPLICABLE;
+               return (0);
+       }
+
+       /*
+        * We need to open the adapter to get this information.
+        *
+        * XXX - PacketOpenAdapter() takes a non-const pointer
+        * as an argument, so we make a copy of the argument and
+        * pass that to it.
+        */
+       name_copy = strdup(name);
+       adapter = PacketOpenAdapter(name_copy);
+       free(name_copy);
+       if (adapter == NULL) {
+               /*
+                * Give up; if they try to open this device, it'll fail.
+                */
+               return (0);
+       }
+
+#ifdef HAVE_AIRPCAP_API
+       /*
+        * Airpcap.sys do not support the below 'OID_GEN_x' values.
+        * Just set these flags (and none of the '*flags' entered with).
+        */
+       if (PacketGetAirPcapHandle(adapter)) {
+               /*
+                * Must be "up" and "running" if the above if succeeded.
+                */
+               *flags = PCAP_IF_UP | PCAP_IF_RUNNING;
+
+               /*
+                * An airpcap device is a wireless device (duh!)
+                */
+               *flags |= PCAP_IF_WIRELESS;
+
+               /*
+                * A "network assosiation state" makes no sense for airpcap.
+                */
+               *flags |= PCAP_IF_CONNECTION_STATUS_NOT_APPLICABLE;
+               PacketCloseAdapter(adapter);
+               return (0);
+       }
+#endif
+
+       /*
+        * Get the hardware status, and derive "up" and "running" from
+        * that.
+        */
+       len = sizeof (hardware_status);
+       status = oid_get_request(adapter, OID_GEN_HARDWARE_STATUS,
+           &hardware_status, &len, errbuf);
+       if (status == 0) {
+               switch (hardware_status) {
+
+               case NdisHardwareStatusReady:
+                       /*
+                        * "Available and capable of sending and receiving
+                        * data over the wire", so up and running.
+                        */
+                       *flags |= PCAP_IF_UP | PCAP_IF_RUNNING;
+                       break;
+
+               case NdisHardwareStatusInitializing:
+               case NdisHardwareStatusReset:
+                       /*
+                        * "Initializing" or "Resetting", so up, but
+                        * not running.
+                        */
+                       *flags |= PCAP_IF_UP;
+                       break;
+
+               case NdisHardwareStatusClosing:
+               case NdisHardwareStatusNotReady:
+                       /*
+                        * "Closing" or "Not ready", so neither up nor
+                        * running.
+                        */
+                       break;
+               }
+       } else {
+               /*
+                * Can't get the hardware status, so assume both up and
+                * running.
+                */
+               *flags |= PCAP_IF_UP | PCAP_IF_RUNNING;
+       }
+
+       /*
+        * Get the network type.
+        */
+#ifdef OID_GEN_PHYSICAL_MEDIUM
+       /*
+        * Try the OIDs we have for this, in order.
+        */
+       for (i = 0; i < N_GEN_PHYSICAL_MEDIUM_OIDS; i++) {
+               len = sizeof (phys_medium);
+               status = oid_get_request(adapter, gen_physical_medium_oids[i],
+                   &phys_medium, &len, errbuf);
+               if (status == 0) {
+                       /*
+                        * Success.
+                        */
+                       break;
+               }
+               /*
+                * Failed.  We can't determine whether it failed
+                * because that particular OID isn't supported
+                * or because some other problem occurred, so we
+                * just drive on and try the next OID.
+                */
+       }
+       if (status == 0) {
+               /*
+                * We got the physical medium.
+                */
+               switch (phys_medium) {
+
+               case NdisPhysicalMediumWirelessLan:
+               case NdisPhysicalMediumWirelessWan:
+               case NdisPhysicalMediumNative802_11:
+               case NdisPhysicalMediumBluetooth:
+               case NdisPhysicalMediumUWB:
+               case NdisPhysicalMediumIrda:
+                       /*
+                        * Wireless.
+                        */
+                       *flags |= PCAP_IF_WIRELESS;
+                       break;
+
+               default:
+                       /*
+                        * Not wireless.
+                        */
+                       break;
+               }
+       }
+#endif
+
+       /*
+        * Get the connection status.
+        */
+#ifdef OID_GEN_LINK_STATE
+       len = sizeof(link_state);
+       status = oid_get_request(adapter, OID_GEN_LINK_STATE, &link_state,
+           &len, errbuf);
+       if (status == 0) {
+               /*
+                * NOTE: this also gives us the receive and transmit
+                * link state.
+                */
+               switch (link_state.MediaConnectState) {
+
+               case MediaConnectStateConnected:
+                       /*
+                        * It's connected.
+                        */
+                       *flags |= PCAP_IF_CONNECTION_STATUS_CONNECTED;
+                       break;
+
+               case MediaConnectStateDisconnected:
+                       /*
+                        * It's disconnected.
+                        */
+                       *flags |= PCAP_IF_CONNECTION_STATUS_DISCONNECTED;
+                       break;
+               }
+       }
+#else
+       /*
+        * OID_GEN_LINK_STATE isn't supported because it's not in our SDK.
+        */
+       status = -1;
+#endif
+       if (status == -1) {
+               /*
+                * OK, OID_GEN_LINK_STATE didn't work, try
+                * OID_GEN_MEDIA_CONNECT_STATUS.
+                */
+               status = oid_get_request(adapter, OID_GEN_MEDIA_CONNECT_STATUS,
+                   &connect_status, &len, errbuf);
+               if (status == 0) {
+                       switch (connect_status) {
+
+                       case NdisMediaStateConnected:
+                               /*
+                                * It's connected.
+                                */
+                               *flags |= PCAP_IF_CONNECTION_STATUS_CONNECTED;
+                               break;
+
+                       case NdisMediaStateDisconnected:
+                               /*
+                                * It's disconnected.
+                                */
+                               *flags |= PCAP_IF_CONNECTION_STATUS_DISCONNECTED;
+                               break;
+                       }
+               }
+       }
+       PacketCloseAdapter(adapter);
+       return (0);
+}
+
+int
+pcap_platform_finddevs(pcap_if_list_t *devlistp, char *errbuf)
+{
+       int ret = 0;
+       const char *desc;
+       char *AdaptersName;
+       ULONG NameLength;
+       char *name;
+
+       /*
+        * Find out how big a buffer we need.
+        *
+        * This call should always return FALSE; if the error is
+        * ERROR_INSUFFICIENT_BUFFER, NameLength will be set to
+        * the size of the buffer we need, otherwise there's a
+        * problem, and NameLength should be set to 0.
+        *
+        * It shouldn't require NameLength to be set, but,
+        * at least as of WinPcap 4.1.3, it checks whether
+        * NameLength is big enough before it checks for a
+        * NULL buffer argument, so, while it'll still do
+        * the right thing if NameLength is uninitialized and
+        * whatever junk happens to be there is big enough
+        * (because the pointer argument will be null), it's
+        * still reading an uninitialized variable.
+        */
+       NameLength = 0;
+       if (!PacketGetAdapterNames(NULL, &NameLength))
+       {
+               DWORD last_error = GetLastError();
+
+               if (last_error != ERROR_INSUFFICIENT_BUFFER)
+               {
+                       pcap_fmt_errmsg_for_win32_err(errbuf, PCAP_ERRBUF_SIZE,
+                           last_error, "PacketGetAdapterNames");
+                       return (-1);
+               }
+       }
+
+       if (NameLength <= 0)
+               return 0;
+       AdaptersName = (char*) malloc(NameLength);
+       if (AdaptersName == NULL)
+       {
+               pcap_snprintf(errbuf, PCAP_ERRBUF_SIZE, "Cannot allocate enough memory to list the adapters.");
+               return (-1);
+       }
+
+       if (!PacketGetAdapterNames(AdaptersName, &NameLength)) {
+               pcap_fmt_errmsg_for_win32_err(errbuf, PCAP_ERRBUF_SIZE,
+                   GetLastError(), "PacketGetAdapterNames");
+               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
+               /*
+                * Get additional flags.
+                */
+               if (get_if_flags(name, &flags, errbuf) == -1) {
+                       /*
+                        * Failure.
+                        */
+                       ret = -1;
+                       break;
+               }
+
+               /*
+                * Add an entry for this interface.
+                */
+               if (pcap_add_if_npf(devlistp, name, flags, desc,
+                   errbuf) == -1) {
+                       /*
+                        * Failure.
+                        */
+                       ret = -1;
+                       break;
+               }
+               name += strlen(name) + 1;
+               desc += strlen(desc) + 1;
+       }
+
+       free(AdaptersName);
+       return (ret);
+}
+
+/*
+ * 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(char *errbuf)
+{
+       DWORD dwVersion;
+       DWORD dwWindowsMajorVersion;
+
+#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 = ADAPTERSNAME_LEN;
+               static char AdaptersName[ADAPTERSNAME_LEN];
+
+               if (PacketGetAdapterNames(AdaptersName,&NameLength) )
+                       return (AdaptersName);
+               else
+                       return NULL;
+       } else {
+               /*
+                * Windows NT (NT 4.0 and later).
+                * Convert the names to Unicode for backward compatibility.
+                */
+               ULONG NameLength = ADAPTERSNAME_LEN;
+               static WCHAR AdaptersName[ADAPTERSNAME_LEN];
+               size_t BufferSpaceLeft;
+               char *tAstr;
+               WCHAR *Unameptr;
+               char *Adescptr;
+               size_t namelen, i;
+               WCHAR *TAdaptersName = (WCHAR*)malloc(ADAPTERSNAME_LEN * sizeof(WCHAR));
+               int NAdapts = 0;
+
+               if(TAdaptersName == NULL)
+               {
+                       (void)pcap_snprintf(errbuf, PCAP_ERRBUF_SIZE, "memory allocation failure");
+                       return NULL;
+               }
+
+               if ( !PacketGetAdapterNames((PTSTR)TAdaptersName,&NameLength) )
+               {
+                       pcap_fmt_errmsg_for_win32_err(errbuf, PCAP_ERRBUF_SIZE,
+                           GetLastError(), "PacketGetAdapterNames");
+                       free(TAdaptersName);
+                       return NULL;
+               }
+
+
+               BufferSpaceLeft = ADAPTERSNAME_LEN * sizeof(WCHAR);
+               tAstr = (char*)TAdaptersName;
+               Unameptr = AdaptersName;
+
+               /*
+                * Convert the device names to Unicode into AdapterName.
+                */
+               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++;
+
+                       /*
+                        * Count this adapter.
+                        */
+                       NAdapts++;
+               } while (namelen != 1);
+
+               /*
+                * Copy the descriptions, but don't convert them from
+                * ASCII to Unicode.
+                */
+               Adescptr = (char *)Unameptr;
+               while(NAdapts--)
+               {
+                       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);
+       }
+}
+
+/*
+ * We can't use the same code that we use on UN*X, as that's doing
+ * UN*X-specific calls.
+ *
+ * We don't just fetch the entire list of devices, search for the
+ * particular device, and use its first IPv4 address, as that's too
+ * much work to get just one device's netmask.
+ */
+int
+pcap_lookupnet(const char *device, bpf_u_int32 *netp, bpf_u_int32 *maskp,
+    char *errbuf)
+{
+       /*
+        * We need only the first IPv4 address, so we must scan the array returned by PacketGetNetInfo()
+        * in order to skip non IPv4 (i.e. IPv6 addresses)
+        */
+       npf_if_addr if_addrs[MAX_NETWORK_ADDRESSES];
+       LONG if_addr_size = MAX_NETWORK_ADDRESSES;
+       struct sockaddr_in *t_addr;
+       LONG i;
+
+       if (!PacketGetNetInfoEx((void *)device, if_addrs, &if_addr_size)) {
+               *netp = *maskp = 0;
+               return (0);
+       }
+
+       for(i = 0; i < if_addr_size; i++)
+       {
+               if(if_addrs[i].IPAddress.ss_family == AF_INET)
+               {
+                       t_addr = (struct sockaddr_in *) &(if_addrs[i].IPAddress);
+                       *netp = t_addr->sin_addr.S_un.S_addr;
+                       t_addr = (struct sockaddr_in *) &(if_addrs[i].SubnetMask);
+                       *maskp = t_addr->sin_addr.S_un.S_addr;
+
+                       *netp &= *maskp;
+                       return (0);
+               }
+
+       }
+
+       *netp = *maskp = 0;
+       return (0);
+}
+
+static const char *pcap_lib_version_string;
+
+#ifdef HAVE_VERSION_H
+/*
+ * 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/Npcap version
+ * number when building as part of WinPcap/Npcap.  (It'd be nice to do so
+ * for the packet.dll version number as well.)
+ */
+#include "../../version.h"
+
+static const char pcap_version_string[] =
+       WINPCAP_PRODUCT_NAME " version " WINPCAP_VER_STRING ", based on " PCAP_VERSION_STRING;
+
+const char *
+pcap_lib_version(void)
+{
+       if (pcap_lib_version_string == NULL) {
+               /*
+                * Generate the version string.
+                */
+               char *packet_version_string = PacketGetVersion();
+
+               if (strcmp(WINPCAP_VER_STRING, packet_version_string) == 0) {
+                       /*
+                        * WinPcap/Npcap version string and packet.dll version
+                        * string are the same; just report the WinPcap/Npcap
+                        * version.
+                        */
+                       pcap_lib_version_string = pcap_version_string;
+               } else {
+                       /*
+                        * WinPcap/Npcap version string and packet.dll version
+                        * string are different; that shouldn't be the
+                        * case (the two libraries should come from the
+                        * same version of WinPcap/Npcap), so we report both
+                        * versions.
+                        */
+                       char *full_pcap_version_string;
+
+                       if (pcap_asprintf(&full_pcap_version_string,
+                           WINPCAP_PRODUCT_NAME " version " WINPCAP_VER_STRING " (packet.dll version %s), based on " PCAP_VERSION_STRING,
+                           packet_version_string) != -1) {
+                               /* Success */
+                               pcap_lib_version_string = full_pcap_version_string;
+                       }
+               }
+       }
+       return (pcap_lib_version_string);
+}
+
+#else /* HAVE_VERSION_H */
+
+/*
+ * libpcap being built for Windows, not as part of a WinPcap/Npcap source
+ * tree.
+ */
+const char *
+pcap_lib_version(void)
+{
+       if (pcap_lib_version_string == NULL) {
+               /*
+                * Generate the version string.  Report the packet.dll
+                * version.
+                */
+               char *full_pcap_version_string;
+
+               if (pcap_asprintf(&full_pcap_version_string,
+                   PCAP_VERSION_STRING " (packet.dll version %s)",
+                   PacketGetVersion()) != -1) {
+                       /* Success */
+                       pcap_lib_version_string = full_pcap_version_string;
+               }
+       }
+       return (pcap_lib_version_string);
+}
+#endif /* HAVE_VERSION_H */
index 934fb2c..2ae27bf 100644 (file)
  */
 
 #ifdef HAVE_CONFIG_H
-#include "config.h"
+#include <config.h>
 #endif
 
-#include <sys/param.h>                 /* optionally get BSD define */
-
 #include <string.h>
 
-#ifdef HAVE_OS_PROTO_H
-#include "os-proto.h"
-#endif
-
 #include "pcap-int.h"
 
 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);
+       (void)pcap_strlcpy(ebuf, nosup, PCAP_ERRBUF_SIZE);
        return (NULL);
 }
 
 int
-pcap_platform_finddevs(pcap_if_t **alldevsp, char *errbuf)
+pcap_platform_finddevs(pcap_if_list_t *devlistp _U_, char *errbuf _U_)
 {
+       /*
+        * There are no interfaces on which we can capture.
+        */
        return (0);
 }
+
+#ifdef _WIN32
+int
+pcap_lookupnet(const char *device _U_, bpf_u_int32 *netp _U_,
+    bpf_u_int32 *maskp _U_, char *errbuf)
+{
+       (void)pcap_strlcpy(errbuf, nosup, PCAP_ERRBUF_SIZE);
+       return (-1);
+}
+#endif
+
+/*
+ * Libpcap version string.
+ */
+const char *
+pcap_lib_version(void)
+{
+       return (PCAP_VERSION_STRING);
+}
index 96a4a50..fde97ba 100644 (file)
--- a/pcap-pf.c
+++ b/pcap-pf.c
@@ -23,7 +23,7 @@
  */
 
 #ifdef HAVE_CONFIG_H
-#include "config.h"
+#include <config.h>
 #endif
 
 #include <sys/types.h>
@@ -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_strerror(errno));
+                       pcap_fmt_errmsg_for_errno(pc->errbuf,
+                           sizeof(pc->errbuf), errno, "pf read");
                        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_strerror(errno));
+               pcap_fmt_errmsg_for_errno(p->errbuf, PCAP_ERRBUF_SIZE,
+                   errno, "send");
                return (-1);
        }
        return (ret);
-}                           
+}
 
 static int
 pcap_stats_pf(pcap_t *p, struct pcap_stat *ps)
@@ -302,6 +302,7 @@ pcap_activate_pf(pcap_t *p)
        int backlog = -1;       /* request the most */
        struct enfilter Filter;
        struct endevp devparams;
+       int err;
 
        /*
         * Initially try a read/write open (to allow the inject
@@ -321,16 +322,39 @@ 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\
-your system may not be properly configured; see the packetfilter(4) man page\n",
-                       p->opt.source, pcap_strerror(errno));
+               if (errno == EACCES) {
+                       pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
+                           "pf open: %s: Permission denied\n"
+"your system may not be properly configured; see the packetfilter(4) man page",
+                           p->opt.device);
+                       err = PCAP_ERROR_PERM_DENIED;
+               } else {
+                       pcap_fmt_errmsg_for_errno(p->errbuf, PCAP_ERRBUF_SIZE,
+                           errno, "pf open: %s", p->opt.device);
+                       err = PCAP_ERROR;
+               }
                goto bad;
        }
+
+       /*
+        * Turn a negative snapshot value (invalid), a snapshot value of
+        * 0 (unspecified), or a value bigger than the normal maximum
+        * value, into the maximum allowed value.
+        *
+        * If some application really *needs* a bigger snapshot
+        * length, we should just increase MAXIMUM_SNAPLEN.
+        */
+       if (p->snapshot <= 0 || p->snapshot > MAXIMUM_SNAPLEN)
+               p->snapshot = MAXIMUM_SNAPLEN;
+
        pf->OrigMissed = -1;
        enmode = ENTSTAMP|ENNONEXCL;
        if (!p->opt.immediate)
@@ -338,8 +362,9 @@ 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_strerror(errno));
+               pcap_fmt_errmsg_for_errno(p->errbuf, PCAP_ERRBUF_SIZE,
+                   errno, "EIOCMBIS");
+               err = PCAP_ERROR;
                goto bad;
        }
 #ifdef ENCOPYALL
@@ -349,14 +374,16 @@ 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_strerror(errno));
+               pcap_fmt_errmsg_for_errno(p->errbuf, PCAP_ERRBUF_SIZE,
+                   errno, "EIOCSETW");
+               err = PCAP_ERROR;
                goto bad;
        }
        /* discover interface type */
        if (ioctl(p->fd, EIOCDEVP, (caddr_t)&devparams) < 0) {
-               snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "EIOCDEVP: %s",
-                   pcap_strerror(errno));
+               pcap_fmt_errmsg_for_errno(p->errbuf, PCAP_ERRBUF_SIZE,
+                   errno, "EIOCDEVP");
+               err = PCAP_ERROR;
                goto bad;
        }
        /* HACK: to compile prior to Ultrix 4.2 */
@@ -437,8 +464,9 @@ 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);
+               err = PCAP_ERROR;
                goto bad;
        }
        /* set truncation */
@@ -450,8 +478,9 @@ 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_strerror(errno));
+               pcap_fmt_errmsg_for_errno(p->errbuf, PCAP_ERRBUF_SIZE,
+                   errno, "EIOCTRUNCATE");
+               err = PCAP_ERROR;
                goto bad;
        }
        /* accept all packets */
@@ -459,8 +488,9 @@ 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_strerror(errno));
+               pcap_fmt_errmsg_for_errno(p->errbuf, PCAP_ERRBUF_SIZE,
+                   errno, "EIOCSETF");
+               err = PCAP_ERROR;
                goto bad;
        }
 
@@ -469,16 +499,19 @@ 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_strerror(errno));
+                       pcap_fmt_errmsg_for_errno(p->errbuf, PCAP_ERRBUF_SIZE,
+                           errno, "EIOCSRTIMEOUT");
+                       err = PCAP_ERROR;
                        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);
+               pcap_fmt_errmsg_for_errno(p->errbuf, PCAP_ERRBUF_SIZE,
+                   errno, "malloc");
+               err = PCAP_ERROR;
                goto bad;
        }
 
@@ -499,15 +532,15 @@ your system may not be properly configured; see the packetfilter(4) man page\n",
        return (0);
  bad:
        pcap_cleanup_live_common(p);
-       return (PCAP_ERROR);
+       return (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_pf));
+       p = pcap_create_common(ebuf, sizeof (struct pcap_pf));
        if (p == NULL)
                return (NULL);
 
@@ -515,12 +548,44 @@ pcap_create_interface(const char *device, char *ebuf)
        return (p);
 }
 
-int
-pcap_platform_finddevs(pcap_if_t **alldevsp, char *errbuf)
+/*
+ * 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);
+}
+
+static int
+get_if_flags(const char *name _U_, bpf_u_int32 *flags _U_, char *errbuf _U_)
 {
+       /*
+        * Nothing we can do other than mark loopback devices as "the
+        * connected/disconnected status doesn't apply".
+        *
+        * XXX - is there a way to find out whether an adapter has
+        * something plugged into it?
+        */
+       if (*flags & PCAP_IF_LOOPBACK) {
+               /*
+                * Loopback devices aren't wireless, and "connected"/
+                * "disconnected" doesn't apply to them.
+                */
+               *flags |= PCAP_IF_CONNECTION_STATUS_NOT_APPLICABLE;
+               return (0);
+       }
        return (0);
 }
 
+int
+pcap_platform_finddevs(pcap_if_list_t *devlistp, char *errbuf)
+{
+       return (pcap_findalldevs_interfaces(devlistp, errbuf, can_be_bound,
+           get_if_flags));
+}
+
 static int
 pcap_setfilter_pf(pcap_t *p, struct bpf_program *fp)
 {
@@ -547,8 +612,8 @@ 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),
-                                   "BIOCSETF: %s", pcap_strerror(errno));
+                               pcap_fmt_errmsg_for_errno(p->errbuf,
+                                   sizeof(p->errbuf), errno, "BIOCSETF");
                                return (-1);
                        }
 
@@ -607,3 +672,12 @@ pcap_setfilter_pf(pcap_t *p, struct bpf_program *fp)
        pf->filtering_in_kernel = 0;
        return (0);
 }
+
+/*
+ * Libpcap version string.
+ */
+const char *
+pcap_lib_version(void)
+{
+       return (PCAP_VERSION_STRING);
+}
diff --git a/pcap-rdmasniff.c b/pcap-rdmasniff.c
new file mode 100644 (file)
index 0000000..c50fe3f
--- /dev/null
@@ -0,0 +1,436 @@
+/*
+ * Copyright (c) 2017 Pure Storage, Inc.
+ * 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.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include "pcap-int.h"
+#include "pcap-rdmasniff.h"
+
+#include <infiniband/verbs.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sys/time.h>
+
+#if !defined(IBV_FLOW_ATTR_SNIFFER)
+#define IBV_FLOW_ATTR_SNIFFER  3
+#endif
+
+static const int RDMASNIFF_NUM_RECEIVES = 128;
+static const int RDMASNIFF_RECEIVE_SIZE = 10000;
+
+struct pcap_rdmasniff {
+       struct ibv_device *             rdma_device;
+       struct ibv_context *            context;
+       struct ibv_comp_channel *       channel;
+       struct ibv_pd *                 pd;
+       struct ibv_cq *                 cq;
+       struct ibv_qp *                 qp;
+       struct ibv_flow *               flow;
+       struct ibv_mr *                 mr;
+       u_char *                        oneshot_buffer;
+       unsigned                        port_num;
+       int                             cq_event;
+       u_int                           packets_recv;
+};
+
+static int
+rdmasniff_stats(pcap_t *handle, struct pcap_stat *stat)
+{
+       struct pcap_rdmasniff *priv = handle->priv;
+
+       stat->ps_recv = priv->packets_recv;
+       stat->ps_drop = 0;
+       stat->ps_ifdrop = 0;
+
+       return 0;
+}
+
+static void
+rdmasniff_cleanup(pcap_t *handle)
+{
+       struct pcap_rdmasniff *priv = handle->priv;
+
+       ibv_dereg_mr(priv->mr);
+       ibv_destroy_flow(priv->flow);
+       ibv_destroy_qp(priv->qp);
+       ibv_destroy_cq(priv->cq);
+       ibv_dealloc_pd(priv->pd);
+       ibv_destroy_comp_channel(priv->channel);
+       ibv_close_device(priv->context);
+       free(priv->oneshot_buffer);
+
+       pcap_cleanup_live_common(handle);
+}
+
+static void
+rdmasniff_post_recv(pcap_t *handle, uint64_t wr_id)
+{
+       struct pcap_rdmasniff *priv = handle->priv;
+       struct ibv_sge sg_entry;
+       struct ibv_recv_wr wr, *bad_wr;
+
+       sg_entry.length = RDMASNIFF_RECEIVE_SIZE;
+       sg_entry.addr = (uintptr_t) handle->buffer + RDMASNIFF_RECEIVE_SIZE * wr_id;
+       sg_entry.lkey = priv->mr->lkey;
+
+       wr.wr_id = wr_id;
+       wr.num_sge = 1;
+       wr.sg_list = &sg_entry;
+       wr.next = NULL;
+
+       ibv_post_recv(priv->qp, &wr, &bad_wr);
+}
+
+static int
+rdmasniff_read(pcap_t *handle, int max_packets, pcap_handler callback, u_char *user)
+{
+       struct pcap_rdmasniff *priv = handle->priv;
+       struct ibv_cq *ev_cq;
+       void *ev_ctx;
+       struct ibv_wc wc;
+       struct pcap_pkthdr pkth;
+       u_char *pktd;
+       int count = 0;
+
+       if (!priv->cq_event) {
+               while (ibv_get_cq_event(priv->channel, &ev_cq, &ev_ctx) < 0) {
+                       if (errno != EINTR) {
+                               return PCAP_ERROR;
+                       }
+                       if (handle->break_loop) {
+                               handle->break_loop = 0;
+                               return PCAP_ERROR_BREAK;
+                       }
+               }
+               ibv_ack_cq_events(priv->cq, 1);
+               ibv_req_notify_cq(priv->cq, 0);
+               priv->cq_event = 1;
+       }
+
+       while (count < max_packets || PACKET_COUNT_IS_UNLIMITED(max_packets)) {
+               if (ibv_poll_cq(priv->cq, 1, &wc) != 1) {
+                       priv->cq_event = 0;
+                       break;
+               }
+
+               if (wc.status != IBV_WC_SUCCESS) {
+                       fprintf(stderr, "failed WC wr_id %lld status %d/%s\n",
+                               (unsigned long long) wc.wr_id,
+                               wc.status, ibv_wc_status_str(wc.status));
+                       continue;
+               }
+
+               pkth.len = wc.byte_len;
+               pkth.caplen = min(pkth.len, (u_int)handle->snapshot);
+               gettimeofday(&pkth.ts, NULL);
+
+               pktd = (u_char *) handle->buffer + wc.wr_id * RDMASNIFF_RECEIVE_SIZE;
+
+               if (handle->fcode.bf_insns == NULL ||
+                   bpf_filter(handle->fcode.bf_insns, pktd, pkth.len, pkth.caplen)) {
+                       callback(user, &pkth, pktd);
+                       ++priv->packets_recv;
+                       ++count;
+               }
+
+               rdmasniff_post_recv(handle, wc.wr_id);
+
+               if (handle->break_loop) {
+                       handle->break_loop = 0;
+                       return PCAP_ERROR_BREAK;
+               }
+       }
+
+       return count;
+}
+
+static void
+rdmasniff_oneshot(u_char *user, const struct pcap_pkthdr *h, const u_char *bytes)
+{
+       struct oneshot_userdata *sp = (struct oneshot_userdata *) user;
+       pcap_t *handle = sp->pd;
+       struct pcap_rdmasniff *priv = handle->priv;
+
+       *sp->hdr = *h;
+       memcpy(priv->oneshot_buffer, bytes, h->caplen);
+       *sp->pkt = priv->oneshot_buffer;
+}
+
+static int
+rdmasniff_activate(pcap_t *handle)
+{
+       struct pcap_rdmasniff *priv = handle->priv;
+       struct ibv_qp_init_attr qp_init_attr;
+       struct ibv_qp_attr qp_attr;
+       struct ibv_flow_attr flow_attr;
+       struct ibv_port_attr port_attr;
+       int i;
+
+       priv->context = ibv_open_device(priv->rdma_device);
+       if (!priv->context) {
+               pcap_snprintf(handle->errbuf, PCAP_ERRBUF_SIZE,
+                             "Failed to open device %s", handle->opt.device);
+               goto error;
+       }
+
+       priv->pd = ibv_alloc_pd(priv->context);
+       if (!priv->pd) {
+               pcap_snprintf(handle->errbuf, PCAP_ERRBUF_SIZE,
+                             "Failed to alloc PD for device %s", handle->opt.device);
+               goto error;
+       }
+
+       priv->channel = ibv_create_comp_channel(priv->context);
+       if (!priv->channel) {
+               pcap_snprintf(handle->errbuf, PCAP_ERRBUF_SIZE,
+                             "Failed to create comp channel for device %s", handle->opt.device);
+               goto error;
+       }
+
+       priv->cq = ibv_create_cq(priv->context, RDMASNIFF_NUM_RECEIVES,
+                                NULL, priv->channel, 0);
+       if (!priv->cq) {
+               pcap_snprintf(handle->errbuf, PCAP_ERRBUF_SIZE,
+                             "Failed to create CQ for device %s", handle->opt.device);
+               goto error;
+       }
+
+       ibv_req_notify_cq(priv->cq, 0);
+
+       memset(&qp_init_attr, 0, sizeof qp_init_attr);
+       qp_init_attr.send_cq = qp_init_attr.recv_cq = priv->cq;
+       qp_init_attr.cap.max_recv_wr = RDMASNIFF_NUM_RECEIVES;
+       qp_init_attr.cap.max_recv_sge = 1;
+       qp_init_attr.qp_type = IBV_QPT_RAW_PACKET;
+       priv->qp = ibv_create_qp(priv->pd, &qp_init_attr);
+       if (!priv->qp) {
+               pcap_snprintf(handle->errbuf, PCAP_ERRBUF_SIZE,
+                             "Failed to create QP for device %s", handle->opt.device);
+               goto error;
+       }
+
+       memset(&qp_attr, 0, sizeof qp_attr);
+       qp_attr.qp_state = IBV_QPS_INIT;
+       qp_attr.port_num = priv->port_num;
+       if (ibv_modify_qp(priv->qp, &qp_attr, IBV_QP_STATE | IBV_QP_PORT)) {
+               pcap_snprintf(handle->errbuf, PCAP_ERRBUF_SIZE,
+                             "Failed to modify QP to INIT for device %s", handle->opt.device);
+               goto error;
+       }
+
+       memset(&qp_attr, 0, sizeof qp_attr);
+       qp_attr.qp_state = IBV_QPS_RTR;
+       if (ibv_modify_qp(priv->qp, &qp_attr, IBV_QP_STATE)) {
+               pcap_snprintf(handle->errbuf, PCAP_ERRBUF_SIZE,
+                             "Failed to modify QP to RTR for device %s", handle->opt.device);
+               goto error;
+       }
+
+       memset(&flow_attr, 0, sizeof flow_attr);
+       flow_attr.type = IBV_FLOW_ATTR_SNIFFER;
+       flow_attr.size = sizeof flow_attr;
+       flow_attr.port = priv->port_num;
+       priv->flow = ibv_create_flow(priv->qp, &flow_attr);
+       if (!priv->flow) {
+               pcap_snprintf(handle->errbuf, PCAP_ERRBUF_SIZE,
+                             "Failed to create flow for device %s", handle->opt.device);
+               goto error;
+       }
+
+       handle->bufsize = RDMASNIFF_NUM_RECEIVES * RDMASNIFF_RECEIVE_SIZE;
+       handle->buffer = malloc(handle->bufsize);
+       if (!handle->buffer) {
+               pcap_snprintf(handle->errbuf, PCAP_ERRBUF_SIZE,
+                             "Failed to allocate receive buffer for device %s", handle->opt.device);
+               goto error;
+       }
+
+       priv->oneshot_buffer = malloc(RDMASNIFF_RECEIVE_SIZE);
+       if (!priv->oneshot_buffer) {
+               pcap_snprintf(handle->errbuf, PCAP_ERRBUF_SIZE,
+                             "Failed to allocate oneshot buffer for device %s", handle->opt.device);
+               goto error;
+       }
+
+       priv->mr = ibv_reg_mr(priv->pd, handle->buffer, handle->bufsize, IBV_ACCESS_LOCAL_WRITE);
+       if (!priv->mr) {
+               pcap_snprintf(handle->errbuf, PCAP_ERRBUF_SIZE,
+                             "Failed to register MR for device %s", handle->opt.device);
+               goto error;
+       }
+
+
+       for (i = 0; i < RDMASNIFF_NUM_RECEIVES; ++i) {
+               rdmasniff_post_recv(handle, i);
+       }
+
+       if (!ibv_query_port(priv->context, priv->port_num, &port_attr) &&
+           port_attr.link_layer == IBV_LINK_LAYER_INFINIBAND) {
+               handle->linktype = DLT_INFINIBAND;
+       } else {
+               handle->linktype = DLT_EN10MB;
+       }
+
+       if (handle->snapshot <= 0 || handle->snapshot > RDMASNIFF_RECEIVE_SIZE)
+               handle->snapshot = RDMASNIFF_RECEIVE_SIZE;
+
+       handle->offset = 0;
+       handle->read_op = rdmasniff_read;
+       handle->stats_op = rdmasniff_stats;
+       handle->cleanup_op = rdmasniff_cleanup;
+       handle->setfilter_op = install_bpf_program;
+       handle->setdirection_op = NULL;
+       handle->set_datalink_op = NULL;
+       handle->getnonblock_op = pcap_getnonblock_fd;
+       handle->setnonblock_op = pcap_setnonblock_fd;
+       handle->oneshot_callback = rdmasniff_oneshot;
+       handle->selectable_fd = priv->channel->fd;
+
+       return 0;
+
+error:
+       if (priv->mr) {
+               ibv_dereg_mr(priv->mr);
+       }
+
+       if (priv->flow) {
+               ibv_destroy_flow(priv->flow);
+       }
+
+       if (priv->qp) {
+               ibv_destroy_qp(priv->qp);
+       }
+
+       if (priv->cq) {
+               ibv_destroy_cq(priv->cq);
+       }
+
+       if (priv->channel) {
+               ibv_destroy_comp_channel(priv->channel);
+       }
+
+       if (priv->pd) {
+               ibv_dealloc_pd(priv->pd);
+       }
+
+       if (priv->context) {
+               ibv_close_device(priv->context);
+       }
+
+       if (priv->oneshot_buffer) {
+               free(priv->oneshot_buffer);
+       }
+
+       return PCAP_ERROR;
+}
+
+pcap_t *
+rdmasniff_create(const char *device, char *ebuf, int *is_ours)
+{
+       struct pcap_rdmasniff *priv;
+       struct ibv_device **dev_list;
+       int numdev;
+       size_t namelen;
+       const char *port;
+       unsigned port_num;
+       int i;
+       pcap_t *p = NULL;
+
+       *is_ours = 0;
+
+       dev_list = ibv_get_device_list(&numdev);
+       if (!dev_list || !numdev) {
+               return NULL;
+       }
+
+       namelen = strlen(device);
+
+       port = strchr(device, ':');
+       if (port) {
+               port_num = strtoul(port + 1, NULL, 10);
+               if (port_num > 0) {
+                       namelen = port - device;
+               } else {
+                       port_num = 1;
+               }
+       } else {
+               port_num = 1;
+       }
+
+       for (i = 0; i < numdev; ++i) {
+               if (strlen(dev_list[i]->name) == namelen &&
+                   !strncmp(device, dev_list[i]->name, namelen)) {
+                       *is_ours = 1;
+
+                       p = pcap_create_common(ebuf, sizeof (struct pcap_rdmasniff));
+                       if (p) {
+                               p->activate_op = rdmasniff_activate;
+                               priv = p->priv;
+                               priv->rdma_device = dev_list[i];
+                               priv->port_num = port_num;
+                       }
+                       break;
+               }
+       }
+
+       ibv_free_device_list(dev_list);
+       return p;
+}
+
+int
+rdmasniff_findalldevs(pcap_if_list_t *devlistp, char *err_str)
+{
+       struct ibv_device **dev_list;
+       int numdev;
+       int i;
+       int ret = 0;
+
+       dev_list = ibv_get_device_list(&numdev);
+       if (!dev_list || !numdev) {
+               return 0;
+       }
+
+       for (i = 0; i < numdev; ++i) {
+               /*
+                * XXX - do the notions of "up", "running", or
+                * "connected" apply here?
+                */
+               if (!add_dev(devlistp, dev_list[i]->name, 0, "RDMA sniffer", err_str)) {
+                       ret = -1;
+                       goto out;
+               }
+       }
+
+out:
+       ibv_free_device_list(dev_list);
+       return ret;
+}
diff --git a/pcap-rdmasniff.h b/pcap-rdmasniff.h
new file mode 100644 (file)
index 0000000..ff1f3c2
--- /dev/null
@@ -0,0 +1,2 @@
+pcap_t *rdmasniff_create(const char *device, char *ebuf, int *is_ours);
+int rdmasniff_findalldevs(pcap_if_list_t *devlistp, char *err_str);
diff --git a/pcap-rpcap-int.h b/pcap-rpcap-int.h
new file mode 100644 (file)
index 0000000..e707a85
--- /dev/null
@@ -0,0 +1,75 @@
+/*
+ * 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_INT_H__
+#define __PCAP_RPCAP_INT_H__
+
+#include "pcap.h"
+#include "sockutils.h" /* Needed for some structures (like SOCKET, sockaddr_in) which are used here */
+
+/*
+ * \file pcap-rpcap-int.h
+ *
+ * This file keeps all the definitions used by the RPCAP client and server,
+ * other than the protocol definitions.
+ *
+ * \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.
+ */
+
+/*********************************************************
+ *                                                       *
+ * General definitions / typedefs for the RPCAP protocol *
+ *                                                       *
+ *********************************************************/
+
+/*
+ * \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
+
+/*********************************************************
+ *                                                       *
+ * Exported function prototypes                          *
+ *                                                       *
+ *********************************************************/
+void rpcap_createhdr(struct rpcap_header *header, uint8 type, uint16 value, uint32 length);
+int rpcap_senderror(SOCKET sock, char *error, unsigned short errcode, char *errbuf);
+
+#endif
diff --git a/pcap-rpcap.c b/pcap-rpcap.c
new file mode 100644 (file)
index 0000000..705f06f
--- /dev/null
@@ -0,0 +1,3233 @@
+/*
+ * 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 "ftmacros.h"
+
+#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 "sockutils.h"
+#include "pcap-int.h"
+#include "rpcap-protocol.h"
+#include "pcap-rpcap.h"
+
+/*
+ * This file contains the pcap module for capturing from a remote machine's
+ * interfaces using 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 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.
+ *
+ * XXX - actually, null-terminating the error string is part of the
+ * contract for the pcap API; if there's any place in the pcap code
+ * that doesn't guarantee null-termination, even at the expense of
+ * cutting the message short, that's a bug and needs to be fixed.
+ */
+
+#define PCAP_STATS_STANDARD    0       /* Used by pcap_stats_rpcap to see if we want standard or extended statistics */
+#ifdef _WIN32
+#define PCAP_STATS_EX          1       /* Used by pcap_stats_rpcap to see if we want standard or extended statistics */
+#endif
+
+/*
+ * \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;
+       uint8 protocol_version;
+       struct activehosts *next;
+};
+
+/* Keeps a list of all the opened connections in the active mode. */
+static struct activehosts *activeHosts;
+
+/*
+ * 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.
+ */
+static SOCKET sockmain;
+
+/*
+ * Private data for capturing remotely using the rpcap protocol.
+ */
+struct pcap_rpcap {
+       /*
+        * This is '1' if we're the network client; it is needed by several
+        * functions (such as pcap_setfilter()) to know whether they have
+        * to use the socket or 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() */
+       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. */
+
+       uint8 protocol_version;         /* negotiated protocol version */
+
+       unsigned int TotNetDrops;       /* keeps the number of packets that have been dropped by the network */
+
+       /*
+        * This keeps the number of packets that have been received by the
+        * application.
+        *
+        * Packets dropped by the kernel buffer are not counted in this
+        * variable. It 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;
+
+       struct pcap_stat stat;
+       /* XXX */
+       struct pcap *next;              /* list of open pcaps that need stuff cleared on close */
+};
+
+/****************************************************
+ *                                                  *
+ * Locally defined functions                        *
+ *                                                  *
+ ****************************************************/
+static struct pcap_stat *rpcap_stats_rpcap(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 void pcap_save_current_filter_rpcap(pcap_t *fp, const char *filter);
+static int pcap_setfilter_rpcap(pcap_t *fp, struct bpf_program *prog);
+static int pcap_setsampling_remote(pcap_t *fp);
+static int pcap_startcapture_remote(pcap_t *fp);
+static int rpcap_recv_msg_header(SOCKET sock, struct rpcap_header *header, char *errbuf);
+static int rpcap_check_msg_ver(SOCKET sock, uint8 expected_ver, struct rpcap_header *header, char *errbuf);
+static int rpcap_check_msg_type(SOCKET sock, uint8 request_type, struct rpcap_header *header, uint16 *errcode, char *errbuf);
+static int rpcap_process_msg_header(SOCKET sock, uint8 ver, uint8 request_type, struct rpcap_header *header, char *errbuf);
+static int rpcap_recv(SOCKET sock, void *buffer, size_t toread, uint32 *plen, char *errbuf);
+static void rpcap_msg_err(SOCKET sockctrl, uint32 plen, char *remote_errbuf);
+static int rpcap_discard(SOCKET sock, uint32 len, char *errbuf);
+static int rpcap_read_packet_msg(SOCKET sock, pcap_t *p, size_t size);
+
+/****************************************************
+ *                                                  *
+ * Function bodies                                  *
+ *                                                  *
+ ****************************************************/
+
+/*
+ * This function translates (i.e. de-serializes) a 'rpcap_sockaddr'
+ * structure from the network byte order to a 'sockaddr_in" or
+ * 'sockaddr_in6' structure in the host byte order.
+ *
+ * It accepts an 'rpcap_sockaddr' structure as it is received from the
+ * network, and checks the address family field against various values
+ * to see whether it looks like an IPv4 address, an IPv6 address, or
+ * neither of those.  It checks for multiple values in order to try
+ * to handle older rpcap daemons that sent the native OS's 'sockaddr_in'
+ * or 'sockaddr_in6' structures over the wire with some members
+ * byte-swapped, and to handle the fact that AF_INET6 has different
+ * values on different OSes.
+ *
+ * For IPv4 addresses, it converts the address family to host byte
+ * order from network byte order and puts it into the structure,
+ * sets the length if a sockaddr structure has a length, converts the
+ * port number to host byte order from network byte order and puts
+ * it into the structure, copies over the IPv4 address, and zeroes
+ * out the zero padding.
+ *
+ * For IPv6 addresses, it converts the address family to host byte
+ * order from network byte order and puts it into the structure,
+ * sets the length if a sockaddr structure has a length, converts the
+ * port number and flow information to host byte order from network
+ * byte order and puts them into the structure, copies over the IPv6
+ * address, and converts the scope ID to host byte order from network
+ * byte order and puts it into the structure.
+ *
+ * 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, or is of an address family other
+ * than AF_INET or AF_INET6, so the RPCAP daemon sent a 'sockaddr_storage'
+ * structure containing all 'zero' values.
+ *
+ * Older RPCAPDs sent the addresses over the wire in the OS's native
+ * structure format.  For most OSes, this looks like the over-the-wire
+ * format, but might have a different value for AF_INET6 than the value
+ * on the machine receiving the reply.  For OSes with the newer BSD-style
+ * sockaddr structures, this has, instead of a 2-byte address family,
+ * a 1-byte structure length followed by a 1-byte address family.  The
+ * RPCAPD code would put the address family in network byte order before
+ * sending it; that would set it to 0 on a little-endian machine, as
+ * htons() of any value between 1 and 255 would result in a value > 255,
+ * with its lower 8 bits zero, so putting that back into a 1-byte field
+ * would set it to 0.
+ *
+ * Therefore, for older RPCAPDs running on an OS with newer BSD-style
+ * sockaddr structures, the family field, if treated as a big-endian
+ * (network byte order) 16-bit field, would be:
+ *
+ *     (length << 8) | family if sent by a big-endian machine
+ *     (length << 8) if sent by a little-endian machine
+ *
+ * For current RPCAPDs, and for older RPCAPDs running on an OS with
+ * older BSD-style sockaddr structures, the family field, if treated
+ * as a big-endian 16-bit field, would just contain the family.
+ *
+ * \param sockaddrin: a 'rpcap_sockaddr' 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.
+ */
+
+/*
+ * Possible IPv4 family values other than the designated over-the-wire value,
+ * which is 2 (because everybody uses 2 for AF_INET4).
+ */
+#define SOCKADDR_IN_LEN                16      /* length of struct sockaddr_in */
+#define SOCKADDR_IN6_LEN       28      /* length of struct sockaddr_in6 */
+#define NEW_BSD_AF_INET_BE     ((SOCKADDR_IN_LEN << 8) | 2)
+#define NEW_BSD_AF_INET_LE     (SOCKADDR_IN_LEN << 8)
+
+/*
+ * Possible IPv6 family values other than the designated over-the-wire value,
+ * which is 23 (because that's what Windows uses, and most RPCAP servers
+ * out there are probably running Windows, as WinPcap includes the server
+ * but few if any UN*Xes build and ship it).
+ *
+ * The new BSD sockaddr structure format was in place before 4.4-Lite, so
+ * all the free-software BSDs use it.
+ */
+#define NEW_BSD_AF_INET6_BSD_BE                ((SOCKADDR_IN6_LEN << 8) | 24)  /* NetBSD, OpenBSD, BSD/OS */
+#define NEW_BSD_AF_INET6_FREEBSD_BE    ((SOCKADDR_IN6_LEN << 8) | 28)  /* FreeBSD, DragonFly BSD */
+#define NEW_BSD_AF_INET6_DARWIN_BE     ((SOCKADDR_IN6_LEN << 8) | 30)  /* macOS, iOS, anything else Darwin-based */
+#define NEW_BSD_AF_INET6_LE            (SOCKADDR_IN6_LEN << 8)
+#define LINUX_AF_INET6                 10
+#define HPUX_AF_INET6                  22
+#define AIX_AF_INET6                   24
+#define SOLARIS_AF_INET6               26
+
+static int
+rpcap_deseraddr(struct rpcap_sockaddr *sockaddrin, struct sockaddr_storage **sockaddrout, char *errbuf)
+{
+       /* Warning: we support only AF_INET and AF_INET6 */
+       switch (ntohs(sockaddrin->family))
+       {
+       case RPCAP_AF_INET:
+       case NEW_BSD_AF_INET_BE:
+       case NEW_BSD_AF_INET_LE:
+               {
+               struct rpcap_sockaddr_in *sockaddrin_ipv4;
+               struct sockaddr_in *sockaddrout_ipv4;
+
+               (*sockaddrout) = (struct sockaddr_storage *) malloc(sizeof(struct sockaddr_in));
+               if ((*sockaddrout) == NULL)
+               {
+                       pcap_fmt_errmsg_for_errno(errbuf, PCAP_ERRBUF_SIZE,
+                           errno, "malloc() failed");
+                       return -1;
+               }
+               sockaddrin_ipv4 = (struct rpcap_sockaddr_in *) sockaddrin;
+               sockaddrout_ipv4 = (struct sockaddr_in *) (*sockaddrout);
+               sockaddrout_ipv4->sin_family = AF_INET;
+               sockaddrout_ipv4->sin_port = ntohs(sockaddrin_ipv4->port);
+               memcpy(&sockaddrout_ipv4->sin_addr, &sockaddrin_ipv4->addr, sizeof(sockaddrout_ipv4->sin_addr));
+               memset(sockaddrout_ipv4->sin_zero, 0, sizeof(sockaddrout_ipv4->sin_zero));
+               break;
+               }
+
+#ifdef AF_INET6
+       case RPCAP_AF_INET6:
+       case NEW_BSD_AF_INET6_BSD_BE:
+       case NEW_BSD_AF_INET6_FREEBSD_BE:
+       case NEW_BSD_AF_INET6_DARWIN_BE:
+       case NEW_BSD_AF_INET6_LE:
+       case LINUX_AF_INET6:
+       case HPUX_AF_INET6:
+       case AIX_AF_INET6:
+       case SOLARIS_AF_INET6:
+               {
+               struct rpcap_sockaddr_in6 *sockaddrin_ipv6;
+               struct sockaddr_in6 *sockaddrout_ipv6;
+
+               (*sockaddrout) = (struct sockaddr_storage *) malloc(sizeof(struct sockaddr_in6));
+               if ((*sockaddrout) == NULL)
+               {
+                       pcap_fmt_errmsg_for_errno(errbuf, PCAP_ERRBUF_SIZE,
+                           errno, "malloc() failed");
+                       return -1;
+               }
+               sockaddrin_ipv6 = (struct rpcap_sockaddr_in6 *) sockaddrin;
+               sockaddrout_ipv6 = (struct sockaddr_in6 *) (*sockaddrout);
+               sockaddrout_ipv6->sin6_family = AF_INET6;
+               sockaddrout_ipv6->sin6_port = ntohs(sockaddrin_ipv6->port);
+               sockaddrout_ipv6->sin6_flowinfo = ntohl(sockaddrin_ipv6->flowinfo);
+               memcpy(&sockaddrout_ipv6->sin6_addr, &sockaddrin_ipv6->addr, sizeof(sockaddrout_ipv6->sin6_addr));
+               sockaddrout_ipv6->sin6_scope_id = ntohl(sockaddrin_ipv6->scope_id);
+               break;
+               }
+#endif
+
+       default:
+               /*
+                * It is neither AF_INET nor AF_INET6 (or, if the OS doesn't
+                * support AF_INET6, it's not AF_INET).
+                */
+               *sockaddrout = NULL;
+               break;
+       }
+       return 0;
+}
+
+/*
+ * This function reads a packet from the network socket.  It does not
+ * deliver the packet to a pcap_dispatch()/pcap_loop() callback (hence
+ * the "nocb" string into its name).
+ *
+ * This function is called by pcap_read_rpcap().
+ *
+ * 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 pcap_rpcap *pr = p->priv;        /* structure used when doing a remote live capture */
+       struct rpcap_header *header;            /* general header according to the RPCAP format */
+       struct rpcap_pkthdr *net_pkt_header;    /* header of the packet, from the message */
+       u_char *net_pkt_data;                   /* packet data from the message */
+       uint32 plen;
+       int retval;                             /* generic return value */
+       int msglen;
+
+       /* Structures needed for the select() call */
+       struct timeval tv;                      /* maximum time the select() can block waiting for data */
+       fd_set rfds;                            /* set of socket descriptors we have to check */
+
+       /*
+        * Define the packet buffer 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(pr->rmt_sockdata, &rfds);
+
+       retval = select((int) pr->rmt_sockdata + 1, &rfds, NULL, NULL, &tv);
+       if (retval == -1)
+       {
+#ifndef _WIN32
+               if (errno == EINTR)
+               {
+                       /* Interrupted. */
+                       return 0;
+               }
+#endif
+               sock_geterror("select()", p->errbuf, PCAP_ERRBUF_SIZE);
+               return -1;
+       }
+
+       /* There is no data waiting, so return '0' */
+       if (retval == 0)
+               return 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 *) p->buffer;
+       net_pkt_header = (struct rpcap_pkthdr *) ((char *)p->buffer + sizeof(struct rpcap_header));
+       net_pkt_data = (u_char *)p->buffer + sizeof(struct rpcap_header) + sizeof(struct rpcap_pkthdr);
+
+       if (pr->rmt_flags & PCAP_OPENFLAG_DATATX_UDP)
+       {
+               /* Read the entire message from the network */
+               msglen = sock_recv_dgram(pr->rmt_sockdata, p->buffer,
+                   p->bufsize, p->errbuf, PCAP_ERRBUF_SIZE);
+               if (msglen == -1)
+               {
+                       /* Network error. */
+                       return -1;
+               }
+               if (msglen == -3)
+               {
+                       /* Interrupted receive. */
+                       return 0;
+               }
+               if ((size_t)msglen < sizeof(struct rpcap_header))
+               {
+                       /*
+                        * Message is shorter than an rpcap header.
+                        */
+                       pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
+                           "UDP packet message is shorter than an rpcap header");
+                       return -1;
+               }
+               plen = ntohl(header->plen);
+               if ((size_t)msglen < sizeof(struct rpcap_header) + plen)
+               {
+                       /*
+                        * Message is shorter than the header claims it
+                        * is.
+                        */
+                       pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
+                           "UDP packet message is shorter than its rpcap header claims");
+                       return -1;
+               }
+       }
+       else
+       {
+               int status;
+
+               if ((size_t)p->cc < sizeof(struct rpcap_header))
+               {
+                       /*
+                        * We haven't read any of the packet header yet.
+                        * The size we should get is the size of the
+                        * packet header.
+                        */
+                       status = rpcap_read_packet_msg(pr->rmt_sockdata, p,
+                           sizeof(struct rpcap_header));
+                       if (status == -1)
+                       {
+                               /* Network error. */
+                               return -1;
+                       }
+                       if (status == -3)
+                       {
+                               /* Interrupted receive. */
+                               return 0;
+                       }
+               }
+
+               /*
+                * We have the header, so we know how long the
+                * message payload is.  The size we should get
+                * is the size of the packet header plus the
+                * size of the payload.
+                */
+               plen = ntohl(header->plen);
+               if (plen > p->bufsize - sizeof(struct rpcap_header))
+               {
+                       /*
+                        * This is bigger than the largest
+                        * record we'd expect.  (We do it by
+                        * subtracting in order to avoid an
+                        * overflow.)
+                        */
+                       pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
+                           "Server sent us a message larger than the largest expected packet message");
+                       return -1;
+               }
+               status = rpcap_read_packet_msg(pr->rmt_sockdata, p,
+                   sizeof(struct rpcap_header) + plen);
+               if (status == -1)
+               {
+                       /* Network error. */
+                       return -1;
+               }
+               if (status == -3)
+               {
+                       /* Interrupted receive. */
+                       return 0;
+               }
+
+               /*
+                * We have the entire message; reset the buffer pointer
+                * and count, as the next read should start a new
+                * message.
+                */
+               p->bp = p->buffer;
+               p->cc = 0;
+       }
+
+       /*
+        * We have the entire message.
+        */
+       header->plen = plen;
+
+       /*
+        * Did the server specify the version we negotiated?
+        */
+       if (rpcap_check_msg_ver(pr->rmt_sockdata, pr->protocol_version,
+           header, p->errbuf) == -1)
+       {
+               return 0;       /* Return 'no packets received' */
+       }
+
+       /*
+        * Is this a RPCAP_MSG_PACKET message?
+        */
+       if (header->type != RPCAP_MSG_PACKET)
+       {
+               return 0;       /* Return 'no packets received' */
+       }
+
+       if (ntohl(net_pkt_header->caplen) > plen)
+       {
+               pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
+                   "Packet's captured data goes past the end of the received packet message.");
+               return -1;
+       }
+
+       /* Fill in packet header */
+       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);
+
+       /* Supply a pointer to the beginning of the packet data */
+       *pkt_data = net_pkt_data;
+
+       /*
+        * 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
+        */
+       pr->TotCapt++;
+
+       if (pr->rmt_flags & PCAP_OPENFLAG_DATATX_UDP)
+       {
+               unsigned int npkt;
+
+               /* 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 (pr->TotCapt != npkt)
+               {
+                       pr->TotNetDrops += (npkt - pr->TotCapt);
+                       pr->TotCapt = npkt;
+               }
+       }
+
+       /* Packet read successfully */
+       return 1;
+}
+
+/*
+ * This function reads a packet from the network 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.
+ */
+static int pcap_read_rpcap(pcap_t *p, int cnt, pcap_handler callback, u_char *user)
+{
+       struct pcap_rpcap *pr = p->priv;        /* structure used when doing a remote live capture */
+       struct pcap_pkthdr pkt_header;
+       u_char *pkt_data;
+       int n = 0;
+       int ret;
+
+       /*
+        * If this is client-side, and we haven't already started
+        * the capture, start it now.
+        */
+       if (pr->rmt_clientside)
+       {
+               /* We are on an remote capture */
+               if (!pr->rmt_capstarted)
+               {
+                       /*
+                        * The capture isn't started yet, so try to
+                        * start it.
+                        */
+                       if (pcap_startcapture_remote(p))
+                               return -1;
+               }
+       }
+
+       while (n < cnt || PACKET_COUNT_IS_UNLIMITED(cnt))
+       {
+               /*
+                * Has "pcap_breakloop()" been called?
+                */
+               if (p->break_loop) {
+                       /*
+                        * Yes - clear the flag that indicates that it
+                        * has, and return PCAP_ERROR_BREAK to indicate
+                        * that we were told to break out of the loop.
+                        */
+                       p->break_loop = 0;
+                       return (PCAP_ERROR_BREAK);
+               }
+
+               /*
+                * Read some packets.
+                */
+               ret = pcap_read_nocb_remote(p, &pkt_header, &pkt_data);
+               if (ret == 1)
+               {
+                       /*
+                        * We got a packet.  Hand it to the callback
+                        * and count it so we can return the count.
+                        */
+                       (*callback)(user, &pkt_header, pkt_data);
+                       n++;
+               }
+               else if (ret == -1)
+               {
+                       /* Error. */
+                       return ret;
+               }
+               else
+               {
+                       /*
+                        * No packet; this could mean that we timed
+                        * out, or that we got interrupted, or that
+                        * we got a bad packet.
+                        *
+                        * Were we told to break out of the loop?
+                        */
+                       if (p->break_loop) {
+                               /*
+                                * Yes.
+                                */
+                               p->break_loop = 0;
+                               return (PCAP_ERROR_BREAK);
+                       }
+                       /* No - return the number of packets we've processed. */
+                       return n;
+               }
+       }
+       return n;
+}
+
+/*
+ * This function sends a CLOSE command to the capture server.
+ *
+ * It is called when the user calls pcap_close().  It sends a command
+ * to our peer that says 'ok, let's stop capturing'.
+ *
+ * WARNING: Since we're closing the connection, we do not check for errors.
+ */
+static void pcap_cleanup_rpcap(pcap_t *fp)
+{
+       struct pcap_rpcap *pr = fp->priv;       /* structure used when doing a remote live capture */
+       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? */
+
+       /* detect if we're in active mode */
+       temp = activeHosts;
+       while (temp)
+       {
+               if (temp->sockctrl == pr->rmt_sockctrl)
+               {
+                       active = 1;
+                       break;
+               }
+               temp = temp->next;
+       }
+
+       if (!active)
+       {
+               rpcap_createhdr(&header, pr->protocol_version,
+                   RPCAP_MSG_CLOSE, 0, 0);
+
+               /*
+                * Send the close request; don't report any errors, as
+                * we're closing this pcap_t, and have no place to report
+                * the error.  No reply is sent to this message.
+                */
+               (void)sock_send(pr->rmt_sockctrl, (char *)&header,
+                   sizeof(struct rpcap_header), NULL, 0);
+       }
+       else
+       {
+               rpcap_createhdr(&header, pr->protocol_version,
+                   RPCAP_MSG_ENDCAP_REQ, 0, 0);
+
+               /*
+                * Send the end capture request; don't report any errors,
+                * as we're closing this pcap_t, and have no place to
+                * report the error.
+                */
+               if (sock_send(pr->rmt_sockctrl, (char *)&header,
+                   sizeof(struct rpcap_header), NULL, 0) == 0)
+               {
+                       /*
+                        * Wait for the answer; don't report any errors,
+                        * as we're closing this pcap_t, and have no
+                        * place to report the error.
+                        */
+                       if (rpcap_process_msg_header(pr->rmt_sockctrl,
+                           pr->protocol_version, RPCAP_MSG_ENDCAP_REQ,
+                           &header, NULL) == 0)
+                       {
+                               (void)rpcap_discard(pr->rmt_sockctrl,
+                                   header.plen, NULL);
+                       }
+               }
+       }
+
+       if (pr->rmt_sockdata)
+       {
+               sock_close(pr->rmt_sockdata, NULL, 0);
+               pr->rmt_sockdata = 0;
+       }
+
+       if ((!active) && (pr->rmt_sockctrl))
+               sock_close(pr->rmt_sockctrl, NULL, 0);
+
+       pr->rmt_sockctrl = 0;
+
+       if (pr->currentfilter)
+       {
+               free(pr->currentfilter);
+               pr->currentfilter = NULL;
+       }
+
+       pcap_cleanup_live_common(fp);
+
+       /* To avoid inconsistencies in the number of sock_init() */
+       sock_cleanup();
+}
+
+/*
+ * This function retrieves network statistics from our peer;
+ * it provides only the standard statistics.
+ */
+static int pcap_stats_rpcap(pcap_t *p, struct pcap_stat *ps)
+{
+       struct pcap_stat *retval;
+
+       retval = rpcap_stats_rpcap(p, ps, PCAP_STATS_STANDARD);
+
+       if (retval)
+               return 0;
+       else
+               return -1;
+}
+
+#ifdef _WIN32
+/*
+ * This function retrieves network statistics from our peer;
+ * it provides the additional statistics supported by pcap_stats_ex().
+ */
+static struct pcap_stat *pcap_stats_ex_rpcap(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_rpcap(p, &(p->stat), PCAP_STATS_EX));
+}
+#endif
+
+/*
+ * This function retrieves network statistics from our peer.  It
+ * is used by the two previous functions.
+ *
+ * It can be called in two modes:
+ * - PCAP_STATS_STANDARD: if we want just standard statistics (i.e.,
+ *   for pcap_stats())
+ * - PCAP_STATS_EX: if we want extended statistics (i.e., for
+ *   pcap_stats_ex())
+ *
+ * This 'mode' parameter is needed because in pcap_stats() the variable that
+ * keeps the statistics is allocated by the user. On Windows, this structure
+ * has been extended in order to keep new stats. However, if the user has a
+ * smaller structure and it passes it to pcap_stats(), this function will
+ * try to fill in more data than the size of the structure, so that memory
+ * after the structure will be overwritten.
+ *
+ * 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 no longer exists because the structure that's filled
+ * in is part of the pcap_t, so that it can be guaranteed to be large
+ * enough for the additional statistics.
+ *
+ * \param p: the pcap_t structure related to the current instance.
+ *
+ * \param ps: a pointer to a 'pcap_stat' structure, needed for compatibility
+ * with pcap_stat(), where 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_rpcap(pcap_t *p, struct pcap_stat *ps, int mode)
+{
+       struct pcap_rpcap *pr = p->priv;        /* structure used when doing a remote live capture */
+       struct rpcap_header header;             /* header of the RPCAP packet */
+       struct rpcap_stats netstats;            /* statistics sent on the network */
+       uint32 plen;                            /* data remaining in the message */
+
+#ifdef _WIN32
+       if (mode != PCAP_STATS_STANDARD && mode != PCAP_STATS_EX)
+#else
+       if (mode != PCAP_STATS_STANDARD)
+#endif
+       {
+               pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
+                   "Invalid stats mode %d", mode);
+               return NULL;
+       }
+
+       /*
+        * If the capture has not yet started, we cannot request statistics
+        * for the capture from our peer, so we return 0 for all statistics,
+        * as nothing's been seen yet.
+        */
+       if (!pr->rmt_capstarted)
+       {
+               ps->ps_drop = 0;
+               ps->ps_ifdrop = 0;
+               ps->ps_recv = 0;
+#ifdef _WIN32
+               if (mode == PCAP_STATS_EX)
+               {
+                       ps->ps_capt = 0;
+                       ps->ps_sent = 0;
+                       ps->ps_netdrop = 0;
+               }
+#endif /* _WIN32 */
+
+               return ps;
+       }
+
+       rpcap_createhdr(&header, pr->protocol_version,
+           RPCAP_MSG_STATS_REQ, 0, 0);
+
+       /* Send the PCAP_STATS command */
+       if (sock_send(pr->rmt_sockctrl, (char *)&header,
+           sizeof(struct rpcap_header), p->errbuf, PCAP_ERRBUF_SIZE) < 0)
+               return NULL;            /* Unrecoverable network error */
+
+       /* Receive and process the reply message header. */
+       if (rpcap_process_msg_header(pr->rmt_sockctrl, pr->protocol_version,
+           RPCAP_MSG_STATS_REQ, &header, p->errbuf) == -1)
+               return NULL;            /* Error */
+
+       plen = header.plen;
+
+       /* Read the reply body */
+       if (rpcap_recv(pr->rmt_sockctrl, (char *)&netstats,
+           sizeof(struct rpcap_stats), &plen, p->errbuf) == -1)
+               goto error;
+
+       ps->ps_drop = ntohl(netstats.krnldrop);
+       ps->ps_ifdrop = ntohl(netstats.ifdrop);
+       ps->ps_recv = ntohl(netstats.ifrecv);
+#ifdef _WIN32
+       if (mode == PCAP_STATS_EX)
+       {
+               ps->ps_capt = pr->TotCapt;
+               ps->ps_netdrop = pr->TotNetDrops;
+               ps->ps_sent = ntohl(netstats.svrcapt);
+       }
+#endif /* _WIN32 */
+
+       /* Discard the rest of the message. */
+       if (rpcap_discard(pr->rmt_sockctrl, plen, p->errbuf) == -1)
+               goto error_nodiscard;
+
+       return ps;
+
+error:
+       /*
+        * Discard the rest of the message.
+        * We already reported an error; if this gets an error, just
+        * drive on.
+        */
+       (void)rpcap_discard(pr->rmt_sockctrl, plen, NULL);
+
+error_nodiscard:
+       return NULL;
+}
+
+/*
+ * This function returns the entry in the list of active hosts for this
+ * active connection (active mode only), or NULL if there is no
+ * active connection or an error occurred.  It is just for internal
+ * use.
+ *
+ * \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 error: a pointer to an int that is set to 1 if an error occurred
+ * 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 entry for this host in the list of active connections
+ * if found, NULL if it's not found or there's an error.
+ */
+static struct activehosts *
+rpcap_remoteact_getsock(const char *host, int *error, 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));
+               *error = 1;
+               return NULL;
+       }
+
+       temp = activeHosts;
+
+       while (temp)
+       {
+               ai_next = addrinfo;
+               while (ai_next)
+               {
+                       if (sock_cmpaddr(&temp->host, (struct sockaddr_storage *) ai_next->ai_addr) == 0)
+                       {
+                               *error = 0;
+                               freeaddrinfo(addrinfo);
+                               return temp;
+                       }
+
+                       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.
+        */
+       *error = 0;
+       return NULL;
+}
+
+/*
+ * This function starts a remote capture.
+ *
+ * This function is required 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.
+ *
+ * \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.
+ */
+static int pcap_startcapture_remote(pcap_t *fp)
+{
+       struct pcap_rpcap *pr = fp->priv;       /* structure used when doing a remote live capture */
+       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 data connection */
+       uint32 plen;
+       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;
+       socklen_t itemp;
+       int sockbufsize = 0;
+       uint32 server_sockbufsize;
+
+       /*
+        * 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 == pr->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(pr->rmt_sockctrl, (struct sockaddr *) &saddr, &saddrlen) == -1)
+       {
+               sock_geterror("getsockname()", fp->errbuf, PCAP_ERRBUF_SIZE);
+               goto error_nodiscard;
+       }
+       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_nodiscard;
+       }
+
+       /*
+        * 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) || (pr->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 = (pr->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_nodiscard;
+
+               if ((sockdata = sock_open(addrinfo, SOCKOPEN_SERVER,
+                       1 /* max 1 connection in queue */, fp->errbuf, PCAP_ERRBUF_SIZE)) == INVALID_SOCKET)
+                       goto error_nodiscard;
+
+               /* 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_nodiscard;
+               }
+
+               /* 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_nodiscard;
+               }
+       }
+
+       /*
+        * 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_nodiscard;
+
+       rpcap_createhdr((struct rpcap_header *) sendbuf,
+           pr->protocol_version, 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_nodiscard;
+
+       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) || (pr->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 (pr->rmt_flags & PCAP_OPENFLAG_PROMISCUOUS)
+               startcapreq->flags |= RPCAP_STARTCAPREQ_FLAG_PROMISC;
+       if (pr->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_nodiscard;
+
+       if (sock_send(pr->rmt_sockctrl, sendbuf, sendbufidx, fp->errbuf,
+           PCAP_ERRBUF_SIZE) < 0)
+               goto error_nodiscard;
+
+       /* Receive and process the reply message header. */
+       if (rpcap_process_msg_header(pr->rmt_sockctrl, pr->protocol_version,
+           RPCAP_MSG_STARTCAP_REQ, &header, fp->errbuf) == -1)
+               goto error_nodiscard;
+
+       plen = header.plen;
+
+       if (rpcap_recv(pr->rmt_sockctrl, (char *)&startcapreply,
+           sizeof(struct rpcap_startcapreply), &plen, fp->errbuf) == -1)
+               goto error;
+
+       /*
+        * 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 (!(pr->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 = (pr->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 == INVALID_SOCKET)
+                       {
+                               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 */
+       pr->rmt_sockdata = sockdata;
+
+       /*
+        * Set the size of the socket buffer for the data socket.
+        * It has the same size as the local capture buffer used
+        * on the other side of the connection.
+        */
+       server_sockbufsize = 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(): getsockopt() failed", fp->errbuf, PCAP_ERRBUF_SIZE);
+               goto error;
+       }
+
+       /*
+        * 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 (server_sockbufsize <= (u_int) fp->snapshot)
+               server_sockbufsize += sizeof(struct pcap_pkthdr);
+
+       /* if the current socket buffer is smaller than the desired one */
+       if ((u_int) sockbufsize < server_sockbufsize)
+       {
+               /*
+                * Loop until the buffer size is OK or the original
+                * socket buffer size is larger than this one.
+                */
+               for (;;)
+               {
+                       res = setsockopt(sockdata, SOL_SOCKET, SO_RCVBUF,
+                           (char *)&(server_sockbufsize),
+                           sizeof(server_sockbufsize));
+
+                       if (res == 0)
+                               break;
+
+                       /*
+                        * If something goes wrong, halve the buffer size
+                        * (checking that it does not become smaller than
+                        * the current one).
+                        */
+                       server_sockbufsize /= 2;
+
+                       if ((u_int) sockbufsize >= server_sockbufsize)
+                       {
+                               server_sockbufsize = 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
+        * largest possible packet message for the snapshot size,
+        * namely the length of the message header plus the length
+        * of the packet header plus the snapshot length.
+        */
+       fp->bufsize = sizeof(struct rpcap_header) + sizeof(struct rpcap_pkthdr) + fp->snapshot;
+
+       fp->buffer = (u_char *)malloc(fp->bufsize);
+       if (fp->buffer == NULL)
+       {
+               pcap_fmt_errmsg_for_errno(fp->errbuf, PCAP_ERRBUF_SIZE,
+                   errno, "malloc");
+               goto error;
+       }
+
+       /*
+        * The buffer is currently empty.
+        */
+       fp->bp = fp->buffer;
+       fp->cc = 0;
+
+       /* Discard the rest of the message. */
+       if (rpcap_discard(pr->rmt_sockctrl, plen, fp->errbuf) == -1)
+               goto error_nodiscard;
+
+       /*
+        * 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 (pr->rmt_flags & PCAP_OPENFLAG_NOCAPTURE_RPCAP)
+       {
+               struct bpf_program fcode;
+
+               if (pcap_createfilter_norpcappkt(fp, &fcode) == -1)
+                       goto error;
+
+               /* We cannot use 'pcap_setfilter_rpcap' because formally the capture has not been started yet */
+               /* (the 'pr->rmt_capstarted' variable will be updated some lines below) */
+               if (pcap_updatefilter_remote(fp, &fcode) == -1)
+                       goto error;
+
+               pcap_freecode(&fcode);
+       }
+
+       pr->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.
+        */
+
+       /*
+        * Discard the rest of the message.
+        * We already reported an error; if this gets an error, just
+        * drive on.
+        */
+       (void)rpcap_discard(pr->rmt_sockctrl, plen, NULL);
+
+error_nodiscard:
+       if ((sockdata) && (sockdata != -1))             /* we can be here because sockdata said 'error' */
+               sock_close(sockdata, NULL, 0);
+
+       if (!active)
+               sock_close(pr->rmt_sockctrl, NULL, 0);
+
+       if (addrinfo != NULL)
+               freeaddrinfo(addrinfo);
+
+       /*
+        * We do not have to call pcap_close() here, because this function is always called
+        * by the user in case something bad happens
+        */
+#if 0
+       if (fp)
+       {
+               pcap_close(fp);
+               fp= NULL;
+       }
+#endif
+
+       return -1;
+}
+
+/*
+ * This function takes a bpf program and sends it to the other host.
+ *
+ * This function can be called in two cases:
+ * - pcap_startcapture_remote() 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. pcap_setfilter()
+ *   after the capture has been started)
+ *
+ * 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;
+}
+
+/*
+ * This function updates a filter on a remote host.
+ *
+ * It is called when the user wants to update a filter.
+ * In case we're capturing from the network, it sends the filter to our
+ * peer.
+ * This function is *not* called automatically when the user calls
+ * pcap_setfilter().
+ * There will be two cases:
+ * - the capture has been started: in this case, pcap_setfilter_rpcap()
+ *   calls pcap_updatefilter_remote()
+ * - the capture has not started yet: in this case, pcap_setfilter_rpcap()
+ *   stores the filter into the pcap_t structure, and then the filter is
+ *   sent with pcap_startcap().
+ *
+ * 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.
+ *
+ * XXX - we really should have pcap_setfilter() always discard packets
+ * received with the old filter, and have a separate pcap_setfilter_noflush()
+ * function that doesn't discard any packets.
+ */
+static int pcap_updatefilter_remote(pcap_t *fp, struct bpf_program *prog)
+{
+       struct pcap_rpcap *pr = fp->priv;       /* structure used when doing a remote live capture */
+       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 */
+
+       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,
+           pr->protocol_version, 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(pr->rmt_sockctrl, sendbuf, sendbufidx, fp->errbuf,
+           PCAP_ERRBUF_SIZE) < 0)
+               return -1;
+
+       /* Receive and process the reply message header. */
+       if (rpcap_process_msg_header(pr->rmt_sockctrl, pr->protocol_version,
+           RPCAP_MSG_UPDATEFILTER_REQ, &header, fp->errbuf) == -1)
+               return -1;
+
+       /*
+        * It shouldn't have any contents; discard it if it does.
+        */
+       if (rpcap_discard(pr->rmt_sockctrl, header.plen, fp->errbuf) == -1)
+               return -1;
+
+       return 0;
+}
+
+static void
+pcap_save_current_filter_rpcap(pcap_t *fp, const char *filter)
+{
+       struct pcap_rpcap *pr = fp->priv;       /* structure used when doing a remote live capture */
+
+       /*
+        * Check if:
+        *  - We are on an remote capture
+        *  - we do not want to capture RPCAP traffic
+        *
+        * If so, we have to save the current filter, because we have to
+        * add some piece of stuff later
+        */
+       if (pr->rmt_clientside &&
+           (pr->rmt_flags & PCAP_OPENFLAG_NOCAPTURE_RPCAP))
+       {
+               if (pr->currentfilter)
+                       free(pr->currentfilter);
+
+               if (filter == NULL)
+                       filter = "";
+
+               pr->currentfilter = strdup(filter);
+       }
+}
+
+/*
+ * This function sends a filter to a remote host.
+ *
+ * This function is called when the user wants to set a filter.
+ * It sends the filter to our peer.
+ * This function is called automatically when the user calls pcap_setfilter().
+ *
+ * Parameters and return values are exactly the same of pcap_setfilter().
+ */
+static int pcap_setfilter_rpcap(pcap_t *fp, struct bpf_program *prog)
+{
+       struct pcap_rpcap *pr = fp->priv;       /* structure used when doing a remote live capture */
+
+       if (!pr->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;
+}
+
+/*
+ * This function updates 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)
+{
+       struct pcap_rpcap *pr = fp->priv;       /* structure used when doing a remote live capture */
+       int RetVal = 0;
+
+       /* We do not want to capture our RPCAP traffic. So, let's update the filter */
+       if (pr->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;
+
+               /* Get the name/port of our peer */
+               saddrlen = sizeof(struct sockaddr_storage);
+               if (getpeername(pr->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(pr->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(pr->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;
+               }
+
+               if (pr->currentfilter && pr->currentfilter[0] != '\0')
+               {
+                       /*
+                        * We have a current filter; add items to it to
+                        * filter out this rpcap session.
+                        */
+                       if (pcap_asprintf(&newfilter,
+                           "(%s) and not (host %s and host %s and port %s and port %s) and not (host %s and host %s and port %s)",
+                           pr->currentfilter, myaddress, peeraddress,
+                           myctrlport, peerctrlport, myaddress, peeraddress,
+                           mydataport) == -1)
+                       {
+                               /* Failed. */
+                               pcap_snprintf(fp->errbuf, PCAP_ERRBUF_SIZE,
+                                   "Can't allocate memory for new filter");
+                               return -1;
+                       }
+               }
+               else
+               {
+                       /*
+                        * We have no current filter; construct a filter to
+                        * filter out this rpcap session.
+                        */
+                       if (pcap_asprintf(&newfilter,
+                           "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) == -1)
+                       {
+                               /* Failed. */
+                               pcap_snprintf(fp->errbuf, PCAP_ERRBUF_SIZE,
+                                   "Can't allocate memory for new filter");
+                               return -1;
+                       }
+               }
+
+               /*
+                * This is only an hack to prevent the save_current_filter
+                * routine, which will be called when we call pcap_compile(),
+                * from saving the modified filter.
+                */
+               pr->rmt_clientside = 0;
+
+               if (pcap_compile(fp, prog, newfilter, 1, 0) == -1)
+                       RetVal = -1;
+
+               /* Undo the hack. */
+               pr->rmt_clientside = 1;
+
+               free(newfilter);
+       }
+
+       return RetVal;
+}
+
+/*
+ * This function sets sampling parameters in the remote host.
+ *
+ * It 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 *fp)
+{
+       struct pcap_rpcap *pr = fp->priv;       /* structure used when doing a remote live capture */
+       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 */
+
+       /* If no samping is requested, return 'ok' */
+       if (fp->rmt_samp.method == PCAP_SAMP_NOSAMP)
+               return 0;
+
+       /*
+        * Check for sampling parameters that don't fit in a message.
+        * We'll let the server complain about invalid parameters
+        * that do fit into the message.
+        */
+       if (fp->rmt_samp.method < 0 || fp->rmt_samp.method > 255) {
+               pcap_snprintf(fp->errbuf, PCAP_ERRBUF_SIZE,
+                   "Invalid sampling method %d", fp->rmt_samp.method);
+               return -1;
+       }
+       if (fp->rmt_samp.value < 0 || fp->rmt_samp.value > 65535) {
+               pcap_snprintf(fp->errbuf, PCAP_ERRBUF_SIZE,
+                   "Invalid sampling value %d", fp->rmt_samp.value);
+               return -1;
+       }
+
+       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,
+           pr->protocol_version, 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, fp->errbuf, PCAP_ERRBUF_SIZE))
+               return -1;
+
+       memset(sampling_pars, 0, sizeof(struct rpcap_sampling));
+
+       sampling_pars->method = (uint8)fp->rmt_samp.method;
+       sampling_pars->value = (uint16)htonl(fp->rmt_samp.value);
+
+       if (sock_send(pr->rmt_sockctrl, sendbuf, sendbufidx, fp->errbuf,
+           PCAP_ERRBUF_SIZE) < 0)
+               return -1;
+
+       /* Receive and process the reply message header. */
+       if (rpcap_process_msg_header(pr->rmt_sockctrl, pr->protocol_version,
+           RPCAP_MSG_SETSAMPLING_REQ, &header, fp->errbuf) == -1)
+               return -1;
+
+       /*
+        * It shouldn't have any contents; discard it if it does.
+        */
+       if (rpcap_discard(pr->rmt_sockctrl, header.plen, fp->errbuf) == -1)
+               return -1;
+
+       return 0;
+}
+
+/*********************************************************
+ *                                                       *
+ * Miscellaneous functions                               *
+ *                                                       *
+ *********************************************************/
+
+/*
+ * This function performs authentication and protocol version
+ * negotiation.  It is required in order to open the connection
+ * with the other end party.
+ *
+ * It sends authentication parameters on the control socket and
+ * reads the reply.  If the reply is a success indication, it
+ * checks whether the reply includes minimum and maximum supported
+ * versions from the server; if not, it assumes both are 0, as
+ * that means it's an older server that doesn't return supported
+ * version numbers in authentication replies, so it only supports
+ * version 0.  It then tries to determine the maximum version
+ * supported both by us and by the server.  If it can find such a
+ * version, it sets us up to use that version; otherwise, it fails,
+ * indicating that there is no version supported by us and by the
+ * server.
+ *
+ * \param sock: the socket we are currently using.
+ *
+ * \param ver: pointer to variable to which to set the protocol version
+ * number we selected.
+ *
+ * \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 a network problem or the fact that the authorization
+ * failed.
+ *
+ * \return '0' if everything is fine, '-1' for an error.  For errors,
+ * an error message string is returned in the 'errbuf' variable.
+ */
+static int rpcap_doauth(SOCKET sockctrl, uint8 *ver, 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;
+       size_t str_length;
+       uint32 plen;
+       struct rpcap_authreply authreply;       /* authentication reply message */
+       uint8 ourvers;
+
+       if (auth)
+       {
+               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)
+                       {
+                               str_length = strlen(auth->username);
+                               if (str_length > 65535)
+                               {
+                                       pcap_snprintf(errbuf, PCAP_ERRBUF_SIZE, "User name is too long (> 65535 bytes)");
+                                       return -1;
+                               }
+                               length += (uint16)str_length;
+                       }
+                       if (auth->password)
+                       {
+                               str_length = strlen(auth->password);
+                               if (str_length > 65535)
+                               {
+                                       pcap_snprintf(errbuf, PCAP_ERRBUF_SIZE, "Password is too long (> 65535 bytes)");
+                                       return -1;
+                               }
+                               length += (uint16)str_length;
+                       }
+                       break;
+
+               default:
+                       pcap_snprintf(errbuf, PCAP_ERRBUF_SIZE, "Authentication type not recognized.");
+                       return -1;
+               }
+
+               auth_type = (uint16)auth->type;
+       }
+       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, 0,
+           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(sockctrl, sendbuf, sendbufidx, errbuf,
+           PCAP_ERRBUF_SIZE) < 0)
+               return -1;
+
+       /* Receive and process the reply message header */
+       if (rpcap_process_msg_header(sockctrl, 0, RPCAP_MSG_AUTH_REQ,
+           &header, errbuf) == -1)
+               return -1;
+
+       /*
+        * OK, it's an authentication reply, so we're logged in.
+        *
+        * Did it send any additional information?
+        */
+       plen = header.plen;
+       if (plen != 0)
+       {
+               /* Yes - is it big enough to be version information? */
+               if (plen < sizeof(struct rpcap_authreply))
+               {
+                       /* No - discard it and fail. */
+                       (void)rpcap_discard(sockctrl, plen, NULL);
+                       return -1;
+               }
+
+               /* Read the reply body */
+               if (rpcap_recv(sockctrl, (char *)&authreply,
+                   sizeof(struct rpcap_authreply), &plen, errbuf) == -1)
+               {
+                       (void)rpcap_discard(sockctrl, plen, NULL);
+                       return -1;
+               }
+
+               /* Discard the rest of the message, if there is any. */
+               if (rpcap_discard(sockctrl, plen, errbuf) == -1)
+                       return -1;
+
+               /*
+                * Check the minimum and maximum versions for sanity;
+                * the minimum must be <= the maximum.
+                */
+               if (authreply.minvers > authreply.maxvers)
+               {
+                       /*
+                        * Bogus - give up on this server.
+                        */
+                       pcap_snprintf(errbuf, PCAP_ERRBUF_SIZE,
+                           "The server's minimum supported protocol version is greater than its maximum supported protocol version");
+                       return -1;
+               }
+       }
+       else
+       {
+               /* No - it supports only version 0. */
+               authreply.minvers = 0;
+               authreply.maxvers = 0;
+       }
+
+       /*
+        * OK, let's start with the maximum version the server supports.
+        */
+       ourvers = authreply.maxvers;
+
+#if RPCAP_MIN_VERSION != 0
+       /*
+        * If that's less than the minimum version we support, we
+        * can't communicate.
+        */
+       if (ourvers < RPCAP_MIN_VERSION)
+               goto novers;
+#endif
+
+       /*
+        * If that's greater than the maximum version we support,
+        * choose the maximum version we support.
+        */
+       if (ourvers > RPCAP_MAX_VERSION)
+       {
+               ourvers = RPCAP_MAX_VERSION;
+
+               /*
+                * If that's less than the minimum version they
+                * support, we can't communicate.
+                */
+               if (ourvers < authreply.minvers)
+                       goto novers;
+       }
+
+       *ver = ourvers;
+       return 0;
+
+novers:
+       /*
+        * There is no version we both support; that is a fatal error.
+        */
+       pcap_snprintf(errbuf, PCAP_ERRBUF_SIZE,
+           "The server doesn't support any protocol version that we support");
+       return -1;
+}
+
+/* We don't currently support non-blocking mode. */
+static int
+pcap_getnonblock_rpcap(pcap_t *p)
+{
+       pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
+           "Non-blocking mode isn't supported for capturing remotely with rpcap");
+       return (-1);
+}
+
+static int
+pcap_setnonblock_rpcap(pcap_t *p, int nonblock _U_)
+{
+       pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
+           "Non-blocking mode isn't supported for capturing remotely with rpcap");
+       return (-1);
+}
+
+static int
+rpcap_setup_session(const char *source, struct pcap_rmtauth *auth,
+    int *activep, SOCKET *sockctrlp, uint8 *protocol_versionp,
+    char *host, char *port, char *iface, char *errbuf)
+{
+       int type;
+       struct activehosts *activeconn;         /* active connection, if there is one */
+       int error;                              /* 1 if rpcap_remoteact_getsock got an error */
+
+       /*
+        * 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(source, &type, host, port, iface, errbuf) == -1)
+               return -1;
+
+       /*
+        * It must be remote.
+        */
+       if (type != PCAP_SRC_IFREMOTE)
+       {
+               pcap_snprintf(errbuf, PCAP_ERRBUF_SIZE,
+                   "Non-remote interface passed to remote capture routine");
+               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 */
+       activeconn = rpcap_remoteact_getsock(host, &error, errbuf);
+       if (activeconn != NULL)
+       {
+               *activep = 1;
+               *sockctrlp = activeconn->sockctrl;
+               *protocol_versionp = activeconn->protocol_version;
+       }
+       else
+       {
+               *activep = 0;
+               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 */
+
+               if (error)
+               {
+                       /*
+                        * Call failed.
+                        */
+                       return -1;
+               }
+
+               /*
+                * 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 (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 ((*sockctrlp = sock_open(addrinfo, SOCKOPEN_CLIENT, 0,
+                   errbuf, PCAP_ERRBUF_SIZE)) == INVALID_SOCKET)
+               {
+                       freeaddrinfo(addrinfo);
+                       return -1;
+               }
+
+               /* addrinfo is no longer used */
+               freeaddrinfo(addrinfo);
+               addrinfo = NULL;
+
+               if (rpcap_doauth(*sockctrlp, protocol_versionp, auth,
+                   errbuf) == -1)
+               {
+                       sock_close(*sockctrlp, NULL, 0);
+                       return -1;
+               }
+       }
+       return 0;
+}
+
+/*
+ * This function opens a remote adapter by opening an RPCAP connection and
+ * so on.
+ *
+ * It does the job of pcap_open_live() for a remote interface; it's called
+ * by pcap_open() for remote interfaces.
+ *
+ * We do not start the capture until pcap_startcapture_remote() is called.
+ *
+ * This is because, when doing a remote capture, we cannot start capturing
+ * data as soon as 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 function does this job: it sends an "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 do some dirty things in order to make everything work.
+ *
+ * \param source: see pcap_open().
+ * \param snaplen: see pcap_open().
+ * \param flags: see pcap_open().
+ * \param read_timeout: see pcap_open().
+ * \param auth: see pcap_open().
+ * \param errbuf: see pcap_open().
+ *
+ * \return a pcap_t pointer in case of success, NULL otherwise. In case of
+ * success, the pcap_t pointer can be used as a parameter to the following
+ * calls (pcap_compile() and so on). In case of problems, errbuf contains
+ * a text explanation of error.
+ *
+ * WARNING: In case we call pcap_compile() and the capture has not yet
+ * been started, the filter will be saved into the pcap_t structure,
+ * and it will be sent to the other host later (when
+ * pcap_startcapture_remote() is called).
+ */
+pcap_t *pcap_open_rpcap(const char *source, int snaplen, int flags, int read_timeout, struct pcap_rmtauth *auth, char *errbuf)
+{
+       pcap_t *fp;
+       char *source_str;
+       struct pcap_rpcap *pr;          /* structure used when doing a remote live capture */
+       char host[PCAP_BUF_SIZE], ctrlport[PCAP_BUF_SIZE], iface[PCAP_BUF_SIZE];
+       SOCKET sockctrl;
+       uint8 protocol_version;                 /* negotiated protocol version */
+       int active;
+       uint32 plen;
+       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 */
+
+       /* RPCAP-related variables */
+       struct rpcap_header header;             /* header of the RPCAP packet */
+       struct rpcap_openreply openreply;       /* open reply message */
+
+       fp = pcap_create_common(errbuf, sizeof (struct pcap_rpcap));
+       if (fp == NULL)
+       {
+               return NULL;
+       }
+       source_str = strdup(source);
+       if (source_str == NULL) {
+               pcap_fmt_errmsg_for_errno(errbuf, PCAP_ERRBUF_SIZE,
+                   errno, "malloc");
+               return NULL;
+       }
+
+       /*
+        * Turn a negative snapshot value (invalid), a snapshot value of
+        * 0 (unspecified), or a value bigger than the normal maximum
+        * value, into the maximum allowed value.
+        *
+        * If some application really *needs* a bigger snapshot
+        * length, we should just increase MAXIMUM_SNAPLEN.
+        *
+        * XXX - should we leave this up to the remote server to
+        * do?
+        */
+       if (snaplen <= 0 || snaplen > MAXIMUM_SNAPLEN)
+               snaplen = MAXIMUM_SNAPLEN;
+
+       fp->opt.device = source_str;
+       fp->snapshot = snaplen;
+       fp->opt.timeout = read_timeout;
+       pr = fp->priv;
+       pr->rmt_flags = flags;
+
+       /*
+        * Attempt to set up the session with the server.
+        */
+       if (rpcap_setup_session(fp->opt.device, auth, &active, &sockctrl,
+           &protocol_version, host, ctrlport, iface, errbuf) == -1)
+       {
+               /* Session setup failed. */
+               pcap_close(fp);
+               return NULL;
+       }
+
+       /*
+        * 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, errbuf, PCAP_ERRBUF_SIZE))
+               goto error_nodiscard;
+
+       rpcap_createhdr((struct rpcap_header *) sendbuf, protocol_version,
+           RPCAP_MSG_OPEN_REQ, 0, (uint32) strlen(iface));
+
+       if (sock_bufferize(iface, (int) strlen(iface), sendbuf, &sendbufidx,
+               RPCAP_NETBUF_SIZE, SOCKBUF_BUFFERIZE, errbuf, PCAP_ERRBUF_SIZE))
+               goto error_nodiscard;
+
+       if (sock_send(sockctrl, sendbuf, sendbufidx, errbuf,
+           PCAP_ERRBUF_SIZE) < 0)
+               goto error_nodiscard;
+
+       /* Receive and process the reply message header. */
+       if (rpcap_process_msg_header(sockctrl, protocol_version,
+           RPCAP_MSG_OPEN_REQ, &header, errbuf) == -1)
+               goto error_nodiscard;
+       plen = header.plen;
+
+       /* Read the reply body */
+       if (rpcap_recv(sockctrl, (char *)&openreply,
+           sizeof(struct rpcap_openreply), &plen, errbuf) == -1)
+               goto error;
+
+       /* Discard the rest of the message, if there is any. */
+       if (rpcap_discard(sockctrl, plen, errbuf) == -1)
+               goto error_nodiscard;
+
+       /* Set proper fields into the pcap_t struct */
+       fp->linktype = ntohl(openreply.linktype);
+       fp->tzoff = ntohl(openreply.tzoff);
+       pr->rmt_sockctrl = sockctrl;
+       pr->protocol_version = protocol_version;
+       pr->rmt_clientside = 1;
+
+       /* This code is duplicated from the end of this function */
+       fp->read_op = pcap_read_rpcap;
+       fp->save_current_filter_op = pcap_save_current_filter_rpcap;
+       fp->setfilter_op = pcap_setfilter_rpcap;
+       fp->getnonblock_op = pcap_getnonblock_rpcap;
+       fp->setnonblock_op = pcap_setnonblock_rpcap;
+       fp->stats_op = pcap_stats_rpcap;
+#ifdef _WIN32
+       fp->stats_ex_op = pcap_stats_ex_rpcap;
+#endif
+       fp->cleanup_op = pcap_cleanup_rpcap;
+
+       fp->activated = 1;
+       return fp;
+
+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.
+        */
+
+       /*
+        * Discard the rest of the message.
+        * We already reported an error; if this gets an error, just
+        * drive on.
+        */
+       (void)rpcap_discard(sockctrl, plen, NULL);
+
+error_nodiscard:
+       if (!active)
+               sock_close(sockctrl, NULL, 0);
+
+       pcap_close(fp);
+       return NULL;
+}
+
+/* String identifier to be used in the pcap_findalldevs_ex() */
+#define PCAP_TEXT_SOURCE_ADAPTER "Network adapter"
+#define PCAP_TEXT_SOURCE_ADAPTER_LEN (sizeof PCAP_TEXT_SOURCE_ADAPTER - 1)
+/* String identifier to be used in the pcap_findalldevs_ex() */
+#define PCAP_TEXT_SOURCE_ON_REMOTE_HOST "on remote node"
+#define PCAP_TEXT_SOURCE_ON_REMOTE_HOST_LEN (sizeof PCAP_TEXT_SOURCE_ON_REMOTE_HOST - 1)
+
+static void
+freeaddr(struct pcap_addr *addr)
+{
+       free(addr->addr);
+       free(addr->netmask);
+       free(addr->broadaddr);
+       free(addr->dstaddr);
+       free(addr);
+}
+
+int
+pcap_findalldevs_ex_remote(const char *source, struct pcap_rmtauth *auth, pcap_if_t **alldevs, char *errbuf)
+{
+       uint8 protocol_version;         /* protocol version */
+       SOCKET sockctrl;                /* socket descriptor of the control connection */
+       uint32 plen;
+       struct rpcap_header header;     /* structure that keeps the general header of the rpcap protocol */
+       int i, j;               /* temp variables */
+       int nif;                /* Number of interfaces listed */
+       int active;                     /* 'true' if we the other end-party is in active mode */
+       char host[PCAP_BUF_SIZE], port[PCAP_BUF_SIZE];
+       char tmpstring[PCAP_BUF_SIZE + 1];              /* Needed to convert names and descriptions from 'old' syntax to the 'new' one */
+       pcap_if_t *lastdev;     /* Last device in the pcap_if_t list */
+       pcap_if_t *dev;         /* Device we're adding to the pcap_if_t list */
+
+       /* List starts out empty. */
+       (*alldevs) = NULL;
+       lastdev = NULL;
+
+       /*
+        * Attempt to set up the session with the server.
+        */
+       if (rpcap_setup_session(source, auth, &active, &sockctrl,
+           &protocol_version, host, port, NULL, errbuf) == -1)
+       {
+               /* Session setup failed. */
+               return -1;
+       }
+
+       /* RPCAP findalldevs command */
+       rpcap_createhdr(&header, protocol_version, RPCAP_MSG_FINDALLIF_REQ,
+           0, 0);
+
+       if (sock_send(sockctrl, (char *)&header, sizeof(struct rpcap_header),
+           errbuf, PCAP_ERRBUF_SIZE) < 0)
+               goto error_nodiscard;
+
+       /* Receive and process the reply message header. */
+       if (rpcap_process_msg_header(sockctrl, protocol_version,
+           RPCAP_MSG_FINDALLIF_REQ, &header, errbuf) == -1)
+               goto error_nodiscard;
+
+       plen = header.plen;
+
+       /* 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 */
+               struct pcap_addr *addr, *prevaddr;
+
+               tmpstring2[PCAP_BUF_SIZE] = 0;
+
+               /* receive the findalldevs structure from remote host */
+               if (rpcap_recv(sockctrl, (char *)&findalldevs_if,
+                   sizeof(struct rpcap_findalldevs_if), &plen, errbuf) == -1)
+                       goto error;
+
+               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 */
+               dev = (pcap_if_t *)malloc(sizeof(pcap_if_t));
+               if (dev == NULL)
+               {
+                       pcap_fmt_errmsg_for_errno(errbuf, PCAP_ERRBUF_SIZE,
+                           errno, "malloc() failed");
+                       goto error;
+               }
+
+               /* Initialize the structure to 'zero' */
+               memset(dev, 0, sizeof(pcap_if_t));
+
+               /* Append it to the list. */
+               if (lastdev == NULL)
+               {
+                       /*
+                        * List is empty, so it's also the first device.
+                        */
+                       *alldevs = dev;
+               }
+               else
+               {
+                       /*
+                        * Append after the last device.
+                        */
+                       lastdev->next = dev;
+               }
+               /* It's now the last device. */
+               lastdev = dev;
+
+               /* 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 */
+                       if (rpcap_recv(sockctrl, tmpstring,
+                           findalldevs_if.namelen, &plen, errbuf) == -1)
+                               goto error;
+
+                       tmpstring[findalldevs_if.namelen] = 0;
+
+                       /* Create the new device identifier */
+                       if (pcap_createsrcstr(tmpstring2, PCAP_SRC_IFREMOTE,
+                           host, port, tmpstring, errbuf) == -1)
+                               goto error;
+
+                       dev->name = strdup(tmpstring2);
+                       if (dev->name == NULL)
+                       {
+                               pcap_fmt_errmsg_for_errno(errbuf,
+                                   PCAP_ERRBUF_SIZE, errno, "malloc() failed");
+                               goto error;
+                       }
+               }
+
+               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 */
+                       if (rpcap_recv(sockctrl, tmpstring,
+                           findalldevs_if.desclen, &plen, errbuf) == -1)
+                               goto error;
+
+                       tmpstring[findalldevs_if.desclen] = 0;
+
+                       if (pcap_asprintf(&dev->description,
+                           "%s '%s' %s %s", PCAP_TEXT_SOURCE_ADAPTER,
+                           tmpstring, PCAP_TEXT_SOURCE_ON_REMOTE_HOST, host) == -1)
+                       {
+                               pcap_fmt_errmsg_for_errno(errbuf,
+                                   PCAP_ERRBUF_SIZE, errno, "malloc() failed");
+                               goto error;
+                       }
+               }
+
+               dev->flags = ntohl(findalldevs_if.flags);
+
+               prevaddr = 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 */
+                       if (rpcap_recv(sockctrl, (char *)&ifaddr,
+                           sizeof(struct rpcap_findalldevs_ifaddr),
+                           &plen, errbuf) == -1)
+                               goto error;
+
+                       /*
+                        * Deserialize all the address components.
+                        */
+                       addr = (struct pcap_addr *) malloc(sizeof(struct pcap_addr));
+                       if (addr == NULL)
+                       {
+                               pcap_fmt_errmsg_for_errno(errbuf,
+                                   PCAP_ERRBUF_SIZE, errno, "malloc() failed");
+                               goto error;
+                       }
+                       addr->next = NULL;
+                       addr->addr = NULL;
+                       addr->netmask = NULL;
+                       addr->broadaddr = NULL;
+                       addr->dstaddr = NULL;
+
+                       if (rpcap_deseraddr(&ifaddr.addr,
+                               (struct sockaddr_storage **) &addr->addr, errbuf) == -1)
+                       {
+                               freeaddr(addr);
+                               goto error;
+                       }
+                       if (rpcap_deseraddr(&ifaddr.netmask,
+                               (struct sockaddr_storage **) &addr->netmask, errbuf) == -1)
+                       {
+                               freeaddr(addr);
+                               goto error;
+                       }
+                       if (rpcap_deseraddr(&ifaddr.broadaddr,
+                               (struct sockaddr_storage **) &addr->broadaddr, errbuf) == -1)
+                       {
+                               freeaddr(addr);
+                               goto error;
+                       }
+                       if (rpcap_deseraddr(&ifaddr.dstaddr,
+                               (struct sockaddr_storage **) &addr->dstaddr, errbuf) == -1)
+                       {
+                               freeaddr(addr);
+                               goto error;
+                       }
+
+                       if ((addr->addr == NULL) && (addr->netmask == NULL) &&
+                               (addr->broadaddr == NULL) && (addr->dstaddr == NULL))
+                       {
+                               /*
+                                * None of the addresses are IPv4 or IPv6
+                                * addresses, so throw this entry away.
+                                */
+                               free(addr);
+                       }
+                       else
+                       {
+                               /*
+                                * Add this entry to the list.
+                                */
+                               if (prevaddr == NULL)
+                               {
+                                       dev->addresses = addr;
+                               }
+                               else
+                               {
+                                       prevaddr->next = addr;
+                               }
+                               prevaddr = addr;
+                       }
+               }
+       }
+
+       /* Discard the rest of the message. */
+       if (rpcap_discard(sockctrl, plen, errbuf) == 1)
+               goto error_nodiscard;
+
+       /* 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
+        */
+       (void) rpcap_discard(sockctrl, plen, NULL);
+
+error_nodiscard:
+       /* 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();
+
+       /* Free whatever interfaces we've allocated. */
+       pcap_freealldevs(*alldevs);
+
+       return -1;
+}
+
+/*
+ * Active mode routines.
+ *
+ * The old libpcap API is somewhat ugly, and makes active mode difficult
+ * to implement; we provide some APIs for it that work only with rpcap.
+ */
+
+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 */
+       uint8 protocol_version;                 /* negotiated protocol version */
+       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 (SOCKET)-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)
+               {
+                       return (SOCKET)-2;
+               }
+       }
+       else
+       {
+               if (sock_initaddress(address, port, &hints, &addrinfo, errbuf, PCAP_ERRBUF_SIZE) == -1)
+               {
+                       return (SOCKET)-2;
+               }
+       }
+
+
+       if ((sockmain = sock_open(addrinfo, SOCKOPEN_SERVER, 1, errbuf, PCAP_ERRBUF_SIZE)) == INVALID_SOCKET)
+       {
+               freeaddrinfo(addrinfo);
+               return (SOCKET)-2;
+       }
+       freeaddrinfo(addrinfo);
+
+       /* 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 == INVALID_SOCKET)
+       {
+               sock_geterror("accept()", errbuf, PCAP_ERRBUF_SIZE);
+               return (SOCKET)-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, 0, PCAP_ERR_REMOTEACCEPT, errbuf, NULL);
+               sock_close(sockctrl, NULL, 0);
+               return (SOCKET)-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, 0, PCAP_ERR_REMOTEACCEPT, errbuf, NULL);
+               sock_close(sockctrl, NULL, 0);
+               return (SOCKET)-1;
+       }
+
+       /*
+        * Send authentication to the remote machine.
+        */
+       if (rpcap_doauth(sockctrl, &protocol_version, auth, errbuf) == -1)
+       {
+               /* Unrecoverable error. */
+               rpcap_senderror(sockctrl, 0, PCAP_ERR_REMOTEACCEPT, errbuf, NULL);
+               sock_close(sockctrl, NULL, 0);
+               return (SOCKET)-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_fmt_errmsg_for_errno(errbuf, PCAP_ERRBUF_SIZE,
+                   errno, "malloc() failed");
+               rpcap_senderror(sockctrl, protocol_version, PCAP_ERR_REMOTEACCEPT, errbuf, NULL);
+               sock_close(sockctrl, NULL, 0);
+               return (SOCKET)-1;
+       }
+
+       memcpy(&temp->host, &from, fromlen);
+       temp->sockctrl = sockctrl;
+       temp->protocol_version = protocol_version;
+       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;
+                               int status = 0;
+
+                               /* Close this connection */
+                               rpcap_createhdr(&header, temp->protocol_version,
+                                   RPCAP_MSG_CLOSE, 0, 0);
+
+                               /*
+                                * Don't check for errors, since we're
+                                * just cleaning up.
+                                */
+                               if (sock_send(temp->sockctrl,
+                                   (char *)&header,
+                                   sizeof(struct rpcap_header), errbuf,
+                                   PCAP_ERRBUF_SIZE) < 0)
+                               {
+                                       /*
+                                        * Let that error be the one we
+                                        * report.
+                                        */
+                                       (void)sock_close(temp->sockctrl, NULL,
+                                          0);
+                                       status = -1;
+                               }
+                               else
+                               {
+                                       if (sock_close(temp->sockctrl, errbuf,
+                                          PCAP_ERRBUF_SIZE) == -1)
+                                               status = -1;
+                               }
+
+                               /*
+                                * Remove the host from the list of active
+                                * hosts.
+                                */
+                               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 status;
+                       }
+
+                       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;
+               }
+
+               pcap_strlcat(hostlist, hoststr, PCAP_ERRBUF_SIZE);
+               hostlist[len - 1] = sep;
+               hostlist[len] = 0;
+
+               temp = temp->next;
+       }
+
+       return 0;
+}
+
+/*
+ * Receive the header of a message.
+ */
+static int rpcap_recv_msg_header(SOCKET sock, struct rpcap_header *header, char *errbuf)
+{
+       int nrecv;
+
+       nrecv = sock_recv(sock, (char *) header, sizeof(struct rpcap_header),
+           SOCK_RECEIVEALL_YES|SOCK_EOF_IS_ERROR, errbuf,
+           PCAP_ERRBUF_SIZE);
+       if (nrecv == -1)
+       {
+               /* Network error. */
+               return -1;
+       }
+       header->plen = ntohl(header->plen);
+       return 0;
+}
+
+/*
+ * Make sure the protocol version of a received message is what we were
+ * expecting.
+ */
+static int rpcap_check_msg_ver(SOCKET sock, uint8 expected_ver, struct rpcap_header *header, char *errbuf)
+{
+       /*
+        * Did the server specify the version we negotiated?
+        */
+       if (header->ver != expected_ver)
+       {
+               /*
+                * Discard the rest of the message.
+                */
+               if (rpcap_discard(sock, header->plen, errbuf) == -1)
+                       return -1;
+
+               /*
+                * Tell our caller that it's not the negotiated version.
+                */
+               if (errbuf != NULL)
+               {
+                       pcap_snprintf(errbuf, PCAP_ERRBUF_SIZE,
+                           "Server sent us a message with version %u when we were expecting %u",
+                           header->ver, expected_ver);
+               }
+               return -1;
+       }
+       return 0;
+}
+
+/*
+ * Check the message type of a received message, which should either be
+ * the expected message type or RPCAP_MSG_ERROR.
+ */
+static int rpcap_check_msg_type(SOCKET sock, uint8 request_type, struct rpcap_header *header, uint16 *errcode, char *errbuf)
+{
+       const char *request_type_string;
+       const char *msg_type_string;
+
+       /*
+        * What type of message is it?
+        */
+       if (header->type == RPCAP_MSG_ERROR)
+       {
+               /*
+                * The server reported an error.
+                * Hand that error back to our caller.
+                */
+               *errcode = ntohs(header->value);
+               rpcap_msg_err(sock, header->plen, errbuf);
+               return -1;
+       }
+
+       *errcode = 0;
+
+       /*
+        * For a given request type value, the expected reply type value
+        * is the request type value with ORed with RPCAP_MSG_IS_REPLY.
+        */
+       if (header->type != (request_type | RPCAP_MSG_IS_REPLY))
+       {
+               /*
+                * This isn't a reply to the request we sent.
+                */
+
+               /*
+                * Discard the rest of the message.
+                */
+               if (rpcap_discard(sock, header->plen, errbuf) == -1)
+                       return -1;
+
+               /*
+                * Tell our caller about it.
+                */
+               request_type_string = rpcap_msg_type_string(request_type);
+               msg_type_string = rpcap_msg_type_string(header->type);
+               if (errbuf != NULL)
+               {
+                       if (request_type_string == NULL)
+                       {
+                               /* This should not happen. */
+                               pcap_snprintf(errbuf, PCAP_ERRBUF_SIZE,
+                                   "rpcap_check_msg_type called for request message with type %u",
+                                   request_type);
+                               return -1;
+                       }
+                       if (msg_type_string != NULL)
+                               pcap_snprintf(errbuf, PCAP_ERRBUF_SIZE,
+                                   "%s message received in response to a %s message",
+                                   msg_type_string, request_type_string);
+                       else
+                               pcap_snprintf(errbuf, PCAP_ERRBUF_SIZE,
+                                   "Message of unknown type %u message received in response to a %s request",
+                                   header->type, request_type_string);
+               }
+               return -1;
+       }
+
+       return 0;
+}
+
+/*
+ * Receive and process the header of a message.
+ */
+static int rpcap_process_msg_header(SOCKET sock, uint8 expected_ver, uint8 request_type, struct rpcap_header *header, char *errbuf)
+{
+       uint16 errcode;
+
+       if (rpcap_recv_msg_header(sock, header, errbuf) == -1)
+       {
+               /* Network error. */
+               return -1;
+       }
+
+       /*
+        * Did the server specify the version we negotiated?
+        */
+       if (rpcap_check_msg_ver(sock, expected_ver, header, errbuf) == -1)
+               return -1;
+
+       /*
+        * Check the message type.
+        */
+       return rpcap_check_msg_type(sock, request_type, header,
+           &errcode, errbuf);
+}
+
+/*
+ * Read data from a message.
+ * If we're trying to read more data that remains, puts an error
+ * message into errmsgbuf and returns -2.  Otherwise, tries to read
+ * the data and, if that succeeds, subtracts the amount read from
+ * the number of bytes of data that remains.
+ * Returns 0 on success, logs a message and returns -1 on a network
+ * error.
+ */
+static int rpcap_recv(SOCKET sock, void *buffer, size_t toread, uint32 *plen, char *errbuf)
+{
+       int nread;
+
+       if (toread > *plen)
+       {
+               /* The server sent us a bad message */
+               pcap_snprintf(errbuf, PCAP_ERRBUF_SIZE, "Message payload is too short");
+               return -1;
+       }
+       nread = sock_recv(sock, buffer, toread,
+           SOCK_RECEIVEALL_YES|SOCK_EOF_IS_ERROR, errbuf, PCAP_ERRBUF_SIZE);
+       if (nread == -1)
+       {
+               return -1;
+       }
+       *plen -= nread;
+       return 0;
+}
+
+/*
+ * This handles the RPCAP_MSG_ERROR message.
+ */
+static void rpcap_msg_err(SOCKET sockctrl, uint32 plen, char *remote_errbuf)
+{
+       char errbuf[PCAP_ERRBUF_SIZE];
+
+       if (plen >= PCAP_ERRBUF_SIZE)
+       {
+               /*
+                * Message is too long; just read as much of it as we
+                * can into the buffer provided, and discard the rest.
+                */
+               if (sock_recv(sockctrl, remote_errbuf, PCAP_ERRBUF_SIZE - 1,
+                   SOCK_RECEIVEALL_YES|SOCK_EOF_IS_ERROR, errbuf,
+                   PCAP_ERRBUF_SIZE) == -1)
+               {
+                       // Network error.
+                       pcap_snprintf(remote_errbuf, PCAP_ERRBUF_SIZE, "Read of error message from client failed: %s", errbuf);
+                       return;
+               }
+
+               /*
+                * Null-terminate it.
+                */
+               remote_errbuf[PCAP_ERRBUF_SIZE - 1] = '\0';
+
+               /*
+                * Throw away the rest.
+                */
+               (void)rpcap_discard(sockctrl, plen - (PCAP_ERRBUF_SIZE - 1), remote_errbuf);
+       }
+       else if (plen == 0)
+       {
+               /* Empty error string. */
+               remote_errbuf[0] = '\0';
+       }
+       else
+       {
+               if (sock_recv(sockctrl, remote_errbuf, plen,
+                   SOCK_RECEIVEALL_YES|SOCK_EOF_IS_ERROR, errbuf,
+                   PCAP_ERRBUF_SIZE) == -1)
+               {
+                       // Network error.
+                       pcap_snprintf(remote_errbuf, PCAP_ERRBUF_SIZE, "Read of error message from client failed: %s", errbuf);
+                       return;
+               }
+
+               /*
+                * Null-terminate it.
+                */
+               remote_errbuf[plen] = '\0';
+       }
+}
+
+/*
+ * Discard data from a connection.
+ * Mostly used to discard wrong-sized messages.
+ * Returns 0 on success, logs a message and returns -1 on a network
+ * error.
+ */
+static int rpcap_discard(SOCKET sock, uint32 len, char *errbuf)
+{
+       if (len != 0)
+       {
+               if (sock_discard(sock, len, errbuf, PCAP_ERRBUF_SIZE) == -1)
+               {
+                       // Network error.
+                       return -1;
+               }
+       }
+       return 0;
+}
+
+/*
+ * Read bytes into the pcap_t's buffer until we have the specified
+ * number of bytes read or we get an error or interrupt indication.
+ */
+static int rpcap_read_packet_msg(SOCKET sock, pcap_t *p, size_t size)
+{
+       u_char *bp;
+       int cc;
+       int bytes_read;
+
+       bp = p->bp;
+       cc = p->cc;
+
+       /*
+        * Loop until we have the amount of data requested or we get
+        * an error or interrupt.
+        */
+       while ((size_t)cc < size)
+       {
+               /*
+                * We haven't read all of the packet header yet.
+                * Read what remains, which could be all of it.
+                */
+               bytes_read = sock_recv(sock, bp, size - cc,
+                   SOCK_RECEIVEALL_NO|SOCK_EOF_IS_ERROR, p->errbuf,
+                   PCAP_ERRBUF_SIZE);
+               if (bytes_read == -1)
+               {
+                       /*
+                        * Network error.  Update the read pointer and
+                        * byte count, and return an error indication.
+                        */
+                       p->bp = bp;
+                       p->cc = cc;
+                       return -1;
+               }
+               if (bytes_read == -3)
+               {
+                       /*
+                        * Interrupted receive.  Update the read
+                        * pointer and byte count, and return
+                        * an interrupted indication.
+                        */
+                       p->bp = bp;
+                       p->cc = cc;
+                       return -3;
+               }
+               if (bytes_read == 0)
+               {
+                       /*
+                        * EOF - server terminated the connection.
+                        * Update the read pointer and byte count, and
+                        * return an error indication.
+                        */
+                       pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
+                           "The server terminated the connection.");
+                       return -1;
+               }
+               bp += bytes_read;
+               cc += bytes_read;
+       }
+       p->bp = bp;
+       p->cc = cc;
+       return 0;
+}
diff --git a/pcap-rpcap.h b/pcap-rpcap.h
new file mode 100644 (file)
index 0000000..6ad6d98
--- /dev/null
@@ -0,0 +1,49 @@
+/*
+ * 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 pcap_rpcap_h
+#define        pcap_rpcap_h
+
+/*
+ * Internal interfaces for "pcap_open()".
+ */
+pcap_t *pcap_open_rpcap(const char *source, int snaplen, int flags,
+    int read_timeout, struct pcap_rmtauth *auth, char *errbuf);
+
+/*
+ * Internal interfaces for "pcap_findalldevs_ex()".
+ */
+int    pcap_findalldevs_ex_remote(const char *source,
+    struct pcap_rmtauth *auth, pcap_if_t **alldevs, char *errbuf);
+
+#endif
index 2b93c14..748d7af 100644 (file)
 .\" 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
@@ -130,4 +130,4 @@ the packet not been truncated by the snapshot length.  The two lengths
 will be equal if the number of bytes of packet data are less than or
 equal to the snapshot length.
 .SH SEE ALSO
-pcap(3PCAP), pcap-linktype(@MAN_MISC_INFO@)
+pcap(3PCAP)
index 2f0ff33..24cb47b 100644 (file)
@@ -1,21 +1,12 @@
 /*
  * pcap-septel.c: Packet capture interface for Intel/Septel card.
  *
- * The functionality of this code attempts to mimic that of pcap-linux as much
- * as possible.  This code is compiled in several different ways depending on
- * whether SEPTEL_ONLY and HAVE_SEPTEL_API are defined.  If HAVE_SEPTEL_API is
- * not defined it should not get compiled in, otherwise if SEPTEL_ONLY is
- * defined then the 'septel_' function calls are renamed to 'pcap_'
- * equivalents.  If SEPTEL_ONLY is not defined then nothing is altered - the
- * septel_ functions will be called as required from their
- * pcap-linux/equivalents.
- *
  * Authors: Gilbert HOYEK (gil_hoyek@hotmail.com), Elias M. KHOURY
  * (+961 3 485243)
  */
 
 #ifdef HAVE_CONFIG_H
-#include "config.h"
+#include <config.h>
 #endif
 
 #include <sys/param.h>
@@ -43,7 +34,8 @@
 
 static int septel_setfilter(pcap_t *p, struct bpf_program *fp);
 static int septel_stats(pcap_t *p, struct pcap_stat *ps);
-static int septel_setnonblock(pcap_t *p, int nonblock, char *errbuf);
+static int septel_getnonblock(pcap_t *p);
+static int septel_setnonblock(pcap_t *p, int nonblock);
 
 /*
  * Private data for capturing on Septel devices.
@@ -181,7 +173,7 @@ loop:
 static int
 septel_inject(pcap_t *handle, const void *buf _U_, size_t size _U_)
 {
-  strlcpy(handle->errbuf, "Sending packets isn't supported on Septel cards",
+  pcap_strlcpy(handle->errbuf, "Sending packets isn't supported on Septel cards",
           PCAP_ERRBUF_SIZE);
   return (-1);
 }
@@ -194,9 +186,20 @@ 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;
-  
+
+  /*
+   * Turn a negative snapshot value (invalid), a snapshot value of
+   * 0 (unspecified), or a value bigger than the normal maximum
+   * value, into the maximum allowed value.
+   *
+   * If some application really *needs* a bigger snapshot
+   * length, we should just increase MAXIMUM_SNAPLEN.
+   */
+  if (handle->snapshot <= 0 || handle->snapshot > MAXIMUM_SNAPLEN)
+    handle->snapshot = MAXIMUM_SNAPLEN;
+
   handle->bufsize = 0;
 
   /*
@@ -208,7 +211,7 @@ static pcap_t *septel_activate(pcap_t* handle) {
   handle->inject_op = septel_inject;
   handle->setfilter_op = septel_setfilter;
   handle->set_datalink_op = NULL; /* can't change data link type */
-  handle->getnonblock_op = pcap_getnonblock_fd;
+  handle->getnonblock_op = septel_getnonblock;
   handle->setnonblock_op = septel_setnonblock;
   handle->stats_op = septel_stats;
 
@@ -232,11 +235,20 @@ 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;
 
        p->activate_op = septel_activate;
+       /*
+        * Set these up front, so that, even if our client tries
+        * to set non-blocking mode before we're activated, or
+        * query the state of non-blocking mode, they get an error,
+        * rather than having the non-blocking mode option set
+        * for use later.
+        */
+       p->getnonblock_op = septel_getnonblock;
+       p->setnonblock_op = septel_setnonblock;
        return p;
 }
 
@@ -244,18 +256,22 @@ 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;
 }
 
 
 int
-septel_findalldevs(pcap_if_t **devlistp, char *errbuf)
+septel_findalldevs(pcap_if_list_t *devlistp, char *errbuf)
 {
-  return (pcap_add_if(devlistp,"septel",0,
-                      "Intel/Septel device",errbuf));
+  /*
+   * XXX - do the notions of "up", "running", or "connected" apply here?
+   */
+  if (add_dev(devlistp,"septel",0,"Intel/Septel device",errbuf) == NULL)
+    return -1;
+  return 0;
 }
 
 
@@ -275,19 +291,64 @@ 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),
-            "malloc: %s", pcap_strerror(errno));
+  if (install_bpf_program(p, fp) < 0)
     return -1;
-  }
 
   return (0);
 }
 
+/*
+ * We don't support non-blocking mode.  I'm not sure what we'd
+ * do to support it and, given that we don't support select()/
+ * poll()/epoll_wait()/kevent() etc., it probably doesn't
+ * matter.
+ */
+static int
+septel_getnonblock(pcap_t *p)
+{
+  fprintf(p->errbuf, PCAP_ERRBUF_SIZE, "Non-blocking mode not supported on Septel devices");
+  return (-1);
+}
 
 static int
-septel_setnonblock(pcap_t *p, int nonblock, char *errbuf)
+septel_setnonblock(pcap_t *p, int nonblock _U_)
 {
-  fprintf(errbuf, PCAP_ERRBUF_SIZE, "Non-blocking mode not supported on Septel devices");
+  fprintf(p->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_list_t *devlistp, char *errbuf)
+{
+  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);
+}
+
+/*
+ * Libpcap version string.
+ */
+const char *
+pcap_lib_version(void)
+{
+  return (PCAP_VERSION_STRING " (Septel-only)");
+}
+#endif
index b6e1168..0e648b2 100644 (file)
@@ -10,4 +10,4 @@
  */
 
 pcap_t *septel_create(const char *device, char *ebuf, int *is_ours);
-int septel_findalldevs(pcap_if_t **devlistp, char *errbuf);
+int septel_findalldevs(pcap_if_list_t *devlistp, char *errbuf);
index d507e1e..b9dda9c 100644 (file)
@@ -25,7 +25,7 @@
  */
 
 #ifdef HAVE_CONFIG_H
-#include "config.h"
+#include <config.h>
 #endif
 
 #include <stdio.h>
@@ -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,12 @@ 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_fmt_errmsg_for_errno(errbuf, PCAP_ERRBUF_SIZE,
+                           errno, "malloc");
                        continue;
                }
                strcpy(ptr2, ptr);                                                              /* copy the IP address into our malloc'ed memory */
@@ -402,14 +407,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 +558,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 +573,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 +583,8 @@ 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_fmt_errmsg_for_errno(errbuf,
+                                           PCAP_ERRBUF_SIZE, errno, "malloc");
                                        return -1;
                                }
                                memset((char *)iff, 0, sizeof(pcap_if_t)); /* bzero() is deprecated, replaced with memset() */
@@ -586,7 +593,9 @@ 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_fmt_errmsg_for_errno(errbuf,
+                                                   PCAP_ERRBUF_SIZE, errno,
+                                                   "malloc");
                                                return -1;
                                        }
                                        memcpy(iff->name, (ptr + 1), *ptr);                                             /* copy the name into the malloc'ed space */
@@ -597,7 +606,9 @@ 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_fmt_errmsg_for_errno(errbuf,
+                                                   PCAP_ERRBUF_SIZE, errno,
+                                                   "malloc");
                                                return -1;
                                        }
                                        memcpy(iff->description, (ptr + 1), *ptr);                              /* copy the name into the malloc'ed space */
@@ -617,15 +628,19 @@ 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_fmt_errmsg_for_errno(errbuf,
+                                                   PCAP_ERRBUF_SIZE, errno,
+                                                   "malloc");
                                                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_fmt_errmsg_for_errno(errbuf,
+                                                           PCAP_ERRBUF_SIZE,
+                                                           errno, "malloc");
                                                        return -1;
                                                }
                                                memset((char *)s, 0, sizeof(struct sockaddr_in)); /* bzero() is deprecated, replaced with memset() */
@@ -637,7 +652,9 @@ 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_fmt_errmsg_for_errno(errbuf,
+                                                           PCAP_ERRBUF_SIZE,
+                                                           errno, "malloc");
                                                        return -1;
                                                }
                                                /* bzero() is deprecated, replaced with memset() */
@@ -651,7 +668,9 @@ 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_fmt_errmsg_for_errno(errbuf,
+                                                           PCAP_ERRBUF_SIZE,
+                                                           errno, "malloc");
                                                        return -1;
                                                }
                                                /* bzero() is deprecated, replaced with memset() */
@@ -665,7 +684,9 @@ 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_fmt_errmsg_for_errno(errbuf,
+                                                           PCAP_ERRBUF_SIZE,
+                                                           errno, "malloc");
                                                        return -1;
                                                }
                                                /* bzero() is deprecated, replaced with memset() */
@@ -682,10 +703,13 @@ 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_fmt_errmsg_for_errno(errbuf,
+                                           PCAP_ERRBUF_SIZE, errno, "realloc");
                                        return -1;
                                }
+                               iff->name = bigger_buffer;
                                strcpy(iff->name, newname);                                                                                             /* to this new name */
                        }
                }
@@ -814,9 +838,9 @@ static int acn_open_live(const char *name, char *errbuf, int *linktype) {           /* re
        int                     chassis, geoslot;
        unit_t          *u;
        iface_t         *p;
-       pcap_if_t       *alldevsp;
+       pcap_if_list_t  devlist;
 
-       pcap_findalldevs_interfaces(&alldevsp, errbuf);
+       pcap_platform_finddevs(&devlist, errbuf);
        for (chassis = 0; chassis <= MAX_CHASSIS; chassis++) {                                                                          /* scan the table... */
                for (geoslot = 0; geoslot <= MAX_GEOSLOT; geoslot++) {
                        u = &units[chassis][geoslot];
@@ -860,7 +884,7 @@ static void acn_start_monitor(int fd, int snaplen, int timeout, int promiscuous,
 }
 
 static int pcap_inject_acn(pcap_t *p, const void *buf _U_, size_t size _U_) {
-       strlcpy(p->errbuf, "Sending packets isn't supported on ACN adapters",
+       pcap_strlcpy(p->errbuf, "Sending packets isn't supported on ACN adapters",
            PCAP_ERRBUF_SIZE);
        return (-1);
 }
@@ -892,7 +916,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 +975,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,10 +1005,22 @@ 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;
+
+       /*
+        * Turn a negative snapshot value (invalid), a snapshot value of
+        * 0 (unspecified), or a value bigger than the normal maximum
+        * value, into the maximum allowed value.
+        *
+        * If some application really *needs* a bigger snapshot
+        * length, we should just increase MAXIMUM_SNAPLEN.
+        */
+       if (handle->snapshot <= 0 || handle->snapshot > MAXIMUM_SNAPLEN)
+               handle->snapshot = MAXIMUM_SNAPLEN;
+
        handle->fd = fd;
        handle->bufsize = handle->snapshot;
 
@@ -992,8 +1028,8 @@ static int pcap_activate_sita(pcap_t *handle) {
 
        handle->buffer   = malloc(handle->bufsize + handle->offset);
        if (!handle->buffer) {
-               snprintf(handle->errbuf, PCAP_ERRBUF_SIZE,
-                        "malloc: %s", pcap_strerror(errno));
+               pcap_fmt_errmsg_for_errno(handle->errbuf, PCAP_ERRBUF_SIZE,
+                   errno, "malloc");
                pcap_cleanup_acn(handle);
                return PCAP_ERROR;
        }
@@ -1007,13 +1043,45 @@ 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_list_t *devlistp, 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;
+               }
+       devlistp->beginning = 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;
+}
+
+/*
+ * Libpcap version string.
+ */
+const char *
+pcap_lib_version(void)
+{
+       return PCAP_VERSION_STRING " (SITA-only)";
+}
index 97408d8..4a8fe1a 100644 (file)
@@ -411,7 +411,7 @@ A { text-decoration:none }
                                        <TR>
                                                <TD VALIGN=TOP>Interface ID</TD>
                                                <TD VALIGN=TOP ALIGN=CENTER>1</TD>
-                                               <TD VALIGN=TOP>A NULL to indicate an an empty 'interface ID'.</TD>
+                                               <TD VALIGN=TOP>A NULL to indicate an empty 'interface ID'.</TD>
                                        </TR>
                                </TABLE>
                        </TD>
index ee6ffa4..50d92cd 100644 (file)
@@ -1,21 +1,28 @@
 #ifdef HAVE_CONFIG_H
-#include "config.h"
+#include <config.h>
 #endif
 
+#ifndef _WIN32
 #include <sys/param.h>
+#endif /* !_WIN32 */
 
 #include <stdlib.h>
 #include <string.h>
 #include <errno.h>
 
 #include <ctype.h>
+#ifndef _WIN32
 #include <netinet/in.h>
 #include <sys/mman.h>
 #include <sys/socket.h>
 #include <sys/types.h>
 #include <unistd.h>
+#endif /* !_WIN32 */
 
 #include <snf.h>
+#if SNF_VERSION_API >= 0x0003
+#define SNF_HAVE_INJECT_API
+#endif
 
 #include "pcap-int.h"
 #include "pcap-snf.h"
 struct pcap_snf {
        snf_handle_t snf_handle; /* opaque device handle */
        snf_ring_t   snf_ring;   /* opaque device ring handle */
-        int          snf_timeout;
-        int          snf_boardnum;
+#ifdef SNF_HAVE_INJECT_API
+       snf_inject_t snf_inj;    /* inject handle, if inject is used */
+#endif
+       int          snf_timeout;
+       int          snf_boardnum;
 };
 
 static int
@@ -41,11 +51,12 @@ 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",
-                        pcap_strerror(rc));
+       if ((rc = snf_ring_getstats(snfps->snf_ring, &stats))) {
+               pcap_fmt_errmsg_for_errno(p->errbuf, PCAP_ERRBUF_SIZE,
+                   rc, "snf_get_stats");
                return -1;
        }
        ps->ps_recv = stats.ring_pkt_recv + stats.ring_pkt_overflow;
@@ -59,16 +70,17 @@ snf_platform_cleanup(pcap_t *p)
 {
        struct pcap_snf *ps = p->priv;
 
-       if (p == NULL)
-               return;
-
+#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);
 }
 
 static int
-snf_getnonblock(pcap_t *p, char *errbuf)
+snf_getnonblock(pcap_t *p)
 {
        struct pcap_snf *ps = p->priv;
 
@@ -76,7 +88,7 @@ snf_getnonblock(pcap_t *p, char *errbuf)
 }
 
 static int
-snf_setnonblock(pcap_t *p, int nonblock, char *errbuf)
+snf_setnonblock(pcap_t *p, int nonblock)
 {
        struct pcap_snf *ps = p->priv;
 
@@ -95,14 +107,24 @@ 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;
-       if (ts_nanosec == 0)
-               return (struct timeval) { 0, 0 };
+       long tv_nsec;
+        const static struct timeval zero_timeval;
+
+        if (ts_nanosec == 0)
+                return zero_timeval;
+
        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;
 }
 
@@ -113,11 +135,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?
@@ -131,16 +155,19 @@ 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",
-                                        pcap_strerror(err));
+                       }
+                       else {
+                               pcap_fmt_errmsg_for_errno(p->errbuf,
+                                   PCAP_ERRBUF_SIZE, err, "snf_read");
                                return -1;
                        }
                }
@@ -151,12 +178,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++;
                }
-               n++;
+
+               /* After one successful packet is received, we won't block
+               * again for that timeout. */
+               if (timeout != 0)
+                       timeout = 0;
        }
        return (n);
 }
@@ -183,52 +215,97 @@ 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_fmt_errmsg_for_errno(p->errbuf, PCAP_ERRBUF_SIZE,
+                           rc, "snf_inject_open");
+                       return (-1);
+               }
+       }
+
+       rc = snf_inject_send(ps->snf_inj, -1, 0, buf, size);
+       if (!rc) {
+               return (size);
+       }
+       else {
+               pcap_fmt_errmsg_for_errno(p->errbuf, PCAP_ERRBUF_SIZE,
+                   rc, "snf_inject_send");
+               return (-1);
+       }
+#else
+       pcap_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,
-                        "device is NULL: %s", pcap_strerror(errno));
+               pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "device is NULL");
                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;
 
+
+        /* Allow pcap_set_buffer_size() to set dataring_size.
+         * Default is zero which allows setting from env SNF_DATARING_SIZE.
+         * pcap_set_buffer_size() is in bytes while snf_open() accepts values
+         * between 0 and 1048576 in Megabytes. Values in this range are
+         * mapped to 1MB.
+         */
        err = snf_open(ps->snf_boardnum,
                        0, /* let SNF API parse SNF_NUM_RINGS, if set */
                        NULL, /* default RSS, or use SNF_RSS_FLAGS env */
-                       0, /* default to SNF_DATARING_SIZE from env */
+                        (p->opt.buffer_size > 0 && p->opt.buffer_size < 1048576) ? 1048576 : p->opt.buffer_size, /* default to SNF_DATARING_SIZE from env */
                        flags, /* may want pshared */
                        &ps->snf_handle);
        if (err != 0) {
-               snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
-                        "snf_open failed: %s", pcap_strerror(err));
+               pcap_fmt_errmsg_for_errno(p->errbuf, PCAP_ERRBUF_SIZE,
+                   err, "snf_open failed");
                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_fmt_errmsg_for_errno(p->errbuf, PCAP_ERRBUF_SIZE,
+                   err, "snf_ring_open_id(ring=%d) failed", ring_id);
                return -1;
        }
 
+       /*
+        * Turn a negative snapshot value (invalid), a snapshot value of
+        * 0 (unspecified), or a value bigger than the normal maximum
+        * value, into the maximum allowed value.
+        *
+        * If some application really *needs* a bigger snapshot
+        * length, we should just increase MAXIMUM_SNAPLEN.
+        */
+       if (p->snapshot <= 0 || p->snapshot > MAXIMUM_SNAPLEN)
+               p->snapshot = MAXIMUM_SNAPLEN;
+
        if (p->opt.timeout <= 0)
                ps->snf_timeout = -1;
        else
@@ -236,15 +313,17 @@ snf_activate(pcap_t* p)
 
        err = snf_start(ps->snf_handle);
        if (err != 0) {
-               snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
-                        "snf_start failed: %s", pcap_strerror(err));
+               pcap_fmt_errmsg_for_errno(p->errbuf, PCAP_ERRBUF_SIZE,
+                   err, "snf_start failed");
                return -1;
        }
 
        /*
         * "select()" and "poll()" don't work on snf descriptors.
         */
+#ifndef _WIN32
        p->selectable_fd = -1;
+#endif /* !_WIN32 */
        p->linktype = DLT_EN10MB;
        p->read_op = snf_read;
        p->inject_op = snf_inject;
@@ -255,16 +334,178 @@ 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)
+snf_findalldevs(pcap_if_list_t *devlistp, char *errbuf)
 {
+       pcap_if_t *dev;
+#ifdef _WIN32
+       struct sockaddr_in addr;
+#endif
+       struct snf_ifaddrs *ifaddrs, *ifa;
+       char name[MAX_DESC_LENGTH];
+       char desc[MAX_DESC_LENGTH];
+       int ret, allports = 0, merge = 0;
+       const char *nr = NULL;
+
+       if (snf_init(SNF_VERSION_API)) {
+               (void)pcap_snprintf(errbuf, PCAP_ERRBUF_SIZE,
+                   "snf_getifaddrs: snf_init failed");
+               return (-1);
+       }
+
+       if (snf_getifaddrs(&ifaddrs) || ifaddrs == NULL)
+       {
+               pcap_fmt_errmsg_for_errno(errbuf, PCAP_ERRBUF_SIZE,
+                   errno, "snf_getifaddrs");
+               return (-1);
+       }
+       if ((nr = getenv("SNF_FLAGS")) && *nr) {
+               errno = 0;
+               merge = strtol(nr, NULL, 0);
+               if (errno) {
+                       (void)pcap_snprintf(errbuf, PCAP_ERRBUF_SIZE,
+                               "snf_getifaddrs: SNF_FLAGS is not a valid number");
+                       return (-1);
+               }
+               merge = merge & SNF_F_AGGREGATE_PORTMASK;
+       }
+
+       for (ifa = ifaddrs; ifa != NULL; ifa = ifa->snf_ifa_next) {
+               /*
+                * Myricom SNF adapter ports may appear as regular
+                * network interfaces, which would already have been
+                * added to the list of adapters by pcap_platform_finddevs()
+                * if this isn't an SNF-only version of libpcap.
+                *
+                * Our create routine intercepts pcap_create() calls for
+                * those interfaces and arranges that they will be
+                * opened using the SNF API instead.
+                *
+                * So if we already have an entry for the device, we
+                * don't add an additional entry for it, we just
+                * update the description for it, if any, to indicate
+                * which snfN device it is.  Otherwise, we add an entry
+                * for it.
+                *
+                * In either case, if SNF_F_AGGREGATE_PORTMASK is set
+                * in SNF_FLAGS, we add this port to the bitmask
+                * of ports, which we use to generate a device
+                * we can use to capture on all ports.
+                *
+                * Generate the description string.  If port aggregation
+                * is set, use 2^{port number} as the unit number,
+                * rather than {port number}.
+                *
+                * XXX - do entries in this list have IP addresses for
+                * the port?  If so, should we add them to the
+                * entry for the device, if they're not already in the
+                * list of IP addresses for the device?
+                */
+               (void)pcap_snprintf(desc,MAX_DESC_LENGTH,"Myricom %ssnf%d",
+                       merge ? "Merge Bitmask Port " : "",
+                       merge ? 1 << ifa->snf_ifa_portnum : ifa->snf_ifa_portnum);
+               /*
+                * Add the port to the bitmask.
+                */
+               if (merge)
+                       allports |= 1 << ifa->snf_ifa_portnum;
+               /*
+                * See if there's already an entry for the device
+                * with the name ifa->snf_ifa_name.
+                */
+               dev = find_dev(devlistp, ifa->snf_ifa_name);
+               if (dev != NULL) {
+                       /*
+                        * Yes.  Update its description.
+                        */
+                       char *desc_str;
+
+                       desc_str = strdup(desc);
+                       if (desc_str == NULL) {
+                               pcap_fmt_errmsg_for_errno(errbuf,
+                                   PCAP_ERRBUF_SIZE, errno,
+                                   "snf_findalldevs strdup");
+                               return -1;
+                       }
+                       free(dev->description);
+                       dev->description = desc_str;
+               } else {
+                       /*
+                        * No.  Add an entry for it.
+                        *
+                        * XXX - is there a notion of "up" or "running",
+                        * and can we determine whether something's
+                        * plugged into the adapter and set
+                        * PCAP_IF_CONNECTION_STATUS_CONNECTED or
+                        * PCAP_IF_CONNECTION_STATUS_DISCONNECTED?
+                        */
+                       dev = add_dev(devlistp, ifa->snf_ifa_name, 0, desc,
+                           errbuf);
+                       if (dev == NULL)
+                               return -1;
+#ifdef _WIN32
+                       /*
+                        * On Windows, fill in IP# from device name
+                        */
+                        ret = inet_pton(AF_INET, dev->name, &addr.sin_addr);
+                        if (ret == 1) {
+                               /*
+                                * Successful conversion of device name
+                                * to IPv4 address.
+                                */
+                               addr.sin_family = AF_INET;
+                               if (add_addr_to_dev(dev, &addr, sizeof(addr),
+                                   NULL, 0, NULL, 0, NULL, 0, errbuf) == -1)
+                                       return -1;
+                        } else if (ret == -1) {
+                               /*
+                                * Error.
+                                */
+                               pcap_fmt_errmsg_for_errno(errbuf,
+                                   PCAP_ERRBUF_SIZE, errno,
+                                   "sinf_findalldevs inet_pton");
+                                return -1;
+                        }
+#endif _WIN32
+               }
+       }
+       snf_freeifaddrs(ifaddrs);
        /*
-        * There are no platform-specific devices since each device
-        * exists as a regular Ethernet device.
-        */
+        * Create a snfX entry if port aggregation is enabled
+                */
+       if (merge) {
+               /*
+                * Add a new entry with all ports bitmask
+                */
+               (void)pcap_snprintf(name,MAX_DESC_LENGTH,"snf%d",allports);
+               (void)pcap_snprintf(desc,MAX_DESC_LENGTH,"Myricom Merge Bitmask All Ports snf%d",
+                       allports);
+               /*
+                * XXX - is there any notion of "up" and "running" that
+                * would apply to this device, given that it handles
+                * multiple ports?
+                *
+                * Presumably, there's no notion of "connected" vs.
+                * "disconnected", as "is this plugged into a network?"
+                * would be a per-port property.
+                */
+               if (add_dev(devlistp, name,
+                   PCAP_IF_CONNECTION_STATUS_NOT_APPLICABLE, desc,
+                   errbuf) == NULL)
+                       return (-1);
+               /*
+                * XXX - should we give it a list of addresses with all
+                * the addresses for all the ports?
+                */
+       }
+
        return 0;
 }
 
@@ -295,7 +536,7 @@ snf_create(const char *device, char *ebuf, int *is_ours)
        devlen = strlen(device) + 1;
        ifa = ifaddrs;
        while (ifa) {
-               if (!strncmp(device, ifa->snf_ifa_name, devlen)) {
+               if (strncmp(device, ifa->snf_ifa_name, devlen) == 0) {
                        boardnum = ifa->snf_ifa_boardnum;
                        break;
                }
@@ -313,18 +554,68 @@ snf_create(const char *device, char *ebuf, int *is_ours)
                        /* Nope, not a supported name */
                        *is_ours = 0;
                        return NULL;
-                   }
+               }
        }
 
        /* 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_fmt_errmsg_for_errno(ebuf, PCAP_ERRBUF_SIZE, errno,
+                   "malloc");
+               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 SNF interfaces.
+ */
+int
+pcap_platform_finddevs(pcap_if_list_t *devlistp, char *errbuf)
+{
+       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;
+}
+
+/*
+ * Libpcap version string.
+ */
+const char *
+pcap_lib_version(void)
+{
+       return (PCAP_VERSION_STRING " (SNF-only)");
+}
+#endif
index c9d7722..ffc64ad 100644 (file)
@@ -1,2 +1,2 @@
 pcap_t *snf_create(const char *, char *, int *);
-int snf_findalldevs(pcap_if_t **devlistp, char *errbuf);
+int snf_findalldevs(pcap_if_list_t *devlistp, char *errbuf);
index e6232c2..9c6fbd4 100644 (file)
@@ -24,7 +24,7 @@
  */
 
 #ifdef HAVE_CONFIG_H
-#include "config.h"
+#include <config.h>
 #endif
 
 #include <sys/types.h>
@@ -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_strerror(errno));
+                       pcap_fmt_errmsg_for_errno(p->errbuf, sizeof(p->errbuf),
+                           errno, "pcap_read");
                        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,8 +223,8 @@ 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_strerror(errno));
+               pcap_fmt_errmsg_for_errno(p->errbuf, PCAP_ERRBUF_SIZE,
+                   errno, "send");
                return (-1);
        }
        return (ret);
@@ -247,8 +247,8 @@ 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_strerror(errno));
+                       pcap_fmt_errmsg_for_errno(p->errbuf, PCAP_ERRBUF_SIZE,
+                           errno, "NIOCSCHUNK");
                        return (-1);
                }
        }
@@ -260,8 +260,8 @@ 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_strerror(errno));
+                       pcap_fmt_errmsg_for_errno(p->errbuf, PCAP_ERRBUF_SIZE,
+                           errno, "NIOCSTIME");
                        return (-1);
                }
        }
@@ -272,8 +272,8 @@ 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_strerror(errno));
+               pcap_fmt_errmsg_for_errno(p->errbuf, PCAP_ERRBUF_SIZE,
+                   errno, "NIOCSFLAGS");
                return (-1);
        }
        return (0);
@@ -286,7 +286,8 @@ 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";
+       int err;
 
        if (p->opt.rfmon) {
                /*
@@ -296,6 +297,17 @@ pcap_activate_snit(pcap_t *p)
                return (PCAP_ERROR_RFMON_NOTSUP);
        }
 
+       /*
+        * Turn a negative snapshot value (invalid), a snapshot value of
+        * 0 (unspecified), or a value bigger than the normal maximum
+        * value, into the maximum allowed value.
+        *
+        * If some application really *needs* a bigger snapshot
+        * length, we should just increase MAXIMUM_SNAPLEN.
+        */
+       if (p->snapshot <= 0 || p->snapshot > MAXIMUM_SNAPLEN)
+               p->snapshot = MAXIMUM_SNAPLEN;
+
        if (p->snapshot < 96)
                /*
                 * NIT requires a snapshot length of at least 96.
@@ -320,20 +332,26 @@ 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_strerror(errno));
+               if (errno == EACCES)
+                       err = PCAP_ERROR_PERM_DENIED;
+               else
+                       err = PCAP_ERROR;
+               pcap_fmt_errmsg_for_errno(p->errbuf, PCAP_ERRBUF_SIZE,
+                   errno, "%s", dev);
                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_strerror(errno));
+               pcap_fmt_errmsg_for_errno(p->errbuf, PCAP_ERRBUF_SIZE,
+                   errno, "I_SRDOPT");
+               err = PCAP_ERROR;
                goto bad;
        }
        if (ioctl(fd, I_PUSH, "nbuf") < 0) {
-               snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "push nbuf: %s",
-                   pcap_strerror(errno));
+               pcap_fmt_errmsg_for_errno(p->errbuf, PCAP_ERRBUF_SIZE,
+                   errno, "push nbuf");
+               err = PCAP_ERROR;
                goto bad;
        }
        /* set the chunksize */
@@ -342,20 +360,27 @@ 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_strerror(errno));
+               pcap_fmt_errmsg_for_errno(p->errbuf, PCAP_ERRBUF_SIZE,
+                   errno, "NIOCSCHUNK");
+               err = PCAP_ERROR;
                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",
-                       ifr.ifr_name, pcap_strerror(errno));
+               /*
+                * XXX - is there an error that means "no such device"?
+                * Is there one that means "that device doesn't support
+                * STREAMS NIT"?
+                */
+               pcap_fmt_errmsg_for_errno(p->errbuf, PCAP_ERRBUF_SIZE,
+                   errno, "NIOCBIND: %s", ifr.ifr_name);
+               err = PCAP_ERROR;
                goto bad;
        }
 
@@ -364,12 +389,15 @@ 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_strerror(errno));
+               pcap_fmt_errmsg_for_errno(p->errbuf, PCAP_ERRBUF_SIZE,
+                   errno, "NIOCSSNAP");
+               err = PCAP_ERROR;
                goto bad;
        }
-       if (nit_setflags(p) < 0)
+       if (nit_setflags(p) < 0) {
+               err = PCAP_ERROR;
                goto bad;
+       }
 
        (void)ioctl(fd, I_FLUSH, (char *)FLUSHR);
        /*
@@ -378,9 +406,11 @@ 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);
+               pcap_fmt_errmsg_for_errno(p->errbuf, PCAP_ERRBUF_SIZE,
+                   errno, "malloc");
+               err = PCAP_ERROR;
                goto bad;
        }
 
@@ -422,15 +452,15 @@ pcap_activate_snit(pcap_t *p)
        return (0);
  bad:
        pcap_cleanup_live_common(p);
-       return (PCAP_ERROR);
+       return (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_snit));
+       p = pcap_create_common(ebuf, sizeof (struct pcap_snit));
        if (p == NULL)
                return (NULL);
 
@@ -438,8 +468,39 @@ pcap_create_interface(const char *device, char *ebuf)
        return (p);
 }
 
-int
-pcap_platform_finddevs(pcap_if_t **alldevsp, char *errbuf)
+/*
+ * 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);
+}
+
+static int
+get_if_flags(const char *name _U_, bpf_u_int32 *flags _U_, char *errbuf _U_)
+{
+       /*
+        * Nothing we can do.
+        * XXX - is there a way to find out whether an adapter has
+        * something plugged into it?
+        */
        return (0);
 }
+
+int
+pcap_platform_finddevs(pcap_if_list_t *devlistp, char *errbuf)
+{
+       return (pcap_findalldevs_interfaces(devlistp, errbuf, can_be_bound,
+           get_if_flags));
+}
+
+/*
+ * Libpcap version string.
+ */
+const char *
+pcap_lib_version(void)
+{
+       return (PCAP_VERSION_STRING);
+}
index 7993e70..a598bae 100644 (file)
@@ -20,7 +20,7 @@
  */
 
 #ifdef HAVE_CONFIG_H
-#include "config.h"
+#include <config.h>
 #endif
 
 #include <sys/param.h>
@@ -95,8 +95,8 @@ again:
                case EWOULDBLOCK:
                        return (0);                     /* XXX */
                }
-               snprintf(p->errbuf, sizeof(p->errbuf),
-                   "read: %s", pcap_strerror(errno));
+               pcap_fmt_errmsg_for_errno(p->errbuf, sizeof(p->errbuf),
+                   errno, "read");
                return (-1);
        }
        sh = (struct snoopheader *)p->buffer;
@@ -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_strerror(errno));
+               pcap_fmt_errmsg_for_errno(p->errbuf, PCAP_ERRBUF_SIZE,
+                   errno, "send");
                return (-1);
        }
        return (ret);
-}                           
+}
 
 static int
 pcap_stats_snoop(pcap_t *p, struct pcap_stat *ps)
@@ -167,8 +167,8 @@ 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),
-                   "SIOCRAWSTATS: %s", pcap_strerror(errno));
+               pcap_fmt_errmsg_for_errno(p->errbuf, sizeof(p->errbuf),
+                   errno, "SIOCRAWSTATS");
                return (-1);
        }
 
@@ -212,23 +212,30 @@ 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_strerror(errno));
+               pcap_fmt_errmsg_for_errno(p->errbuf, PCAP_ERRBUF_SIZE,
+                   errno, "snoop socket");
                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",
-                   pcap_strerror(errno));
+               /*
+                * 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_fmt_errmsg_for_errno(p->errbuf, PCAP_ERRBUF_SIZE,
+                   errno, "snoop bind");
                goto bad;
        }
        memset(&sf, 0, sizeof(sf));
        if (ioctl(fd, SIOCADDSNOOP, &sf) < 0) {
-               snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "SIOCADDSNOOP: %s",
-                   pcap_strerror(errno));
+               pcap_fmt_errmsg_for_errno(p->errbuf, PCAP_ERRBUF_SIZE,
+                   errno, "SIOCADDSNOOP");
                goto bad;
        }
        if (p->opt.buffer_size != 0)
@@ -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;
        }
@@ -316,6 +323,17 @@ pcap_activate_snoop(pcap_t *p)
                return (PCAP_ERROR_RFMON_NOTSUP);
        }
 
+       /*
+        * Turn a negative snapshot value (invalid), a snapshot value of
+        * 0 (unspecified), or a value bigger than the normal maximum
+        * value, into the maximum allowed value.
+        *
+        * If some application really *needs* a bigger snapshot
+        * length, we should just increase MAXIMUM_SNAPLEN.
+        */
+       if (p->snapshot <= 0 || p->snapshot > MAXIMUM_SNAPLEN)
+               p->snapshot = MAXIMUM_SNAPLEN;
+
 #ifdef SIOCGIFMTU
        /*
         * XXX - IRIX appears to give you an error if you try to set the
@@ -323,10 +341,10 @@ 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_strerror(errno));
+               pcap_fmt_errmsg_for_errno(p->errbuf, PCAP_ERRBUF_SIZE,
+                   errno, "SIOCGIFMTU");
                goto bad;
        }
        /*
@@ -359,22 +377,22 @@ 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_strerror(errno));
+               pcap_fmt_errmsg_for_errno(p->errbuf, PCAP_ERRBUF_SIZE,
+                   errno, "SIOCSNOOPLEN");
                goto bad;
        }
        v = 1;
        if (ioctl(fd, SIOCSNOOPING, &v) < 0) {
-               snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "SIOCSNOOPING: %s",
-                   pcap_strerror(errno));
+               pcap_fmt_errmsg_for_errno(p->errbuf, PCAP_ERRBUF_SIZE,
+                   errno, "SIOCSNOOPING");
                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_strerror(errno));
+               pcap_fmt_errmsg_for_errno(p->errbuf, PCAP_ERRBUF_SIZE,
+                   errno, "malloc");
                goto bad;
        }
 
@@ -399,11 +417,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 +429,39 @@ pcap_create_interface(const char *device, char *ebuf)
        return (p);
 }
 
-int
-pcap_platform_finddevs(pcap_if_t **alldevsp, char *errbuf)
+/*
+ * 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);
+}
+
+static int
+get_if_flags(const char *name _U_, bpf_u_int32 *flags _U_, char *errbuf _U_)
+{
+       /*
+        * Nothing we can do.
+        * XXX - is there a way to find out whether an adapter has
+        * something plugged into it?
+        */
        return (0);
 }
+
+int
+pcap_platform_finddevs(pcap_if_list_t *devlistp, char *errbuf)
+{
+       return (pcap_findalldevs_interfaces(devlistp, errbuf, can_be_bound,
+           get_if_flags));
+}
+
+/*
+ * Libpcap version string.
+ */
+const char *
+pcap_lib_version(void)
+{
+       return (PCAP_VERSION_STRING);
+}
diff --git a/pcap-tc.c b/pcap-tc.c
new file mode 100644 (file)
index 0000000..65fb0e2
--- /dev/null
+++ b/pcap-tc.c
@@ -0,0 +1,1292 @@
+/*
+ * 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);
+static int TcSetNonBlock(pcap_t *p, int nonblock);
+static void TcCleanup(pcap_t *p);
+static int TcInject(pcap_t *p, const void *buf, int 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_list_t *devlist, char *errbuf)
+{
+       TC_API_LOAD_STATUS loadStatus;
+       ULONG numPorts;
+       PTC_PORT pPorts = NULL;
+       TC_STATUS status;
+       int result = 0;
+       pcap_if_t *dev;
+       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)
+                               add_dev(devlist, dev->name, dev->flags, dev->description, errbuf);
+               }
+
+               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;
+       }
+
+       /*
+        * Turn a negative snapshot value (invalid), a snapshot value of
+        * 0 (unspecified), or a value bigger than the normal maximum
+        * value, into the maximum allowed value.
+        *
+        * If some application really *needs* a bigger snapshot
+        * length, we should just increase MAXIMUM_SNAPLEN.
+        */
+       if (p->snapshot <= 0 || p->snapshot > MAXIMUM_SNAPLEN)
+               p->snapshot = MAXIMUM_SNAPLEN;
+
+       /*
+        * 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;
+       /*
+        * Set these up front, so that, even if our client tries
+        * to set non-blocking mode before we're activated, or
+        * query the state of non-blocking mode, they get an error,
+        * rather than having the non-blocking mode option set
+        * for use later.
+        */
+       p->getnonblock_op = TcGetNonBlock;
+       p->setnonblock_op = TcSetNonBlock;
+       return p;
+}
+
+static int TcSetDatalink(pcap_t *p, int dlt)
+{
+       /*
+        * We don't have to do any work here; pcap_set_datalink() checks
+        * whether the value is in the list of DLT_ values we
+        * supplied, so we don't have to, and, if it is valid, sets
+        * p->linktype to the new value; we don't have to do anything
+        * in hardware, we just use what's in p->linktype.
+        *
+        * We do have to have a routine, however, so that pcap_set_datalink()
+        * doesn't think we don't support setting the link-layer header
+        * type at all.
+        */
+       return 0;
+}
+
+static int TcGetNonBlock(pcap_t *p)
+{
+       pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
+           "Non-blocking mode isn't supported for TurboCap ports");
+       return -1;
+}
+
+static int TcSetNonBlock(pcap_t *p, int nonblock)
+{
+       pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
+           "Non-blocking mode isn't supported 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, int 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(ENABLE_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)
+       {
+               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;
+       }
+
+#if defined(_WIN32) && defined(ENABLE_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/pcap-tc.h b/pcap-tc.h
new file mode 100644 (file)
index 0000000..f7b2d12
--- /dev/null
+++ b/pcap-tc.h
@@ -0,0 +1,54 @@
+/*
+ * 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.
+ *
+ */
+
+#ifndef __PCAP_TC_H__
+#define __PCAP_TC_H__
+
+/*
+ * needed because gcc headers do not have C_ASSERT
+ */
+#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_list_t *devlistp, char *errbuf);
+
+#endif
index f86f833..6437e80 100644 (file)
@@ -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
@@ -93,9 +93,9 @@ call and before a
 call to specify the type of time stamp to be used on the device.
 The time stamp types are listed here; the first value is the #define to
 use in code, the second value is the value returned by
-.B pcap_tstamp_type_val_to_name()
+.B pcap_tstamp_type_val_to_name(3PCAP)
 and accepted by
-.BR pcap_tstamp_type_name_to_val() .
+.BR pcap_tstamp_type_name_to_val(3PCAP) .
 .RS 5
 .TP 5
 .BR PCAP_TSTAMP_HOST " - " host
@@ -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,44 @@ 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(3PCAP)
similarity index 62%
rename from pcap-stdinc.h
rename to pcap-types.h
index f70dcce..9614f9f 100644 (file)
  * (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
+#ifndef pcap_types_h
+#define pcap_types_h
 
 /*
- * Avoids a compiler warning in case this was already defined
- * (someone defined _WINSOCKAPI_ when including 'windows.h', in order
- * to prevent it from including 'winsock.h')
+ * Get u_int defined, by hook or by crook.
  */
-#ifdef _WINSOCKAPI_
-#undef _WINSOCKAPI_
+#ifdef _WIN32
+
+  /*
+   * This defines u_int.
+   */
+  #include <winsock2.h>
+#else /* _WIN32 */
+  /*
+   * This defines u_int, among other types.
+   */
+  #include <sys/types.h>
 #endif
 
-#include <winsock2.h>
-#include <fcntl.h>
-#include <time.h>
-#include <io.h>
-
-#include "bittypes.h"
-#include "IP6_misc.h"
-
-#define caddr_t char*
-
-#if defined(_MSC_VER)
-  #define snprintf  _snprintf
-  #define vsnprintf _vsnprintf
-  #define strdup    _strdup
-#endif
-
-#define inline __inline
-
-#ifdef __MINGW32__
-  #include <stdint.h>
-#else
-  #ifndef _UINTPTR_T_DEFINED
-    #ifdef  _WIN64
-      typedef unsigned __int64    uintptr_t;
-    #else
-      typedef _W64 unsigned int   uintptr_t;
-    #endif
-    #define _UINTPTR_T_DEFINED
-  #endif
-
-  #ifndef _INTPTR_T_DEFINED
-    #ifdef  _WIN64
-      typedef __int64    intptr_t;
-    #else
-      typedef _W64 int   intptr_t;
-    #endif
-    #define _INTPTR_T_DEFINED
-  #endif
-#endif /*__MINGW32__*/
-
-#endif /* pcap_stdinc_h */
+#endif /* pcap_types_h */
index bdabf00..b306dca 100644 (file)
@@ -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,9 +32,9 @@
  * Modifications: Kris Katterjohn <katterjohn@gmail.com>
  *
  */
+
 #ifdef HAVE_CONFIG_H
-#include "config.h"
+#include <config.h>
 #endif
 
 #include "pcap-int.h"
 #include <stdlib.h>
 #include <unistd.h>
 #include <fcntl.h>
+#include <limits.h>
 #include <string.h>
 #include <dirent.h>
 #include <byteswap.h>
 #include <netinet/in.h>
 #include <sys/ioctl.h>
 #include <sys/mman.h>
+#include <sys/utsname.h>
 #ifdef HAVE_LINUX_USBDEVICE_FS_H
 /*
  * We might need <linux/compiler.h> to define __user for
@@ -85,8 +87,8 @@
 #endif
 
 struct mon_bin_stats {
-       u_int32_t queued;
-       u_int32_t dropped;
+       uint32_t queued;
+       uint32_t dropped;
 };
 
 struct mon_bin_get {
@@ -138,24 +140,131 @@ static int usb_inject_linux(pcap_t *, const void *, size_t);
 static int usb_setdirection_linux(pcap_t *, pcap_direction_t);
 static void usb_cleanup_linux_mmap(pcap_t *);
 
+static int
+have_binary_usbmon(void)
+{
+       struct utsname utsname;
+       char *version_component, *endp;
+       int major, minor, subminor;
+
+       if (uname(&utsname) == 0) {
+               /*
+                * 2.6.21 is the first release with the binary-mode
+                * USB monitoring.
+                */
+               version_component = utsname.release;
+               major = strtol(version_component, &endp, 10);
+               if (endp != version_component && *endp == '.') {
+                       /*
+                        * OK, that was a valid major version.
+                        * Is it 3 or greater?  If so, we have binary
+                        * mode support.
+                        */
+                       if (major >= 3)
+                               return 1;
+
+                       /*
+                        * Is it 1 or less?  If so, we don't have binary
+                        * mode support.  (In fact, we don't have any
+                        * USB monitoring....)
+                        */
+                       if (major <= 1)
+                               return 0;
+               }
+
+               /*
+                * OK, this is a 2.x kernel.
+                * What's 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 is 2.6 or later?  (There shouldn't be a
+                        * "later", as 2.6.x went to 3.x, but we'll
+                        * check anyway.)
+                        */
+                       if (minor < 6) {
+                               /*
+                                * No, so no binary support (did 2.4 have
+                                * any USB monitoring at all?)
+                                */
+                               return 0;
+                       }
+
+                       /*
+                        * OK, this is a 2.6.x kernel.
+                        * What's the subminor version?
+                        */
+                       version_component = endp + 1;
+                       subminor = strtol(version_component, &endp, 10);
+                       if (endp != version_component &&
+                           (*endp == '.' || *endp == '\0')) {
+                               /*
+                                * OK, that was a valid subminor version.
+                                * Is it 21 or greater?
+                                */
+                               if (subminor >= 21) {
+                                       /*
+                                        * Yes - we have binary mode
+                                        * support.
+                                        */
+                                       return 1;
+                               }
+                       }
+               }
+       }
+
+       /*
+        * Either uname() failed, in which case we just say "no binary
+        * mode support", or we don't have binary mode support.
+        */
+       return 0;
+}
+
 /* facility to add an USB device to the device list*/
-static int 
-usb_dev_add(pcap_if_t** alldevsp, int n, char *err_str)
+static int
+usb_dev_add(pcap_if_list_t *devlistp, 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);
+       /*
+        * XXX - is there any notion of "up" and "running"?
+        */
+       if (n == 0) {
+               /*
+                * As this refers to all buses, there's no notion of
+                * "connected" vs. "disconnected", as that's a property
+                * that would apply to a particular USB interface.
+                */
+               if (add_dev(devlistp, dev_name,
+                   PCAP_IF_CONNECTION_STATUS_NOT_APPLICABLE,
+                   "Raw USB traffic, all USB buses", err_str) == NULL)
+                       return -1;
+       } else {
+               /*
+                * XXX - is there a way to determine whether anything's
+                * plugged into this bus interface or not, and set
+                * PCAP_IF_CONNECTION_STATUS_CONNECTED or
+                * PCAP_IF_CONNECTION_STATUS_DISCONNECTED?
+                */
+               pcap_snprintf(dev_descr, 30, "Raw USB traffic, bus number %d", n);
+               if (add_dev(devlistp, dev_name, 0, dev_descr, err_str) == NULL)
+                       return -1;
+       }
 
-       if (pcap_add_if(alldevsp, dev_name, 0, 
-           dev_descr, err_str) < 0)
-               return -1;
-       return 0; 
+       return 0;
 }
 
-int 
-usb_findalldevs(pcap_if_t **alldevsp, char *err_str)
+int
+usb_findalldevs(pcap_if_list_t *devlistp, char *err_str)
 {
+       char usb_mon_dir[PATH_MAX];
+       char *usb_mon_prefix;
+       size_t usb_mon_prefix_len;
        struct dirent* data;
        int ret = 0;
        DIR* dir;
@@ -163,62 +272,211 @@ usb_findalldevs(pcap_if_t **alldevsp, char *err_str)
        char* name;
        size_t len;
 
-       /* try scanning sysfs usb bus directory */
-       dir = opendir(SYS_USB_BUS_DIR);
-       if (dir != NULL) {
-               while ((ret == 0) && ((data = readdir(dir)) != 0)) {
-                       name = data->d_name;
+       if (have_binary_usbmon()) {
+               /*
+                * We have binary-mode support.
+                * What do the device names look like?
+                * Split LINUX_USB_MON_DEV into a directory that we'll
+                * scan and a file name prefix that we'll check for.
+                */
+               pcap_strlcpy(usb_mon_dir, LINUX_USB_MON_DEV, sizeof usb_mon_dir);
+               usb_mon_prefix = strrchr(usb_mon_dir, '/');
+               if (usb_mon_prefix == NULL) {
+                       /*
+                        * This "shouldn't happen".  Just give up if it
+                        * does.
+                        */
+                       return 0;
+               }
+               *usb_mon_prefix++ = '\0';
+               usb_mon_prefix_len = strlen(usb_mon_prefix);
 
-                       if (strncmp(name, "usb", 3) != 0)
-                               continue;
+               /*
+                * Open the directory and scan it.
+                */
+               dir = opendir(usb_mon_dir);
+               if (dir != NULL) {
+                       while ((ret == 0) && ((data = readdir(dir)) != 0)) {
+                               name = data->d_name;
 
-                       if (sscanf(&name[3], "%d", &n) == 0) 
-                               continue;
+                               /*
+                                * Is this a usbmon device?
+                                */
+                               if (strncmp(name, usb_mon_prefix, usb_mon_prefix_len) != 0)
+                                       continue;       /* no */
+
+                               /*
+                                * What's the device number?
+                                */
+                               if (sscanf(&name[usb_mon_prefix_len], "%d", &n) == 0)
+                                       continue;       /* failed */
+
+                               ret = usb_dev_add(devlistp, n, err_str);
+                       }
 
-                       ret = usb_dev_add(alldevsp, n, err_str);
+                       closedir(dir);
                }
+               return 0;
+       } else {
+               /*
+                * We have only text mode support.
+                * We don't look for the text devices because we can't
+                * look for them without root privileges, and we don't
+                * want to require root privileges to enumerate devices
+                * (we want to let the user to try a device and get
+                * an error, rather than seeing no devices and asking
+                * "why am I not seeing devices" and forcing a long
+                * process of poking to figure out whether it's "no
+                * privileges" or "your kernel is too old" or "the
+                * usbmon module isn't loaded" or...).
+                *
+                * Instead, we look to see what buses we have.
+                * If the kernel is so old that it doesn't have
+                * binary-mode support, it's also so old that
+                * it doesn't have a "scan all buses" device.
+                *
+                * First, try scanning sysfs USB bus directory.
+                */
+               dir = opendir(SYS_USB_BUS_DIR);
+               if (dir != NULL) {
+                       while ((ret == 0) && ((data = readdir(dir)) != 0)) {
+                               name = data->d_name;
 
-               closedir(dir);
-               return ret;
-       }
+                               if (strncmp(name, "usb", 3) != 0)
+                                       continue;
 
-       /* 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)) {
-                       name = data->d_name;
-                       len = strlen(name);
+                               if (sscanf(&name[3], "%d", &n) == 0)
+                                       continue;
 
-                       /* if this file name does not end with a number it's not of our interest */
-                       if ((len < 1) || !isdigit(name[--len]))
-                               continue;
-                       while (isdigit(name[--len]));
-                       if (sscanf(&name[len+1], "%d", &n) != 1) 
-                               continue;
+                               ret = usb_dev_add(devlistp, n, err_str);
+                       }
+
+                       closedir(dir);
+                       return 0;
+               }
 
-                       ret = usb_dev_add(alldevsp, n, err_str);
+               /* 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)) {
+                               name = data->d_name;
+                               len = strlen(name);
+
+                               /* if this file name does not end with a number it's not of our interest */
+                               if ((len < 1) || !isdigit(name[--len]))
+                                       continue;
+                               while (isdigit(name[--len]));
+                               if (sscanf(&name[len+1], "%d", &n) != 1)
+                                       continue;
+
+                               ret = usb_dev_add(devlistp, n, err_str);
+                       }
+
+                       closedir(dir);
+                       return ret;
                }
 
-               closedir(dir);
-               return ret;
+               /* neither of them worked */
+               return 0;
        }
+}
 
-       /* neither of them worked */
-       return 0;
+/*
+ * Matches what's in mon_bin.c in the Linux kernel.
+ */
+#define MIN_RING_SIZE  (8*1024)
+#define MAX_RING_SIZE  (1200*1024)
+
+static int
+usb_set_ring_size(pcap_t* handle, int header_size)
+{
+       /*
+        * A packet from binary usbmon has:
+        *
+        *  1) a fixed-length header, of size header_size;
+        *  2) descriptors, for isochronous transfers;
+        *  3) the payload.
+        *
+        * The kernel buffer has a size, defaulting to 300KB, with a
+        * minimum of 8KB and a maximum of 1200KB.  The size is set with
+        * the MON_IOCT_RING_SIZE ioctl; the size passed in is rounded up
+        * to a page size.
+        *
+        * No more than {buffer size}/5 bytes worth of payload is saved.
+        * Therefore, if we subtract the fixed-length size from the
+        * snapshot length, we have the biggest payload we want (we
+        * don't worry about the descriptors - if we have descriptors,
+        * we'll just discard the last bit of the payload to get it
+        * to fit).  We multiply that result by 5 and set the buffer
+        * size to that value.
+        */
+       int ring_size;
+
+       if (handle->snapshot < header_size)
+               handle->snapshot = header_size;
+       /* The maximum snapshot size is small enough that this won't overflow */
+       ring_size = (handle->snapshot - header_size) * 5;
+
+       /*
+        * Will this get an error?
+        * (There's no wqy to query the minimum or maximum, so we just
+        * copy the value from the kernel source.  We don't round it
+        * up to a multiple of the page size.)
+        */
+       if (ring_size > MAX_RING_SIZE) {
+               /*
+                * Yes.  Lower the ring size to the maximum, and set the
+                * snapshot length to the value that would give us a
+                * maximum-size ring.
+                */
+               ring_size = MAX_RING_SIZE;
+               handle->snapshot = header_size + (MAX_RING_SIZE/5);
+       } else if (ring_size < MIN_RING_SIZE) {
+               /*
+                * Yes.  Raise the ring size to the minimum, but leave
+                * the snapshot length unchanged, so we show the
+                * callback no more data than specified by the
+                * snapshot length.
+                */
+               ring_size = MIN_RING_SIZE;
+       }
+
+       if (ioctl(handle->fd, MON_IOCT_RING_SIZE, ring_size) == -1) {
+               pcap_fmt_errmsg_for_errno(handle->errbuf, PCAP_ERRBUF_SIZE,
+                   errno, "Can't set ring size from fd %d", handle->fd);
+               return -1;
+       }
+       return ring_size;
 }
 
-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) 
+       int len;
+
+       /*
+        * Attempt to set the ring size as appropriate for the snapshot
+        * length, reducing the snapshot length if that'd make the ring
+        * bigger than the kernel supports.
+        */
+       len = usb_set_ring_size(handle, (int)sizeof(pcap_usb_header_mmapped));
+       if (len == -1) {
+               /* Failed.  Fall back on non-memory-mapped access. */
                return 0;
+       }
 
        handlep->mmapbuflen = len;
        handlep->mmapbuf = mmap(0, handlep->mmapbuflen, PROT_READ,
            MAP_SHARED, handle->fd, 0);
-       return handlep->mmapbuf != MAP_FAILED;
+       if (handlep->mmapbuf == MAP_FAILED) {
+               /*
+                * Failed.  We don't treat that as a fatal error, we
+                * just try to fall back on non-memory-mapped access.
+                */
+               return 0;
+       }
+       return 1;
 }
 
 #ifdef HAVE_LINUX_USBDEVICE_FS_H
@@ -243,11 +501,11 @@ probe_devices(int bus)
        struct usbdevfs_ctrltransfer ctrl;
        struct dirent* data;
        int ret = 0;
-       char buf[40];
+       char buf[sizeof("/dev/bus/usb/000/") + NAME_MAX];
        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 +517,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;
@@ -269,7 +527,7 @@ probe_devices(int bus)
                 * Sigh.  Different kernels have different member names
                 * for this structure.
                 */
-#ifdef HAVE_USBDEVFS_CTRLTRANSFER_BREQUESTTYPE
+#ifdef HAVE_STRUCT_USBDEVFS_CTRLTRANSFER_BREQUESTTYPE
                ctrl.bRequestType = USB_DIR_IN | USB_TYPE_STANDARD | USB_RECIP_DEVICE;
                ctrl.bRequest = USB_REQ_GET_DESCRIPTOR;
                ctrl.wValue = USB_DT_DEVICE << 8;
@@ -328,7 +586,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);
 
@@ -341,6 +599,18 @@ usb_activate(pcap_t* handle)
 {
        struct pcap_usb_linux *handlep = handle->priv;
        char            full_path[USB_LINE_LEN];
+       int             ret;
+
+       /*
+        * Turn a negative snapshot value (invalid), a snapshot value of
+        * 0 (unspecified), or a value bigger than the normal maximum
+        * value, into the maximum allowed value.
+        *
+        * If some application really *needs* a bigger snapshot
+        * length, we should just increase MAXIMUM_SNAPLEN.
+        */
+       if (handle->snapshot <= 0 || handle->snapshot > MAXIMUM_SNAPLEN)
+               handle->snapshot = MAXIMUM_SNAPLEN;
 
        /* Initialize some components of the pcap structure. */
        handle->bufsize = handle->snapshot;
@@ -355,19 +625,61 @@ 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);  
-       handle->fd = open(full_path, O_RDONLY, 0);
-       if (handle->fd >= 0)
+       if (have_binary_usbmon())
        {
-               if (handle->opt.rfmon) {
+               /*
+                * We have binary-mode support.
+                * Try to open the binary interface.
+                */
+               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)
+               {
+                       /*
+                        * The attempt failed; why?
+                        */
+                       switch (errno) {
+
+                       case ENOENT:
+                               /*
+                                * The device doesn't exist.
+                                * That could either mean that there's
+                                * no support for monitoring USB buses
+                                * (which probably means "the usbmon
+                                * module isn't loaded") or that there
+                                * is but that *particular* device
+                                * doesn't exist (no "scan all buses"
+                                * device if the bus index is 0, no
+                                * such bus if the bus index isn't 0).
+                                */
+                               return PCAP_ERROR_NO_SUCH_DEVICE;
+
+                       case EACCES:
+                               /*
+                                * We didn't have permission to open it.
+                                */
+                               return PCAP_ERROR_PERM_DENIED;
+
+                       default:
+                               /*
+                                * Something went wrong.
+                                */
+                               pcap_fmt_errmsg_for_errno(handle->errbuf,
+                                   PCAP_ERRBUF_SIZE, errno,
+                                   "Can't open USB bus file %s", full_path);
+                               return PCAP_ERROR;
+                       }
+               }
+
+               if (handle->opt.rfmon)
+               {
                        /*
                         * Monitor mode doesn't apply to USB devices.
                         */
@@ -375,8 +687,10 @@ usb_activate(pcap_t* handle)
                        return PCAP_ERROR_RFMON_NOTSUP;
                }
 
-               /* binary api is available, try to use fast mmap access */
-               if (usb_mmap(handle)) {
+               /* try to use fast mmap access */
+               if (usb_mmap(handle))
+               {
+                       /* We succeeded. */
                        handle->linktype = DLT_USB_LINUX_MMAPPED;
                        handle->stats_op = usb_stats_linux_bin;
                        handle->read_op = usb_read_linux_mmap;
@@ -386,14 +700,26 @@ usb_activate(pcap_t* handle)
 #endif
 
                        /*
-                        * "handle->fd" is a real file, so "select()" and
-                        * "poll()" work on it.
+                        * "handle->fd" is a real file, so
+                        * "select()" and "poll()" work on it.
                         */
                        handle->selectable_fd = handle->fd;
                        return 0;
                }
 
-               /* can't mmap, use plain binary interface access */
+               /*
+                * We failed; try plain binary interface access.
+                *
+                * Attempt to set the ring size as appropriate for
+                * the snapshot length, reducing the snapshot length
+                * if that'd make the ring bigger than the kernel
+                * supports.
+                */
+               if (usb_set_ring_size(handle, (int)sizeof(pcap_usb_header)) == -1) {
+                       /* Failed. */
+                       close(handle->fd);
+                       return PCAP_ERROR;
+               }
                handle->stats_op = usb_stats_linux_bin;
                handle->read_op = usb_read_linux_bin;
 #ifdef HAVE_LINUX_USBDEVICE_FS_H
@@ -401,8 +727,11 @@ usb_activate(pcap_t* handle)
 #endif
        }
        else {
-               /*Binary interface not available, try open text interface */
-               snprintf(full_path, USB_LINE_LEN, USB_TEXT_DIR"/%dt", handlep->bus_index);  
+               /*
+                * We don't have binary mode support.
+                * Try opening the text-mode device.
+                */
+               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,18 +741,47 @@ 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,
-                                       "Can't open USB bus file %s: %s", full_path, strerror(errno));
-                               return PCAP_ERROR;
+                               if (errno == ENOENT)
+                               {
+                                       /*
+                                        * The problem is that the file
+                                        * doesn't exist.  Report that as
+                                        * "no such device".  (That could
+                                        * mean "no such USB bus" or
+                                        * "monitoring not supported".)
+                                        */
+                                       ret = PCAP_ERROR_NO_SUCH_DEVICE;
+                               }
+                               else if (errno == EACCES)
+                               {
+                                       /*
+                                        * The problem is that we don't
+                                        * have sufficient permission to
+                                        * open the file.  Report that.
+                                        */
+                                       ret = PCAP_ERROR_PERM_DENIED;
+                               }
+                               else
+                               {
+                                       /*
+                                        * Some other error.
+                                        */
+                                       ret = PCAP_ERROR;
+                               }
+                               pcap_fmt_errmsg_for_errno(handle->errbuf,
+                                   PCAP_ERRBUF_SIZE, errno,
+                                   "Can't open USB bus file %s",
+                                   full_path);
+                               return ret;
                        }
                }
 
-               if (handle->opt.rfmon) {
+               if (handle->opt.rfmon)
+               {
                        /*
                         * Monitor mode doesn't apply to USB devices.
                         */
@@ -445,30 +803,30 @@ usb_activate(pcap_t* handle)
         * buffer */
        handle->buffer = malloc(handle->bufsize);
        if (!handle->buffer) {
-               snprintf(handle->errbuf, PCAP_ERRBUF_SIZE,
-                        "malloc: %s", pcap_strerror(errno));
+               pcap_fmt_errmsg_for_errno(handle->errbuf, PCAP_ERRBUF_SIZE,
+                   errno, "malloc");
                close(handle->fd);
                return PCAP_ERROR;
        }
        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)
+usb_read_linux(pcap_t *handle, int max_packets _U_, 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 +854,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,
-                   "Can't read from fd %d: %s", handle->fd, strerror(errno));
+               pcap_fmt_errmsg_for_errno(handle->errbuf, PCAP_ERRBUF_SIZE,
+                   errno, "Can't read from fd %d", handle->fd);
                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,11 +879,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", 
-                       string, errno, strerror(errno));
+               pcap_fmt_errmsg_for_errno(handle->errbuf, PCAP_ERRBUF_SIZE,
+                   errno, "Can't get timestamp for message '%s'", string);
                return -1;
        }
        uhdr->ts_sec = pkth.ts.tv_sec;
@@ -567,15 +924,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 +949,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 +974,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 +988,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 +1006,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,
@@ -663,14 +1020,14 @@ got:
 }
 
 static int
-usb_inject_linux(pcap_t *handle, const void *buf, size_t size)
+usb_inject_linux(pcap_t *handle, const void *buf _U_, size_t size _U_)
 {
-       snprintf(handle->errbuf, PCAP_ERRBUF_SIZE, "inject not supported on "
-               "USB devices");
+       pcap_snprintf(handle->errbuf, PCAP_ERRBUF_SIZE,
+           "Packet injection is 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 +1037,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,13 +1047,13 @@ 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", 
-                               string, strerror(errno));
+                       pcap_fmt_errmsg_for_errno(handle->errbuf,
+                           PCAP_ERRBUF_SIZE, errno,
+                           "Can't open USB stats file %s", string);
                        return -1;
                }
        }
@@ -709,19 +1066,23 @@ 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;
        }
        string[ret] = 0;
 
+       stats->ps_recv = handlep->packets_read;
+       stats->ps_drop = 0;     /* unless we find text_lost */
+       stats->ps_ifdrop = 0;
+
        /* 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;
 
@@ -731,22 +1092,20 @@ usb_stats_linux(pcap_t *handle, struct pcap_stat *stats)
                        break;
                consumed += cnt;
                ptr += cnt;
-               if (strcmp(token, "nreaders") == 0)
-                       ret = sscanf(ptr, "%d", &stats->ps_drop);
-               else 
-                       ret = sscanf(ptr, "%d", &dummy);
-               if (ntok != 1)
+               if (strcmp(token, "text_lost") == 0)
+                       ntok = sscanf(ptr, "%d%n", &stats->ps_drop, &cnt);
+               else
+                       ntok = sscanf(ptr, "%d%n", &dummy, &cnt);
+               if ((ntok != 1) || (cnt < 0))
                        break;
                consumed += cnt;
                ptr += cnt;
        }
 
-       stats->ps_recv = handlep->packets_read;
-       stats->ps_ifdrop = 0;
        return 0;
 }
 
-static int 
+static int
 usb_setdirection_linux(pcap_t *p, pcap_direction_t d)
 {
        p->direction = d;
@@ -754,7 +1113,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,8 +1122,8 @@ 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,
-                       "Can't read stats from fd %d:%s ", handle->fd, strerror(errno));
+               pcap_fmt_errmsg_for_errno(handle->errbuf, PCAP_ERRBUF_SIZE,
+                   errno, "Can't read stats from fd %d", handle->fd);
                return -1;
        }
 
@@ -775,21 +1134,21 @@ 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
-usb_read_linux_bin(pcap_t *handle, int max_packets, pcap_handler callback, u_char *user)
+usb_read_linux_bin(pcap_t *handle, int max_packets _U_, pcap_handler callback, u_char *user)
 {
        struct pcap_usb_linux *handlep = handle->priv;
        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,18 +1165,49 @@ 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,
-                   "Can't read from fd %d: %s", handle->fd, strerror(errno));
+               pcap_fmt_errmsg_for_errno(handle->errbuf, PCAP_ERRBUF_SIZE,
+                   errno, "Can't read from fd %d", handle->fd);
                return -1;
        }
 
-       /* we can get less that than really captured from kernel, depending on
-        * snaplen, so adjust header accordingly */
+       /*
+        * info.hdr->data_len is the number of bytes of isochronous
+        * descriptors (if any) plus the number of bytes of data
+        * provided.  There are no isochronous descriptors here,
+        * because we're using the old 48-byte header.
+        *
+        * If info.hdr->data_flag is non-zero, there's no URB data;
+        * info.hdr->urb_len is the size of the buffer into which
+        * data is to be placed; it does not represent the amount
+        * of data transferred.  If info.hdr->data_flag is zero,
+        * there is URB data, and info.hdr->urb_len is the number
+        * of bytes transmitted or received; it doesn't include
+        * isochronous descriptors.
+        *
+        * The kernel may give us more data than the snaplen; if it did,
+        * reduce the data length so that the total number of bytes we
+        * tell our client we have is not greater than the snaplen.
+        */
        if (info.hdr->data_len < clen)
                clen = info.hdr->data_len;
        info.hdr->data_len = clen;
-       pkth.caplen = clen + sizeof(pcap_usb_header);
-       pkth.len = info.hdr->data_len + sizeof(pcap_usb_header);
+       pkth.caplen = sizeof(pcap_usb_header) + clen;
+       if (info.hdr->data_flag) {
+               /*
+                * No data; just base the on-the-wire length on
+                * info.hdr->data_len (so that it's >= the captured
+                * length).
+                */
+               pkth.len = sizeof(pcap_usb_header) + info.hdr->data_len;
+       } else {
+               /*
+                * We got data; base the on-the-wire length on
+                * info.hdr->urb_len, so that it includes data
+                * discarded by the USB monitor device due to
+                * its buffer being too small.
+                */
+               pkth.len = sizeof(pcap_usb_header) + info.hdr->urb_len;
+       }
        pkth.ts.tv_sec = info.hdr->ts_sec;
        pkth.ts.tv_usec = info.hdr->ts_usec;
 
@@ -833,7 +1223,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
@@ -844,12 +1234,12 @@ usb_read_linux_mmap(pcap_t *handle, int max_packets, pcap_handler callback, u_ch
        struct mon_bin_mfetch fetch;
        int32_t vec[VEC_SIZE];
        struct pcap_pkthdr pkth;
-       pcap_usb_header* hdr;
+       pcap_usb_header_mmapped* hdr;
        int nflush = 0;
        int packets = 0;
-       int clen, max_clen;
+       u_int clen, max_clen;
 
-       max_clen = handle->snapshot - sizeof(pcap_usb_header);
+       max_clen = handle->snapshot - sizeof(pcap_usb_header_mmapped);
 
        for (;;) {
                int i, ret;
@@ -877,8 +1267,9 @@ 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,
-                           "Can't mfetch fd %d: %s", handle->fd, strerror(errno));
+                       pcap_fmt_errmsg_for_errno(handle->errbuf,
+                           PCAP_ERRBUF_SIZE, errno, "Can't mfetch fd %d",
+                           handle->fd);
                        return -1;
                }
 
@@ -886,19 +1277,52 @@ usb_read_linux_mmap(pcap_t *handle, int max_packets, pcap_handler callback, u_ch
                nflush = fetch.nfetch;
                for (i=0; i<fetch.nfetch; ++i) {
                        /* discard filler */
-                       hdr = (pcap_usb_header*) &handlep->mmapbuf[vec[i]];
-                       if (hdr->event_type == '@') 
+                       hdr = (pcap_usb_header_mmapped*) &handlep->mmapbuf[vec[i]];
+                       if (hdr->event_type == '@')
                                continue;
 
-                       /* we can get less that than really captured from kernel, depending on
-                       * snaplen, so adjust header accordingly */
+                       /*
+                        * hdr->data_len is the number of bytes of
+                        * isochronous descriptors (if any) plus the
+                        * number of bytes of data provided.
+                        *
+                        * If hdr->data_flag is non-zero, there's no
+                        * URB data; hdr->urb_len is the size of the
+                        * buffer into which data is to be placed; it does
+                        * not represent the amount of data transferred.
+                        * If hdr->data_flag is zero, there is URB data,
+                        * and hdr->urb_len is the number of bytes
+                        * transmitted or received; it doesn't include
+                        * isochronous descriptors.
+                        *
+                        * The kernel may give us more data than the
+                        * snaplen; if it did, reduce the data length
+                        * so that the total number of bytes we
+                        * tell our client we have is not greater than
+                        * the snaplen.
+                        */
                        clen = max_clen;
                        if (hdr->data_len < clen)
                                clen = hdr->data_len;
-
-                       /* get packet info from header*/
-                       pkth.caplen = clen + sizeof(pcap_usb_header_mmapped);
-                       pkth.len = hdr->data_len + sizeof(pcap_usb_header_mmapped);
+                       pkth.caplen = sizeof(pcap_usb_header_mmapped) + clen;
+                       if (hdr->data_flag) {
+                               /*
+                                * No data; just base the on-the-wire length
+                                * on hdr->data_len (so that it's >= the
+                                * captured length).
+                                */
+                               pkth.len = sizeof(pcap_usb_header_mmapped) +
+                                   hdr->data_len;
+                       } else {
+                               /*
+                                * We got data; base the on-the-wire length
+                                * on hdr->urb_len, so that it includes
+                                * data discarded by the USB monitor device
+                                * due to its buffer being too small.
+                                */
+                               pkth.len = sizeof(pcap_usb_header_mmapped) +
+                                   (hdr->ndesc * sizeof (usb_isodesc)) + hdr->urb_len;
+                       }
                        pkth.ts.tv_sec = hdr->ts_sec;
                        pkth.ts.tv_usec = hdr->ts_usec;
 
@@ -917,7 +1341,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_fmt_errmsg_for_errno(handle->errbuf, PCAP_ERRBUF_SIZE,
+                   errno, "Can't mflush fd %d", handle->fd);
+               return -1;
+       }
        return packets;
 }
 
index 06dee01..3ddc12f 100644 (file)
@@ -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
@@ -34,5 +34,5 @@
 /*
  * Prototypes for USB-related functions
  */
-int usb_findalldevs(pcap_if_t **alldevsp, char *err_str);
+int usb_findalldevs(pcap_if_list_t *devlistp, char *err_str);
 pcap_t *usb_create(const char *device, char *ebuf, int *is_ours);
diff --git a/pcap-win32.c b/pcap-win32.c
deleted file mode 100644 (file)
index f63b5c4..0000000
+++ /dev/null
@@ -1,951 +0,0 @@
-/*
- * Copyright (c) 1999 - 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.
- *
- */
-
-#include <pcap-int.h>
-#include <Packet32.h>
-#ifdef __MINGW32__
-#ifdef __MINGW64__
-#include <ntddndis.h>
-#else  /*__MINGW64__*/
-#include <ddk/ntddndis.h>
-#include <ddk/ndis.h>
-#endif /*__MINGW64__*/
-#else /*__MINGW32__*/
-#include <ntddndis.h>
-#endif /*__MINGW32__*/
-#ifdef HAVE_DAG_API
-#include <dagnew.h>
-#include <dagapi.h>
-#endif /* HAVE_DAG_API */
-#ifdef __MINGW32__
-int* _errno();
-#define errno (*_errno())
-#endif /* __MINGW32__ */
-
-static int pcap_setfilter_win32_npf(pcap_t *, struct bpf_program *);
-static int pcap_setfilter_win32_dag(pcap_t *, struct bpf_program *);
-static int pcap_getnonblock_win32(pcap_t *, char *);
-static int pcap_setnonblock_win32(pcap_t *, int, char *);
-
-/*dimension of the buffer in the pcap_t structure*/
-#define        WIN32_DEFAULT_USER_BUFFER_SIZE 256000
-
-/*dimension of the buffer in the kernel driver NPF */
-#define        WIN32_DEFAULT_KERNEL_BUFFER_SIZE 1000000
-
-/* Equivalent to ntohs(), but a lot faster under Windows */
-#define SWAPS(_X) ((_X & 0xff) << 8) | (_X >> 8)
-
-/*
- * Private data for capturing on WinPcap devices.
- */
-struct pcap_win {
-       int nonblock;
-
-       int filtering_in_kernel; /* using kernel filter */
-
-#ifdef HAVE_DAG_API
-       int     dag_fcs_bits;   /* Number of checksum bits from link layer */
-#endif
-};
-
-/*
- * Header that the WinPcap driver associates to the packets.
- * Once was in bpf.h
- */
-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;
-}
-
-/* Start winsock */
-int 
-wsockinit()
-{
-       WORD wVersionRequested;
-       WSADATA wsaData;
-       static int err = -1;
-       static int done = 0;
-
-       if (done)
-               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;
-}
-
-int pcap_wsockinit()
-{
-       return wsockinit();
-}
-
-static int
-pcap_stats_win32(pcap_t *p, struct pcap_stat *ps)
-{
-
-       if(PacketGetStats(p->adapter, (struct bpf_stat*)ps) != TRUE){
-               snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "PacketGetStats error: %s", pcap_win32strerror());
-               return -1;
-       }
-
-       return 0;
-}
-
-/* Set the dimension of the kernel-level capture buffer */
-static int
-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;
-       }
-       return 0;
-}
-
-/* Set the driver working mode */
-static int
-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;
-       }
-
-       return 0;
-}
-
-/*set the minimum amount of data that will release a read call*/
-static int
-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;
-       }
-       return 0;
-}
-
-/*return the Adapter for a pcap_t*/
-static Adapter *
-pcap_getadapter_win32(pcap_t *p)
-{
-       return p->adapter;
-}
-
-static int
-pcap_read_win32_npf(pcap_t *p, int cnt, pcap_handler callback, u_char *user)
-{
-       int cc;
-       int n = 0;
-       register u_char *bp, *ep;
-       u_char *datap;
-       struct pcap_win *pw = p->priv;
-
-       cc = p->cc;
-       if (p->cc == 0) {
-               /*
-                * Has "pcap_breakloop()" been called?
-                */
-               if (p->break_loop) {
-                       /*
-                        * Yes - clear the flag that indicates that it
-                        * has, and return PCAP_ERROR_BREAK to indicate
-                        * that we were told to break out of the loop.
-                        */
-                       p->break_loop = 0;
-                       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");
-                       return (PCAP_ERROR);
-               }
-                       
-               cc = p->Packet->ulBytesReceived;
-
-               bp = p->Packet->Buffer;
-       } 
-       else
-               bp = p->bp;
-
-       /*
-        * Loop through each packet.
-        */
-#define bhp ((struct bpf_hdr *)bp)
-       ep = bp + cc;
-       while (1) {
-               register int caplen, hdrlen;
-
-               /*
-                * Has "pcap_breakloop()" been called?
-                * If so, return immediately - if we haven't read any
-                * packets, clear the flag and return PCAP_ERROR_BREAK
-                * 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 (PCAP_ERROR_BREAK);
-                       } else {
-                               p->bp = bp;
-                               p->cc = ep - bp;
-                               return (n);
-                       }
-               }
-               if (bp >= ep)
-                       break;
-
-               caplen = bhp->bh_caplen;
-               hdrlen = bhp->bh_hdrlen;
-               datap = bp + hdrlen;
-
-               /*
-                * Short-circuit evaluation: if using BPF filter
-                * in kernel, no need to do it now - we already know
-                * the packet passed the filter.
-                *
-                * XXX - bpf_filter() should always return TRUE if
-                * handed a null pointer for the program, but it might
-                * just try to "run" the filter, so we check here.
-                */
-               if (pw->filtering_in_kernel ||
-                   p->fcode.bf_insns == NULL ||
-                   bpf_filter(p->fcode.bf_insns, datap, bhp->bh_datalen, caplen)) {
-                       /*
-                        * XXX A bpf_hdr matches a pcap_pkthdr.
-                        */
-                       (*callback)(user, (struct pcap_pkthdr*)bp, datap);
-                       bp += Packet_WORDALIGN(caplen + hdrlen);
-                       if (++n >= cnt && !PACKET_COUNT_IS_UNLIMITED(cnt)) {
-                               p->bp = bp;
-                               p->cc = ep - bp;
-                               return (n);
-                       }
-               } else {
-                       /*
-                        * Skip this packet.
-                        */
-                       bp += Packet_WORDALIGN(caplen + hdrlen);
-               }
-       }
-#undef bhp
-       p->cc = 0;
-       return (n);
-}
-
-#ifdef HAVE_DAG_API
-static int
-pcap_read_win32_dag(pcap_t *p, int cnt, pcap_handler callback, u_char *user)
-{
-       struct pcap_win *pw = p->priv;
-       u_char *dp = NULL;
-       int     packet_len = 0, caplen = 0;
-       struct pcap_pkthdr      pcap_header;
-       u_char *endofbuf;
-       int n = 0;
-       dag_record_t *header;
-       unsigned erf_record_len;
-       ULONGLONG ts;
-       int cc;
-       unsigned swt;
-       unsigned dfp = p->adapter->DagFastProcess;
-
-       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");
-                       return (-1);
-               }
-
-               cc = p->Packet->ulBytesReceived;
-               if(cc == 0)
-                       /* The timeout has expired but we no packets arrived */
-                       return 0;
-               header = (dag_record_t*)p->adapter->DagBuffer;
-       } 
-       else
-               header = (dag_record_t*)p->bp;
-       
-       endofbuf = (char*)header + cc;
-       
-       /* 
-        * Cycle through the packets 
-        */
-       do
-       {
-               erf_record_len = SWAPS(header->rlen);
-               if((char*)header + erf_record_len > endofbuf)
-                       break;
-
-               /* Increase the number of captured packets */
-               pw->stat.ps_recv++;
-               
-               /* Find the beginning of the packet */
-               dp = ((u_char *)header) + dag_record_size;
-
-               /* Determine actual packet len */
-               switch(header->type) 
-               {
-               case TYPE_ATM:
-                       packet_len = ATM_SNAPLEN;
-                       caplen = ATM_SNAPLEN;
-                       dp += 4;
-
-                       break;
-
-               case TYPE_ETH:
-                       swt = SWAPS(header->wlen);
-                       packet_len = swt - (pw->dag_fcs_bits);
-                       caplen = erf_record_len - dag_record_size - 2;
-                       if (caplen > packet_len)
-                       {
-                               caplen = packet_len;
-                       }
-                       dp += 2;
-                       
-                       break;
-               
-               case TYPE_HDLC_POS:
-                       swt = SWAPS(header->wlen);
-                       packet_len = swt - (pw->dag_fcs_bits);
-                       caplen = erf_record_len - dag_record_size;
-                       if (caplen > packet_len)
-                       {
-                               caplen = packet_len;
-                       }
-                       
-                       break;
-               }
-               
-               if(caplen > p->snapshot)
-                       caplen = p->snapshot;
-
-               /*
-                * 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 
-                       {
-                               p->bp = (char*)header;
-                               p->cc = endofbuf - (char*)header;
-                               return (n);
-                       }
-               }
-
-               if(!dfp)
-               {
-                       /* convert between timestamp formats */
-                       ts = header->ts;
-                       pcap_header.ts.tv_sec = (int)(ts >> 32);
-                       ts = (ts & 0xffffffffi64) * 1000000;
-                       ts += 0x80000000; /* rounding */
-                       pcap_header.ts.tv_usec = (int)(ts >> 32);
-                       if (pcap_header.ts.tv_usec >= 1000000) {
-                               pcap_header.ts.tv_usec -= 1000000;
-                               pcap_header.ts.tv_sec++;
-                       }
-               }
-               
-               /* No underlaying filtering system. We need to filter on our own */
-               if (p->fcode.bf_insns) 
-               {
-                       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)) 
-               {
-                       p->bp = (char*)header;
-                       p->cc = endofbuf - (char*)header;
-                       return (n);
-               }
-       }
-       while((u_char*)header < endofbuf);
-       
-  return 1;
-}
-#endif /* HAVE_DAG_API */
-
-/* Send a packet to the network */
-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;
-       }
-       
-       PacketInitPacket(PacketToSend,(PVOID)buf,size);
-       if(PacketSendPacket(p->adapter,PacketToSend,TRUE) == FALSE){
-               snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "send error: PacketSendPacket failed");
-               PacketFreePacket(PacketToSend);
-               return -1;
-       }
-
-       PacketFreePacket(PacketToSend);
-
-       /*
-        * We assume it all got sent if "PacketSendPacket()" succeeded.
-        * "pcap_inject()" is expected to return the number of bytes
-        * sent.
-        */
-       return size;
-}
-
-static void
-pcap_cleanup_win32(pcap_t *p)
-{
-       if (p->adapter != NULL) {
-               PacketCloseAdapter(p->adapter);
-               p->adapter = NULL;
-       }
-       if (p->Packet) {
-               PacketFreePacket(p->Packet);
-               p->Packet = NULL;
-       }
-       pcap_cleanup_live_common(p);
-}
-
-static int
-pcap_activate_win32(pcap_t *p)
-{
-       struct pcap_win *pw = p->priv;
-       NetType type;
-
-       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.
-                */
-               return (PCAP_ERROR_RFMON_NOTSUP);
-       }
-
-       /* Init WinSock */
-       wsockinit();
-
-       p->adapter = PacketOpenAdapter(p->opt.source);
-       
-       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;
-       }
-       
-       /*get network type*/
-       if(PacketGetNetType (p->adapter,&type) == FALSE)
-       {
-               snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "Cannot determine the network type: %s", pcap_win32strerror());
-               goto bad;
-       }
-       
-       /*Set the linktype*/
-       switch (type.LinkType) 
-       {
-       case NdisMediumWan:
-               p->linktype = DLT_EN10MB;
-               break;
-               
-       case NdisMedium802_3:
-               p->linktype = DLT_EN10MB;
-               /*
-                * This is (presumably) a real Ethernet capture; give it a
-                * link-layer-type list with DLT_EN10MB and DLT_DOCSIS, so
-                * that an application can let you choose it, in case you're
-                * capturing DOCSIS traffic that a Cisco Cable Modem
-                * Termination System is putting out onto an Ethernet (it
-                * doesn't put an Ethernet header onto the wire, it puts raw
-                * DOCSIS frames out on the wire inside the low-level
-                * Ethernet framing).
-                */
-               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_DOCSIS;
-                       p->dlt_count = 2;
-               }
-               break;
-               
-       case NdisMediumFddi:
-               p->linktype = DLT_FDDI;
-               break;
-               
-       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;
-
-       case NdisMediumPPPSerial:
-               p->linktype = DLT_PPP_SERIAL;
-               break;
-
-       case NdisMediumNull:
-               p->linktype = DLT_NULL;
-               break;
-
-       case NdisMediumBare80211:
-               p->linktype = DLT_IEEE802_11;
-               break;
-
-       case NdisMediumRadio80211:
-               p->linktype = DLT_IEEE802_11_RADIO;
-               break;
-
-       case NdisMediumPpi:
-               p->linktype = DLT_PPI;
-               break;
-
-       default:
-               p->linktype = DLT_EN10MB;                       /*an unknown adapter is assumed to be ethernet*/
-               break;
-       }
-
-       /* Set promiscuous mode */
-       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");
-                       goto bad;
-               }
-       }
-       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");
-                       goto bad;
-               }
-       }
-
-       /* 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 
-        */
-               /*
-                * If the buffer size wasn't explicitly set, default to
-                * WIN32_DEFAULT_USER_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");
-                       goto bad;
-               }
-               
-               p->buffer = (u_char *)malloc(p->bufsize);
-               if (p->buffer == NULL) 
-               {
-                       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());
-                               goto bad;
-                       }
-               }
-               else
-               {
-                       /* tell the driver to copy the buffer only if it contains at least 16K */
-                       if(PacketSetMinToCopy(p->adapter,16000)==FALSE)
-                       {
-                               snprintf(p->errbuf, PCAP_ERRBUF_SIZE,"Error calling PacketSetMinToCopy: %s", pcap_win32strerror());
-                               goto bad;
-                       }
-               }
-       }
-       else
-#ifdef HAVE_DAG_API
-       {
-       /* 
-        * Dag Card 
-        */
-               LONG    status;
-               HKEY    dagkey;
-               DWORD   lptype;
-               DWORD   lpcbdata;
-               int             postype = 0;
-               char    keyname[512];
-               
-               snprintf(keyname, sizeof(keyname), "%s\\CardParams\\%s", 
-                       "SYSTEM\\CurrentControlSet\\Services\\DAG",
-                       strstr(_strlwr(p->opt.source), "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 
-                * 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)
-       {
-               /* install dag specific handlers for read and setfilter */
-               p->read_op = pcap_read_win32_dag;
-               p->setfilter_op = pcap_setfilter_win32_dag;
-       }
-       else
-       {
-#endif /* HAVE_DAG_API */
-               /* install traditional npf handlers for read and setfilter */
-               p->read_op = pcap_read_win32_npf;
-               p->setfilter_op = pcap_setfilter_win32_npf;
-#ifdef HAVE_DAG_API
-       }
-#endif /* HAVE_DAG_API */
-       p->setdirection_op = NULL;      /* Not implemented. */
-           /* XXX - can this be implemented on some versions of Windows? */
-       p->inject_op = pcap_inject_win32;
-       p->set_datalink_op = NULL;      /* can't change data link type */
-       p->getnonblock_op = pcap_getnonblock_win32;
-       p->setnonblock_op = pcap_setnonblock_win32;
-       p->stats_op = pcap_stats_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->cleanup_op = pcap_cleanup_win32;
-
-       return (0);
-bad:
-       pcap_cleanup_win32(p);
-       return (PCAP_ERROR);
-}
-
-pcap_t *
-pcap_create_interface(const char *device, 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));
-       }
-
-       if (p == NULL)
-               return (NULL);
-
-       p->activate_op = pcap_activate_win32;
-       return (p);
-}
-
-static int
-pcap_setfilter_win32_npf(pcap_t *p, struct bpf_program *fp)
-{
-       struct pcap_win *pw = p->priv;
-
-       if(PacketSetBpf(p->adapter,fp)==FALSE){
-               /*
-                * Kernel filter not installed.
-                *
-                * XXX - we don't know whether this failed because:
-                *
-                *  the kernel rejected the filter program as invalid,
-                *  in which case we should fall back on userland
-                *  filtering;
-                *
-                *  the kernel rejected the filter program as too big,
-                *  in which case we should again fall back on
-                *  userland filtering;
-                *
-                *  there was some other problem, in which case we
-                *  should probably report an error.
-                *
-                * For NPF devices, the Win32 status will be
-                * STATUS_INVALID_DEVICE_REQUEST for invalid
-                * filters, but I don't know what it'd be for
-                * other problems, and for some other devices
-                * it might not be set at all.
-                *
-                * So we just fall back on userland filtering in
-                * all cases.
-                */
-
-               /*
-                * install_bpf_program() validates the program.
-                *
-                * XXX - what if we already have a filter in the kernel?
-                */
-               if (install_bpf_program(p, fp) < 0)
-                       return (-1);
-               pw->filtering_in_kernel = 0;    /* filtering in userland */
-               return (0);
-       }
-
-       /*
-        * It worked.
-        */
-       pw->filtering_in_kernel = 1;    /* filtering in the kernel */
-
-       /*
-        * Discard any previously-received packets, as they might have
-        * passed whatever filter was formerly in effect, but might
-        * not pass this filter (BIOCSETF discards packets buffered
-        * in the kernel, so you can lose packets in any case).
-        */
-       p->cc = 0;
-       return (0);
-}
-
-/*
- * We filter at user level, since the kernel driver does't process the packets
- */
-static int 
-pcap_setfilter_win32_dag(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) 
-       {
-               snprintf(p->errbuf, sizeof(p->errbuf),
-                       "setfilter, unable to install the filter: %s", pcap_strerror(errno));
-               return -1;
-       }
-       
-       return (0);
-}
-
-static int
-pcap_getnonblock_win32(pcap_t *p, char *errbuf)
-{
-       struct pcap_win *pw = p->priv;
-
-       /*
-        * XXX - if there were a PacketGetReadTimeout() call, we
-        * would use it, and return 1 if the timeout is -1
-        * and 0 otherwise.
-        */
-       return (pw->nonblock);
-}
-
-static int
-pcap_setnonblock_win32(pcap_t *p, int nonblock, char *errbuf)
-{
-       struct pcap_win *pw = p->priv;
-       int newtimeout;
-
-       if (nonblock) {
-               /*
-                * Set the read timeout to -1 for non-blocking mode.
-                */
-               newtimeout = -1;
-       } else {
-               /*
-                * 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.)
-                */
-               newtimeout = p->opt.timeout;
-       }
-       if (!PacketSetReadTimeout(p->adapter, newtimeout)) {
-               snprintf(errbuf, PCAP_ERRBUF_SIZE,
-                   "PacketSetReadTimeout: %s", pcap_win32strerror());
-               return (-1);
-       }
-       pw->nonblock = (newtimeout == -1);
-       return (0);
-}
-
-/*platform-dependent routine to add devices other than NDIS interfaces*/
-int
-pcap_platform_finddevs(pcap_if_t **alldevsp, char *errbuf)
-{
-       return (0);
-}
index f5a7e0c..8010140 100644 (file)
@@ -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 "25 July 2018"
 .SH NAME
 pcap \- Packet Capture library
 .SH SYNOPSIS
@@ -150,46 +150,51 @@ and
 .BR pcap_can_set_rfmon ()
 can be used to determine whether an adapter can be put into monitor
 mode.
-.IP "read timeout"
+.IP "packet buffer timeout"
 If, when capturing, packets are delivered as soon as they arrive, the
 application capturing the packets will be woken up for each packet as it
 arrives, and might have to make one or more calls to the operating
 system to fetch each packet.
 .IP
 If, instead, packets are not delivered as soon as they arrive, but are
-delivered after a short delay (called a "read timeout"), more than one
-packet can be accumulated before the packets are delivered, so that a
-single wakeup would be done for multiple packets, and each set of calls
-made to the operating system would supply multiple packets, rather than
-a single packet.  This reduces the per-packet CPU overhead if packets
-are arriving at a high rate, increasing the number of packets per second
-that can be captured.
+delivered after a short delay (called a "packet buffer timeout"), more
+than one packet can be accumulated before the packets are delivered, so
+that a single wakeup would be done for multiple packets, and each set of
+calls made to the operating system would supply multiple packets, rather
+than a single packet.  This reduces the per-packet CPU overhead if
+packets are arriving at a high rate, increasing the number of packets
+per second that can be captured.
 .IP
-The read timeout is required so that an application won't wait for the
-operating system's capture buffer to fill up before packets are
+The packet buffer timeout is required so that an application won't wait
+for the operating system's capture buffer to fill up before packets are
 delivered; if packets are arriving slowly, that wait could take an
 arbitrarily long period of time.
 .IP
-Not all platforms support a read timeout; on platforms that
-don't, the read timeout is ignored.  A zero value for the timeout,
-on platforms that support a read timeout,
-will cause a read to wait forever to allow enough packets to
-arrive, with no timeout.
+Not all platforms support a packet buffer timeout; on platforms that
+don't, the packet buffer timeout is ignored.  A zero value for the
+timeout, on platforms that support a packet buffer timeout, will cause a
+read to wait forever to allow enough packets to arrive, with no timeout.
+A negative value is invalid; the result of setting the timeout to a
+negative value is unpredictable.
 .IP
 .BR NOTE :
-the read timeout cannot be used to cause calls that read
+the packet buffer timeout cannot be used to cause calls that read
 packets to return within a limited period of time, because, on some
-platforms, the read timeout isn't supported, and, on other platforms,
-the timer doesn't start until at least one packet arrives.  This means
-that the read timeout should
+platforms, the packet buffer timeout isn't supported, and, on other
+platforms, the timer doesn't start until at least one packet arrives.
+This means that the packet buffer timeout should
 .B NOT
 be used, for example, in an interactive application to allow the packet
 capture loop to ``poll'' for user input periodically, as there's no
 guarantee that a call reading packets will return after the timeout
 expires even if no packets have arrived.
 .IP
-The read timeout is set with
+The packet buffer timeout is set with
 .BR pcap_set_timeout ().
+.IP "immediate mode"
+In immediate mode, packets are always delivered as soon as they arrive,
+with no buffering.  Immediate mode is set with
+.BR pcap_set_immediate_mode ().
 .IP "buffer size"
 Packets that arrive for a capture are stored in a buffer, so that they
 do not have to be read by the application as soon as they arrive.  On
@@ -244,7 +249,7 @@ that device.  A user can be given that privilege by, for example, adding
 that privilege to the user's
 .B defaultpriv
 key with the
-.B usermod (1M)
+.B usermod (@MAN_ADMIN_COMMANDS@)
 command.
 .TP
 .B Under HP-UX with DLPI:
@@ -282,13 +287,13 @@ packet capture on an interface probably requires that either
 promiscuous-mode or copy-all-mode operation, or both modes of
 operation, be enabled on that interface.
 .TP
-.B Under BSD (this includes Mac OS X):
+.B Under BSD (this includes macOS):
 You must have read access to
 .I /dev/bpf*
 on systems that don't have a cloning BPF device, or to
 .I /dev/bpf
 on systems that do.
-On BSDs with a devfs (this includes Mac OS X), this might involve more
+On BSDs with a devfs (this includes macOS), this might involve more
 than just having somebody with super-user access setting the ownership
 or permissions on the BPF devices - it might involve configuring devfs
 to set the ownership or permissions every time the system is booted,
@@ -303,7 +308,7 @@ link-layer header whose contents can differ for different network
 interfaces.  To determine the format of the packets supplied by the
 handle, call
 .BR pcap_datalink ();
-.I http://www.tcpdump.org/linktypes.html
+.I https://www.tcpdump.org/linktypes.html
 lists the values it returns and describes the packet formats that
 correspond to those values.
 .PP
@@ -354,12 +359,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
@@ -382,6 +400,11 @@ set promiscuous mode for a not-yet-activated
 .B pcap_t
 for live capture
 .TP
+.BR pcap_set_protocol_linux (3PCAP)
+set capture protocol for a not-yet-activated
+.B pcap_t
+for live capture (Linux only)
+.TP
 .BR pcap_set_rfmon (3PCAP)
 set monitor mode for a not-yet-activated
 .B pcap_t
@@ -393,7 +416,12 @@ determine whether monitor mode can be set for a
 for live capture
 .TP
 .BR pcap_set_timeout (3PCAP)
-set read timeout for a not-yet-activated
+set packet buffer timeout for a not-yet-activated
+.B pcap_t
+for live capture
+.TP
+.BR pcap_set_immediate_mode (3PCAP)
+set immediate mode for a not-yet-activated
 .B pcap_t
 for live capture
 .TP
@@ -424,6 +452,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 +590,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
@@ -577,10 +615,13 @@ and
 will, if no packets are currently available to be read, block waiting
 for packets to become available.  On some, but
 .I not
-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.
+all, platforms, if a packet buffer timeout was specified, the wait will
+terminate after the packet buffer 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.  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,17 +637,43 @@ 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 ().
+If the routine indicates that data is
+available to read on the descriptor, an attempt should be made to read
+from the device.
+.PP
 Not all handles have such a descriptor available;
 .BR pcap_get_selectable_fd ()
-will return \-1 if no such descriptor exists.  In addition, for various
+will return
+.B PCAP_ERROR
+if no such descriptor is available.  If no such
+descriptor is available, this may be because the device must be polled
+periodically for packets; in that case,
+.BR pcap_get_required_select_timeout ()
+will return a pointer to a
+.B struct timeval
+whose value can be used as a timeout in those routines.  When the
+routine returns, an attmept should be made to read packets from the
+device.  If
+.BR pcap_get_required_select_timeout ()
+returns NULL, no such timeout is available, and those routines cannot be
+used with the device.
+.PP
+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 packet buffer timeout expires, a
+.BR select (),
+.BR poll (),
+or other such call may, if the packet buffer timeout expires, indicate
+that a descriptor is ready to read even if there are no packets
+available to read.
 .TP
 .B Routines
 .RS
@@ -654,6 +721,15 @@ that can be used in calls such as
 .BR select (2)
 and
 .BR poll (2)
+.TP
+.BR pcap_get_required_select_timeout (3PCAP)
+if no descriptor usable with
+.BR select (2)
+and
+.BR poll (2)
+is available for the
+.BR pcap_t ,
+attempt to get a timeout usable with those routines
 .RE
 .SS Filters
 In order to cause only certain packets to be returned when reading
@@ -851,7 +927,7 @@ To get a string giving version information about libpcap, call
 .BR pcap_lib_version (3PCAP)
 get library version string
 .RE
-.SH BACKWARDS COMPATIBILITY
+.SH BACKWARD COMPATIBILITY
 .PP
 In versions of libpcap prior to 1.0, the
 .B pcap.h
@@ -883,7 +959,7 @@ script or some other configuration script to check whether the libpcap
 1.0 APIs are available and use them only if they are.
 .SH SEE ALSO
 autoconf(1), tcpdump(1), tcpslice(1), pcap-filter(@MAN_MISC_INFO@), pfconfig(8),
-usermod(1M)
+usermod(@MAN_ADMIN_COMMANDS@)
 .SH AUTHORS
 The original authors of libpcap are:
 .LP
@@ -895,11 +971,12 @@ Lawrence Berkeley National Laboratory, University of California, Berkeley, CA.
 The current version is available from "The Tcpdump Group"'s Web site at
 .LP
 .RS
-.I http://www.tcpdump.org/
+.I https://www.tcpdump.org/
 .RE
 .SH BUGS
-Please send problems, bugs, questions, desirable enhancements, etc. to:
+To report a security issue please send an e-mail to security@tcpdump.org.
 .LP
-.RS
-tcpdump-workers@lists.tcpdump.org
-.RE
+To report bugs and other problems, contribute patches, request a
+feature, provide generic feedback etc please see the file
+.I CONTRIBUTING
+in the libpcap source tree root.
diff --git a/pcap.c b/pcap.c
index badc312..5c8b51a 100644 (file)
--- a/pcap.c
+++ b/pcap.c
  */
 
 #ifdef HAVE_CONFIG_H
-#include "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>
+#include <pcap-types.h>
+#ifndef _WIN32
+#include <sys/param.h>
+#ifndef MSDOS
+#include <sys/file.h>
 #endif
-#ifdef HAVE_SYS_BITYPES_H
-#include <sys/bitypes.h>
+#include <sys/ioctl.h>
+#include <sys/socket.h>
+#ifdef HAVE_SYS_SOCKIO_H
+#include <sys/sockio.h>
 #endif
-#include <sys/types.h>
-#endif /* WIN32 */
 
+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 <stdio.h>
 #include <stdlib.h>
 #include <string.h>
 #endif
 #include <fcntl.h>
 #include <errno.h>
+#ifdef HAVE_LIMITS_H
+#include <limits.h>
+#else
+#define INT_MAX                2147483647
+#endif
 
 #ifdef HAVE_OS_PROTO_H
 #include "os-proto.h"
@@ -68,6 +78,8 @@
 
 #include "pcap-int.h"
 
+#include "optimize.h"
+
 #ifdef HAVE_DAG_API
 #include "pcap-dag.h"
 #endif /* HAVE_DAG_API */
 #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
 #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
 
+#ifdef PCAP_SUPPORT_NETMAP
+#include "pcap-netmap.h"
+#endif
+
 #ifdef PCAP_SUPPORT_DBUS
 #include "pcap-dbus.h"
 #endif
 
+#ifdef PCAP_SUPPORT_RDMASNIFF
+#include "pcap-rdmasniff.h"
+#endif
+
+#ifdef _WIN32
+/*
+ * DllMain(), required when built as a Windows DLL.
+ */
+BOOL WINAPI DllMain(
+  HANDLE hinstDLL,
+  DWORD dwReason,
+  LPVOID lpvReserved
+)
+{
+       return (TRUE);
+}
+
+/*
+ * Start WinSock.
+ * Exported in case some applications using WinPcap/Npcap called it,
+ * even though it wasn't exported.
+ */
+int
+wsockinit(void)
+{
+       WORD wVersionRequested;
+       WSADATA wsaData;
+       static int err = -1;
+       static int done = 0;
+
+       if (done)
+               return (err);
+
+       wVersionRequested = MAKEWORD( 1, 1);
+       err = WSAStartup( wVersionRequested, &wsaData );
+       atexit ((void(*)(void))WSACleanup);
+       done = 1;
+
+       if ( err != 0 )
+               err = -1;
+       return (err);
+}
+
+/*
+ * This is the exported function; new programs should call this.
+ */
 int
-pcap_not_initialized(pcap_t *pcap _U_)
+pcap_wsockinit(void)
+{
+       return (wsockinit());
+}
+#endif /* _WIN32 */
+
+/*
+ * String containing the library version.
+ * Not explicitly exported via a header file - the right API to use
+ * is pcap_lib_version() - but some programs included it, so we
+ * provide it.
+ *
+ * We declare it here, right before defining it, to squelch any
+ * warnings we might get from compilers about the lack of a
+ * declaration.
+ */
+PCAP_API char pcap_version[];
+PCAP_API_DEF char pcap_version[] = PACKAGE_VERSION;
+
+static void
+pcap_set_not_initialized_message(pcap_t *pcap)
+{
+       if (pcap->activated) {
+               /* A module probably forgot to set the function pointer */
+               (void)pcap_snprintf(pcap->errbuf, sizeof(pcap->errbuf),
+                   "This operation isn't properly handled by that device");
+               return;
+       }
+       /* 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");
+}
+
+static int
+pcap_read_not_initialized(pcap_t *pcap, int cnt _U_, pcap_handler callback _U_,
+    u_char *user _U_)
+{
+       pcap_set_not_initialized_message(pcap);
+       /* this means 'not initialized' */
+       return (PCAP_ERROR_NOT_ACTIVATED);
+}
+
+static int
+pcap_inject_not_initialized(pcap_t *pcap, const void * buf _U_, size_t size _U_)
+{
+       pcap_set_not_initialized_message(pcap);
+       /* this means 'not initialized' */
+       return (PCAP_ERROR_NOT_ACTIVATED);
+}
+
+static int
+pcap_setfilter_not_initialized(pcap_t *pcap, struct bpf_program *fp _U_)
+{
+       pcap_set_not_initialized_message(pcap);
+       /* this means 'not initialized' */
+       return (PCAP_ERROR_NOT_ACTIVATED);
+}
+
+static int
+pcap_setdirection_not_initialized(pcap_t *pcap, pcap_direction_t d _U_)
+{
+       pcap_set_not_initialized_message(pcap);
+       /* this means 'not initialized' */
+       return (PCAP_ERROR_NOT_ACTIVATED);
+}
+
+static int
+pcap_set_datalink_not_initialized(pcap_t *pcap, int dlt _U_)
+{
+       pcap_set_not_initialized_message(pcap);
+       /* this means 'not initialized' */
+       return (PCAP_ERROR_NOT_ACTIVATED);
+}
+
+static int
+pcap_getnonblock_not_initialized(pcap_t *pcap)
+{
+       pcap_set_not_initialized_message(pcap);
+       /* this means 'not initialized' */
+       return (PCAP_ERROR_NOT_ACTIVATED);
+}
+
+static int
+pcap_stats_not_initialized(pcap_t *pcap, struct pcap_stat *ps _U_)
+{
+       pcap_set_not_initialized_message(pcap);
+       /* this means 'not initialized' */
+       return (PCAP_ERROR_NOT_ACTIVATED);
+}
+
+#ifdef _WIN32
+struct pcap_stat *
+pcap_stats_ex_not_initialized(pcap_t *pcap, int *pcap_stat_size _U_)
+{
+       pcap_set_not_initialized_message(pcap);
+       return (NULL);
+}
+
+static int
+pcap_setbuff_not_initialized(pcap_t *pcap, int dim _U_)
+{
+       pcap_set_not_initialized_message(pcap);
+       /* this means 'not initialized' */
+       return (PCAP_ERROR_NOT_ACTIVATED);
+}
+
+static int
+pcap_setmode_not_initialized(pcap_t *pcap, int mode _U_)
+{
+       pcap_set_not_initialized_message(pcap);
+       /* this means 'not initialized' */
+       return (PCAP_ERROR_NOT_ACTIVATED);
+}
+
+static int
+pcap_setmintocopy_not_initialized(pcap_t *pcap, int size _U_)
 {
+       pcap_set_not_initialized_message(pcap);
        /* this means 'not initialized' */
        return (PCAP_ERROR_NOT_ACTIVATED);
 }
 
-#ifdef WIN32
-Adapter *
-pcap_no_adapter(pcap_t *pcap _U_)
+static HANDLE
+pcap_getevent_not_initialized(pcap_t *pcap)
+{
+       pcap_set_not_initialized_message(pcap);
+       return (INVALID_HANDLE_VALUE);
+}
+
+static int
+pcap_oid_get_request_not_initialized(pcap_t *pcap, bpf_u_int32 oid _U_,
+    void *data _U_, size_t *lenp _U_)
+{
+       pcap_set_not_initialized_message(pcap);
+       return (PCAP_ERROR_NOT_ACTIVATED);
+}
+
+static int
+pcap_oid_set_request_not_initialized(pcap_t *pcap, bpf_u_int32 oid _U_,
+    const void *data _U_, size_t *lenp _U_)
+{
+       pcap_set_not_initialized_message(pcap);
+       return (PCAP_ERROR_NOT_ACTIVATED);
+}
+
+static u_int
+pcap_sendqueue_transmit_not_initialized(pcap_t *pcap, pcap_send_queue* queue, int sync)
+{
+       pcap_set_not_initialized_message(pcap);
+       return (0);
+}
+
+static int
+pcap_setuserbuffer_not_initialized(pcap_t *pcap, int size _U_)
+{
+       pcap_set_not_initialized_message(pcap);
+       return (PCAP_ERROR_NOT_ACTIVATED);
+}
+
+static int
+pcap_live_dump_not_initialized(pcap_t *pcap, char *filename _U_, int maxsize _U_,
+    int maxpacks _U_)
+{
+       pcap_set_not_initialized_message(pcap);
+       return (PCAP_ERROR_NOT_ACTIVATED);
+}
+
+static int
+pcap_live_dump_ended_not_initialized(pcap_t *pcap, int sync _U_)
+{
+       pcap_set_not_initialized_message(pcap);
+       return (PCAP_ERROR_NOT_ACTIVATED);
+}
+
+static PAirpcapHandle
+pcap_get_airpcap_handle_not_initialized(pcap_t *pcap)
 {
+       pcap_set_not_initialized_message(pcap);
        return (NULL);
 }
 #endif
@@ -159,20 +385,29 @@ pcap_list_tstamp_types(pcap_t *p, int **tstamp_typesp)
        if (p->tstamp_type_count == 0) {
                /*
                 * We don't support multiple time stamp types.
+                * That means the only type we support is PCAP_TSTAMP_HOST;
+                * set up a list containing only that type.
                 */
-               *tstamp_typesp = NULL;
+               *tstamp_typesp = (int*)malloc(sizeof(**tstamp_typesp));
+               if (*tstamp_typesp == NULL) {
+                       pcap_fmt_errmsg_for_errno(p->errbuf, sizeof(p->errbuf),
+                           errno, "malloc");
+                       return (PCAP_ERROR);
+               }
+               **tstamp_typesp = PCAP_TSTAMP_HOST;
+               return (1);
        } else {
                *tstamp_typesp = (int*)calloc(sizeof(**tstamp_typesp),
                    p->tstamp_type_count);
                if (*tstamp_typesp == NULL) {
-                       (void)snprintf(p->errbuf, sizeof(p->errbuf),
-                           "malloc: %s", pcap_strerror(errno));
+                       pcap_fmt_errmsg_for_errno(p->errbuf, sizeof(p->errbuf),
+                           errno, "malloc");
                        return (PCAP_ERROR);
                }
                (void)memcpy(*tstamp_typesp, p->tstamp_type_list,
                    sizeof(**tstamp_typesp) * p->tstamp_type_count);
+               return (p->tstamp_type_count);
        }
-       return (p->tstamp_type_count);
 }
 
 /*
@@ -270,45 +505,15 @@ 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));
-}
+/*
+ * Implementation of a pcap_if_list_t.
+ */
+struct pcap_if_list {
+       pcap_if_t *beginning;
+};
 
-pcap_t *
-pcap_create(const char *source, char *errbuf)
-{
-       return (snf_create(source, errbuf));
-}
-#else /* regular pcap */
-struct capture_source_type {
-       int (*findalldevs_op)(pcap_if_t **, char *);
+static struct capture_source_type {
+       int (*findalldevs_op)(pcap_if_list_t *, char *);
        pcap_t *(*create_op)(const char *, char *, int *);
 } capture_source_types[] = {
 #ifdef HAVE_DAG_API
@@ -320,27 +525,30 @@ 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
 #ifdef PCAP_SUPPORT_NETFILTER
        { netfilter_findalldevs, netfilter_create },
 #endif
+#ifdef PCAP_SUPPORT_NETMAP
+       { pcap_netmap_findalldevs, pcap_netmap_create },
+#endif
 #ifdef PCAP_SUPPORT_DBUS
        { dbus_findalldevs, dbus_create },
 #endif
+#ifdef PCAP_SUPPORT_RDMASNIFF
+       { rdmasniff_findalldevs, rdmasniff_create },
+#endif
        { NULL, NULL }
 };
 
@@ -354,26 +562,21 @@ int
 pcap_findalldevs(pcap_if_t **alldevsp, char *errbuf)
 {
        size_t i;
+       pcap_if_list_t devlist;
 
        /*
-        * 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) {
+       devlist.beginning = NULL;
+       if (pcap_platform_finddevs(&devlist, errbuf) == -1) {
                /*
-                * We had an error; free the list we've been
-                * constructing.
+                * Failed - free all of the entries we were given
+                * before we failed.
                 */
-               if (*alldevsp != NULL) {
-                       pcap_freealldevs(*alldevsp);
-                       *alldevsp = NULL;
-               }
+               if (devlist.beginning != NULL)
+                       pcap_freealldevs(devlist.beginning);
+               *alldevsp = NULL;
                return (-1);
        }
 
@@ -382,89 +585,1632 @@ pcap_findalldevs(pcap_if_t **alldevsp, char *errbuf)
         * source types what interfaces they have.
         */
        for (i = 0; capture_source_types[i].findalldevs_op != NULL; i++) {
-               if (capture_source_types[i].findalldevs_op(alldevsp, errbuf) == -1) {
+               if (capture_source_types[i].findalldevs_op(&devlist, errbuf) == -1) {
                        /*
                         * We had an error; free the list we've been
                         * constructing.
                         */
-                       if (*alldevsp != NULL) {
-                               pcap_freealldevs(*alldevsp);
-                               *alldevsp = NULL;
-                       }
+                       if (devlist.beginning != NULL)
+                               pcap_freealldevs(devlist.beginning);
+                       *alldevsp = NULL;
                        return (-1);
                }
        }
 
+       /*
+        * Return the first entry of the list of all devices.
+        */
+       *alldevsp = devlist.beginning;
        return (0);
 }
 
-pcap_t *
-pcap_create(const char *source, char *errbuf)
+static struct sockaddr *
+dup_sockaddr(struct sockaddr *sa, size_t sa_length)
 {
-       size_t i;
-       int is_theirs;
-       pcap_t *p;
+       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 an instance number.  Add 1 to the
+                * instance number, and use 0 for "no instance
+                * number", so we don't put "no instance number"
+                * devices and "instance 0" devices together.
+                */
+               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) + 1;
+               else
+                       n = 0;
+       }
+       if (!(dev->flags & PCAP_IF_RUNNING))
+               n |= 0x80000000;
+       if (!(dev->flags & PCAP_IF_UP))
+               n |= 0x40000000;
 
        /*
-        * A null source 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.
+        * Give non-wireless interfaces that aren't disconnected a better
+        * figure of merit than interfaces that are disconnected, as
+        * "disconnected" should indicate that the interface isn't
+        * plugged into a network and thus won't give you any traffic.
+        *
+        * For wireless interfaces, it means "associated with a network",
+        * which we presume not to necessarily prevent capture, as you
+        * might run the adapter in some flavor of monitor mode.
         */
-       if (source == NULL)
-               source = "any";
+       if (!(dev->flags & PCAP_IF_WIRELESS) &&
+           (dev->flags & PCAP_IF_CONNECTION_STATUS) == PCAP_IF_CONNECTION_STATUS_DISCONNECTED)
+               n |= 0x20000000;
 
        /*
-        * Try each of the non-local-network-interface capture
-        * source types until we find one that works for this
-        * device or run out of types.
+        * Sort loopback devices after non-loopback devices, *except* for
+        * disconnected devices.
         */
-       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);
-               if (is_theirs) {
+       if (dev->flags & PCAP_IF_LOOPBACK)
+               n |= 0x10000000;
+
+       return (n);
+}
+
+#ifndef _WIN32
+/*
+ * 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 macOS, 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 *
+#ifdef SIOCGIFDESCR
+get_if_description(const char *name)
+{
+       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);
+       pcap_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 && description[0] == '\0') {
                        /*
-                        * The device name refers to a device of the
-                        * type in question; either it succeeded,
-                        * in which case p refers to a pcap_t to
-                        * later activate for the device, or it
-                        * failed, in which case p is null and we
-                        * should return that to report the failure
-                        * to create.
+                        * Description is empty, so discard it.
                         */
-                       return (p);
+                       free(description);
+                       description = NULL;
                }
        }
 
+#ifdef __FreeBSD__
        /*
-        * OK, try it as a regular network interface.
+        * 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.
         */
-       return (pcap_create_interface(source, errbuf));
-}
-#endif
+       if (description == NULL) {
+               if (strncmp(name, "usbus", 5) == 0) {
+                       /*
+                        * OK, it begins with "usbus".
+                        */
+                       long busnum;
+                       char *p;
 
-static void
-initialize_ops(pcap_t *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.
+                                * (If that fails, we don't worry about
+                                * it, we just return NULL.)
+                                */
+                               if (pcap_asprintf(&description,
+                                   "USB bus number %ld", busnum) == -1) {
+                                       /* Failed. */
+                                       description = NULL;
+                               }
+                       }
+               }
+       }
+#endif
+       return (description);
+#else /* SIOCGIFDESCR */
+get_if_description(const char *name _U_)
 {
-       /*
-        * Set operation pointers for operations that only work on
-        * an activated pcap_t to point to a routine that returns
-        * a "this isn't activated" error.
+       return (NULL);
+#endif /* SIOCGIFDESCR */
+}
+
+/*
+ * Look for a given device in the specified list of devices.
+ *
+ * If we find it, return a pointer to its entry.
+ *
+ * If we don't find it, attempt to add an entry for it, with the specified
+ * IFF_ flags and description, and, if that succeeds, return a pointer to
+ * the new entry, otherwise return NULL and set errbuf to an error message.
+ */
+pcap_if_t *
+find_or_add_if(pcap_if_list_t *devlistp, const char *name,
+    bpf_u_int32 if_flags, get_if_flags_func get_flags_func, char *errbuf)
+{
+       bpf_u_int32 pcap_flags;
+
+       /*
+        * Convert IFF_ flags to pcap flags.
+        */
+       pcap_flags = 0;
+#ifdef IFF_LOOPBACK
+       if (if_flags & IFF_LOOPBACK)
+               pcap_flags |= PCAP_IF_LOOPBACK;
+#else
+       /*
+        * We don't have IFF_LOOPBACK, so look at the device name to
+        * see if it looks like a loopback device.
+        */
+       if (name[0] == 'l' && name[1] == 'o' &&
+           (isdigit((unsigned char)(name[2])) || name[2] == '\0')
+               pcap_flags |= PCAP_IF_LOOPBACK;
+#endif
+#ifdef IFF_UP
+       if (if_flags & IFF_UP)
+               pcap_flags |= PCAP_IF_UP;
+#endif
+#ifdef IFF_RUNNING
+       if (if_flags & IFF_RUNNING)
+               pcap_flags |= PCAP_IF_RUNNING;
+#endif
+
+       /*
+        * Attempt to find an entry for this device; if we don't find one,
+        * attempt to add one.
+        */
+       return (find_or_add_dev(devlistp, name, pcap_flags,
+           get_flags_func, get_if_description(name), errbuf));
+}
+
+/*
+ * Look for a given 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, attempt to add an entry for it, with the specified
+ * IFF_ flags and description, and, if that succeeds, add the specified
+ * address to its list of addresses if that address is non-null, and
+ * return 0, otherwise return -1 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_if(pcap_if_list_t *devlistp, const char *name,
+    bpf_u_int32 if_flags, get_if_flags_func get_flags_func,
+    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;
+
+       /*
+        * Check whether the device exists and, if not, add it.
+        */
+       curdev = find_or_add_if(devlistp, name, if_flags, get_flags_func,
+           errbuf);
+       if (curdev == NULL) {
+               /*
+                * Error - give up.
+                */
+               return (-1);
+       }
+
+       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.
+        */
+       return (add_addr_to_dev(curdev, addr, addr_size, netmask,
+           netmask_size, broadaddr, broadaddr_size, dstaddr,
+           dstaddr_size, errbuf));
+}
+#endif /* _WIN32 */
+
+/*
+ * Add an entry to the list of addresses for an interface.
+ * "curdev" is the entry for that interface.
+ */
+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;
+
+       /*
+        * Allocate the new entry and fill it in.
+        */
+       curaddr = (pcap_addr_t *)malloc(sizeof(pcap_addr_t));
+       if (curaddr == NULL) {
+               pcap_fmt_errmsg_for_errno(errbuf, PCAP_ERRBUF_SIZE,
+                   errno, "malloc");
+               return (-1);
+       }
+
+       curaddr->next = NULL;
+       if (addr != NULL && addr_size != 0) {
+               curaddr->addr = (struct sockaddr *)dup_sockaddr(addr, addr_size);
+               if (curaddr->addr == NULL) {
+                       pcap_fmt_errmsg_for_errno(errbuf, PCAP_ERRBUF_SIZE,
+                           errno, "malloc");
+                       free(curaddr);
+                       return (-1);
+               }
+       } else
+               curaddr->addr = NULL;
+
+       if (netmask != NULL && netmask_size != 0) {
+               curaddr->netmask = (struct sockaddr *)dup_sockaddr(netmask, netmask_size);
+               if (curaddr->netmask == NULL) {
+                       pcap_fmt_errmsg_for_errno(errbuf, PCAP_ERRBUF_SIZE,
+                           errno, "malloc");
+                       if (curaddr->addr != NULL)
+                               free(curaddr->addr);
+                       free(curaddr);
+                       return (-1);
+               }
+       } else
+               curaddr->netmask = NULL;
+
+       if (broadaddr != NULL && broadaddr_size != 0) {
+               curaddr->broadaddr = (struct sockaddr *)dup_sockaddr(broadaddr, broadaddr_size);
+               if (curaddr->broadaddr == NULL) {
+                       pcap_fmt_errmsg_for_errno(errbuf, PCAP_ERRBUF_SIZE,
+                           errno, "malloc");
+                       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 && dstaddr_size != 0) {
+               curaddr->dstaddr = (struct sockaddr *)dup_sockaddr(dstaddr, dstaddr_size);
+               if (curaddr->dstaddr == NULL) {
+                       pcap_fmt_errmsg_for_errno(errbuf, PCAP_ERRBUF_SIZE,
+                           errno, "malloc");
+                       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 and set *curdev_ret to point to it.
+ *
+ * If we don't find it, attempt to add an entry for it, with the specified
+ * flags and description, and, if that succeeds, return 0, otherwise
+ * return -1 and set errbuf to an error message.
+ */
+pcap_if_t *
+find_or_add_dev(pcap_if_list_t *devlistp, const char *name, bpf_u_int32 flags,
+    get_if_flags_func get_flags_func, const char *description, char *errbuf)
+{
+       pcap_if_t *curdev;
+
+       /*
+        * Is there already an entry in the list for this device?
+        */
+       curdev = find_dev(devlistp, name);
+       if (curdev != NULL) {
+               /*
+                * Yes, return it.
+                */
+               return (curdev);
+       }
+
+       /*
+        * No, we didn't find it.
+        */
+
+       /*
+        * Try to get additional flags for the device.
+        */
+       if ((*get_flags_func)(name, &flags, errbuf) == -1) {
+               /*
+                * Failed.
+                */
+               return (NULL);
+       }
+
+       /*
+        * Now, try to add it to the list of devices.
+        */
+       return (add_dev(devlistp, name, flags, description, errbuf));
+}
+
+/*
+ * Look for a given device in the specified list of devices, and return
+ * the entry for it if we find it or NULL if we don't.
+ */
+pcap_if_t *
+find_dev(pcap_if_list_t *devlistp, const char *name)
+{
+       pcap_if_t *curdev;
+
+       /*
+        * Is there an entry in the list for this device?
+        */
+       for (curdev = devlistp->beginning; curdev != NULL;
+           curdev = curdev->next) {
+               if (strcmp(name, curdev->name) == 0) {
+                       /*
+                        * We found it, so, yes, there is.  No need to
+                        * add it.  Provide the entry we found to our
+                        * caller.
+                        */
+                       return (curdev);
+               }
+       }
+
+       /*
+        * No.
+        */
+       return (NULL);
+}
+
+/*
+ * Attempt to add an entry for a device, with the specified flags
+ * and description, and, if that succeeds, return 0 and return a pointer
+ * to the new entry, otherwise return NULL and set errbuf to an error
+ * message.
+ *
+ * If we weren't given a description, try to get one.
+ */
+pcap_if_t *
+add_dev(pcap_if_list_t *devlistp, const char *name, bpf_u_int32 flags,
+    const char *description, char *errbuf)
+{
+       pcap_if_t *curdev, *prevdev, *nextdev;
+       u_int this_figure_of_merit, nextdev_figure_of_merit;
+
+       curdev = malloc(sizeof(pcap_if_t));
+       if (curdev == NULL) {
+               pcap_fmt_errmsg_for_errno(errbuf, PCAP_ERRBUF_SIZE,
+                   errno, "malloc");
+               return (NULL);
+       }
+
+       /*
+        * Fill in the entry.
+        */
+       curdev->next = NULL;
+       curdev->name = strdup(name);
+       if (curdev->name == NULL) {
+               pcap_fmt_errmsg_for_errno(errbuf, PCAP_ERRBUF_SIZE,
+                   errno, "malloc");
+               free(curdev);
+               return (NULL);
+       }
+       if (description == NULL) {
+               /*
+                * We weren't handed a description for the interface.
+                */
+               curdev->description = NULL;
+       } else {
+               /*
+                * We were handed a description; make a copy.
+                */
+               curdev->description = strdup(description);
+               if (curdev->description == NULL) {
+                       pcap_fmt_errmsg_for_errno(errbuf, PCAP_ERRBUF_SIZE,
+                           errno, "malloc");
+                       free(curdev->name);
+                       free(curdev);
+                       return (NULL);
+               }
+       }
+       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 = devlistp->beginning;
+               } 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.  Make it
+                * the first element in the list of devices.
+                */
+               devlistp->beginning = curdev;
+       } else
+               prevdev->next = curdev;
+       return (curdev);
+}
+
+/*
+ * 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);
+       }
+}
+
+/*
+ * pcap-npf.c has its own pcap_lookupdev(), for compatibility reasons, as
+ * it actually returns the names of all interfaces, with a NUL separator
+ * between them; some callers may depend on that.
+ *
+ * MS-DOS has its own pcap_lookupdev(), but that might be useful only
+ * as an optimization.
+ *
+ * In all other cases, we just use pcap_findalldevs() to get a list of
+ * devices, and pick from that list.
+ */
+#if !defined(HAVE_PACKET32) && !defined(MSDOS)
+/*
+ * 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.
+ */
+char *
+pcap_lookupdev(char *errbuf)
+{
+       pcap_if_t *alldevs;
+#ifdef _WIN32
+  /*
+   * Windows - use the same size as the old WinPcap 3.1 code.
+   * XXX - this is probably bigger than it needs to be.
+   */
+  #define IF_NAMESIZE 8192
+#else
+  /*
+   * UN*X - use the system's interface name size.
+   * XXX - that might not be large enough for capture devices
+   * that aren't regular network interfaces.
+   */
+  /* for old BSD systems, including bsdi3 */
+  #ifndef IF_NAMESIZE
+  #define IF_NAMESIZE IFNAMSIZ
+  #endif
+#endif
+       static char device[IF_NAMESIZE + 1];
+       char *ret;
+
+       if (pcap_findalldevs(&alldevs, errbuf) == -1)
+               return (NULL);
+
+       if (alldevs == NULL || (alldevs->flags & PCAP_IF_LOOPBACK)) {
+               /*
+                * There are no devices on the list, or the first device
+                * on the list is a loopback device, which means there
+                * are no non-loopback devices on the list.  This means
+                * we can't return any device.
+                *
+                * XXX - why not return a loopback device?  If we can't
+                * capture on it, it won't be on the list, and if it's
+                * on the list, there aren't any non-loopback devices,
+                * so why not just supply it as the default device?
+                */
+               (void)pcap_strlcpy(errbuf, "no suitable device found",
+                   PCAP_ERRBUF_SIZE);
+               ret = NULL;
+       } else {
+               /*
+                * Return the name of the first device on the list.
+                */
+               (void)pcap_strlcpy(device, alldevs->name, sizeof(device));
+               ret = device;
+       }
+
+       pcap_freealldevs(alldevs);
+       return (ret);
+}
+#endif /* !defined(HAVE_PACKET32) && !defined(MSDOS) */
+
+#if !defined(_WIN32) && !defined(MSDOS)
+/*
+ * We don't just fetch the entire list of devices, search for the
+ * particular device, and use its first IPv4 address, as that's too
+ * much work to get just one device's netmask.
+ *
+ * If we had an API to get attributes for a given device, we could
+ * use that.
+ */
+int
+pcap_lookupnet(const char *device, bpf_u_int32 *netp, bpf_u_int32 *maskp,
+    char *errbuf)
+{
+       register int fd;
+       register struct sockaddr_in *sin4;
+       struct ifreq ifr;
+
+       /*
+        * The pseudo-device "any" listens on all interfaces and therefore
+        * has the network address and -mask "0.0.0.0" therefore catching
+        * all traffic. Using NULL for the interface is the same as "any".
+        */
+       if (!device || strcmp(device, "any") == 0
+#ifdef HAVE_DAG_API
+           || strstr(device, "dag") != NULL
+#endif
+#ifdef HAVE_SEPTEL_API
+           || strstr(device, "septel") != NULL
+#endif
+#ifdef PCAP_SUPPORT_BT
+           || strstr(device, "bluetooth") != NULL
+#endif
+#ifdef PCAP_SUPPORT_USB
+           || strstr(device, "usbmon") != NULL
+#endif
+#ifdef HAVE_SNF_API
+           || strstr(device, "snf") != NULL
+#endif
+#ifdef PCAP_SUPPORT_NETMAP
+           || strncmp(device, "netmap:", 7) == 0
+           || strncmp(device, "vale", 4) == 0
+#endif
+           ) {
+               *netp = *maskp = 0;
+               return 0;
+       }
+
+       fd = socket(AF_INET, SOCK_DGRAM, 0);
+       if (fd < 0) {
+               pcap_fmt_errmsg_for_errno(errbuf, PCAP_ERRBUF_SIZE,
+                   errno, "socket");
+               return (-1);
+       }
+       memset(&ifr, 0, sizeof(ifr));
+#ifdef linux
+       /* XXX Work around Linux kernel bug */
+       ifr.ifr_addr.sa_family = AF_INET;
+#endif
+       (void)pcap_strlcpy(ifr.ifr_name, device, sizeof(ifr.ifr_name));
+       if (ioctl(fd, SIOCGIFADDR, (char *)&ifr) < 0) {
+               if (errno == EADDRNOTAVAIL) {
+                       (void)pcap_snprintf(errbuf, PCAP_ERRBUF_SIZE,
+                           "%s: no IPv4 address assigned", device);
+               } else {
+                       pcap_fmt_errmsg_for_errno(errbuf, PCAP_ERRBUF_SIZE,
+                           errno, "SIOCGIFADDR: %s", device);
+               }
+               (void)close(fd);
+               return (-1);
+       }
+       sin4 = (struct sockaddr_in *)&ifr.ifr_addr;
+       *netp = sin4->sin_addr.s_addr;
+       memset(&ifr, 0, sizeof(ifr));
+#ifdef linux
+       /* XXX Work around Linux kernel bug */
+       ifr.ifr_addr.sa_family = AF_INET;
+#endif
+       (void)pcap_strlcpy(ifr.ifr_name, device, sizeof(ifr.ifr_name));
+       if (ioctl(fd, SIOCGIFNETMASK, (char *)&ifr) < 0) {
+               pcap_fmt_errmsg_for_errno(errbuf, PCAP_ERRBUF_SIZE,
+                   errno, "SIOCGIFNETMASK: %s", device);
+               (void)close(fd);
+               return (-1);
+       }
+       (void)close(fd);
+       *maskp = sin4->sin_addr.s_addr;
+       if (*maskp == 0) {
+               if (IN_CLASSA(*netp))
+                       *maskp = IN_CLASSA_NET;
+               else if (IN_CLASSB(*netp))
+                       *maskp = IN_CLASSB_NET;
+               else if (IN_CLASSC(*netp))
+                       *maskp = IN_CLASSC_NET;
+               else {
+                       (void)pcap_snprintf(errbuf, PCAP_ERRBUF_SIZE,
+                           "inet class for 0x%x unknown", *netp);
+                       return (-1);
+               }
+       }
+       *netp &= *maskp;
+       return (0);
+}
+#endif /* !defined(_WIN32) && !defined(MSDOS) */
+
+#ifdef ENABLE_REMOTE
+#include "pcap-rpcap.h"
+
+/*
+ * Extract a substring from a string.
+ */
+static char *
+get_substring(const char *p, size_t len, char *ebuf)
+{
+       char *token;
+
+       token = malloc(len + 1);
+       if (token == NULL) {
+               pcap_fmt_errmsg_for_errno(ebuf, PCAP_ERRBUF_SIZE,
+                   errno, "malloc");
+               return (NULL);
+       }
+       memcpy(token, p, len);
+       token[len] = '\0';
+       return (token);
+}
+
+/*
+ * Parse a capture source that might be a URL.
+ *
+ * If the source is not a URL, *schemep, *userinfop, *hostp, and *portp
+ * are set to NULL, *pathp is set to point to the source, and 0 is
+ * returned.
+ *
+ * If source is a URL, and the URL refers to a local device (a special
+ * case of rpcap:), *schemep, *userinfop, *hostp, and *portp are set
+ * to NULL, *pathp is set to point to the device name, and 0 is returned.
+ *
+ * If source is a URL, and it's not a special case that refers to a local
+ * device, and the parse succeeds:
+ *
+ *    *schemep is set to point to an allocated string containing the scheme;
+ *
+ *    if user information is present in the URL, *userinfop is set to point
+ *    to an allocated string containing the user information, otherwise
+ *    it's set to NULL;
+ *
+ *    if host information is present in the URL, *hostp is set to point
+ *    to an allocated string containing the host information, otherwise
+ *    it's set to NULL;
+ *
+ *    if a port number is present in the URL, *portp is set to point
+ *    to an allocated string containing the port number, otherwise
+ *    it's set to NULL;
+ *
+ *    *pathp is set to point to an allocated string containing the
+ *    path;
+ *
+ * and 0 is returned.
+ *
+ * If the parse fails, ebuf is set to an error string, and -1 is returned.
+ */
+static int
+pcap_parse_source(const char *source, char **schemep, char **userinfop,
+    char **hostp, char **portp, char **pathp, char *ebuf)
+{
+       char *colonp;
+       size_t scheme_len;
+       char *scheme;
+       const char *endp;
+       size_t authority_len;
+       char *authority;
+       char *parsep, *atsignp, *bracketp;
+       char *userinfo, *host, *port, *path;
+
+       /*
+        * Start out returning nothing.
+        */
+       *schemep = NULL;
+       *userinfop = NULL;
+       *hostp = NULL;
+       *portp = NULL;
+       *pathp = NULL;
+
+       /*
+        * RFC 3986 says:
+        *
+        *   URI         = scheme ":" hier-part [ "?" query ] [ "#" fragment ]
+        *
+        *   hier-part   = "//" authority path-abempty
+        *               / path-absolute
+        *               / path-rootless
+        *               / path-empty
+        *
+        *   authority   = [ userinfo "@" ] host [ ":" port ]
+        *
+        *   userinfo    = *( unreserved / pct-encoded / sub-delims / ":" )
+         *
+         * Step 1: look for the ":" at the end of the scheme.
+        * A colon in the source is *NOT* sufficient to indicate that
+        * this is a URL, as interface names on some platforms might
+        * include colons (e.g., I think some Solaris interfaces
+        * might).
+        */
+       colonp = strchr(source, ':');
+       if (colonp == NULL) {
+               /*
+                * The source is the device to open.
+                * Return a NULL pointer for the scheme, user information,
+                * host, and port, and return the device as the path.
+                */
+               *pathp = strdup(source);
+               if (*pathp == NULL) {
+                       pcap_fmt_errmsg_for_errno(ebuf, PCAP_ERRBUF_SIZE,
+                           errno, "malloc");
+                       return (-1);
+               }
+               return (0);
+       }
+
+       /*
+        * All schemes must have "//" after them, i.e. we only support
+        * hier-part   = "//" authority path-abempty, not
+        * hier-part   = path-absolute
+        * hier-part   = path-rootless
+        * hier-part   = path-empty
+        *
+        * We need that in order to distinguish between a local device
+        * name that happens to contain a colon and a URI.
+        */
+       if (strncmp(colonp + 1, "//", 2) != 0) {
+               /*
+                * The source is the device to open.
+                * Return a NULL pointer for the scheme, user information,
+                * host, and port, and return the device as the path.
+                */
+               *pathp = strdup(source);
+               if (*pathp == NULL) {
+                       pcap_fmt_errmsg_for_errno(ebuf, PCAP_ERRBUF_SIZE,
+                           errno, "malloc");
+                       return (-1);
+               }
+               return (0);
+       }
+
+       /*
+        * XXX - check whether the purported scheme could be a scheme?
+        */
+
+       /*
+        * OK, this looks like a URL.
+        * Get the scheme.
+        */
+       scheme_len = colonp - source;
+       scheme = malloc(scheme_len + 1);
+       if (scheme == NULL) {
+               pcap_fmt_errmsg_for_errno(ebuf, PCAP_ERRBUF_SIZE,
+                   errno, "malloc");
+               return (-1);
+       }
+       memcpy(scheme, source, scheme_len);
+       scheme[scheme_len] = '\0';
+
+       /*
+        * Treat file: specially - take everything after file:// as
+        * the pathname.
+        */
+       if (pcap_strcasecmp(scheme, "file") == 0) {
+               *pathp = strdup(colonp + 3);
+               if (*pathp == NULL) {
+                       pcap_fmt_errmsg_for_errno(ebuf, PCAP_ERRBUF_SIZE,
+                           errno, "malloc");
+                       free(scheme);
+                       return (-1);
+               }
+               *schemep = scheme;
+               return (0);
+       }
+
+       /*
+        * The WinPcap documentation says you can specify a local
+        * interface with "rpcap://{device}"; we special-case
+        * that here.  If the scheme is "rpcap", and there are
+        * no slashes past the "//", we just return the device.
+        *
+        * XXX - %-escaping?
+        */
+       if (pcap_strcasecmp(scheme, "rpcap") == 0 &&
+           strchr(colonp + 3, '/') == NULL) {
+               /*
+                * Local device.
+                *
+                * Return a NULL pointer for the scheme, user information,
+                * host, and port, and return the device as the path.
+                */
+               free(scheme);
+               *pathp = strdup(colonp + 3);
+               if (*pathp == NULL) {
+                       pcap_fmt_errmsg_for_errno(ebuf, PCAP_ERRBUF_SIZE,
+                           errno, "malloc");
+                       return (-1);
+               }
+               return (0);
+       }
+
+       /*
+        * OK, now start parsing the authority.
+        * Get token, terminated with / or terminated at the end of
+        * the string.
+        */
+       authority_len = strcspn(colonp + 3, "/");
+       authority = get_substring(colonp + 3, authority_len, ebuf);
+       if (authority == NULL) {
+               /*
+                * Error.
+                */
+               free(scheme);
+               return (-1);
+       }
+       endp = colonp + 3 + authority_len;
+
+       /*
+        * Now carve the authority field into its components.
+        */
+       parsep = authority;
+
+       /*
+        * Is there a userinfo field?
+        */
+       atsignp = strchr(parsep, '@');
+       if (atsignp != NULL) {
+               /*
+                * Yes.
+                */
+               size_t userinfo_len;
+
+               userinfo_len = atsignp - parsep;
+               userinfo = get_substring(parsep, userinfo_len, ebuf);
+               if (userinfo == NULL) {
+                       /*
+                        * Error.
+                        */
+                       free(authority);
+                       free(scheme);
+                       return (-1);
+               }
+               parsep = atsignp + 1;
+       } else {
+               /*
+                * No.
+                */
+               userinfo = NULL;
+       }
+
+       /*
+        * Is there a host field?
+        */
+       if (*parsep == '\0') {
+               /*
+                * No; there's no host field or port field.
+                */
+               host = NULL;
+               port = NULL;
+       } else {
+               /*
+                * Yes.
+                */
+               size_t host_len;
+
+               /*
+                * Is it an IP-literal?
+                */
+               if (*parsep == '[') {
+                       /*
+                        * Yes.
+                        * Treat verything up to the closing square
+                        * bracket as the IP-Literal; we don't worry
+                        * about whether it's a valid IPv6address or
+                        * IPvFuture (or an IPv4address, for that
+                        * matter, just in case we get handed a
+                        * URL with an IPv4 IP-Literal, of the sort
+                        * that pcap_createsrcstr() used to generate,
+                        * and that pcap_parsesrcstr(), in the original
+                        * WinPcap code, accepted).
+                        */
+                       bracketp = strchr(parsep, ']');
+                       if (bracketp == NULL) {
+                               /*
+                                * There's no closing square bracket.
+                                */
+                               pcap_snprintf(ebuf, PCAP_ERRBUF_SIZE,
+                                   "IP-literal in URL doesn't end with ]");
+                               free(userinfo);
+                               free(authority);
+                               free(scheme);
+                               return (-1);
+                       }
+                       if (*(bracketp + 1) != '\0' &&
+                           *(bracketp + 1) != ':') {
+                               /*
+                                * There's extra crud after the
+                                * closing square bracketn.
+                                */
+                               pcap_snprintf(ebuf, PCAP_ERRBUF_SIZE,
+                                   "Extra text after IP-literal in URL");
+                               free(userinfo);
+                               free(authority);
+                               free(scheme);
+                               return (-1);
+                       }
+                       host_len = (bracketp - 1) - parsep;
+                       host = get_substring(parsep + 1, host_len, ebuf);
+                       if (host == NULL) {
+                               /*
+                                * Error.
+                                */
+                               free(userinfo);
+                               free(authority);
+                               free(scheme);
+                               return (-1);
+                       }
+                       parsep = bracketp + 1;
+               } else {
+                       /*
+                        * No.
+                        * Treat everything up to a : or the end of
+                        * the string as the host.
+                        */
+                       host_len = strcspn(parsep, ":");
+                       host = get_substring(parsep, host_len, ebuf);
+                       if (host == NULL) {
+                               /*
+                                * Error.
+                                */
+                               free(userinfo);
+                               free(authority);
+                               free(scheme);
+                               return (-1);
+                       }
+                       parsep = parsep + host_len;
+               }
+
+               /*
+                * Is there a port field?
+                */
+               if (*parsep == ':') {
+                       /*
+                        * Yes.  It's the rest of the authority field.
+                        */
+                       size_t port_len;
+
+                       parsep++;
+                       port_len = strlen(parsep);
+                       port = get_substring(parsep, port_len, ebuf);
+                       if (port == NULL) {
+                               /*
+                                * Error.
+                                */
+                               free(host);
+                               free(userinfo);
+                               free(authority);
+                               free(scheme);
+                               return (-1);
+                       }
+               } else {
+                       /*
+                        * No.
+                        */
+                       port = NULL;
+               }
+       }
+       free(authority);
+
+       /*
+        * Everything else is the path.  Strip off the leading /.
+        */
+       if (*endp == '\0')
+               path = strdup("");
+       else
+               path = strdup(endp + 1);
+       if (path == NULL) {
+               pcap_fmt_errmsg_for_errno(ebuf, PCAP_ERRBUF_SIZE,
+                   errno, "malloc");
+               free(port);
+               free(host);
+               free(userinfo);
+               free(scheme);
+               return (-1);
+       }
+       *schemep = scheme;
+       *userinfop = userinfo;
+       *hostp = host;
+       *portp = port;
+       *pathp = path;
+       return (0);
+}
+
+int
+pcap_createsrcstr(char *source, int type, const char *host, const char *port,
+    const char *name, char *errbuf)
+{
+       switch (type) {
+
+       case PCAP_SRC_FILE:
+               pcap_strlcpy(source, PCAP_SRC_FILE_STRING, PCAP_BUF_SIZE);
+               if (name != NULL && *name != '\0') {
+                       pcap_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:
+               pcap_strlcpy(source, PCAP_SRC_IF_STRING, PCAP_BUF_SIZE);
+               if (host != NULL && *host != '\0') {
+                       if (strchr(host, ':') != NULL) {
+                               /*
+                                * The host name contains a colon, so it's
+                                * probably an IPv6 address, and needs to
+                                * be included in square brackets.
+                                */
+                               pcap_strlcat(source, "[", PCAP_BUF_SIZE);
+                               pcap_strlcat(source, host, PCAP_BUF_SIZE);
+                               pcap_strlcat(source, "]", PCAP_BUF_SIZE);
+                       } else
+                               pcap_strlcat(source, host, PCAP_BUF_SIZE);
+
+                       if (port != NULL && *port != '\0') {
+                               pcap_strlcat(source, ":", PCAP_BUF_SIZE);
+                               pcap_strlcat(source, port, PCAP_BUF_SIZE);
+                       }
+
+                       pcap_strlcat(source, "/", PCAP_BUF_SIZE);
+               } else {
+                       pcap_snprintf(errbuf, PCAP_ERRBUF_SIZE,
+                           "The host name cannot be NULL.");
+                       return (-1);
+               }
+
+               if (name != NULL && *name != '\0')
+                       pcap_strlcat(source, name, PCAP_BUF_SIZE);
+
+               return (0);
+
+       case PCAP_SRC_IFLOCAL:
+               pcap_strlcpy(source, PCAP_SRC_IF_STRING, PCAP_BUF_SIZE);
+
+               if (name != NULL && *name != '\0')
+                       pcap_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 *scheme, *tmpuserinfo, *tmphost, *tmpport, *tmppath;
+
+       /* Initialization stuff */
+       if (host)
+               *host = '\0';
+       if (port)
+               *port = '\0';
+       if (name)
+               *name = '\0';
+
+       /* Parse the source string */
+       if (pcap_parse_source(source, &scheme, &tmpuserinfo, &tmphost,
+           &tmpport, &tmppath, errbuf) == -1) {
+               /*
+                * Fail.
+                */
+               return (-1);
+       }
+
+       if (scheme == NULL) {
+               /*
+                * Local device.
+                */
+               if (name && tmppath)
+                       pcap_strlcpy(name, tmppath, PCAP_BUF_SIZE);
+               if (type)
+                       *type = PCAP_SRC_IFLOCAL;
+               free(tmppath);
+               free(tmpport);
+               free(tmphost);
+               free(tmpuserinfo);
+               return (0);
+       }
+
+       if (strcmp(scheme, "rpcap") == 0) {
+               /*
+                * rpcap://
+                *
+                * pcap_parse_source() has already handled the case of
+                * rpcap://device
+                */
+               if (host && tmphost) {
+                       if (tmpuserinfo)
+                               pcap_snprintf(host, PCAP_BUF_SIZE, "%s@%s",
+                                   tmpuserinfo, tmphost);
+                       else
+                               pcap_strlcpy(host, tmphost, PCAP_BUF_SIZE);
+               }
+               if (port && tmpport)
+                       pcap_strlcpy(port, tmpport, PCAP_BUF_SIZE);
+               if (name && tmppath)
+                       pcap_strlcpy(name, tmppath, PCAP_BUF_SIZE);
+               if (type)
+                       *type = PCAP_SRC_IFREMOTE;
+               free(tmppath);
+               free(tmpport);
+               free(tmphost);
+               free(tmpuserinfo);
+               free(scheme);
+               return (0);
+       }
+
+       if (strcmp(scheme, "file") == 0) {
+               /*
+                * file://
+                */
+               if (name && tmppath)
+                       pcap_strlcpy(name, tmppath, PCAP_BUF_SIZE);
+               if (type)
+                       *type = PCAP_SRC_FILE;
+               free(tmppath);
+               free(tmpport);
+               free(tmphost);
+               free(tmpuserinfo);
+               free(scheme);
+               return (0);
+       }
+
+       /*
+        * Neither rpcap: nor file:; just treat the entire string
+        * as a local device.
+        */
+       if (name)
+               pcap_strlcpy(name, source, PCAP_BUF_SIZE);
+       if (type)
+               *type = PCAP_SRC_IFLOCAL;
+       free(tmppath);
+       free(tmpport);
+       free(tmphost);
+       free(tmpuserinfo);
+       free(scheme);
+       return (0);
+}
+#endif
+
+pcap_t *
+pcap_create(const char *device, char *errbuf)
+{
+       size_t i;
+       int is_theirs;
+       pcap_t *p;
+       char *device_str;
+
+       /*
+        * 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 (device == NULL)
+               device_str = strdup("any");
+       else {
+#ifdef _WIN32
+               /*
+                * On Windows, for backwards compatibility reasons,
+                * pcap_lookupdev() returns a pointer to a sequence of
+                * pairs of UTF-16LE device names and local code page
+                * description strings.
+                *
+                * This means that if a program uses pcap_lookupdev()
+                * to get a default device, and hands that to an API
+                * that opens devices, we'll get handed a UTF-16LE
+                * string, not a string in the local code page.
+                *
+                * To work around that, we check whether the string
+                * looks as if it might be a UTF-16LE strinh and, if
+                * so, convert it back to the local code page's
+                * extended ASCII.
+                *
+                * XXX - you *cannot* reliably detect whether a
+                * string is UTF-16LE or not; "a" could either
+                * be a one-character ASCII string or the first
+                * character of a UTF-16LE string.  This particular
+                * version of this heuristic dates back to WinPcap
+                * 4.1.1; PacketOpenAdapter() does uses the same
+                * heuristic, with the exact same vulnerability.
+                */
+               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_fmt_errmsg_for_errno(errbuf,
+                                   PCAP_ERRBUF_SIZE, errno,
+                                   "malloc");
+                               return (NULL);
+                       }
+
+                       pcap_snprintf(device_str, length + 1, "%ws",
+                           (const wchar_t *)device);
+               } else
+#endif
+                       device_str = strdup(device);
+       }
+       if (device_str == NULL) {
+               pcap_fmt_errmsg_for_errno(errbuf, PCAP_ERRBUF_SIZE,
+                   errno, "malloc");
+               return (NULL);
+       }
+
+       /*
+        * Try each of the non-local-network-interface capture
+        * source types until we find one that works for this
+        * device or run out of types.
+        */
+       for (i = 0; capture_source_types[i].create_op != NULL; i++) {
+               is_theirs = 0;
+               p = capture_source_types[i].create_op(device_str, errbuf,
+                   &is_theirs);
+               if (is_theirs) {
+                       /*
+                        * The device name refers to a device of the
+                        * type in question; either it succeeded,
+                        * in which case p refers to a pcap_t to
+                        * later activate for the device, or it
+                        * failed, in which case p is null and we
+                        * 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);
+               }
+       }
+
+       /*
+        * OK, try it as a regular network interface.
+        */
+       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);
+}
+
+/*
+ * Set nonblocking mode on an unactivated pcap_t; this sets a flag
+ * checked by pcap_activate(), which sets the mode after calling
+ * the activate routine.
+ */
+static int
+pcap_setnonblock_unactivated(pcap_t *p, int nonblock)
+{
+       p->opt.nonblock = nonblock;
+       return (0);
+}
+
+static void
+initialize_ops(pcap_t *p)
+{
+       /*
+        * Set operation pointers for operations that only work on
+        * an activated pcap_t to point to a routine that returns
+        * a "this isn't activated" error.
         */
-       p->read_op = (read_op_t)pcap_not_initialized;
-       p->inject_op = (inject_op_t)pcap_not_initialized;
-       p->setfilter_op = (setfilter_op_t)pcap_not_initialized;
-       p->setdirection_op = (setdirection_op_t)pcap_not_initialized;
-       p->set_datalink_op = (set_datalink_op_t)pcap_not_initialized;
-       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
-       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->read_op = pcap_read_not_initialized;
+       p->inject_op = pcap_inject_not_initialized;
+       p->setfilter_op = pcap_setfilter_not_initialized;
+       p->setdirection_op = pcap_setdirection_not_initialized;
+       p->set_datalink_op = pcap_set_datalink_not_initialized;
+       p->getnonblock_op = pcap_getnonblock_not_initialized;
+       p->stats_op = pcap_stats_not_initialized;
+#ifdef _WIN32
+       p->stats_ex_op = pcap_stats_ex_not_initialized;
+       p->setbuff_op = pcap_setbuff_not_initialized;
+       p->setmode_op = pcap_setmode_not_initialized;
+       p->setmintocopy_op = pcap_setmintocopy_not_initialized;
+       p->getevent_op = pcap_getevent_not_initialized;
+       p->oid_get_request_op = pcap_oid_get_request_not_initialized;
+       p->oid_set_request_op = pcap_oid_set_request_not_initialized;
+       p->sendqueue_transmit_op = pcap_sendqueue_transmit_not_initialized;
+       p->setuserbuffer_op = pcap_setuserbuffer_not_initialized;
+       p->live_dump_op = pcap_live_dump_not_initialized;
+       p->live_dump_ended_op = pcap_live_dump_ended_not_initialized;
+       p->get_airpcap_handle_op = pcap_get_airpcap_handle_not_initialized;
 #endif
 
        /*
@@ -492,24 +2238,38 @@ pcap_alloc_pcap_t(char *ebuf, size_t size)
         * plus a structure following it of size "size".  The
         * structure following it is a private data structure
         * for the routines that handle this pcap_t.
+        *
+        * The structure following it must be aligned on
+        * the appropriate alignment boundary for this platform.
+        * We align on an 8-byte boundary as that's probably what
+        * at least some platforms do, even with 32-bit integers,
+        * and because we can't be sure that some values won't
+        * require 8-byte alignment even on platforms with 32-bit
+        * integers.
         */
-       chunk = malloc(sizeof (pcap_t) + size);
+#define PCAP_T_ALIGNED_SIZE    ((sizeof(pcap_t) + 7U) & ~0x7U)
+       chunk = malloc(PCAP_T_ALIGNED_SIZE + size);
        if (chunk == NULL) {
-               snprintf(ebuf, PCAP_ERRBUF_SIZE, "malloc: %s",
-                   pcap_strerror(errno));
+               pcap_fmt_errmsg_for_errno(ebuf, PCAP_ERRBUF_SIZE,
+                   errno, "malloc");
                return (NULL);
        }
-       memset(chunk, 0, sizeof (pcap_t) + size);
+       memset(chunk, 0, PCAP_T_ALIGNED_SIZE + size);
 
        /*
         * Get a pointer to the pcap_t at the beginning.
         */
        p = (pcap_t *)chunk;
 
-#ifndef WIN32
+#ifdef _WIN32
+       p->handle = INVALID_HANDLE_VALUE;       /* not opened yet */
+#else /* _WIN32 */
        p->fd = -1;     /* not opened yet */
+#ifndef MSDOS
        p->selectable_fd = -1;
-#endif
+       p->required_select_timeout = NULL;
+#endif /* MSDOS */
+#endif /* _WIN32 */
 
        if (size == 0) {
                /* No private data was requested. */
@@ -519,14 +2279,14 @@ pcap_alloc_pcap_t(char *ebuf, size_t size)
                 * Set the pointer to the private data; that's the structure
                 * of size "size" following the pcap_t.
                 */
-               p->priv = (void *)(chunk + sizeof (pcap_t));
+               p->priv = (void *)(chunk + PCAP_T_ALIGNED_SIZE);
        }
 
        return (p);
 }
 
 pcap_t *
-pcap_create_common(const char *source, char *ebuf, size_t size)
+pcap_create_common(char *ebuf, size_t size)
 {
        pcap_t *p;
 
@@ -534,14 +2294,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
@@ -550,17 +2302,39 @@ pcap_create_common(const char *source, char *ebuf, size_t size)
         */
        p->can_set_rfmon_op = pcap_cant_set_rfmon;
 
+       /*
+        * If pcap_setnonblock() is called on a not-yet-activated
+        * pcap_t, default to setting a flag and turning
+        * on non-blocking mode when activated.
+        */
+       p->setnonblock_op = pcap_setnonblock_unactivated;
+
        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 = 0;                /* max packet size unspecified */
+       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;
+       /*
+        * Platform-dependent options.
+        */
+#ifdef __linux__
+       p->opt.protocol = 0;
+#endif
+#ifdef _WIN32
+       p->opt.nocapture_local = 0;
+#endif
+
+       /*
+        * Start out with no BPF code generation flags set.
+        */
+       p->bpf_codegen_flags = 0;
+
        return (p);
 }
 
@@ -568,7 +2342,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);
        }
@@ -620,6 +2394,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.
         */
@@ -633,7 +2414,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.
                                 */
@@ -663,6 +2444,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);
 }
@@ -676,6 +2463,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
@@ -693,7 +2487,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.
                                 */
@@ -730,9 +2524,25 @@ pcap_activate(pcap_t *p)
        if (pcap_check_activated(p))
                return (PCAP_ERROR_ACTIVATED);
        status = p->activate_op(p);
-       if (status >= 0)
+       if (status >= 0) {
+               /*
+                * If somebody requested non-blocking mode before
+                * calling pcap_activate(), turn it on now.
+                */
+               if (p->opt.nonblock) {
+                       status = p->setnonblock_op(p, 1);
+                       if (status < 0) {
+                               /*
+                                * Failed.  Undo everything done by
+                                * the activate operation.
+                                */
+                               p->cleanup_op(p);
+                               initialize_ops(p);
+                               return (status);
+                       }
+               }
                p->activated = 1;
-       else {
+       else {
                if (p->errbuf[0] == '\0') {
                        /*
                         * No error message supplied by the activate routine;
@@ -740,7 +2550,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));
                }
 
@@ -754,12 +2564,69 @@ 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;
+#ifdef ENABLE_REMOTE
+       char host[PCAP_BUF_SIZE + 1];
+       char port[PCAP_BUF_SIZE + 1];
+       char name[PCAP_BUF_SIZE + 1];
+       int srctype;
+
+       /*
+        * 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 (device == NULL)
+               device = "any";
+
+       /*
+        * Retrofit - we have to make older applications compatible with
+        * remote capture.
+        * So we're calling pcap_open_remote() from here; this is a very
+        * dirty hack.
+        * 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(device, &srctype, host, port, name, errbuf))
+               return (NULL);
+
+       if (srctype == PCAP_SRC_IFREMOTE) {
+               /*
+                * Although we already have host, port and iface, we prefer
+                * to pass only 'device' to pcap_open_rpcap(), so that it has
+                * to call pcap_parsesrcstr() again.
+                * This is less optimized, but much clearer.
+                */
+               return (pcap_open_rpcap(device, snaplen,
+                   promisc ? PCAP_OPENFLAG_PROMISCUOUS : 0, to_ms,
+                   NULL, errbuf));
+       }
+       if (srctype == PCAP_SRC_FILE) {
+               pcap_snprintf(errbuf, PCAP_ERRBUF_SIZE, "unknown URL scheme \"file\"");
+               return (NULL);
+       }
+       if (srctype == PCAP_SRC_IFLOCAL) {
+               /*
+                * If it starts with rpcap://, that refers to a local device
+                * (no host part in the URL). Remove the rpcap://, and
+                * fall through to the regular open path.
+                */
+               if (strncmp(device, PCAP_SRC_IF_STRING, strlen(PCAP_SRC_IF_STRING)) == 0) {
+                       size_t len = strlen(device) - strlen(PCAP_SRC_IF_STRING) + 1;
+
+                       if (len > 0)
+                               device += strlen(PCAP_SRC_IF_STRING);
+               }
+       }
+#endif /* ENABLE_REMOTE */
 
-       p = pcap_create(source, errbuf);
+       p = pcap_create(device, errbuf);
        if (p == NULL)
                return (NULL);
        status = pcap_set_snaplen(p, snaplen);
@@ -788,15 +2655,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,
-                   p->errbuf);
+               pcap_snprintf(errbuf, PCAP_ERRBUF_SIZE, "%s: %.*s", device,
+                   PCAP_ERRBUF_SIZE - 3, 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_statustostr(status), p->errbuf);
+               pcap_snprintf(errbuf, PCAP_ERRBUF_SIZE, "%s: %s (%.*s)", device,
+                   pcap_statustostr(status), PCAP_ERRBUF_SIZE - 6, 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);
@@ -812,13 +2679,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);
 }
@@ -829,16 +2689,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)
 {
@@ -908,8 +2758,8 @@ 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),
-                           "malloc: %s", pcap_strerror(errno));
+                       pcap_fmt_errmsg_for_errno(p->errbuf, sizeof(p->errbuf),
+                           errno, "malloc");
                        return (PCAP_ERROR);
                }
                **dlt_buffer = p->linktype;
@@ -917,8 +2767,8 @@ 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),
-                           "malloc: %s", pcap_strerror(errno));
+                       pcap_fmt_errmsg_for_errno(p->errbuf, sizeof(p->errbuf),
+                           errno, "malloc");
                        return (PCAP_ERROR);
                }
                (void)memcpy(*dlt_buffer, p->dlt_list,
@@ -950,6 +2800,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
@@ -967,7 +2820,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;
@@ -995,11 +2848,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);
        }
@@ -1097,133 +2950,150 @@ 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 v1"),
+       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_KONTRON, "IPMB with Kontron pseudo-header"),
+       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(IPMB_LINUX, "IPMB with Linux/Pigeon Point pseudo-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(USB_DARWIN, "USB with Darwin header"),
+       DLT_CHOICE(OPENFLOW, "OpenBSD DLT_OPENFLOW"),
+       DLT_CHOICE(SDLC, "IBM SDLC frames"),
+       DLT_CHOICE(TI_LLN_SNIFFER, "TI LLN sniffer frames"),
+       DLT_CHOICE(VSOCK, "Linux vsock"),
+       DLT_CHOICE(NORDIC_BLE, "Nordic Semiconductor Bluetooth LE sniffer frames"),
+       DLT_CHOICE(DOCSIS31_XRA31, "Excentis XRA-31 DOCSIS 3.1 RF sniffer frames"),
+       DLT_CHOICE(ETHERNET_MPACKET, "802.3br mPackets"),
+       DLT_CHOICE(DISPLAYPORT_AUX, "DisplayPort AUX channel monitoring data"),
+       DLT_CHOICE(LINUX_SLL2, "Linux cooked v2"),
        DLT_CHOICE_SENTINEL
 };
 
@@ -1233,8 +3103,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);
@@ -1247,7 +3116,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);
 }
@@ -1264,6 +3133,21 @@ pcap_datalink_val_to_description(int dlt)
        return (NULL);
 }
 
+const char *
+pcap_datalink_val_to_description_or_dlt(int dlt)
+{
+        static char unkbuf[40];
+        const char *description;
+
+        description = pcap_datalink_val_to_description(dlt);
+        if (description != NULL) {
+                return description;
+        } else {
+                (void)pcap_snprintf(unkbuf, sizeof(unkbuf), "DLT %u", dlt);
+                return unkbuf;
+        }
+}
+
 struct tstamp_type_choice {
        const char *name;
        const char *description;
@@ -1347,6 +3231,14 @@ pcap_minor_version(pcap_t *p)
        return (p->version_minor);
 }
 
+int
+pcap_bufsize(pcap_t *p)
+{
+       if (!p->activated)
+               return (PCAP_ERROR_NOT_ACTIVATED);
+       return (p->bufsize);
+}
+
 FILE *
 pcap_file(pcap_t *p)
 {
@@ -1356,26 +3248,32 @@ pcap_file(pcap_t *p)
 int
 pcap_fileno(pcap_t *p)
 {
-#ifndef WIN32
+#ifndef _WIN32
        return (p->fd);
 #else
-       if (p->adapter != NULL)
-               return ((int)(DWORD)p->adapter->hFile);
+       if (p->handle != INVALID_HANDLE_VALUE)
+               return ((int)(DWORD)p->handle);
        else
                return (PCAP_ERROR);
 #endif
 }
 
-#if !defined(WIN32) && !defined(MSDOS)
+#if !defined(_WIN32) && !defined(MSDOS)
 int
 pcap_get_selectable_fd(pcap_t *p)
 {
        return (p->selectable_fd);
 }
+
+struct timeval *
+pcap_get_required_select_timeout(pcap_t *p)
+{
+       return (p->required_select_timeout);
+}
 #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);
 }
@@ -1391,14 +3289,18 @@ pcap_getnonblock(pcap_t *p, char *errbuf)
 {
        int ret;
 
-       ret = p->getnonblock_op(p, errbuf);
+       ret = p->getnonblock_op(p);
        if (ret == -1) {
                /*
-                * In case somebody depended on the bug wherein
-                * the error message was put into p->errbuf
-                * by pcap_getnonblock_fd().
+                * The get nonblock operation sets p->errbuf; this
+                * function *shouldn't* have had a separate errbuf
+                * argument, as it didn't need one, but I goofed
+                * when adding it.
+                *
+                * We copy the error message to errbuf, so callers
+                * can find it in either place.
                 */
-               strlcpy(p->errbuf, errbuf, PCAP_ERRBUF_SIZE);
+               pcap_strlcpy(errbuf, p->errbuf, PCAP_ERRBUF_SIZE);
        }
        return (ret);
 }
@@ -1406,20 +3308,17 @@ 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)
+pcap_getnonblock_fd(pcap_t *p)
 {
        int fdflags;
 
        fdflags = fcntl(p->fd, F_GETFL, 0);
        if (fdflags == -1) {
-               snprintf(errbuf, PCAP_ERRBUF_SIZE, "F_GETFL: %s",
-                   pcap_strerror(errno));
+               pcap_fmt_errmsg_for_errno(p->errbuf, PCAP_ERRBUF_SIZE,
+                   errno, "F_GETFL");
                return (-1);
        }
        if (fdflags & O_NONBLOCK)
@@ -1434,19 +3333,23 @@ pcap_setnonblock(pcap_t *p, int nonblock, char *errbuf)
 {
        int ret;
 
-       ret = p->setnonblock_op(p, nonblock, errbuf);
+       ret = p->setnonblock_op(p, nonblock);
        if (ret == -1) {
                /*
-                * In case somebody depended on the bug wherein
-                * the error message was put into p->errbuf
-                * by pcap_setnonblock_fd().
+                * The set nonblock operation sets p->errbuf; this
+                * function *shouldn't* have had a separate errbuf
+                * argument, as it didn't need one, but I goofed
+                * when adding it.
+                *
+                * We copy the error message to errbuf, so callers
+                * can find it in either place.
                 */
-               strlcpy(p->errbuf, errbuf, PCAP_ERRBUF_SIZE);
+               pcap_strlcpy(errbuf, p->errbuf, PCAP_ERRBUF_SIZE);
        }
        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
@@ -1454,14 +3357,14 @@ pcap_setnonblock(pcap_t *p, int nonblock, char *errbuf)
  * needs to do some additional work.)
  */
 int
-pcap_setnonblock_fd(pcap_t *p, int nonblock, char *errbuf)
+pcap_setnonblock_fd(pcap_t *p, int nonblock)
 {
        int fdflags;
 
        fdflags = fcntl(p->fd, F_GETFL, 0);
        if (fdflags == -1) {
-               snprintf(errbuf, PCAP_ERRBUF_SIZE, "F_GETFL: %s",
-                   pcap_strerror(errno));
+               pcap_fmt_errmsg_for_errno(p->errbuf, PCAP_ERRBUF_SIZE,
+                   errno, "F_GETFL");
                return (-1);
        }
        if (nonblock)
@@ -1469,47 +3372,14 @@ 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_strerror(errno));
+               pcap_fmt_errmsg_for_errno(p->errbuf, PCAP_ERRBUF_SIZE,
+                   errno, "F_SETFL");
                return (-1);
        }
        return (0);
 }
 #endif
 
-#ifdef WIN32
-/*
- * Generate a string for the last 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)
-{
-       DWORD error;
-       static char errbuf[PCAP_ERRBUF_SIZE+1];
-       int errlen;
-       char *p;
-
-       error = GetLastError();
-       FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM, NULL, error, 0, errbuf,
-           PCAP_ERRBUF_SIZE, NULL);
-
-       /*
-        * "FormatMessage()" "helpfully" sticks CR/LF at the end of the
-        * message.  Get rid of it.
-        */
-       errlen = strlen(errbuf);
-       if (errlen >= 2) {
-               errbuf[errlen - 1] = '\0';
-               errbuf[errlen - 2] = '\0';
-       }
-       p = strchr(errbuf, '\0');
-       snprintf (p, sizeof(errbuf)-(p-errbuf), " (%lu)", error);
-       return (errbuf);
-}
-#endif
-
 /*
  * Generate error strings for PCAP_ERROR_ and PCAP_WARNING_ values.
  */
@@ -1565,7 +3435,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);
 }
 
@@ -1576,16 +3446,25 @@ const char *
 pcap_strerror(int errnum)
 {
 #ifdef HAVE_STRERROR
+#ifdef _WIN32
+       static char errbuf[PCAP_ERRBUF_SIZE];
+       errno_t err = strerror_s(errbuf, PCAP_ERRBUF_SIZE, errnum);
+
+       if (err != 0) /* err = 0 if successful */
+               pcap_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
 }
 
@@ -1605,74 +3484,146 @@ 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
                return (p->setdirection_op(p, d));
 }
 
-int
-pcap_stats(pcap_t *p, struct pcap_stat *ps)
+int
+pcap_stats(pcap_t *p, struct pcap_stat *ps)
+{
+       return (p->stats_op(p, ps));
+}
+
+#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)
+{
+       return (p->setbuff_op(p, dim));
+}
+
+int
+pcap_setmode(pcap_t *p, int mode)
+{
+       return (p->setmode_op(p, mode));
+}
+
+int
+pcap_setmintocopy(pcap_t *p, int size)
+{
+       return (p->setmintocopy_op(p, size));
+}
+
+HANDLE
+pcap_getevent(pcap_t *p)
+{
+       return (p->getevent_op(p));
+}
+
+int
+pcap_oid_get_request(pcap_t *p, bpf_u_int32 oid, void *data, size_t *lenp)
+{
+       return (p->oid_get_request_op(p, oid, data, lenp));
+}
+
+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));
+}
+
+pcap_send_queue *
+pcap_sendqueue_alloc(u_int memsize)
 {
-       return (p->stats_op(p, ps));
+       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);
 }
 
-static int
-pcap_stats_dead(pcap_t *p, struct pcap_stat *ps _U_)
+void
+pcap_sendqueue_destroy(pcap_send_queue *queue)
 {
-       snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
-           "Statistics aren't available from a pcap_open_dead pcap_t");
-       return (-1);
+       free(queue->buffer);
+       free(queue);
 }
 
-#ifdef WIN32
 int
-pcap_setbuff(pcap_t *p, int dim)
+pcap_sendqueue_queue(pcap_send_queue *queue, const struct pcap_pkthdr *pkt_header, const u_char *pkt_data)
 {
-       return (p->setbuff_op(p, dim));
+       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);
 }
 
-static int
-pcap_setbuff_dead(pcap_t *p, int dim)
+u_int
+pcap_sendqueue_transmit(pcap_t *p, pcap_send_queue *queue, int sync)
 {
-       snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
-           "The kernel buffer size cannot be set on a pcap_open_dead pcap_t");
-       return (-1);
+       return (p->sendqueue_transmit_op(p, queue, sync));
 }
 
 int
-pcap_setmode(pcap_t *p, int mode)
+pcap_setuserbuffer(pcap_t *p, int size)
 {
-       return (p->setmode_op(p, mode));
+       return (p->setuserbuffer_op(p, size));
 }
 
-static int
-pcap_setmode_dead(pcap_t *p, int mode)
+int
+pcap_live_dump(pcap_t *p, char *filename, int maxsize, int maxpacks)
 {
-       snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
-           "impossible to set mode on a pcap_open_dead pcap_t");
-       return (-1);
+       return (p->live_dump_op(p, filename, maxsize, maxpacks));
 }
 
 int
-pcap_setmintocopy(pcap_t *p, int size)
+pcap_live_dump_ended(pcap_t *p, int sync)
 {
-       return (p->setmintocopy_op(p, size));
+       return (p->live_dump_ended_op(p, sync));
 }
 
-Adapter *
-pcap_get_adapter(pcap_t *p)
+PAirpcapHandle
+pcap_get_airpcap_handle(pcap_t *p)
 {
-       return (p->getadapter_op(p));
-}
+       PAirpcapHandle handle;
 
-static int
-pcap_setmintocopy_dead(pcap_t *p, int size)
-{
-       snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
-           "The mintocopy parameter cannot be set on a pcap_open_dead pcap_t");
-       return (-1);
+       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);
 }
 #endif
 
@@ -1718,12 +3669,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);
+                       pcap_strlcpy(p->errbuf, "atexit failed", PCAP_ERRBUF_SIZE);
                        return (0);
                }
                did_atexit = 1;
@@ -1788,7 +3738,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;
@@ -1797,51 +3747,6 @@ pcap_cleanup_live_common(pcap_t *p)
 #endif
 }
 
-static void
-pcap_cleanup_dead(pcap_t *p _U_)
-{
-       /* Nothing to do. */
-}
-
-pcap_t *
-pcap_open_dead_with_tstamp_precision(int linktype, int snaplen, u_int precision)
-{
-       pcap_t *p;
-
-       switch (precision) {
-
-       case PCAP_TSTAMP_PRECISION_MICRO:
-       case PCAP_TSTAMP_PRECISION_NANO:
-               break;
-
-       default:
-               return NULL;
-       }
-       p = malloc(sizeof(*p));
-       if (p == NULL)
-               return NULL;
-       memset (p, 0, sizeof(*p));
-       p->snapshot = snaplen;
-       p->linktype = linktype;
-       p->opt.tstamp_precision = precision;
-       p->stats_op = pcap_stats_dead;
-#ifdef WIN32
-       p->setbuff_op = pcap_setbuff_dead;
-       p->setmode_op = pcap_setmode_dead;
-       p->setmintocopy_op = pcap_setmintocopy_dead;
-#endif
-       p->cleanup_op = pcap_cleanup_dead;
-       p->activated = 1;
-       return (p);
-}
-
-pcap_t *
-pcap_open_dead(int linktype, int snaplen)
-{
-       return (pcap_open_dead_with_tstamp_precision(linktype, snaplen,
-           PCAP_TSTAMP_PRECISION_MICRO));
-}
-
 /*
  * API compatible with WinPcap's "send a packet" routine - returns -1
  * on error, 0 otherwise.
@@ -1869,8 +3774,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);
 }
@@ -1893,122 +3798,270 @@ 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
+static int
+pcap_can_set_rfmon_dead(pcap_t *p)
+{
+       pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
+           "Rfmon mode doesn't apply on a pcap_open_dead pcap_t");
+       return (PCAP_ERROR);
+}
 
-#ifdef WIN32
-/*
- * 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.)
- */
-static const char wpcap_version_string[] = "4.0";
-static const char pcap_version_string_fmt[] =
-    "WinPcap 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;
+static int
+pcap_read_dead(pcap_t *p, int cnt _U_, pcap_handler callback _U_,
+    u_char *user _U_)
+{
+       pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
+           "Packets aren't available from a pcap_open_dead pcap_t");
+       return (-1);
+}
 
-const char *
-pcap_lib_version(void)
+static int
+pcap_inject_dead(pcap_t *p, const void *buf _U_, size_t size _U_)
 {
-       char *packet_version_string;
-       size_t full_pcap_version_string_len;
+       pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
+           "Packets can't be sent on a pcap_open_dead pcap_t");
+       return (-1);
+}
 
-       if (full_pcap_version_string == NULL) {
-               /*
-                * Generate the version string.
-                */
-               packet_version_string = PacketGetVersion();
-               if (strcmp(wpcap_version_string, packet_version_string) == 0) {
-                       /*
-                        * WinPcap version string and packet.dll version
-                        * string are the same; just report the WinPcap
-                        * version.
-                        */
-                       full_pcap_version_string_len =
-                           (sizeof pcap_version_string_fmt - 4) +
-                           strlen(wpcap_version_string) +
-                           strlen(pcap_version_string);
-                       full_pcap_version_string =
-                           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_version_string);
-               } else {
-                       /*
-                        * WinPcap version string and packet.dll version
-                        * string are different; that shouldn't be the
-                        * case (the two libraries should come from the
-                        * same version of WinPcap), so we report both
-                        * versions.
-                        */
-                       full_pcap_version_string_len =
-                           (sizeof pcap_version_string_packet_dll_fmt - 6) +
-                           strlen(wpcap_version_string) +
-                           strlen(packet_version_string) +
-                           strlen(pcap_version_string);
-                       full_pcap_version_string = malloc(full_pcap_version_string_len);
-                       if (full_pcap_version_string == NULL)
-                               return (NULL);
-                       sprintf(full_pcap_version_string,
-                           pcap_version_string_packet_dll_fmt,
-                           wpcap_version_string, packet_version_string,
-                           pcap_version_string);
-               }
-       }
-       return (full_pcap_version_string);
+static int
+pcap_setfilter_dead(pcap_t *p, struct bpf_program *fp _U_)
+{
+       pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
+           "A filter cannot be set on a pcap_open_dead pcap_t");
+       return (-1);
+}
+
+static int
+pcap_setdirection_dead(pcap_t *p, pcap_direction_t d _U_)
+{
+       pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
+           "The packet direction cannot be set on a pcap_open_dead pcap_t");
+       return (-1);
+}
+
+static int
+pcap_set_datalink_dead(pcap_t *p, int dlt _U_)
+{
+       pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
+           "The link-layer header type cannot be set on a pcap_open_dead pcap_t");
+       return (-1);
 }
 
-#elif defined(MSDOS)
+static int
+pcap_getnonblock_dead(pcap_t *p)
+{
+       pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
+           "A pcap_open_dead pcap_t does not have a non-blocking mode setting");
+       return (-1);
+}
 
-static char *full_pcap_version_string;
+static int
+pcap_setnonblock_dead(pcap_t *p, int nonblock _U_)
+{
+       pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
+           "A pcap_open_dead pcap_t does not have a non-blocking mode setting");
+       return (-1);
+}
 
-const char *
-pcap_lib_version (void)
+static int
+pcap_stats_dead(pcap_t *p, struct pcap_stat *ps _U_)
+{
+       pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
+           "Statistics aren't available from a pcap_open_dead pcap_t");
+       return (-1);
+}
+
+#ifdef _WIN32
+struct pcap_stat *
+pcap_stats_ex_dead(pcap_t *p, int *pcap_stat_size _U_)
+{
+       pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
+           "Statistics aren't available from a pcap_open_dead pcap_t");
+       return (NULL);
+}
+
+static int
+pcap_setbuff_dead(pcap_t *p, int dim)
+{
+       pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
+           "The kernel buffer size cannot be set on a pcap_open_dead pcap_t");
+       return (-1);
+}
+
+static int
+pcap_setmode_dead(pcap_t *p, int mode)
+{
+       pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
+           "impossible to set mode on a pcap_open_dead pcap_t");
+       return (-1);
+}
+
+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);
+}
+
+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);
+}
+
+static int
+pcap_oid_get_request_dead(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 pcap_open_dead pcap_t");
+       return (PCAP_ERROR);
+}
+
+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);
+}
+
+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);
+}
+
+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);
+}
+
+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);
+}
+
+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);
+}
+
+static PAirpcapHandle
+pcap_get_airpcap_handle_dead(pcap_t *p)
+{
+       return (NULL);
+}
+#endif /* _WIN32 */
+
+static void
+pcap_cleanup_dead(pcap_t *p _U_)
+{
+       /* Nothing to do. */
+}
+
+pcap_t *
+pcap_open_dead_with_tstamp_precision(int linktype, int snaplen, u_int precision)
 {
-       char *packet_version_string;
-       size_t full_pcap_version_string_len;
-       static char dospfx[] = "DOS-";
+       pcap_t *p;
+
+       switch (precision) {
+
+       case PCAP_TSTAMP_PRECISION_MICRO:
+       case PCAP_TSTAMP_PRECISION_NANO:
+               break;
 
-       if (full_pcap_version_string == NULL) {
+       default:
                /*
-                * Generate the version string.
+                * This doesn't really matter, but we don't have any way
+                * to report particular errors, so the only failure we
+                * should have is a memory allocation failure.  Just
+                * pick microsecond precision.
                 */
-               full_pcap_version_string_len =
-                   sizeof dospfx + strlen(pcap_version_string);
-               full_pcap_version_string =
-                   malloc(full_pcap_version_string_len);
-               if (full_pcap_version_string == NULL)
-                       return (NULL);
-               strcpy(full_pcap_version_string, dospfx);
-               strcat(full_pcap_version_string, pcap_version_string);
+               precision = PCAP_TSTAMP_PRECISION_MICRO;
+               break;
        }
-       return (full_pcap_version_string);
+       p = malloc(sizeof(*p));
+       if (p == NULL)
+               return NULL;
+       memset (p, 0, sizeof(*p));
+       p->snapshot = snaplen;
+       p->linktype = linktype;
+       p->opt.tstamp_precision = precision;
+       p->can_set_rfmon_op = pcap_can_set_rfmon_dead;
+       p->read_op = pcap_read_dead;
+       p->inject_op = pcap_inject_dead;
+       p->setfilter_op = pcap_setfilter_dead;
+       p->setdirection_op = pcap_setdirection_dead;
+       p->set_datalink_op = pcap_set_datalink_dead;
+       p->getnonblock_op = pcap_getnonblock_dead;
+       p->setnonblock_op = pcap_setnonblock_dead;
+       p->stats_op = pcap_stats_dead;
+#ifdef _WIN32
+       p->stats_ex_op = pcap_stats_ex_dead;
+       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);
+}
+
+pcap_t *
+pcap_open_dead(int linktype, int snaplen)
+{
+       return (pcap_open_dead_with_tstamp_precision(linktype, snaplen,
+           PCAP_TSTAMP_PRECISION_MICRO));
 }
 
-#else /* UN*X */
+#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);
 
-const char *
-pcap_lib_version(void)
+PCAP_API_DEF void
+pcap_set_parser_debug(int value)
 {
-       return (pcap_version_string);
+       pcap_debug = value;
 }
 #endif
index 7cb0a8e..15dc5a8 100644 (file)
@@ -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
  * 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
+
+#include <pcap/pcap-inttypes.h>
 
 /*
  * Header prepended libpcap to each bluetooth h4 frame,
  * fields are in network byte order
  */
 typedef struct _pcap_bluetooth_h4_header {
-       u_int32_t direction; /* if first bit is set direction is incoming */
+       uint32_t direction; /* if first bit is set direction is incoming */
 } pcap_bluetooth_h4_header;
 
 /*
@@ -47,9 +49,8 @@ typedef struct _pcap_bluetooth_h4_header {
  * fields are in network byte order
  */
 typedef struct _pcap_bluetooth_linux_monitor_header {
-       u_int16_t adapter_id;
-       u_int16_t opcode;
+       uint16_t adapter_id;
+       uint16_t opcode;
 } pcap_bluetooth_linux_monitor_header;
 
-
 #endif
index ff88fd0..9d74895 100644 (file)
@@ -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
  * 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
+ * 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.
  *
@@ -59,7 +55,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
  *
  * 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/funcattrs.h>
+
 #ifdef __cplusplus
 extern "C" {
 #endif
@@ -87,7 +86,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 +105,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.
@@ -1469,13 +244,8 @@ struct bpf_insn {
 #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);
-#else
-extern int bpf_validate();
-extern u_int bpf_filter();
-#endif
+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);
 
 /*
  * Number of scratch memory words (for BPF_LD|BPF_MEM and BPF_ST).
similarity index 69%
rename from Win32/Src/ffs.c
rename to pcap/can_socketcan.h
index 099ff8e..332d9ff 100644 (file)
@@ -1,7 +1,12 @@
 /*-
- * Copyright (c) 1990, 1993
+ * 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:
@@ -12,8 +17,8 @@
  *    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.
+ *      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.
  * SUCH DAMAGE.
  */
 
-#if defined(LIBC_SCCS) && !defined(lint)
-static char sccsid[] = "@(#)ffs.c      8.1 (Berkeley) 6/4/93";
-#endif /* LIBC_SCCS and not lint */
+#ifndef lib_pcap_can_socketcan_h
+#define lib_pcap_can_socketcan_h
 
-#include <string.h>
+#include <pcap/pcap-inttypes.h>
 
 /*
- * ffs -- vax ffs instruction
+ * SocketCAN header, as per Documentation/networking/can.txt in the
+ * Linux source.
  */
-int
-ffs(mask)
-       register int mask;
-{
-       register int bit;
+typedef struct {
+       uint32_t can_id;
+       uint8_t payload_length;
+       uint8_t pad;
+       uint8_t reserved1;
+       uint8_t reserved2;
+} pcap_can_socketcan_hdr;
 
-       if (mask == 0)
-               return(0);
-       for (bit = 1; !(mask & 1); bit++)
-               mask >>= 1;
-       return(bit);
-}
+#endif
diff --git a/pcap/compiler-tests.h b/pcap/compiler-tests.h
new file mode 100644 (file)
index 0000000..ea5962c
--- /dev/null
@@ -0,0 +1,163 @@
+/* -*- 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_compiler_tests_h
+#define lib_pcap_compiler_tests_h
+
+/*
+ * 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
+
+/*
+ * Note that the C90 spec's "6.8.1 Conditional inclusion" and the
+ * C99 spec's and C11 spec's "6.10.1 Conditional inclusion" say:
+ *
+ *    Prior to evaluation, macro invocations in the list of preprocessing
+ *    tokens that will become the controlling constant expression are
+ *    replaced (except for those macro names modified by the defined unary
+ *    operator), just as in normal text.  If the token "defined" is
+ *    generated as a result of this replacement process or use of the
+ *    "defined" unary operator does not match one of the two specified
+ *    forms prior to macro replacement, the behavior is undefined.
+ *
+ * so you shouldn't use defined() in a #define that's used in #if or
+ * #elif.  Some versions of Clang, for example, will warn about this.
+ *
+ * Instead, we check whether the pre-defined macros for particular
+ * compilers are defined and, if not, define the "is this version XXX
+ * or a later version of this compiler" macros as 0.
+ */
+
+/*
+ * 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.
+ */
+
+#if ! defined(__GNUC__)
+#define PCAP_IS_AT_LEAST_GNUC_VERSION(major, minor) 0
+#else
+#define PCAP_IS_AT_LEAST_GNUC_VERSION(major, minor) \
+       (__GNUC__ > (major) || \
+        (__GNUC__ == (major) && __GNUC_MINOR__ >= (minor)))
+#endif
+
+/*
+ * Check whether this is Clang major.minor or a later release.
+ */
+
+#if !defined(__clang__)
+#define PCAP_IS_AT_LEAST_CLANG_VERSION(major, minor) 0
+#else
+#define PCAP_IS_AT_LEAST_CLANG_VERSION(major, minor) \
+       (__clang_major__ > (major) || \
+        (__clang_major__ == (major) && __clang_minor__ >= (minor)))
+#endif
+
+/*
+ * Check whether this is Sun C/SunPro C/Oracle Studio major.minor
+ * or a later release.
+ *
+ * The version number in __SUNPRO_C is encoded in hex BCD, with the
+ * uppermost hex digit being the major version number, the next
+ * one or two hex digits being the minor version number, and
+ * the last digit being the patch version.
+ *
+ * It represents the *compiler* version, not the product version;
+ * see
+ *
+ *    https://sourceforge.net/p/predef/wiki/Compilers/
+ *
+ * for a partial mapping, which we assume continues for later
+ * 12.x product releases.
+ */
+
+#if ! defined(__SUNPRO_C)
+#define PCAP_IS_AT_LEAST_SUNC_VERSION(major,minor) 0
+#else
+#define PCAP_SUNPRO_VERSION_TO_BCD(major, minor) \
+       (((minor) >= 10) ? \
+           (((major) << 12) | (((minor)/10) << 8) | (((minor)%10) << 4)) : \
+           (((major) << 8) | ((minor) << 4)))
+#define PCAP_IS_AT_LEAST_SUNC_VERSION(major,minor) \
+       (__SUNPRO_C >= PCAP_SUNPRO_VERSION_TO_BCD((major), (minor)))
+#endif
+
+/*
+ * Check whether this is IBM XL C major.minor or a later release.
+ *
+ * The version number in __xlC__ has the major version in the
+ * upper 8 bits and the minor version in the lower 8 bits.
+ */
+
+#if ! defined(__xlC__)
+#define PCAP_IS_AT_LEAST_XL_C_VERSION(major,minor) 0
+#else
+#define PCAP_IS_AT_LEAST_XL_C_VERSION(major, minor) \
+       (__xlC__ >= (((major) << 8) | (minor)))
+#endif
+
+/*
+ * Check whether this is HP aC++/HP C major.minor or a later release.
+ *
+ * The version number in __HP_aCC is encoded in zero-padded decimal BCD,
+ * with the "A." stripped off, the uppermost two decimal digits being
+ * the major version number, the next two decimal digits being the minor
+ * version number, and the last two decimal digits being the patch version.
+ * (Strip off the A., remove the . between the major and minor version
+ * number, and add two digits of patch.)
+ */
+
+#if ! defined(__HP_aCC)
+#define PCAP_IS_AT_LEAST_HP_C_VERSION(major,minor) 0
+#else
+#define PCAP_IS_AT_LEAST_HP_C_VERSION(major,minor) \
+       (__HP_aCC >= ((major)*10000 + (minor)*100))
+#endif
+
+#endif /* lib_pcap_compiler_tests_h */
diff --git a/pcap/dlt.h b/pcap/dlt.h
new file mode 100644 (file)
index 0000000..8dacf02
--- /dev/null
@@ -0,0 +1,1434 @@
+/*-
+ * 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. 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
+ *
+ *     https://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
+ * macOS; 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.
+ */
+
+/*
+ * 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 macOS - 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.
+ *
+ * We keep the name DLT_IEEE802_15_4 as an alias for backwards
+ * compatibility, but, again, this should *only* be used for 802.15.4
+ * frames that include the FCS.
+ */
+#define DLT_IEEE802_15_4_WITHFCS       195
+#define DLT_IEEE802_15_4               DLT_IEEE802_15_4_WITHFCS
+
+/*
+ * 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 a 2-byte header, followed by
+ * the I2C slave address, followed by the netFn and LUN, etc..
+ * Requested by Chanthy Toeung <chanthy.toeung@ca.kontron.com>.
+ *
+ * XXX - this used to be called DLT_IPMB, back when we got the
+ * impression from the email thread requesting it that the packet
+ * had no extra 2-byte header.  We've renamed it; if anybody used
+ * DLT_IPMB and assumed no 2-byte header, this will cause the compile
+ * to fail, at which point we'll have to figure out what to do about
+ * the two header types using the same DLT_/LINKTYPE_ value.  If that
+ * doesn't happen, we'll assume nobody used it and that the redefinition
+ * is safe.
+ */
+#define DLT_IPMB_KONTRON       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
+
+/*
+ * PPP, 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     /* Don't confuse with DLT_PPP_WITH_DIRECTION */
+
+/*
+ * Cisco HDLC, 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_C_HDLC_WITH_DIR    205
+
+/*
+ * Frame Relay, with a one-byte direction pseudo-header prepended - zero
+ * means "received by this host" (DCE -> DTE), non-zero (any non-zero
+ * value) means "sent by this host" (DTE -> DCE) - as per Will Barker
+ * <w.barker@zen.co.uk>.
+ */
+#define DLT_FRELAY_WITH_DIR    206
+
+/*
+ * LAPB, with a one-byte direction pseudo-header prepended - zero means
+ * "received by this host" (DCE -> DTE), non-zero (any non-zero value)
+ * means "sent by this host" (DTE -> DCE)- as per Will Barker
+ * <w.barker@zen.co.uk>.
+ */
+#define DLT_LAPB_WITH_DIR      207
+
+/*
+ * 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 {
+ *     uint8_t   dli_version;
+ *     uint8_t   dli_family;
+ *     uint16_t  dli_htype;
+ *     uint32_t  dli_pktlen;
+ *     uint32_t  dli_ifindex;
+ *     uint32_t  dli_grifindex;
+ *     uint32_t  dli_zsrc;
+ *     uint32_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 macOS*; 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 macOS, you can't do so with
+ * this version of libpcap, just as you can't with Apple's libpcap -
+ * on macOS, 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
+
+/*
+ * USB packets, beginning with a Darwin (macOS, etc.) header.
+ */
+#define DLT_USB_DARWIN 266
+
+/*
+ * OpenBSD DLT_OPENFLOW.
+ */
+#define DLT_OPENFLOW   267
+
+/*
+ * SDLC frames containing SNA PDUs.
+ */
+#define DLT_SDLC       268
+
+/*
+ * per "Selvig, Bjorn" <b.selvig@ti.com> used for
+ * TI protocol sniffer.
+ */
+#define DLT_TI_LLN_SNIFFER     269
+
+/*
+ * per: Erik de Jong <erikdejong at gmail.com> for
+ *   https://github.com/eriknl/LoRaTap/releases/tag/v0.1
+ */
+#define DLT_LORATAP             270
+
+/*
+ * per: Stefanha at gmail.com for
+ *   http://lists.sandelman.ca/pipermail/tcpdump-workers/2017-May/000772.html
+ * and: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/tree/include/uapi/linux/vsockmon.h
+ * for: http://qemu-project.org/Features/VirtioVsock
+ */
+#define DLT_VSOCK               271
+
+/*
+ * Nordic Semiconductor Bluetooth LE sniffer.
+ */
+#define DLT_NORDIC_BLE         272
+
+/*
+ * Excentis DOCSIS 3.1 RF sniffer (XRA-31)
+ *   per: bruno.verstuyft at excentis.com
+ *        http://www.xra31.com/xra-header
+ */
+#define DLT_DOCSIS31_XRA31     273
+
+/*
+ * mPackets, as specified by IEEE 802.3br Figure 99-4, starting
+ * with the preamble and always ending with a CRC field.
+ */
+#define DLT_ETHERNET_MPACKET   274
+
+/*
+ * DisplayPort AUX channel monitoring data as specified by VESA
+ * DisplayPort(DP) Standard preceeded by a pseudo-header.
+ *    per dirk.eibach at gdsys.cc
+ */
+#define DLT_DISPLAYPORT_AUX    275
+
+/*
+ * Linux cooked sockets v2.
+ */
+#define DLT_LINUX_SLL2 276
+
+/*
+ * 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       276     /* 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/pcap/funcattrs.h b/pcap/funcattrs.h
new file mode 100644 (file)
index 0000000..e64da93
--- /dev/null
@@ -0,0 +1,263 @@
+/* -*- 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_funcattrs_h
+#define lib_pcap_funcattrs_h
+
+#include <pcap/compiler-tests.h>
+
+/*
+ * Attributes to apply to functions and their arguments, using various
+ * compiler-specific extensions.
+ */
+
+/*
+ * 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.
+ */
+
+#if defined(_WIN32)
+  /*
+   * For Windows:
+   *
+   *    when building libpcap:
+   *
+   *       if we're building it as a DLL, we have to declare API
+   *       functions with __declspec(dllexport);
+   *
+   *       if we're building it as a static library, we don't want
+   *       to do so.
+   *
+   *    when using libpcap:
+   *
+   *       if we're using the DLL, calls to its functions are a
+   *       little more efficient if they're declared with
+   *       __declspec(dllimport);
+   *
+   *       if we're not using the dll, we don't want to declare
+   *       them that way.
+   *
+   * So:
+   *
+   *    if pcap_EXPORTS is defined, we define PCAP_API_DEF as
+   *     __declspec(dllexport);
+   *
+   *    if PCAP_DLL is defined, we define PCAP_API_DEF as
+   *    __declspec(dllimport);
+   *
+   *    otherwise, we define PCAP_API_DEF as nothing.
+   */
+  #if defined(pcap_EXPORTS)
+    /*
+     * We're compiling libpcap as a DLL, so we should export functions
+     * in our API.
+     */
+    #define PCAP_API_DEF       __declspec(dllexport)
+  #elif defined(PCAP_DLL)
+    /*
+     * We're using libpcap as a DLL, so the calls will be a little more
+     * efficient if we explicitly import the functions.
+     */
+    #define PCAP_API_DEF       __declspec(dllimport)
+  #else
+    /*
+     * Either we're building libpcap as a static library, or we're using
+     * it as a static library, or we don't know for certain that we're
+     * using it as a dynamic library, so neither import nor export the
+     * functions explicitly.
+     */
+    #define PCAP_API_DEF
+  #endif
+#elif defined(MSDOS)
+  /* XXX - does this need special treatment? */
+  #define PCAP_API_DEF
+#else /* UN*X */
+  #ifdef pcap_EXPORTS
+    /*
+     * We're compiling libpcap as a (dynamic) shared library, 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 PCAP_IS_AT_LEAST_GNUC_VERSION(3,4) \
+        || PCAP_IS_AT_LEAST_XL_C_VERSION(12,0)
+      /*
+       * GCC 3.4 or later, or some compiler asserting compatibility with
+       * GCC 3.4 or later, or XL C 13.0 or later, so we have
+       * __attribute__((visibility()).
+       */
+      #define PCAP_API_DEF     __attribute__((visibility("default")))
+    #elif PCAP_IS_AT_LEAST_SUNC_VERSION(5,5)
+      /*
+       * 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
+
+/*
+ * PCAP_NORETURN, before a function declaration, means "this function
+ * never returns".  (It must go before the function declaration, e.g.
+ * "extern PCAP_NORETURN func(...)" rather than after the function
+ * declaration, as the MSVC version has to go before the declaration.)
+ *
+ * PCAP_NORETURN_DEF, before a function *definition*, means "this
+ * function never returns"; it would be used only for static functions
+ * that are defined before any use, and thus have no declaration.
+ * (MSVC doesn't support that; I guess the "decl" in "__declspec"
+ * means "declaration", and __declspec doesn't work with definitions.)
+ */
+#if __has_attribute(noreturn) \
+    || PCAP_IS_AT_LEAST_GNUC_VERSION(2,5) \
+    || PCAP_IS_AT_LEAST_SUNC_VERSION(5,9) \
+    || PCAP_IS_AT_LEAST_XL_C_VERSION(10,1) \
+    || PCAP_IS_AT_LEAST_HP_C_VERSION(6,10)
+  /*
+   * Compiler with support for __attribute((noreturn)), or GCC 2.5 or
+   * later, or some compiler asserting compatibility with GCC 2.5 or
+   * later, or Solaris Studio 12 (Sun C 5.9) or later, or IBM XL C 10.1
+   * or later (do any earlier versions of XL C support this?), or HP aCC
+   * A.06.10 or later.
+   */
+  #define PCAP_NORETURN __attribute((noreturn))
+  #define PCAP_NORETURN_DEF __attribute((noreturn))
+#elif defined(_MSC_VER)
+  /*
+   * MSVC.
+   */
+  #define PCAP_NORETURN __declspec(noreturn)
+  #define PCAP_NORETURN_DEF
+#else
+  #define PCAP_NORETURN
+  #define PCAP_NORETURN_DEF
+#endif
+
+/*
+ * PCAP_PRINTFLIKE(x,y), after a function declaration, means "this function
+ * does printf-style formatting, with the xth argument being the format
+ * string and the yth argument being the first argument for the format
+ * string".
+ */
+#if __has_attribute(__format__) \
+    || PCAP_IS_AT_LEAST_GNUC_VERSION(2,3) \
+    || PCAP_IS_AT_LEAST_XL_C_VERSION(10,1) \
+    || PCAP_IS_AT_LEAST_HP_C_VERSION(6,10)
+  /*
+   * Compiler with support for it, or GCC 2.3 or later, or some compiler
+   * asserting compatibility with GCC 2.3 or 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
+
+/*
+ * PCAP_DEPRECATED(func, msg), after a function declaration, marks the
+ * function as deprecated.
+ *
+ * The first argument is the name of the function; the second argument is
+ * a string giving the warning message to use if the compiler supports that.
+ *
+ * (Thank you, Microsoft, for requiring the function name.)
+ */
+#if __has_attribute(deprecated) \
+    || PCAP_IS_AT_LEAST_GNUC_VERSION(4,5) \
+    || PCAP_IS_AT_LEAST_SUNC_VERSION(5,13)
+  /*
+   * Compiler that supports __has_attribute and __attribute__((deprecated)),
+   * or GCC 4.5 or later, or Sun/Oracle C 12.4 (Sun C 5.13) or later.
+   *
+   * Those support __attribute__((deprecated(msg))) (we assume, perhaps
+   * incorrectly, that anything that supports __has_attribute() is
+   * recent enough to support __attribute__((deprecated(msg)))).
+   */
+  #define PCAP_DEPRECATED(func, msg)   __attribute__((deprecated(msg)))
+#elif PCAP_IS_AT_LEAST_GNUC_VERSION(3,1)
+  /*
+   * GCC 3.1 through 4.4.
+   *
+   * Those support __attribute__((deprecated)) but not
+   * __attribute__((deprecated(msg))).
+   */
+  #define PCAP_DEPRECATED(func, msg)   __attribute__((deprecated))
+#elif (defined(_MSC_VER) && (_MSC_VER >= 1500)) && !defined(BUILDING_PCAP)
+  /*
+   * MSVC from Visual Studio 2008 or later, and we're not building
+   * libpcap itself.
+   *
+   * If we *are* building libpcap, we don't want this, as it'll warn
+   * us even if we *define* the function.
+   */
+  #define PCAP_DEPRECATED(func, msg)   __pragma(deprecated(func))
+#else
+  #define PCAP_DEPRECATED(func, msg)
+#endif
+
+/*
+ * For flagging arguments as format strings in MSVC.
+ */
+#ifdef _MSC_VER
+ #include <sal.h>
+ #if _MSC_VER > 1400
+  #define PCAP_FORMAT_STRING(p) _Printf_format_string_ p
+ #else
+  #define PCAP_FORMAT_STRING(p) __format_string p
+ #endif
+#else
+ #define PCAP_FORMAT_STRING(p) p
+#endif
+
+#endif /* lib_pcap_funcattrs_h */
index d3a3432..c66846d 100644 (file)
@@ -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,19 @@ 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 *);
-#ifdef INET6
-struct addrinfo *pcap_nametoaddrinfo(const char *);
-#endif
-bpf_u_int32 pcap_nametonetaddr(const char *);
+PCAP_API bpf_u_int32 **pcap_nametoaddr(const char *);
+PCAP_API struct addrinfo *pcap_nametoaddrinfo(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 +76,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
index 388dd0c..f7c85b5 100644 (file)
  * DAMAGE.
  */
 
-#ifndef _PCAP_NFLOG_H__
-#define _PCAP_NFLOG_H__
+#ifndef lib_pcap_nflog_h
+#define lib_pcap_nflog_h
+
+#include <pcap/pcap-inttypes.h>
 
 /*
  * Structure of an NFLOG header and TLV parts, as described at
- * http://www.tcpdump.org/linktypes/LINKTYPE_NFLOG.html
+ * https://www.tcpdump.org/linktypes/LINKTYPE_NFLOG.html
  *
  * The NFLOG header is big-endian.
  *
  * data, etc.).
  */
 typedef struct nflog_hdr {
-       u_int8_t        nflog_family;           /* address family */
-       u_int8_t        nflog_version;          /* version */
-       u_int16_t       nflog_rid;              /* resource ID */
+       uint8_t         nflog_family;   /* address family */
+       uint8_t         nflog_version;  /* version */
+       uint16_t        nflog_rid;      /* resource ID */
 } nflog_hdr_t;
 
 typedef struct nflog_tlv {
-       u_int16_t       tlv_length;             /* tlv length */
-       u_int16_t       tlv_type;               /* tlv type */
+       uint16_t        tlv_length;     /* tlv length */
+       uint16_t        tlv_type;       /* tlv type */
        /* value follows this */
 } nflog_tlv_t;
 
 typedef struct nflog_packet_hdr {
-       u_int16_t       hw_protocol;    /* hw protocol */
-       u_int8_t        hook;           /* netfilter hook */
-       u_int8_t        pad;            /* padding to 32 bits */
+       uint16_t        hw_protocol;    /* hw protocol */
+       uint8_t         hook;           /* netfilter hook */
+       uint8_t         pad;            /* padding to 32 bits */
 } nflog_packet_hdr_t;
 
 typedef struct nflog_hwaddr {
-       u_int16_t       hw_addrlen;     /* address length */
-       u_int16_t       pad;            /* padding to 32-bit boundary */
-       u_int8_t        hw_addr[8];     /* address, up to 8 bytes */
+       uint16_t        hw_addrlen;     /* address length */
+       uint16_t        pad;            /* padding to 32-bit boundary */
+       uint8_t         hw_addr[8];     /* address, up to 8 bytes */
 } nflog_hwaddr_t;
 
 typedef struct nflog_timestamp {
-       u_int64_t       sec;
-       u_int64_t       usec;
+       uint64_t        sec;
+       uint64_t        usec;
 } nflog_timestamp_t;
 
 /*
diff --git a/pcap/pcap-inttypes.h b/pcap/pcap-inttypes.h
new file mode 100644 (file)
index 0000000..8b1eb8b
--- /dev/null
@@ -0,0 +1,128 @@
+/*
+ * Copyright (c) 2002 - 2005 NetGroup, Politecnico di Torino (Italy)
+ * Copyright (c) 2005 - 2009 CACE Technologies, Inc. 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 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_pcap_inttypes_h
+#define pcap_pcap_inttypes_h
+
+/*
+ * Get the integer types and PRi[doux]64 values from C99 <inttypes.h>
+ * defined, by hook or by crook.
+ */
+#if defined(_MSC_VER)
+  /*
+   * Compiler is MSVC.
+   */
+  #if _MSC_VER >= 1800
+    /*
+     * VS 2013 or newer; we have <inttypes.h>.
+     */
+    #include <inttypes.h>
+  #else
+    /*
+     * Earlier VS; we have to define this stuff ourselves.
+     */
+    typedef unsigned char uint8_t;
+    typedef signed char int8_t;
+    typedef unsigned short uint16_t;
+    typedef signed short int16_t;
+    typedef unsigned int uint32_t;
+    typedef signed int int32_t;
+    #ifdef _MSC_EXTENSIONS
+      typedef unsigned _int64 uint64_t;
+      typedef _int64 int64_t;
+    #else /* _MSC_EXTENSIONS */
+      typedef unsigned long long uint64_t;
+      typedef long long int64_t;
+    #endif
+  #endif
+
+  /*
+   * 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
+
+  /*
+   * MSVC's support library doesn't support %zu to print a size_t until
+   * Visual Studio 2017, but supports %Iu earlier, so use that.
+   */
+  #define PRIsize      "Iu"
+#elif defined(__MINGW32__) || !defined(_WIN32)
+  /*
+   * Compiler is MinGW or target is UN*X or MS-DOS.  Just use
+   * <inttypes.h>.
+   */
+  #include <inttypes.h>
+
+  /*
+   * Assume the support library supports %zu; it's required by C99.
+   */
+  #define PRIsize      "zu"
+#endif
+
+#endif /* pcap/pcap-inttypes.h */
index 7e1f2cd..90614dd 100644 (file)
  * SUCH DAMAGE.
  */
 
+/*
+ * Remote packet capture mechanisms and extensions from WinPcap:
+ *
+ * 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 lib_pcap_pcap_h
 #define lib_pcap_pcap_h
 
-#if defined(WIN32)
-  #include <pcap-stdinc.h>
+#include <pcap/funcattrs.h>
+
+#include <pcap/pcap-inttypes.h>
+
+#if defined(_WIN32)
+  #include <winsock2.h>                /* u_int, u_char etc. */
+  #include <io.h>              /* _get_osfhandle() */
 #elif defined(MSDOS)
-  #include <sys/types.h>
-  #include <sys/socket.h>  /* u_int, u_char etc. */
+  #include <sys/types.h>       /* u_int, u_char etc. */
+  #include <sys/socket.h>
 #else /* UN*X */
-  #include <sys/types.h>
+  #include <sys/types.h>       /* u_int, u_char etc. */
   #include <sys/time.h>
-#endif /* WIN32/MSDOS/UN*X */
+#endif /* _WIN32/MSDOS/UN*X */
+
+#include <pcap/socket.h>       /* for SOCKET, as the active-mode rpcap APIs use it */
 
 #ifndef PCAP_DONT_INCLUDE_PCAP_BPF_H
 #include <pcap/bpf.h>
@@ -170,9 +211,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 */
+#ifdef _WIN32
+       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 */
 };
 
 #ifdef MSDOS
@@ -219,9 +262,15 @@ struct pcap_if {
        bpf_u_int32 flags;      /* PCAP_IF_ interface flags */
 };
 
-#define PCAP_IF_LOOPBACK       0x00000001      /* interface is loopback */
-#define PCAP_IF_UP             0x00000002      /* interface is up */
-#define PCAP_IF_RUNNING                0x00000004      /* interface is running */
+#define PCAP_IF_LOOPBACK                               0x00000001      /* interface is loopback */
+#define PCAP_IF_UP                                     0x00000002      /* interface is up */
+#define PCAP_IF_RUNNING                                        0x00000004      /* interface is running */
+#define PCAP_IF_WIRELESS                               0x00000008      /* interface is wireless (*NOT* necessarily Wi-Fi!) */
+#define PCAP_IF_CONNECTION_STATUS                      0x00000030      /* connection status: */
+#define PCAP_IF_CONNECTION_STATUS_UNKNOWN              0x00000000      /* unknown */
+#define PCAP_IF_CONNECTION_STATUS_CONNECTED            0x00000010      /* connected */
+#define PCAP_IF_CONNECTION_STATUS_DISCONNECTED         0x00000020      /* disconnected */
+#define PCAP_IF_CONNECTION_STATUS_NOT_APPLICABLE       0x00000030      /* not applicable */
 
 /*
  * Representation of an interface address.
@@ -271,27 +320,38 @@ 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);
+/*
+ * We're deprecating pcap_lookupdev() for various reasons (not
+ * thread-safe, can behave weirdly with WinPcap).  Callers
+ * should use pcap_findalldevs() and use the first device.
+ */
+PCAP_API char  *pcap_lookupdev(char *)
+PCAP_DEPRECATED(pcap_lookupdev, "use 'pcap_findalldevs' and use the first device");
+
+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);
+
+#ifdef __linux__
+PCAP_API int   pcap_set_protocol_linux(pcap_t *, int);
+#endif
 
 /*
  * Time stamp types.
@@ -346,136 +406,568 @@ 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 must not define them as macros.
+   *
+   * If we're not building libpcap, given that the version of the C runtime
+   * with which libpcap was built might be different from the version
+   * of the C runtime with which an application using libpcap was built,
+   * and that a FILE structure may differ between the two versions of the
+   * C runtime, calls to _fileno() must use the version of _fileno() in
+   * the C runtime used to open the FILE *, not the version in the C
+   * runtime with which libpcap was built.  (Maybe once the Universal CRT
+   * rules the world, this will cease to be a problem.)
+   */
+  #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 const char *pcap_datalink_val_to_description_or_dlt(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 *);
+PCAP_API int   pcap_bufsize(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 *);
 
-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 *);
+#ifdef _WIN32
+  PCAP_API int pcap_wsockinit(void);
+#endif
 
-int    pcap_findalldevs(pcap_if_t **, char *);
-void   pcap_freealldevs(pcap_if_t *);
+PCAP_API pcap_dumper_t *pcap_dump_open(pcap_t *, const char *);
+#ifdef _WIN32
+  PCAP_API pcap_dumper_t *pcap_dump_hopen(pcap_t *, intptr_t);
+  /*
+   * If we're building libpcap, this is an internal routine in sf-pcap.c, so
+   * we must not define it as a macro.
+   *
+   * If we're not building libpcap, given that the version of the C runtime
+   * with which libpcap was built might be different from the version
+   * of the C runtime with which an application using libpcap was built,
+   * and that a FILE structure may differ between the two versions of the
+   * C runtime, calls to _fileno() must use the version of _fileno() in
+   * the C runtime used to open the FILE *, not the version in the C
+   * runtime with which libpcap was built.  (Maybe once the Universal CRT
+   * rules the world, this will cease to be a problem.)
+   */
+  #ifndef BUILDING_PCAP
+    #define pcap_dump_fopen(p,f) \
+       pcap_dump_hopen(p, _get_osfhandle(_fileno(f)))
+  #endif
+#else /*_WIN32*/
+  PCAP_API pcap_dumper_t *pcap_dump_fopen(pcap_t *, FILE *fp);
+#endif /*_WIN32*/
+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 int64_t       pcap_dump_ftell64(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 *);
+
+PCAP_API int   pcap_findalldevs(pcap_if_t **, char *);
+PCAP_API void  pcap_freealldevs(pcap_if_t *);
 
-const char *pcap_lib_version(void);
+/*
+ * We return a pointer to the version string, 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).
+ *
+ * On Windows, the string is constructed at run time.
+ */
+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)
+
+  /*
+   * 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 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);
+
+  PCAP_API void pcap_sendqueue_destroy(pcap_send_queue* queue);
+
+  PCAP_API int pcap_sendqueue_queue(pcap_send_queue* queue, const struct pcap_pkthdr *pkt_header, const u_char *pkt_data);
+
+  PCAP_API u_int pcap_sendqueue_transmit(pcap_t *p, pcap_send_queue* queue, int sync);
 
-#if defined(WIN32)
+  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
+   */
+
+  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
+   */
+
+  PCAP_API int pcap_get_selectable_fd(pcap_t *);
+  PCAP_API struct timeval *pcap_get_required_select_timeout(pcap_t *);
+
+#endif /* _WIN32/MSDOS/UN*X */
 
 /*
- * Win32 definitions
+ * Remote capture definitions.
+ *
+ * These routines are only present if libpcap has been configured to
+ * include remote capture support.
  */
 
-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);
+/*
+ * 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
 
-#ifdef WPCAP
-/* Include file with the wpcap-specific extensions */
-#include <Win32-Extensions.h>
-#endif /* WPCAP */
+/*
+ * The type of input source, passed to pcap_open().
+ */
+#define PCAP_SRC_FILE          2       /* local savefile */
+#define PCAP_SRC_IFLOCAL       3       /* local network interface */
+#define PCAP_SRC_IFREMOTE      4       /* interface on a remote host, using RPCAP */
 
-#define MODE_CAPT 0
-#define MODE_STAT 1
-#define MODE_MON 2
+/*
+ * The formats allowed by 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]
+ */
 
-#elif defined(MSDOS)
+/*
+ * URL schemes for capture source.
+ */
+/*
+ * This string indicates that the user wants to open a capture from a
+ * local file.
+ */
+#define PCAP_SRC_FILE_STRING "file://"
+/*
+ * 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://"
 
 /*
- * MS-DOS definitions
+ * Flags to pass to pcap_open().
  */
 
-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);
+/*
+ * Specifies whether promiscuous mode is to be used.
+ */
+#define PCAP_OPENFLAG_PROMISCUOUS              0x00000001
 
-#else /* UN*X */
+/*
+ * Specifies, for an RPCAP capture, whether 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               0x00000002
+
+/*
+ * Specifies wheether 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.
+ *
+ * Has no effect on local interfaces or savefiles.
+ */
+#define PCAP_OPENFLAG_NOCAPTURE_RPCAP          0x00000004
+
+/*
+ * Specifies whether 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
+ * such as bridges that should ignore the traffic they just sent.
+ *
+ * Supported only on Windows.
+ */
+#define PCAP_OPENFLAG_NOCAPTURE_LOCAL          0x00000008
+
+/*
+ * 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 (such as, for example,
+ * a bridge) that need the best responsiveness.
+ *
+ * The equivalent with pcap_create()/pcap_activate() is "immediate mode".
+ */
+#define PCAP_OPENFLAG_MAX_RESPONSIVENESS       0x00000010
+
+/*
+ * Remote authentication methods.
+ * These are used in the 'type' member of the pcap_rmtauth structure.
+ */
+
+/*
+ * NULL authentication.
+ *
+ * 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
+/*
+ * 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.
+ *
+ * *******NOTE********: the username and password are sent over the network
+ * to the capture server *IN CLEAR TEXT*.  Don't use this on a network
+ * that you don't completely control!  (And be *really* careful in your
+ * definition of "completely"!)
+ */
+#define RPCAP_RMTAUTH_PWD 1
+
+/*
+ * 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;
+};
+
+/*
+ * This routine can open a savefile, a local device, or a device on
+ * a remote machine running an RPCAP server.
+ *
+ * For opening a savefile, the pcap_open_offline routines can be used,
+ * and will work just as well; code using them will work on more
+ * platforms than code using pcap_open() to open savefiles.
+ *
+ * For opening a local device, pcap_open_live() can be used; it supports
+ * most of the capabilities that pcap_open() supports, and code using it
+ * will work on more platforms than code using pcap_open().  pcap_create()
+ * and pcap_activate() can also be used; they support all capabilities
+ * that pcap_open() supports, except for the Windows-only
+ * PCAP_OPENFLAG_NOCAPTURE_LOCAL, and support additional capabilities.
+ *
+ * For opening a remote capture, pcap_open() is currently the only
+ * API available.
+ */
+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);
+
+/*
+ * This routine can scan a directory for savefiles, list local capture
+ * devices, or list capture devices on a remote machine running an RPCAP
+ * server.
+ *
+ * For scanning for savefiles, it can be used on both UN*X systems and
+ * Windows systems; for each directory entry it sees, it tries to open
+ * the file as a savefile using pcap_open_offline(), and only includes
+ * it in the list of files if the open succeeds, so it filters out
+ * files for which the user doesn't have read permission, as well as
+ * files that aren't valid savefiles readable by libpcap.
+ *
+ * For listing local capture devices, it's just a wrapper around
+ * pcap_findalldevs(); code using pcap_findalldevs() will work on more
+ * platforms than code using pcap_findalldevs_ex().
+ *
+ * For listing remote capture devices, pcap_findalldevs_ex() is currently
+ * the only API available.
+ */
+PCAP_API int   pcap_findalldevs_ex(const char *source,
+           struct pcap_rmtauth *auth, pcap_if_t **alldevs, char *errbuf);
+
+/*
+ * Sampling methods.
+ *
+ * These allow pcap_loop(), pcap_dispatch(), pcap_next(), and pcap_next_ex()
+ * to see only a sample of packets, rather than all packets.
+ *
+ * Currently, they work only on Windows local captures.
+ */
+
+/*
+ * Specifies that no sampling is to be done on the current capture.
+ *
+ * In this case, no sampling algorithms are applied to the current capture.
+ */
+#define PCAP_SAMP_NOSAMP       0
+
+/*
+ * Specifies 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
+
+/*
+ * Specifies 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
+
+/*
+ * 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 *after* 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; see above.
+        */
+       int method;
+
+       /*
+        * This value depends on the sampling method defined.
+        * For its meaning, see above.
+        */
+       int value;
+};
+
+/*
+ * New functions.
+ */
+PCAP_API struct pcap_samp *pcap_setsampling(pcap_t *p);
 
 /*
- * UN*X definitions
+ * RPCAP active mode.
  */
 
-int    pcap_get_selectable_fd(pcap_t *);
+/* Maximum length of an host name (needed for the RPCAP active mode) */
+#define RPCAP_HOSTLIST_SIZE 1024
 
-#endif /* WIN32/MSDOS/UN*X */
+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(void);
 
 #ifdef __cplusplus
 }
index 38da29f..392faae 100644 (file)
@@ -74,6 +74,8 @@
 #ifndef lib_pcap_sll_h
 #define lib_pcap_sll_h
 
+#include <pcap/pcap-inttypes.h>
+
 /*
  * A DLT_LINUX_SLL fake link-layer header.
  */
 #define SLL_ADDRLEN    8               /* length of address field */
 
 struct sll_header {
-       u_int16_t sll_pkttype;          /* packet type */
-       u_int16_t sll_hatype;           /* link-layer address type */
-       u_int16_t sll_halen;            /* link-layer address length */
-       u_int8_t sll_addr[SLL_ADDRLEN]; /* link-layer address */
-       u_int16_t sll_protocol;         /* protocol */
+       uint16_t sll_pkttype;           /* packet type */
+       uint16_t sll_hatype;            /* link-layer address type */
+       uint16_t sll_halen;             /* link-layer address length */
+       uint8_t  sll_addr[SLL_ADDRLEN]; /* link-layer address */
+       uint16_t sll_protocol;          /* protocol */
+};
+
+/*
+ * A DLT_LINUX_SLL2 fake link-layer header.
+ */
+#define SLL2_HDR_LEN   20              /* total header length */
+
+struct sll2_header {
+       uint16_t sll2_protocol;                 /* protocol */
+       uint16_t sll2_reserved_mbz;             /* reserved - must be zero */
+       uint32_t sll2_if_index;                 /* 1-based interface index */
+       uint16_t sll2_hatype;                   /* link-layer address type */
+       uint8_t  sll2_pkttype;                  /* packet type */
+       uint8_t  sll2_halen;                    /* link-layer address length */
+       uint8_t  sll2_addr[SLL_ADDRLEN];        /* link-layer address */
 };
 
 /*
- * The LINUX_SLL_ values for "sll_pkttype"; these correspond to the
- * PACKET_ values on Linux, but are defined here so that they're
- * available even on systems other than Linux, and so that they
- * don't change even if the PACKET_ values change.
+ * The LINUX_SLL_ values for "sll_pkttype" and LINUX_SLL2_ values for
+ * "sll2_pkttype"; these correspond to the PACKET_ values on Linux,
+ * which are defined by a header under include/uapi in the current
+ * kernel source, and are thus not going to change on Linux.  We
+ * define them here so that they're available even on systems other
+ * than Linux.
  */
 #define LINUX_SLL_HOST         0
 #define LINUX_SLL_BROADCAST    1
@@ -101,10 +120,11 @@ struct sll_header {
 #define LINUX_SLL_OUTGOING     4
 
 /*
- * The LINUX_SLL_ values for "sll_protocol"; these correspond to the
- * ETH_P_ values on Linux, but are defined here so that they're
- * available even on systems other than Linux.  We assume, for now,
- * that the ETH_P_ values won't change in Linux; if they do, then:
+ * The LINUX_SLL_ values for "sll_protocol" and LINUX_SLL2_ values for
+ * "sll2_protocol"; these correspond to the ETH_P_ values on Linux, but
+ * are defined here so that they're available even on systems other than
+ * Linux.  We assume, for now, that the ETH_P_ values won't change in
+ * Linux; if they do, then:
  *
  *     if we don't translate them in "pcap-linux.c", capture files
  *     won't necessarily be readable if captured on a system that
@@ -123,5 +143,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/pcap/socket.h b/pcap/socket.h
new file mode 100644 (file)
index 0000000..6f27cba
--- /dev/null
@@ -0,0 +1,93 @@
+/* -*- 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_socket_h
+#define lib_pcap_socket_h
+
+/*
+ * Some minor differences between sockets on various platforms.
+ * We include whatever sockets are needed for Internet-protocol
+ * socket access on UN*X and Windows.
+ */
+#ifdef _WIN32
+  /* Need windef.h for defines used in winsock2.h under MingW32 */
+  #ifdef __MINGW32__
+    #include <windef.h>
+  #endif
+  #include <winsock2.h>
+  #include <ws2tcpip.h>
+
+  /*
+   * Winsock doesn't have this UN*X type; it's used in the UN*X
+   * sockets API.
+   *
+   * XXX - do we need to worry about UN*Xes so old that *they*
+   * don't have it, either?
+   */
+  typedef int socklen_t;
+
+  /*
+   * Winsock doesn't have this POSIX type; it's used for the
+   * tv_usec value of struct timeval.
+   */
+  typedef long suseconds_t;
+#else /* _WIN32 */
+  #include <sys/types.h>
+  #include <sys/socket.h>
+  #include <netdb.h>           /* for struct addrinfo/getaddrinfo() */
+  #include <netinet/in.h>      /* for sockaddr_in, in BSD at least */
+  #include <arpa/inet.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 /* _WIN32 */
+
+#endif /* lib_pcap_socket_h */
index 52cb5a3..e485ec8 100644 (file)
@@ -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
  * 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
+
+#include <pcap/pcap-inttypes.h>
+
+/*
  * possible transfer mode
  */
 #define URB_TRANSFER_IN   0x80
  * Appears at the front of each Control S-type packet in DLT_USB captures.
  */
 typedef struct _usb_setup {
-       u_int8_t bmRequestType;
-       u_int8_t bRequest;
-       u_int16_t wValue;
-       u_int16_t wIndex;
-       u_int16_t wLength;
+       uint8_t bmRequestType;
+       uint8_t bRequest;
+       uint16_t wValue;
+       uint16_t wIndex;
+       uint16_t wLength;
 } pcap_usb_setup;
 
 /*
@@ -75,19 +77,19 @@ typedef struct _iso_rec {
  * Appears at the front of each packet in DLT_USB_LINUX captures.
  */
 typedef struct _usb_header {
-       u_int64_t id;
-       u_int8_t event_type;
-       u_int8_t transfer_type;
-       u_int8_t endpoint_number;
-       u_int8_t device_address;
-       u_int16_t bus_id;
+       uint64_t id;
+       uint8_t event_type;
+       uint8_t transfer_type;
+       uint8_t endpoint_number;
+       uint8_t device_address;
+       uint16_t bus_id;
        char setup_flag;/*if !=0 the urb setup header is not present*/
        char data_flag; /*if !=0 no urb data is present*/
        int64_t ts_sec;
        int32_t ts_usec;
        int32_t status;
-       u_int32_t urb_len;
-       u_int32_t data_len; /* amount of urb data really present in this event*/
+       uint32_t urb_len;
+       uint32_t data_len; /* amount of urb data really present in this event*/
        pcap_usb_setup setup;
 } pcap_usb_header;
 
@@ -100,27 +102,27 @@ typedef struct _usb_header {
  * Appears at the front of each packet in DLT_USB_LINUX_MMAPPED captures.
  */
 typedef struct _usb_header_mmapped {
-       u_int64_t id;
-       u_int8_t event_type;
-       u_int8_t transfer_type;
-       u_int8_t endpoint_number;
-       u_int8_t device_address;
-       u_int16_t bus_id;
+       uint64_t id;
+       uint8_t event_type;
+       uint8_t transfer_type;
+       uint8_t endpoint_number;
+       uint8_t device_address;
+       uint16_t bus_id;
        char setup_flag;/*if !=0 the urb setup header is not present*/
        char data_flag; /*if !=0 no urb data is present*/
        int64_t ts_sec;
        int32_t ts_usec;
        int32_t status;
-       u_int32_t urb_len;
-       u_int32_t data_len; /* amount of urb data really present in this event*/
+       uint32_t urb_len;
+       uint32_t data_len; /* amount of urb data really present in this event*/
        union {
                pcap_usb_setup setup;
                iso_rec iso;
        } s;
        int32_t interval;       /* for Interrupt and Isochronous events */
        int32_t start_frame;    /* for Isochronous events */
-       u_int32_t xfer_flags;   /* copy of URB's transfer flags */
-       u_int32_t ndesc;        /* number of isochronous descriptors */
+       uint32_t xfer_flags;    /* copy of URB's transfer flags */
+       uint32_t ndesc; /* number of isochronous descriptors */
 } pcap_usb_header_mmapped;
 
 /*
@@ -133,9 +135,9 @@ typedef struct _usb_header_mmapped {
  */
 typedef struct _usb_isodesc {
        int32_t         status;
-       u_int32_t       offset;
-       u_int32_t       len;
-       u_int8_t        pad[4];
+       uint32_t        offset;
+       uint32_t        len;
+       uint8_t pad[4];
 } usb_isodesc;
 
 #endif
index 021f612..b29dd73 100644 (file)
 #ifndef lib_pcap_vlan_h
 #define lib_pcap_vlan_h
 
+#include <pcap/pcap-inttypes.h>
+
 struct vlan_tag {
-       u_int16_t       vlan_tpid;              /* ETH_P_8021Q */
-       u_int16_t       vlan_tci;               /* VLAN TCI */
+       uint16_t        vlan_tpid;              /* ETH_P_8021Q */
+       uint16_t        vlan_tci;               /* VLAN TCI */
 };
 
 #define VLAN_TAG_LEN   4
index 61887a7..162a929 100644 (file)
@@ -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 "31 July 2016"
 .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
-.B pcap_set_tstamp_type()
+The time stamp type specified in a previous
+.B pcap_set_tstamp_type(3PCAP)
 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(3PCAP)
+or
+.B pcap_perror(3PCAP)
+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
-.B PCAP_ERROR
-if another error occurred.
-If
-.B PCAP_WARNING
-or
+The capture source device is not up.
+.TP
 .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(3PCAP)
+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)
index a395820..cc000d2 100644 (file)
@@ -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 "25 July 2018"
 .SH NAME
 pcap_breakloop \- force a pcap_dispatch() or pcap_loop() call to return
 .SH SYNOPSIS
@@ -33,12 +33,13 @@ void pcap_breakloop(pcap_t *);
 .SH DESCRIPTION
 .B pcap_breakloop()
 sets a flag that will force
-.B pcap_dispatch()
+.B pcap_dispatch(3PCAP)
 or
-.B pcap_loop()
+.B pcap_loop(3PCAP)
 to return rather than looping; they will return the number of packets
-that have been processed so far, or \-2 if no packets have been
-processed so far.
+that have been processed so far, or
+.B PCAP_ERROR_BREAK
+if no packets have been processed so far.
 .PP
 This routine is safe to use inside a signal handler on UNIX or a console
 control handler on Windows, as it merely sets a flag that is checked
@@ -60,11 +61,23 @@ packets arrive and the call completes.
 .PP
 .ft B
 Note also that, in a multi-threaded application, if one thread is
-blocked in pcap_dispatch(), pcap_loop(), pcap_next(), or pcap_next_ex(),
+blocked in pcap_dispatch(), pcap_loop(), pcap_next(3PCAP), or pcap_next_ex(3PCAP),
 a call to pcap_breakloop() in a different thread will not unblock that
-thread; you will need to use whatever mechanism the OS provides for
+thread.
+.ft R
+You will need to use whatever mechanism the OS provides for
 breaking a thread out of blocking calls in order to unblock the thread,
-such as thread cancellation in systems that support POSIX threads.
+such as thread cancellation or thread signalling in systems that support
+POSIX threads, or
+.B SetEvent()
+on the result of
+.B pcap_getevent()
+on a
+.B pcap_t
+on which the thread is blocked on Windows.  Asynchronous procedure calls
+will not work on Windows, as a thread blocked on a
+.B pcap_t
+will not be in an alertable state.
 .ft R
 .PP
 Note that
@@ -87,12 +100,16 @@ or
 .B pcap_loop()
 after it is called; at most one more packet might be processed.
 .PP
-If \-2 is returned from
+If
+.B PCAP_ERROR_BREAK
+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.
+subsequent call will return
+.B PCAP_ERROR_BREAK
+and clear the flag.
 .SH SEE ALSO
-pcap(3PCAP), pcap_loop(3PCAP), pcap_next_ex(3PCAP)
+pcap(3PCAP)
index b579804..0baac7a 100644 (file)
@@ -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 "31 July 2016"
 .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,
-.B pcap_geterr()
+Another error occurred.
+.B pcap_geterr(3PCAP)
 or
-.B pcap_perror()
+.B \%pcap_perror(3PCAP)
 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(3PCAP)
+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)
index 91eb677..e2316a4 100644 (file)
@@ -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
index 0e5276a..824f52b 100644 (file)
@@ -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 "22 August 2018"
 .SH NAME
 pcap_compile \- compile a filter expression
 .SH SYNOPSIS
@@ -52,19 +52,38 @@ captured; it is used only when checking for IPv4 broadcast addresses in
 the filter program.  If the netmask of the network on which packets are
 being captured isn't known to the program, or if packets are being
 captured on the Linux "any" pseudo-interface that can capture on more
-than one network, a value of PCAP_NETMASK_UNKNOWN can be supplied; tests
+than one network, a value of
+.B PCAP_NETMASK_UNKNOWN
+can be supplied; tests
 for IPv4 broadcast addresses will fail to compile, but all other tests in
 the filter program will be OK.
+.LP
+NOTE: in libpcap 1.8.0 and later,
+.B pcap_compile()
+can be used in multiple threads within a single process.  However, in
+earlier versions of libpcap, it is
+.I not
+safe to use
+.B pcap_compile()
+in multiple threads in a single process without some form of mutual
+exclusion allowing only one thread to call it at any given time.
 .SH RETURN VALUE
 .B pcap_compile()
-returns 0 on success and \-1 on failure.
-If \-1 is returned,
-.B pcap_geterr()
+returns 0 on success and
+.B PCAP_ERROR
+on failure. If
+.B PCAP_ERROR
+is returned,
+.B pcap_geterr(3PCAP)
 or
-.B pcap_perror()
+.B pcap_perror(3PCAP)
 may be called with
 .I p
 as an argument to fetch or display the error text.
+.SH BACKWARD COMPATIBILITY
+.PP
+The
+.B PCAP_NETMASK_UNKNOWN
+constant became available in libpcap release 1.1.0.
 .SH SEE ALSO
 pcap(3PCAP), pcap_setfilter(3PCAP), pcap_freecode(3PCAP),
-pcap_geterr(3PCAP), pcap-filter(@MAN_MISC_INFO@)
index 5c537fc..5a15007 100644 (file)
@@ -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
@@ -48,7 +48,7 @@ argument of "any" or
 can be used to capture packets from all interfaces.
 .PP
 The returned handle must be activated with
-.B pcap_activate()
+.B pcap_activate(3PCAP)
 before packets can be captured
 with it; options for the capture, such as promiscuous mode, can be set
 on the handle before activating it.
@@ -69,4 +69,4 @@ is assumed to be able to hold at least
 .B PCAP_ERRBUF_SIZE
 chars.
 .SH SEE ALSO
-pcap(3PCAP), pcap_activate(3PCAP)
+pcap(3PCAP)
index b07fc28..2620368 100644 (file)
@@ -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
@@ -37,11 +37,11 @@ specified by
 .IR p .
 .PP
 It must not be called on a pcap descriptor created by
-.B pcap_create()
+.B \%pcap_create(3PCAP)
 that has not yet been activated by
-.BR pcap_activate() .
+.BR \%pcap_activate(3PCAP) .
 .PP
-.I http://www.tcpdump.org/linktypes.html
+.I https://www.tcpdump.org/linktypes.html
 lists the values
 .B pcap_datalink()
 can return and describes the packet formats that
index c61e91e..dd4688f 100644 (file)
@@ -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 "25 July 2018"
 .SH NAME
 pcap_datalink_name_to_val \- get the link-layer header type value
 corresponding to a header type name
@@ -41,6 +41,9 @@ 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
+.B PCAP_ERROR
+if the name is not a known
+type name..
 .SH SEE ALSO
 pcap(3PCAP)
index 0b17825..f42165f 100644 (file)
 .\" 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 "12 October 2016"
 .SH NAME
-pcap_datalink_val_to_name, pcap_datalink_val_to_description \- get a
+pcap_datalink_val_to_name, pcap_datalink_val_to_description,
+pcap_datalink_val_to_description_or_dlt \- get a
 name or description for a link-layer header type value
 .SH SYNOPSIS
 .nf
@@ -30,17 +31,36 @@ name or description for a link-layer header type value
 .ft B
 const char *pcap_datalink_val_to_name(int dlt);
 const char *pcap_datalink_val_to_description(int dlt);
+const char *pcap_datalink_val_to_description_or_dlt(int dlt);
 .ft
 .fi
 .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.
+.PP
+.B pcap_datalink_val_to_description_or_dlt()
+translates a link-layer header type value to a short description of that
+link-layer header type just like pcap_datalink_val_to_description.
+If the type value does not correspond to a known
+.B DLT_
+value, the string "DLT n" is returned, where n is the value of
+the dlt argument.
+.SH SEE ALSO
+pcap(3PCAP)
index c7d29f5..7f201b7 100644 (file)
@@ -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
@@ -35,17 +35,16 @@ u_char *sp);
 .SH DESCRIPTION
 .B pcap_dump()
 outputs a packet to the ``savefile'' opened with
-.BR pcap_dump_open() .
+.BR pcap_dump_open(3PCAP) .
 Note that its calling arguments are suitable for use with
-.B pcap_dispatch()
+.B pcap_dispatch(3PCAP)
 or
-.BR pcap_loop() .
-If called directly, the 
+.BR pcap_loop(3PCAP) .
+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() .
 .SH SEE ALSO
-pcap(3PCAP), pcap_dump_open(3PCAP), pcap_dispatch(3PCAP),
-pcap_loop(3PCAP)
+pcap(3PCAP)
index afd00cb..bd95a52 100644 (file)
@@ -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
index 982b0dc..d207431 100644 (file)
@@ -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
@@ -33,6 +33,6 @@ FILE *pcap_dump_file(pcap_dumper_t *p);
 .SH DESCRIPTION
 .B pcap_dump_file()
 returns the standard I/O stream of the ``savefile'' opened by
-.BR pcap_dump_open() .
+.BR pcap_dump_open(3PCAP) .
 .SH SEE ALSO
 pcap(3PCAP)
index ba98dee..5d17474 100644 (file)
@@ -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 "25 July 2018"
 .SH NAME
 pcap_dump_flush \- flush to a savefile packets dumped
 .SH SYNOPSIS
@@ -34,10 +34,12 @@ int pcap_dump_flush(pcap_dumper_t *p);
 .B pcap_dump_flush()
 flushes the output buffer to the ``savefile,'' so that any packets
 written with
-.B pcap_dump()
+.B pcap_dump(3PCAP)
 but not yet written to the ``savefile'' will be written.
 .SH RETURN VALUE
 .B pcap_dump_flush()
-returns 0 on success and \-1 on failure.
+returns 0 on success and
+.B PCAP_ERROR
+on failure.
 .SH SEE ALSO
-pcap(3PCAP), pcap_dump_open(3PCAP), pcap_dump(3PCAP)
+pcap(3PCAP), pcap_dump_open(3PCAP)
index 6d5c828..20cb995 100644 (file)
@@ -17,9 +17,9 @@
 .\" 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 "25 July 2018"
 .SH NAME
-pcap_dump_ftell \- get the current file offset for a savefile being written
+pcap_dump_ftell, pcap_dump_ftell64 \- get the current file offset for a savefile being written
 .SH SYNOPSIS
 .nf
 .ft B
@@ -28,15 +28,31 @@ pcap_dump_ftell \- get the current file offset for a savefile being written
 .LP
 .ft B
 long pcap_dump_ftell(pcap_dumper_t *p);
+.ft B
+int64_t pcap_dump_ftell64(pcap_dumper_t *p);
 .ft
 .fi
 .SH DESCRIPTION
 .B pcap_dump_ftell()
 returns the current file position for the ``savefile'', representing the
 number of bytes written by
-.B pcap_dump_open()
+.B pcap_dump_open(3PCAP)
 and
-.BR pcap_dump() .
-\-1 is returned on error.
+.BR pcap_dump(3PCAP) .
+.B PCAP_ERROR
+is returned on error. If the current file position does not fit in a
+.BR long ,
+it will be truncated; this can happen on 32-bit UNIX-like systems with
+large file support and on Windows.
+.B pcap_dump_ftell64()
+returns the current file position in a
+.BR int64_t ,
+so if file offsets that don't fit in a
+.B long
+but that fit in a
+.B int64_t
+are supported, this will return the file offset without truncation.
+.B PCAP_ERROR
+is returned on error.
 .SH SEE ALSO
-pcap(3PCAP), pcap_dump_open(3PCAP), pcap_dump(3PCAP)
+pcap(3PCAP)
index 47ea321..b86696f 100644 (file)
@@ -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 "22 August 2018"
 .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
@@ -47,39 +48,56 @@ for
 .PP
 .B pcap_dump_fopen()
 is called to write data to an existing open stream
-.IR fp .
+.IR fp ;
+this stream will be closed by a subsequent call to
+.BR pcap_dump_close(3PCAP) .
 Note that on Windows, that stream should be opened in binary mode.
 .PP
 .I p
 is a capture or ``savefile'' handle returned by an earlier call to
-.B pcap_create()
+.B pcap_create(3PCAP)
 and activated by an earlier call to
-.BR pcap_activate() ,
+.BR \%pcap_activate(3PCAP) ,
 or returned by an earlier call to
-.BR pcap_open_offline() ,
-.BR pcap_open_live() ,
+.BR \%pcap_open_offline(3PCAP) ,
+.BR pcap_open_live(3PCAP) ,
 or
-.BR pcap_open_dead() .
-The link-layer type and snapshot length from
+.BR pcap_open_dead(3PCAP) .
+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
 structure to use in subsequent
-.B pcap_dump()
+.B pcap_dump(3PCAP)
 and
-.B pcap_dump_close()
+.B pcap_dump_close(3PCAP)
 calls is returned on success.
 .B NULL
 is returned on failure.
 If
 .B NULL
 is returned,
-.B pcap_geterr(\fIp\fB)
+.B pcap_geterr(3PCAP)
 can be used to get the error text.
+.SH BACKWARD COMPATIBILITY
+.PP
+The
+.B pcap_dump_open_append()
+function became available in libpcap release 1.7.2.  In previous
+releases, there is no support for appending packets to an existing
+savefile.
 .SH SEE ALSO
-pcap(3PCAP), pcap_create(3PCAP), pcap_activate(3PCAP),
-pcap_open_offline(3PCAP), pcap_open_live(3PCAP), pcap_open_dead(3PCAP),
-pcap_dump(3PCAP), pcap_dump_close(3PCAP), pcap_geterr(3PCAP),
-pcap-savefile(@MAN_FILE_FORMATS@)
+pcap(3PCAP),
+\%pcap-savefile(@MAN_FILE_FORMATS@)
index 7b18c81..981451b 100644 (file)
@@ -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
@@ -34,13 +34,15 @@ FILE *pcap_file(pcap_t *p);
 .B pcap_file()
 returns the standard I/O stream of the ``savefile,'' if a ``savefile''
 was opened with
-.BR pcap_open_offline() ,
-or NULL, if a network device was opened with
-.B pcap_create()
+.BR pcap_open_offline(3PCAP) ,
+or
+.BR NULL ,
+if a network device was opened with
+.B pcap_create(3PCAP)
 and
-.BR pcap_activate() ,
+.BR \%pcap_activate(3PCAP) ,
 or with
-.BR pcap_open_live() .
+.BR pcap_open_live(3PCAP) .
 .PP
 Note that the Packet Capture library is usually built with large file
 support, so the standard I/O stream of the ``savefile'' might refer to
@@ -50,8 +52,8 @@ should, if possible, use calls that support large files on the return
 value of
 .B pcap_file()
 or the value returned by
-.B fileno()
+.B fileno(3)
 when passed the return value of
 .BR pcap_file() .
 .SH SEE ALSO
-pcap(3PCAP), pcap_open_offline(3PCAP)
+pcap(3PCAP)
index 39d068b..60ac129 100644 (file)
@@ -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 "25 July 2018"
 .SH NAME
 pcap_fileno \- get the file descriptor for a live capture
 .SH SYNOPSIS
@@ -35,32 +35,31 @@ If
 .I p
 refers to a network device that was opened for a live capture using
 a combination of
-.B pcap_create()
+.B pcap_create(3PCAP)
 and
-.BR pcap_activate() ,
+.BR pcap_activate(3PCAP) ,
 or using
-.BR pcap_open_live() ,
+.BR pcap_open_live(3PCAP) ,
 .B pcap_fileno()
 returns the file descriptor from which captured packets are read.
 .LP
 If
 .I p
 refers to a ``savefile'' that was opened using functions such as
-.BR pcap_open_offline()
+.BR pcap_open_offline(3PCAP)
 or
-.BR pcap_fopen_offline() ,
+.BR pcap_fopen_offline(3PCAP) ,
 a ``dead''
 .B pcap_t
 opened using
-.BR pcap_open_dead() ,
+.BR pcap_open_dead(3PCAP) ,
 or a
 .B pcap_t
 that was created with
 .B pcap_create()
 but that has not yet been activated with
 .BR pcap_activate() ,
-it returns \-1.
+it returns
+.BR PCAP_ERROR .
 .SH SEE ALSO
-pcap(3PCAP), pcap_create(3PCAP), pcap_activate(3PCAP),
-pcap_open_live(3PCAP), pcap_open_offline(3PCAP),
-pcap_fopen_offline(3PCAP), pcap_open_dead(3PCAP)
+pcap(3PCAP)
index 00bb911..712e255 100644 (file)
@@ -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 "22 August 2018"
 .SH NAME
 pcap_findalldevs, pcap_freealldevs \- get a list of capture devices, and
 free that list
@@ -40,11 +40,11 @@ void pcap_freealldevs(pcap_if_t *alldevs);
 .SH DESCRIPTION
 .B pcap_findalldevs()
 constructs a list of network devices that can be opened with
-.B pcap_create()
+.B pcap_create(3PCAP)
 and
-.B pcap_activate()
+.B pcap_activate(3PCAP)
 or with
-.BR pcap_open_live() .
+.BR pcap_open_live(3PCAP) .
 (Note that there may be network devices that cannot be opened by the
 process calling
 .BR pcap_findalldevs() ,
@@ -98,6 +98,30 @@ set if the device is up
 .TP
 .B PCAP_IF_RUNNING
 set if the device is running
+.TP
+.B PCAP_IF_WIRELESS
+set if the device is a wireless interface; this includes IrDA as well as
+radio-based networks such as IEEE 802.15.4 and IEEE 802.11, so it
+doesn't just mean Wi-Fi
+.TP
+.B PCAP_IF_CONNECTION_STATUS
+a bitmask for an indication of whether the adapter is connected or not;
+for wireless interfaces, "connected" means "associated with a network"
+.TP
+The possible values for the connection status bits are:
+.TP
+.B PCAP_IF_CONNECTION_STATUS_UNKNOWN
+it's unknown whether the adapter is connected or not
+.TP
+.B PCAP_IF_CONNECTION_STATUS_CONNECTED
+the adapter is connected
+.TP
+.B PCAP_IF_CONNECTION_STATUS_DISCONNECTED
+the adapter is disconnected
+.TP
+.B PCAP_IF_CONNECTION_STATUS_NOT_APPLICABLE
+the notion of "connected" and "disconnected" don't apply to this
+interface; for example, it doesn't apply to a loopback device
 .RE
 .RE
 .PP
@@ -170,21 +194,38 @@ for IPv6 addresses, it can be interpreted as if it pointed to a
 .BR "struct sockaddr_in6".
 .PP
 The list of devices must be freed with
-.BR pcap_freealldevs() ,
+.BR pcap_freealldevs(3PCAP) ,
 which frees the list pointed to by
 .IR alldevs .
 .SH RETURN VALUE
 .B pcap_findalldevs()
-returns 0 on success and \-1 on failure; as indicated, finding no
+returns 0 on success and
+.B PCAP_ERROR
+on failure; as indicated, finding no
 devices is considered success, rather than failure, so 0 will be
-returned in that case.
-If \-1 is returned,
+returned in that case. If
+.B PCAP_ERROR
+is returned,
 .I errbuf
 is filled in with an appropriate error message.
 .I errbuf
 is assumed to be able to hold at least
 .B PCAP_ERRBUF_SIZE
 chars.
+.SH BACKWARD COMPATIBILITY
+.PP
+The
+.B PCAP_IF_UP
+and
+.B PCAP_IF_RUNNING
+constants became available in libpcap release 1.6.1.  The
+.BR PCAP_IF_WIRELESS ,
+.BR PCAP_IF_CONNECTION_STATUS ,
+.BR PCAP_IF_CONNECTION_STATUS_UNKNOWN ,
+.BR PCAP_IF_CONNECTION_STATUS_CONNECTED ,
+.BR PCAP_IF_CONNECTION_STATUS_DISCONNECTED ,
+and
+.B PCAP_IF_CONNECTION_STATUS_NOT_APPLICABLE
+constants became available in libpcap release 1.9.0.
 .SH SEE ALSO
-pcap(3PCAP), pcap_create(3PCAP), pcap_activate(3PCAP),
-pcap_open_live(3PCAP)
+pcap(3PCAP)
index c3c3ea6..4e71efa 100644 (file)
@@ -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
@@ -35,9 +35,9 @@ void pcap_freecode(struct bpf_program *);
 is used to free up allocated memory pointed to by a
 .I bpf_program
 struct generated by
-.B pcap_compile()
+.B pcap_compile(3PCAP)
 when that BPF program is no longer needed, for example after it
 has been made the filter program for a pcap structure by a call to
-.BR pcap_setfilter() .
+.BR pcap_setfilter(3PCAP) .
 .SH SEE ALSO
-pcap(3PCAP), pcap_compile(3PCAP), pcap_setfilter(3PCAP)
+pcap(3PCAP)
diff --git a/pcap_get_required_select_timeout.3pcap b/pcap_get_required_select_timeout.3pcap
new file mode 100644 (file)
index 0000000..e58cb4e
--- /dev/null
@@ -0,0 +1,98 @@
+.\" Copyright (c) 1994, 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.
+.\"
+.TH PCAP_GET_REQUIRED_SELECT_TIMEOUT 3PCAP "25 July 2018"
+.SH NAME
+pcap_get_required_select_timeout \- get a file descriptor on which a
+select() can be done for a live capture
+.SH SYNOPSIS
+.nf
+.ft B
+#include <pcap/pcap.h>
+.ft
+.LP
+.ft B
+struct timeval *pcap_get_required_select_timeout(pcap_t *p);
+.ft
+.fi
+.SH DESCRIPTION
+.B pcap_get_required_select_timeout()
+returns, on UNIX, a pointer to a
+.B struct timeval
+containing a value that must be used as the minimum timeout in
+.BR select(2) ,
+.BR poll(2) ,
+.BR epoll_wait(2) ,
+and
+.B kevent()
+calls if
+.B pcap_get_selectable_fd(3PCAP)
+returns
+.BR PCAP_ERROR .
+.PP
+The timeout that should be used in those calls must be no larger than
+the smallest of all timeouts returned by
+.B \%pcap_get_required_select_timeout()
+for devices from which packets will be captured.
+.PP
+The device for which
+.B pcap_get_selectable_fd()
+returned
+.B PCAP_ERROR
+must be put in non-blocking mode with
+.BR pcap_setnonblock(3PCAP) ,
+and an attempt must always be made to read packets from the device
+when the
+.BR select() ,
+.BR poll() ,
+.BR epoll_wait() ,
+or
+.B kevent()
+call returns.
+.PP
+Note that a device on which a read can be done without blocking may,
+on some platforms, not have any packets to read if the packet buffer
+timeout has expired.  A call to
+.B pcap_dispatch(3PCAP)
+or
+.B pcap_next_ex(3PCAP)
+will return 0 in this case, but will not block.
+.PP
+.B pcap_get_required_select_timeout()
+is not available on Windows.
+.SH RETURN VALUE
+A pointer to a
+.B struct timeval
+is returned if the timeout is required; otherwise
+.B NULL
+is returned.
+.SH BACKWARD COMPATIBILITY
+This function became available in libpcap release 1.9.0.  In previous
+releases,
+.BR select() ,
+.BR poll() ,
+.BR epoll_wait() ,
+and
+.B kevent()
+cannot be used on any capture source for which
+.B pcap_get_selectable_fd
+returns \-1.
+.SH SEE ALSO
+pcap(3PCAP), pcap_get_selectable_fd(3PCAP), select(2), poll(2),
+epoll_wait(2), kqueue(2)
index 6ae06a1..7f43db3 100644 (file)
@@ -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 "25 July 2018"
 .SH NAME
 pcap_get_selectable_fd \- get a file descriptor on which a select() can
 be done for a live capture
@@ -36,23 +36,50 @@ 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(2) ,
+.BR poll(2) ,
+.BR epoll_wait(2) ,
+.BR kevent() ,
+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
-.B pcap_create()
+a descriptor exists, or
+.BR PCAP_ERROR ,
+if no such descriptor exists.
+.PP
+Some network devices opened with
+.B pcap_create(3PCAP)
 and
-.BR pcap_activate() ,
+.BR pcap_activate(3PCAP) ,
 or with
-.BR pcap_open_live() ,
-do not support
-.B select()
+.BR pcap_open_live(3PCAP) ,
+do not support those calls (for example, regular network devices on
+FreeBSD 4.3 and 4.4, and Endace DAG devices), so
+.B PCAP_ERROR
+is returned for
+those devices.  In that case, those calls must be given a timeout less
+than or equal to the timeout returned by
+.B pcap_get_required_select_timeout(3PCAP)
+for the device for which
+.B pcap_get_selectable_fd()
+returned
+.BR PCAP_ERROR ,
+the device must be put in non-blocking mode with a call to
+.BR \%pcap_setnonblock(3PCAP) ,
+and an attempt must always be made to read packets from the device
+when the call returns.  If
+.B \%pcap_get_required_select_timeout()
+returns
+.BR NULL ,
+it is not possible to wait for packets to arrive on the device in an
+event loop.
+.PP
+Note that a device on which a read can be done without blocking may,
+on some platforms, not have any packets to read if the packet buffer
+timeout has expired.  A call to
+.B pcap_dispatch(3PCAP)
 or
-.B poll()
-(for example, regular network devices on FreeBSD 4.3 and 4.4, and Endace
-DAG devices), so \-1 is returned for those devices.
+.B pcap_next_ex(3PCAP)
+will return 0 in this case, but will not block.
 .PP
 Note that in:
 .IP
@@ -64,64 +91,61 @@ OpenBSD prior to OpenBSD 2.4;
 .IP
 Mac OS X prior to Mac OS X 10.7;
 .PP
-.B select()
+.BR select() ,
+.BR poll() ,
 and
-.B poll()
+.B kevent()
 do not work correctly on BPF devices;
 .B pcap_get_selectable_fd()
 will return a file descriptor on most of those versions (the exceptions
 being FreeBSD 4.3 and 4.4), but a simple
-.B select()
-or
-.B poll()
-will not indicate that the descriptor is readable until a full buffer's
-worth of packets is received, even if the read timeout expires before
-then.  To work around this, an application that uses
-.B select()
+.BR select() ,
+.BR poll() ,
 or
-.B poll()
-to wait for packets to arrive must put the
+.B kevent()
+call will not indicate that the descriptor is readable until a full
+buffer's worth of packets is received, even if the packet timeout
+expires before then.  To work around this, code that uses
+those calls to wait for packets to arrive must put the
 .B pcap_t
-in non-blocking mode, and must arrange that the
-.B select()
-or
-.B poll()
-have a timeout less than or equal to the read timeout,
+in non-blocking mode, and must arrange that the call
+have a timeout less than or equal to the packet buffer timeout,
 and must try to read packets after that timeout expires, regardless of
-whether
-.B select()
-or
-.B poll()
-indicated that the file descriptor for the
+whether the call indicated that the file descriptor for the
 .B pcap_t
 is ready to be read or not.  (That workaround will not work in FreeBSD
-4.3 and later; however, in FreeBSD 4.6 and later,
-.B select()
-and
-.B poll()
+4.3 and later; however, in FreeBSD 4.6 and later, those calls
 work correctly on BPF devices, so the workaround isn't necessary,
 although it does no harm.)
 .PP
 Note also that
 .B poll()
+and
+.B kevent()
 doesn't work on character special files, including BPF devices, in Mac
 OS X 10.4 and 10.5, so, while
 .B select()
 can be used on the descriptor returned by
 .BR pcap_get_selectable_fd() ,
 .B poll()
-cannot be used on it those versions of Mac OS X.  Kqueues also don't
-work on that descriptor.
+and
+.B kevent()
+cannot be used on it those versions of Mac OS X.
 .BR poll() ,
-but not kqueues, work on that descriptor in Mac OS X releases prior to
+but not
+.BR kevent() ,
+works on that descriptor in Mac OS X releases prior to
 10.4;
 .B poll()
-and kqueues work on that descriptor in Mac OS X 10.6 and later.
+and
+.B kevent()
+work on that descriptor in Mac OS X 10.6 and later.
 .PP
 .B pcap_get_selectable_fd()
 is not available on Windows.
 .SH RETURN VALUE
-A selectable file descriptor is returned if one exists; otherwise, \-1
+A selectable file descriptor is returned if one exists; otherwise,
+.B PCAP_ERROR
 is returned.
 .SH SEE ALSO
-pcap(3PCAP), select(2), poll(2)
+pcap(3PCAP), kqueue(2)
index 656c142..2e72e0b 100644 (file)
@@ -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
@@ -46,6 +46,10 @@ or
 which indicates
 that pcap captures contains time stamps in microseconds or nanoseconds
 respectively.
+.SH BACKWARD COMPATIBILITY
+This function became available in libpcap release 1.5.1.  In previous
+releases, time stamps from a capture device or savefile are always given
+in seconds and microseconds.
 .SH SEE ALSO
 pcap(3PCAP),
 pcap_set_tstamp_precision(3PCAP),
index fcabec3..ee681c8 100644 (file)
@@ -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 "15 January 2016"
 .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
index 7ccdf2c..92a9263 100644 (file)
@@ -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 "25 July 2018"
 .SH NAME
 pcap_inject, pcap_sendpacket \- transmit a packet
 .SH SYNOPSIS
@@ -42,7 +42,7 @@ is the number of bytes in the packet.
 Note that, even if you successfully open the network interface, you
 might not have permission to send packets on it, or it might not support
 sending packets; as
-.I pcap_open_live()
+.B pcap_open_live(3PCAP)
 doesn't have a flag to indicate whether to open for capturing, sending,
 or capturing and sending, you cannot request an open that supports
 sending and be notified at open time whether sending will be possible.
@@ -72,17 +72,23 @@ comes from OpenBSD;
 comes from WinPcap.  Both are provided for compatibility.)
 .SH RETURN VALUE
 .B pcap_inject()
-returns the number of bytes written on success and \-1 on failure.
+returns the number of bytes written on success and
+.B PCAP_ERROR
+on failure.
 .PP
 .B pcap_sendpacket()
-returns 0 on success and \-1 on failure.
+returns 0 on success and
+.B PCAP_ERROR
+on failure.
 .PP
-If \-1 is returned,
-.B pcap_geterr()
+If
+.B PCAP_ERROR
+is returned,
+.B pcap_geterr(3PCAP)
 or
-.B pcap_perror()
+.B pcap_perror(3PCAP)
 may be called with
 .I p
 as an argument to fetch or display the error text.
 .SH SEE ALSO
-pcap(3PCAP), pcap_geterr(3PCAP)
+pcap(3PCAP)
index a120616..67f762f 100644 (file)
@@ -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
@@ -39,11 +39,11 @@ than the current system.  For a live capture, it always returns false
 (0).
 .PP
 It must not be called on a pcap descriptor created by
-.B pcap_create()
+.B \%pcap_create(3PCAP)
 that has not yet been activated by
-.BR pcap_activate() .
+.BR \%pcap_activate(3PCAP) .
 .SH RETURN VALUE
-.B pcap_datalink()
+.B pcap_is_swapped()
 returns true (1) or false (0) on success and
 .B PCAP_ERROR_NOT_ACTIVATED
 if called on a capture handle that has been created but not activated.
index 3ec2e32..4b86b2d 100644 (file)
@@ -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
index 607efde..60ba478 100644 (file)
@@ -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 "25 July 2018"
 .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
@@ -47,9 +47,9 @@ which frees the list of link-layer header types pointed to by
 .IR dlt_list .
 .LP
 It must not be called on a pcap descriptor created by
-.B pcap_create()
+.B \%pcap_create(3PCAP)
 that has not yet been activated by
-.BR pcap_activate() .
+.BR \%pcap_activate(3PCAP) .
 .SH RETURN VALUE
 .B pcap_list_datalinks()
 returns the number of link-layer header types in the array on success,
@@ -57,17 +57,17 @@ returns the number of link-layer header types in the array on success,
 if called on a capture handle that has been created but not activated,
 and
 .B PCAP_ERROR
-(\-1) on other errors.
+on other errors.
 If
 .B PCAP_ERROR
 is returned,
-.B pcap_geterr()
+.B pcap_geterr(3PCAP)
 or
-.B pcap_perror()
+.B \%pcap_perror(3PCAP)
 may be called with
 .I p
 as an argument to fetch or display the error text.
 .SH SEE ALSO
-pcap(3PCAP), pcap_geterr(3PCAP),
+pcap(3PCAP),
 pcap_datalink_val_to_name(3PCAP),
 pcap-linktype(@MAN_MISC_INFO@)
index 66d3d66..e2487f7 100644 (file)
@@ -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 2018"
 .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
@@ -54,17 +54,28 @@ which frees the list pointed to by
 returns the number of time stamp types in the array on success and
 .B PCAP_ERROR
 on failure.
-A return value of zero means that you cannot specify a time stamp type;
-you are limited to the capture device's default time stamp type.
+A return value of one means that the only time stamp type supported is
+the one in the list, which is the capture device's default time stamp
+type.  A return value of zero means that the only time stamp type
+supported is
+.BR PCAP_TSTAMP_HOST ,
+which is the capture device's default time stamp type (only older
+versions of libpcap will return that; newer versions will always return
+one or more types).
 If
 .B PCAP_ERROR
 is returned,
-.B pcap_geterr()
+.B pcap_geterr(3PCAP)
 or
-.B pcap_perror()
+.B pcap_perror(3PCAP)
 may be called with
 .I p
 as an argument to fetch or display the error text.
+.SH BACKWARD COMPATIBILITY
+.PP
+These functions became available in libpcap release 1.2.1.  In previous
+releases, the time stamp type cannot be set; only the default time stamp
+type offered by a capture source is available.
 .SH SEE ALSO
-pcap(3PCAP), pcap_geterr(3PCAP), pcap_tstamp_type_val_to_name(3PCAP),
+pcap(3PCAP), pcap_tstamp_type_val_to_name(3PCAP),
 pcap-tstamp(@MAN_MISC_INFO@)
index 79dda42..29f09e3 100644 (file)
@@ -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 "8 September 2017"
 .SH NAME
 pcap_lookupdev \- find the default device on which to capture
 .SH SYNOPSIS
@@ -32,20 +32,28 @@ char errbuf[PCAP_ERRBUF_SIZE];
 .ft
 .LP
 .ft B
-char *pcap_lookupdev(char *errbuf);
+[DEPRECATED] char *pcap_lookupdev(char *errbuf);
 .ft
 .fi
 .SH DESCRIPTION
+.B This interface is obsoleted by
+.BR pcap_findalldevs (3PCAP).
+To find a default device on which to capture, call
+.B pcap_findalldevs()
+and, if the list it returns is not empty, use the first device in the
+list.  (If the list is empty, there are no devices on which capture is
+possible.)
+.LP
 .B pcap_lookupdev()
 returns a pointer to a string giving the name of a network device
 suitable for use with
-.B pcap_create()
+.B pcap_create(3PCAP)
 and
-.BR pcap_activate() ,
+.BR \%pcap_activate(3PCAP) ,
 or with
-.BR pcap_open_live() ,
+.BR pcap_open_live(3PCAP) ,
 and with
-.BR pcap_lookupnet() .
+.BR pcap_lookupnet(3PCAP) .
 If there is an error,
 .B NULL
 is returned and
@@ -56,5 +64,16 @@ is assumed to be able to hold at least
 .B PCAP_ERRBUF_SIZE
 chars.
 .SH SEE ALSO
-pcap(3PCAP), pcap_create(3PCAP), pcap_activate(3PCAP),
-pcap_open_live(3PCAP), pcap_lookupnet(3PCAP)
+pcap(3PCAP)
+.SH BUGS
+The pointer returned by
+.B pcap_lookupdev()
+points to a static buffer; subsequent calls to
+.B pcap_lookupdev()
+in the same thread, or calls to
+.B pcap_lookupdev()
+in another thread, may overwrite that buffer.
+.LP
+In WinPcap, this function may return a UTF-16 string rather than an
+ASCII or UTF-8 string.
+
index a3d14ae..f609445 100644 (file)
@@ -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 "25 July 2018"
 .SH NAME
 pcap_lookupnet \- find the IPv4 network number and netmask for a device
 .SH SYNOPSIS
@@ -51,8 +51,11 @@ are
 pointers.
 .SH RETURN VALUE
 .B pcap_lookupnet()
-returns 0 on success and \-1 on failure.
-If \-1 is returned,
+returns 0 on success and
+.B PCAP_ERROR
+on failure. If
+.B PCAP_ERROR
+is returned,
 .I errbuf
 is filled in with an appropriate error message.
 .I errbuf
index d18dc06..0193714 100644 (file)
@@ -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 "25 July 2018"
 .SH NAME
 pcap_loop, pcap_dispatch \- process packets from a live capture or savefile
 .SH SYNOPSIS
@@ -47,11 +47,11 @@ processes packets from a live capture or ``savefile'' until
 .I cnt
 packets are processed, the end of the ``savefile'' is
 reached when reading from a ``savefile'',
-.B pcap_breakloop()
+.B pcap_breakloop(3PCAP)
 is called, or an error occurs.
 It does
 .B not
-return when live read timeouts occur.
+return when live packet buffer timeouts occur.
 A value of \-1 or 0 for
 .I cnt
 is equivalent to infinity, so that packets are processed until another
@@ -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
@@ -116,20 +123,20 @@ them.
 .PP
 The bytes of data from the packet begin with a link-layer header.  The
 format of the link-layer header is indicated by the return value of the
-.B pcap_datalink()
+.B pcap_datalink(3PCAP)
 routine when handed the
 .B pcap_t
 value also passed to
 .B pcap_loop()
 or
 .BR pcap_dispatch() .
-.I http://www.tcpdump.org/linktypes.html
+.I https://www.tcpdump.org/linktypes.html
 lists the values
 .B pcap_datalink()
 can return and describes the packet formats that
 correspond to those values.  The value it returns will be valid for all
 packets received unless and until
-.B pcap_set_datalink()
+.B pcap_set_datalink(3PCAP)
 is called; after a successful call to
 .BR pcap_set_datalink() ,
 all subsequent packets will have a link-layer header of the type
@@ -153,40 +160,47 @@ for Ethernet.
 returns 0 if
 .I cnt
 is exhausted or if, when reading from a ``savefile'', no more packets
-are available.  It returns \-1 if an error occurs or \-2 if the loop
-terminated due to a call to
+are available.  It returns
+.B PCAP_ERROR
+if an error occurs or
+.B PCAP_ERROR_BREAK
+if the loop terminated due to a call to
 .B pcap_breakloop()
 before any packets were processed.
 It does
 .B not
-return when live read timeouts occur; instead, it attempts to read more
-packets.
+return when live packet buffer timeouts occur; instead, it attempts to
+read more packets.
 .PP
 .B pcap_dispatch()
 returns the number of packets processed on success; this can be 0 if no
 packets were read from a live capture (if, for example, they were
 discarded because they didn't pass the packet filter, or if, on
-platforms that support a read timeout that starts before any packets
-arrive, the timeout expires before any packets arrive, or if the file
-descriptor for the capture device is in non-blocking mode and no packets
-were available to be read) or if no more packets are available in a
-``savefile.''  It returns \-1 if an error occurs or \-2 if the loop
-terminated due to a call to
+platforms that support a packet buffer timeout that starts before any
+packets arrive, the timeout expires before any packets arrive, or if the
+file descriptor for the capture device is in non-blocking mode and no
+packets were available to be read) or if no more packets are available
+in a ``savefile.'' It returns
+.B PCAP_ERROR
+if an error occurs or
+.B PCAP_ERROR_BREAK
+if the loop terminated due to a call to
 .B pcap_breakloop()
 before any packets were processed.
 .ft B
 If your application uses pcap_breakloop(),
-make sure that you explicitly check for \-1 and \-2, rather than just
-checking for a return value < 0.
+make sure that you explicitly check for PCAP_ERROR and PCAP_ERROR_BREAK,
+rather than just checking for a return value < 0.
 .ft R
 .PP
-If \-1 is returned,
-.B pcap_geterr()
+If
+.B PCAP_ERROR
+is returned,
+.B pcap_geterr(3PCAP)
 or
-.B pcap_perror()
+.B pcap_perror(3PCAP)
 may be called with
 .I p
 as an argument to fetch or display the error text.
 .SH SEE ALSO
-pcap(3PCAP), pcap_geterr(3PCAP), pcap_breakloop(3PCAP),
-pcap_datalink(3PCAP)
+pcap(3PCAP)
index a085838..2fedfd2 100644 (file)
@@ -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 "8 January 2018"
 .SH NAME
 pcap_major_version, pcap_minor_version \- get the version number of a savefile
 .SH SYNOPSIS
@@ -41,7 +41,7 @@ returns the major number of the file format of the ``savefile'' and
 returns the minor number of the file format of the ``savefile''.  The
 version number is stored in the ``savefile''; note that the meaning of
 its values depends on the type of ``savefile'' (for example, pcap or
-pcap-NG).
+pcapng).
 .PP
 If
 .I p
index c310c2f..f0eb82d 100644 (file)
@@ -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 "25 July 2018"
 .SH NAME
 pcap_next_ex, pcap_next \- read the next packet from a pcap_t
 .SH SYNOPSIS
@@ -49,9 +49,9 @@ and the packet data are not to be freed by the caller, and are not
 guaranteed to be valid after the next call to
 .BR pcap_next_ex() ,
 .BR pcap_next() ,
-.BR pcap_loop() ,
+.BR pcap_loop(3PCAP) ,
 or
-.BR pcap_dispatch() ;
+.BR pcap_dispatch(3PCAP) ;
 if the code needs them to remain valid, it must make a copy of them.
 .PP
 .B pcap_next()
@@ -78,20 +78,20 @@ is filled in with the appropriate values for the packet.
 .PP
 The bytes of data from the packet begin with a link-layer header.  The
 format of the link-layer header is indicated by the return value of the
-.B pcap_datalink()
+.B pcap_datalink(PCAP)
 routine when handed the
 .B pcap_t
 value also passed to
 .B pcap_loop()
 or
 .BR pcap_dispatch() .
-.I http://www.tcpdump.org/linktypes.html
+.I https://www.tcpdump.org/linktypes.html
 lists the values
 .B pcap_datalink()
 can return and describes the packet formats that
 correspond to those values.  The value it returns will be valid for all
 packets received unless and until
-.B pcap_set_datalink()
+.B pcap_set_datalink(3PCAP)
 is called; after a successful call to
 .BR pcap_set_datalink() ,
 all subsequent packets will have a link-layer header of the type
@@ -112,15 +112,19 @@ have some other data link type, such as
 for Ethernet.
 .SH RETURN VALUE
 .B pcap_next_ex()
-returns 1 if the packet was read without problems, 0
-if packets are being read from a live capture and the timeout expired,
-\-1 if an error occurred while reading the packet, and \-2 if
-packets are being read from a ``savefile'' and there are no more
-packets to read from the savefile.
-If \-1 is returned,
-.B pcap_geterr()
+returns 1 if the packet was read without problems, 0 if packets are
+being read from a live capture and the packet buffer timeout expired,
+.B PCAP_ERROR
+if an error occurred while reading the packet, and
+.B PCAP_ERROR_BREAK
+if packets
+are being read from a ``savefile'' and there are no more packets to read
+from the savefile.  If
+.B PCAP_ERROR
+is returned,
+.B pcap_geterr(3PCAP)
 or
-.B pcap_perror()
+.B pcap_perror(3PCAP)
 may be called with
 .I p
 as an argument to fetch or display the error text.
@@ -128,14 +132,13 @@ as an argument to fetch or display the error text.
 .B pcap_next()
 returns a pointer to the packet data on success, and returns
 .B NULL
-if an error occurred, or if no packets were read from a live
-capture (if, for example, they were discarded because they didn't pass
-the packet filter, or if, on platforms that support a read timeout that
-starts before any packets arrive, the timeout expires before any packets
-arrive, or if the file descriptor for the capture device is in
+if an error occurred, or if no packets were read from a live capture
+(if, for example, they were discarded because they didn't pass the
+packet filter, or if, on platforms that support a packet buffer timeout
+that starts before any packets arrive, the timeout expires before any
+packets arrive, or if the file descriptor for the capture device is in
 non-blocking mode and no packets were available to be read), or if no
-more packets are available in a ``savefile.''  Unfortunately, there is
-no way to determine whether an error occurred or not.
+more packets are available in a ``savefile.'' Unfortunately, there is no
+way to determine whether an error occurred or not.
 .SH SEE ALSO
-pcap(3PCAP), pcap_geterr(3PCAP), pcap_dispatch(3PCAP),
-pcap_datalink(3PCAP)
+pcap(3PCAP)
index b471c6a..724f836 100644 (file)
@@ -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
@@ -39,7 +39,7 @@ checks whether a filter matches a packet.
 is a pointer to a
 .I bpf_program
 struct, usually the result of a call to
-.BR pcap_compile() .
+.BR pcap_compile(3PCAP) .
 .I h
 points to the
 .I pcap_pkthdr
@@ -52,4 +52,4 @@ returns the return value of the filter program.  This will be zero if
 the packet doesn't match the filter and non-zero if the packet matches
 the filter.
 .SH SEE ALSO
-pcap(3PCAP), pcap_compile(3PCAP)
+pcap(3PCAP)
index 2d1b48c..97a97f3 100644 (file)
@@ -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
@@ -43,10 +43,10 @@ are used for creating a
 structure to use when calling the other functions in libpcap.  It is
 typically used when just using libpcap for compiling BPF code; it can
 also be used if using
-.BR pcap_dump_open() ,
-.BR pcap_dump() ,
+.BR pcap_dump_open(3PCAP) ,
+.BR pcap_dump(3PCAP) ,
 and
-.B pcap_dump_close()
+.B pcap_dump_close(3PCAP)
 to write a savefile if there is no
 .B pcap_t
 that supplies the packets to be written.
@@ -73,7 +73,6 @@ seconds and microseconds, and
 .B PCAP_TSTAMP_PRECISION_NANO
 should be specified if the packets to be written have time stamps in
 seconds and nanoseconds.  Its value does not affect
-.BR pcap_compile() .
+.BR pcap_compile(3PCAP) .
 .SH SEE ALSO
-pcap(3PCAP), pcap_compile(3PCAP), pcap_dump_open(3PCAP),
-pcap-linktype(@MAN_MISC_INFO@)
+pcap(3PCAP), \%pcap-linktype(@MAN_MISC_INFO@)
index 715994b..3286e29 100644 (file)
@@ -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 "6 December 2017"
 .SH NAME
 pcap_open_live \- open a device for capturing
 .SH SYNOPSIS
@@ -56,7 +56,10 @@ specifies the snapshot length to be set on the handle.
 specifies if the interface is to be put into promiscuous mode.
 .PP
 .I to_ms
-specifies the read timeout in milliseconds.
+specifies the packet buffer timeout, as a non-negative value, in
+milliseconds.  (See
+.BR pcap (3PCAP)
+for an explanation of the packet buffer timeout.)
 .SH RETURN VALUE
 .B pcap_open_live()
 returns a
@@ -84,4 +87,4 @@ is assumed to be able to hold at least
 .B PCAP_ERRBUF_SIZE
 chars.
 .SH SEE ALSO
-pcap(3PCAP), pcap_create(3PCAP), pcap_activate(3PCAP)
+pcap_create(3PCAP), pcap_activate(3PCAP)
index 7239729..2bfbbac 100644 (file)
@@ -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 "8 January 2018 "
 .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
@@ -55,7 +55,7 @@ which is the file format used by, among other programs,
 .BR tcpdump (1)
 and
 .BR tcpslice (1),
-or can have the pcap-ng file format, although not all pcap-ng files can
+or can have the pcapng file format, although not all pcapng files can
 be read.
 The name "-" is a synonym for
 .BR stdin .
@@ -81,7 +81,8 @@ or
 .B pcap_fopen_offline_with_tstamp_precision()
 to read dumped data from an existing open stream
 .IR fp .
-.B pcap_fopen_offline_with_tstamp_precision() takes an additional
+.B pcap_fopen_offline_with_tstamp_precision()
+takes an additional
 .I precision
 argument as described above.
 Note that on Windows, that stream should be opened in binary mode.
@@ -105,5 +106,11 @@ is filled in with an appropriate error message.
 is assumed to be able to hold at least
 .B PCAP_ERRBUF_SIZE
 chars.
+.SH BACKWARD COMPATIBILITY
+.B pcap_open_offline_with_tstamp_precision
+and
+.B pcap_fopen_offline_with_tstamp_precision
+became available in libpcap release 1.5.1.  In previous releases, time
+stamps from a savefile are always given in seconds and microseconds.
 .SH SEE ALSO
 pcap(3PCAP), pcap-savefile(@MAN_FILE_FORMATS@)
index fea1df7..684f739 100644 (file)
@@ -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
index 60a7bfc..66cfdb1 100644 (file)
@@ -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 "25 July 2018"
 .SH NAME
 pcap_set_datalink \- set the link-layer header type to be used by a
 capture device
@@ -38,14 +38,16 @@ to the type specified by
 .IR dlt .
 .SH RETURN VALUE
 .B pcap_set_datalink()
-returns 0 on success and \-1 on failure.
-If \-1 is returned,
-.B pcap_geterr()
+returns 0 on success and
+.B PCAP_ERROR
+on failure. If
+.B PCAP_ERROR
+is returned,
+.B pcap_geterr(3PCAP)
 or
-.B pcap_perror()
+.B pcap_perror(3PCAP)
 may be called with
 .I p
 as an argument to fetch or display the error text.
 .SH SEE ALSO
-pcap(3PCAP), pcap_geterr(3PCAP),
-pcap_datalink_name_to_val(3PCAP)
+pcap(3PCAP), pcap_datalink_name_to_val(3PCAP)
similarity index 54%
rename from pcap_set_immediate_mode.3pcap
rename to pcap_set_immediate_mode.3pcap.in
index 87ec98b..2fe45c5 100644 (file)
@@ -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 "22 August 2018"
 .SH NAME
 pcap_set_immediate_mode \- set immediate mode for a not-yet-activated capture
 handle
@@ -34,7 +34,8 @@ int pcap_set_immediate_mode(pcap_t *p, int immediate_mode);
 .SH DESCRIPTION
 .B pcap_set_immediate_mode()
 sets whether immediate mode should be set on a capture handle when
-the handle is activated.
+the handle is activated.  In immediate mode, packets are always
+delivered as soon as they arrive, with no buffering.
 If
 .I immediate_mode
 is non-zero, immediate mode will be set, otherwise it will not be set.
@@ -43,5 +44,52 @@ is non-zero, immediate mode will be set, otherwise it will not be set.
 returns 0 on success or
 .B PCAP_ERROR_ACTIVATED
 if called on a capture handle that has been activated.
+.SH BACKWARD COMPATIBILITY
+.PP
+This function became available in libpcap release 1.5.0.  In previous
+releases, if immediate delivery of packets is required:
+.IP
+on FreeBSD, NetBSD, OpenBSD, DragonFly BSD, macOS, and Solaris 11,
+immediate mode must be turned on with a
+.B BIOCIMMEDIATE
+.BR ioctl (2),
+as documented in
+.BR bpf(@MAN_DEVICES@) ,
+on the descriptor returned by
+.B pcap_fileno(3PCAP),
+after
+.BR pcap_activate(3PCAP)
+is called;
+.IP
+on Solaris 10 and earlier versions of Solaris, immediate mode must be
+turned on by using a read timeout of 0 when opening the device (this
+will not provide immediate delivery of packets on other platforms, so
+don't assume it's sufficient);
+.IP
+on Digital UNIX/Tru64 UNIX, immediate mode must be turned on by doing a
+.B BIOCMBIC
+.BR ioctl ,
+as documented in
+.BR packetfilter(7) ,
+to clear the
+.B ENBATCH
+flag on the descriptor returned by
+.B pcap_fileno(3PCAP),
+after
+.BR pcap_activate(3PCAP)
+is called;
+.IP
+on Windows, immediate mode must be turned on by calling
+.B pcap_setmintocopy()
+with a size of 0.
+.PP
+On Linux, with previous releases of libpcap, capture devices are always
+in immediate mode; however, in 1.5.0 and later, they are, by default,
+.B not
+in immediate mode, so if
+.B pcap_set_immediate_mode()
+is available, it should be used.
+.PP
+On other platforms, capture devices are always in immediate mode.
 .SH SEE ALSO
 pcap(3PCAP), pcap_create(3PCAP), pcap_activate(3PCAP)
index 5d17572..fcd797a 100644 (file)
@@ -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/pcap_set_protocol_linux.3pcap b/pcap_set_protocol_linux.3pcap
new file mode 100644 (file)
index 0000000..873017b
--- /dev/null
@@ -0,0 +1,68 @@
+.\" Copyright (c) 1994, 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.
+.\"
+.TH PCAP_SET_PROTOCOL_LINUX 3PCAP "24 August 2017"
+.SH NAME
+pcap_set_protocol_linux \- set capture protocol for a not-yet-activated
+capture handle
+.SH SYNOPSIS
+.nf
+.ft B
+#include <pcap/pcap.h>
+.LP
+.ft B
+int pcap_set_protocol_linux(pcap_t *p, int protocol);
+.ft
+.fi
+.SH DESCRIPTION
+On network interface devices on Linux,
+.B pcap_set_protocol_linux()
+sets the protocol to be used in the
+.BR socket (2)
+call to create a capture socket when the handle is activated.  The
+argument is a link-layer protocol value, such as the values in the
+.B <linux/if_ether.h>
+header file, specified in host byte order.
+If
+.I protocol
+is non-zero, packets of that protocol will be captured when the
+handle is activated, otherwise, all packets will be captured.  This
+function is only provided on Linux, and, if it is used on any device
+other than a network interface, it will have no effect.
+.LP
+It should not be used in portable code; instead, a filter should be
+specified with
+.BR pcap_setfilter(3PCAP) .
+.LP
+If a given network interface provides a standard link-layer header, with
+a standard packet type, but provides some packet types with a different
+socket-layer protocol type from the one in the link-layer header, that
+packet type cannot be filtered with a filter specified with
+.B pcap_setfilter()
+but can be filtered by specifying the socket-layer protocol type using
+.BR pcap_set_protocol_linux() .
+.SH RETURN VALUE
+.B pcap_set_protocol_linux()
+returns 0 on success or
+.B PCAP_ERROR_ACTIVATED
+if called on a capture handle that has been activated.
+.SH BACKWARD COMPATIBILITY
+This function became available in libpcap release 1.9.0.
+.SH SEE ALSO
+pcap(3PCAP), pcap_create(3PCAP), pcap_activate(3PCAP)
index a386e8b..691518a 100644 (file)
@@ -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
index 8080ea1..44eb154 100644 (file)
@@ -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
index b728203..e67b813 100644 (file)
 .\" 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 "6 December 2017"
 .SH NAME
-pcap_set_timeout \- set the read timeout for a not-yet-activated
-capture handle
+pcap_set_timeout \- set the packet buffer timeout for a
+not-yet-activated capture handle
 .SH SYNOPSIS
 .nf
 .ft B
@@ -32,14 +32,22 @@ int pcap_set_timeout(pcap_t *p, int to_ms);
 .fi
 .SH DESCRIPTION
 .B pcap_set_timeout()
-sets the read timeout that will be used on a capture handle when
-the handle is activated to
+sets the packet buffer timeout that will be used on a capture handle
+when the handle is activated to
 .IR to_ms ,
-which is in units of milliseconds.
+which is in units of milliseconds.  (See
+.BR pcap (3PCAP)
+for an explanation of the packet buffer timeout.)
+.LP
+The behavior, if the timeout isn't specified, is undefined, as is the
+behavior if the timeout is set to zero or to a negative value.  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_create(3PCAP), pcap_activate(3PCAP),
+\%pcap_set_immediate_mode(3PCAP)
index 053a4c6..dc2b4b3 100644 (file)
@@ -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
@@ -39,22 +39,27 @@ sets the precision of the time stamp desired for packets captured on the pcap
 descriptor to the type specified by
 .IR tstamp_precision .
 It must be called on a pcap descriptor created by
-.B pcap_create()
+.B pcap_create(3PCAP)
 that has not yet been activated by
-.BR pcap_activate() .
+.BR pcap_activate(3PCAP) .
 Two time stamp precisions are supported, microseconds and nanoseconds. One can
 use options
 .B PCAP_TSTAMP_PRECISION_MICRO and
 .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,
+supported by the capture device,
 .B PCAP_ERROR_TSTAMP_PRECISION_NOTSUP
-if operating system does not support requested time stamp precision,
+if the capture device does not support the requested time stamp
+precision,
 .B PCAP_ERROR_ACTIVATED
 if called on a capture handle that has been activated.
+.SH BACKWARD COMPATIBILITY
+This function became available in libpcap release 1.5.1.  In previous
+releases, time stamps from a capture device or savefile are always given
+in seconds and microseconds.
 .SH SEE ALSO
 pcap(3PCAP),
 pcap_get_tstamp_precision(3PCAP),
index 261c315..9833f46 100644 (file)
@@ -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 "22 August 2018"
 .SH NAME
 pcap_set_tstamp_type \- set the time stamp type to be used by a
 capture device
@@ -34,14 +34,14 @@ int pcap_set_tstamp_type(pcap_t *p, int tstamp_type);
 .fi
 .SH DESCRIPTION
 .B pcap_set_tstamp_type()
-sets the the type of time stamp desired for packets captured on the pcap
+sets the type of time stamp desired for packets captured on the pcap
 descriptor to the type specified by
 .IR tstamp_type .
 It must be called on a pcap descriptor created by
-.B pcap_create()
+.B pcap_create(3PCAP)
 that has not yet been activated by
-.BR pcap_activate() .
-.B pcap_list_tstamp_types()
+.BR pcap_activate(3PCAP) .
+.B pcap_list_tstamp_types(3PCAP)
 will give a list of the time stamp types supported by a given capture
 device.
 See
@@ -52,14 +52,19 @@ 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
 .B PCAP_ERROR_CANTSET_TSTAMP_TYPE
-if the capture device doesn't support setting the time stamp type.
+if the capture device doesn't support setting the time stamp type (only
+older versions of libpcap will return that; newer versions will always
+allow the time stamp type to be set to the default type).
+.SH BACKWARD COMPATIBILITY
+.PP
+This function became available in libpcap release 1.2.1.  In previous
+releases, the time stamp type cannot be set; only the default time stamp
+type offered by a capture source is available.
 .SH SEE ALSO
 pcap(3PCAP),
-pcap_list_tstamp_types(3PCAP),
-pcap_tstamp_type_name_to_val(3PCAP),
-pcap-tstamp(@MAN_MISC_INFO@)
+pcap_tstamp_type_name_to_val(3PCAP)
index 70920b1..f174b98 100644 (file)
@@ -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 "25 July 2018"
 .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,
@@ -57,13 +57,16 @@ support
 This operation is not supported if a ``savefile'' is being read.
 .SH RETURN VALUE
 .B pcap_setdirection()
-returns 0 on success and \-1 on failure.
-If \-1 is returned,
-.B pcap_geterr()
+returns 0 on success and
+.B PCAP_ERROR
+on failure. If
+.B PCAP_ERROR
+is returned,
+.B pcap_geterr(3PCAP)
 or
-.B pcap_perror()
+.B pcap_perror(3PCAP)
 may be called with
 .I p
 as an argument to fetch or display the error text.
 .SH SEE ALSO
-pcap(3PCAP), pcap_geterr(3PCAP)
+pcap(3PCAP)
index c737797..8729693 100644 (file)
@@ -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 "25 July 2018"
 .SH NAME
 pcap_setfilter \- set the filter
 .SH SYNOPSIS
@@ -37,16 +37,19 @@ is used to specify a filter program.
 is a pointer to a
 .I bpf_program
 struct, usually the result of a call to
-.BR pcap_compile() .
+.BR \%pcap_compile(3PCAP) .
 .SH RETURN VALUE
 .B pcap_setfilter()
-returns 0 on success and \-1 on failure.
-If \-1 is returned,
-.B pcap_geterr()
+returns 0 on success and
+.B PCAP_ERROR
+on failure. If
+.B PCAP_ERROR
+is returned,
+.B pcap_geterr(3PCAP)
 or
-.B pcap_perror()
+.B pcap_perror(3PCAP)
 may be called with
 .I p
 as an argument to fetch or display the error text.
 .SH SEE ALSO
-pcap(3PCAP), pcap_compile(3PCAP), pcap_geterr(3PCAP)
+pcap(3PCAP)
index 37b2203..e8adebe 100644 (file)
@@ -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 "25 July 2018"
 .SH NAME
 pcap_setnonblock, pcap_getnonblock \- set or get the state of
 non-blocking mode on a capture device
@@ -43,25 +43,37 @@ puts a capture handle into ``non-blocking'' mode, or takes it out
 of ``non-blocking'' mode, depending on whether the
 .I nonblock
 argument is non-zero or zero.  It has no effect on ``savefiles''.
-If there is an error, \-1 is returned and
+If there is an error,
+.B PCAP_ERROR
+is returned and
 .I errbuf
 is filled in with an appropriate error message; otherwise, 0 is
 returned.
 In
 ``non-blocking'' mode, an attempt to read from the capture descriptor
 with
-.B pcap_dispatch()
+.B pcap_dispatch(3PCAP)
 will, if no packets are currently available to be read, return 0
 immediately rather than blocking waiting for packets to arrive.
-.B pcap_loop()
+.B pcap_loop(3PCAP)
 and
-.B pcap_next()
+.B pcap_next(3PCAP)
 will not work in ``non-blocking'' mode.
+.PP
+When first activated with
+.B pcap_activate(3PCAP)
+or opened with
+.B pcap_open_live(3PCAP) ,
+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
 always returns 0 on ``savefiles''.
-If there is an error, \-1 is returned and
+If there is an error,
+.B PCAP_ERROR
+is returned and
 .I errbuf
 is filled in with an appropriate error message.
 .PP
@@ -70,4 +82,4 @@ is assumed to be able to hold at least
 .B PCAP_ERRBUF_SIZE
 chars.
 .SH SEE ALSO
-pcap(3PCAP), pcap_loop(3PCAP), pcap_next_ex(3PCAP), pcap_geterr(3PCAP)
+pcap(3PCAP), pcap_next_ex(3PCAP), pcap_geterr(3PCAP)
index 47eb42a..ee54bb0 100644 (file)
@@ -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
@@ -33,16 +33,16 @@ int pcap_snapshot(pcap_t *p);
 .SH DESCRIPTION
 .B pcap_snapshot()
 returns the snapshot length specified when
-.B pcap_set_snapshot()
+.B pcap_set_snaplen(3PCAP)
 or
-.B pcap_open_live()
+.B pcap_open_live(3PCAP)
 was called, for a live capture, or the snapshot length from the capture
 file, for a ``savefile''.
 .PP
 It must not be called on a pcap descriptor created by
-.B pcap_create()
+.B \%pcap_create(3PCAP)
 that has not yet been activated by
-.BR pcap_activate() .
+.BR \%pcap_activate(3PCAP) .
 .SH RETURN VALUE
 .B pcap_snapshot()
 returns the snapshot length on success and
index 159054e..465dada 100644 (file)
@@ -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 "25 July 2018"
 .SH NAME
 pcap_stats \- get capture statistics
 .SH SYNOPSIS
@@ -83,15 +83,18 @@ statistic is unavailable, so it should not be treated as an indication
 that the interface did not drop any packets.
 .SH RETURN VALUE
 .B pcap_stats()
-returns 0 on success and returns \-1 if there is an error or if
+returns 0 on success and returns
+.B PCAP_ERROR
+if there is an error or if
 .I p
-doesn't support packet statistics.
-If \-1 is returned,
-.B pcap_geterr()
+doesn't support packet statistics. If
+.B PCAP_ERROR
+is returned,
+.B pcap_geterr(3PCAP)
 or
-.B pcap_perror()
+.B pcap_perror(3PCAP)
 may be called with
 .I p
 as an argument to fetch or display the error text.
 .SH SEE ALSO
-pcap(3PCAP), pcap_geterr(3PCAP)
+pcap(3PCAP)
index 77b8c5f..9c2057a 100644 (file)
@@ -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
index 7185162..a5775f4 100644 (file)
@@ -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
@@ -37,4 +37,4 @@ is provided in case
 isn't available.  It returns an error message string corresponding to
 .IR error .
 .SH SEE ALSO
-strerror(3)
+pcap(3PCAP)
index 8fcc4d7..fdcc6c6 100644 (file)
@@ -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 "22 August 2018"
 .SH NAME
 pcap_tstamp_type_name_to_val \- get the time stamp type value
 corresponding to a time stamp type name
@@ -38,8 +38,11 @@ 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 BACKWARD COMPATIBILITY
+.PP
+This function became available in libpcap release 1.2.1.
 .SH SEE ALSO
 pcap(3PCAP), pcap_tstamp_type_val_to_name(3PCAP)
index 903cea7..9374f48 100644 (file)
@@ -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 "22 August 2018"
 .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
@@ -45,5 +45,8 @@ translates a time stamp type value to a short description of that time
 stamp type.
 .B NULL
 is returned on failure.
+.SH BACKWARD COMPATIBILITY
+.PP
+These functions became available in libpcap release 1.2.1.
 .SH SEE ALSO
 pcap(3PCAP), pcap_tstamp_type_name_to_val(3PCAP)
diff --git a/portability.h b/portability.h
new file mode 100644 (file)
index 0000000..543846e
--- /dev/null
@@ -0,0 +1,177 @@
+/*
+ * 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.
+ */
+#include <stdarg.h>    /* we declare varargs functions on some platforms */
+
+#include "pcap/funcattrs.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#ifdef HAVE_STRLCAT
+  #define pcap_strlcat strlcat
+#else
+  #if defined(_MSC_VER) || defined(__MINGW32__)
+    /*
+     * strncat_s() is supported at least back to Visual
+     * Studio 2005.
+     */
+    #define pcap_strlcat(x, y, z) \
+       strncat_s((x), (z), (y), _TRUNCATE)
+  #else
+    /*
+     * Define it ourselves.
+     */
+    extern size_t pcap_strlcat(char * restrict dst, const char * restrict src, size_t dstsize);
+  #endif
+#endif
+
+#ifdef HAVE_STRLCPY
+  #define pcap_strlcpy strlcpy
+#else
+  #if defined(_MSC_VER) || defined(__MINGW32__)
+    /*
+     * strncpy_s() is supported at least back to Visual
+     * Studio 2005.
+     */
+    #define pcap_strlcpy(x, y, z) \
+       strncpy_s((x), (z), (y), _TRUNCATE)
+  #else
+    /*
+     * Define it ourselves.
+     */
+    extern size_t pcap_strlcpy(char * restrict dst, const char * restrict src, size_t dstsize);
+  #endif
+#endif
+
+#ifdef _MSC_VER
+  #define isascii      __isascii
+
+  /*
+   * If <crtdbg.h> has been included, and _DEBUG is defined, and
+   * __STDC__ is zero, <crtdbg.h> will define strdup() to call
+   * _strdup_dbg().  So if it's already defined, don't redefine
+   * it.
+   */
+  #ifndef strdup
+  #define strdup       _strdup
+  #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, PCAP_FORMAT_STRING(const char *), ...)
+    PCAP_PRINTFLIKE(3, 4);
+#endif
+
+#ifdef HAVE_VSNPRINTF
+#define pcap_vsnprintf vsnprintf
+#else
+extern int pcap_vsnprintf(char *, size_t, const char *, va_list ap);
+#endif
+
+/*
+ * We also want asprintf(), for some cases where we use it to construct
+ * dynamically-allocated variable-length strings.
+ */
+#ifdef HAVE_ASPRINTF
+#define pcap_asprintf asprintf
+#else
+extern int pcap_asprintf(char **, PCAP_FORMAT_STRING(const char *), ...)
+    PCAP_PRINTFLIKE(2, 3);
+#endif
+
+#ifdef HAVE_VASPRINTF
+#define pcap_vasprintf vasprintf
+#else
+extern int pcap_vasprintf(char **, const char *, va_list ap);
+#endif
+
+#ifdef HAVE_STRTOK_R
+  #define pcap_strtok_r        strtok_r
+#else
+  #ifdef _WIN32
+    /*
+     * Microsoft gives it a different name.
+     */
+    #define pcap_strtok_r      strtok_s
+  #else
+    /*
+     * Define it ourselves.
+     */
+    extern char *pcap_strtok_r(char *, const char *, char **);
+  #endif
+#endif /* HAVE_STRTOK_R */
+
+#ifdef _WIN32
+  #if !defined(__cplusplus)
+    #define inline __inline
+  #endif
+#endif /* _WIN32 */
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/rpcap-protocol.c b/rpcap-protocol.c
new file mode 100644 (file)
index 0000000..692f7c5
--- /dev/null
@@ -0,0 +1,195 @@
+/*
+ * 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 "sockutils.h"
+#include "portability.h"
+#include "rpcap-protocol.h"
+#include <pcap/pcap.h>
+
+/*
+ * This file contains functions used both by the rpcap client and the
+ * rpcap daemon.
+ */
+
+/*
+ * This function sends a RPCAP error to our peer.
+ *
+ * It has to be called when the main program detects an error.
+ * It will send to our 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
+ * whether the error can be recovered in some way or if it is a
+ * non-recoverable one.
+ *
+ * \param sock: the socket we are currently using.
+ *
+ * \param ver: the protocol version we want to put in the reply.
+ *
+ * \param errcode: a integer which tells the other party the type of error
+ * we had.
+ *
+ * \param error: an user-allocated (and '0' terminated) buffer that contains
+ * the error description that has to be transmitted to our peer. The
+ * error message cannot be longer than PCAP_ERRBUF_SIZE.
+ *
+ * \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, uint8 ver, unsigned short errcode, const char *error, 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, ver, 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) < 0)
+               return -1;
+
+       return 0;
+}
+
+/*
+ * This function fills in a structure of type rpcap_header.
+ *
+ * It is provided just because the creation of an rpcap header is 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 ver: a value (in the host byte order) which will be placed into the
+ * header.ver field and that represents the protocol version number of the
+ * current message.
+ *
+ * \param type: a value (in the host byte 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 byte 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, representing 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 ver, uint8 type, uint16 value, uint32 length)
+{
+       memset(header, 0, sizeof(struct rpcap_header));
+
+       header->ver = ver;
+       header->type = type;
+       header->value = htons(value);
+       header->plen = htonl(length);
+}
+
+/*
+ * Convert a message type to a string containing the type name.
+ */
+static const char *requests[] =
+{
+       NULL,                           /* not a valid message type */
+       "RPCAP_MSG_ERROR",
+       "RPCAP_MSG_FINDALLIF_REQ",
+       "RPCAP_MSG_OPEN_REQ",
+       "RPCAP_MSG_STARTCAP_REQ",
+       "RPCAP_MSG_UPDATEFILTER_REQ",
+       "RPCAP_MSG_CLOSE",
+       "RPCAP_MSG_PACKET",
+       "RPCAP_MSG_AUTH_REQ",
+       "RPCAP_MSG_STATS_REQ",
+       "RPCAP_MSG_ENDCAP_REQ",
+       "RPCAP_MSG_SETSAMPLING_REQ",
+};
+#define NUM_REQ_TYPES  (sizeof requests / sizeof requests[0])
+
+static const char *replies[] =
+{
+       NULL,
+       NULL,                   /* this would be a reply to RPCAP_MSG_ERROR */
+       "RPCAP_MSG_FINDALLIF_REPLY",
+       "RPCAP_MSG_OPEN_REPLY",
+       "RPCAP_MSG_STARTCAP_REPLY",
+       "RPCAP_MSG_UPDATEFILTER_REPLY",
+       NULL,                   /* this would be a reply to RPCAP_MSG_CLOSE */
+       NULL,                   /* this would be a reply to RPCAP_MSG_PACKET */
+       "RPCAP_MSG_AUTH_REPLY",
+       "RPCAP_MSG_STATS_REPLY",
+       "RPCAP_MSG_ENDCAP_REPLY",
+       "RPCAP_MSG_SETSAMPLING_REPLY",
+};
+#define NUM_REPLY_TYPES        (sizeof replies / sizeof replies[0])
+
+const char *
+rpcap_msg_type_string(uint8 type)
+{
+       if (type & RPCAP_MSG_IS_REPLY) {
+               type &= ~RPCAP_MSG_IS_REPLY;
+               if (type >= NUM_REPLY_TYPES)
+                       return NULL;
+               return replies[type];
+       } else {
+               if (type >= NUM_REQ_TYPES)
+                       return NULL;
+               return requests[type];
+       }
+}
diff --git a/rpcap-protocol.h b/rpcap-protocol.h
new file mode 100644 (file)
index 0000000..8ae8b62
--- /dev/null
@@ -0,0 +1,423 @@
+/*
+ * 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 __RPCAP_PROTOCOL_H__
+#define __RPCAP_PROTOCOL_H__
+
+#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. */
+
+/*
+ * Minimum and maximum supported versions of the protocol.
+ *
+ * If new message types are added, the protocol version MUST be changed,
+ * so that a client knows, from the negotiated protocol version, what
+ * messages can be sent to the server.
+ *
+ * If the format of an existing message type is changed, the protocol
+ * version MUST be changed, so that each side knows, from the negotiated
+ * protocol version, what format should be used.
+ *
+ * The RPCAP_MSG_ERROR format MUST not change, as it's used to, among
+ * other things, report "incorrect version number" errors, where, if
+ * the format changed, the sender of the message might not know what
+ * versions the recipient would understand, or might know a version
+ * they support (the version number they sent) but might not know
+ * the format of the message in that version.
+ *
+ * Other message versions SHOULD not change, as that would complicate
+ * the process of interpreting the message, making it version-dependent.
+ * Introducing a new message with a new format is preferable.
+ *
+ * Version negotiation is done as part of the authentication process:
+ *
+ * The client sends an authentication request, with a version number
+ * of 0.  All servers must accept authentication requests with a version
+ * number of 0, even if they don't support version 0 for any other
+ * requests.
+ *
+ * The server attempts to authenticate the client.  If that succeeds,
+ * older servers - which only support version 0 - will send an
+ * authentication reply with no payload.  Newer servers - which might
+ * support other versions - will send an authentication reply with
+ * a payload giving the minimum and maximum versions it supports.
+ *
+ * The client attempts to find the largest version number that is
+ * in both its range of supported versions and the server's supported
+ * versions.  If it fails, it gives up; otherwise, it uses that version.
+ */
+#define RPCAP_MIN_VERSION 0
+#define RPCAP_MAX_VERSION 0
+
+/*
+ * Version numbers are unsigned, so if RPCAP_MIN_VERSION is 0, they
+ * are >= the minimum version, by definition; don't check against
+ * RPCAP_MIN_VERSION, as you may get compiler warnings that the
+ * comparison will always succeed.
+ */
+#if RPCAP_MIN_VERSION == 0
+#define RPCAP_VERSION_IS_SUPPORTED(v)  \
+       ((v) <= RPCAP_MAX_VERSION)
+#else
+#define RPCAP_VERSION_IS_SUPPORTED(v)  \
+       ((v) >= RPCAP_MIN_VERSION && (v) <= RPCAP_MAX_VERSION)
+#endif
+
+/*
+ * 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 client in active mode, when the client waits for incoming
+ * connections from other hosts
+ */
+#define RPCAP_HOSTLIST_SEP " ,;\n\r"
+
+/*********************************************************
+ *                                                       *
+ * Protocol messages formats                             *
+ *                                                       *
+ *********************************************************/
+/*
+ * WARNING: This file defines some structures that are used to transfer
+ * data on the network.
+ * Note that your 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-bit boundary, but be careful in any case.
+ *
+ * The layout of these structures MUST not be changed.  If a packet
+ * format is different in different versions of the protocol, versions
+ * of the structure should be provided for all the different versions or
+ * version ranges (if more than one version of the protocol has the same
+ * layout) that we support.
+ */
+
+/*
+ * WARNING: These typedefs MUST be of a specific size.
+ * You might have to change them on your platform.
+ *
+ * XXX - use the C99 types?  Microsoft's newer versions of Visual Studio
+ * support them.
+ */
+typedef unsigned char uint8;   /* 8-bit unsigned integer */
+typedef unsigned short uint16; /* 16-bit unsigned integer */
+typedef unsigned int uint32;   /* 32-bit unsigned integer */
+typedef int int32;             /* 32-bit signed integer */
+
+/* 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 data that may appear at the end of an authentication reply,
+ * giving the minimum and maximum versions of the protocol that the
+ * server supports.
+ *
+ * Older servers don't provide this; they support only version 0.
+ */
+struct rpcap_authreply
+{
+       uint8 minvers;  /* Minimum version supported */
+       uint8 maxvers;  /* Maximum version supported */
+};
+
+/* 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 an address as sent over the wire.
+ *
+ * Do *NOT* use struct sockaddr_storage, as the layout for that is
+ * machine-dependent.
+ *
+ * RFC 2553 gives two sample layouts, both of which are 128 bytes long,
+ * both of which are aligned on an 8-byte boundary, and both of which
+ * have 2 bytes before the address data.
+ *
+ * However, one has a 2-byte address family value at the beginning
+ * and the other has a 1-byte address length value and a 1-byte
+ * address family value; this reflects the fact that the original
+ * BSD sockaddr structure had a 2-byte address family value, which
+ * was later changed to a 1-byte address length value and a 1-byte
+ * address family value, when support for variable-length OSI
+ * network-layer addresses was added.
+ *
+ * Furthermore, Solaris's struct sockaddr_storage is 256 bytes
+ * long.
+ *
+ * This structure is supposed to be aligned on an 8-byte boundary;
+ * the message header is 8 bytes long, so we don't have to do
+ * anything to ensure it's aligned on that boundary within a packet,
+ * so we just define it as 128 bytes long, with a 2-byte address
+ * family.  (We only support IPv4 and IPv6 addresses, which are fixed-
+ * length.)  That way, it's the same size as sockaddr_storage on
+ * Windows, and it'll look like what an older Windows client will
+ * expect.
+ *
+ * In addition, do *NOT* use the host's AF_ value for an address,
+ * as the value for AF_INET6 is machine-dependent.  We use the
+ * Windows value, so it'll look like what an older Windows client
+ * will expect.
+ *
+ * (The Windows client is the only one that has been distributed
+ * as a standard part of *pcap; UN*X clients are probably built
+ * from source by the user or administrator, so they're in a
+ * better position to upgrade an old client.  Therefore, we
+ * try to make what goes over the wire look like what comes
+ * from a Windows server.)
+ */
+struct rpcap_sockaddr
+{
+       uint16  family;                 /* Address family */
+       char    data[128-2];            /* Data */
+};
+
+/*
+ * Format of an IPv4 address as sent over the wire.
+ */
+#define RPCAP_AF_INET  2               /* Value on all OSes */
+struct rpcap_sockaddr_in
+{
+       uint16  family;                 /* Address family */
+       uint16  port;                   /* Port number */
+       uint32  addr;                   /* IPv4 address */
+       uint8   zero[8];                /* Padding */
+};
+
+/*
+ * Format of an IPv6 address as sent over the wire.
+ */
+#define RPCAP_AF_INET6 23              /* Value on Windows */
+struct rpcap_sockaddr_in6
+{
+       uint16  family;                 /* Address family */
+       uint16  port;                   /* Port number */
+       uint32  flowinfo;               /* IPv6 flow information */
+       uint8   addr[16];               /* IPv6 address */
+       uint32  scope_id;               /* Scope zone index */
+};
+
+/* Format of the message for the address listing (findalldevs command) */
+struct rpcap_findalldevs_ifaddr
+{
+       struct rpcap_sockaddr addr;             /* Network address */
+       struct rpcap_sockaddr netmask;          /* Netmask for that address */
+       struct rpcap_sockaddr broadaddr;        /* Broadcast address for that address */
+       struct rpcap_sockaddr 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 */
+};
+
+/*
+ * Messages field coding.
+ *
+ * These values are used in messages sent over the network, and MUST
+ * not be changed.
+ */
+#define RPCAP_MSG_IS_REPLY             0x080   /* Flag indicating a reply */
+
+#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      (RPCAP_MSG_FINDALLIF_REQ | RPCAP_MSG_IS_REPLY)          /* Keeps the list of all the remote interfaces */
+#define RPCAP_MSG_OPEN_REPLY           (RPCAP_MSG_OPEN_REQ | RPCAP_MSG_IS_REPLY)               /* The remote device has been opened correctly */
+#define RPCAP_MSG_STARTCAP_REPLY       (RPCAP_MSG_STARTCAP_REQ | RPCAP_MSG_IS_REPLY)           /* The capture is starting correctly */
+#define RPCAP_MSG_UPDATEFILTER_REPLY   (RPCAP_MSG_UPDATEFILTER_REQ | RPCAP_MSG_IS_REPLY)       /* The filter has been applied correctly on the remote device */
+#define RPCAP_MSG_AUTH_REPLY           (RPCAP_MSG_AUTH_REQ | RPCAP_MSG_IS_REPLY)               /* Sends a message that says 'ok, authorization successful' */
+#define RPCAP_MSG_STATS_REPLY          (RPCAP_MSG_STATS_REQ | RPCAP_MSG_IS_REPLY)              /* Message that keeps the network statistics */
+#define RPCAP_MSG_ENDCAP_REPLY         (RPCAP_MSG_ENDCAP_REQ | RPCAP_MSG_IS_REPLY)             /* Confirms that the capture stopped successfully */
+#define RPCAP_MSG_SETSAMPLING_REPLY    (RPCAP_MSG_SETSAMPLING_REQ | RPCAP_MSG_IS_REPLY)                /* Confirms that the capture stopped successfully */
+
+#define RPCAP_STARTCAPREQ_FLAG_PROMISC         0x00000001      /* Enables promiscuous mode (default: disabled) */
+#define RPCAP_STARTCAPREQ_FLAG_DGRAM           0x00000002      /* Use a datagram (i.e. UDP) connection for the data stream (default: use TCP)*/
+#define RPCAP_STARTCAPREQ_FLAG_SERVEROPEN      0x00000004      /* The server has to open the data connection toward the client */
+#define RPCAP_STARTCAPREQ_FLAG_INBOUND         0x00000008      /* Capture only inbound packets (take care: the flag has no effect with promiscuous enabled) */
+#define RPCAP_STARTCAPREQ_FLAG_OUTBOUND                0x00000010      /* Capture only outbound packets (take care: the flag has no effect 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.
+ *
+ * These values are used in messages sent over the network, and MUST
+ * not be changed.
+ */
+#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 */
+#define PCAP_ERR_AUTH_FAILED           18      /* The user couldn't be authenticated */
+#define PCAP_ERR_TLS_REQUIRED          19      /* The server requires TLS to connect */
+#define PCAP_ERR_AUTH_TYPE_NOTSUP      20      /* The authentication type isn't supported */
+
+/*
+ * \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
+
+/*********************************************************
+ *                                                       *
+ * Routines used by the rpcap client and rpcap daemon    *
+ *                                                       *
+ *********************************************************/
+
+#include "sockutils.h"
+
+extern void rpcap_createhdr(struct rpcap_header *header, uint8 ver, uint8 type, uint16 value, uint32 length);
+extern const char *rpcap_msg_type_string(uint8 type);
+extern int rpcap_senderror(SOCKET sock, uint8 ver, uint16 errcode, const char *error, char *errbuf);
+
+#endif
diff --git a/rpcapd/CMakeLists.txt b/rpcapd/CMakeLists.txt
new file mode 100644 (file)
index 0000000..1821c85
--- /dev/null
@@ -0,0 +1,163 @@
+if(UNIX)
+  check_function_exists(crypt HAVE_CRYPT_IN_SYSTEM_LIBRARIES)
+  if(HAVE_CRYPT_IN_SYSTEM_LIBRARIES)
+    set(HAVE_CRYPT TRUE)
+  else(HAVE_CRYPT_IN_SYSTEM_LIBRARIES)
+    check_library_exists(crypt crypt "" HAVE_CRYPT_IN_LIBCRYPT)
+    if(HAVE_CRYPT_IN_LIBCRYPT)
+      set(RPCAPD_LINK_LIBRARIES ${RPCAPD_LINK_LIBRARIES} crypt)
+      set(HAVE_CRYPT TRUE)
+    else(HAVE_CRYPT_IN_LIBCRYPT)
+      message(WARNING "crypt() not found. Won't be able to build rpcapd.")
+    endif(HAVE_CRYPT_IN_LIBCRYPT)
+  endif(HAVE_CRYPT_IN_SYSTEM_LIBRARIES)
+endif(UNIX)
+
+#
+# On UN*X, we need pthreads and crypt().
+#
+if(WIN32 OR ((CMAKE_USE_PTHREADS_INIT OR PTHREADS_FOUND) AND HAVE_CRYPT))
+  if(UNIX)
+    #
+    # Do we have getspnam()?
+    #
+    check_function_exists(getspnam HAVE_GETSPNAM)
+
+    #
+    # Find library needed for getaddrinfo.
+    # NOTE: if you hand check_library_exists as its last argument a variable
+    # that's been set, it skips the test, so we need different variables.
+    #
+    include(CheckLibraryExists)
+    check_function_exists(getaddrinfo STDLIBS_HAVE_GETADDRINFO)
+    if(NOT STDLIBS_HAVE_GETADDRINFO)
+      check_library_exists(xnet getaddrinfo "" LIBXNET_HAS_GETADDRINFO)
+      if(LIBXNET_HAS_GETADDRINFO)
+        set(RPCAPD_LINK_LIBRARIES ${RPCAPD_LINK_LIBRARIES} xnet)
+      else(LIBXNET_HAS_GETADDRINFO)
+        include(CMakePushCheckState)
+        cmake_push_check_state()
+        set(CMAKE_REQUIRED_LIBRARIES nsl)
+        check_library_exists(socket getaddrinfo "" LIBSOCKET_HAS_GETADDRINFO)
+        cmake_pop_check_state()
+        if(LIBSOCKET_HAS_GETADDRINFO)
+          set(RPCAPD_LINK_LIBRARIES ${RPCAPD_LINK_LIBRARIES} socket nsl)
+        endif(LIBSOCKET_HAS_GETADDRINFO)
+      endif(LIBXNET_HAS_GETADDRINFO)
+    endif(NOT STDLIBS_HAVE_GETADDRINFO)
+  endif(UNIX)
+
+  if(WIN32)
+    set(RPCAPD_EXTRA_SOURCES
+        win32-svc.c
+        ${pcap_SOURCE_DIR}/missing/getopt.c
+        ${pcap_SOURCE_DIR}/missing/win_snprintf.c
+        rpcapd.rc)
+    include_directories(${pcap_SOURCE_DIR}/rpcapd ${pcap_SOURCE_DIR}/missing)
+  endif(WIN32)
+
+  add_executable(rpcapd
+    daemon.c
+    fileconf.c
+    log.c
+    rpcapd.c
+    ${pcap_SOURCE_DIR}/rpcap-protocol.c
+    ${pcap_SOURCE_DIR}/sockutils.c
+    ${pcap_SOURCE_DIR}/fmtutils.c
+    ${RPCAPD_EXTRA_SOURCES}
+  )
+
+  if(NOT C_ADDITIONAL_FLAGS STREQUAL "")
+    set_target_properties(rpcapd PROPERTIES COMPILE_FLAGS ${C_ADDITIONAL_FLAGS})
+  endif()
+
+  #
+  # By default, build rpcapd universal with the appropriate set of
+  # architectures for the OS on which we're doing the build.
+  #
+  if(APPLE AND "${CMAKE_OSX_ARCHITECTURES}" STREQUAL "")
+    #
+    # Get the major version of Darwin.
+    #
+    string(REGEX MATCH "^([0-9]+)" SYSTEM_VERSION_MAJOR "${CMAKE_SYSTEM_VERSION}")
+
+    if(SYSTEM_VERSION_MAJOR EQUAL 9)
+      #
+      # Leopard.  Build for 32-bit x86 and 32-bit PowerPC, with
+      # 32-bit x86 first.
+      #
+      set(OSX_PROGRAM_ARCHITECTURES "i386;ppc")
+    elseif(SYSTEM_VERSION_MAJOR EQUAL 10)
+      #
+      # Snow Leopard.  Build for x86-64 and 32-bit x86, with
+      # x86-64 first.
+      #
+      set(OSX_PROGRAM_ARCHITECTURES "x86_64;i386")
+    else()
+      #
+      # Post-Snow Leopard.  Build only for x86-64.
+      # XXX - update if and when Apple adds ARM-based Macs.
+      # (You're on your own for iOS etc.)
+      #
+      set(OSX_PROGRAM_ARCHITECTURES "x86_64")
+    endif()
+
+    set_target_properties(rpcapd PROPERTIES
+      OSX_ARCHITECTURES "${OSX_PROGRAM_ARCHITECTURES}")
+  endif()
+
+  if(WIN32)
+    target_link_libraries(rpcapd ${LIBRARY_NAME}
+      ${RPCAPD_LINK_LIBRARIES} ${PCAP_LINK_LIBRARIES} ${CMAKE_THREAD_LIBS_INIT})
+  else(WIN32)
+    target_link_libraries(rpcapd ${LIBRARY_NAME}_static
+      ${RPCAPD_LINK_LIBRARIES} ${PCAP_LINK_LIBRARIES} ${CMAKE_THREAD_LIBS_INIT})
+  endif(WIN32)
+
+  ######################################
+  # Install rpcap daemon and man pages
+  ######################################
+
+  #
+  # "Define GNU standard installation directories", which actually
+  # are also defined, to some degree, by autotools, and at least
+  # some of which are general UN*X conventions.
+  #
+  include(GNUInstallDirs)
+
+  set(MANADMIN_EXPAND rpcapd.manadmin.in)
+
+  set(MANFILE_EXPAND rpcapd-config.manfile.in)
+
+  if(MSVC AND CMAKE_SIZEOF_VOID_P EQUAL 8)
+    install(TARGETS rpcapd DESTINATION bin/amd64)
+  else(MSVC AND CMAKE_SIZEOF_VOID_P EQUAL 8)
+    install(TARGETS rpcapd DESTINATION bin)
+  endif(MSVC AND CMAKE_SIZEOF_VOID_P EQUAL 8)
+
+  # On UN*X, and on Windows when not using MSVC, generate process man
+  # pages and arrange that they be installed.
+  if(NOT MSVC)
+    #
+    # Man pages.
+    #
+    # For each section of the manual for which we have man pages
+    # that require macro expansion, do the expansion.
+    #
+    set(MANADMIN "")
+    foreach(TEMPLATE_MANPAGE ${MANADMIN_EXPAND})
+        string(REPLACE ".manadmin.in" ".${MAN_ADMIN_COMMANDS}" MANPAGE ${TEMPLATE_MANPAGE})
+        configure_file(${CMAKE_CURRENT_SOURCE_DIR}/${TEMPLATE_MANPAGE} ${CMAKE_CURRENT_BINARY_DIR}/${MANPAGE} @ONLY)
+        set(MANADMIN ${MANADMIN} ${CMAKE_CURRENT_BINARY_DIR}/${MANPAGE})
+    endforeach(TEMPLATE_MANPAGE)
+    install(FILES ${MANADMIN} DESTINATION ${CMAKE_INSTALL_MANDIR}/man${MAN_ADMIN_COMMANDS})
+
+    set(MANFILE "")
+    foreach(TEMPLATE_MANPAGE ${MANFILE_EXPAND})
+        string(REPLACE ".manfile.in" ".${MAN_FILE_FORMATS}" MANPAGE ${TEMPLATE_MANPAGE})
+        configure_file(${CMAKE_CURRENT_SOURCE_DIR}/${TEMPLATE_MANPAGE} ${CMAKE_CURRENT_BINARY_DIR}/${MANPAGE} @ONLY)
+        set(MANFILE ${MANFILE} ${CMAKE_CURRENT_BINARY_DIR}/${MANPAGE})
+    endforeach(TEMPLATE_MANPAGE)
+    install(FILES ${MANFILE} DESTINATION ${CMAKE_INSTALL_MANDIR}/man${MAN_FILE_FORMATS})
+  endif(NOT MSVC)
+endif(WIN32 OR ((CMAKE_USE_PTHREADS_INIT OR PTHREADS_FOUND) AND HAVE_CRYPT))
diff --git a/rpcapd/Makefile.in b/rpcapd/Makefile.in
new file mode 100644 (file)
index 0000000..88e632a
--- /dev/null
@@ -0,0 +1,141 @@
+#  Copyright (c) 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.
+
+#
+# Various configurable paths (remember to edit Makefile.in, not Makefile)
+#
+
+# Top level hierarchy
+prefix = @prefix@
+exec_prefix = @exec_prefix@
+datarootdir = @datarootdir@
+# Pathname of directory to install the configure program
+bindir = @bindir@
+# Pathname of directory to install the rpcapd daemon
+sbindir = @sbindir@
+# Pathname of directory to install the include files
+includedir = @includedir@
+# Pathname of directory to install the library
+libdir =  @libdir@
+# Pathname of directory to install the man pages
+mandir = @mandir@
+
+# VPATH
+srcdir = @srcdir@
+VPATH = @srcdir@
+
+#
+# You shouldn't need to edit anything below.
+#
+
+LD = /usr/bin/ld
+CC = @CC@
+AR = @AR@
+LN_S = @LN_S@
+MKDEP = @MKDEP@
+CCOPT = @V_CCOPT@
+INCLS = -I. -I.. -I@srcdir@ -I@srcdir@/.. @V_INCLS@
+DEFS = @DEFS@ @V_DEFS@
+ADDLOBJS = @ADDLOBJS@
+ADDLARCHIVEOBJS = @ADDLARCHIVEOBJS@
+LIBS = @LIBS@
+PTHREAD_LIBS = @PTHREAD_LIBS@
+CROSSFLAGS=
+CFLAGS = @CFLAGS@   ${CROSSFLAGS}
+LDFLAGS = @LDFLAGS@ ${CROSSFLAGS}
+DYEXT = @DYEXT@
+V_RPATH_OPT = @V_RPATH_OPT@
+DEPENDENCY_CFLAG = @DEPENDENCY_CFLAG@
+PROG=libpcap
+RPCAPD_LIBS = @RPCAPD_LIBS@
+
+# Standard CFLAGS
+FULL_CFLAGS = $(CCOPT) @V_PROG_CCOPT_FAT@ $(INCLS) $(DEFS) $(CFLAGS)
+
+INSTALL = @INSTALL@
+INSTALL_PROGRAM = @INSTALL_PROGRAM@
+INSTALL_DATA = @INSTALL_DATA@
+
+# 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
+# problem if you don't own the file but can write to the directory.
+.c.o:
+       @rm -f $@
+       $(CC) $(FULL_CFLAGS) -c $(srcdir)/$*.c
+
+SRC =  daemon.c \
+       fileconf.c \
+       log.c \
+       rpcapd.c
+
+OBJ =  $(SRC:.c=.o) ../rpcap-protocol.o ../sockutils.o ../fmtutils.o
+PUBHDR =
+
+HDR = $(PUBHDR) log.h
+
+TAGFILES = \
+       $(SRC) $(HDR)
+
+CLEANFILES = $(OBJ) rpcapd
+
+MANADMIN = \
+       rpcapd.manadmin.in
+
+MANFILE = \
+       rpcapd-config.manfile.in
+
+rpcapd: $(OBJ) ../libpcap.a
+       $(CC) $(CCOPT) $(CFLAGS) $(LDFLAGS) @V_PROG_LDFLAGS_FAT@ \
+           -o $@ $(OBJ) ../libpcap.a $(LIBS) $(RPCAPD_LIBS) $(PTHREAD_LIBS)
+clean:
+       rm -f $(CLEANFILES)
+
+distclean: clean
+       rm -f Makefile config.cache config.log config.status \
+           config.h stamp-h stamp-h.in
+       rm -f $(MANADMIN:.in=) $(MANFILE:.in=)
+       rm -rf autom4te.cache
+
+install: rpcapd
+       [ -d $(DESTDIR)$(sbindir) ] || \
+           (mkdir -p $(DESTDIR)$(sbindir); chmod 755 $(DESTDIR)$(sbindir))
+       $(INSTALL_PROGRAM) rpcapd $(DESTDIR)$(sbindir)/rpcapd
+       [ -d $(DESTDIR)$(mandir)/man@MAN_ADMIN_COMMANDS@ ] || \
+           (mkdir -p $(DESTDIR)$(mandir)/man@MAN_ADMIN_COMMANDS@; chmod 755 $(DESTDIR)$(mandir)/man@MAN_ADMIN_COMMANDS@)
+       [ -d $(DESTDIR)$(mandir)/man@MAN_FILE_FORMATS@ ] || \
+           (mkdir -p $(DESTDIR)$(mandir)/man@MAN_FILE_FORMATS@; chmod 755 $(DESTDIR)$(mandir)/man@MAN_FILE_FORMATS@)
+       for i in $(MANADMIN); do \
+               $(INSTALL_DATA) `echo $$i | sed 's/.manadmin.in/.manadmin/'` \
+                   $(DESTDIR)$(mandir)/man@MAN_ADMIN_COMMANDS@/`echo $$i | sed 's/.manadmin.in/.@MAN_ADMIN_COMMANDS@/'`; done
+       for i in $(MANFILE); do \
+               $(INSTALL_DATA) `echo $$i | sed 's/.manfile.in/.manfile/'` \
+                   $(DESTDIR)$(mandir)/man@MAN_FILE_FORMATS@/`echo $$i | sed 's/.manfile.in/.@MAN_FILE_FORMATS@/'`; done
+
+uninstall:
+       rm -f $(DESTDIR)$(sbindir)/rpcapd
+       for i in $(MANADMIN); do \
+               rm -f $(DESTDIR)$(mandir)/man@MAN_ADMIN_COMMANDS@/`echo $$i | sed 's/.manadmin.in/.@MAN_ADMIN_COMMANDS@/'`; done
+       for i in $(MANFILE); do \
+               rm -f $(DESTDIR)$(mandir)/man@MAN_FILE_FORMATS@/`echo $$i | sed 's/.manfile.in/.@MAN_FILE_FORMATS@/'`; done
+
+tags: $(TAGFILES)
+       ctags -wtd $(TAGFILES)
+
+depend:
+       ../$(MKDEP) -c "$(CC)" -m "$(DEPENDENCY_CFLAG)" $(CFLAGS) $(DEFS) $(INCLS) $(SRC)
similarity index 55%
rename from Win32/Include/inetprivate.h
rename to rpcapd/config_params.h
index e25ed3d..c219ce1 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1999 - 2003
+ * Copyright (c) 2002 - 2003
  * NetGroup, Politecnico di Torino (Italy)
  * All rights reserved.
  *
  *
  */
 
-#include <sys/types.h>
-#include <string.h>
-#include <stdlib.h>
-#include <ctype.h>
-#include <net/netdb.h>
-#include <stdio.h>
-#include <errno.h>
-#include <arpa/nameser.h>
+#ifndef __CONFIG_PARAMS_H__
+#define __CONFIG_PARAMS_H__
+
+//
+// Parameters set from the configuration file.
+//
+
+#define MAX_LINE 2048          /* Maximum chars allowed for the host list (in passive mode) */
+#define MAX_HOST_LIST 64000
+#define MAX_ACTIVE_LIST 10
+
+struct active_pars
+{
+       char address[MAX_LINE + 1];     // keeps the network address (either numeric or literal) to of the active client
+       char port[MAX_LINE + 1];        // keeps the network port to bind to
+       int ai_family;                  // address faimly to use
+};
+
+extern char hostlist[MAX_HOST_LIST + 1];       //!< Keeps the list of the hosts that are allowed to connect to this server
+extern struct active_pars activelist[MAX_ACTIVE_LIST];         //!< Keeps the list of the hosts (host, port) on which I want to connect to (active mode)
+extern int nullAuthAllowed;                    //!< '1' if we permit NULL authentication, '0' otherwise
+extern char loadfile[MAX_LINE + 1];            //!< Name of the file from which we have to load the configuration
 
-extern void _sethtent(int f);
-extern void _endhtent(void);
-extern struct hostent *_gethtent(void);
-extern struct hostent *_gethtbyname(const char *name);
-extern struct hostent *_gethtbyaddr(const char *addr, int len,
-                int type);
-extern int _validuser(FILE *hostf, const char *rhost,
-                const char *luser, const char *ruser, int baselen);
-extern int _checkhost(const char *rhost, const char *lhost, int len);
-#if 0
-extern void putlong(u_long l, u_char *msgp);
-extern void putshort(u_short l, u_char *msgp);
-extern u_int32_t _getlong(register const u_char *msgp);
-extern u_int16_t _getshort(register const u_char *msgp);
-extern void p_query(char *msg);
-extern void fp_query(char *msg, FILE *file);
-extern char *p_cdname(char *cp, char *msg, FILE *file);
-extern char *p_rr(char *cp, char *msg, FILE *file);
-extern char *p_type(int type);
-extern char * p_class(int class);
-extern char *p_time(u_long value);
 #endif
-extern char * hostalias(const char *name);
-extern void sethostfile(char *name);
-extern void _res_close (void);
-extern void ruserpass(const char *host, char **aname, char **apass);
diff --git a/rpcapd/daemon.c b/rpcapd/daemon.c
new file mode 100644 (file)
index 0000000..209dba2
--- /dev/null
@@ -0,0 +1,2747 @@
+/*
+ * 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
+
+#include "ftmacros.h"
+#include "varattrs.h"
+
+#include <errno.h>             // for the errno variable
+#include <stdlib.h>            // for malloc(), free(), ...
+#include <string.h>            // for strlen(), ...
+
+#ifdef _WIN32
+  #include <process.h>         // for threads
+#else
+  #include <unistd.h>
+  #include <pthread.h>
+  #include <signal.h>
+  #include <sys/time.h>
+  #include <sys/types.h>       // for select() and such
+  #include <pwd.h>             // for password management
+#endif
+
+#ifdef HAVE_GETSPNAM
+#include <shadow.h>            // for password management
+#endif
+
+#include <pcap.h>              // for libpcap/WinPcap calls
+
+#include "fmtutils.h"
+#include "sockutils.h"         // for socket calls
+#include "portability.h"
+#include "rpcap-protocol.h"
+#include "daemon.h"
+#include "log.h"
+
+//
+// Timeout, in seconds, when we're waiting for a client to send us an
+// authentication request; if they don't send us a request within that
+// interval, we drop the connection, so we don't stay stuck forever.
+//
+#define RPCAP_TIMEOUT_INIT 90
+
+//
+// Timeout, in seconds, when we're waiting for an authenticated client
+// to send us a request, if a capture isn't in progress; if they don't
+// send us a request within that interval, we drop the connection, so
+// we don't stay stuck forever.
+//
+#define RPCAP_TIMEOUT_RUNTIME 180
+
+//
+// Time, in seconds, that we wait after a failed authentication attempt
+// before processing the next request; this prevents a client from
+// rapidly trying different accounts or passwords.
+//
+#define RPCAP_SUSPEND_WRONGAUTH 1
+
+// Parameters for the service loop.
+struct daemon_slpars
+{
+       SOCKET sockctrl;        //!< SOCKET ID of the control connection
+       int isactive;           //!< Not null if the daemon has to run in active mode
+       int nullAuthAllowed;    //!< '1' if we permit NULL authentication, '0' otherwise
+};
+
+//
+// Data for a session managed by a thread.
+// It includes both a Boolean indicating whether we *have* a thread,
+// and a platform-dependent (UN*X vs. Windows) identifier for the
+// thread; on Windows, we could use an invalid handle to indicate
+// that we don't have a thread, but there *is* no portable "no thread"
+// value for a pthread_t on UN*X.
+//
+struct session {
+       SOCKET sockctrl;
+       SOCKET sockdata;
+       uint8 protocol_version;
+       pcap_t *fp;
+       unsigned int TotCapt;
+       int     have_thread;
+#ifdef _WIN32
+       HANDLE thread;
+#else
+       pthread_t thread;
+#endif
+};
+
+// Locally defined functions
+static int daemon_msg_err(SOCKET sockctrl, uint32 plen);
+static int daemon_msg_auth_req(struct daemon_slpars *pars, uint32 plen);
+static int daemon_AuthUserPwd(char *username, char *password, char *errbuf);
+
+static int daemon_msg_findallif_req(uint8 ver, struct daemon_slpars *pars,
+    uint32 plen);
+
+static int daemon_msg_open_req(uint8 ver, struct daemon_slpars *pars,
+    uint32 plen, char *source, size_t sourcelen);
+static int daemon_msg_startcap_req(uint8 ver, struct daemon_slpars *pars,
+    uint32 plen, char *source, struct session **sessionp,
+    struct rpcap_sampling *samp_param);
+static int daemon_msg_endcap_req(uint8 ver, struct daemon_slpars *pars,
+    struct session *session);
+
+static int daemon_msg_updatefilter_req(uint8 ver, struct daemon_slpars *pars,
+    struct session *session, uint32 plen);
+static int daemon_unpackapplyfilter(SOCKET sockctrl, struct session *session, uint32 *plenp, char *errbuf);
+
+static int daemon_msg_stats_req(uint8 ver, struct daemon_slpars *pars,
+    struct session *session, uint32 plen, struct pcap_stat *stats,
+    unsigned int svrcapt);
+
+static int daemon_msg_setsampling_req(uint8 ver, struct daemon_slpars *pars,
+    uint32 plen, struct rpcap_sampling *samp_param);
+
+static void daemon_seraddr(struct sockaddr_storage *sockaddrin, struct rpcap_sockaddr *sockaddrout);
+#ifdef _WIN32
+static unsigned __stdcall daemon_thrdatamain(void *ptr);
+#else
+static void *daemon_thrdatamain(void *ptr);
+static void noop_handler(int sign);
+#endif
+
+static int rpcapd_recv_msg_header(SOCKET sock, struct rpcap_header *headerp);
+static int rpcapd_recv(SOCKET sock, char *buffer, size_t toread, uint32 *plen, char *errmsgbuf);
+static int rpcapd_discard(SOCKET sock, uint32 len);
+static void session_close(struct session *);
+
+static int is_url(const char *source);
+
+int
+daemon_serviceloop(SOCKET sockctrl, int isactive, char *passiveClients,
+    int nullAuthAllowed)
+{
+       struct daemon_slpars pars;              // service loop parameters
+       char errbuf[PCAP_ERRBUF_SIZE + 1];      // keeps the error string, prior to be printed
+       char errmsgbuf[PCAP_ERRBUF_SIZE + 1];   // buffer for errors to send to the client
+       int host_port_check_status;
+       int nrecv;
+       struct rpcap_header header;             // RPCAP message general header
+       uint32 plen;                            // payload length from header
+       int authenticated = 0;                  // 1 if the client has successfully authenticated
+       char source[PCAP_BUF_SIZE+1];           // keeps the string that contains the interface to open
+       int got_source = 0;                     // 1 if we've gotten the source from an open request
+#ifndef _WIN32
+       struct sigaction action;
+#endif
+       struct session *session = NULL;         // struct session main variable
+       const char *msg_type_string;            // string for message type
+       int client_told_us_to_close = 0;        // 1 if the client told us to close the capture
+
+       // needed to save the values of the statistics
+       struct pcap_stat stats;
+       unsigned int svrcapt;
+
+       struct rpcap_sampling samp_param;       // in case sampling has been requested
+
+       // 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
+       int retval;                             // select() return value
+
+       *errbuf = 0;    // Initialize errbuf
+
+       // Set parameters structure
+       pars.sockctrl = sockctrl;
+       pars.isactive = isactive;               // active mode
+       pars.nullAuthAllowed = nullAuthAllowed;
+
+       //
+       // We have a connection.
+       //
+       // If it's a passive mode connection, check whether the connecting
+       // host is among the ones allowed.
+       //
+       // In either case, we were handed a copy of the host list; free it
+       // as soon as we're done with it.
+       //
+       if (pars.isactive)
+       {
+               // Nothing to do.
+               free(passiveClients);
+               passiveClients = NULL;
+       }
+       else
+       {
+               struct sockaddr_storage from;
+               socklen_t fromlen;
+
+               //
+               // Get the address of the other end of the connection.
+               //
+               fromlen = sizeof(struct sockaddr_storage);
+               if (getpeername(pars.sockctrl, (struct sockaddr *)&from,
+                   &fromlen) == -1)
+               {
+                       sock_geterror("getpeername()", errmsgbuf, PCAP_ERRBUF_SIZE);
+                       if (rpcap_senderror(pars.sockctrl, 0, PCAP_ERR_NETW, errmsgbuf, errbuf) == -1)
+                               rpcapd_log(LOGPRIO_ERROR, "Send to client failed: %s", errbuf);
+                       goto end;
+               }
+
+               //
+               // Are they in the list of host/port combinations we allow?
+               //
+               host_port_check_status = sock_check_hostlist(passiveClients, RPCAP_HOSTLIST_SEP, &from, errmsgbuf, PCAP_ERRBUF_SIZE);
+               free(passiveClients);
+               passiveClients = NULL;
+               if (host_port_check_status < 0)
+               {
+                       if (host_port_check_status == -2) {
+                               //
+                               // We got an error; log it.
+                               //
+                               rpcapd_log(LOGPRIO_ERROR, "%s", errmsgbuf);
+                       }
+
+                       //
+                       // Sorry, we can't let you in.
+                       //
+                       if (rpcap_senderror(pars.sockctrl, 0, PCAP_ERR_HOSTNOAUTH, errmsgbuf, errbuf) == -1)
+                               rpcapd_log(LOGPRIO_ERROR, "Send to client failed: %s", errbuf);
+                       goto end;
+               }
+       }
+
+#ifndef _WIN32
+       //
+       // Catch SIGUSR1, but do nothing.  We use it to interrupt the
+       // capture thread to break it out of a loop in which it's
+       // blocked waiting for packets to arrive.
+       //
+       // We don't want interrupted system calls to restart, so that
+       // the read routine for the pcap_t gets EINTR rather than
+       // restarting if it's blocked in a system call.
+       //
+       memset(&action, 0, sizeof (action));
+       action.sa_handler = noop_handler;
+       action.sa_flags = 0;
+       sigemptyset(&action.sa_mask);
+       sigaction(SIGUSR1, &action, NULL);
+#endif
+
+       //
+       // The client must first authenticate; loop until they send us a
+       // message with a version we support and credentials we accept,
+       // they send us a close message indicating that they're giving up,
+       // or we get a network error or other fatal error.
+       //
+       while (!authenticated)
+       {
+               //
+               // If we're not in active mode, we use select(), with a
+               // timeout, to wait for an authentication request; if
+               // the timeout expires, we drop the connection, so that
+               // a client can't just connect to us and leave us
+               // waiting forever.
+               //
+               if (!pars.isactive)
+               {
+                       FD_ZERO(&rfds);
+                       // We do not have to block here
+                       tv.tv_sec = RPCAP_TIMEOUT_INIT;
+                       tv.tv_usec = 0;
+
+                       FD_SET(pars.sockctrl, &rfds);
+
+                       retval = select(pars.sockctrl + 1, &rfds, NULL, NULL, &tv);
+                       if (retval == -1)
+                       {
+                               sock_geterror("select() failed", errmsgbuf, PCAP_ERRBUF_SIZE);
+                               if (rpcap_senderror(pars.sockctrl, 0, PCAP_ERR_NETW, errmsgbuf, errbuf) == -1)
+                                       rpcapd_log(LOGPRIO_ERROR, "Send to client failed: %s", errbuf);
+                               goto end;
+                       }
+
+                       // The timeout has expired
+                       // So, this was a fake connection. Drop it down
+                       if (retval == 0)
+                       {
+                               if (rpcap_senderror(pars.sockctrl, 0, PCAP_ERR_INITTIMEOUT, "The RPCAP initial timeout has expired", errbuf) == -1)
+                                       rpcapd_log(LOGPRIO_ERROR, "Send to client failed: %s", errbuf);
+                               goto end;
+                       }
+               }
+
+               //
+               // Read the message header from the client.
+               //
+               nrecv = rpcapd_recv_msg_header(pars.sockctrl, &header);
+               if (nrecv == -1)
+               {
+                       // Fatal error.
+                       goto end;
+               }
+               if (nrecv == -2)
+               {
+                       // Client closed the connection.
+                       goto end;
+               }
+
+               plen = header.plen;
+
+               //
+               // While we're in the authentication pharse, all requests
+               // must use version 0.
+               //
+               if (header.ver != 0)
+               {
+                       //
+                       // Send it back to them with their version.
+                       //
+                       if (rpcap_senderror(pars.sockctrl, header.ver,
+                           PCAP_ERR_WRONGVER,
+                           "RPCAP version in requests in the authentication phase must be 0",
+                           errbuf) == -1)
+                       {
+                               // That failed; log a message and give up.
+                               rpcapd_log(LOGPRIO_ERROR, "Send to client failed: %s", errbuf);
+                               goto end;
+                       }
+
+                       // Discard the rest of the message and drop the
+                       // connection.
+                       (void)rpcapd_discard(pars.sockctrl, plen);
+                       goto end;
+               }
+
+               switch (header.type)
+               {
+                       case RPCAP_MSG_AUTH_REQ:
+                               retval = daemon_msg_auth_req(&pars, plen);
+                               if (retval == -1)
+                               {
+                                       // Fatal error; a message has
+                                       // been logged, so just give up.
+                                       goto end;
+                               }
+                               if (retval == -2)
+                               {
+                                       // Non-fatal error; we sent back
+                                       // an error message, so let them
+                                       // try again.
+                                       continue;
+                               }
+
+                               // OK, we're authenticated; we sent back
+                               // a reply, so start serving requests.
+                               authenticated = 1;
+                               break;
+
+                       case RPCAP_MSG_CLOSE:
+                               //
+                               // The client is giving up.
+                               // Discard the rest of the message, if
+                               // there is anything more.
+                               //
+                               (void)rpcapd_discard(pars.sockctrl, plen);
+                               // We're done with this client.
+                               goto end;
+
+                       case RPCAP_MSG_ERROR:
+                               // Log this and close the connection?
+                               // XXX - is this what happens in active
+                               // mode, where *we* initiate the
+                               // connection, and the client gives us
+                               // an error message rather than a "let
+                               // me log in" message, indicating that
+                               // we're not allowed to connect to them?
+                               (void)daemon_msg_err(pars.sockctrl, plen);
+                               goto end;
+
+                       case RPCAP_MSG_FINDALLIF_REQ:
+                       case RPCAP_MSG_OPEN_REQ:
+                       case RPCAP_MSG_STARTCAP_REQ:
+                       case RPCAP_MSG_UPDATEFILTER_REQ:
+                       case RPCAP_MSG_STATS_REQ:
+                       case RPCAP_MSG_ENDCAP_REQ:
+                       case RPCAP_MSG_SETSAMPLING_REQ:
+                               //
+                               // These requests can't be sent until
+                               // the client is authenticated.
+                               //
+                               msg_type_string = rpcap_msg_type_string(header.type);
+                               if (msg_type_string != NULL)
+                               {
+                                       pcap_snprintf(errmsgbuf, PCAP_ERRBUF_SIZE, "%s request sent before authentication was completed", msg_type_string);
+                               }
+                               else
+                               {
+                                       pcap_snprintf(errmsgbuf, PCAP_ERRBUF_SIZE, "Message of type %u sent before authentication was completed", header.type);
+                               }
+                               if (rpcap_senderror(pars.sockctrl, header.ver,
+                                   PCAP_ERR_WRONGMSG, errmsgbuf, errbuf) == -1)
+                               {
+                                       rpcapd_log(LOGPRIO_ERROR, "Send to client failed: %s", errbuf);
+                                       goto end;
+                               }
+                               // Discard the rest of the message.
+                               if (rpcapd_discard(pars.sockctrl, plen) == -1)
+                               {
+                                       // Network error.
+                                       goto end;
+                               }
+                               break;
+
+                       case RPCAP_MSG_PACKET:
+                       case RPCAP_MSG_FINDALLIF_REPLY:
+                       case RPCAP_MSG_OPEN_REPLY:
+                       case RPCAP_MSG_STARTCAP_REPLY:
+                       case RPCAP_MSG_UPDATEFILTER_REPLY:
+                       case RPCAP_MSG_AUTH_REPLY:
+                       case RPCAP_MSG_STATS_REPLY:
+                       case RPCAP_MSG_ENDCAP_REPLY:
+                       case RPCAP_MSG_SETSAMPLING_REPLY:
+                               //
+                               // These are server-to-client messages.
+                               //
+                               msg_type_string = rpcap_msg_type_string(header.type);
+                               if (msg_type_string != NULL)
+                               {
+                                       pcap_snprintf(errmsgbuf, PCAP_ERRBUF_SIZE, "Server-to-client message %s received from client", msg_type_string);
+                               }
+                               else
+                               {
+                                       pcap_snprintf(errmsgbuf, PCAP_ERRBUF_SIZE, "Server-to-client message of type %u received from client", header.type);
+                               }
+                               if (rpcap_senderror(pars.sockctrl, header.ver,
+                                   PCAP_ERR_WRONGMSG, errmsgbuf, errbuf) == -1)
+                               {
+                                       rpcapd_log(LOGPRIO_ERROR, "Send to client failed: %s", errbuf);
+                                       goto end;
+                               }
+                               // Discard the rest of the message.
+                               if (rpcapd_discard(pars.sockctrl, plen) == -1)
+                               {
+                                       // Fatal error.
+                                       goto end;
+                               }
+                               break;
+
+                       default:
+                               //
+                               // Unknown message type.
+                               //
+                               pcap_snprintf(errmsgbuf, PCAP_ERRBUF_SIZE, "Unknown message type %u", header.type);
+                               if (rpcap_senderror(pars.sockctrl, header.ver,
+                                   PCAP_ERR_WRONGMSG, errmsgbuf, errbuf) == -1)
+                               {
+                                       rpcapd_log(LOGPRIO_ERROR, "Send to client failed: %s", errbuf);
+                                       goto end;
+                               }
+                               // Discard the rest of the message.
+                               if (rpcapd_discard(pars.sockctrl, plen) == -1)
+                               {
+                                       // Fatal error.
+                                       goto end;
+                               }
+                               break;
+               }
+       }
+
+       //
+       // OK, the client has authenticated itself, and we can start
+       // processing regular requests from it.
+       //
+
+       //
+       // We don't have any statistics yet.
+       //
+       stats.ps_ifdrop = 0;
+       stats.ps_recv = 0;
+       stats.ps_drop = 0;
+       svrcapt = 0;
+
+       //
+       // Service requests.
+       //
+       for (;;)
+       {
+               errbuf[0] = 0;  // clear errbuf
+
+               // Avoid zombies connections; check if the connection is opens but no commands are performed
+               // from more than RPCAP_TIMEOUT_RUNTIME
+               // Conditions:
+               // - I have to be in normal mode (no active mode)
+               // - if the device is open, I don't have to be in the middle of a capture (session->sockdata)
+               // - if the device is closed, I have always to check if a new command arrives
+               //
+               // Be carefully: the capture can have been started, but an error occurred (so session != NULL, but
+               //  sockdata is 0
+               if ((!pars.isactive) &&  ((session == NULL) || ((session != NULL) && (session->sockdata == 0))))
+               {
+                       // Check for the initial timeout
+                       FD_ZERO(&rfds);
+                       // We do not have to block here
+                       tv.tv_sec = RPCAP_TIMEOUT_RUNTIME;
+                       tv.tv_usec = 0;
+
+                       FD_SET(pars.sockctrl, &rfds);
+
+                       retval = select(pars.sockctrl + 1, &rfds, NULL, NULL, &tv);
+                       if (retval == -1)
+                       {
+                               sock_geterror("select() failed", errmsgbuf, PCAP_ERRBUF_SIZE);
+                               if (rpcap_senderror(pars.sockctrl, 0,
+                                   PCAP_ERR_NETW, errmsgbuf, errbuf) == -1)
+                                       rpcapd_log(LOGPRIO_ERROR, "Send to client failed: %s", errbuf);
+                               goto end;
+                       }
+
+                       // The timeout has expired
+                       // So, this was a fake connection. Drop it down
+                       if (retval == 0)
+                       {
+                               if (rpcap_senderror(pars.sockctrl, 0,
+                                   PCAP_ERR_INITTIMEOUT,
+                                   "The RPCAP initial timeout has expired",
+                                   errbuf) == -1)
+                                       rpcapd_log(LOGPRIO_ERROR, "Send to client failed: %s", errbuf);
+                               goto end;
+                       }
+               }
+
+               //
+               // Read the message header from the client.
+               //
+               nrecv = rpcapd_recv_msg_header(pars.sockctrl, &header);
+               if (nrecv == -1)
+               {
+                       // Fatal error.
+                       goto end;
+               }
+               if (nrecv == -2)
+               {
+                       // Client closed the connection.
+                       goto end;
+               }
+
+               plen = header.plen;
+
+               //
+               // Did the client specify a protocol version that we
+               // support?
+               //
+               if (!RPCAP_VERSION_IS_SUPPORTED(header.ver))
+               {
+                       //
+                       // Tell them it's not a supported version.
+                       // Send the error message with their version,
+                       // so they don't reject it as having the wrong
+                       // version.
+                       //
+                       if (rpcap_senderror(pars.sockctrl,
+                           header.ver, PCAP_ERR_WRONGVER,
+                           "RPCAP version in message isn't supported by the server",
+                           errbuf) == -1)
+                       {
+                               // That failed; log a message and give up.
+                               rpcapd_log(LOGPRIO_ERROR, "Send to client failed: %s", errbuf);
+                               goto end;
+                       }
+
+                       // Discard the rest of the message.
+                       (void)rpcapd_discard(pars.sockctrl, plen);
+                       // Give up on them.
+                       goto end;
+               }
+
+               switch (header.type)
+               {
+                       case RPCAP_MSG_ERROR:           // The other endpoint reported an error
+                       {
+                               (void)daemon_msg_err(pars.sockctrl, plen);
+                               // Do nothing; just exit; the error code is already into the errbuf
+                               // XXX - actually exit....
+                               break;
+                       }
+
+                       case RPCAP_MSG_FINDALLIF_REQ:
+                       {
+                               if (daemon_msg_findallif_req(header.ver, &pars, plen) == -1)
+                               {
+                                       // Fatal error; a message has
+                                       // been logged, so just give up.
+                                       goto end;
+                               }
+                               break;
+                       }
+
+                       case RPCAP_MSG_OPEN_REQ:
+                       {
+                               //
+                               // Process the open request, and keep
+                               // the source from it, for use later
+                               // when the capture is started.
+                               //
+                               // XXX - we don't care if the client sends
+                               // us multiple open requests, the last
+                               // one wins.
+                               //
+                               retval = daemon_msg_open_req(header.ver, &pars,
+                                   plen, source, sizeof(source));
+                               if (retval == -1)
+                               {
+                                       // Fatal error; a message has
+                                       // been logged, so just give up.
+                                       goto end;
+                               }
+                               got_source = 1;
+                               break;
+                       }
+
+                       case RPCAP_MSG_STARTCAP_REQ:
+                       {
+                               if (!got_source)
+                               {
+                                       // They never told us what device
+                                       // to capture on!
+                                       if (rpcap_senderror(pars.sockctrl,
+                                           header.ver,
+                                           PCAP_ERR_STARTCAPTURE,
+                                           "No capture device was specified",
+                                           errbuf) == -1)
+                                       {
+                                               // Fatal error; log an
+                                               // error and  give up.
+                                               rpcapd_log(LOGPRIO_ERROR, "Send to client failed: %s", errbuf);
+                                               goto end;
+                                       }
+                                       if (rpcapd_discard(pars.sockctrl, plen) == -1)
+                                       {
+                                               goto end;
+                                       }
+                                       break;
+                               }
+
+                               if (daemon_msg_startcap_req(header.ver, &pars,
+                                   plen, source, &session, &samp_param) == -1)
+                               {
+                                       // Fatal error; a message has
+                                       // been logged, so just give up.
+                                       goto end;
+                               }
+                               break;
+                       }
+
+                       case RPCAP_MSG_UPDATEFILTER_REQ:
+                       {
+                               if (session)
+                               {
+                                       if (daemon_msg_updatefilter_req(header.ver,
+                                           &pars, session, plen) == -1)
+                                       {
+                                               // Fatal error; a message has
+                                               // been logged, so just give up.
+                                               goto end;
+                                       }
+                               }
+                               else
+                               {
+                                       if (rpcap_senderror(pars.sockctrl,
+                                           header.ver, PCAP_ERR_UPDATEFILTER,
+                                           "Device not opened. Cannot update filter",
+                                           errbuf) == -1)
+                                       {
+                                               // That failed; log a message and give up.
+                                               rpcapd_log(LOGPRIO_ERROR, "Send to client failed: %s", errbuf);
+                                               goto end;
+                                       }
+                               }
+                               break;
+                       }
+
+                       case RPCAP_MSG_CLOSE:           // The other endpoint close the pcap session
+                       {
+                               //
+                               // Indicate to our caller that the client
+                               // closed the control connection.
+                               // This is used only in case of active mode.
+                               //
+                               client_told_us_to_close = 1;
+                               rpcapd_log(LOGPRIO_DEBUG, "The other end system asked to close the connection.");
+                               goto end;
+                       }
+
+                       case RPCAP_MSG_STATS_REQ:
+                       {
+                               if (daemon_msg_stats_req(header.ver, &pars,
+                                   session, plen, &stats, svrcapt) == -1)
+                               {
+                                       // Fatal error; a message has
+                                       // been logged, so just give up.
+                                       goto end;
+                               }
+                               break;
+                       }
+
+                       case RPCAP_MSG_ENDCAP_REQ:              // The other endpoint close the current capture session
+                       {
+                               if (session)
+                               {
+                                       // Save statistics (we can need them in the future)
+                                       if (pcap_stats(session->fp, &stats))
+                                       {
+                                               svrcapt = session->TotCapt;
+                                       }
+                                       else
+                                       {
+                                               stats.ps_ifdrop = 0;
+                                               stats.ps_recv = 0;
+                                               stats.ps_drop = 0;
+                                               svrcapt = 0;
+                                       }
+
+                                       if (daemon_msg_endcap_req(header.ver,
+                                           &pars, session) == -1)
+                                       {
+                                               free(session);
+                                               session = NULL;
+                                               // Fatal error; a message has
+                                               // been logged, so just give up.
+                                               goto end;
+                                       }
+                                       free(session);
+                                       session = NULL;
+                               }
+                               else
+                               {
+                                       rpcap_senderror(pars.sockctrl,
+                                           header.ver, PCAP_ERR_ENDCAPTURE,
+                                           "Device not opened. Cannot close the capture",
+                                           errbuf);
+                               }
+                               break;
+                       }
+
+                       case RPCAP_MSG_SETSAMPLING_REQ:
+                       {
+                               if (daemon_msg_setsampling_req(header.ver,
+                                   &pars, plen, &samp_param) == -1)
+                               {
+                                       // Fatal error; a message has
+                                       // been logged, so just give up.
+                                       goto end;
+                               }
+                               break;
+                       }
+
+                       case RPCAP_MSG_AUTH_REQ:
+                       {
+                               //
+                               // We're already authenticated; you don't
+                               // get to reauthenticate.
+                               //
+                               rpcapd_log(LOGPRIO_INFO, "The client sent an RPCAP_MSG_AUTH_REQ message after authentication was completed");
+                               if (rpcap_senderror(pars.sockctrl, header.ver,
+                                   PCAP_ERR_WRONGMSG,
+                                   "RPCAP_MSG_AUTH_REQ request sent after authentication was completed",
+                                   errbuf) == -1)
+                               {
+                                       rpcapd_log(LOGPRIO_ERROR, "Send to client failed: %s", errbuf);
+                                       goto end;
+                               }
+                               // Discard the rest of the message.
+                               if (rpcapd_discard(pars.sockctrl, plen) == -1)
+                               {
+                                       // Fatal error.
+                                       goto end;
+                               }
+                               goto end;
+
+                       case RPCAP_MSG_PACKET:
+                       case RPCAP_MSG_FINDALLIF_REPLY:
+                       case RPCAP_MSG_OPEN_REPLY:
+                       case RPCAP_MSG_STARTCAP_REPLY:
+                       case RPCAP_MSG_UPDATEFILTER_REPLY:
+                       case RPCAP_MSG_AUTH_REPLY:
+                       case RPCAP_MSG_STATS_REPLY:
+                       case RPCAP_MSG_ENDCAP_REPLY:
+                       case RPCAP_MSG_SETSAMPLING_REPLY:
+                               //
+                               // These are server-to-client messages.
+                               //
+                               msg_type_string = rpcap_msg_type_string(header.type);
+                               if (msg_type_string != NULL)
+                               {
+                                       rpcapd_log(LOGPRIO_INFO, "The client sent a %s server-to-client message", msg_type_string);
+                                       pcap_snprintf(errmsgbuf, PCAP_ERRBUF_SIZE, "Server-to-client message %s received from client", msg_type_string);
+                               }
+                               else
+                               {
+                                       rpcapd_log(LOGPRIO_INFO, "The client sent a server-to-client message of type %u", header.type);
+                                       pcap_snprintf(errmsgbuf, PCAP_ERRBUF_SIZE, "Server-to-client message of type %u received from client", header.type);
+                               }
+                               if (rpcap_senderror(pars.sockctrl, header.ver,
+                                   PCAP_ERR_WRONGMSG, errmsgbuf, errbuf) == -1)
+                               {
+                                       rpcapd_log(LOGPRIO_ERROR, "Send to client failed: %s", errbuf);
+                                       goto end;
+                               }
+                               // Discard the rest of the message.
+                               if (rpcapd_discard(pars.sockctrl, plen) == -1)
+                               {
+                                       // Fatal error.
+                                       goto end;
+                               }
+                               goto end;
+
+                       default:
+                               //
+                               // Unknown message type.
+                               //
+                               rpcapd_log(LOGPRIO_INFO, "The client sent a message of type %u", header.type);
+                               pcap_snprintf(errmsgbuf, PCAP_ERRBUF_SIZE, "Unknown message type %u", header.type);
+                               if (rpcap_senderror(pars.sockctrl, header.ver,
+                                   PCAP_ERR_WRONGMSG, errbuf, errmsgbuf) == -1)
+                               {
+                                       rpcapd_log(LOGPRIO_ERROR, "Send to client failed: %s", errbuf);
+                                       goto end;
+                               }
+                               // Discard the rest of the message.
+                               if (rpcapd_discard(pars.sockctrl, plen) == -1)
+                               {
+                                       // Fatal error.
+                                       goto end;
+                               }
+                               goto end;
+                       }
+               }
+       }
+
+end:
+       // The service loop is finishing up.
+       // If we have a capture session running, close it.
+       if (session)
+       {
+               session_close(session);
+               free(session);
+               session = NULL;
+       }
+
+       sock_close(sockctrl, NULL, 0);
+
+       // Print message and return
+       rpcapd_log(LOGPRIO_DEBUG, "I'm exiting from the child loop");
+
+       return client_told_us_to_close;
+}
+
+/*
+ * This handles the RPCAP_MSG_ERR message.
+ */
+static int
+daemon_msg_err(SOCKET sockctrl, uint32 plen)
+{
+       char errbuf[PCAP_ERRBUF_SIZE];
+       char remote_errbuf[PCAP_ERRBUF_SIZE];
+
+       if (plen >= PCAP_ERRBUF_SIZE)
+       {
+               /*
+                * Message is too long; just read as much of it as we
+                * can into the buffer provided, and discard the rest.
+                */
+               if (sock_recv(sockctrl, remote_errbuf, PCAP_ERRBUF_SIZE - 1,
+                   SOCK_RECEIVEALL_YES|SOCK_EOF_IS_ERROR, errbuf,
+                   PCAP_ERRBUF_SIZE) == -1)
+               {
+                       // Network error.
+                       rpcapd_log(LOGPRIO_ERROR, "Read from client failed: %s", errbuf);
+                       return -1;
+               }
+               if (rpcapd_discard(sockctrl, plen - (PCAP_ERRBUF_SIZE - 1)) == -1)
+               {
+                       // Network error.
+                       return -1;
+               }
+
+               /*
+                * Null-terminate it.
+                */
+               remote_errbuf[PCAP_ERRBUF_SIZE - 1] = '\0';
+       }
+       else if (plen == 0)
+       {
+               /* Empty error string. */
+               remote_errbuf[0] = '\0';
+       }
+       else
+       {
+               if (sock_recv(sockctrl, remote_errbuf, plen,
+                   SOCK_RECEIVEALL_YES|SOCK_EOF_IS_ERROR, errbuf,
+                   PCAP_ERRBUF_SIZE) == -1)
+               {
+                       // Network error.
+                       rpcapd_log(LOGPRIO_ERROR, "Read from client failed: %s", errbuf);
+                       return -1;
+               }
+
+               /*
+                * Null-terminate it.
+                */
+               remote_errbuf[plen] = '\0';
+       }
+       // Log the message
+       rpcapd_log(LOGPRIO_ERROR, "Error from client: %s", remote_errbuf);
+       return 0;
+}
+
+/*
+ * This handles the RPCAP_MSG_AUTH_REQ message.
+ * It checks if the authentication credentials supplied by the user are valid.
+ *
+ * This function is called if the daemon receives a RPCAP_MSG_AUTH_REQ
+ * message in its authentication loop.  It reads the body of the
+ * authentication message from the network and checks whether the
+ * credentials are valid.
+ *
+ * \param sockctrl: the socket for the control connection.
+ *
+ * \param nullAuthAllowed: '1' if the NULL authentication is allowed.
+ *
+ * \param errbuf: a user-allocated buffer in which the error message
+ * (if one) has to be written.  It must be at least PCAP_ERRBUF_SIZE
+ * bytes long.
+ *
+ * \return '0' if everything is fine, '-1' if an unrecoverable error occurred,
+ * or '-2' if the authentication failed.  For errors, an error message is
+ * returned in the 'errbuf' variable; this gives a message for the
+ * unrecoverable error or for the authentication failure.
+ */
+static int
+daemon_msg_auth_req(struct daemon_slpars *pars, uint32 plen)
+{
+       char errbuf[PCAP_ERRBUF_SIZE];          // buffer for network errors
+       char errmsgbuf[PCAP_ERRBUF_SIZE];       // buffer for errors to send to the client
+       int status;
+       struct rpcap_auth auth;                 // RPCAP authentication header
+       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_authreply *authreply;      // authentication reply message
+
+       status = rpcapd_recv(pars->sockctrl, (char *) &auth, sizeof(struct rpcap_auth), &plen, errmsgbuf);
+       if (status == -1)
+       {
+               return -1;
+       }
+       if (status == -2)
+       {
+               goto error;
+       }
+
+       switch (ntohs(auth.type))
+       {
+               case RPCAP_RMTAUTH_NULL:
+               {
+                       if (!pars->nullAuthAllowed)
+                       {
+                               // Send the client an error reply.
+                               pcap_snprintf(errmsgbuf, PCAP_ERRBUF_SIZE,
+                                   "Authentication failed; NULL authentication not permitted.");
+                               if (rpcap_senderror(pars->sockctrl, 0,
+                                   PCAP_ERR_AUTH_FAILED, errmsgbuf, errbuf) == -1)
+                               {
+                                       // That failed; log a message and give up.
+                                       rpcapd_log(LOGPRIO_ERROR, "Send to client failed: %s", errbuf);
+                                       return -1;
+                               }
+                               goto error_noreply;
+                       }
+                       break;
+               }
+
+               case RPCAP_RMTAUTH_PWD:
+               {
+                       char *username, *passwd;
+                       uint32 usernamelen, passwdlen;
+
+                       usernamelen = ntohs(auth.slen1);
+                       username = (char *) malloc (usernamelen + 1);
+                       if (username == NULL)
+                       {
+                               pcap_fmt_errmsg_for_errno(errmsgbuf,
+                                   PCAP_ERRBUF_SIZE, errno, "malloc() failed");
+                               goto error;
+                       }
+                       status = rpcapd_recv(pars->sockctrl, username, usernamelen, &plen, errmsgbuf);
+                       if (status == -1)
+                       {
+                               free(username);
+                               return -1;
+                       }
+                       if (status == -2)
+                       {
+                               free(username);
+                               goto error;
+                       }
+                       username[usernamelen] = '\0';
+
+                       passwdlen = ntohs(auth.slen2);
+                       passwd = (char *) malloc (passwdlen + 1);
+                       if (passwd == NULL)
+                       {
+                               pcap_fmt_errmsg_for_errno(errmsgbuf,
+                                   PCAP_ERRBUF_SIZE, errno, "malloc() failed");
+                               free(username);
+                               goto error;
+                       }
+                       status = rpcapd_recv(pars->sockctrl, passwd, passwdlen, &plen, errmsgbuf);
+                       if (status == -1)
+                       {
+                               free(username);
+                               free(passwd);
+                               return -1;
+                       }
+                       if (status == -2)
+                       {
+                               free(username);
+                               free(passwd);
+                               goto error;
+                       }
+                       passwd[passwdlen] = '\0';
+
+                       if (daemon_AuthUserPwd(username, passwd, errmsgbuf))
+                       {
+                               //
+                               // Authentication failed.  Let the client
+                               // know.
+                               //
+                               free(username);
+                               free(passwd);
+                               if (rpcap_senderror(pars->sockctrl, 0,
+                                   PCAP_ERR_AUTH_FAILED, errmsgbuf, errbuf) == -1)
+                               {
+                                       // That failed; log a message and give up.
+                                       rpcapd_log(LOGPRIO_ERROR, "Send to client failed: %s", errbuf);
+                                       return -1;
+                               }
+
+                               //
+                               // Suspend for 1 second, so that they can't
+                               // hammer us with repeated tries with an
+                               // attack such as a dictionary attack.
+                               //
+                               // WARNING: this delay is inserted only
+                               // at this point; if the client closes the
+                               // connection and reconnects, the suspension
+                               // time does not have any effect.
+                               //
+                               sleep_secs(RPCAP_SUSPEND_WRONGAUTH);
+                               goto error_noreply;
+                       }
+
+                       free(username);
+                       free(passwd);
+                       break;
+                       }
+
+               default:
+                       pcap_snprintf(errmsgbuf, PCAP_ERRBUF_SIZE,
+                           "Authentication type not recognized.");
+                       if (rpcap_senderror(pars->sockctrl, 0,
+                           PCAP_ERR_AUTH_TYPE_NOTSUP, errmsgbuf, errbuf) == -1)
+                       {
+                               // That failed; log a message and give up.
+                               rpcapd_log(LOGPRIO_ERROR, "Send to client failed: %s", errbuf);
+                               return -1;
+                       }
+                       goto error_noreply;
+       }
+
+       // The authentication succeeded; let the client know.
+       if (sock_bufferize(NULL, sizeof(struct rpcap_header), NULL, &sendbufidx,
+           RPCAP_NETBUF_SIZE, SOCKBUF_CHECKONLY, errmsgbuf, PCAP_ERRBUF_SIZE) == -1)
+               goto error;
+
+       rpcap_createhdr((struct rpcap_header *) sendbuf, 0,
+           RPCAP_MSG_AUTH_REPLY, 0, sizeof(struct rpcap_authreply));
+
+       authreply = (struct rpcap_authreply *) &sendbuf[sendbufidx];
+
+       if (sock_bufferize(NULL, sizeof(struct rpcap_authreply), NULL, &sendbufidx,
+           RPCAP_NETBUF_SIZE, SOCKBUF_CHECKONLY, errmsgbuf, PCAP_ERRBUF_SIZE) == -1)
+               goto error;
+
+       //
+       // Indicate to our peer what versions we support.
+       //
+       memset(authreply, 0, sizeof(struct rpcap_authreply));
+       authreply->minvers = RPCAP_MIN_VERSION;
+       authreply->maxvers = RPCAP_MAX_VERSION;
+
+       // Send the reply.
+       if (sock_send(pars->sockctrl, sendbuf, sendbufidx, errbuf, PCAP_ERRBUF_SIZE) == -1)
+       {
+               // That failed; log a messsage and give up.
+               rpcapd_log(LOGPRIO_ERROR, "Send to client failed: %s", errbuf);
+               return -1;
+       }
+
+       // Check if all the data has been read; if not, discard the data in excess
+       if (rpcapd_discard(pars->sockctrl, plen) == -1)
+       {
+               return -1;
+       }
+
+       return 0;
+
+error:
+       if (rpcap_senderror(pars->sockctrl, 0, PCAP_ERR_AUTH, errmsgbuf,
+           errbuf) == -1)
+       {
+               // That failed; log a message and give up.
+               rpcapd_log(LOGPRIO_ERROR, "Send to client failed: %s", errbuf);
+               return -1;
+       }
+
+error_noreply:
+       // Check if all the data has been read; if not, discard the data in excess
+       if (rpcapd_discard(pars->sockctrl, plen) == -1)
+       {
+               return -1;
+       }
+
+       return -2;
+}
+
+static int
+daemon_AuthUserPwd(char *username, char *password, char *errbuf)
+{
+#ifdef _WIN32
+       /*
+        * Warning: the user which launches the process must have the
+        * SE_TCB_NAME right.
+        * This corresponds to have the "Act as part of the Operating System"
+        * turned on (administrative tools, local security settings, local
+        * policies, user right assignment)
+        * However, it seems to me that if you run it as a service, this
+        * right should be provided by default.
+        *
+        * XXX - hopefully, this returns errors such as ERROR_LOGON_FAILURE,
+        * which merely indicates that the user name or password is
+        * incorrect, not whether it's the user name or the password
+        * that's incorrect, so a client that's trying to brute-force
+        * accounts doesn't know whether it's the user name or the
+        * password that's incorrect, so it doesn't know whether to
+        * stop trying to log in with a given user name and move on
+        * to another user name.
+        */
+       DWORD error;
+       HANDLE Token;
+       char errmsgbuf[PCAP_ERRBUF_SIZE];       // buffer for errors to log
+
+       if (LogonUser(username, ".", password, LOGON32_LOGON_NETWORK, LOGON32_PROVIDER_DEFAULT, &Token) == 0)
+       {
+               pcap_snprintf(errbuf, PCAP_ERRBUF_SIZE, "Authentication failed");
+               error = GetLastError();
+               if (error != ERROR_LOGON_FAILURE)
+               {
+                       // Some error other than an authentication error;
+                       // log it.
+                       pcap_fmt_errmsg_for_win32_err(errmsgbuf,
+                           PCAP_ERRBUF_SIZE, error, "LogonUser() failed");
+                       rpcapd_log(LOGPRIO_ERROR, "%s", errmsgbuf);
+               }
+               return -1;
+       }
+
+       // This call should change the current thread to the selected user.
+       // I didn't test it.
+       if (ImpersonateLoggedOnUser(Token) == 0)
+       {
+               pcap_snprintf(errbuf, PCAP_ERRBUF_SIZE, "Authentication failed");
+               pcap_fmt_errmsg_for_win32_err(errmsgbuf, PCAP_ERRBUF_SIZE,
+                   GetLastError(), "ImpersonateLoggedOnUser() failed");
+               rpcapd_log(LOGPRIO_ERROR, "%s", errmsgbuf);
+               CloseHandle(Token);
+               return -1;
+       }
+
+       CloseHandle(Token);
+       return 0;
+
+#else
+       /*
+        * See
+        *
+        *      http://www.unixpapa.com/incnote/passwd.html
+        *
+        * We use the Solaris/Linux shadow password authentication if
+        * we have getspnam(), otherwise we just do traditional
+        * authentication, which, on some platforms, might work, even
+        * with shadow passwords, if we're running as root.  Traditional
+        * authenticaion won't work if we're not running as root, as
+        * I think these days all UN*Xes either won't return the password
+        * at all with getpwnam() or will only do so if you're root.
+        *
+        * XXX - perhaps what we *should* be using is PAM, if we have
+        * it.  That might hide all the details of username/password
+        * authentication, whether it's done with a visible-to-root-
+        * only password database or some other authentication mechanism,
+        * behind its API.
+        */
+       int error;
+       struct passwd *user;
+       char *user_password;
+#ifdef HAVE_GETSPNAM
+       struct spwd *usersp;
+#endif
+       char *crypt_password;
+
+       // This call is needed to get the uid
+       if ((user = getpwnam(username)) == NULL)
+       {
+               pcap_snprintf(errbuf, PCAP_ERRBUF_SIZE, "Authentication failed");
+               return -1;
+       }
+
+#ifdef HAVE_GETSPNAM
+       // This call is needed to get the password; otherwise 'x' is returned
+       if ((usersp = getspnam(username)) == NULL)
+       {
+               pcap_snprintf(errbuf, PCAP_ERRBUF_SIZE, "Authentication failed");
+               return -1;
+       }
+       user_password = usersp->sp_pwdp;
+#else
+       /*
+        * XXX - what about other platforms?
+        * The unixpapa.com page claims this Just Works on *BSD if you're
+        * running as root - it's from 2000, so it doesn't indicate whether
+        * macOS (which didn't come out until 2001, under the name Mac OS
+        * X) behaves like the *BSDs or not, and might also work on AIX.
+        * HP-UX does something else.
+        *
+        * Again, hopefully PAM hides all that.
+        */
+       user_password = user->pw_passwd;
+#endif
+
+       //
+       // The Single UNIX Specification says that if crypt() fails it
+       // sets errno, but some implementatons that haven't been run
+       // through the SUS test suite might not do so.
+       //
+       errno = 0;
+       crypt_password = crypt(password, user_password);
+       if (crypt_password == NULL)
+       {
+               error = errno;
+               pcap_snprintf(errbuf, PCAP_ERRBUF_SIZE, "Authentication failed");
+               if (error == 0)
+               {
+                       // It didn't set errno.
+                       rpcapd_log(LOGPRIO_ERROR, "crypt() failed");
+               }
+               else
+               {
+                       rpcapd_log(LOGPRIO_ERROR, "crypt() failed: %s",
+                           strerror(error));
+               }
+               return -1;
+       }
+       if (strcmp(user_password, crypt_password) != 0)
+       {
+               pcap_snprintf(errbuf, PCAP_ERRBUF_SIZE, "Authentication failed");
+               return -1;
+       }
+
+       if (setuid(user->pw_uid))
+       {
+               error = errno;
+               pcap_fmt_errmsg_for_errno(errbuf, PCAP_ERRBUF_SIZE,
+                   error, "setuid");
+               rpcapd_log(LOGPRIO_ERROR, "setuid() failed: %s",
+                   strerror(error));
+               return -1;
+       }
+
+/*     if (setgid(user->pw_gid))
+       {
+               error = errno;
+               pcap_fmt_errmsg_for_errno(errbuf, PCAP_ERRBUF_SIZE,
+                   errno, "setgid");
+               rpcapd_log(LOGPRIO_ERROR, "setgid() failed: %s",
+                   strerror(error));
+               return -1;
+       }
+*/
+       return 0;
+
+#endif
+
+}
+
+static int
+daemon_msg_findallif_req(uint8 ver, struct daemon_slpars *pars, uint32 plen)
+{
+       char errbuf[PCAP_ERRBUF_SIZE];          // buffer for network errors
+       char errmsgbuf[PCAP_ERRBUF_SIZE];       // buffer for errors to send to the client
+       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
+       pcap_if_t *alldevs = NULL;              // pointer to the header of the interface chain
+       pcap_if_t *d;                           // temp pointer needed to scan the interface chain
+       struct pcap_addr *address;              // pcap structure that keeps a network address of an interface
+       struct rpcap_findalldevs_if *findalldevs_if;// rpcap structure that packet all the data of an interface together
+       uint32 replylen;                        // length of reply payload
+       uint16 nif = 0;                         // counts the number of interface listed
+
+       // Discard the rest of the message; there shouldn't be any payload.
+       if (rpcapd_discard(pars->sockctrl, plen) == -1)
+       {
+               // Network error.
+               return -1;
+       }
+
+       // Retrieve the device list
+       if (pcap_findalldevs(&alldevs, errmsgbuf) == -1)
+               goto error;
+
+       if (alldevs == NULL)
+       {
+               if (rpcap_senderror(pars->sockctrl, ver, PCAP_ERR_NOREMOTEIF,
+                       "No interfaces found! Make sure libpcap/WinPcap is properly installed"
+                       " and you have the right to access to the remote device.",
+                       errbuf) == -1)
+               {
+                       rpcapd_log(LOGPRIO_ERROR, "Send to client failed: %s", errbuf);
+                       return -1;
+               }
+               return 0;
+       }
+
+       // This checks the number of interfaces and computes the total
+       // length of the payload.
+       replylen = 0;
+       for (d = alldevs; d != NULL; d = d->next)
+       {
+               nif++;
+
+               if (d->description)
+                       replylen += strlen(d->description);
+               if (d->name)
+                       replylen += strlen(d->name);
+
+               replylen += sizeof(struct rpcap_findalldevs_if);
+
+               for (address = d->addresses; address != NULL; address = address->next)
+               {
+                       /*
+                        * Send only IPv4 and IPv6 addresses over the wire.
+                        */
+                       switch (address->addr->sa_family)
+                       {
+                       case AF_INET:
+#ifdef AF_INET6
+                       case AF_INET6:
+#endif
+                               replylen += (sizeof(struct rpcap_sockaddr) * 4);
+                               break;
+
+                       default:
+                               break;
+                       }
+               }
+       }
+
+       // RPCAP findalldevs command
+       if (sock_bufferize(NULL, sizeof(struct rpcap_header), NULL,
+           &sendbufidx, RPCAP_NETBUF_SIZE, SOCKBUF_CHECKONLY, errmsgbuf,
+           PCAP_ERRBUF_SIZE) == -1)
+               goto error;
+
+       rpcap_createhdr((struct rpcap_header *) sendbuf, ver,
+           RPCAP_MSG_FINDALLIF_REPLY, nif, replylen);
+
+       // send the interface list
+       for (d = alldevs; d != NULL; d = d->next)
+       {
+               uint16 lname, ldescr;
+
+               findalldevs_if = (struct rpcap_findalldevs_if *) &sendbuf[sendbufidx];
+
+               if (sock_bufferize(NULL, sizeof(struct rpcap_findalldevs_if), NULL,
+                   &sendbufidx, RPCAP_NETBUF_SIZE, SOCKBUF_CHECKONLY, errmsgbuf, PCAP_ERRBUF_SIZE) == -1)
+                       goto error;
+
+               memset(findalldevs_if, 0, sizeof(struct rpcap_findalldevs_if));
+
+               if (d->description) ldescr = (short) strlen(d->description);
+               else ldescr = 0;
+               if (d->name) lname = (short) strlen(d->name);
+               else lname = 0;
+
+               findalldevs_if->desclen = htons(ldescr);
+               findalldevs_if->namelen = htons(lname);
+               findalldevs_if->flags = htonl(d->flags);
+
+               for (address = d->addresses; address != NULL; address = address->next)
+               {
+                       /*
+                        * Send only IPv4 and IPv6 addresses over the wire.
+                        */
+                       switch (address->addr->sa_family)
+                       {
+                       case AF_INET:
+#ifdef AF_INET6
+                       case AF_INET6:
+#endif
+                               findalldevs_if->naddr++;
+                               break;
+
+                       default:
+                               break;
+                       }
+               }
+               findalldevs_if->naddr = htons(findalldevs_if->naddr);
+
+               if (sock_bufferize(d->name, lname, sendbuf, &sendbufidx,
+                   RPCAP_NETBUF_SIZE, SOCKBUF_BUFFERIZE, errmsgbuf,
+                   PCAP_ERRBUF_SIZE) == -1)
+                       goto error;
+
+               if (sock_bufferize(d->description, ldescr, sendbuf, &sendbufidx,
+                   RPCAP_NETBUF_SIZE, SOCKBUF_BUFFERIZE, errmsgbuf,
+                   PCAP_ERRBUF_SIZE) == -1)
+                       goto error;
+
+               // send all addresses
+               for (address = d->addresses; address != NULL; address = address->next)
+               {
+                       struct rpcap_sockaddr *sockaddr;
+
+                       /*
+                        * Send only IPv4 and IPv6 addresses over the wire.
+                        */
+                       switch (address->addr->sa_family)
+                       {
+                       case AF_INET:
+#ifdef AF_INET6
+                       case AF_INET6:
+#endif
+                               sockaddr = (struct rpcap_sockaddr *) &sendbuf[sendbufidx];
+                               if (sock_bufferize(NULL, sizeof(struct rpcap_sockaddr), NULL,
+                                   &sendbufidx, RPCAP_NETBUF_SIZE, SOCKBUF_CHECKONLY, errmsgbuf, PCAP_ERRBUF_SIZE) == -1)
+                                       goto error;
+                               daemon_seraddr((struct sockaddr_storage *) address->addr, sockaddr);
+
+                               sockaddr = (struct rpcap_sockaddr *) &sendbuf[sendbufidx];
+                               if (sock_bufferize(NULL, sizeof(struct rpcap_sockaddr), NULL,
+                                   &sendbufidx, RPCAP_NETBUF_SIZE, SOCKBUF_CHECKONLY, errmsgbuf, PCAP_ERRBUF_SIZE) == -1)
+                                       goto error;
+                               daemon_seraddr((struct sockaddr_storage *) address->netmask, sockaddr);
+
+                               sockaddr = (struct rpcap_sockaddr *) &sendbuf[sendbufidx];
+                               if (sock_bufferize(NULL, sizeof(struct rpcap_sockaddr), NULL,
+                                   &sendbufidx, RPCAP_NETBUF_SIZE, SOCKBUF_CHECKONLY, errmsgbuf, PCAP_ERRBUF_SIZE) == -1)
+                                       goto error;
+                               daemon_seraddr((struct sockaddr_storage *) address->broadaddr, sockaddr);
+
+                               sockaddr = (struct rpcap_sockaddr *) &sendbuf[sendbufidx];
+                               if (sock_bufferize(NULL, sizeof(struct rpcap_sockaddr), NULL,
+                                   &sendbufidx, RPCAP_NETBUF_SIZE, SOCKBUF_CHECKONLY, errmsgbuf, PCAP_ERRBUF_SIZE) == -1)
+                                       goto error;
+                               daemon_seraddr((struct sockaddr_storage *) address->dstaddr, sockaddr);
+                               break;
+
+                       default:
+                               break;
+                       }
+               }
+       }
+
+       // We no longer need the device list. Free it.
+       pcap_freealldevs(alldevs);
+
+       // Send a final command that says "now send it!"
+       if (sock_send(pars->sockctrl, sendbuf, sendbufidx, errbuf, PCAP_ERRBUF_SIZE) == -1)
+       {
+               rpcapd_log(LOGPRIO_ERROR, "Send to client failed: %s", errbuf);
+               return -1;
+       }
+
+       return 0;
+
+error:
+       if (alldevs)
+               pcap_freealldevs(alldevs);
+
+       if (rpcap_senderror(pars->sockctrl, ver, PCAP_ERR_FINDALLIF,
+           errmsgbuf, errbuf) == -1)
+       {
+               rpcapd_log(LOGPRIO_ERROR, "Send to client failed: %s", errbuf);
+               return -1;
+       }
+       return 0;
+}
+
+/*
+       \param plen: the length of the current message (needed in order to be able
+       to discard excess data in the message, if present)
+*/
+static int
+daemon_msg_open_req(uint8 ver, struct daemon_slpars *pars, uint32 plen,
+    char *source, size_t sourcelen)
+{
+       char errbuf[PCAP_ERRBUF_SIZE];          // buffer for network errors
+       char errmsgbuf[PCAP_ERRBUF_SIZE];       // buffer for errors to send to the client
+       pcap_t *fp;                             // pcap_t main variable
+       int nread;
+       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_openreply *openreply;      // open reply message
+
+       if (plen > sourcelen - 1)
+       {
+               pcap_snprintf(errmsgbuf, PCAP_ERRBUF_SIZE, "Source string too long");
+               goto error;
+       }
+
+       nread = sock_recv(pars->sockctrl, source, plen,
+           SOCK_RECEIVEALL_YES|SOCK_EOF_IS_ERROR, errbuf, PCAP_ERRBUF_SIZE);
+       if (nread == -1)
+       {
+               rpcapd_log(LOGPRIO_ERROR, "Read from client failed: %s", errbuf);
+               return -1;
+       }
+       source[nread] = '\0';
+       plen -= nread;
+
+       // Is this a URL rather than a device?
+       // If so, reject it.
+       if (is_url(source))
+       {
+               pcap_snprintf(errmsgbuf, PCAP_ERRBUF_SIZE, "Source string refers to a remote device");
+               goto error;
+       }
+
+       // Open the selected device
+       // This is a fake open, since we do that only to get the needed parameters, then we close the device again
+       if ((fp = pcap_open_live(source,
+                       1500 /* fake snaplen */,
+                       0 /* no promis */,
+                       1000 /* fake timeout */,
+                       errmsgbuf)) == NULL)
+               goto error;
+
+       // Now, I can send a RPCAP open reply message
+       if (sock_bufferize(NULL, sizeof(struct rpcap_header), NULL, &sendbufidx,
+           RPCAP_NETBUF_SIZE, SOCKBUF_CHECKONLY, errmsgbuf, PCAP_ERRBUF_SIZE) == -1)
+               goto error;
+
+       rpcap_createhdr((struct rpcap_header *) sendbuf, ver,
+           RPCAP_MSG_OPEN_REPLY, 0, sizeof(struct rpcap_openreply));
+
+       openreply = (struct rpcap_openreply *) &sendbuf[sendbufidx];
+
+       if (sock_bufferize(NULL, sizeof(struct rpcap_openreply), NULL, &sendbufidx,
+           RPCAP_NETBUF_SIZE, SOCKBUF_CHECKONLY, errmsgbuf, PCAP_ERRBUF_SIZE) == -1)
+               goto error;
+
+       memset(openreply, 0, sizeof(struct rpcap_openreply));
+       openreply->linktype = htonl(pcap_datalink(fp));
+       openreply->tzoff = 0; /* This is always 0 for live captures */
+
+       // We're done with the pcap_t.
+       pcap_close(fp);
+
+       // Send the reply.
+       if (sock_send(pars->sockctrl, sendbuf, sendbufidx, errbuf, PCAP_ERRBUF_SIZE) == -1)
+       {
+               rpcapd_log(LOGPRIO_ERROR, "Send to client failed: %s", errbuf);
+               return -1;
+       }
+       return 0;
+
+error:
+       if (rpcap_senderror(pars->sockctrl, ver, PCAP_ERR_OPEN,
+           errmsgbuf, errbuf) == -1)
+       {
+               // That failed; log a message and give up.
+               rpcapd_log(LOGPRIO_ERROR, "Send to client failed: %s", errbuf);
+               return -1;
+       }
+
+       // Check if all the data has been read; if not, discard the data in excess
+       if (rpcapd_discard(pars->sockctrl, plen) == -1)
+       {
+               return -1;
+       }
+       return 0;
+}
+
+/*
+       \param plen: the length of the current message (needed in order to be able
+       to discard excess data in the message, if present)
+*/
+static int
+daemon_msg_startcap_req(uint8 ver, struct daemon_slpars *pars, uint32 plen,
+    char *source, struct session **sessionp,
+    struct rpcap_sampling *samp_param _U_)
+{
+       char errbuf[PCAP_ERRBUF_SIZE];          // buffer for network errors
+       char errmsgbuf[PCAP_ERRBUF_SIZE];       // buffer for errors to send to the client
+       char portdata[PCAP_BUF_SIZE];           // temp variable needed to derive the data port
+       char peerhost[PCAP_BUF_SIZE];           // temp variable needed to derive the host name of our peer
+       struct session *session = NULL;         // saves state of session
+       int status;
+       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
+
+       // socket-related variables
+       struct addrinfo hints;                  // temp, needed to open a socket connection
+       struct addrinfo *addrinfo;              // temp, needed to open a socket 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 ret;                                // return value from functions
+
+       // RPCAP-related variables
+       struct rpcap_startcapreq startcapreq;           // start capture request message
+       struct rpcap_startcapreply *startcapreply;      // start capture reply message
+       int serveropen_dp;                                                      // keeps who is going to open the data connection
+
+       addrinfo = NULL;
+
+       status = rpcapd_recv(pars->sockctrl, (char *) &startcapreq,
+           sizeof(struct rpcap_startcapreq), &plen, errmsgbuf);
+       if (status == -1)
+       {
+               goto fatal_error;
+       }
+       if (status == -2)
+       {
+               goto error;
+       }
+
+       startcapreq.flags = ntohs(startcapreq.flags);
+
+       // Create a session structure
+       session = malloc(sizeof(struct session));
+       if (session == NULL)
+       {
+               pcap_snprintf(errmsgbuf, PCAP_ERRBUF_SIZE, "Can't allocate session structure");
+               goto error;
+       }
+
+       session->sockdata = INVALID_SOCKET;
+       // We don't have a thread yet.
+       session->have_thread = 0;
+       //
+       // We *shouldn't* have to initialize the thread indicator
+       // itself, because the compiler *should* realize that we
+       // only use this if have_thread isn't 0, but we *do* have
+       // to do it, because not all compilers *do* realize that.
+       //
+       // There is no "invalid thread handle" value for a UN*X
+       // pthread_t, so we just zero it out.
+       //
+#ifdef _WIN32
+       session->thread = INVALID_HANDLE_VALUE;
+#else
+       memset(&session->thread, 0, sizeof(session->thread));
+#endif
+
+       // Open the selected device
+       if ((session->fp = pcap_open_live(source,
+                       ntohl(startcapreq.snaplen),
+                       (startcapreq.flags & RPCAP_STARTCAPREQ_FLAG_PROMISC) ? 1 : 0 /* local device, other flags not needed */,
+                       ntohl(startcapreq.read_timeout),
+                       errmsgbuf)) == NULL)
+               goto error;
+
+#if 0
+       // Apply sampling parameters
+       fp->rmt_samp.method = samp_param->method;
+       fp->rmt_samp.value = samp_param->value;
+#endif
+
+       /*
+       We're in active mode if:
+       - we're using TCP, and the user wants us to be in active mode
+       - we're using UDP
+       */
+       serveropen_dp = (startcapreq.flags & RPCAP_STARTCAPREQ_FLAG_SERVEROPEN) || (startcapreq.flags & RPCAP_STARTCAPREQ_FLAG_DGRAM) || pars->isactive;
+
+       /*
+       Gets the sockaddr structure referred to the other peer in the ctrl connection
+
+       We need that because:
+       - if we're in passive mode, we need to know the address family we want to use
+       (the same used for the ctrl socket)
+       - if we're in active mode, we need to know the network address of the other host
+       we want to connect to
+       */
+       saddrlen = sizeof(struct sockaddr_storage);
+       if (getpeername(pars->sockctrl, (struct sockaddr *) &saddr, &saddrlen) == -1)
+       {
+               sock_geterror("getpeername()", errmsgbuf, PCAP_ERRBUF_SIZE);
+               goto error;
+       }
+
+       memset(&hints, 0, sizeof(struct addrinfo));
+       hints.ai_socktype = (startcapreq.flags & RPCAP_STARTCAPREQ_FLAG_DGRAM) ? SOCK_DGRAM : SOCK_STREAM;
+       hints.ai_family = saddr.ss_family;
+
+       // Now we have to create a new socket to send packets
+       if (serveropen_dp)              // Data connection is opened by the server toward the client
+       {
+               pcap_snprintf(portdata, sizeof portdata, "%d", ntohs(startcapreq.portdata));
+
+               // Get the name of the other peer (needed to connect to that specific network address)
+               if (getnameinfo((struct sockaddr *) &saddr, saddrlen, peerhost,
+                               sizeof(peerhost), NULL, 0, NI_NUMERICHOST))
+               {
+                       sock_geterror("getnameinfo()", errmsgbuf, PCAP_ERRBUF_SIZE);
+                       goto error;
+               }
+
+               if (sock_initaddress(peerhost, portdata, &hints, &addrinfo, errmsgbuf, PCAP_ERRBUF_SIZE) == -1)
+                       goto error;
+
+               if ((session->sockdata = sock_open(addrinfo, SOCKOPEN_CLIENT, 0, errmsgbuf, PCAP_ERRBUF_SIZE)) == INVALID_SOCKET)
+                       goto error;
+       }
+       else            // Data connection is opened by the client toward the server
+       {
+               hints.ai_flags = AI_PASSIVE;
+
+               // Let's the server socket pick up a free network port for us
+               if (sock_initaddress(NULL, "0", &hints, &addrinfo, errmsgbuf, PCAP_ERRBUF_SIZE) == -1)
+                       goto error;
+
+               if ((session->sockdata = sock_open(addrinfo, SOCKOPEN_SERVER, 1 /* max 1 connection in queue */, errmsgbuf, PCAP_ERRBUF_SIZE)) == INVALID_SOCKET)
+                       goto error;
+
+               // get the complete sockaddr structure used in the data connection
+               saddrlen = sizeof(struct sockaddr_storage);
+               if (getsockname(session->sockdata, (struct sockaddr *) &saddr, &saddrlen) == -1)
+               {
+                       sock_geterror("getsockname()", errmsgbuf, 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()", errmsgbuf, PCAP_ERRBUF_SIZE);
+                       goto error;
+               }
+       }
+
+       // addrinfo is no longer used
+       freeaddrinfo(addrinfo);
+       addrinfo = NULL;
+
+       // Needed to send an error on the ctrl connection
+       session->sockctrl = pars->sockctrl;
+       session->protocol_version = ver;
+
+       // Now I can set the filter
+       ret = daemon_unpackapplyfilter(pars->sockctrl, session, &plen, errmsgbuf);
+       if (ret == -1)
+       {
+               // Fatal error.  A message has been logged; just give up.
+               goto fatal_error;
+       }
+       if (ret == -2)
+       {
+               // Non-fatal error.  Send an error message to the client.
+               goto error;
+       }
+
+       // Now, I can send a RPCAP start capture reply message
+       if (sock_bufferize(NULL, sizeof(struct rpcap_header), NULL, &sendbufidx,
+           RPCAP_NETBUF_SIZE, SOCKBUF_CHECKONLY, errmsgbuf, PCAP_ERRBUF_SIZE) == -1)
+               goto error;
+
+       rpcap_createhdr((struct rpcap_header *) sendbuf, ver,
+           RPCAP_MSG_STARTCAP_REPLY, 0, sizeof(struct rpcap_startcapreply));
+
+       startcapreply = (struct rpcap_startcapreply *) &sendbuf[sendbufidx];
+
+       if (sock_bufferize(NULL, sizeof(struct rpcap_startcapreply), NULL,
+           &sendbufidx, RPCAP_NETBUF_SIZE, SOCKBUF_CHECKONLY, errmsgbuf, PCAP_ERRBUF_SIZE) == -1)
+               goto error;
+
+       memset(startcapreply, 0, sizeof(struct rpcap_startcapreply));
+       startcapreply->bufsize = htonl(pcap_bufsize(session->fp));
+
+       if (!serveropen_dp)
+       {
+               unsigned short port = (unsigned short)strtoul(portdata,NULL,10);
+               startcapreply->portdata = htons(port);
+       }
+
+       if (sock_send(pars->sockctrl, sendbuf, sendbufidx, errbuf, PCAP_ERRBUF_SIZE) == -1)
+       {
+               // That failed; log a message and give up.
+               rpcapd_log(LOGPRIO_ERROR, "Send to client failed: %s", errbuf);
+               goto fatal_error;
+       }
+
+       if (!serveropen_dp)
+       {
+               SOCKET socktemp;        // We need another socket, since we're going to accept() a connection
+
+               // Connection creation
+               saddrlen = sizeof(struct sockaddr_storage);
+
+               socktemp = accept(session->sockdata, (struct sockaddr *) &saddr, &saddrlen);
+
+               if (socktemp == INVALID_SOCKET)
+               {
+                       sock_geterror("accept()", errbuf, PCAP_ERRBUF_SIZE);
+                       rpcapd_log(LOGPRIO_ERROR, "Accept of data connection failed: %s",
+                           errbuf);
+                       goto error;
+               }
+
+               // Now that I accepted the connection, the server socket is no longer needed
+               sock_close(session->sockdata, NULL, 0);
+               session->sockdata = socktemp;
+       }
+
+       // Now we have to create a new thread to receive packets
+#ifdef _WIN32
+       session->thread = (HANDLE)_beginthreadex(NULL, 0, daemon_thrdatamain,
+           (void *) session, 0, NULL);
+       if (session->thread == 0)
+       {
+               pcap_snprintf(errbuf, PCAP_ERRBUF_SIZE, "Error creating the data thread");
+               goto error;
+       }
+#else
+       ret = pthread_create(&session->thread, NULL, daemon_thrdatamain,
+           (void *) session);
+       if (ret != 0)
+       {
+               pcap_fmt_errmsg_for_errno(errbuf, PCAP_ERRBUF_SIZE,
+                   ret, "Error creating the data thread");
+               goto error;
+       }
+#endif
+       session->have_thread = 1;
+
+       // Check if all the data has been read; if not, discard the data in excess
+       if (rpcapd_discard(pars->sockctrl, plen) == -1)
+               goto fatal_error;
+
+       *sessionp = session;
+       return 0;
+
+error:
+       //
+       // Not a fatal error, so send the client an error message and
+       // keep serving client requests.
+       //
+       *sessionp = NULL;
+
+       if (addrinfo)
+               freeaddrinfo(addrinfo);
+
+       if (session)
+       {
+               session_close(session);
+               free(session);
+       }
+
+       if (rpcap_senderror(pars->sockctrl, ver, PCAP_ERR_STARTCAPTURE,
+           errmsgbuf, errbuf) == -1)
+       {
+               // That failed; log a message and give up.
+               rpcapd_log(LOGPRIO_ERROR, "Send to client failed: %s", errbuf);
+               return -1;
+       }
+
+       // Check if all the data has been read; if not, discard the data in excess
+       if (rpcapd_discard(pars->sockctrl, plen) == -1)
+       {
+               // Network error.
+               return -1;
+       }
+
+       return 0;
+
+fatal_error:
+       //
+       // Fatal network error, so don't try to communicate with
+       // the client, just give up.
+       //
+       *sessionp = NULL;
+
+       if (session)
+       {
+               session_close(session);
+               free(session);
+       }
+
+       return -1;
+}
+
+static int
+daemon_msg_endcap_req(uint8 ver, struct daemon_slpars *pars,
+    struct session *session)
+{
+       char errbuf[PCAP_ERRBUF_SIZE];          // buffer for network errors
+       struct rpcap_header header;
+
+       session_close(session);
+
+       rpcap_createhdr(&header, ver, RPCAP_MSG_ENDCAP_REPLY, 0, 0);
+
+       if (sock_send(pars->sockctrl, (char *) &header, sizeof(struct rpcap_header), errbuf, PCAP_ERRBUF_SIZE) == -1)
+       {
+               // That failed; log a message and give up.
+               rpcapd_log(LOGPRIO_ERROR, "Send to client failed: %s", errbuf);
+               return -1;
+       }
+
+       return 0;
+}
+
+//
+// We impose a limit on the filter program size, so that, on Windows,
+// where there's only one server process with multiple threads, it's
+// harder to eat all the server address space by sending larger filter
+// programs.  (This isn't an issue on UN*X, where there are multiple
+// server processes, one per client connection.)
+//
+// We pick a value that limits each filter to 64K; that value is twice
+// the in-kernel limit for Linux and 16 times the in-kernel limit for
+// *BSD and macOS.
+//
+// It also prevents an overflow on 32-bit platforms when calculating
+// the total size of the filter program.  (It's not an issue on 64-bit
+// platforms with a 64-bit size_t, as the filter size is 32 bits.)
+//
+#define RPCAP_BPF_MAXINSNS     8192
+
+static int
+daemon_unpackapplyfilter(SOCKET sockctrl, struct session *session, uint32 *plenp, char *errmsgbuf)
+{
+       int status;
+       struct rpcap_filter filter;
+       struct rpcap_filterbpf_insn insn;
+       struct bpf_insn *bf_insn;
+       struct bpf_program bf_prog;
+       unsigned int i;
+
+       status = rpcapd_recv(sockctrl, (char *) &filter,
+           sizeof(struct rpcap_filter), plenp, errmsgbuf);
+       if (status == -1)
+       {
+               return -1;
+       }
+       if (status == -2)
+       {
+               return -2;
+       }
+
+       bf_prog.bf_len = ntohl(filter.nitems);
+
+       if (ntohs(filter.filtertype) != RPCAP_UPDATEFILTER_BPF)
+       {
+               pcap_snprintf(errmsgbuf, PCAP_ERRBUF_SIZE, "Only BPF/NPF filters are currently supported");
+               return -2;
+       }
+
+       if (bf_prog.bf_len > RPCAP_BPF_MAXINSNS)
+       {
+               pcap_snprintf(errmsgbuf, PCAP_ERRBUF_SIZE,
+                   "Filter program is larger than the maximum size of %u instructions",
+                   RPCAP_BPF_MAXINSNS);
+               return -2;
+       }
+       bf_insn = (struct bpf_insn *) malloc (sizeof(struct bpf_insn) * bf_prog.bf_len);
+       if (bf_insn == NULL)
+       {
+               pcap_fmt_errmsg_for_errno(errmsgbuf, PCAP_ERRBUF_SIZE,
+                   errno, "malloc() failed");
+               return -2;
+       }
+
+       bf_prog.bf_insns = bf_insn;
+
+       for (i = 0; i < bf_prog.bf_len; i++)
+       {
+               status = rpcapd_recv(sockctrl, (char *) &insn,
+                   sizeof(struct rpcap_filterbpf_insn), plenp, errmsgbuf);
+               if (status == -1)
+               {
+                       return -1;
+               }
+               if (status == -2)
+               {
+                       return -2;
+               }
+
+               bf_insn->code = ntohs(insn.code);
+               bf_insn->jf = insn.jf;
+               bf_insn->jt = insn.jt;
+               bf_insn->k = ntohl(insn.k);
+
+               bf_insn++;
+       }
+
+       if (bpf_validate(bf_prog.bf_insns, bf_prog.bf_len) == 0)
+       {
+               pcap_snprintf(errmsgbuf, PCAP_ERRBUF_SIZE, "The filter contains bogus instructions");
+               return -2;
+       }
+
+       if (pcap_setfilter(session->fp, &bf_prog))
+       {
+               pcap_snprintf(errmsgbuf, PCAP_ERRBUF_SIZE, "RPCAP error: %s", pcap_geterr(session->fp));
+               return -2;
+       }
+
+       return 0;
+}
+
+static int
+daemon_msg_updatefilter_req(uint8 ver, struct daemon_slpars *pars,
+    struct session *session, uint32 plen)
+{
+       char errbuf[PCAP_ERRBUF_SIZE];
+       char errmsgbuf[PCAP_ERRBUF_SIZE];       // buffer for errors to send to the client
+       int ret;                                // status of daemon_unpackapplyfilter()
+       struct rpcap_header header;             // keeps the answer to the updatefilter command
+
+       ret = daemon_unpackapplyfilter(pars->sockctrl, session, &plen, errmsgbuf);
+       if (ret == -1)
+       {
+               // Fatal error.  A message has been logged; just give up.
+               return -1;
+       }
+       if (ret == -2)
+       {
+               // Non-fatal error.  Send an error reply to the client.
+               goto error;
+       }
+
+       // Check if all the data has been read; if not, discard the data in excess
+       if (rpcapd_discard(pars->sockctrl, plen) == -1)
+       {
+               // Network error.
+               return -1;
+       }
+
+       // A response is needed, otherwise the other host does not know that everything went well
+       rpcap_createhdr(&header, ver, RPCAP_MSG_UPDATEFILTER_REPLY, 0, 0);
+
+       if (sock_send(pars->sockctrl, (char *) &header, sizeof (struct rpcap_header), pcap_geterr(session->fp), PCAP_ERRBUF_SIZE))
+       {
+               // That failed; log a messsage and give up.
+               rpcapd_log(LOGPRIO_ERROR, "Send to client failed: %s", errbuf);
+               return -1;
+       }
+
+       return 0;
+
+error:
+       if (rpcapd_discard(pars->sockctrl, plen) == -1)
+       {
+               return -1;
+       }
+       rpcap_senderror(pars->sockctrl, ver, PCAP_ERR_UPDATEFILTER,
+           errmsgbuf, NULL);
+
+       return 0;
+}
+
+/*!
+       \brief Received the sampling parameters from remote host and it stores in the pcap_t structure.
+*/
+static int
+daemon_msg_setsampling_req(uint8 ver, struct daemon_slpars *pars, uint32 plen,
+    struct rpcap_sampling *samp_param)
+{
+       char errbuf[PCAP_ERRBUF_SIZE];          // buffer for network errors
+       char errmsgbuf[PCAP_ERRBUF_SIZE];
+       struct rpcap_header header;
+       struct rpcap_sampling rpcap_samp;
+       int status;
+
+       status = rpcapd_recv(pars->sockctrl, (char *) &rpcap_samp, sizeof(struct rpcap_sampling), &plen, errmsgbuf);
+       if (status == -1)
+       {
+               return -1;
+       }
+       if (status == -2)
+       {
+               goto error;
+       }
+
+       // Save these settings in the pcap_t
+       samp_param->method = rpcap_samp.method;
+       samp_param->value = ntohl(rpcap_samp.value);
+
+       // A response is needed, otherwise the other host does not know that everything went well
+       rpcap_createhdr(&header, ver, RPCAP_MSG_SETSAMPLING_REPLY, 0, 0);
+
+       if (sock_send(pars->sockctrl, (char *) &header, sizeof (struct rpcap_header), errbuf, PCAP_ERRBUF_SIZE) == -1)
+       {
+               // That failed; log a messsage and give up.
+               rpcapd_log(LOGPRIO_ERROR, "Send to client failed: %s", errbuf);
+               return -1;
+       }
+
+       if (rpcapd_discard(pars->sockctrl, plen) == -1)
+       {
+               return -1;
+       }
+
+       return 0;
+
+error:
+       if (rpcap_senderror(pars->sockctrl, ver, PCAP_ERR_SETSAMPLING,
+           errmsgbuf, errbuf) == -1)
+       {
+               // That failed; log a message and give up.
+               rpcapd_log(LOGPRIO_ERROR, "Send to client failed: %s", errbuf);
+               return -1;
+       }
+
+       // Check if all the data has been read; if not, discard the data in excess
+       if (rpcapd_discard(pars->sockctrl, plen) == -1)
+       {
+               return -1;
+       }
+
+       return 0;
+}
+
+static int
+daemon_msg_stats_req(uint8 ver, struct daemon_slpars *pars,
+    struct session *session, uint32 plen, struct pcap_stat *stats,
+    unsigned int svrcapt)
+{
+       char errbuf[PCAP_ERRBUF_SIZE];          // buffer for network errors
+       char errmsgbuf[PCAP_ERRBUF_SIZE];       // buffer for errors to send to the client
+       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_stats *netstats;           // statistics sent on the network
+
+       // Checks that the header does not contain other data; if so, discard it
+       if (rpcapd_discard(pars->sockctrl, plen) == -1)
+       {
+               // Network error.
+               return -1;
+       }
+
+       if (sock_bufferize(NULL, sizeof(struct rpcap_header), NULL,
+           &sendbufidx, RPCAP_NETBUF_SIZE, SOCKBUF_CHECKONLY, errmsgbuf, PCAP_ERRBUF_SIZE) == -1)
+               goto error;
+
+       rpcap_createhdr((struct rpcap_header *) sendbuf, ver,
+           RPCAP_MSG_STATS_REPLY, 0, (uint16) sizeof(struct rpcap_stats));
+
+       netstats = (struct rpcap_stats *) &sendbuf[sendbufidx];
+
+       if (sock_bufferize(NULL, sizeof(struct rpcap_stats), NULL,
+           &sendbufidx, RPCAP_NETBUF_SIZE, SOCKBUF_CHECKONLY, errmsgbuf, PCAP_ERRBUF_SIZE) == -1)
+               goto error;
+
+       if (session && session->fp)
+       {
+               if (pcap_stats(session->fp, stats) == -1)
+               {
+                       pcap_snprintf(errmsgbuf, PCAP_ERRBUF_SIZE, "%s", pcap_geterr(session->fp));
+                       goto error;
+               }
+
+               netstats->ifdrop = htonl(stats->ps_ifdrop);
+               netstats->ifrecv = htonl(stats->ps_recv);
+               netstats->krnldrop = htonl(stats->ps_drop);
+               netstats->svrcapt = htonl(session->TotCapt);
+       }
+       else
+       {
+               // We have to keep compatibility with old applications,
+               // which ask for statistics also when the capture has
+               // already stopped.
+               netstats->ifdrop = htonl(stats->ps_ifdrop);
+               netstats->ifrecv = htonl(stats->ps_recv);
+               netstats->krnldrop = htonl(stats->ps_drop);
+               netstats->svrcapt = htonl(svrcapt);
+       }
+
+       // Send the packet
+       if (sock_send(pars->sockctrl, sendbuf, sendbufidx, errbuf, PCAP_ERRBUF_SIZE) == -1)
+       {
+               rpcapd_log(LOGPRIO_ERROR, "Send to client failed: %s", errbuf);
+               return -1;
+       }
+
+       return 0;
+
+error:
+       rpcap_senderror(pars->sockctrl, ver, PCAP_ERR_GETSTATS,
+           errmsgbuf, NULL);
+       return 0;
+}
+
+#ifdef _WIN32
+static unsigned __stdcall
+#else
+static void *
+#endif
+daemon_thrdatamain(void *ptr)
+{
+       char errbuf[PCAP_ERRBUF_SIZE + 1];      // error buffer
+       struct session *session;                // pointer to the struct session for this session
+       int retval;                                                     // general variable used to keep the return value of other functions
+       struct rpcap_pkthdr *net_pkt_header;// header of the packet
+       struct pcap_pkthdr *pkt_header;         // pointer to the buffer that contains the header of the current packet
+       u_char *pkt_data;                                       // pointer to the buffer that contains the current packet
+       size_t sendbufsize;                     // size for the send buffer
+       char *sendbuf;                                          // temporary buffer in which data to be sent is buffered
+       int sendbufidx;                                         // index which keeps the number of bytes currently buffered
+       int status;
+#ifndef _WIN32
+       sigset_t sigusr1;                       // signal set with just SIGUSR1
+#endif
+
+       session = (struct session *) ptr;
+
+       session->TotCapt = 0;                   // counter which is incremented each time a packet is received
+
+       // Initialize errbuf
+       memset(errbuf, 0, sizeof(errbuf));
+
+       //
+       // We need a buffer large enough to hold a buffer large enough
+       // for a maximum-size packet for this pcap_t.
+       //
+       if (pcap_snapshot(session->fp) < 0)
+       {
+               //
+               // The snapshot length is negative.
+               // This "should not happen".
+               //
+               rpcapd_log(LOGPRIO_ERROR,
+                   "Unable to allocate the buffer for this child thread: snapshot length of %d is negative",
+                       pcap_snapshot(session->fp));
+               sendbuf = NULL; // we can't allocate a buffer, so nothing to free
+               goto error;
+       }
+       //
+       // size_t is unsigned, and the result of pcap_snapshot() is signed;
+       // on no platform that we support is int larger than size_t.
+       // This means that, unless the extra information we prepend to
+       // a maximum-sized packet is impossibly large, the sum of the
+       // snapshot length and the size of that extra information will
+       // fit in a size_t.
+       //
+       // So we don't need to make sure that sendbufsize will overflow.
+       //
+       sendbufsize = sizeof(struct rpcap_header) + sizeof(struct rpcap_pkthdr) + pcap_snapshot(session->fp);
+       sendbuf = (char *) malloc (sendbufsize);
+       if (sendbuf == NULL)
+       {
+               rpcapd_log(LOGPRIO_ERROR,
+                   "Unable to allocate the buffer for this child thread");
+               goto error;
+       }
+
+#ifndef _WIN32
+       //
+       // Set the signal set to include just SIGUSR1, and block that
+       // signal; we only want it unblocked when we're reading
+       // packets - we dn't want any other system calls, such as
+       // ones being used to send to the client or to log messages,
+       // to be interrupted.
+       //
+       sigemptyset(&sigusr1);
+       sigaddset(&sigusr1, SIGUSR1);
+       pthread_sigmask(SIG_BLOCK, &sigusr1, NULL);
+#endif
+
+       // Retrieve the packets
+       for (;;)
+       {
+#ifndef _WIN32
+               //
+               // Unblock SIGUSR1 while we might be waiting for packets.
+               //
+               pthread_sigmask(SIG_UNBLOCK, &sigusr1, NULL);
+#endif
+               retval = pcap_next_ex(session->fp, &pkt_header, (const u_char **) &pkt_data);   // cast to avoid a compiler warning
+#ifndef _WIN32
+               //
+               // Now block it again.
+               //
+               pthread_sigmask(SIG_BLOCK, &sigusr1, NULL);
+#endif
+               if (retval < 0)
+                       break;          // error
+               if (retval == 0)        // Read timeout elapsed
+                       continue;
+
+               sendbufidx = 0;
+
+               // Bufferize the general header
+               if (sock_bufferize(NULL, sizeof(struct rpcap_header), NULL,
+                   &sendbufidx, sendbufsize, SOCKBUF_CHECKONLY, errbuf,
+                   PCAP_ERRBUF_SIZE) == -1)
+               {
+                       rpcapd_log(LOGPRIO_ERROR,
+                           "sock_bufferize() error sending packet message: %s",
+                           errbuf);
+                       goto error;
+               }
+
+               rpcap_createhdr((struct rpcap_header *) sendbuf,
+                   session->protocol_version, RPCAP_MSG_PACKET, 0,
+                   (uint16) (sizeof(struct rpcap_pkthdr) + pkt_header->caplen));
+
+               net_pkt_header = (struct rpcap_pkthdr *) &sendbuf[sendbufidx];
+
+               // Bufferize the pkt header
+               if (sock_bufferize(NULL, sizeof(struct rpcap_pkthdr), NULL,
+                   &sendbufidx, sendbufsize, SOCKBUF_CHECKONLY, errbuf,
+                   PCAP_ERRBUF_SIZE) == -1)
+               {
+                       rpcapd_log(LOGPRIO_ERROR,
+                           "sock_bufferize() error sending packet message: %s",
+                           errbuf);
+                       goto error;
+               }
+
+               net_pkt_header->caplen = htonl(pkt_header->caplen);
+               net_pkt_header->len = htonl(pkt_header->len);
+               net_pkt_header->npkt = htonl(++(session->TotCapt));
+               net_pkt_header->timestamp_sec = htonl(pkt_header->ts.tv_sec);
+               net_pkt_header->timestamp_usec = htonl(pkt_header->ts.tv_usec);
+
+               // Bufferize the pkt data
+               if (sock_bufferize((char *) pkt_data, pkt_header->caplen,
+                   sendbuf, &sendbufidx, sendbufsize, SOCKBUF_BUFFERIZE,
+                   errbuf, PCAP_ERRBUF_SIZE) == -1)
+               {
+                       rpcapd_log(LOGPRIO_ERROR,
+                           "sock_bufferize() error sending packet message: %s",
+                           errbuf);
+                       goto error;
+               }
+
+               // Send the packet
+               // If the client dropped the connection, don't report an
+               // error, just quit.
+               status = sock_send(session->sockdata, sendbuf, sendbufidx, errbuf, PCAP_ERRBUF_SIZE);
+               if (status < 0)
+               {
+                       if (status == -1)
+                       {
+                               //
+                               // Error other than "client closed the
+                               // connection out from under us"; report
+                               // it.
+                               //
+                               rpcapd_log(LOGPRIO_ERROR,
+                                   "Send of packet to client failed: %s",
+                                   errbuf);
+                       }
+
+                       //
+                       // Give up in either case.
+                       //
+                       goto error;
+               }
+       }
+
+       if (retval < 0 && retval != PCAP_ERROR_BREAK)
+       {
+               //
+               // Failed with an error other than "we were told to break
+               // out of the loop".
+               //
+               // The latter just means that the client told us to stop
+               // capturing, so there's no error to report.
+               //
+               pcap_snprintf(errbuf, PCAP_ERRBUF_SIZE, "Error reading the packets: %s", pcap_geterr(session->fp));
+               rpcap_senderror(session->sockctrl, session->protocol_version,
+                   PCAP_ERR_READEX, errbuf, NULL);
+       }
+
+error:
+       //
+       // The main thread will clean up the session structure.
+       //
+       free(sendbuf);
+
+       return 0;
+}
+
+#ifndef _WIN32
+//
+// Do-nothing handler for SIGUSR1; the sole purpose of SIGUSR1 is to
+// interrupt the data thread if it's blocked in a system call waiting
+// for packets to arrive.
+//
+static void noop_handler(int sign _U_)
+{
+}
+#endif
+
+/*!
+       \brief It serializes a network address.
+
+       It accepts a 'sockaddr_storage' structure as input, and it converts it appropriately into a format
+       that can be used to be sent on the network. Basically, it applies all the hton()
+       conversion required to the input variable.
+
+       \param sockaddrin a 'sockaddr_storage' pointer to the variable that has to be
+       serialized. This variable can be both a 'sockaddr_in' and 'sockaddr_in6'.
+
+       \param sockaddrout an 'rpcap_sockaddr' pointer to the variable that will contain
+       the serialized data. This variable has to be allocated by the user.
+
+       \warning This function supports only AF_INET and AF_INET6 address families.
+*/
+static void
+daemon_seraddr(struct sockaddr_storage *sockaddrin, struct rpcap_sockaddr *sockaddrout)
+{
+       memset(sockaddrout, 0, sizeof(struct sockaddr_storage));
+
+       // There can be the case in which the sockaddrin is not available
+       if (sockaddrin == NULL) return;
+
+       // Warning: we support only AF_INET and AF_INET6
+       switch (sockaddrin->ss_family)
+       {
+       case AF_INET:
+               {
+               struct sockaddr_in *sockaddrin_ipv4;
+               struct rpcap_sockaddr_in *sockaddrout_ipv4;
+
+               sockaddrin_ipv4 = (struct sockaddr_in *) sockaddrin;
+               sockaddrout_ipv4 = (struct rpcap_sockaddr_in *) sockaddrout;
+               sockaddrout_ipv4->family = htons(RPCAP_AF_INET);
+               sockaddrout_ipv4->port = htons(sockaddrin_ipv4->sin_port);
+               memcpy(&sockaddrout_ipv4->addr, &sockaddrin_ipv4->sin_addr, sizeof(sockaddrout_ipv4->addr));
+               memset(sockaddrout_ipv4->zero, 0, sizeof(sockaddrout_ipv4->zero));
+               break;
+               }
+
+#ifdef AF_INET6
+       case AF_INET6:
+               {
+               struct sockaddr_in6 *sockaddrin_ipv6;
+               struct rpcap_sockaddr_in6 *sockaddrout_ipv6;
+
+               sockaddrin_ipv6 = (struct sockaddr_in6 *) sockaddrin;
+               sockaddrout_ipv6 = (struct rpcap_sockaddr_in6 *) sockaddrout;
+               sockaddrout_ipv6->family = htons(RPCAP_AF_INET6);
+               sockaddrout_ipv6->port = htons(sockaddrin_ipv6->sin6_port);
+               sockaddrout_ipv6->flowinfo = htonl(sockaddrin_ipv6->sin6_flowinfo);
+               memcpy(&sockaddrout_ipv6->addr, &sockaddrin_ipv6->sin6_addr, sizeof(sockaddrout_ipv6->addr));
+               sockaddrout_ipv6->scope_id = htonl(sockaddrin_ipv6->sin6_scope_id);
+               break;
+               }
+#endif
+       }
+}
+
+
+/*!
+       \brief Suspends a thread for secs seconds.
+*/
+void sleep_secs(int secs)
+{
+#ifdef _WIN32
+       Sleep(secs*1000);
+#else
+       unsigned secs_remaining;
+
+       if (secs <= 0)
+               return;
+       secs_remaining = secs;
+       while (secs_remaining != 0)
+               secs_remaining = sleep(secs_remaining);
+#endif
+}
+
+/*
+ * Read the header of a message.
+ */
+static int
+rpcapd_recv_msg_header(SOCKET sock, struct rpcap_header *headerp)
+{
+       int nread;
+       char errbuf[PCAP_ERRBUF_SIZE];          // buffer for network errors
+
+       nread = sock_recv(sock, (char *) headerp, sizeof(struct rpcap_header),
+           SOCK_RECEIVEALL_YES|SOCK_EOF_ISNT_ERROR, errbuf, PCAP_ERRBUF_SIZE);
+       if (nread == -1)
+       {
+               // Network error.
+               rpcapd_log(LOGPRIO_ERROR, "Read from client failed: %s", errbuf);
+               return -1;
+       }
+       if (nread == 0)
+       {
+               // Immediate EOF; that's treated like a close message.
+               return -2;
+       }
+       headerp->plen = ntohl(headerp->plen);
+       return 0;
+}
+
+/*
+ * Read data from a message.
+ * If we're trying to read more data that remains, puts an error
+ * message into errmsgbuf and returns -2.  Otherwise, tries to read
+ * the data and, if that succeeds, subtracts the amount read from
+ * the number of bytes of data that remains.
+ * Returns 0 on success, logs a message and returns -1 on a network
+ * error.
+ */
+static int
+rpcapd_recv(SOCKET sock, char *buffer, size_t toread, uint32 *plen, char *errmsgbuf)
+{
+       int nread;
+       char errbuf[PCAP_ERRBUF_SIZE];          // buffer for network errors
+
+       if (toread > *plen)
+       {
+               // Tell the client and continue.
+               pcap_snprintf(errmsgbuf, PCAP_ERRBUF_SIZE, "Message payload is too short");
+               return -2;
+       }
+       nread = sock_recv(sock, buffer, toread,
+           SOCK_RECEIVEALL_YES|SOCK_EOF_IS_ERROR, errbuf, PCAP_ERRBUF_SIZE);
+       if (nread == -1)
+       {
+               rpcapd_log(LOGPRIO_ERROR, "Read from client failed: %s", errbuf);
+               return -1;
+       }
+       *plen -= nread;
+       return 0;
+}
+
+/*
+ * Discard data from a connection.
+ * Mostly used to discard wrong-sized messages.
+ * Returns 0 on success, logs a message and returns -1 on a network
+ * error.
+ */
+static int
+rpcapd_discard(SOCKET sock, uint32 len)
+{
+       char errbuf[PCAP_ERRBUF_SIZE + 1];      // keeps the error string, prior to be printed
+
+       if (len != 0)
+       {
+               if (sock_discard(sock, len, errbuf, PCAP_ERRBUF_SIZE) == -1)
+               {
+                       // Network error.
+                       rpcapd_log(LOGPRIO_ERROR, "Read from client failed: %s", errbuf);
+                       return -1;
+               }
+       }
+       return 0;
+}
+
+//
+// Shut down any packet-capture thread associated with the session,
+// close the SSL handle for the data socket if we have one, close
+// the data socket if we have one, and close the underlying packet
+// capture handle if we have one.
+//
+// We do not, of course, touch the controlling socket that's also
+// copied into the session, as the service loop might still use it.
+//
+static void session_close(struct session *session)
+{
+       if (session->have_thread)
+       {
+               //
+               // Tell the data connection thread main capture loop to
+               // break out of that loop.
+               //
+               // This may be sufficient to wake up a blocked thread,
+               // but it's not guaranteed to be sufficient.
+               //
+               pcap_breakloop(session->fp);
+
+#ifdef _WIN32
+               //
+               // Set the event on which a read would block, so that,
+               // if it's currently blocked waiting for packets to
+               // arrive, it'll wake up, so it can see the "break
+               // out of the loop" indication.  (pcap_breakloop()
+               // might do this, but older versions don't.  Setting
+               // it twice should, at worst, cause an extra wakeup,
+               // which shouldn't be a problem.)
+               //
+               // XXX - what about modules other than NPF?
+               //
+               SetEvent(pcap_getevent(session->fp));
+
+               //
+               // Wait for the thread to exit, so we don't close
+               // sockets out from under it.
+               //
+               // XXX - have a timeout, so we don't wait forever?
+               //
+               WaitForSingleObject(session->thread, INFINITE);
+
+               //
+               // Release the thread handle, as we're done with
+               // it.
+               //
+               CloseHandle(session->thread);
+               session->have_thread = 0;
+               session->thread = INVALID_HANDLE_VALUE;
+#else
+               //
+               // Send a SIGUSR1 signal to the thread, so that, if
+               // it's currently blocked waiting for packets to arrive,
+               // it'll wake up (we've turned off SA_RESTART for
+               // SIGUSR1, so that the system call in which it's blocked
+               // should return EINTR rather than restarting).
+               //
+               pthread_kill(session->thread, SIGUSR1);
+
+               //
+               // Wait for the thread to exit, so we don't close
+               // sockets out from under it.
+               //
+               // XXX - have a timeout, so we don't wait forever?
+               //
+               pthread_join(session->thread, NULL);
+               session->have_thread = 0;
+               memset(&session->thread, 0, sizeof(session->thread));
+#endif
+       }
+
+       if (session->sockdata != INVALID_SOCKET)
+       {
+               sock_close(session->sockdata, NULL, 0);
+               session->sockdata = INVALID_SOCKET;
+       }
+
+       if (session->fp)
+       {
+               pcap_close(session->fp);
+               session->fp = NULL;
+       }
+}
+
+//
+// Check whether a capture source string is a URL or not.
+// This includes URLs that refer to a local device; a scheme, followed
+// by ://, followed by *another* scheme and ://, is just silly, and
+// anybody who supplies that will get an error.
+//
+static int
+is_url(const char *source)
+{
+       char *colonp;
+
+       /*
+        * RFC 3986 says:
+        *
+        *   URI         = scheme ":" hier-part [ "?" query ] [ "#" fragment ]
+        *
+        *   hier-part   = "//" authority path-abempty
+        *               / path-absolute
+        *               / path-rootless
+        *               / path-empty
+        *
+        *   authority   = [ userinfo "@" ] host [ ":" port ]
+        *
+        *   userinfo    = *( unreserved / pct-encoded / sub-delims / ":" )
+        *
+        * Step 1: look for the ":" at the end of the scheme.
+        * A colon in the source is *NOT* sufficient to indicate that
+        * this is a URL, as interface names on some platforms might
+        * include colons (e.g., I think some Solaris interfaces
+        * might).
+        */
+       colonp = strchr(source, ':');
+       if (colonp == NULL)
+       {
+               /*
+                * The source is the device to open.  It's not a URL.
+                */
+               return (0);
+       }
+
+       /*
+        * All schemes must have "//" after them, i.e. we only support
+        * hier-part   = "//" authority path-abempty, not
+        * hier-part   = path-absolute
+        * hier-part   = path-rootless
+        * hier-part   = path-empty
+        *
+        * We need that in order to distinguish between a local device
+        * name that happens to contain a colon and a URI.
+        */
+       if (strncmp(colonp + 1, "//", 2) != 0)
+       {
+               /*
+                * The source is the device to open.  It's not a URL.
+                */
+               return (0);
+       }
+
+       /*
+        * It's a URL.
+        */
+       return (1);
+}
diff --git a/rpcapd/daemon.h b/rpcapd/daemon.h
new file mode 100644 (file)
index 0000000..74e17da
--- /dev/null
@@ -0,0 +1,46 @@
+/*
+ * 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 __DAEMON_H__
+#define __DAEMON_H__
+
+//
+// Returns 1 if the client closed the control connection explicitly, 0
+// otherwise; the return value is used only by callers that call us
+// for active mode.
+//
+int daemon_serviceloop(SOCKET sockctrl, int isactive, char *passiveClients,
+    int nullAuthAllowed);
+
+void sleep_secs(int secs);
+
+#endif
diff --git a/rpcapd/fileconf.c b/rpcapd/fileconf.c
new file mode 100644 (file)
index 0000000..2f15c01
--- /dev/null
@@ -0,0 +1,557 @@
+/*
+ * 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.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include "ftmacros.h"
+
+#include <stdio.h>
+#include <string.h>
+#include <ctype.h>
+#include <signal.h>
+#include <pcap.h>              // for PCAP_ERRBUF_SIZE
+
+#include "portability.h"
+#include "rpcapd.h"
+#include "config_params.h"     // configuration file parameters
+#include "fileconf.h"
+#include "rpcap-protocol.h"
+#include "log.h"
+
+//
+// Parameter names.
+//
+#define PARAM_ACTIVECLIENT     "ActiveClient"
+#define PARAM_PASSIVECLIENT    "PassiveClient"
+#define PARAM_NULLAUTHPERMIT   "NullAuthPermit"
+
+static char *skipws(char *ptr);
+
+void fileconf_read(void)
+{
+       FILE *fp;
+       unsigned int num_active_clients;
+
+       if ((fp = fopen(loadfile, "r")) != NULL)
+       {
+               char line[MAX_LINE + 1];
+               unsigned int lineno;
+
+               hostlist[0] = 0;
+               num_active_clients = 0;
+               lineno = 0;
+
+               while (fgets(line, MAX_LINE, fp) != NULL)
+               {
+                       size_t linelen;
+                       char *ptr;
+                       char *param;
+                       size_t result;
+                       size_t toklen;
+
+                       lineno++;
+
+                       linelen = strlen(line);
+                       if (line[linelen - 1] != '\n')
+                       {
+                               int c;
+
+                               //
+                               // Either the line doesn't fit in
+                               // the buffer, or we got an EOF
+                               // before the EOL.  Assume it's the
+                               // former.
+                               //
+                               rpcapd_log(LOGPRIO_ERROR,
+                                   "%s, line %u is longer than %u characters",
+                                   loadfile, lineno, MAX_LINE);
+
+                               //
+                               // Eat characters until we get an NL.
+                               //
+                               while ((c = getc(fp)) != '\n')
+                               {
+                                       if (c == EOF)
+                                               goto done;
+                               }
+
+                               //
+                               // Try the next line.
+                               //
+                               continue;
+                       }
+                       ptr = line;
+
+                       //
+                       // Skip leading white space, if any.
+                       //
+                       ptr = skipws(ptr);
+                       if (ptr == NULL)
+                       {
+                               // Blank line.
+                               continue;
+                       }
+
+                       //
+                       // Is the next character a "#"?  If so, this
+                       // line is a comment; skip to the next line.
+                       //
+                       if (*ptr == '#')
+                               continue;
+
+                       //
+                       // Is the next character alphabetic?  If not,
+                       // this isn't a valid parameter name.
+                       //
+                       if (!isascii((unsigned char)*ptr) ||
+                           !isalpha((unsigned char)*ptr))
+                       {
+                               rpcapd_log(LOGPRIO_ERROR,
+                                   "%s, line %u doesn't have a valid parameter name",
+                                   loadfile, lineno);
+                               continue;
+                       }
+
+                       //
+                       // Grab the first token, which is made of
+                       // alphanumerics, underscores, and hyphens.
+                       // That's the name of the parameter being set.
+                       //
+                       param = ptr;
+                       while (isascii((unsigned char)*ptr) &&
+                           (isalnum((unsigned char)*ptr) || *ptr == '-' || *ptr == '_'))
+                               ptr++;
+
+                       //
+                       // Skip over white space, if any.
+                       //
+                       ptr = skipws(ptr);
+                       if (ptr == NULL || *ptr != '=')
+                       {
+                               //
+                               // We hit the end of the line before
+                               // finding a non-white space character,
+                               // or we found one but it's not an "=".
+                               // That means there's no "=", so this
+                               // line is invalid.  Complain and skip
+                               // this line.
+                               //
+                               rpcapd_log(LOGPRIO_ERROR,
+                                   "%s, line %u has a parameter but no =",
+                                   loadfile, lineno);
+                               continue;
+                       }
+
+                       //
+                       // We found the '='; set it to '\0', and skip
+                       // past it.
+                       //
+                       *ptr++ = '\0';
+
+                       //
+                       // Skip past any white space after the "=".
+                       //
+                       ptr = skipws(ptr);
+                       if (ptr == NULL)
+                       {
+                               //
+                               // The value is empty.
+                               //
+                               rpcapd_log(LOGPRIO_ERROR,
+                                   "%s, line %u has a parameter but no value",
+                                   loadfile, lineno);
+                               continue;
+                       }
+
+                       //
+                       // OK, what parameter is this?
+                       //
+                       if (strcmp(param, PARAM_ACTIVECLIENT) == 0) {
+                               //
+                               // Add this to the list of active clients.
+                               //
+                               char *address, *port;
+
+                               //
+                               // We can't have more than MAX_ACTIVE_LIST
+                               // active clients.
+                               //
+                               if (num_active_clients >= MAX_ACTIVE_LIST)
+                               {
+                                       //
+                                       // Too many entries for the active
+                                       // client list.  Complain and
+                                       // ignore it.
+                                       //
+                                       rpcapd_log(LOGPRIO_ERROR,
+                                           "%s, line %u has an %s parameter, but we already have %u active clients",
+                                           loadfile, lineno, PARAM_ACTIVECLIENT,
+                                           MAX_ACTIVE_LIST);
+                                       continue;
+                               }
+
+                               //
+                               // Get the address.
+                               // It's terminated by a host list separator
+                               // *or* a #; there *shouldn't* be a #, as
+                               // that starts a comment, and that would
+                               // mean that we have no port.
+                               //
+                               address = ptr;
+                               toklen = strcspn(ptr, RPCAP_HOSTLIST_SEP "#");
+                               ptr += toklen;  // skip to the terminator
+                               if (toklen == 0)
+                               {
+                                       if (isascii((unsigned char)*ptr) &&
+                                           (isspace((unsigned char)*ptr) || *ptr == '#' || *ptr == '\0'))
+                                       {
+                                               //
+                                               // The first character it saw
+                                               // was a whitespace character
+                                               // or a comment character.
+                                               // This means that there's
+                                               // no value.
+                                               //
+                                               rpcapd_log(LOGPRIO_ERROR,
+                                                   "%s, line %u has a parameter but no value",
+                                                   loadfile, lineno);
+                                       }
+                                       else
+                                       {
+                                               //
+                                               // This means that the first
+                                               // character it saw was a
+                                               // separator.  This means that
+                                               // there's no address in the
+                                               // value, just a port.
+                                               //
+                                               rpcapd_log(LOGPRIO_ERROR,
+                                                   "%s, line %u has an %s parameter with a value containing no address",
+                                                   loadfile, lineno, PARAM_ACTIVECLIENT);
+                                       }
+                                       continue;
+                               }
+
+                               //
+                               // Null-terminate the address, and skip past
+                               // it.
+                               //
+                               *ptr++ = '\0';
+
+                               //
+                               // Skip any white space following the
+                               // separating character.
+                               //
+                               ptr = skipws(ptr);
+                               if (ptr == NULL)
+                               {
+                                       //
+                                       // The value is empty, so there's
+                                       // no port in the value.
+                                       //
+                                       rpcapd_log(LOGPRIO_ERROR,
+                                           "%s, line %u has an %s parameter with a value containing no port",
+                                           loadfile, lineno, PARAM_ACTIVECLIENT);
+                                       continue;
+                               }
+
+                               //
+                               // Get the port.
+                               // We look for a white space character
+                               // or a # as a terminator; the # introduces
+                               // a comment that runs to the end of the
+                               // line.
+                               //
+                               port = ptr;
+                               toklen = strcspn(ptr, " \t#\r\n");
+                               ptr += toklen;
+                               if (toklen == 0)
+                               {
+                                       //
+                                       // The value is empty, so there's
+                                       // no port in the value.
+                                       //
+                                       rpcapd_log(LOGPRIO_ERROR,
+                                           "%s, line %u has an %s parameter with a value containing no port",
+                                           loadfile, lineno, PARAM_ACTIVECLIENT);
+                                       continue;
+                               }
+
+                               //
+                               // Null-terminate the port, and skip past
+                               // it.
+                               //
+                               *ptr++ = '\0';
+                               result = pcap_strlcpy(activelist[num_active_clients].address, address, sizeof(activelist[num_active_clients].address));
+                               if (result >= sizeof(activelist[num_active_clients].address))
+                               {
+                                       //
+                                       // It didn't fit.
+                                       //
+                                       rpcapd_log(LOGPRIO_ERROR,
+                                           "%s, line %u has an %s parameter with an address with more than %u characters",
+                                           loadfile, lineno, PARAM_ACTIVECLIENT,
+                                           (unsigned int)(sizeof(activelist[num_active_clients].address) - 1));
+                                       continue;
+                               }
+                               if (strcmp(port, "DEFAULT") == 0) // the user choose a custom port
+                                       result = pcap_strlcpy(activelist[num_active_clients].port, RPCAP_DEFAULT_NETPORT_ACTIVE, sizeof(activelist[num_active_clients].port));
+                               else
+                                       result = pcap_strlcpy(activelist[num_active_clients].port, port, sizeof(activelist[num_active_clients].port));
+                               if (result >= sizeof(activelist[num_active_clients].address))
+                               {
+                                       //
+                                       // It didn't fit.
+                                       //
+                                       rpcapd_log(LOGPRIO_ERROR,
+                                           "%s, line %u has an %s parameter with an port with more than %u characters",
+                                           loadfile, lineno, PARAM_ACTIVECLIENT,
+                                           (unsigned int)(sizeof(activelist[num_active_clients].port) - 1));
+                                       continue;
+                               }
+
+                               num_active_clients++;
+                       }
+                       else if (strcmp(param, PARAM_PASSIVECLIENT) == 0)
+                       {
+                               char *eos;
+                               char *host;
+
+                               //
+                               // Get the host.
+                               // We look for a white space character
+                               // or a # as a terminator; the # introduces
+                               // a comment that runs to the end of the
+                               // line.
+                               //
+                               host = ptr;
+                               toklen = strcspn(ptr, " \t#\r\n");
+                               if (toklen == 0)
+                               {
+                                       //
+                                       // The first character it saw
+                                       // was a whitespace character
+                                       // or a comment character.
+                                       // This means that there's
+                                       // no value.
+                                       //
+                                       rpcapd_log(LOGPRIO_ERROR,
+                                           "%s, line %u has a parameter but no value",
+                                           loadfile, lineno);
+                                       continue;
+                               }
+                               ptr += toklen;
+                               *ptr++ = '\0';
+
+                               //
+                               // Append this to the host list.
+                               // Save the curren end-of-string for the
+                               // host list, in case the new host doesn't
+                               // fit, so that we can discard the partially-
+                               // copied host name.
+                               //
+                               eos = hostlist + strlen(hostlist);
+                               if (eos != hostlist)
+                               {
+                                       //
+                                       // The list is not empty, so prepend
+                                       // a comma before adding this host.
+                                       //
+                                       result = pcap_strlcat(hostlist, ",", sizeof(hostlist));
+                                       if (result >= sizeof(hostlist))
+                                       {
+                                               //
+                                               // It didn't fit.  Discard
+                                               // the comma (which wasn't
+                                               // added, but...), complain,
+                                               // and ignore this line.
+                                               //
+                                               *eos = '\0';
+                                               rpcapd_log(LOGPRIO_ERROR,
+                                                   "%s, line %u has a %s parameter with a host name that doesn't fit",
+                                                   loadfile, lineno, PARAM_PASSIVECLIENT);
+                                               continue;
+                                       }
+                               }
+                               result = pcap_strlcat(hostlist, host, sizeof(hostlist));
+                               if (result >= sizeof(hostlist))
+                               {
+                                       //
+                                       // It didn't fit.  Discard the comma,
+                                       // complain, and ignore this line.
+                                       //
+                                       *eos = '\0';
+                                       rpcapd_log(LOGPRIO_ERROR,
+                                           "%s, line %u has a %s parameter with a host name that doesn't fit",
+                                           loadfile, lineno, PARAM_PASSIVECLIENT);
+                                       continue;
+                               }
+                       }
+                       else if (strcmp(param, PARAM_NULLAUTHPERMIT) == 0)
+                       {
+                               char *setting;
+
+                               //
+                               // Get the setting.
+                               // We look for a white space character
+                               // or a # as a terminator; the # introduces
+                               // a comment that runs to the end of the
+                               // line.
+                               //
+                               setting = ptr;
+                               toklen = strcspn(ptr, " \t#\r\n");
+                               ptr += toklen;
+                               if (toklen == 0)
+                               {
+                                       //
+                                       // The first character it saw
+                                       // was a whitespace character
+                                       // or a comment character.
+                                       // This means that there's
+                                       // no value.
+                                       //
+                                       rpcapd_log(LOGPRIO_ERROR,
+                                           "%s, line %u has a parameter but no value",
+                                           loadfile, lineno);
+                                       continue;
+                               }
+                               *ptr++ = '\0';
+
+                               //
+                               // XXX - should we complain if it's
+                               // neither "yes" nor "no"?
+                               //
+                               if (strcmp(setting, "YES") == 0)
+                                       nullAuthAllowed = 1;
+                               else
+                                       nullAuthAllowed = 0;
+                       }
+                       else
+                       {
+                               rpcapd_log(LOGPRIO_ERROR,
+                                   "%s, line %u has an unknown parameter %s",
+                                   loadfile, lineno, param);
+                               continue;
+                       }
+               }
+
+done:
+               // clear the remaining fields of the active list
+               for (int i = num_active_clients; i < MAX_ACTIVE_LIST; i++)
+               {
+                       activelist[i].address[0] = 0;
+                       activelist[i].port[0] = 0;
+                       num_active_clients++;
+               }
+
+               rpcapd_log(LOGPRIO_DEBUG, "New passive host list: %s", hostlist);
+               fclose(fp);
+       }
+}
+
+int fileconf_save(const char *savefile)
+{
+       FILE *fp;
+
+       if ((fp = fopen(savefile, "w")) != NULL)
+       {
+               char *token; /*, *port;*/                                       // temp, needed to separate items into the hostlist
+               char temphostlist[MAX_HOST_LIST + 1];
+               int i = 0;
+               char *lasts;
+
+               fprintf(fp, "# Configuration file help.\n\n");
+
+               // Save list of clients which are allowed to connect to us in passive mode
+               fprintf(fp, "# Hosts which are allowed to connect to this server (passive mode)\n");
+               fprintf(fp, "# Format: PassiveClient = <name or address>\n\n");
+
+               strncpy(temphostlist, hostlist, MAX_HOST_LIST);
+               temphostlist[MAX_HOST_LIST] = 0;
+
+               token = pcap_strtok_r(temphostlist, RPCAP_HOSTLIST_SEP, &lasts);
+               while(token != NULL)
+               {
+                       fprintf(fp, "%s = %s\n", PARAM_PASSIVECLIENT, token);
+                       token = pcap_strtok_r(NULL, RPCAP_HOSTLIST_SEP, &lasts);
+               }
+
+
+               // Save list of clients which are allowed to connect to us in active mode
+               fprintf(fp, "\n\n");
+               fprintf(fp, "# Hosts to which this server is trying to connect to (active mode)\n");
+               fprintf(fp, "# Format: ActiveClient = <name or address>, <port | DEFAULT>\n\n");
+
+
+               while ((i < MAX_ACTIVE_LIST) && (activelist[i].address[0] != 0))
+               {
+                       fprintf(fp, "%s = %s, %s\n", PARAM_ACTIVECLIENT,
+                           activelist[i].address, activelist[i].port);
+                       i++;
+               }
+
+               // Save if we want to permit NULL authentication
+               fprintf(fp, "\n\n");
+               fprintf(fp, "# Permit NULL authentication: YES or NO\n\n");
+
+               fprintf(fp, "%s = %s\n", PARAM_NULLAUTHPERMIT,
+                   nullAuthAllowed ? "YES" : "NO");
+
+               fclose(fp);
+               return 0;
+       }
+       else
+       {
+               return -1;
+       }
+
+}
+
+//
+// Skip over white space.
+// If we hit a CR or LF, return NULL, otherwise return a pointer to
+// the first non-white space character.  Replace white space characters
+// other than CR or LF with '\0', so that, if we're skipping white space
+// after a token, the token is null-terminated.
+//
+static char *skipws(char *ptr)
+{
+       while (isascii((unsigned char)*ptr) && isspace((unsigned char)*ptr)) {
+               if (*ptr == '\r' || *ptr == '\n')
+                       return NULL;
+               *ptr++ = '\0';
+       }
+       return ptr;
+}
similarity index 77%
rename from pcap-canusb-linux.h
rename to rpcapd/fileconf.h
index c8f3be1..912dd32 100644 (file)
@@ -1,5 +1,6 @@
 /*
- * Copyright (c) 2009 Felix Obenhuber
+ * Copyright (c) 2002 - 2003
+ * NetGroup, Politecnico di Torino (Italy)
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
@@ -11,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. 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 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
  *
  */
 
-/*
- * Prototypes for SocketCAN related functions
- */
-pcap_t* canusb_create(const char *device, char *ebuf, int *is_ours);
-int canusb_findalldevs(pcap_if_t **pdevlist, char* errbuf);
+#ifndef __FILECONF_H__
+#define __FILECONF_H__
+
+void fileconf_read(void);
+int fileconf_save(const char *savefile);
 
+#endif
diff --git a/rpcapd/log.c b/rpcapd/log.c
new file mode 100644 (file)
index 0000000..7b5fee5
--- /dev/null
@@ -0,0 +1,260 @@
+/*
+ * Copyright (c) 1993, 1994, 1995, 1996, 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: (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.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <stdio.h>
+#include <stdarg.h>
+#include <stdlib.h>
+
+#ifdef _WIN32
+#include <windows.h>
+#else
+#include <syslog.h>
+#endif
+
+#include "portability.h"
+
+#include "log.h"
+
+static int log_to_systemlog;
+static int log_debug_messages;
+
+static void rpcapd_vlog_stderr(log_priority,
+    PCAP_FORMAT_STRING(const char *), va_list) PCAP_PRINTFLIKE(2, 0);
+
+static void rpcapd_vlog_stderr(log_priority priority, const char *message, va_list ap)
+{
+       const char *tag;
+
+       /*
+        * Squelch warnings from compilers that *don't* assume that
+        * priority always has a valid enum value and therefore don't
+        * assume that we'll always go through one of the case arms.
+        *
+        * If we have a default case, compilers that *do* assume that
+        * will then complain about the default case code being
+        * unreachable.
+        *
+        * Damned if you do, damned if you don't.
+        */
+       tag = "";
+
+       switch (priority) {
+
+       case LOGPRIO_DEBUG:
+               tag = "DEBUG: ";
+               break;
+
+       case LOGPRIO_INFO:
+               tag = "";
+               break;
+
+       case LOGPRIO_WARNING:
+               tag = "warning: ";
+               break;
+
+       case LOGPRIO_ERROR:
+               tag = "error: ";
+               break;
+       }
+
+       fprintf(stderr, "rpcapd: %s", tag);
+       vfprintf(stderr, message, ap);
+       putc('\n', stderr);
+}
+
+static void rpcapd_vlog_systemlog(log_priority,
+    PCAP_FORMAT_STRING(const char *), va_list) PCAP_PRINTFLIKE(2, 0);
+
+#ifdef _WIN32
+#define MESSAGE_SUBKEY \
+    "SYSTEM\\CurrentControlSet\\Services\\EventLog\\Application\\rpcapd"
+
+static void rpcapd_vlog_systemlog(log_priority priority, const char *message,
+    va_list ap)
+{
+#if 0
+       static int initialized = 0;
+       HKEY hey_handle;
+       static HANDLE log_handle;
+       WORD eventlog_type;
+       DWORD event_id;
+       char msgbuf[1024];
+       char *strings[1];
+
+       if (!initialized) {
+               /*
+                * Register our message stuff in the Registry.
+                *
+                * First, create the registry key for us.  If the key
+                * already exists, this succeeds and returns a handle
+                * for it.
+                */
+               if (RegCreateKey(HKEY_LOCAL_MACHINE, MESSAGE_SUBKEY,
+                   &key_handle) != ERROR_SUCCESS) {
+                       /*
+                        * Failed - give up and just log this message,
+                        * and all subsequent messages, to the
+                        * standard error.
+                        */
+                       log_to_systemlog = 0;
+                       initialized = 1;
+                       rpcapd_vlog_stderr(priority, message, ap);
+                       return;
+               }
+               log_handle = RegisterEventSource(NULL, "rpcapd");
+               initialized = 1;
+       }
+
+       switch (priority) {
+
+       case LOGPRIO_DEBUG:
+               //
+               // XXX - what *should* we do about debug messages?
+               //
+               eventlog_type = EVENTLOG_INFORMATION_TYPE;
+               event_id = RPCAPD_INFO_ID;
+               break;
+
+       case LOGPRIO_INFO:
+               eventlog_type = EVENTLOG_INFORMATION_TYPE;
+               event_id = RPCAPD_INFO_ID;
+               break;
+
+       case LOGPRIO_WARNING:
+               eventlog_type = EVENTLOG_WARNING_TYPE;
+               event_id = RPCAPD_WARNING_ID;
+               break;
+
+       case LOGPRIO_ERROR:
+               eventlog_type = EVENTLOG_ERROR_TYPE;
+               event_id = RPCAPD_ERROR_ID;
+               break;
+
+       default:
+               /* Don't do this. */
+               return;
+       }
+
+       vsprintf(msgbuf, message, ap);
+
+       strings[0] = msgbuf;
+       /*
+        * If this fails, how are we going to report it?
+        */
+       (void) ReportEvent(log_handle, eventlog_type, 0, event_id, NULL, 1, 0,
+           strings, NULL);
+#else
+       rpcapd_vlog_stderr(priority, message, ap);
+#endif
+}
+#else
+static void rpcapd_vlog_systemlog(log_priority priority, const char *message,
+    va_list ap)
+{
+       static int initialized = 0;
+       int syslog_priority;
+
+       if (!initialized) {
+               //
+               // Open the log.
+               //
+               openlog("rpcapd", LOG_PID, LOG_DAEMON);
+               initialized = 1;
+       }
+
+       switch (priority) {
+
+       case LOGPRIO_DEBUG:
+               syslog_priority = LOG_DEBUG;
+               break;
+
+       case LOGPRIO_INFO:
+               syslog_priority = LOG_INFO;
+               break;
+
+       case LOGPRIO_WARNING:
+               syslog_priority = LOG_WARNING;
+               break;
+
+       case LOGPRIO_ERROR:
+               syslog_priority = LOG_ERR;
+               break;
+
+       default:
+               /* Don't do this. */
+               return;
+       }
+
+#ifdef HAVE_VSYSLOG
+       vsyslog(syslog_priority, message, ap);
+#else
+       /*
+        * Thanks, IBM, for not providing vsyslog() in AIX!
+        *
+        * They also warn that the syslog functions shouldn't
+        * be used in multithreaded programs, but the only thing
+        * obvious that seems to make the syslog_r functions
+        * better is that they have an additional argument
+        * that points to the information that's static to
+        * the syslog code in non-thread-safe versions.  Most
+        * of that data is set by openlog(); since we already
+        * do an openlog before doing logging, and don't
+        * change that data afterwards, I suspect that, in
+        * practice, the regular syslog routines are OK for
+        * us (especially given that we'd end up having one
+        * static struct syslog_data anyway, which means we'd
+        * just be like the non-thread-safe version).
+        */
+       char logbuf[1024+1];
+
+       pcap_vsnprintf(logbuf, sizeof logbuf, message, ap);
+       syslog(syslog_priority, "%s", logbuf);
+#endif
+}
+#endif
+
+void rpcapd_log_set(int log_to_systemlog_arg, int log_debug_messages_arg)
+{
+       log_debug_messages = log_debug_messages_arg;
+       log_to_systemlog = log_to_systemlog_arg;
+}
+
+void rpcapd_log(log_priority priority, const char *message, ...)
+{
+       va_list ap;
+
+       if (priority != LOGPRIO_DEBUG || log_debug_messages) {
+               va_start(ap, message);
+               if (log_to_systemlog)
+               {
+                       rpcapd_vlog_systemlog(priority, message, ap);
+               }
+               else
+               {
+                       rpcapd_vlog_stderr(priority, message, ap);
+               }
+               va_end(ap);
+       }
+}
diff --git a/rpcapd/log.h b/rpcapd/log.h
new file mode 100644 (file)
index 0000000..28a6cee
--- /dev/null
@@ -0,0 +1,34 @@
+/*
+ * Copyright (c) 1993, 1994, 1995, 1996, 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: (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.
+ */
+
+#include "pcap/funcattrs.h"
+
+extern void rpcapd_log_set(int, int);
+
+typedef enum {
+       LOGPRIO_DEBUG,
+       LOGPRIO_INFO,
+       LOGPRIO_WARNING,
+       LOGPRIO_ERROR
+} log_priority;
+
+extern void rpcapd_log(log_priority priority,
+    PCAP_FORMAT_STRING(const char *message), ...) PCAP_PRINTFLIKE(2, 3);
diff --git a/rpcapd/org.tcpdump.rpcapd.plist b/rpcapd/org.tcpdump.rpcapd.plist
new file mode 100644 (file)
index 0000000..db3223a
--- /dev/null
@@ -0,0 +1,30 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
+<plist version="1.0">
+<dict>
+       <key>Disabled</key>
+       <false/>
+       <key>Label</key>
+       <string>com.tcpdump.rpcapd</string>
+       <key>Program</key>
+       <string>/usr/local/libexec/rpcapd</string>
+       <key>ProgramArguments</key>
+       <array>
+               <string>/usr/local/libexec/rpcapd</string>
+               <string>-i</string>
+       </array>
+       <key>Sockets</key>
+       <dict>
+               <key>Listeners</key>
+               <dict>
+                       <key>SockServiceName</key>
+                       <string>2002</string>
+               </dict>
+       </dict>
+       <key>inetdCompatibility</key>
+       <dict>
+               <key>Wait</key>
+               <false/>
+       </dict>
+</dict>
+</plist>
diff --git a/rpcapd/rpcapd-config.manfile.in b/rpcapd/rpcapd-config.manfile.in
new file mode 100644 (file)
index 0000000..1a87529
--- /dev/null
@@ -0,0 +1,78 @@
+.\" Copyright (c) 1994, 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.
+.\"
+.TH RPCAPD-CONFIG @MAN_FILE_FORMATS@ "6 January 2019"
+.SH NAME
+rpcapd-config \- rpcapd configuration file format
+.SH DESCRIPTION
+An 
+.B rpcapd
+configuration file allows parameters to be set for
+.BR rpcapd (@MAN_ADMIN_COMMANDS@).
+.LP
+A # introduces a comment that runs to the end of the line.  Blank lines,
+and lines with only a comment, are ignored.  Leading and trailing white
+space on a line are also ignored.
+.LP
+Lines that set a parameter are of the form
+.IP
+\fIparameter\fB=\fIvalue\fR
+.LP
+Whitespace preceding or following the = is ignored.
+.LP
+The
+.IR parameter s
+are:
+.TP
+.B ActiveClient
+.I value
+is a host name or IP addresse, followed by a comma,
+semicolon, or space, followed by a port name and address or
+.BR DEFAULT .
+.B DEFAULT
+specifies the default active mode port for rpcapd, port 2003.
+Each
+.B ActiveClient
+line adds the host and port to the list of clients to which the server
+should connect in active mode.
+.TP
+.B PassiveClient
+.I value
+is a host name or IP addresse, followed by a comma,
+semicolon, or space, followed by a port name and address or
+.BR DEFAULT .
+.B DEFAULT
+specifies the default passive mode port for rpcapd, port 2002.
+Each
+.B PassiveClient
+line adds the host and port to the list of clients addresses and ports
+that are allowed to connect to the server in passive mode.
+.TP
+.B NullAuthPermit
+.I value
+is either
+.B YES
+or
+.BR NO .
+.B YES
+means that null authentication is permitted;
+.B No
+means that it is not permitted.
+.SH SEE ALSO
+rpcapd(@MAN_ADMIN_COMMANDS@)
diff --git a/rpcapd/rpcapd.c b/rpcapd/rpcapd.c
new file mode 100644 (file)
index 0000000..430acdc
--- /dev/null
@@ -0,0 +1,1359 @@
+/*
+ * 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
+
+#include "ftmacros.h"
+
+#include <errno.h>             // for the errno variable
+#include <string.h>            // for strtok, etc
+#include <stdlib.h>            // for malloc(), free(), ...
+#include <pcap.h>              // for PCAP_ERRBUF_SIZE
+#include <signal.h>            // for signal()
+
+#include "fmtutils.h"
+#include "sockutils.h"         // for socket calls
+#include "varattrs.h"          // for _U_
+#include "portability.h"
+#include "rpcapd.h"
+#include "config_params.h"     // configuration file parameters
+#include "fileconf.h"          // for the configuration file management
+#include "rpcap-protocol.h"
+#include "daemon.h"            // the true main() method of this daemon
+#include "log.h"
+
+#ifdef _WIN32
+  #include <process.h>         // for thread stuff
+  #include "win32-svc.h"       // for Win32 service stuff
+  #include "getopt.h"          // for getopt()-for-Windows
+#else
+  #include <fcntl.h>           // for open()
+  #include <unistd.h>          // for exit()
+  #include <sys/wait.h>                // waitpid()
+#endif
+
+//
+// Element in list of sockets on which we're listening for connections.
+//
+struct listen_sock {
+       struct listen_sock *next;
+       SOCKET sock;
+};
+
+// Global variables
+char hostlist[MAX_HOST_LIST + 1];              //!< Keeps the list of the hosts that are allowed to connect to this server
+struct active_pars activelist[MAX_ACTIVE_LIST];        //!< Keeps the list of the hosts (host, port) on which I want to connect to (active mode)
+int nullAuthAllowed;                           //!< '1' if we permit NULL authentication, '0' otherwise
+static struct listen_sock *listen_socks;       //!< sockets on which we listen
+char loadfile[MAX_LINE + 1];                   //!< Name of the file from which we have to load the configuration
+static int passivemode = 1;                    //!< '1' if we want to run in passive mode as well
+static struct addrinfo mainhints;              //!< temporary struct to keep settings needed to open the new socket
+static char address[MAX_LINE + 1];             //!< keeps the network address (either numeric or literal) to bind to
+static char port[MAX_LINE + 1];                        //!< keeps the network port to bind to
+#ifdef _WIN32
+static HANDLE state_change_event;              //!< event to signal that a state change should take place
+#endif
+static volatile sig_atomic_t shutdown_server;  //!< '1' if the server is to shut down
+static volatile sig_atomic_t reread_config;    //!< '1' if the server is to re-read its configuration
+
+extern char *optarg;   // for getopt()
+
+// Function definition
+#ifdef _WIN32
+static unsigned __stdcall main_active(void *ptr);
+static BOOL WINAPI main_ctrl_event(DWORD);
+#else
+static void *main_active(void *ptr);
+static void main_terminate(int sign);
+static void main_reread_config(int sign);
+#endif
+static void accept_connections(void);
+static void accept_connection(SOCKET listen_sock);
+#ifndef _WIN32
+static void main_reap_children(int sign);
+#endif
+#ifdef _WIN32
+static unsigned __stdcall main_passive_serviceloop_thread(void *ptr);
+#endif
+
+#define RPCAP_ACTIVE_WAIT 30           /* Waiting time between two attempts to open a connection, in active mode (default: 30 sec) */
+
+/*!
+       \brief Prints the usage screen if it is launched in console mode.
+*/
+static void printusage(void)
+{
+       const char *usagetext =
+       "USAGE:"
+       " "  PROGRAM_NAME " [-b <address>] [-p <port>] [-4] [-l <host_list>] [-a <host,port>]\n"
+       "              [-n] [-v] [-d] "
+#ifndef _WIN32
+       "[-i] "
+#endif
+        "[-D] [-s <config_file>] [-f <config_file>]\n\n"
+       "  -b <address>    the address to bind to (either numeric or literal).\n"
+       "                  Default: binds to all local IPv4 and IPv6 addresses\n\n"
+       "  -p <port>       the port to bind to.\n"
+       "                  Default: binds to port " RPCAP_DEFAULT_NETPORT "\n\n"
+       "  -4              use only IPv4.\n"
+       "                  Default: use both IPv4 and IPv6 waiting sockets\n\n"
+       "  -l <host_list>  a file that contains a list of hosts that are allowed\n"
+       "                  to connect to this server (if more than one, list them one\n"
+       "                  per line).\n"
+       "                  We suggest to use literal names (instead of numeric ones)\n"
+       "                  in order to avoid problems with different address families.\n\n"
+       "  -n              permit NULL authentication (usually used with '-l')\n\n"
+       "  -a <host,port>  run in active mode when connecting to 'host' on port 'port'\n"
+       "                  In case 'port' is omitted, the default port (" RPCAP_DEFAULT_NETPORT_ACTIVE ") is used\n\n"
+       "  -v              run in active mode only (default: if '-a' is specified, it\n"
+       "                  accepts passive connections as well)\n\n"
+       "  -d              run in daemon mode (UNIX only) or as a service (Win32 only)\n"
+       "                  Warning (Win32): this switch is provided automatically when\n"
+       "                  the service is started from the control panel\n\n"
+#ifndef _WIN32
+       "  -i              run in inetd mode (UNIX only)\n\n"
+#endif
+       "  -D              log debugging messages\n\n"
+       "  -s <config_file> save the current configuration to file\n\n"
+       "  -f <config_file> load the current configuration from file; all switches\n"
+       "                  specified from the command line are ignored\n\n"
+       "  -h              print this help screen\n\n";
+
+       (void)fprintf(stderr, "RPCAPD, a remote packet capture daemon.\n"
+       "Compiled with %s\n\n", pcap_lib_version());
+       printf("%s", usagetext);
+}
+
+
+
+//! Program main
+int main(int argc, char *argv[])
+{
+       char savefile[MAX_LINE + 1];            // name of the file on which we have to save the configuration
+       int log_to_systemlog = 0;               // Non-zero if we should log to the "system log" rather than the standard error
+       int isdaemon = 0;                       // Non-zero if the user wants to run this program as a daemon
+#ifndef _WIN32
+       int isrunbyinetd = 0;                   // Non-zero if this is being run by inetd or something inetd-like
+#endif
+       int log_debug_messages = 0;             // Non-zero if the user wants debug messages logged
+       int retval;                             // keeps the returning value from several functions
+       char errbuf[PCAP_ERRBUF_SIZE + 1];      // keeps the error string, prior to be printed
+#ifndef _WIN32
+       struct sigaction action;
+#endif
+
+       savefile[0] = 0;
+       loadfile[0] = 0;
+       hostlist[0] = 0;
+
+       // Initialize errbuf
+       memset(errbuf, 0, sizeof(errbuf));
+
+       strncpy(address, RPCAP_DEFAULT_NETADDR, MAX_LINE);
+       strncpy(port, RPCAP_DEFAULT_NETPORT, MAX_LINE);
+
+       // Prepare to open a new server socket
+       memset(&mainhints, 0, sizeof(struct addrinfo));
+
+       mainhints.ai_family = PF_UNSPEC;
+       mainhints.ai_flags = AI_PASSIVE;        // Ready to a bind() socket
+       mainhints.ai_socktype = SOCK_STREAM;
+
+       // Getting the proper command line options
+       while ((retval = getopt(argc, argv, "b:dDhip:4l:na:s:f:v")) != -1)
+       {
+               switch (retval)
+               {
+                       case 'D':
+                               log_debug_messages = 1;
+                               rpcapd_log_set(log_to_systemlog, log_debug_messages);
+                               break;
+                       case 'b':
+                               strncpy(address, optarg, MAX_LINE);
+                               break;
+                       case 'p':
+                               strncpy(port, optarg, MAX_LINE);
+                               break;
+                       case '4':
+                               mainhints.ai_family = PF_INET;          // IPv4 server only
+                               break;
+                       case 'd':
+                               isdaemon = 1;
+                               log_to_systemlog = 1;
+                               rpcapd_log_set(log_to_systemlog, log_debug_messages);
+                               break;
+                       case 'i':
+#ifdef _WIN32
+                               printusage();
+                               exit(1);
+#else
+                               isrunbyinetd = 1;
+                               log_to_systemlog = 1;
+                               rpcapd_log_set(log_to_systemlog, log_debug_messages);
+#endif
+                               break;
+                       case 'n':
+                               nullAuthAllowed = 1;
+                               break;
+                       case 'v':
+                               passivemode = 0;
+                               break;
+                       case 'l':
+                       {
+                               strncpy(hostlist, optarg, sizeof(hostlist));
+                               break;
+                       }
+                       case 'a':
+                       {
+                               char *tmpaddress, *tmpport;
+                               char *lasts;
+                               int i = 0;
+
+                               tmpaddress = pcap_strtok_r(optarg, RPCAP_HOSTLIST_SEP, &lasts);
+
+                               while ((tmpaddress != NULL) && (i < MAX_ACTIVE_LIST))
+                               {
+                                       tmpport = pcap_strtok_r(NULL, RPCAP_HOSTLIST_SEP, &lasts);
+
+                                       pcap_strlcpy(activelist[i].address, tmpaddress, MAX_LINE);
+
+                                       if ((tmpport == NULL) || (strcmp(tmpport, "DEFAULT") == 0)) // the user choose a custom port
+                                               pcap_strlcpy(activelist[i].port, RPCAP_DEFAULT_NETPORT_ACTIVE, MAX_LINE);
+                                       else
+                                               pcap_strlcpy(activelist[i].port, tmpport, MAX_LINE);
+
+                                       tmpaddress = pcap_strtok_r(NULL, RPCAP_HOSTLIST_SEP, &lasts);
+
+                                       i++;
+                               }
+
+                               if (i > MAX_ACTIVE_LIST)
+                                       rpcapd_log(LOGPRIO_ERROR, "Only MAX_ACTIVE_LIST active connections are currently supported.");
+
+                               // I don't initialize the remaining part of the structure, since
+                               // it is already zeroed (it is a global var)
+                               break;
+                       }
+                       case 'f':
+                               pcap_strlcpy(loadfile, optarg, MAX_LINE);
+                               break;
+                       case 's':
+                               pcap_strlcpy(savefile, optarg, MAX_LINE);
+                               break;
+                       case 'h':
+                               printusage();
+                               exit(0);
+                               /*NOTREACHED*/
+                       default:
+                               exit(1);
+                               /*NOTREACHED*/
+               }
+       }
+
+#ifndef _WIN32
+       if (isdaemon && isrunbyinetd)
+       {
+               rpcapd_log(LOGPRIO_ERROR, "rpcapd: -d and -i can't be used together");
+               exit(1);
+       }
+#endif
+
+       if (sock_init(errbuf, PCAP_ERRBUF_SIZE) == -1)
+       {
+               rpcapd_log(LOGPRIO_ERROR, "%s", errbuf);
+               exit(-1);
+       }
+
+       if (savefile[0] && fileconf_save(savefile))
+               rpcapd_log(LOGPRIO_DEBUG, "Error when saving the configuration to file");
+
+       // If the file does not exist, it keeps the settings provided by the command line
+       if (loadfile[0])
+               fileconf_read();
+
+#ifdef WIN32
+       //
+       // Create a handle to signal the main loop to tell it to do
+       // something.
+       //
+       state_change_event = CreateEvent(NULL, FALSE, FALSE, NULL);
+       if (state_change_event == NULL)
+       {
+               sock_geterror("Can't create state change event", errbuf,
+                   PCAP_ERRBUF_SIZE);
+               rpcapd_log(LOGPRIO_ERROR, "%s", errbuf);
+               exit(2);
+       }
+
+       //
+       // Catch control signals.
+       //
+       if (!SetConsoleCtrlHandler(main_ctrl_event, TRUE))
+       {
+               sock_geterror("Can't set control handler", errbuf,
+                   PCAP_ERRBUF_SIZE);
+               rpcapd_log(LOGPRIO_ERROR, "%s", errbuf);
+               exit(2);
+       }
+#else
+       memset(&action, 0, sizeof (action));
+       action.sa_handler = main_terminate;
+       action.sa_flags = 0;
+       sigemptyset(&action.sa_mask);
+       sigaction(SIGTERM, &action, NULL);
+       memset(&action, 0, sizeof (action));
+       action.sa_handler = main_reap_children;
+       action.sa_flags = 0;
+       sigemptyset(&action.sa_mask);
+       sigaction(SIGCHLD, &action, NULL);
+       // Ignore SIGPIPE - we'll get EPIPE when trying to write to a closed
+       // connection, we don't want to get killed by a signal in that case
+       signal(SIGPIPE, SIG_IGN);
+#endif
+
+#ifndef _WIN32
+       if (isrunbyinetd)
+       {
+               //
+               // -i was specified, indicating that this is being run
+               // by inetd or something that can run network daemons
+               // as if it were inetd (xinetd, launchd, systemd, etc.).
+               //
+               // We assume that the program that launched us just
+               // duplicated a single socket for the connection
+               // to our standard input, output, and error, so we
+               // can just use the standard input as our control
+               // socket.
+               //
+               int sockctrl;
+               int devnull_fd;
+
+               //
+               // Duplicate the standard input as the control socket.
+               //
+               sockctrl = dup(0);
+               if (sockctrl == -1)
+               {
+                       sock_geterror("Can't dup standard input", errbuf,
+                           PCAP_ERRBUF_SIZE);
+                       rpcapd_log(LOGPRIO_ERROR, "%s", errbuf);
+                       exit(2);
+               }
+
+               //
+               // Try to set the standard input, output, and error
+               // to /dev/null.
+               //
+               devnull_fd = open("/dev/null", O_RDWR);
+               if (devnull_fd != -1)
+               {
+                       //
+                       // If this fails, just drive on.
+                       //
+                       (void)dup2(devnull_fd, 0);
+                       (void)dup2(devnull_fd, 1);
+                       (void)dup2(devnull_fd, 2);
+                       close(devnull_fd);
+               }
+
+               //
+               // Handle this client.
+               // This is passive mode, so we don't care whether we were
+               // told by the client to close.
+               //
+               char *hostlist_copy = strdup(hostlist);
+               if (hostlist_copy == NULL)
+               {
+                       rpcapd_log(LOGPRIO_ERROR, "Out of memory copying the host/port list");
+                       exit(0);
+               }
+               (void)daemon_serviceloop(sockctrl, 0, hostlist_copy,
+                   nullAuthAllowed);
+
+               //
+               // Nothing more to do.
+               //
+               exit(0);
+       }
+#endif
+
+       if (isdaemon)
+       {
+               //
+               // This is being run as a daemon.
+               // On UN*X, it might be manually run, or run from an
+               // rc file.
+               //
+#ifndef _WIN32
+               int pid;
+
+               //
+               // Daemonize ourselves.
+               //
+               // Unix Network Programming, pg 336
+               //
+               if ((pid = fork()) != 0)
+                       exit(0);                // Parent terminates
+
+               // First child continues
+               // Set daemon mode
+               setsid();
+
+               // generated under unix with 'kill -HUP', needed to reload the configuration
+               memset(&action, 0, sizeof (action));
+               action.sa_handler = main_reread_config;
+               action.sa_flags = 0;
+               sigemptyset(&action.sa_mask);
+               sigaction(SIGHUP, &action, NULL);
+
+               if ((pid = fork()) != 0)
+                       exit(0);                // First child terminates
+
+               // LINUX WARNING: the current linux implementation of pthreads requires a management thread
+               // to handle some hidden stuff. So, as soon as you create the first thread, two threads are
+               // created. Fom this point on, the number of threads active are always one more compared
+               // to the number you're expecting
+
+               // Second child continues
+//             umask(0);
+//             chdir("/");
+#else
+               //
+               // This is being run as a service on Windows.
+               //
+               // If this call succeeds, it is blocking on Win32
+               //
+               if (svc_start() != 1)
+                       rpcapd_log(LOGPRIO_DEBUG, "Unable to start the service");
+
+               // When the previous call returns, the entire application has to be stopped.
+               exit(0);
+#endif
+       }
+       else    // Console mode
+       {
+#ifndef _WIN32
+               // Enable the catching of Ctrl+C
+               memset(&action, 0, sizeof (action));
+               action.sa_handler = main_terminate;
+               action.sa_flags = 0;
+               sigemptyset(&action.sa_mask);
+               sigaction(SIGINT, &action, NULL);
+
+               // generated under unix with 'kill -HUP', needed to reload the configuration
+               // We do not have this kind of signal in Win32
+               memset(&action, 0, sizeof (action));
+               action.sa_handler = main_reread_config;
+               action.sa_flags = 0;
+               sigemptyset(&action.sa_mask);
+               sigaction(SIGHUP, &action, NULL);
+#endif
+
+               printf("Press CTRL + C to stop the server...\n");
+       }
+
+       // If we're a Win32 service, we have already called this function in the service_main
+       main_startup();
+
+       // The code should never arrive here (since the main_startup is blocking)
+       //  however this avoids a compiler warning
+       exit(0);
+}
+
+void main_startup(void)
+{
+       char errbuf[PCAP_ERRBUF_SIZE + 1];      // keeps the error string, prior to be printed
+       struct addrinfo *addrinfo;              // keeps the addrinfo chain; required to open a new socket
+       int i;
+#ifdef _WIN32
+       HANDLE threadId;                        // handle for the subthread
+#else
+       pid_t pid;
+#endif
+
+       i = 0;
+       addrinfo = NULL;
+       memset(errbuf, 0, sizeof(errbuf));
+
+       // Starts all the active threads
+       while ((i < MAX_ACTIVE_LIST) && (activelist[i].address[0] != 0))
+       {
+               activelist[i].ai_family = mainhints.ai_family;
+
+#ifdef _WIN32
+               threadId = (HANDLE)_beginthreadex(NULL, 0, main_active,
+                   (void *)&activelist[i], 0, NULL);
+               if (threadId == 0)
+               {
+                       rpcapd_log(LOGPRIO_DEBUG, "Error creating the active child threads");
+                       continue;
+               }
+               CloseHandle(threadId);
+#else
+               if ((pid = fork()) == 0)        // I am the child
+               {
+                       main_active((void *) &activelist[i]);
+                       exit(0);
+               }
+#endif
+               i++;
+       }
+
+       /*
+        * The code that manages the active connections is not blocking;
+        * the code that manages the passive connection is blocking.
+        * So, if the user does not want to run in passive mode, we have
+        * to block the main thread here, otherwise the program ends and
+        * all threads are stopped.
+        *
+        * WARNING: this means that in case we have only active mode,
+        * the program does not terminate even if all the child thread
+        * terminates. The user has always to press Ctrl+C (or send a
+        * SIGTERM) to terminate the program.
+        */
+       if (passivemode)
+       {
+               struct addrinfo *tempaddrinfo;
+
+               //
+               // Get a list of sockets on which to listen.
+               //
+               if (sock_initaddress((address[0]) ? address : NULL, port, &mainhints, &addrinfo, errbuf, PCAP_ERRBUF_SIZE) == -1)
+               {
+                       rpcapd_log(LOGPRIO_DEBUG, "%s", errbuf);
+                       return;
+               }
+
+               for (tempaddrinfo = addrinfo; tempaddrinfo;
+                    tempaddrinfo = tempaddrinfo->ai_next)
+               {
+                       SOCKET sock;
+                       struct listen_sock *sock_info;
+
+                       if ((sock = sock_open(tempaddrinfo, SOCKOPEN_SERVER, SOCKET_MAXCONN, errbuf, PCAP_ERRBUF_SIZE)) == INVALID_SOCKET)
+                       {
+                               switch (tempaddrinfo->ai_family)
+                               {
+                               case AF_INET:
+                               {
+                                       struct sockaddr_in *in;
+                                       char addrbuf[INET_ADDRSTRLEN];
+
+                                       in = (struct sockaddr_in *)tempaddrinfo->ai_addr;
+                                       rpcapd_log(LOGPRIO_WARNING, "Can't listen on socket for %s:%u: %s",
+                                           inet_ntop(AF_INET, &in->sin_addr,
+                                               addrbuf, sizeof (addrbuf)),
+                                           ntohs(in->sin_port),
+                                           errbuf);
+                                       break;
+                               }
+
+                               case AF_INET6:
+                               {
+                                       struct sockaddr_in6 *in6;
+                                       char addrbuf[INET6_ADDRSTRLEN];
+
+                                       in6 = (struct sockaddr_in6 *)tempaddrinfo->ai_addr;
+                                       rpcapd_log(LOGPRIO_WARNING, "Can't listen on socket for %s:%u: %s",
+                                           inet_ntop(AF_INET6, &in6->sin6_addr,
+                                               addrbuf, sizeof (addrbuf)),
+                                           ntohs(in6->sin6_port),
+                                           errbuf);
+                                       break;
+                               }
+
+                               default:
+                                       rpcapd_log(LOGPRIO_WARNING, "Can't listen on socket for address family %u: %s",
+                                           tempaddrinfo->ai_family,
+                                           errbuf);
+                                       break;
+                               }
+                               continue;
+                       }
+
+                       sock_info = (struct listen_sock *) malloc(sizeof (struct listen_sock));
+                       if (sock_info == NULL)
+                       {
+                               rpcapd_log(LOGPRIO_ERROR, "Can't allocate structure for listen socket");
+                               exit(2);
+                       }
+                       sock_info->sock = sock;
+                       sock_info->next = listen_socks;
+                       listen_socks = sock_info;
+               }
+
+               freeaddrinfo(addrinfo);
+
+               if (listen_socks == NULL)
+               {
+                       rpcapd_log(LOGPRIO_ERROR, "Can't listen on any address");
+                       exit(2);
+               }
+
+               //
+               // Now listen on all of them, waiting for connections.
+               //
+               accept_connections();
+       }
+
+       //
+       // We're done; exit.
+       //
+       rpcapd_log(LOGPRIO_DEBUG, PROGRAM_NAME " is closing.\n");
+
+#ifndef _WIN32
+       //
+       // Sends a KILL signal to all the processes in this process's
+       // process group; i.e., it kills all the child processes
+       // we've created.
+       //
+       // XXX - that also includes us, so we will be killed as well;
+       // that may cause a message to be printed or logged.
+       //
+       kill(0, SIGKILL);
+#endif
+
+       //
+       // Just leave.  We shouldn't need to clean up sockets or
+       // anything else, and if we try to do so, we'll could end
+       // up closing sockets, or shutting Winsock down, out from
+       // under service loops, causing all sorts of noisy error
+       // messages.
+       //
+       // We shouldn't need to worry about cleaning up any resources
+       // such as handles, sockets, threads, etc. - exit() should
+       // terminate the process, causing all those resources to be
+       // cleaned up (including the threads; Microsoft claims in the
+       // ExitProcess() documentation that, if ExitProcess() is called,
+       // "If a thread is waiting on a kernel object, it will not be
+       // terminated until the wait has completed.", but claims in the
+       // _beginthread()/_beginthreadex() documentation that "All threads
+       // are terminated if any thread calls abort, exit, _exit, or
+       // ExitProcess." - the latter appears to be the case, even for
+       // threads waiting on the event for a pcap_t).
+       //
+       exit(0);
+}
+
+#ifdef _WIN32
+static void
+send_state_change_event(void)
+{
+       char errbuf[PCAP_ERRBUF_SIZE + 1];      // keeps the error string, prior to be printed
+
+       if (!SetEvent(state_change_event))
+       {
+               sock_geterror("SetEvent on shutdown event failed", errbuf,
+                   PCAP_ERRBUF_SIZE);
+               rpcapd_log(LOGPRIO_ERROR, "%s", errbuf);
+       }
+}
+
+void
+send_shutdown_notification(void)
+{
+       //
+       // Indicate that the server should shut down.
+       //
+       shutdown_server = 1;
+
+       //
+       // Send a state change event, to wake up WSAWaitForMultipleEvents().
+       //
+       send_state_change_event();
+}
+
+void
+send_reread_configuration_notification(void)
+{
+       //
+       // Indicate that the server should re-read its configuration file.
+       //
+       reread_config = 1;
+
+       //
+       // Send a state change event, to wake up WSAWaitForMultipleEvents().
+       //
+       send_state_change_event();
+}
+
+static BOOL WINAPI main_ctrl_event(DWORD ctrltype)
+{
+       //
+       // ctrltype is one of:
+       //
+       // CTRL_C_EVENT - we got a ^C; this is like SIGINT
+       // CTRL_BREAK_EVENT - we got Ctrl+Break
+       // CTRL_CLOSE_EVENT - the console was closed; this is like SIGHUP
+       // CTRL_LOGOFF_EVENT - a user is logging off; this is received
+       //   only by services
+       // CTRL_SHUTDOWN_EVENT - the systemis shutting down; this is
+       //   received only by services
+       //
+       // For now, we treat all but CTRL_LOGOFF_EVENT as indications
+       // that we should shut down.
+       //
+       switch (ctrltype)
+       {
+               case CTRL_C_EVENT:
+               case CTRL_BREAK_EVENT:
+               case CTRL_CLOSE_EVENT:
+               case CTRL_SHUTDOWN_EVENT:
+                       //
+                       // Set a shutdown notification.
+                       //
+                       send_shutdown_notification();
+                       break;
+
+               default:
+                       break;
+       }
+
+       //
+       // We handled this.
+       //
+       return TRUE;
+}
+#else
+static void main_terminate(int sign _U_)
+{
+       //
+       // Note that the server should shut down.
+       // select() should get an EINTR error when we return,
+       // so it will wake up and know it needs to check the flag.
+       //
+       shutdown_server = 1;
+}
+
+static void main_reread_config(int sign _U_)
+{
+       //
+       // Note that the server should re-read its configuration file.
+       // select() should get an EINTR error when we return,
+       // so it will wake up and know it needs to check the flag.
+       //
+       reread_config = 1;
+}
+
+static void main_reap_children(int sign _U_)
+{
+       pid_t pid;
+       int exitstat;
+
+       // Reap all child processes that have exited.
+       // For reference, Stevens, pg 128
+
+       while ((pid = waitpid(-1, &exitstat, WNOHANG)) > 0)
+               rpcapd_log(LOGPRIO_DEBUG, "Child terminated");
+
+       return;
+}
+#endif
+
+//
+// Loop waiting for incoming connections and accepting them.
+//
+static void
+accept_connections(void)
+{
+#ifdef _WIN32
+       struct listen_sock *sock_info;
+       DWORD num_events;
+       WSAEVENT *events;
+       int i;
+       char errbuf[PCAP_ERRBUF_SIZE + 1];      // keeps the error string, prior to be printed
+
+       //
+       // How big does the set of events need to be?
+       // One for the shutdown event, plus one for every socket on which
+       // we'll be listening.
+       //
+       num_events = 1;         // shutdown event
+       for (sock_info = listen_socks; sock_info;
+           sock_info = sock_info->next)
+       {
+               if (num_events == WSA_MAXIMUM_WAIT_EVENTS)
+               {
+                       //
+                       // WSAWaitForMultipleEvents() doesn't support
+                       // more than WSA_MAXIMUM_WAIT_EVENTS events
+                       // on which to wait.
+                       //
+                       rpcapd_log(LOGPRIO_ERROR, "Too many sockets on which to listen");
+                       exit(2);
+               }
+               num_events++;
+       }
+
+       //
+       // Allocate the array of events.
+       //
+       events = (WSAEVENT *) malloc(num_events * sizeof (WSAEVENT));
+       if (events == NULL)
+       {
+               rpcapd_log(LOGPRIO_ERROR, "Can't allocate array of events which to listen");
+               exit(2);
+       }
+
+       //
+       // Fill it in.
+       //
+       events[0] = state_change_event; // state change event first
+       for (sock_info = listen_socks, i = 1; sock_info;
+           sock_info = sock_info->next, i++)
+       {
+               WSAEVENT event;
+
+               //
+               // Create an event that is signaled if there's a connection
+               // to accept on the socket in question.
+               //
+               event = WSACreateEvent();
+               if (event == WSA_INVALID_EVENT)
+               {
+                       sock_geterror("Can't create socket event", errbuf,
+                           PCAP_ERRBUF_SIZE);
+                       rpcapd_log(LOGPRIO_ERROR, "%s", errbuf);
+                       exit(2);
+               }
+               if (WSAEventSelect(sock_info->sock, event, FD_ACCEPT) == SOCKET_ERROR)
+               {
+                       sock_geterror("Can't setup socket event", errbuf,
+                           PCAP_ERRBUF_SIZE);
+                       rpcapd_log(LOGPRIO_ERROR, "%s", errbuf);
+                       exit(2);
+               }
+               events[i] = event;
+       }
+
+       for (;;)
+       {
+               //
+               // Wait for incoming connections.
+               //
+               DWORD ret;
+
+               ret = WSAWaitForMultipleEvents(num_events, events, FALSE,
+                   WSA_INFINITE, FALSE);
+               if (ret == WSA_WAIT_FAILED)
+               {
+                       sock_geterror("WSAWaitForMultipleEvents failed", errbuf,
+                           PCAP_ERRBUF_SIZE);
+                       rpcapd_log(LOGPRIO_ERROR, "%s", errbuf);
+                       exit(2);
+               }
+
+               if (ret == WSA_WAIT_EVENT_0)
+               {
+                       //
+                       // The state change event was set.
+                       //
+                       if (shutdown_server)
+                       {
+                               //
+                               // Time to quit. Exit the loop.
+                               //
+                               break;
+                       }
+                       if (reread_config)
+                       {
+                               //
+                               // We should re-read the configuration
+                               // file.
+                               //
+                               reread_config = 0;      // clear the indicator
+                               fileconf_read();
+                       }
+               }
+
+               //
+               // Check each socket.
+               //
+               for (sock_info = listen_socks, i = 1; sock_info;
+                   sock_info = sock_info->next, i++)
+               {
+                       WSANETWORKEVENTS network_events;
+
+                       if (WSAEnumNetworkEvents(sock_info->sock,
+                           events[i], &network_events) == SOCKET_ERROR)
+                       {
+                               sock_geterror("WSAEnumNetworkEvents failed",
+                                   errbuf, PCAP_ERRBUF_SIZE);
+                               rpcapd_log(LOGPRIO_ERROR, "%s", errbuf);
+                               exit(2);
+                       }
+                       if (network_events.lNetworkEvents & FD_ACCEPT)
+                       {
+                               //
+                               // Did an error occur?
+                               //
+                               if (network_events.iErrorCode[FD_ACCEPT_BIT] != 0)
+                               {
+                                       //
+                                       // Yes - report it and keep going.
+                                       //
+                                       sock_fmterror("Socket error",
+                                           network_events.iErrorCode[FD_ACCEPT_BIT],
+                                           errbuf,
+                                           PCAP_ERRBUF_SIZE);
+                                       rpcapd_log(LOGPRIO_ERROR, "%s", errbuf);
+                                       continue;
+                               }
+
+                               //
+                               // Accept the connection.
+                               //
+                               accept_connection(sock_info->sock);
+                       }
+               }
+       }
+#else
+       struct listen_sock *sock_info;
+       int num_sock_fds;
+
+       //
+       // How big does the bitset of sockets on which to select() have
+       // to be?
+       //
+       num_sock_fds = 0;
+       for (sock_info = listen_socks; sock_info; sock_info = sock_info->next)
+       {
+               if (sock_info->sock + 1 > num_sock_fds)
+               {
+                       if ((unsigned int)(sock_info->sock + 1) >
+                           (unsigned int)FD_SETSIZE)
+                       {
+                               rpcapd_log(LOGPRIO_ERROR, "Socket FD is too bit for an fd_set");
+                               exit(2);
+                       }
+                       num_sock_fds = sock_info->sock + 1;
+               }
+       }
+
+       for (;;)
+       {
+               fd_set sock_fds;
+               int ret;
+
+               //
+               // Set up an fd_set for all the sockets on which we're
+               // listening.
+               //
+               // This set is modified by select(), so we have to
+               // construct it anew each time.
+               //
+               FD_ZERO(&sock_fds);
+               for (sock_info = listen_socks; sock_info;
+                   sock_info = sock_info->next)
+               {
+                       FD_SET(sock_info->sock, &sock_fds);
+               }
+
+               //
+               // Wait for incoming connections.
+               //
+               ret = select(num_sock_fds, &sock_fds, NULL, NULL, NULL);
+               if (ret == -1)
+               {
+                       if (errno == EINTR)
+                       {
+                               //
+                               // If this is a "terminate the
+                               // server" signal, exit the loop,
+                               // otherwise just keep trying.
+                               //
+                               if (shutdown_server)
+                               {
+                                       //
+                                       // Time to quit.  Exit the loop.
+                                       //
+                                       break;
+                               }
+                               if (reread_config)
+                               {
+                                       //
+                                       // We should re-read the configuration
+                                       // file.
+                                       //
+                                       reread_config = 0;      // clear the indicator
+                                       fileconf_read();
+                               }
+
+                               //
+                               // Go back and wait again.
+                               //
+                               continue;
+                       }
+                       else
+                       {
+                               rpcapd_log(LOGPRIO_ERROR, "select failed: %s",
+                                   strerror(errno));
+                               exit(2);
+                       }
+               }
+
+               //
+               // Check each socket.
+               //
+               for (sock_info = listen_socks; sock_info;
+                   sock_info = sock_info->next)
+               {
+                       if (FD_ISSET(sock_info->sock, &sock_fds))
+                       {
+                               //
+                               // Accept the connection.
+                               //
+                               accept_connection(sock_info->sock);
+                       }
+               }
+       }
+#endif
+
+       //
+       // Close all the listen sockets.
+       //
+       for (sock_info = listen_socks; sock_info; sock_info = sock_info->next)
+       {
+               closesocket(sock_info->sock);
+       }
+       sock_cleanup();
+}
+
+#ifdef _WIN32
+//
+// A structure to hold the parameters to the daemon service loop
+// thread on Windows.
+//
+// (On UN*X, there is no need for this explicit copy since the
+// fork "inherits" the parent stack.)
+//
+struct params_copy {
+       SOCKET sockctrl;
+       char *hostlist;
+};
+#endif
+
+//
+// Accept a connection and start a worker thread, on Windows, or a
+// worker process, on UN*X, to handle the connection.
+//
+static void
+accept_connection(SOCKET listen_sock)
+{
+       char errbuf[PCAP_ERRBUF_SIZE + 1];      // keeps the error string, prior to be printed
+       SOCKET sockctrl;                        // keeps the socket ID for this control connection
+       struct sockaddr_storage from;           // generic sockaddr_storage variable
+       socklen_t fromlen;                      // keeps the length of the sockaddr_storage variable
+
+#ifdef _WIN32
+       HANDLE threadId;                        // handle for the subthread
+       u_long off = 0;
+       struct params_copy *params_copy = NULL;
+#else
+       pid_t pid;
+#endif
+
+       // Initialize errbuf
+       memset(errbuf, 0, sizeof(errbuf));
+
+       for (;;)
+       {
+               // Accept the connection
+               fromlen = sizeof(struct sockaddr_storage);
+
+               sockctrl = accept(listen_sock, (struct sockaddr *) &from, &fromlen);
+
+               if (sockctrl != INVALID_SOCKET)
+               {
+                       // Success.
+                       break;
+               }
+
+               // The accept() call can return this error when a signal is catched
+               // In this case, we have simply to ignore this error code
+               // Stevens, pg 124
+#ifdef _WIN32
+               if (WSAGetLastError() == WSAEINTR)
+#else
+               if (errno == EINTR)
+#endif
+                       continue;
+
+               // Don't check for errors here, since the error can be due to the fact that the thread
+               // has been killed
+               sock_geterror("accept()", errbuf, PCAP_ERRBUF_SIZE);
+               rpcapd_log(LOGPRIO_ERROR, "Accept of control connection from client failed: %s",
+                   errbuf);
+               return;
+       }
+
+#ifdef _WIN32
+       //
+       // Put the socket back into blocking mode; doing WSAEventSelect()
+       // on the listen socket makes that socket non-blocking, and it
+       // appears that sockets returned from an accept() on that socket
+       // are also non-blocking.
+       //
+       // First, we have to un-WSAEventSelect() this socket, and then
+       // we can turn non-blocking mode off.
+       //
+       // If this fails, we aren't guaranteed that, for example, any
+       // of the error message will be sent - if it can't be put in
+       // the socket queue, the send will just fail.
+       //
+       // So we just log the message and close the connection.
+       //
+       if (WSAEventSelect(sockctrl, NULL, 0) == SOCKET_ERROR)
+       {
+               sock_geterror("WSAEventSelect()", errbuf, PCAP_ERRBUF_SIZE);
+               rpcapd_log(LOGPRIO_ERROR, "%s", errbuf);
+               sock_close(sockctrl, NULL, 0);
+               return;
+       }
+       if (ioctlsocket(sockctrl, FIONBIO, &off) == SOCKET_ERROR)
+       {
+               sock_geterror("ioctlsocket(FIONBIO)", errbuf, PCAP_ERRBUF_SIZE);
+               rpcapd_log(LOGPRIO_ERROR, "%s", errbuf);
+               sock_close(sockctrl, NULL, 0);
+               return;
+       }
+
+       //
+       // Make a copy of the host list to pass to the new thread, so that
+       // if we update it in the main thread, it won't catch us in the
+       // middle of updating it.
+       //
+       // daemon_serviceloop() will free it once it's done with it.
+       //
+       char *hostlist_copy = strdup(hostlist);
+       if (hostlist_copy == NULL)
+       {
+               rpcapd_log(LOGPRIO_ERROR, "Out of memory copying the host/port list");
+               sock_close(sockctrl, NULL, 0);
+               return;
+       }
+
+       //
+       // Allocate a location to hold the values of sockctrl.
+       // It will be freed in the newly-created thread once it's
+       // finished with it.
+       //
+       params_copy = malloc(sizeof(*params_copy));
+       if (params_copy == NULL)
+       {
+               rpcapd_log(LOGPRIO_ERROR, "Out of memory allocating the parameter copy structure");
+               free(hostlist_copy);
+               sock_close(sockctrl, NULL, 0);
+               return;
+       }
+       params_copy->sockctrl = sockctrl;
+       params_copy->hostlist = hostlist_copy;
+
+       threadId = (HANDLE)_beginthreadex(NULL, 0,
+           main_passive_serviceloop_thread, (void *) params_copy, 0, NULL);
+       if (threadId == 0)
+       {
+               rpcapd_log(LOGPRIO_ERROR, "Error creating the child thread");
+               free(params_copy);
+               free(hostlist_copy);
+               sock_close(sockctrl, NULL, 0);
+               return;
+       }
+       CloseHandle(threadId);
+#else /* _WIN32 */
+       pid = fork();
+       if (pid == -1)
+       {
+               rpcapd_log(LOGPRIO_ERROR, "Error creating the child process: %s",
+                   strerror(errno));
+               sock_close(sockctrl, NULL, 0);
+               return;
+       }
+       if (pid == 0)
+       {
+               //
+               // Child process.
+               //
+               // Close the socket on which we're listening (must
+               // be open only in the parent).
+               //
+               closesocket(listen_sock);
+
+#if 0
+               //
+               // Modify thread params so that it can be killed at any time
+               // XXX - is this necessary?  This is the main and, currently,
+               // only thread in the child process, and nobody tries to
+               // cancel us, although *we* may cancel the thread that's
+               // handling the capture loop.
+               //
+               if (pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, NULL))
+                       goto end;
+               if (pthread_setcanceltype(PTHREAD_CANCEL_ASYNCHRONOUS, NULL))
+                       goto end;
+#endif
+
+               //
+               // Run the service loop.
+               // This is passive mode, so we don't care whether we were
+               // told by the client to close.
+               //
+               char *hostlist_copy = strdup(hostlist);
+               if (hostlist_copy == NULL)
+               {
+                       rpcapd_log(LOGPRIO_ERROR, "Out of memory copying the host/port list");
+                       exit(0);
+               }
+               (void)daemon_serviceloop(sockctrl, 0, hostlist_copy,
+                   nullAuthAllowed);
+
+               exit(0);
+       }
+
+       // I am the parent
+       // Close the socket for this session (must be open only in the child)
+       closesocket(sockctrl);
+#endif /* _WIN32 */
+}
+
+/*!
+       \brief 'true' main of the program in case the active mode is turned on.
+
+       This function loops forever trying to connect to the remote host, until the
+       daemon is turned down.
+
+       \param ptr: it keeps the 'activepars' parameters.  It is a 'void *'
+       just because the thread APIs want this format.
+*/
+#ifdef _WIN32
+static unsigned __stdcall
+#else
+static void *
+#endif
+main_active(void *ptr)
+{
+       char errbuf[PCAP_ERRBUF_SIZE + 1];      // keeps the error string, prior to be printed
+       SOCKET sockctrl;                        // keeps the socket ID for this control connection
+       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 active_pars *activepars;
+
+       activepars = (struct active_pars *) ptr;
+
+       // 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_socktype = SOCK_STREAM;
+       hints.ai_family = activepars->ai_family;
+
+       rpcapd_log(LOGPRIO_DEBUG, "Connecting to host %s, port %s, using protocol %s",
+           activepars->address, activepars->port, (hints.ai_family == AF_INET) ? "IPv4":
+           (hints.ai_family == AF_INET6) ? "IPv6" : "Unspecified");
+
+       // Initialize errbuf
+       memset(errbuf, 0, sizeof(errbuf));
+
+       // Do the work
+       if (sock_initaddress(activepars->address, activepars->port, &hints, &addrinfo, errbuf, PCAP_ERRBUF_SIZE) == -1)
+       {
+               rpcapd_log(LOGPRIO_DEBUG, "%s", errbuf);
+               return 0;
+       }
+
+       for (;;)
+       {
+               int activeclose;
+
+               if ((sockctrl = sock_open(addrinfo, SOCKOPEN_CLIENT, 0, errbuf, PCAP_ERRBUF_SIZE)) == INVALID_SOCKET)
+               {
+                       rpcapd_log(LOGPRIO_DEBUG, "%s", errbuf);
+
+                       pcap_snprintf(errbuf, PCAP_ERRBUF_SIZE, "Error connecting to host %s, port %s, using protocol %s",
+                                       activepars->address, activepars->port, (hints.ai_family == AF_INET) ? "IPv4":
+                                       (hints.ai_family == AF_INET6) ? "IPv6" : "Unspecified");
+
+                       rpcapd_log(LOGPRIO_DEBUG, "%s", errbuf);
+
+                       sleep_secs(RPCAP_ACTIVE_WAIT);
+
+                       continue;
+               }
+
+               char *hostlist_copy = strdup(hostlist);
+               if (hostlist_copy == NULL)
+               {
+                       rpcapd_log(LOGPRIO_ERROR, "Out of memory copying the host/port list");
+                       activeclose = 0;
+                       sock_close(sockctrl, NULL, 0);
+               }
+               else
+               {
+                       //
+                       // daemon_serviceloop() will free the copy.
+                       //
+                       activeclose = daemon_serviceloop(sockctrl, 1,
+                           hostlist_copy, nullAuthAllowed);
+               }
+
+               // If the connection is closed by the user explicitely, don't try to connect to it again
+               // just exit the program
+               if (activeclose == 1)
+                       break;
+       }
+
+       freeaddrinfo(addrinfo);
+       return 0;
+}
+
+#ifdef _WIN32
+//
+// Main routine of a passive-mode service thread.
+//
+unsigned __stdcall main_passive_serviceloop_thread(void *ptr)
+{
+       struct params_copy params = *(struct params_copy *)ptr;
+       free(ptr);
+
+       //
+       // Handle this client.
+       // This is passive mode, so we don't care whether we were
+       // told by the client to close.
+       //
+       (void)daemon_serviceloop(params.sockctrl, 0, params.hostlist,
+           nullAuthAllowed);
+
+       return 0;
+}
+#endif
diff --git a/rpcapd/rpcapd.h b/rpcapd/rpcapd.h
new file mode 100644 (file)
index 0000000..90ba7ff
--- /dev/null
@@ -0,0 +1,44 @@
+/*
+ * 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 __RPCAPD_H__
+#define __RPCAPD_H__
+
+#define PROGRAM_NAME "rpcapd"
+#define SOCKET_MAXCONN 10      /* Maximum number of connections queued into the accept() */
+#ifdef _WIN32
+void send_shutdown_notification(void); // Send notification to shut down the daemon
+void send_reread_configuration_notification(void);     // Send notification to re-read the configuration file
+#endif
+void main_startup(void);
+
+#endif
diff --git a/rpcapd/rpcapd.inetd.conf b/rpcapd/rpcapd.inetd.conf
new file mode 100644 (file)
index 0000000..86823f0
--- /dev/null
@@ -0,0 +1 @@
+2002 stream tcp nowait root /usr/local/sbin/rpcapd rpcapd -i
diff --git a/rpcapd/rpcapd.manadmin.in b/rpcapd/rpcapd.manadmin.in
new file mode 100644 (file)
index 0000000..0a9d4e0
--- /dev/null
@@ -0,0 +1,233 @@
+.\"  rpcapd.8
+.\"
+.\"  Copyright (c) 2002-2005 NetGroup, Politecnico di Torino (Italy)
+.\"  Copyright (c) 2005-2009 CACE Technologies
+.\"  Copyright (c) 2018-     The TCPdump Group
+.\"  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.
+.\"
+.TH RPCAPD @MAN_ADMIN_COMMANDS@ "April 20, 2018"
+.SH NAME
+rpcapd \- capture daemon to be controlled by a remote libpcap application
+.SH SYNOPSIS
+.na
+rpcapd
+[
+.B \-b
+.I address
+] [
+.B \-p
+.I port
+] [
+.B \-4
+] [
+.B \-l
+.I host_list
+]
+.br
+.ti +8
+[
+.B \-a
+.IR host , port
+] [
+.B \-n
+] [
+.B \-v
+] [
+.B \-d
+] [
+.B \-i
+]
+.br
+.ti +8
+[
+.B \-D
+] [
+.B \-s
+.I config_file
+] [
+.B \-f
+.I config_file
+]
+.br
+.ad
+.SH DESCRIPTION
+.LP
+\fIRpcapd\fP is a daemon (Unix) or service (Win32) that allows the capture
+and filter part of libpcap to be run on a remote system.
+.LP
+Rpcapd can run in two modes: passive mode (default) and active mode.
+.LP
+In passive mode, the client (e.g., a network sniffer) connects to
+.BR rpcapd .
+It then sends hem the appropriate commands to start the capture.
+.LP
+In active mode,
+.B rpcapd
+tries to establish a connection toward the client
+(e.g., a network sniffer). The client then sends the appropriate commands
+to rpcapd to start the capture.
+.LP
+Active mode is useful in case
+.B rpcapd
+is run behind a firewall and
+cannot receive connections from the external world. In this case,
+.B rpcapd
+can be configured to establish the connection to a given host,
+which has to be configured in order to wait for that connection. After
+establishing the connection, the protocol continues its job in almost
+the same way in both active and passive mode.
+.SH Configuration file
+.LP
+The user can create a configuration file in the same folder of the
+executable, and put the configuration commands in there. In order for
+rpcapd to execute the commands, you have to restart it on Win32, i.e.
+the initialization file is parsed only at the beginning). The UNIX
+version of rpcapd will reread the configuration file when receiving a
+HUP signel. In that case, all the existing connections remain in place,
+while the new connections will be created according to the new parameters.
+.LP
+In case a user does not want to create the configuration file manually,
+they can launch rpcapd with the requested parameters plus "-s filename".
+Rpcapd will parse all the parameters and save them into the specified
+configuration file.
+.SH Installing rpcapd on Win32
+.LP
+The remote daemon is installed automatically when installing WinPcap.
+The installation process places the rpcapd file into the WinPcap folder.
+This file can be executed either from the command line, or as a service.
+For instance, the installation process updates the list of available
+services list and it creates a new item (Remote Packet Capture Protocol
+v.0 (experimental) ).  To avoid security problems, the service is
+inactive and it has to be started manually (control panel -
+administrative tools - services - start).
+.LP
+The service has a set of "standard" parameters, i.e. it is launched
+with the
+.B \-d
+flag (in order to make it run as a service) and the
+.B "-f rpcapd.ini"
+flag.
+.SH Starting rpcapd on Win32
+.LP
+The rpcapd executable can be launched directly, i.e.  it can run in the
+foreground as well (not as a daemon/service).  The procedure is quite
+simple: you have to invoke the executable from the command line with all
+the requested parameters except for the
+.B \-d
+flag.  The capture server will
+start in the foreground.
+.SH Installing rpcapd on Unix-like systems
+TBD
+.SH Starting rpcapd on Unix-like systems
+.B rpcapd
+needs sufficient privileges to perform packet capture, e.g.
+run as root or be owned by root and have suid set. Most operating
+systems provide more elegant solutions when run as user than the
+above solutions, all of them different.
+.SH OPTIONS
+.TP
+.BI \-b " address"
+Bind to the IP address specified by
+.I address
+(either numeric or literal).
+By default,
+.B rpcapd
+binds to all local IPv4 and IPv6 addresses.
+.TP
+.BI \-p " port"
+Bind to the port specified by
+.IR port .
+By default,
+.B rpcapd
+binds to port 2002.
+.TP
+.B \-4
+Listen only on IPv4 addresses.
+By default,
+.B rpcapd
+listens on both IPv4 and IPv6 addresses.
+.TP
+.BI -l " host_list"
+Only allow hosts specified in the
+.I host_list
+argument to connect to this server.
+.I host_list
+is a list of host names or IP addresses, separated by commas.
+We suggest that you use use host names rather than literal IP addresses
+in order to avoid problems with different address families.
+.TP
+.B \-n
+Permit NULL authentication (usually used with
+.BR \-l ).
+.TP
+.BI \-a " host" , "port"
+Run in active mode, connecting to host
+.I host
+on port
+.IR port .
+In case
+.I port
+is omitted, the default port (2003) is used.
+.TP
+.B -v
+Run in active mode only; by default, if
+.B \-a
+is specified,
+.B rpcapd
+it accepts passive connections as well.
+.TP
+.B \-d
+Run in daemon mode (UNIX only) or as a service (Win32 only)
+Warning (Win32): this switch is provided automatically when
+the service is started from the control panel.
+.TP
+.B \-i
+Run in inetd mode (UNIX only).
+.TP
+.B \-D
+Log debugging messages.
+.TP
+.BI \-s " config_file"
+Save the current configuration to
+.I config_file
+in the format specified by
+.BR rpcapd-config (@MAN_FILE_FORMATS@).
+.TP
+.BI \-f " config_file"
+Load the current configuration from
+.I config_file
+in the format specified by
+.BR rpcapd-config (@MAN_FILE_FORMATS@);
+all switches specified from the command line are ignored.
+.TP
+.B \-h
+Print this help screen.
+.br
+.ad
+.SH "SEE ALSO"
+pcap(3PCAP), rpcapd-config(@MAN_FILE_FORMATS@)
diff --git a/rpcapd/rpcapd.rc b/rpcapd/rpcapd.rc
new file mode 100644 (file)
index 0000000..695c00b
--- /dev/null
@@ -0,0 +1,39 @@
+#include "config.h"
+#undef PACKAGE_NAME
+#include <winver.h>
+#include <rpcapd.h>
+#define PACKAGE_NAME PROGRAM_NAME
+
+  VS_VERSION_INFO VERSIONINFO
+    FILEVERSION    PACKAGE_VERSION_DLL
+    PRODUCTVERSION PACKAGE_VERSION_DLL
+    FILEFLAGSMASK  0x3fL
+    FILEOS         VOS__WINDOWS32
+    FILETYPE       VFT_APP
+#ifdef _DEBUG
+    FILEFLAGS 0x1L
+#else
+    FILEFLAGS 0x0L
+#endif
+  BEGIN
+    BLOCK "StringFileInfo"
+    BEGIN
+      BLOCK "040904b0"
+      BEGIN
+        VALUE "Comments",         "https://github.com/the-tcpdump-group/libpcap/"
+        VALUE "CompanyName",      "The TCPdump Group"
+        VALUE "FileDescription",  "Remote Packet Capture Daemon"
+        VALUE "FileVersion",      "PACKAGE_VERSION_DLL"
+        VALUE "InternalName",     PACKAGE_NAME
+        VALUE "LegalCopyright",   "Copyright (c) The TCPdump Group"
+        VALUE "LegalTrademarks",  ""
+        VALUE "OriginalFilename", "rpcapd.exe"
+        VALUE "ProductName",      PACKAGE_NAME
+        VALUE "ProductVersion",   PACKAGE_VERSION
+      END
+    END
+  BLOCK "VarFileInfo"
+  BEGIN
+    VALUE "Translation", 0x0, 1200
+  END
+  END
diff --git a/rpcapd/rpcapd.socket b/rpcapd/rpcapd.socket
new file mode 100644 (file)
index 0000000..9d5a0bd
--- /dev/null
@@ -0,0 +1,9 @@
+[Unit]
+Description=Rpcap Socket for Per-Connection Servers
+
+[Socket]
+ListenStream=2002
+Accept=yes
+
+[Install]
+WantedBy=sockets.target
diff --git a/rpcapd/rpcapd.xinetd.conf b/rpcapd/rpcapd.xinetd.conf
new file mode 100644 (file)
index 0000000..2c79348
--- /dev/null
@@ -0,0 +1,8 @@
+service rpcap {
+        socket_type = stream
+        protocol = tcp
+        wait = no
+        user = root
+        server = /usr/local/sbin/rpcapd
+        server_args = -i
+}
diff --git a/rpcapd/rpcapd@.service b/rpcapd/rpcapd@.service
new file mode 100644 (file)
index 0000000..92d1171
--- /dev/null
@@ -0,0 +1,6 @@
+[Unit]
+Description=Rpcap Per-Connection Server
+
+[Service]
+ExecStart=-/usr/local/sbin/rpcapd -i
+StandardInput=socket
diff --git a/rpcapd/win32-svc.c b/rpcapd/win32-svc.c
new file mode 100644 (file)
index 0000000..3a19910
--- /dev/null
@@ -0,0 +1,169 @@
+/*
+ * 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.
+ *
+ */
+
+
+#include "rpcapd.h"
+#include <pcap.h>              // for PCAP_ERRBUF_SIZE
+#include "fmtutils.h"
+#include "portability.h"
+#include "fileconf.h"
+#include "log.h"
+
+static SERVICE_STATUS_HANDLE service_status_handle;
+static SERVICE_STATUS service_status;
+
+static void WINAPI svc_main(DWORD argc, char **argv);
+static void update_svc_status(DWORD state, DWORD progress_indicator);
+
+int svc_start(void)
+{
+       int rc;
+       SERVICE_TABLE_ENTRY ste[] =
+       {
+               { PROGRAM_NAME, svc_main },
+               { NULL, NULL }
+       };
+       char string[PCAP_ERRBUF_SIZE];
+
+       // This call is blocking. A new thread is created which will launch
+       // the svc_main() function
+       if ((rc = StartServiceCtrlDispatcher(ste)) == 0) {
+               pcap_fmt_errmsg_for_win32_err(string, sizeof (string),
+                   GetLastError(), "StartServiceCtrlDispatcher() failed");
+               rpcapd_log(LOGPRIO_ERROR, "%s", string);
+       }
+
+       return rc; // FALSE if this is not started as a service
+}
+
+void WINAPI svc_control_handler(DWORD Opcode)
+{
+       switch(Opcode)
+       {
+               case SERVICE_CONTROL_STOP:
+                       //
+                       // XXX - is this sufficient to clean up the service?
+                       // To be really honest, only the main socket and
+                       // such these stuffs are cleared; however the threads
+                       // that are running are not stopped.
+                       // This can be seen by placing a breakpoint at the
+                       // end of svc_main(), in which you will see that is
+                       // never reached. However, as soon as you set the
+                       // service status to "stopped", the
+                       // StartServiceCtrlDispatcher() returns and the main
+                       // thread ends. Then, Win32 has a good automatic
+                       // cleanup, so that all the threads which are still
+                       // running are stopped when the main thread ends.
+                       //
+                       send_shutdown_notification();
+
+                       update_svc_status(SERVICE_STOP_PENDING, 0);
+                       break;
+
+               /*
+                       Pause and Continue have an usual meaning and they are used just to be able
+                       to change the running parameters at run-time. In other words, they act
+                       like the SIGHUP signal on UNIX. All the running threads continue to run and
+                       they are not paused at all.
+                       Particularly,
+                       - PAUSE does nothing
+                       - CONTINUE re-reads the configuration file and creates the new threads that
+                       can be needed according to the new configuration.
+               */
+               case SERVICE_CONTROL_PAUSE:
+                       update_svc_status(SERVICE_PAUSED, 0);
+                       break;
+
+               case SERVICE_CONTROL_CONTINUE:
+                       update_svc_status(SERVICE_RUNNING, 0);
+                       //
+                       // Tell the main loop to re-read the configuration.
+                       //
+                       send_reread_configuration_notification();
+                       break;
+
+               case SERVICE_CONTROL_INTERROGATE:
+                       // Fall through to send current status.
+                       //      WARNING: not implemented
+                       update_svc_status(SERVICE_RUNNING, 0);
+                       MessageBox(NULL, "Not implemented", "warning", MB_OK);
+                       break;
+
+               case SERVICE_CONTROL_PARAMCHANGE:
+                       //
+                       // Tell the main loop to re-read the configuration.
+                       //
+                       send_reread_configuration_notification();
+                       break;
+       }
+
+       // Send current status.
+       return;
+}
+
+void WINAPI svc_main(DWORD argc, char **argv)
+{
+       service_status_handle = RegisterServiceCtrlHandler(PROGRAM_NAME, svc_control_handler);
+
+       if (!service_status_handle)
+               return;
+
+       service_status.dwServiceType = SERVICE_WIN32_OWN_PROCESS | SERVICE_INTERACTIVE_PROCESS;
+       service_status.dwControlsAccepted = SERVICE_ACCEPT_STOP | SERVICE_ACCEPT_PAUSE_CONTINUE | SERVICE_ACCEPT_PARAMCHANGE;
+       // | SERVICE_ACCEPT_SHUTDOWN ;
+       update_svc_status(SERVICE_RUNNING, 0);
+
+       //
+       // Service requests until we're told to stop.
+       //
+       main_startup();
+
+       //
+       // It returned, so we were told to stop.
+       //
+       update_svc_status(SERVICE_STOPPED, 0);
+}
+
+static void
+update_svc_status(DWORD state, DWORD progress_indicator)
+{
+       service_status.dwWin32ExitCode = NO_ERROR;
+       service_status.dwCurrentState = state;
+       service_status.dwCheckPoint = progress_indicator;
+       service_status.dwWaitHint = 0;
+       SetServiceStatus(service_status_handle, &service_status);
+}
+
+/*
+sc create rpcapd DisplayName= "Remote Packet Capture Protocol v.0 (experimental)" binpath= "C:\cvsroot\winpcap\wpcap\PRJ\Debug\rpcapd -d -f rpcapd.ini"
+sc description rpcapd "Allows to capture traffic on this host from a remote machine."
+*/
similarity index 78%
rename from pcap-can-linux.h
rename to rpcapd/win32-svc.h
index fe806ff..3f511d2 100644 (file)
@@ -1,5 +1,6 @@
 /*
- * Copyright (c) 2009 Felix Obenhuber
+ * Copyright (c) 2002 - 2003
+ * NetGroup, Politecnico di Torino (Italy)
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
@@ -11,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. 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 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
@@ -29,8 +30,4 @@
  *
  */
 
-/*
- * 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);
+int svc_start(void);
diff --git a/runlex.sh b/runlex.sh
deleted file mode 100755 (executable)
index 24c3c2e..0000000
--- a/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
index 0ab2fde..5b1e14c 100644 (file)
  */
 
 #ifdef HAVE_CONFIG_H
-#include "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>
-#endif
-#include <sys/types.h>
-#endif /* WIN32 */
+#include <pcap-types.h>
+#ifdef _WIN32
+#include <io.h>
+#include <fcntl.h>
+#endif /* _WIN32 */
 
 #include <errno.h>
 #include <memory.h>
 #include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
+#include <limits.h> /* for INT_MAX */
 
 #include "pcap-int.h"
-#include "pcap/usb.h"
 
 #ifdef HAVE_OS_PROTO_H
 #include "os-proto.h"
 #endif
 
 #include "sf-pcap.h"
-#include "sf-pcap-ng.h"
+#include "sf-pcapng.h"
+#include "pcap-common.h"
+
+#ifdef _WIN32
+/*
+ * These aren't exported on Windows, because they would only work if both
+ * WinPcap/Npcap and the code using it were to use the Universal CRT; otherwise,
+ * a FILE structure in WinPcap/Npcap 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__)
@@ -76,7 +86,7 @@
 #endif
 
 static int
-sf_getnonblock(pcap_t *p, char *errbuf)
+sf_getnonblock(pcap_t *p _U_)
 {
        /*
         * This is a savefile, not a live capture file, so never say
@@ -86,7 +96,7 @@ sf_getnonblock(pcap_t *p, char *errbuf)
 }
 
 static int
-sf_setnonblock(pcap_t *p, int nonblock, char *errbuf)
+sf_setnonblock(pcap_t *p, int nonblock _U_)
 {
        /*
         * This is a savefile, not a live capture file, so reject
@@ -96,24 +106,32 @@ 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);
 }
 
 static int
-sf_stats(pcap_t *p, struct pcap_stat *ps)
+sf_stats(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 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 +139,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,16 +147,80 @@ 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)
+{
+       pcap_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
 sf_inject(pcap_t *p, const void *buf _U_, size_t size _U_)
 {
-       strlcpy(p->errbuf, "Sending packets isn't supported on savefiles",
+       pcap_strlcpy(p->errbuf, "Sending packets isn't supported on savefiles",
            PCAP_ERRBUF_SIZE);
        return (-1);
 }
@@ -148,9 +230,9 @@ sf_inject(pcap_t *p, const void *buf _U_, size_t size _U_)
  * single device? IN, OUT or both?
  */
 static int
-sf_setdirection(pcap_t *p, pcap_direction_t d)
+sf_setdirection(pcap_t *p, pcap_direction_t d _U_)
 {
-       snprintf(p->errbuf, sizeof(p->errbuf),
+       pcap_snprintf(p->errbuf, sizeof(p->errbuf),
            "Setting direction is not supported on savefiles");
        return (-1);
 }
@@ -167,15 +249,20 @@ sf_cleanup(pcap_t *p)
 
 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,14 +271,16 @@ pcap_open_offline_with_tstamp_precision(const char *fname, u_int precision,
 #endif
        }
        else {
-#if !defined(WIN32) && !defined(MSDOS)
-               fp = fopen(fname, "r");
-#else
+               /*
+                * "b" is supported as of C90, so *all* UN*Xes should
+                * support it, even though it does nothing.  It's
+                * required on Windows, as the file is a binary file
+                * and must be read in binary mode.
+                */
                fp = fopen(fname, "rb");
-#endif
                if (fp == NULL) {
-                       snprintf(errbuf, PCAP_ERRBUF_SIZE, "%s: %s", fname,
-                           pcap_strerror(errno));
+                       pcap_fmt_errmsg_for_errno(errbuf, PCAP_ERRBUF_SIZE,
+                           errno, "%s", fname);
                        return (NULL);
                }
        }
@@ -210,7 +299,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 +307,19 @@ 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_fmt_errmsg_for_errno(errbuf, PCAP_ERRBUF_SIZE,
+                   errno, "_open_osfhandle");
                return NULL;
        }
 
        file = _fdopen(fd, "rb");
-       if ( file == NULL ) 
+       if ( file == NULL )
        {
-               snprintf(errbuf, PCAP_ERRBUF_SIZE, pcap_strerror(errno));
+               pcap_fmt_errmsg_for_errno(errbuf, PCAP_ERRBUF_SIZE,
+                   errno, "_fdopen");
+               _close(fd);
                return NULL;
        }
 
@@ -242,14 +334,41 @@ pcap_t* pcap_hopen_offline(intptr_t osfd, char *errbuf)
 }
 #endif
 
-static pcap_t *(*check_headers[])(bpf_u_int32, FILE *, u_int, char *, int *) = {
+/*
+ * Given a link-layer header type and snapshot length, return a
+ * snapshot length to use when reading the file; it's guaranteed
+ * to be > 0 and <= INT_MAX.
+ *
+ * XXX - the only reason why we limit it to <= INT_MAX is so that
+ * it fits in p->snapshot, and the only reason that p->snapshot is
+ * signed is that pcap_snapshot() returns an int, not an unsigned int.
+ */
+bpf_u_int32
+pcap_adjust_snapshot(bpf_u_int32 linktype, bpf_u_int32 snaplen)
+{
+       if (snaplen == 0 || snaplen > INT_MAX) {
+               /*
+                * Bogus snapshot length; use the maximum for this
+                * link-layer type as a fallback.
+                *
+                * XXX - we don't clamp snapshot lengths that are
+                * <= INT_MAX but > max_snaplen_for_dlt(linktype),
+                * so a capture file could cause us to allocate
+                * a Really Big Buffer.
+                */
+               snaplen = max_snaplen_for_dlt(linktype);
+       }
+       return snaplen;
+}
+
+static pcap_t *(*check_headers[])(const uint8_t *, FILE *, u_int, char *, int *) = {
        pcap_check_header,
        pcap_ng_check_header
 };
 
 #define        N_FILE_TYPES    (sizeof check_headers / sizeof check_headers[0])
 
-#ifdef WIN32
+#ifdef _WIN32
 static
 #endif
 pcap_t *
@@ -257,29 +376,27 @@ pcap_fopen_offline_with_tstamp_precision(FILE *fp, u_int precision,
     char *errbuf)
 {
        register pcap_t *p;
-       bpf_u_int32 magic;
+       uint8_t magic[4];
        size_t amt_read;
        u_int i;
        int err;
 
        /*
         * Read the first 4 bytes of the file; the network analyzer dump
-        * file formats we support (pcap and pcap-ng), and several other
+        * file formats we support (pcap and pcapng), and several other
         * formats we might support in the future (such as snoop, DOS and
         * Windows Sniffer, and Microsoft Network Monitor) all have magic
         * numbers that are unique in their first 4 bytes.
         */
-       amt_read = fread((char *)&magic, 1, sizeof(magic), fp);
+       amt_read = fread(&magic, 1, sizeof(magic), fp);
        if (amt_read != sizeof(magic)) {
                if (ferror(fp)) {
-                       snprintf(errbuf, PCAP_ERRBUF_SIZE,
-                           "error reading dump file: %s",
-                           pcap_strerror(errno));
+                       pcap_fmt_errmsg_for_errno(errbuf, PCAP_ERRBUF_SIZE,
+                           errno, "error reading dump file");
                } else {
-                       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);
+                       pcap_snprintf(errbuf, PCAP_ERRBUF_SIZE,
+                           "truncated dump file; tried to read %" PRIsize " file header bytes, only got %" PRIsize,
+                           sizeof(magic), amt_read);
                }
                return (NULL);
        }
@@ -304,7 +421,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 +430,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 +449,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 +470,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 *
index a247c99..effcf81 100644 (file)
--- a/scanner.l
+++ b/scanner.l
@@ -1,3 +1,68 @@
+%top {
+/* Must come first for _LARGE_FILE_API on AIX. */
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+/*
+ * Must come first to avoid warnings on Windows.
+ *
+ * Flex-generated scanners may only include <inttypes.h> if __STDC_VERSION__
+ * is defined with a value >= 199901, meaning "full C99", and MSVC may not
+ * define it with that value, because it isn't 100% C99-compliant, even
+ * though it has an <inttypes.h> capable of defining everything the Flex
+ * scanner needs.
+ *
+ * We, however, will include it if we know we have an MSVC version that has
+ * it; this means that we may define the INTn_MAX and UINTn_MAX values in
+ * scanner.c, and then include <stdint.h>, which may define them differently
+ * (same value, but different string of characters), causing compiler warnings.
+ *
+ * If we include it here, and they're defined, that'll prevent scanner.c
+ * from defining them.  So we include <pcap/pcap-inttypes.h>, to get
+ * <inttypes.h> if we have it.
+ */
+#include <pcap/pcap-inttypes.h>
+
+#include "diag-control.h"
+}
+
+/*
+ * 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
  * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
  */
 
-#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>
-#endif
-#include <sys/types.h>
-#endif /* WIN32 */
-
 #include <ctype.h>
 #include <string.h>
 
 #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
+#include <winsock2.h>
+#include <ws2tcpip.h>
+/*
+ * 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.
+ */
+#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"
 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
-
-#define yylval pcap_lval
-extern YYSTYPE yylval;
+/*
+ * Disable diagnostics in the code generated by Flex.
+ */
+DIAG_OFF_FLEX
 
 %}
 
@@ -241,13 +311,7 @@ mask               return NETMASK;
 port           return PORT;
 portrange      return PORTRANGE;
 proto          return PROTO;
-protochain     {
-#ifdef NO_PROTOCHAIN
-                 bpf_error("%s not supported", yytext);
-#else
-                 return PROTOCHAIN;
-#endif
-               }
+protochain     return PROTOCHAIN;
 
 gateway                return GATEWAY;
 
@@ -279,6 +343,7 @@ vlan                return VLAN;
 mpls           return MPLS;
 pppoed         return PPPOED;
 pppoes         return PPPOES;
+geneve         return GENEVE;
 
 lane           return LANE;
 llc            return LLC;
@@ -326,103 +391,101 @@ hsls            return HSLS;
 "=="                   return '=';
 "<<"                   return LSH;
 ">>"                   return RSH;
-${B}                   { yylval.e = pcap_ether_aton(((char *)yytext)+1);
-                         if (yylval.e == NULL)
-                               bpf_error("malloc");
-                         return AID; }
-{MAC}                  { yylval.e = pcap_ether_aton((char *)yytext);
-                         if (yylval.e == NULL)
-                               bpf_error("malloc");
-                         return EID; }
-{N}                    { yylval.i = stoi((char *)yytext); return NUM; }
+${B}                   { yylval->s = sdup(yyextra, yytext); return AID; }
+{MAC}                  { yylval->s = sdup(yyextra, yytext); return EID; }
+{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;
                          memset(&hints, 0, sizeof(hints));
                          hints.ai_family = AF_INET6;
                          hints.ai_flags = AI_NUMERICHOST;
-                         if (getaddrinfo(yytext, NULL, &hints, &res))
-                               bpf_error("bogus IPv6 address %s", yytext);
-                         else {
+                         if (getaddrinfo(yytext, NULL, &hints, &res)) {
+                               bpf_set_error(yyextra, "bogus IPv6 address %s", yytext);
+                               yylval->s = NULL;
+                         } else {
                                freeaddrinfo(res);
-                               yylval.s = sdup((char *)yytext); return HID6;
+                               yylval->s = sdup(yyextra, (char *)yytext);
                          }
 #else
-                         bpf_error("IPv6 address %s not supported", yytext);
+                         bpf_set_error(yyextra, "IPv6 address %s not supported", yytext);
+                         yylval->s = NULL;
 #endif /*INET6*/
+                         return HID6;
                        }
-{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; }
+{B}:+({B}:+)+          { bpf_set_error(yyextra, "bogus ethernet address %s", yytext); yylval->s = NULL; return EID; }
+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; }
+
+icmp6type       { yylval->i = 0; return NUM; }
+icmp6code       { yylval->i = 1; return NUM; }
+
+icmp6-echo      { yylval->i = 128; return NUM; }
+icmp6-echoreply { yylval->i = 129; return NUM; }
+icmp6-multicastlistenerquery    { yylval->i = 130; return NUM; }
+icmp6-multicastlistenerreportv1 { yylval->i = 131; return NUM; }
+icmp6-multicastlistenerdone     { yylval->i = 132; return NUM; }
+icmp6-routersolicit   { yylval->i = 133; return NUM; }
+icmp6-routeradvert    { yylval->i = 134; return NUM; }
+icmp6-neighborsolicit { yylval->i = 135; return NUM; }
+icmp6-neighboradvert  { yylval->i = 136; return NUM; }
+icmp6-redirect    { yylval->i = 137; return NUM; }
+icmp6-routerrenum { yylval->i = 138; return NUM; }
+icmp6-nodeinformationquery      { yylval->i = 139; return NUM; }
+icmp6-nodeinformationresponse   { yylval->i = 140; return NUM; }
+icmp6-ineighbordiscoverysolicit { yylval->i = 141; return NUM; }
+icmp6-ineighbordiscoveryadvert  { yylval->i = 142; return NUM; }
+icmp6-multicastlistenerreportv2 { yylval->i = 143; return NUM; }
+icmp6-homeagentdiscoveryrequest { yylval->i = 144; return NUM; }
+icmp6-homeagentdiscoveryreply   { yylval->i = 145; return NUM; }
+icmp6-mobileprefixsolicit       { yylval->i = 146; return NUM; }
+icmp6-mobileprefixadvert        { yylval->i = 147; return NUM; }
+icmp6-certpathsolicit           { yylval->i = 148; return NUM; }
+icmp6-certpathadvert            { yylval->i = 149; return NUM; }
+icmp6-multicastrouteradvert     { yylval->i = 151; return NUM; }
+icmp6-multicastroutersolicit    { yylval->i = 152; return NUM; }
+icmp6-multicastrouterterm       { yylval->i = 153; 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; }
-[^ \[\]\t\n\-_.A-Za-z0-9!<>()&|=]+ {
-                       bpf_error("illegal token: %s", yytext); }
-.                      { bpf_error("illegal char '%c'", *yytext); }
+                        yylval->s = sdup(yyextra, (char *)yytext); return ID; }
+"\\"[^ !()\n\t]+       { yylval->s = sdup(yyextra, (char *)yytext + 1); return ID; }
+.                      { return LEX_ERROR; }
 %%
-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.
+ * Turn diagnostics back on, so we check the code that we've written.
  */
-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;
-}
+DIAG_ON_FLEX
 
 /* Hex digit to integer. */
 static inline int
-xdtoi(c)
-       register int c;
+xdtoi(int c)
 {
        if (isdigit(c))
                return c - '0';
@@ -437,8 +500,7 @@ xdtoi(c)
  * preceding 0x or 0 and uses hex or octal instead of decimal.
  */
 static int
-stoi(s)
-       char *s;
+stoi(char *s)
 {
        int base = 10;
        int n = 0;
index 8180bc9..60c73a8 100644 (file)
--- a/sf-pcap.c
+++ b/sf-pcap.c
  * dependent values so we can print the dump file on any architecture.
  */
 
-#ifndef lint
-static const char rcsid[] _U_ =
-    "@(#) $Header$ (LBL)";
-#endif
-
 #ifdef HAVE_CONFIG_H
-#include "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>
-#endif
-#include <sys/types.h>
-#endif /* WIN32 */
+#include <pcap-types.h>
+#ifdef _WIN32
+#include <io.h>
+#include <fcntl.h>
+#endif /* _WIN32 */
 
 #include <errno.h>
 #include <memory.h>
 #include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
+#include <limits.h> /* for INT_MAX */
 
 #include "pcap-int.h"
 
@@ -70,7 +58,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__)
@@ -122,6 +110,20 @@ static const char rcsid[] _U_ =
 
 static int pcap_next_packet(pcap_t *p, struct pcap_pkthdr *hdr, u_char **datap);
 
+#ifdef _WIN32
+/*
+ * This isn't exported on Windows, because it would only work if both
+ * libpcap and the code using it were using the same C runtime; otherwise they
+ * would be using different definitions of a FILE structure.
+ *
+ * Instead we define this as a macro in pcap/pcap.h that wraps the hopen
+ * version that we do export, passing it a raw OS HANDLE, as defined by the
+ * Win32 / Win64 ABI, obtained from the _fileno() and _get_osfhandle()
+ * functions of the appropriate CRT.
+ */
+static pcap_dumper_t *pcap_dump_fopen(pcap_t *p, FILE *f);
+#endif /* _WIN32 */
+
 /*
  * Private data for reading pcap savefiles.
  */
@@ -148,9 +150,10 @@ struct pcap_sf {
  * relevant information from the header.
  */
 pcap_t *
-pcap_check_header(bpf_u_int32 magic, FILE *fp, u_int precision, char *errbuf,
-    int *err)
+pcap_check_header(const uint8_t *magic, FILE *fp, u_int precision, char *errbuf,
+                 int *err)
 {
+       bpf_u_int32 magic_int;
        struct pcap_file_header hdr;
        size_t amt_read;
        pcap_t *p;
@@ -167,11 +170,14 @@ pcap_check_header(bpf_u_int32 magic, FILE *fp, u_int precision, char *errbuf,
         * number for a pcap savefile, or for a byte-swapped pcap
         * savefile.
         */
-       if (magic != TCPDUMP_MAGIC && magic != KUZNETZOV_TCPDUMP_MAGIC &&
-           magic != NSEC_TCPDUMP_MAGIC) {
-               magic = SWAPLONG(magic);
-               if (magic != TCPDUMP_MAGIC && magic != KUZNETZOV_TCPDUMP_MAGIC &&
-                   magic != NSEC_TCPDUMP_MAGIC)
+       memcpy(&magic_int, magic, sizeof(magic_int));
+       if (magic_int != TCPDUMP_MAGIC &&
+           magic_int != KUZNETZOV_TCPDUMP_MAGIC &&
+           magic_int != NSEC_TCPDUMP_MAGIC) {
+               magic_int = SWAPLONG(magic_int);
+               if (magic_int != TCPDUMP_MAGIC &&
+                   magic_int != KUZNETZOV_TCPDUMP_MAGIC &&
+                   magic_int != NSEC_TCPDUMP_MAGIC)
                        return (NULL);  /* nope */
                swapped = 1;
        }
@@ -180,19 +186,17 @@ pcap_check_header(bpf_u_int32 magic, FILE *fp, u_int precision, char *errbuf,
         * They are.  Put the magic number in the header, and read
         * the rest of the header.
         */
-       hdr.magic = magic;
+       hdr.magic = magic_int;
        amt_read = fread(((char *)&hdr) + sizeof hdr.magic, 1,
            sizeof(hdr) - sizeof(hdr.magic), fp);
        if (amt_read != sizeof(hdr) - sizeof(hdr.magic)) {
                if (ferror(fp)) {
-                       snprintf(errbuf, PCAP_ERRBUF_SIZE,
-                           "error reading dump file: %s",
-                           pcap_strerror(errno));
+                       pcap_fmt_errmsg_for_errno(errbuf, PCAP_ERRBUF_SIZE,
+                           errno, "error reading dump file");
                } else {
-                       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);
+                       pcap_snprintf(errbuf, PCAP_ERRBUF_SIZE,
+                           "truncated dump file; tried to read %" PRIsize " file header bytes, only got %" PRIsize,
+                           sizeof(hdr), amt_read);
                }
                *err = 1;
                return (NULL);
@@ -211,13 +215,28 @@ 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;
+       }
+
+       /*
         * OK, this is a good pcap file.
         * Allocate a pcap_t for it.
         */
@@ -231,9 +250,9 @@ pcap_check_header(bpf_u_int32 magic, FILE *fp, u_int precision, char *errbuf,
        p->version_major = hdr.version_major;
        p->version_minor = hdr.version_minor;
        p->tzoff = hdr.thiszone;
-       p->snapshot = hdr.snaplen;
        p->linktype = linktype_to_dlt(LT_LINKTYPE(hdr.linktype));
        p->linktype_ext = LT_LINKTYPE_EXT(hdr.linktype);
+       p->snapshot = pcap_adjust_snapshot(p->linktype, hdr.snaplen);
 
        p->next_packet_op = pcap_next_packet;
 
@@ -248,7 +267,7 @@ pcap_check_header(bpf_u_int32 magic, FILE *fp, u_int precision, char *errbuf,
        switch (precision) {
 
        case PCAP_TSTAMP_PRECISION_MICRO:
-               if (magic == NSEC_TCPDUMP_MAGIC) {
+               if (magic_int == NSEC_TCPDUMP_MAGIC) {
                        /*
                         * The file has nanoseconds, the user
                         * wants microseconds; scale the
@@ -265,7 +284,7 @@ pcap_check_header(bpf_u_int32 magic, FILE *fp, u_int precision, char *errbuf,
                break;
 
        case PCAP_TSTAMP_PRECISION_NANO:
-               if (magic == NSEC_TCPDUMP_MAGIC) {
+               if (magic_int == NSEC_TCPDUMP_MAGIC) {
                        /*
                         * The file has nanoseconds, the
                         * user wants nanoseconds; nothing to do.
@@ -282,7 +301,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;
@@ -319,7 +338,7 @@ pcap_check_header(bpf_u_int32 magic, FILE *fp, u_int precision, char *errbuf,
                break;
        }
 
-       if (magic == KUZNETZOV_TCPDUMP_MAGIC) {
+       if (magic_int == KUZNETZOV_TCPDUMP_MAGIC) {
                /*
                 * XXX - the patch that's in some versions of libpcap
                 * changes the packet header but not the magic number,
@@ -359,25 +378,33 @@ pcap_check_header(bpf_u_int32 magic, FILE *fp, u_int precision, char *errbuf,
                         * length will be misleading if you use it to figure
                         * out why a capture doesn't have all the packet data,
                         * but there's not much we can do to avoid that.
+                        *
+                        * But don't grow the snapshot length past the
+                        * maximum value of an int.
                         */
-                       p->snapshot += 14;
+                       if (p->snapshot <= INT_MAX - 14)
+                               p->snapshot += 14;
+                       else
+                               p->snapshot = INT_MAX;
                }
        } else
                ps->hdrsize = sizeof(struct pcap_sf_pkthdr);
 
        /*
         * Allocate a buffer for the packet data.
+        * Choose the minimum of the file's snapshot length and 2K bytes;
+        * that should be enough for most network packets - we'll grow it
+        * if necessary.  That way, we don't allocate a huge chunk of
+        * memory just because there's a huge snapshot length, as the
+        * snapshot length might be larger than the size of the largest
+        * packet.
         */
        p->bufsize = p->snapshot;
-       if (p->bufsize <= 0) {
-               /*
-                * Bogus snapshot length; use the maximum as a fallback.
-                */
-               p->bufsize = MAXIMUM_SNAPLEN;
-       }
+       if (p->bufsize > 2048)
+               p->bufsize = 2048;
        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);
@@ -389,6 +416,24 @@ pcap_check_header(bpf_u_int32 magic, FILE *fp, u_int precision, char *errbuf,
 }
 
 /*
+ * Grow the packet buffer to the specified size.
+ */
+static int
+grow_buffer(pcap_t *p, u_int bufsize)
+{
+       void *bigger_buffer;
+
+       bigger_buffer = realloc(p->buffer, bufsize);
+       if (bigger_buffer == NULL) {
+               pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "out of memory");
+               return (0);
+       }
+       p->buffer = bigger_buffer;
+       p->bufsize = bufsize;
+       return (1);
+}
+
+/*
  * Read and return the next packet from the savefile.  Return the header
  * in hdr and a pointer to the contents in data.  Return 0 on success, 1
  * if there were no more packets, and -1 on an error.
@@ -412,16 +457,14 @@ 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,
-                           "error reading dump file: %s",
-                           pcap_strerror(errno));
+                       pcap_fmt_errmsg_for_errno(p->errbuf, PCAP_ERRBUF_SIZE,
+                           errno, "error reading dump file");
                        return (-1);
                } else {
                        if (amt_read != 0) {
-                               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);
+                               pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
+                                   "truncated dump file; tried to read %" PRIsize " header bytes, only got %" PRIsize,
+                                   ps->hdrsize, amt_read);
                                return (-1);
                        }
                        /* EOF */
@@ -490,69 +533,174 @@ pcap_next_packet(pcap_t *p, struct pcap_pkthdr *hdr, u_char **data)
                break;
        }
 
-       if (hdr->caplen > p->bufsize) {
+       /*
+        * Is the packet bigger than we consider sane?
+        */
+       if (hdr->caplen > max_snaplen_for_dlt(p->linktype)) {
+               /*
+                * Yes.  This may be a damaged or fuzzed file.
+                *
+                * Is it bigger than the snapshot length?
+                * (We don't treat that as an error if it's not
+                * bigger than the maximum we consider sane; see
+                * below.)
+                */
+               if (hdr->caplen > (bpf_u_int32)p->snapshot) {
+                       pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
+                           "invalid packet capture length %u, bigger than "
+                           "snaplen of %d", hdr->caplen, p->snapshot);
+               } else {
+                       pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
+                           "invalid packet capture length %u, bigger than "
+                           "maximum of %u", hdr->caplen,
+                           max_snaplen_for_dlt(p->linktype));
+               }
+               return (-1);
+       }
+
+       if (hdr->caplen > (bpf_u_int32)p->snapshot) {
                /*
+                * The packet is bigger than the snapshot length
+                * for this file.
+                *
                 * 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.
+                * length correctly in the savefile header.
+                *
+                * libpcap 0.4 and later on Solaris 2.3 should set the
+                * snapshot length correctly in the pcap file header,
+                * even though they don't set a snapshot length in bufmod
+                * (the buggy bufmod chops off the *beginning* of the
+                * packet if a snapshot length is specified); they should
+                * also reduce the captured length, as supplied to the
+                * per-packet callback, to the snapshot length if it's
+                * greater than the snapshot length, so the code using
+                * libpcap should see the packet cut off at the snapshot
+                * length, even though the full packet is copied up to
+                * userland.
+                *
+                * However, perhaps some versions of libpcap failed to
+                * set the snapshot length currectly in the file header
+                * or the per-packet header, or perhaps this is a
+                * corrupted safefile or a savefile built/modified by a
+                * fuzz tester, so we check anyway.  We grow the buffer
+                * to be big enough for the snapshot length, read up
+                * to the snapshot length, discard the rest of the
+                * packet, and report the snapshot length as the captured
+                * length; we don't want to hand our caller a packet
+                * bigger than the snapshot length, because they might
+                * be assuming they'll never be handed such a packet,
+                * and might copy the packet into a snapshot-length-
+                * sized buffer, assuming it'll fit.
                 */
-               static u_char *tp = NULL;
-               static size_t tsize = 0;
-
-               if (hdr->caplen > MAXIMUM_SNAPLEN) {
-                       snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
-                           "bogus savefile header");
-                       return (-1);
-               }
+               size_t bytes_to_discard;
+               size_t bytes_to_read, bytes_read;
+               char discard_buf[4096];
 
-               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");
+               if (hdr->caplen > p->bufsize) {
+                       /*
+                        * Grow the buffer to the snapshot length.
+                        */
+                       if (!grow_buffer(p, p->snapshot))
                                return (-1);
-                       }
                }
-               amt_read = fread((char *)tp, 1, hdr->caplen, fp);
-               if (amt_read != hdr->caplen) {
+
+               /*
+                * Read the first p->snapshot bytes into the buffer.
+                */
+               amt_read = fread(p->buffer, 1, p->snapshot, fp);
+               if (amt_read != (bpf_u_int32)p->snapshot) {
                        if (ferror(fp)) {
-                               snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
-                                   "error reading dump file: %s",
-                                   pcap_strerror(errno));
+                               pcap_fmt_errmsg_for_errno(p->errbuf,
+                                    PCAP_ERRBUF_SIZE, errno,
+                                   "error reading dump file");
                        } else {
-                               snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
-                                   "truncated dump file; tried to read %u captured bytes, only got %lu",
-                                   hdr->caplen, (unsigned long)amt_read);
+                               /*
+                                * 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 %" PRIsize,
+                                   p->snapshot, amt_read);
                        }
                        return (-1);
                }
+
+               /*
+                * Now read and discard what's left.
+                */
+               bytes_to_discard = hdr->caplen - p->snapshot;
+               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_fmt_errmsg_for_errno(p->errbuf,
+                                           PCAP_ERRBUF_SIZE, errno,
+                                           "error reading dump file");
+                               } else {
+                                       pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
+                                           "truncated dump file; tried to read %u captured bytes, only got %" PRIsize,
+                                           hdr->caplen, bytes_read);
+                               }
+                               return (-1);
+                       }
+                       bytes_to_discard -= amt_read;
+               }
+
                /*
-                * 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.
+                * 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);
+               hdr->caplen = p->snapshot;
        } else {
+               /*
+                * The packet is within the snapshot length for this file.
+                */
+               if (hdr->caplen > p->bufsize) {
+                       /*
+                        * Grow the buffer to the next power of 2, or
+                        * the snaplen, whichever is lower.
+                        */
+                       u_int new_bufsize;
+
+                       new_bufsize = hdr->caplen;
+                       /*
+                        * http://graphics.stanford.edu/~seander/bithacks.html#RoundUpPowerOf2
+                        */
+                       new_bufsize--;
+                       new_bufsize |= new_bufsize >> 1;
+                       new_bufsize |= new_bufsize >> 2;
+                       new_bufsize |= new_bufsize >> 4;
+                       new_bufsize |= new_bufsize >> 8;
+                       new_bufsize |= new_bufsize >> 16;
+                       new_bufsize++;
+
+                       if (new_bufsize > (u_int)p->snapshot)
+                               new_bufsize = p->snapshot;
+
+                       if (!grow_buffer(p, new_bufsize))
+                               return (-1);
+               }
+
                /* 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,
-                                   "error reading dump file: %s",
-                                   pcap_strerror(errno));
+                               pcap_fmt_errmsg_for_errno(p->errbuf,
+                                   PCAP_ERRBUF_SIZE, errno,
+                                   "error reading dump file");
                        } else {
-                               snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
-                                   "truncated dump file; tried to read %u captured bytes, only got %lu",
-                                   hdr->caplen, (unsigned long)amt_read);
+                               pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
+                                   "truncated dump file; tried to read %u captured bytes, only got %" PRIsize,
+                                   hdr->caplen, amt_read);
                        }
                        return (-1);
                }
@@ -608,7 +756,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.
@@ -619,11 +767,11 @@ pcap_setup_dump(pcap_t *p, int linktype, FILE *f, const char *fname)
        if (f == stdout)
                SET_BINMODE(f);
        else
-               setbuf(f, NULL);
+               setvbuf(f, NULL, _IONBF, 0);
 #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",
-                   fname, pcap_strerror(errno));
+               pcap_fmt_errmsg_for_errno(p->errbuf, PCAP_ERRBUF_SIZE,
+                   errno, "Can't write to %s", fname);
                if (f != stdout)
                        (void)fclose(f);
                return (NULL);
@@ -645,49 +793,89 @@ 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)
-               f = fopen(fname, "w");
-#else
+               /*
+                * "b" is supported as of C90, so *all* UN*Xes should
+                * support it, even though it does nothing.  It's
+                * required on Windows, as the file is a binary file
+                * and must be written in binary mode.
+                */
                f = fopen(fname, "wb");
-#endif
                if (f == NULL) {
-                       snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "%s: %s",
-                           fname, pcap_strerror(errno));
+                       pcap_fmt_errmsg_for_errno(p->errbuf, PCAP_ERRBUF_SIZE,
+                           errno, "%s", fname);
                        return (NULL);
                }
        }
        return (pcap_setup_dump(p, linktype, f, fname));
 }
 
+#ifdef _WIN32
+/*
+ * Initialize so that sf_write() will output to a stream wrapping the given raw
+ * OS file HANDLE.
+ */
+pcap_dumper_t *
+pcap_dump_hopen(pcap_t *p, intptr_t osfd)
+{
+       int fd;
+       FILE *file;
+
+       fd = _open_osfhandle(osfd, _O_APPEND);
+       if (fd < 0) {
+               pcap_fmt_errmsg_for_errno(p->errbuf, PCAP_ERRBUF_SIZE,
+                   errno, "_open_osfhandle");
+               return NULL;
+       }
+
+       file = _fdopen(fd, "wb");
+       if (file == NULL) {
+               pcap_fmt_errmsg_for_errno(p->errbuf, PCAP_ERRBUF_SIZE,
+                   errno, "_fdopen");
+               _close(fd);
+               return NULL;
+       }
+
+       return pcap_dump_fopen(p, file);
+}
+#endif /* _WIN32 */
+
 /*
  * Initialize so that sf_write() will output to the given stream.
  */
+#ifdef _WIN32
+static
+#endif /* _WIN32 */
 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 +885,202 @@ 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"));
+
+       /*
+        * "a" will cause the file *not* to be truncated if it exists
+        * but will cause it to be created if it doesn't.  It will
+        * also cause all writes to be done at the end of the file,
+        * but will allow reads to be done anywhere in the file.  This
+        * is what we need, because we need to read from the beginning
+        * of the file to see if it already has a header and packets
+        * or if it doesn't.
+        *
+        * "b" is supported as of C90, so *all* UN*Xes should support it,
+        * even though it does nothing.  It's required on Windows, as the
+        * file is a binary file and must be read in binary mode.
+        */
+       f = fopen(fname, "ab+");
+       if (f == NULL) {
+               pcap_fmt_errmsg_for_errno(p->errbuf, PCAP_ERRBUF_SIZE,
+                   errno, "%s", fname);
+               return (NULL);
+       }
+
+       /*
+        * Try to read a pcap header.
+        *
+        * We do not assume that the file will be positioned at the
+        * beginning immediately after we've opened it - we seek to
+        * the beginning.  ISO C says it's implementation-defined
+        * whether the file position indicator is at the beginning
+        * or the end of the file after an append-mode open, and
+        * it wasn't obvious from the Single UNIX Specification
+        * or the Microsoft documentation how that works on SUS-
+        * compliant systems or on Windows.
+        */
+       if (fseek(f, 0, SEEK_SET) == -1) {
+               pcap_fmt_errmsg_for_errno(p->errbuf, PCAP_ERRBUF_SIZE,
+                   errno, "Can't seek to the beginning of %s", fname);
+               (void)fclose(f);
+               return (NULL);
+       }
+       amt_read = fread(&ph, 1, sizeof (ph), f);
+       if (amt_read != sizeof (ph)) {
+               if (ferror(f)) {
+                       pcap_fmt_errmsg_for_errno(p->errbuf, PCAP_ERRBUF_SIZE,
+                           errno, "%s", fname);
+                       (void)fclose(f);
+                       return (NULL);
+               } else if (feof(f) && amt_read > 0) {
+                       pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
+                           "%s: truncated pcap file header", fname);
+                       (void)fclose(f);
+                       return (NULL);
+               }
+       }
+
+#if defined(_WIN32) || defined(MSDOS)
+       /*
+        * We turn off buffering.
+        * XXX - why?  And why not on the standard output?
+        */
+       setvbuf(f, NULL, _IONBF, 0);
+#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);
+                               (void)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);
+                               (void)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);
+                       (void)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);
+                       (void)fclose(f);
+                       return (NULL);
+
+               default:
+                       pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
+                           "%s: not a pcap file", fname);
+                       (void)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);
+                       (void)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);
+                       (void)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);
+                       (void)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_fmt_errmsg_for_errno(p->errbuf, PCAP_ERRBUF_SIZE,
+                           errno, "Can't write to %s", fname);
+                       (void)fclose(f);
+                       return (NULL);
+               }
+       }
+
+       /*
+        * Start writing at the end of the file.
+        *
+        * XXX - this shouldn't be necessary, given that we're opening
+        * the file in append mode, and ISO C specifies that all writes
+        * are done at the end of the file in that mode.
+        */
+       if (fseek(f, 0, SEEK_END) == -1) {
+               pcap_fmt_errmsg_for_errno(p->errbuf, PCAP_ERRBUF_SIZE,
+                   errno, "Can't seek to the end of %s", fname);
+               (void)fclose(f);
+               return (NULL);
+       }
+       return ((pcap_dumper_t *)f);
+}
+
 FILE *
 pcap_dump_file(pcap_dumper_t *p)
 {
@@ -709,6 +1093,45 @@ pcap_dump_ftell(pcap_dumper_t *p)
        return (ftell((FILE *)p));
 }
 
+#if defined(HAVE_FSEEKO)
+/*
+ * We have fseeko(), so we have ftello().
+ * If we have large file support (files larger than 2^31-1 bytes),
+ * ftello() will give us a current file position with more than 32
+ * bits.
+ */
+int64_t
+pcap_dump_ftell64(pcap_dumper_t *p)
+{
+       return (ftello((FILE *)p));
+}
+#elif defined(_MSC_VER)
+/*
+ * We have Visual Studio; we support only 2005 and later, so we have
+ * _ftelli64().
+ */
+int64_t
+pcap_dump_ftell64(pcap_dumper_t *p)
+{
+       return (_ftelli64((FILE *)p));
+}
+#else
+/*
+ * We don't have ftello() or _ftelli64(), so fall back on ftell().
+ * Either long is 64 bits, in which case ftell() should suffice,
+ * or this is probably an older 32-bit UN*X without large file
+ * support, which means you'll probably get errors trying to
+ * write files > 2^31-1, so it won't matter anyway.
+ *
+ * XXX - what about MinGW?
+ */
+int64_t
+pcap_dump_ftell64(pcap_dumper_t *p)
+{
+       return (ftell((FILE *)p));
+}
+#endif
+
 int
 pcap_dump_flush(pcap_dumper_t *p)
 {
index e9c7eaf..bc7150f 100644 (file)
--- a/sf-pcap.h
+++ b/sf-pcap.h
@@ -31,7 +31,7 @@
 #ifndef sf_pcap_h
 #define        sf_pcap_h
 
-extern pcap_t *pcap_check_header(bpf_u_int32 magic, FILE *fp,
+extern pcap_t *pcap_check_header(const uint8_t *magic, FILE *fp,
     u_int precision, char *errbuf, int *err);
 
 #endif
similarity index 58%
rename from sf-pcap-ng.c
rename to sf-pcapng.c
index 3a1d445..afaeb05 100644 (file)
  * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
  * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
  *
- * sf-pcap-ng.c - pcap-ng-file-format-specific code from savefile.c
+ * sf-pcapng.c - pcapng-file-format-specific code from savefile.c
  */
 
-#ifndef lint
-static const char rcsid[] _U_ =
-    "@(#) $Header$ (LBL)";
-#endif
-
 #ifdef HAVE_CONFIG_H
-#include "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>
-#endif
-#include <sys/types.h>
-#endif /* WIN32 */
+#include <pcap/pcap-inttypes.h>
 
 #include <errno.h>
 #include <memory.h>
@@ -58,7 +41,7 @@ static const char rcsid[] _U_ =
 #include "os-proto.h"
 #endif
 
-#include "sf-pcap-ng.h"
+#include "sf-pcapng.h"
 
 /*
  * Block types.
@@ -102,12 +85,12 @@ struct option_header {
  * Section Header Block.
  */
 #define BT_SHB                 0x0A0D0D0A
-
+#define BT_SHB_INSANE_MAX       1024U*1024U*1U  /* 1MB should be enough */
 struct section_header_block {
        bpf_u_int32     byte_order_magic;
        u_short         major_version;
        u_short         minor_version;
-       u_int64_t       section_length;
+       uint64_t        section_length;
        /* followed by options and trailer */
 };
 
@@ -121,6 +104,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,26 +187,66 @@ 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;
 
 /*
  * Per-interface information.
  */
 struct pcap_ng_if {
-       u_int tsresol;                  /* time stamp resolution */
-       u_int64_t tsoffset;             /* time stamp offset */
+       uint64_t tsresol;               /* time stamp resolution */
        tstamp_scale_type_t scale_type; /* how to scale */
+       uint64_t scale_factor;          /* time stamp scale factor for power-of-10 tsresol */
+       uint64_t tsoffset;              /* time stamp offset */
 };
 
+/*
+ * Per-pcap_t private data.
+ *
+ * max_blocksize is the maximum size of a block that we'll accept.  We
+ * reject blocks bigger than this, so we don't consume too much memory
+ * with a truly huge block.  It can change as we see IDBs with different
+ * link-layer header types.  (Currently, we don't support IDBs with
+ * different link-layer header types, but we will support it in the
+ * future, when we offer file-reading APIs that support it.)
+ *
+ * XXX - that's an issue on ILP32 platforms, where the maximum block
+ * size of 2^31-1 would eat all but one byte of the entire address space.
+ * It's less of an issue on ILP64/LLP64 platforms, but the actual size
+ * of the address space may be limited by 1) the number of *significant*
+ * address bits (currently, x86-64 only supports 48 bits of address), 2)
+ * any limitations imposed by the operating system; 3) any limitations
+ * imposed by the amount of available backing store for anonymous pages,
+ * so we impose a limit regardless of the size of a pointer.
+ */
 struct pcap_ng_sf {
-       u_int user_tsresol;             /* time stamp resolution requested by the user */
+       uint64_t user_tsresol;          /* time stamp resolution requested by the user */
+       u_int max_blocksize;            /* don't grow buffer size past this */
        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 */
 };
 
+/*
+ * The maximum block size we start with; we use an arbitrary value of
+ * 16 MiB.
+ */
+#define INITIAL_MAX_BLOCKSIZE  (16*1024*1024)
+
+/*
+ * Maximum block size for a given maximum snapshot length; we define it
+ * as the size of an EPB with a max_snaplen-sized packet and 128KB of
+ * options.
+ */
+#define MAX_BLOCKSIZE_FOR_SNAPLEN(max_snaplen) \
+       (sizeof (struct block_header) + \
+        sizeof (struct enhanced_packet_block) + \
+        (max_snaplen) + 131072 + \
+        sizeof (struct block_trailer))
+
 static void pcap_ng_cleanup(pcap_t *p);
 static int pcap_ng_next_packet(pcap_t *p, struct pcap_pkthdr *hdr,
     u_char **data);
@@ -236,16 +260,14 @@ 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,
-                           "error reading dump file: %s",
-                           pcap_strerror(errno));
+                       pcap_fmt_errmsg_for_errno(errbuf, PCAP_ERRBUF_SIZE,
+                           errno, "error reading dump file");
                } else {
                        if (amt_read == 0 && !fail_on_eof)
                                return (0);     /* EOF */
-                       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);
+                       pcap_snprintf(errbuf, PCAP_ERRBUF_SIZE,
+                           "truncated pcapng dump file; tried to read %" PRIsize " bytes, only got %" PRIsize,
+                           bytes_to_read, amt_read);
                }
                return (-1);
        }
@@ -255,8 +277,14 @@ read_bytes(FILE *fp, void *buf, size_t bytes_to_read, int fail_on_eof,
 static int
 read_block(FILE *fp, pcap_t *p, struct block_cursor *cursor, char *errbuf)
 {
+       struct pcap_ng_sf *ps;
        int status;
        struct block_header bhdr;
+       struct block_trailer *btrlr;
+       u_char *bdata;
+       size_t data_remaining;
+
+       ps = p->priv;
 
        status = read_bytes(fp, &bhdr, sizeof(bhdr), 0, errbuf);
        if (status <= 0)
@@ -268,29 +296,28 @@ read_block(FILE *fp, pcap_t *p, struct block_cursor *cursor, char *errbuf)
        }
 
        /*
-        * Is this block "too big"?
-        *
-        * We choose 16MB as "too big", for now, so that we handle
-        * "reasonably" large buffers but don't chew up all the
-        * memory if we read a malformed file.
-        */
-       if (bhdr.total_length > 16*1024*1024) {
-               snprintf(errbuf, PCAP_ERRBUF_SIZE,
-                   "pcap-ng block size %u > maximum %u",
-                   bhdr.total_length, 16*1024*1024);
-                   return (-1);
-       }
-
-       /*
         * Is this block "too small" - i.e., is it shorter than a block
         * header plus a block trailer?
         */
        if (bhdr.total_length < sizeof(struct block_header) +
            sizeof(struct block_trailer)) {
-               snprintf(errbuf, PCAP_ERRBUF_SIZE,
-                   "block in pcap-ng dump file has a length of %u < %lu",
+               pcap_snprintf(errbuf, PCAP_ERRBUF_SIZE,
+                   "block in pcapng dump file has a length of %u < %" PRIsize,
                    bhdr.total_length,
-                   (unsigned long)(sizeof(struct block_header) + sizeof(struct block_trailer)));
+                   sizeof(struct block_header) + sizeof(struct block_trailer));
+               return (-1);
+       }
+
+       /*
+        * Is the block total length a multiple of 4?
+        */
+       if ((bhdr.total_length % 4) != 0) {
+               /*
+                * No.  Report that as an error.
+                */
+               pcap_snprintf(errbuf, PCAP_ERRBUF_SIZE,
+                   "block in pcapng dump file has a length of %u that is not a multiple of 4" PRIsize,
+                   bhdr.total_length);
                return (-1);
        }
 
@@ -299,13 +326,22 @@ read_block(FILE *fp, pcap_t *p, struct block_cursor *cursor, char *errbuf)
         */
        if (p->bufsize < bhdr.total_length) {
                /*
-                * No - make it big enough.
+                * No - make it big enough, unless it's too big, in
+                * which case we fail.
                 */
-               p->buffer = realloc(p->buffer, bhdr.total_length);
-               if (p->buffer == NULL) {
-                       snprintf(errbuf, PCAP_ERRBUF_SIZE, "out of memory");
+               void *bigger_buffer;
+
+               if (bhdr.total_length > ps->max_blocksize) {
+                       pcap_snprintf(errbuf, PCAP_ERRBUF_SIZE, "pcapng block size %u > maximum %u", bhdr.total_length,
+                           ps->max_blocksize);
+                       return (-1);
+               }
+               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 +349,36 @@ 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);
 
        /*
+        * Get the block size from the trailer.
+        */
+       btrlr = (struct block_trailer *)(bdata + data_remaining - sizeof (struct block_trailer));
+       if (p->swapped)
+               btrlr->total_length = SWAPLONG(btrlr->total_length);
+
+       /*
+        * Is the total length from the trailer the same as the total
+        * length from the header?
+        */
+       if (bhdr.total_length != btrlr->total_length) {
+               /*
+                * No.
+                */
+               pcap_snprintf(errbuf, PCAP_ERRBUF_SIZE,
+                   "block total length in header and trailer don't match");
+               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,8 +394,8 @@ 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,
-                   "block of type %u in pcap-ng dump file is too short",
+               pcap_snprintf(errbuf, PCAP_ERRBUF_SIZE,
+                   "block of type %u in pcapng dump file is too short",
                    cursor->block_type);
                return (NULL);
        }
@@ -400,13 +456,13 @@ 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)
+process_idb_options(pcap_t *p, struct block_cursor *cursor, uint64_t *tsresol,
+    uint64_t *tsoffset, int *is_binary, char *errbuf)
 {
        struct option_header *opthdr;
        void *optvalue;
        int saw_tsresol, saw_tsoffset;
-       u_char tsresol_opt;
+       uint8_t tsresol_opt;
        u_int i;
 
        saw_tsresol = 0;
@@ -439,7 +495,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,57 +504,70 @@ 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);
                        }
                        saw_tsresol = 1;
-                       tsresol_opt = *(u_int *)optvalue;
+                       memcpy(&tsresol_opt, optvalue, sizeof(tsresol_opt));
                        if (tsresol_opt & 0x80) {
                                /*
                                 * Resolution is negative power of 2.
                                 */
-                               *tsresol = 1 << (tsresol_opt & 0x7F);
+                               uint8_t tsresol_shift = (tsresol_opt & 0x7F);
+
+                               if (tsresol_shift > 63) {
+                                       /*
+                                        * Resolution is too high; 2^-{res}
+                                        * won't fit in a 64-bit value.
+                                        */
+                                       pcap_snprintf(errbuf, PCAP_ERRBUF_SIZE,
+                                           "Interface Description Block if_tsresol option resolution 2^-%u is too high",
+                                           tsresol_shift);
+                                       return (-1);
+                               }
+                               *is_binary = 1;
+                               *tsresol = ((uint64_t)1) << tsresol_shift;
                        } else {
                                /*
                                 * Resolution is negative power of 10.
                                 */
-                               *tsresol = 1;
-                               for (i = 0; i < tsresol_opt; i++)
-                                       *tsresol *= 10;
-                       }
-                       if (*tsresol == 0) {
-                               /*
-                                * Resolution is too high.
-                                */
-                               if (tsresol_opt & 0x80) {
-                                       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,
+                               if (tsresol_opt > 19) {
+                                       /*
+                                        * Resolution is too high; 2^-{res}
+                                        * won't fit in a 64-bit value (the
+                                        * largest power of 10 that fits
+                                        * in a 64-bit value is 10^19, as
+                                        * the largest 64-bit unsigned
+                                        * value is ~1.8*10^19).
+                                        */
+                                       pcap_snprintf(errbuf, PCAP_ERRBUF_SIZE,
                                            "Interface Description Block if_tsresol option resolution 10^-%u is too high",
                                            tsresol_opt);
+                                       return (-1);
                                }
-                               return (-1);
+                               *is_binary = 0;
+                               *tsresol = 1;
+                               for (i = 0; i < tsresol_opt; i++)
+                                       *tsresol *= 10;
                        }
                        break;
 
                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);
                        }
@@ -521,8 +590,9 @@ static int
 add_interface(pcap_t *p, struct block_cursor *cursor, char *errbuf)
 {
        struct pcap_ng_sf *ps;
-       u_int tsresol;
-       u_int64_t tsoffset;
+       uint64_t tsresol;
+       uint64_t tsoffset;
+       int is_binary;
 
        ps = p->priv;
 
@@ -538,43 +608,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 pcapng 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.
+                        */
+                       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.
                         */
-                       ps->ifaces_size *= 2;
-                       ps->ifaces = realloc(ps->ifaces, ps->ifaces_size * sizeof (struct pcap_ng_if));
+                       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,67 +718,53 @@ 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);
 }
 
 /*
- * Check whether this is a pcap-ng savefile and, if it is, extract the
+ * Check whether this is a pcapng savefile and, if it is, extract the
  * relevant information from the header.
  */
 pcap_t *
-pcap_ng_check_header(bpf_u_int32 magic, FILE *fp, u_int precision, char *errbuf,
-    int *err)
+pcap_ng_check_header(const uint8_t *magic, FILE *fp, u_int precision,
+    char *errbuf, int *err)
 {
+       bpf_u_int32 magic_int;
        size_t amt_read;
        bpf_u_int32 total_length;
        bpf_u_int32 byte_order_magic;
@@ -664,16 +784,17 @@ 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 pcapng savefile.
         */
-       if (magic != BT_SHB) {
+       memcpy(&magic_int, magic, sizeof(magic_int));
+       if (magic_int != BT_SHB) {
                /*
                 * XXX - check whether this looks like what the block
                 * type would be after being munged by mapping between
                 * UN*X and DOS/Windows text file format and, if it
                 * does, look for the byte-order magic number in
                 * the appropriate place and, if we find it, report
-                * this as possibly being a pcap-ng file transferred
+                * this as possibly being a pcapng file transferred
                 * between UN*X and Windows in text file format?
                 */
                return (NULL);  /* nope */
@@ -693,32 +814,30 @@ 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,
-                           "error reading dump file: %s",
-                           pcap_strerror(errno));
+                       pcap_fmt_errmsg_for_errno(errbuf, PCAP_ERRBUF_SIZE,
+                           errno, "error reading dump file");
                        *err = 1;
                        return (NULL);  /* fail */
                }
 
                /*
                 * Possibly a weird short text file, so just say
-                * "not pcap-ng".
+                * "not pcapng".
                 */
                return (NULL);
        }
        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,
-                           "error reading dump file: %s",
-                           pcap_strerror(errno));
+                       pcap_fmt_errmsg_for_errno(errbuf, PCAP_ERRBUF_SIZE,
+                           errno, "error reading dump file");
                        *err = 1;
                        return (NULL);  /* fail */
                }
 
                /*
                 * Possibly a weird short text file, so just say
-                * "not pcap-ng".
+                * "not pcapng".
                 */
                return (NULL);
        }
@@ -726,7 +845,7 @@ pcap_ng_check_header(bpf_u_int32 magic, FILE *fp, u_int precision, char *errbuf,
                byte_order_magic = SWAPLONG(byte_order_magic);
                if (byte_order_magic != BYTE_ORDER_MAGIC) {
                        /*
-                        * Not a pcap-ng file.
+                        * Not a pcapng file.
                         */
                        return (NULL);
                }
@@ -737,17 +856,20 @@ 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,
-                   "Section Header Block in pcap-ng dump file has a length of %u < %lu",
+       if (total_length < sizeof(*bhdrp) + sizeof(*shbp) + sizeof(struct block_trailer) ||
+            (total_length > BT_SHB_INSANE_MAX)) {
+               pcap_snprintf(errbuf, PCAP_ERRBUF_SIZE,
+                   "Section Header Block in pcapng dump file has invalid length %" PRIsize " < _%u_ < %u (BT_SHB_INSANE_MAX)",
+                   sizeof(*bhdrp) + sizeof(*shbp) + sizeof(struct block_trailer),
                    total_length,
-                   (unsigned long)(sizeof(*bhdrp) + sizeof(*shbp) + sizeof(struct block_trailer)));
+                   BT_SHB_INSANE_MAX);
+
                *err = 1;
                return (NULL);
        }
 
        /*
-        * OK, this is a good pcap-ng file.
+        * OK, this is a good pcapng file.
         * Allocate a pcap_t for it.
         */
        p = pcap_open_offline_common(errbuf, sizeof (struct pcap_ng_sf));
@@ -773,7 +895,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;
@@ -792,31 +914,36 @@ pcap_ng_check_header(bpf_u_int32 magic, FILE *fp, u_int precision, char *errbuf,
         *      Packet Block containing a full-size Ethernet frame, and
         *      leaving room for some options.
         *
-        * If we find a bigger block, we reallocate the buffer.
+        * If we find a bigger block, we reallocate the buffer, up to
+        * the maximum size.  We start out with a maximum size of
+        * INITIAL_MAX_BLOCKSIZE; if we see any link-layer header types
+        * with a maximum snapshot that results in a larger maximum
+        * block length, we boost the maximum.
         */
        p->bufsize = 2048;
        if (p->bufsize < total_length)
                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);
        }
+       ps->max_blocksize = INITIAL_MAX_BLOCKSIZE;
 
        /*
         * Copy the stuff we've read to the buffer, and read the rest
         * of the SHB.
         */
        bhdrp = (struct block_header *)p->buffer;
-       shbp = (struct section_header_block *)(p->buffer + sizeof(struct block_header));
-       bhdrp->block_type = magic;
+       shbp = (struct section_header_block *)((u_char *)p->buffer + sizeof(struct block_header));
+       bhdrp->block_type = magic_int;
        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)),
-           total_length - (sizeof(magic) + sizeof(total_length) + sizeof(byte_order_magic)),
+           (u_char *)p->buffer + (sizeof(magic_int) + sizeof(total_length) + sizeof(byte_order_magic)),
+           total_length - (sizeof(magic_int) + sizeof(total_length) + sizeof(byte_order_magic)),
            1, errbuf) == -1)
                goto fail;
 
@@ -831,10 +958,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 pcapng savefile version %u.%u",
+                   shbp->major_version, shbp->minor_version);
                goto fail;
        }
        p->version_major = shbp->major_version;
@@ -855,7 +984,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;
                }
@@ -886,6 +1015,7 @@ pcap_ng_check_header(bpf_u_int32 magic, FILE *fp, u_int precision, char *errbuf,
                         */
                        if (!add_interface(p, &cursor, errbuf))
                                goto fail;
+
                        goto done;
 
                case BT_EPB:
@@ -896,7 +1026,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;
 
@@ -910,10 +1040,18 @@ pcap_ng_check_header(bpf_u_int32 magic, FILE *fp, u_int precision, char *errbuf,
 
 done:
        p->tzoff = 0;   /* XXX - not used in pcap */
-       p->snapshot = idbp->snaplen;
        p->linktype = linktype_to_dlt(idbp->linktype);
+       p->snapshot = pcap_adjust_snapshot(p->linktype, idbp->snaplen);
        p->linktype_ext = 0;
 
+       /*
+        * If the maximum block size for a packet with the maximum
+        * snapshot length for this DLT_ is bigger than the current
+        * maximum block size, increase the maximum.
+        */
+       if (MAX_BLOCKSIZE_FOR_SNAPLEN(max_snaplen_for_dlt(p->linktype)) > ps->max_blocksize)
+               ps->max_blocksize = MAX_BLOCKSIZE_FOR_SNAPLEN(max_snaplen_for_dlt(p->linktype));
+
        p->next_packet_op = pcap_ng_next_packet;
        p->cleanup_op = pcap_ng_cleanup;
 
@@ -954,7 +1092,7 @@ pcap_ng_next_packet(pcap_t *p, struct pcap_pkthdr *hdr, u_char **data)
        struct interface_description_block *idbp;
        struct section_header_block *shbp;
        FILE *fp = p->rfile;
-       u_int64_t t, sec, frac;
+       uint64_t t, sec, frac;
 
        /*
         * Look for an Enhanced Packet Block, a Simple Packet Block,
@@ -990,17 +1128,17 @@ pcap_ng_next_packet(pcap_t *p, struct pcap_pkthdr *hdr, u_char **data)
                                interface_id = SWAPLONG(epbp->interface_id);
                                hdr->caplen = SWAPLONG(epbp->caplen);
                                hdr->len = SWAPLONG(epbp->len);
-                               t = ((u_int64_t)SWAPLONG(epbp->timestamp_high)) << 32 |
+                               t = ((uint64_t)SWAPLONG(epbp->timestamp_high)) << 32 |
                                    SWAPLONG(epbp->timestamp_low);
                        } else {
                                interface_id = epbp->interface_id;
                                hdr->caplen = epbp->caplen;
                                hdr->len = epbp->len;
-                               t = ((u_int64_t)epbp->timestamp_high) << 32 |
+                               t = ((uint64_t)epbp->timestamp_high) << 32 |
                                    epbp->timestamp_low;
                        }
                        goto found;
-                       
+
                case BT_SPB:
                        /*
                         * Get a pointer to the fixed-length portion of the
@@ -1032,7 +1170,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;
@@ -1055,13 +1193,13 @@ pcap_ng_next_packet(pcap_t *p, struct pcap_pkthdr *hdr, u_char **data)
                                interface_id = SWAPSHORT(pbp->interface_id);
                                hdr->caplen = SWAPLONG(pbp->caplen);
                                hdr->len = SWAPLONG(pbp->len);
-                               t = ((u_int64_t)SWAPLONG(pbp->timestamp_high)) << 32 |
+                               t = ((uint64_t)SWAPLONG(pbp->timestamp_high)) << 32 |
                                    SWAPLONG(pbp->timestamp_low);
                        } else {
                                interface_id = pbp->interface_id;
                                hdr->caplen = pbp->caplen;
                                hdr->len = pbp->len;
-                               t = ((u_int64_t)pbp->timestamp_high) << 32 |
+                               t = ((uint64_t)pbp->timestamp_high) << 32 |
                                    pbp->timestamp_low;
                        }
                        goto found;
@@ -1093,13 +1231,19 @@ 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,
+
+                       /*
+                        * Check against the *adjusted* value of this IDB's
+                        * snapshot length.
+                        */
+                       if ((bpf_u_int32)p->snapshot !=
+                           pcap_adjust_snapshot(p->linktype, 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 +1295,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 +1303,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,8 +1313,8 @@ 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,
-                                   "unknown pcap-ng savefile major version number %u",
+                               pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
+                                   "unknown pcapng savefile major version number %u",
                                    shbp->major_version);
                                return (-1);
                        }
@@ -1192,7 +1336,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 +1347,30 @@ 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);
        }
 
+       if (hdr->caplen > (bpf_u_int32)p->snapshot) {
+               pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
+                   "invalid packet capture length %u, bigger than "
+                   "snaplen of %d", hdr->caplen, p->snapshot);
+               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 +1380,111 @@ found:
                 */
                break;
 
-       case SCALE_UP:
-       case SCALE_DOWN:
+       case SCALE_UP_DEC:
+               /*
+                * 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.
+                *
+                * 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 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.
+                * 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.
                 *
-                * Is there something clever we could do if
-                * ps->ifaces[interface_id].tsresol is a power of 2?
+                * 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;
+
+       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->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.
similarity index 86%
rename from sf-pcap-ng.h
rename to sf-pcapng.h
index 3c93498..835082a 100644 (file)
  * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
  * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
  *
- * sf-pcap-ng.h - pcap-ng-file-format-specific routines
+ * sf-pcapng.h - pcapng-file-format-specific routines
  *
- * Used to read pcap-ng savefiles.
+ * Used to read pcapng savefiles.
  */
 
-#ifndef sf_pcap_ng_h
-#define        sf_pcap_ng_h
+#ifndef sf_pcapng_h
+#define        sf_pcapng_h
 
-extern pcap_t *pcap_ng_check_header(bpf_u_int32 magic, FILE *fp,
+extern pcap_t *pcap_ng_check_header(const uint8_t *magic, FILE *fp,
     u_int precision, char *errbuf, int *err);
 
 #endif
diff --git a/sockutils.c b/sockutils.c
new file mode 100644 (file)
index 0000000..d3e9464
--- /dev/null
@@ -0,0 +1,1637 @@
+/*
+ * 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 "ftmacros.h"
+
+#include <string.h>
+#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 "pcap-int.h"
+
+#include "sockutils.h"
+#include "portability.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)"
+
+/*
+ * On UN*X, send() and recv() return ssize_t.
+ *
+ * On Windows, send() and recv() return an int.
+ *
+ *   Wth MSVC, there *is* no ssize_t.
+ *
+ *   With MinGW, there is an ssize_t type; it is either an int (32 bit)
+ *   or a long long (64 bit).
+ *
+ * So, on Windows, if we don't have ssize_t defined, define it as an
+ * int, so we can use it, on all platforms, as the type of variables
+ * that hold the return values from send() and recv().
+ */
+#if defined(_WIN32) && !defined(_SSIZE_T_DEFINED)
+typedef int ssize_t;
+#endif
+
+/****************************************************
+ *                                                  *
+ * Locally defined functions                        *
+ *                                                  *
+ ****************************************************/
+
+static int sock_ismcastaddr(const struct sockaddr *saddr);
+
+/****************************************************
+ *                                                  *
+ * Function bodies                                  *
+ *                                                  *
+ ****************************************************/
+
+/*
+ * Format an error message given an errno value (UN*X) or a WinSock error
+ * (Windows).
+ */
+void sock_fmterror(const char *caller, int errcode, char *errbuf, int errbuflen)
+{
+       if (errbuf == NULL)
+               return;
+
+#ifdef _WIN32
+       pcap_fmt_errmsg_for_win32_err(errbuf, errbuflen, errcode,
+           "%s", caller);
+#else
+       pcap_fmt_errmsg_for_errno(errbuf, errbuflen, errcode,
+           "%s", caller);
+#endif
+}
+
+/*
+ * \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'.
+ *
+ * \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
+       sock_fmterror(caller, GetLastError(), errbuf, errbuflen);
+#else
+       sock_fmterror(caller, errno, errbuf, errbuflen);
+#endif
+}
+
+/*
+ * \brief This function initializes the socket mechanism if it hasn't
+ * already been initialized or reinitializes it after it has been
+ * cleaned up.
+ *
+ * On UN*Xes, it doesn't need to do anything; on Windows, it needs to
+ * initialize Winsock.
+ *
+ * \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 no error message is supplied.
+ *
+ * \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 buffer pointed to by 'errbuf' variable.
+ */
+#ifdef _WIN32
+int sock_init(char *errbuf, int errbuflen)
+{
+       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++;
+       return 0;
+}
+#else
+int sock_init(char *errbuf _U_, int errbuflen _U_)
+{
+       /*
+        * Nothing to do on UN*Xes.
+        */
+       return 0;
+}
+#endif
+
+/*
+ * \brief This function cleans up the socket mechanism if we have no
+ * sockets left open.
+ *
+ * On UN*Xes, it doesn't need to do anything; on Windows, it needs
+ * to clean up Winsock.
+ *
+ * \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, INVALID_SOCKET 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;
+#if defined(SO_NOSIGPIPE) || defined(IPV6_V6ONLY) || defined(IPV6_BINDV6ONLY)
+       int on = 1;
+#endif
+
+       sock = socket(addrinfo->ai_family, addrinfo->ai_socktype, addrinfo->ai_protocol);
+       if (sock == INVALID_SOCKET)
+       {
+               sock_geterror("socket()", errbuf, errbuflen);
+               return INVALID_SOCKET;
+       }
+
+       /*
+        * Disable SIGPIPE, if we have SO_NOSIGPIPE.  We don't want to
+        * have to deal with signals if the peer closes the connection,
+        * especially in client programs, which may not even be aware that
+        * they're sending to sockets.
+        */
+#ifdef SO_NOSIGPIPE
+       if (setsockopt(sock, SOL_SOCKET, SO_NOSIGPIPE, (char *)&on,
+           sizeof (int)) == -1)
+       {
+               sock_geterror("setsockopt(SO_NOSIGPIPE)", errbuf, errbuflen);
+               closesocket(sock);
+               return INVALID_SOCKET;
+       }
+#endif
+
+       /* This is a server socket */
+       if (server)
+       {
+               /*
+                * Allow a new server to bind the socket after the old one
+                * exited, even if lingering sockets are still present.
+                *
+                * Don't treat an error as a failure.
+                */
+               int optval = 1;
+               (void)setsockopt(sock, SOL_SOCKET, SO_REUSEADDR,
+                   (char *)&optval, sizeof (optval));
+
+#if defined(IPV6_V6ONLY) || defined(IPV6_BINDV6ONLY)
+               /*
+                * Force the use of IPv6-only addresses.
+                *
+                * RFC 3493 indicates that you can support IPv4 on an
+                * IPv6 socket:
+                *
+                *    https://tools.ietf.org/html/rfc3493#section-3.7
+                *
+                * and that this is the default behavior.  This means
+                * that if we first create an IPv6 socket bound to the
+                * "any" address, it is, in effect, also bound to the
+                * IPv4 "any" address, so when we create an IPv4 socket
+                * and try to bind it to the IPv4 "any" address, it gets
+                * EADDRINUSE.
+                *
+                * Not all network stacks support IPv4 on IPv6 sockets;
+                * pre-NT 6 Windows stacks don't support it, and the
+                * OpenBSD stack doesn't support it for security reasons
+                * (see the OpenBSD inet6(4) man page).  Therefore, we
+                * don't want to rely on this behavior.
+                *
+                * So we try to disable it, using either the IPV6_V6ONLY
+                * option from RFC 3493:
+                *
+                *    https://tools.ietf.org/html/rfc3493#section-5.3
+                *
+                * or the IPV6_BINDV6ONLY option from older UN*Xes.
+                */
+#ifndef IPV6_V6ONLY
+  /* For older systems */
+  #define IPV6_V6ONLY IPV6_BINDV6ONLY
+#endif /* IPV6_V6ONLY */
+               if (addrinfo->ai_family == PF_INET6)
+               {
+                       if (setsockopt(sock, IPPROTO_IPV6, IPV6_V6ONLY,
+                           (char *)&on, sizeof (int)) == -1)
+                       {
+                               if (errbuf)
+                                       pcap_snprintf(errbuf, errbuflen, "setsockopt(IPV6_V6ONLY)");
+                               closesocket(sock);
+                               return INVALID_SOCKET;
+                       }
+               }
+#endif /* defined(IPV6_V6ONLY) || defined(IPV6_BINDV6ONLY) */
+
+               /* 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);
+                       closesocket(sock);
+                       return INVALID_SOCKET;
+               }
+
+               if (addrinfo->ai_socktype == SOCK_STREAM)
+                       if (listen(sock, nconn) == -1)
+                       {
+                               sock_geterror("listen()", errbuf, errbuflen);
+                               closesocket(sock);
+                               return INVALID_SOCKET;
+                       }
+
+               /* 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("Connect to socket failed",
+                                   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?  %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 INVALID_SOCKET;
+               }
+               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;
+}
+
+/*
+ * gai_errstring() has some problems:
+ *
+ * 1) on Windows, Microsoft explicitly says it's not thread-safe;
+ * 2) on UN*X, the Single UNIX Specification doesn't say it *is*
+ *    thread-safe, so an implementation might use a static buffer
+ *    for unknown error codes;
+ * 3) the error message for the most likely error, EAI_NONAME, is
+ *    truly horrible on several platforms ("nodename nor servname
+ *    provided, or not known"?  It's typically going to be "not
+ *    known", not "oopsie, I passed null pointers for the host name
+ *    and service name", not to mention they forgot the "neither");
+ *
+ * so we roll our own.
+ */
+static void
+get_gai_errstring(char *errbuf, int errbuflen, const char *prefix, int err,
+    const char *hostname, const char *portname)
+{
+       char hostport[PCAP_ERRBUF_SIZE];
+
+       if (hostname != NULL && portname != NULL)
+               pcap_snprintf(hostport, PCAP_ERRBUF_SIZE, "%s:%s",
+                   hostname, portname);
+       else if (hostname != NULL)
+               pcap_snprintf(hostport, PCAP_ERRBUF_SIZE, "%s",
+                   hostname);
+       else if (portname != NULL)
+               pcap_snprintf(hostport, PCAP_ERRBUF_SIZE, ":%s",
+                   portname);
+       else
+               pcap_snprintf(hostport, PCAP_ERRBUF_SIZE, "<no host or port!>");
+       switch (err)
+       {
+#ifdef EAI_ADDRFAMILY
+               case EAI_ADDRFAMILY:
+                       pcap_snprintf(errbuf, errbuflen,
+                           "%sAddress family for %s not supported",
+                           prefix, hostport);
+                       break;
+#endif
+
+               case EAI_AGAIN:
+                       pcap_snprintf(errbuf, errbuflen,
+                           "%s%s could not be resolved at this time",
+                           prefix, hostport);
+                       break;
+
+               case EAI_BADFLAGS:
+                       pcap_snprintf(errbuf, errbuflen,
+                           "%sThe ai_flags parameter for looking up %s had an invalid value",
+                           prefix, hostport);
+                       break;
+
+               case EAI_FAIL:
+                       pcap_snprintf(errbuf, errbuflen,
+                           "%sA non-recoverable error occurred when attempting to resolve %s",
+                           prefix, hostport);
+                       break;
+
+               case EAI_FAMILY:
+                       pcap_snprintf(errbuf, errbuflen,
+                           "%sThe address family for looking up %s was not recognized",
+                           prefix, hostport);
+                       break;
+
+               case EAI_MEMORY:
+                       pcap_snprintf(errbuf, errbuflen,
+                           "%sOut of memory trying to allocate storage when looking up %s",
+                           prefix, hostport);
+                       break;
+
+               /*
+                * RFC 2553 had both EAI_NODATA and EAI_NONAME.
+                *
+                * RFC 3493 has only EAI_NONAME.
+                *
+                * Some implementations define EAI_NODATA and EAI_NONAME
+                * to the same value, others don't.  If EAI_NODATA is
+                * defined and isn't the same as EAI_NONAME, we handle
+                * EAI_NODATA.
+                */
+#if defined(EAI_NODATA) && EAI_NODATA != EAI_NONAME
+               case EAI_NODATA:
+                       pcap_snprintf(errbuf, errbuflen,
+                           "%sNo address associated with %s",
+                           prefix, hostport);
+                       break;
+#endif
+
+               case EAI_NONAME:
+                       pcap_snprintf(errbuf, errbuflen,
+                           "%sThe host name %s couldn't be resolved",
+                           prefix, hostport);
+                       break;
+
+               case EAI_SERVICE:
+                       pcap_snprintf(errbuf, errbuflen,
+                           "%sThe service value specified when looking up %s as not recognized for the socket type",
+                           prefix, hostport);
+                       break;
+
+               case EAI_SOCKTYPE:
+                       pcap_snprintf(errbuf, errbuflen,
+                           "%sThe socket type specified when looking up %s as not recognized",
+                           prefix, hostport);
+                       break;
+
+#ifdef EAI_SYSTEM
+               case EAI_SYSTEM:
+                       /*
+                        * Assumed to be UN*X.
+                        */
+                       pcap_snprintf(errbuf, errbuflen,
+                           "%sAn error occurred when looking up %s: %s",
+                           prefix, hostport, pcap_strerror(errno));
+                       break;
+#endif
+
+#ifdef EAI_BADHINTS
+               case EAI_BADHINTS:
+                       pcap_snprintf(errbuf, errbuflen,
+                           "%sInvalid value for hints when looking up %s",
+                           prefix, hostport);
+                       break;
+#endif
+
+#ifdef EAI_PROTOCOL
+               case EAI_PROTOCOL:
+                       pcap_snprintf(errbuf, errbuflen,
+                           "%sResolved protocol when looking up %s is unknown",
+                           prefix, hostport);
+                       break;
+#endif
+
+#ifdef EAI_OVERFLOW
+               case EAI_OVERFLOW:
+                       pcap_snprintf(errbuf, errbuflen,
+                           "%sArgument buffer overflow when looking up %s",
+                           prefix, hostport);
+                       break;
+#endif
+
+               default:
+                       pcap_snprintf(errbuf, errbuflen,
+                           "%sgetaddrinfo() error %d when looking up %s",
+                           prefix, err, hostport);
+                       break;
+       }
+}
+
+/*
+ * \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 (errbuf)
+               {
+                       get_gai_errstring(errbuf, errbuflen, "", retval,
+                           host, port);
+               }
+               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");
+               freeaddrinfo(*addrinfo);
+               *addrinfo = NULL;
+               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");
+               freeaddrinfo(*addrinfo);
+               *addrinfo = NULL;
+               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 an error other than
+ * "connection reset" or "peer has closed the receive side" occurred,
+ * '-2' if we got one of those errors.
+ * For errors, an error message is returned in the 'errbuf' variable.
+ */
+int sock_send(SOCKET sock, const char *buffer, size_t size,
+    char *errbuf, int errbuflen)
+{
+       int remaining;
+       ssize_t nsent;
+
+       if (size > INT_MAX)
+       {
+               if (errbuf)
+               {
+                       pcap_snprintf(errbuf, errbuflen,
+                           "Can't send more than %u bytes with sock_send",
+                           INT_MAX);
+               }
+               return -1;
+       }
+       remaining = (int)size;
+
+       do {
+#ifdef MSG_NOSIGNAL
+               /*
+                * Send with MSG_NOSIGNAL, so that we don't get SIGPIPE
+                * on errors on stream-oriented sockets when the other
+                * end breaks the connection.
+                * The EPIPE error is still returned.
+                */
+               nsent = send(sock, buffer, remaining, MSG_NOSIGNAL);
+#else
+               nsent = send(sock, buffer, remaining, 0);
+#endif
+
+               if (nsent == -1)
+               {
+                       /*
+                        * If the client closed the connection out from
+                        * under us, there's no need to log that as an
+                        * error.
+                        */
+                       int errcode;
+
+#ifdef _WIN32
+                       errcode = GetLastError();
+                       if (errcode == WSAECONNRESET ||
+                           errcode == WSAECONNABORTED)
+                       {
+                               /*
+                                * WSAECONNABORTED appears to be the error
+                                * returned in Winsock when you try to send
+                                * on a connection where the peer has closed
+                                * the receive side.
+                                */
+                               return -2;
+                       }
+                       sock_fmterror("send()", errcode, errbuf, errbuflen);
+#else
+                       errcode = errno;
+                       if (errcode == ECONNRESET || errcode == EPIPE)
+                       {
+                               /*
+                                * EPIPE is what's returned on UN*X when
+                                * you try to send on a connection when
+                                * the peer has closed the receive side.
+                                */
+                               return -2;
+                       }
+                       sock_fmterror("send()", errcode, errbuf, errbuflen);
+#endif
+                       return -1;
+               }
+
+               remaining -= nsent;
+               buffer += nsent;
+       } while (remaining != 0);
+
+       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 flags:
+ *
+ *   SOCK_RECEIVALL_XXX:
+ *
+ *     if SOCK_RECEIVEALL_NO, return as soon as some data is ready
+ *     if SOCK_RECEIVALL_YES, wait until 'size' data has been
+ *         received (in case the socket does not have enough data available).
+ *
+ *   SOCK_EOF_XXX:
+ *
+ *     if SOCK_EOF_ISNT_ERROR, if the first read returns 0, just return 0,
+ *         and return an error on any subsequent read that returns 0;
+ *     if SOCK_EOF_IS_ERROR, if any read returns 0, return an error.
+ *
+ * \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.
+ */
+
+int sock_recv(SOCKET sock, void *buffer, size_t size, int flags,
+    char *errbuf, int errbuflen)
+{
+       char *bufp = buffer;
+       int remaining;
+       ssize_t nread;
+
+       if (size == 0)
+       {
+               return 0;
+       }
+       if (size > INT_MAX)
+       {
+               if (errbuf)
+               {
+                       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 ((flags & SOCK_EOF_IS_ERROR) ||
+                           (remaining != (int) size))
+                       {
+                               /*
+                                * Either we've already read some data,
+                                * or we're always supposed to return
+                                * an error on EOF.
+                                */
+                               if (errbuf)
+                               {
+                                       pcap_snprintf(errbuf, errbuflen,
+                                           "The other host terminated the connection.");
+                               }
+                               return -1;
+                       }
+                       else
+                               return 0;
+               }
+
+               /*
+                * Do we want to read the amount requested, or just return
+                * what we got?
+                */
+               if (!(flags & SOCK_RECEIVEALL_YES))
+               {
+                       /*
+                        * Just return what we got.
+                        */
+                       return (int) nread;
+               }
+
+               bufp += nread;
+               remaining -= nread;
+
+               if (remaining == 0)
+                       return (int) size;
+       }
+}
+
+/*
+ * Receives a datagram from a socket.
+ *
+ * Returns the size of the datagram on success or -1 on error.
+ */
+int sock_recv_dgram(SOCKET sock, void *buffer, size_t size,
+    char *errbuf, int errbuflen)
+{
+       ssize_t nread;
+#ifndef _WIN32
+       struct msghdr message;
+       struct iovec iov;
+#endif
+
+       if (size == 0)
+       {
+               return 0;
+       }
+       if (size > INT_MAX)
+       {
+               if (errbuf)
+               {
+                       pcap_snprintf(errbuf, errbuflen,
+                           "Can't read more than %u bytes with sock_recv_dgram",
+                           INT_MAX);
+               }
+               return -1;
+       }
+
+       /*
+        * This should be a datagram socket, so we should get the
+        * entire datagram in one recv() or recvmsg() call, and
+        * don't need to loop.
+        */
+#ifdef _WIN32
+       nread = recv(sock, buffer, size, 0);
+       if (nread == SOCKET_ERROR)
+       {
+               /*
+                * To quote the MSDN documentation for recv(),
+                * "If the datagram or message is larger than
+                * the buffer specified, the buffer is filled
+                * with the first part of the datagram, and recv
+                * generates the error WSAEMSGSIZE. For unreliable
+                * protocols (for example, UDP) the excess data is
+                * lost..."
+                *
+                * So if the message is bigger than the buffer
+                * supplied to us, the excess data is discarded,
+                * and we'll report an error.
+                */
+               sock_geterror("recv()", errbuf, errbuflen);
+               return -1;
+       }
+#else /* _WIN32 */
+       /*
+        * The Single UNIX Specification says that a recv() on
+        * a socket for a message-oriented protocol will discard
+        * the excess data.  It does *not* indicate that the
+        * receive will fail with, for example, EMSGSIZE.
+        *
+        * Therefore, we use recvmsg(), which appears to be
+        * the only way to get a "message truncated" indication
+        * when receiving a message for a message-oriented
+        * protocol.
+        */
+       message.msg_name = NULL;        /* we don't care who it's from */
+       message.msg_namelen = 0;
+       iov.iov_base = buffer;
+       iov.iov_len = size;
+       message.msg_iov = &iov;
+       message.msg_iovlen = 1;
+#ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
+       message.msg_control = NULL;     /* we don't care about control information */
+       message.msg_controllen = 0;
+#endif
+#ifdef HAVE_STRUCT_MSGHDR_MSG_FLAGS
+       message.msg_flags = 0;
+#endif
+       nread = recvmsg(sock, &message, 0);
+       if (nread == -1)
+       {
+               if (errno == EINTR)
+                       return -3;
+               sock_geterror("recv()", errbuf, errbuflen);
+               return -1;
+       }
+#ifdef HAVE_STRUCT_MSGHDR_MSG_FLAGS
+       /*
+        * XXX - Solaris supports this, but only if you ask for the
+        * X/Open version of recvmsg(); should we use that, or will
+        * that cause other problems?
+        */
+       if (message.msg_flags & MSG_TRUNC)
+       {
+               /*
+                * Message was bigger than the specified buffer size.
+                *
+                * Report this as an error, as the Microsoft documentation
+                * implies we'd do in a similar case on Windows.
+                */
+               pcap_snprintf(errbuf, errbuflen, "recv(): Message too long");
+               return -1;
+       }
+#endif /* HAVE_STRUCT_MSGHDR_MSG_FLAGS */
+#endif /* _WIN32 */
+
+       /*
+        * The size we're reading fits in an int, so the return value
+        * will fit in an int.
+        */
+       return (int)nread;
+}
+
+/*
+ * \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;
+       }
+
+       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;
+               int getaddrinfo_failed = 0;
+
+               /*
+                * 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, NULL, &hints, &addrinfo);
+                       if (retval != 0)
+                       {
+                               if (errbuf)
+                                       get_gai_errstring(errbuf, errbuflen,
+                                           "Allowed host list error: ",
+                                           retval, token, NULL);
+
+                               /*
+                                * Note that at least one call to getaddrinfo()
+                                * failed.
+                                */
+                               getaddrinfo_failed = 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);
+                                       freeaddrinfo(addrinfo);
+                                       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;
+               }
+
+               free(temphostlist);
+
+               if (getaddrinfo_failed) {
+                       /*
+                        * At least one getaddrinfo() call failed;
+                        * treat that as an error, so rpcapd knows
+                        * that it should log it locally as well
+                        * as telling the client about it.
+                        */
+                       return -2;
+               } else {
+                       /*
+                        * All getaddrinfo() calls succeeded, but
+                        * the host wasn't in the list.
+                        */
+                       if (errbuf)
+                               pcap_snprintf(errbuf, errbuflen, "The host is not in the allowed host list. Connection refused.");
+                       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;
+       }
+
+       /* Returns the numeric address of the host that triggered the error */
+       return sock_getascii_addrport(&mysockaddr, address, addrlen, port, portlen, flags, errbuf, errbuflen);
+}
+
+/*
+ * \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)
+                               pcap_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)
+               {
+                       pcap_strlcpy(address, SOCKET_NO_NAME_AVAILABLE, addrlen);
+                       address[addrlen - 1] = 0;
+               }
+
+               if (port)
+               {
+                       pcap_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/sockutils.h b/sockutils.h
new file mode 100644 (file)
index 0000000..8a45b3d
--- /dev/null
@@ -0,0 +1,162 @@
+/*
+ * 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__
+
+#ifdef _MSC_VER
+#pragma once
+#endif
+
+#include "pcap/socket.h"
+
+#ifndef _WIN32
+  /* UN*X */
+  #include <unistd.h>  /* close() */
+
+  /*!
+   * \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
+
+/*
+ * 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
+ * \{
+ */
+
+/****************************************************
+ *                                                  *
+ * 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
+
+/*
+ * Flags for sock_recv().
+ */
+#define SOCK_RECEIVEALL_NO     0x00000000      /* Don't wait to receive all data */
+#define SOCK_RECEIVEALL_YES    0x00000001      /* Wait to receive all data */
+
+#define SOCK_EOF_ISNT_ERROR    0x00000000      /* Return 0 on EOF */
+#define SOCK_EOF_IS_ERROR      0x00000002      /* Return an error on EOF */
+
+/*
+ * \}
+ */
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/*
+ * \defgroup ExportedFunc Exported Functions
+ */
+
+/*
+ * \addtogroup ExportedFunc
+ * \{
+ */
+
+int sock_init(char *errbuf, int errbuflen);
+void sock_cleanup(void);
+void sock_fmterror(const char *caller, int errcode, char *errbuf, int errbuflen);
+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 sock, void *buffer, size_t size, int receiveall,
+    char *errbuf, int errbuflen);
+int sock_recv_dgram(SOCKET sock, void *buffer, size_t size,
+    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 sock, const char *buffer, size_t 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 sock, 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/testprogs/CMakeLists.txt b/testprogs/CMakeLists.txt
new file mode 100644 (file)
index 0000000..b8ef9b7
--- /dev/null
@@ -0,0 +1,40 @@
+if(MSVC)
+  file(GLOB PROJECT_SOURCE_LIST_WIN32_C ${pcap_SOURCE_DIR}/missing/getopt.c)
+  include_directories(${pcap_SOURCE_DIR}/missing)
+endif(MSVC)
+
+add_custom_target(testprogs)
+
+macro(add_test_executable _executable)
+  add_executable(${_executable} EXCLUDE_FROM_ALL
+    ${_executable}.c ${PROJECT_SOURCE_LIST_WIN32_C})
+  if(NOT C_ADDITIONAL_FLAGS STREQUAL "")
+    set_target_properties(${_executable} PROPERTIES
+      COMPILE_FLAGS ${C_ADDITIONAL_FLAGS})
+  endif()
+  if(WIN32)
+    target_link_libraries(${_executable}
+      ${ARGN} ${LIBRARY_NAME} ${PCAP_LINK_LIBRARIES})
+  else(WIN32)
+    target_link_libraries(${_executable}
+      ${ARGN} ${LIBRARY_NAME}_static ${PCAP_LINK_LIBRARIES})
+  endif(WIN32)
+  add_dependencies(testprogs ${_executable})
+endmacro()
+
+add_test_executable(can_set_rfmon_test)
+add_test_executable(capturetest)
+add_test_executable(filtertest)
+add_test_executable(findalldevstest)
+add_test_executable(opentest)
+add_test_executable(reactivatetest)
+
+if(NOT WIN32)
+  add_test_executable(selpolltest)
+endif()
+
+add_test_executable(threadsignaltest ${CMAKE_THREAD_LIBS_INIT})
+
+if(NOT WIN32)
+  add_test_executable(valgrindtest)
+endif()
diff --git a/testprogs/Makefile.in b/testprogs/Makefile.in
new file mode 100644 (file)
index 0000000..ec0a472
--- /dev/null
@@ -0,0 +1,144 @@
+#  Copyright (c) 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.
+
+#
+# Various configurable paths (remember to edit Makefile.in, not Makefile)
+#
+
+# Top level hierarchy
+prefix = @prefix@
+exec_prefix = @exec_prefix@
+datarootdir = @datarootdir@
+# Pathname of directory to install the configure program
+bindir = @bindir@
+# Pathname of directory to install the rpcapd daemon
+sbindir = @sbindir@
+# Pathname of directory to install the include files
+includedir = @includedir@
+# Pathname of directory to install the library
+libdir =  @libdir@
+# Pathname of directory to install the man pages
+mandir = @mandir@
+
+# VPATH
+srcdir = @srcdir@
+VPATH = @srcdir@
+
+#
+# You shouldn't need to edit anything below.
+#
+
+LD = /usr/bin/ld
+CC = @CC@
+AR = @AR@
+LN_S = @LN_S@
+MKDEP = @MKDEP@
+CCOPT = @V_CCOPT@
+INCLS = -I. -I.. -I@srcdir@ -I@srcdir@/.. @V_INCLS@
+DEFS = @DEFS@ @V_DEFS@
+ADDLOBJS = @ADDLOBJS@
+ADDLARCHIVEOBJS = @ADDLARCHIVEOBJS@
+LIBS = @LIBS@
+PTHREAD_LIBS = @PTHREAD_LIBS@
+CROSSFLAGS=
+CFLAGS = @CFLAGS@   ${CROSSFLAGS}
+LDFLAGS = @LDFLAGS@ ${CROSSFLAGS}
+DYEXT = @DYEXT@
+V_RPATH_OPT = @V_RPATH_OPT@
+DEPENDENCY_CFLAG = @DEPENDENCY_CFLAG@
+EXTRA_NETWORK_LIBS=@EXTRA_NETWORK_LIBS@
+
+# Standard CFLAGS for building test programs
+FULL_CFLAGS = $(CCOPT) $(INCLS) $(DEFS) $(CFLAGS)
+
+INSTALL = @INSTALL@
+INSTALL_PROGRAM = @INSTALL_PROGRAM@
+INSTALL_DATA = @INSTALL_DATA@
+
+# 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
+# problem if you don't own the file but can write to the directory.
+.c.o:
+       @rm -f $@
+       $(CC) $(FULL_CFLAGS) -c $(srcdir)/$*.c
+
+SRC = @VALGRINDTEST_SRC@ \
+       capturetest.c \
+       can_set_rfmon_test.c \
+       filtertest.c \
+       findalldevstest.c \
+       opentest.c \
+       reactivatetest.c \
+       selpolltest.c \
+       threadsignaltest.c
+
+TESTS = $(SRC:.c=)
+
+TAGFILES = \
+       $(SRC) $(HDR)
+
+CLEANFILES = $(OBJ) $(TESTS)
+
+all: $(TESTS)
+
+capturetest: $(srcdir)/capturetest.c ../libpcap.a
+       $(CC) $(FULL_CFLAGS) -I. -L. -o capturetest $(srcdir)/capturetest.c ../libpcap.a $(LIBS)
+
+can_set_rfmon_test: $(srcdir)/can_set_rfmon_test.c ../libpcap.a
+       $(CC) $(FULL_CFLAGS) -I. -L. -o can_set_rfmon_test $(srcdir)/can_set_rfmon_test.c ../libpcap.a $(LIBS)
+
+filtertest: $(srcdir)/filtertest.c ../libpcap.a
+       $(CC) $(FULL_CFLAGS) -I. -L. -o filtertest $(srcdir)/filtertest.c ../libpcap.a $(EXTRA_NETWORK_LIBS) $(LIBS)
+
+findalldevstest: $(srcdir)/findalldevstest.c ../libpcap.a
+       $(CC) $(FULL_CFLAGS) -I. -L. -o findalldevstest $(srcdir)/findalldevstest.c ../libpcap.a $(EXTRA_NETWORK_LIBS) $(LIBS)
+
+opentest: $(srcdir)/opentest.c ../libpcap.a
+       $(CC) $(FULL_CFLAGS) -I. -L. -o opentest $(srcdir)/opentest.c ../libpcap.a $(LIBS)
+
+reactivatetest: $(srcdir)/reactivatetest.c ../libpcap.a
+       $(CC) $(FULL_CFLAGS) -I. -L. -o reactivatetest $(srcdir)/reactivatetest.c ../libpcap.a $(LIBS)
+
+selpolltest: $(srcdir)/selpolltest.c ../libpcap.a
+       $(CC) $(FULL_CFLAGS) -I. -L. -o selpolltest $(srcdir)/selpolltest.c ../libpcap.a $(LIBS)
+
+threadsignaltest: $(srcdir)/threadsignaltest.c ../libpcap.a
+       $(CC) $(FULL_CFLAGS) -I. -L. -o threadsignaltest $(srcdir)/threadsignaltest.c ../libpcap.a $(LIBS) $(PTHREAD_LIBS)
+
+valgrindtest: $(srcdir)/valgrindtest.c ../libpcap.a
+       $(CC) $(FULL_CFLAGS) -I. -L. -o valgrindtest $(srcdir)/valgrindtest.c ../libpcap.a $(LIBS)
+
+clean:
+       rm -f $(CLEANFILES)
+       rm -rf *.dSYM
+
+distclean: clean
+       rm -f Makefile config.cache config.log config.status \
+           config.h stamp-h stamp-h.in
+       rm -rf autom4te.cache
+
+install:
+
+uninstall:
+
+tags: $(TAGFILES)
+       ctags -wtd $(TAGFILES)
+
+depend:
+       ../$(MKDEP) -c "$(CC)" -m "$(DEPENDENCY_CFLAG)" $(CFLAGS) $(DEFS) $(INCLS) $(SRC)
diff --git a/testprogs/can_set_rfmon_test.c b/testprogs/can_set_rfmon_test.c
new file mode 100644 (file)
index 0000000..f6188ba
--- /dev/null
@@ -0,0 +1,96 @@
+/*
+ * 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.
+ */
+
+#include "varattrs.h"
+
+#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>
+
+#include "pcap/funcattrs.h"
+
+static const char *program_name;
+
+/* Forwards */
+static void PCAP_NORETURN error(PCAP_FORMAT_STRING(const char *), ...) PCAP_PRINTFLIKE(1,2);
+
+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 */
+}
similarity index 89%
rename from tests/capturetest.c
rename to testprogs/capturetest.c
index e70e69a..d625cb4 100644 (file)
  * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
  */
 
+#include "varattrs.h"
+
 #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 +32,33 @@ The Regents of the University of California.  All rights reserved.\n";
 #include <string.h>
 #include <stdarg.h>
 #include <limits.h>
-#include <unistd.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>
 
+#include "pcap/funcattrs.h"
+
+#ifdef _WIN32
+  #include "portability.h"
+#endif
+
 static char *program_name;
 
 /* 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)
 {
@@ -63,6 +69,7 @@ main(int argc, char **argv)
        int timeout = 1000;
        int immediate = 0;
        int nonblock = 0;
+       pcap_if_t *devlist;
        bpf_u_int32 localnet, netmask;
        struct bpf_program fcode;
        char ebuf[PCAP_ERRBUF_SIZE];
@@ -117,9 +124,12 @@ main(int argc, char **argv)
        }
 
        if (device == NULL) {
-               device = pcap_lookupdev(ebuf);
-               if (device == NULL)
+               if (pcap_findalldevs(&devlist, ebuf) == -1)
                        error("%s", ebuf);
+               if (devlist == NULL)
+                       error("no interfaces available for capture");
+               device = strdup(devlist->name);
+               pcap_freealldevs(devlist);
        }
        *ebuf = '\0';
        pd = pcap_create(device, ebuf);
@@ -197,11 +207,13 @@ main(int argc, char **argv)
                    program_name, pcap_geterr(pd));
        }
        pcap_close(pd);
+       pcap_freecode(&fcode);
+       free(cmdbuf);
        exit(status == -1 ? 1 : 0);
 }
 
 static void
-countme(u_char *user, const struct pcap_pkthdr *h, const u_char *sp)
+countme(u_char *user, const struct pcap_pkthdr *h _U_, const u_char *sp _U_)
 {
        int *counterp = (int *)user;
 
similarity index 71%
rename from tests/filtertest.c
rename to testprogs/filtertest.c
index d603376..7e2d6d6 100644 (file)
@@ -19,6 +19,8 @@
  * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
  */
 
+#include "varattrs.h"
+
 #ifndef lint
 static const char copyright[] _U_ =
     "@(#) Copyright (c) 1988, 1989, 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1997, 2000\n\
@@ -26,7 +28,7 @@ The Regents of the University of California.  All rights reserved.\n";
 #endif
 
 #ifdef HAVE_CONFIG_H
-#include "config.h"
+#include <config.h>
 #endif
 
 #include <pcap.h>
@@ -34,29 +36,44 @@ The Regents of the University of California.  All rights reserved.\n";
 #include <stdlib.h>
 #include <string.h>
 #include <stdarg.h>
-#include <unistd.h>
+#ifdef _WIN32
+  #include "getopt.h"
+  #include "unix.h"
+#else
+  #include <unistd.h>
+#endif
 #include <fcntl.h>
 #include <errno.h>
-#include <arpa/inet.h>
+#ifdef _WIN32
+  #include <winsock2.h>
+  #include <ws2tcpip.h>
+#else
+  #include <sys/socket.h>
+  #include <arpa/inet.h>
+#endif
 #include <sys/types.h>
 #include <sys/stat.h>
 
-#ifndef HAVE___ATTRIBUTE__
-#define __attribute__(x)
+#include "pcap/funcattrs.h"
+
+#ifdef BDEBUG
+/*
+ * We have pcap_set_optimizer_debug() and pcap_set_print_dot_graph() in
+ * libpcap; declare them (they're not declared by any libpcap header,
+ * because they're special hacks, only available if libpcap was configured
+ * to include them, and only intended for use by libpcap developers trying
+ * to debug the optimizer for filter expressions).
+ */
+PCAP_API void pcap_set_optimizer_debug(int);
+PCAP_API void pcap_set_print_dot_graph(int);
 #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)));
-
-extern int optind;
-extern int opterr;
-extern char *optarg;
+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);
 
 /*
  * On Windows, we need to open the file in binary mode, so that
@@ -179,37 +196,51 @@ main(int argc, char **argv)
        char *cp;
        int op;
        int dflag;
+       int gflag;
        char *infile;
        int Oflag;
        long snaplen;
+       char *p;
        int dlt;
+       int have_fcode = 0;
        bpf_u_int32 netmask = PCAP_NETMASK_UNKNOWN;
        char *cmdbuf;
        pcap_t *pd;
        struct bpf_program fcode;
 
-#ifdef WIN32
-       if(wsockinit() != 0) return 1;
-#endif /* WIN32 */
+#ifdef _WIN32
+       if (pcap_wsockinit() != 0)
+               return 1;
+#endif /* _WIN32 */
 
        dflag = 1;
+       gflag = 0;
+
        infile = NULL;
        Oflag = 1;
        snaplen = 68;
-  
+
        if ((cp = strrchr(argv[0], '/')) != NULL)
                program_name = cp + 1;
        else
                program_name = argv[0];
 
        opterr = 0;
-       while ((op = getopt(argc, argv, "dF:m:Os:")) != -1) {
+       while ((op = getopt(argc, argv, "dF:gm:Os:")) != -1) {
                switch (op) {
 
                case 'd':
                        ++dflag;
                        break;
 
+               case 'g':
+#ifdef BDEBUG
+                       ++gflag;
+#else
+                       error("libpcap and filtertest not built with optimizer debugging enabled");
+#endif
+                       break;
+
                case 'F':
                        infile = optarg;
                        break;
@@ -219,12 +250,23 @@ main(int argc, char **argv)
                        break;
 
                case 'm': {
-                       in_addr_t addr;
+                       bpf_u_int32 addr;
+
+                       switch (inet_pton(AF_INET, optarg, &addr)) {
 
-                       addr = inet_addr(optarg);
-                       if (addr == INADDR_NONE)
+                       case 0:
                                error("invalid netmask %s", optarg);
-                       netmask = addr;
+                               break;
+
+                       case -1:
+                               error("invalid netmask %s: %s", optarg,
+                                   pcap_strerror(errno));
+                               break;
+
+                       case 1:
+                               netmask = addr;
+                               break;
+                       }
                        break;
                }
 
@@ -252,23 +294,51 @@ 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
                cmdbuf = copy_argv(&argv[optind+1]);
 
+#ifdef BDEBUG
+       pcap_set_optimizer_debug(dflag);
+       pcap_set_print_dot_graph(gflag);
+#endif
+
        pd = pcap_open_dead(dlt, snaplen);
        if (pd == NULL)
                error("Can't open fake pcap_t");
 
        if (pcap_compile(pd, &fcode, cmdbuf, Oflag, netmask) < 0)
                error("%s", pcap_geterr(pd));
+
+       have_fcode = 1;
        if (!bpf_validate(fcode.bf_insns, fcode.bf_len))
                warn("Filter doesn't pass validation");
+
+#ifdef BDEBUG
+       if (cmdbuf != NULL) {
+               // 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);
+       } else
+               printf("machine codes for empty filter:\n");
+#endif
+
        bpf_dump(&fcode, dflag);
+       free(cmdbuf);
+       if (have_fcode)
+               pcap_freecode (&fcode);
        pcap_close(pd);
        exit(0);
 }
@@ -279,7 +349,11 @@ usage(void)
        (void)fprintf(stderr, "%s, with %s\n", program_name,
            pcap_lib_version());
        (void)fprintf(stderr,
+#ifdef BDEBUG
+           "Usage: %s [-dgO] [ -F file ] [ -m netmask] [ -s snaplen ] dlt [ expression ]\n",
+#else
            "Usage: %s [-dO] [ -F file ] [ -m netmask] [ -s snaplen ] dlt [ expression ]\n",
+#endif
            program_name);
        exit(1);
 }
diff --git a/testprogs/findalldevstest.c b/testprogs/findalldevstest.c
new file mode 100644 (file)
index 0000000..e535e25
--- /dev/null
@@ -0,0 +1,311 @@
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <stdlib.h>
+#include <string.h>
+#include <sys/types.h>
+#ifdef _WIN32
+  #include <winsock2.h>
+  #include <ws2tcpip.h>
+  #include <windows.h>
+#else
+  #include <sys/socket.h>
+  #include <netinet/in.h>
+  #include <arpa/inet.h>
+  #include <netdb.h>
+  #include <unistd.h>
+#endif
+
+#include <pcap.h>
+
+#include "pcap/funcattrs.h"
+
+static int ifprint(pcap_if_t *d);
+static char *iptos(bpf_u_int32 in);
+
+#ifdef _WIN32
+#include "portability.h"
+
+/*
+ * 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()
+ */
+#define ERRBUF_SIZE    1024
+static const char *
+win32_strerror(DWORD error)
+{
+  static char errbuf[ERRBUF_SIZE+1];
+  size_t errlen;
+
+  FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM, NULL, error, 0, errbuf,
+                ERRBUF_SIZE, NULL);
+
+  /*
+   * "FormatMessage()" "helpfully" sticks CR/LF at the end of the
+   * message.  Get rid of it.
+   */
+  errlen = strlen(errbuf);
+  if (errlen >= 2) {
+    errbuf[errlen - 1] = '\0';
+    errbuf[errlen - 2] = '\0';
+    errlen -= 2;
+  }
+  return errbuf;
+}
+
+static char *
+getpass(const char *prompt)
+{
+  HANDLE console_handle = GetStdHandle(STD_INPUT_HANDLE);
+  DWORD console_mode, save_console_mode;
+  static char password[128+1];
+  char *p;
+
+  fprintf(stderr, "%s", prompt);
+
+  /*
+   * Turn off echoing.
+   */
+  if (!GetConsoleMode(console_handle, &console_mode)) {
+    fprintf(stderr, "Can't get console mode: %s\n",
+            win32_strerror(GetLastError()));
+    exit(1);
+  }
+  save_console_mode = console_mode;
+  console_mode &= ~ENABLE_ECHO_INPUT;
+  if (!SetConsoleMode(console_handle, console_mode)) {
+    fprintf(stderr, "Can't set console mode: %s\n",
+            win32_strerror(GetLastError()));
+    exit(1);
+  }
+  if (fgets(password, sizeof password, stdin) == NULL) {
+    fprintf(stderr, "\n");
+    SetConsoleMode(console_handle, save_console_mode);
+    exit(1);
+  }
+  fprintf(stderr, "\n");
+  SetConsoleMode(console_handle, save_console_mode);
+  p = strchr(password, '\n');
+  if (p != NULL)
+    *p = '\0';
+ return password;
+}
+#endif
+
+int main(int argc, char **argv)
+{
+  pcap_if_t *alldevs;
+  pcap_if_t *d;
+  bpf_u_int32 net, mask;
+  int exit_status = 0;
+  char errbuf[PCAP_ERRBUF_SIZE+1];
+#ifdef ENABLE_REMOTE
+  struct pcap_rmtauth auth;
+  char username[128+1];
+  char *p;
+  char *password;
+#endif
+
+#ifdef ENABLE_REMOTE
+  if (argc >= 2)
+  {
+    if (pcap_findalldevs_ex(argv[1], NULL, &alldevs, errbuf) == -1)
+    {
+      /*
+       * OK, try it with a user name and password.
+       */
+      fprintf(stderr, "User name: ");
+      if (fgets(username, sizeof username, stdin) == NULL)
+        exit(1);
+      p = strchr(username, '\n');
+      if (p != NULL)
+        *p = '\0';
+      password = getpass("Password: ");
+      auth.type = RPCAP_RMTAUTH_PWD;
+      auth.username = username;
+      auth.password = password;
+      if (pcap_findalldevs_ex(argv[1], &auth, &alldevs, errbuf) == -1)
+      {
+        fprintf(stderr,"Error in pcap_findalldevs: %s\n",errbuf);
+        exit(1);
+      }
+    }
+  }
+  else
+#endif
+  {
+    if (pcap_findalldevs(&alldevs, errbuf) == -1)
+    {
+      fprintf(stderr,"Error in pcap_findalldevs: %s\n",errbuf);
+      exit(1);
+    }
+  }
+  for(d=alldevs;d;d=d->next)
+  {
+    if (!ifprint(d))
+      exit_status = 2;
+  }
+
+  if (alldevs != NULL)
+  {
+    if (pcap_lookupnet(alldevs->name, &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));
+    }
+  }
+
+  pcap_freealldevs(alldevs);
+  exit(exit_status);
+}
+
+static int ifprint(pcap_if_t *d)
+{
+  pcap_addr_t *a;
+  char ipv4_buf[INET_ADDRSTRLEN];
+  char ipv6_buf[INET6_ADDRSTRLEN];
+  const char *sep;
+  int status = 1; /* success */
+
+  printf("%s\n",d->name);
+  if (d->description)
+    printf("\tDescription: %s\n",d->description);
+  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 = ", ";
+  }
+  if (d->flags & PCAP_IF_WIRELESS) {
+    printf("%sWIRELESS", sep);
+    switch (d->flags & PCAP_IF_CONNECTION_STATUS) {
+
+    case PCAP_IF_CONNECTION_STATUS_UNKNOWN:
+      printf(" (association status unknown)");
+      break;
+
+    case PCAP_IF_CONNECTION_STATUS_CONNECTED:
+      printf(" (associated)");
+      break;
+
+    case PCAP_IF_CONNECTION_STATUS_DISCONNECTED:
+      printf(" (not associated)");
+      break;
+
+    case PCAP_IF_CONNECTION_STATUS_NOT_APPLICABLE:
+      break;
+    }
+  } else {
+    switch (d->flags & PCAP_IF_CONNECTION_STATUS) {
+
+    case PCAP_IF_CONNECTION_STATUS_UNKNOWN:
+      printf(" (connection status unknown)");
+      break;
+
+    case PCAP_IF_CONNECTION_STATUS_CONNECTED:
+      printf(" (connected)");
+      break;
+
+    case PCAP_IF_CONNECTION_STATUS_DISCONNECTED:
+      printf(" (disconnected)");
+      break;
+
+    case PCAP_IF_CONNECTION_STATUS_NOT_APPLICABLE:
+      break;
+    }
+  }
+  sep = ", ";
+  printf("\n");
+
+  for(a=d->addresses;a;a=a->next) {
+    if (a->addr != NULL)
+      switch(a->addr->sa_family) {
+      case AF_INET:
+        printf("\tAddress Family: AF_INET\n");
+        if (a->addr)
+          printf("\t\tAddress: %s\n",
+            inet_ntop(AF_INET,
+               &((struct sockaddr_in *)(a->addr))->sin_addr,
+               ipv4_buf, sizeof ipv4_buf));
+        if (a->netmask)
+          printf("\t\tNetmask: %s\n",
+            inet_ntop(AF_INET,
+               &((struct sockaddr_in *)(a->netmask))->sin_addr,
+               ipv4_buf, sizeof ipv4_buf));
+        if (a->broadaddr)
+          printf("\t\tBroadcast Address: %s\n",
+            inet_ntop(AF_INET,
+               &((struct sockaddr_in *)(a->broadaddr))->sin_addr,
+               ipv4_buf, sizeof ipv4_buf));
+        if (a->dstaddr)
+          printf("\t\tDestination Address: %s\n",
+            inet_ntop(AF_INET,
+               &((struct sockaddr_in *)(a->dstaddr))->sin_addr,
+               ipv4_buf, sizeof ipv4_buf));
+        break;
+#ifdef INET6
+      case AF_INET6:
+        printf("\tAddress Family: AF_INET6\n");
+        if (a->addr)
+          printf("\t\tAddress: %s\n",
+            inet_ntop(AF_INET6,
+               ((struct sockaddr_in6 *)(a->addr))->sin6_addr.s6_addr,
+               ipv6_buf, sizeof ipv6_buf));
+        if (a->netmask)
+          printf("\t\tNetmask: %s\n",
+            inet_ntop(AF_INET6,
+              ((struct sockaddr_in6 *)(a->netmask))->sin6_addr.s6_addr,
+               ipv6_buf, sizeof ipv6_buf));
+        if (a->broadaddr)
+          printf("\t\tBroadcast Address: %s\n",
+            inet_ntop(AF_INET6,
+              ((struct sockaddr_in6 *)(a->broadaddr))->sin6_addr.s6_addr,
+               ipv6_buf, sizeof ipv6_buf));
+        if (a->dstaddr)
+          printf("\t\tDestination Address: %s\n",
+            inet_ntop(AF_INET6,
+              ((struct sockaddr_in6 *)(a->dstaddr))->sin6_addr.s6_addr,
+               ipv6_buf, sizeof ipv6_buf));
+        break;
+#endif
+      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 */
+#define IPTOSBUFFERS   12
+static char *iptos(bpf_u_int32 in)
+{
+       static char output[IPTOSBUFFERS][3*4+3+1];
+       static short which;
+       u_char *p;
+
+       p = (u_char *)&in;
+       which = (which + 1 == IPTOSBUFFERS ? 0 : which + 1);
+       sprintf(output[which], "%d.%d.%d.%d", p[0], p[1], p[2], p[3]);
+       return output[which];
+}
similarity index 86%
rename from tests/opentest.c
rename to testprogs/opentest.c
index 0c91531..bad38eb 100644 (file)
  * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
  */
 
+#include "varattrs.h"
+
 #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 +32,27 @@ The Regents of the University of California.  All rights reserved.\n";
 #include <stdlib.h>
 #include <string.h>
 #include <stdarg.h>
-#include <unistd.h>
+#ifdef _WIN32
+  #include "getopt.h"
+#else
+  #include <unistd.h>
+#endif
 #include <errno.h>
 
+#include "pcap/funcattrs.h"
+
+#ifdef _WIN32
+  #include "portability.h"
+#endif
+
 #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 *, ...);
-
-extern int optind;
-extern int opterr;
-extern char *optarg;
+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)
@@ -53,6 +61,7 @@ main(int argc, char **argv)
        register char *cp, *device;
        int dorfmon, dopromisc, snaplen, useactivate, bufsize;
        char ebuf[PCAP_ERRBUF_SIZE];
+       pcap_if_t *devlist;
        pcap_t *pd;
        int status = 0;
 
@@ -113,10 +122,18 @@ main(int argc, char **argv)
                }
        }
 
+       if (device == NULL) {
+               if (pcap_findalldevs(&devlist, ebuf) == -1)
+                       error("%s", ebuf);
+               if (devlist == NULL)
+                       error("no interfaces available for capture");
+               device = strdup(devlist->name);
+               pcap_freealldevs(devlist);
+       }
        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 +174,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 +183,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);
similarity index 93%
rename from tests/reactivatetest.c
rename to testprogs/reactivatetest.c
index 9031a64..d7f3e32 100644 (file)
  * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
  */
 
+#include "varattrs.h"
+
 #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
@@ -31,8 +33,10 @@ The Regents of the University of California.  All rights reserved.\n";
 #include <string.h>
 #include <stdarg.h>
 
+#include "pcap/funcattrs.h"
+
 /* Forwards */
-static void error(const char *, ...);
+static void PCAP_NORETURN error(PCAP_FORMAT_STRING(const char *), ...) PCAP_PRINTFLIKE(1,2);
 
 int
 main(void)
similarity index 57%
rename from tests/selpolltest.c
rename to testprogs/selpolltest.c
index d94fb56..329281d 100644 (file)
  * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
  */
 
+#include "varattrs.h"
+
 #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 +43,26 @@ 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;
+#include "pcap/funcattrs.h"
+
+static char *program_name;
 
 /* 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)
 {
@@ -58,15 +70,19 @@ main(int argc, char **argv)
        bpf_u_int32 localnet, netmask;
        register char *cp, *cmdbuf, *device;
        int doselect, dopoll, dotimeout, dononblock;
+       const char *mechanism;
        struct bpf_program fcode;
        char ebuf[PCAP_ERRBUF_SIZE];
+       pcap_if_t *devlist;
        int selectable_fd;
+       struct timeval *required_timeout;
        int status;
        int packet_count;
 
        device = NULL;
        doselect = 0;
        dopoll = 0;
+       mechanism = NULL;
        dotimeout = 0;
        dononblock = 0;
        if ((cp = strrchr(argv[0], '/')) != NULL)
@@ -84,10 +100,12 @@ main(int argc, char **argv)
 
                case 's':
                        doselect = 1;
+                       mechanism = "select() and pcap_dispatch()";
                        break;
 
                case 'p':
                        dopoll = 1;
+                       mechanism = "poll() and pcap_dispatch()";
                        break;
 
                case 't':
@@ -113,9 +131,12 @@ main(int argc, char **argv)
                return 1;
        }
        if (device == NULL) {
-               device = pcap_lookupdev(ebuf);
-               if (device == NULL)
+               if (pcap_findalldevs(&devlist, ebuf) == -1)
                        error("%s", ebuf);
+               if (devlist == NULL)
+                       error("no interfaces available for capture");
+               device = strdup(devlist->name);
+               pcap_freealldevs(devlist);
        }
        *ebuf = '\0';
        pd = pcap_open_live(device, 65535, 0, 1000, ebuf);
@@ -132,58 +153,112 @@ main(int argc, char **argv)
 
        if (pcap_compile(pd, &fcode, cmdbuf, 1, netmask) < 0)
                error("%s", pcap_geterr(pd));
-
        if (pcap_setfilter(pd, &fcode) < 0)
                error("%s", pcap_geterr(pd));
-       if (pcap_get_selectable_fd(pd) == -1)
-               error("pcap_get_selectable_fd() fails");
+
+       if (doselect || dopoll) {
+               /*
+                * We need either an FD on which to do select()/poll()
+                * or, if there isn't one, a timeout to use in select()/
+                * poll().
+                */
+               selectable_fd = pcap_get_selectable_fd(pd);
+               if (selectable_fd == -1) {
+                       printf("Listening on %s, using %s, with a timeout\n",
+                           device, mechanism);
+                       required_timeout = pcap_get_required_select_timeout(pd);
+                       if (required_timeout == NULL)
+                               error("select()/poll() isn't supported on %s, even with a timeout",
+                                   device);
+
+                       /*
+                        * As we won't be notified by select() or poll()
+                        * that a read can be done, we'll have to periodically
+                        * try reading from the device every time the required
+                        * timeout expires, and we don't want those attempts
+                        * to block if nothing has arrived in that interval,
+                        * so we want to force non-blocking mode.
+                        */
+                       dononblock = 1;
+               } else {
+                       printf("Listening on %s, using %s\n", device,
+                           mechanism);
+                       required_timeout = NULL;
+               }
+       } else
+               printf("Listening on %s, using pcap_dispatch()\n", device);
+
        if (dononblock) {
                if (pcap_setnonblock(pd, 1, ebuf) == -1)
                        error("pcap_setnonblock failed: %s", ebuf);
        }
-       selectable_fd = pcap_get_selectable_fd(pd);
-       printf("Listening on %s\n", device);
        if (doselect) {
                for (;;) {
                        fd_set setread, setexcept;
                        struct timeval seltimeout;
 
                        FD_ZERO(&setread);
-                       FD_SET(selectable_fd, &setread);
-                       FD_ZERO(&setexcept);
-                       FD_SET(selectable_fd, &setexcept);
+                       if (selectable_fd != -1) {
+                               FD_SET(selectable_fd, &setread);
+                               FD_ZERO(&setexcept);
+                               FD_SET(selectable_fd, &setexcept);
+                       }
                        if (dotimeout) {
                                seltimeout.tv_sec = 0;
-                               seltimeout.tv_usec = 1000;
+                               if (required_timeout != NULL &&
+                                   required_timeout->tv_usec < 1000)
+                                       seltimeout.tv_usec = required_timeout->tv_usec;
+                               else
+                                       seltimeout.tv_usec = 1000;
                                status = select(selectable_fd + 1, &setread,
                                    NULL, &setexcept, &seltimeout);
-                       } else {
+                       } else if (required_timeout != NULL) {
+                               seltimeout = *required_timeout;
                                status = select(selectable_fd + 1, &setread,
+                                   NULL, &setexcept, &seltimeout);
+                       } else {
+                               status = select((selectable_fd == -1) ?
+                                   0 : selectable_fd + 1, &setread,
                                    NULL, &setexcept, NULL);
                        }
                        if (status == -1) {
                                printf("Select returns error (%s)\n",
                                    strerror(errno));
                        } else {
-                               if (status == 0)
-                                       printf("Select timed out: ");
-                               else
-                                       printf("Select returned a descriptor: ");
-                               if (FD_ISSET(selectable_fd, &setread))
-                                       printf("readable, ");
-                               else
-                                       printf("not readable, ");
-                               if (FD_ISSET(selectable_fd, &setexcept))
-                                       printf("exceptional condition\n");
-                               else
-                                       printf("no exceptional condition\n");
+                               if (selectable_fd == -1) {
+                                       if (status != 0)
+                                               printf("Select returned a descriptor\n");
+                               } else {
+                                       if (status == 0)
+                                               printf("Select timed out: ");
+                                       else
+                                               printf("Select returned a descriptor: ");
+                                       if (FD_ISSET(selectable_fd, &setread))
+                                               printf("readable, ");
+                                       else
+                                               printf("not readable, ");
+                                       if (FD_ISSET(selectable_fd, &setexcept))
+                                               printf("exceptional condition\n");
+                                       else
+                                               printf("no exceptional condition\n");
+                               }
                                packet_count = 0;
                                status = pcap_dispatch(pd, -1, countme,
                                    (u_char *)&packet_count);
                                if (status < 0)
                                        break;
-                               printf("%d packets seen, %d packets counted after select returns\n",
-                                   status, packet_count);
+                               /*
+                                * Don't report this if we're using a
+                                * required timeout and we got no packets,
+                                * because that could be a very short timeout,
+                                * and we don't want to spam the user with
+                                * a ton of "no packets" reports.
+                                */
+                               if (status != 0 || packet_count != 0 ||
+                                   required_timeout != NULL) {
+                                       printf("%d packets seen, %d packets counted after select returns\n",
+                                           status, packet_count);
+                               }
                        }
                }
        } else if (dopoll) {
@@ -195,41 +270,59 @@ main(int argc, char **argv)
                        fd.events = POLLIN;
                        if (dotimeout)
                                polltimeout = 1;
+                       else if (required_timeout != NULL &&
+                           required_timeout->tv_usec >= 1000)
+                               polltimeout = required_timeout->tv_usec/1000;
                        else
                                polltimeout = -1;
-                       status = poll(&fd, 1, polltimeout);
+                       status = poll(&fd, (selectable_fd == -1) ? 0 : 1, polltimeout);
                        if (status == -1) {
                                printf("Poll returns error (%s)\n",
                                    strerror(errno));
                        } else {
-                               if (status == 0)
-                                       printf("Poll timed out\n");
-                               else {
-                                       printf("Poll returned a descriptor: ");
-                                       if (fd.revents & POLLIN)
-                                               printf("readable, ");
-                                       else
-                                               printf("not readable, ");
-                                       if (fd.revents & POLLERR)
-                                               printf("exceptional condition, ");
-                                       else
-                                               printf("no exceptional condition, ");
-                                       if (fd.revents & POLLHUP)
-                                               printf("disconnect, ");
-                                       else
-                                               printf("no disconnect, ");
-                                       if (fd.revents & POLLNVAL)
-                                               printf("invalid\n");
-                                       else
-                                               printf("not invalid\n");
+                               if (selectable_fd == -1) {
+                                       if (status != 0)
+                                               printf("Poll returned a descriptor\n");
+                               } else {
+                                       if (status == 0)
+                                               printf("Poll timed out\n");
+                                       else {
+                                               printf("Poll returned a descriptor: ");
+                                               if (fd.revents & POLLIN)
+                                                       printf("readable, ");
+                                               else
+                                                       printf("not readable, ");
+                                               if (fd.revents & POLLERR)
+                                                       printf("exceptional condition, ");
+                                               else
+                                                       printf("no exceptional condition, ");
+                                               if (fd.revents & POLLHUP)
+                                                       printf("disconnect, ");
+                                               else
+                                                       printf("no disconnect, ");
+                                               if (fd.revents & POLLNVAL)
+                                                       printf("invalid\n");
+                                               else
+                                                       printf("not invalid\n");
+                                       }
                                }
                                packet_count = 0;
                                status = pcap_dispatch(pd, -1, countme,
                                    (u_char *)&packet_count);
                                if (status < 0)
                                        break;
-                               printf("%d packets seen, %d packets counted after poll returns\n",
-                                   status, packet_count);
+                               /*
+                                * Don't report this if we're using a
+                                * required timeout and we got no packets,
+                                * because that could be a very short timeout,
+                                * and we don't want to spam the user with
+                                * a ton of "no packets" reports.
+                                */
+                               if (status != 0 || packet_count != 0 ||
+                                   required_timeout != NULL) {
+                                       printf("%d packets seen, %d packets counted after poll returns\n",
+                                           status, packet_count);
+                               }
                        }
                }
        } else {
@@ -264,7 +357,7 @@ main(int argc, char **argv)
 }
 
 static void
-countme(u_char *user, const struct pcap_pkthdr *h, const u_char *sp)
+countme(u_char *user, const struct pcap_pkthdr *h _U_, const u_char *sp _U_)
 {
        int *counterp = (int *)user;
 
diff --git a/testprogs/threadsignaltest.c b/testprogs/threadsignaltest.c
new file mode 100644 (file)
index 0000000..a60bb49
--- /dev/null
@@ -0,0 +1,393 @@
+/*
+ * 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.
+ */
+
+#include "varattrs.h"
+
+#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 <limits.h>
+#ifdef _WIN32
+  #include <winsock2.h>
+  #include <windows.h>
+
+  #define THREAD_HANDLE                        HANDLE
+  #define THREAD_FUNC_ARG_TYPE         LPVOID
+  #define THREAD_FUNC_RETURN_TYPE      DWORD __stdcall
+
+  #include "getopt.h"
+#else
+  #include <pthread.h>
+  #include <signal.h>
+  #include <unistd.h>
+
+  #define THREAD_HANDLE                        pthread_t
+  #define THREAD_FUNC_ARG_TYPE         void *
+  #define THREAD_FUNC_RETURN_TYPE      void *
+#endif
+#include <errno.h>
+#include <sys/types.h>
+
+#include <pcap.h>
+
+#include "pcap/funcattrs.h"
+
+#ifdef _WIN32
+  #include "portability.h"
+#endif
+
+static char *program_name;
+
+/* Forwards */
+static void countme(u_char *, const struct pcap_pkthdr *, const u_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;
+
+#ifdef _WIN32
+/*
+ * 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()
+ */
+#define ERRBUF_SIZE    1024
+static const char *
+win32_strerror(DWORD error)
+{
+  static char errbuf[ERRBUF_SIZE+1];
+  size_t errlen;
+
+  FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM, NULL, error, 0, errbuf,
+                ERRBUF_SIZE, NULL);
+
+  /*
+   * "FormatMessage()" "helpfully" sticks CR/LF at the end of the
+   * message.  Get rid of it.
+   */
+  errlen = strlen(errbuf);
+  if (errlen >= 2) {
+    errbuf[errlen - 1] = '\0';
+    errbuf[errlen - 2] = '\0';
+    errlen -= 2;
+  }
+  return errbuf;
+}
+#else
+static void
+catch_sigusr1(int sig _U_)
+{
+       printf("Got SIGUSR1\n");
+}
+#endif
+
+static void
+sleep_secs(int secs)
+{
+#ifdef _WIN32
+       Sleep(secs*1000);
+#else
+       unsigned secs_remaining;
+
+       if (secs <= 0)
+               return;
+       secs_remaining = secs;
+       while (secs_remaining != 0)
+               secs_remaining = sleep(secs_remaining);
+#endif
+}
+
+static THREAD_FUNC_RETURN_TYPE
+capture_thread_func(THREAD_FUNC_ARG_TYPE arg)
+{
+       char *device = arg;
+       int packet_count;
+       int status;
+#ifndef _WIN32
+       struct sigaction action;
+       sigset_t mask;
+#endif
+
+#ifndef _WIN32
+       sigemptyset(&mask);
+       action.sa_handler = catch_sigusr1;
+       action.sa_mask = mask;
+       action.sa_flags = 0;
+       if (sigaction(SIGUSR1, &action, NULL) == -1)
+               error("Can't catch SIGUSR1: %s", strerror(errno));
+#endif
+
+       printf("Listening on %s\n", device);
+       for (;;) {
+               packet_count = 0;
+               status = pcap_dispatch(pd, -1, countme,
+                   (u_char *)&packet_count);
+               if (status < 0)
+                       break;
+               if (status != 0) {
+                       printf("%d packets seen, %d packets counted after pcap_dispatch returns\n",
+                           status, packet_count);
+               } else
+                       printf("No packets seen by pcap_dispatch\n");
+       }
+       if (status == -2) {
+               /*
+                * We got interrupted, so perhaps we didn't
+                * manage to finish a line we were printing.
+                * Print an extra newline, just in case.
+                */
+               putchar('\n');
+               printf("Loop got broken\n");
+       }
+       (void)fflush(stdout);
+       if (status == -1) {
+               /*
+                * Error.  Report it.
+                */
+               (void)fprintf(stderr, "%s: pcap_loop: %s\n",
+                   program_name, pcap_geterr(pd));
+       }
+       return 0;
+}
+
+int
+main(int argc, char **argv)
+{
+       register int op;
+       register char *cp, *cmdbuf, *device;
+       int immediate = 0;
+       pcap_if_t *devlist;
+       bpf_u_int32 localnet, netmask;
+       struct bpf_program fcode;
+       char ebuf[PCAP_ERRBUF_SIZE];
+       int status;
+       THREAD_HANDLE capture_thread;
+#ifndef _WIN32
+       void *retval;
+#endif
+
+       device = NULL;
+       if ((cp = strrchr(argv[0], '/')) != NULL)
+               program_name = cp + 1;
+       else
+               program_name = argv[0];
+
+       opterr = 0;
+       while ((op = getopt(argc, argv, "i:")) != -1) {
+               switch (op) {
+
+               case 'i':
+                       device = optarg;
+                       break;
+
+               default:
+                       usage();
+                       /* NOTREACHED */
+               }
+       }
+
+       if (device == NULL) {
+               if (pcap_findalldevs(&devlist, ebuf) == -1)
+                       error("%s", ebuf);
+               if (devlist == NULL)
+                       error("no interfaces available for capture");
+               device = strdup(devlist->name);
+               pcap_freealldevs(devlist);
+       }
+       *ebuf = '\0';
+       pd = pcap_create(device, ebuf);
+       if (pd == NULL)
+               error("%s", ebuf);
+       status = pcap_set_snaplen(pd, 65535);
+       if (status != 0)
+               error("%s: pcap_set_snaplen failed: %s",
+                           device, pcap_statustostr(status));
+       if (immediate) {
+               status = pcap_set_immediate_mode(pd, 1);
+               if (status != 0)
+                       error("%s: pcap_set_immediate_mode failed: %s",
+                           device, pcap_statustostr(status));
+       }
+       status = pcap_set_timeout(pd, 5*60*1000);
+       if (status != 0)
+               error("%s: pcap_set_timeout failed: %s",
+                   device, pcap_statustostr(status));
+       status = pcap_activate(pd);
+       if (status < 0) {
+               /*
+                * pcap_activate() failed.
+                */
+               error("%s: %s\n(%s)", device,
+                   pcap_statustostr(status), pcap_geterr(pd));
+       } else if (status > 0) {
+               /*
+                * pcap_activate() succeeded, but it's warning us
+                * of a problem it had.
+                */
+               warning("%s: %s\n(%s)", device,
+                   pcap_statustostr(status), pcap_geterr(pd));
+       }
+       if (pcap_lookupnet(device, &localnet, &netmask, ebuf) < 0) {
+               localnet = 0;
+               netmask = 0;
+               warning("%s", ebuf);
+       }
+       cmdbuf = copy_argv(&argv[optind]);
+
+       if (pcap_compile(pd, &fcode, cmdbuf, 1, netmask) < 0)
+               error("%s", pcap_geterr(pd));
+
+       if (pcap_setfilter(pd, &fcode) < 0)
+               error("%s", pcap_geterr(pd));
+
+#ifdef _WIN32
+       capture_thread = CreateThread(NULL, 0, capture_thread_func, device,
+           0, NULL);
+       if (capture_thread == NULL)
+               error("Can't create capture thread: %s",
+                   win32_strerror(GetLastError()));
+#else
+       status = pthread_create(&capture_thread, NULL, capture_thread_func,
+           device);
+       if (status != 0)
+               error("Can't create capture thread: %s", strerror(status));
+#endif
+       sleep_secs(60);
+       pcap_breakloop(pd);
+#ifdef _WIN32
+       printf("Setting event\n");
+       if (!SetEvent(pcap_getevent(pd)))
+               error("Can't set event for pcap_t: %s",
+                   win32_strerror(GetLastError()));
+       if (WaitForSingleObject(capture_thread, INFINITE) == WAIT_FAILED)
+               error("Wait for thread termination failed: %s",
+                   win32_strerror(GetLastError()));
+       CloseHandle(capture_thread);
+#else
+       printf("Sending SIGUSR1\n");
+       status = pthread_kill(capture_thread, SIGUSR1);
+       if (status != 0)
+               warning("Can't interrupt capture thread: %s", strerror(status));
+       status = pthread_join(capture_thread, &retval);
+       if (status != 0)
+               error("Wait for thread termination failed: %s",
+                   strerror(status));
+#endif
+
+       pcap_close(pd);
+       pcap_freecode(&fcode);
+       exit(status == -1 ? 1 : 0);
+}
+
+static void
+countme(u_char *user, const struct pcap_pkthdr *h _U_, const u_char *sp _U_)
+{
+       int *counterp = (int *)user;
+
+       (*counterp)++;
+}
+
+static void
+usage(void)
+{
+       (void)fprintf(stderr, "Usage: %s [ -m ] [ -i interface ] [ -t timeout] [expression]\n",
+           program_name);
+       exit(1);
+}
+
+/* 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 */
+}
+
+/* VARARGS */
+static void
+warning(const char *fmt, ...)
+{
+       va_list ap;
+
+       (void)fprintf(stderr, "%s: WARNING: ", 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);
+       }
+}
+
+/*
+ * Copy arg vector into a new buffer, concatenating arguments with spaces.
+ */
+static char *
+copy_argv(register char **argv)
+{
+       register char **p;
+       register u_int len = 0;
+       char *buf;
+       char *src, *dst;
+
+       p = argv;
+       if (*p == 0)
+               return 0;
+
+       while (*p)
+               len += strlen(*p++) + 1;
+
+       buf = (char *)malloc(len);
+       if (buf == NULL)
+               error("copy_argv: malloc");
+
+       p = argv;
+       dst = buf;
+       while ((src = *p++) != NULL) {
+               while ((*dst++ = *src++) != '\0')
+                       ;
+               dst[-1] = ' ';
+       }
+       dst[-1] = '\0';
+
+       return buf;
+}
diff --git a/testprogs/unix.h b/testprogs/unix.h
new file mode 100644 (file)
index 0000000..68ef4cb
--- /dev/null
@@ -0,0 +1,58 @@
+/*
+ * 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 unix_h
+#define        unix_h
+
+/*
+ * Definitions to make MSVC C runtime library structures and functions
+ * look like the UNIX structures and functions they are intended to
+ * resemble.
+ */
+#ifdef _MSC_VER
+  #define stat         _stat
+  #define fstat                _fstat
+
+  #define open         _open
+  #define O_RDONLY     _O_RDONLY
+  #define O_WRONLY     _O_WRONLY
+  #define O_RDWR       _O_RDWR
+  #define O_BINARY     _O_BINARY
+  #define O_CREAT      _O_CREAT
+  #define O_TRUNC      _O_TRUNC
+  #define read         _read
+  #define write                _write
+  #define close                _close
+#endif
+
+#endif
similarity index 86%
rename from tests/valgrindtest.c
rename to testprogs/valgrindtest.c
index 1d88377..104ef6a 100644 (file)
  * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
  */
 
+#include "varattrs.h"
+
+/*
+ * 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 macOS:
+ *
+ *     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 macOS
+ * 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\
@@ -26,7 +52,7 @@ The Regents of the University of California.  All rights reserved.\n";
 #endif
 
 #ifdef HAVE_CONFIG_H
-#include "config.h"
+#include <config.h>
 #endif
 
 #include <stdio.h>
@@ -40,8 +66,10 @@ The Regents of the University of California.  All rights reserved.\n";
 #include <sys/types.h>
 #include <sys/stat.h>
 
-#if defined(__APPLE__) || defined(__FreeBSD__) || defined(__NetBSD__) || defined(__OpenBSD__) || defined(__DragonFly__)
-/* BSD-flavored OS - use BPF */
+#include "pcap/funcattrs.h"
+
+#if defined(__APPLE__) || defined(__FreeBSD__) || defined(__NetBSD__) || defined(__OpenBSD__) || defined(__DragonFly__) || defined(_AIX) || defined(sun)
+/* OS with BPF - use BPF */
 #define USE_BPF
 #elif defined(linux)
 /* Linux - use socket filters */
@@ -72,22 +100,13 @@ 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)));
-
-extern int optind;
-extern int opterr;
-extern char *optarg;
+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
@@ -214,7 +233,8 @@ main(int argc, char **argv)
        int dorfmon, useactivate;
        char ebuf[PCAP_ERRBUF_SIZE];
        char *infile;
-       char *cmdbuf;
+       const char *cmdbuf;
+       pcap_if_t *devlist;
        pcap_t *pd;
        int status = 0;
        int pcap_fd;
@@ -231,7 +251,7 @@ main(int argc, char **argv)
        dorfmon = 0;
        useactivate = 0;
        infile = NULL;
-  
+
        if ((cp = strrchr(argv[0], '/')) != NULL)
                program_name = cp + 1;
        else
@@ -269,11 +289,12 @@ main(int argc, char **argv)
                 * No interface specified; get whatever pcap_lookupdev()
                 * finds.
                 */
-               device = pcap_lookupdev(ebuf);
-               if (device == NULL) {
-                       error("couldn't find interface to use: %s",
-                           ebuf);
-               }
+               if (pcap_findalldevs(&devlist, ebuf) == -1)
+                       error("%s", ebuf);
+               if (devlist == NULL)
+                       error("no interfaces available for capture");
+               device = strdup(devlist->name);
+               pcap_freealldevs(devlist);
        }
 
        if (infile != NULL) {
diff --git a/tests/findalldevstest.c b/tests/findalldevstest.c
deleted file mode 100644 (file)
index ec7c950..0000000
+++ /dev/null
@@ -1,131 +0,0 @@
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-
-#include <stdlib.h>
-#include <sys/types.h>
-#include <sys/socket.h>
-#include <netinet/in.h>
-#include <arpa/inet.h>
-#include <netdb.h>
-
-#include <pcap.h>
-
-static void ifprint(pcap_if_t *d);
-static char *iptos(bpf_u_int32 in);
-
-int main(int argc, char **argv)
-{
-  pcap_if_t *alldevs;
-  pcap_if_t *d;
-  char *s;
-  bpf_u_int32 net, mask;
-  
-  char errbuf[PCAP_ERRBUF_SIZE+1];
-  if (pcap_findalldevs(&alldevs, errbuf) == -1)
-  {
-    fprintf(stderr,"Error in pcap_findalldevs: %s\n",errbuf);
-    exit(1);
-  }
-  for(d=alldevs;d;d=d->next)
-  {
-    ifprint(d);
-  }
-
-  if ( (s = pcap_lookupdev(errbuf)) == NULL)
-  {
-    fprintf(stderr,"Error in pcap_lookupdev: %s\n",errbuf);
-  }
-  else
-  {
-    printf("Preferred device name: %s\n",s);
-  }
-
-  if (pcap_lookupnet(s, &net, &mask, errbuf) < 0)
-  {
-    fprintf(stderr,"Error in pcap_lookupnet: %s\n",errbuf);
-  }
-  else
-  {
-    printf("Preferred device is on network: %s/%s\n",iptos(net), iptos(mask));
-  }
-  
-  exit(0);
-}
-
-static void ifprint(pcap_if_t *d)
-{
-  pcap_addr_t *a;
-#ifdef INET6
-  char ntop_buf[INET6_ADDRSTRLEN];
-#endif
-
-  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");
-
-  for(a=d->addresses;a;a=a->next) {
-    switch(a->addr->sa_family)
-    {
-      case AF_INET:
-        printf("\tAddress Family: AF_INET\n");
-        if (a->addr)
-          printf("\t\tAddress: %s\n",
-            inet_ntoa(((struct sockaddr_in *)(a->addr))->sin_addr));
-        if (a->netmask)
-          printf("\t\tNetmask: %s\n",
-            inet_ntoa(((struct sockaddr_in *)(a->netmask))->sin_addr));
-        if (a->broadaddr)
-          printf("\t\tBroadcast Address: %s\n",
-            inet_ntoa(((struct sockaddr_in *)(a->broadaddr))->sin_addr));
-        if (a->dstaddr)
-          printf("\t\tDestination Address: %s\n",
-            inet_ntoa(((struct sockaddr_in *)(a->dstaddr))->sin_addr));
-        break;
-#ifdef INET6
-      case AF_INET6:
-        printf("\tAddress Family: AF_INET6\n");
-        if (a->addr)
-          printf("\t\tAddress: %s\n",
-            inet_ntop(AF_INET6,
-               ((struct sockaddr_in6 *)(a->addr))->sin6_addr.s6_addr,
-               ntop_buf, sizeof ntop_buf));
-        if (a->netmask)
-          printf("\t\tNetmask: %s\n",
-            inet_ntop(AF_INET6,
-              ((struct sockaddr_in6 *)(a->netmask))->sin6_addr.s6_addr,
-               ntop_buf, sizeof ntop_buf));
-        if (a->broadaddr)
-          printf("\t\tBroadcast Address: %s\n",
-            inet_ntop(AF_INET6,
-              ((struct sockaddr_in6 *)(a->broadaddr))->sin6_addr.s6_addr,
-               ntop_buf, sizeof ntop_buf));
-        if (a->dstaddr)
-          printf("\t\tDestination Address: %s\n",
-            inet_ntop(AF_INET6,
-              ((struct sockaddr_in6 *)(a->dstaddr))->sin6_addr.s6_addr,
-               ntop_buf, sizeof ntop_buf));
-        break;
-#endif
-      default:
-        printf("\tAddress Family: Unknown (%d)\n", a->addr->sa_family);
-        break;
-    }
-  }
-  printf("\n");
-}
-
-/* From tcptraceroute */
-#define IPTOSBUFFERS   12
-static char *iptos(bpf_u_int32 in)
-{
-       static char output[IPTOSBUFFERS][3*4+3+1];
-       static short which;
-       u_char *p;
-
-       p = (u_char *)&in;
-       which = (which + 1 == IPTOSBUFFERS ? 0 : which + 1);
-       sprintf(output[which], "%d.%d.%d.%d", p[0], p[1], p[2], p[3]);
-       return output[which];
-}
diff --git a/tests/shb-option-too-long.pcapng b/tests/shb-option-too-long.pcapng
new file mode 100644 (file)
index 0000000..f773974
Binary files /dev/null and b/tests/shb-option-too-long.pcapng differ
similarity index 73%
rename from fad-null.c
rename to varattrs.h
index cecfbcb..05bfe8c 100644 (file)
@@ -1,6 +1,6 @@
 /* -*- Mode: c; tab-width: 8; indent-tabs-mode: 1; c-basic-offset: 8; -*- */
 /*
- * Copyright (c) 1994, 1995, 1996, 1997, 1998
+ * 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
  * SUCH DAMAGE.
  */
 
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
+#ifndef varattrs_h
+#define varattrs_h
 
-#include <pcap.h>
+#include <pcap/compiler-tests.h>
 
 /*
- * Get a list of all interfaces that are up and that we can open.
- * Returns -1 on error, 0 otherwise.
- * The list, as returned through "alldevsp", may be null if no interfaces
- * were up and could be opened.
- *
- * This is the implementation used on platforms that have no support for
- * packet capture.
+ * Attributes to apply to variables, using various compiler-specific
+ * extensions.
  */
-int
-pcap_findalldevs_interfaces(pcap_if_t **alldevsp, char *errbuf)
-{
-       /*
-        * Succeed, but don't return any interfaces; we return only those
-        * we can open, and we can't open any if there's no support
-        * for packet capture.
-        */
-       *alldevsp = NULL;
-       return (0);
-}
+
+#if __has_attribute(unused) \
+    || PCAP_IS_AT_LEAST_GNUC_VERSION(2,0)
+  /*
+   * Compiler with support for __attribute__((unused)), or GCC 2.0 and
+   * later, so it supports __attribute__((unused)).
+   */
+  #define _U_ __attribute__((unused))
+#else
+  /*
+   * We don't know of any way to mark a variable as unused.
+   */
+  #define _U_
+#endif
+
+#endif