Merge "Update libpcap to 1.9.0"
diff --git a/Android.bp b/Android.bp
index 1d3a5cb..f18fb08 100644
--- a/Android.bp
+++ b/Android.bp
@@ -43,22 +43,20 @@
         "pcap-netfilter-linux-android.c",
         "fad-getad.c",
         "pcap.c",
-        "inet.c",
-        "fad-helpers.c",
         "gencode.c",
         "optimize.c",
         "nametoaddr.c",
         "etherent.c",
+        "fmtutils.c",
         "savefile.c",
         "sf-pcap.c",
-        "sf-pcap-ng.c",
+        "sf-pcapng.c",
         "pcap-common.c",
         "bpf_image.c",
+        "bpf_filter.c",
         "bpf_dump.c",
         "scanner.c",
         "grammar.c",
-        "bpf_filter.c",
-        "version.c",
     ],
 
     export_include_dirs: ["."],
@@ -74,13 +72,15 @@
     gtest: false,
     // (Matches order in libpcap's Makefile.)
     srcs: [
-        "tests/capturetest.c",
-        "tests/can_set_rfmon_test.c",
-        "tests/filtertest.c",
-        "tests/findalldevstest.c",
-        "tests/opentest.c",
-        "tests/reactivatetest.c",
-        "tests/selpolltest.c",
+        "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/valgrindtest.c",
     ],
     static_libs: ["libpcap"],
     test_per_src: true,
diff --git a/CHANGES b/CHANGES
index 1784096..4607f14 100644
--- a/CHANGES
+++ b/CHANGES
@@ -1,3 +1,82 @@
+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'.
diff --git a/CMakeLists.txt b/CMakeLists.txt
index 0ed8b61..905ba61 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -1,167 +1,848 @@
-cmake_minimum_required( VERSION 2.8.8 )
+cmake_minimum_required(VERSION 2.8.6)
 
-project( pcap )
 #
-# Call the library "wpcap" on Windows, for backwards compatibility.
+# 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( WIN32 )
-    set( LIBRARY_NAME wpcap )
-else()
-    set( LIBRARY_NAME pcap )
+if(POLICY CMP0042)
+    cmake_policy(SET CMP0042 OLD)
 endif()
 
+set(CMAKE_MODULE_PATH ${CMAKE_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
 ###################################################################
 
-option (INET6 "Enable IPv6" ON)
-if( MSVC )
-    option (USE_STATIC_RT "Use static Runtime" ON)
-endif( MSVC )
-option (BUILD_SHARED_LIBS "Build shared libraries" ON)
-if( WIN32 )
+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 )
+endif(WIN32)
+
+# To pacify those who hate the protochain instruction
+option(NO_PROTOCHAIN "Disable protochain instruction" OFF)
 
 #
-# XXX - this should be an option, defaulting to "yes" for Windows and to
-# "no", for now, on UN*X.
+# 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.
 #
-if( WIN32 )
-    set( HAVE_REMOTE 1 )
-endif( WIN32 )
+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()
+
+#
+# By default, build 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 LESS 8)
+        #
+        # Pre-Tiger.  Build only for 32-bit PowerPC.
+        #
+        set(CMAKE_OSX_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(CMAKE_OSX_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 x86,
+            # with 32-bit PowerPC first.
+            # (I'm guessing that's what Apple does.)
+            #
+            set(CMAKE_OSX_ARCHITECTURES "ppc;ppc64;i386")
+        else()
+            #
+            # With Intel support including x86-64 support.
+            # Build for 32-bit PowerPC, 64-bit PowerPC, x86,
+            # and x86-64, with 32-bit PowerPC first.
+            # (I'm guessing that's what Apple does.)
+            #
+            set(CMAKE_OSX_ARCHITECTURES "ppc;ppc64;i386;x86_64")
+        endif()
+    elseif(SYSTEM_VERSION_MAJOR EQUAL 9)
+        #
+        # Leopard.  Build for 32-bit PowerPC, 64-bit
+        # PowerPC, x86, and x86-64, with 32-bit PowerPC
+        # first.  (That's what Apple does.)
+        #
+        set(CMAKE_OSX_ARCHITECTURES "ppc;ppc64;i386;x86_64")
+    elseif(SYSTEM_VERSION_MAJOR EQUAL 10)
+        #
+        # 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.)
+        #
+        set(CMAKE_OSX_ARCHITECTURES "x86_64;i386;ppc")
+    else()
+        #
+        # 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.
+        #
+        set(CMAKE_OSX_ARCHITECTURES "x86_64;i386")
+    endif()
+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_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 )
+add_definitions(-DHAVE_CONFIG_H)
 
 include_directories(
     ${CMAKE_CURRENT_BINARY_DIR}
     ${pcap_SOURCE_DIR}
 )
 
-if( WIN32 )
-    if( NOT "${PACKET_DLL_DIR}" STREQUAL "" )
-        include_directories("${PACKET_DLL_DIR}/Include")
-        if( CMAKE_CL_64 )
-            link_directories("${PACKET_DLL_DIR}/Lib/x64")
-        else( CMAKE_CL_64 )
-            link_directories("${PACKET_DLL_DIR}/Lib")
-        endif( CMAKE_CL_64 )
-    endif()
-    include_directories(
-        ../Common/
-        Win32/Include
-    )
-endif( WIN32)
+include(CheckFunctionExists)
+include(CMakePushCheckState)
 
-add_definitions( -DBUILDING_PCAP )
+if(WIN32)
 
-if( MSVC )
-    add_definitions( -D__STDC__ )
-    add_definitions( -D_CRT_SECURE_NO_WARNINGS )
-    add_definitions( "-D_U_=" )
-elseif( CMAKE_COMPILER_IS_GNUCXX )
-    add_definitions( "-D_U_=__attribute__((unused))" )
-else(MSVC)
-    add_definitions( "-D_U_=" )
-endif( MSVC )
+    if(IS_DIRECTORY ${CMAKE_HOME_DIRECTORY}/../../Common)
+        include_directories(${CMAKE_HOME_DIRECTORY}/../../Common)
+    endif(IS_DIRECTORY ${CMAKE_HOME_DIRECTORY}/../../Common)
 
-if( MSVC )
-    if (USE_STATIC_RT)
-        MESSAGE( STATUS "Use STATIC runtime" )
-        set(NAME_RT MT)
-        set (CMAKE_CXX_FLAGS_MINSIZEREL     "${CMAKE_CXX_FLAGS_MINSIZEREL} /MT")
-        set (CMAKE_CXX_FLAGS_RELWITHDEBINFO "${CMAKE_CXX_FLAGS_RELWITHDEBINFO} /MT")
-        set (CMAKE_CXX_FLAGS_RELEASE        "${CMAKE_CXX_FLAGS_RELEASE} /MT")
-        set (CMAKE_CXX_FLAGS_DEBUG          "${CMAKE_CXX_FLAGS_DEBUG} /MTd")
+    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)
 
-        set (CMAKE_C_FLAGS_MINSIZEREL       "${CMAKE_C_FLAGS_MINSIZEREL} /MT")
-        set (CMAKE_C_FLAGS_RELWITHDEBINFO   "${CMAKE_C_FLAGS_RELWITHDEBINFO} /MT")
-        set (CMAKE_C_FLAGS_RELEASE          "${CMAKE_C_FLAGS_RELEASE} /MT")
-        set (CMAKE_C_FLAGS_DEBUG            "${CMAKE_C_FLAGS_DEBUG} /MTd")
-    else (USE_STATIC_RT)
-        MESSAGE( STATUS "Use DYNAMIC runtime" )
-        set(NAME_RT MD)
-        set (CMAKE_CXX_FLAGS_MINSIZEREL     "${CMAKE_CXX_FLAGS_MINSIZEREL} /MD")
-        set (CMAKE_CXX_FLAGS_RELWITHDEBINFO "${CMAKE_CXX_FLAGS_RELWITHDEBINFO} /MD")
-        set (CMAKE_CXX_FLAGS_RELEASE        "${CMAKE_CXX_FLAGS_RELEASE} /MD")
-        set (CMAKE_CXX_FLAGS_DEBUG          "${CMAKE_CXX_FLAGS_DEBUG} /MDd")
+endif(WIN32)
 
-        set (CMAKE_C_FLAGS_MINSIZEREL       "${CMAKE_C_FLAGS_MINSIZEREL} /MD")
-        set (CMAKE_C_FLAGS_RELWITHDEBINFO   "${CMAKE_C_FLAGS_RELWITHDEBINFO} /MD")
-        set (CMAKE_C_FLAGS_RELEASE          "${CMAKE_C_FLAGS_RELEASE} /MD")
-        set (CMAKE_C_FLAGS_DEBUG            "${CMAKE_C_FLAGS_DEBUG} /MDd")
-   endif (USE_STATIC_RT)
-endif( MSVC )
+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(CheckFunctionExists)
+include(CheckIncludeFiles)
 include(CheckStructHasMember)
 include(CheckTypeSize)
 
 #
 # 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 )
-check_include_file( limits.h HAVE_LIMITS_H )
+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( strlcpy HAVE_STRLCPY )
-check_function_exists( snprintf HAVE_SNPRINTF )
-check_function_exists( vsnprintf HAVE_VSNPRINTF )
-check_function_exists( strtok_r HAVE_STRTOK_R )
+check_function_exists(strerror HAVE_STRERROR)
+check_function_exists(strerror_r HAVE_STRERROR_R)
+check_function_exists(strerror_s HAVE_STRERROR_S)
+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(strtok_r HAVE_STRTOK_R)
 
-if (WIN32)
+#
+# 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)
+include(CheckSymbolExists)
+if(WIN32)
     #
-    # Check for Windows-only functions, such as packet.dll functions.
+    # We need winsock2.h and ws2tcpip.h.
     #
-    check_function_exists( PacketIsLoopbackAdapter HAVE_PACKET_IS_LOOPBACK_ADAPTER )
-endif()
+    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_struct() macro that's like check_struct_has_member()
+# 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_struct_has_member() and look for ss_family.
+# so we use check_type_size() and ignore the size.
 #
-check_struct_has_member("struct sockaddr_storage" ss_family sys/socket.h  HAVE_SOCKADDR_STORAGE)
-set(CMAKE_EXTRA_INCLUDE_FILES unistd.h sys/socket.h)
+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)
-set(CMAKE_EXTRA_INCLUDE_FILES unistd.h)
+cmake_pop_check_state()
 
 #
 # Structure fields.
 #
-check_struct_has_member("struct sockaddr" sa_len sys/socket.h HAVE_SOCKADDR_SA_LEN )
+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)
 
-if( INET6 )
-    MESSAGE( STATUS "Use IPv6" )
-endif( INET6 )
+#
+# 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()
 
-if( WIN32 )
-    add_definitions( -DHAVE_ADDRINFO )
-endif( WIN32 )
+#
+# 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()
 
-######################################
-# External dependencies
-######################################
+#
+# 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
@@ -169,104 +850,337 @@
 
 set(PROJECT_SOURCE_LIST_C
     bpf_dump.c
+    bpf_filter.c
     bpf_image.c
     etherent.c
-    fad-helpers.c
+    fmtutils.c
     gencode.c
-    inet.c
     nametoaddr.c
     optimize.c
     pcap-common.c
     pcap.c
     savefile.c
-    sf-pcap-ng.c
+    sf-pcapng.c
     sf-pcap.c
-    bpf/net/bpf_filter.c
 )
 
-if( WIN32 )
-    set(PROJECT_SOURCE_LIST_C ${PROJECT_SOURCE_LIST_C} missing/win_snprintf.c )
+if(WIN32)
+    set(PROJECT_SOURCE_LIST_C ${PROJECT_SOURCE_LIST_C} missing/win_snprintf.c)
 else()
-    if( NOT HAVE_SNPRINTF )
-        set(PROJECT_SOURCE_LIST_C ${PROJECT_SOURCE_LIST_C} missing/snprintf.c )
-    endif( NOT HAVE_SNPRINTF )
-    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 )
-
-if( HAVE_REMOTE )
-    set(PROJECT_SOURCE_LIST_C ${PROJECT_SOURCE_LIST_C}
-        pcap-new.c pcap-rpcap.c sockutils.c)
-endif( HAVE_REMOTE )
+    if(NOT HAVE_SNPRINTF)
+        set(PROJECT_SOURCE_LIST_C ${PROJECT_SOURCE_LIST_C} missing/snprintf.c)
+    endif(NOT HAVE_SNPRINTF)
+    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.
+# Determine the main pcap-XXX.c file to use, and the libraries with
+# which we need to link libpcap, if any.
 #
-if( WIN32 )
+if(WIN32)
     #
-    # WinPcap.
+    # Windows.
     #
-    set( PCAP_TYPE win32 )
-else()
+    # Has the user explicitly specified a capture type?
     #
-    # UN*X - figure out what type of packet capture mechanism we
-    # have.
-    #
-    if( EXISTS /dev/bpf )
-	#
-	# Cloning BPF device.
-	#
-	set( PCAP_TYPE bpf )
-	AC_DEFINE(HAVE_CLONING_BPF,1,[define if you have a cloning BPF device])
-    elseif( EXISTS /dev/bpf0 )
-	set( PCAP_TYPE bpf )
-
+    if(PCAP_TYPE STREQUAL "")
         #
-        # XXX - many more BPF checks.
+        # The user didn't explicitly specify a capture mechanism.
+        # Check whether we have packet.dll.
         #
-    elseif( EXISTS /usr/include/net/pfilt.h )
-        #
-        # DEC OSF/1, Digital UNIX, Tru64 UNIX
-        #
-	set( PCAP_TYPE pf )
-    elseif( EXISTS /dev/enet )
-        set( PCAP_TYPE enet )
-    elseif( EXISTS /dev/nit )
-        set( PCAP_TYPE snit )
-    elseif( EXISTS /usr/include/sys/net/nit.h )
-        set( PCAP_TYPE nit )
-    elseif( EXISTS /usr/include/linux/socket.h )
-        set( PCAP_TYPE linux )
-
-	#
-	# Do we have the wireless extensions?
-	#
-        check_include_file( linux/wireless.h HAVE_LINUX_WIRELESS_H )
-
-        #
-        # XXX - many more Linux checks.
-	#
-    elseif( EXISTS /usr/include/net/raw.h )
-        set( PCAP_TYPE snoop )
-    elseif( EXISTS /usr/include/odmi.h )
-        #
-        # 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.
-        #
-        set( PCAP_TYPE bpf )
-    elseif( /usr/include/sys/dlpi.h )
-        set( PCAP_TYPE dlpi )
-
-        #
-        # XXX - many more DLPI checks.
-        #
-    else()
-	set( PCAP_TYPE null )
+        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()
-endif( WIN32 )
+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/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/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/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)
 
 #
@@ -274,31 +1188,54 @@
 # if we support capturing.  Don't bother if we don't support
 # capturing.
 #
-if( NOT WIN32 )
+if(NOT WIN32)
     #
     # UN*X - figure out what type of interface list mechanism we
     # have.
     #
-    if( ${PCAP_TYPE} STREQUAL "null" )
-        #
-        # We can't capture, so we can't open any capture
-        # devices, so we won't return any interfaces.
-        #
-        set( FINDALLDEVS_TYPE null )
-    else()
-        check_function_exists( getifaddrs HAVE_GETIFADDRS )
-        if( ${HAVE_GETIFADDRS} )
+    # 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_file( ifaddrs.h HAVE_IFADDRS_H )
-            if( ${HAVE_IFADDRS_H} )
+            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 )
+                set(FINDALLDEVS_TYPE getad)
             else()
                 #
                 # We don't have the header - give up.
@@ -309,60 +1246,491 @@
                 # 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>." )
+                message(FATAL_ERROR "Your system has getifaddrs() but doesn't have a usable <ifaddrs.h>.")
             endif()
         else()
             #
-            # Well, we don't have "getifaddrs()", so we have to use
-            # some other mechanism; determine what that mechanism is.
+            # 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.
             #
-            # The first thing we use is the type of capture mechanism,
-            # which is somewhat of a proxy for the OS we're using.
+            # 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.
             #
-            if( ${PCAP_TYPE} STREQUAL "dlpi" OR ${PCAP_TYPE} STREQUAL "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.
-                #
-                try_compile( HAVE_SIOCGLIFCONF ${CMAKE_CURRENT_BINARY_DIR} "${pcap_SOURCE_DIR}/config/have_siocglifconf.c"  )
-                message( STATUS "HAVE_SIOCGLIFCONF = ${HAVE_SIOCGLIFCONF}" )
-                if( HAVE_SIOCGLIFCONF )
-                    set( FINDALLDEVS_TYPE glifc )
-                else()
-                    set( FINDALLDEVS_TYPE gifc )
-                endif()
+            # 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)
                 #
-                # Assume we just have SIOCGIFCONF.
-                # (XXX - on at least later Linux kernels, there's
-                # another mechanism, and we should be using that
-                # instead.)
+                # OK, is HCI_CHANNEL_MONITOR defined?
                 #
-                set( FINDALLDEVS_TYPE gifc )
+               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})
+        set(PCAP_LINK_LIBRARIES ${PCAP_LINK_LIBRARIES} ${DBUS_LIBRARIES})
+    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()
-    message(STATUS "Find-interfaces mechanism type: ${FINDALLDEVS_TYPE}")
-    set( PROJECT_SOURCE_LIST_C ${PROJECT_SOURCE_LIST_C} fad-${FINDALLDEVS_TYPE}.c )
 endif()
 
-file(GLOB PROJECT_SOURCE_LIST_CORE_H
+# 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_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_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
 )
-set( PROJECT_SOURCE_LIST_H ${PROJECT_SOURCE_LIST_H} ${PROJECT_SOURCE_LIST_CORE_H} )
-
-if( WIN32 )
-    file(GLOB PROJECT_SOURCE_LIST_WIN32_H
-        Win32/Include/*.h
-    )
-    set( PROJECT_SOURCE_LIST_H ${PROJECT_SOURCE_LIST_H} ${PROJECT_SOURCE_LIST_WIN32_H} )
-endif( WIN32 )
 
 #
-# {Flex} and YACC/Berkeley YACC/Bison.
+# 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.
 #
@@ -371,8 +1739,8 @@
 # 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." )
+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}")
 
@@ -391,7 +1759,7 @@
 #
 set_source_files_properties(${CMAKE_CURRENT_BINARY_DIR}/scanner.c PROPERTIES
     GENERATED TRUE
-    OBJECT_DEPENDS ${CMAKE_CURRENT_BINARY_DIR}/scanner.h
+    OBJECT_DEPENDS ${CMAKE_CURRENT_BINARY_DIR}/grammar.h
 )
 
 #
@@ -403,19 +1771,19 @@
 # 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." )
+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 notby looking at the last component
+# 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" )
+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
@@ -430,6 +1798,7 @@
 #
 set_source_files_properties(${CMAKE_CURRENT_BINARY_DIR}/grammar.c PROPERTIES
     GENERATED TRUE
+    OBJECT_DEPENDS ${CMAKE_CURRENT_BINARY_DIR}/scanner.h
 )
 
 #
@@ -437,84 +1806,491 @@
 #
 #set(PROJECT_SOURCE_LIST_C ${PROJECT_SOURCE_LIST_C} ${CMAKE_CURRENT_BINARY_DIR}/grammar.c)
 
-if( WIN32 )
-    #
-    # CMake does not love Windows.
-    #
-    file(TO_NATIVE_PATH "${pcap_SOURCE_DIR}/GenVersion.bat" GenVersion_path)
-    file(TO_NATIVE_PATH "${pcap_SOURCE_DIR}/VERSION" VERSION_path)
-    file(TO_NATIVE_PATH "${pcap_SOURCE_DIR}/pcap_version.h.in" version_h_in_path)
-    file(TO_NATIVE_PATH "${CMAKE_CURRENT_BINARY_DIR}/pcap_version.h" version_h_path)
-    add_custom_command(
-        OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/pcap_version.h
-        SOURCE ${pcap_SOURCE_DIR}/VERSION ${pcap_SOURCE_DIR}/pcap_version.h.in
-        COMMAND ${GenVersion_path} ${VERSION_path} ${version_h_in_path} ${version_h_path}
-        DEPENDS ${pcap_SOURCE_DIR}/VERSION ${pcap_SOURCE_DIR}/pcap_version.h.in
-    )
-else( WIN32 )
-    add_custom_command(
-        OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/version.c
-        SOURCE ${pcap_SOURCE_DIR}/VERSION
-        COMMAND ${pcap_SOURCE_DIR}/gen_version_c.sh ${pcap_SOURCE_DIR}/VERSION ${CMAKE_CURRENT_BINARY_DIR}/version.c
-        DEPENDS ${pcap_SOURCE_DIR}/VERSION
-    )
-    add_custom_command(
-        OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/pcap_version.h
-        SOURCE ${pcap_SOURCE_DIR}/VERSION
-        COMMAND ${pcap_SOURCE_DIR}/gen_version_header.sh ${pcap_SOURCE_DIR}/VERSION ${pcap_SOURCE_DIR}/pcap_version.h.in ${CMAKE_CURRENT_BINARY_DIR}/pcap_version.h
-        DEPENDS ${pcap_SOURCE_DIR}/VERSION
-    )
+#
+# 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, administrative commands and daemons in section 8).
+# Individual cases can override this.
+#
+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()
 
     #
-    # Since version.c does not exists yet when cmake is run, mark
-    # it as generated.
+    # Use System V conventions for man pages.
     #
-    set_source_files_properties(${CMAKE_CURRENT_BINARY_DIR}/version.c PROPERTIES
-        GENERATED TRUE
-    )
-
+    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")
     #
-    # Add version.c to the list of sources.
+    # 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(PROJECT_SOURCE_LIST_C ${PROJECT_SOURCE_LIST_C} ${CMAKE_CURRENT_BINARY_DIR}/version.c)
-endif( WIN32 )
+    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)
+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)
 
-#
-# Since pcap_version.h does not exists yet when cmake is run, mark
-# it as generated.
-#
-set_source_files_properties(${CMAKE_CURRENT_BINARY_DIR}/pcap_version.h PROPERTIES
-    GENERATED TRUE
-)
-
-#
-# Add pcap_version.h to the list of headers.
-#
-set(PROJECT_SOURCE_LIST_H ${PROJECT_SOURCE_LIST_H} ${CMAKE_CURRENT_BINARY_DIR}/pcap_version.h)
+    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)
+    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
 ######################################
 
-add_library(${LIBRARY_NAME}
+#
+# 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)
+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_SOURCE_LIST_H}
+    ${PROJECT_EXTERNAL_OBJECT_LIST}
 )
+add_dependencies(${LIBRARY_NAME}_static SerializeTarget)
+set_target_properties(${LIBRARY_NAME}_static PROPERTIES
+    COMPILE_DEFINITIONS BUILDING_PCAP)
 
-if( WIN32 )
-    target_link_libraries ( ${LIBRARY_NAME}
-        packet
-        ws2_32
+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 )
+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()
 
 ######################################
 # 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_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_immediate_mode.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 lib)
+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_SOURCE_DIR}/pcap-config.in ${CMAKE_CURRENT_BINARY_DIR}/pcap-config @ONLY)
+    configure_file(${CMAKE_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_SOURCE_DIR}/${MANPAGE})
+    endforeach(MANPAGE)
+    install(FILES ${MAN1} DESTINATION ${CMAKE_INSTALL_MANDIR}/man1)
+
+    set(MAN3PCAP "")
+    foreach(MANPAGE ${MAN3PCAP_NOEXPAND})
+        set(MAN3PCAP ${MAN3PCAP} ${CMAKE_SOURCE_DIR}/${MANPAGE})
+    endforeach(MANPAGE)
+    foreach(TEMPLATE_MANPAGE ${MAN3PCAP_EXPAND})
+        string(REPLACE ".in" "" MANPAGE ${TEMPLATE_MANPAGE})
+        configure_file(${CMAKE_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_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_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
index 0000000..69b5972
--- /dev/null
+++ b/CONTRIBUTING.md
@@ -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 b40152f..8b7e7ce 100644
--- a/CREDITS
+++ b/CREDITS
@@ -1,21 +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>
+The current maintainers (in alphabetical order):
     Denis Ovsienko                <denis at ovsienko dot info>
-    Fulvio Risso                  <risso at polito dot it>
+    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>
-    Francois-Xavier Le Bail       <fx dot lebail at yahoo dot com>
 
-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>
@@ -62,9 +59,10 @@
     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>
@@ -99,6 +97,7 @@
     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>
@@ -114,6 +113,7 @@
     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>
@@ -129,7 +129,7 @@
     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                   <paolo dot abeni at email dot it> and 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>
@@ -145,6 +145,8 @@
     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>
@@ -167,6 +169,7 @@
     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>
@@ -176,5 +179,8 @@
     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/
diff --git a/GenVersion.bat b/GenVersion.bat
deleted file mode 100644
index babf373..0000000
--- a/GenVersion.bat
+++ /dev/null
@@ -1,23 +0,0 @@
-REM
-REM Automatically generate pcap_version.h based on pcap_version.h.in
-REM for Windows
-REM The version string comes from VERSION
-REM @echo off
-REM
-
-setlocal enableextensions disabledelayedexpansion
-
-set "search=%%%%LIBPCAP_VERSION%%%%"
-set /p replace=<%1
-
-if exist %3 del %3 2>nul
-
-for /f "delims=" %%i in ('type %2' ) do (
-	set "line=%%i"
-	setlocal enabledelayedexpansion
-	set "line=!line:%search%=%replace%!"
-	>>%3 echo(!line!
-	endlocal
-)
-
-echo pcap_version.h generated
diff --git a/INSTALL.txt b/INSTALL.md
similarity index 89%
rename from INSTALL.txt
rename to INSTALL.md
index f305aa2..96c87a2 100644
--- a/INSTALL.txt
+++ b/INSTALL.md
@@ -69,10 +69,6 @@
 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
@@ -250,43 +246,27 @@
 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 WinPcap)
 VERSION		- version of this release
 acconfig.h	- support for post-2.13 autoconf
 aclocal.m4	- autoconf macros
@@ -314,7 +294,6 @@
 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
@@ -347,6 +326,7 @@
 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
@@ -360,7 +340,6 @@
 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
diff --git a/METADATA b/METADATA
new file mode 100644
index 0000000..36f21c3
--- /dev/null
+++ b/METADATA
@@ -0,0 +1,18 @@
+name: "libpcap"
+description: "A system-independent interface for user-level packet capture."
+third_party {
+  url {
+    type: HOMEPAGE
+    value: "https://www.tcpdump.org/"
+  }
+  url {
+    type: ARCHIVE
+    value: "https://github.com/the-tcpdump-group/libpcap/archive/libpcap-1.9.0.tar.gz"
+  }
+  version: "libcap-1.9.0"
+  last_upgrade_date {
+    year: 2018
+    month: 7
+    day: 22
+  }
+}
diff --git a/Makefile.in b/Makefile.in
index e71d973..dff75ec 100644
--- a/Makefile.in
+++ b/Makefile.in
@@ -27,6 +27,8 @@
 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,8 +50,9 @@
 LN_S = @LN_S@
 MKDEP = @MKDEP@
 CCOPT = @V_CCOPT@
+SHLIB_CCOPT = @V_SHLIB_CCOPT@
 INCLS = -I. @V_INCLS@
-DEFS = -DBUILDING_PCAP @DEFS@ @V_DEFS@
+DEFS = -DBUILDING_PCAP -Dpcap_EXPORTS @DEFS@ @V_DEFS@
 ADDLOBJS = @ADDLOBJS@
 ADDLARCHIVEOBJS = @ADDLARCHIVEOBJS@
 LIBS = @LIBS@
@@ -60,9 +63,13 @@
 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) $(SHLIB_CCOPT) $(INCLS) $(DEFS) $(CFLAGS)
 
 INSTALL = @INSTALL@
 INSTALL_PROGRAM = @INSTALL_PROGRAM@
@@ -79,13 +86,14 @@
 	@rm -f $@
 	$(CC) $(FULL_CFLAGS) -c $(srcdir)/$*.c
 
-PSRC =	pcap-@V_PCAP@.c @USB_SRC@ @BT_SRC@ @BT_MONITOR_SRC@ @NETFILTER_SRC@ @DBUS_SRC@
+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 fad-helpers.c gencode.c optimize.c nametoaddr.c \
-	etherent.c savefile.c sf-pcap.c sf-pcap-ng.c pcap-common.c \
-	bpf_image.c bpf_dump.c
-GENSRC = scanner.c grammar.c bpf_filter.c version.c
+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)
@@ -100,8 +108,10 @@
 	pcap/bpf.h \
 	pcap/bluetooth.h \
 	pcap/can_socketcan.h \
+	pcap/compiler-tests.h \
 	pcap/dlt.h \
-	pcap/export-defs.h \
+	pcap/funcattrs.h \
+	pcap/pcap-inttypes.h \
 	pcap/ipnet.h \
 	pcap/namedb.h \
 	pcap/nflog.h \
@@ -113,51 +123,38 @@
 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 = \
-	@VALGRINDTEST@ \
-	capturetest \
-	can_set_rfmon_test \
-	filtertest \
-	findalldevstest \
-	opentest \
-	reactivatetest \
-	selpolltest
-
-TESTS_SRC = \
-	tests/valgrindtest.c \
-	tests/capturetest.c \
-	tests/can_set_rfmon_test.c \
-	tests/filtertest.c \
-	tests/findalldevstest.c \
-	tests/opentest.c \
-	tests/reactivatetest.c \
-	tests/selpolltest.c
+	sf-pcapng.h \
+	sunatmpos.h \
+	varattrs.h
 
 GENHDR = \
-	scanner.h grammar.h pcap_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
 
@@ -191,6 +188,7 @@
 	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 \
@@ -207,6 +205,7 @@
 	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 \
@@ -231,38 +230,31 @@
 	pcap-tstamp.manmisc.in
 
 EXTRA_DIST = \
-	$(TESTS_SRC) \
 	CHANGES \
 	ChmodBPF/ChmodBPF \
 	ChmodBPF/StartupParameters.plist \
 	CREDITS \
 	CMakeLists.txt \
-	GenVersion.bat \
-	INSTALL.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/preconfigure.cmake \
-	config/have_siocglifconf.c \
+	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 \
@@ -273,9 +265,6 @@
 	fad-getad.c \
 	fad-gifc.c \
 	fad-glifc.c \
-	fad-helpers.c \
-	gen_version_c.sh \
-	gen_version_header.sh \
 	grammar.y \
 	install-sh \
 	lbl/os-aix4.h \
@@ -286,6 +275,7 @@
 	lbl/os-solaris2.h \
 	lbl/os-sunos4.h \
 	lbl/os-ultrix4.h \
+	libpcap.pc.in \
 	missing/getopt.c \
 	missing/getopt.h \
 	missing/snprintf.c \
@@ -293,18 +283,15 @@
 	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 \
 	pcap-bpf.c \
 	pcap-bt-linux.c \
@@ -316,6 +303,7 @@
 	pcap-dag.h \
 	pcap-dbus.c \
 	pcap-dbus.h \
+	pcap-dll.rc \
 	pcap-dlpi.c \
 	pcap-dos.c \
 	pcap-dos.h \
@@ -327,11 +315,16 @@
 	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.h \
+	pcap-rpcap-int.h \
 	pcap-septel.c \
 	pcap-septel.h \
 	pcap-sita.h \
@@ -345,20 +338,48 @@
 	pcap-tc.h \
 	pcap-usb-linux.c \
 	pcap-usb-linux.h \
-	pcap-win32.c \
-	remote-ext.h \
+	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-stderr.c \
+	rpcapd/org.tcpdump.rpcapd.plist \
+	rpcapd/rpcapd.c \
+	rpcapd/rpcapd.h \
+	rpcapd/rpcapd.inetd.conf \
+	rpcapd/rpcapd.manadmin.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 \
-	tests/CMakeLists.txt \
-	pcap_version.h.in \
-	Win32/Include/Gnuc.h \
-	Win32/Include/net/if.h \
+	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 pcap-config
+all: libpcap.a shared $(BUILD_RPCAPD) libpcap.pc pcap-config
 
 libpcap.a: $(OBJ)
 	@rm -f $@
@@ -371,20 +392,18 @@
 	@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
@@ -434,7 +453,7 @@
 #
 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
 
 #
@@ -455,8 +474,6 @@
 scanner.o: scanner.c grammar.h
 	$(CC) $(FULL_CFLAGS) -c scanner.c
 
-pcap.o: pcap_version.h
-
 grammar.c: $(srcdir)/grammar.y
 	$(YACC) -p pcap_ -o grammar.c -d $<
 grammar.h: grammar.c
@@ -466,43 +483,20 @@
 		$(MAKE) $(MAKEFLAGS) grammar.c; \
 	fi
 
-grammar.o: grammar.c
+grammar.o: grammar.c scanner.h
 	$(CC) $(FULL_CFLAGS) -c grammar.c
 
 gencode.o: $(srcdir)/gencode.c grammar.h scanner.h
 	$(CC) $(FULL_CFLAGS) -c $(srcdir)/gencode.c
 
-version.o: version.c
-	$(CC) $(FULL_CFLAGS) -c version.c
-
 snprintf.o: $(srcdir)/missing/snprintf.c
 	$(CC) $(FULL_CFLAGS) -o $@ -c $(srcdir)/missing/snprintf.c
 
 strtok_r.o: $(srcdir)/missing/strtok_r.c
 	$(CC) $(FULL_CFLAGS) -o $@ -c $(srcdir)/missing/strtok_r.c
 
-version.c: $(srcdir)/VERSION $(srcdir)/gen_version_c.sh
-	#
-	# Older programs import this if they want to show the
-	# libpcap version number, rather than calling
-	# pcap_lib_version(), so we need to export it.
-	#
-	@rm -f $@
-	$(srcdir)/gen_version_c.sh $(srcdir)/VERSION $@
-
-pcap_version.h: $(srcdir)/VERSION $(srcdir)/pcap_version.h.in $(srcdir)/gen_version_header.sh
-	@rm -f $@
-	$(srcdir)/gen_version_header.sh $(srcdir)/VERSION $(srcdir)/pcap_version.h.in $@
-
-bpf_filter.c: $(srcdir)/bpf/net/bpf_filter.c
-	rm -f bpf_filter.c
-	ln -s $(srcdir)/bpf/net/bpf_filter.c bpf_filter.c
-
-bpf_filter.o: bpf_filter.c
-	$(CC) $(FULL_CFLAGS) -c bpf_filter.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
@@ -513,7 +507,16 @@
 #
 # 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
@@ -522,35 +525,20 @@
 	chmod a+x $@
 
 #
+# Remote pcap daemon.
+#
+build-rpcapd: libpcap.a
+	cd rpcapd; $(MAKE)
+
+#
 # Test programs - not built by default, and not installed.
 #
-tests: $(TESTS)
+testprogs: FORCE
+	cd testprogs; $(MAKE)
 
-capturetest: tests/capturetest.c libpcap.a
-	$(CC) $(FULL_CFLAGS) -I. -L. -o capturetest $(srcdir)/tests/capturetest.c libpcap.a $(LIBS)
+FORCE:
 
-can_set_rfmon_test: tests/can_set_rfmon_test.c libpcap.a
-	$(CC) $(FULL_CFLAGS) -I. -L. -o can_set_rfmon_test $(srcdir)/tests/can_set_rfmon_test.c libpcap.a $(LIBS)
-
-filtertest: tests/filtertest.c libpcap.a
-	$(CC) $(FULL_CFLAGS) -I. -L. -o filtertest $(srcdir)/tests/filtertest.c libpcap.a $(LIBS)
-
-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)
-
-reactivatetest: tests/reactivatetest.c libpcap.a
-	$(CC) $(FULL_CFLAGS) -I. -L. -o reactivatetest $(srcdir)/tests/reactivatetest.c libpcap.a $(LIBS)
-
-selpolltest: tests/selpolltest.c libpcap.a
-	$(CC) $(FULL_CFLAGS) -I. -L. -o selpolltest $(srcdir)/tests/selpolltest.c libpcap.a $(LIBS)
-
-valgrindtest: tests/valgrindtest.c libpcap.a
-	$(CC) $(FULL_CFLAGS) -I. -L. -o valgrindtest $(srcdir)/tests/valgrindtest.c libpcap.a $(LIBS)
-
-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) ] || \
@@ -571,6 +559,9 @@
 	[ -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
@@ -671,11 +662,15 @@
 	# 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
@@ -723,15 +718,22 @@
 	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)
@@ -742,11 +744,13 @@
 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 b/README.md
similarity index 61%
rename from README
rename to README.md
index 9f65948..78cc3c4 100644
--- a/README
+++ b/README.md
@@ -1,18 +1,18 @@
+To report a security issue please send an e-mail to security@tcpdump.org.
+
+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.
+
+The directory doc/ has README files about specific operating systems and
+options.
+
 LIBPCAP 1.x.y
-
-www.tcpdump.org
-
-Please send inquiries/comments/reports to:
-	tcpdump-workers@lists.tcpdump.org
+Now maintained by "The Tcpdump Group"
+https://www.tcpdump.org
 
 Anonymous Git is available via:
-	git clone git://bpf.tcpdump.org/libpcap
-
-Please submit patches by forking the branch on GitHub at
-
-	http://github.com/the-tcpdump-group/libpcap/tree/master
-
-and issuing a pull request.
+        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 @@
 
 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,17 +62,18 @@
 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:
 
@@ -87,20 +88,6 @@
 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
+Current versions can be found at https://www.tcpdump.org.
 
-	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.
-
- - The TCPdump team
+ - The TCPdump group
diff --git a/README.version b/README.version
deleted file mode 100644
index 256063e..0000000
--- a/README.version
+++ /dev/null
@@ -1,2 +0,0 @@
-URL: http://www.tcpdump.org/release/libpcap-1.8.1.tar.gz
-Version: 1.8.1
diff --git a/SUNOS4/nit_if.o.sparc b/SUNOS4/nit_if.o.sparc
deleted file mode 100644
index d05073e..0000000
--- a/SUNOS4/nit_if.o.sparc
+++ /dev/null
Binary files differ
diff --git a/SUNOS4/nit_if.o.sun3 b/SUNOS4/nit_if.o.sun3
deleted file mode 100644
index c393fc6..0000000
--- a/SUNOS4/nit_if.o.sun3
+++ /dev/null
Binary files 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
index ef01039..0000000
--- a/SUNOS4/nit_if.o.sun4c.4.0.3c
+++ /dev/null
Binary files differ
diff --git a/VERSION b/VERSION
index a8fdfda..f8e233b 100644
--- a/VERSION
+++ b/VERSION
@@ -1 +1 @@
-1.8.1
+1.9.0
diff --git a/Win32/Include/Gnuc.h b/Win32/Include/Gnuc.h
deleted file mode 100644
index e1b5951..0000000
--- a/Win32/Include/Gnuc.h
+++ /dev/null
@@ -1,8 +0,0 @@
-/* inline foo */
-#ifndef __cplusplus
-#ifdef __GNUC__
-#define inline __inline
-#else
-#define inline
-#endif
-#endif
diff --git a/Win32/Include/net/if.h b/Win32/Include/net/if.h
deleted file mode 100644
index 58d3c16..0000000
--- a/Win32/Include/net/if.h
+++ /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/Prj/wpcap.vcxproj b/Win32/Prj/wpcap.vcxproj
index c923357..43b7099 100644
--- a/Win32/Prj/wpcap.vcxproj
+++ b/Win32/Prj/wpcap.vcxproj
@@ -100,7 +100,7 @@
       <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;BUILDING_PCAP;HAVE_STRERROR;__STDC__;INET6;_WINDOWS;HAVE_ADDRINFO;HAVE_REMOTE;WIN32;_U_=;YY_NO_UNISTD_H;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+      <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>
@@ -125,7 +125,7 @@
       <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;BUILDING_PCAP;HAVE_STRERROR;__STDC__;INET6;_WINDOWS;HAVE_ADDRINFO;HAVE_REMOTE;WIN32;_U_=;YY_NO_UNISTD_H;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+      <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>
@@ -151,7 +151,7 @@
       <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;BUILDING_PCAP;HAVE_STRERROR;__STDC__;INET6;_WINDOWS;HAVE_ADDRINFO;HAVE_REMOTE;WIN32;_U_=;YY_NO_UNISTD_H;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+      <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>
@@ -177,7 +177,7 @@
       <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;BUILDING_PCAP;HAVE_STRERROR;__STDC__;INET6;_WINDOWS;HAVE_ADDRINFO;HAVE_REMOTE;WIN32;_U_=;YY_NO_UNISTD_H;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+      <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>
@@ -198,7 +198,6 @@
     <ClCompile Include="..\..\bpf_dump.c" />
     <ClCompile Include="..\..\bpf_image.c" />
     <ClCompile Include="..\..\etherent.c" />
-    <ClCompile Include="..\..\fad-helpers.c" />
     <ClCompile Include="..\..\gencode.c" />
     <ClCompile Include="..\..\grammar.c" />
     <ClCompile Include="..\..\inet.c" />
@@ -212,7 +211,7 @@
     <ClCompile Include="..\..\pcap.c" />
     <ClCompile Include="..\..\savefile.c" />
     <ClCompile Include="..\..\scanner.c" />
-    <ClCompile Include="..\..\sf-pcap-ng.c" />
+    <ClCompile Include="..\..\sf-pcapng.c" />
     <ClCompile Include="..\..\sf-pcap.c" />
     <ClCompile Include="..\..\sockutils.c" />
   </ItemGroup>
@@ -231,4 +230,4 @@
   <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
   <ImportGroup Label="ExtensionTargets">
   </ImportGroup>
-</Project>
\ No newline at end of file
+</Project>
diff --git a/Win32/Prj/wpcap.vcxproj.filters b/Win32/Prj/wpcap.vcxproj.filters
index 72f1492..6e06ccb 100644
--- a/Win32/Prj/wpcap.vcxproj.filters
+++ b/Win32/Prj/wpcap.vcxproj.filters
@@ -43,7 +43,7 @@
     <ClCompile Include="..\..\sf-pcap.c">
       <Filter>Source Files</Filter>
     </ClCompile>
-    <ClCompile Include="..\..\sf-pcap-ng.c">
+    <ClCompile Include="..\..\sf-pcapng.c">
       <Filter>Source Files</Filter>
     </ClCompile>
     <ClCompile Include="..\..\pcap-common.c">
diff --git a/aclocal.m4 b/aclocal.m4
index 83f5761..ac163d4 100644
--- a/aclocal.m4
+++ b/aclocal.m4
@@ -266,6 +266,14 @@
 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])
@@ -287,8 +295,38 @@
 	    [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])
@@ -384,8 +422,7 @@
 	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'
@@ -395,7 +432,7 @@
 			# We can't run mkdep, so have "make depend" do
 			# nothing.
 			#
-			MKDEP=:
+			MKDEP='${srcdir}/nomkdep'
 		fi
 		rm -rf conftest*
 	else
@@ -404,7 +441,7 @@
 		# We can't run mkdep, so have "make depend" do
 		# nothing.
 		#
-		MKDEP=:
+		MKDEP='${srcdir}/nomkdep'
 	fi
 	AC_SUBST(DEPENDENCY_CFLAG)
 	AC_SUBST(MKDEP)
@@ -419,7 +456,7 @@
 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
@@ -432,7 +469,7 @@
 	    # 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;
@@ -470,13 +507,13 @@
 			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"
@@ -492,7 +529,7 @@
 		    ;;
 
 	    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.
@@ -507,7 +544,7 @@
 	    # 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;
@@ -533,7 +570,7 @@
 		    #
 		    # "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,"
@@ -541,7 +578,7 @@
 		    ;;
 
 	    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 "
@@ -564,7 +601,7 @@
 		    ;;
 
 	    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 "
@@ -691,90 +728,6 @@
     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:
@@ -932,6 +885,50 @@
 		    AC_LBL_CHECK_COMPILER_OPT($1, -Wshadow)
 		    AC_LBL_CHECK_COMPILER_OPT($1, -Wdeclaration-after-statement)
 		    AC_LBL_CHECK_COMPILER_OPT($1, -Wused-but-marked-unused)
+		    AC_LBL_CHECK_COMPILER_OPT($1, -Wdocumentation)
+		    AC_LBL_CHECK_COMPILER_OPT($1, -Wcomma)
+		    AC_LBL_CHECK_COMPILER_OPT($1, -Wmissing-noreturn)
+		    # Warns about safeguards added in case the enums are
+		    # extended
+		    # AC_LBL_CHECK_COMPILER_OPT($1, -Wcovered-switch-default)
+		    AC_LBL_CHECK_COMPILER_OPT($1, -Wmissing-variable-declarations)
+		    AC_LBL_CHECK_COMPILER_OPT($1, -Wunused-parameter)
+		    AC_LBL_CHECK_COMPILER_OPT($1, -Wformat-nonliteral)
+		    #
+		    # 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()
 	    #
@@ -1020,234 +1017,62 @@
 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 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
-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 On most operating systems, they're available in the system library.
 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 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
-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 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 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))
+    #
+    # 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)
+
+	#
+	# 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 Test for __attribute__
-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
-
-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)
-])
-
-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])
diff --git a/bpf_dump.c b/bpf_dump.c
index d5ab61e..a9c9116 100644
--- a/bpf_dump.c
+++ b/bpf_dump.c
@@ -20,12 +20,14 @@
  */
 
 #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,7 @@
 	}
 	for (i = 0; i < n; ++insn, ++i) {
 #ifdef BDEBUG
-		extern int bids[];
-		if (bids[i] > 0)
+		if (i < NBIDS && bids[i] > 0)
 			printf("[%02d]", bids[i] - 1);
 		else
 			printf(" -- ");
diff --git a/bpf_filter.c b/bpf_filter.c
deleted file mode 120000
index 0605488..0000000
--- a/bpf_filter.c
+++ /dev/null
@@ -1 +0,0 @@
-./bpf/net/bpf_filter.c
\ No newline at end of file
diff --git a/bpf/net/bpf_filter.c b/bpf_filter.c
similarity index 68%
rename from bpf/net/bpf_filter.c
rename to bpf_filter.c
index 01a1b64..615ed3f 100644
--- a/bpf/net/bpf_filter.c
+++ b/bpf_filter.c
@@ -39,47 +39,21 @@
  */
 
 #ifdef HAVE_CONFIG_H
-#include "config.h"
+#include <config.h>
 #endif
 
-#ifdef _WIN32
+#include <pcap/pcap-inttypes.h>
+#include "pcap-types.h"
 
-#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
-
+#ifndef _WIN32
 #include <sys/param.h>
 #include <sys/types.h>
 #include <sys/time.h>
-
-#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/bpf.h>
 
-#if !defined(KERNEL) && !defined(_KERNEL)
 #include <stdlib.h>
-#endif
 
 #define int32 bpf_int32
 #define u_int32 bpf_u_int32
@@ -117,84 +91,6 @@
 		 (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;
-}
-#endif
-
 #ifdef __linux__
 #include <linux/types.h>
 #include <linux/if_packet.h>
@@ -220,27 +116,12 @@
  * Thanks to Ani Sinha <ani@arista.com> for providing initial implementation
  */
 u_int
-bpf_filter_with_aux_data(pc, p, wirelen, buflen, aux_data)
-	register const struct bpf_insn *pc;
-	register const u_char *p;
-	u_int wirelen;
-	register u_int buflen;
-	register const struct bpf_aux_data *aux_data;
+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 bpf_u_int32 k;
 	u_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
 
 	if (pc == 0)
 		/*
@@ -250,16 +131,12 @@
 	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;
 
@@ -269,16 +146,7 @@
 		case BPF_LD|BPF_W|BPF_ABS:
 			k = pc->k;
 			if (k > buflen || sizeof(int32_t) > buflen - k) {
-#if defined(KERNEL) || defined(_KERNEL)
-				if (m == NULL)
-					return 0;
-				A = m_xword(m, k, &merr);
-				if (merr != 0)
-					return 0;
-				continue;
-#else
 				return 0;
-#endif
 			}
 			A = EXTRACT_LONG(&p[k]);
 			continue;
@@ -286,65 +154,37 @@
 		case BPF_LD|BPF_H|BPF_ABS:
 			k = pc->k;
 			if (k > buflen || sizeof(int16_t) > buflen - k) {
-#if defined(KERNEL) || defined(_KERNEL)
-				if (m == NULL)
-					return 0;
-				A = m_xhalf(m, k, &merr);
-				if (merr != 0)
-					return 0;
-				continue;
-#else
 				return 0;
-#endif
 			}
 			A = EXTRACT_SHORT(&p[k]);
 			continue;
 
 		case BPF_LD|BPF_B|BPF_ABS:
-			{
-#if defined(SKF_AD_VLAN_TAG) && defined(SKF_AD_VLAN_TAG_PRESENT)
-				int code = BPF_S_ANC_NONE;
-#define ANCILLARY(CODE) case SKF_AD_OFF + SKF_AD_##CODE:		\
-				code = BPF_S_ANC_##CODE;		\
-                                        if (!aux_data)                  \
-                                                return 0;               \
-                                        break;
+			switch (pc->k) {
 
-				switch (pc->k) {
-					ANCILLARY(VLAN_TAG);
-					ANCILLARY(VLAN_TAG_PRESENT);
-				default :
-#endif
-					k = pc->k;
-					if (k >= buflen) {
-#if defined(KERNEL) || defined(_KERNEL)
-						if (m == NULL)
-							return 0;
-						n = m;
-						MINDEX(len, n, k);
-						A = mtod(n, u_char *)[k];
-						continue;
-#else
-						return 0;
-#endif
-					}
-					A = p[k];
-#if defined(SKF_AD_VLAN_TAG) && defined(SKF_AD_VLAN_TAG_PRESENT)
-				}
-				switch (code) {
-				case BPF_S_ANC_VLAN_TAG:
-					if (aux_data)
-						A = aux_data->vlan_tag;
-					break;
+#if defined(SKF_AD_VLAN_TAG_PRESENT)
+			case SKF_AD_OFF + SKF_AD_VLAN_TAG:
+				if (!aux_data)
+					return 0;
+				A = aux_data->vlan_tag;
+				break;
 
-				case BPF_S_ANC_VLAN_TAG_PRESENT:
-					if (aux_data)
-						A = aux_data->vlan_tag_present;
-					break;
-				}
+			case SKF_AD_OFF + SKF_AD_VLAN_TAG_PRESENT:
+				if (!aux_data)
+					return 0;
+				A = aux_data->vlan_tag_present;
+				break;
 #endif
-				continue;
+			default:
+				k = pc->k;
+				if (k >= buflen) {
+					return 0;
+				}
+				A = p[k];
+				break;
 			}
+			continue;
+
 		case BPF_LD|BPF_W|BPF_LEN:
 			A = wirelen;
 			continue;
@@ -357,16 +197,7 @@
 			k = X + pc->k;
 			if (pc->k > buflen || X > buflen - pc->k ||
 			    sizeof(int32_t) > buflen - k) {
-#if defined(KERNEL) || defined(_KERNEL)
-				if (m == NULL)
-					return 0;
-				A = m_xword(m, k, &merr);
-				if (merr != 0)
-					return 0;
-				continue;
-#else
 				return 0;
-#endif
 			}
 			A = EXTRACT_LONG(&p[k]);
 			continue;
@@ -375,16 +206,7 @@
 			k = X + pc->k;
 			if (X > buflen || pc->k > buflen - X ||
 			    sizeof(int16_t) > buflen - k) {
-#if defined(KERNEL) || defined(_KERNEL)
-				if (m == NULL)
-					return 0;
-				A = m_xhalf(m, k, &merr);
-				if (merr != 0)
-					return 0;
-				continue;
-#else
 				return 0;
-#endif
 			}
 			A = EXTRACT_SHORT(&p[k]);
 			continue;
@@ -392,16 +214,7 @@
 		case BPF_LD|BPF_B|BPF_IND:
 			k = X + pc->k;
 			if (pc->k >= buflen || X >= buflen - pc->k) {
-#if defined(KERNEL) || defined(_KERNEL)
-				if (m == NULL)
-					return 0;
-				n = m;
-				MINDEX(len, n, k);
-				A = mtod(n, u_char *)[k];
-				continue;
-#else
 				return 0;
-#endif
 			}
 			A = p[k];
 			continue;
@@ -409,16 +222,7 @@
 		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;
@@ -448,18 +252,11 @@
 			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:
@@ -599,11 +396,8 @@
 }
 
 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(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);
 }
@@ -621,22 +415,13 @@
  * 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 < (u_int)len; ++i) {
 		p = &f[i];
@@ -657,14 +442,6 @@
 				 * 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)
@@ -736,11 +513,7 @@
 			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 >= (u_int)len)
-#endif
 					return 0;
 				break;
 			case BPF_JEQ:
diff --git a/bpf_image.c b/bpf_image.c
index 01ec536..ab41d1e 100644
--- a/bpf_image.c
+++ b/bpf_image.c
@@ -20,22 +20,10 @@
  */
 
 #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>
@@ -47,266 +35,290 @@
 #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)pcap_snprintf(operand, sizeof operand, fmt, v);
 	if (BPF_CLASS(p->code) == BPF_JMP && BPF_OP(p->code) != BPF_JA) {
 		(void)pcap_snprintf(image, sizeof image,
 			      "(%03d) %-8s %-16s jt %d\tjf %d",
diff --git a/chmod_bpf b/chmod_bpf
index 0a30d99..946fec3 100755
--- 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
index 0000000..ef13528
--- /dev/null
+++ b/cmake/Modules/FindDAG.cmake
@@ -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
index 0000000..ca53a5a
--- /dev/null
+++ b/cmake/Modules/FindFseeko.cmake
@@ -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
index 0000000..be5f0d4
--- /dev/null
+++ b/cmake/Modules/FindLFS.cmake
@@ -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
index 0000000..1311cdb
--- /dev/null
+++ b/cmake/Modules/FindPacket.cmake
@@ -0,0 +1,81 @@
+#
+# 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
+set(64BIT_SUBDIR "")
+if(CMAKE_SIZEOF_VOID_P EQUAL 8)
+  set(64BIT_SUBDIR "/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
+  PATH_SUFFIXES Lib${64BIT_SUBDIR} lib${64BIT_SUBDIR}
+)
+
+# 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
index 0000000..76dcced
--- /dev/null
+++ b/cmake/Modules/FindSNF.cmake
@@ -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
index 0000000..bb24c66
--- /dev/null
+++ b/cmake/Modules/FindTC.cmake
@@ -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/config/have_siocglifconf.c b/cmake/have_siocglifconf.c
similarity index 100%
rename from config/have_siocglifconf.c
rename to cmake/have_siocglifconf.c
diff --git a/cmake/preconfigure.cmake b/cmake/preconfigure.cmake
deleted file mode 100644
index c8c92a4..0000000
--- a/cmake/preconfigure.cmake
+++ /dev/null
@@ -1,55 +0,0 @@
-if( NOT LIBPCAP_PRECONFIGURED )
-    set( LIBPCAP_PRECONFIGURED TRUE )
-
-    ###################################################################
-    #   Parameters
-    ###################################################################
-
-    option (USE_STATIC_RT "Use static Runtime" ON)
-
-    ######################################
-    # Project setings
-    ######################################
-
-    add_definitions( -DBUILDING_PCAP )
-
-    if( MSVC )
-        add_definitions( -D__STDC__ )
-        add_definitions( -D_CRT_SECURE_NO_WARNINGS )
-        add_definitions( "-D_U_=" )
-    elseif( CMAKE_COMPILER_IS_GNUCXX )
-        add_definitions( "-D_U_=__attribute__((unused))" )
-    else(MSVC)
-        add_definitions( "-D_U_=" )
-    endif( MSVC )
-
-    if (USE_STATIC_RT)
-        MESSAGE( STATUS "Use STATIC runtime" )
-
-        if( MSVC )
-            set (CMAKE_CXX_FLAGS_MINSIZEREL     "${CMAKE_CXX_FLAGS_MINSIZEREL} /MT")
-            set (CMAKE_CXX_FLAGS_RELWITHDEBINFO "${CMAKE_CXX_FLAGS_RELWITHDEBINFO} /MT")
-            set (CMAKE_CXX_FLAGS_RELEASE        "${CMAKE_CXX_FLAGS_RELEASE} /MT")
-            set (CMAKE_CXX_FLAGS_DEBUG          "${CMAKE_CXX_FLAGS_DEBUG} /MTd")
-
-            set (CMAKE_C_FLAGS_MINSIZEREL       "${CMAKE_C_FLAGS_MINSIZEREL} /MT")
-            set (CMAKE_C_FLAGS_RELWITHDEBINFO   "${CMAKE_C_FLAGS_RELWITHDEBINFO} /MT")
-            set (CMAKE_C_FLAGS_RELEASE          "${CMAKE_C_FLAGS_RELEASE} /MT")
-            set (CMAKE_C_FLAGS_DEBUG            "${CMAKE_C_FLAGS_DEBUG} /MTd")
-        endif( MSVC )
-    else (USE_STATIC_RT)
-        MESSAGE( STATUS "Use DYNAMIC runtime" )
-
-        if( MSVC )
-            set (CMAKE_CXX_FLAGS_MINSIZEREL     "${CMAKE_CXX_FLAGS_MINSIZEREL} /MD")
-            set (CMAKE_CXX_FLAGS_RELWITHDEBINFO "${CMAKE_CXX_FLAGS_RELWITHDEBINFO} /MD")
-            set (CMAKE_CXX_FLAGS_RELEASE        "${CMAKE_CXX_FLAGS_RELEASE} /MD")
-            set (CMAKE_CXX_FLAGS_DEBUG          "${CMAKE_CXX_FLAGS_DEBUG} /MDd")
-
-            set (CMAKE_C_FLAGS_MINSIZEREL       "${CMAKE_C_FLAGS_MINSIZEREL} /MD")
-            set (CMAKE_C_FLAGS_RELWITHDEBINFO   "${CMAKE_C_FLAGS_RELWITHDEBINFO} /MD")
-            set (CMAKE_C_FLAGS_RELEASE          "${CMAKE_C_FLAGS_RELEASE} /MD")
-            set (CMAKE_C_FLAGS_DEBUG            "${CMAKE_C_FLAGS_DEBUG} /MDd")
-        endif( MSVC )
-    endif (USE_STATIC_RT)
-endif( NOT LIBPCAP_PRECONFIGURED )
diff --git a/cmake_uninstall.cmake.in b/cmake_uninstall.cmake.in
new file mode 100644
index 0000000..2037e36
--- /dev/null
+++ b/cmake_uninstall.cmake.in
@@ -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
index 94edb5f..6760cec 100644
--- a/cmakeconfig.h.in
+++ b/cmakeconfig.h.in
@@ -1,10 +1,19 @@
 /* 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 if you have a cloning BPF device */
-#cmakedefine HAVE_CLONING_BPF 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 if you have the DAG API */
 #cmakedefine HAVE_DAG_API 1
@@ -15,21 +24,20 @@
 /* define if you have dag_get_stream_erf_types() */
 #cmakedefine HAVE_DAG_GET_STREAM_ERF_TYPES 1
 
-/* define if you have streams capable DAG API */
-#cmakedefine HAVE_DAG_STREAMS_API 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', and to 0 if you
-   don't. */
+/* Define to 1 if you have the declaration of `ether_hostton' */
 #cmakedefine HAVE_DECL_ETHER_HOSTTON 1
 
-/* define if you have a /dev/dlpi */
-#cmakedefine HAVE_DEV_DLPI 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
 
-/* if passive_req_t primitive exists */
-#cmakedefine HAVE_DLPI_PASSIVE 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
@@ -37,15 +45,15 @@
 /* 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
+
 /* on HP-UX 10.20 or later */
 #cmakedefine HAVE_HPUX10_20_OR_LATER 1
 
 /* on HP-UX 9.x */
 #cmakedefine HAVE_HPUX9 1
 
-/* if ppa_info_t_dl_module_id exists */
-#cmakedefine HAVE_HP_PPA_INFO_T_DL_MODULE_ID_1 1
-
 /* Define to 1 if you have the <inttypes.h> header file. */
 #cmakedefine HAVE_INTTYPES_H 1
 
@@ -76,24 +84,24 @@
 /* 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/if_packet.h> header file. */
-#cmakedefine HAVE_LINUX_IF_PACKET_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
 
-/* if tp_vlan_tci exists */
-#cmakedefine HAVE_LINUX_TPACKET_AUXDATA_TP_VLAN_TCI 1
-
-/* Define to 1 if you have the <linux/types.h> header file. */
-#cmakedefine HAVE_LINUX_TYPES_H 1
-
 /* Define to 1 if you have the <linux/usbdevice_fs.h> header file. */
 #cmakedefine HAVE_LINUX_USBDEVICE_FS_H 1
 
@@ -103,32 +111,35 @@
 /* Define to 1 if you have the <memory.h> header file. */
 #cmakedefine HAVE_MEMORY_H 1
 
-/* Define to 1 if you have the <netinet/ether.h> header file. */
-#cmakedefine HAVE_NETINET_ETHER_H 1
-
-/* Define to 1 if you have the <netinet/if_ether.h> header file. */
-#cmakedefine HAVE_NETINET_IF_ETHER_H 1
-
-/* Define to 1 if you have the <netpacket/if_packet.h> header file. */
-#cmakedefine HAVE_NETPACKET_IF_PACKET_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 remote packet capture is to be supported */
-#cmakedefine HAVE_REMOTE 1
-
-/* Define to 1 if you have the <paths.h> header file. */
-#cmakedefine HAVE_PATHS_H 1
+/* Define to 1 if Packet32 API (WinPcap NPF driver) is available */
+#cmakedefine HAVE_PACKET32 1
 
 /* define if net/pfvar.h defines PF_NAT through PF_NORDR */
 #cmakedefine HAVE_PF_NAT_THROUGH_PF_NORDR 1
@@ -142,18 +153,18 @@
 /* Define to 1 if you have the `snprintf' function. */
 #cmakedefine HAVE_SNPRINTF 1
 
-/* if struct sockaddr has the sa_len member */
-#cmakedefine HAVE_SOCKADDR_SA_LEN 1
-
-/* if struct sockaddr_storage exists */
-#cmakedefine HAVE_SOCKADDR_STORAGE 1
-
-/* define if socklen_t is defined */
+/* 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
 
@@ -163,17 +174,57 @@
 /* Define to 1 if you have the `strerror' function. */
 #cmakedefine HAVE_STRERROR 1
 
+/* Define to 1 if you have the `strerror_r' function. */
+#cmakedefine HAVE_STRERROR_R 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 you have the <sys/bitypes.h> header file. */
-#cmakedefine HAVE_SYS_BITYPES_H 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
@@ -181,9 +232,15 @@
 /* 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
 
@@ -196,27 +253,15 @@
 /* define if you have the TurboCap API */
 #cmakedefine HAVE_TC_API 1
 
-/* if if_packet.h has tpacket_stats defined */
-#cmakedefine HAVE_TPACKET_STATS 1
-
 /* Define to 1 if you have the <unistd.h> header file. */
 #cmakedefine HAVE_UNISTD_H 1
 
-/* if struct usbdevfs_ctrltransfer has bRequestType */
-#cmakedefine HAVE_USBDEVFS_CTRLTRANSFER_BREQUESTTYPE 1
-
 /* Define to 1 if you have the `vsnprintf' function. */
 #cmakedefine HAVE_VSNPRINTF 1
 
 /* Define to 1 if you have the `PacketIsLoopbackAdapter' function. */
 #cmakedefine HAVE_PACKET_IS_LOOPBACK_ADAPTER 1
 
-/* define if the system supports zerocopy BPF */
-#cmakedefine HAVE_ZEROCOPY_BPF 1
-
-/* define if your compiler has __attribute__ */
-#cmakedefine HAVE___ATTRIBUTE__ 1
-
 /* IPv6 */
 #cmakedefine INET6 1
 
@@ -224,10 +269,7 @@
 #cmakedefine LBL_ALIGN 1
 
 /* path for device for USB sniffing */
-#cmakedefine LINUX_USB_MON_DEV 1
-
-/* if we need a pcap_parse wrapper around yyparse */
-#cmakedefine NEED_YYPARSE_WRAPPER 1
+#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
@@ -235,17 +277,23 @@
 /* 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 1
+#cmakedefine PACKAGE_NAME "@PACKAGE_NAME@"
 
 /* Define to the full name and version of this package. */
-#cmakedefine PACKAGE_STRING 1
+#cmakedefine PACKAGE_STRING "@PACKAGE_STRING@"
 
 /* Define to the one symbol short name of this package. */
 #cmakedefine PACKAGE_TARNAME 1
@@ -254,10 +302,7 @@
 #cmakedefine PACKAGE_URL 1
 
 /* Define to the version of this package. */
-#cmakedefine PACKAGE_VERSION 1
-
-/* /dev/dlpi directory */
-#cmakedefine PCAP_DEV_PREFIX 1
+#cmakedefine PACKAGE_VERSION "@PACKAGE_VERSION@"
 
 /* target host supports Bluetooth sniffing */
 #cmakedefine PCAP_SUPPORT_BT 1
@@ -271,21 +316,30 @@
 /* target host supports netfilter sniffing */
 #cmakedefine PCAP_SUPPORT_NETFILTER 1
 
-/* use Linux packet ring capture if available */
+/* 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
 
-/* if struct sockaddr_hci has hci_channel member */
-#cmakedefine SOCKADDR_HCI_HAS_HCI_CHANNEL 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
 
@@ -306,40 +360,7 @@
 /* define on AIX to get certain functions */
 #cmakedefine _SUN 1
 
-/* define if your compiler allows __attribute__((format)) without a warning */
-#cmakedefine __ATTRIBUTE___FORMAT_OK 1
-
 #if 0
-/* to handle Ultrix compilers that don't support const in prototypes */
-#cmakedefine const 1
-
-/* Define as token for inline if inlining supported */
-#cmakedefine inline 1
-
-/* Define to `short' if int16_t not defined. */
-#cmakedefine int16_t 1
-
-/* Define to `int' if int32_t not defined. */
-#cmakedefine int32_t 1
-
-/* Define to `long long' if int64_t not defined. */
-#cmakedefine int64_t 1
-
-/* Define to `signed char' if int8_t not defined. */
-#cmakedefine int8_t 1
-
 /* on sinix */
 #cmakedefine sinix 1
-
-/* Define to `unsigned short' if u_int16_t not defined. */
-#cmakedefine u_int16_t 1
-
-/* Define to `unsigned int' if u_int32_t not defined. */
-#cmakedefine u_int32_t 1
-
-/* Define to `unsigned long long' if u_int64_t not defined. */
-#cmakedefine u_int64_t 1
-
-/* Define to `unsigned char' if u_int8_t not defined. */
-#cmakedefine u_int8_t 1
 #endif
diff --git a/config.guess b/config.guess
old mode 100644
new mode 100755
index 44290b8..2b79f6d
--- a/config.guess
+++ b/config.guess
@@ -1,8 +1,8 @@
 #! /bin/sh
 # Attempt to guess a canonical system name.
-#   Copyright 1992-2015 Free Software Foundation, Inc.
+#   Copyright 1992-2018 Free Software Foundation, Inc.
 
-timestamp='2015-02-23'
+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
@@ -15,7 +15,7 @@
 # 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
@@ -27,7 +27,7 @@
 # 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>.
 
@@ -39,7 +39,7 @@
 
 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
@@ -50,7 +50,7 @@
 GNU config.guess ($timestamp)
 
 Originally written by Per Bothner.
-Copyright 1992-2015 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."
@@ -101,15 +101,15 @@
 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 ;
@@ -132,14 +132,14 @@
 UNAME_SYSTEM=`(uname -s) 2>/dev/null`  || UNAME_SYSTEM=unknown
 UNAME_VERSION=`(uname -v) 2>/dev/null` || UNAME_VERSION=unknown
 
-case "${UNAME_SYSTEM}" in
+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
+	eval "$set_cc_for_build"
+	cat <<-EOF > "$dummy.c"
 	#include <features.h>
 	#if defined(__UCLIBC__)
 	LIBC=uclibc
@@ -149,13 +149,20 @@
 	LIBC=gnu
 	#endif
 	EOF
-	eval `$CC_FOR_BUILD -E $dummy.c 2>/dev/null | grep '^LIBC' | sed 's, ,,g'`
+	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*,
@@ -169,27 +176,30 @@
 	# portion of the name.  We always set it to "unknown".
 	sysctl="sysctl -n hw.machine_arch"
 	UNAME_MACHINE_ARCH=`(uname -p 2>/dev/null || \
-	    /sbin/$sysctl 2>/dev/null || \
-	    /usr/sbin/$sysctl 2>/dev/null || \
+	    "/sbin/$sysctl" 2>/dev/null || \
+	    "/usr/sbin/$sysctl" 2>/dev/null || \
 	    echo unknown)`
-	case "${UNAME_MACHINE_ARCH}" in
+	case "$UNAME_MACHINE_ARCH" in
 	    armeb) machine=armeb-unknown ;;
 	    arm*) machine=arm-unknown ;;
 	    sh3el) machine=shl-unknown ;;
 	    sh3eb) machine=sh-unknown ;;
 	    sh5el) machine=sh5le-unknown ;;
 	    earmv*)
-		arch=`echo ${UNAME_MACHINE_ARCH} | sed -e 's,^e\(armv[0-9]\).*$,\1,'`
-		endian=`echo ${UNAME_MACHINE_ARCH} | sed -ne 's,^.*\(eb\)$,\1,p'`
-		machine=${arch}${endian}-unknown
+		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 ;;
+	    *) machine="$UNAME_MACHINE_ARCH"-unknown ;;
 	esac
 	# The Operating System including object format, if it has switched
-	# to ELF recently, or will in the future.
-	case "${UNAME_MACHINE_ARCH}" in
-	    arm*|earm*|i386|m68k|ns32k|sh3*|sparc|vax)
-		eval $set_cc_for_build
+	# 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"
 		if echo __ELF__ | $CC_FOR_BUILD -E - 2>/dev/null \
 			| grep -q __ELF__
 		then
@@ -205,10 +215,10 @@
 		;;
 	esac
 	# Determine ABI tags.
-	case "${UNAME_MACHINE_ARCH}" in
+	case "$UNAME_MACHINE_ARCH" in
 	    earm*)
 		expr='s/^earmv[0-9]/-eabi/;s/eb$//'
-		abi=`echo ${UNAME_MACHINE_ARCH} | sed -e "$expr"`
+		abi=`echo "$UNAME_MACHINE_ARCH" | sed -e "$expr"`
 		;;
 	esac
 	# The OS release
@@ -216,39 +226,55 @@
 	# 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}${abi}"
+	echo "$machine-${os}${release}${abi-}"
 	exit ;;
     *:Bitrig:*:*)
 	UNAME_MACHINE_ARCH=`arch | sed 's/Bitrig.//'`
-	echo ${UNAME_MACHINE_ARCH}-unknown-bitrig${UNAME_RELEASE}
+	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)
@@ -265,63 +291,54 @@
 	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
@@ -333,7 +350,7 @@
 	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:*:*)
 	echo arm-unknown-riscos
@@ -360,38 +377,38 @@
 	    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
@@ -400,25 +417,25 @@
 		;;
 	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
@@ -429,44 +446,44 @@
     # 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[]) {
@@ -475,23 +492,23 @@
 #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
@@ -517,17 +534,17 @@
     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)
@@ -544,7 +561,7 @@
 	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
@@ -556,14 +573,14 @@
 	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()
@@ -574,7 +591,7 @@
 			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
@@ -588,7 +605,7 @@
 	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
@@ -597,18 +614,18 @@
 		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
@@ -623,28 +640,28 @@
 	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>
@@ -677,13 +694,13 @@
 		    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
@@ -694,23 +711,23 @@
 	    # $ 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 ()
@@ -735,11 +752,11 @@
 	  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:*:*)
@@ -748,7 +765,7 @@
     *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:*:*)
@@ -756,9 +773,9 @@
 	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*:*:*)
@@ -783,127 +800,109 @@
 	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 ;;
     *:MINGW64*:*)
-	echo ${UNAME_MACHINE}-pc-mingw64
+	echo "$UNAME_MACHINE"-pc-mingw64
 	exit ;;
     *:MINGW*:*)
-	echo ${UNAME_MACHINE}-pc-mingw32
+	echo "$UNAME_MACHINE"-pc-mingw32
 	exit ;;
     *:MSYS*:*)
-	echo ${UNAME_MACHINE}-pc-msys
-	exit ;;
-    i*:windows32*:*)
-	# uname -m includes "-pc" on this system.
-	echo ${UNAME_MACHINE}-mingw32
+	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-${LIBC}`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/[-(].*//'`-${LIBC}
+	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-${LIBC}
+	echo "$UNAME_MACHINE"-unknown-linux-"$LIBC"
 	exit ;;
     aarch64_be:Linux:*:*)
 	UNAME_MACHINE=aarch64_be
-	echo ${UNAME_MACHINE}-unknown-linux-${LIBC}
+	echo "$UNAME_MACHINE"-unknown-linux-"$LIBC"
 	exit ;;
     alpha:Linux:*:*)
 	case `sed -n '/^cpu model/s/^.*: \(.*\)/\1/p' < /proc/cpuinfo` in
@@ -916,58 +915,64 @@
 	  EV68*) UNAME_MACHINE=alphaev68 ;;
 	esac
 	objdump --private-headers /bin/sh | grep -q ld.so.1
-	if test "$?" = 0 ; then LIBC="gnulibc1" ; fi
-	echo ${UNAME_MACHINE}-unknown-linux-${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}
+	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-${LIBC}
+	    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-${LIBC}eabi
+		echo "$UNAME_MACHINE"-unknown-linux-"$LIBC"eabi
 	    else
-		echo ${UNAME_MACHINE}-unknown-linux-${LIBC}eabihf
+		echo "$UNAME_MACHINE"-unknown-linux-"$LIBC"eabihf
 	    fi
 	fi
 	exit ;;
     avr32*:Linux:*:*)
-	echo ${UNAME_MACHINE}-unknown-linux-${LIBC}
+	echo "$UNAME_MACHINE"-unknown-linux-"$LIBC"
 	exit ;;
     cris:Linux:*:*)
-	echo ${UNAME_MACHINE}-axis-linux-${LIBC}
+	echo "$UNAME_MACHINE"-axis-linux-"$LIBC"
 	exit ;;
     crisv32:Linux:*:*)
-	echo ${UNAME_MACHINE}-axis-linux-${LIBC}
+	echo "$UNAME_MACHINE"-axis-linux-"$LIBC"
+	exit ;;
+    e2k:Linux:*:*)
+	echo "$UNAME_MACHINE"-unknown-linux-"$LIBC"
 	exit ;;
     frv:Linux:*:*)
-	echo ${UNAME_MACHINE}-unknown-linux-${LIBC}
+	echo "$UNAME_MACHINE"-unknown-linux-"$LIBC"
 	exit ;;
     hexagon:Linux:*:*)
-	echo ${UNAME_MACHINE}-unknown-linux-${LIBC}
+	echo "$UNAME_MACHINE"-unknown-linux-"$LIBC"
 	exit ;;
     i*86:Linux:*:*)
-	echo ${UNAME_MACHINE}-pc-linux-${LIBC}
+	echo "$UNAME_MACHINE"-pc-linux-"$LIBC"
 	exit ;;
     ia64:Linux:*:*)
-	echo ${UNAME_MACHINE}-unknown-linux-${LIBC}
+	echo "$UNAME_MACHINE"-unknown-linux-"$LIBC"
+	exit ;;
+    k1om:Linux:*:*)
+	echo "$UNAME_MACHINE"-unknown-linux-"$LIBC"
 	exit ;;
     m32r*:Linux:*:*)
-	echo ${UNAME_MACHINE}-unknown-linux-${LIBC}
+	echo "$UNAME_MACHINE"-unknown-linux-"$LIBC"
 	exit ;;
     m68*:Linux:*:*)
-	echo ${UNAME_MACHINE}-unknown-linux-${LIBC}
+	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
@@ -981,64 +986,70 @@
 	#endif
 	#endif
 EOF
-	eval `$CC_FOR_BUILD -E $dummy.c 2>/dev/null | grep '^CPU'`
-	test x"${CPU}" != x && { echo "${CPU}-unknown-linux-${LIBC}"; exit; }
+	eval "`$CC_FOR_BUILD -E "$dummy.c" 2>/dev/null | grep '^CPU'`"
+	test "x$CPU" != x && { echo "$CPU-unknown-linux-$LIBC"; exit; }
 	;;
+    mips64el:Linux:*:*)
+	echo "$UNAME_MACHINE"-unknown-linux-"$LIBC"
+	exit ;;
     openrisc*:Linux:*:*)
-	echo or1k-unknown-linux-${LIBC}
+	echo or1k-unknown-linux-"$LIBC"
 	exit ;;
     or32:Linux:*:* | or1k*:Linux:*:*)
-	echo ${UNAME_MACHINE}-unknown-linux-${LIBC}
+	echo "$UNAME_MACHINE"-unknown-linux-"$LIBC"
 	exit ;;
     padre:Linux:*:*)
-	echo sparc-unknown-linux-${LIBC}
+	echo sparc-unknown-linux-"$LIBC"
 	exit ;;
     parisc64:Linux:*:* | hppa64:Linux:*:*)
-	echo hppa64-unknown-linux-${LIBC}
+	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-${LIBC} ;;
-	  PA8*) echo hppa2.0-unknown-linux-${LIBC} ;;
-	  *)    echo hppa-unknown-linux-${LIBC} ;;
+	  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-${LIBC}
+	echo powerpc64-unknown-linux-"$LIBC"
 	exit ;;
     ppc:Linux:*:*)
-	echo powerpc-unknown-linux-${LIBC}
+	echo powerpc-unknown-linux-"$LIBC"
 	exit ;;
     ppc64le:Linux:*:*)
-	echo powerpc64le-unknown-linux-${LIBC}
+	echo powerpc64le-unknown-linux-"$LIBC"
 	exit ;;
     ppcle:Linux:*:*)
-	echo powerpcle-unknown-linux-${LIBC}
+	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-${LIBC}
+	echo "$UNAME_MACHINE"-ibm-linux-"$LIBC"
 	exit ;;
     sh64*:Linux:*:*)
-	echo ${UNAME_MACHINE}-unknown-linux-${LIBC}
+	echo "$UNAME_MACHINE"-unknown-linux-"$LIBC"
 	exit ;;
     sh*:Linux:*:*)
-	echo ${UNAME_MACHINE}-unknown-linux-${LIBC}
+	echo "$UNAME_MACHINE"-unknown-linux-"$LIBC"
 	exit ;;
     sparc:Linux:*:* | sparc64:Linux:*:*)
-	echo ${UNAME_MACHINE}-unknown-linux-${LIBC}
+	echo "$UNAME_MACHINE"-unknown-linux-"$LIBC"
 	exit ;;
     tile*:Linux:*:*)
-	echo ${UNAME_MACHINE}-unknown-linux-${LIBC}
+	echo "$UNAME_MACHINE"-unknown-linux-"$LIBC"
 	exit ;;
     vax:Linux:*:*)
-	echo ${UNAME_MACHINE}-dec-linux-${LIBC}
+	echo "$UNAME_MACHINE"-dec-linux-"$LIBC"
 	exit ;;
     x86_64:Linux:*:*)
-	echo ${UNAME_MACHINE}-unknown-linux-${LIBC}
+	echo "$UNAME_MACHINE"-pc-linux-"$LIBC"
 	exit ;;
     xtensa*:Linux:*:*)
-	echo ${UNAME_MACHINE}-unknown-linux-${LIBC}
+	echo "$UNAME_MACHINE"-unknown-linux-"$LIBC"
 	exit ;;
     i*86:DYNIX/ptx:4*:*)
 	# ptx 4.0 does uname -s correctly, with DYNIX/ptx in there.
@@ -1052,34 +1063,34 @@
 	# 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]*)
@@ -1089,12 +1100,12 @@
 	    *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
@@ -1104,9 +1115,9 @@
 			&& 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:*:*:*)
@@ -1114,7 +1125,7 @@
 	# 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 ;;
@@ -1126,9 +1137,9 @@
 	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:*)
@@ -1148,9 +1159,9 @@
 	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; } ;;
@@ -1159,28 +1170,28 @@
 	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
@@ -1191,7 +1202,7 @@
     *: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
@@ -1211,23 +1222,23 @@
 	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.
@@ -1246,46 +1257,56 @@
 	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
-	eval $set_cc_for_build
+	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 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
+		       (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
@@ -1296,27 +1317,33 @@
 	    # that Apple uses in portable devices.
 	    UNAME_PROCESSOR=x86_64
 	fi
-	echo ${UNAME_PROCESSOR}-apple-darwin${UNAME_RELEASE}
+	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}
+	echo nse-tandem-nsk"$UNAME_RELEASE"
 	exit ;;
-    NSR-?:NONSTOP_KERNEL:*:*)
-	echo nsr-tandem-nsk${UNAME_RELEASE}
+    NSR-*:NONSTOP_KERNEL:*:*)
+	echo nsr-tandem-nsk"$UNAME_RELEASE"
+	exit ;;
+    NSV-*:NONSTOP_KERNEL:*:*)
+	echo nsv-tandem-nsk"$UNAME_RELEASE"
+	exit ;;
+    NSX-*:NONSTOP_KERNEL:*:*)
+	echo nsx-tandem-nsk"$UNAME_RELEASE"
 	exit ;;
     *:NonStop-UX:*:*)
 	echo mips-compaq-nonstopux
@@ -1325,18 +1352,18 @@
 	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
@@ -1357,14 +1384,14 @@
 	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 ;;
@@ -1373,34 +1400,48 @@
 	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 "$0: unable to guess system type" >&2
+
+case "$UNAME_MACHINE:$UNAME_SYSTEM" in
+    mips:Linux | mips64:Linux)
+	# If we got here on MIPS GNU/Linux, output extra information.
+	cat >&2 <<EOF
+
+NOTE: MIPS GNU/Linux systems require a C compiler to fully recognize
+the system type. Please install a C compiler and try again.
+EOF
+	;;
+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
 
@@ -1419,16 +1460,16 @@
 /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: "'"
diff --git a/config.h b/config.h
index 9ce0ffc..1dc9c7f 100644
--- a/config.h
+++ b/config.h
@@ -1,11 +1,23 @@
 /* config.h.  Generated from config.h.in by configure.  */
 /* 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 <dagapi.h> header file. */
+/* #undef HAVE_DAGAPI_H */
 
 /* define if you have the DAG API */
 /* #undef HAVE_DAG_API */
@@ -16,40 +28,45 @@
 /* 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' */
 #define HAVE_DECL_ETHER_HOSTTON 1
 
-/* 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. */
+#define HAVE_FFS 1
+
 /* Define to 1 if fseeko (and presumably ftello) exists and is declared. */
 #define HAVE_FSEEKO 1
 
+/* Define to 1 if you have the `getspnam' function. */
+/* #undef HAVE_GETSPNAM */
+
 /* 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. */
 #define HAVE_INTTYPES_H 1
 
+/* Define to 1 if you have the `dag' library (-ldag). */
+/* #undef HAVE_LIBDAG */
+
 /* if libdlpi exists */
 /* #undef HAVE_LIBDLPI */
 
@@ -77,24 +94,24 @@
 /* Define to 1 if you have the <linux/ethtool.h> header file. */
 #define HAVE_LINUX_ETHTOOL_H 1
 
+/* 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. */
 #define HAVE_LINUX_IF_BONDING_H 1
 
-/* Define to 1 if you have the <linux/if_packet.h> header file. */
-#define HAVE_LINUX_IF_PACKET_H 1
-
 /* Define to 1 if you have the <linux/net_tstamp.h> header file. */
 #define HAVE_LINUX_NET_TSTAMP_H 1
 
+/* Define to 1 if you have the <linux/socket.h> header file. */
+#define HAVE_LINUX_SOCKET_H 1
+
 /* Define to 1 if you have the <linux/sockios.h> header file. */
 #define HAVE_LINUX_SOCKIOS_H 1
 
-/* if tp_vlan_tci exists */
-#define HAVE_LINUX_TPACKET_AUXDATA_TP_VLAN_TCI 1
-
-/* Define to 1 if you have the <linux/types.h> header file. */
-#define HAVE_LINUX_TYPES_H 1
-
 /* Define to 1 if you have the <linux/usbdevice_fs.h> header file. */
 #define HAVE_LINUX_USBDEVICE_FS_H 1
 
@@ -104,24 +121,30 @@
 /* Define to 1 if you have the <memory.h> header file. */
 #define HAVE_MEMORY_H 1
 
-/* Define to 1 if you have the <netinet/ether.h> header file. */
-#define HAVE_NETINET_ETHER_H 1
-
-/* Define to 1 if you have the <netinet/if_ether.h> header file. */
-#define HAVE_NETINET_IF_ETHER_H 1
-
-/* 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. */
 #define HAVE_NETPACKET_PACKET_H 1
 
+/* 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 */
 
@@ -137,18 +160,18 @@
 /* Define to 1 if you have the `snprintf' function. */
 #define HAVE_SNPRINTF 1
 
-/* if struct sockaddr has the sa_len member */
-/* #undef HAVE_SOCKADDR_SA_LEN */
-
-/* if struct sockaddr_storage exists */
-#define HAVE_SOCKADDR_STORAGE 1
-
-/* define if socklen_t is defined */
+/* Define to 1 if the system has the type `socklen_t'. */
 #define HAVE_SOCKLEN_T 1
 
 /* 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. */
 #define HAVE_STDINT_H 1
 
@@ -158,12 +181,21 @@
 /* Define to 1 if you have the `strerror' function. */
 #define HAVE_STRERROR 1
 
+/* Define to 1 if you have the `strerror_r' function. */
+#define HAVE_STRERROR_R 1
+
+/* 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. */
 #define HAVE_STRINGS_H 1
 
 /* Define to 1 if you have the <string.h> header file. */
 #define HAVE_STRING_H 1
 
+/* Define to 1 if you have the `strlcat' function. */
+#define HAVE_STRLCAT 1
+
 /* Define to 1 if you have the `strlcpy' function. */
 #define HAVE_STRLCPY 1
 
@@ -176,8 +208,30 @@
 /* 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'. */
+#define HAVE_STRUCT_SOCKADDR_STORAGE 1
+
+/* Define to 1 if `tp_vlan_tci' is a member of `struct tpacket_auxdata'. */
+#define HAVE_STRUCT_TPACKET_AUXDATA_TP_VLAN_TCI 1
+
+/* Define to 1 if the system has the type `struct tpacket_stats'. */
+#define HAVE_STRUCT_TPACKET_STATS 1
+
+/* Define to 1 if `bRequestType' is a member of `struct
+   usbdevfs_ctrltransfer'. */
+#define HAVE_STRUCT_USBDEVFS_CTRLTRANSFER_BREQUESTTYPE 1
 
 /* Define to 1 if you have the <sys/bufmod.h> header file. */
 /* #undef HAVE_SYS_BUFMOD_H */
@@ -185,11 +239,14 @@
 /* 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/select.h> header file. */
-#define HAVE_SYS_SELECT_H 1
+/* 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 */
@@ -203,24 +260,12 @@
 /* define if you have the TurboCap API */
 /* #undef HAVE_TC_API */
 
-/* if if_packet.h has tpacket_stats defined */
-#define HAVE_TPACKET_STATS 1
-
 /* Define to 1 if you have the <unistd.h> header file. */
 #define HAVE_UNISTD_H 1
 
-/* if struct usbdevfs_ctrltransfer has bRequestType */
-#define HAVE_USBDEVFS_CTRLTRANSFER_BREQUESTTYPE 1
-
 /* Define to 1 if you have the `vsnprintf' function. */
 #define HAVE_VSNPRINTF 1
 
-/* define if the system supports zerocopy BPF */
-/* #undef HAVE_ZEROCOPY_BPF */
-
-/* define if your compiler has __attribute__ */
-#define HAVE___ATTRIBUTE__ 1
-
 /* IPv6 */
 #define INET6 1
 
@@ -236,6 +281,9 @@
 /* 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 */
 
@@ -243,22 +291,19 @@
 #define PACKAGE_BUGREPORT ""
 
 /* Define to the full name of this package. */
-#define PACKAGE_NAME ""
+#define PACKAGE_NAME "pcap"
 
 /* Define to the full name and version of this package. */
-#define PACKAGE_STRING ""
+#define PACKAGE_STRING "pcap 1.9.0-PRE-GIT"
 
 /* Define to the one symbol short name of this package. */
-#define PACKAGE_TARNAME ""
+#define PACKAGE_TARNAME "pcap"
 
 /* Define to the home page for this package. */
 #define PACKAGE_URL ""
 
 /* Define to the version of this package. */
-#define PACKAGE_VERSION ""
-
-/* /dev/dlpi directory */
-/* #undef PCAP_DEV_PREFIX */
+#define PACKAGE_VERSION "1.9.0-PRE-GIT"
 
 /* target host supports Bluetooth sniffing */
 /* #undef PCAP_SUPPORT_BT */
@@ -272,21 +317,30 @@
 /* target host supports netfilter sniffing */
 #define PCAP_SUPPORT_NETFILTER 1
 
-/* use Linux packet ring capture if available */
+/* target host supports netmap */
+/* #undef PCAP_SUPPORT_NETMAP */
+
+/* use packet ring capture support on Linux if available */
 #define PCAP_SUPPORT_PACKET_RING 1
 
+/* target host supports RDMA sniffing */
+/* #undef PCAP_SUPPORT_RDMASNIFF */
+
 /* target host supports USB sniffing */
 #define PCAP_SUPPORT_USB 1
 
 /* 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. */
 #define STDC_HEADERS 1
 
+/* Define to 1 if strings.h declares `ffs' */
+#define 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 */
 
@@ -311,38 +365,11 @@
 /* define on AIX to get certain functions */
 /* #undef _SUN */
 
-/* define if your compiler allows __attribute__((format)) without a warning */
-#define __ATTRIBUTE___FORMAT_OK 1
-
 /* to handle Ultrix compilers that don't support const in prototypes */
 /* #undef const */
 
 /* Define as token for inline if inlining supported */
 #define inline 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 */
diff --git a/config.h.in b/config.h.in
index e85b2a3..b1a20a4 100644
--- a/config.h.in
+++ b/config.h.in
@@ -1,10 +1,22 @@
 /* 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 <dagapi.h> header file. */
+#undef HAVE_DAGAPI_H
 
 /* define if you have the DAG API */
 #undef HAVE_DAG_API
@@ -15,40 +27,45 @@
 /* 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
+
 /* 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
 
@@ -76,24 +93,24 @@
 /* Define to 1 if you have the <linux/ethtool.h> header file. */
 #undef HAVE_LINUX_ETHTOOL_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/if_packet.h> header file. */
-#undef HAVE_LINUX_IF_PACKET_H
-
 /* Define to 1 if you have the <linux/net_tstamp.h> header file. */
 #undef HAVE_LINUX_NET_TSTAMP_H
 
+/* Define to 1 if you have the <linux/socket.h> header file. */
+#undef HAVE_LINUX_SOCKET_H
+
 /* Define to 1 if you have the <linux/sockios.h> header file. */
 #undef HAVE_LINUX_SOCKIOS_H
 
-/* if tp_vlan_tci exists */
-#undef HAVE_LINUX_TPACKET_AUXDATA_TP_VLAN_TCI
-
-/* 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/usbdevice_fs.h> header file. */
 #undef HAVE_LINUX_USBDEVICE_FS_H
 
@@ -103,24 +120,30 @@
 /* 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
 
@@ -136,18 +159,18 @@
 /* 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
 
@@ -157,12 +180,21 @@
 /* Define to 1 if you have the `strerror' function. */
 #undef HAVE_STRERROR
 
+/* Define to 1 if you have the `strerror_r' function. */
+#undef HAVE_STRERROR_R
+
+/* 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
 
@@ -175,8 +207,30 @@
 /* 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
@@ -184,11 +238,14 @@
 /* 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/select.h> header file. */
-#undef HAVE_SYS_SELECT_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
@@ -202,24 +259,12 @@
 /* define if you have the TurboCap API */
 #undef HAVE_TC_API
 
-/* if if_packet.h has tpacket_stats defined */
-#undef HAVE_TPACKET_STATS
-
 /* 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 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__
-
 /* IPv6 */
 #undef INET6
 
@@ -235,6 +280,9 @@
 /* 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
 
@@ -256,9 +304,6 @@
 /* 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
 
@@ -271,21 +316,30 @@
 /* target host supports netfilter sniffing */
 #undef PCAP_SUPPORT_NETFILTER
 
-/* use Linux packet ring capture if available */
+/* 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
 
@@ -310,38 +364,11 @@
 /* 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
diff --git a/config.sub b/config.sub
old mode 100644
new mode 100755
index bc855a2..c95acc6
--- a/config.sub
+++ b/config.sub
@@ -1,8 +1,8 @@
 #! /bin/sh
 # Configuration validation subroutine script.
-#   Copyright 1992-2015 Free Software Foundation, Inc.
+#   Copyright 1992-2018 Free Software Foundation, Inc.
 
-timestamp='2015-02-22'
+timestamp='2018-07-03'
 
 # 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
@@ -15,7 +15,7 @@
 # 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
@@ -33,7 +33,7 @@
 # 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
@@ -53,12 +53,11 @@
 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
@@ -68,7 +67,7 @@
 version="\
 GNU config.sub ($timestamp)
 
-Copyright 1992-2015 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."
@@ -95,7 +94,7 @@
 
     *local*)
        # First pass through any local machine types.
-       echo $1
+       echo "$1"
        exit ;;
 
     * )
@@ -111,134 +110,455 @@
     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-musl* | linux-uclibc* | uclinux-uclibc* | uclinux-gnu* | kfreebsd*-gnu* | \
-  knetbsd*-gnu* | netbsd*-gnu* | netbsd*-eabi* | \
-  kopensolaris*-gnu* | \
-  storm-chaos* | os2-emx* | rtmk-nova*)
-    os=-$maybe_os
-    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.
+# Separate into logical components for further validation
+case $1 in
+	*-*-*-*-*)
+		echo Invalid configuration \`"$1"\': more than four components >&2
+		exit 1
 		;;
-	-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
+	*-*-*-*)
+		basic_machine=$field1-$field2
+		os=$field3-$field4
 		;;
-	-bluegene*)
-		os=-cnk
+	*-*-*)
+		# 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
 		;;
-	-sim | -cisco | -oki | -wec | -winbond)
-		os=
-		basic_machine=$1
+	*-*)
+		# 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
 		;;
-	-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
-		;;
-	-ptx*)
-		basic_machine=`echo $1 | sed -e 's/86-.*/86-sequent/'`
-		;;
-	-windowsnt*)
-		os=`echo $os | sed -e 's/windowsnt/winnt/'`
-		;;
-	-psos*)
-		os=-psos
-		;;
-	-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
 
@@ -253,17 +573,18 @@
 	| alpha64 | alpha64ev[4-8] | alpha64ev56 | alpha64ev6[78] | alpha64pca5[67] \
 	| am33_2.0 \
 	| arc | arceb \
-	| arm | arm[bl]e | arme[lb] | armv[2-8] | armv[3-8][lb] | armv7[arm] \
+	| arm | arm[bl]e | arme[lb] | armv[2-8] | armv[3-8][lb] | armv6m | armv[78][arm] \
 	| avr | avr32 \
+	| ba \
 	| be32 | be64 \
 	| bfin \
-	| c4x | c8051 | clipper \
+	| c4x | c8051 | clipper | csky \
 	| d10v | d30v | dlx | dsp16xx \
-	| epiphany \
+	| 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 \
@@ -296,16 +617,18 @@
 	| mt \
 	| msp430 \
 	| nds32 | nds32le | nds32be \
+	| nfp \
 	| nios | nios2 | nios2eb | nios2el \
 	| ns16k | ns32k \
 	| open8 | or1k | or1knd | or32 \
-	| pdp10 | pdp11 | pj | pjl \
+	| pdp10 | pj | pjl \
 	| powerpc | powerpc64 | powerpc64le | powerpcle \
+	| pru \
 	| pyramid \
-	| riscv32 | riscv64 \
+	| 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 +637,7 @@
 	| ubicom32 \
 	| v850 | v850e | v850e1 | v850e2 | v850es | v850e2v3 \
 	| visium \
-	| we32k \
+	| wasm32 \
 	| x86 | xc16x | xstormy16 | xtensa \
 	| z8k | z80)
 		basic_machine=$basic_machine-unknown
@@ -333,20 +656,23 @@
 		;;
 	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 | z8k)
+	m88110 | m680[12346]0 | m683?2 | m68360 | m5200 | v70 | w65)
+		;;
+	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
@@ -362,11 +688,6 @@
 	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-* \
@@ -376,17 +697,18 @@
 	| alphapca5[67]-* | alpha64pca5[67]-* | arc-* | arceb-* \
 	| arm-*  | armbe-* | armle-* | armeb-* | armv*-* \
 	| avr-* | avr32-* \
+	| ba-* \
 	| be32-* | be64-* \
 	| bfin-* | bs2000-* \
 	| c[123]* | c30-* | [cjt]90-* | c4x-* \
-	| c8051-* | 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-* \
@@ -420,6 +742,7 @@
 	| mt-* \
 	| msp430-* \
 	| nds32-* | nds32le-* | nds32be-* \
+	| nfp-* \
 	| nios-* | nios2-* | nios2eb-* | nios2el-* \
 	| none-* | np1-* | ns16k-* | ns32k-* \
 	| open8-* \
@@ -427,13 +750,15 @@
 	| 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*-* \
@@ -442,6 +767,7 @@
 	| v850-* | v850e-* | v850e1-* | v850es-* | v850e2-* | v850e2v3-* \
 	| vax-* \
 	| visium-* \
+	| wasm32-* \
 	| we32k-* \
 	| x86-* | x86_64-* | xc16x-* | xps100-* \
 	| xstormy16-* | xtensa*-* \
@@ -454,138 +780,77 @@
 		;;
 	# 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
@@ -598,7 +863,7 @@
 		;;
 	crx)
 		basic_machine=crx-unknown
-		os=-elf
+		os=${os:-elf}
 		;;
 	da30 | da30-*)
 		basic_machine=m68k-da30
@@ -608,50 +873,38 @@
 		;;
 	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
@@ -659,45 +912,13 @@
 	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
 		;;
@@ -727,200 +948,82 @@
 	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
-		;;
 	leon-*|leon[3-9]-*)
-		basic_machine=sparc-`echo $basic_machine | sed 's/-.*//'`
-		;;
-	m68knommu)
-		basic_machine=m68k-unknown
-		os=-linux
+		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*)
 		basic_machine=microblaze-xilinx
 		;;
-	mingw64)
-		basic_machine=x86_64-pc
-		os=-mingw64
-		;;
-	mingw32)
-		basic_machine=i686-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
-		;;
-	moxiebox)
-		basic_machine=moxie-unknown
-		os=-moxiebox
-		;;
-	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=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
+		basic_machine=`echo "$basic_machine" | sed -e 's/ms1-/mt-/'`
 		;;
 	news-3600 | risc-news)
 		basic_machine=mips-sony
-		os=-newsos
+		os=newsos
 		;;
-	necv70)
-		basic_machine=v70-nec
-		os=-sysv
-		;;
-	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
 		;;
@@ -933,40 +1036,26 @@
 	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
@@ -981,7 +1070,7 @@
 		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
@@ -996,16 +1085,16 @@
 		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
@@ -1015,43 +1104,27 @@
 	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 | rdos64)
-		basic_machine=x86_64-pc
-		os=-rdos
-		;;
-	rdos32)
-		basic_machine=i386-pc
-		os=-rdos
-		;;
-	rom68k)
-		basic_machine=m68k-rom68k
-		os=-coff
-		;;
 	rm[46]00)
 		basic_machine=mips-siemens
 		;;
@@ -1064,10 +1137,6 @@
 	s390x | s390x-*)
 		basic_machine=s390x-ibm
 		;;
-	sa29200)
-		basic_machine=a29k-amd
-		os=-udi
-		;;
 	sb1)
 		basic_machine=mipsisa64sb1-unknown
 		;;
@@ -1076,32 +1145,17 @@
 		;;
 	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
@@ -1109,44 +1163,12 @@
 	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
 		;;
@@ -1156,25 +1178,9 @@
 	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
@@ -1182,85 +1188,32 @@
 	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
@@ -1286,10 +1239,6 @@
 	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
 		;;
@@ -1299,9 +1248,6 @@
 	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
 		;;
@@ -1321,7 +1267,7 @@
 		# 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
@@ -1329,10 +1275,10 @@
 # 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/'`
 		;;
 	*)
 		;;
@@ -1340,197 +1286,246 @@
 
 # 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.*)
+	bluegene*)
+		os=cnk
+		;;
+	solaris1 | solaris1.*)
 		os=`echo $os | sed -e 's|solaris1|sunos4|'`
 		;;
-	-solaris)
-		os=-solaris2
+	solaris)
+		os=solaris2
 		;;
-	-svr4*)
-		os=-sysv4
+	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* | -plan9* \
-	      | -amigaos* | -amigados* | -msdos* | -newsos* | -unicos* | -aof* \
-	      | -aos* | -aros* \
-	      | -nindy* | -vxsim* | -vxworks* | -ebmon* | -hms* | -mvs* \
-	      | -clix* | -riscos* | -uniplus* | -iris* | -rtu* | -xenix* \
-	      | -hiux* | -386bsd* | -knetbsd* | -mirbsd* | -netbsd* \
-	      | -bitrig* | -openbsd* | -solidbsd* \
-	      | -ekkobsd* | -kfreebsd* | -freebsd* | -riscix* | -lynxos* \
-	      | -bosx* | -nextstep* | -cxux* | -aout* | -elf* | -oabi* \
-	      | -ptx* | -coff* | -ecoff* | -winnt* | -domain* | -vsta* \
-	      | -udi* | -eabi* | -lites* | -ieee* | -go32* | -aux* \
-	      | -chorusos* | -chorusrdb* | -cegcc* \
-	      | -cygwin* | -msys* | -pe* | -psos* | -moss* | -proelf* | -rtems* \
-	      | -mingw32* | -mingw64* | -linux-gnu* | -linux-android* \
-	      | -linux-newlib* | -linux-musl* | -linux-uclibc* \
-	      | -uxpv* | -beos* | -mpeix* | -udk* | -moxiebox* \
-	      | -interix* | -uwin* | -mks* | -rhapsody* | -darwin* | -opened* \
-	      | -openstep* | -oskit* | -conix* | -pw32* | -nonstopux* \
-	      | -storm-chaos* | -tops10* | -tenex* | -tops20* | -its* \
-	      | -os2* | -vos* | -palmos* | -uclinux* | -nucleus* \
-	      | -morphos* | -superux* | -rtmk* | -rtmk-nova* | -windiss* \
-	      | -powermax* | -dnix* | -nx6 | -nx7 | -sei* | -dragonfly* \
-	      | -skyos* | -haiku* | -rdos* | -toppers* | -drops* | -es* | -tirtos*)
+	# 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*)
+	nto-qnx*)
+		;;
+	nto*)
 		os=`echo $os | sed -e 's|nto|nto-qnx|'`
 		;;
-	-sim | -es1800* | -hms* | -xray | -os68k* | -none* | -v88r* \
-	      | -windows* | -osx | -abug | -netware* | -os9* | -beos* | -haiku* \
-	      | -macos* | -mpw* | -magic* | -mmixware* | -mon960* | -lnews*)
+	sim | xray | os68k* | v88r* \
+	    | windows* | osx | abug | netware* | os9* \
+	    | macos* | mpw* | magic* | mmixware* | mon960* | lnews*)
 		;;
-	-mac*)
-		os=`echo $os | sed -e 's|mac|macos|'`
+	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
 		;;
-	-ns2 )
-		os=-nextstep2
+	ctix* | uts*)
+		os=sysv
 		;;
-	-nsk*)
-		os=-nsk
+	nova*)
+		os=rtmk-nova
+		;;
+	ns2)
+		os=nextstep2
+		;;
+	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
+	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
@@ -1548,176 +1543,179 @@
 
 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
+		os=elf
+		;;
+	clipper-intergraph)
+		os=clix
 		;;
 	hexagon-*)
-		os=-elf
+		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
+		;;
+	pru-*)
+		os=elf
 		;;
 	*-be)
-		os=-beos
-		;;
-	*-haiku)
-		os=-haiku
+		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
-		;;
-	*-next )
-		os=-nextstep
-		;;
-	*-sequent)
-		os=-ptx
-		;;
-	*-crds)
-		os=-unos
-		;;
-	*-ns)
-		os=-genix
-		;;
-	i370-*)
-		os=-mvs
+		os=luna
 		;;
 	*-next)
-		os=-nextstep3
+		os=nextstep
+		;;
+	*-sequent)
+		os=ptx
+		;;
+	*-crds)
+		os=unos
+		;;
+	*-ns)
+		os=genix
+		;;
+	i370-*)
+		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
@@ -1728,79 +1726,82 @@
 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: "'"
diff --git a/configure b/configure
index 4c64875..9a8c158 100755
--- 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.0-PRE-GIT.
 #
 #
 # Copyright (C) 1992-1996, 1998-2012 Free Software Foundation, Inc.
@@ -575,12 +575,12 @@
 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.0-PRE-GIT'
+PACKAGE_STRING='pcap 1.9.0-PRE-GIT'
+PACKAGE_BUGREPORT=''
+PACKAGE_URL=''
 
 ac_unique_file="pcap.c"
 # Factoring default headers for most tests.
@@ -623,17 +623,26 @@
 INSTALL_DATA
 INSTALL_SCRIPT
 INSTALL_PROGRAM
-PCAP_SUPPORT_PACKET_RING
+RDMA_SRC
+PCAP_SUPPORT_RDMASNIFF
 DBUS_SRC
 PCAP_SUPPORT_DBUS
 PKGCONFIG
 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
 DYEXT
@@ -645,6 +654,7 @@
 V_SONAME_OPT
 V_SHLIB_OPT
 V_SHLIB_CMD
+V_SHLIB_CCOPT
 V_PCAP
 V_LEX
 V_INCLS
@@ -661,8 +671,8 @@
 LEXLIB
 LEX_OUTPUT_ROOT
 LEX
-HAVE_LINUX_TPACKET_AUXDATA
-VALGRINDTEST
+PCAP_SUPPORT_PACKET_RING
+VALGRINDTEST_SRC
 LIBOBJS
 EGREP
 GREP
@@ -734,9 +744,8 @@
 with_sita
 with_pcap
 with_libnl
+enable_packet_ring
 enable_ipv6
-enable_optimizer_dbg
-enable_yydebug
 with_dag
 with_dag_includes
 with_dag_libraries
@@ -745,12 +754,16 @@
 with_snf_includes
 with_snf_libraries
 with_turbocap
+enable_remote
+enable_optimizer_dbg
+enable_yydebug
 enable_universal
 enable_shared
 enable_usb
+enable_netmap
 enable_bluetooth
 enable_dbus
-enable_packet_ring
+enable_rdma
 '
       ac_precious_vars='build_alias
 host_alias
@@ -803,7 +816,7 @@
 localstatedir='${prefix}/var'
 includedir='${prefix}/include'
 oldincludedir='/usr/include'
-docdir='${datarootdir}/doc/${PACKAGE}'
+docdir='${datarootdir}/doc/${PACKAGE_TARNAME}'
 infodir='${datarootdir}/info'
 htmldir='${docdir}'
 dvidir='${docdir}'
@@ -1303,7 +1316,7 @@
   # 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.0-PRE-GIT to adapt to many kinds of systems.
 
 Usage: $0 [OPTION]... [VAR=VALUE]...
 
@@ -1351,7 +1364,7 @@
   --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]
@@ -1368,7 +1381,9 @@
 fi
 
 if test -n "$ac_init_help"; then
-
+  case $ac_init_help in
+     short | recursive ) echo "Configuration of pcap 1.9.0-PRE-GIT:";;
+   esac
   cat <<\_ACEOF
 
 Optional Features:
@@ -1377,20 +1392,25 @@
   --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-usb            enable nusb support [default=yes, if support
+  --enable-usb            enable USB capture support [default=yes, if support
+                          available]
+  --enable-netmap         enable netmap support [default=yes, if support
                           available]
   --enable-bluetooth      enable Bluetooth support [default=yes, if support
                           available]
   --enable-dbus           enable D-Bus capture support [default=yes, if
                           support available]
-  --enable-packet-ring    enable Linux packet ring support [default=yes]
+  --enable-rdma           enable RDMA capture support [default=yes, if support
+                          available]
 
 Optional Packages:
   --with-PACKAGE[=ARG]    use PACKAGE [ARG=yes]
@@ -1500,7 +1520,7 @@
 test -n "$ac_init_help" && exit $ac_status
 if $ac_init_version; then
   cat <<\_ACEOF
-configure
+pcap configure 1.9.0-PRE-GIT
 generated by GNU Autoconf 2.69
 
 Copyright (C) 2012 Free Software Foundation, Inc.
@@ -1552,6 +1572,52 @@
 
 } # 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.
@@ -1749,106 +1815,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
@@ -1961,11 +1927,122 @@
   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.0-PRE-GIT, which was
 generated by GNU Autoconf 2.69.  Invocation command line was
 
   $ $0 $@
@@ -2314,6 +2391,8 @@
 
 
 
+
+
 ac_aux_dir=
 for ac_dir in "$srcdir" "$srcdir/.." "$srcdir/../.."; do
   if test -f "$ac_dir/install-sh"; then
@@ -2527,6 +2606,10 @@
 	    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'
@@ -3316,6 +3399,183 @@
 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
+
+
 
 
 
@@ -3363,8 +3623,47 @@
 
 		{ $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"
-		V_CCOPT="$V_CCOPT -fvisibility=hidden"
+		if test x"$can_add_to_cflags" = "xyes"
+		then
+		    V_CCOPT="$V_CCOPT -fvisibility=hidden"
+		fi
 
 else
 
@@ -3424,8 +3723,47 @@
 
 		{ $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"
-		V_CCOPT="$V_CCOPT -fvisibility=hidden"
+		if test x"$can_add_to_cflags" = "xyes"
+		then
+		    V_CCOPT="$V_CCOPT -fvisibility=hidden"
+		fi
 
 else
 
@@ -3547,8 +3885,47 @@
 
 		{ $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"
-		V_CCOPT="$V_CCOPT -xldscope=hidden"
+		if test x"$can_add_to_cflags" = "xyes"
+		then
+		    V_CCOPT="$V_CCOPT -xldscope=hidden"
+		fi
 
 else
 
@@ -3605,7 +3982,7 @@
 	    # 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;
@@ -3643,13 +4020,13 @@
 			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"
@@ -3665,7 +4042,7 @@
 		    ;;
 
 	    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.
@@ -3680,7 +4057,7 @@
 	    # 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;
@@ -3706,7 +4083,7 @@
 		    #
 		    # "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,"
@@ -3714,7 +4091,7 @@
 		    ;;
 
 	    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 "
@@ -3737,7 +4114,7 @@
 		    ;;
 
 	    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 "
@@ -3809,140 +4186,277 @@
 _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 :
+#
+# Try to arrange for large file support.
+#
+# Check whether --enable-largefile was given.
+if test "${enable_largefile+set}" = set; then :
+  enableval=$enable_largefile;
+fi
+
+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
-
-cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+  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 <stdlib.h>
-
-static void foo(void) __attribute__ ((noreturn));
-
-static void
-foo(void)
-{
-  exit(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 << 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(int argc, char **argv)
+main ()
 {
-  foo();
-}
 
-_ACEOF
-if ac_fn_c_try_compile "$LINENO"; then :
-  ac_cv___attribute__=yes
-else
-  ac_cv___attribute__=no
-fi
-rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
-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_=\"\""
-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}: 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_n "(cached) " >&6
-else
-
-save_CFLAGS="$CFLAGS"
-CFLAGS="$CFLAGS $ac_lbl_cc_force_warning_errors"
-cat confdefs.h - <<_ACEOF >conftest.$ac_ext
-/* end confdefs.h.  */
-
-
-#include <stdlib.h>
-#include <stdio.h>
-
-int
-main(int argc  __attribute((unused)), char **argv __attribute((unused)))
-{
-  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
+	 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
-
-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_=\"\""
+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___unused" >&5
-$as_echo "$ac_cv___attribute___unused" >&6; }
+{ $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__((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 :
+  { $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>
-
-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 << 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(int argc, char **argv)
+main ()
 {
-  foo("%s", "test");
-}
 
+  ;
+  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_file_offset_bits=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 _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];
+int
+main ()
+{
+
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+  ac_cv_sys_file_offset_bits=64; break
+fi
+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
+  while :; do
+  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 ()
+{
+
+  ;
+  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 << 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 ()
+{
+
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+  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
+
+
 fi
 
-CFLAGS="$save_CFLAGS"
-if test "$ac_cv___attribute___format" = "yes"; 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
+  while :; do
+  cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+#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=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*
 
-$as_echo "#define __ATTRIBUTE___FORMAT_OK 1" >>confdefs.h
+# 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
-{ $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'
@@ -4341,397 +4855,7 @@
 done
 
 
-for ac_header in sys/bitypes.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 :
-  cat >>confdefs.h <<_ACEOF
-#define HAVE_SYS_BITYPES_H 1
-_ACEOF
-
-fi
-
-done
-
-
-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 :
-
-else
-
-$as_echo "#define int8_t signed char" >>confdefs.h
-
-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 :
-
-else
-
-$as_echo "#define u_int8_t unsigned char" >>confdefs.h
-
-fi
-
-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 "#define int16_t short" >>confdefs.h
-
-	$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 :
-
-else
-
-$as_echo "#define u_int16_t unsigned short" >>confdefs.h
-
-fi
-
-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 :
-
-else
-
-$as_echo "#define int32_t int" >>confdefs.h
-
-fi
-
-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 :
-
-else
-
-$as_echo "#define u_int32_t unsigned int" >>confdefs.h
-
-fi
-
-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
-
-fi
-
-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 :
-
-else
-
-$as_echo "#define u_int64_t unsigned long long" >>confdefs.h
-
-fi
-
-
-#
-# Try to arrange for large file support.
-#
-# Check whether --enable-largefile was given.
-if test "${enable_largefile+set}" = set; then :
-  enableval=$enable_largefile;
-fi
-
-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 << 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 ()
-{
-
-  ;
-  return 0;
-}
-_ACEOF
-	 if ac_fn_c_try_compile "$LINENO"; then :
-  break
-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
-fi
-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_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 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
-  while :; do
-  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 ()
-{
-
-  ;
-  return 0;
-}
-_ACEOF
-if ac_fn_c_try_compile "$LINENO"; then :
-  ac_cv_sys_file_offset_bits=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 _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];
-int
-main ()
-{
-
-  ;
-  return 0;
-}
-_ACEOF
-if ac_fn_c_try_compile "$LINENO"; then :
-  ac_cv_sys_file_offset_bits=64; break
-fi
-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
-  while :; do
-  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 ()
-{
-
-  ;
-  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 << 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 ()
-{
-
-  ;
-  return 0;
-}
-_ACEOF
-if ac_fn_c_try_compile "$LINENO"; then :
-  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
-
-
-fi
-
-{ $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
-  while :; do
-  cat confdefs.h - <<_ACEOF >conftest.$ac_ext
-/* end confdefs.h.  */
-#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=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
-
-
-for ac_header in sys/ioccom.h sys/select.h sys/sockio.h limits.h
+for ac_header in sys/ioccom.h sys/sockio.h limits.h
 do :
   as_ac_Header=`$as_echo "ac_cv_header_$ac_header" | $as_tr_sh`
 ac_fn_c_check_header_mongrel "$LINENO" "$ac_header" "$as_ac_Header" "$ac_includes_default"
@@ -4744,25 +4868,12 @@
 
 done
 
-for ac_header in linux/types.h
+for ac_header in netpacket/packet.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 :
+  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_LINUX_TYPES_H 1
-_ACEOF
-
-fi
-
-done
-
-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
+#define HAVE_NETPACKET_PACKET_H 1
 _ACEOF
 
 fi
@@ -4818,50 +4929,6 @@
 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>
-"
-if test "x$ac_cv_header_netinet_if_ether_h" = xyes; then :
-  cat >>confdefs.h <<_ACEOF
-#define HAVE_NETINET_IF_ETHER_H 1
-_ACEOF
-
-fi
-
-done
-
-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.
-	#
-	{ $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
-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>
-#include <netinet/in.h>
-struct mbuf;
-struct rtentry;
-#include <net/if.h>
-"
-if test "x$ac_cv_header_netinet_if_ether_h" = xyes; then :
-  cat >>confdefs.h <<_ACEOF
-#define HAVE_NETINET_IF_ETHER_H 1
-_ACEOF
-
-fi
-
-done
-
-fi
 
 case "$host_os" in
 linux*|uclinux*)
@@ -4931,7 +4998,7 @@
 	    fi
     fi
 
-for ac_func in strerror strlcpy
+for ac_func in strerror strerror_r strerror_s strlcpy strlcat
 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"
@@ -4992,77 +5059,61 @@
 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
-# "gethostbyname() -ish function".
+# "getaddrinfo()-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 :
-  $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 gethostbyname ();
-int
-main ()
-{
-return gethostbyname ();
-  ;
-  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
-fi
-rm -f core conftest.err conftest.$ac_objext \
-    conftest$ac_exeext
-  if ${ac_cv_search_gethostbyname+:} false; then :
-  break
-fi
-done
-if ${ac_cv_search_gethostbyname+:} false; then :
+    #
+    # 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
-  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"
 
-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 :
+	#
+	# 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
   ac_check_lib_save_LIBS=$LIBS
@@ -5076,93 +5127,54 @@
 #ifdef __cplusplus
 extern "C"
 #endif
-char gethostbyname ();
+char getaddrinfo ();
 int
 main ()
 {
-return gethostbyname ();
+return getaddrinfo ();
   ;
   return 0;
 }
 _ACEOF
 if ac_fn_c_try_link "$LINENO"; then :
-  ac_cv_lib_socket_gethostbyname=yes
+  ac_cv_lib_socket_getaddrinfo=yes
 else
-  ac_cv_lib_socket_gethostbyname=no
+  ac_cv_lib_socket_getaddrinfo=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"
-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 :
 
-    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 :
+	    #
+	    # OK, we found it in libsocket.
+	    #
+	    LIBS="-lsocket -lnsl $LIBS"
 
 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 :
+	    #
+	    # 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="-lsocket -lnsl $LIBS"
+LIBS="-lxnet -lsocket -lnsl $LIBS"
 cat confdefs.h - <<_ACEOF >conftest.$ac_ext
 /* end confdefs.h.  */
 
@@ -5172,30 +5184,36 @@
 #ifdef __cplusplus
 extern "C"
 #endif
-char socket ();
+char recvmsg ();
 int
 main ()
 {
-return socket ();
+return recvmsg ();
   ;
   return 0;
 }
 _ACEOF
 if ac_fn_c_try_link "$LINENO"; then :
-  ac_cv_lib_socket_socket=yes
+  ac_cv_lib_xnet_recvmsg=yes
 else
-  ac_cv_lib_socket_socket=no
+  ac_cv_lib_xnet_recvmsg=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"
+{ $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
@@ -5258,13 +5276,267 @@
 
 
 #
+# 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_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_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.  */
+#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, 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.)
+# 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.
 #
@@ -5281,20 +5553,135 @@
 
 if test "$ac_cv_func_ether_hostton" = yes; then
 	#
-	# OK, we have ether_hostton().  Do we have <netinet/if_ether.h>?
+	# OK, we have ether_hostton().  Is it declared in <net/ethernet.h>?
 	#
-	if test "$ac_cv_header_netinet_if_ether_h" = yes; then
+	# 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
 		#
-		# Yes.  Does it declare 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().
+		#
+		# 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>
 #include <sys/socket.h>
-#include <netinet/in.h>
-#include <arpa/inet.h>
-struct mbuf;
-struct rtentry;
 #include <net/if.h>
+#include <netinet/in.h>
 #include <netinet/if_ether.h>
 
 "
@@ -5308,63 +5695,27 @@
 
 	fi
 	#
-	# Did that succeed?
+	# After all that, is ether_hostton() declared?
 	#
-	if test "$ac_cv_have_decl_ether_hostton" != yes; then
+	if test "$ac_cv_have_decl_ether_hostton" = yes; then
 		#
-		# No, how about <netinet/ether.h>, as on Linux?
+		# Yes.
 		#
-		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
+$as_echo "#define HAVE_DECL_ETHER_HOSTTON 1" >>confdefs.h
 
-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>
-
-"
-if test "x$ac_cv_have_decl_ether_hostton" = xyes; then :
-
-
-$as_echo "#define NETINET_ETHER_H_DECLARES_ETHER_HOSTTON /**/" >>confdefs.h
-
-
-fi
-
-		fi
-	fi
-	#
-	# Is ether_hostton() declared?
-	#
-	if test "$ac_cv_have_decl_ether_hostton" != yes; then
+        else
 		#
 		# No, we'll have to declare it ourselves.
-		# Do we have "struct ether_addr"?
+		# 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 <netinet/in.h>
-#include <arpa/inet.h>
-struct mbuf;
-struct rtentry;
-#include <net/if.h>
-#include <netinet/if_ether.h>
+			#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 :
@@ -5376,16 +5727,153 @@
 
 fi
 
-
-$as_echo "#define HAVE_DECL_ETHER_HOSTTON 0" >>confdefs.h
-
-	else
-
-$as_echo "#define HAVE_DECL_ETHER_HOSTTON 1" >>confdefs.h
-
 	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_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_exeext conftest.$ac_ext
+LIBS=$ac_check_lib_save_LIBS
+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"
+
+else
+
+			#
+			# 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
+  ac_check_lib_save_LIBS=$LIBS
+LIBS="-lpthread  $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_link "$LINENO"; then :
+  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.
@@ -5412,7 +5900,7 @@
 # only tests with BPF and PF_PACKET sockets; only enable it if
 # we have BPF or PF_PACKET sockets.
 #
-VALGRINDTEST=
+VALGRINDTEST_SRC=
 
 #
 # SITA support is mutually exclusive with native capture support;
@@ -5433,80 +5921,209 @@
 
 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
 
 # Check whether --with-pcap was given.
 if test "${with_pcap+set}" = set; then :
   withval=$with_pcap;
 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
-
-
-	#
-	# We have BPF, so build valgrindtest with "make test".
-	#
-	VALGRINDTEST=valgrindtest
-elif test -r /dev/bpf0 ; then
-	V_PCAP=bpf
-
-	#
-	# We have BPF, so build valgrindtest with "make test".
-	#
-	VALGRINDTEST=valgrindtest
-elif test -r /usr/include/net/pfilt.h ; then
-	V_PCAP=pf
-elif test -r /dev/enet ; then
-	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
-
-	#
-	# XXX - this won't work with older kernels that have SOCK_PACKET
-	# sockets but not PF_PACKET sockets.
-	#
-	VALGRINDTEST=valgrindtest
-elif test -r /usr/include/net/raw.h ; then
-	V_PCAP=snoop
-elif test -r /usr/include/odmi.h ; then
-	#
-	# 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
-
-	#
-	# We have BPF, so build valgrindtest with "make test".
-	#
-	VALGRINDTEST=valgrindtest
-elif test -r /usr/include/sys/dlpi.h ; then
-	V_PCAP=dlpi
-elif test -c /dev/enet ; then		# check again in case not readable
-	V_PCAP=enet
-elif test -c /dev/nit ; then		# check again in case not readable
-	V_PCAP=snit
 else
-	V_PCAP=null
+	#
+	# 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/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.  */
+
+#include <sys/types.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 ()
+{
+u_int i = BIOCSETIF;
+  ;
+  return 0;
+}
+_ACEOF
+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_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
+
+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
+
+fi
+
+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; }
 
@@ -5640,73 +6257,25 @@
 	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.
+	# 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.
 	#
-	{ $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_n "(cached) " >&6
-else
-  cat confdefs.h - <<_ACEOF >conftest.$ac_ext
-/* end confdefs.h.  */
+	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>
 
-#       include <sys/types.h>
-#       include <sys/dlpi.h>
-int
-main ()
-{
-u_int i = sizeof(dl_passive_req_t)
-  ;
-  return 0;
-}
+"
+if test "x$ac_cv_type_dl_passive_req_t" = xyes; then :
+
+cat >>confdefs.h <<_ACEOF
+#define HAVE_DL_PASSIVE_REQ_T 1
 _ACEOF
-if ac_fn_c_try_compile "$LINENO"; then :
-  ac_cv_lbl_has_dl_passive_req_t=yes
-else
-  ac_cv_lbl_has_dl_passive_req_t=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_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)
@@ -5738,6 +6307,8 @@
 # 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
 
 
@@ -5746,10 +6317,18 @@
 
                 incdir=-I/usr/include/libnl3
                 libnldir=
-                if test x$withval != x ; then
-                  libnldir=-L${withval}/lib/.libs
-                  incdir=-I${withval}/include
-                fi
+                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.
@@ -5959,73 +6538,50 @@
 
 done
 
-	{ $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 :
-  $as_echo_n "(cached) " >&6
-else
-  cat confdefs.h - <<_ACEOF >conftest.$ac_ext
-/* end confdefs.h.  */
 
-#  include <linux/if_packet.h>
-int
-main ()
-{
-struct tpacket_stats stats
-  ;
-  return 0;
-}
+	#
+	# 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
-if ac_fn_c_try_compile "$LINENO"; then :
-  ac_cv_lbl_tpacket_stats=yes
-else
-  ac_cv_lbl_tpacket_stats=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_tpacket_stats" >&5
-$as_echo "$ac_cv_lbl_tpacket_stats" >&6; }
-   if test $ac_cv_lbl_tpacket_stats = yes; then
 
-$as_echo "#define HAVE_TPACKET_STATS 1" >>confdefs.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_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>
 
-   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.  */
+"
+if test "x$ac_cv_member_struct_tpacket_auxdata_tp_vlan_tci" = xyes; then :
 
-#	include <sys/types.h>
-#	include <linux/if_packet.h>
-int
-main ()
-{
-u_int i = sizeof(((struct tpacket_auxdata *)0)->tp_vlan_tci)
-  ;
-  return 0;
-}
+cat >>confdefs.h <<_ACEOF
+#define HAVE_STRUCT_TPACKET_AUXDATA_TP_VLAN_TCI 1
 _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
 
-    { $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_LINUX_TPACKET_AUXDATA_TP_VLAN_TCI 1" >>confdefs.h
-
-    fi
 	;;
 
 bpf)
@@ -6045,46 +6601,16 @@
 done
 
 
-	{ $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>
-int
-main ()
-{
-return (BIOCROTZBUF + BPF_BUFMODE_ZBUF);
-  ;
-  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_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>
+	#
+	# 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 :
@@ -6126,10 +6652,10 @@
 	;;
 
 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;}
+	;;
+
+*)
+	as_fn_error $? "$V_PCAP is not a valid pcap type" "$LINENO" 5
 	;;
 esac
 
@@ -6171,33 +6697,34 @@
 else
 
 		#
-		# Well, we don't have "getifaddrs()", so we have to use
-		# some other mechanism; determine what that mechanism is.
+		# 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.
 		#
-		# The first thing we use is the type of capture mechanism,
-		# which is somewhat of a proxy for the OS we're using.
+		# 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.
 		#
-		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
+		# 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 :
+		if ${ac_cv_lbl_have_siocglifconf+:} false; then :
   $as_echo_n "(cached) " >&6
 else
   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>
+			#include <sys/file.h>
+			#include <sys/ioctl.h>
+			#include <sys/socket.h>
+			#include <sys/sockio.h>
 int
 main ()
 {
@@ -6214,119 +6741,91 @@
 rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
 fi
 
-			{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lbl_have_siocglifconf" >&5
+		{ $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
-			;;
-
-		*)
-			#
-			# Assume we just have SIOCGIFCONF.
-			# (XXX - on at least later Linux kernels, there's
-			# another mechanism, and we should be using that
-			# instead.)
-			#
+		if test $ac_cv_lbl_have_siocglifconf = yes ; then
+			V_FINDALLDEVS=fad-glifc.c
+		else
 			V_FINDALLDEVS=fad-gifc.c
-			;;
-		esac
-fi
-
-fi
-
-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.  */
-
-	#include <sys/types.h>
-	#include <sys/socket.h>
-
-int
-main ()
-{
- socklen_t x;
-  ;
-  return 0;
-}
-_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
-
-$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
-
-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 :
-
-
-$as_echo "#define INET6 1" >>confdefs.h
-
-
-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
 
 fi
 
-{ $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; }
-# Check whether --enable-optimizer-dbg was given.
-if test "${enable_optimizer_dbg+set}" = set; then :
-  enableval=$enable_optimizer_dbg;
 fi
 
-if test "$enable_optimizer_dbg" = "yes"; then
 
-$as_echo "#define BDEBUG 1" >>confdefs.h
+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
+_ACEOF
 
 fi
-{ $as_echo "$as_me:${as_lineno-$LINENO}: result: ${enable_optimizer_dbg-no}" >&5
-$as_echo "${enable_optimizer_dbg-no}" >&6; }
 
-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether to build parser debugging code" >&5
-$as_echo_n "checking whether to build parser debugging code... " >&6; }
-# Check whether --enable-yydebug was given.
-if test "${enable_yydebug+set}" = set; then :
-  enableval=$enable_yydebug;
+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
+
+# Check whether --enable-packet-ring was given.
+if test "${enable_packet_ring+set}" = set; then :
+  enableval=$enable_packet_ring;
+else
+  enable_packet_ring=yes
 fi
 
-if test "$enable_yydebug" = "yes"; then
 
-$as_echo "#define YYDEBUG 1" >>confdefs.h
+if test "x$enable_packet_ring" != "xno" ; then
+
+$as_echo "#define PCAP_SUPPORT_PACKET_RING 1" >>confdefs.h
+
 
 fi
-{ $as_echo "$as_me:${as_lineno-$LINENO}: result: ${enable_yydebug-no}" >&5
-$as_echo "${enable_yydebug-no}" >&6; }
+
+#
+# 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_type_socklen_t" = xyes; then :
+
+cat >>confdefs.h <<_ACEOF
+#define HAVE_SOCKLEN_T 1
+_ACEOF
+
+
+fi
+
+
+# Check whether --enable-ipv6 was given.
+if test "${enable_ipv6+set}" = set; then :
+  enableval=$enable_ipv6;
+else
+  enable_ipv6=yes
+fi
+
+if test "$enable_ipv6" != "no"; then
+	#
+	# We've already made sure we have getaddrinfo above in
+	# AC_LBL_LIBRARY_NET.
+	#
+
+$as_echo "#define INET6 1" >>confdefs.h
+
+fi
 
 # Check for Endace DAG card support.
 
@@ -6389,12 +6888,8 @@
 fi
 
 
-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
@@ -6408,25 +6903,28 @@
 		dag_lib_dir="$dag_root/lib"
 	fi
 
-	if test -z "$dag_tools_dir"; then
-		dag_tools_dir="$dag_root/tools"
-	fi
+	V_INCLS="$V_INCLS -I$dag_include_dir"
 
-	if test -r $dag_include_dir/dagapi.h; then
-		ac_cv_lbl_dag_api=yes
-	fi
+	for ac_header in dagapi.h
+do :
+  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 HAVE_DAGAPI_H 1
+_ACEOF
 
-	if test "$ac_cv_lbl_dag_api" = yes; then
-		{ $as_echo "$as_me:${as_lineno-$LINENO}: result: yes ($dag_include_dir)" >&5
-$as_echo "yes ($dag_include_dir)" >&6; }
+fi
 
-		V_INCLS="$V_INCLS -I$dag_include_dir"
+done
+
+
+	if test "$ac_cv_header_dagapi_h" = yes; then
 
 		if test $V_PCAP != dag ; then
 			 SSRC="$SSRC pcap-dag.c"
 		fi
 
-		# See if we can find a general version string.
+		# 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
@@ -6468,9 +6966,56 @@
 { $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"
+  cat >>confdefs.h <<_ACEOF
+#define HAVE_LIBDAG 1
+_ACEOF
+
+  LIBS="-ldag $LIBS"
+
 else
-  dag_streams="0"
+  as_fn_error $? "DAG library lacks streams support" "$LINENO" 5
+fi
+
+		{ $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
+  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_stream64 ();
+int
+main ()
+{
+return dag_attach_stream64 ();
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_c_try_link "$LINENO"; then :
+  ac_cv_lib_dag_dag_attach_stream64=yes
+else
+  ac_cv_lib_dag_dag_attach_stream64=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_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}: checking for dag_get_erf_types in -ldag" >&5
@@ -6562,12 +7107,17 @@
 
 		LDFLAGS=$saved_ldflags
 
-		if test "$dag_streams" = 1; then
+		#
+		# 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"
 
-$as_echo "#define HAVE_DAG_STREAMS_API 1" >>confdefs.h
+		if test "$dag_large_streams" = 1; then
 
-			LIBS="$LIBS -ldag"
-			LDFLAGS="$LDFLAGS -L$dag_lib_dir"
+$as_echo "#define HAVE_DAG_LARGE_STREAMS_API 1" >>confdefs.h
 
 			{ $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; }
@@ -6615,7 +7165,10 @@
 
 $as_echo "#define HAVE_DAG_VDAG 1" >>confdefs.h
 
-				LIBS="$LIBS -lpthread"
+				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
 
@@ -6623,8 +7176,6 @@
 $as_echo "#define HAVE_DAG_API 1" >>confdefs.h
 
 	else
-		{ $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
-$as_echo "no" >&6; }
 
 		if test "$V_PCAP" = dag; then
 			# User requested "dag" capture type but we couldn't
@@ -6980,6 +7531,182 @@
 	fi
 fi
 
+{ $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
+  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
+
+		#
+		# No.  Do we have it in -lcrypt?
+		#
+		{ $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
+  ac_check_lib_save_LIBS=$LIBS
+LIBS="-lcrypt  $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 crypt ();
+int
+main ()
+{
+return crypt ();
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_c_try_link "$LINENO"; then :
+  ac_cv_lib_crypt_crypt=yes
+else
+  ac_cv_lib_crypt_crypt=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_crypt_crypt" >&5
+$as_echo "$ac_cv_lib_crypt_crypt" >&6; }
+if test "x$ac_cv_lib_crypt_crypt" = xyes; then :
+
+			#
+			# Yes; add -lcrypt to the libraries for rpcapd.
+			#
+			RPCAPD_LIBS="$RPCAPD_LIBS -lcrypt"
+
+else
+
+			as_fn_error $? "rpcapd requires crypt(), but we didn't find it" "$LINENO" 5
+
+fi
+
+
+fi
+
+
+	#
+	# 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
+
+fi
+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
+
+
+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 "x$ac_cv_member_struct_msghdr_msg_flags" = xyes; then :
+
+cat >>confdefs.h <<_ACEOF
+#define HAVE_STRUCT_MSGHDR_MSG_FLAGS 1
+_ACEOF
+
+
+fi
+
+
+
+$as_echo "#define ENABLE_REMOTE /**/" >>confdefs.h
+
+	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; }
+# Check whether --enable-optimizer-dbg was given.
+if test "${enable_optimizer_dbg+set}" = set; then :
+  enableval=$enable_optimizer_dbg;
+fi
+
+if test "$enable_optimizer_dbg" = "yes"; then
+
+$as_echo "#define BDEBUG 1" >>confdefs.h
+
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: ${enable_optimizer_dbg-no}" >&5
+$as_echo "${enable_optimizer_dbg-no}" >&6; }
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether to build parser debugging code" >&5
+$as_echo_n "checking whether to build parser debugging code... " >&6; }
+# Check whether --enable-yydebug was given.
+if test "${enable_yydebug+set}" = set; then :
+  enableval=$enable_yydebug;
+fi
+
+if test "$enable_yydebug" = "yes"; then
+
+$as_echo "#define YYDEBUG 1" >>confdefs.h
+
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: ${enable_yydebug-no}" >&5
+$as_echo "${enable_yydebug-no}" >&6; }
+
 #
 # Look for {f}lex.
 #
@@ -7234,17 +7961,22 @@
 $as_echo "$tcpdump_cv_capable_yacc" >&6; }
 if test $tcpdump_cv_capable_yacc = insufficient ; then
 	as_fn_error $? "$YACC is insufficient to compile libpcap.
- libpcap requires Bison, Berkeley YACC, or another YACC compatible with them." "$LINENO" 5
+ libpcap requires Bison, a newer version of Berkeley YACC with support
+ for reentrant parsers, or another YACC compatible with them." "$LINENO" 5
 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).
+# 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 (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_FILE_FORMATS=5
 MAN_MISC_INFO=7
+MAN_ADMIN_COMMANDS=8
 case "$host_os" in
 
 aix*)
@@ -7389,6 +8121,7 @@
 	#
 	# Use System V conventions for man pages.
 	#
+	MAN_ADMIN_COMMANDS=1m
 	MAN_FILE_FORMATS=4
 	MAN_MISC_INFO=5
 	;;
@@ -7398,6 +8131,7 @@
 	#
 	# Use System V conventions for man pages.
 	#
+	MAN_ADMIN_COMMANDS=1m
 	MAN_FILE_FORMATS=4
 	MAN_MISC_INFO=5
 	;;
@@ -7407,6 +8141,7 @@
 	#
 	# Use System V conventions for man pages.
 	#
+	MAN_ADMIN_COMMANDS=1m
 	MAN_FILE_FORMATS=4
 	MAN_MISC_INFO=5
 	;;
@@ -7436,7 +8171,9 @@
 
 irix*)
 	#
-	# Use System V conventions for man pages.
+	# 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
@@ -7458,7 +8195,10 @@
 	DYEXT="so"
 
 	#
-	# Use System V conventions for man pages.
+	# 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
@@ -7504,11 +8244,30 @@
 
 
 	DYEXT="so"
+
 	#
-	# Use System V conventions for man pages.
+	# 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).
 	#
-	MAN_FILE_FORMATS=4
-	MAN_MISC_INFO=5
+	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
+	esac
 	;;
 esac
 
@@ -7793,8 +8552,47 @@
 
 		{ $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"
-		V_CCOPT="$V_CCOPT -Wall"
+		if test x"$can_add_to_cflags" = "xyes"
+		then
+		    V_CCOPT="$V_CCOPT -Wall"
+		fi
 
 else
 
@@ -7836,8 +8634,47 @@
 
 		{ $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
+
+			#
+			# 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 -Wsign-compare"
+		if test x"$can_add_to_cflags" = "xyes"
+		then
+		    V_CCOPT="$V_CCOPT -Wsign-compare"
+		fi
 
 else
 
@@ -7879,8 +8716,47 @@
 
 		{ $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.  */
+
+_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 -Wmissing-prototypes"
+		fi
 
 else
 
@@ -7922,8 +8798,47 @@
 
 		{ $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 -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
+
+			#
+			# 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 -Wstrict-prototypes"
+		fi
 
 else
 
@@ -7965,8 +8880,47 @@
 
 		{ $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
+
+			#
+			# 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 -Wshadow"
+		if test x"$can_add_to_cflags" = "xyes"
+		then
+		    V_CCOPT="$V_CCOPT -Wshadow"
+		fi
 
 else
 
@@ -8008,8 +8962,47 @@
 
 		{ $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 -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; }
+			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 -Wdeclaration-after-statement"
+		if test x"$can_add_to_cflags" = "xyes"
+		then
+		    V_CCOPT="$V_CCOPT -Wdeclaration-after-statement"
+		fi
 
 else
 
@@ -8051,8 +9044,655 @@
 
 		{ $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 -Wused-but-marked-unused"
+		if test x"$can_add_to_cflags" = "xyes"
+		then
+		    V_CCOPT="$V_CCOPT -Wused-but-marked-unused"
+		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 -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.  */
+
+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 -Wdocumentation " >&5
+$as_echo_n "checking whether -Wdocumentation ... " >&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 -Wdocumentation"
+		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
+
+else
+
+		{ $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+		CFLAGS="$save_CFLAGS"
+
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+
+
+	{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether the compiler supports the -Wmissing-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 ()
+{
+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 -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
+
+			#
+			# 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 -Wmissing-noreturn"
+		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
+
+		    # Warns about safeguards added in case the enums are
+		    # extended
+		    # AC_LBL_CHECK_COMPILER_OPT(V_CCOPT, -Wcovered-switch-default)
+
+	{ $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.  */
+
+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 -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; }
+
+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 -Wmissing-variable-declarations"
+		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 -Wunused-parameter option" >&5
+$as_echo_n "checking whether the compiler supports the -Wunused-parameter option... " >&6; }
+	save_CFLAGS="$CFLAGS"
+	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.  */
+
+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 -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"
+		if test x"$can_add_to_cflags" = "xyes"
+		then
+		    V_CCOPT="$V_CCOPT -Wunused-parameter"
+		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 -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.  */
+
+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 -Wformat-nonliteral " >&5
+$as_echo_n "checking whether -Wformat-nonliteral ... " >&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 -Wformat-nonliteral"
+		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
+
+		    #
+		    # 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 -Wunreachable-code option" >&5
+$as_echo_n "checking whether the compiler supports the -Wunreachable-code option... " >&6; }
+	save_CFLAGS="$CFLAGS"
+	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.  */
+
+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 "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"
+		if test x"$can_add_to_cflags" = "xyes"
+		then
+		    V_CCOPT="$V_CCOPT -Wunreachable-code"
+		fi
 
 else
 
@@ -8135,8 +9775,11 @@
 /* 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"
@@ -8148,7 +9791,7 @@
 			# We can't run mkdep, so have "make depend" do
 			# nothing.
 			#
-			MKDEP=:
+			MKDEP='${srcdir}/nomkdep'
 		fi
 		rm -rf conftest*
 	else
@@ -8158,7 +9801,7 @@
 		# We can't run mkdep, so have "make depend" do
 		# nothing.
 		#
-		MKDEP=:
+		MKDEP='${srcdir}/nomkdep'
 	fi
 
 
@@ -8184,108 +9827,68 @@
 	    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
+#
+# 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>
 
-    fi
+"
+if test "x$ac_cv_type_struct_sockaddr_storage" = xyes; then :
 
-{ $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.  */
-
-#	include <sys/types.h>
-#	include <sys/socket.h>
-int
-main ()
-{
-u_int i = sizeof (struct sockaddr_storage)
-  ;
-  return 0;
-}
+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
+#
+# 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>
 
-    fi
+"
+if test "x$ac_cv_member_dl_hp_ppa_info_t_dl_module_id_1" = xyes; then :
 
-{ $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.  */
-
-#	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;
-}
+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
 
 { $as_echo "$as_me:${as_lineno-$LINENO}: checking if unaligned accesses fail" >&5
 $as_echo_n "checking if unaligned accesses fail... " >&6; }
@@ -8382,8 +9985,12 @@
 
     fi
 
-rm -f net
-ln -s ${srcdir}/bpf/net net
+
+
+
+
+
+
 
 
 
@@ -8493,45 +10100,23 @@
 	  # "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 :
-  $as_echo_n "(cached) " >&6
-else
-  cat confdefs.h - <<_ACEOF >conftest.$ac_ext
-/* end confdefs.h.  */
+	  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>
 
-$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>
-int
-main ()
-{
-u_int i = sizeof(((struct usbdevfs_ctrltransfer *)0)->bRequestType)
-  ;
-  return 0;
-}
+"
+if test "x$ac_cv_member_struct_usbdevfs_ctrltransfer_bRequestType" = xyes; then :
+
+cat >>confdefs.h <<_ACEOF
+#define HAVE_STRUCT_USBDEVFS_CTRLTRANSFER_BREQUESTTYPE 1
 _ACEOF
-if ac_fn_c_try_compile "$LINENO"; then :
-  ac_cv_usbdevfs_ctrltransfer_has_bRequestType=yes
-else
-  ac_cv_usbdevfs_ctrltransfer_has_bRequestType=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 "#define HAVE_USBDEVFS_CTRLTRANSFER_BREQUESTTYPE 1" >>confdefs.h
-
-	    fi
 	fi
 	;;
     freebsd*)
@@ -8619,6 +10204,61 @@
 
 
 
+# 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 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 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
+#define NETMAP_WITH_LIBS
+#include <net/netmap_user.h>
+int
+main ()
+{
+
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+  ac_cv_net_netmap_user_can_compile=yes
+else
+  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_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_NETMAP 1" >>confdefs.h
+
+	    NETMAP_SRC=pcap-netmap.c
+	fi
+
+
+fi
+
+
 # Check whether --enable-bluetooth was given.
 if test "${enable_bluetooth+set}" = set; then :
   enableval=$enable_bluetooth;
@@ -8639,112 +10279,102 @@
 		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
+
+					    { $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
+
 
 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
+else
+
+			#
+			# 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
+			fi
+
+fi
+
+
 		;;
 	*)
 		if test "x$enable_bluetooth" = "xyes" ; then
-		    as_fn_error $? "no Bluetooth sniffing support implemented for $host_os" "$LINENO" 5
+			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:${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
 		;;
@@ -8774,20 +10404,20 @@
 
 		darwin*)
 			#
-			# We don't support D-Bus sniffing on OS X; see
+			# 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.
 			#
-			as_fn_error $? "Due to freedesktop.org bug 74029, D-Bus capture support is not available on OS X" "$LINENO" 5
+			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 OS X; see
+			# We don't support D-Bus sniffing on macOS; see
 			#
 			# https://bugs.freedesktop.org/show_bug.cgi?id=74029
 			#
@@ -8904,38 +10534,117 @@
 
 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
-_ACEOF
-
-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
-
-# Check whether --enable-packet-ring was given.
-if test "${enable_packet_ring+set}" = set; then :
-  enableval=$enable_packet_ring;
+# Check whether --enable-rdma was given.
+if test "${enable_rdma+set}" = set; then :
+  enableval=$enable_rdma;
 else
-  enable_packet_ring=yes
+  enable_rdmasniff=ifavailable
 fi
 
 
-if test "x$enable_packet_ring" != "xno" ; then
+if test "xxx_only" = yes; then
+	# User requested something-else-only pcap, so they don't
+	# want RDMA support.
+	enable_rdmasniff=no
+fi
 
-$as_echo "#define PCAP_SUPPORT_PACKET_RING 1" >>confdefs.h
+if test "x$enable_rdmasniff" != "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
+
+
+
+fi
+
 
 
 fi
@@ -9039,7 +10748,7 @@
 
 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_tstamp_precision.3pcap pcap_set_tstamp_type.3pcap rpcapd/Makefile rpcapd/rpcapd.manadmin testprogs/Makefile"
 
 cat >confcache <<\_ACEOF
 # This file is a shell script that caches the results of configure
@@ -9547,7 +11256,7 @@
 # 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.0-PRE-GIT, which was
 generated by GNU Autoconf 2.69.  Invocation command line was
 
   CONFIG_FILES    = $CONFIG_FILES
@@ -9613,7 +11322,7 @@
 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.0-PRE-GIT
 configured by $0, generated by GNU Autoconf 2.69,
   with options \\"\$ac_cs_config\\"
 
@@ -9758,6 +11467,9 @@
     "pcap_open_offline.3pcap") CONFIG_FILES="$CONFIG_FILES pcap_open_offline.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" ;;
+    "testprogs/Makefile") CONFIG_FILES="$CONFIG_FILES testprogs/Makefile" ;;
 
   *) as_fn_error $? "invalid argument: \`$ac_config_target'" "$LINENO" 5;;
   esac
@@ -10315,7 +12027,7 @@
   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
index da2f940..eff6eb8 100644
--- a/configure.ac
+++ b/configure.ac
@@ -14,80 +14,23 @@
 # config.sub.
 #
 
-AC_PREREQ(2.61)
-AC_INIT(pcap.c)
+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)
-AC_PROG_CC
+#
+# Try to enable as many C99 features as we can.
+# At minimum, we want C++/C99-style // comments.
+#
+AC_PROG_CC_C99
 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.
@@ -104,9 +47,8 @@
 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/select.h sys/sockio.h limits.h)
-AC_CHECK_HEADERS(linux/types.h)
-AC_CHECK_HEADERS(linux/if_packet.h netpacket/packet.h netpacket/if_packet.h)
+AC_CHECK_HEADERS(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>])
@@ -128,25 +70,6 @@
 	    ],
 	    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
 
 case "$host_os" in
 linux*|uclinux*)
@@ -160,7 +83,7 @@
 
 AC_LBL_FIXINCLUDES
 
-AC_CHECK_FUNCS(strerror strlcpy)
+AC_CHECK_FUNCS(strerror strerror_r strerror_s strlcpy strlcat)
 
 needsnprintf=no
 AC_CHECK_FUNCS(vsnprintf snprintf,,
@@ -177,31 +100,298 @@
 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
-# "gethostbyname() -ish function".
+# "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, 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.)
+# 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().  Do we have <netinet/if_ether.h>?
+	# OK, we have ether_hostton().  Is it declared in <net/ethernet.h>?
 	#
-	if test "$ac_cv_header_netinet_if_ether_h" = yes; then
+	# 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
 		#
-		# Yes.  Does it declare 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().
+		#
+		# 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,,
@@ -210,69 +400,94 @@
 		    [
 #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/in.h>
 #include <netinet/if_ether.h>
 		    ])
 	fi
 	#
-	# Did that succeed?
+	# After all that, is ether_hostton() declared?
 	#
-	if test "$ac_cv_have_decl_ether_hostton" != yes; then
+	if test "$ac_cv_have_decl_ether_hostton" = yes; then
 		#
-		# No, how about <netinet/ether.h>, as on Linux?
+		# Yes.
 		#
-		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
+		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"?
+		# 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 <netinet/in.h>
-#include <arpa/inet.h>
-struct mbuf;
-struct rtentry;
-#include <net/if.h>
-#include <netinet/if_ether.h>
+			#include <sys/types.h>
+			#include <sys/socket.h>
+			#include <net/if.h>
+			#include <netinet/in.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
 
+#
+# 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,
@@ -293,7 +508,7 @@
 # only tests with BPF and PF_PACKET sockets; only enable it if
 # we have BPF or PF_PACKET sockets.
 #
-VALGRINDTEST=
+VALGRINDTEST_SRC=
 
 #
 # SITA support is mutually exclusive with native capture support;
@@ -309,83 +524,139 @@
 	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])
-
-	#
-	# We have BPF, so build valgrindtest with "make test".
-	#
-	VALGRINDTEST=valgrindtest
-elif test -r /dev/bpf0 ; then
-	V_PCAP=bpf
-
-	#
-	# We have BPF, so build valgrindtest with "make test".
-	#
-	VALGRINDTEST=valgrindtest
-elif test -r /usr/include/net/pfilt.h ; then
-	V_PCAP=pf
-elif test -r /dev/enet ; then
-	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
-
-	#
-	# XXX - this won't work with older kernels that have SOCK_PACKET
-	# sockets but not PF_PACKET sockets.
-	#
-	VALGRINDTEST=valgrindtest
-elif test -r /usr/include/net/raw.h ; then
-	V_PCAP=snoop
-elif test -r /usr/include/odmi.h ; then
-	#
-	# 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
-
-	#
-	# We have BPF, so build valgrindtest with "make test".
-	#
-	VALGRINDTEST=valgrindtest
-elif test -r /usr/include/sys/dlpi.h ; then
-	V_PCAP=dlpi
-elif test -c /dev/enet ; then		# check again in case not readable
-	V_PCAP=enet
-elif test -c /dev/nit ; then		# check again in case not readable
-	V_PCAP=snit
 else
-	V_PCAP=null
+	#
+	# 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/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/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)
+AC_SUBST(VALGRINDTEST_SRC)
 
 #
 # Do capture-mechanism-dependent tests.
@@ -445,29 +716,16 @@
 	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.
+	# 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_LBL_DL_PASSIVE_REQ_T
+	AC_CHECK_TYPES(dl_passive_req_t,,,
+	    [
+		#include <sys/types.h>
+		#include <sys/dlpi.h>
+	    ])
 	;;
 
 linux)
@@ -486,17 +744,25 @@
 	#
 	AC_ARG_WITH(libnl,
 	AC_HELP_STRING([--without-libnl],[disable libnl support @<:@default=yes, on Linux, if present@:>@]),
-		with_libnl=$withval,,)
+		with_libnl=$withval,with_libnl=if_available)
 
 	if test x$with_libnl != xno ; then
 		have_any_nl="no"
 
                 incdir=-I/usr/include/libnl3
                 libnldir=
-                if test x$withval != x ; then
-                  libnldir=-L${withval}/lib/.libs
-                  incdir=-I${withval}/include
-                fi
+                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.
@@ -563,8 +829,32 @@
 AC_INCLUDES_DEFAULT
 #include <linux/types.h>
 	    ])
-	AC_LBL_TPACKET_STATS
-	AC_LBL_LINUX_TPACKET_AUXDATA_TP_VLAN_TCI
+
+	#
+	# 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)
@@ -573,32 +863,18 @@
 	#
 	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);],
+	#
+	# Check whether we have struct BPF_TIMEVAL.
+	#
+	AC_CHECK_TYPES(struct BPF_TIMEVAL,,,
 	    [
-		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>
-		    ])
+		#include <sys/types.h>
+		#include <sys/ioctl.h>
+		#ifdef HAVE_SYS_IOCCOM_H
+		#include <sys/ioccom.h>
+		#endif
+		#include <net/bpf.h>
+	    ])
 	;;
 
 dag)
@@ -629,8 +905,10 @@
 	;;
 
 null)
-	AC_MSG_WARN(cannot determine packet capture interface)
-	AC_MSG_WARN((see the INSTALL doc for more info))
+	;;
+
+*)
+	AC_MSG_ERROR($V_PCAP is not a valid pcap type)
 	;;
 esac
 
@@ -666,98 +944,83 @@
 		])
 	],[
 		#
-		# Well, we don't have "getifaddrs()", so we have to use
-		# some other mechanism; determine what that mechanism is.
+		# 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.
 		#
-		# The first thing we use is the type of capture mechanism,
-		# which is somewhat of a proxy for the OS we're using.
+		# 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.
 		#
-		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=fad-glifc.c
-			else
-				V_FINDALLDEVS=fad-gifc.c
-			fi
-			;;
-
-		*)
-			#
-			# Assume we just have SIOCGIFCONF.
-			# (XXX - on at least later Linux kernels, there's
-			# another mechanism, and we should be using that
-			# instead.)
-			#
+		# 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
-			;;
-		esac])
+		fi
+	])
 fi
 ])
 
-AC_MSG_CHECKING(for socklen_t)
-AC_TRY_COMPILE([
+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>
-	],
-	[ 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@:>@]),
+AC_HELP_STRING([--enable-ipv6],[build IPv6-capable version @<:@default=yes@:>@]),
     [],
-    [enable_ipv6=ifavailable])
+    [enable_ipv6=yes])
 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
-	    ])
+	#
+	# We've already made sure we have getaddrinfo above in
+	# AC_LBL_LIBRARY_NET.
+	#
+	AC_DEFINE(INET6,1,[IPv6])
 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 (located in directory DIR, if supplied).  @<:@default=yes, if present@:>@]),
@@ -808,11 +1071,8 @@
 	dag_lib_dir=$withval
 ],[])
 
-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
@@ -826,29 +1086,25 @@
 		dag_lib_dir="$dag_root/lib"
 	fi
 
-	if test -z "$dag_tools_dir"; then
-		dag_tools_dir="$dag_root/tools"
-	fi
+	V_INCLS="$V_INCLS -I$dag_include_dir"
 
-	if test -r $dag_include_dir/dagapi.h; then
-		ac_cv_lbl_dag_api=yes
-	fi
+	AC_CHECK_HEADERS([dagapi.h])
 
-	if test "$ac_cv_lbl_dag_api" = yes; then
-		AC_MSG_RESULT([yes ($dag_include_dir)])
-
-		V_INCLS="$V_INCLS -I$dag_include_dir"
+	if test "$ac_cv_header_dagapi_h" = yes; then
 
 		if test $V_PCAP != dag ; then
 			 SSRC="$SSRC pcap-dag.c"
 		fi
 
-		# See if we can find a general version string.
+		# 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], [dag_streams="1"], [dag_streams="0"])
+		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], [
@@ -856,21 +1112,28 @@
 
 		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"
+		#
+		# 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()])
-				LIBS="$LIBS -lpthread"
+				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
-		AC_MSG_RESULT(no)
 
 		if test "$V_PCAP" = dag; then
 			# User requested "dag" capture type but we couldn't
@@ -1140,6 +1403,92 @@
 	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.
 #
@@ -1180,17 +1529,22 @@
 	fi)
 if test $tcpdump_cv_capable_yacc = insufficient ; then
 	AC_MSG_ERROR([$YACC is insufficient to compile libpcap.
- libpcap requires Bison, Berkeley YACC, or another YACC compatible with them.])
+ libpcap requires Bison, a newer version of Berkeley YACC with support
+ for reentrant parsers, or another YACC compatible with them.])
 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).
+# 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 (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_FILE_FORMATS=5
 MAN_MISC_INFO=7
+MAN_ADMIN_COMMANDS=8
 case "$host_os" in
 
 aix*)
@@ -1239,7 +1593,7 @@
 	DYEXT="dylib"
 	V_CCOPT="$V_CCOPT -fno-common"
 	AC_ARG_ENABLE(universal,
-	AC_HELP_STRING([--disable-universal],[don't build universal on OS X]))
+	AC_HELP_STRING([--disable-universal],[don't build universal on macOS]))
 	if test "$enable_universal" != "no"; then
 		case "$host_os" in
 
@@ -1327,6 +1681,7 @@
 	#
 	# Use System V conventions for man pages.
 	#
+	MAN_ADMIN_COMMANDS=1m
 	MAN_FILE_FORMATS=4
 	MAN_MISC_INFO=5
 	;;
@@ -1336,6 +1691,7 @@
 	#
 	# Use System V conventions for man pages.
 	#
+	MAN_ADMIN_COMMANDS=1m
 	MAN_FILE_FORMATS=4
 	MAN_MISC_INFO=5
 	;;
@@ -1345,6 +1701,7 @@
 	#
 	# Use System V conventions for man pages.
 	#
+	MAN_ADMIN_COMMANDS=1m
 	MAN_FILE_FORMATS=4
 	MAN_MISC_INFO=5
 	;;
@@ -1378,7 +1735,9 @@
 
 irix*)
 	#
-	# Use System V conventions for man pages.
+	# 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
@@ -1400,7 +1759,10 @@
 	DYEXT="so"
 
 	#
-	# Use System V conventions for man pages.
+	# 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
@@ -1424,11 +1786,30 @@
 	AC_DEFINE(HAVE_SOLARIS,1,[On solaris])
 
 	DYEXT="so"
+
 	#
-	# Use System V conventions for man pages.
+	# 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).
 	#
-	MAN_FILE_FORMATS=4
-	MAN_MISC_INFO=5
+	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
+	esac
 	;;
 esac
 
@@ -1444,23 +1825,51 @@
 
 AC_LBL_DEVEL(V_CCOPT)
 
-AC_LBL_SOCKADDR_SA_LEN
+#
+# 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>
+    ])
 
-AC_LBL_SOCKADDR_STORAGE
+#
+# Check to see if there's a sockaddr_storage structure.
+#
+AC_CHECK_TYPES(struct sockaddr_storage,,,
+    [
+	#include <sys/types.h>
+	#include <sys/socket.h>
+    ])
 
-AC_LBL_HP_PPA_INFO_T_DL_MODULE_ID_1
+#
+# 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
 
-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_CCOPT)
 AC_SUBST(V_SHLIB_CMD)
 AC_SUBST(V_SHLIB_OPT)
 AC_SUBST(V_SONAME_OPT)
@@ -1472,9 +1881,15 @@
 AC_SUBST(DYEXT)
 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 nusb support @<:@default=yes, if support available@:>@])],
+[AC_HELP_STRING([--enable-usb],[enable USB capture support @<:@default=yes, if support available@:>@])],
     [],
     [enable_usb=yes])
 
@@ -1518,25 +1933,14 @@
 	  # "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
+	  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*)
@@ -1582,9 +1986,9 @@
 #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_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,
@@ -1600,6 +2004,38 @@
 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@:>@])],
     [],
@@ -1616,67 +2052,67 @@
 	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)
+		    [
+			#
+			# 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_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
+			#
+			# 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)
+			AC_MSG_ERROR(no Bluetooth sniffing support implemented for $host_os)
 		else
-		    AC_MSG_NOTICE(no Bluetooth sniffing support implemented for $host_os)
+			AC_MSG_NOTICE(no Bluetooth sniffing support implemented for $host_os)
 		fi
 		;;
 	esac
@@ -1702,20 +2138,20 @@
 
 		darwin*)
 			#
-			# We don't support D-Bus sniffing on OS X; see
+			# 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 OS X])
+			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 OS X; see
+			# We don't support D-Bus sniffing on macOS; see
 			#
 			# https://bugs.freedesktop.org/show_bug.cgi?id=74029
 			#
@@ -1774,32 +2210,54 @@
 	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_ARG_ENABLE([rdma],
+[AC_HELP_STRING([--enable-rdma],[enable RDMA capture support @<:@default=yes, if support available@:>@])],
+    [],
+    [enable_rdmasniff=ifavailable])
 
-dnl The packet ring capture facility of Linux, described in
-dnl Documentation/networking/packet_mmap.txt, is not 32/64-bit compatible before
-dnl version 2.6.27. A 32-bit kernel requires a 32-bit userland, and likewise for
-dnl 64-bit. The effect of this is that a 32-bit libpcap binary will not run
-dnl correctly on a 64-bit kernel (the binary will use the wrong offsets into a
-dnl kernel struct). This problem was solved in Linux 2.6.27. Use
-dnl --disable-packet-ring whenever a 32-bit application must run on a 64-bit
-dnl target host, and either the build host or the target host run Linux 2.6.26
-dnl or earlier.
-AC_ARG_ENABLE([packet-ring],
-[AC_HELP_STRING([--enable-packet-ring],[enable Linux packet ring support @<:@default=yes@:>@])],
-,enable_packet_ring=yes)
+if test "xxx_only" = yes; then
+	# User requested something-else-only pcap, so they don't
+	# want RDMA support.
+	enable_rdmasniff=no
+fi
 
-if test "x$enable_packet_ring" != "xno" ; then
-	AC_DEFINE(PCAP_SUPPORT_PACKET_RING, 1, [use Linux packet ring capture if available])
-	AC_SUBST(PCAP_SUPPORT_PACKET_RING)
+if test "x$enable_rdmasniff" != "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
@@ -1808,7 +2266,7 @@
 
 AC_OUTPUT_COMMANDS([if test -f .devel; then
 	echo timestamp > stamp-h
-	cat Makefile-devel-adds >> Makefile
+	cat $srcdir/Makefile-devel-adds >> Makefile
 	make depend
 fi])
 AC_OUTPUT(Makefile pcap-filter.manmisc pcap-linktype.manmisc
@@ -1817,5 +2275,6 @@
 	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)
+	pcap_set_tstamp_type.3pcap rpcapd/Makefile rpcapd/rpcapd.manadmin
+	testprogs/Makefile)
 exit 0
diff --git a/diag-control.h b/diag-control.h
new file mode 100644
index 0000000..cfc581b
--- /dev/null
+++ b/diag-control.h
@@ -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 */
diff --git a/dlpisubs.c b/dlpisubs.c
index fb94a60..5f6e41a 100644
--- a/dlpisubs.c
+++ b/dlpisubs.c
@@ -12,7 +12,7 @@
  */
 
 #ifdef HAVE_CONFIG_H
-#include "config.h"
+#include <config.h>
 #endif
 
 #ifndef DL_IPATM
@@ -271,7 +271,16 @@
 
 #ifdef DL_IPNET
 	case DL_IPNET:
-		p->linktype = DLT_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
@@ -349,7 +358,8 @@
 	p->bufsize = PKTBUFSIZE;
 	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);
 	}
 
@@ -383,6 +393,6 @@
 static void
 pcap_stream_err(const char *func, int err, char *errbuf)
 {
-	pcap_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
index 0000000..ff77128
--- /dev/null
+++ b/doc/DLT_ALLOCATE_HOWTO.md
@@ -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/README.Win32 b/doc/README.Win32
similarity index 100%
rename from README.Win32
rename to doc/README.Win32
diff --git a/README.aix b/doc/README.aix
similarity index 100%
rename from README.aix
rename to doc/README.aix
diff --git a/README.dag b/doc/README.dag
similarity index 100%
rename from README.dag
rename to doc/README.dag
diff --git a/README.hpux b/doc/README.hpux
similarity index 100%
rename from README.hpux
rename to doc/README.hpux
diff --git a/README.linux b/doc/README.linux.md
similarity index 100%
rename from README.linux
rename to doc/README.linux.md
diff --git a/README.macosx b/doc/README.macos
similarity index 85%
rename from README.macosx
rename to doc/README.macos
index 3dc9211..3cceb23 100644
--- a/README.macosx
+++ b/doc/README.macos
@@ -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 @@
 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
diff --git a/README.septel b/doc/README.septel
similarity index 96%
rename from README.septel
rename to doc/README.septel
index 483de6a..fa2c0c9 100644
--- a/README.septel
+++ b/doc/README.septel
@@ -40,7 +40,7 @@
 
 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
diff --git a/README.sita b/doc/README.sita
similarity index 96%
rename from README.sita
rename to doc/README.sita
index 014d51d..5a65822 100644
--- a/README.sita
+++ b/doc/README.sita
@@ -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
diff --git a/README.tru64 b/doc/README.tru64
similarity index 100%
rename from README.tru64
rename to doc/README.tru64
diff --git a/etherent.c b/etherent.c
index 5cfd1b4..5f49961 100644
--- a/etherent.c
+++ b/etherent.c
@@ -20,22 +20,10 @@
  */
 
 #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>
@@ -50,26 +38,23 @@
 #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 @@
 }
 
 static inline int
-skip_line(f)
-	FILE *f;
+skip_line(FILE *f)
 {
 	int c;
 
@@ -96,47 +80,61 @@
 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 @@
 
 		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 @@
 			(void)skip_line(fp);
 
 		return &e;
-
-	} while (c != EOF);
-
-	return (NULL);
+	}
 }
diff --git a/extract.h b/extract.h
index face5b7..aa3ff99 100644
--- a/extract.h
+++ b/extract.h
@@ -23,6 +23,9 @@
 #include <arpa/inet.h>
 #endif
 
+#include <pcap/pcap-inttypes.h>
+#include <pcap/compiler-tests.h>
+
 /*
  * Macros to extract possibly-unaligned big-endian integral values.
  */
@@ -30,15 +33,16 @@
 /*
  * The processor doesn't natively handle unaligned loads.
  */
-#if defined(__GNUC__) && defined(HAVE___ATTRIBUTE__) && \
+#if PCAP_IS_AT_LEAST_GNUC_VERSION(2,0) && \
     (defined(__alpha) || defined(__alpha__) || \
      defined(__mips) || defined(__mips__))
-
 /*
- * This is a GCC-compatible compiler and we have __attribute__, which
- * we assume that mean we have __attribute__((packed)), and this is
- * MIPS or Alpha, which has instructions that can help when doing
- * unaligned loads.
+ * 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;
diff --git a/fad-getad.c b/fad-getad.c
index b67b5cd..5236fbb 100644
--- a/fad-getad.c
+++ b/fad-getad.c
@@ -33,7 +33,7 @@
  */
 
 #ifdef HAVE_CONFIG_H
-#include "config.h"
+#include <config.h>
 #endif
 
 #include <sys/types.h>
@@ -102,10 +102,10 @@
  * 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 @@
 	}
 }
 #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,10 +144,9 @@
  * could be opened.
  */
 int
-pcap_findalldevs_interfaces(pcap_if_t **alldevsp, char *errbuf,
-    int (*check_usable)(const char *))
+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;
@@ -169,8 +168,8 @@
 	 * those.
 	 */
 	if (getifaddrs(&ifap) != 0) {
-		(void)pcap_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) {
@@ -233,7 +232,7 @@
 		/*
 		 * 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.
@@ -265,8 +264,8 @@
 		/*
 		 * Add information for this address to the list.
 		 */
-		if (add_addr_to_iflist(&devlist, ifa->ifa_name,
-		    if_flags_to_pcap_flags(ifa->ifa_name, ifa->ifa_flags),
+		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) {
@@ -277,16 +276,5 @@
 
 	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);
 }
diff --git a/fad-gifc.c b/fad-gifc.c
index 1b24af2..6b16127 100644
--- a/fad-gifc.c
+++ b/fad-gifc.c
@@ -33,7 +33,7 @@
  */
 
 #ifdef HAVE_CONFIG_H
-#include "config.h"
+#include <config.h>
 #endif
 
 #include <sys/param.h>
@@ -57,6 +57,12 @@
 #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 @@
  * 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,10 +138,9 @@
  * we already have that.
  */
 int
-pcap_findalldevs_interfaces(pcap_if_t **alldevsp, char *errbuf,
-    int (*check_usable)(const char *))
+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;
 	size_t n;
@@ -155,8 +160,8 @@
 	 */
 	fd = socket(AF_INET, SOCK_DGRAM, 0);
 	if (fd < 0) {
-		(void)pcap_snprintf(errbuf, PCAP_ERRBUF_SIZE,
-		    "socket: %s", pcap_strerror(errno));
+		pcap_fmt_errmsg_for_errno(errbuf, PCAP_ERRBUF_SIZE,
+		    errno, "socket");
 		return (-1);
 	}
 
@@ -169,10 +174,20 @@
 	 */
 	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)pcap_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);
 		}
@@ -182,13 +197,13 @@
 		memset(buf, 0, buf_size);
 		if (ioctl(fd, SIOCGIFCONF, (char *)&ifc) < 0
 		    && errno != EINVAL) {
-			(void)pcap_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);
@@ -255,11 +270,10 @@
 		if (ioctl(fd, SIOCGIFFLAGS, (char *)&ifrflags) < 0) {
 			if (errno == ENXIO)
 				continue;
-			(void)pcap_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;
 		}
@@ -279,11 +293,11 @@
 				netmask = NULL;
 				netmask_size = 0;
 			} else {
-				(void)pcap_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;
 			}
@@ -310,11 +324,11 @@
 					broadaddr = NULL;
 					broadaddr_size = 0;
 				} else {
-					(void)pcap_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;
 				}
@@ -349,11 +363,11 @@
 					dstaddr = NULL;
 					dstaddr_size = 0;
 				} else {
-					(void)pcap_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;
 				}
@@ -401,8 +415,8 @@
 		/*
 		 * Add information for this address to the list.
 		 */
-		if (add_addr_to_iflist(&devlist, ifrp->ifr_name,
-		    if_flags_to_pcap_flags(ifrp->ifr_name, ifrflags.ifr_flags),
+		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) {
@@ -413,16 +427,5 @@
 	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);
 }
diff --git a/fad-glifc.c b/fad-glifc.c
index 511481c..f22f56d 100644
--- a/fad-glifc.c
+++ b/fad-glifc.c
@@ -33,7 +33,7 @@
  */
 
 #ifdef HAVE_CONFIG_H
-#include "config.h"
+#include <config.h>
 #endif
 
 #include <sys/param.h>
@@ -75,10 +75,9 @@
  * SIOCGLIFCONF rather than SIOCGIFCONF in order to get IPv6 addresses.)
  */
 int
-pcap_findalldevs_interfaces(pcap_if_t **alldevsp, char *errbuf,
-    int (*check_usable)(const char *))
+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;
@@ -98,8 +97,8 @@
 	 */
 	fd4 = socket(AF_INET, SOCK_DGRAM, 0);
 	if (fd4 < 0) {
-		(void)pcap_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);
 	}
 
@@ -108,8 +107,8 @@
 	 */
 	fd6 = socket(AF_INET6, SOCK_DGRAM, 0);
 	if (fd6 < 0) {
-		(void)pcap_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);
 	}
@@ -121,8 +120,8 @@
 	ifn.lifn_flags = 0;
 	ifn.lifn_count = 0;
 	if (ioctl(fd4, SIOCGLIFNUM, (char *)&ifn) < 0) {
-		(void)pcap_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);
@@ -134,8 +133,8 @@
 	buf_size = ifn.lifn_count * sizeof (struct lifreq);
 	buf = malloc(buf_size);
 	if (buf == NULL) {
-		(void)pcap_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);
@@ -150,8 +149,8 @@
 	ifc.lifc_flags = 0;
 	memset(buf, 0, buf_size);
 	if (ioctl(fd4, SIOCGLIFCONF, (char *)&ifc) < 0) {
-		(void)pcap_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);
@@ -199,11 +198,10 @@
 		if (ioctl(fd, SIOCGLIFFLAGS, (char *)&ifrflags) < 0) {
 			if (errno == ENXIO)
 				continue;
-			(void)pcap_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;
 		}
@@ -222,11 +220,11 @@
 				 */
 				netmask = NULL;
 			} else {
-				(void)pcap_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;
 			}
@@ -250,11 +248,11 @@
 					 */
 					broadaddr = NULL;
 				} else {
-					(void)pcap_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;
 				}
@@ -285,11 +283,11 @@
 					 */
 					dstaddr = NULL;
 				} else {
-					(void)pcap_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;
 				}
@@ -329,8 +327,8 @@
 		/*
 		 * Add information for this address to the list.
 		 */
-		if (add_addr_to_iflist(&devlist, ifrp->lifr_name,
-		    if_flags_to_pcap_flags(ifrp->lifr_name, ifrflags.lifr_flags),
+		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),
@@ -344,16 +342,5 @@
 	(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-helpers.c b/fad-helpers.c
deleted file mode 100644
index 4860bc5..0000000
--- a/fad-helpers.c
+++ /dev/null
@@ -1,884 +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
-
-#ifndef _WIN32
-/* Not all systems have IFF_LOOPBACK */
-#ifdef IFF_LOOPBACK
-#define ISLOOPBACK(name, flags) ((flags) & IFF_LOOPBACK)
-#else
-#define ISLOOPBACK(name, flags) ((name)[0] == 'l' && (name)[1] == 'o' && \
-    (isdigit((unsigned char)((name)[2])) || (name)[2] == '\0'))
-#endif
-
-#ifdef IFF_UP
-#define ISUP(flags) ((flags) & IFF_UP)
-#else
-#define ISUP(flags) 0
-#endif
-
-#ifdef IFF_RUNNING
-#define ISRUNNING(flags) ((flags) & IFF_RUNNING)
-#else
-#define ISRUNNING(flags) 0
-#endif
-
-/*
- * Map UN*X-style interface flags to libpcap flags.
- */
-bpf_u_int32
-if_flags_to_pcap_flags(const char *name _U_, u_int if_flags)
-{
-	bpf_u_int32 pcap_flags;
-
-	pcap_flags = 0;
-	if (ISLOOPBACK(name, if_flags))
-		pcap_flags |= PCAP_IF_LOOPBACK;
-	if (ISUP(if_flags))
-		pcap_flags |= PCAP_IF_UP;
-	if (ISRUNNING(if_flags))
-		pcap_flags |= PCAP_IF_RUNNING;
-	return (pcap_flags);
-}
-#endif
-
-static struct sockaddr *
-dup_sockaddr(struct sockaddr *sa, size_t sa_length)
-{
-	struct sockaddr *newsa;
-
-	if ((newsa = malloc(sa_length)) == NULL)
-		return (NULL);
-	return (memcpy(newsa, sa, sa_length));
-}
-
-/*
- * Construct a "figure of merit" for an interface, for use when sorting
- * the list of interfaces, in which interfaces that are up are superior
- * to interfaces that aren't up, interfaces that are up and running are
- * superior to interfaces that are up but not running, and non-loopback
- * interfaces that are up and running are superior to loopback interfaces,
- * and interfaces with the same flags have a figure of merit that's higher
- * the lower the instance number.
- *
- * The goal is to try to put the interfaces most likely to be useful for
- * capture at the beginning of the list.
- *
- * The figure of merit, which is lower the "better" the interface is,
- * has the uppermost bit set if the interface isn't running, the bit
- * below that set if the interface isn't up, the bit below that set
- * if the interface is a loopback interface, and the interface index
- * in the 29 bits below that.  (Yes, we assume u_int is 32 bits.)
- */
-static u_int
-get_figure_of_merit(pcap_if_t *dev)
-{
-	const char *cp;
-	u_int n;
-
-	if (strcmp(dev->name, "any") == 0) {
-		/*
-		 * Give the "any" device an artificially high instance
-		 * number, so it shows up after all other non-loopback
-		 * interfaces.
-		 */
-		n = 0x1FFFFFFF;	/* 29 all-1 bits */
-	} else {
-		/*
-		 * A number at the end of the device name string is
-		 * assumed to be a unit number.
-		 */
-		cp = dev->name + strlen(dev->name) - 1;
-		while (cp-1 >= dev->name && *(cp-1) >= '0' && *(cp-1) <= '9')
-			cp--;
-		if (*cp >= '0' && *cp <= '9')
-			n = atoi(cp);
-		else
-			n = 0;
-	}
-	if (!(dev->flags & PCAP_IF_RUNNING))
-		n |= 0x80000000;
-	if (!(dev->flags & PCAP_IF_UP))
-		n |= 0x40000000;
-	if (dev->flags & PCAP_IF_LOOPBACK)
-		n |= 0x20000000;
-	return (n);
-}
-
-/*
- * Try to get a description for a given device.
- * Returns a mallocated description if it could and NULL if it couldn't.
- *
- * XXX - on FreeBSDs that support it, should it get the sysctl named
- * "dev.{adapter family name}.{adapter unit}.%desc" to get a description
- * of the adapter?  Note that "dev.an.0.%desc" is "Aironet PC4500/PC4800"
- * with my Cisco 350 card, so the name isn't entirely descriptive.  The
- * "dev.an.0.%pnpinfo" has a better description, although one might argue
- * that the problem is really a driver bug - if it can find out that it's
- * a Cisco 340 or 350, rather than an old Aironet card, it should use
- * that in the description.
- *
- * Do NetBSD, DragonflyBSD, or OpenBSD support this as well?  FreeBSD
- * and OpenBSD let you get a description, but it's not generated by the OS,
- * it's set with another ioctl that ifconfig supports; we use that to get
- * a description in FreeBSD and OpenBSD, but if there is no such
- * description available, it still might be nice to get some description
- * string based on the device type or something such as that.
- *
- * In OS X, the System Configuration framework can apparently return
- * names in 10.4 and later.
- *
- * It also appears that freedesktop.org's HAL offers an "info.product"
- * string, but the HAL specification says it "should not be used in any
- * UI" and "subsystem/capability specific properties" should be used
- * instead and, in any case, I think HAL is being deprecated in
- * favor of other stuff such as DeviceKit.  DeviceKit doesn't appear
- * to have any obvious product information for devices, but maybe
- * I haven't looked hard enough.
- *
- * Using the System Configuration framework, or HAL, or DeviceKit, or
- * whatever, would require that libpcap applications be linked with
- * the frameworks/libraries in question.  That shouldn't be a problem
- * for programs linking with the shared version of libpcap (unless
- * you're running on AIX - which I think is the only UN*X that doesn't
- * support linking a shared library with other libraries on which it
- * depends, and having an executable linked only with the first shared
- * library automatically pick up the other libraries when started -
- * and using HAL or whatever).  Programs linked with the static
- * version of libpcap would have to use pcap-config with the --static
- * flag in order to get the right linker flags in order to pick up
- * the additional libraries/frameworks; those programs need that anyway
- * for libpcap 1.1 and beyond on Linux, as, by default, it requires
- * -lnl.
- *
- * Do any other UN*Xes, or desktop environments support getting a
- * description?
- */
-static char *
-get_if_description(const char *name)
-{
-#ifdef SIOCGIFDESCR
-	char *description = NULL;
-	int s;
-	struct ifreq ifrdesc;
-#ifndef IFDESCRSIZE
-	size_t descrlen = 64;
-#else
-	size_t descrlen = IFDESCRSIZE;
-#endif /* IFDESCRSIZE */
-
-	/*
-	 * Get the description for the interface.
-	 */
-	memset(&ifrdesc, 0, sizeof ifrdesc);
-	strlcpy(ifrdesc.ifr_name, name, sizeof ifrdesc.ifr_name);
-	s = socket(AF_INET, SOCK_DGRAM, 0);
-	if (s >= 0) {
-#ifdef __FreeBSD__
-		/*
-		 * On FreeBSD, if the buffer isn't big enough for the
-		 * description, the ioctl succeeds, but the description
-		 * isn't copied, ifr_buffer.length is set to the description
-		 * length, and ifr_buffer.buffer is set to NULL.
-		 */
-		for (;;) {
-			free(description);
-			if ((description = malloc(descrlen)) != NULL) {
-				ifrdesc.ifr_buffer.buffer = description;
-				ifrdesc.ifr_buffer.length = descrlen;
-				if (ioctl(s, SIOCGIFDESCR, &ifrdesc) == 0) {
-					if (ifrdesc.ifr_buffer.buffer ==
-					    description)
-						break;
-					else
-						descrlen = ifrdesc.ifr_buffer.length;
-				} else {
-					/*
-					 * Failed to get interface description.
-					 */
-					free(description);
-					description = NULL;
-					break;
-				}
-			} else
-				break;
-		}
-#else /* __FreeBSD__ */
-		/*
-		 * The only other OS that currently supports
-		 * SIOCGIFDESCR is OpenBSD, and it has no way
-		 * to get the description length - it's clamped
-		 * to a maximum of IFDESCRSIZE.
-		 */
-		if ((description = malloc(descrlen)) != NULL) {
-			ifrdesc.ifr_data = (caddr_t)description;
-			if (ioctl(s, SIOCGIFDESCR, &ifrdesc) != 0) {
-				/*
-				 * Failed to get interface description.
-				 */
-				free(description);
-				description = NULL;
-			}
-		}
-#endif /* __FreeBSD__ */
-		close(s);
-		if (description != NULL && strlen(description) == 0) {
-			/*
-			 * Description is empty, so discard it.
-			 */
-			free(description);
-			description = NULL;
-		}
-	}
-
-#ifdef __FreeBSD__
-	/*
-	 * For FreeBSD, if we didn't get a description, and this is
-	 * a device with a name of the form usbusN, label it as a USB
-	 * bus.
-	 */
-	if (description == NULL) {
-		if (strncmp(name, "usbus", 5) == 0) {
-			/*
-			 * OK, it begins with "usbus".
-			 */
-			long busnum;
-			char *p;
-
-			errno = 0;
-			busnum = strtol(name + 5, &p, 10);
-			if (errno == 0 && p != name + 5 && *p == '\0' &&
-			    busnum >= 0 && busnum <= INT_MAX) {
-				/*
-				 * OK, it's a valid number that's not
-				 * bigger than INT_MAX.  Construct
-				 * a description from it.
-				 */
-				static const char descr_prefix[] = "USB bus number ";
-				size_t descr_size;
-
-				/*
-				 * Allow enough room for a 32-bit bus number.
-				 * sizeof (descr_prefix) includes the
-				 * terminating NUL.
-				 */
-				descr_size = sizeof (descr_prefix) + 10;
-				description = malloc(descr_size);
-				if (description != NULL) {
-					pcap_snprintf(description, descr_size,
-					    "%s%ld", descr_prefix, busnum);
-				}
-			}
-		}
-	}
-#endif
-	return (description);
-#else /* SIOCGIFDESCR */
-	return (NULL);
-#endif /* SIOCGIFDESCR */
-}
-
-/*
- * Look for a given device in the specified list of devices.
- *
- * If we find it, return 0 and set *curdev_ret to point to it.
- *
- * If we don't find it, check whether we can open it:
- *
- *     If that fails with PCAP_ERROR_NO_SUCH_DEVICE or
- *     PCAP_ERROR_IFACE_NOT_UP, don't attempt to add an entry for
- *     it, as that probably means it exists but doesn't support
- *     packet capture.
- *
- *     Otherwise, attempt to add an entry for it, with the specified
- *     ifnet flags and description, and, if that succeeds, return 0
- *     and set *curdev_ret to point to the new entry, otherwise
- *     return PCAP_ERROR and set errbuf to an error message.  If we
- *     weren't given a description, try to get one.
- */
-int
-add_or_find_if(pcap_if_t **curdev_ret, pcap_if_t **alldevs, const char *name,
-    bpf_u_int32 flags, const char *description, char *errbuf)
-{
-	pcap_t *p;
-	pcap_if_t *curdev, *prevdev, *nextdev;
-	u_int this_figure_of_merit, nextdev_figure_of_merit;
-	char open_errbuf[PCAP_ERRBUF_SIZE];
-	int ret;
-
-	/*
-	 * Is there already an entry in the list for this interface?
-	 */
-	for (curdev = *alldevs; curdev != NULL; curdev = curdev->next) {
-		if (strcmp(name, curdev->name) == 0)
-			break;	/* yes, we found it */
-	}
-
-	if (curdev == NULL) {
-		/*
-		 * No, we didn't find it.
-		 *
-		 * Can we open this interface for live capture?
-		 *
-		 * We do this check so that interfaces that are
-		 * supplied by the interface enumeration mechanism
-		 * we're using but that don't support packet capture
-		 * aren't included in the list.  Loopback interfaces
-		 * on Solaris are an example of this; we don't just
-		 * omit loopback interfaces on all platforms because
-		 * you *can* capture on loopback interfaces on some
-		 * OSes.
-		 *
-		 * On OS X, we don't do this check if the device
-		 * name begins with "wlt"; at least some versions
-		 * of OS X offer monitor mode capturing by having
-		 * a separate "monitor mode" device for each wireless
-		 * adapter, rather than by implementing the ioctls
-		 * that {Free,Net,Open,DragonFly}BSD provide.
-		 * Opening that device puts the adapter into monitor
-		 * mode, which, at least for some adapters, causes
-		 * them to deassociate from the network with which
-		 * they're associated.
-		 *
-		 * Instead, we try to open the corresponding "en"
-		 * device (so that we don't end up with, for users
-		 * without sufficient privilege to open capture
-		 * devices, a list of adapters that only includes
-		 * the wlt devices).
-		 */
-#ifdef __APPLE__
-		if (strncmp(name, "wlt", 3) == 0) {
-			char *en_name;
-			size_t en_name_len;
-
-			/*
-			 * Try to allocate a buffer for the "en"
-			 * device's name.
-			 */
-			en_name_len = strlen(name) - 1;
-			en_name = malloc(en_name_len + 1);
-			if (en_name == NULL) {
-				(void)pcap_snprintf(errbuf, PCAP_ERRBUF_SIZE,
-				    "malloc: %s", pcap_strerror(errno));
-				return (-1);
-			}
-			strcpy(en_name, "en");
-			strcat(en_name, name + 3);
-			p = pcap_create(en_name, open_errbuf);
-			free(en_name);
-		} else
-#endif /* __APPLE */
-		p = pcap_create(name, open_errbuf);
-		if (p == NULL) {
-			/*
-			 * The attempt to create the pcap_t failed;
-			 * that's probably an indication that we're
-			 * out of memory.
-			 *
-			 * Don't bother including this interface,
-			 * but don't treat it as an error.
-			 */
-			*curdev_ret = NULL;
-			return (0);
-		}
-		/* Small snaplen, so we don't try to allocate much memory. */
-		pcap_set_snaplen(p, 68);
-		ret = pcap_activate(p);
-		pcap_close(p);
-		switch (ret) {
-
-		case PCAP_ERROR_NO_SUCH_DEVICE:
-		case PCAP_ERROR_IFACE_NOT_UP:
-			/*
-			 * We expect these two errors - they're the
-			 * reason we try to open the device.
-			 *
-			 * PCAP_ERROR_NO_SUCH_DEVICE typically means
-			 * "there's no such device *known to the
-			 * OS's capture mechanism*", so, even though
-			 * it might be a valid network interface, you
-			 * can't capture on it (e.g., the loopback
-			 * device in Solaris up to Solaris 10, or
-			 * the vmnet devices in OS X with VMware
-			 * Fusion).  We don't include those devices
-			 * in our list of devices, as there's no
-			 * point in doing so - they're not available
-			 * for capture.
-			 *
-			 * PCAP_ERROR_IFACE_NOT_UP means that the
-			 * OS's capture mechanism doesn't work on
-			 * interfaces not marked as up; some capture
-			 * mechanisms *do* support that, so we no
-			 * longer reject those interfaces out of hand,
-			 * but we *do* want to reject them if they
-			 * can't be opened for capture.
-			 */
-			*curdev_ret = NULL;
-			return (0);
-		}
-
-		/*
-		 * Yes, we can open it, or we can't, for some other
-		 * reason.
-		 *
-		 * If we can open it, we want to offer it for
-		 * capture, as you can capture on it.  If we can't,
-		 * we want to offer it for capture, so that, if
-		 * the user tries to capture on it, they'll get
-		 * an error and they'll know why they can't
-		 * capture on it (e.g., insufficient permissions)
-		 * or they'll report it as a problem (and then
-		 * have the error message to provide as information).
-		 *
-		 * Allocate a new entry.
-		 */
-		curdev = malloc(sizeof(pcap_if_t));
-		if (curdev == NULL) {
-			(void)pcap_snprintf(errbuf, PCAP_ERRBUF_SIZE,
-			    "malloc: %s", pcap_strerror(errno));
-			return (-1);
-		}
-
-		/*
-		 * Fill in the entry.
-		 */
-		curdev->next = NULL;
-		curdev->name = strdup(name);
-		if (curdev->name == NULL) {
-			(void)pcap_snprintf(errbuf, PCAP_ERRBUF_SIZE,
-			    "malloc: %s", pcap_strerror(errno));
-			free(curdev);
-			return (-1);
-		}
-		if (description == NULL) {
-			/*
-			 * We weren't handed a description for the
-			 * interface, so see if we can generate one
-			 * ourselves.
-			 */
-			curdev->description = get_if_description(name);
-		} else {
-			/*
-			 * We were handed a description; make a copy.
-			 */
-			curdev->description = strdup(description);
-			if (curdev->description == NULL) {
-				(void)pcap_snprintf(errbuf, PCAP_ERRBUF_SIZE,
-				    "malloc: %s", pcap_strerror(errno));
-				free(curdev->name);
-				free(curdev);
-				return (-1);
-			}
-		}
-		curdev->addresses = NULL;	/* list starts out as empty */
-		curdev->flags = flags;
-
-		/*
-		 * Add it to the list, in the appropriate location.
-		 * First, get the "figure of merit" for this
-		 * interface.
-		 */
-		this_figure_of_merit = get_figure_of_merit(curdev);
-
-		/*
-		 * Now look for the last interface with an figure of merit
-		 * less than or equal to the new interface's figure of
-		 * merit.
-		 *
-		 * We start with "prevdev" being NULL, meaning we're before
-		 * the first element in the list.
-		 */
-		prevdev = NULL;
-		for (;;) {
-			/*
-			 * Get the interface after this one.
-			 */
-			if (prevdev == NULL) {
-				/*
-				 * The next element is the first element.
-				 */
-				nextdev = *alldevs;
-			} else
-				nextdev = prevdev->next;
-
-			/*
-			 * Are we at the end of the list?
-			 */
-			if (nextdev == NULL) {
-				/*
-				 * Yes - we have to put the new entry
-				 * after "prevdev".
-				 */
-				break;
-			}
-
-			/*
-			 * Is the new interface's figure of merit less
-			 * than the next interface's figure of merit,
-			 * meaning that the new interface is better
-			 * than the next interface?
-			 */
-			nextdev_figure_of_merit = get_figure_of_merit(nextdev);
-			if (this_figure_of_merit < nextdev_figure_of_merit) {
-				/*
-				 * Yes - we should put the new entry
-				 * before "nextdev", i.e. after "prevdev".
-				 */
-				break;
-			}
-
-			prevdev = nextdev;
-		}
-
-		/*
-		 * Insert before "nextdev".
-		 */
-		curdev->next = nextdev;
-
-		/*
-		 * Insert after "prevdev" - unless "prevdev" is null,
-		 * in which case this is the first interface.
-		 */
-		if (prevdev == NULL) {
-			/*
-			 * This is the first interface.  Pass back a
-			 * pointer to it, and put "curdev" before
-			 * "nextdev".
-			 */
-			*alldevs = curdev;
-		} else
-			prevdev->next = curdev;
-	}
-
-	*curdev_ret = curdev;
-	return (0);
-}
-
-/*
- * Try to get a description for a given device, and then look for that
- * device in the specified list of devices.
- *
- * If we find it, then, if the specified address isn't null, add it to
- * the list of addresses for the device and return 0.
- *
- * If we don't find it, check whether we can open it:
- *
- *     If that fails with PCAP_ERROR_NO_SUCH_DEVICE or
- *     PCAP_ERROR_IFACE_NOT_UP, don't attempt to add an entry for
- *     it, as that probably means it exists but doesn't support
- *     packet capture.
- *
- *     Otherwise, attempt to add an entry for it, with the specified
- *     ifnet flags, and, if that succeeds, add the specified address
- *     to its list of addresses if that address is non-null, set
- *     *curdev_ret to point to the new entry, and return 0, otherwise
- *     return PCAP_ERROR and set errbuf to an error message.
- *
- * (We can get called with a null address because we might get a list
- * of interface name/address combinations from the underlying OS, with
- * the address being absent in some cases, rather than a list of
- * interfaces with each interface having a list of addresses, so this
- * call may be the only call made to add to the list, and we want to
- * add interfaces even if they have no addresses.)
- */
-int
-add_addr_to_iflist(pcap_if_t **alldevs, const char *name, bpf_u_int32 flags,
-    struct sockaddr *addr, size_t addr_size,
-    struct sockaddr *netmask, size_t netmask_size,
-    struct sockaddr *broadaddr, size_t broadaddr_size,
-    struct sockaddr *dstaddr, size_t dstaddr_size,
-    char *errbuf)
-{
-	pcap_if_t *curdev;
-
-	if (add_or_find_if(&curdev, alldevs, name, flags, NULL, errbuf) == -1) {
-		/*
-		 * Error - give up.
-		 */
-		return (-1);
-	}
-	if (curdev == NULL) {
-		/*
-		 * Device wasn't added because it can't be opened.
-		 * Not a fatal error.
-		 */
-		return (0);
-	}
-
-	if (addr == NULL) {
-		/*
-		 * There's no address to add; this entry just meant
-		 * "here's a new interface".
-		 */
-		return (0);
-	}
-
-	/*
-	 * "curdev" is an entry for this interface, and we have an
-	 * address for it; add an entry for that address to the
-	 * interface's list of addresses.
-	 *
-	 * Allocate the new entry and fill it in.
-	 */
-	return (add_addr_to_dev(curdev, addr, addr_size, netmask,
-	    netmask_size, broadaddr, broadaddr_size, dstaddr,
-	    dstaddr_size, errbuf));
-}
-
-/*
- * Add an entry to the list of addresses for an interface.
- * "curdev" is the entry for that interface.
- * If this is the first IP address added to the interface, move it
- * in the list as appropriate.
- */
-int
-add_addr_to_dev(pcap_if_t *curdev,
-    struct sockaddr *addr, size_t addr_size,
-    struct sockaddr *netmask, size_t netmask_size,
-    struct sockaddr *broadaddr, size_t broadaddr_size,
-    struct sockaddr *dstaddr, size_t dstaddr_size,
-    char *errbuf)
-{
-	pcap_addr_t *curaddr, *prevaddr, *nextaddr;
-
-	curaddr = malloc(sizeof(pcap_addr_t));
-	if (curaddr == NULL) {
-		(void)pcap_snprintf(errbuf, PCAP_ERRBUF_SIZE,
-		    "malloc: %s", pcap_strerror(errno));
-		return (-1);
-	}
-
-	curaddr->next = NULL;
-	if (addr != NULL) {
-		curaddr->addr = dup_sockaddr(addr, addr_size);
-		if (curaddr->addr == NULL) {
-			(void)pcap_snprintf(errbuf, PCAP_ERRBUF_SIZE,
-			    "malloc: %s", pcap_strerror(errno));
-			free(curaddr);
-			return (-1);
-		}
-	} else
-		curaddr->addr = NULL;
-
-	if (netmask != NULL) {
-		curaddr->netmask = dup_sockaddr(netmask, netmask_size);
-		if (curaddr->netmask == NULL) {
-			(void)pcap_snprintf(errbuf, PCAP_ERRBUF_SIZE,
-			    "malloc: %s", pcap_strerror(errno));
-			if (curaddr->addr != NULL)
-				free(curaddr->addr);
-			free(curaddr);
-			return (-1);
-		}
-	} else
-		curaddr->netmask = NULL;
-
-	if (broadaddr != NULL) {
-		curaddr->broadaddr = dup_sockaddr(broadaddr, broadaddr_size);
-		if (curaddr->broadaddr == NULL) {
-			(void)pcap_snprintf(errbuf, PCAP_ERRBUF_SIZE,
-			    "malloc: %s", pcap_strerror(errno));
-			if (curaddr->netmask != NULL)
-				free(curaddr->netmask);
-			if (curaddr->addr != NULL)
-				free(curaddr->addr);
-			free(curaddr);
-			return (-1);
-		}
-	} else
-		curaddr->broadaddr = NULL;
-
-	if (dstaddr != NULL) {
-		curaddr->dstaddr = dup_sockaddr(dstaddr, dstaddr_size);
-		if (curaddr->dstaddr == NULL) {
-			(void)pcap_snprintf(errbuf, PCAP_ERRBUF_SIZE,
-			    "malloc: %s", pcap_strerror(errno));
-			if (curaddr->broadaddr != NULL)
-				free(curaddr->broadaddr);
-			if (curaddr->netmask != NULL)
-				free(curaddr->netmask);
-			if (curaddr->addr != NULL)
-				free(curaddr->addr);
-			free(curaddr);
-			return (-1);
-		}
-	} else
-		curaddr->dstaddr = NULL;
-
-	/*
-	 * Find the end of the list of addresses.
-	 */
-	for (prevaddr = curdev->addresses; prevaddr != NULL; prevaddr = nextaddr) {
-		nextaddr = prevaddr->next;
-		if (nextaddr == NULL) {
-			/*
-			 * This is the end of the list.
-			 */
-			break;
-		}
-	}
-
-	if (prevaddr == NULL) {
-		/*
-		 * The list was empty; this is the first member.
-		 */
-		curdev->addresses = curaddr;
-	} else {
-		/*
-		 * "prevaddr" is the last member of the list; append
-		 * this member to it.
-		 */
-		prevaddr->next = curaddr;
-	}
-
-	return (0);
-}
-
-/*
- * Look for a given device in the specified list of devices.
- *
- * If we find it, return 0.
- *
- * If we don't find it, check whether we can open it:
- *
- *     If that fails with PCAP_ERROR_NO_SUCH_DEVICE or
- *     PCAP_ERROR_IFACE_NOT_UP, don't attempt to add an entry for
- *     it, as that probably means it exists but doesn't support
- *     packet capture.
- *
- *     Otherwise, attempt to add an entry for it, with the specified
- *     ifnet flags and description, and, if that succeeds, return 0
- *     and set *curdev_ret to point to the new entry, otherwise
- *     return PCAP_ERROR and set errbuf to an error message.
- */
-int
-pcap_add_if(pcap_if_t **devlist, const char *name, u_int flags,
-    const char *description, char *errbuf)
-{
-	pcap_if_t *curdev;
-
-	return (add_or_find_if(&curdev, devlist, name, flags, description,
-	    errbuf));
-}
-
-
-/*
- * Free a list of interfaces.
- */
-void
-pcap_freealldevs(pcap_if_t *alldevs)
-{
-	pcap_if_t *curdev, *nextdev;
-	pcap_addr_t *curaddr, *nextaddr;
-
-	for (curdev = alldevs; curdev != NULL; curdev = nextdev) {
-		nextdev = curdev->next;
-
-		/*
-		 * Free all addresses.
-		 */
-		for (curaddr = curdev->addresses; curaddr != NULL; curaddr = nextaddr) {
-			nextaddr = curaddr->next;
-			if (curaddr->addr)
-				free(curaddr->addr);
-			if (curaddr->netmask)
-				free(curaddr->netmask);
-			if (curaddr->broadaddr)
-				free(curaddr->broadaddr);
-			if (curaddr->dstaddr)
-				free(curaddr->dstaddr);
-			free(curaddr);
-		}
-
-		/*
-		 * Free the name string.
-		 */
-		free(curdev->name);
-
-		/*
-		 * Free the description string, if any.
-		 */
-		if (curdev->description != NULL)
-			free(curdev->description);
-
-		/*
-		 * Free the interface.
-		 */
-		free(curdev);
-	}
-}
diff --git a/fmtutils.c b/fmtutils.c
new file mode 100644
index 0000000..f1a8907
--- /dev/null
+++ b/fmtutils.c
@@ -0,0 +1,131 @@
+/*
+ * 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;
+#if defined(HAVE_STRERROR_S)
+	errno_t err;
+#elif defined(HAVE_STRERROR_R)
+	int err;
+#endif
+
+	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)
+	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_STRERROR_R)
+	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
+}
diff --git a/fmtutils.h b/fmtutils.h
new file mode 100644
index 0000000..62c78fd
--- /dev/null
+++ b/fmtutils.h
@@ -0,0 +1,50 @@
+/*
+ * 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 fmtutils_h
+#define	fmtutils_h
+
+#include "pcap/funcattrs.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+void	pcap_fmt_errmsg_for_errno(char *, size_t, int,
+    PCAP_FORMAT_STRING(const char *), ...) PCAP_PRINTFLIKE(4, 5);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/ftmacros.h b/ftmacros.h
new file mode 100644
index 0000000..de8da98
--- /dev/null
+++ b/ftmacros.h
@@ -0,0 +1,115 @@
+/*
+ * 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)
+  /*
+   * We can't turn _GNU_SOURCE on because some versions of GNU Libc
+   * will give the GNU version of strerror_r(), which returns a
+   * string pointer and doesn't necessarily fill in the buffer,
+   * rather than the standard version of strerror_r(), which
+   * returns 0 or an errno and always fills in the buffer.  We
+   * require both of the latter behaviors.
+   *
+   * So we try turning everything else on that we can.  This includes
+   * defining _XOPEN_SOURCE as 600, because we want to force crypt()
+   * to be declared on systems that use GNU libc, such as most Linux
+   * distributions.
+   */
+  #define _POSIX_C_SOURCE 200809L
+  #define _XOPEN_SOURCE 600
+
+  /*
+   * 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
diff --git a/gen_version_c.sh b/gen_version_c.sh
deleted file mode 100755
index d5a5e75..0000000
--- a/gen_version_c.sh
+++ /dev/null
@@ -1,11 +0,0 @@
-#! /bin/sh
-echo '#include <pcap/export-defs.h>' > "$2"
-echo 'PCAP_API_DEF' >> "$2"
-if grep GIT "$1" >/dev/null; then
-	read ver <"$1"
-	echo $ver | tr -d '\012'
-	date +_%Y_%m_%d
-else
-	cat "$1"
-fi | sed -e 's/.*/char pcap_version[] = "&";/' >> "$2"
-
diff --git a/gen_version_header.sh b/gen_version_header.sh
deleted file mode 100755
index 6b4b82d..0000000
--- a/gen_version_header.sh
+++ /dev/null
@@ -1,19 +0,0 @@
-#! /bin/sh
-print_version_string()
-{
-	if grep GIT "$1" >/dev/null
-	then
-		read ver <"$1"
-		echo $ver | tr -d '\012'
-		date +_%Y_%m_%d
-	else
-		cat "$1"
-	fi
-}
-if test $# != 3
-then
-	echo "Usage: gen_version_header.sh <version file> <template> <output file>" 1>&2
-	exit 1
-fi
-version_string=`print_version_string "$1"`
-sed "s/%%LIBPCAP_VERSION%%/$version_string/" "$2" >"$3"
diff --git a/gencode.c b/gencode.c
index a887f27..959a56e 100644
--- a/gencode.c
+++ b/gencode.c
@@ -21,33 +21,21 @@
  */
 
 #ifdef HAVE_CONFIG_H
-#include "config.h"
+#include <config.h>
 #endif
 
+#include <pcap-types.h>
 #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 */
+  #include <ws2tcpip.h>
+#else
+  #include <sys/socket.h>
 
-#ifndef _WIN32
+  #ifdef __NetBSD__
+    #include <sys/param.h>
+  #endif
 
-#ifdef __NetBSD__
-#include <sys/param.h>
-#endif
-
-#include <netinet/in.h>
-#include <arpa/inet.h>
-
+  #include <netinet/in.h>
+  #include <arpa/inet.h>
 #endif /* _WIN32 */
 
 #include <stdlib.h>
@@ -94,17 +82,17 @@
 #define offsetof(s, e) ((size_t)&((s *)0)->e)
 #endif
 
-#ifdef INET6
 #ifdef _WIN32
-#if defined(__MINGW32__) && defined(DEFINE_ADDITIONAL_IPV6_STUFF)
+  #ifdef INET6
+    #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];
+	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
@@ -121,12 +109,12 @@
 struct sockaddr_in6
   {
     __SOCKADDR_COMMON (sin6_);
-    u_int16_t sin6_port;		/* Transport layer port # */
-    u_int32_t sin6_flowinfo;	/* IPv6 flow information */
+    uint16_t sin6_port;		/* Transport layer port # */
+    uint32_t sin6_flowinfo;	/* IPv6 flow information */
     struct in6_addr sin6_addr;	/* IPv6 address */
   };
 
-#ifndef EAI_ADDRFAMILY
+      #ifndef EAI_ADDRFAMILY
 struct addrinfo {
 	int	ai_flags;	/* AI_PASSIVE, AI_CANONNAME */
 	int	ai_family;	/* PF_xxx */
@@ -137,12 +125,12 @@
 	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 /* EAI_ADDRFAMILY */
+    #endif /* defined(__MINGW32__) && defined(DEFINE_ADDITIONAL_IPV6_STUFF) */
+  #endif /* INET6 */
 #else /* _WIN32 */
-#include <netdb.h>	/* for "struct addrinfo" */
+  #include <netdb.h>	/* for "struct addrinfo" */
 #endif /* _WIN32 */
-#endif /* INET6 */
 #include <pcap/namedb.h>
 
 #include "nametoaddr.h"
@@ -277,7 +265,6 @@
 	/* XXX */
 	u_int pcap_fddipad;
 
-#ifdef INET6
 	/*
 	 * As errors are handled by a longjmp, anything allocated must
 	 * be freed in the longjmp handler, so it must be reachable
@@ -288,7 +275,6 @@
 	 * any addrinfo structure that would need to be freed.
 	 */
 	struct addrinfo *ai;
-#endif
 
 	/*
 	 * Various code constructs need to know the layout of the packet.
@@ -358,6 +344,11 @@
 	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;
@@ -426,7 +417,7 @@
 	int cur_chunk;
 };
 
-void
+void PCAP_NORETURN
 bpf_syntax_error(compiler_state_t *cstate, const char *msg)
 {
 	bpf_error(cstate, "syntax error in filter expression: %s", msg);
@@ -434,7 +425,7 @@
 }
 
 /* VARARGS */
-void
+void PCAP_NORETURN
 bpf_error(compiler_state_t *cstate, const char *fmt, ...)
 {
 	va_list ap;
@@ -523,7 +514,8 @@
     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(compiler_state_t *);
 static struct block *gen_portatom(compiler_state_t *, int, bpf_int32);
@@ -582,7 +574,8 @@
 
 	cp = &cstate->chunks[cstate->cur_chunk];
 	if (n > cp->n_left) {
-		++cp, k = ++cstate->cur_chunk;
+		++cp;
+		k = ++cstate->cur_chunk;
 		if (k >= NCHUNKS)
 			bpf_error(cstate, "out of memory");
 		size = CHUNK0SIZE << k;
@@ -653,7 +646,7 @@
 	return b;
 }
 
-static inline void
+static inline PCAP_NORETURN_DEF void
 syntax(compiler_state_t *cstate)
 {
 	bpf_error(cstate, "syntax error in filter expression");
@@ -663,6 +656,9 @@
 pcap_compile(pcap_t *p, struct bpf_program *program,
 	     const char *buf, int optimize, bpf_u_int32 mask)
 {
+#ifdef _WIN32
+	static int done = 0;
+#endif
 	compiler_state_t cstate;
 	const char * volatile xbuf = buf;
 	yyscan_t scanner = NULL;
@@ -670,14 +666,6 @@
 	u_int len;
 	int  rc;
 
-#ifdef _WIN32
-	static int done = 0;
-
-	if (!done)
-		pcap_wsockinit();
-	done = 1;
-#endif
-
 	/*
 	 * If this pcap_t hasn't been activated, it doesn't have a
 	 * link-layer type, so we can't use it.
@@ -685,12 +673,41 @@
 	if (!p->activated) {
 		pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
 		    "not-yet-activated pcap_t passed to pcap_compile");
-		rc = -1;
-		goto quit;
+		return (-1);
 	}
+
+#ifdef _WIN32
+	if (!done)
+		pcap_wsockinit();
+	done = 1;
+#endif
+
+#ifdef ENABLE_REMOTE
+	/*
+	 * 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 code did.
+	 */
+	if (p->save_current_filter_op != NULL)
+		(p->save_current_filter_op)(p, buf);
+#endif
+
 	initchunks(&cstate);
 	cstate.no_optimize = 0;
+#ifdef INET6
 	cstate.ai = NULL;
+#endif
 	cstate.ic.root = NULL;
 	cstate.ic.cur_mark = 0;
 	cstate.bpf_pcap = p;
@@ -716,7 +733,8 @@
 	}
 
 	if (pcap_lex_init(&scanner) != 0)
-		bpf_error(&cstate, "can't initialize scanner: %s", pcap_strerror(errno));
+		pcap_fmt_errmsg_for_errno(p->errbuf, PCAP_ERRBUF_SIZE,
+		    errno, "can't initialize scanner");
 	in_buffer = pcap__scan_string(xbuf ? xbuf : "", scanner);
 
 	/*
@@ -800,8 +818,7 @@
  * 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;
 
@@ -822,8 +839,7 @@
  * 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;
 
@@ -885,8 +901,7 @@
 }
 
 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;
@@ -897,8 +912,7 @@
 }
 
 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);
@@ -908,8 +922,7 @@
 }
 
 void
-gen_not(b)
-	struct block *b;
+gen_not(struct block *b)
 {
 	b->sense = !b->sense;
 }
@@ -1061,10 +1074,10 @@
 	 * Assume it's not raw ATM with a pseudo-header, for now.
 	 */
 	cstate->is_atm = 0;
-	cstate->off_vpi = -1;
-	cstate->off_vci = -1;
-	cstate->off_proto = -1;
-	cstate->off_payload = -1;
+	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 not Geneve.
@@ -1072,14 +1085,19 @@
 	cstate->is_geneve = 0;
 
 	/*
+	 * No variable length VLAN offset by default
+	 */
+	cstate->is_vlan_vloffset = 0;
+
+	/*
 	 * And assume we're not doing SS7.
 	 */
-	cstate->off_li = -1;
-	cstate->off_li_hsl = -1;
-	cstate->off_sio = -1;
-	cstate->off_opc = -1;
-	cstate->off_dpc = -1;
-	cstate->off_sls = -1;
+	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;
 
 	cstate->label_stack_depth = 0;
 	cstate->vlan_stack_depth = 0;
@@ -1089,7 +1107,7 @@
 	case DLT_ARCNET:
 		cstate->off_linktype.constant_part = 2;
 		cstate->off_linkpl.constant_part = 6;
-		cstate->off_nl = 0;	/* XXX in reality, variable! */
+		cstate->off_nl = 0;		/* XXX in reality, variable! */
 		cstate->off_nl_nosnap = 0;	/* no 802.2 LLC */
 		break;
 
@@ -1403,7 +1421,7 @@
 		cstate->off_linktype.constant_part = 4;
 		cstate->off_linkpl.constant_part = 4;
 		cstate->off_nl = 0;
-		cstate->off_nl_nosnap = -1;	/* no 802.2 LLC */
+		cstate->off_nl_nosnap = OFFSET_NOT_SET;	/* no 802.2 LLC */
                 break;
 
 	case DLT_JUNIPER_ATM1:
@@ -1434,63 +1452,63 @@
 		cstate->off_linktype.constant_part = 4;
 		cstate->off_linkpl.constant_part = 6;
 		cstate->off_nl = 0;
-		cstate->off_nl_nosnap = -1;	/* no 802.2 LLC */
+		cstate->off_nl_nosnap = OFFSET_NOT_SET;	/* no 802.2 LLC */
 		break;
 
 	case DLT_JUNIPER_GGSN:
 		cstate->off_linktype.constant_part = 6;
 		cstate->off_linkpl.constant_part = 12;
 		cstate->off_nl = 0;
-		cstate->off_nl_nosnap = -1;	/* no 802.2 LLC */
+		cstate->off_nl_nosnap = OFFSET_NOT_SET;	/* no 802.2 LLC */
 		break;
 
 	case DLT_JUNIPER_ES:
 		cstate->off_linktype.constant_part = 6;
 		cstate->off_linkpl.constant_part = OFFSET_NOT_SET;	/* not really a network layer but raw IP addresses */
-		cstate->off_nl = -1;		/* not really a network layer but raw IP addresses */
-		cstate->off_nl_nosnap = -1;	/* no 802.2 LLC */
+		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:
 		cstate->off_linktype.constant_part = 12;
 		cstate->off_linkpl.constant_part = 12;
-		cstate->off_nl = 0;		/* raw IP/IP6 header */
-		cstate->off_nl_nosnap = -1;	/* no 802.2 LLC */
+		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:
 		cstate->off_linktype.constant_part = OFFSET_NOT_SET;
 		cstate->off_linkpl.constant_part = OFFSET_NOT_SET;
-		cstate->off_nl = -1;
-		cstate->off_nl_nosnap = -1;
+		cstate->off_nl = OFFSET_NOT_SET;
+		cstate->off_nl_nosnap = OFFSET_NOT_SET;
 		break;
 
 	case DLT_JUNIPER_SERVICES:
 		cstate->off_linktype.constant_part = 12;
 		cstate->off_linkpl.constant_part = OFFSET_NOT_SET;	/* L3 proto location dep. on cookie type */
-		cstate->off_nl = -1;		/* L3 proto location dep. on cookie type */
-		cstate->off_nl_nosnap = -1;	/* no 802.2 LLC */
+		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:
 		cstate->off_linktype.constant_part = 18;
 		cstate->off_linkpl.constant_part = OFFSET_NOT_SET;
-		cstate->off_nl = -1;
-		cstate->off_nl_nosnap = -1;
+		cstate->off_nl = OFFSET_NOT_SET;
+		cstate->off_nl_nosnap = OFFSET_NOT_SET;
 		break;
 
 	case DLT_JUNIPER_ST:
 		cstate->off_linktype.constant_part = 18;
 		cstate->off_linkpl.constant_part = OFFSET_NOT_SET;
-		cstate->off_nl = -1;
-		cstate->off_nl_nosnap = -1;
+		cstate->off_nl = OFFSET_NOT_SET;
+		cstate->off_nl_nosnap = OFFSET_NOT_SET;
 		break;
 
 	case DLT_JUNIPER_ISM:
 		cstate->off_linktype.constant_part = 8;
 		cstate->off_linkpl.constant_part = OFFSET_NOT_SET;
-		cstate->off_nl = -1;
-		cstate->off_nl_nosnap = -1;
+		cstate->off_nl = OFFSET_NOT_SET;
+		cstate->off_nl_nosnap = OFFSET_NOT_SET;
 		break;
 
 	case DLT_JUNIPER_VS:
@@ -1499,8 +1517,8 @@
 	case DLT_JUNIPER_ATM_CEMIC:
 		cstate->off_linktype.constant_part = 8;
 		cstate->off_linkpl.constant_part = OFFSET_NOT_SET;
-		cstate->off_nl = -1;
-		cstate->off_nl_nosnap = -1;
+		cstate->off_nl = OFFSET_NOT_SET;
+		cstate->off_nl_nosnap = OFFSET_NOT_SET;
 		break;
 
 	case DLT_MTP2:
@@ -1512,8 +1530,8 @@
 		cstate->off_sls = 7;
 		cstate->off_linktype.constant_part = OFFSET_NOT_SET;
 		cstate->off_linkpl.constant_part = OFFSET_NOT_SET;
-		cstate->off_nl = -1;
-		cstate->off_nl_nosnap = -1;
+		cstate->off_nl = OFFSET_NOT_SET;
+		cstate->off_nl_nosnap = OFFSET_NOT_SET;
 		break;
 
 	case DLT_MTP2_WITH_PHDR:
@@ -1525,8 +1543,8 @@
 		cstate->off_sls = 11;
 		cstate->off_linktype.constant_part = OFFSET_NOT_SET;
 		cstate->off_linkpl.constant_part = OFFSET_NOT_SET;
-		cstate->off_nl = -1;
-		cstate->off_nl_nosnap = -1;
+		cstate->off_nl = OFFSET_NOT_SET;
+		cstate->off_nl_nosnap = OFFSET_NOT_SET;
 		break;
 
 	case DLT_ERF:
@@ -1538,8 +1556,8 @@
 		cstate->off_sls = 27;
 		cstate->off_linktype.constant_part = OFFSET_NOT_SET;
 		cstate->off_linkpl.constant_part = OFFSET_NOT_SET;
-		cstate->off_nl = -1;
-		cstate->off_nl_nosnap = -1;
+		cstate->off_nl = OFFSET_NOT_SET;
+		cstate->off_nl_nosnap = OFFSET_NOT_SET;
 		break;
 
 	case DLT_PFSYNC:
@@ -1555,15 +1573,15 @@
 		 */
 		cstate->off_linktype.constant_part = OFFSET_NOT_SET;	/* variable, min 15, max 71 steps of 7 */
 		cstate->off_linkpl.constant_part = OFFSET_NOT_SET;
-		cstate->off_nl = -1;		/* variable, min 16, max 71 steps of 7 */
-		cstate->off_nl_nosnap = -1;	/* no 802.2 LLC */
+		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:
 		cstate->off_linktype.constant_part = 1;
 		cstate->off_linkpl.constant_part = 24;	/* ipnet header length */
 		cstate->off_nl = 0;
-		cstate->off_nl_nosnap = -1;
+		cstate->off_nl_nosnap = OFFSET_NOT_SET;
 		break;
 
 	case DLT_NETANALYZER:
@@ -1591,8 +1609,8 @@
 		    cstate->linktype <= DLT_MATCHING_MAX) {
 			cstate->off_linktype.constant_part = OFFSET_NOT_SET;
 			cstate->off_linkpl.constant_part = OFFSET_NOT_SET;
-			cstate->off_nl = -1;
-			cstate->off_nl_nosnap = -1;
+			cstate->off_nl = OFFSET_NOT_SET;
+			cstate->off_nl_nosnap = OFFSET_NOT_SET;
 		} else {
 			bpf_error(cstate, "unknown data link type %d", cstate->linktype);
 		}
@@ -1717,7 +1735,7 @@
 
 	default:
 		abort();
-		return NULL;
+		/* NOTREACHED */
 	}
 	return s;
 }
@@ -1781,6 +1799,7 @@
 	return s;
 }
 
+
 static struct block *
 gen_uncond(compiler_state_t *cstate, int rsense)
 {
@@ -2798,6 +2817,28 @@
 	}
 
 	/*
+	 * 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
@@ -2883,8 +2924,7 @@
  * Map an Ethernet type to the equivalent PPP type.
  */
 static int
-ethertype_to_ppptype(proto)
-	int proto;
+ethertype_to_ppptype(int proto)
 {
 	switch (proto) {
 
@@ -2971,7 +3011,7 @@
  */
 #define BSD_AFNUM_INET6_BSD	24	/* NetBSD, OpenBSD, BSD/OS, Npcap */
 #define BSD_AFNUM_INET6_FREEBSD	28	/* FreeBSD */
-#define BSD_AFNUM_INET6_DARWIN	30	/* OS X, iOS, other Darwin-based OSes */
+#define BSD_AFNUM_INET6_DARWIN	30	/* macOS, iOS, other Darwin-based OSes */
 
 /*
  * Generate code to match a particular packet type by matching the
@@ -3527,14 +3567,14 @@
 {
 	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 */
+	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);
 }
 
@@ -3827,6 +3867,30 @@
 		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");
+		break;
+
+	case Q_ADDR2:
+		bpf_error(cstate, "'addr2' and 'address2' are not valid qualifiers for addresses other than 802.11 MAC addresses");
+		break;
+
+	case Q_ADDR3:
+		bpf_error(cstate, "'addr3' and 'address3' are not valid qualifiers for addresses other than 802.11 MAC addresses");
+		break;
+
+	case Q_ADDR4:
+		bpf_error(cstate, "'addr4' and 'address4' are not valid qualifiers for addresses other than 802.11 MAC addresses");
+		break;
+
+	case Q_RA:
+		bpf_error(cstate, "'ra' is not a valid qualifier for addresses other than 802.11 MAC addresses");
+		break;
+
+	case Q_TA:
+		bpf_error(cstate, "'ta' is not a valid qualifier for addresses other than 802.11 MAC addresses");
+		break;
+
 	default:
 		abort();
 	}
@@ -3843,7 +3907,7 @@
 {
 	struct block *b0, *b1;
 	u_int offset;
-	u_int32_t *a, *m;
+	uint32_t *a, *m;
 
 	switch (dir) {
 
@@ -3868,12 +3932,36 @@
 		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");
+		break;
+
+	case Q_ADDR2:
+		bpf_error(cstate, "'addr2' and 'address2' are not valid qualifiers for addresses other than 802.11 MAC addresses");
+		break;
+
+	case Q_ADDR3:
+		bpf_error(cstate, "'addr3' and 'address3' are not valid qualifiers for addresses other than 802.11 MAC addresses");
+		break;
+
+	case Q_ADDR4:
+		bpf_error(cstate, "'addr4' and 'address4' are not valid qualifiers for addresses other than 802.11 MAC addresses");
+		break;
+
+	case Q_RA:
+		bpf_error(cstate, "'ra' is not a valid qualifier for addresses other than 802.11 MAC addresses");
+		break;
+
+	case Q_TA:
+		bpf_error(cstate, "'ta' is not a valid qualifier for addresses other than 802.11 MAC addresses");
+		break;
+
 	default:
 		abort();
 	}
 	/* this order is important */
-	a = (u_int32_t *)addr;
-	m = (u_int32_t *)mask;
+	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);
@@ -3913,19 +4001,19 @@
 		return b1;
 
 	case Q_ADDR1:
-		bpf_error(cstate, "'addr1' is only supported on 802.11 with 802.11 headers");
+		bpf_error(cstate, "'addr1' and 'address1' are only supported on 802.11 with 802.11 headers");
 		break;
 
 	case Q_ADDR2:
-		bpf_error(cstate, "'addr2' is only supported on 802.11 with 802.11 headers");
+		bpf_error(cstate, "'addr2' and 'address2' are only supported on 802.11 with 802.11 headers");
 		break;
 
 	case Q_ADDR3:
-		bpf_error(cstate, "'addr3' is only supported on 802.11 with 802.11 headers");
+		bpf_error(cstate, "'addr3' and 'address3' are only supported on 802.11 with 802.11 headers");
 		break;
 
 	case Q_ADDR4:
-		bpf_error(cstate, "'addr4' is only supported on 802.11 with 802.11 headers");
+		bpf_error(cstate, "'addr4' and 'address4' are only supported on 802.11 with 802.11 headers");
 		break;
 
 	case Q_RA:
@@ -3969,19 +4057,19 @@
 		return b1;
 
 	case Q_ADDR1:
-		bpf_error(cstate, "'addr1' is only supported on 802.11");
+		bpf_error(cstate, "'addr1' and 'address1' are only supported on 802.11");
 		break;
 
 	case Q_ADDR2:
-		bpf_error(cstate, "'addr2' is only supported on 802.11");
+		bpf_error(cstate, "'addr2' and 'address2' are only supported on 802.11");
 		break;
 
 	case Q_ADDR3:
-		bpf_error(cstate, "'addr3' is only supported on 802.11");
+		bpf_error(cstate, "'addr3' and 'address3' are only supported on 802.11");
 		break;
 
 	case Q_ADDR4:
-		bpf_error(cstate, "'addr4' is only supported on 802.11");
+		bpf_error(cstate, "'addr4' and 'address4' are only supported on 802.11");
 		break;
 
 	case Q_RA:
@@ -4025,19 +4113,19 @@
 		return b1;
 
 	case Q_ADDR1:
-		bpf_error(cstate, "'addr1' is only supported on 802.11");
+		bpf_error(cstate, "'addr1' and 'address1' are only supported on 802.11");
 		break;
 
 	case Q_ADDR2:
-		bpf_error(cstate, "'addr2' is only supported on 802.11");
+		bpf_error(cstate, "'addr2' and 'address2' are only supported on 802.11");
 		break;
 
 	case Q_ADDR3:
-		bpf_error(cstate, "'addr3' is only supported on 802.11");
+		bpf_error(cstate, "'addr3' and 'address3' are only supported on 802.11");
 		break;
 
 	case Q_ADDR4:
-		bpf_error(cstate, "'addr4' is only supported on 802.11");
+		bpf_error(cstate, "'addr4' and 'address4' are only supported on 802.11");
 		break;
 
 	case Q_RA:
@@ -4506,19 +4594,19 @@
 		return b1;
 
 	case Q_ADDR1:
-		bpf_error(cstate, "'addr1' is only supported on 802.11");
+		bpf_error(cstate, "'addr1' and 'address1' are only supported on 802.11");
 		break;
 
 	case Q_ADDR2:
-		bpf_error(cstate, "'addr2' is only supported on 802.11");
+		bpf_error(cstate, "'addr2' and 'address2' are only supported on 802.11");
 		break;
 
 	case Q_ADDR3:
-		bpf_error(cstate, "'addr3' is only supported on 802.11");
+		bpf_error(cstate, "'addr3' and 'address3' are only supported on 802.11");
 		break;
 
 	case Q_ADDR4:
-		bpf_error(cstate, "'addr4' is only supported on 802.11");
+		bpf_error(cstate, "'addr4' and 'address4' are only supported on 802.11");
 		break;
 
 	case Q_RA:
@@ -4634,7 +4722,7 @@
 
         case Q_IP:
                 /* match the bottom-of-stack bit */
-                b0 = gen_mcmp(cstate, OR_LINKPL, -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(cstate, OR_LINKPL, 0, BPF_B, 0x40, 0xf0);
                 gen_and(b0, b1);
@@ -4642,7 +4730,7 @@
 
        case Q_IPV6:
                 /* match the bottom-of-stack bit */
-                b0 = gen_mcmp(cstate, OR_LINKPL, -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(cstate, OR_LINKPL, 0, BPF_B, 0x60, 0xf0);
                 gen_and(b0, b1);
@@ -4902,13 +4990,12 @@
 
 #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(cstate, "direction applied to 'gateway'");
@@ -4956,12 +5043,48 @@
 			bpf_error(cstate,
 			    "'gateway' supported only on ethernet/FDDI/token ring/802.11/ATM LANE/Fibre Channel");
 		}
-		b1 = gen_host(cstate, **alist++, 0xffffffff, proto, Q_OR, Q_HOST);
-		while (*alist) {
-			tmp = gen_host(cstate, **alist++, 0xffffffff, proto, Q_OR,
-			    Q_HOST);
-			gen_or(b1, tmp);
-			b1 = tmp;
+		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);
@@ -5643,9 +5766,7 @@
 
 #if 0
 struct stmt *
-gen_joinsp(s, n)
-	struct stmt **s;
-	int n;
+gen_joinsp(struct stmt **s, int n)
 {
 	return NULL;
 }
@@ -5695,7 +5816,7 @@
 	if (cstate->off_linkpl.is_variable)
 		bpf_error(cstate, "'protochain' not supported with variable length headers");
 
-	cstate->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
@@ -6199,13 +6320,11 @@
 	int tproto;
 	u_char *eaddr;
 	bpf_u_int32 mask, addr;
-#ifndef INET6
-	bpf_u_int32 **alist;
-#else
-	int tproto6;
-	struct sockaddr_in *sin4;
-	struct sockaddr_in6 *sin6;
 	struct addrinfo *res, *res0;
+	struct sockaddr_in *sin4;
+#ifdef INET6
+	int tproto6;
+	struct sockaddr_in6 *sin6;
 	struct in6_addr mask128;
 #endif /*INET6*/
 	struct block *b, *tmp;
@@ -6304,46 +6423,39 @@
 			 */
 			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(cstate, "unknown host '%s'", name);
-			tproto = proto;
-			if (cstate->off_linktype.constant_part == OFFSET_NOT_SET &&
-			    tproto == Q_DEFAULT)
-				tproto = Q_IP;
-			b = gen_host(cstate, **alist++, 0xffffffff, tproto, dir, q.addr);
-			while (*alist) {
-				tmp = gen_host(cstate, **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(cstate, "unknown host '%s'", name);
 			cstate->ai = res;
 			b = tmp = NULL;
-			tproto = tproto6 = proto;
+			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(cstate, ntohl(sin4->sin_addr.s_addr),
 						0xffffffff, tproto, dir, q.addr);
 					break;
+#ifdef INET6
 				case AF_INET6:
 					if (tproto6 == Q_IP)
 						continue;
@@ -6353,6 +6465,7 @@
 					tmp = gen_host6(cstate, &sin6->sin6_addr,
 						&mask128, tproto6, dir, q.addr);
 					break;
+#endif
 				default:
 					continue;
 				}
@@ -6369,7 +6482,6 @@
 					: " for specified address family");
 			}
 			return b;
-#endif /*INET6*/
 		}
 
 	case Q_PORT:
@@ -6467,11 +6579,15 @@
 		if (eaddr == NULL)
 			bpf_error(cstate, "unknown ether host: %s", name);
 
-		alist = pcap_nametoaddr(name);
-		if (alist == NULL || *alist == NULL)
+		res = pcap_nametoaddrinfo(name);
+		cstate->ai = res;
+		if (res == NULL)
 			bpf_error(cstate, "unknown host '%s'", name);
-		b = gen_gateway(eaddr, alist, proto, dir);
-		free(eaddr);
+		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(cstate, "'gateway' not supported in this configuration");
@@ -6544,7 +6660,6 @@
 		/* NOTREACHED */
 	}
 	/* NOTREACHED */
-	return NULL;
 }
 
 struct block *
@@ -6663,7 +6778,7 @@
 	struct in6_addr *addr;
 	struct in6_addr mask;
 	struct block *b;
-	u_int32_t *a, *m;
+	uint32_t *a, *m;
 
 	if (s2)
 		bpf_error(cstate, "no mask %s supported", s2);
@@ -6685,8 +6800,8 @@
 			(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(cstate, "non-network bits set in \"%s/%d\"", s1, masklen);
@@ -6710,7 +6825,6 @@
 		bpf_error(cstate, "invalid qualifier against IPv6 address");
 		/* NOTREACHED */
 	}
-	return NULL;
 }
 #endif /*INET6*/
 
@@ -6748,12 +6862,10 @@
 	}
 	bpf_error(cstate, "ethernet address used in non-ether expression");
 	/* NOTREACHED */
-	return NULL;
 }
 
 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
@@ -7003,8 +7115,58 @@
 		inst->b = b;
 		break;
 	case Q_ICMPV6:
-		bpf_error(cstate, "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(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(cstate, BPF_ST);
@@ -7176,7 +7338,6 @@
 	}
 	bpf_error(cstate, "too many registers needed to evaluate expression");
 	/* NOTREACHED */
-	return 0;
 }
 
 /*
@@ -7331,7 +7492,6 @@
 	}
 	bpf_error(cstate, "only link-layer/IP broadcast filters supported");
 	/* NOTREACHED */
-	return NULL;
 }
 
 /*
@@ -7527,7 +7687,6 @@
 	}
 	bpf_error(cstate, "link-layer multicast filters supported only on ethernet/FDDI/token ring/ARCNET/802.11/ATM LANE/Fibre Channel");
 	/* NOTREACHED */
-	return NULL;
 }
 
 /*
@@ -7628,8 +7787,18 @@
 	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)
 		/*
@@ -7655,7 +7824,6 @@
 #else /* defined(linux) && defined(PF_PACKET) && defined(SO_ATTACH_FILTER) */
 		bpf_error(cstate, "inbound/outbound not supported on linktype %d",
 		    cstate->linktype);
-		b0 = NULL;
 		/* NOTREACHED */
 #endif /* defined(linux) && defined(PF_PACKET) && defined(SO_ATTACH_FILTER) */
 	}
@@ -7772,51 +7940,45 @@
 }
 #else /* !HAVE_NET_PFVAR_H */
 struct block *
-gen_pf_ifname(compiler_state_t *cstate, const char *ifname)
+gen_pf_ifname(compiler_state_t *cstate, const char *ifname _U_)
 {
 	bpf_error(cstate, "libpcap was compiled without pf support");
 	/* NOTREACHED */
-	return (NULL);
 }
 
 struct block *
-gen_pf_ruleset(compiler_state_t *cstate, char *ruleset)
+gen_pf_ruleset(compiler_state_t *cstate, char *ruleset _U_)
 {
 	bpf_error(cstate, "libpcap was compiled on a machine without pf support");
 	/* NOTREACHED */
-	return (NULL);
 }
 
 struct block *
-gen_pf_rnr(compiler_state_t *cstate, int rnr)
+gen_pf_rnr(compiler_state_t *cstate, int rnr _U_)
 {
 	bpf_error(cstate, "libpcap was compiled on a machine without pf support");
 	/* NOTREACHED */
-	return (NULL);
 }
 
 struct block *
-gen_pf_srnr(compiler_state_t *cstate, int srnr)
+gen_pf_srnr(compiler_state_t *cstate, int srnr _U_)
 {
 	bpf_error(cstate, "libpcap was compiled on a machine without pf support");
 	/* NOTREACHED */
-	return (NULL);
 }
 
 struct block *
-gen_pf_reason(compiler_state_t *cstate, int reason)
+gen_pf_reason(compiler_state_t *cstate, int reason _U_)
 {
 	bpf_error(cstate, "libpcap was compiled on a machine without pf support");
 	/* NOTREACHED */
-	return (NULL);
 }
 
 struct block *
-gen_pf_action(compiler_state_t *cstate, int action)
+gen_pf_action(compiler_state_t *cstate, int action _U_)
 {
 	bpf_error(cstate, "libpcap was compiled on a machine without pf support");
 	/* NOTREACHED */
-	return (NULL);
 }
 #endif /* HAVE_NET_PFVAR_H */
 
@@ -7888,9 +8050,6 @@
 		bpf_error(cstate, "aid supported only on ARCnet");
 		/* NOTREACHED */
 	}
-	bpf_error(cstate, "ARCnet address used in non-arc expression");
-	/* NOTREACHED */
-	return NULL;
 }
 
 static struct block *
@@ -7920,19 +8079,19 @@
 		return b1;
 
 	case Q_ADDR1:
-		bpf_error(cstate, "'addr1' is only supported on 802.11");
+		bpf_error(cstate, "'addr1' and 'address1' are only supported on 802.11");
 		break;
 
 	case Q_ADDR2:
-		bpf_error(cstate, "'addr2' is only supported on 802.11");
+		bpf_error(cstate, "'addr2' and 'address2' are only supported on 802.11");
 		break;
 
 	case Q_ADDR3:
-		bpf_error(cstate, "'addr3' is only supported on 802.11");
+		bpf_error(cstate, "'addr3' and 'address3' are only supported on 802.11");
 		break;
 
 	case Q_ADDR4:
-		bpf_error(cstate, "'addr4' is only supported on 802.11");
+		bpf_error(cstate, "'addr4' and 'address4' are only supported on 802.11");
 		break;
 
 	case Q_RA:
@@ -7947,11 +8106,143 @@
 	/* NOTREACHED */
 }
 
-#if defined(SKF_AD_VLAN_TAG) && defined(SKF_AD_VLAN_TAG_PRESENT)
+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, int vlan_num)
+{
+	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, int vlan_num)
+{
+	struct block *b0, *b1;
+
+	b0 = gen_vlan_tpid_test(cstate);
+
+	if (vlan_num >= 0) {
+		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 (bypass loading VID from packet data) */
+	cnt = 0;
+	for (s2 = b_vid->stmts; s2; s2 = s2->next)
+		cnt++;
+	s2 = new_stmt(cstate, JMP(BPF_JA));
+	s2->s.k = cnt;
+	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, int vlan_num)
 {
-        struct block *b0, *b1;
+        struct block *b0, *b_tpid, *b_vid = NULL;
         struct slist *s;
 
         /* generate new filter code based on extracting packet
@@ -7963,59 +8254,34 @@
         b0->stmts = s;
         b0->s.k = 1;
 
-        if (vlan_num >= 0) {
-                s = new_stmt(cstate, BPF_LD|BPF_B|BPF_ABS);
-                s->s.k = SKF_AD_OFF + SKF_AD_VLAN_TAG;
+	/*
+	 * 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 (vlan_num >= 0)
+		b_vid = gen_vlan_vid_test(cstate, vlan_num);
 
-                b1 = new_block(cstate, JMP(BPF_JEQ));
-                b1->stmts = s;
-                b1->s.k = (bpf_int32) vlan_num;
+	gen_vlan_patch_tpid_test(cstate, b_tpid);
+	gen_or(b0, b_tpid);
+	b0 = b_tpid;
 
-                gen_and(b0,b1);
-                b0 = b1;
-        }
+	if (vlan_num >= 0) {
+		gen_vlan_patch_vid_test(cstate, b_vid);
+		gen_and(b0, b_vid);
+		b0 = b_vid;
+	}
 
         return b0;
 }
 #endif
 
-static struct block *
-gen_vlan_no_bpf_extensions(compiler_state_t *cstate, int vlan_num)
-{
-        struct block *b0, *b1;
-
-        /* check for VLAN, including QinQ */
-        b0 = gen_linktype(cstate, ETHERTYPE_8021Q);
-        b1 = gen_linktype(cstate, ETHERTYPE_8021AD);
-        gen_or(b0,b1);
-        b0 = b1;
-        b1 = gen_linktype(cstate, ETHERTYPE_8021QINQ);
-        gen_or(b0,b1);
-        b0 = b1;
-
-        /* If a specific VLAN is requested, check VLAN id */
-        if (vlan_num >= 0) {
-                b1 = gen_mcmp(cstate, OR_LINKPL, 0, BPF_H,
-                              (bpf_int32)vlan_num, 0x0fff);
-                gen_and(b0, b1);
-                b0 = b1;
-        }
-
-	/*
-	 * The payload follows the full header, including the
-	 * VLAN tags, so skip past this VLAN tag.
-	 */
-        cstate->off_linkpl.constant_part += 4;
-
-	/*
-	 * The link-layer type information follows the VLAN tags, so
-	 * skip past this VLAN tag.
-	 */
-        cstate->off_linktype.constant_part += 4;
-
-        return b0;
-}
-
 /*
  * support IEEE 802.1Q VLAN trunk over ethernet
  */
@@ -8064,7 +8330,7 @@
 	case DLT_EN10MB:
 	case DLT_NETANALYZER:
 	case DLT_NETANALYZER_TRANSPARENT:
-#if defined(SKF_AD_VLAN_TAG) && defined(SKF_AD_VLAN_TAG_PRESENT)
+#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 &&
@@ -8136,7 +8402,6 @@
             default:
                     bpf_error(cstate, "no MPLS support for data link type %d",
                           cstate->linktype);
-                    b0 = NULL;
                     /*NOTREACHED*/
                     break;
             }
@@ -8557,7 +8822,7 @@
 	case A_VPI:
 		if (!cstate->is_atm)
 			bpf_error(cstate, "'vpi' supported only on raw ATM");
-		if (cstate->off_vpi == (u_int)-1)
+		if (cstate->off_vpi == OFFSET_NOT_SET)
 			abort();
 		b0 = gen_ncmp(cstate, OR_LINKHDR, cstate->off_vpi, BPF_B, 0xffffffff, jtype,
 		    reverse, jvalue);
@@ -8566,21 +8831,21 @@
 	case A_VCI:
 		if (!cstate->is_atm)
 			bpf_error(cstate, "'vci' supported only on raw ATM");
-		if (cstate->off_vci == (u_int)-1)
+		if (cstate->off_vci == OFFSET_NOT_SET)
 			abort();
 		b0 = gen_ncmp(cstate, OR_LINKHDR, cstate->off_vci, BPF_H, 0xffffffff, jtype,
 		    reverse, jvalue);
 		break;
 
 	case A_PROTOTYPE:
-		if (cstate->off_proto == (u_int)-1)
+		if (cstate->off_proto == OFFSET_NOT_SET)
 			abort();	/* XXX - this isn't on FreeBSD */
 		b0 = gen_ncmp(cstate, OR_LINKHDR, cstate->off_proto, BPF_B, 0x0f, jtype,
 		    reverse, jvalue);
 		break;
 
 	case A_MSGTYPE:
-		if (cstate->off_payload == (u_int)-1)
+		if (cstate->off_payload == OFFSET_NOT_SET)
 			abort();
 		b0 = gen_ncmp(cstate, OR_LINKHDR, cstate->off_payload + MSG_TYPE_POS, BPF_B,
 		    0xffffffff, jtype, reverse, jvalue);
@@ -8589,7 +8854,7 @@
 	case A_CALLREFTYPE:
 		if (!cstate->is_atm)
 			bpf_error(cstate, "'callref' supported only on raw ATM");
-		if (cstate->off_proto == (u_int)-1)
+		if (cstate->off_proto == OFFSET_NOT_SET)
 			abort();
 		b0 = gen_ncmp(cstate, OR_LINKHDR, cstate->off_proto, BPF_B, 0xffffffff,
 		    jtype, reverse, jvalue);
@@ -8791,7 +9056,7 @@
 		/* FALLTHROUGH */
 
 	case M_SIO:
-		if (cstate->off_sio == (u_int)-1)
+		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)
@@ -8804,7 +9069,7 @@
 	case MH_OPC:
 		newoff_opc+=3;
         case M_OPC:
-	        if (cstate->off_opc == (u_int)-1)
+	        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)
@@ -8828,7 +9093,7 @@
 		/* FALLTHROUGH */
 
 	case M_DPC:
-	        if (cstate->off_dpc == (u_int)-1)
+	        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)
@@ -8848,7 +9113,7 @@
 	case MH_SLS:
 	  newoff_sls+=3;
 	case M_SLS:
-	        if (cstate->off_sls == (u_int)-1)
+	        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)
diff --git a/gencode.h b/gencode.h
index 2b089d2..88def5a 100644
--- a/gencode.h
+++ b/gencode.h
@@ -19,6 +19,8 @@
  * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
  */
 
+#include "pcap/funcattrs.h"
+
 /*
  * ATM support:
  *
@@ -53,10 +55,6 @@
  * POSSIBILITY OF SUCH DAMAGE.
  */
 
-#ifndef HAVE___ATTRIBUTE__
-#define __attribute__(x)
-#endif /* HAVE___ATTRIBUTE__ */
-
 /* Address qualifiers. */
 
 #define Q_HOST		1
@@ -268,6 +266,11 @@
 	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 */
@@ -340,11 +343,29 @@
 struct block *gen_mtp3field_code(compiler_state_t *, int, bpf_u_int32,
     bpf_u_int32, int);
 
+#ifndef HAVE_NET_PFVAR_H
+PCAP_NORETURN
+#endif
 struct block *gen_pf_ifname(compiler_state_t *, const char *);
+#ifndef HAVE_NET_PFVAR_H
+PCAP_NORETURN
+#endif
 struct block *gen_pf_rnr(compiler_state_t *, int);
+#ifndef HAVE_NET_PFVAR_H
+PCAP_NORETURN
+#endif
 struct block *gen_pf_srnr(compiler_state_t *, int);
+#ifndef HAVE_NET_PFVAR_H
+PCAP_NORETURN
+#endif
 struct block *gen_pf_ruleset(compiler_state_t *, char *);
+#ifndef HAVE_NET_PFVAR_H
+PCAP_NORETURN
+#endif
 struct block *gen_pf_reason(compiler_state_t *, int);
+#ifndef HAVE_NET_PFVAR_H
+PCAP_NORETURN
+#endif
 struct block *gen_pf_action(compiler_state_t *, int);
 
 struct block *gen_p80211_type(compiler_state_t *, int, int);
@@ -366,20 +387,13 @@
 };
 
 void bpf_optimize(compiler_state_t *, struct icode *ic);
-void bpf_syntax_error(compiler_state_t *, const char *);
-void bpf_error(compiler_state_t *, const char *, ...)
-    __attribute__((noreturn))
-#ifdef __ATTRIBUTE___FORMAT_OK
-    __attribute__((format (printf, 2, 3)))
-#endif /* __ATTRIBUTE___FORMAT_OK */
-    ;
+void PCAP_NORETURN bpf_syntax_error(compiler_state_t *, const char *);
+void PCAP_NORETURN bpf_error(compiler_state_t *, const char *, ...)
+    PCAP_PRINTFLIKE(2, 3);
 
 void finish_parse(compiler_state_t *, struct block *);
 char *sdup(compiler_state_t *, const char *);
 
-struct _opt_state;
-typedef struct _opt_state opt_state_t;
-
 struct bpf_insn *icode_to_fcode(compiler_state_t *, struct icode *,
     struct block *, u_int *);
 void sappend(struct slist *, struct slist *);
diff --git a/grammar.c b/grammar.c
index 673449b..2be760b 100644
--- a/grammar.c
+++ b/grammar.c
@@ -1,8 +1,8 @@
-/* A Bison parser, made by GNU Bison 3.0.2.  */
+/* A Bison parser, made by GNU Bison 3.0.4.  */
 
 /* Bison implementation for Yacc-like parsers in C
 
-   Copyright (C) 1984, 1989-1990, 2000-2013 Free Software Foundation, Inc.
+   Copyright (C) 1984, 1989-1990, 2000-2015 Free Software Foundation, Inc.
 
    This program is free software: you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
@@ -44,7 +44,7 @@
 #define YYBISON 1
 
 /* Bison version.  */
-#define YYBISON_VERSION "3.0.2"
+#define YYBISON_VERSION "3.0.4"
 
 /* Skeleton name.  */
 #define YYSKELETON_NAME "yacc.c"
@@ -93,19 +93,15 @@
  */
 
 #ifdef HAVE_CONFIG_H
-#include "config.h"
+#include <config.h>
 #endif
 
-#ifdef _WIN32
-#include <pcap-stdinc.h>
-#else /* _WIN32 */
-#include <sys/types.h>
-#include <sys/socket.h>
-#endif /* _WIN32 */
-
 #include <stdlib.h>
 
 #ifndef _WIN32
+#include <sys/types.h>
+#include <sys/socket.h>
+
 #if __STDC__
 struct mbuf;
 struct rtentry;
@@ -117,6 +113,8 @@
 
 #include <stdio.h>
 
+#include "diag-control.h"
+
 #include "pcap-int.h"
 
 #include "gencode.h"
@@ -136,9 +134,30 @@
 #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 */
@@ -245,8 +264,8 @@
 
 static struct qual qerr = { Q_UNDEF, Q_UNDEF, Q_UNDEF, Q_UNDEF };
 
-static void
-yyerror(void *yyscanner, compiler_state_t *cstate, const char *msg)
+static PCAP_NORETURN_DEF void
+yyerror(void *yyscanner _U_, compiler_state_t *cstate, const char *msg)
 {
 	bpf_syntax_error(cstate, msg);
 	/* NOTREACHED */
@@ -292,28 +311,24 @@
 	}
 }
 #else /* !HAVE_NET_PFVAR_H */
-static int
-pfreason_to_num(compiler_state_t *cstate, const char *reason)
+static PCAP_NORETURN_DEF int
+pfreason_to_num(compiler_state_t *cstate, const char *reason _U_)
 {
 	bpf_error(cstate, "libpcap was compiled on a machine without pf support");
 	/*NOTREACHED*/
-
-	/* this is to make the VC compiler happy */
-	return -1;
 }
 
-static int
-pfaction_to_num(compiler_state_t *cstate, const char *action)
+static PCAP_NORETURN_DEF int
+pfaction_to_num(compiler_state_t *cstate, const char *action _U_)
 {
 	bpf_error(cstate, "libpcap was compiled on a machine without pf support");
 	/*NOTREACHED*/
-
-	/* this is to make the VC compiler happy */
-	return -1;
 }
 #endif /* HAVE_NET_PFVAR_H */
 
-#line 317 "grammar.c" /* yacc.c:339  */
+DIAG_OFF_BISON_BYACC
+
+#line 332 "grammar.c" /* yacc.c:339  */
 
 # ifndef YY_NULLPTR
 #  if defined __cplusplus && 201103L <= __cplusplus
@@ -592,10 +607,10 @@
 
 /* Value type.  */
 #if ! defined YYSTYPE && ! defined YYSTYPE_IS_DECLARED
-typedef union YYSTYPE YYSTYPE;
+
 union YYSTYPE
 {
-#line 271 "grammar.y" /* yacc.c:355  */
+#line 286 "grammar.y" /* yacc.c:355  */
 
 	int i;
 	bpf_u_int32 h;
@@ -611,8 +626,10 @@
 	} blk;
 	struct block *rblk;
 
-#line 615 "grammar.c" /* yacc.c:355  */
+#line 630 "grammar.c" /* yacc.c:355  */
 };
+
+typedef union YYSTYPE YYSTYPE;
 # define YYSTYPE_IS_TRIVIAL 1
 # define YYSTYPE_IS_DECLARED 1
 #endif
@@ -625,7 +642,7 @@
 
 /* Copy the second part of user declarations.  */
 
-#line 629 "grammar.c" /* yacc.c:358  */
+#line 646 "grammar.c" /* yacc.c:358  */
 
 #ifdef short
 # undef short
@@ -934,29 +951,29 @@
   /* YYRLINE[YYN] -- Source line where rule number YYN was defined.  */
 static const yytype_uint16 yyrline[] =
 {
-       0,   345,   345,   349,   351,   353,   354,   355,   356,   357,
-     359,   361,   363,   364,   366,   368,   369,   371,   373,   386,
-     395,   404,   413,   422,   424,   426,   428,   429,   430,   432,
-     434,   436,   437,   439,   440,   441,   442,   443,   444,   446,
-     447,   448,   449,   451,   453,   454,   455,   456,   457,   458,
-     461,   462,   465,   466,   467,   468,   469,   470,   471,   472,
-     473,   474,   475,   476,   479,   480,   481,   482,   485,   487,
-     488,   489,   490,   491,   492,   493,   494,   495,   496,   497,
-     498,   499,   500,   501,   502,   503,   504,   505,   506,   507,
-     508,   509,   510,   511,   512,   513,   514,   515,   516,   517,
-     518,   519,   520,   521,   522,   523,   524,   525,   527,   528,
-     529,   530,   531,   532,   533,   534,   535,   536,   537,   538,
-     539,   540,   541,   542,   543,   544,   545,   548,   549,   550,
-     551,   552,   553,   556,   561,   564,   568,   571,   572,   578,
-     579,   599,   615,   616,   637,   640,   641,   654,   655,   658,
-     661,   662,   663,   665,   666,   667,   669,   670,   672,   673,
-     674,   675,   676,   677,   678,   679,   680,   681,   682,   683,
-     684,   685,   686,   688,   689,   690,   691,   692,   694,   695,
-     697,   698,   699,   700,   701,   702,   703,   705,   706,   707,
-     708,   711,   712,   714,   715,   716,   717,   719,   726,   727,
-     730,   731,   732,   733,   734,   735,   738,   739,   740,   741,
-     742,   743,   744,   745,   747,   748,   749,   750,   752,   765,
-     766
+       0,   360,   360,   364,   366,   368,   369,   370,   371,   372,
+     374,   376,   378,   379,   381,   383,   384,   386,   388,   401,
+     410,   419,   428,   437,   439,   441,   443,   444,   445,   447,
+     449,   451,   452,   454,   455,   456,   457,   458,   459,   461,
+     462,   463,   464,   466,   468,   469,   470,   471,   472,   473,
+     476,   477,   480,   481,   482,   483,   484,   485,   486,   487,
+     488,   489,   490,   491,   494,   495,   496,   497,   500,   502,
+     503,   504,   505,   506,   507,   508,   509,   510,   511,   512,
+     513,   514,   515,   516,   517,   518,   519,   520,   521,   522,
+     523,   524,   525,   526,   527,   528,   529,   530,   531,   532,
+     533,   534,   535,   536,   537,   538,   539,   540,   542,   543,
+     544,   545,   546,   547,   548,   549,   550,   551,   552,   553,
+     554,   555,   556,   557,   558,   559,   560,   563,   564,   565,
+     566,   567,   568,   571,   576,   579,   583,   586,   587,   593,
+     594,   614,   630,   631,   652,   655,   656,   669,   670,   673,
+     676,   677,   678,   680,   681,   682,   684,   685,   687,   688,
+     689,   690,   691,   692,   693,   694,   695,   696,   697,   698,
+     699,   700,   701,   703,   704,   705,   706,   707,   709,   710,
+     712,   713,   714,   715,   716,   717,   718,   720,   721,   722,
+     723,   726,   727,   729,   730,   731,   732,   734,   741,   742,
+     745,   746,   747,   748,   749,   750,   753,   754,   755,   756,
+     757,   758,   759,   760,   762,   763,   764,   765,   767,   780,
+     781
 };
 #endif
 
@@ -2060,90 +2077,90 @@
   switch (yyn)
     {
         case 2:
-#line 346 "grammar.y" /* yacc.c:1646  */
+#line 361 "grammar.y" /* yacc.c:1646  */
     {
 	finish_parse(cstate, (yyvsp[0].blk).b);
 }
-#line 2068 "grammar.c" /* yacc.c:1646  */
+#line 2085 "grammar.c" /* yacc.c:1646  */
     break;
 
   case 4:
-#line 351 "grammar.y" /* yacc.c:1646  */
+#line 366 "grammar.y" /* yacc.c:1646  */
     { (yyval.blk).q = qerr; }
-#line 2074 "grammar.c" /* yacc.c:1646  */
+#line 2091 "grammar.c" /* yacc.c:1646  */
     break;
 
   case 6:
-#line 354 "grammar.y" /* yacc.c:1646  */
+#line 369 "grammar.y" /* yacc.c:1646  */
     { gen_and((yyvsp[-2].blk).b, (yyvsp[0].blk).b); (yyval.blk) = (yyvsp[0].blk); }
-#line 2080 "grammar.c" /* yacc.c:1646  */
+#line 2097 "grammar.c" /* yacc.c:1646  */
     break;
 
   case 7:
-#line 355 "grammar.y" /* yacc.c:1646  */
+#line 370 "grammar.y" /* yacc.c:1646  */
     { gen_and((yyvsp[-2].blk).b, (yyvsp[0].blk).b); (yyval.blk) = (yyvsp[0].blk); }
-#line 2086 "grammar.c" /* yacc.c:1646  */
+#line 2103 "grammar.c" /* yacc.c:1646  */
     break;
 
   case 8:
-#line 356 "grammar.y" /* yacc.c:1646  */
+#line 371 "grammar.y" /* yacc.c:1646  */
     { gen_or((yyvsp[-2].blk).b, (yyvsp[0].blk).b); (yyval.blk) = (yyvsp[0].blk); }
-#line 2092 "grammar.c" /* yacc.c:1646  */
+#line 2109 "grammar.c" /* yacc.c:1646  */
     break;
 
   case 9:
-#line 357 "grammar.y" /* yacc.c:1646  */
+#line 372 "grammar.y" /* yacc.c:1646  */
     { gen_or((yyvsp[-2].blk).b, (yyvsp[0].blk).b); (yyval.blk) = (yyvsp[0].blk); }
-#line 2098 "grammar.c" /* yacc.c:1646  */
+#line 2115 "grammar.c" /* yacc.c:1646  */
     break;
 
   case 10:
-#line 359 "grammar.y" /* yacc.c:1646  */
+#line 374 "grammar.y" /* yacc.c:1646  */
     { (yyval.blk) = (yyvsp[-1].blk); }
-#line 2104 "grammar.c" /* yacc.c:1646  */
+#line 2121 "grammar.c" /* yacc.c:1646  */
     break;
 
   case 11:
-#line 361 "grammar.y" /* yacc.c:1646  */
+#line 376 "grammar.y" /* yacc.c:1646  */
     { (yyval.blk) = (yyvsp[-1].blk); }
-#line 2110 "grammar.c" /* yacc.c:1646  */
+#line 2127 "grammar.c" /* yacc.c:1646  */
     break;
 
   case 13:
-#line 364 "grammar.y" /* yacc.c:1646  */
+#line 379 "grammar.y" /* yacc.c:1646  */
     { (yyval.blk).b = gen_ncode(cstate, NULL, (bpf_u_int32)(yyvsp[0].i),
 						   (yyval.blk).q = (yyvsp[-1].blk).q); }
-#line 2117 "grammar.c" /* yacc.c:1646  */
+#line 2134 "grammar.c" /* yacc.c:1646  */
     break;
 
   case 14:
-#line 366 "grammar.y" /* yacc.c:1646  */
+#line 381 "grammar.y" /* yacc.c:1646  */
     { (yyval.blk) = (yyvsp[-1].blk); }
-#line 2123 "grammar.c" /* yacc.c:1646  */
+#line 2140 "grammar.c" /* yacc.c:1646  */
     break;
 
   case 15:
-#line 368 "grammar.y" /* yacc.c:1646  */
+#line 383 "grammar.y" /* yacc.c:1646  */
     { (yyval.blk).b = gen_scode(cstate, (yyvsp[0].s), (yyval.blk).q = (yyvsp[-1].blk).q); }
-#line 2129 "grammar.c" /* yacc.c:1646  */
+#line 2146 "grammar.c" /* yacc.c:1646  */
     break;
 
   case 16:
-#line 369 "grammar.y" /* yacc.c:1646  */
+#line 384 "grammar.y" /* yacc.c:1646  */
     { (yyval.blk).b = gen_mcode(cstate, (yyvsp[-2].s), NULL, (yyvsp[0].i),
 				    (yyval.blk).q = (yyvsp[-3].blk).q); }
-#line 2136 "grammar.c" /* yacc.c:1646  */
+#line 2153 "grammar.c" /* yacc.c:1646  */
     break;
 
   case 17:
-#line 371 "grammar.y" /* yacc.c:1646  */
+#line 386 "grammar.y" /* yacc.c:1646  */
     { (yyval.blk).b = gen_mcode(cstate, (yyvsp[-2].s), (yyvsp[0].s), 0,
 				    (yyval.blk).q = (yyvsp[-3].blk).q); }
-#line 2143 "grammar.c" /* yacc.c:1646  */
+#line 2160 "grammar.c" /* yacc.c:1646  */
     break;
 
   case 18:
-#line 373 "grammar.y" /* yacc.c:1646  */
+#line 388 "grammar.y" /* yacc.c:1646  */
     {
 				  /* Decide how to parse HID based on proto */
 				  (yyval.blk).q = (yyvsp[-1].blk).q;
@@ -2157,11 +2174,11 @@
 				  	bpf_error(cstate, "'protochain' modifier applied to ip host");
 				  (yyval.blk).b = gen_ncode(cstate, (yyvsp[0].s), 0, (yyval.blk).q);
 				}
-#line 2161 "grammar.c" /* yacc.c:1646  */
+#line 2178 "grammar.c" /* yacc.c:1646  */
     break;
 
   case 19:
-#line 386 "grammar.y" /* yacc.c:1646  */
+#line 401 "grammar.y" /* yacc.c:1646  */
     {
 #ifdef INET6
 				  (yyval.blk).b = gen_mcode6(cstate, (yyvsp[-2].s), NULL, (yyvsp[0].i),
@@ -2171,11 +2188,11 @@
 					"in this configuration");
 #endif /*INET6*/
 				}
-#line 2175 "grammar.c" /* yacc.c:1646  */
+#line 2192 "grammar.c" /* yacc.c:1646  */
     break;
 
   case 20:
-#line 395 "grammar.y" /* yacc.c:1646  */
+#line 410 "grammar.y" /* yacc.c:1646  */
     {
 #ifdef INET6
 				  (yyval.blk).b = gen_mcode6(cstate, (yyvsp[0].s), 0, 128,
@@ -2185,11 +2202,11 @@
 					"in this configuration");
 #endif /*INET6*/
 				}
-#line 2189 "grammar.c" /* yacc.c:1646  */
+#line 2206 "grammar.c" /* yacc.c:1646  */
     break;
 
   case 21:
-#line 404 "grammar.y" /* yacc.c:1646  */
+#line 419 "grammar.y" /* yacc.c:1646  */
     {
 				  (yyval.blk).b = gen_ecode(cstate, (yyvsp[0].e), (yyval.blk).q = (yyvsp[-1].blk).q);
 				  /*
@@ -2199,11 +2216,11 @@
 				   */
 				  free((yyvsp[0].e));
 				}
-#line 2203 "grammar.c" /* yacc.c:1646  */
+#line 2220 "grammar.c" /* yacc.c:1646  */
     break;
 
   case 22:
-#line 413 "grammar.y" /* yacc.c:1646  */
+#line 428 "grammar.y" /* yacc.c:1646  */
     {
 				  (yyval.blk).b = gen_acode(cstate, (yyvsp[0].e), (yyval.blk).q = (yyvsp[-1].blk).q);
 				  /*
@@ -2213,691 +2230,691 @@
 				   */
 				  free((yyvsp[0].e));
 				}
-#line 2217 "grammar.c" /* yacc.c:1646  */
+#line 2234 "grammar.c" /* yacc.c:1646  */
     break;
 
   case 23:
-#line 422 "grammar.y" /* yacc.c:1646  */
+#line 437 "grammar.y" /* yacc.c:1646  */
     { gen_not((yyvsp[0].blk).b); (yyval.blk) = (yyvsp[0].blk); }
-#line 2223 "grammar.c" /* yacc.c:1646  */
+#line 2240 "grammar.c" /* yacc.c:1646  */
     break;
 
   case 24:
-#line 424 "grammar.y" /* yacc.c:1646  */
+#line 439 "grammar.y" /* yacc.c:1646  */
     { (yyval.blk) = (yyvsp[-1].blk); }
-#line 2229 "grammar.c" /* yacc.c:1646  */
+#line 2246 "grammar.c" /* yacc.c:1646  */
     break;
 
   case 25:
-#line 426 "grammar.y" /* yacc.c:1646  */
+#line 441 "grammar.y" /* yacc.c:1646  */
     { (yyval.blk) = (yyvsp[-1].blk); }
-#line 2235 "grammar.c" /* yacc.c:1646  */
+#line 2252 "grammar.c" /* yacc.c:1646  */
     break;
 
   case 27:
-#line 429 "grammar.y" /* yacc.c:1646  */
+#line 444 "grammar.y" /* yacc.c:1646  */
     { gen_and((yyvsp[-2].blk).b, (yyvsp[0].blk).b); (yyval.blk) = (yyvsp[0].blk); }
-#line 2241 "grammar.c" /* yacc.c:1646  */
+#line 2258 "grammar.c" /* yacc.c:1646  */
     break;
 
   case 28:
-#line 430 "grammar.y" /* yacc.c:1646  */
+#line 445 "grammar.y" /* yacc.c:1646  */
     { gen_or((yyvsp[-2].blk).b, (yyvsp[0].blk).b); (yyval.blk) = (yyvsp[0].blk); }
-#line 2247 "grammar.c" /* yacc.c:1646  */
+#line 2264 "grammar.c" /* yacc.c:1646  */
     break;
 
   case 29:
-#line 432 "grammar.y" /* yacc.c:1646  */
+#line 447 "grammar.y" /* yacc.c:1646  */
     { (yyval.blk).b = gen_ncode(cstate, NULL, (bpf_u_int32)(yyvsp[0].i),
 						   (yyval.blk).q = (yyvsp[-1].blk).q); }
-#line 2254 "grammar.c" /* yacc.c:1646  */
+#line 2271 "grammar.c" /* yacc.c:1646  */
     break;
 
   case 32:
-#line 437 "grammar.y" /* yacc.c:1646  */
+#line 452 "grammar.y" /* yacc.c:1646  */
     { gen_not((yyvsp[0].blk).b); (yyval.blk) = (yyvsp[0].blk); }
-#line 2260 "grammar.c" /* yacc.c:1646  */
+#line 2277 "grammar.c" /* yacc.c:1646  */
     break;
 
   case 33:
-#line 439 "grammar.y" /* yacc.c:1646  */
+#line 454 "grammar.y" /* yacc.c:1646  */
     { QSET((yyval.blk).q, (yyvsp[-2].i), (yyvsp[-1].i), (yyvsp[0].i)); }
-#line 2266 "grammar.c" /* yacc.c:1646  */
+#line 2283 "grammar.c" /* yacc.c:1646  */
     break;
 
   case 34:
-#line 440 "grammar.y" /* yacc.c:1646  */
+#line 455 "grammar.y" /* yacc.c:1646  */
     { QSET((yyval.blk).q, (yyvsp[-1].i), (yyvsp[0].i), Q_DEFAULT); }
-#line 2272 "grammar.c" /* yacc.c:1646  */
+#line 2289 "grammar.c" /* yacc.c:1646  */
     break;
 
   case 35:
-#line 441 "grammar.y" /* yacc.c:1646  */
+#line 456 "grammar.y" /* yacc.c:1646  */
     { QSET((yyval.blk).q, (yyvsp[-1].i), Q_DEFAULT, (yyvsp[0].i)); }
-#line 2278 "grammar.c" /* yacc.c:1646  */
+#line 2295 "grammar.c" /* yacc.c:1646  */
     break;
 
   case 36:
-#line 442 "grammar.y" /* yacc.c:1646  */
+#line 457 "grammar.y" /* yacc.c:1646  */
     { QSET((yyval.blk).q, (yyvsp[-1].i), Q_DEFAULT, Q_PROTO); }
-#line 2284 "grammar.c" /* yacc.c:1646  */
+#line 2301 "grammar.c" /* yacc.c:1646  */
     break;
 
   case 37:
-#line 443 "grammar.y" /* yacc.c:1646  */
+#line 458 "grammar.y" /* yacc.c:1646  */
     { QSET((yyval.blk).q, (yyvsp[-1].i), Q_DEFAULT, Q_PROTOCHAIN); }
-#line 2290 "grammar.c" /* yacc.c:1646  */
+#line 2307 "grammar.c" /* yacc.c:1646  */
     break;
 
   case 38:
-#line 444 "grammar.y" /* yacc.c:1646  */
+#line 459 "grammar.y" /* yacc.c:1646  */
     { QSET((yyval.blk).q, (yyvsp[-1].i), Q_DEFAULT, (yyvsp[0].i)); }
-#line 2296 "grammar.c" /* yacc.c:1646  */
+#line 2313 "grammar.c" /* yacc.c:1646  */
     break;
 
   case 39:
-#line 446 "grammar.y" /* yacc.c:1646  */
+#line 461 "grammar.y" /* yacc.c:1646  */
     { (yyval.blk) = (yyvsp[0].blk); }
-#line 2302 "grammar.c" /* yacc.c:1646  */
+#line 2319 "grammar.c" /* yacc.c:1646  */
     break;
 
   case 40:
-#line 447 "grammar.y" /* yacc.c:1646  */
+#line 462 "grammar.y" /* yacc.c:1646  */
     { (yyval.blk).b = (yyvsp[-1].blk).b; (yyval.blk).q = (yyvsp[-2].blk).q; }
-#line 2308 "grammar.c" /* yacc.c:1646  */
+#line 2325 "grammar.c" /* yacc.c:1646  */
     break;
 
   case 41:
-#line 448 "grammar.y" /* yacc.c:1646  */
+#line 463 "grammar.y" /* yacc.c:1646  */
     { (yyval.blk).b = gen_proto_abbrev(cstate, (yyvsp[0].i)); (yyval.blk).q = qerr; }
-#line 2314 "grammar.c" /* yacc.c:1646  */
+#line 2331 "grammar.c" /* yacc.c:1646  */
     break;
 
   case 42:
-#line 449 "grammar.y" /* yacc.c:1646  */
+#line 464 "grammar.y" /* yacc.c:1646  */
     { (yyval.blk).b = gen_relation(cstate, (yyvsp[-1].i), (yyvsp[-2].a), (yyvsp[0].a), 0);
 				  (yyval.blk).q = qerr; }
-#line 2321 "grammar.c" /* yacc.c:1646  */
+#line 2338 "grammar.c" /* yacc.c:1646  */
     break;
 
   case 43:
-#line 451 "grammar.y" /* yacc.c:1646  */
+#line 466 "grammar.y" /* yacc.c:1646  */
     { (yyval.blk).b = gen_relation(cstate, (yyvsp[-1].i), (yyvsp[-2].a), (yyvsp[0].a), 1);
 				  (yyval.blk).q = qerr; }
-#line 2328 "grammar.c" /* yacc.c:1646  */
+#line 2345 "grammar.c" /* yacc.c:1646  */
     break;
 
   case 44:
-#line 453 "grammar.y" /* yacc.c:1646  */
+#line 468 "grammar.y" /* yacc.c:1646  */
     { (yyval.blk).b = (yyvsp[0].rblk); (yyval.blk).q = qerr; }
-#line 2334 "grammar.c" /* yacc.c:1646  */
+#line 2351 "grammar.c" /* yacc.c:1646  */
     break;
 
   case 45:
-#line 454 "grammar.y" /* yacc.c:1646  */
+#line 469 "grammar.y" /* yacc.c:1646  */
     { (yyval.blk).b = gen_atmtype_abbrev(cstate, (yyvsp[0].i)); (yyval.blk).q = qerr; }
-#line 2340 "grammar.c" /* yacc.c:1646  */
+#line 2357 "grammar.c" /* yacc.c:1646  */
     break;
 
   case 46:
-#line 455 "grammar.y" /* yacc.c:1646  */
+#line 470 "grammar.y" /* yacc.c:1646  */
     { (yyval.blk).b = gen_atmmulti_abbrev(cstate, (yyvsp[0].i)); (yyval.blk).q = qerr; }
-#line 2346 "grammar.c" /* yacc.c:1646  */
+#line 2363 "grammar.c" /* yacc.c:1646  */
     break;
 
   case 47:
-#line 456 "grammar.y" /* yacc.c:1646  */
+#line 471 "grammar.y" /* yacc.c:1646  */
     { (yyval.blk).b = (yyvsp[0].blk).b; (yyval.blk).q = qerr; }
-#line 2352 "grammar.c" /* yacc.c:1646  */
+#line 2369 "grammar.c" /* yacc.c:1646  */
     break;
 
   case 48:
-#line 457 "grammar.y" /* yacc.c:1646  */
+#line 472 "grammar.y" /* yacc.c:1646  */
     { (yyval.blk).b = gen_mtp2type_abbrev(cstate, (yyvsp[0].i)); (yyval.blk).q = qerr; }
-#line 2358 "grammar.c" /* yacc.c:1646  */
+#line 2375 "grammar.c" /* yacc.c:1646  */
     break;
 
   case 49:
-#line 458 "grammar.y" /* yacc.c:1646  */
+#line 473 "grammar.y" /* yacc.c:1646  */
     { (yyval.blk).b = (yyvsp[0].blk).b; (yyval.blk).q = qerr; }
-#line 2364 "grammar.c" /* yacc.c:1646  */
+#line 2381 "grammar.c" /* yacc.c:1646  */
     break;
 
   case 51:
-#line 462 "grammar.y" /* yacc.c:1646  */
+#line 477 "grammar.y" /* yacc.c:1646  */
     { (yyval.i) = Q_DEFAULT; }
-#line 2370 "grammar.c" /* yacc.c:1646  */
+#line 2387 "grammar.c" /* yacc.c:1646  */
     break;
 
   case 52:
-#line 465 "grammar.y" /* yacc.c:1646  */
+#line 480 "grammar.y" /* yacc.c:1646  */
     { (yyval.i) = Q_SRC; }
-#line 2376 "grammar.c" /* yacc.c:1646  */
+#line 2393 "grammar.c" /* yacc.c:1646  */
     break;
 
   case 53:
-#line 466 "grammar.y" /* yacc.c:1646  */
+#line 481 "grammar.y" /* yacc.c:1646  */
     { (yyval.i) = Q_DST; }
-#line 2382 "grammar.c" /* yacc.c:1646  */
+#line 2399 "grammar.c" /* yacc.c:1646  */
     break;
 
   case 54:
-#line 467 "grammar.y" /* yacc.c:1646  */
+#line 482 "grammar.y" /* yacc.c:1646  */
     { (yyval.i) = Q_OR; }
-#line 2388 "grammar.c" /* yacc.c:1646  */
+#line 2405 "grammar.c" /* yacc.c:1646  */
     break;
 
   case 55:
-#line 468 "grammar.y" /* yacc.c:1646  */
+#line 483 "grammar.y" /* yacc.c:1646  */
     { (yyval.i) = Q_OR; }
-#line 2394 "grammar.c" /* yacc.c:1646  */
+#line 2411 "grammar.c" /* yacc.c:1646  */
     break;
 
   case 56:
-#line 469 "grammar.y" /* yacc.c:1646  */
+#line 484 "grammar.y" /* yacc.c:1646  */
     { (yyval.i) = Q_AND; }
-#line 2400 "grammar.c" /* yacc.c:1646  */
+#line 2417 "grammar.c" /* yacc.c:1646  */
     break;
 
   case 57:
-#line 470 "grammar.y" /* yacc.c:1646  */
+#line 485 "grammar.y" /* yacc.c:1646  */
     { (yyval.i) = Q_AND; }
-#line 2406 "grammar.c" /* yacc.c:1646  */
+#line 2423 "grammar.c" /* yacc.c:1646  */
     break;
 
   case 58:
-#line 471 "grammar.y" /* yacc.c:1646  */
+#line 486 "grammar.y" /* yacc.c:1646  */
     { (yyval.i) = Q_ADDR1; }
-#line 2412 "grammar.c" /* yacc.c:1646  */
+#line 2429 "grammar.c" /* yacc.c:1646  */
     break;
 
   case 59:
-#line 472 "grammar.y" /* yacc.c:1646  */
+#line 487 "grammar.y" /* yacc.c:1646  */
     { (yyval.i) = Q_ADDR2; }
-#line 2418 "grammar.c" /* yacc.c:1646  */
+#line 2435 "grammar.c" /* yacc.c:1646  */
     break;
 
   case 60:
-#line 473 "grammar.y" /* yacc.c:1646  */
+#line 488 "grammar.y" /* yacc.c:1646  */
     { (yyval.i) = Q_ADDR3; }
-#line 2424 "grammar.c" /* yacc.c:1646  */
+#line 2441 "grammar.c" /* yacc.c:1646  */
     break;
 
   case 61:
-#line 474 "grammar.y" /* yacc.c:1646  */
+#line 489 "grammar.y" /* yacc.c:1646  */
     { (yyval.i) = Q_ADDR4; }
-#line 2430 "grammar.c" /* yacc.c:1646  */
+#line 2447 "grammar.c" /* yacc.c:1646  */
     break;
 
   case 62:
-#line 475 "grammar.y" /* yacc.c:1646  */
+#line 490 "grammar.y" /* yacc.c:1646  */
     { (yyval.i) = Q_RA; }
-#line 2436 "grammar.c" /* yacc.c:1646  */
+#line 2453 "grammar.c" /* yacc.c:1646  */
     break;
 
   case 63:
-#line 476 "grammar.y" /* yacc.c:1646  */
+#line 491 "grammar.y" /* yacc.c:1646  */
     { (yyval.i) = Q_TA; }
-#line 2442 "grammar.c" /* yacc.c:1646  */
+#line 2459 "grammar.c" /* yacc.c:1646  */
     break;
 
   case 64:
-#line 479 "grammar.y" /* yacc.c:1646  */
+#line 494 "grammar.y" /* yacc.c:1646  */
     { (yyval.i) = Q_HOST; }
-#line 2448 "grammar.c" /* yacc.c:1646  */
+#line 2465 "grammar.c" /* yacc.c:1646  */
     break;
 
   case 65:
-#line 480 "grammar.y" /* yacc.c:1646  */
+#line 495 "grammar.y" /* yacc.c:1646  */
     { (yyval.i) = Q_NET; }
-#line 2454 "grammar.c" /* yacc.c:1646  */
+#line 2471 "grammar.c" /* yacc.c:1646  */
     break;
 
   case 66:
-#line 481 "grammar.y" /* yacc.c:1646  */
+#line 496 "grammar.y" /* yacc.c:1646  */
     { (yyval.i) = Q_PORT; }
-#line 2460 "grammar.c" /* yacc.c:1646  */
+#line 2477 "grammar.c" /* yacc.c:1646  */
     break;
 
   case 67:
-#line 482 "grammar.y" /* yacc.c:1646  */
+#line 497 "grammar.y" /* yacc.c:1646  */
     { (yyval.i) = Q_PORTRANGE; }
-#line 2466 "grammar.c" /* yacc.c:1646  */
+#line 2483 "grammar.c" /* yacc.c:1646  */
     break;
 
   case 68:
-#line 485 "grammar.y" /* yacc.c:1646  */
+#line 500 "grammar.y" /* yacc.c:1646  */
     { (yyval.i) = Q_GATEWAY; }
-#line 2472 "grammar.c" /* yacc.c:1646  */
+#line 2489 "grammar.c" /* yacc.c:1646  */
     break;
 
   case 69:
-#line 487 "grammar.y" /* yacc.c:1646  */
+#line 502 "grammar.y" /* yacc.c:1646  */
     { (yyval.i) = Q_LINK; }
-#line 2478 "grammar.c" /* yacc.c:1646  */
+#line 2495 "grammar.c" /* yacc.c:1646  */
     break;
 
   case 70:
-#line 488 "grammar.y" /* yacc.c:1646  */
+#line 503 "grammar.y" /* yacc.c:1646  */
     { (yyval.i) = Q_IP; }
-#line 2484 "grammar.c" /* yacc.c:1646  */
+#line 2501 "grammar.c" /* yacc.c:1646  */
     break;
 
   case 71:
-#line 489 "grammar.y" /* yacc.c:1646  */
+#line 504 "grammar.y" /* yacc.c:1646  */
     { (yyval.i) = Q_ARP; }
-#line 2490 "grammar.c" /* yacc.c:1646  */
+#line 2507 "grammar.c" /* yacc.c:1646  */
     break;
 
   case 72:
-#line 490 "grammar.y" /* yacc.c:1646  */
+#line 505 "grammar.y" /* yacc.c:1646  */
     { (yyval.i) = Q_RARP; }
-#line 2496 "grammar.c" /* yacc.c:1646  */
+#line 2513 "grammar.c" /* yacc.c:1646  */
     break;
 
   case 73:
-#line 491 "grammar.y" /* yacc.c:1646  */
+#line 506 "grammar.y" /* yacc.c:1646  */
     { (yyval.i) = Q_SCTP; }
-#line 2502 "grammar.c" /* yacc.c:1646  */
+#line 2519 "grammar.c" /* yacc.c:1646  */
     break;
 
   case 74:
-#line 492 "grammar.y" /* yacc.c:1646  */
+#line 507 "grammar.y" /* yacc.c:1646  */
     { (yyval.i) = Q_TCP; }
-#line 2508 "grammar.c" /* yacc.c:1646  */
+#line 2525 "grammar.c" /* yacc.c:1646  */
     break;
 
   case 75:
-#line 493 "grammar.y" /* yacc.c:1646  */
+#line 508 "grammar.y" /* yacc.c:1646  */
     { (yyval.i) = Q_UDP; }
-#line 2514 "grammar.c" /* yacc.c:1646  */
+#line 2531 "grammar.c" /* yacc.c:1646  */
     break;
 
   case 76:
-#line 494 "grammar.y" /* yacc.c:1646  */
+#line 509 "grammar.y" /* yacc.c:1646  */
     { (yyval.i) = Q_ICMP; }
-#line 2520 "grammar.c" /* yacc.c:1646  */
+#line 2537 "grammar.c" /* yacc.c:1646  */
     break;
 
   case 77:
-#line 495 "grammar.y" /* yacc.c:1646  */
+#line 510 "grammar.y" /* yacc.c:1646  */
     { (yyval.i) = Q_IGMP; }
-#line 2526 "grammar.c" /* yacc.c:1646  */
+#line 2543 "grammar.c" /* yacc.c:1646  */
     break;
 
   case 78:
-#line 496 "grammar.y" /* yacc.c:1646  */
+#line 511 "grammar.y" /* yacc.c:1646  */
     { (yyval.i) = Q_IGRP; }
-#line 2532 "grammar.c" /* yacc.c:1646  */
+#line 2549 "grammar.c" /* yacc.c:1646  */
     break;
 
   case 79:
-#line 497 "grammar.y" /* yacc.c:1646  */
+#line 512 "grammar.y" /* yacc.c:1646  */
     { (yyval.i) = Q_PIM; }
-#line 2538 "grammar.c" /* yacc.c:1646  */
+#line 2555 "grammar.c" /* yacc.c:1646  */
     break;
 
   case 80:
-#line 498 "grammar.y" /* yacc.c:1646  */
+#line 513 "grammar.y" /* yacc.c:1646  */
     { (yyval.i) = Q_VRRP; }
-#line 2544 "grammar.c" /* yacc.c:1646  */
+#line 2561 "grammar.c" /* yacc.c:1646  */
     break;
 
   case 81:
-#line 499 "grammar.y" /* yacc.c:1646  */
+#line 514 "grammar.y" /* yacc.c:1646  */
     { (yyval.i) = Q_CARP; }
-#line 2550 "grammar.c" /* yacc.c:1646  */
+#line 2567 "grammar.c" /* yacc.c:1646  */
     break;
 
   case 82:
-#line 500 "grammar.y" /* yacc.c:1646  */
+#line 515 "grammar.y" /* yacc.c:1646  */
     { (yyval.i) = Q_ATALK; }
-#line 2556 "grammar.c" /* yacc.c:1646  */
+#line 2573 "grammar.c" /* yacc.c:1646  */
     break;
 
   case 83:
-#line 501 "grammar.y" /* yacc.c:1646  */
+#line 516 "grammar.y" /* yacc.c:1646  */
     { (yyval.i) = Q_AARP; }
-#line 2562 "grammar.c" /* yacc.c:1646  */
+#line 2579 "grammar.c" /* yacc.c:1646  */
     break;
 
   case 84:
-#line 502 "grammar.y" /* yacc.c:1646  */
+#line 517 "grammar.y" /* yacc.c:1646  */
     { (yyval.i) = Q_DECNET; }
-#line 2568 "grammar.c" /* yacc.c:1646  */
+#line 2585 "grammar.c" /* yacc.c:1646  */
     break;
 
   case 85:
-#line 503 "grammar.y" /* yacc.c:1646  */
+#line 518 "grammar.y" /* yacc.c:1646  */
     { (yyval.i) = Q_LAT; }
-#line 2574 "grammar.c" /* yacc.c:1646  */
+#line 2591 "grammar.c" /* yacc.c:1646  */
     break;
 
   case 86:
-#line 504 "grammar.y" /* yacc.c:1646  */
+#line 519 "grammar.y" /* yacc.c:1646  */
     { (yyval.i) = Q_SCA; }
-#line 2580 "grammar.c" /* yacc.c:1646  */
+#line 2597 "grammar.c" /* yacc.c:1646  */
     break;
 
   case 87:
-#line 505 "grammar.y" /* yacc.c:1646  */
+#line 520 "grammar.y" /* yacc.c:1646  */
     { (yyval.i) = Q_MOPDL; }
-#line 2586 "grammar.c" /* yacc.c:1646  */
+#line 2603 "grammar.c" /* yacc.c:1646  */
     break;
 
   case 88:
-#line 506 "grammar.y" /* yacc.c:1646  */
+#line 521 "grammar.y" /* yacc.c:1646  */
     { (yyval.i) = Q_MOPRC; }
-#line 2592 "grammar.c" /* yacc.c:1646  */
+#line 2609 "grammar.c" /* yacc.c:1646  */
     break;
 
   case 89:
-#line 507 "grammar.y" /* yacc.c:1646  */
+#line 522 "grammar.y" /* yacc.c:1646  */
     { (yyval.i) = Q_IPV6; }
-#line 2598 "grammar.c" /* yacc.c:1646  */
+#line 2615 "grammar.c" /* yacc.c:1646  */
     break;
 
   case 90:
-#line 508 "grammar.y" /* yacc.c:1646  */
+#line 523 "grammar.y" /* yacc.c:1646  */
     { (yyval.i) = Q_ICMPV6; }
-#line 2604 "grammar.c" /* yacc.c:1646  */
+#line 2621 "grammar.c" /* yacc.c:1646  */
     break;
 
   case 91:
-#line 509 "grammar.y" /* yacc.c:1646  */
+#line 524 "grammar.y" /* yacc.c:1646  */
     { (yyval.i) = Q_AH; }
-#line 2610 "grammar.c" /* yacc.c:1646  */
+#line 2627 "grammar.c" /* yacc.c:1646  */
     break;
 
   case 92:
-#line 510 "grammar.y" /* yacc.c:1646  */
+#line 525 "grammar.y" /* yacc.c:1646  */
     { (yyval.i) = Q_ESP; }
-#line 2616 "grammar.c" /* yacc.c:1646  */
+#line 2633 "grammar.c" /* yacc.c:1646  */
     break;
 
   case 93:
-#line 511 "grammar.y" /* yacc.c:1646  */
+#line 526 "grammar.y" /* yacc.c:1646  */
     { (yyval.i) = Q_ISO; }
-#line 2622 "grammar.c" /* yacc.c:1646  */
+#line 2639 "grammar.c" /* yacc.c:1646  */
     break;
 
   case 94:
-#line 512 "grammar.y" /* yacc.c:1646  */
+#line 527 "grammar.y" /* yacc.c:1646  */
     { (yyval.i) = Q_ESIS; }
-#line 2628 "grammar.c" /* yacc.c:1646  */
+#line 2645 "grammar.c" /* yacc.c:1646  */
     break;
 
   case 95:
-#line 513 "grammar.y" /* yacc.c:1646  */
+#line 528 "grammar.y" /* yacc.c:1646  */
     { (yyval.i) = Q_ISIS; }
-#line 2634 "grammar.c" /* yacc.c:1646  */
+#line 2651 "grammar.c" /* yacc.c:1646  */
     break;
 
   case 96:
-#line 514 "grammar.y" /* yacc.c:1646  */
+#line 529 "grammar.y" /* yacc.c:1646  */
     { (yyval.i) = Q_ISIS_L1; }
-#line 2640 "grammar.c" /* yacc.c:1646  */
+#line 2657 "grammar.c" /* yacc.c:1646  */
     break;
 
   case 97:
-#line 515 "grammar.y" /* yacc.c:1646  */
+#line 530 "grammar.y" /* yacc.c:1646  */
     { (yyval.i) = Q_ISIS_L2; }
-#line 2646 "grammar.c" /* yacc.c:1646  */
+#line 2663 "grammar.c" /* yacc.c:1646  */
     break;
 
   case 98:
-#line 516 "grammar.y" /* yacc.c:1646  */
+#line 531 "grammar.y" /* yacc.c:1646  */
     { (yyval.i) = Q_ISIS_IIH; }
-#line 2652 "grammar.c" /* yacc.c:1646  */
+#line 2669 "grammar.c" /* yacc.c:1646  */
     break;
 
   case 99:
-#line 517 "grammar.y" /* yacc.c:1646  */
+#line 532 "grammar.y" /* yacc.c:1646  */
     { (yyval.i) = Q_ISIS_LSP; }
-#line 2658 "grammar.c" /* yacc.c:1646  */
+#line 2675 "grammar.c" /* yacc.c:1646  */
     break;
 
   case 100:
-#line 518 "grammar.y" /* yacc.c:1646  */
+#line 533 "grammar.y" /* yacc.c:1646  */
     { (yyval.i) = Q_ISIS_SNP; }
-#line 2664 "grammar.c" /* yacc.c:1646  */
+#line 2681 "grammar.c" /* yacc.c:1646  */
     break;
 
   case 101:
-#line 519 "grammar.y" /* yacc.c:1646  */
+#line 534 "grammar.y" /* yacc.c:1646  */
     { (yyval.i) = Q_ISIS_PSNP; }
-#line 2670 "grammar.c" /* yacc.c:1646  */
+#line 2687 "grammar.c" /* yacc.c:1646  */
     break;
 
   case 102:
-#line 520 "grammar.y" /* yacc.c:1646  */
+#line 535 "grammar.y" /* yacc.c:1646  */
     { (yyval.i) = Q_ISIS_CSNP; }
-#line 2676 "grammar.c" /* yacc.c:1646  */
+#line 2693 "grammar.c" /* yacc.c:1646  */
     break;
 
   case 103:
-#line 521 "grammar.y" /* yacc.c:1646  */
+#line 536 "grammar.y" /* yacc.c:1646  */
     { (yyval.i) = Q_CLNP; }
-#line 2682 "grammar.c" /* yacc.c:1646  */
+#line 2699 "grammar.c" /* yacc.c:1646  */
     break;
 
   case 104:
-#line 522 "grammar.y" /* yacc.c:1646  */
+#line 537 "grammar.y" /* yacc.c:1646  */
     { (yyval.i) = Q_STP; }
-#line 2688 "grammar.c" /* yacc.c:1646  */
+#line 2705 "grammar.c" /* yacc.c:1646  */
     break;
 
   case 105:
-#line 523 "grammar.y" /* yacc.c:1646  */
+#line 538 "grammar.y" /* yacc.c:1646  */
     { (yyval.i) = Q_IPX; }
-#line 2694 "grammar.c" /* yacc.c:1646  */
+#line 2711 "grammar.c" /* yacc.c:1646  */
     break;
 
   case 106:
-#line 524 "grammar.y" /* yacc.c:1646  */
+#line 539 "grammar.y" /* yacc.c:1646  */
     { (yyval.i) = Q_NETBEUI; }
-#line 2700 "grammar.c" /* yacc.c:1646  */
+#line 2717 "grammar.c" /* yacc.c:1646  */
     break;
 
   case 107:
-#line 525 "grammar.y" /* yacc.c:1646  */
+#line 540 "grammar.y" /* yacc.c:1646  */
     { (yyval.i) = Q_RADIO; }
-#line 2706 "grammar.c" /* yacc.c:1646  */
+#line 2723 "grammar.c" /* yacc.c:1646  */
     break;
 
   case 108:
-#line 527 "grammar.y" /* yacc.c:1646  */
+#line 542 "grammar.y" /* yacc.c:1646  */
     { (yyval.rblk) = gen_broadcast(cstate, (yyvsp[-1].i)); }
-#line 2712 "grammar.c" /* yacc.c:1646  */
+#line 2729 "grammar.c" /* yacc.c:1646  */
     break;
 
   case 109:
-#line 528 "grammar.y" /* yacc.c:1646  */
+#line 543 "grammar.y" /* yacc.c:1646  */
     { (yyval.rblk) = gen_multicast(cstate, (yyvsp[-1].i)); }
-#line 2718 "grammar.c" /* yacc.c:1646  */
+#line 2735 "grammar.c" /* yacc.c:1646  */
     break;
 
   case 110:
-#line 529 "grammar.y" /* yacc.c:1646  */
+#line 544 "grammar.y" /* yacc.c:1646  */
     { (yyval.rblk) = gen_less(cstate, (yyvsp[0].i)); }
-#line 2724 "grammar.c" /* yacc.c:1646  */
+#line 2741 "grammar.c" /* yacc.c:1646  */
     break;
 
   case 111:
-#line 530 "grammar.y" /* yacc.c:1646  */
+#line 545 "grammar.y" /* yacc.c:1646  */
     { (yyval.rblk) = gen_greater(cstate, (yyvsp[0].i)); }
-#line 2730 "grammar.c" /* yacc.c:1646  */
+#line 2747 "grammar.c" /* yacc.c:1646  */
     break;
 
   case 112:
-#line 531 "grammar.y" /* yacc.c:1646  */
+#line 546 "grammar.y" /* yacc.c:1646  */
     { (yyval.rblk) = gen_byteop(cstate, (yyvsp[-1].i), (yyvsp[-2].i), (yyvsp[0].i)); }
-#line 2736 "grammar.c" /* yacc.c:1646  */
+#line 2753 "grammar.c" /* yacc.c:1646  */
     break;
 
   case 113:
-#line 532 "grammar.y" /* yacc.c:1646  */
+#line 547 "grammar.y" /* yacc.c:1646  */
     { (yyval.rblk) = gen_inbound(cstate, 0); }
-#line 2742 "grammar.c" /* yacc.c:1646  */
+#line 2759 "grammar.c" /* yacc.c:1646  */
     break;
 
   case 114:
-#line 533 "grammar.y" /* yacc.c:1646  */
+#line 548 "grammar.y" /* yacc.c:1646  */
     { (yyval.rblk) = gen_inbound(cstate, 1); }
-#line 2748 "grammar.c" /* yacc.c:1646  */
+#line 2765 "grammar.c" /* yacc.c:1646  */
     break;
 
   case 115:
-#line 534 "grammar.y" /* yacc.c:1646  */
+#line 549 "grammar.y" /* yacc.c:1646  */
     { (yyval.rblk) = gen_vlan(cstate, (yyvsp[0].i)); }
-#line 2754 "grammar.c" /* yacc.c:1646  */
+#line 2771 "grammar.c" /* yacc.c:1646  */
     break;
 
   case 116:
-#line 535 "grammar.y" /* yacc.c:1646  */
+#line 550 "grammar.y" /* yacc.c:1646  */
     { (yyval.rblk) = gen_vlan(cstate, -1); }
-#line 2760 "grammar.c" /* yacc.c:1646  */
+#line 2777 "grammar.c" /* yacc.c:1646  */
     break;
 
   case 117:
-#line 536 "grammar.y" /* yacc.c:1646  */
+#line 551 "grammar.y" /* yacc.c:1646  */
     { (yyval.rblk) = gen_mpls(cstate, (yyvsp[0].i)); }
-#line 2766 "grammar.c" /* yacc.c:1646  */
+#line 2783 "grammar.c" /* yacc.c:1646  */
     break;
 
   case 118:
-#line 537 "grammar.y" /* yacc.c:1646  */
+#line 552 "grammar.y" /* yacc.c:1646  */
     { (yyval.rblk) = gen_mpls(cstate, -1); }
-#line 2772 "grammar.c" /* yacc.c:1646  */
+#line 2789 "grammar.c" /* yacc.c:1646  */
     break;
 
   case 119:
-#line 538 "grammar.y" /* yacc.c:1646  */
+#line 553 "grammar.y" /* yacc.c:1646  */
     { (yyval.rblk) = gen_pppoed(cstate); }
-#line 2778 "grammar.c" /* yacc.c:1646  */
+#line 2795 "grammar.c" /* yacc.c:1646  */
     break;
 
   case 120:
-#line 539 "grammar.y" /* yacc.c:1646  */
+#line 554 "grammar.y" /* yacc.c:1646  */
     { (yyval.rblk) = gen_pppoes(cstate, (yyvsp[0].i)); }
-#line 2784 "grammar.c" /* yacc.c:1646  */
+#line 2801 "grammar.c" /* yacc.c:1646  */
     break;
 
   case 121:
-#line 540 "grammar.y" /* yacc.c:1646  */
+#line 555 "grammar.y" /* yacc.c:1646  */
     { (yyval.rblk) = gen_pppoes(cstate, -1); }
-#line 2790 "grammar.c" /* yacc.c:1646  */
+#line 2807 "grammar.c" /* yacc.c:1646  */
     break;
 
   case 122:
-#line 541 "grammar.y" /* yacc.c:1646  */
+#line 556 "grammar.y" /* yacc.c:1646  */
     { (yyval.rblk) = gen_geneve(cstate, (yyvsp[0].i)); }
-#line 2796 "grammar.c" /* yacc.c:1646  */
+#line 2813 "grammar.c" /* yacc.c:1646  */
     break;
 
   case 123:
-#line 542 "grammar.y" /* yacc.c:1646  */
+#line 557 "grammar.y" /* yacc.c:1646  */
     { (yyval.rblk) = gen_geneve(cstate, -1); }
-#line 2802 "grammar.c" /* yacc.c:1646  */
+#line 2819 "grammar.c" /* yacc.c:1646  */
     break;
 
   case 124:
-#line 543 "grammar.y" /* yacc.c:1646  */
+#line 558 "grammar.y" /* yacc.c:1646  */
     { (yyval.rblk) = (yyvsp[0].rblk); }
-#line 2808 "grammar.c" /* yacc.c:1646  */
+#line 2825 "grammar.c" /* yacc.c:1646  */
     break;
 
   case 125:
-#line 544 "grammar.y" /* yacc.c:1646  */
+#line 559 "grammar.y" /* yacc.c:1646  */
     { (yyval.rblk) = (yyvsp[0].rblk); }
-#line 2814 "grammar.c" /* yacc.c:1646  */
+#line 2831 "grammar.c" /* yacc.c:1646  */
     break;
 
   case 126:
-#line 545 "grammar.y" /* yacc.c:1646  */
+#line 560 "grammar.y" /* yacc.c:1646  */
     { (yyval.rblk) = (yyvsp[0].rblk); }
-#line 2820 "grammar.c" /* yacc.c:1646  */
+#line 2837 "grammar.c" /* yacc.c:1646  */
     break;
 
   case 127:
-#line 548 "grammar.y" /* yacc.c:1646  */
+#line 563 "grammar.y" /* yacc.c:1646  */
     { (yyval.rblk) = gen_pf_ifname(cstate, (yyvsp[0].s)); }
-#line 2826 "grammar.c" /* yacc.c:1646  */
+#line 2843 "grammar.c" /* yacc.c:1646  */
     break;
 
   case 128:
-#line 549 "grammar.y" /* yacc.c:1646  */
+#line 564 "grammar.y" /* yacc.c:1646  */
     { (yyval.rblk) = gen_pf_ruleset(cstate, (yyvsp[0].s)); }
-#line 2832 "grammar.c" /* yacc.c:1646  */
+#line 2849 "grammar.c" /* yacc.c:1646  */
     break;
 
   case 129:
-#line 550 "grammar.y" /* yacc.c:1646  */
+#line 565 "grammar.y" /* yacc.c:1646  */
     { (yyval.rblk) = gen_pf_rnr(cstate, (yyvsp[0].i)); }
-#line 2838 "grammar.c" /* yacc.c:1646  */
+#line 2855 "grammar.c" /* yacc.c:1646  */
     break;
 
   case 130:
-#line 551 "grammar.y" /* yacc.c:1646  */
+#line 566 "grammar.y" /* yacc.c:1646  */
     { (yyval.rblk) = gen_pf_srnr(cstate, (yyvsp[0].i)); }
-#line 2844 "grammar.c" /* yacc.c:1646  */
+#line 2861 "grammar.c" /* yacc.c:1646  */
     break;
 
   case 131:
-#line 552 "grammar.y" /* yacc.c:1646  */
+#line 567 "grammar.y" /* yacc.c:1646  */
     { (yyval.rblk) = gen_pf_reason(cstate, (yyvsp[0].i)); }
-#line 2850 "grammar.c" /* yacc.c:1646  */
+#line 2867 "grammar.c" /* yacc.c:1646  */
     break;
 
   case 132:
-#line 553 "grammar.y" /* yacc.c:1646  */
+#line 568 "grammar.y" /* yacc.c:1646  */
     { (yyval.rblk) = gen_pf_action(cstate, (yyvsp[0].i)); }
-#line 2856 "grammar.c" /* yacc.c:1646  */
-    break;
-
-  case 133:
-#line 557 "grammar.y" /* yacc.c:1646  */
-    { (yyval.rblk) = gen_p80211_type(cstate, (yyvsp[-2].i) | (yyvsp[0].i),
-					IEEE80211_FC0_TYPE_MASK |
-					IEEE80211_FC0_SUBTYPE_MASK);
-				}
-#line 2865 "grammar.c" /* yacc.c:1646  */
-    break;
-
-  case 134:
-#line 561 "grammar.y" /* yacc.c:1646  */
-    { (yyval.rblk) = gen_p80211_type(cstate, (yyvsp[0].i),
-					IEEE80211_FC0_TYPE_MASK);
-				}
 #line 2873 "grammar.c" /* yacc.c:1646  */
     break;
 
-  case 135:
-#line 564 "grammar.y" /* yacc.c:1646  */
-    { (yyval.rblk) = gen_p80211_type(cstate, (yyvsp[0].i),
+  case 133:
+#line 572 "grammar.y" /* yacc.c:1646  */
+    { (yyval.rblk) = gen_p80211_type(cstate, (yyvsp[-2].i) | (yyvsp[0].i),
 					IEEE80211_FC0_TYPE_MASK |
 					IEEE80211_FC0_SUBTYPE_MASK);
 				}
 #line 2882 "grammar.c" /* yacc.c:1646  */
     break;
 
+  case 134:
+#line 576 "grammar.y" /* yacc.c:1646  */
+    { (yyval.rblk) = gen_p80211_type(cstate, (yyvsp[0].i),
+					IEEE80211_FC0_TYPE_MASK);
+				}
+#line 2890 "grammar.c" /* yacc.c:1646  */
+    break;
+
+  case 135:
+#line 579 "grammar.y" /* yacc.c:1646  */
+    { (yyval.rblk) = gen_p80211_type(cstate, (yyvsp[0].i),
+					IEEE80211_FC0_TYPE_MASK |
+					IEEE80211_FC0_SUBTYPE_MASK);
+				}
+#line 2899 "grammar.c" /* yacc.c:1646  */
+    break;
+
   case 136:
-#line 568 "grammar.y" /* yacc.c:1646  */
+#line 583 "grammar.y" /* yacc.c:1646  */
     { (yyval.rblk) = gen_p80211_fcdir(cstate, (yyvsp[0].i)); }
-#line 2888 "grammar.c" /* yacc.c:1646  */
+#line 2905 "grammar.c" /* yacc.c:1646  */
     break;
 
   case 138:
-#line 572 "grammar.y" /* yacc.c:1646  */
+#line 587 "grammar.y" /* yacc.c:1646  */
     { (yyval.i) = str2tok((yyvsp[0].s), ieee80211_types);
 				  if ((yyval.i) == -1)
 				  	bpf_error(cstate, "unknown 802.11 type name");
 				}
-#line 2897 "grammar.c" /* yacc.c:1646  */
+#line 2914 "grammar.c" /* yacc.c:1646  */
     break;
 
   case 140:
-#line 579 "grammar.y" /* yacc.c:1646  */
+#line 594 "grammar.y" /* yacc.c:1646  */
     { const struct tok *types = NULL;
 				  int i;
 				  for (i = 0;; i++) {
@@ -2916,11 +2933,11 @@
 				  if ((yyval.i) == -1)
 					bpf_error(cstate, "unknown 802.11 subtype name");
 				}
-#line 2920 "grammar.c" /* yacc.c:1646  */
+#line 2937 "grammar.c" /* yacc.c:1646  */
     break;
 
   case 141:
-#line 599 "grammar.y" /* yacc.c:1646  */
+#line 614 "grammar.y" /* yacc.c:1646  */
     { int i;
 				  for (i = 0;; i++) {
 				  	if (ieee80211_type_subtypes[i].tok == NULL) {
@@ -2935,17 +2952,17 @@
 					}
 				  }
 				}
-#line 2939 "grammar.c" /* yacc.c:1646  */
+#line 2956 "grammar.c" /* yacc.c:1646  */
     break;
 
   case 142:
-#line 615 "grammar.y" /* yacc.c:1646  */
+#line 630 "grammar.y" /* yacc.c:1646  */
     { (yyval.rblk) = gen_llc(cstate); }
-#line 2945 "grammar.c" /* yacc.c:1646  */
+#line 2962 "grammar.c" /* yacc.c:1646  */
     break;
 
   case 143:
-#line 616 "grammar.y" /* yacc.c:1646  */
+#line 631 "grammar.y" /* yacc.c:1646  */
     { if (pcap_strcasecmp((yyvsp[0].s), "i") == 0)
 					(yyval.rblk) = gen_llc_i(cstate);
 				  else if (pcap_strcasecmp((yyvsp[0].s), "s") == 0)
@@ -2966,17 +2983,17 @@
 					}
 				  }
 				}
-#line 2970 "grammar.c" /* yacc.c:1646  */
+#line 2987 "grammar.c" /* yacc.c:1646  */
     break;
 
   case 144:
-#line 637 "grammar.y" /* yacc.c:1646  */
+#line 652 "grammar.y" /* yacc.c:1646  */
     { (yyval.rblk) = gen_llc_s_subtype(cstate, LLC_RNR); }
-#line 2976 "grammar.c" /* yacc.c:1646  */
+#line 2993 "grammar.c" /* yacc.c:1646  */
     break;
 
   case 146:
-#line 641 "grammar.y" /* yacc.c:1646  */
+#line 656 "grammar.y" /* yacc.c:1646  */
     { if (pcap_strcasecmp((yyvsp[0].s), "nods") == 0)
 					(yyval.i) = IEEE80211_FC1_DIR_NODS;
 				  else if (pcap_strcasecmp((yyvsp[0].s), "tods") == 0)
@@ -2988,412 +3005,412 @@
 				  else
 					bpf_error(cstate, "unknown 802.11 direction");
 				}
-#line 2992 "grammar.c" /* yacc.c:1646  */
+#line 3009 "grammar.c" /* yacc.c:1646  */
     break;
 
   case 147:
-#line 654 "grammar.y" /* yacc.c:1646  */
+#line 669 "grammar.y" /* yacc.c:1646  */
     { (yyval.i) = (yyvsp[0].i); }
-#line 2998 "grammar.c" /* yacc.c:1646  */
+#line 3015 "grammar.c" /* yacc.c:1646  */
     break;
 
   case 148:
-#line 655 "grammar.y" /* yacc.c:1646  */
+#line 670 "grammar.y" /* yacc.c:1646  */
     { (yyval.i) = pfreason_to_num(cstate, (yyvsp[0].s)); }
-#line 3004 "grammar.c" /* yacc.c:1646  */
+#line 3021 "grammar.c" /* yacc.c:1646  */
     break;
 
   case 149:
-#line 658 "grammar.y" /* yacc.c:1646  */
+#line 673 "grammar.y" /* yacc.c:1646  */
     { (yyval.i) = pfaction_to_num(cstate, (yyvsp[0].s)); }
-#line 3010 "grammar.c" /* yacc.c:1646  */
+#line 3027 "grammar.c" /* yacc.c:1646  */
     break;
 
   case 150:
-#line 661 "grammar.y" /* yacc.c:1646  */
+#line 676 "grammar.y" /* yacc.c:1646  */
     { (yyval.i) = BPF_JGT; }
-#line 3016 "grammar.c" /* yacc.c:1646  */
+#line 3033 "grammar.c" /* yacc.c:1646  */
     break;
 
   case 151:
-#line 662 "grammar.y" /* yacc.c:1646  */
+#line 677 "grammar.y" /* yacc.c:1646  */
     { (yyval.i) = BPF_JGE; }
-#line 3022 "grammar.c" /* yacc.c:1646  */
+#line 3039 "grammar.c" /* yacc.c:1646  */
     break;
 
   case 152:
-#line 663 "grammar.y" /* yacc.c:1646  */
+#line 678 "grammar.y" /* yacc.c:1646  */
     { (yyval.i) = BPF_JEQ; }
-#line 3028 "grammar.c" /* yacc.c:1646  */
+#line 3045 "grammar.c" /* yacc.c:1646  */
     break;
 
   case 153:
-#line 665 "grammar.y" /* yacc.c:1646  */
+#line 680 "grammar.y" /* yacc.c:1646  */
     { (yyval.i) = BPF_JGT; }
-#line 3034 "grammar.c" /* yacc.c:1646  */
+#line 3051 "grammar.c" /* yacc.c:1646  */
     break;
 
   case 154:
-#line 666 "grammar.y" /* yacc.c:1646  */
+#line 681 "grammar.y" /* yacc.c:1646  */
     { (yyval.i) = BPF_JGE; }
-#line 3040 "grammar.c" /* yacc.c:1646  */
+#line 3057 "grammar.c" /* yacc.c:1646  */
     break;
 
   case 155:
-#line 667 "grammar.y" /* yacc.c:1646  */
+#line 682 "grammar.y" /* yacc.c:1646  */
     { (yyval.i) = BPF_JEQ; }
-#line 3046 "grammar.c" /* yacc.c:1646  */
+#line 3063 "grammar.c" /* yacc.c:1646  */
     break;
 
   case 156:
-#line 669 "grammar.y" /* yacc.c:1646  */
+#line 684 "grammar.y" /* yacc.c:1646  */
     { (yyval.a) = gen_loadi(cstate, (yyvsp[0].i)); }
-#line 3052 "grammar.c" /* yacc.c:1646  */
+#line 3069 "grammar.c" /* yacc.c:1646  */
     break;
 
   case 158:
-#line 672 "grammar.y" /* yacc.c:1646  */
+#line 687 "grammar.y" /* yacc.c:1646  */
     { (yyval.a) = gen_load(cstate, (yyvsp[-3].i), (yyvsp[-1].a), 1); }
-#line 3058 "grammar.c" /* yacc.c:1646  */
+#line 3075 "grammar.c" /* yacc.c:1646  */
     break;
 
   case 159:
-#line 673 "grammar.y" /* yacc.c:1646  */
+#line 688 "grammar.y" /* yacc.c:1646  */
     { (yyval.a) = gen_load(cstate, (yyvsp[-5].i), (yyvsp[-3].a), (yyvsp[-1].i)); }
-#line 3064 "grammar.c" /* yacc.c:1646  */
+#line 3081 "grammar.c" /* yacc.c:1646  */
     break;
 
   case 160:
-#line 674 "grammar.y" /* yacc.c:1646  */
+#line 689 "grammar.y" /* yacc.c:1646  */
     { (yyval.a) = gen_arth(cstate, BPF_ADD, (yyvsp[-2].a), (yyvsp[0].a)); }
-#line 3070 "grammar.c" /* yacc.c:1646  */
+#line 3087 "grammar.c" /* yacc.c:1646  */
     break;
 
   case 161:
-#line 675 "grammar.y" /* yacc.c:1646  */
+#line 690 "grammar.y" /* yacc.c:1646  */
     { (yyval.a) = gen_arth(cstate, BPF_SUB, (yyvsp[-2].a), (yyvsp[0].a)); }
-#line 3076 "grammar.c" /* yacc.c:1646  */
+#line 3093 "grammar.c" /* yacc.c:1646  */
     break;
 
   case 162:
-#line 676 "grammar.y" /* yacc.c:1646  */
+#line 691 "grammar.y" /* yacc.c:1646  */
     { (yyval.a) = gen_arth(cstate, BPF_MUL, (yyvsp[-2].a), (yyvsp[0].a)); }
-#line 3082 "grammar.c" /* yacc.c:1646  */
+#line 3099 "grammar.c" /* yacc.c:1646  */
     break;
 
   case 163:
-#line 677 "grammar.y" /* yacc.c:1646  */
+#line 692 "grammar.y" /* yacc.c:1646  */
     { (yyval.a) = gen_arth(cstate, BPF_DIV, (yyvsp[-2].a), (yyvsp[0].a)); }
-#line 3088 "grammar.c" /* yacc.c:1646  */
+#line 3105 "grammar.c" /* yacc.c:1646  */
     break;
 
   case 164:
-#line 678 "grammar.y" /* yacc.c:1646  */
+#line 693 "grammar.y" /* yacc.c:1646  */
     { (yyval.a) = gen_arth(cstate, BPF_MOD, (yyvsp[-2].a), (yyvsp[0].a)); }
-#line 3094 "grammar.c" /* yacc.c:1646  */
+#line 3111 "grammar.c" /* yacc.c:1646  */
     break;
 
   case 165:
-#line 679 "grammar.y" /* yacc.c:1646  */
+#line 694 "grammar.y" /* yacc.c:1646  */
     { (yyval.a) = gen_arth(cstate, BPF_AND, (yyvsp[-2].a), (yyvsp[0].a)); }
-#line 3100 "grammar.c" /* yacc.c:1646  */
+#line 3117 "grammar.c" /* yacc.c:1646  */
     break;
 
   case 166:
-#line 680 "grammar.y" /* yacc.c:1646  */
+#line 695 "grammar.y" /* yacc.c:1646  */
     { (yyval.a) = gen_arth(cstate, BPF_OR, (yyvsp[-2].a), (yyvsp[0].a)); }
-#line 3106 "grammar.c" /* yacc.c:1646  */
+#line 3123 "grammar.c" /* yacc.c:1646  */
     break;
 
   case 167:
-#line 681 "grammar.y" /* yacc.c:1646  */
+#line 696 "grammar.y" /* yacc.c:1646  */
     { (yyval.a) = gen_arth(cstate, BPF_XOR, (yyvsp[-2].a), (yyvsp[0].a)); }
-#line 3112 "grammar.c" /* yacc.c:1646  */
+#line 3129 "grammar.c" /* yacc.c:1646  */
     break;
 
   case 168:
-#line 682 "grammar.y" /* yacc.c:1646  */
+#line 697 "grammar.y" /* yacc.c:1646  */
     { (yyval.a) = gen_arth(cstate, BPF_LSH, (yyvsp[-2].a), (yyvsp[0].a)); }
-#line 3118 "grammar.c" /* yacc.c:1646  */
+#line 3135 "grammar.c" /* yacc.c:1646  */
     break;
 
   case 169:
-#line 683 "grammar.y" /* yacc.c:1646  */
+#line 698 "grammar.y" /* yacc.c:1646  */
     { (yyval.a) = gen_arth(cstate, BPF_RSH, (yyvsp[-2].a), (yyvsp[0].a)); }
-#line 3124 "grammar.c" /* yacc.c:1646  */
+#line 3141 "grammar.c" /* yacc.c:1646  */
     break;
 
   case 170:
-#line 684 "grammar.y" /* yacc.c:1646  */
+#line 699 "grammar.y" /* yacc.c:1646  */
     { (yyval.a) = gen_neg(cstate, (yyvsp[0].a)); }
-#line 3130 "grammar.c" /* yacc.c:1646  */
+#line 3147 "grammar.c" /* yacc.c:1646  */
     break;
 
   case 171:
-#line 685 "grammar.y" /* yacc.c:1646  */
+#line 700 "grammar.y" /* yacc.c:1646  */
     { (yyval.a) = (yyvsp[-1].a); }
-#line 3136 "grammar.c" /* yacc.c:1646  */
+#line 3153 "grammar.c" /* yacc.c:1646  */
     break;
 
   case 172:
-#line 686 "grammar.y" /* yacc.c:1646  */
+#line 701 "grammar.y" /* yacc.c:1646  */
     { (yyval.a) = gen_loadlen(cstate); }
-#line 3142 "grammar.c" /* yacc.c:1646  */
+#line 3159 "grammar.c" /* yacc.c:1646  */
     break;
 
   case 173:
-#line 688 "grammar.y" /* yacc.c:1646  */
+#line 703 "grammar.y" /* yacc.c:1646  */
     { (yyval.i) = '&'; }
-#line 3148 "grammar.c" /* yacc.c:1646  */
+#line 3165 "grammar.c" /* yacc.c:1646  */
     break;
 
   case 174:
-#line 689 "grammar.y" /* yacc.c:1646  */
+#line 704 "grammar.y" /* yacc.c:1646  */
     { (yyval.i) = '|'; }
-#line 3154 "grammar.c" /* yacc.c:1646  */
+#line 3171 "grammar.c" /* yacc.c:1646  */
     break;
 
   case 175:
-#line 690 "grammar.y" /* yacc.c:1646  */
+#line 705 "grammar.y" /* yacc.c:1646  */
     { (yyval.i) = '<'; }
-#line 3160 "grammar.c" /* yacc.c:1646  */
+#line 3177 "grammar.c" /* yacc.c:1646  */
     break;
 
   case 176:
-#line 691 "grammar.y" /* yacc.c:1646  */
+#line 706 "grammar.y" /* yacc.c:1646  */
     { (yyval.i) = '>'; }
-#line 3166 "grammar.c" /* yacc.c:1646  */
+#line 3183 "grammar.c" /* yacc.c:1646  */
     break;
 
   case 177:
-#line 692 "grammar.y" /* yacc.c:1646  */
+#line 707 "grammar.y" /* yacc.c:1646  */
     { (yyval.i) = '='; }
-#line 3172 "grammar.c" /* yacc.c:1646  */
+#line 3189 "grammar.c" /* yacc.c:1646  */
     break;
 
   case 179:
-#line 695 "grammar.y" /* yacc.c:1646  */
+#line 710 "grammar.y" /* yacc.c:1646  */
     { (yyval.i) = (yyvsp[-1].i); }
-#line 3178 "grammar.c" /* yacc.c:1646  */
+#line 3195 "grammar.c" /* yacc.c:1646  */
     break;
 
   case 180:
-#line 697 "grammar.y" /* yacc.c:1646  */
+#line 712 "grammar.y" /* yacc.c:1646  */
     { (yyval.i) = A_LANE; }
-#line 3184 "grammar.c" /* yacc.c:1646  */
+#line 3201 "grammar.c" /* yacc.c:1646  */
     break;
 
   case 181:
-#line 698 "grammar.y" /* yacc.c:1646  */
+#line 713 "grammar.y" /* yacc.c:1646  */
     { (yyval.i) = A_METAC;	}
-#line 3190 "grammar.c" /* yacc.c:1646  */
+#line 3207 "grammar.c" /* yacc.c:1646  */
     break;
 
   case 182:
-#line 699 "grammar.y" /* yacc.c:1646  */
+#line 714 "grammar.y" /* yacc.c:1646  */
     { (yyval.i) = A_BCC; }
-#line 3196 "grammar.c" /* yacc.c:1646  */
+#line 3213 "grammar.c" /* yacc.c:1646  */
     break;
 
   case 183:
-#line 700 "grammar.y" /* yacc.c:1646  */
+#line 715 "grammar.y" /* yacc.c:1646  */
     { (yyval.i) = A_OAMF4EC; }
-#line 3202 "grammar.c" /* yacc.c:1646  */
+#line 3219 "grammar.c" /* yacc.c:1646  */
     break;
 
   case 184:
-#line 701 "grammar.y" /* yacc.c:1646  */
+#line 716 "grammar.y" /* yacc.c:1646  */
     { (yyval.i) = A_OAMF4SC; }
-#line 3208 "grammar.c" /* yacc.c:1646  */
+#line 3225 "grammar.c" /* yacc.c:1646  */
     break;
 
   case 185:
-#line 702 "grammar.y" /* yacc.c:1646  */
+#line 717 "grammar.y" /* yacc.c:1646  */
     { (yyval.i) = A_SC; }
-#line 3214 "grammar.c" /* yacc.c:1646  */
+#line 3231 "grammar.c" /* yacc.c:1646  */
     break;
 
   case 186:
-#line 703 "grammar.y" /* yacc.c:1646  */
+#line 718 "grammar.y" /* yacc.c:1646  */
     { (yyval.i) = A_ILMIC; }
-#line 3220 "grammar.c" /* yacc.c:1646  */
+#line 3237 "grammar.c" /* yacc.c:1646  */
     break;
 
   case 187:
-#line 705 "grammar.y" /* yacc.c:1646  */
+#line 720 "grammar.y" /* yacc.c:1646  */
     { (yyval.i) = A_OAM; }
-#line 3226 "grammar.c" /* yacc.c:1646  */
+#line 3243 "grammar.c" /* yacc.c:1646  */
     break;
 
   case 188:
-#line 706 "grammar.y" /* yacc.c:1646  */
+#line 721 "grammar.y" /* yacc.c:1646  */
     { (yyval.i) = A_OAMF4; }
-#line 3232 "grammar.c" /* yacc.c:1646  */
+#line 3249 "grammar.c" /* yacc.c:1646  */
     break;
 
   case 189:
-#line 707 "grammar.y" /* yacc.c:1646  */
+#line 722 "grammar.y" /* yacc.c:1646  */
     { (yyval.i) = A_CONNECTMSG; }
-#line 3238 "grammar.c" /* yacc.c:1646  */
+#line 3255 "grammar.c" /* yacc.c:1646  */
     break;
 
   case 190:
-#line 708 "grammar.y" /* yacc.c:1646  */
+#line 723 "grammar.y" /* yacc.c:1646  */
     { (yyval.i) = A_METACONNECT; }
-#line 3244 "grammar.c" /* yacc.c:1646  */
+#line 3261 "grammar.c" /* yacc.c:1646  */
     break;
 
   case 191:
-#line 711 "grammar.y" /* yacc.c:1646  */
+#line 726 "grammar.y" /* yacc.c:1646  */
     { (yyval.blk).atmfieldtype = A_VPI; }
-#line 3250 "grammar.c" /* yacc.c:1646  */
+#line 3267 "grammar.c" /* yacc.c:1646  */
     break;
 
   case 192:
-#line 712 "grammar.y" /* yacc.c:1646  */
+#line 727 "grammar.y" /* yacc.c:1646  */
     { (yyval.blk).atmfieldtype = A_VCI; }
-#line 3256 "grammar.c" /* yacc.c:1646  */
+#line 3273 "grammar.c" /* yacc.c:1646  */
     break;
 
   case 194:
-#line 715 "grammar.y" /* yacc.c:1646  */
+#line 730 "grammar.y" /* yacc.c:1646  */
     { (yyval.blk).b = gen_atmfield_code(cstate, (yyvsp[-2].blk).atmfieldtype, (bpf_int32)(yyvsp[0].i), (bpf_u_int32)(yyvsp[-1].i), 0); }
-#line 3262 "grammar.c" /* yacc.c:1646  */
+#line 3279 "grammar.c" /* yacc.c:1646  */
     break;
 
   case 195:
-#line 716 "grammar.y" /* yacc.c:1646  */
+#line 731 "grammar.y" /* yacc.c:1646  */
     { (yyval.blk).b = gen_atmfield_code(cstate, (yyvsp[-2].blk).atmfieldtype, (bpf_int32)(yyvsp[0].i), (bpf_u_int32)(yyvsp[-1].i), 1); }
-#line 3268 "grammar.c" /* yacc.c:1646  */
+#line 3285 "grammar.c" /* yacc.c:1646  */
     break;
 
   case 196:
-#line 717 "grammar.y" /* yacc.c:1646  */
+#line 732 "grammar.y" /* yacc.c:1646  */
     { (yyval.blk).b = (yyvsp[-1].blk).b; (yyval.blk).q = qerr; }
-#line 3274 "grammar.c" /* yacc.c:1646  */
+#line 3291 "grammar.c" /* yacc.c:1646  */
     break;
 
   case 197:
-#line 719 "grammar.y" /* yacc.c:1646  */
+#line 734 "grammar.y" /* yacc.c:1646  */
     {
 	(yyval.blk).atmfieldtype = (yyvsp[-1].blk).atmfieldtype;
 	if ((yyval.blk).atmfieldtype == A_VPI ||
 	    (yyval.blk).atmfieldtype == A_VCI)
 		(yyval.blk).b = gen_atmfield_code(cstate, (yyval.blk).atmfieldtype, (bpf_int32) (yyvsp[0].i), BPF_JEQ, 0);
 	}
-#line 3285 "grammar.c" /* yacc.c:1646  */
+#line 3302 "grammar.c" /* yacc.c:1646  */
     break;
 
   case 199:
-#line 727 "grammar.y" /* yacc.c:1646  */
+#line 742 "grammar.y" /* yacc.c:1646  */
     { gen_or((yyvsp[-2].blk).b, (yyvsp[0].blk).b); (yyval.blk) = (yyvsp[0].blk); }
-#line 3291 "grammar.c" /* yacc.c:1646  */
+#line 3308 "grammar.c" /* yacc.c:1646  */
     break;
 
   case 200:
-#line 730 "grammar.y" /* yacc.c:1646  */
+#line 745 "grammar.y" /* yacc.c:1646  */
     { (yyval.i) = M_FISU; }
-#line 3297 "grammar.c" /* yacc.c:1646  */
+#line 3314 "grammar.c" /* yacc.c:1646  */
     break;
 
   case 201:
-#line 731 "grammar.y" /* yacc.c:1646  */
+#line 746 "grammar.y" /* yacc.c:1646  */
     { (yyval.i) = M_LSSU; }
-#line 3303 "grammar.c" /* yacc.c:1646  */
+#line 3320 "grammar.c" /* yacc.c:1646  */
     break;
 
   case 202:
-#line 732 "grammar.y" /* yacc.c:1646  */
+#line 747 "grammar.y" /* yacc.c:1646  */
     { (yyval.i) = M_MSU; }
-#line 3309 "grammar.c" /* yacc.c:1646  */
+#line 3326 "grammar.c" /* yacc.c:1646  */
     break;
 
   case 203:
-#line 733 "grammar.y" /* yacc.c:1646  */
+#line 748 "grammar.y" /* yacc.c:1646  */
     { (yyval.i) = MH_FISU; }
-#line 3315 "grammar.c" /* yacc.c:1646  */
+#line 3332 "grammar.c" /* yacc.c:1646  */
     break;
 
   case 204:
-#line 734 "grammar.y" /* yacc.c:1646  */
+#line 749 "grammar.y" /* yacc.c:1646  */
     { (yyval.i) = MH_LSSU; }
-#line 3321 "grammar.c" /* yacc.c:1646  */
+#line 3338 "grammar.c" /* yacc.c:1646  */
     break;
 
   case 205:
-#line 735 "grammar.y" /* yacc.c:1646  */
+#line 750 "grammar.y" /* yacc.c:1646  */
     { (yyval.i) = MH_MSU; }
-#line 3327 "grammar.c" /* yacc.c:1646  */
+#line 3344 "grammar.c" /* yacc.c:1646  */
     break;
 
   case 206:
-#line 738 "grammar.y" /* yacc.c:1646  */
+#line 753 "grammar.y" /* yacc.c:1646  */
     { (yyval.blk).mtp3fieldtype = M_SIO; }
-#line 3333 "grammar.c" /* yacc.c:1646  */
+#line 3350 "grammar.c" /* yacc.c:1646  */
     break;
 
   case 207:
-#line 739 "grammar.y" /* yacc.c:1646  */
+#line 754 "grammar.y" /* yacc.c:1646  */
     { (yyval.blk).mtp3fieldtype = M_OPC; }
-#line 3339 "grammar.c" /* yacc.c:1646  */
+#line 3356 "grammar.c" /* yacc.c:1646  */
     break;
 
   case 208:
-#line 740 "grammar.y" /* yacc.c:1646  */
+#line 755 "grammar.y" /* yacc.c:1646  */
     { (yyval.blk).mtp3fieldtype = M_DPC; }
-#line 3345 "grammar.c" /* yacc.c:1646  */
+#line 3362 "grammar.c" /* yacc.c:1646  */
     break;
 
   case 209:
-#line 741 "grammar.y" /* yacc.c:1646  */
+#line 756 "grammar.y" /* yacc.c:1646  */
     { (yyval.blk).mtp3fieldtype = M_SLS; }
-#line 3351 "grammar.c" /* yacc.c:1646  */
+#line 3368 "grammar.c" /* yacc.c:1646  */
     break;
 
   case 210:
-#line 742 "grammar.y" /* yacc.c:1646  */
+#line 757 "grammar.y" /* yacc.c:1646  */
     { (yyval.blk).mtp3fieldtype = MH_SIO; }
-#line 3357 "grammar.c" /* yacc.c:1646  */
+#line 3374 "grammar.c" /* yacc.c:1646  */
     break;
 
   case 211:
-#line 743 "grammar.y" /* yacc.c:1646  */
+#line 758 "grammar.y" /* yacc.c:1646  */
     { (yyval.blk).mtp3fieldtype = MH_OPC; }
-#line 3363 "grammar.c" /* yacc.c:1646  */
+#line 3380 "grammar.c" /* yacc.c:1646  */
     break;
 
   case 212:
-#line 744 "grammar.y" /* yacc.c:1646  */
+#line 759 "grammar.y" /* yacc.c:1646  */
     { (yyval.blk).mtp3fieldtype = MH_DPC; }
-#line 3369 "grammar.c" /* yacc.c:1646  */
+#line 3386 "grammar.c" /* yacc.c:1646  */
     break;
 
   case 213:
-#line 745 "grammar.y" /* yacc.c:1646  */
+#line 760 "grammar.y" /* yacc.c:1646  */
     { (yyval.blk).mtp3fieldtype = MH_SLS; }
-#line 3375 "grammar.c" /* yacc.c:1646  */
+#line 3392 "grammar.c" /* yacc.c:1646  */
     break;
 
   case 215:
-#line 748 "grammar.y" /* yacc.c:1646  */
+#line 763 "grammar.y" /* yacc.c:1646  */
     { (yyval.blk).b = gen_mtp3field_code(cstate, (yyvsp[-2].blk).mtp3fieldtype, (u_int)(yyvsp[0].i), (u_int)(yyvsp[-1].i), 0); }
-#line 3381 "grammar.c" /* yacc.c:1646  */
+#line 3398 "grammar.c" /* yacc.c:1646  */
     break;
 
   case 216:
-#line 749 "grammar.y" /* yacc.c:1646  */
+#line 764 "grammar.y" /* yacc.c:1646  */
     { (yyval.blk).b = gen_mtp3field_code(cstate, (yyvsp[-2].blk).mtp3fieldtype, (u_int)(yyvsp[0].i), (u_int)(yyvsp[-1].i), 1); }
-#line 3387 "grammar.c" /* yacc.c:1646  */
+#line 3404 "grammar.c" /* yacc.c:1646  */
     break;
 
   case 217:
-#line 750 "grammar.y" /* yacc.c:1646  */
+#line 765 "grammar.y" /* yacc.c:1646  */
     { (yyval.blk).b = (yyvsp[-1].blk).b; (yyval.blk).q = qerr; }
-#line 3393 "grammar.c" /* yacc.c:1646  */
+#line 3410 "grammar.c" /* yacc.c:1646  */
     break;
 
   case 218:
-#line 752 "grammar.y" /* yacc.c:1646  */
+#line 767 "grammar.y" /* yacc.c:1646  */
     {
 	(yyval.blk).mtp3fieldtype = (yyvsp[-1].blk).mtp3fieldtype;
 	if ((yyval.blk).mtp3fieldtype == M_SIO ||
@@ -3406,17 +3423,17 @@
 	    (yyval.blk).mtp3fieldtype == MH_SLS)
 		(yyval.blk).b = gen_mtp3field_code(cstate, (yyval.blk).mtp3fieldtype, (u_int) (yyvsp[0].i), BPF_JEQ, 0);
 	}
-#line 3410 "grammar.c" /* yacc.c:1646  */
+#line 3427 "grammar.c" /* yacc.c:1646  */
     break;
 
   case 220:
-#line 766 "grammar.y" /* yacc.c:1646  */
+#line 781 "grammar.y" /* yacc.c:1646  */
     { gen_or((yyvsp[-2].blk).b, (yyvsp[0].blk).b); (yyval.blk) = (yyvsp[0].blk); }
-#line 3416 "grammar.c" /* yacc.c:1646  */
+#line 3433 "grammar.c" /* yacc.c:1646  */
     break;
 
 
-#line 3420 "grammar.c" /* yacc.c:1646  */
+#line 3437 "grammar.c" /* yacc.c:1646  */
       default: break;
     }
   /* User semantic actions sometimes alter yychar, and that requires
@@ -3644,5 +3661,5 @@
 #endif
   return yyresult;
 }
-#line 768 "grammar.y" /* yacc.c:1906  */
+#line 783 "grammar.y" /* yacc.c:1906  */
 
diff --git a/grammar.h b/grammar.h
index 2a495a0..286cc79 100644
--- a/grammar.h
+++ b/grammar.h
@@ -1,8 +1,8 @@
-/* A Bison parser, made by GNU Bison 3.0.2.  */
+/* A Bison parser, made by GNU Bison 3.0.4.  */
 
 /* Bison interface for Yacc-like parsers in C
 
-   Copyright (C) 1984, 1989-1990, 2000-2013 Free Software Foundation, Inc.
+   Copyright (C) 1984, 1989-1990, 2000-2015 Free Software Foundation, Inc.
 
    This program is free software: you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
@@ -289,10 +289,10 @@
 
 /* Value type.  */
 #if ! defined YYSTYPE && ! defined YYSTYPE_IS_DECLARED
-typedef union YYSTYPE YYSTYPE;
+
 union YYSTYPE
 {
-#line 271 "grammar.y" /* yacc.c:1909  */
+#line 286 "grammar.y" /* yacc.c:1909  */
 
 	int i;
 	bpf_u_int32 h;
@@ -310,6 +310,8 @@
 
 #line 312 "grammar.h" /* yacc.c:1909  */
 };
+
+typedef union YYSTYPE YYSTYPE;
 # define YYSTYPE_IS_TRIVIAL 1
 # define YYSTYPE_IS_DECLARED 1
 #endif
diff --git a/grammar.y b/grammar.y
index 8e1d40a..be80e2b 100644
--- a/grammar.y
+++ b/grammar.y
@@ -21,7 +21,7 @@
 /*
  * And we need to pass the compiler state to the scanner.
  */
-%parse-param {compiler_state_t *cstate}
+%parse-param { compiler_state_t *cstate }
 
 %{
 /*
@@ -47,19 +47,15 @@
  */
 
 #ifdef HAVE_CONFIG_H
-#include "config.h"
+#include <config.h>
 #endif
 
-#ifdef _WIN32
-#include <pcap-stdinc.h>
-#else /* _WIN32 */
-#include <sys/types.h>
-#include <sys/socket.h>
-#endif /* _WIN32 */
-
 #include <stdlib.h>
 
 #ifndef _WIN32
+#include <sys/types.h>
+#include <sys/socket.h>
+
 #if __STDC__
 struct mbuf;
 struct rtentry;
@@ -71,6 +67,8 @@
 
 #include <stdio.h>
 
+#include "diag-control.h"
+
 #include "pcap-int.h"
 
 #include "gencode.h"
@@ -90,9 +88,30 @@
 #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 */
@@ -199,8 +218,8 @@
 
 static struct qual qerr = { Q_UNDEF, Q_UNDEF, Q_UNDEF, Q_UNDEF };
 
-static void
-yyerror(void *yyscanner, compiler_state_t *cstate, const char *msg)
+static PCAP_NORETURN_DEF void
+yyerror(void *yyscanner _U_, compiler_state_t *cstate, const char *msg)
 {
 	bpf_syntax_error(cstate, msg);
 	/* NOTREACHED */
@@ -246,26 +265,22 @@
 	}
 }
 #else /* !HAVE_NET_PFVAR_H */
-static int
-pfreason_to_num(compiler_state_t *cstate, const char *reason)
+static PCAP_NORETURN_DEF int
+pfreason_to_num(compiler_state_t *cstate, const char *reason _U_)
 {
 	bpf_error(cstate, "libpcap was compiled on a machine without pf support");
 	/*NOTREACHED*/
-
-	/* this is to make the VC compiler happy */
-	return -1;
 }
 
-static int
-pfaction_to_num(compiler_state_t *cstate, const char *action)
+static PCAP_NORETURN_DEF int
+pfaction_to_num(compiler_state_t *cstate, const char *action _U_)
 {
 	bpf_error(cstate, "libpcap was compiled on a machine without pf support");
 	/*NOTREACHED*/
-
-	/* this is to make the VC compiler happy */
-	return -1;
 }
 #endif /* HAVE_NET_PFVAR_H */
+
+DIAG_OFF_BISON_BYACC
 %}
 
 %union {
diff --git a/inet.c b/inet.c
deleted file mode 100644
index 16a483d..0000000
--- a/inet.c
+++ /dev/null
@@ -1,403 +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 <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__ */
-
-#include "pcap-int.h"
-
-#ifdef HAVE_OS_PROTO_H
-#include "os-proto.h"
-#endif
-
-#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)pcap_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)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 {
-			(void)pcap_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)strlcpy(ifr.ifr_name, device, sizeof(ifr.ifr_name));
-	if (ioctl(fd, SIOCGIFNETMASK, (char *)&ifr) < 0) {
-		(void)pcap_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)pcap_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.
- *
- * In the best of all possible worlds, this would be the same as on
- * UN*X, but there may be software that expects this to return a
- * full list of devices after the first device.
- */
-#define ADAPTERSNAME_LEN	8192
-char *
-pcap_lookupdev(errbuf)
-	register char *errbuf;
-{
-	DWORD dwVersion;
-	DWORD dwWindowsMajorVersion;
-	char our_errbuf[PCAP_ERRBUF_SIZE+1];
-
-#pragma warning (push)
-#pragma warning (disable: 4996) /* disable MSVC's GetVersion() deprecated warning here */
-	dwVersion = GetVersion();	/* get the OS version */
-#pragma warning (pop)
-	dwWindowsMajorVersion = (DWORD)(LOBYTE(LOWORD(dwVersion)));
-
-	if (dwVersion >= 0x80000000 && dwWindowsMajorVersion >= 4) {
-		/*
-		 * Windows 95, 98, ME.
-		 */
-		ULONG NameLength = 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_win32_err_to_str(GetLastError(), our_errbuf);
-			(void)pcap_snprintf(errbuf, PCAP_ERRBUF_SIZE,
-				"PacketGetAdapterNames: %s", our_errbuf);
-			free(TAdaptersName);
-			return NULL;
-		}
-
-
-		BufferSpaceLeft = ADAPTERSNAME_LEN * sizeof(WCHAR);
-		tAstr = (char*)TAdaptersName;
-		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);
-	}
-}
-
-
-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 */
diff --git a/libpcap.pc.in b/libpcap.pc.in
new file mode 100644
index 0000000..d74cbc5
--- /dev/null
+++ b/libpcap.pc.in
@@ -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/getopt.c b/missing/getopt.c
index cc798e1..7c897c6 100644
--- a/missing/getopt.c
+++ b/missing/getopt.c
@@ -56,10 +56,7 @@
  *	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)
 {
 	char *cp;
 	static char *__progname;
diff --git a/missing/getopt.h b/missing/getopt.h
index d176345..fc83c94 100644
--- a/missing/getopt.h
+++ b/missing/getopt.h
@@ -2,6 +2,6 @@
  * Header for the getopt() we supply if the platform doesn't supply it.
  */
 extern char *optarg;			/* getopt(3) external variables */
-extern int optind, opterr, optopt;
+extern int optind, opterr, optreset, optopt;
 
 extern int getopt(int nargc, char * const *nargv, const char *ostr);
diff --git a/missing/strtok_r.c b/missing/strtok_r.c
index c9c94b9..5fca2f3 100644
--- a/missing/strtok_r.c
+++ b/missing/strtok_r.c
@@ -35,7 +35,7 @@
  */
 
 #ifdef HAVE_CONFIG_H
-#include "config.h"
+#include <config.h>
 #endif
 
 #include "portability.h"
diff --git a/msdos/common.dj b/msdos/common.dj
deleted file mode 100644
index dacfd1f..0000000
--- a/msdos/common.dj
+++ /dev/null
@@ -1,86 +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
-
-#
-# This value is normally not important. Used by 'dxe3gen' in
-# msdos/pm_drvr/makefile.dj to make "dynamically loaded modules".
-# But this is not finished.
-#
-#GCC_LIB  = $(shell gcc -print-libgcc-file-name)
-GCC_LIB  = .
-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))
-
-OBJ_DIR = djgpp.obj
-
-ifeq ($(wildcard $(GCC_LIB)),)
-check_gcclib:
-	@echo libgcc.a not found. Set \"$(GCC_LIB)\" to \"/djgpp/lib/gcc/djgpp/4.X/libgcc.a\"
-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 -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) -o $@ $<
-	@echo
-
-%.o: %.s
-	$(CC) -c $(CFLAGS) -x assembler-with-cpp -o $@ $<
-	@echo
-
diff --git a/msdos/makefile b/msdos/makefile
index 234a276..599a619 100644
--- a/msdos/makefile
+++ b/msdos/makefile
@@ -23,7 +23,7 @@
 
 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 inet.c msdos\ndis2.c msdos\pktdrvr.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
@@ -118,8 +118,6 @@
 
 pcap.obj: pcap.c pcap-dos.h pcap-int.h pcap.h pcap-bpf.h
 
-inet.obj: inet.c 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
 
@@ -158,8 +156,6 @@
 
 pcap.o32: pcap.c pcap-dos.h pcap-int.h pcap.h pcap-bpf.h
 
-inet.o32: inet.c 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
 
diff --git a/msdos/makefile.dj b/msdos/makefile.dj
index 3f56da9..190db00 100644
--- a/msdos/makefile.dj
+++ b/msdos/makefile.dj
@@ -24,7 +24,7 @@
 
 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-pcap-ng.c inet.c \
+          savefile.c pcap.c sf-pcap.c sf-pcapng.c \
           msdos/pktdrvr.c msdos/ndis2.c # missing/snprintf.c
 
 OBJECTS = $(addprefix $(OBJ_DIR)/, $(notdir $(SOURCES:.c=.o)))
diff --git a/msdos/makefile.wc b/msdos/makefile.wc
index 61ba137..0246012 100644
--- a/msdos/makefile.wc
+++ b/msdos/makefile.wc
@@ -28,7 +28,7 @@
        $(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)\inet.obj     $(OBJDIR)\ndis2.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        &
@@ -108,8 +108,6 @@
 
 $(OBJDIR)\pcap.obj: pcap.c pcap-dos.h pcap-int.h pcap.h pcap-bpf.h
 
-$(OBJDIR)\inet.obj: inet.c 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
 
diff --git a/msdos/ndis2.c b/msdos/ndis2.c
deleted file mode 100644
index 526b221..0000000
--- a/msdos/ndis2.c
+++ /dev/null
@@ -1,860 +0,0 @@
-/*
- * Copyright (c) 1993,1994
- *      Texas A&M University.  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 Texas A&M University
- *      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 UNIVERSITY 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 UNIVERSITY 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.
- *
- * Developers:
- *             David K. Hess, Douglas Lee Schales, David R. Safford
- *
- * Heavily modified for Metaware HighC + GNU C 2.8+
- *             Gisle Vanem 1998
- */
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <dos.h>
-#include <io.h>
-#include <fcntl.h>
-#include <malloc.h>
-#include <string.h>
-
-#include "pcap-dos.h"
-#include "pcap-int.h"
-#include "msdos/ndis2.h"
-
-#if defined(USE_NDIS2)
-
-/*
- *  Packet buffer handling
- */
-extern int     FreePktBuf  (PktBuf *buf);
-extern int     EnquePktBuf (PktBuf *buf);
-extern PktBuf* AllocPktBuf (void);
-
-/*
- *  Various defines
- */
-#define MAX_NUM_DEBUG_STRINGS 90
-#define DEBUG_STRING_LENGTH   80
-#define STACK_POOL_SIZE       6
-#define STACK_SIZE            256
-
-#define MEDIA_FDDI            1
-#define MEDIA_ETHERNET        2
-#define MEDIA_TOKEN           3
-
-static int     startDebug     = 0;
-static int     stopDebug      = 0;
-
-static DWORD   droppedPackets = 0L;
-static WORD    frameSize      = 0;
-static WORD    headerSize     = 0;
-static int     mediaType      = 0;
-static char   *lastErr        = NULL;
-
-static BYTE    debugStrings [MAX_NUM_DEBUG_STRINGS][DEBUG_STRING_LENGTH];
-static BYTE   *freeStacks   [STACK_POOL_SIZE];
-static int     freeStackPtr = STACK_POOL_SIZE - 1;
-
-static ProtMan protManEntry = NULL;
-static WORD    protManDS    = 0;
-static volatile int xmitPending;
-
-static struct _PktBuf        *txBufPending;
-static struct _CardHandle    *handle;
-static struct _CommonChars    common;
-static struct _ProtocolChars  protChars;
-static struct _ProtDispatch   lowerTable;
-
-static struct _FailingModules failingModules;
-static struct _BindingsList   bindings;
-
-static struct {
-         WORD  err_num;
-         char *err_text;
-       } ndis_errlist[] = {
-
-  { ERR_SUCCESS,
-    "The function completed successfully.\n"  },
-
-  { ERR_WAIT_FOR_RELEASE,
-    "The ReceiveChain completed successfully but the protocol has\n"
-    "retained control of the buffer.\n"  },
-
-  { ERR_REQUEST_QUEUED,
-    "The current request has been queued.\n"  },
-
-  { ERR_FRAME_NOT_RECOGNIZED,
-    "Frame not recognized.\n"  },
-
-  { ERR_FRAME_REJECTED,
-    "Frame was discarded.\n"  },
-
-  { ERR_FORWARD_FRAME,
-    "Protocol wishes to forward frame to another protocol.\n"  },
-
-  { ERR_OUT_OF_RESOURCE,
-    "Out of resource.\n"  },
-
-  { ERR_INVALID_PARAMETER,
-    "Invalid parameter.\n"  },
-
-  { ERR_INVALID_FUNCTION,
-    "Invalid function.\n"  },
-
-  { ERR_NOT_SUPPORTED,
-    "Not supported.\n"  },
-
-  { ERR_HARDWARE_ERROR,
-    "Hardware error.\n"  },
-
-  { ERR_TRANSMIT_ERROR,
-    "The packet was not transmitted due to an error.\n"  },
-
-  { ERR_NO_SUCH_DESTINATION,
-    "Token ring packet was not recognized when transmitted.\n"  },
-
-  { ERR_BUFFER_TOO_SMALL,
-    "Provided buffer was too small.\n"  },
-
-  { ERR_ALREADY_STARTED,
-    "Network drivers already started.\n"  },
-
-  { ERR_INCOMPLETE_BINDING,
-    "Protocol driver could not complete its bindings.\n"  },
-
-  { ERR_DRIVER_NOT_INITIALIZED,
-    "MAC did not initialize properly.\n"  },
-
-  { ERR_HARDWARE_NOT_FOUND,
-    "Hardware not found.\n"  },
-
-  { ERR_HARDWARE_FAILURE,
-    "Hardware failure.\n"  },
-
-  { ERR_CONFIGURATION_FAILURE,
-    "Configuration failure.\n"  },
-
-  { ERR_INTERRUPT_CONFLICT,
-    "Interrupt conflict.\n"  },
-
-  { ERR_INCOMPATIBLE_MAC,
-    "The MAC is not compatible with the protocol.\n"  },
-
-  { ERR_INITIALIZATION_FAILED,
-    "Initialization failed.\n"  },
-
-  { ERR_NO_BINDING,
-    "Binding did not occur.\n"  },
-
-  { ERR_NETWORK_MAY_NOT_BE_CONNECTED,
-    "The network may not be connected to the adapter.\n"  },
-
-  { ERR_INCOMPATIBLE_OS_VERSION,
-    "The version of the operating system is incompatible with the protocol.\n"  },
-
-  { ERR_ALREADY_REGISTERED,
-    "The protocol is already registered.\n"  },
-
-  { ERR_PATH_NOT_FOUND,
-    "PROTMAN.EXE could not be found.\n"  },
-
-  { ERR_INSUFFICIENT_MEMORY,
-    "Insufficient memory.\n"  },
-
-  { ERR_INFO_NOT_FOUND,
-    "Protocol Mananger info structure is lost or corrupted.\n"  },
-
-  { ERR_GENERAL_FAILURE,
-    "General failure.\n"  }
-};
-
-/*
- *  Some handy macros
- */
-#define PERROR(str)    printf("%s (%d): %s\n", __FILE__,__LINE__,str)
-#define DEBUG_RING()   (debugStrings[stopDebug+1 == MAX_NUM_DEBUG_STRINGS ? \
-                        stopDebug = 0 : ++stopDebug])
-
-/*
- * needs rewrite for DOSX
- */
-#define MAC_DISPATCH(hnd)  ((struct _MacUpperDispatch*)(hnd)->common->upperDispatchTable)
-#define MAC_STATUS(hnd)    ((struct _MacStatusTable*)  (hnd)->common->serviceStatus)
-#define MAC_CHAR(hnd)      ((struct _MacChars*)        (hnd)->common->serviceChars)
-
-#ifdef NDIS_DEBUG
-  #define DEBUG0(str)      printf (str)
-  #define DEBUG1(fmt,a)    printf (fmt,a)
-  #define DEBUG2(fmt,a,b)  printf (fmt,a,b)
-  #define TRACE0(str)      sprintf (DEBUG_RING(),str)
-  #define TRACE1(fmt,a)    sprintf (DEBUG_RING(),fmt,a)
-#else
-  #define DEBUG0(str)      ((void)0)
-  #define DEBUG1(fmt,a)    ((void)0)
-  #define DEBUG2(fmt,a,b)  ((void)0)
-  #define TRACE0(str)      ((void)0)
-  #define TRACE1(fmt,a)    ((void)0)
-#endif
-
-/*
- * This routine is called from both threads
- */
-void NdisFreeStack (BYTE *aStack)
-{
-  GUARD();
-
-  if (freeStackPtr == STACK_POOL_SIZE - 1)
-     PERROR ("tried to free too many stacks");
-
-  freeStacks[++freeStackPtr] = aStack;
-
-  if (freeStackPtr == 0)
-     TRACE0 ("freeStackPtr went positive\n");
-
-  UNGUARD();
-}
-
-/*
- * This routine is called from callbacks to allocate local data
- */
-BYTE *NdisAllocStack (void)
-{
-  BYTE *stack;
-
-  GUARD();
-
-  if (freeStackPtr < 0)
-  {
-    /* Ran out of stack buffers. Return NULL which will start
-     * dropping packets
-     */
-    TRACE0 ("freeStackPtr went negative\n");
-    stack = 0;
-  }
-  else
-    stack = freeStacks[freeStackPtr--];
-
-  UNGUARD();
-  return (stack);
-}
-
-CALLBACK (NdisSystemRequest (DWORD param1, DWORD param2, WORD param3,
-                             WORD opcode, WORD targetDS))
-{
-  static int            bindEntry = 0;
-  struct _CommonChars  *macCommon;
-  volatile WORD result;
-
-  switch (opcode)
-  {
-    case REQ_INITIATE_BIND:
-         macCommon = (struct _CommonChars*) param2;
-         if (macCommon == NULL)
-	 {
-           printf ("There is an NDIS misconfiguration.\n");
-           result = ERR_GENERAL_FAILURE;
-	   break;
-	 }
-         DEBUG2 ("module name %s\n"
-                 "module type %s\n",
-                 macCommon->moduleName,
-                 ((MacChars*) macCommon->serviceChars)->macName);
-
-         /* Binding to the MAC */
-         result = macCommon->systemRequest ((DWORD)&common, (DWORD)&macCommon,
-                                            0, REQ_BIND,
-                                            macCommon->moduleDS);
-
-         if (!strcmp(bindings.moduleName[bindEntry], handle->moduleName))
-              handle->common = macCommon;
-         else PERROR ("unknown module");
-         ++bindEntry;
-	 break;
-
-    case REQ_INITIATE_UNBIND:
-         macCommon = (struct _CommonChars*) param2;
-         result = macCommon->systemRequest ((DWORD)&common, 0,
-                                            0, REQ_UNBIND,
-                                            macCommon->moduleDS);
-         break;
-
-    default:
-         result = ERR_GENERAL_FAILURE;
-	 break;
-  }
-  ARGSUSED (param1);
-  ARGSUSED (param3);
-  ARGSUSED (targetDS);
-  return (result);
-}
-
-CALLBACK (NdisRequestConfirm (WORD protId, WORD macId,   WORD reqHandle,
-                              WORD status, WORD request, WORD protDS))
-{
-  ARGSUSED (protId);    ARGSUSED (macId);
-  ARGSUSED (reqHandle); ARGSUSED (status);
-  ARGSUSED (request);   ARGSUSED (protDS);
-  return (ERR_SUCCESS);
-}
-
-CALLBACK (NdisTransmitConfirm (WORD protId, WORD macId, WORD reqHandle,
-                               WORD status, WORD protDS))
-{
-  xmitPending--;
-  FreePktBuf (txBufPending);  /* Add passed ECB back to the free list */
-
-  ARGSUSED (reqHandle);
-  ARGSUSED (status);
-  ARGSUSED (protDS);
-  return (ERR_SUCCESS);
-}
-
-
-/*
- * The primary function for receiving packets
- */
-CALLBACK (NdisReceiveLookahead (WORD  macId,      WORD  frameSize,
-                                WORD  bytesAvail, BYTE *buffer,
-                                BYTE *indicate,   WORD  protDS))
-{
-  int     result;
-  PktBuf *pktBuf;
-  WORD    bytesCopied;
-  struct _TDBufDescr tDBufDescr;
-
-#if 0
-  TRACE1 ("lookahead length = %d, ", bytesAvail);
-  TRACE1 ("ecb = %08lX, ",          *ecb);
-  TRACE1 ("count = %08lX\n",         count);
-  TRACE1 ("offset = %08lX, ",        offset);
-  TRACE1 ("timesAllowed = %d, ",     timesAllowed);
-  TRACE1 ("packet size = %d\n",      look->dataLookAheadLen);
-#endif
-
-  /* Allocate a buffer for the packet
-   */
-  if ((pktBuf = AllocPktBuf()) == NULL)
-  {
-    droppedPackets++;
-    return (ERR_FRAME_REJECTED);
-  }
-
-  /*
-   * Now kludge things. Note we will have to undo this later. This will
-   * make the packet contiguous after the MLID has done the requested copy.
-   */
-
-  tDBufDescr.tDDataCount = 1;
-  tDBufDescr.tDBufDescrRec[0].tDPtrType = NDIS_PTR_PHYSICAL;
-  tDBufDescr.tDBufDescrRec[0].tDDataPtr = pktBuf->buffer;
-  tDBufDescr.tDBufDescrRec[0].tDDataLen = pktBuf->length;
-  tDBufDescr.tDBufDescrRec[0].dummy     = 0;
-
-  result = MAC_DISPATCH(handle)->transferData (&bytesCopied, 0, &tDBufDescr,
-                                               handle->common->moduleDS);
-  pktBuf->packetLength = bytesCopied;
-
-  if (result == ERR_SUCCESS)
-       EnquePktBuf(pktBuf);
-  else FreePktBuf (pktBuf);
-
-  ARGSUSED (frameSize);
-  ARGSUSED (bytesAvail);
-  ARGSUSED (indicate);
-  ARGSUSED (protDS);
-
-  return (ERR_SUCCESS);
-}
-
-CALLBACK (NdisIndicationComplete (WORD macId, WORD protDS))
-{
-  ARGSUSED (macId);
-  ARGSUSED (protDS);
-
-  /* We don't give a hoot about these. Just return
-   */
-  return (ERR_SUCCESS);
-}
-
-/*
- * This is the OTHER way we may receive packets
- */
-CALLBACK (NdisReceiveChain (WORD macId, WORD frameSize, WORD reqHandle,
-                            struct _RxBufDescr *rxBufDescr,
-                            BYTE *indicate, WORD protDS))
-{
-  struct _PktBuf *pktBuf;
-  int     i;
-
-  /*
-   * For now we copy the entire packet over to a PktBuf structure. This may be
-   * a performance hit but this routine probably isn't called very much, and
-   * it is a lot of work to do it otherwise. Also if it is a filter protocol
-   * packet we could end up sucking up MAC buffes.
-   */
-
-  if ((pktBuf = AllocPktBuf()) == NULL)
-  {
-    droppedPackets++;
-    return (ERR_FRAME_REJECTED);
-  }
-  pktBuf->packetLength = 0;
-
-  /* Copy the packet to the buffer
-   */
-  for (i = 0; i < rxBufDescr->rxDataCount; ++i)
-  {
-    struct _RxBufDescrRec *rxDescr = &rxBufDescr->rxBufDescrRec[i];
-
-    memcpy (pktBuf->buffer + pktBuf->packetLength,
-            rxDescr->rxDataPtr, rxDescr->rxDataLen);
-    pktBuf->packetLength += rxDescr->rxDataLen;
-  }
-
-  EnquePktBuf (pktBuf);
-
-  ARGSUSED (frameSize);
-  ARGSUSED (reqHandle);
-  ARGSUSED (indicate);
-  ARGSUSED (protDS);
-
-  /* This frees up the buffer for the MAC to use
-   */
-  return (ERR_SUCCESS);
-}
-
-CALLBACK (NdisStatusProc (WORD macId,  WORD param1, BYTE *indicate,
-                          WORD opcode, WORD protDS))
-{
-  switch (opcode)
-  {
-    case STATUS_RING_STATUS:
-	 break;
-    case STATUS_ADAPTER_CHECK:
-	 break;
-    case STATUS_START_RESET:
-	 break;
-    case STATUS_INTERRUPT:
-	 break;
-    case STATUS_END_RESET:
-	 break;
-    default:
-	 break;
-  }
-  ARGSUSED (macId);
-  ARGSUSED (param1);
-  ARGSUSED (indicate);
-  ARGSUSED (opcode);
-  ARGSUSED (protDS);
-
-  /* We don't need to do anything about this stuff yet
-   */
-  return (ERR_SUCCESS);
-}
-
-/*
- * Tell the NDIS driver to start the delivery of the packet
- */
-int NdisSendPacket (struct _PktBuf *pktBuf, int macId)
-{
-  struct _TxBufDescr txBufDescr;
-  int     result;
-
-  xmitPending++;
-  txBufPending = pktBuf;    /* we only have 1 pending Tx at a time */
-
-  txBufDescr.txImmedLen  = 0;
-  txBufDescr.txImmedPtr  = NULL;
-  txBufDescr.txDataCount = 1;
-  txBufDescr.txBufDescrRec[0].txPtrType = NDIS_PTR_PHYSICAL;
-  txBufDescr.txBufDescrRec[0].dummy     = 0;
-  txBufDescr.txBufDescrRec[0].txDataLen = pktBuf->packetLength;
-  txBufDescr.txBufDescrRec[0].txDataPtr = pktBuf->buffer;
-
-  result = MAC_DISPATCH(handle)->transmitChain (common.moduleId,
-                                                pktBuf->handle,
-                                                &txBufDescr,
-                                                handle->common->moduleDS);
-  switch (result)
-  {
-    case ERR_OUT_OF_RESOURCE:
-         /* Note that this should not happen but if it does there is not
-          * much we can do about it
-          */
-         printf ("ERROR: transmit queue overflowed\n");
-         return (0);
-
-    case ERR_SUCCESS:
-         /* Everything was hunky dory and synchronous. Free up the
-          * packet buffer
-          */
-         xmitPending--;
-         FreePktBuf (pktBuf);
-         return (1);
-
-    case ERR_REQUEST_QUEUED:
-         /* Everything was hunky dory and asynchronous. Do nothing
-          */
-         return (1);
-
-    default:
-         printf ("Tx fail, code = %04X\n", result);
-         return (0);
-  }
-}
-
-
-
-static int ndis_nerr = sizeof(ndis_errlist) / sizeof(ndis_errlist[0]);
-
-static char *Ndis_strerror (WORD errorCode)
-{
-  static char buf[30];
-  int    i;
-
-  for (i = 0; i < ndis_nerr; i++)
-      if (errorCode == ndis_errlist[i].err_num)
-         return (ndis_errlist[i].err_text);
-
-  sprintf (buf,"unknown error %d",errorCode);
-  return (buf);
-}
-
-
-char *NdisLastError (void)
-{
-  char *errStr = lastErr;
-  lastErr = NULL;
-  return (errStr);
-}
-
-int NdisOpen (void)
-{
-  struct _ReqBlock reqBlock;
-  int     result;
-  int     ndisFd = open (NDIS_PATH, O_RDONLY);
-
-  if (ndisFd < 0)
-  {
-    printf ("Could not open NDIS Protocol Manager device.\n");
-    return (0);
-  }
-
-  memset (&reqBlock, 0, sizeof(ReqBlock));
-
-  reqBlock.opcode = PM_GET_PROTOCOL_MANAGER_LINKAGE;
-
-  result = NdisGetLinkage (ndisFd, (char*)&reqBlock, sizeof(ReqBlock));
-  if (result != 0)
-  {
-    printf ("Could not get Protocol Manager linkage.\n");
-    close (ndisFd);
-    return (0);
-  }
-
-  close (ndisFd);
-  protManEntry = (ProtMan) reqBlock.pointer1;
-  protManDS    = reqBlock.word1;
-
-  DEBUG2 ("Entry Point = %04X:%04X\n", FP_SEG(protManEntry),FP_OFF(protManEntry));
-  DEBUG1 ("ProtMan DS  = %04X\n", protManDS);
-  return (1);
-}
-
-
-int NdisRegisterAndBind (int promis)
-{
-  struct _ReqBlock reqBlock;
-  WORD    result;
-
-  memset (&common,0,sizeof(common));
-
-  common.tableSize = sizeof (common);
-
-  common.majorNdisVersion   = 2;
-  common.minorNdisVersion   = 0;
-  common.majorModuleVersion = 2;
-  common.minorModuleVersion = 0;
-
-  /* Indicates binding from below and dynamically loaded
-   */
-  common.moduleFlags = 0x00000006L;
-
-  strcpy (common.moduleName, "PCAP");
-
-  common.protocolLevelUpper = 0xFF;
-  common.protocolLevelLower = 1;
-  common.interfaceLower     = 1;
-#ifdef __DJGPP__
-  common.moduleDS           = _dos_ds; /* the callback data segment */
-#else
-  common.moduleDS           = _DS;
-#endif
-
-  common.systemRequest      = (SystemRequest) systemRequestGlue;
-  common.serviceChars       = (BYTE*) &protChars;
-  common.serviceStatus      = NULL;
-  common.upperDispatchTable = NULL;
-  common.lowerDispatchTable = (BYTE*) &lowerTable;
-
-  protChars.length  = sizeof (protChars);
-  protChars.name[0] = 0;
-  protChars.type    = 0;
-
-  lowerTable.backPointer        = &common;
-  lowerTable.requestConfirm     = requestConfirmGlue;
-  lowerTable.transmitConfirm    = transmitConfirmGlue;
-  lowerTable.receiveLookahead   = receiveLookaheadGlue;
-  lowerTable.indicationComplete = indicationCompleteGlue;
-  lowerTable.receiveChain       = receiveChainGlue;
-  lowerTable.status             = statusGlue;
-  lowerTable.flags              = 3;
-  if (promis)
-     lowerTable.flags |= 4;   /* promiscous mode (receive everything) */
-
-  bindings.numBindings = 1;
-  strcpy (bindings.moduleName[0], handle->moduleName);
-
-  /* Register ourselves with NDIS
-   */
-  reqBlock.opcode   = PM_REGISTER_MODULE;
-  reqBlock.pointer1 = (BYTE FAR*) &common;
-  reqBlock.pointer2 = (BYTE FAR*) &bindings;
-
-  result = (*protManEntry) (&reqBlock, protManDS);
-  if (result)
-  {
-    printf ("Protman registering failed: %s\n", Ndis_strerror(result));
-    return (0);
-  }
-
-  /* Start the binding process
-   */
-  reqBlock.opcode   = PM_BIND_AND_START;
-  reqBlock.pointer1 = (BYTE FAR*) &failingModules;
-
-  result = (*protManEntry) (&reqBlock, protManDS);
-  if (result)
-  {
-    printf ("Start binding failed: %s\n", Ndis_strerror(result));
-    return (0);
-  }
-  return (1);
-}
-
-static int CheckMacFeatures (CardHandle *card)
-{
-  DWORD      serviceFlags;
-  BYTE _far *mediaString;
-  BYTE _far *mac_addr;
-
-  DEBUG2 ("checking card features\n"
-          "common table address = %08lX, macId = %d\n",
-          card->common, card->common->moduleId);
-
-  serviceFlags = MAC_CHAR (handle)->serviceFlags;
-
-  if ((serviceFlags & SF_PROMISCUOUS) == 0)
-  {
-    printf ("The MAC %s does not support promiscuous mode.\n",
-            card->moduleName);
-    return (0);
-  }
-
-  mediaString = MAC_CHAR (handle)->macName;
-
-  DEBUG1 ("media type = %s\n",mediaString);
-
-  /* Get the media type. And set the header size
-   */
-  if (!strncmp(mediaString,"802.3",5) ||
-      !strncmp(mediaString,"DIX",3)   ||
-      !strncmp(mediaString,"DIX+802.3",9))
-       headerSize = sizeof (EthernetIIHeader);
-
-  else if (!strncmp(mediaString,"FDDI",4))
-       headerSize = sizeof (FddiHeader) +
-                    sizeof (Ieee802Dot2SnapHeader);
-  else
-  {
-    printf ("Unsupported MAC type: `%s'\n", mediaString);
-    return (0);
-  }
-
-  frameSize = MAC_CHAR (handle)->maxFrameSize;
-  mac_addr  = MAC_CHAR (handle)->currentAddress;
-
-  printf ("Hardware address: %02X:%02X:%02X:%02X:%02X:%02X\n",
-          mac_addr[0], mac_addr[1], mac_addr[2],
-          mac_addr[3], mac_addr[4], mac_addr[5]);
-  return (1);
-}
-
-static int NdisStartMac (CardHandle *card)
-{
-  WORD result;
-
-  /* Set the lookahead length
-   */
-  result = MAC_DISPATCH(handle)->request (common.moduleId, 0,
-                                          headerSize, 0,
-                                          REQ_SET_LOOKAHEAD,
-                                          card->common->moduleDS);
-
-  /* We assume that if we got INVALID PARAMETER then either this
-   * is not supported or will work anyway. NE2000 does this.
-   */
-  if (result != ERR_SUCCESS && result != ERR_INVALID_PARAMETER)
-  {
-    DEBUG1 ("Set lookahead failed: %s\n", Ndis_strerror(result));
-    return (0);
-  }
-
-  /* Set the packet filter. Note that for some medias and drivers we
-   * must specify all three flags or the card(s) will not operate correctly.
-   */
-  result = MAC_DISPATCH(handle)->request (common.moduleId, 0,
-                      /* all packets */   FILTER_PROMISCUOUS |
-                      /* packets to us */ FILTER_DIRECTED    |
-                      /* broadcasts */    FILTER_BROADCAST,
-                                          0, REQ_SET_PACKET_FILTER,
-                                          card->common->moduleDS);
-  if (result != ERR_SUCCESS)
-  {
-    DEBUG1 ("Set packet filter failed: %s\n", Ndis_strerror(result));
-    return (0);
-  }
-
-  /* If OPEN/CLOSE supported then open the adapter
-   */
-  if (MAC_CHAR(handle)->serviceFlags & SF_OPEN_CLOSE)
-  {
-    result = MAC_DISPATCH(handle)->request (common.moduleId, 0, 0, NULL,
-                                            REQ_OPEN_ADAPTER,
-                                            card->common->moduleDS);
-    if (result != ERR_SUCCESS)
-    {
-      DEBUG1 ("Opening the MAC failed: %s\n", Ndis_strerror(result));
-      return (0);
-    }
-  }
-  return (1);
-}
-
-void NdisShutdown (void)
-{
-  struct _ReqBlock reqBlock;
-  int     result, i;
-
-  if (!handle)
-     return;
-
-  /* If the adapters support open and are open then close them
-   */
-  if ((MAC_CHAR(handle)->serviceFlags & SF_OPEN_CLOSE) &&
-      (MAC_STATUS(handle)->macStatus & MAC_OPEN))
-  {
-    result = MAC_DISPATCH(handle)->request (common.moduleId, 0, 0, 0,
-                                            REQ_CLOSE_ADAPTER,
-                                            handle->common->moduleDS);
-    if (result != ERR_SUCCESS)
-    {
-      printf ("Closing the MAC failed: %s\n", Ndis_strerror(result));
-      return;
-    }
-  }
-
-  /* Tell the Protocol Manager to unbind and stop
-   */
-  reqBlock.opcode   = PM_UNBIND_AND_STOP;
-  reqBlock.pointer1 = (BYTE FAR*) &failingModules;
-  reqBlock.pointer2 = NULL;
-
-  result = (*protManEntry) (&reqBlock, protManDS);
-  if (result)
-     printf ("Unbind failed: %s\n",  Ndis_strerror(result));
-
-  for (i = 0; i < STACK_POOL_SIZE; ++i)
-     free (freeStacks[i] - STACK_SIZE);
-
-  handle = NULL;
-}
-
-int NdisInit (int promis)
-{
-  int i, result;
-
-  /* Allocate the real mode stacks used for NDIS callbacks
-   */
-  for (i = 0; i < STACK_POOL_SIZE; ++i)
-  {
-    freeStacks[i] = malloc (STACK_SIZE);
-    if (!freeStacks[i])
-       return (0);
-    freeStacks[i] += STACK_SIZE;
-  }
-
-  if (!NdisOpen())
-     return (0);
-
-  if (!NdisRegisterAndBind(promis))
-     return (0);
-
-  DEBUG1 ("My module id: %d\n", common.moduleId);
-  DEBUG1 ("Handle id;    %d\n", handle->common->moduleId);
-  DEBUG1 ("MAC card:     %-16s - ", handle->moduleName);
-
-  atexit (NdisShutdown);
-
-  if (!CheckMacFeatures(&handle))
-     return (0);
-
-  switch (mediaType)
-  {
-    case MEDIA_FDDI:
-         DEBUG0 ("Media type: FDDI");
-	 break;
-    case MEDIA_ETHERNET:
-         DEBUG0 ("Media type: ETHERNET");
-	 break;
-    default:
-         DEBUG0 ("Unsupported media.\n");
-         return (0);
-  }
-
-  DEBUG1 (" - Frame size: %d\n", frameSize);
-
-  if (!NdisStartMac(&handle))
-     return (0);
-  return (1);
-}
-#endif  /* USE_NDIS2 */
-
diff --git a/msdos/ndis2.h b/msdos/ndis2.h
deleted file mode 100644
index f278b5d..0000000
--- a/msdos/ndis2.h
+++ /dev/null
@@ -1,559 +0,0 @@
-/*
- * Copyright (c) 1993,1994
- *      Texas A&M University.  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 Texas A&M University
- *      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 UNIVERSITY 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 UNIVERSITY 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.
- *
- * Developers:
- *             David K. Hess, Douglas Lee Schales, David R. Safford
- *
- * Heavily modified for Metaware HighC + GNU C 2.8+
- *             Gisle Vanem 1998
- */
-
-#ifndef __PCAP_NDIS_H
-#define __PCAP_NDIS_H
-
-#if defined (__HIGHC__)
-  #define pascal          _CC(_CALLEE_POPS_STACK & ~_REVERSE_PARMS) /* calling convention */
-  #define CALLBACK(foo)   pascal WORD foo
-  #define PAS_PTR(x,arg)  typedef FAR WORD pascal (*x) arg
-  #define GUARD()         _inline (0x9C,0xFA)   /* pushfd, cli */
-  #define UNGUARD()       _inline (0x9D)        /* popfd */
-  #define FAR             _far
-
-#elif defined(__GNUC__)
-  #define CALLBACK(foo)   WORD foo __attribute__((stdcall))
-  #define PAS_PTR(x,arg)  typedef WORD (*x) arg __attribute__((stdcall))
-  #define GUARD()         __asm__ __volatile__ ("pushfd; cli")
-  #define UNGUARD()       __asm__ __volatile__ ("popfd")
-  #define FAR
-
-#elif defined (__TURBOC__)
-  #define CALLBACK(foo)   WORD pascal foo
-  #define PAS_PTR(x,arg)  typedef WORD pascal (_far *x) arg
-  #define GUARD()         _asm { pushf; cli }
-  #define UNGUARD()       _asm { popf }
-  #define FAR             _far
-
-#elif defined (__WATCOMC__)
-  #define CALLBACK(foo)   WORD pascal foo
-  #define PAS_PTR(x,arg)  typedef WORD pascal (_far *x) arg
-  #define GUARD()         _disable()
-  #define UNGUARD()       _enable()
-  #define FAR             _far
-
-#else
-  #error Unsupported compiler
-#endif
-
-
-/*
- *  Forwards
- */
-struct _ReqBlock;
-struct _TxBufDescr;
-struct _TDBufDescr;
-
-/*
- * Protocol Manager API
- */
-PAS_PTR (ProtMan, (struct _ReqBlock FAR*, WORD));
-
-/*
- * System request
- */
-PAS_PTR (SystemRequest, (DWORD, DWORD, WORD, WORD, WORD));
-
-/*
- * MAC API
- */
-PAS_PTR (TransmitChain, (WORD, WORD, struct _TxBufDescr FAR*, WORD));
-PAS_PTR (TransferData,  (WORD*,WORD, struct _TDBufDescr FAR*, WORD));
-PAS_PTR (Request,       (WORD, WORD, WORD, DWORD, WORD, WORD));
-PAS_PTR (ReceiveRelease,(WORD, WORD));
-PAS_PTR (IndicationOn,  (WORD));
-PAS_PTR (IndicationOff, (WORD));
-
-
-typedef enum {
-        HARDWARE_NOT_INSTALLED  = 0,
-        HARDWARE_FAILED_DIAG    = 1,
-        HARDWARE_FAILED_CONFIG  = 2,
-        HARDWARE_HARD_FAULT     = 3,
-        HARDWARE_SOFT_FAULT     = 4,
-        HARDWARE_OK             = 7,
-        HARDWARE_MASK           = 0x0007,
-        MAC_BOUND               = 0x0008,
-        MAC_OPEN                = 0x0010,
-        DIAG_IN_PROGRESS        = 0x0020
-      } NdisMacStatus;
-
-typedef enum {
-        STATUS_RING_STATUS      = 1,
-        STATUS_ADAPTER_CHECK    = 2,
-        STATUS_START_RESET      = 3,
-        STATUS_INTERRUPT        = 4,
-        STATUS_END_RESET        = 5
-      } NdisStatus;
-
-typedef enum {
-        FILTER_DIRECTED         = 1,
-        FILTER_BROADCAST        = 2,
-        FILTER_PROMISCUOUS      = 4,
-        FILTER_SOURCE_ROUTE     = 8
-      } NdisPacketFilter;
-
-typedef enum {
-        REQ_INITIATE_DIAGNOSTICS     = 1,
-        REQ_READ_ERROR_LOG           = 2,
-        REQ_SET_STATION_ADDRESS      = 3,
-        REQ_OPEN_ADAPTER             = 4,
-        REQ_CLOSE_ADAPTER            = 5,
-        REQ_RESET_MAC                = 6,
-        REQ_SET_PACKET_FILTER        = 7,
-        REQ_ADD_MULTICAST_ADDRESS    = 8,
-        REQ_DELETE_MULTICAST_ADDRESS = 9,
-        REQ_UPDATE_STATISTICS        = 10,
-        REQ_CLEAR_STATISTICS         = 11,
-        REQ_INTERRUPT_REQUEST        = 12,
-        REQ_SET_FUNCTIONAL_ADDRESS   = 13,
-        REQ_SET_LOOKAHEAD            = 14
-      } NdisGeneralRequest;
-
-typedef enum {
-        SF_BROADCAST             = 0x00000001L,
-        SF_MULTICAST             = 0x00000002L,
-        SF_FUNCTIONAL            = 0x00000004L,
-        SF_PROMISCUOUS           = 0x00000008L,
-        SF_SOFT_ADDRESS          = 0x00000010L,
-        SF_STATS_CURRENT         = 0x00000020L,
-        SF_INITIATE_DIAGS        = 0x00000040L,
-        SF_LOOPBACK              = 0x00000080L,
-        SF_RECEIVE_CHAIN         = 0x00000100L,
-        SF_SOURCE_ROUTING        = 0x00000200L,
-        SF_RESET_MAC             = 0x00000400L,
-        SF_OPEN_CLOSE            = 0x00000800L,
-        SF_INTERRUPT_REQUEST     = 0x00001000L,
-        SF_SOURCE_ROUTING_BRIDGE = 0x00002000L,
-        SF_VIRTUAL_ADDRESSES     = 0x00004000L
-      } NdisMacServiceFlags;
-
-typedef enum {
-        REQ_INITIATE_BIND        = 1,
-        REQ_BIND                 = 2,
-        REQ_INITIATE_PREBIND     = 3,
-        REQ_INITIATE_UNBIND      = 4,
-        REQ_UNBIND               = 5
-      } NdisSysRequest;
-
-typedef enum  {
-        PM_GET_PROTOCOL_MANAGER_INFO      = 1,
-        PM_REGISTER_MODULE                = 2,
-        PM_BIND_AND_START                 = 3,
-        PM_GET_PROTOCOL_MANAGER_LINKAGE   = 4,
-        PM_GET_PROTOCOL_INI_PATH          = 5,
-        PM_REGISTER_PROTOCOL_MANAGER_INFO = 6,
-        PM_INIT_AND_REGISTER              = 7,
-        PM_UNBIND_AND_STOP                = 8,
-        PM_BIND_STATUS                    = 9,
-        PM_REGISTER_STATUS                = 10
-      } NdisProtManager;
-
-
-typedef enum {
-        ERR_SUCCESS                      = 0x00,
-        ERR_WAIT_FOR_RELEASE             = 0x01,
-        ERR_REQUEST_QUEUED               = 0x02,
-        ERR_FRAME_NOT_RECOGNIZED         = 0x03,
-        ERR_FRAME_REJECTED               = 0x04,
-        ERR_FORWARD_FRAME                = 0x05,
-        ERR_OUT_OF_RESOURCE              = 0x06,
-        ERR_INVALID_PARAMETER            = 0x07,
-        ERR_INVALID_FUNCTION             = 0x08,
-        ERR_NOT_SUPPORTED                = 0x09,
-        ERR_HARDWARE_ERROR               = 0x0A,
-        ERR_TRANSMIT_ERROR               = 0x0B,
-        ERR_NO_SUCH_DESTINATION          = 0x0C,
-        ERR_BUFFER_TOO_SMALL             = 0x0D,
-        ERR_ALREADY_STARTED              = 0x20,
-        ERR_INCOMPLETE_BINDING           = 0x21,
-        ERR_DRIVER_NOT_INITIALIZED       = 0x22,
-        ERR_HARDWARE_NOT_FOUND           = 0x23,
-        ERR_HARDWARE_FAILURE             = 0x24,
-        ERR_CONFIGURATION_FAILURE        = 0x25,
-        ERR_INTERRUPT_CONFLICT           = 0x26,
-        ERR_INCOMPATIBLE_MAC             = 0x27,
-        ERR_INITIALIZATION_FAILED        = 0x28,
-        ERR_NO_BINDING                   = 0x29,
-        ERR_NETWORK_MAY_NOT_BE_CONNECTED = 0x2A,
-        ERR_INCOMPATIBLE_OS_VERSION      = 0x2B,
-        ERR_ALREADY_REGISTERED           = 0x2C,
-        ERR_PATH_NOT_FOUND               = 0x2D,
-        ERR_INSUFFICIENT_MEMORY          = 0x2E,
-        ERR_INFO_NOT_FOUND               = 0x2F,
-        ERR_GENERAL_FAILURE              = 0xFF
-      } NdisError;
-
-#define NDIS_PARAM_INTEGER   0
-#define NDIS_PARAM_STRING    1
-
-#define NDIS_TX_BUF_LENGTH   8
-#define NDIS_TD_BUF_LENGTH   1
-#define NDIS_RX_BUF_LENGTH   8
-
-#define NDIS_PTR_PHYSICAL    0
-#define NDIS_PTR_VIRTUAL     2
-
-#define NDIS_PATH    "PROTMAN$"
-
-
-typedef struct _CommonChars {
-        WORD  tableSize;
-        BYTE  majorNdisVersion;        /* 2 - Latest version */
-        BYTE  minorNdisVersion;        /* 0                  */
-        WORD  reserved1;
-        BYTE  majorModuleVersion;
-        BYTE  minorModuleVersion;
-        DWORD moduleFlags;
-        /* 0 - Binding at upper boundary supported
-         * 1 - Binding at lower boundary supported
-         * 2 - Dynamically bound.
-         * 3-31 - Reserved, must be zero.
-         */
-        BYTE  moduleName[16];
-        BYTE  protocolLevelUpper;
-        /* 1 - MAC
-         * 2 - Data Link
-         * 3 - Network
-         * 4 - Transport
-         * 5 - Session
-         * -1 - Not specified
-         */
-        BYTE  interfaceUpper;
-        BYTE  protocolLevelLower;
-        /* 0 - Physical
-         * 1 - MAC
-         * 2 - Data Link
-         * 3 - Network
-         * 4 - Transport
-         * 5 - Session
-         * -1 - Not specified
-         */
-        BYTE  interfaceLower;
-        WORD  moduleId;
-        WORD  moduleDS;
-        SystemRequest systemRequest;
-        BYTE *serviceChars;
-        BYTE *serviceStatus;
-        BYTE *upperDispatchTable;
-        BYTE *lowerDispatchTable;
-        BYTE *reserved2;            /* Must be NULL */
-        BYTE *reserved3;            /* Must be NULL */
-      } CommonChars;
-
-
-typedef struct _MulticastList {
-        WORD   maxMulticastAddresses;
-        WORD   numberMulticastAddresses;
-        BYTE   multicastAddress[16][16];
-      } MulticastList;
-
-
-typedef struct _MacChars {
-        WORD   tableSize;
-        BYTE   macName[16];
-        WORD   addressLength;
-        BYTE   permanentAddress[16];
-        BYTE   currentAddress[16];
-        DWORD  currentFunctionalAddress;
-        MulticastList *multicastList;
-        DWORD  linkSpeed;
-        DWORD  serviceFlags;
-        WORD   maxFrameSize;
-        DWORD  txBufferSize;
-        WORD   txBufferAllocSize;
-        DWORD  rxBufferSize;
-        WORD   rxBufferAllocSize;
-        BYTE   ieeeVendor[3];
-        BYTE   vendorAdapter;
-        BYTE  *vendorAdapterDescription;
-        WORD   interruptLevel;
-        WORD   txQueueDepth;
-        WORD   maxDataBlocks;
-      } MacChars;
-
-
-typedef struct _ProtocolChars {
-        WORD   length;
-        BYTE   name[16];
-        WORD   type;
-      } ProtocolChars;
-
-
-typedef struct _MacUpperDispatch {
-        CommonChars      *backPointer;
-        Request           request;
-        TransmitChain     transmitChain;
-        TransferData      transferData;
-        ReceiveRelease    receiveRelease;
-        IndicationOn      indicationOn;
-        IndicationOff     indicationOff;
-      } MacUpperDispatch;
-
-
-typedef struct _MacStatusTable {
-        WORD   tableSize;
-        DWORD  lastDiag;
-        DWORD  macStatus;
-        WORD   packetFilter;
-        BYTE  *mediaSpecificStats;
-        DWORD  lastClear;
-        DWORD  totalFramesRx;
-        DWORD  totalFramesCrc;
-        DWORD  totalBytesRx;
-        DWORD  totalDiscardBufSpaceRx;
-        DWORD  totalMulticastRx;
-        DWORD  totalBroadcastRx;
-        DWORD  obsolete1[5];
-        DWORD  totalDiscardHwErrorRx;
-        DWORD  totalFramesTx;
-        DWORD  totalBytesTx;
-        DWORD  totalMulticastTx;
-        DWORD  totalBroadcastTx;
-        DWORD  obsolete2[2];
-        DWORD  totalDiscardTimeoutTx;
-        DWORD  totalDiscardHwErrorTx;
-      } MacStatusTable;
-
-
-typedef struct _ProtDispatch {
-        CommonChars *backPointer;
-        DWORD        flags;
-        /* 0 - handles non-LLC frames
-         * 1 - handles specific-LSAP LLC frames
-         * 2 - handles specific-LSAP LLC frames
-         * 3-31 - reserved must be 0
-         */
-        void  (*requestConfirm) (void);
-        void  (*transmitConfirm) (void);
-        void  (*receiveLookahead) (void);
-        void  (*indicationComplete) (void);
-        void  (*receiveChain) (void);
-        void  (*status) (void);
-      } ProtDispatch;
-
-
-typedef struct _ReqBlock {
-        WORD      opcode;
-        WORD      status;
-        BYTE FAR *pointer1;
-        BYTE FAR *pointer2;
-        WORD      word1;
-      } ReqBlock;
-
-
-typedef struct _TxBufDescrRec {
-        BYTE   txPtrType;
-        BYTE   dummy;
-        WORD   txDataLen;
-        BYTE  *txDataPtr;
-      } TxBufDescrRec;
-
-
-typedef struct _TxBufDescr {
-        WORD          txImmedLen;
-        BYTE         *txImmedPtr;
-        WORD          txDataCount;
-        TxBufDescrRec txBufDescrRec[NDIS_TX_BUF_LENGTH];
-      } TxBufDescr;
-
-
-typedef struct _TDBufDescrRec {
-        BYTE   tDPtrType;
-        BYTE   dummy;
-        WORD   tDDataLen;
-        BYTE  *tDDataPtr;
-      } TDBufDescrRec;
-
-
-typedef struct _TDBufDescr {
-        WORD          tDDataCount;
-        TDBufDescrRec tDBufDescrRec[NDIS_TD_BUF_LENGTH];
-      } TDBufDescr;
-
-
-typedef struct _RxBufDescrRec {
-        WORD   rxDataLen;
-        BYTE  *rxDataPtr;
-      } RxBufDescrRec;
-
-
-typedef struct _RxBufDescr {
-        WORD          rxDataCount;
-        RxBufDescrRec rxBufDescrRec[NDIS_RX_BUF_LENGTH];
-      } RxBufDescr;
-
-
-typedef struct _PktBuf {
-	struct _PktBuf *nextLink;
-	struct _PktBuf *prevLink;
-        int    handle;
-        int    length;
-        int    packetLength;
-        DWORD  sequence;
-        BYTE  *buffer;
-      } PktBuf;
-
-
-typedef struct _CardHandle {
-        BYTE         moduleName[16];
-        CommonChars *common;
-      } CardHandle;
-
-
-typedef struct _BindingsList {
-        WORD  numBindings;
-        BYTE  moduleName[2][16];
-      } BindingsList;
-
-
-typedef struct _FailingModules {
-        BYTE  upperModuleName[16];
-        BYTE  lowerModuleName[16];
-      } FailingModules;
-
-
-typedef union _HardwareAddress {
-        BYTE  bytes[6];
-        WORD  words[3];
-        struct {
-          BYTE bytes[6];
-        } addr;
-      } HardwareAddress;
-
-
-typedef struct _FddiHeader {
-        BYTE             frameControl;
-        HardwareAddress  etherDestHost;
-        HardwareAddress  etherSrcHost;
-      } FddiHeader;
-
-
-typedef struct _EthernetIIHeader {
-        HardwareAddress  etherDestHost;
-        HardwareAddress  etherSrcHost;
-        WORD             etherType;
-      } EthernetIIHeader;
-
-
-typedef struct _Ieee802Dot5Header {
-        HardwareAddress  etherDestHost;
-        HardwareAddress  etherSrcHost;
-        BYTE             routeInfo[30];
-      } Ieee802Dot5Header;
-
-
-typedef struct _Ieee802Dot2SnapHeader {
-        BYTE  dsap;                      /* 0xAA */
-        BYTE  ssap;                      /* 0xAA */
-        BYTE  control;                   /* 3    */
-        BYTE protocolId[5];
-      } Ieee802Dot2SnapHeader;
-
-
-/*
- *  Prototypes
- */
-extern char *NdisLastError        (void);
-extern int   NdisOpen             (void);
-extern int   NdisInit             (int promis);
-extern int   NdisRegisterAndBind  (int promis);
-extern void  NdisShutdown         (void);
-extern void  NdisCheckMacFeatures (struct _CardHandle *card);
-extern int   NdisSendPacket       (struct _PktBuf *pktBuf, int macId);
-
-/*
- *  Assembly "glue" functions
- */
-extern int systemRequestGlue();
-extern int requestConfirmGlue();
-extern int transmitConfirmGlue();
-extern int receiveLookaheadGlue();
-extern int indicationCompleteGlue();
-extern int receiveChainGlue();
-extern int statusGlue();
-
-/*
- *  IOCTL function
- */
-#ifdef __SMALL__
-extern int _far NdisGetLinkage (int handle, char *data, int size);
-#else
-extern int NdisGetLinkage (int handle, char *data, int size);
-#endif
-
-/*
- *  NDIS callback handlers
- */
-CALLBACK (NdisSystemRequest     (DWORD,DWORD, WORD, WORD, WORD));
-CALLBACK (NdisRequestConfirm    ( WORD, WORD, WORD, WORD, WORD,WORD));
-CALLBACK (NdisTransmitConfirm   ( WORD, WORD, WORD, WORD, WORD));
-CALLBACK (NdisReceiveLookahead  ( WORD, WORD, WORD, BYTE*, BYTE*, WORD));
-CALLBACK (NdisReceiveChain      ( WORD, WORD, WORD, struct _RxBufDescr*, BYTE*, WORD));
-CALLBACK (NdisStatusProc        ( WORD, WORD, BYTE*, WORD,WORD));
-CALLBACK (NdisIndicationComplete( WORD, WORD));
-
-BYTE *NdisAllocStack (void);
-void  NdisFreeStack  (BYTE*);
-
-#ifdef __HIGHC__
-  #define RENAME_ASM_SYM(x) pragma Alias(x,"@" #x "")  /* prepend `@' */
-  #define RENAME_C_SYM(x)   pragma Alias(x,"_" #x "")  /* prepend `_' */
-
-  RENAME_ASM_SYM (systemRequestGlue);
-  RENAME_ASM_SYM (requestConfirmGlue);
-  RENAME_ASM_SYM (transmitConfirmGlue);
-  RENAME_ASM_SYM (receiveLookaheadGlue);
-  RENAME_ASM_SYM (indicationCompleteGlue);
-  RENAME_ASM_SYM (receiveChainGlue);
-  RENAME_ASM_SYM (statusGlue);
-  RENAME_ASM_SYM (NdisGetLinkage);
-  RENAME_C_SYM   (NdisSystemRequest);
-  RENAME_C_SYM   (NdisRequestConfirm);
-  RENAME_C_SYM   (NdisTransmitConfirm);
-  RENAME_C_SYM   (NdisReceiveLookahead);
-  RENAME_C_SYM   (NdisIndicationComplete);
-  RENAME_C_SYM   (NdisReceiveChain);
-  RENAME_C_SYM   (NdisStatusProc);
-  RENAME_C_SYM   (NdisAllocStack);
-  RENAME_C_SYM   (NdisFreeStack);
-#endif
-
-#endif
diff --git a/msdos/ndis_0.asm b/msdos/ndis_0.asm
deleted file mode 100644
index ea65e0f..0000000
--- a/msdos/ndis_0.asm
+++ /dev/null
@@ -1,188 +0,0 @@
-PAGE 60,132
-NAME NDIS_0
-
-ifdef DOSX
-  .386
-  _TEXT   SEGMENT PUBLIC DWORD USE16 'CODE'
-  _TEXT   ENDS
-  _DATA   SEGMENT PUBLIC DWORD USE16 'CODE'
-  _DATA   ENDS
-  _TEXT32 SEGMENT PUBLIC BYTE  USE32 'CODE'
-  _TEXT32 ENDS
-  CB_DSEG EQU <CS>                          ; DOSX is tiny-model
-  D_SEG   EQU <_TEXT SEGMENT>
-  D_END   EQU <_TEXT ENDS>
-  ASSUME  CS:_TEXT,DS:_TEXT
-
-  PUSHREGS equ <pushad>
-  POPREGS  equ <popad>
-
-  PUBPROC macro name
-          align 4
-          public @&name
-          @&name label near
-          endm
-else
-  .286
-  _TEXT   SEGMENT PUBLIC DWORD 'CODE'
-  _TEXT   ENDS
-  _DATA   SEGMENT PUBLIC DWORD 'DATA'
-  _DATA   ENDS
-  CB_DSEG EQU <SEG _DATA>                   ; 16bit is small/large model
-  D_SEG   EQU <_DATA SEGMENT>
-  D_END   EQU <_DATA ENDS>
-  ASSUME  CS:_TEXT,DS:_DATA
-
-  PUSHREGS equ <pusha>
-  POPREGS  equ <popa>
-
-  PUBPROC  macro name
-           public _&name
-           _&name label far
-           endm
-endif
-
-;-------------------------------------------
-
-D_SEG
-
-D_END
-
-
-_TEXT SEGMENT
-
-EXTRN _NdisSystemRequest      : near
-EXTRN _NdisRequestConfirm     : near
-EXTRN _NdisTransmitConfirm    : near
-EXTRN _NdisReceiveLookahead   : near
-EXTRN _NdisIndicationComplete : near
-EXTRN _NdisReceiveChain       : near
-EXTRN _NdisStatusProc         : near
-EXTRN _NdisAllocStack         : near
-EXTRN _NdisFreeStack          : near
-
-;
-; *ALL* interrupt threads come through this macro.
-;
-CALLBACK macro callbackProc, argsSize
-
-     pushf
-     PUSHREGS                ;; Save the registers
-
-     push es
-     push ds
-     mov  ax,CB_DSEG         ;; Load DS
-     mov  ds,ax
-     call _NdisAllocStack    ;; Get and install a stack.
-
-     mov  bx,ss              ;; Save off the old stack in other regs
-     mov  cx,sp
-     mov  ss,dx              ;; Install the new one
-     mov  sp,ax
-     push bx                 ;; Save the old one on to the new stack
-     push cx
-     sub  sp,&argsSize       ;; Allocate space for arguments on the stack
-
-     mov  ax,ss              ;; Set up the destination for the move
-     mov  es,ax
-     mov  di,sp
-     mov  ds,bx              ;; Set up the source for the move.
-     mov  si,cx
-     add  si,4+6+32
-
-     mov  cx,&argsSize       ;; Move the arguments to the stack.
-     shr  cx,1
-     cld
-     rep  movsw
-
-     mov  ax,CB_DSEG         ;; Set my data segment again.
-     mov  ds,ax
-
-     call &callbackProc      ;; Call the real callback.
-     pop  di                 ;; Pop off the old stack
-     pop  si
-     mov  bx,ss              ;; Save off the current allocated stack.
-     mov  cx,sp
-     mov  ss,si              ;; Restore the old stack
-     mov  sp,di
-     push ax                 ;; Save the return code
-     push bx                 ;; Free the stack. Push the pointer to it
-     push cx
-     call _NdisFreeStack
-     add  sp,4
-     pop  ax                 ;; Get the return code back
-     add  di,32              ;; Get a pointer to ax on the stack
-     mov  word ptr ss:[di],ax
-     pop  ds
-     pop  es
-
-     POPREGS
-     popf
-endm
-
-;
-; Define all of the callbacks for the NDIS procs.
-;
-
-PUBPROC systemRequestGlue
-CALLBACK _NdisSystemRequest,14
-RETF
-
-PUBPROC requestConfirmGlue
-CALLBACK _NdisRequestConfirm,12
-RETF
-
-PUBPROC transmitConfirmGlue
-CALLBACK _NdisTransmitConfirm,10
-RETF
-
-PUBPROC receiveLookaheadGlue
-CALLBACK _NdisReceiveLookahead,16
-RETF
-
-PUBPROC indicationCompleteGlue
-CALLBACK _NdisIndicationComplete,4
-RETF
-
-PUBPROC receiveChainGlue
-CALLBACK _NdisReceiveChain,16
-RETF
-
-PUBPROC statusGlue
-CALLBACK _NdisStatusProc,12
-RETF
-
-;
-; int FAR NdisGetLinkage (int handle, char *data, int size);
-;
-
-ifdef DOSX
-  PUBPROC NdisGetLinkage
-          push ebx
-          mov ebx, [esp+8]              ; device handle
-          mov eax, 4402h                ; IOCTRL read function
-          mov edx, [esp+12]             ; DS:EDX -> result data
-          mov ecx, [esp+16]             ; ECX = length
-          int 21h
-          pop ebx
-          jc  @fail
-          xor eax, eax
-  @fail:  ret
-
-else
-  PUBPROC NdisGetLinkage
-          enter 0, 0
-          mov bx, [bp+6]
-          mov ax, 4402h
-          mov dx, [bp+8]
-          mov cx, [bp+12]
-          int 21h
-          jc  @fail
-          xor ax, ax
-  @fail:  leave
-          retf
-endif
-
-ENDS
-
-END
diff --git a/msdos/readme.dos b/msdos/readme.dos
index 990a2e8..b95483f 100644
--- a/msdos/readme.dos
+++ b/msdos/readme.dos
@@ -127,7 +127,7 @@
 
    But linking the library with `tcpdump' is the ultimate test. DOS/djgpp
    should now hopefully be a supported target. Get the sources at:
-     http://www.tcpdump.org/
+     https://www.tcpdump.org/
    or
      https://github.com/the-tcpdump-group/tcpdump/
 
diff --git a/nametoaddr.c b/nametoaddr.c
index 71280b3..194ff45 100644
--- a/nametoaddr.c
+++ b/nametoaddr.c
@@ -23,7 +23,7 @@
  */
 
 #ifdef HAVE_CONFIG_H
-#include "config.h"
+#include <config.h>
 #endif
 
 #ifdef DECNETLIB
@@ -32,62 +32,99 @@
 #endif
 
 #ifdef _WIN32
-#include <pcap-stdinc.h>
+  #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.  pcap-stdinc.h
- * includes Ws2tcpip.h, so we don't need to include it ourselves.
- */
-#include <Wspiapi.h>
-#endif
-
+  #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 <sys/param.h>
-#include <sys/types.h>				/* concession to AIX */
-#include <sys/socket.h>
-#include <sys/time.h>
+  #include <netinet/in.h>
 
-#include <netinet/in.h>
-#endif /* _WIN32 */
+  #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() */
 
-#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>
+    #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>
@@ -111,11 +148,10 @@
 #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)
@@ -141,7 +177,6 @@
 		return 0;
 }
 
-#ifdef INET6
 struct addrinfo *
 pcap_nametoaddrinfo(const char *name)
 {
@@ -158,23 +193,17 @@
 	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
-	struct netent *np;
-
-	if ((np = getnetbyname(name)) != NULL)
-		return np->n_net;
-	else
-		return 0;
-#else
+#ifdef _WIN32
 	/*
 	 * There's no "getnetbyname()" on Windows.
 	 *
@@ -188,7 +217,66 @@
 	 * of *UN*X* machines.)
 	 */
 	return 0;
-#endif
+#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;
+
+	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;
+	}
+  #elif defined(HAVE_SOLARIS_IRIX_GETNETBYNAME_R)
+	/*
+	 * We have Solaris's and IRIX's reentrant getnetbyname_r().
+	 */
+	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 */
 }
 
 /*
@@ -199,20 +287,113 @@
 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;
@@ -291,12 +472,62 @@
 	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
@@ -316,7 +547,12 @@
  * 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 },
@@ -380,17 +616,16 @@
 	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
@@ -401,7 +636,7 @@
 
 	*addr = 0;
 	len = 0;
-	while (1) {
+	for (;;) {
 		n = 0;
 		while (*s && *s != '.')
 			n = n * 10 + *s++ - '0';
@@ -449,7 +684,7 @@
 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)
@@ -470,7 +705,11 @@
 }
 
 #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)
 {
@@ -502,17 +741,10 @@
 	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)
 {
@@ -529,10 +761,13 @@
 }
 #endif
 
+/*
+ * XXX - not guaranteed to be thread-safe!
+ */
 int
+#ifdef	DECNETLIB
 __pcap_nametodnaddr(const char *name, u_short *res)
 {
-#ifdef	DECNETLIB
 	struct nodeent *getnodebyname();
 	struct nodeent *nep;
 
@@ -543,6 +778,8 @@
 	memcpy((char *)res, (char *)nep->n_addr, sizeof(unsigned short));
 	return(1);
 #else
+__pcap_nametodnaddr(const char *name _U_, u_short *res _U_)
+{
 	return(0);
 #endif
 }
diff --git a/net b/net
deleted file mode 120000
index b3eaca9..0000000
--- a/net
+++ /dev/null
@@ -1 +0,0 @@
-./bpf/net
\ No newline at end of file
diff --git a/nomkdep b/nomkdep
new file mode 100755
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
diff --git a/optimize.c b/optimize.c
index 19980dc..7c6424b 100644
--- a/optimize.c
+++ b/optimize.c
@@ -18,26 +18,14 @@
  * 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>
@@ -49,39 +37,149 @@
 #include "pcap-int.h"
 
 #include "gencode.h"
+#include "optimize.h"
 
 #ifdef HAVE_OS_PROTO_H
 #include "os-proto.h"
 #endif
 
 #ifdef BDEBUG
-int pcap_optimizer_debug;
-#endif
-
-#if defined(MSDOS) && !defined(__DJGPP__)
-extern int _w32_ffs (int mask);
-#define ffs _w32_ffs
-#endif
-
 /*
- * So is the check for _MSC_VER done because MinGW has this?
+ * 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.
  */
-#if defined(_WIN32) && defined (_MSC_VER)
+static int pcap_optimizer_debug;
+
 /*
- * ffs -- vax ffs instruction
+ * Routine to set that flag.
  *
- * XXX - with versions of VS that have it, use _BitScanForward()?
+ * 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
+
+/*
+ * 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
+
+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
-ffs(int mask)
+lowest_set_bit(int mask)
 {
-	int bit;
+	unsigned int v = (unsigned int)mask;
 
-	if (mask == 0)
-		return(0);
-	for (bit = 1; !(mask & 1); bit++)
-		mask >>= 1;
-	return(bit);
+	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
 
@@ -127,7 +225,7 @@
 	bpf_int32 const_val;
 };
 
-struct _opt_state {
+typedef struct {
 	/*
 	 * A flag to indicate that further optimization is needed.
 	 * Iterative passes are continued until a given pass yields no
@@ -210,7 +308,7 @@
 	struct vmapinfo *vmap;
 	struct valnode *vnode_base;
 	struct valnode *next_vnode;
-};
+} opt_state_t;
 
 typedef struct {
 	/*
@@ -290,7 +388,7 @@
 	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 = opt_state->nodewords; --i >= 0;)
 		root->dom[i] = 0;
@@ -330,7 +428,7 @@
 
 	x = opt_state->all_edge_sets;
 	for (i = opt_state->n_edges * opt_state->edgewords; --i >= 0; )
-		x[i] = ~0;
+		x[i] = 0xFFFFFFFFU;
 
 	/* root->level is the highest level no found. */
 	memset(root->et.edom, 0, opt_state->edgewords * sizeof(*(uset)0));
@@ -563,7 +661,7 @@
 	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 = opt_state->hashtbl[hash]; p; p = p->next)
@@ -590,7 +688,7 @@
 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;
@@ -601,7 +699,7 @@
  * (Unary operators are handled elsewhere.)
  */
 static void
-fold_op(compiler_state_t *cstate, struct icode *ic, opt_state_t *opt_state,
+fold_op(compiler_state_t *cstate, opt_state_t *opt_state,
     struct stmt *s, int v0, int v1)
 {
 	bpf_u_int32 a, b;
@@ -943,7 +1041,7 @@
  * evaluation and code transformations weren't folded together.
  */
 static void
-opt_stmt(compiler_state_t *cstate, struct icode *ic, opt_state_t *opt_state,
+opt_stmt(compiler_state_t *cstate, opt_state_t *opt_state,
     struct stmt *s, int val[], int alter)
 {
 	int op;
@@ -1032,7 +1130,7 @@
 				}
 			}
 			if (opt_state->vmap[val[A_ATOM]].is_const) {
-				fold_op(cstate, ic, opt_state, s, val[A_ATOM], K(s->k));
+				fold_op(cstate, opt_state, s, val[A_ATOM], K(s->k));
 				val[A_ATOM] = K(s->k);
 				break;
 			}
@@ -1053,7 +1151,7 @@
 		op = BPF_OP(s->code);
 		if (alter && opt_state->vmap[val[X_ATOM]].is_const) {
 			if (opt_state->vmap[val[A_ATOM]].is_const) {
-				fold_op(cstate, ic, opt_state, s, val[A_ATOM], val[X_ATOM]);
+				fold_op(cstate, opt_state, s, val[A_ATOM], val[X_ATOM]);
 				val[A_ATOM] = K(s->k);
 			}
 			else {
@@ -1177,7 +1275,7 @@
 }
 
 static void
-opt_blk(compiler_state_t *cstate, struct icode *ic, opt_state_t *opt_state,
+opt_blk(compiler_state_t *cstate, opt_state_t *opt_state,
     struct block *b, int do_stmts)
 {
 	struct slist *s;
@@ -1228,7 +1326,7 @@
 	aval = b->val[A_ATOM];
 	xval = b->val[X_ATOM];
 	for (s = b->stmts; s; s = s->next)
-		opt_stmt(cstate, ic, opt_state, &s->s, b->val, do_stmts);
+		opt_stmt(cstate, opt_state, &s->s, b->val, do_stmts);
 
 	/*
 	 * This is a special case: if we don't use anything from this
@@ -1254,8 +1352,9 @@
 	 * 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;
@@ -1380,7 +1479,7 @@
 		register bpf_u_int32 x = ep->edom[i];
 
 		while (x != 0) {
-			k = ffs(x) - 1;
+			k = lowest_set_bit(x);
 			x &=~ (1 << k);
 			k += i * BITS_PER_WORD;
 
@@ -1431,7 +1530,7 @@
 		diffp = &JF(b->in_edges->pred);
 
 	at_top = 1;
-	while (1) {
+	for (;;) {
 		if (*diffp == 0)
 			return;
 
@@ -1448,7 +1547,7 @@
 		at_top = 0;
 	}
 	samep = &JF(*diffp);
-	while (1) {
+	for (;;) {
 		if (*samep == 0)
 			return;
 
@@ -1522,7 +1621,7 @@
 		diffp = &JF(b->in_edges->pred);
 
 	at_top = 1;
-	while (1) {
+	for (;;) {
 		if (*diffp == 0)
 			return;
 
@@ -1539,7 +1638,7 @@
 		at_top = 0;
 	}
 	samep = &JT(*diffp);
-	while (1) {
+	for (;;) {
 		if (*samep == 0)
 			return;
 
@@ -1600,7 +1699,7 @@
 	find_inedges(opt_state, ic->root);
 	for (i = maxlevel; i >= 0; --i)
 		for (p = opt_state->levels[i]; p; p = p->link)
-			opt_blk(cstate, ic, opt_state, p, do_stmts);
+			opt_blk(cstate, opt_state, p, do_stmts);
 
 	if (do_stmts)
 		/*
@@ -1683,7 +1782,7 @@
 {
 
 #ifdef BDEBUG
-	if (pcap_optimizer_debug > 1) {
+	if (pcap_optimizer_debug > 1 || pcap_print_dot_graph) {
 		printf("opt_loop(root, %d) begin\n", do_stmts);
 		opt_dump(cstate, ic);
 	}
@@ -1697,7 +1796,7 @@
 		find_edom(opt_state, ic->root);
 		opt_blks(cstate, opt_state, ic, do_stmts);
 #ifdef BDEBUG
-		if (pcap_optimizer_debug > 1) {
+		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(cstate, ic);
 		}
@@ -1718,14 +1817,14 @@
 	opt_loop(cstate, &opt_state, ic, 1);
 	intern_blocks(&opt_state, ic);
 #ifdef BDEBUG
-	if (pcap_optimizer_debug > 1) {
+	if (pcap_optimizer_debug > 1 || pcap_print_dot_graph) {
 		printf("after intern_blocks()\n");
 		opt_dump(cstate, ic);
 	}
 #endif
 	opt_root(&ic->root);
 #ifdef BDEBUG
-	if (pcap_optimizer_debug > 1) {
+	if (pcap_optimizer_debug > 1 || pcap_print_dot_graph) {
 		printf("after opt_root()\n");
 		opt_dump(cstate, ic);
 	}
@@ -1763,7 +1862,7 @@
 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)
@@ -2013,7 +2112,7 @@
  * and expect it to provide meaningful information.
  */
 #ifdef BDEBUG
-int bids[1000];
+int bids[NBIDS];
 #endif
 
 /*
@@ -2030,7 +2129,7 @@
 	struct slist *src;
 	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(ic, p))
@@ -2088,7 +2187,7 @@
 	    {
 		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,
@@ -2108,7 +2207,11 @@
 					/*NOTREACHED*/
 				}
 
-				dst->jt = i - off - 1;
+				if (i - off - 1 >= 256) {
+					bpf_error(cstate, ljerr, "out-of-range jump", off);
+					/*NOTREACHED*/
+				}
+				dst->jt = (u_char)(i - off - 1);
 				jt++;
 			}
 			if (offset[i] == src->s.jf) {
@@ -2116,7 +2219,11 @@
 					bpf_error(cstate, ljerr, "multiple matches", off);
 					/*NOTREACHED*/
 				}
-				dst->jf = i - off - 1;
+				if (i - off - 1 >= 256) {
+					bpf_error(cstate, ljerr, "out-of-range jump", off);
+					/*NOTREACHED*/
+				}
+				dst->jf = (u_char)(i - off - 1);
 				jf++;
 			}
 		}
@@ -2133,7 +2240,8 @@
 		free(offset);
 
 #ifdef BDEBUG
-	bids[dst - conv_state->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;
@@ -2148,13 +2256,17 @@
 			return(0);
 		    }
 		    /* branch if T to following jump */
-		    dst->jt = extrajmps;
+		    if (extrajmps >= 256) {
+			bpf_error(cstate, "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 */
@@ -2165,13 +2277,17 @@
 		    }
 		    /* branch if F to following jump */
 		    /* if two jumps are inserted, F goes to second one */
-		    dst->jf = extrajmps;
+		    if (extrajmps >= 256) {
+			bpf_error(cstate, "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);
 }
@@ -2207,7 +2323,7 @@
 	 * Loop doing convert_code_r() until no branches remain
 	 * with too-large offsets.
 	 */
-	while (1) {
+	for (;;) {
 	    unMarkAll(ic);
 	    n = *lenp = count_stmts(ic, root);
 
@@ -2258,8 +2374,8 @@
 	p->fcode.bf_len = fp->bf_len;
 	p->fcode.bf_insns = (struct bpf_insn *)malloc(prog_size);
 	if (p->fcode.bf_insns == NULL) {
-		pcap_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);
@@ -2287,7 +2403,7 @@
 	}
 	fprintf(out, "\" tooltip=\"");
 	for (i = 0; i < BPF_MEMWORDS; i++)
-		if (block->val[i] != 0)
+		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]);
@@ -2346,10 +2462,8 @@
 	f.bf_insns = icode_to_fcode(cstate, ic, ic->root, &f.bf_len);
 
 	fprintf(out, "digraph BPF {\n");
-	ic->cur_mark = 0;
 	unMarkAll(ic);
 	dot_dump_node(ic, ic->root, &f, out);
-	ic->cur_mark = 0;
 	unMarkAll(ic);
 	dot_dump_edge(ic, ic->root, out);
 	fprintf(out, "}\n");
@@ -2372,11 +2486,11 @@
 static void
 opt_dump(compiler_state_t *cstate, struct icode *ic)
 {
-	/* if optimizer debugging is enabled, output DOT graph
-	 * `pcap_optimizer_debug=4' is equivalent to -dddd to follow -d/-dd/-ddd
-	 * convention in tcpdump command line
+	/*
+	 * If the CFG, in DOT format, is requested, output it rather than
+	 * the code that would be generated from that graph.
 	 */
-	if (pcap_optimizer_debug > 3)
+	if (pcap_print_dot_graph)
 		dot_dump(cstate, ic);
 	else
 		plain_dump(cstate, ic);
diff --git a/sf-pcap-ng.h b/optimize.h
similarity index 79%
copy from sf-pcap-ng.h
copy to optimize.h
index 3c93498..56b31f4 100644
--- a/sf-pcap-ng.h
+++ b/optimize.h
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1993, 1994, 1995, 1996, 1997
+ * 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
@@ -17,16 +17,12 @@
  * 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.
- *
- * sf-pcap-ng.h - pcap-ng-file-format-specific routines
- *
- * Used to read pcap-ng savefiles.
  */
 
-#ifndef sf_pcap_ng_h
-#define	sf_pcap_ng_h
-
-extern pcap_t *pcap_ng_check_header(bpf_u_int32 magic, FILE *fp,
-    u_int precision, char *errbuf, int *err);
-
+/*
+ * Some stuff for use when debugging the optimizer.
+ */
+#ifdef BDEBUG
+#define NBIDS	1000
+extern int bids[NBIDS];
 #endif
diff --git a/pcap-bpf.c b/pcap-bpf.c
index b765904..6ce383b 100644
--- a/pcap-bpf.c
+++ b/pcap-bpf.c
@@ -20,20 +20,17 @@
  */
 
 #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.
@@ -57,10 +54,6 @@
 #include <dirent.h>
 #endif
 
-#ifdef HAVE_ZEROCOPY_BPF
-#include <machine/atomic.h>
-#endif
-
 #include <net/if.h>
 
 #ifdef _AIX
@@ -82,6 +75,16 @@
 #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>
@@ -121,7 +124,7 @@
 #include <string.h>
 #include <unistd.h>
 
-#ifdef HAVE_NET_IF_MEDIA_H
+#ifdef SIOCGIFMEDIA
 # include <net/if_media.h>
 #endif
 
@@ -224,8 +227,9 @@
 #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
@@ -252,7 +256,7 @@
  * 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;
@@ -260,11 +264,11 @@
 	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;
@@ -274,7 +278,7 @@
 		return (0);
 	}
 #endif
-	return (pcap_setnonblock_fd(p, nonblock, errbuf));
+	return (pcap_setnonblock_fd(p, nonblock));
 }
 
 #ifdef HAVE_ZEROCOPY_BPF
@@ -365,8 +369,8 @@
 			if (data)
 				return (data);
 			if (ioctl(p->fd, BIOCROTZBUF, &bz) < 0) {
-				(void) pcap_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));
@@ -393,8 +397,8 @@
 			}
 			return (0);
 		} else if (r < 0) {
-			(void) pcap_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);
 		}
 	}
@@ -412,8 +416,8 @@
 	 * data.
 	 */
 	if (ioctl(p->fd, BIOCROTZBUF, &bz) < 0) {
-		(void) pcap_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));
@@ -455,8 +459,8 @@
 	p->tstamp_precision_count = 2;
 	p->tstamp_precision_list = malloc(2 * sizeof(u_int));
 	if (p->tstamp_precision_list == NULL) {
-		snprintf(ebuf, PCAP_ERRBUF_SIZE, "malloc: %s",
-		    pcap_strerror(errno));
+		pcap_fmt_errmsg_for_errno(ebuf, PCAP_ERRBUF_SIZE, errno,
+		    "malloc");
 		free(p);
 		return (NULL);
 	}
@@ -473,13 +477,11 @@
 static int
 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
 	/*
@@ -491,40 +493,55 @@
 		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;
-		pcap_snprintf(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)pcap_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
@@ -561,9 +578,8 @@
 			 * if any.
 			 */
 			fd = PCAP_ERROR_PERM_DENIED;
-			pcap_snprintf(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:
@@ -571,13 +587,11 @@
 			 * Some other problem.
 			 */
 			fd = PCAP_ERROR;
-			pcap_snprintf(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);
 }
@@ -629,8 +643,8 @@
 			return (PCAP_ERROR_IFACE_NOT_UP);
 
 		default:
-			pcap_snprintf(errbuf, PCAP_ERRBUF_SIZE,
-			    "BIOCSETIF: %s: %s", name, pcap_strerror(errno));
+			pcap_fmt_errmsg_for_errno(errbuf, PCAP_ERRBUF_SIZE,
+			    errno, "BIOCSETIF: %s", name);
 			close(fd);
 			return (PCAP_ERROR);
 		}
@@ -653,14 +667,14 @@
 
 		bdlp->bfl_list = (u_int *) malloc(sizeof(u_int) * (bdlp->bfl_len + 1));
 		if (bdlp->bfl_list == NULL) {
-			(void)pcap_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)pcap_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);
 		}
@@ -714,8 +728,8 @@
 		 * this device"; don't treat it as an error.
 		 */
 		if (errno != EINVAL) {
-			(void)pcap_snprintf(ebuf, PCAP_ERRBUF_SIZE,
-			    "BIOCGDLTLIST: %s", pcap_strerror(errno));
+			pcap_fmt_errmsg_for_errno(ebuf, PCAP_ERRBUF_SIZE,
+			    errno, "BIOCGDLTLIST");
 			return (PCAP_ERROR);
 		}
 	}
@@ -735,7 +749,7 @@
 #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.
 	 *
@@ -781,8 +795,8 @@
 		}
 		fd = socket(AF_INET, SOCK_DGRAM, 0);
 		if (fd == -1) {
-			(void)pcap_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));
@@ -836,9 +850,8 @@
 			return (PCAP_ERROR_IFACE_NOT_UP);
 
 		default:
-			pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
-			    "BIOCSETIF: %s: %s",
-			    p->opt.device, pcap_strerror(errno));
+			pcap_fmt_errmsg_for_errno(p->errbuf, PCAP_ERRBUF_SIZE,
+			    errno, "BIOCSETIF: %s", p->opt.device);
 			close(fd);
 			return (PCAP_ERROR);
 		}
@@ -900,8 +913,8 @@
 	 * by libpcap, and thus not yet seen by the application.
 	 */
 	if (ioctl(p->fd, BIOCGSTATS, (caddr_t)&s) < 0) {
-		pcap_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);
 	}
 
@@ -1028,8 +1041,8 @@
 				/* fall through */
 #endif
 			}
-			pcap_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 = (u_char *)p->buffer;
@@ -1182,13 +1195,13 @@
 #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
@@ -1197,14 +1210,13 @@
 		 *	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)pcap_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);
 		}
 
@@ -1215,8 +1227,8 @@
 	}
 #endif /* __APPLE__ */
 	if (ret == -1) {
-		pcap_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);
@@ -1304,8 +1316,8 @@
 
 	major = genmajor(BPF_NAME);
 	if (major == -1) {
-		pcap_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);
 	}
@@ -1314,9 +1326,8 @@
 	if (!minors) {
 		minors = genminor("bpf", major, 0, BPF_MINORS, 1, 1);
 		if (!minors) {
-			pcap_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);
 		}
@@ -1327,20 +1338,19 @@
 
 	rc = stat(BPF_NODE "0", &sbuf);
 	if (rc == -1 && errno != ENOENT) {
-		pcap_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) {
-				pcap_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);
 			}
 		}
@@ -1349,14 +1359,13 @@
 	/* Check if the driver is loaded */
 	memset(&cfg_ld, 0x0, sizeof(cfg_ld));
 	cfg_ld.path = buf;
-	sprintf(cfg_ld.path, "%s/%s", DRIVER_PATH, BPF_NAME);
+	pcap_snprintf(cfg_ld.path, sizeof(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) {
-			pcap_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);
 		}
 	}
@@ -1369,9 +1378,8 @@
 	for (i = 0; i < BPF_MINORS; i++) {
 		cfg_bpf.devno = domakedev(major, i);
 		if (sysconfig(SYS_CFGKMOD, (void *)&cfg_km, sizeof(cfg_km)) == -1) {
-			pcap_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);
 		}
 	}
@@ -1535,9 +1543,10 @@
 					 * exist.
 					 */
 					err = PCAP_ERROR_NO_SUCH_DEVICE;
-					pcap_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
@@ -1559,9 +1568,9 @@
 				 * just report "no such device".
 				 */
 				err = PCAP_ERROR_NO_SUCH_DEVICE;
-				pcap_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);
 		}
@@ -1569,8 +1578,8 @@
 		/*
 		 * No such device.
 		 */
-		pcap_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) {
 		/*
@@ -1586,8 +1595,8 @@
 		 * Some other error; fill in the error string, and
 		 * return PCAP_ERROR.
 		 */
-		pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "BIOCSETIF: %s: %s",
-		    p->opt.device, pcap_strerror(errno));
+		pcap_fmt_errmsg_for_errno(p->errbuf, PCAP_ERRBUF_SIZE,
+		    errno, "BIOCSETIF: %s", p->opt.device);
 		return (PCAP_ERROR);
 	}
 }
@@ -1659,8 +1668,8 @@
 	p->fd = fd;
 
 	if (ioctl(fd, BIOCVERSION, (caddr_t)&bv) < 0) {
-		pcap_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;
 	}
@@ -1672,13 +1681,24 @@
 		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)
 	/*
 	 * Retrieve the zoneid of the zone we are currently executing in.
 	 */
 	if ((ifr.lifr_zoneid = getzoneid()) == -1) {
-		pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "getzoneid(): %s",
-		    pcap_strerror(errno));
+		pcap_fmt_errmsg_for_errno(p->errbuf, PCAP_ERRBUF_SIZE,
+		    errno, "getzoneid()");
 		status = PCAP_ERROR;
 		goto bad;
 	}
@@ -1704,16 +1724,15 @@
 		(void) strlcpy(path_zname, p->opt.device, znamelen + 1);
 		ifr.lifr_zoneid = getzoneidbyname(path_zname);
 		if (ifr.lifr_zoneid == -1) {
-			pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
-			    "getzoneidbyname(%s): %s", path_zname,
-			pcap_strerror(errno));
+			pcap_fmt_errmsg_for_errno(p->errbuf, PCAP_ERRBUF_SIZE,
+			    errno, "getzoneidbyname(%s)", path_zname);
 			status = PCAP_ERROR;
 			goto bad;
 		}
 		lnamep = strdup(zonesep + 1);
 		if (lnamep == NULL) {
-			pcap_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;
 		}
@@ -1724,8 +1743,8 @@
 
 	pb->device = strdup(p->opt.device);
 	if (pb->device == NULL) {
-		pcap_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;
 	}
@@ -1779,10 +1798,10 @@
 							 * exist.
 							 */
 							status = PCAP_ERROR_NO_SUCH_DEVICE;
-							pcap_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);
@@ -1793,18 +1812,17 @@
 						 * report "no such device".
 						 */
 						status = PCAP_ERROR_NO_SUCH_DEVICE;
-						pcap_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.device) + 2);
 				if (wltdev == NULL) {
-					(void)pcap_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;
 				}
@@ -1844,9 +1862,9 @@
 			 */
 			s = socket(AF_LOCAL, SOCK_DGRAM, 0);
 			if (s < 0) {
-				pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
-				    "Can't open socket: %s",
-				    pcap_strerror(errno));
+				pcap_fmt_errmsg_for_errno(p->errbuf,
+				    PCAP_ERRBUF_SIZE, errno,
+				    "Can't open socket");
 				status = PCAP_ERROR;
 				goto bad;
 			}
@@ -1877,9 +1895,10 @@
 					    "Invalid USB bus interface %s",
 					    p->opt.device);
 				} else {
-					pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
-					    "Can't create interface for %s: %s",
-					    p->opt.device, pcap_strerror(errno));
+					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;
@@ -1922,8 +1941,8 @@
 		 * size.
 		 */
 		if (ioctl(fd, BIOCGETZMAX, (caddr_t)&zbufmax) < 0) {
-			pcap_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;
 		}
@@ -1949,8 +1968,8 @@
 		pb->zbuf2 = mmap(NULL, pb->zbufsize, PROT_READ | PROT_WRITE,
 		    MAP_ANON, -1, 0);
 		if (pb->zbuf1 == MAP_FAILED || pb->zbuf2 == MAP_FAILED) {
-			pcap_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;
 		}
@@ -1959,15 +1978,15 @@
 		bz.bz_bufb = pb->zbuf2;
 		bz.bz_buflen = pb->zbufsize;
 		if (ioctl(fd, BIOCSETZBUF, (caddr_t)&bz) < 0) {
-			pcap_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.device, ifnamsiz);
 		if (ioctl(fd, BIOCSETIF, (caddr_t)&ifr) < 0) {
-			pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "BIOCSETIF: %s: %s",
-			    p->opt.device, pcap_strerror(errno));
+			pcap_fmt_errmsg_for_errno(p->errbuf, PCAP_ERRBUF_SIZE,
+			    errno, "BIOCSETIF: %s", p->opt.device);
 			status = PCAP_ERROR;
 			goto bad;
 		}
@@ -1985,9 +2004,9 @@
 			 */
 			if (ioctl(fd, BIOCSBLEN,
 			    (caddr_t)&p->opt.buffer_size) < 0) {
-				pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
-				    "BIOCSBLEN: %s: %s", p->opt.device,
-				    pcap_strerror(errno));
+				pcap_fmt_errmsg_for_errno(p->errbuf,
+				    PCAP_ERRBUF_SIZE, errno,
+				    "BIOCSBLEN: %s", p->opt.device);
 				status = PCAP_ERROR;
 				goto bad;
 			}
@@ -2054,8 +2073,8 @@
 
 	/* Get the data link layer type. */
 	if (ioctl(fd, BIOCGDLT, (caddr_t)&v) < 0) {
-		pcap_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;
 	}
@@ -2299,8 +2318,8 @@
 	 * BSDs - check CVS log for "bpf.c"?
 	 */
 	if (ioctl(fd, BIOCSHDRCMPLT, &spoof_eth_src) == -1) {
-		(void)pcap_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;
 	}
@@ -2341,8 +2360,8 @@
 			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) {
-				pcap_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;
 			}
@@ -2351,8 +2370,8 @@
 			to.tv_sec = p->opt.timeout / 1000;
 			to.tv_usec = (p->opt.timeout * 1000) % 1000000;
 			if (ioctl(p->fd, BIOCSRTIMEOUT, (caddr_t)&to) < 0) {
-				pcap_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;
 			}
@@ -2386,8 +2405,8 @@
 #endif /* _AIX */
 		v = 1;
 		if (ioctl(p->fd, BIOCIMMEDIATE, &v) < 0) {
-			pcap_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;
 		}
@@ -2408,8 +2427,8 @@
 	if (p->opt.promisc) {
 		/* set promiscuous mode, just warn if it fails */
 		if (ioctl(p->fd, BIOCPROMISC, NULL) < 0) {
-			pcap_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;
 		}
 	}
@@ -2417,16 +2436,16 @@
 #ifdef BIOCSTSTAMP
 	v = BPF_T_BINTIME;
 	if (ioctl(p->fd, BIOCSTSTAMP, &v) < 0) {
-		snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "BIOCSTSTAMP: %s",
-		    pcap_strerror(errno));
+		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) {
-		pcap_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;
 	}
@@ -2436,8 +2455,8 @@
 #endif
 	p->buffer = malloc(p->bufsize);
 	if (p->buffer == NULL) {
-		pcap_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;
 	}
@@ -2467,8 +2486,8 @@
 	total_prog.bf_len = 1;
 	total_prog.bf_insns = &total_insn;
 	if (ioctl(p->fd, BIOCSETF, (caddr_t)&total_prog) < 0) {
-		pcap_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;
 	}
@@ -2550,6 +2569,44 @@
 	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) {
 		/*
@@ -2584,7 +2641,18 @@
 
 #if defined(__FreeBSD__) && defined(SIOCIFCREATE2)
 static int
-finddevs_usb(pcap_if_t **alldevsp, char *errbuf)
+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;
@@ -2624,7 +2692,6 @@
 	while ((usbitem = readdir(usbdir)) != NULL) {
 		char *p;
 		size_t busnumlen;
-		int err;
 
 		if (strcmp(usbitem->d_name, ".") == 0 ||
 		    strcmp(usbitem->d_name, "..") == 0) {
@@ -2640,11 +2707,18 @@
 		memcpy(name, usbus_prefix, USBUS_PREFIX_LEN);
 		memcpy(name + USBUS_PREFIX_LEN, usbitem->d_name, busnumlen);
 		*(name + USBUS_PREFIX_LEN + busnumlen) = '\0';
-		err = pcap_add_if(alldevsp, name, PCAP_IF_UP, NULL, errbuf);
-		if (err != 0) {
+		/*
+		 * 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 (err);
+			return (PCAP_ERROR);
 		}
 	}
 	free(name);
@@ -2653,17 +2727,116 @@
 }
 #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) {
+			/*
+			 * Not supported, so we can't provide any
+			 * additional information.  Assume that
+			 * this means that "connected" vs.
+			 * "disconnected" doesn't apply.
+			 */
+			*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(alldevsp, errbuf, check_bpf_bindable) == -1)
+	if (pcap_findalldevs_interfaces(devlistp, errbuf, check_bpf_bindable,
+	    get_if_flags) == -1)
 		return (-1);	/* failure */
 
 #if defined(__FreeBSD__) && defined(SIOCIFCREATE2)
-	if (finddevs_usb(alldevsp, errbuf) == -1)
+	if (finddevs_usb(devlistp, errbuf) == -1)
 		return (-1);
 #endif
 
@@ -2684,8 +2857,8 @@
 
 	sock = socket(AF_INET, SOCK_DGRAM, 0);
 	if (sock == -1) {
-		pcap_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);
 	}
 
@@ -2716,8 +2889,8 @@
 			return (PCAP_ERROR_RFMON_NOTSUP);
 
 		default:
-			pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
-			    "SIOCGIFMEDIA 1: %s", pcap_strerror(errno));
+			pcap_fmt_errmsg_for_errno(p->errbuf, PCAP_ERRBUF_SIZE,
+			    errno, "SIOCGIFMEDIA 1");
 			close(sock);
 			return (PCAP_ERROR);
 		}
@@ -2736,15 +2909,15 @@
 	 */
 	media_list = malloc(req.ifm_count * sizeof(*media_list));
 	if (media_list == NULL) {
-		pcap_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) {
-		pcap_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);
@@ -2804,8 +2977,8 @@
 			    sizeof(ifr.ifr_name));
 			ifr.ifr_media = req.ifm_current | IFM_IEEE80211_MONITOR;
 			if (ioctl(sock, SIOCSIFMEDIA, &ifr) == -1) {
-				pcap_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);
 			}
@@ -3029,8 +3202,8 @@
 	 * some kernels.
 	 */
 	if (errno != EINVAL) {
-		pcap_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);
 	}
 
@@ -3058,11 +3231,10 @@
 	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) pcap_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);
@@ -3080,10 +3252,9 @@
 
 	seesent = (d == PCAP_D_INOUT);
 	if (ioctl(p->fd, BIOCSSEESENT, &seesent) == -1) {
-		(void) pcap_snprintf(p->errbuf, sizeof(p->errbuf),
-		    "Cannot set direction to %s: %s",
-		        (d == PCAP_D_INOUT) ? "PCAP_D_INOUT" : "PCAP_D_IN",
-			strerror(errno));
+		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);
@@ -3099,10 +3270,23 @@
 {
 #ifdef BIOCSDLT
 	if (ioctl(p->fd, BIOCSDLT, &dlt) == -1) {
-		(void) pcap_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);
 }
+
+/*
+ * 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
+}
diff --git a/pcap-bt-linux.c b/pcap-bt-linux.c
index 4452fe4..07ed1c7 100644
--- a/pcap-bt-linux.c
+++ b/pcap-bt-linux.c
@@ -33,17 +33,13 @@
  */
 
 #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>
@@ -74,7 +70,7 @@
 };
 
 int
-bt_findalldevs(pcap_if_t **alldevsp, char *err_str)
+bt_findalldevs(pcap_if_list_t *devlistp, char *err_str)
 {
 	struct hci_dev_list_req *dev_list;
 	struct hci_dev_req *dev_req;
@@ -87,8 +83,8 @@
 		/* if bluetooth is not supported this this is not fatal*/
 		if (errno == EAFNOSUPPORT)
 			return 0;
-		pcap_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;
 	}
 
@@ -105,9 +101,8 @@
 
 	if (ioctl(sock, HCIGETDEVLIST, (void *) dev_list) < 0)
 	{
-		pcap_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;
 	}
@@ -119,13 +114,19 @@
 		pcap_snprintf(dev_name, 20, BT_IFACE"%d", dev_req->dev_id);
 		pcap_snprintf(dev_descr, 30, "Bluetooth adapter number %d", i);
 
-		if (pcap_add_if(alldevsp, dev_name, 0,
-		       dev_descr, err_str) < 0)
+		/*
+		 * 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:
@@ -198,6 +199,17 @@
 		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 = BT_CTRL_SIZE+sizeof(pcap_bluetooth_h4_header)+handle->snapshot;
 	handle->linktype = DLT_BLUETOOTH_HCI_H4_WITH_PHDR;
@@ -215,29 +227,29 @@
 	/* Create HCI socket */
 	handle->fd = socket(AF_BLUETOOTH, SOCK_RAW, BTPROTO_HCI);
 	if (handle->fd < 0) {
-		pcap_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) {
-		pcap_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) {
-		pcap_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) {
-		pcap_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;
 	}
 
@@ -247,8 +259,8 @@
 	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) {
-		pcap_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;
 	}
 
@@ -256,13 +268,12 @@
 	/* 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) {
-		pcap_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;
 	}
 
@@ -281,8 +292,8 @@
 		if (setsockopt(handle->fd, SOL_SOCKET, SO_RCVBUF,
 		    &handle->opt.buffer_size,
 		    sizeof(handle->opt.buffer_size)) == -1) {
-			pcap_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;
 		}
 	}
@@ -296,7 +307,7 @@
 }
 
 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;
@@ -329,8 +340,8 @@
 	} while ((ret == -1) && (errno == EINTR));
 
 	if (ret < 0) {
-		pcap_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;
 	}
 
@@ -366,7 +377,7 @@
 }
 
 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_)
 {
 	pcap_snprintf(handle->errbuf, PCAP_ERRBUF_SIZE, "inject not supported on "
     		"bluetooth devices");
@@ -389,8 +400,8 @@
 	} while ((ret == -1) && (errno == EINTR));
 
 	if (ret < 0) {
-		pcap_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);
 
 	}
diff --git a/pcap-bt-linux.h b/pcap-bt-linux.h
index e098654..163bd34 100644
--- a/pcap-bt-linux.h
+++ b/pcap-bt-linux.h
@@ -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);
diff --git a/pcap-bt-monitor-linux.c b/pcap-bt-monitor-linux.c
index 521d6d5..c222c10 100644
--- a/pcap-bt-monitor-linux.c
+++ b/pcap-bt-monitor-linux.c
@@ -30,7 +30,7 @@
  */
 
 #ifdef HAVE_CONFIG_H
-#include "config.h"
+#include <config.h>
 #endif
 
 #include <errno.h>
@@ -60,12 +60,21 @@
 } __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;
     }
@@ -110,8 +119,8 @@
     } while ((ret == -1) && (errno == EINTR));
 
     if (ret < 0) {
-        pcap_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;
     }
 
@@ -173,6 +182,17 @@
         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 (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;
 
@@ -187,15 +207,15 @@
 
     handle->fd = socket(AF_BLUETOOTH, SOCK_RAW, BTPROTO_HCI);
     if (handle->fd < 0) {
-        pcap_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) {
-        pcap_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;
     }
 
@@ -205,15 +225,15 @@
     addr.hci_channel = HCI_CHANNEL_MONITOR;
 
     if (bind(handle->fd, (struct sockaddr *) &addr, sizeof(addr)) < 0) {
-        pcap_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) {
-        pcap_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;
     }
 
diff --git a/pcap-bt-monitor-linux.h b/pcap-bt-monitor-linux.h
index aada2bc..8133710 100644
--- a/pcap-bt-monitor-linux.h
+++ b/pcap-bt-monitor-linux.h
@@ -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-common.c b/pcap-common.c
index 84368f6..b379d8f 100644
--- a/pcap-common.c
+++ b/pcap-common.c
@@ -18,26 +18,14 @@
  * 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"
@@ -496,9 +484,14 @@
 
 /*
  * 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
@@ -703,14 +696,14 @@
  * 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.
@@ -887,7 +880,7 @@
 
 /*
  * 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,
@@ -984,7 +977,7 @@
  * 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
@@ -1028,7 +1021,76 @@
  */
 #define LINKTYPE_RDS		265
 
-#define LINKTYPE_MATCHING_MAX	265		/* highest value in the "matching" range */
+/*
+ * 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
+
+#define LINKTYPE_MATCHING_MAX	275		/* 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;
@@ -1175,7 +1237,22 @@
 	return linktype;
 }
 
-#define EXTRACT_
+/*
+ * Return the maximum snapshot length for a given DLT_ value.
+ *
+ * For most link-layer types, we use MAXIMUM_SNAPLEN, but for DLT_DBUS,
+ * the maximum is 134217728, as per
+ *
+ *    https://dbus.freedesktop.org/doc/dbus-specification.html#message-protocol-messages
+ */
+u_int
+max_snaplen_for_dlt(int dlt)
+{
+	if (dlt == DLT_DBUS)
+		return 134217728;
+	else
+		return MAXIMUM_SNAPLEN;
+}
 
 /*
  * DLT_LINUX_SLL packets with a protocol type of LINUX_SLL_P_CAN or
@@ -1192,7 +1269,7 @@
 	u_int caplen = hdr->caplen;
 	u_int length = hdr->len;
 	struct sll_header *shdr = (struct sll_header *)buf;
-	u_int16_t protocol;
+	uint16_t protocol;
 	pcap_can_socketcan_hdr *chdr;
 
 	if (caplen < (u_int) sizeof(struct sll_header) ||
@@ -1338,7 +1415,7 @@
 		if (uhdr->transfer_type == URB_ISOCHRONOUS) {
 			/* swap the values in struct linux_usb_isodesc */
 			usb_isodesc *pisodesc;
-			u_int32_t i;
+			uint32_t i;
 
 			pisodesc = (usb_isodesc *)(void *)(buf+offset);
 			for (i = 0; i < uhdr->ndesc; i++) {
@@ -1384,7 +1461,7 @@
 	nflog_tlv_t *tlv;
 	u_int caplen = hdr->caplen;
 	u_int length = hdr->len;
-	u_int16_t size;
+	uint16_t size;
 
 	if (caplen < (u_int) sizeof(nflog_hdr_t) ||
 	    length < (u_int) sizeof(nflog_hdr_t)) {
diff --git a/pcap-common.h b/pcap-common.h
index 6ac5bcd..8795a82 100644
--- a/pcap-common.h
+++ b/pcap-common.h
@@ -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,
@@ -13,9 +35,13 @@
  * 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 void swap_pseudo_headers(int linktype, struct pcap_pkthdr *hdr,
     u_char *data);
+
+extern u_int max_snaplen_for_dlt(int dlt);
diff --git a/pcap-config b/pcap-config
deleted file mode 100755
index ec97bd7..0000000
--- a/pcap-config
+++ /dev/null
@@ -1,89 +0,0 @@
-#! /bin/sh
-
-#
-# Script to give the appropriate compiler flags and linker flags
-# to use when building code that uses libpcap.
-#
-prefix="/usr/local"
-exec_prefix="${prefix}"
-includedir="${prefix}/include"
-libdir="${exec_prefix}/lib"
-V_RPATH_OPT="-Wl,-rpath,"
-LIBS=""
-
-static=0
-show_cflags=0
-show_libs=0
-while [ "$#" != 0 ]
-do
-	case "$1" in
-
-	--static)
-		static=1
-		;;
-
-	--cflags)
-		show_cflags=1
-		;;
-
-	--libs)
-		show_libs=1
-		;;
-
-	--additional-libs)
-		show_additional_libs=1
-		;;
-	esac
-	shift
-done
-if [ "$V_RPATH_OPT" != "" ]
-then
-	#
-	# If libdir isn't /usr/lib, add it to the run-time linker path.
-	#
-	if [ "$libdir" != "/usr/lib" ]
-	then
-		RPATH=$V_RPATH_OPT$libdir
-	fi
-fi
-if [ "$static" = 1 ]
-then
-	#
-	# Include LIBS so that the flags include libraries containing
-	# routines that libpcap uses.
-	#
-	if [ "$show_cflags" = 1 -a "$show_libs" = 1 ]
-	then
-		echo "-I$includedir -L$libdir -lpcap $LIBS"
-	elif [ "$show_cflags" = 1 -a "$show_additional_libs" = 1 ]
-	then
-		echo "-I$includedir -L$libdir $LIBS"
-	elif [ "$show_cflags" = 1 ]
-	then
-		echo "-I$includedir"
-	elif [ "$show_libs" = 1 ]
-	then
-		echo "-L$libdir -lpcap $LIBS"
-	elif [ "$show_additional_libs" = 1 ]
-	then
-		echo "$LIBS"
-	fi
-else
-	#
-	# Omit LIBS - libpcap is assumed to be linked with those
-	# libraries, so there's no need to do so explicitly.
-	#
-	if [ "$show_cflags" = 1 -a "$show_libs" = 1 ]
-	then
-		echo "-I$includedir -L$libdir $RPATH -lpcap"
-	elif [ "$show_cflags" = 1 -a "$show_additional_libs" = 1 ]
-	then
-		echo "-I$includedir"
-	elif [ "$show_cflags" = 1 ]
-	then
-		echo "-I$includedir"
-	elif [ "$show_libs" = 1 ]
-	then
-		echo "-L$libdir $RPATH -lpcap"
-	fi
-fi
diff --git a/pcap-config.in b/pcap-config.in
index 206be3b..54ca42f 100644
--- a/pcap-config.in
+++ b/pcap-config.in
@@ -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 @@
 	#
 	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 @@
 		echo "-I$includedir"
 	elif [ "$show_libs" = 1 ]
 	then
-		echo "-L$libdir $RPATH -lpcap"
+		echo "-L$libdir $RPATH -l$PACKAGE_NAME"
 	fi
 fi
diff --git a/pcap-dag.c b/pcap-dag.c
index 201696c..6b7c791 100644
--- a/pcap-dag.c
+++ b/pcap-dag.c
@@ -1,5 +1,5 @@
 /*
- * pcap-dag.c: Packet capture interface for Emulex EndaceDAG cards.
+ * pcap-dag.c: Packet capture interface for Endace DAG cards.
  *
  * The functionality of this code attempts to mimic that of pcap-linux as much
  * as possible.  This code is compiled in several different ways depending on
@@ -12,11 +12,11 @@
  * Authors: Richard Littin, Sean Irvine ({richard,sean}@reeltwo.com)
  * Modifications: Jesper Peterson
  *                Koryn Grant
- *                Stephen Donnelly <stephen.donnelly@emulex.com>
+ *                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 */
@@ -41,6 +41,7 @@
 #include "dagnew.h"
 #include "dagapi.h"
 #include "dagpci.h"
+#include "dag_config_api.h"
 
 #include "pcap-dag.h"
 
@@ -54,96 +55,100 @@
 #endif
 
 
-#ifndef TYPE_AAL5
-#define TYPE_AAL5               4
+#ifndef ERF_TYPE_AAL5
+#define ERF_TYPE_AAL5               4
 #endif
 
-#ifndef TYPE_MC_HDLC
-#define TYPE_MC_HDLC            5
+#ifndef ERF_TYPE_MC_HDLC
+#define ERF_TYPE_MC_HDLC            5
 #endif
 
-#ifndef TYPE_MC_RAW
-#define TYPE_MC_RAW             6
+#ifndef ERF_TYPE_MC_RAW
+#define ERF_TYPE_MC_RAW             6
 #endif
 
-#ifndef TYPE_MC_ATM
-#define TYPE_MC_ATM             7
+#ifndef ERF_TYPE_MC_ATM
+#define ERF_TYPE_MC_ATM             7
 #endif
 
-#ifndef TYPE_MC_RAW_CHANNEL
-#define TYPE_MC_RAW_CHANNEL     8
+#ifndef ERF_TYPE_MC_RAW_CHANNEL
+#define ERF_TYPE_MC_RAW_CHANNEL     8
 #endif
 
-#ifndef TYPE_MC_AAL5
-#define TYPE_MC_AAL5            9
+#ifndef ERF_TYPE_MC_AAL5
+#define ERF_TYPE_MC_AAL5            9
 #endif
 
-#ifndef TYPE_COLOR_HDLC_POS
-#define TYPE_COLOR_HDLC_POS     10
+#ifndef ERF_TYPE_COLOR_HDLC_POS
+#define ERF_TYPE_COLOR_HDLC_POS     10
 #endif
 
-#ifndef TYPE_COLOR_ETH
-#define TYPE_COLOR_ETH          11
+#ifndef ERF_TYPE_COLOR_ETH
+#define ERF_TYPE_COLOR_ETH          11
 #endif
 
-#ifndef TYPE_MC_AAL2
-#define TYPE_MC_AAL2            12
+#ifndef ERF_TYPE_MC_AAL2
+#define ERF_TYPE_MC_AAL2            12
 #endif
 
-#ifndef TYPE_IP_COUNTER
-#define TYPE_IP_COUNTER         13
+#ifndef ERF_TYPE_IP_COUNTER
+#define ERF_TYPE_IP_COUNTER         13
 #endif
 
-#ifndef TYPE_TCP_FLOW_COUNTER
-#define TYPE_TCP_FLOW_COUNTER   14
+#ifndef ERF_TYPE_TCP_FLOW_COUNTER
+#define ERF_TYPE_TCP_FLOW_COUNTER   14
 #endif
 
-#ifndef TYPE_DSM_COLOR_HDLC_POS
-#define TYPE_DSM_COLOR_HDLC_POS 15
+#ifndef ERF_TYPE_DSM_COLOR_HDLC_POS
+#define ERF_TYPE_DSM_COLOR_HDLC_POS 15
 #endif
 
-#ifndef TYPE_DSM_COLOR_ETH
-#define TYPE_DSM_COLOR_ETH      16
+#ifndef ERF_TYPE_DSM_COLOR_ETH
+#define ERF_TYPE_DSM_COLOR_ETH      16
 #endif
 
-#ifndef TYPE_COLOR_MC_HDLC_POS
-#define TYPE_COLOR_MC_HDLC_POS  17
+#ifndef ERF_TYPE_COLOR_MC_HDLC_POS
+#define ERF_TYPE_COLOR_MC_HDLC_POS  17
 #endif
 
-#ifndef TYPE_AAL2
-#define TYPE_AAL2               18
+#ifndef ERF_TYPE_AAL2
+#define ERF_TYPE_AAL2               18
 #endif
 
-#ifndef TYPE_COLOR_HASH_POS
-#define TYPE_COLOR_HASH_POS     19
+#ifndef ERF_TYPE_COLOR_HASH_POS
+#define ERF_TYPE_COLOR_HASH_POS     19
 #endif
 
-#ifndef TYPE_COLOR_HASH_ETH
-#define TYPE_COLOR_HASH_ETH     20
+#ifndef ERF_TYPE_COLOR_HASH_ETH
+#define ERF_TYPE_COLOR_HASH_ETH     20
 #endif
 
-#ifndef TYPE_INFINIBAND
-#define TYPE_INFINIBAND         21
+#ifndef ERF_TYPE_INFINIBAND
+#define ERF_TYPE_INFINIBAND         21
 #endif
 
-#ifndef TYPE_IPV4
-#define TYPE_IPV4               22
+#ifndef ERF_TYPE_IPV4
+#define ERF_TYPE_IPV4               22
 #endif
 
-#ifndef TYPE_IPV6
-#define TYPE_IPV6               23
+#ifndef ERF_TYPE_IPV6
+#define ERF_TYPE_IPV6               23
 #endif
 
-#ifndef TYPE_RAW_LINK
-#define TYPE_RAW_LINK           24
+#ifndef ERF_TYPE_RAW_LINK
+#define ERF_TYPE_RAW_LINK           24
 #endif
 
-#ifndef TYPE_INFINIBAND_LINK
-#define TYPE_INFINIBAND_LINK    25
+#ifndef ERF_TYPE_INFINIBAND_LINK
+#define ERF_TYPE_INFINIBAND_LINK    25
 #endif
 
-#ifndef TYPE_PAD
-#define TYPE_PAD                48
+#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
@@ -173,20 +178,19 @@
  */
 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 {
@@ -205,11 +209,18 @@
 
 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)
@@ -237,26 +248,22 @@
 static void
 dag_platform_cleanup(pcap_t *p)
 {
-	struct pcap_dag *pd = p->pr;
+	struct pcap_dag *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));
+
+	if(pd->dag_ref != NULL) {
+		dag_config_dispose(pd->dag_ref);
 		p->fd = -1;
+		pd->dag_ref = NULL;
 	}
 	delete_pcap_dag(p);
 	pcap_cleanup_live_common(p);
-	/* Note: don't need to call close(p->fd) here as dag_close(p->fd) does this. */
+	/* Note: don't need to call close(p->fd) or dag_close(p->fd) as dag_config_dispose(pd->dag_ref) does this. */
 }
 
 static void
@@ -337,8 +344,7 @@
 {
 	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;
 
@@ -358,7 +364,6 @@
 			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.
@@ -373,10 +378,6 @@
 		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))
 		{
@@ -401,11 +402,7 @@
 		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;
@@ -434,26 +431,22 @@
 		/* 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;
 		}
 
@@ -477,20 +470,20 @@
 			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 */
@@ -510,19 +503,19 @@
 			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;
@@ -530,7 +523,7 @@
 				/* Skip over extension headers */
 				caplen -= (8 * num_ext_hdr);
 
-				if (header->type == TYPE_ATM) {
+				if ((header->type & 0x7f) == ERF_TYPE_ATM) {
 					caplen = packet_len = ATM_CELL_SIZE;
 				}
 				if (p->linktype == DLT_SUNATM) {
@@ -547,17 +540,21 @@
 						    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;
@@ -569,10 +566,14 @@
 				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;
@@ -583,8 +584,15 @@
 				}
 				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;
@@ -611,8 +619,23 @@
 #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 */
@@ -623,13 +646,13 @@
 				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
@@ -715,86 +738,103 @@
  *
  *  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.device;
-#ifdef HAVE_DAG_STREAMS_API
-	uint32_t mindata;
+	char * device = p->opt.device;
+	dag_size_t mindata;
 	struct timeval maxwait;
 	struct timeval poll;
-#endif
 
 	if (device == NULL) {
-		pcap_snprintf(handle->errbuf, PCAP_ERRBUF_SIZE, "device is NULL: %s", pcap_strerror(errno));
+		pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "device is NULL");
 		return -1;
 	}
 
 	/* Initialize some components of the pcap structure. */
-
-#ifdef HAVE_DAG_STREAMS_API
 	newDev = (char *)malloc(strlen(device) + 16);
 	if (newDev == NULL) {
-		pcap_snprintf(handle->errbuf, PCAP_ERRBUF_SIZE, "Can't allocate string for device name: %s", pcap_strerror(errno));
+		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) {
-		pcap_snprintf(handle->errbuf, PCAP_ERRBUF_SIZE, "dag_parse_name: %s", pcap_strerror(errno));
+	if (dag_parse_name(device, newDev, strlen(device) + 16, &pd->dag_stream) < 0) {
+		pcap_fmt_errmsg_for_errno(p->errbuf, PCAP_ERRBUF_SIZE,
+		    errno, "dag_parse_name");
 		goto fail;
 	}
 	device = newDev;
 
-	if (handlep->dag_stream%2) {
-		pcap_snprintf(handle->errbuf, PCAP_ERRBUF_SIZE, "dag_parse_name: tx (even numbered) streams not supported for capture");
+	if (pd->dag_stream%2) {
+		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) {
-			pcap_snprintf(handle->errbuf, PCAP_ERRBUF_SIZE, "Can't allocate string for device name: %s", 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) {
-		pcap_snprintf(handle->errbuf, PCAP_ERRBUF_SIZE, "dag_open %s: %s", device, pcap_strerror(errno));
+	if((pd->dag_ref = dag_config_init((char *)device)) == NULL) {
+		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) {
+		pcap_fmt_errmsg_for_errno(p->errbuf, PCAP_ERRBUF_SIZE,
+		    errno, "dag_config_get_card_fd %s", device);
+		goto fail;
+	}
+
 	/* Open requested stream. Can fail if already locked or on error */
-	if (dag_attach_stream(handle->fd, handlep->dag_stream, 0, 0) < 0) {
-		pcap_snprintf(handle->errbuf, PCAP_ERRBUF_SIZE, "dag_attach_stream: %s", pcap_strerror(errno));
+	if (dag_attach_stream64(p->fd, pd->dag_stream, 0, 0) < 0) {
+		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) {
-		pcap_snprintf(handle->errbuf, PCAP_ERRBUF_SIZE, "dag_get_stream_poll: %s", pcap_strerror(errno));
+		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 {
@@ -808,23 +848,16 @@
 	/* 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) {
-		pcap_snprintf(handle->errbuf, PCAP_ERRBUF_SIZE, "dag_set_stream_poll: %s", pcap_strerror(errno));
+		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) {
-		pcap_snprintf(handle->errbuf, PCAP_ERRBUF_SIZE,"dag_mmap %s: %s", 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.
          * Once the firmware provides 'per-stream slen' this can be supported
@@ -833,63 +866,51 @@
 	/* 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 */
-	pcap_snprintf(conf, 30, "varlen slen=%d", (snaplen + 3) & ~3);
-
-	if(dag_configure(handle->fd, conf) < 0) {
-		pcap_snprintf(handle->errbuf, PCAP_ERRBUF_SIZE,"dag_configure %s: %s", device, pcap_strerror(errno));
-		goto faildetach;
-	}
 #endif
 
-#ifdef HAVE_DAG_STREAMS_API
-	if(dag_start_stream(handle->fd, handlep->dag_stream) < 0) {
-		pcap_snprintf(handle->errbuf, PCAP_ERRBUF_SIZE, "dag_start_stream %s: %s", device, pcap_strerror(errno));
+	if(dag_start_stream(p->fd, pd->dag_stream) < 0) {
+		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) {
-		pcap_snprintf(handle->errbuf, PCAP_ERRBUF_SIZE, "dag_start %s: %s", 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 {
-				pcap_snprintf(handle->errbuf, PCAP_ERRBUF_SIZE,
+				pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
 					"pcap_activate %s: bad ERF_FCS_BITS value (%d) in environment", device, n);
 				goto failstop;
 			}
@@ -901,71 +922,65 @@
 		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)
 		goto failstop;
 
-	handle->bufsize = 0;
+	p->bufsize = 0;
 
-	if (new_pcap_dag(handle) < 0) {
-		pcap_snprintf(handle->errbuf, PCAP_ERRBUF_SIZE, "new_pcap_dag %s: %s", device, pcap_strerror(errno));
+	if (new_pcap_dag(p) < 0) {
+		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);
+	delete_pcap_dag(p);
 
 fail:
-	pcap_cleanup_live_common(handle);
+	pcap_cleanup_live_common(p);
 	if (newDev != NULL) {
 		free((char *)newDev);
 	}
@@ -979,9 +994,7 @@
 	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, '/');
@@ -996,29 +1009,28 @@
 	/* 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;
@@ -1039,8 +1051,8 @@
 	p->tstamp_precision_count = 2;
 	p->tstamp_precision_list = malloc(2 * sizeof(u_int));
 	if (p->tstamp_precision_list == NULL) {
-		pcap_snprintf(ebuf, PCAP_ERRBUF_SIZE, "malloc: %s",
-		    pcap_strerror(errno));
+		pcap_fmt_errmsg_for_errno(ebuf, PCAP_ERRBUF_SIZE,
+		    errno, "malloc");
 		pcap_close(p);
 		return NULL;
 	}
@@ -1052,12 +1064,28 @@
 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;
 
-	/* 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;*/
+	/*
+	 * 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;
+		}
+	}
 
 	*ps = pd->stat;
 
@@ -1065,72 +1093,72 @@
 }
 
 /*
- * 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++) {
 		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);
 		}
-		description = NULL;
 		if ( (dagfd = dag_open(dagname)) >= 0 ) {
+			description = NULL;
 			if ((inf = dag_pciinfo(dagfd)))
 				description = dag_device_name(inf->device_code, 1);
-			if (pcap_add_if(devlistp, name, 0, description, errbuf) == -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);
+			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);
 
-						pcap_snprintf(name,  10, "dag%d:%d", c, stream);
-						if (pcap_add_if(devlistp, name, 0, description, errbuf) == -1) {
-							/*
-							 * Failure.
-							 */
-							ret = -1;
-						}
+					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;
-						}
+					rxstreams--;
+					if(rxstreams <= 0) {
+						break;
 					}
 				}
 			}
-#endif  /* HAVE_DAG_STREAMS_API */
 			dag_close(dagfd);
 		}
 
 	}
-	return (ret);
+	return (0);
 }
 
 /*
@@ -1166,50 +1194,49 @@
 }
 
 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) {
-			pcap_snprintf(errbuf, PCAP_ERRBUF_SIZE, "dag_get_stream_poll: %s", pcap_strerror(errno));
-			return -1;
-		}
-
-		/* Amount of data to collect in Bytes before calling callbacks.
-		 * Important for efficiency, but can introduce latency
-		 * at low packet rates if to_ms not set!
-		 */
-		if(nonblock)
-			mindata = 0;
-		else
-			mindata = 65536;
-
-		if (dag_set_stream_poll(p->fd, pd->dag_stream,
-					mindata, &maxwait, &poll) < 0) {
-			pcap_snprintf(errbuf, PCAP_ERRBUF_SIZE, "dag_set_stream_poll: %s", 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);
 }
@@ -1224,7 +1251,8 @@
 	memset(types, 0, 255);
 
 	if (p->dlt_list == NULL && (p->dlt_list = malloc(255*sizeof(*(p->dlt_list)))) == NULL) {
-		(void)pcap_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);
 	}
 
@@ -1233,7 +1261,8 @@
 #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) {
-		pcap_snprintf(p->errbuf, sizeof(p->errbuf), "dag_get_stream_erf_types: %s", pcap_strerror(errno));
+		pcap_fmt_errmsg_for_errno(p->errbuf, sizeof(p->errbuf),
+		    errno, "dag_get_stream_erf_types");
 		return (-1);
 	}
 
@@ -1242,7 +1271,8 @@
 #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) {
-		pcap_snprintf(p->errbuf, sizeof(p->errbuf), "dag_get_erf_types: %s", pcap_strerror(errno));
+		pcap_fmt_errmsg_for_errno(p->errbuf, sizeof(p->errbuf),
+		    errno, "dag_get_erf_types");
 		return (-1);
 	}
 
@@ -1255,10 +1285,10 @@
 #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;
@@ -1269,10 +1299,10 @@
 				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
@@ -1291,10 +1321,10 @@
 				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;
@@ -1303,8 +1333,8 @@
 				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;
@@ -1317,20 +1347,33 @@
 				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 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_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 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 */
@@ -1360,9 +1403,8 @@
  * There are no regular interfaces, just DAG interfaces.
  */
 int
-pcap_platform_finddevs(pcap_if_t **alldevsp, char *errbuf)
+pcap_platform_finddevs(pcap_if_list_t *devlistp _U_, char *errbuf)
 {
-	*alldevsp = NULL;
 	return (0);
 }
 
@@ -1376,4 +1418,13 @@
 	    "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
diff --git a/pcap-dag.h b/pcap-dag.h
index dfeccd8..67361af 100644
--- a/pcap-dag.h
+++ b/pcap-dag.h
@@ -9,4 +9,4 @@
  */
 
 pcap_t *dag_create(const char *, char *, int *);
-int dag_findalldevs(pcap_if_t **devlistp, char *errbuf);
+int dag_findalldevs(pcap_if_list_t *devlistp, char *errbuf);
diff --git a/pcap-dbus.c b/pcap-dbus.c
index 8e92093..1252975 100644
--- a/pcap-dbus.c
+++ b/pcap-dbus.c
@@ -29,7 +29,7 @@
  */
 
 #ifdef HAVE_CONFIG_H
-#include "config.h"
+#include <config.h>
 #endif
 
 #include <string.h>
@@ -51,7 +51,7 @@
 };
 
 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;
 
@@ -145,6 +145,28 @@
 	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)
 {
@@ -208,11 +230,36 @@
 	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 @@
 		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);
@@ -264,15 +319,32 @@
 		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)
+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;
 }
diff --git a/pcap-dbus.h b/pcap-dbus.h
index 67493cc..c97f2e1 100644
--- a/pcap-dbus.h
+++ b/pcap-dbus.h
@@ -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
index 0000000..fc4f42b
--- /dev/null
+++ b/pcap-dll.rc
@@ -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
diff --git a/pcap-dlpi.c b/pcap-dlpi.c
index a431e7c..430051e 100644
--- a/pcap-dlpi.c
+++ b/pcap-dlpi.c
@@ -69,7 +69,7 @@
  */
 
 #ifdef HAVE_CONFIG_H
-#include "config.h"
+#include <config.h>
 #endif
 
 #include <sys/types.h>
@@ -122,18 +122,29 @@
 #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 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
 
@@ -165,7 +176,7 @@
 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
 
 /*
@@ -227,8 +238,8 @@
 				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;
@@ -251,8 +262,8 @@
 #if defined(DLIOCRAW)
 	ret = write(p->fd, buf, size);
 	if (ret == -1) {
-		pcap_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)
@@ -263,8 +274,8 @@
 	}
 	ret = dlrawdatareq(pd->send_fd, buf, size);
 	if (ret == -1) {
-		pcap_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);
 	}
 	/*
@@ -334,13 +345,15 @@
 }
 
 static int
-open_dlpi_device(const char *name, int *ppa, char *errbuf)
+open_dlpi_device(const char *name, u_int *ppa, char *errbuf)
 {
 	int status;
 	char dname[100];
 	char *cp;
 	int fd;
-#ifndef HAVE_DEV_DLPI
+#ifdef HAVE_DEV_DLPI
+	u_int unit;
+#else
 	char dname2[100];
 #endif
 
@@ -358,7 +371,7 @@
 	 * 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, errbuf);
+	cp = split_dname(dname, &unit, errbuf);
 	if (cp == NULL)
 		return (PCAP_ERROR_NO_SUCH_DEVICE);
 	*cp = '\0';
@@ -380,8 +393,8 @@
 			status = PCAP_ERROR_PERM_DENIED;
 		else
 			status = PCAP_ERROR;
-		pcap_snprintf(errbuf, PCAP_ERRBUF_SIZE,
-		    "%s: %s", cp, pcap_strerror(errno));
+		pcap_fmt_errmsg_for_errno(errbuf, PCAP_ERRBUF_SIZE,
+		    errno, "%s", cp);
 		return (status);
 	}
 
@@ -389,10 +402,10 @@
 	 * 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(fd, dname, *ppa, errbuf);
-	if (*ppa < 0) {
+	status = get_dlpi_ppa(fd, dname, unit, ppa, errbuf);
+	if (status < 0) {
 		close(fd);
-		return (*ppa);
+		return (status);
 	}
 #else
 	/*
@@ -429,8 +442,8 @@
 				status = PCAP_ERROR_PERM_DENIED;
 			else
 				status = PCAP_ERROR;
-			pcap_snprintf(errbuf, PCAP_ERRBUF_SIZE, "%s: %s", dname,
-			    pcap_strerror(errno));
+			pcap_fmt_errmsg_for_errno(errbuf, PCAP_ERRBUF_SIZE,
+			    errno, "%s", dname);
 			return (status);
 		}
 
@@ -469,8 +482,8 @@
 					status = PCAP_ERROR_PERM_DENIED;
 				else
 					status = PCAP_ERROR;
-				pcap_snprintf(errbuf, PCAP_ERRBUF_SIZE, "%s: %s",
-				    dname2, pcap_strerror(errno));
+				pcap_fmt_errmsg_for_errno(errbuf,
+				    PCAP_ERRBUF_SIZE, errno, "%s", dname2);
 			}
 			return (status);
 		}
@@ -489,7 +502,7 @@
 #endif
 	int status = 0;
 	int retv;
-	int ppa;
+	u_int ppa;
 #ifdef HAVE_SOLARIS
 	int isatm = 0;
 #endif
@@ -563,7 +576,7 @@
 		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.
@@ -632,6 +645,17 @@
 #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) {
 		/*
@@ -642,8 +666,8 @@
 		*/
 		if (strioctl(p->fd, A_PROMISCON_REQ, 0, NULL) < 0) {
 			status = PCAP_ERROR;
-			pcap_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
@@ -760,8 +784,8 @@
 	*/
 	if (strioctl(p->fd, DLIOCRAW, 0, NULL) < 0) {
 		status = PCAP_ERROR;
-		pcap_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
@@ -801,8 +825,8 @@
 	*/
 	if (ioctl(p->fd, I_FLUSH, FLUSHR) != 0) {
 		status = PCAP_ERROR;
-		pcap_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;
 	}
 
@@ -845,7 +869,7 @@
  * 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;
@@ -881,7 +905,7 @@
 		    device);
 		return (NULL);
 	}
-	*unitp = (int)unit;
+	*unitp = (u_int)unit;
 	return (cp);
 }
 
@@ -986,7 +1010,7 @@
 is_dlpi_interface(const char *name)
 {
 	int fd;
-	int ppa;
+	u_int ppa;
 	char errbuf[PCAP_ERRBUF_SIZE];
 
 	fd = open_dlpi_device(name, &ppa, errbuf);
@@ -1025,8 +1049,31 @@
 	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;
@@ -1042,7 +1089,8 @@
 	/*
 	 * Get the list of regular interfaces first.
 	 */
-	if (pcap_findalldevs_interfaces(alldevsp, errbuf, is_dlpi_interface) == -1)
+	if (pcap_findalldevs_interfaces(devlistp, errbuf, is_dlpi_interface,
+	    get_if_flags) == -1)
 		return (-1);	/* failure */
 
 #ifdef HAVE_SOLARIS
@@ -1062,13 +1110,18 @@
 	}
 
 	if (strioctl(fd, A_GET_UNITS, sizeof(buf), (char *)&buf) < 0) {
-		pcap_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++) {
 		pcap_snprintf(baname, sizeof baname, "ba%u", i);
-		if (pcap_add_if(alldevsp, baname, 0, NULL, errbuf) < 0)
+		/*
+		 * 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
@@ -1088,9 +1141,8 @@
 
 	flags = 0;
 	if (putmsg(fd, &ctl, (struct strbuf *) NULL, flags) < 0) {
-		pcap_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);
@@ -1118,8 +1170,8 @@
 
 	flags = 0;
 	if (getmsg(fd, &ctl, (struct strbuf*)NULL, &flags) < 0) {
-		pcap_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);
 	}
 
@@ -1141,9 +1193,9 @@
 		case DL_SYSERR:
 			if (uerror != NULL)
 				*uerror = dlp->error_ack.dl_unix_errno;
-			pcap_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);
@@ -1430,7 +1482,7 @@
 	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.
@@ -1552,12 +1604,12 @@
  * 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;
@@ -1567,7 +1619,6 @@
 	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;
@@ -1595,8 +1646,13 @@
 	 */
 	/* get the head first */
 	if (getmsg(fd, &ctl, (struct strbuf *)NULL, &flags) < 0) {
+		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: %s", pcap_strerror(errno));
+		    "get_dlpi_ppa: hpppa getmsg: control buffer has no data");
 		return (PCAP_ERROR);
 	}
 
@@ -1608,7 +1664,7 @@
 		return (PCAP_ERROR);
 	}
 
-	if (ctl.len < DL_HP_PPA_ACK_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);
@@ -1617,8 +1673,8 @@
 
 	/* allocate buffer */
 	if ((ppa_data_buf = (char *)malloc(dlp->dl_length)) == NULL) {
-		pcap_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;
@@ -1626,12 +1682,17 @@
 	ctl.buf = (char *)ppa_data_buf;
 	/* get the data */
 	if (getmsg(fd, &ctl, (struct strbuf *)NULL, &flags) < 0) {
-		pcap_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) {
+	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);
@@ -1643,7 +1704,7 @@
 	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
@@ -1689,10 +1750,10 @@
 		 * device number of a device with the name "/dev/<dev><unit>",
 		 * if such a device exists, as the old code did.
 		 */
-		pcap_snprintf(dname, sizeof(dname), "/dev/%s%d", device, unit);
+		pcap_snprintf(dname, sizeof(dname), "/dev/%s%u", device, unit);
 		if (stat(dname, &statbuf) < 0) {
-			pcap_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);
@@ -1709,7 +1770,7 @@
 	}
 	if (i == ap->dl_count) {
 		pcap_snprintf(ebuf, PCAP_ERRBUF_SIZE,
-		    "can't find /dev/dlpi PPA for %s%d", device, unit);
+		    "can't find /dev/dlpi PPA for %s%u", device, unit);
 		return (PCAP_ERROR_NO_SUCH_DEVICE);
 	}
 	if (ip->dl_hdw_state == HDW_DEAD) {
@@ -1718,9 +1779,9 @@
 		free(ppa_data_buf);
 		return (PCAP_ERROR);
 	}
-	ppa = ip->dl_ppa;
+	*ppa = ip->dl_ppa;
 	free(ppa_data_buf);
-	return (ppa);
+	return (0);
 }
 #endif
 
@@ -1739,8 +1800,8 @@
 
 /* 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;
@@ -1754,24 +1815,24 @@
 	if (nlist(path_vmunix, &nl) < 0) {
 		pcap_snprintf(ebuf, PCAP_ERRBUF_SIZE, "nlist %s failed",
 		    path_vmunix);
-		return (-1);
+		return (PCAP_ERROR);
 	}
 	if (nl[NL_IFNET].n_value == 0) {
 		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) {
-		pcap_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,
@@ -1779,15 +1840,17 @@
 		    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);
+		}
 	}
 
 	pcap_snprintf(ebuf, PCAP_ERRBUF_SIZE, "Can't find %s", ifname);
-	return (-1);
+	return (PCAP_ERROR_NO_SUCH_DEVICE);
 }
 
 static int
@@ -1797,14 +1860,14 @@
 	register int cc;
 
 	if (lseek(fd, addr, SEEK_SET) < 0) {
-		pcap_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) {
-		pcap_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) {
 		pcap_snprintf(ebuf, PCAP_ERRBUF_SIZE, "short read (%d != %d)", cc,
@@ -1835,3 +1898,12 @@
 	p->activate_op = pcap_activate_dlpi;
 	return (p);
 }
+
+/*
+ * Libpcap version string.
+ */
+const char *
+pcap_lib_version(void)
+{
+	return (PCAP_VERSION_STRING);
+}
diff --git a/pcap-dos.c b/pcap-dos.c
index ea6b225..b1b9ecd 100644
--- a/pcap-dos.c
+++ b/pcap-dos.c
@@ -174,6 +174,17 @@
     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;
 
@@ -197,6 +208,7 @@
     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);
@@ -206,6 +218,7 @@
     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;
@@ -467,6 +480,7 @@
        return;
   }
   close_driver();
+  /* XXX - call pcap_cleanup_live_common? */
 }
 
 /*
@@ -539,17 +553,18 @@
 /*
  * 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_platform_finddevs  (pcap_if_t **alldevsp, char *errbuf)
+int pcap_platform_finddevs  (pcap_if_list_t *devlistp, char *errbuf)
 {
   struct device     *dev;
+  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(*addr);
+  int       found = 0;
 
   for (dev = (struct device*)dev_base; dev; dev = dev->next)
   {
@@ -562,6 +577,20 @@
     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.sin_family = AF_INET;
@@ -573,16 +602,10 @@
     broadaddr = (struct sockaddr*) &sa_ll_2;
     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 0   /* Pkt drivers should have no addresses */
-    if (add_addr_to_iflist(&devlist, dev->name, dev->flags, addr, addr_size,
-                           netmask, addr_size, broadaddr, addr_size,
-                           dstaddr, addr_size, errbuf) < 0)
+    if (add_addr_to_dev(curdev, addr, sizeof(*addr),
+                        netmask, sizeof(*netmask),
+                        broadaddr, sizeof(*broadaddr),
+                        dstaddr, sizeof(*dstaddr), errbuf) < 0)
     {
       ret = -1;
       break;
@@ -590,16 +613,9 @@
 #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);
 }
 
@@ -1510,3 +1526,11 @@
 
 #endif /* USE_32BIT_DRIVERS */
 
+/*
+ * Libpcap version string.
+ */
+const char *
+pcap_lib_version(void)
+{
+  return ("DOS-" PCAP_VERSION_STRING);
+}
diff --git a/pcap-enet.c b/pcap-enet.c
index 777d3e3..cd8cdbb 100644
--- a/pcap-enet.c
+++ b/pcap-enet.c
@@ -8,7 +8,7 @@
  */
 
 #ifdef HAVE_CONFIG_H
-#include "config.h"
+#include <config.h>
 #endif
 
 #include <sys/types.h>
diff --git a/pcap-filter.manmisc b/pcap-filter.manmisc
index b9bf387..3548691 100644
--- a/pcap-filter.manmisc
+++ b/pcap-filter.manmisc
@@ -18,7 +18,7 @@
 .\" WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
 .\" MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
 .\"
-.TH PCAP-FILTER 7 "3 August 2015"
+.TH PCAP-FILTER 7 "5 November 2017"
 .SH NAME
 pcap-filter \- packet filter syntax
 .br
@@ -181,9 +181,10 @@
 .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"
@@ -566,7 +567,7 @@
 and
 .B block
 and, with later versions of
-.BR pf (4)),
+.BR pf (4),
 .BR nat ,
 .BR rdr ,
 .B binat
@@ -863,8 +864,9 @@
 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,
@@ -873,9 +875,24 @@
 \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
@@ -1010,11 +1027,12 @@
 .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.
diff --git a/pcap-filter.manmisc.in b/pcap-filter.manmisc.in
index 9d3f34b..3232f7e 100644
--- a/pcap-filter.manmisc.in
+++ b/pcap-filter.manmisc.in
@@ -18,7 +18,7 @@
 .\" WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
 .\" MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
 .\"
-.TH PCAP-FILTER @MAN_MISC_INFO@ "3 August 2015"
+.TH PCAP-FILTER @MAN_MISC_INFO@ "5 November 2017"
 .SH NAME
 pcap-filter \- packet filter syntax
 .br
@@ -181,9 +181,10 @@
 .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"
@@ -566,7 +567,7 @@
 and
 .B block
 and, with later versions of
-.BR pf (4)),
+.BR pf (4),
 .BR nat ,
 .BR rdr ,
 .B binat
@@ -863,8 +864,9 @@
 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,
@@ -873,9 +875,24 @@
 \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
@@ -1010,11 +1027,12 @@
 .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.
diff --git a/pcap-int.h b/pcap-int.h
index 7db7ff5..5888df7 100644
--- a/pcap-int.h
+++ b/pcap-int.h
@@ -34,55 +34,40 @@
 #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
 
-#if defined(_WIN32)
-  /*
-   * Make sure Packet32.h doesn't define BPF structures that we've
-   * probably already defined as a result of including <pcap/pcap.h>.
-   */
-  #define BPF_MAJOR_VERSION
-  #include <Packet32.h>
-#elif defined(MSDOS)
+#ifdef MSDOS
   #include <fcntl.h>
   #include <io.h>
 #endif
 
-#if (defined(_MSC_VER) && (_MSC_VER <= 1200)) /* we are compiling with Visual Studio 6, that doesn't support the LL suffix*/
-
 /*
  * 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.
@@ -114,19 +99,32 @@
 	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
 typedef struct pcap_stat *(*stats_ex_op_t)(pcap_t *, int *);
@@ -155,15 +153,14 @@
 	read_op_t read_op;
 
 	/*
-	 * Method to call 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;
+	HANDLE handle;
 #else
 	int fd;
-	int selectable_fd;
 #endif /* _WIN32 */
 
 	/*
@@ -174,10 +171,14 @@
 	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 */
 	u_int fddipad;
@@ -208,7 +209,7 @@
 	u_char *pkt;
 
 #ifdef _WIN32
-	struct pcap_stat stat;		/* used for pcap_stats_ex() */
+	struct pcap_stat stat;	/* used for pcap_stats_ex() */
 #endif
 
 	/* We're accepting only packets in this direction/these directions. */
@@ -219,6 +220,23 @@
 	 */
 	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.
 	 */
@@ -240,6 +258,7 @@
 	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;
@@ -378,8 +397,8 @@
  * 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 *);
+int	pcap_getnonblock_fd(pcap_t *);
+int	pcap_setnonblock_fd(pcap_t *p, int);
 #endif
 
 /*
@@ -404,32 +423,47 @@
 /*
  * Internal interfaces for "pcap_findalldevs()".
  *
- * "pcap_platform_finddevs()" is a platform-dependent routine to
+ * 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_add_if()" adds an interface to the list of interfaces, for
- * use by various "find interfaces" routines.
+ * "add_dev()" adds an entry to a pcap_if_list_t.
+ *
+ * "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_platform_finddevs(pcap_if_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_t **, char *,
-	    int (*)(const char *));
+int	pcap_findalldevs_interfaces(pcap_if_list_t *, char *,
+	    int (*)(const char *), get_if_flags_func);
 #endif
-int	add_addr_to_iflist(pcap_if_t **, const char *, bpf_u_int32,
-	    struct sockaddr *, size_t, struct sockaddr *, size_t,
-	    struct sockaddr *, size_t, struct sockaddr *, size_t, char *);
+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 *, bpf_u_int32, const char *,
-	    char *);
-int	add_or_find_if(pcap_if_t **, pcap_if_t **, const char *, bpf_u_int32,
-	    const char *, char *);
 #ifndef _WIN32
-bpf_u_int32 if_flags_to_pcap_flags(const char *, u_int);
+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
 
 /*
@@ -462,6 +496,10 @@
 
 int	pcap_strcasecmp(const char *, const char *);
 
+#ifdef YYDEBUG
+extern int pcap_debug;
+#endif
+
 #ifdef __cplusplus
 }
 #endif
diff --git a/pcap-libdlpi.c b/pcap-libdlpi.c
index 625f1e0..a0d1669 100644
--- a/pcap-libdlpi.c
+++ b/pcap-libdlpi.c
@@ -25,7 +25,7 @@
  */
 
 #ifdef HAVE_CONFIG_H
-#include "config.h"
+#include <config.h>
 #endif
 
 #include <sys/types.h>
@@ -137,6 +137,17 @@
 		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);
@@ -209,8 +220,8 @@
 	 */
 	if (ioctl(p->fd, I_FLUSH, FLUSHR) != 0) {
 		status = PCAP_ERROR;
-		pcap_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;
 	}
 
@@ -276,13 +287,36 @@
 	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;
 
@@ -293,23 +327,36 @@
 	/*
 	 * Get the list of regular interfaces first.
 	 */
-	if (pcap_findalldevs_interfaces(alldevsp, errbuf, is_dlpi_interface) == -1)
+	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) {
-		pcap_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:
@@ -437,3 +484,12 @@
 	p->activate_op = pcap_activate_libdlpi;
 	return (p);
 }
+
+/*
+ * Libpcap version string.
+ */
+const char *
+pcap_lib_version(void)
+{
+	return (PCAP_VERSION_STRING);
+}
diff --git a/pcap-linktype.manmisc b/pcap-linktype.manmisc
index e680567..20f2ea2 100644
--- a/pcap-linktype.manmisc
+++ b/pcap-linktype.manmisc
@@ -43,6 +43,6 @@
 .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)
diff --git a/pcap-linktype.manmisc.in b/pcap-linktype.manmisc.in
index 7634a96..68919a7 100644
--- a/pcap-linktype.manmisc.in
+++ b/pcap-linktype.manmisc.in
@@ -43,6 +43,6 @@
 .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)
diff --git a/pcap-linux.c b/pcap-linux.c
index 924df42..49144b6 100644
--- a/pcap-linux.c
+++ b/pcap-linux.c
@@ -113,7 +113,7 @@
 #define _GNU_SOURCE
 
 #ifdef HAVE_CONFIG_H
-#include "config.h"
+#include <config.h>
 #endif
 
 #include <errno.h>
@@ -336,6 +336,8 @@
 /*
  * Prototypes for internal functions and methods.
  */
+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);
 #ifdef HAVE_PF_PACKET_SOCKETS
 static short int map_packet_type_to_sll_type(short int);
@@ -404,12 +406,52 @@
 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
@@ -425,7 +467,7 @@
 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 */
@@ -488,8 +530,8 @@
 	handle->tstamp_precision_count = 2;
 	handle->tstamp_precision_list = malloc(2 * sizeof(u_int));
 	if (handle->tstamp_precision_list == NULL) {
-		pcap_snprintf(ebuf, PCAP_ERRBUF_SIZE, "malloc: %s",
-		    pcap_strerror(errno));
+		pcap_fmt_errmsg_for_errno(ebuf, PCAP_ERRBUF_SIZE,
+		    errno, "malloc");
 		pcap_close(handle);
 		return NULL;
 	}
@@ -575,9 +617,8 @@
 			free(pathstr);
 			return 0;
 		}
-		pcap_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;
 	}
@@ -772,8 +813,8 @@
 	 */
 	handlep->mondevice = strdup(mondevice);
 	if (handlep->mondevice == NULL) {
-		pcap_snprintf(handle->errbuf, PCAP_ERRBUF_SIZE, "strdup: %s",
-			 pcap_strerror(errno));
+		pcap_fmt_errmsg_for_errno(handle->errbuf, PCAP_ERRBUF_SIZE,
+		    errno, "strdup");
 		/*
 		 * Get rid of the monitor device.
 		 */
@@ -938,9 +979,9 @@
 	memset(&ifr, 0, sizeof(ifr));
 	strlcpy(ifr.ifr_name, handlep->mondevice, sizeof(ifr.ifr_name));
 	if (ioctl(sock_fd, SIOCGIFFLAGS, &ifr) == -1) {
-		pcap_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);
@@ -948,9 +989,9 @@
 	}
 	ifr.ifr_flags |= IFF_UP|IFF_RUNNING;
 	if (ioctl(sock_fd, SIOCSIFFLAGS, &ifr) == -1) {
-		pcap_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);
@@ -1008,6 +1049,17 @@
 }
 #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)
 {
@@ -1059,10 +1111,10 @@
 	 * (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)pcap_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;
 	}
 
@@ -1086,8 +1138,8 @@
 	}
 	if (errno == ENODEV) {
 		/* The device doesn't even exist. */
-		(void)pcap_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;
 	}
@@ -1446,6 +1498,17 @@
 		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;
@@ -1473,8 +1536,8 @@
 
 	handlep->device	= strdup(device);
 	if (handlep->device == NULL) {
-		pcap_snprintf(handle->errbuf, PCAP_ERRBUF_SIZE, "strdup: %s",
-			 pcap_strerror(errno) );
+		pcap_fmt_errmsg_for_errno(handle->errbuf, PCAP_ERRBUF_SIZE,
+		    errno, "strdup");
 		return PCAP_ERROR;
 	}
 
@@ -1570,8 +1633,8 @@
 		if (setsockopt(handle->fd, SOL_SOCKET, SO_RCVBUF,
 		    &handle->opt.buffer_size,
 		    sizeof(handle->opt.buffer_size)) == -1) {
-			pcap_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;
 		}
@@ -1581,8 +1644,8 @@
 
 	handle->buffer	 = malloc(handle->bufsize + handle->offset);
 	if (!handle->buffer) {
-		pcap_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;
 	}
@@ -1606,7 +1669,7 @@
  *  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,
@@ -1691,7 +1754,7 @@
 #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;
@@ -1699,9 +1762,9 @@
 		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;
 
@@ -1740,7 +1803,7 @@
 	 */
 	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;
@@ -1751,7 +1814,7 @@
 
 	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 {
 		/*
@@ -1767,15 +1830,15 @@
 			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 */
@@ -1799,8 +1862,8 @@
 			return PCAP_ERROR;
 
 		default:
-			pcap_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;
 		}
 	}
@@ -1856,7 +1919,12 @@
 		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;
@@ -1865,18 +1933,22 @@
 
 			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 = (u_int)packet_len > iov.iov_len ? iov.iov_len : (u_int)packet_len;
 			if (len < (u_int)handlep->vlan_offset)
@@ -1898,11 +1970,14 @@
 			tag->vlan_tpid = htons(VLAN_TPID(aux, aux));
 			tag->vlan_tci = htons(aux->tp_vlan_tci);
 
-                        /* store vlan tci to bpf_aux_data struct for userland bpf filter */
-#if defined(TP_STATUS_VLAN_VALID)
-                        aux_data.vlan_tag = htons(aux->tp_vlan_tci) & 0x0fff;
-                        aux_data.vlan_tag_present = (aux->tp_status & TP_STATUS_VLAN_VALID);
-#endif
+			/*
+			 * 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.
@@ -1910,7 +1985,7 @@
 			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 */
 
 	/*
@@ -1964,16 +2039,16 @@
 #if defined(SIOCGSTAMPNS) && defined(SO_TIMESTAMPNS)
 	if (handle->opt.tstamp_precision == PCAP_TSTAMP_PRECISION_NANO) {
 		if (ioctl(handle->fd, SIOCGSTAMPNS, &pcap_header.ts) == -1) {
-			pcap_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) {
-			pcap_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;
 		}
         }
@@ -2002,7 +2077,7 @@
 	 * 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
@@ -2070,8 +2145,8 @@
 
 	ret = send(handle->fd, buf, size, 0);
 	if (ret == -1) {
-		pcap_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);
@@ -2089,7 +2164,7 @@
 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
@@ -2110,7 +2185,7 @@
 	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;
 
@@ -2124,7 +2199,7 @@
 		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.
 	 */
@@ -2192,8 +2267,8 @@
 		 * is built on a system without "struct tpacket_stats".
 		 */
 		if (errno != EOPNOTSUPP) {
-			pcap_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;
 		}
 	}
@@ -2230,7 +2305,7 @@
 }
 
 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 */
@@ -2278,20 +2353,19 @@
 	if (ioctl(fd, SIOCGIFFLAGS, (char *)&ifrflags) < 0) {
 		if (errno == ENXIO || errno == ENODEV)
 			return (0);	/* device doesn't actually exist - ignore it */
-		(void)pcap_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,
-	    if_flags_to_pcap_flags(name, ifrflags.ifr_flags), NULL,
-	    errbuf) == -1) {
+	if (find_or_add_if(devlistp, name, ifrflags.ifr_flags,
+	    get_if_flags, errbuf) == NULL) {
 		/*
 		 * Failure.
 		 */
@@ -2318,7 +2392,7 @@
  * 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;
@@ -2338,8 +2412,8 @@
 		/*
 		 * Fail if we got some other error.
 		 */
-		(void)pcap_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);
 	}
 
@@ -2348,8 +2422,8 @@
 	 */
 	fd = socket(PF_UNIX, SOCK_RAW, 0);
 	if (fd < 0) {
-		(void)pcap_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);
 	}
@@ -2416,9 +2490,8 @@
 		 * fail due to an error reading the directory?
 		 */
 		if (errno != 0) {
-			(void)pcap_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;
 		}
 	}
@@ -2436,7 +2509,7 @@
  * 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;
@@ -2456,8 +2529,8 @@
 		/*
 		 * Fail if we got some other error.
 		 */
-		(void)pcap_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);
 	}
 
@@ -2466,8 +2539,8 @@
 	 */
 	fd = socket(PF_UNIX, SOCK_RAW, 0);
 	if (fd < 0) {
-		(void)pcap_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);
 	}
@@ -2505,9 +2578,8 @@
 		 * fail due to an error reading the file?
 		 */
 		if (ferror(proc_net_f)) {
-			(void)pcap_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;
 		}
 	}
@@ -2531,15 +2603,187 @@
 	return (1);
 }
 
+/*
+ * Get additional flags for a device, using SIOCGIFMEDIA.
+ */
+static int
+get_if_flags(const char *name, bpf_u_int32 *flags, char *errbuf)
+{
+	int sock;
+	FILE *fh;
+	unsigned int arptype;
+	struct ifreq ifr;
+	struct ethtool_value info;
+
+	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;
+	}
+
+	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;
+	}
+
+	/*
+	 * OK, what type of network is this?
+	 * In particular, is it wired or wireless?
+	 */
+	if (is_wifi(sock, name)) {
+		/*
+		 * Wi-Fi, hence wireless.
+		 */
+		*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));
+	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_t **alldevsp, char *errbuf)
+pcap_platform_finddevs(pcap_if_list_t *devlistp, char *errbuf)
 {
 	int ret;
 
 	/*
 	 * Get the list of regular interfaces first.
 	 */
-	if (pcap_findalldevs_interfaces(alldevsp, errbuf, can_be_bound) == -1)
+	if (pcap_findalldevs_interfaces(devlistp, errbuf, can_be_bound,
+	    get_if_flags) == -1)
 		return (-1);	/* failure */
 
 	/*
@@ -2550,22 +2794,26 @@
 	 * 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);
+	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(alldevsp, errbuf) == -1)
+		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 (pcap_add_if(alldevsp, "any", PCAP_IF_UP|PCAP_IF_RUNNING,
-	    any_descr, errbuf) < 0)
+	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);
@@ -2725,9 +2973,9 @@
 	 */
 	if (handlep->filter_in_userland) {
 		if (reset_kernel_filter(handle) == -1) {
-			pcap_snprintf(handle->errbuf, PCAP_ERRBUF_SIZE,
-			    "can't remove kernel filter: %s",
-			    pcap_strerror(errno));
+			pcap_fmt_errmsg_for_errno(handle->errbuf,
+			    PCAP_ERRBUF_SIZE, errno,
+			    "can't remove kernel filter");
 			err = -2;	/* fatal error */
 		}
 	}
@@ -3226,7 +3474,7 @@
 		 * 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.
 		 */
@@ -3295,6 +3543,13 @@
 		/* handlep->cooked = 1; */
 		break;
 
+#ifndef ARPHRD_VSOCKMON
+#define ARPHRD_VSOCKMON	826
+#endif
+	case ARPHRD_VSOCKMON:
+		handle->linktype = DLT_VSOCK;
+		break;
+
 	default:
 		handle->linktype = -1;
 		break;
@@ -3317,6 +3572,7 @@
 	struct pcap_linux *handlep = handle->priv;
 	const char		*device = handle->opt.device;
 	int			is_any_device = (strcmp(device, "any") == 0);
+	int			protocol = pcap_protocol(handle);
 	int			sock_fd = -1, arptype;
 #ifdef HAVE_PACKET_AUXDATA
 	int			val;
@@ -3335,8 +3591,8 @@
 	 * 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) {
@@ -3347,8 +3603,8 @@
 			return 0;
 		}
 
-		pcap_snprintf(handle->errbuf, PCAP_ERRBUF_SIZE, "socket: %s",
-			 pcap_strerror(errno) );
+		pcap_fmt_errmsg_for_errno(handle->errbuf, PCAP_ERRBUF_SIZE,
+		    errno, "socket");
 		if (errno == EPERM || errno == EACCES) {
 			/*
 			 * You don't have permission to open the
@@ -3449,15 +3705,14 @@
 			 * kernels) - reopen in cooked mode.
 			 */
 			if (close(sock_fd) == -1) {
-				pcap_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) {
-				pcap_snprintf(handle->errbuf, PCAP_ERRBUF_SIZE,
-				    "socket: %s", pcap_strerror(errno));
+				pcap_fmt_errmsg_for_errno(handle->errbuf,
+				    PCAP_ERRBUF_SIZE, errno, "socket");
 				if (errno == EPERM || errno == EACCES) {
 					/*
 					 * You don't have permission to
@@ -3518,7 +3773,7 @@
 		}
 
 		if ((err = iface_bind(sock_fd, handlep->ifindex,
-		    handle->errbuf)) != 1) {
+		    handle->errbuf, protocol)) != 1) {
 		    	close(sock_fd);
 			if (err < 0)
 				return err;
@@ -3581,8 +3836,8 @@
 		mr.mr_type    = PACKET_MR_PROMISC;
 		if (setsockopt(sock_fd, SOL_PACKET, PACKET_ADD_MEMBERSHIP,
 		    &mr, sizeof(mr)) == -1) {
-			pcap_snprintf(handle->errbuf, PCAP_ERRBUF_SIZE,
-				"setsockopt: %s", pcap_strerror(errno));
+			pcap_fmt_errmsg_for_errno(handle->errbuf,
+			    PCAP_ERRBUF_SIZE, errno, "setsockopt");
 			close(sock_fd);
 			return PCAP_ERROR;
 		}
@@ -3594,8 +3849,8 @@
 	val = 1;
 	if (setsockopt(sock_fd, SOL_PACKET, PACKET_AUXDATA, &val,
 		       sizeof(val)) == -1 && errno != ENOPROTOOPT) {
-		pcap_snprintf(handle->errbuf, PCAP_ERRBUF_SIZE,
-			 "setsockopt: %s", pcap_strerror(errno));
+		pcap_fmt_errmsg_for_errno(handle->errbuf, PCAP_ERRBUF_SIZE,
+		    errno, "setsockopt");
 		close(sock_fd);
 		return PCAP_ERROR;
 	}
@@ -3717,9 +3972,8 @@
 	 */
 	handlep->oneshot_buffer = malloc(handle->snapshot);
 	if (handlep->oneshot_buffer == NULL) {
-		pcap_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;
 	}
@@ -3822,10 +4076,9 @@
 			return 1;	/* no */
 
 		/* Failed to even find out; this is a fatal error. */
-		pcap_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;
@@ -3833,10 +4086,8 @@
 	val = version;
 	if (setsockopt(handle->fd, SOL_PACKET, PACKET_VERSION, &val,
 			   sizeof(val)) < 0) {
-		pcap_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;
@@ -3845,9 +4096,8 @@
 	val = VLAN_TAG_LEN;
 	if (setsockopt(handle->fd, SOL_PACKET, PACKET_RESERVE, &val,
 			   sizeof(val)) < 0) {
-		pcap_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;
 	}
 
@@ -3977,8 +4227,8 @@
 			/*
 			 * Failed.
 			 */
-			pcap_snprintf(handle->errbuf, PCAP_ERRBUF_SIZE,
-			    "uname failed: %s", pcap_strerror(errno));
+			pcap_fmt_errmsg_for_errno(handle->errbuf,
+			    PCAP_ERRBUF_SIZE, errno, "uname failed");
 			return -1;
 		}
 		if (strcmp(utsname.machine, ISA_64_BIT) == 0) {
@@ -3999,6 +4249,8 @@
 	return 1;
 }
 
+#define MAX(a,b) ((a)>(b)?(a):(b))
+
 /*
  * Attempt to set up memory-mapped access.
  *
@@ -4042,10 +4294,10 @@
 #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).
@@ -4069,29 +4321,35 @@
 		 * 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.device,
-				    handle->errbuf);
-				if (mtu == -1) {
-					*status = PCAP_ERROR;
-					return -1;
-				}
-				if (frame_size > (unsigned int)mtu + 18)
-					frame_size = (unsigned int)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()
@@ -4100,8 +4358,8 @@
 		len = sizeof(sk_type);
 		if (getsockopt(handle->fd, SOL_SOCKET, SO_TYPE, &sk_type,
 		    &len) < 0) {
-			pcap_snprintf(handle->errbuf, PCAP_ERRBUF_SIZE,
-			    "getsockopt: %s", pcap_strerror(errno));
+			pcap_fmt_errmsg_for_errno(handle->errbuf,
+			    PCAP_ERRBUF_SIZE, errno, "getsockopt");
 			*status = PCAP_ERROR;
 			return -1;
 		}
@@ -4115,8 +4373,8 @@
 				 * PACKET_RESERVE", in which case we fall back
 				 * as best we can.
 				 */
-				pcap_snprintf(handle->errbuf, PCAP_ERRBUF_SIZE,
-				    "getsockopt: %s", pcap_strerror(errno));
+				pcap_fmt_errmsg_for_errno(handle->errbuf,
+				    PCAP_ERRBUF_SIZE, errno, "getsockopt");
 				*status = PCAP_ERROR;
 				return -1;
 			}
@@ -4155,7 +4413,14 @@
 			 */
 		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
@@ -4163,11 +4428,18 @@
 		/* 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:
@@ -4261,9 +4533,9 @@
 				break;
 
 			default:
-				pcap_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;
 			}
@@ -4289,9 +4561,9 @@
 			}
 			if (setsockopt(handle->fd, SOL_PACKET, PACKET_TIMESTAMP,
 				(void *)&timesource, sizeof(timesource))) {
-				pcap_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;
 			}
@@ -4339,9 +4611,8 @@
 			 */
 			return 0;
 		}
-		pcap_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;
 	}
@@ -4351,8 +4622,8 @@
 	handlep->mmapbuf = mmap(0, handlep->mmapbuflen,
 	    PROT_READ|PROT_WRITE, MAP_SHARED, handle->fd, 0);
 	if (handlep->mmapbuf == MAP_FAILED) {
-		pcap_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);
@@ -4364,9 +4635,8 @@
 	handle->cc = req.tp_frame_nr;
 	handle->buffer = malloc(handle->cc * sizeof(union thdr *));
 	if (!handle->buffer) {
-		pcap_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;
@@ -4454,24 +4724,24 @@
 
 
 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(p, nonblock, errbuf) == -1)
+	if (pcap_setnonblock_fd(handle, nonblock) == -1)
 		return -1;
 
 	/*
@@ -4556,9 +4826,9 @@
 		 */
 		ret = poll(&pollinfo, 1, handlep->poll_timeout);
 		if (ret < 0 && errno != EINTR) {
-			pcap_snprintf(handle->errbuf, PCAP_ERRBUF_SIZE,
-				"can't poll on packet socket: %s",
-				pcap_strerror(errno));
+			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))) {
@@ -4596,10 +4866,9 @@
 						PCAP_ERRBUF_SIZE,
 						"The interface went down");
 				} else {
-					pcap_snprintf(handle->errbuf,
-						PCAP_ERRBUF_SIZE,
-						"Error condition on packet socket: %s",
-						strerror(errno));
+					pcap_fmt_errmsg_for_errno(handle->errbuf,
+					    PCAP_ERRBUF_SIZE, errno,
+					    "Error condition on packet socket");
 				}
 				return PCAP_ERROR;
 			}
@@ -4638,6 +4907,7 @@
 	unsigned char *bp;
 	struct sockaddr_ll *sll;
 	struct pcap_pkthdr pcaphdr;
+	unsigned int snaplen = tp_snaplen;
 
 	/* perform sanity check on internal offset. */
 	if (tp_mac + tp_snaplen > handle->bufsize) {
@@ -4698,16 +4968,21 @@
 		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 = tp_vlan_tci & 0x0fff;
 		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, tp_snaplen, &aux_data) == 0)
+		if (bpf_filter_with_aux_data(handle->fcode.bf_insns,
+					     bp,
+					     tp_len,
+					     snaplen,
+					     &aux_data) == 0)
 			return 0;
 	}
 
@@ -4987,11 +5262,7 @@
 				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
+				VLAN_VALID(h.h2, h.h2),
 				h.h2->tp_vlan_tci,
 				VLAN_TPID(h.h2, h.h2));
 		if (ret == 1) {
@@ -5105,11 +5376,7 @@
 					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
+					VLAN_VALID(tp3_hdr, &tp3_hdr->hv1),
 					tp3_hdr->hv1.tp_vlan_tci,
 					VLAN_TPID(tp3_hdr, &tp3_hdr->hv1));
 			if (ret == 1) {
@@ -5257,8 +5524,8 @@
 	strlcpy(ifr.ifr_name, device, sizeof(ifr.ifr_name));
 
 	if (ioctl(fd, SIOCGIFINDEX, &ifr) == -1) {
-		pcap_snprintf(ebuf, PCAP_ERRBUF_SIZE,
-			 "SIOCGIFINDEX: %s", pcap_strerror(errno));
+		pcap_fmt_errmsg_for_errno(ebuf, PCAP_ERRBUF_SIZE,
+		    errno, "SIOCGIFINDEX");
 		return -1;
 	}
 
@@ -5271,7 +5538,7 @@
  *  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;
@@ -5280,7 +5547,7 @@
 	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) {
@@ -5293,8 +5560,8 @@
 			 */
 			return PCAP_ERROR_IFACE_NOT_UP;
 		} else {
-			pcap_snprintf(ebuf, PCAP_ERRBUF_SIZE,
-				 "bind: %s", pcap_strerror(errno));
+			pcap_fmt_errmsg_for_errno(ebuf, PCAP_ERRBUF_SIZE,
+			    errno, "bind");
 			return PCAP_ERROR;
 		}
 	}
@@ -5302,8 +5569,8 @@
 	/* Any pending errors, e.g., network is down? */
 
 	if (getsockopt(fd, SOL_SOCKET, SO_ERROR, &err, &errlen) == -1) {
-		pcap_snprintf(ebuf, PCAP_ERRBUF_SIZE,
-			"getsockopt: %s", pcap_strerror(errno));
+		pcap_fmt_errmsg_for_errno(ebuf, PCAP_ERRBUF_SIZE,
+		    errno, "getsockopt");
 		return 0;
 	}
 
@@ -5317,8 +5584,8 @@
 		 */
 		return PCAP_ERROR_IFACE_NOT_UP;
 	} else if (err > 0) {
-		pcap_snprintf(ebuf, PCAP_ERRBUF_SIZE,
-			"bind: %s", pcap_strerror(err));
+		pcap_fmt_errmsg_for_errno(ebuf, PCAP_ERRBUF_SIZE,
+		    err, "bind");
 		return 0;
 	}
 
@@ -5343,8 +5610,8 @@
 	    sizeof ireq.ifr_ifrn.ifrn_name);
 	if (ioctl(sock_fd, SIOCGIWNAME, &ireq) >= 0)
 		return 1;	/* yes */
-	pcap_snprintf(ebuf, PCAP_ERRBUF_SIZE,
-	    "%s: SIOCGIWNAME: %s", device, pcap_strerror(errno));
+	pcap_fmt_errmsg_for_errno(ebuf, PCAP_ERRBUF_SIZE, errno,
+	    "%s: SIOCGIWNAME", device);
 	if (errno == ENODEV)
 		return PCAP_ERROR_NO_SUCH_DEVICE;
 	return 0;
@@ -5495,9 +5762,8 @@
 			/*
 			 * Failed.
 			 */
-			pcap_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;
 		}
 
@@ -5506,15 +5772,14 @@
 		 */
 		priv = malloc(ireq.u.data.length * sizeof (struct iw_priv_args));
 		if (priv == NULL) {
-			pcap_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) {
-			pcap_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;
 		}
@@ -5768,8 +6033,8 @@
 	memset(&ifr, 0, sizeof(ifr));
 	strlcpy(ifr.ifr_name, device, sizeof(ifr.ifr_name));
 	if (ioctl(sock_fd, SIOCGIFFLAGS, &ifr) == -1) {
-		pcap_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;
@@ -5777,8 +6042,9 @@
 		oldflags = ifr.ifr_flags;
 		ifr.ifr_flags &= ~IFF_UP;
 		if (ioctl(sock_fd, SIOCSIFFLAGS, &ifr) == -1) {
-			pcap_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;
 		}
 	}
@@ -5796,8 +6062,9 @@
 		 */
 		ifr.ifr_flags = oldflags;
 		if (ioctl(sock_fd, SIOCSIFFLAGS, &ifr) == -1) {
-			pcap_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;
@@ -5880,9 +6147,8 @@
 		strlcpy(ireq.ifr_ifrn.ifrn_name, device,
 		    sizeof ireq.ifr_ifrn.ifrn_name);
 		if (ioctl(sock_fd, SIOCGIWFREQ, &ireq) == -1) {
-			pcap_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;
@@ -5957,8 +6223,9 @@
 	if (oldflags != 0) {
 		ifr.ifr_flags = oldflags;
 		if (ioctl(sock_fd, SIOCSIFFLAGS, &ifr) == -1) {
-			pcap_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
@@ -6084,8 +6351,8 @@
 	 */
 	fd = socket(PF_UNIX, SOCK_RAW, 0);
 	if (fd < 0) {
-		(void)pcap_snprintf(ebuf, PCAP_ERRBUF_SIZE,
-		    "socket for SIOCETHTOOL(ETHTOOL_GET_TS_INFO): %s", pcap_strerror(errno));
+		pcap_fmt_errmsg_for_errno(ebuf, PCAP_ERRBUF_SIZE,
+		    errno, "socket for SIOCETHTOOL(ETHTOOL_GET_TS_INFO)");
 		return -1;
 	}
 
@@ -6124,9 +6391,10 @@
 			/*
 			 * Other error.
 			 */
-			pcap_snprintf(ebuf, PCAP_ERRBUF_SIZE,
-			    "%s: SIOCETHTOOL(ETHTOOL_GET_TS_INFO) ioctl failed: %s", device,
-			    strerror(save_errno));
+			pcap_fmt_errmsg_for_errno(ebuf, PCAP_ERRBUF_SIZE,
+			    save_errno,
+			    "%s: SIOCETHTOOL(ETHTOOL_GET_TS_INFO) ioctl failed",
+			    device);
 			return -1;
 		}
 	}
@@ -6226,9 +6494,9 @@
 			 */
 			return 0;
 		}
-		pcap_snprintf(handle->errbuf, PCAP_ERRBUF_SIZE,
-		    "%s: SIOCETHTOOL(%s) ioctl failed: %s", handle->opt.device,
-		    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;
@@ -6317,6 +6585,7 @@
 activate_old(pcap_t *handle)
 {
 	struct pcap_linux *handlep = handle->priv;
+	int		err;
 	int		arptype;
 	struct ifreq	ifr;
 	const char	*device = handle->opt.device;
@@ -6327,9 +6596,10 @@
 
 	handle->fd = socket(PF_INET, SOCK_PACKET, htons(ETH_P_ALL));
 	if (handle->fd == -1) {
-		pcap_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.
@@ -6383,8 +6653,8 @@
 		memset(&ifr, 0, sizeof(ifr));
 		strlcpy(ifr.ifr_name, device, sizeof(ifr.ifr_name));
 		if (ioctl(handle->fd, SIOCGIFFLAGS, &ifr) == -1) {
-			pcap_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) {
@@ -6411,9 +6681,8 @@
 
 			ifr.ifr_flags |= IFF_PROMISC;
 			if (ioctl(handle->fd, SIOCSIFFLAGS, &ifr) == -1) {
-			        pcap_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;
@@ -6521,22 +6790,22 @@
 	memset(&saddr, 0, sizeof(saddr));
 	strlcpy(saddr.sa_data, device, sizeof(saddr.sa_data));
 	if (bind(fd, &saddr, sizeof(saddr)) == -1) {
-		pcap_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) {
-		pcap_snprintf(ebuf, PCAP_ERRBUF_SIZE,
-			"getsockopt: %s", pcap_strerror(errno));
+		pcap_fmt_errmsg_for_errno(ebuf, PCAP_ERRBUF_SIZE,
+		    errno, "getsockopt");
 		return -1;
 	}
 
 	if (err > 0) {
-		pcap_snprintf(ebuf, PCAP_ERRBUF_SIZE,
-			"bind: %s", pcap_strerror(err));
+		pcap_fmt_errmsg_for_errno(ebuf, PCAP_ERRBUF_SIZE,
+		    err, "bind");
 		return -1;
 	}
 
@@ -6561,8 +6830,8 @@
 	strlcpy(ifr.ifr_name, device, sizeof(ifr.ifr_name));
 
 	if (ioctl(fd, SIOCGIFMTU, &ifr) == -1) {
-		pcap_snprintf(ebuf, PCAP_ERRBUF_SIZE,
-			 "SIOCGIFMTU: %s", pcap_strerror(errno));
+		pcap_fmt_errmsg_for_errno(ebuf, PCAP_ERRBUF_SIZE,
+		    errno, "SIOCGIFMTU");
 		return -1;
 	}
 
@@ -6581,8 +6850,8 @@
 	strlcpy(ifr.ifr_name, device, sizeof(ifr.ifr_name));
 
 	if (ioctl(fd, SIOCGIFHWADDR, &ifr) == -1) {
-		pcap_snprintf(ebuf, PCAP_ERRBUF_SIZE,
-			 "SIOCGIFHWADDR: %s", pcap_strerror(errno));
+		pcap_fmt_errmsg_for_errno(ebuf, PCAP_ERRBUF_SIZE,
+		    errno, "SIOCGIFHWADDR");
 		if (errno == ENODEV) {
 			/*
 			 * No such device.
@@ -6614,8 +6883,8 @@
 	len = handle->fcode.bf_len;
 	f = (struct bpf_insn *)malloc(prog_size);
 	if (f == NULL) {
-		pcap_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);
@@ -6791,15 +7060,15 @@
 		 */
 		save_mode = fcntl(handle->fd, F_GETFL, 0);
 		if (save_mode == -1) {
-			pcap_snprintf(handle->errbuf, PCAP_ERRBUF_SIZE,
-			    "can't get FD flags when changing filter: %s",
-			    pcap_strerror(errno));
+			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_snprintf(handle->errbuf, PCAP_ERRBUF_SIZE,
-			    "can't set nonblocking mode when changing filter: %s",
-			    pcap_strerror(errno));
+			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)
@@ -6814,15 +7083,15 @@
 			 */
 			(void)fcntl(handle->fd, F_SETFL, save_mode);
 			(void)reset_kernel_filter(handle);
-			pcap_snprintf(handle->errbuf, PCAP_ERRBUF_SIZE,
-			    "recv failed when changing filter: %s",
-			    pcap_strerror(save_errno));
+			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_snprintf(handle->errbuf, PCAP_ERRBUF_SIZE,
-			    "can't restore FD flags when changing filter: %s",
-			    pcap_strerror(save_errno));
+			pcap_fmt_errmsg_for_errno(handle->errbuf,
+			    PCAP_ERRBUF_SIZE, errno,
+			    "can't restore FD flags when changing filter");
 			return -2;
 		}
 	}
@@ -6851,9 +7120,9 @@
 		 * Report it as a fatal error.
 		 */
 		if (reset_kernel_filter(handle) == -1) {
-			pcap_snprintf(handle->errbuf, PCAP_ERRBUF_SIZE,
-			    "can't remove kernel total filter: %s",
-			    pcap_strerror(errno));
+			pcap_fmt_errmsg_for_errno(handle->errbuf,
+			    PCAP_ERRBUF_SIZE, errno,
+			    "can't remove kernel total filter");
 			return -2;	/* fatal error */
 		}
 
@@ -6865,6 +7134,7 @@
 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,
@@ -6873,7 +7143,45 @@
 	 */
 	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
+}
diff --git a/pcap-netfilter-linux.c b/pcap-netfilter-linux.c
index bde648f..d5c5dcd 100644
--- a/pcap-netfilter-linux.c
+++ b/pcap-netfilter-linux.c
@@ -29,7 +29,7 @@
  */
 
 #ifdef HAVE_CONFIG_H
-#include "config.h"
+#include <config.h>
 #endif
 
 #include "pcap-int.h"
@@ -82,37 +82,90 @@
 	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;
-		}
-		if(errno == ENOBUFS) handlep->packets_nobufs++;
-	} while ((len == -1) && (errno == EINTR || errno == ENOBUFS));
-
-	if (len < 0) {
-		pcap_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));
 
-	buf = (unsigned char *)handle->buffer;
-	while ((u_int)len >= NLMSG_SPACE(0)) {
-		const struct nlmsghdr *nlh = (const struct nlmsghdr *) buf;
-		u_int32_t msg_len;
+		if (len < 0) {
+			pcap_fmt_errmsg_for_errno(handle->errbuf,
+			    PCAP_ERRBUF_SIZE, errno, "Can't receive packet");
+			return PCAP_ERROR;
+		}
+
+		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) || (u_int)len < nlh->nlmsg_len) {
 			pcap_snprintf(handle->errbuf, PCAP_ERRBUF_SIZE, "Message truncated: (got: %d) (nlmsg_len: %u)", len, nlh->nlmsg_len);
@@ -205,12 +258,25 @@
 		}
 
 		msg_len = NLMSG_ALIGN(nlh->nlmsg_len);
-		if (msg_len > (u_int)len)
-			msg_len = (u_int)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;
 
-		len -= msg_len;
-		buf += msg_len;
+		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;
 }
 
@@ -233,20 +299,20 @@
 }
 
 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_)
 {
 	pcap_snprintf(handle->errbuf, PCAP_ERRBUF_SIZE, "inject 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));
 
@@ -310,7 +376,7 @@
 		if (snl.nl_pid != 0 || seq_id != nlh->nlmsg_seq)	/* if not from kernel or wrong sequence skip */
 			continue;
 
-		while ((u_int)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;
@@ -327,13 +393,13 @@
 }
 
 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;
@@ -348,7 +414,7 @@
 }
 
 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)
+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;
@@ -364,7 +430,7 @@
 }
 
 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;
@@ -380,13 +446,13 @@
 }
 
 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;
@@ -402,7 +468,7 @@
 }
 
 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)
+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;
@@ -479,6 +545,17 @@
 		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;
@@ -494,7 +571,8 @@
 	/* Create netlink socket */
 	handle->fd = socket(AF_NETLINK, SOCK_RAW, NETLINK_NETFILTER);
 	if (handle->fd < 0) {
-		pcap_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;
 	}
 
@@ -512,54 +590,68 @@
 
 	handle->buffer = malloc(handle->bufsize);
 	if (!handle->buffer) {
-		pcap_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) {
-			pcap_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) {
-			pcap_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) {
-				pcap_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) {
-				pcap_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) {
-			pcap_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) {
-			pcap_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) {
-				pcap_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) {
-				pcap_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;
 			}
 		}
@@ -578,7 +670,8 @@
 		 * 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) {
-			pcap_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;
 		}
 	}
@@ -635,7 +728,7 @@
 }
 
 int
-netfilter_findalldevs(pcap_if_t **alldevsp, char *err_str)
+netfilter_findalldevs(pcap_if_list_t *devlistp, char *err_str)
 {
 	int sock;
 
@@ -644,15 +737,23 @@
 		/* if netlink is not supported this is not fatal */
 		if (errno == EAFNOSUPPORT || errno == EPROTONOSUPPORT)
 			return 0;
-		pcap_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;
 }
diff --git a/pcap-netfilter-linux.h b/pcap-netfilter-linux.h
index 01d9b39..97b7310 100644
--- a/pcap-netfilter-linux.h
+++ b/pcap-netfilter-linux.h
@@ -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
index 0000000..f150563
--- /dev/null
+++ b/pcap-netmap.c
@@ -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 = 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
index 0000000..6a414fc
--- /dev/null
+++ b/pcap-netmap.h
@@ -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
index 494e425..6fa52e6 100644
--- a/pcap-new.c
+++ b/pcap-new.c
@@ -32,29 +32,26 @@
  */
 
 #ifdef HAVE_CONFIG_H
-#include "config.h"
+#include <config.h>
 #endif
 
+/*
+ * 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 "sockutils.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
+#ifndef _WIN32
 #include <dirent.h>		// for readdir
 #endif
 
-/* Keeps a list of all the opened connections in the active mode. */
-extern struct activehosts *activeHosts;
-
-/*
- * \brief Keeps the main socket identifier when we want to accept a new remote connection (active mode only).
- * See the documentation of pcap_remoteact_accept() and pcap_remoteact_cleanup() for more details.
- */
-SOCKET sockmain;
-
 /* String identifier to be used in the pcap_findalldevs_ex() */
 #define PCAP_TEXT_SOURCE_FILE "File"
 /* String identifier to be used in the pcap_findalldevs_ex() */
@@ -62,21 +59,6 @@
 
 /* String identifier to be used in the pcap_findalldevs_ex() */
 #define PCAP_TEXT_SOURCE_ON_LOCAL_HOST "on local host"
-/* String identifier to be used in the pcap_findalldevs_ex() */
-#define PCAP_TEXT_SOURCE_ON_REMOTE_HOST "on remote node"
-
-/*
-* Private data for capturing on WinPcap devices.
-*/
-struct pcap_win {
-	int nonblock;
-	int rfmon_selfstart;		/* a flag tells whether the monitor mode is set by itself */
-	int filtering_in_kernel;	/* using kernel filter */
-
-#ifdef HAVE_DAG_API
-	int	dag_fcs_bits;		/* Number of checksum bits from link layer */
-#endif
-};
 
 /****************************************************
  *                                                  *
@@ -86,24 +68,16 @@
 
 int pcap_findalldevs_ex(char *source, struct pcap_rmtauth *auth, pcap_if_t **alldevs, char *errbuf)
 {
-	SOCKET sockctrl;		/* socket descriptor of the control connection */
-	uint32 totread = 0;		/* number of bytes of the payload read from the socket */
-	int nread;
-	struct addrinfo hints;		/* temp variable needed to resolve hostnames into to socket representation */
-	struct addrinfo *addrinfo;	/* temp variable needed to resolve hostnames into to socket representation */
-	struct rpcap_header header;	/* structure that keeps the general header of the rpcap protocol */
-	int i, j;		/* temp variables */
-	int naddr;		/* temp var needed to avoid problems with IPv6 addresses */
-	struct pcap_addr *addr;	/* another such temp */
-	int retval;		/* store the return value of the functions */
-	int nif;		/* Number of interfaces listed */
-	int active = 0;	/* 'true' if we the other end-party is in active mode */
-	char host[PCAP_BUF_SIZE], port[PCAP_BUF_SIZE], name[PCAP_BUF_SIZE], path[PCAP_BUF_SIZE], filename[PCAP_BUF_SIZE];
 	int type;
+	char name[PCAP_BUF_SIZE], path[PCAP_BUF_SIZE], filename[PCAP_BUF_SIZE];
 	pcap_t *fp;
 	char tmpstring[PCAP_BUF_SIZE + 1];		/* Needed to convert names and descriptions from 'old' syntax to the 'new' one */
-	pcap_if_t *dev;		/* Previous device into the pcap_if_t chain */
+	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)
 	{
@@ -123,9 +97,10 @@
 	if (pcap_parsesrcstr(source, &type, NULL, NULL, NULL, errbuf) == -1)
 		return -1;
 
-	if (type == PCAP_SRC_IFLOCAL)
+	switch (type)
 	{
-		if (pcap_parsesrcstr(source, &type, host, NULL, NULL, errbuf) == -1)
+	case PCAP_SRC_IFLOCAL:
+		if (pcap_parsesrcstr(source, &type, NULL, NULL, NULL, errbuf) == -1)
 			return -1;
 
 		/* Initialize temporary string */
@@ -135,7 +110,7 @@
 		if (pcap_findalldevs(alldevs, errbuf) == -1)
 			return -1;
 
-		if ((alldevs == NULL) || (*alldevs == NULL))
+		if (*alldevs == NULL)
 		{
 			pcap_snprintf(errbuf, PCAP_ERRBUF_SIZE,
 				"No interfaces found! Make sure libpcap/WinPcap is properly installed"
@@ -159,7 +134,10 @@
 			dev->name = strdup(tmpstring);
 			if (dev->name == NULL)
 			{
-				pcap_snprintf(errbuf, PCAP_ERRBUF_SIZE, "malloc() failed: %s", pcap_strerror(errno));
+				pcap_fmt_errmsg_for_errno(errbuf,
+				    PCAP_ERRBUF_SIZE, errno,
+				    "malloc() failed");
+				pcap_freealldevs(*alldevs);
 				return -1;
 			}
 
@@ -178,7 +156,10 @@
 			dev->description = strdup(tmpstring);
 			if (dev->description == NULL)
 			{
-				pcap_snprintf(errbuf, PCAP_ERRBUF_SIZE, "malloc() failed: %s", pcap_strerror(errno));
+				pcap_fmt_errmsg_for_errno(errbuf,
+				    PCAP_ERRBUF_SIZE, errno,
+				    "malloc() failed");
+				pcap_freealldevs(*alldevs);
 				return -1;
 			}
 
@@ -186,14 +167,11 @@
 		}
 
 		return 0;
-	}
 
-	(*alldevs) = NULL;
-
-	if (type == PCAP_SRC_FILE)
+	case PCAP_SRC_FILE:
 	{
 		size_t stringlen;
-#ifdef WIN32
+#ifdef _WIN32
 		WIN32_FIND_DATA filedata;
 		HANDLE filehandle;
 #else
@@ -201,14 +179,14 @@
 		DIR *unixdir;
 #endif
 
-		if (pcap_parsesrcstr(source, &type, host, port, name, errbuf) == -1)
+		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
+#ifdef _WIN32
 #define ENDING_CHAR '\\'
 #else
 #define ENDING_CHAR '/'
@@ -225,7 +203,7 @@
 		/* Save the path for future reference */
 		pcap_snprintf(path, sizeof(path), "%s", name);
 
-#ifdef WIN32
+#ifdef _WIN32
 		/* To perform directory listing, Win32 must have an 'asterisk' as ending char */
 		if (name[stringlen - 1] != '*')
 		{
@@ -255,10 +233,11 @@
 		}
 #endif
 
+		/* Add all files we find to the list. */
 		do
 		{
 
-#ifdef WIN32
+#ifdef _WIN32
 			pcap_snprintf(filename, sizeof(filename), "%s%s", path, filedata.cFileName);
 #else
 			pcap_snprintf(filename, sizeof(filename), "%s%s", path, filedata->d_name);
@@ -269,37 +248,54 @@
 			if (fp)
 			{
 				/* allocate the main structure */
-				if (*alldevs == NULL)	/* This is in case it is the first file */
-				{
-					(*alldevs) = (pcap_if_t *)malloc(sizeof(pcap_if_t));
-					dev = (*alldevs);
-				}
-				else
-				{
-					dev->next = (pcap_if_t *)malloc(sizeof(pcap_if_t));
-					dev = dev->next;
-				}
-
-				/* check that the malloc() didn't fail */
+				dev = (pcap_if_t *)malloc(sizeof(pcap_if_t));
 				if (dev == NULL)
 				{
-					pcap_snprintf(errbuf, PCAP_ERRBUF_SIZE, "malloc() failed: %s", pcap_strerror(errno));
+					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;
+				}
 
 				stringlen = strlen(tmpstring);
 
 				dev->name = (char *)malloc(stringlen + 1);
 				if (dev->name == NULL)
 				{
-					pcap_snprintf(errbuf, PCAP_ERRBUF_SIZE, "malloc() failed: %s", pcap_strerror(errno));
+					pcap_fmt_errmsg_for_errno(errbuf,
+					    PCAP_ERRBUF_SIZE, errno,
+					    "malloc() failed");
+					pcap_freealldevs(*alldevs);
 					return -1;
 				}
 
@@ -317,7 +313,10 @@
 
 				if (dev->description == NULL)
 				{
-					pcap_snprintf(errbuf, PCAP_ERRBUF_SIZE, "malloc() failed: %s", pcap_strerror(errno));
+					pcap_fmt_errmsg_for_errno(errbuf,
+					    PCAP_ERRBUF_SIZE, errno,
+					    "malloc() failed");
+					pcap_freealldevs(*alldevs);
 					return -1;
 				}
 
@@ -327,14 +326,14 @@
 				pcap_close(fp);
 			}
 		}
-#ifdef WIN32
+#ifdef _WIN32
 		while (FindNextFile(filehandle, &filedata) != 0);
 #else
 		while ( (filedata= readdir(unixdir)) != NULL);
 #endif
 
 
-#ifdef WIN32
+#ifdef _WIN32
 		/* Close the search handle. */
 		FindClose(filehandle);
 #endif
@@ -342,564 +341,21 @@
 		return 0;
 	}
 
-	/* If we come here, it is a remote host */
-
-	/* Retrieve the needed data for getting adapter list */
-	if (pcap_parsesrcstr(source, &type, host, port, NULL, errbuf) == -1)
-		return -1;
-
-	/* Warning: this call can be the first one called by the user. */
-	/* For this reason, we have to initialize the WinSock support. */
-	if (sock_init(errbuf, PCAP_ERRBUF_SIZE) == -1)
-		return -1;
-
-	/* Check for active mode */
-	sockctrl = rpcap_remoteact_getsock(host, &active, errbuf);
-	if (sockctrl == INVALID_SOCKET)
-		return -1;
-
-	if (!active) {
-		/*
-		 * We're not in active mode; let's try to open a new
-		 * control connection.
-		 */
-		addrinfo = NULL;
-
-		memset(&hints, 0, sizeof(struct addrinfo));
-		hints.ai_family = PF_UNSPEC;
-		hints.ai_socktype = SOCK_STREAM;
-
-		if (port[0] == 0)
-		{
-			/* the user chose not to specify the port */
-			if (sock_initaddress(host, RPCAP_DEFAULT_NETPORT, &hints, &addrinfo, errbuf, PCAP_ERRBUF_SIZE) == -1)
-				return -1;
-		}
-		else
-		{
-			if (sock_initaddress(host, port, &hints, &addrinfo, errbuf, PCAP_ERRBUF_SIZE) == -1)
-				return -1;
-		}
-
-		if ((sockctrl = sock_open(addrinfo, SOCKOPEN_CLIENT, 0, errbuf, PCAP_ERRBUF_SIZE)) == -1)
-			goto error;
-
-		/* addrinfo is no longer used */
-		freeaddrinfo(addrinfo);
-		addrinfo = NULL;
-
-		if (rpcap_sendauth(sockctrl, auth, errbuf) == -1)
-		{
-			sock_close(sockctrl, NULL, 0);
-			return -1;
-		}
-	}
-
-	/* RPCAP findalldevs command */
-	rpcap_createhdr(&header, RPCAP_MSG_FINDALLIF_REQ, 0, 0);
-
-	if (sock_send(sockctrl, (char *)&header, sizeof(struct rpcap_header), errbuf, PCAP_ERRBUF_SIZE) == -1)
-		goto error;
-
-	if (sock_recv(sockctrl, (char *)&header, sizeof(struct rpcap_header), SOCK_RECEIVEALL_YES, errbuf, PCAP_ERRBUF_SIZE) == -1)
-		goto error;
-
-	/* Checks if the message is correct */
-	retval = rpcap_checkmsg(errbuf, sockctrl, &header, RPCAP_MSG_FINDALLIF_REPLY, RPCAP_MSG_ERROR, 0);
-
-	if (retval != RPCAP_MSG_FINDALLIF_REPLY)		/* the message is not the one expected */
-	{
-		switch (retval)
-		{
-		case -3:	/* Unrecoverable network error */
-		case -2:	/* The other endpoint send a message that is not allowed here */
-		case -1:	/* The other endpoint has a version number that is not compatible with our */
-			break;
-
-		case RPCAP_MSG_ERROR:		/* The other endpoint reported an error */
-			break;
-
-		default:
-		{
-			pcap_snprintf(errbuf, PCAP_ERRBUF_SIZE, "Internal error");
-			break;
-		};
-		}
-
-		if (!active)
-			sock_close(sockctrl, NULL, 0);
-
-		return -1;
-	}
-
-	/* read the number of interfaces */
-	nif = ntohs(header.value);
-
-	/* loop until all interfaces have been received */
-	for (i = 0; i < nif; i++)
-	{
-		struct rpcap_findalldevs_if findalldevs_if;
-		char tmpstring2[PCAP_BUF_SIZE + 1];		/* Needed to convert names and descriptions from 'old' syntax to the 'new' one */
-		size_t stringlen;
-
-		tmpstring2[PCAP_BUF_SIZE] = 0;
-
-		/* receive the findalldevs structure from remote host */
-		nread = sock_recv(sockctrl, (char *)&findalldevs_if,
-		    sizeof(struct rpcap_findalldevs_if), SOCK_RECEIVEALL_YES,
-		    errbuf, PCAP_ERRBUF_SIZE);
-		if (nread == -1)
-			goto error;
-		totread += nread;
-
-		findalldevs_if.namelen = ntohs(findalldevs_if.namelen);
-		findalldevs_if.desclen = ntohs(findalldevs_if.desclen);
-		findalldevs_if.naddr = ntohs(findalldevs_if.naddr);
-
-		/* allocate the main structure */
-		if (i == 0)
-		{
-			(*alldevs) = (pcap_if_t *)malloc(sizeof(pcap_if_t));
-			dev = (*alldevs);
-		}
-		else
-		{
-			dev->next = (pcap_if_t *)malloc(sizeof(pcap_if_t));
-			dev = dev->next;
-		}
-
-		/* check that the malloc() didn't fail */
-		if (dev == NULL)
-		{
-			pcap_snprintf(errbuf, PCAP_ERRBUF_SIZE, "malloc() failed: %s", pcap_strerror(errno));
-			goto error;
-		}
-
-		/* Initialize the structure to 'zero' */
-		memset(dev, 0, sizeof(pcap_if_t));
-
-		/* allocate mem for name and description */
-		if (findalldevs_if.namelen)
-		{
-
-			if (findalldevs_if.namelen >= sizeof(tmpstring))
-			{
-				pcap_snprintf(errbuf, PCAP_ERRBUF_SIZE, "Interface name too long");
-				goto error;
-			}
-
-			/* Retrieve adapter name */
-			nread = sock_recv(sockctrl, tmpstring,
-			    findalldevs_if.namelen, SOCK_RECEIVEALL_YES,
-			    errbuf, PCAP_ERRBUF_SIZE);
-			if (nread == -1)
-				goto error;
-			totread += nread;
-
-			tmpstring[findalldevs_if.namelen] = 0;
-
-			/* Create the new device identifier */
-			if (pcap_createsrcstr(tmpstring2, PCAP_SRC_IFREMOTE, host, port, tmpstring, errbuf) == -1)
-				return -1;
-
-			stringlen = strlen(tmpstring2);
-
-			dev->name = (char *)malloc(stringlen + 1);
-			if (dev->name == NULL)
-			{
-				pcap_snprintf(errbuf, PCAP_ERRBUF_SIZE, "malloc() failed: %s", pcap_strerror(errno));
-				goto error;
-			}
-
-			/* Copy the new device name into the correct memory location */
-			strlcpy(dev->name, tmpstring2, stringlen + 1);
-		}
-
-		if (findalldevs_if.desclen)
-		{
-			if (findalldevs_if.desclen >= sizeof(tmpstring))
-			{
-				pcap_snprintf(errbuf, PCAP_ERRBUF_SIZE, "Interface description too long");
-				goto error;
-			}
-
-			/* Retrieve adapter description */
-			nread = sock_recv(sockctrl, tmpstring,
-			    findalldevs_if.desclen, SOCK_RECEIVEALL_YES,
-			    errbuf, PCAP_ERRBUF_SIZE);
-			if (nread == -1)
-				goto error;
-			totread += nread;
-
-			tmpstring[findalldevs_if.desclen] = 0;
-
-			pcap_snprintf(tmpstring2, sizeof(tmpstring2) - 1, "%s '%s' %s %s", PCAP_TEXT_SOURCE_ADAPTER,
-				tmpstring, PCAP_TEXT_SOURCE_ON_REMOTE_HOST, host);
-
-			stringlen = strlen(tmpstring2);
-
-			dev->description = (char *)malloc(stringlen + 1);
-
-			if (dev->description == NULL)
-			{
-				pcap_snprintf(errbuf, PCAP_ERRBUF_SIZE, "malloc() failed: %s", pcap_strerror(errno));
-				goto error;
-			}
-
-			/* Copy the new device description into the correct memory location */
-			strlcpy(dev->description, tmpstring2, stringlen + 1);
-		}
-
-		dev->flags = ntohl(findalldevs_if.flags);
-
-		naddr = 0;
-		addr = NULL;
-		/* loop until all addresses have been received */
-		for (j = 0; j < findalldevs_if.naddr; j++)
-		{
-			struct rpcap_findalldevs_ifaddr ifaddr;
-
-			/* Retrieve the interface addresses */
-			nread = sock_recv(sockctrl, (char *)&ifaddr,
-			    sizeof(struct rpcap_findalldevs_ifaddr),
-			    SOCK_RECEIVEALL_YES, errbuf, PCAP_ERRBUF_SIZE);
-			if (nread == -1)
-				goto error;
-			totread += nread;
-
-			/*
-			 * WARNING libpcap bug: the address listing is
-			 * available only for AF_INET.
-			 *
-			 * XXX - IPv6?
-			 */
-			if (ntohs(ifaddr.addr.ss_family) == AF_INET)
-			{
-				if (addr == NULL)
-				{
-					dev->addresses = (struct pcap_addr *) malloc(sizeof(struct pcap_addr));
-					addr = dev->addresses;
-				}
-				else
-				{
-					addr->next = (struct pcap_addr *) malloc(sizeof(struct pcap_addr));
-					addr = addr->next;
-				}
-				naddr++;
-
-				if (addr == NULL)
-				{
-					pcap_snprintf(errbuf, PCAP_ERRBUF_SIZE, "malloc() failed: %s", pcap_strerror(errno));
-					goto error;
-				}
-				addr->next = NULL;
-
-				if (rpcap_deseraddr((struct sockaddr_storage *) &ifaddr.addr,
-					(struct sockaddr_storage **) &addr->addr, errbuf) == -1)
-					goto error;
-				if (rpcap_deseraddr((struct sockaddr_storage *) &ifaddr.netmask,
-					(struct sockaddr_storage **) &addr->netmask, errbuf) == -1)
-					goto error;
-				if (rpcap_deseraddr((struct sockaddr_storage *) &ifaddr.broadaddr,
-					(struct sockaddr_storage **) &addr->broadaddr, errbuf) == -1)
-					goto error;
-				if (rpcap_deseraddr((struct sockaddr_storage *) &ifaddr.dstaddr,
-					(struct sockaddr_storage **) &addr->dstaddr, errbuf) == -1)
-					goto error;
-
-				if ((addr->addr == NULL) && (addr->netmask == NULL) &&
-					(addr->broadaddr == NULL) && (addr->dstaddr == NULL))
-				{
-					free(addr);
-					addr = NULL;
-					if (naddr == 1)
-						naddr = 0;	/* the first item of the list had NULL addresses */
-				}
-			}
-		}
-	}
-
-	/* Checks if all the data has been read; if not, discard the data in excess */
-	if (totread != ntohl(header.plen))
-	{
-		if (sock_discard(sockctrl, ntohl(header.plen) - totread, errbuf, PCAP_ERRBUF_SIZE) == 1)
-			return -1;
-	}
-
-	/* Control connection has to be closed only in case the remote machine is in passive mode */
-	if (!active)
-	{
-		/* DO not send RPCAP_CLOSE, since we did not open a pcap_t; no need to free resources */
-		if (sock_close(sockctrl, errbuf, PCAP_ERRBUF_SIZE))
-			return -1;
-	}
-
-	/* To avoid inconsistencies in the number of sock_init() */
-	sock_cleanup();
-
-	return 0;
-
-error:
-	/*
-	 * In case there has been an error, I don't want to overwrite it with a new one
-	 * if the following call fails. I want to return always the original error.
-	 *
-	 * Take care: this connection can already be closed when we try to close it.
-	 * This happens because a previous error in the rpcapd, which requested to
-	 * closed the connection. In that case, we already recognized that into the
-	 * rpspck_isheaderok() and we already acknowledged the closing.
-	 * In that sense, this call is useless here (however it is needed in case
-	 * the client generates the error).
-	 *
-	 * Checks if all the data has been read; if not, discard the data in excess
-	 */
-	if (totread != ntohl(header.plen))
-	{
-		if (sock_discard(sockctrl, ntohl(header.plen) - totread, NULL, 0) == 1)
-			return -1;
-	}
-
-	/* Control connection has to be closed only in case the remote machine is in passive mode */
-	if (!active)
-		sock_close(sockctrl, NULL, 0);
-
-	/* To avoid inconsistencies in the number of sock_init() */
-	sock_cleanup();
-
-	return -1;
-}
-
-int pcap_createsrcstr(char *source, int type, const char *host, const char *port, const char *name, char *errbuf)
-{
-	switch (type)
-	{
-	case PCAP_SRC_FILE:
-	{
-		strlcpy(source, PCAP_SRC_FILE_STRING, PCAP_BUF_SIZE);
-		if ((name) && (*name))
-		{
-			strlcat(source, name, PCAP_BUF_SIZE);
-			return 0;
-		}
-		else
-		{
-			pcap_snprintf(errbuf, PCAP_ERRBUF_SIZE, "The file name cannot be NULL.");
-			return -1;
-		}
-	}
-
 	case PCAP_SRC_IFREMOTE:
-	{
-		strlcpy(source, PCAP_SRC_IF_STRING, PCAP_BUF_SIZE);
-		if ((host) && (*host))
-		{
-			if ((strcspn(host, "aAbBcCdDeEfFgGhHjJkKlLmMnNoOpPqQrRsStTuUvVwWxXyYzZ")) == strlen(host))
-			{
-				/* the host name does not contains alphabetic chars. So, it is a numeric address */
-				/* In this case we have to include it between square brackets */
-				strlcat(source, "[", PCAP_BUF_SIZE);
-				strlcat(source, host, PCAP_BUF_SIZE);
-				strlcat(source, "]", PCAP_BUF_SIZE);
-			}
-			else
-				strlcat(source, host, PCAP_BUF_SIZE);
-
-			if ((port) && (*port))
-			{
-				strlcat(source, ":", PCAP_BUF_SIZE);
-				strlcat(source, port, PCAP_BUF_SIZE);
-			}
-
-			strlcat(source, "/", PCAP_BUF_SIZE);
-		}
-		else
-		{
-			pcap_snprintf(errbuf, PCAP_ERRBUF_SIZE, "The host name cannot be NULL.");
-			return -1;
-		}
-
-		if ((name) && (*name))
-			strlcat(source, name, PCAP_BUF_SIZE);
-
-		return 0;
-	}
-
-	case PCAP_SRC_IFLOCAL:
-	{
-		strlcpy(source, PCAP_SRC_IF_STRING, PCAP_BUF_SIZE);
-
-		if ((name) && (*name))
-			strlcat(source, name, PCAP_BUF_SIZE);
-
-		return 0;
-	}
+		return pcap_findalldevs_ex_remote(source, auth, alldevs, errbuf);
 
 	default:
-	{
-		pcap_snprintf(errbuf, PCAP_ERRBUF_SIZE, "The interface type is not valid.");
+		strlcpy(errbuf, "Source type not supported", PCAP_ERRBUF_SIZE);
 		return -1;
 	}
-	}
 }
 
-int pcap_parsesrcstr(const char *source, int *type, char *host, char *port, char *name, char *errbuf)
-{
-	char *ptr;
-	int ntoken;
-	char tmpname[PCAP_BUF_SIZE];
-	char tmphost[PCAP_BUF_SIZE];
-	char tmpport[PCAP_BUF_SIZE];
-	int tmptype;
-
-	/* Initialization stuff */
-	tmpname[0] = 0;
-	tmphost[0] = 0;
-	tmpport[0] = 0;
-
-	if (host)
-		*host = 0;
-	if (port)
-		*port = 0;
-	if (name)
-		*name = 0;
-
-	/* Look for a 'rpcap://' identifier */
-	if ((ptr = strstr(source, PCAP_SRC_IF_STRING)) != NULL)
-	{
-		if (strlen(PCAP_SRC_IF_STRING) == strlen(source))
-		{
-			/* The source identifier contains only the 'rpcap://' string. */
-			/* So, this is a local capture. */
-			*type = PCAP_SRC_IFLOCAL;
-			return 0;
-		}
-
-		ptr += strlen(PCAP_SRC_IF_STRING);
-
-		if (strchr(ptr, '[')) /* This is probably a numeric address */
-		{
-			ntoken = sscanf(ptr, "[%[1234567890:.]]:%[^/]/%s", tmphost, tmpport, tmpname);
-
-			if (ntoken == 1)	/* probably the port is missing */
-				ntoken = sscanf(ptr, "[%[1234567890:.]]/%s", tmphost, tmpname);
-
-			tmptype = PCAP_SRC_IFREMOTE;
-		}
-		else
-		{
-			ntoken = sscanf(ptr, "%[^/:]:%[^/]/%s", tmphost, tmpport, tmpname);
-
-			if (ntoken == 1)
-			{
-				/*
-				 * This can be due to two reasons:
-				 * - we want a remote capture, but the network port is missing
-				 * - we want to do a local capture
-				 * To distinguish between the two, we look for the '/' char
-				 */
-				if (strchr(ptr, '/'))
-				{
-					/* We're on a remote capture */
-					sscanf(ptr, "%[^/]/%s", tmphost, tmpname);
-					tmptype = PCAP_SRC_IFREMOTE;
-				}
-				else
-				{
-					/* We're on a local capture */
-					if (*ptr)
-						strlcpy(tmpname, ptr, PCAP_BUF_SIZE);
-
-					/* Clean the host name, since it is a remote capture */
-					/* NOTE: the host name has been assigned in the previous "ntoken= sscanf(...)" line */
-					tmphost[0] = 0;
-
-					tmptype = PCAP_SRC_IFLOCAL;
-				}
-			}
-			else
-				tmptype = PCAP_SRC_IFREMOTE;
-		}
-
-		if (host)
-			strlcpy(host, tmphost, PCAP_BUF_SIZE);
-		if (port)
-			strlcpy(port, tmpport, PCAP_BUF_SIZE);
-		if (type)
-			*type = tmptype;
-
-		if (name)
-		{
-			/*
-			 * If the user wants the host name, but it cannot be located into the source string, return error
-			 * However, if the user is not interested in the interface name (e.g. if we're called by
-			 * pcap_findalldevs_ex(), which does not have interface name, do not return error
-			 */
-			if (tmpname[0])
-			{
-				strlcpy(name, tmpname, PCAP_BUF_SIZE);
-			}
-			else
-			{
-				if (errbuf)
-					pcap_snprintf(errbuf, PCAP_ERRBUF_SIZE, "The interface name has not been specified in the source string.");
-
-				return -1;
-			}
-		}
-
-		return 0;
-	}
-
-	/* Look for a 'file://' identifier */
-	if ((ptr = strstr(source, PCAP_SRC_FILE_STRING)) != NULL)
-	{
-		ptr += strlen(PCAP_SRC_FILE_STRING);
-		if (*ptr)
-		{
-			if (name)
-				strlcpy(name, ptr, PCAP_BUF_SIZE);
-
-			if (type)
-				*type = PCAP_SRC_FILE;
-
-			return 0;
-		}
-		else
-		{
-			if (errbuf)
-				pcap_snprintf(errbuf, PCAP_ERRBUF_SIZE, "The file name has not been specified in the source string.");
-
-			return -1;
-		}
-
-	}
-
-	/* Backward compatibility; the user didn't use the 'rpcap://, file://'  specifiers */
-	if ((source) && (*source))
-	{
-		if (name)
-			strlcpy(name, source, PCAP_BUF_SIZE);
-
-		if (type)
-			*type = PCAP_SRC_IFLOCAL;
-
-		return 0;
-	}
-	else
-	{
-		if (errbuf)
-			pcap_snprintf(errbuf, PCAP_ERRBUF_SIZE, "The interface name has not been specified in the source string.");
-
-		return -1;
-	}
-};
-
 pcap_t *pcap_open(const char *source, int snaplen, int flags, int read_timeout, struct pcap_rmtauth *auth, char *errbuf)
 {
-	char host[PCAP_BUF_SIZE], port[PCAP_BUF_SIZE], name[PCAP_BUF_SIZE];
+	char name[PCAP_BUF_SIZE];
 	int type;
 	pcap_t *fp;
-	int result;
+	int status;
 
 	if (strlen(source) > PCAP_BUF_SIZE)
 	{
@@ -907,359 +363,92 @@
 		return NULL;
 	}
 
-	/* determine the type of the source (file, local, remote) */
-	if (pcap_parsesrcstr(source, &type, host, port, name, errbuf) == -1)
+	/*
+	 * 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:
-		fp = pcap_open_offline(name, errbuf);
+		return pcap_open_offline(name, errbuf);
+
+	case PCAP_SRC_IFLOCAL:
+		fp = pcap_create(name, errbuf);
 		break;
 
 	case PCAP_SRC_IFREMOTE:
-		fp = pcap_create(source, errbuf);
-		if (fp == NULL)
-		{
-			return NULL;
-		}
-
 		/*
-		 * Although we already have host, port and iface, we prefer TO PASS only 'pars' to the
-		 * pcap_open_remote() so that it has to call the pcap_parsesrcstr() again.
+		 * 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.
 		 */
-
-		result = pcap_opensource_remote(fp, auth);
-
-		if (result != 0)
-		{
-			pcap_close(fp);
-			return NULL;
-		}
-
-		struct pcap_md *md;				/* structure used when doing a remote live capture */
-		md = (struct pcap_md *) ((u_char*)fp->priv + sizeof(struct pcap_win));
-
-		fp->snapshot = snaplen;
-		fp->opt.timeout = read_timeout;
-		md->rmt_flags = flags;
-		break;
-
-	case PCAP_SRC_IFLOCAL:
-
-		fp = pcap_open_live(name, snaplen, (flags & PCAP_OPENFLAG_PROMISCUOUS), read_timeout, errbuf);
-
-#ifdef WIN32
-		/*
-		 * these flags are supported on Windows only
-		 */
-		if (fp != NULL && fp->adapter != NULL)
-		{
-			/* disable loopback capture if requested */
-			if (flags & PCAP_OPENFLAG_NOCAPTURE_LOCAL)
-			{
-				if (!PacketSetLoopbackBehavior(fp->adapter, NPF_DISABLE_LOOPBACK))
-				{
-					pcap_snprintf(errbuf, PCAP_ERRBUF_SIZE, "Unable to disable the capture of loopback packets.");
-					pcap_close(fp);
-					return NULL;
-				}
-			}
-
-			/* set mintocopy to zero if requested */
-			if (flags & PCAP_OPENFLAG_MAX_RESPONSIVENESS)
-			{
-				if (!PacketSetMinToCopy(fp->adapter, 0))
-				{
-					pcap_snprintf(errbuf, PCAP_ERRBUF_SIZE, "Unable to set max responsiveness.");
-					pcap_close(fp);
-					return NULL;
-				}
-			}
-		}
-#endif /* WIN32 */
-
-		break;
+		return pcap_open_rpcap(source, snaplen, flags, read_timeout, auth, errbuf);
 
 	default:
 		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)
 {
-	struct pcap_md *md;				/* structure used when doing a remote live capture */
-
-	md = (struct pcap_md *) ((u_char*)p->priv + sizeof(struct pcap_win));
-	return &(md->rmt_samp);
-}
-
-SOCKET pcap_remoteact_accept(const char *address, const char *port, const char *hostlist, char *connectinghost, struct pcap_rmtauth *auth, char *errbuf)
-{
-	/* socket-related variables */
-	struct addrinfo hints;			/* temporary struct to keep settings needed to open the new socket */
-	struct addrinfo *addrinfo;		/* keeps the addrinfo chain; required to open a new socket */
-	struct sockaddr_storage from;	/* generic sockaddr_storage variable */
-	socklen_t fromlen;				/* keeps the length of the sockaddr_storage variable */
-	SOCKET sockctrl;				/* keeps the main socket identifier */
-	struct activehosts *temp, *prev;	/* temp var needed to scan he host list chain */
-
-	*connectinghost = 0;		/* just in case */
-
-	/* Prepare to open a new server socket */
-	memset(&hints, 0, sizeof(struct addrinfo));
-	/* WARNING Currently it supports only ONE socket family among ipv4 and IPv6  */
-	hints.ai_family = AF_INET;		/* PF_UNSPEC to have both IPv4 and IPv6 server */
-	hints.ai_flags = AI_PASSIVE;	/* Ready to a bind() socket */
-	hints.ai_socktype = SOCK_STREAM;
-
-	/* Warning: this call can be the first one called by the user. */
-	/* For this reason, we have to initialize the WinSock support. */
-	if (sock_init(errbuf, PCAP_ERRBUF_SIZE) == -1)
-		return -1;
-
-	/* Do the work */
-	if ((port == NULL) || (port[0] == 0))
-	{
-		if (sock_initaddress(address, RPCAP_DEFAULT_NETPORT_ACTIVE, &hints, &addrinfo, errbuf, PCAP_ERRBUF_SIZE) == -1)
-		{
-			SOCK_ASSERT(errbuf, 1);
-			return -2;
-		}
-	}
-	else
-	{
-		if (sock_initaddress(address, port, &hints, &addrinfo, errbuf, PCAP_ERRBUF_SIZE) == -1)
-		{
-			SOCK_ASSERT(errbuf, 1);
-			return -2;
-		}
-	}
-
-
-	if ((sockmain = sock_open(addrinfo, SOCKOPEN_SERVER, 1, errbuf, PCAP_ERRBUF_SIZE)) == -1)
-	{
-		SOCK_ASSERT(errbuf, 1);
-		return -2;
-	}
-
-	/* Connection creation */
-	fromlen = sizeof(struct sockaddr_storage);
-
-	sockctrl = accept(sockmain, (struct sockaddr *) &from, &fromlen);
-
-	/* We're not using sock_close, since we do not want to send a shutdown */
-	/* (which is not allowed on a non-connected socket) */
-	closesocket(sockmain);
-	sockmain = 0;
-
-	if (sockctrl == -1)
-	{
-		sock_geterror("accept(): ", errbuf, PCAP_ERRBUF_SIZE);
-		return -2;
-	}
-
-	/* Get the numeric for of the name of the connecting host */
-	if (getnameinfo((struct sockaddr *) &from, fromlen, connectinghost, RPCAP_HOSTLIST_SIZE, NULL, 0, NI_NUMERICHOST))
-	{
-		sock_geterror("getnameinfo(): ", errbuf, PCAP_ERRBUF_SIZE);
-		rpcap_senderror(sockctrl, errbuf, PCAP_ERR_REMOTEACCEPT, NULL);
-		sock_close(sockctrl, NULL, 0);
-		return -1;
-	}
-
-	/* checks if the connecting host is among the ones allowed */
-	if (sock_check_hostlist((char *)hostlist, RPCAP_HOSTLIST_SEP, &from, errbuf, PCAP_ERRBUF_SIZE) < 0)
-	{
-		rpcap_senderror(sockctrl, errbuf, PCAP_ERR_REMOTEACCEPT, NULL);
-		sock_close(sockctrl, NULL, 0);
-		return -1;
-	}
-
-	/* Send authentication to the remote machine */
-	if (rpcap_sendauth(sockctrl, auth, errbuf) == -1)
-	{
-		rpcap_senderror(sockctrl, errbuf, PCAP_ERR_REMOTEACCEPT, NULL);
-		sock_close(sockctrl, NULL, 0);
-		return -3;
-	}
-
-	/* Checks that this host does not already have a cntrl connection in place */
-
-	/* Initialize pointers */
-	temp = activeHosts;
-	prev = NULL;
-
-	while (temp)
-	{
-		/* This host already has an active connection in place, so I don't have to update the host list */
-		if (sock_cmpaddr(&temp->host, &from) == 0)
-			return sockctrl;
-
-		prev = temp;
-		temp = temp->next;
-	}
-
-	/* The host does not exist in the list; so I have to update the list */
-	if (prev)
-	{
-		prev->next = (struct activehosts *) malloc(sizeof(struct activehosts));
-		temp = prev->next;
-	}
-	else
-	{
-		activeHosts = (struct activehosts *) malloc(sizeof(struct activehosts));
-		temp = activeHosts;
-	}
-
-	if (temp == NULL)
-	{
-		pcap_snprintf(errbuf, PCAP_ERRBUF_SIZE, "malloc() failed: %s", pcap_strerror(errno));
-		rpcap_senderror(sockctrl, errbuf, PCAP_ERR_REMOTEACCEPT, NULL);
-		sock_close(sockctrl, NULL, 0);
-		return -1;
-	}
-
-	memcpy(&temp->host, &from, fromlen);
-	temp->sockctrl = sockctrl;
-	temp->next = NULL;
-
-	return sockctrl;
-}
-
-int pcap_remoteact_close(const char *host, char *errbuf)
-{
-	struct activehosts *temp, *prev;	/* temp var needed to scan the host list chain */
-	struct addrinfo hints, *addrinfo, *ai_next;	/* temp var needed to translate between hostname to its address */
-	int retval;
-
-	temp = activeHosts;
-	prev = NULL;
-
-	/* retrieve the network address corresponding to 'host' */
-	addrinfo = NULL;
-	memset(&hints, 0, sizeof(struct addrinfo));
-	hints.ai_family = PF_UNSPEC;
-	hints.ai_socktype = SOCK_STREAM;
-
-	retval = getaddrinfo(host, "0", &hints, &addrinfo);
-	if (retval != 0)
-	{
-		pcap_snprintf(errbuf, PCAP_ERRBUF_SIZE, "getaddrinfo() %s", gai_strerror(retval));
-		return -1;
-	}
-
-	while (temp)
-	{
-		ai_next = addrinfo;
-		while (ai_next)
-		{
-			if (sock_cmpaddr(&temp->host, (struct sockaddr_storage *) ai_next->ai_addr) == 0)
-			{
-				struct rpcap_header header;
-
-				/* Close this connection */
-				rpcap_createhdr(&header, RPCAP_MSG_CLOSE, 0, 0);
-
-				/* I don't check for errors, since I'm going to close everything */
-				sock_send(temp->sockctrl, (char *)&header, sizeof(struct rpcap_header), errbuf, PCAP_ERRBUF_SIZE);
-
-				if (sock_close(temp->sockctrl, errbuf, PCAP_ERRBUF_SIZE))
-				{
-					/* To avoid inconsistencies in the number of sock_init() */
-					sock_cleanup();
-
-					return -1;
-				}
-
-				if (prev)
-					prev->next = temp->next;
-				else
-					activeHosts = temp->next;
-
-				freeaddrinfo(addrinfo);
-
-				free(temp);
-
-				/* To avoid inconsistencies in the number of sock_init() */
-				sock_cleanup();
-
-				return 0;
-			}
-
-			ai_next = ai_next->ai_next;
-		}
-		prev = temp;
-		temp = temp->next;
-	}
-
-	if (addrinfo)
-		freeaddrinfo(addrinfo);
-
-	/* To avoid inconsistencies in the number of sock_init() */
-	sock_cleanup();
-
-	pcap_snprintf(errbuf, PCAP_ERRBUF_SIZE, "The host you want to close the active connection is not known");
-	return -1;
-}
-
-void pcap_remoteact_cleanup(void)
-{
-	/* Very dirty, but it works */
-	if (sockmain)
-	{
-		closesocket(sockmain);
-
-		/* To avoid inconsistencies in the number of sock_init() */
-		sock_cleanup();
-	}
-
-}
-
-int pcap_remoteact_list(char *hostlist, char sep, int size, char *errbuf)
-{
-	struct activehosts *temp;	/* temp var needed to scan the host list chain */
-	size_t len;
-	char hoststr[RPCAP_HOSTLIST_SIZE + 1];
-
-	temp = activeHosts;
-
-	len = 0;
-	*hostlist = 0;
-
-	while (temp)
-	{
-		/*int sock_getascii_addrport(const struct sockaddr_storage *sockaddr, char *address, int addrlen, char *port, int portlen, int flags, char *errbuf, int errbuflen) */
-
-		/* Get the numeric form of the name of the connecting host */
-		if (sock_getascii_addrport((struct sockaddr_storage *) &temp->host, hoststr,
-			RPCAP_HOSTLIST_SIZE, NULL, 0, NI_NUMERICHOST, errbuf, PCAP_ERRBUF_SIZE) != -1)
-			/*	if (getnameinfo( (struct sockaddr *) &temp->host, sizeof (struct sockaddr_storage), hoststr, */
-			/*		RPCAP_HOSTLIST_SIZE, NULL, 0, NI_NUMERICHOST) ) */
-		{
-			/*	sock_geterror("getnameinfo(): ", errbuf, PCAP_ERRBUF_SIZE); */
-			return -1;
-		}
-
-		len = len + strlen(hoststr) + 1 /* the separator */;
-
-		if ((size < 0) || (len >= (size_t)size))
-		{
-			pcap_snprintf(errbuf, PCAP_ERRBUF_SIZE, "The string you provided is not able to keep "
-				"the hostnames for all the active connections");
-			return -1;
-		}
-
-		strlcat(hostlist, hoststr, PCAP_ERRBUF_SIZE);
-		hostlist[len - 1] = sep;
-		hostlist[len] = 0;
-
-		temp = temp->next;
-	}
-
-	return 0;
+	return &p->rmt_samp;
 }
diff --git a/pcap-nit.c b/pcap-nit.c
index 1b626e2..6a1a77c 100644
--- a/pcap-nit.c
+++ b/pcap-nit.c
@@ -20,7 +20,7 @@
  */
 
 #ifdef HAVE_CONFIG_H
-#include "config.h"
+#include <config.h>
 #endif
 
 #include <sys/types.h>
@@ -114,8 +114,8 @@
 		if (cc < 0) {
 			if (errno == EWOULDBLOCK)
 				return (0);
-			pcap_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 = (u_char *)p->buffer;
@@ -206,8 +206,8 @@
 	strncpy(sa.sa_data, device, sizeof(sa.sa_data));
 	ret = sendto(p->fd, buf, size, 0, &sa, sizeof(sa));
 	if (ret == -1) {
-		pcap_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);
@@ -249,8 +249,8 @@
 		nioc.nioc_flags |= NF_PROMISC;
 
 	if (ioctl(p->fd, SIOCSNIT, &nioc) < 0) {
-		pcap_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 @@
 		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,8 +291,8 @@
 	memset(p, 0, sizeof(*p));
 	p->fd = fd = socket(AF_NIT, SOCK_RAW, NITPROTO_RAW);
 	if (fd < 0) {
-		pcap_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;
@@ -295,8 +306,8 @@
 		 * they might be the same error, if they both end up
 		 * meaning "NIT doesn't know about that device".
 		 */
-		pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
-		    "bind: %s: %s", snit.snit_ifname, pcap_strerror(errno));
+		pcap_fmt_errmsg_for_errno(p->errbuf, PCAP_ERRBUF_SIZE,
+		    errno, "bind: %s", snit.snit_ifname);
 		goto bad;
 	}
 	if (nit_setflags(p) < 0)
@@ -310,7 +321,8 @@
 	p->bufsize = BUFSPACE;
 	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;
 	}
 
@@ -377,8 +389,29 @@
 	return (1);
 }
 
-int
-pcap_platform_finddevs(pcap_if_t **alldevsp, char *errbuf)
+static int
+get_if_flags(const char *name _U_, bpf_u_int32 *flags _U_, char *errbuf _U_)
 {
-	return (pcap_findalldevs_interfaces(alldevsp, errbuf, can_be_bound));
+	/*
+	 * 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
index 0000000..a9ff0ff
--- /dev/null
+++ b/pcap-npf.c
@@ -0,0 +1,2098 @@
+/*
+ * 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 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)) {
+		char errmsgbuf[PCAP_ERRBUF_SIZE+1];
+
+		pcap_win32_err_to_str(GetLastError(), errmsgbuf);
+		pcap_snprintf(errbuf, PCAP_ERRBUF_SIZE,
+		    "Error calling PacketRequest: %s", errmsgbuf);
+		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;
+	char errbuf[PCAP_ERRBUF_SIZE+1];
+
+	/*
+	 * Try to get statistics.
+	 *
+	 * (Please note - "struct pcap_stat" is *not* the same as
+	 * WinPcap's "struct bpf_stat". It might currently have the
+	 * same layout, but let's not cheat.
+	 *
+	 * Note also that we don't fill in ps_capt, as we might have
+	 * been called by code compiled against an earlier version of
+	 * WinPcap that didn't have ps_capt, in which case filling it
+	 * in would stomp on whatever comes after the structure passed
+	 * to us.
+	 */
+	if (!PacketGetStats(pw->adapter, &bstats)) {
+		pcap_win32_err_to_str(GetLastError(), errbuf);
+		pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
+		    "PacketGetStats error: %s", errbuf);
+		return (-1);
+	}
+	ps->ps_recv = bstats.bs_recv;
+	ps->ps_drop = bstats.bs_drop;
+
+	/*
+	 * XXX - PacketGetStats() doesn't fill this in, so we just
+	 * return 0.
+	 */
+#if 0
+	ps->ps_ifdrop = bstats.ps_ifdrop;
+#else
+	ps->ps_ifdrop = 0;
+#endif
+
+	return (0);
+}
+
+/*
+ * 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;
+	char errbuf[PCAP_ERRBUF_SIZE+1];
+
+	*pcap_stat_size = sizeof (p->stat);
+
+	/*
+	 * Try to get statistics.
+	 *
+	 * (Please note - "struct pcap_stat" is *not* the same as
+	 * WinPcap's "struct bpf_stat". It might currently have the
+	 * same layout, but let's not cheat.)
+	 */
+	if (!PacketGetStatsEx(pw->adapter, &bstats)) {
+		pcap_win32_err_to_str(GetLastError(), errbuf);
+		pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
+		    "PacketGetStatsEx error: %s", errbuf);
+		return (NULL);
+	}
+	p->stat.ps_recv = bstats.bs_recv;
+	p->stat.ps_drop = bstats.bs_drop;
+	p->stat.ps_ifdrop = bstats.ps_ifdrop;
+#ifdef 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;
+	char errbuf[PCAP_ERRBUF_SIZE+1];
+
+	/*
+	 * Allocate a PACKET_OID_DATA structure to hand to PacketRequest().
+	 * It should be big enough to hold "*lenp" bytes of data; it
+	 * will actually be slightly larger, as PACKET_OID_DATA has a
+	 * 1-byte data array at the end, standing in for the variable-length
+	 * data that's actually there.
+	 */
+	oid_data_arg = malloc(sizeof (PACKET_OID_DATA) + *lenp);
+	if (oid_data_arg == NULL) {
+		pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
+		    "Couldn't allocate argument buffer for PacketRequest");
+		return (PCAP_ERROR);
+	}
+
+	oid_data_arg->Oid = oid;
+	oid_data_arg->Length = (ULONG)(*lenp);	/* XXX - check for ridiculously large value? */
+	memcpy(oid_data_arg->Data, data, *lenp);
+	if (!PacketRequest(pw->adapter, TRUE, oid_data_arg)) {
+		pcap_win32_err_to_str(GetLastError(), errbuf);
+		pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
+		    "Error calling PacketRequest: %s", errbuf);
+		free(oid_data_arg);
+		return (PCAP_ERROR);
+	}
+
+	/*
+	 * Get the length actually copied.
+	 */
+	*lenp = oid_data_arg->Length;
+
+	/*
+	 * No need to copy the data - we're doing a set.
+	 */
+	free(oid_data_arg);
+	return (0);
+}
+
+static u_int
+pcap_sendqueue_transmit_npf(pcap_t *p, pcap_send_queue *queue, int sync)
+{
+	struct pcap_win *pw = p->priv;
+	u_int res;
+	char errbuf[PCAP_ERRBUF_SIZE+1];
+
+	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_win32_err_to_str(GetLastError(), errbuf);
+		pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
+		    "Error opening adapter: %s", errbuf);
+	}
+
+	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)) {
+			pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "read error: PacketReceivePacket failed");
+			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;
+	char errbuf[PCAP_ERRBUF_SIZE+1];
+
+	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)
+	{
+		/* Adapter detected but we are not able to open it. Return failure. */
+		pcap_win32_err_to_str(GetLastError(), errbuf);
+		if (pw->rfmon_selfstart)
+		{
+			PacketSetMonitorMode(p->opt.device, 0);
+		}
+		pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
+		    "Error opening adapter: %s", errbuf);
+		return (PCAP_ERROR);
+	}
+
+	/*get network type*/
+	if(PacketGetNetType (pw->adapter,&type) == FALSE)
+	{
+		pcap_win32_err_to_str(GetLastError(), errbuf);
+		pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
+		    "Cannot determine the network type: %s", errbuf);
+		goto bad;
+	}
+
+	/*Set the linktype*/
+	switch (type.LinkType)
+	{
+	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;
+	}
+
+	/*
+	 * 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_win32_err_to_str(GetLastError(), errbuf);
+				pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
+				    "Error calling PacketSetMinToCopy: %s",
+				    errbuf);
+				goto bad;
+			}
+		}
+		else
+		{
+			/* tell the driver to copy the buffer only if it contains at least 16K */
+			if(PacketSetMinToCopy(pw->adapter,16000)==FALSE)
+			{
+				pcap_win32_err_to_str(GetLastError(), errbuf);
+				pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
+				    "Error calling PacketSetMinToCopy: %s",
+				    errbuf);
+				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 (0);
+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)
+	{
+		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;
+	char win_errbuf[PCAP_ERRBUF_SIZE+1];
+
+	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_win32_err_to_str(GetLastError(), win_errbuf);
+		pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
+		    "PacketSetReadTimeout: %s", win_errbuf);
+		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;
+	char our_errbuf[PCAP_ERRBUF_SIZE+1];
+
+	/*
+	 * Find out how big a buffer we need.
+	 *
+	 * This call should always return FALSE; if the error is
+	 * ERROR_INSUFFICIENT_BUFFER, NameLength will be set to
+	 * the size of the buffer we need, otherwise there's a
+	 * problem, and NameLength should be set to 0.
+	 *
+	 * It shouldn't require NameLength to be set, but,
+	 * at least as of WinPcap 4.1.3, it checks whether
+	 * NameLength is big enough before it checks for a
+	 * NULL buffer argument, so, while it'll still do
+	 * the right thing if NameLength is uninitialized and
+	 * whatever junk happens to be there is big enough
+	 * (because the pointer argument will be null), it's
+	 * still reading an uninitialized variable.
+	 */
+	NameLength = 0;
+	if (!PacketGetAdapterNames(NULL, &NameLength))
+	{
+		DWORD last_error = GetLastError();
+
+		if (last_error != ERROR_INSUFFICIENT_BUFFER)
+		{
+			pcap_win32_err_to_str(last_error, our_errbuf);
+			pcap_snprintf(errbuf, PCAP_ERRBUF_SIZE,
+			    "PacketGetAdapterNames: %s", our_errbuf);
+			return (-1);
+		}
+	}
+
+	if (NameLength <= 0)
+		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_win32_err_to_str(GetLastError(), our_errbuf);
+		pcap_snprintf(errbuf, PCAP_ERRBUF_SIZE, "PacketGetAdapterNames: %s",
+		    our_errbuf);
+		free(AdaptersName);
+		return (-1);
+	}
+
+	/*
+	 * "PacketGetAdapterNames()" returned a list of
+	 * null-terminated ASCII interface name strings,
+	 * terminated by a null string, followed by a list
+	 * of null-terminated ASCII interface description
+	 * strings, terminated by a null string.
+	 * This means there are two ASCII nulls at the end
+	 * of the first list.
+	 *
+	 * Find the end of the first list; that's the
+	 * beginning of the second list.
+	 */
+	desc = &AdaptersName[0];
+	while (*desc != '\0' || *(desc + 1) != '\0')
+		desc++;
+
+	/*
+ 	 * Found it - "desc" points to the first of the two
+	 * nulls at the end of the list of names, so the
+	 * first byte of the list of descriptions is two bytes
+	 * after it.
+	 */
+	desc += 2;
+
+	/*
+	 * Loop over the elements in the first list.
+	 */
+	name = &AdaptersName[0];
+	while (*name != '\0') {
+		bpf_u_int32 flags = 0;
+#ifdef HAVE_PACKET_IS_LOOPBACK_ADAPTER
+		/*
+		 * Is this a loopback interface?
+		 */
+		if (PacketIsLoopbackAdapter(name)) {
+			/* Yes */
+			flags |= PCAP_IF_LOOPBACK;
+		}
+#endif
+		/*
+		 * 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;
+	char our_errbuf[PCAP_ERRBUF_SIZE+1];
+
+#pragma warning (push)
+#pragma warning (disable: 4996) /* disable MSVC's GetVersion() deprecated warning here */
+	dwVersion = GetVersion();	/* get the OS version */
+#pragma warning (pop)
+	dwWindowsMajorVersion = (DWORD)(LOBYTE(LOWORD(dwVersion)));
+
+	if (dwVersion >= 0x80000000 && dwWindowsMajorVersion >= 4) {
+		/*
+		 * Windows 95, 98, ME.
+		 */
+		ULONG NameLength = 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_win32_err_to_str(GetLastError(), our_errbuf);
+			(void)pcap_snprintf(errbuf, PCAP_ERRBUF_SIZE,
+				"PacketGetAdapterNames: %s", our_errbuf);
+			free(TAdaptersName);
+			return NULL;
+		}
+
+
+		BufferSpaceLeft = ADAPTERSNAME_LEN * sizeof(WCHAR);
+		tAstr = (char*)TAdaptersName;
+		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 version number
+ * when building WinPcap.  (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;
+static const char pcap_version_string_packet_dll_fmt[] =
+	WINPCAP_PRODUCT_NAME " version " WINPCAP_VER_STRING " (packet.dll version %s), based on " PCAP_VERSION_STRING;
+
+const char *
+pcap_lib_version(void)
+{
+	char *packet_version_string;
+	size_t full_pcap_version_string_len;
+	char *full_pcap_version_string;
+
+	if (pcap_lib_version_string == NULL) {
+		/*
+		 * Generate the version string.
+		 */
+		packet_version_string = PacketGetVersion();
+		if (strcmp(WINPCAP_VER_STRING, packet_version_string) == 0) {
+			/*
+			 * WinPcap version string and packet.dll version
+			 * string are the same; just report the WinPcap
+			 * version.
+			 */
+			pcap_lib_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.
+			 *
+			 * The -2 is for the %s in the format string,
+			 * which will be replaced by packet_version_string.
+			 */
+			full_pcap_version_string_len =
+			    (sizeof pcap_version_string_packet_dll_fmt - 2) +
+			    strlen(packet_version_string);
+			full_pcap_version_string = malloc(full_pcap_version_string_len);
+			if (full_pcap_version_string == NULL)
+				return (NULL);
+			pcap_snprintf(full_pcap_version_string,
+			    full_pcap_version_string_len,
+			    pcap_version_string_packet_dll_fmt,
+			    packet_version_string);
+		}
+		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.
+ */
+static const char pcap_version_string_packet_dll_fmt[] =
+	PCAP_VERSION_STRING " (packet.dll version %s)";
+const char *
+pcap_lib_version(void)
+{
+	char *packet_version_string;
+	size_t full_pcap_version_string_len;
+	char *full_pcap_version_string;
+
+	if (pcap_lib_version_string == NULL) {
+		/*
+		 * Generate the version string.  Report the packet.dll
+		 * version.
+		 *
+		 * The -2 is for the %s in the format string, which will
+		 * be replaced by packet_version_string.
+		 */
+		packet_version_string = PacketGetVersion();
+		full_pcap_version_string_len =
+		    (sizeof pcap_version_string_packet_dll_fmt - 2) +
+		    strlen(packet_version_string);
+		full_pcap_version_string = malloc(full_pcap_version_string_len);
+		if (full_pcap_version_string == NULL)
+			return (NULL);
+		pcap_snprintf(full_pcap_version_string,
+		    full_pcap_version_string_len,
+		    pcap_version_string_packet_dll_fmt,
+		    packet_version_string);
+		pcap_lib_version_string = full_pcap_version_string;
+	}
+	return (pcap_lib_version_string);
+}
+#endif /* HAVE_VERSION_H */
diff --git a/pcap-null.c b/pcap-null.c
index b5fa3ab..92a5e2d 100644
--- a/pcap-null.c
+++ b/pcap-null.c
@@ -20,17 +20,11 @@
  */
 
 #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";
@@ -43,11 +37,29 @@
 }
 
 int
-pcap_platform_finddevs(pcap_if_t **alldevsp, char *errbuf)
+pcap_platform_finddevs(pcap_if_list_t *devlistp, char *errbuf)
 {
 	/*
 	 * There are no interfaces on which we can capture.
 	 */
-	*alldevsp = NULL;
 	return (0);
 }
+
+#ifdef _WIN32
+int
+pcap_lookupnet(const char *device _U_, bpf_u_int32 *netp _U_,
+    bpf_u_int32 *maskp _U_, char *errbuf)
+{
+	(void)strlcpy(errbuf, nosup, PCAP_ERRBUF_SIZE);
+	return (-1);
+}
+#endif
+
+/*
+ * Libpcap version string.
+ */
+const char *
+pcap_lib_version(void)
+{
+	return (PCAP_VERSION_STRING);
+}
diff --git a/pcap-pf.c b/pcap-pf.c
index 7346908..fde97ba 100644
--- 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>
@@ -127,8 +127,8 @@
 				(void)lseek(pc->fd, 0L, SEEK_SET);
 				goto again;
 			}
-			pcap_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 = (u_char *)pc->buffer + pc->offset;
@@ -232,8 +232,8 @@
 
 	ret = write(p->fd, buf, size);
 	if (ret == -1) {
-		pcap_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);
@@ -302,6 +302,7 @@
 	int backlog = -1;	/* request the most */
 	struct enfilter Filter;
 	struct endevp devparams;
+	int err;
 
 	/*
 	 * Initially try a read/write open (to allow the inject
@@ -329,11 +330,31 @@
 	if (p->fd == -1 && errno == EACCES)
 		p->fd = pfopen(p->opt.device, O_RDONLY);
 	if (p->fd < 0) {
-		pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "pf open: %s: %s\n\
-your system may not be properly configured; see the packetfilter(4) man page\n",
-			p->opt.device, 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)
@@ -341,8 +362,9 @@
 	if (p->opt.promisc)
 		enmode |= ENPROMISC;
 	if (ioctl(p->fd, EIOCMBIS, (caddr_t)&enmode) < 0) {
-		pcap_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
@@ -352,14 +374,16 @@
 #endif
 	/* set the backlog */
 	if (ioctl(p->fd, EIOCSETW, (caddr_t)&backlog) < 0) {
-		pcap_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) {
-		pcap_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 */
@@ -442,6 +466,7 @@
 		 */
 		pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
 		    "unknown data-link type %u", devparams.end_dev_type);
+		err = PCAP_ERROR;
 		goto bad;
 	}
 	/* set truncation */
@@ -453,8 +478,9 @@
 	} else
 		p->fddipad = 0;
 	if (ioctl(p->fd, EIOCTRUNCATE, (caddr_t)&p->snapshot) < 0) {
-		pcap_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 */
@@ -462,8 +488,9 @@
 	Filter.enf_Priority = 37;	/* anything > 2 */
 	Filter.enf_FilterLen = 0;	/* means "always true" */
 	if (ioctl(p->fd, EIOCSETF, (caddr_t)&Filter) < 0) {
-		pcap_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;
 	}
 
@@ -472,8 +499,9 @@
 		timeout.tv_sec = p->opt.timeout / 1000;
 		timeout.tv_usec = (p->opt.timeout * 1000) % 1000000;
 		if (ioctl(p->fd, EIOCSRTIMEOUT, (caddr_t)&timeout) < 0) {
-			pcap_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;
 		}
 	}
@@ -481,7 +509,9 @@
 	p->bufsize = BUFSPACE;
 	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;
 	}
 
@@ -502,7 +532,7 @@
 	return (0);
  bad:
 	pcap_cleanup_live_common(p);
-	return (PCAP_ERROR);
+	return (err);
 }
 
 pcap_t *
@@ -528,10 +558,32 @@
 	return (1);
 }
 
-int
-pcap_platform_finddevs(pcap_if_t **alldevsp, char *errbuf)
+static int
+get_if_flags(const char *name _U_, bpf_u_int32 *flags _U_, char *errbuf _U_)
 {
-	return (pcap_findalldevs_interfaces(alldevsp, errbuf, can_be_bound));
+	/*
+	 * 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
@@ -560,8 +612,8 @@
 			 * Yes.  Try to install the filter.
 			 */
 			if (ioctl(p->fd, BIOCSETF, (caddr_t)fp) < 0) {
-				pcap_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);
 			}
 
@@ -620,3 +672,12 @@
 	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
index 0000000..c50fe3f
--- /dev/null
+++ b/pcap-rdmasniff.c
@@ -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
index 0000000..ff1f3c2
--- /dev/null
+++ b/pcap-rdmasniff.h
@@ -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
index 0000000..e707a85
--- /dev/null
+++ b/pcap-rpcap-int.h
@@ -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
index b954058..e9d6245 100644
--- a/pcap-rpcap.c
+++ b/pcap-rpcap.c
@@ -32,53 +32,114 @@
  */
 
 #ifdef HAVE_CONFIG_H
-#include "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 "pcap-int.h"
-#include "pcap-rpcap.h"
 #include "sockutils.h"
+#include "pcap-int.h"
+#include "rpcap-protocol.h"
+#include "pcap-rpcap.h"
 
 /*
- * \file pcap-rpcap.c
+ * This file contains the pcap module for capturing from a remote machine's
+ * interfaces using the RPCAP protocol.
  *
- * This file keeps all the new funtions that are needed for the RPCAP protocol.
- * Almost all the pcap functions need to be modified in order to become compatible
- * with the RPCAP protocol. However, you can find here only the ones that are completely new.
- *
- * This file keeps also the functions that are 'private', i.e. are needed by the RPCAP
- * protocol but are not exported to the user.
- *
- * \warning All the RPCAP functions that are allowed to return a buffer containing
- * the error description can return max PCAP_ERRBUF_SIZE characters.
+ * 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.
+ * 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_remote to see if we want standard or extended statistics */
-#define PCAP_STATS_EX		1	/* Used by pcap_stats_remote to see if we want standard or extended statistics */
+#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. */
-struct activehosts *activeHosts;
+static struct activehosts *activeHosts;
 
 /*
- * Private data for capturing on WinPcap devices.
+ * 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.
  */
-struct pcap_win {
-	int nonblock;
-	int rfmon_selfstart;		/* a flag tells whether the monitor mode is set by itself */
-	int filtering_in_kernel;	/* using kernel filter */
+static SOCKET sockmain;
 
-#ifdef HAVE_DAG_API
-	int	dag_fcs_bits;		/* Number of checksum bits from link layer */
-#endif
+/*
+ * 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 */
 };
 
 /****************************************************
@@ -86,14 +147,23 @@
  * Locally defined functions                        *
  *                                                  *
  ****************************************************/
-static int rpcap_checkver(SOCKET sock, struct rpcap_header *header, char *errbuf);
-static struct pcap_stat *rpcap_stats_remote(pcap_t *p, struct pcap_stat *ps, int mode);
+static 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 int pcap_setfilter_remote(pcap_t *fp, struct bpf_program *prog);
-static int pcap_setsampling_remote(pcap_t *p);
-
+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_sendauth(SOCKET sock, uint8 *ver, struct pcap_rmtauth *auth, char *errbuf);
+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);
 
 /****************************************************
  *                                                  *
@@ -102,21 +172,67 @@
  ****************************************************/
 
 /*
- * \ingroup remote_pri_func
+ * 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.
  *
- * \brief 	It traslates (i.e. de-serializes) a 'sockaddr_storage' structure from
- * the network byte order to 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.
  *
- * It accepts a 'sockaddr_storage' structure as it is received from the network and it
- * converts it into the host byte order (by means of a set of ntoh() ).
- * The function will allocate the 'sockaddrout' variable according to the address family
- * in use. In case the address does not belong to the AF_INET nor AF_INET6 families,
- * 'sockaddrout' is not allocated and a NULL pointer is returned.
- * This usually happens because that address does not exist on the other host, so the
- * RPCAP daemon sent a 'sockaddr_storage' structure containing all 'zero' values.
+ * 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.
  *
- * \param sockaddrin: a 'sockaddr_storage' pointer to the variable that has to be
- * de-serialized.
+ * 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'.
@@ -134,63 +250,114 @@
  *
  * \warning The sockaddrout (if not NULL) must be deallocated by the user.
  */
-int rpcap_deseraddr(struct sockaddr_storage *sockaddrin, struct sockaddr_storage **sockaddrout, char *errbuf)
+
+/*
+ * 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 */
-	if (ntohs(sockaddrin->ss_family) == AF_INET)
+	switch (ntohs(sockaddrin->family))
 	{
-		struct sockaddr_in *sockaddr;
-
-		sockaddr = (struct sockaddr_in *) sockaddrin;
-		sockaddr->sin_family = ntohs(sockaddr->sin_family);
-		sockaddr->sin_port = ntohs(sockaddr->sin_port);
+	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_snprintf(errbuf, PCAP_ERRBUF_SIZE, "malloc() failed: %s", pcap_strerror(errno));
+			pcap_fmt_errmsg_for_errno(errbuf, PCAP_ERRBUF_SIZE,
+			    errno, "malloc() failed");
 			return -1;
 		}
-		memcpy(*sockaddrout, sockaddr, sizeof(struct sockaddr_in));
-		return 0;
-	}
-	if (ntohs(sockaddrin->ss_family) == AF_INET6)
-	{
-		struct sockaddr_in6 *sockaddr;
+		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;
+		}
 
-		sockaddr = (struct sockaddr_in6 *) sockaddrin;
-		sockaddr->sin6_family = ntohs(sockaddr->sin6_family);
-		sockaddr->sin6_port = ntohs(sockaddr->sin6_port);
-		sockaddr->sin6_flowinfo = ntohl(sockaddr->sin6_flowinfo);
-		sockaddr->sin6_scope_id = ntohl(sockaddr->sin6_scope_id);
+#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_snprintf(errbuf, PCAP_ERRBUF_SIZE, "malloc() failed: %s", pcap_strerror(errno));
+			pcap_fmt_errmsg_for_errno(errbuf, PCAP_ERRBUF_SIZE,
+			    errno, "malloc() failed");
 			return -1;
 		}
-		memcpy(*sockaddrout, sockaddr, sizeof(struct sockaddr_in6));
-		return 0;
-	}
+		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
 
-	/* It is neither AF_INET nor AF_INET6 */
-	*sockaddrout = NULL;
+	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;
 }
 
-/* \ingroup remote_pri_func
+/*
+ * 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).
  *
- * \brief It reads a packet from the network socket. This does not make use of
- * callback (hence the "nocb" string into its name).
+ * This function is called by pcap_read_rpcap().
  *
- * This function is called by the several pcap_next_ex() when they detect that
- * we have a remote capture and they are the client side. In that case, they need
- * to read packets from the socket.
- *
- * Parameters and return values are exactly the same of the pcap_next_ex().
- *
- * \warning By choice, this function does not make use of semaphores. A smarter
+ * 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
@@ -202,24 +369,22 @@
  * 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)
+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 */
-	char netbuf[RPCAP_NETBUF_SIZE];		/* size of the network buffer in which the packet is copied, just for UDP */
-	uint32 totread;				/* number of bytes (of payload) currently read from the network (referred to the current pkt) */
-	int nread;
+	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 */
-	fd_set rfds;				/* set of socket descriptors we have to check */
 	struct timeval tv;			/* maximum time the select() can block waiting for data */
-	struct pcap_md *md;			/* structure used when doing a remote live capture */
-
-	md = (struct pcap_md *) ((u_char*)p->priv + sizeof(struct pcap_win));
+	fd_set rfds;				/* set of socket descriptors we have to check */
 
 	/*
-	 * Define the read timeout, to be used in the select()
+	 * 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;
@@ -232,11 +397,18 @@
 	 * 'fp->rmt_sockdata' has always to be set before calling the select(),
 	 * since it is cleared by the select()
 	 */
-	FD_SET(md->rmt_sockdata, &rfds);
+	FD_SET(pr->rmt_sockdata, &rfds);
 
-	retval = select((int) md->rmt_sockdata + 1, &rfds, NULL, NULL, &tv);
+	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;
 	}
@@ -246,190 +418,286 @@
 		return 0;
 
 	/*
-	 * data is here; so, let's copy it into the user buffer.
-	 * I'm going to read a new packet; so I reset the number of bytes (payload only) read
-	 */
-	totread = 0;
-
-	/*
 	 * We have to define 'header' as a pointer to a larger buffer,
 	 * because in case of UDP we have to read all the message within a single call
 	 */
-	header = (struct rpcap_header *) netbuf;
-	net_pkt_header = (struct rpcap_pkthdr *) (netbuf + sizeof(struct rpcap_header));
+	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 (md->rmt_flags & PCAP_OPENFLAG_DATATX_UDP)
+	if (pr->rmt_flags & PCAP_OPENFLAG_DATATX_UDP)
 	{
 		/* Read the entire message from the network */
-		if (sock_recv(md->rmt_sockdata, netbuf, RPCAP_NETBUF_SIZE, SOCK_RECEIVEALL_NO, p->errbuf, PCAP_ERRBUF_SIZE) == -1)
+		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
 	{
-		if (sock_recv(md->rmt_sockdata, netbuf, sizeof(struct rpcap_header), SOCK_RECEIVEALL_YES, p->errbuf, PCAP_ERRBUF_SIZE) == -1)
-			return -1;
-	}
+		int status;
 
-	/* Checks if the message is correct */
-	retval = rpcap_checkmsg(p->errbuf, md->rmt_sockdata, header, RPCAP_MSG_PACKET, 0);
-
-	if (retval != RPCAP_MSG_PACKET)		/* the message is not the one expected */
-	{
-		switch (retval)
+		if ((size_t)p->cc < sizeof(struct rpcap_header))
 		{
-		case -3:		/* Unrecoverable network error */
-			return -1;	/* Do nothing; just exit from here; the error code is already into the errbuf */
-
-		case -2:		/* The other endpoint sent a message that is not allowed here */
-		case -1:		/* The other endpoint has a version number that is not compatible with our */
-			return 0;	/* Return 'no packets received' */
-
-		default:
-			SOCK_ASSERT("Internal error", 1);
-			return 0;	/* Return 'no packets received' */
+			/*
+			 * 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;
+			}
 		}
-	}
-
-	/* In case of TCP, read the remaining of the packet from the socket */
-	if (!(md->rmt_flags & PCAP_OPENFLAG_DATATX_UDP))
-	{
-		/* Read the RPCAP packet header from the network */
-		nread = sock_recv(md->rmt_sockdata, (char *)net_pkt_header,
-		    sizeof(struct rpcap_pkthdr), SOCK_RECEIVEALL_YES,
-		    p->errbuf, PCAP_ERRBUF_SIZE);
-		if (nread == -1)
-			return -1;
-		totread += nread;
-	}
-
-	if ((ntohl(net_pkt_header->caplen) + sizeof(struct pcap_pkthdr)) <= p->bufsize)
-	{
-		/* Initialize returned structures */
-		*pkt_header = (struct pcap_pkthdr *) p->buffer;
-		*pkt_data = (u_char*)p->buffer + sizeof(struct pcap_pkthdr);
-
-		(*pkt_header)->caplen = ntohl(net_pkt_header->caplen);
-		(*pkt_header)->len = ntohl(net_pkt_header->len);
-		(*pkt_header)->ts.tv_sec = ntohl(net_pkt_header->timestamp_sec);
-		(*pkt_header)->ts.tv_usec = ntohl(net_pkt_header->timestamp_usec);
 
 		/*
-		 * I don't update the counter of the packets dropped by the network since we're using TCP,
-		 * therefore no packets are dropped. Just update the number of packets received correctly
+		 * 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.
 		 */
-		md->TotCapt++;
-
-		/* Copies the packet into the data buffer */
-		if (md->rmt_flags & PCAP_OPENFLAG_DATATX_UDP)
+		plen = ntohl(header->plen);
+		if (plen > p->bufsize - sizeof(struct rpcap_header))
 		{
-			unsigned int npkt;
-
 			/*
-			 * In case of UDP the packet has already been read, we have to copy it into 'buffer'.
-			 * Another option should be to declare 'netbuf' as 'static'. However this prevents
-			 * using several pcap instances within the same process (because the static buffer is shared among
-			 * all processes)
+			 * This is bigger than the largest
+			 * record we'd expect.  (We do it by
+			 * subtracting in order to avoid an
+			 * overflow.)
 			 */
-			memcpy(*pkt_data, netbuf + sizeof(struct rpcap_header) + sizeof(struct rpcap_pkthdr), (*pkt_header)->caplen);
-
-			/* We're using UDP, so we need to update the counter of the packets dropped by the network */
-			npkt = ntohl(net_pkt_header->npkt);
-
-			if (md->TotCapt != npkt)
-			{
-				md->TotNetDrops += (npkt - md->TotCapt);
-				md->TotCapt = npkt;
-			}
-
+			pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
+			    "Server sent us a message larger than the largest expected packet message");
+			return -1;
 		}
-		else
+		status = rpcap_read_packet_msg(pr->rmt_sockdata, p,
+		    sizeof(struct rpcap_header) + plen);
+		if (status == -1)
 		{
-			/* In case of TCP, read the remaining of the packet from the socket */
-			nread = sock_recv(md->rmt_sockdata, *pkt_data,
-			    (*pkt_header)->caplen, SOCK_RECEIVEALL_YES,
-			    p->errbuf, PCAP_ERRBUF_SIZE);
-			if (nread == -1)
-				return -1;
-			totread += nread;
-
-			/* Checks if all the data has been read; if not, discard the data in excess */
-			/* This check has to be done only on TCP connections */
-			if (totread != ntohl(header->plen))
-				sock_discard(md->rmt_sockdata, ntohl(header->plen) - totread, NULL, 0);
+			/* Network error. */
+			return -1;
+		}
+		if (status == -3)
+		{
+			/* Interrupted receive. */
+			return 0;
 		}
 
-
-		/* Packet read successfully */
-		return 1;
+		/*
+		 * 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;
 	}
-	else
+
+	/*
+	 * 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)
 	{
-		pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "Received a packet that is larger than the internal buffer size.");
+		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;
 }
 
-/* \ingroup remote_pri_func
- *
- * \brief It reads a packet from the network socket.
- *
- * This function is called by the several pcap_read() when they detect that
- * we have a remote capture and they are the client side. In that case, they need
- * to read packets from the socket.
+/*
+ * This function 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.
- *
- * Parameters and return values are exactly the same of the pcap_read().
  */
-static int pcap_read_remote(pcap_t *p, int cnt, pcap_handler callback, u_char *user)
+static int pcap_read_rpcap(pcap_t *p, int cnt, pcap_handler callback, u_char *user)
 {
-	struct pcap_pkthdr *pkt_header;
+	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;
 
-	while ((n < cnt) || (cnt < 0))
+	/*
+	 * If this is client-side, and we haven't already started
+	 * the capture, start it now.
+	 */
+	if (pr->rmt_clientside)
 	{
-		if (pcap_read_nocb_remote(p, &pkt_header, &pkt_data) == 1)
+		/* We are on an remote capture */
+		if (!pr->rmt_capstarted)
 		{
-			(*callback)(user, pkt_header, pkt_data);
+			/*
+			 * 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;
 }
 
-/* \ingroup remote_pri_func
+/*
+ * This function sends a CLOSE command to the capture server.
  *
- * \brief It 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'.
  *
- * This function is called when the user wants to close a pcap_t adapter.
- * In case we're capturing from the network, it sends a command to the other
- * peer that says 'ok, let's stop capturing'.
- * This function is called automatically when the user calls the pcap_close().
- *
- * Parameters and return values are exactly the same of the pcap_close().
- *
- * \warning Since we're closing the connection, we do not check for errors.
+ * WARNING: Since we're closing the connection, we do not check for errors.
  */
-static void pcap_cleanup_remote(pcap_t *fp)
+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? */
-	struct pcap_md *md;				/* structure used when doing a remote live capture */
-
-	md = (struct pcap_md *) ((u_char*)fp->priv + sizeof(struct pcap_win));
+	int active = 0;				/* active mode or not? */
 
 	/* detect if we're in active mode */
 	temp = activeHosts;
 	while (temp)
 	{
-		if (temp->sockctrl == md->rmt_sockctrl)
+		if (temp->sockctrl == pr->rmt_sockctrl)
 		{
 			active = 1;
 			break;
@@ -439,61 +707,75 @@
 
 	if (!active)
 	{
-		rpcap_createhdr(&header, RPCAP_MSG_CLOSE, 0, 0);
+		rpcap_createhdr(&header, pr->protocol_version,
+		    RPCAP_MSG_CLOSE, 0, 0);
 
-		/* I don't check for errors, since I'm going to close everything */
-		sock_send(md->rmt_sockctrl, (char *)&header, sizeof(struct rpcap_header), NULL, 0);
+		/*
+		 * 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, RPCAP_MSG_ENDCAP_REQ, 0, 0);
+		rpcap_createhdr(&header, pr->protocol_version,
+		    RPCAP_MSG_ENDCAP_REQ, 0, 0);
 
-		/* I don't check for errors, since I'm going to close everything */
-		sock_send(md->rmt_sockctrl, (char *)&header, sizeof(struct rpcap_header), NULL, 0);
-
-		/* wait for the answer */
-		/* Don't check what we got, since the present libpcap does not uses this pcap_t anymore */
-		sock_recv(md->rmt_sockctrl, (char *)&header, sizeof(struct rpcap_header), SOCK_RECEIVEALL_YES, NULL, 0);
-
-		if (ntohl(header.plen) != 0)
-			sock_discard(md->rmt_sockctrl, ntohl(header.plen), NULL, 0);
+		/*
+		 * 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 (md->rmt_sockdata)
+	if (pr->rmt_sockdata)
 	{
-		sock_close(md->rmt_sockdata, NULL, 0);
-		md->rmt_sockdata = 0;
+		sock_close(pr->rmt_sockdata, NULL, 0);
+		pr->rmt_sockdata = 0;
 	}
 
-	if ((!active) && (md->rmt_sockctrl))
-		sock_close(md->rmt_sockctrl, NULL, 0);
+	if ((!active) && (pr->rmt_sockctrl))
+		sock_close(pr->rmt_sockctrl, NULL, 0);
 
-	md->rmt_sockctrl = 0;
+	pr->rmt_sockctrl = 0;
 
-	if (md->currentfilter)
+	if (pr->currentfilter)
 	{
-		free(md->currentfilter);
-		md->currentfilter = NULL;
+		free(pr->currentfilter);
+		pr->currentfilter = NULL;
 	}
 
 	/* To avoid inconsistencies in the number of sock_init() */
 	sock_cleanup();
 }
 
-/* \ingroup remote_pri_func
- *
- * \brief It retrieves network statistics from the other peer.
- *
- * This function is just a void cointainer, since the work is done by the rpcap_stats_remote().
- * See that funcion for more details.
- *
- * Parameters and return values are exactly the same of the pcap_stats().
+/*
+ * This function retrieves network statistics from our peer;
+ * it provides only the standard statistics.
  */
-static int pcap_stats_remote(pcap_t *p, struct pcap_stat *ps)
+static int pcap_stats_rpcap(pcap_t *p, struct pcap_stat *ps)
 {
 	struct pcap_stat *retval;
 
-	retval = rpcap_stats_remote(p, ps, PCAP_STATS_STANDARD);
+	retval = rpcap_stats_rpcap(p, ps, PCAP_STATS_STANDARD);
 
 	if (retval)
 		return 0;
@@ -502,414 +784,237 @@
 }
 
 #ifdef _WIN32
-/* \ingroup remote_pri_func
- *
- * \brief It retrieves network statistics from the other peer.
- *
- * This function is just a void cointainer, since the work is done by the rpcap_stats_remote().
- * See that funcion for more details.
- *
- * Parameters and return values are exactly the same of the pcap_stats_ex().
+/*
+ * 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_remote(pcap_t *p, int *pcap_stat_size)
+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_remote(p, &(p->stat), PCAP_STATS_EX));
+	return (rpcap_stats_rpcap(p, &(p->stat), PCAP_STATS_EX));
 }
 #endif
 
-/* \ingroup remote_pri_func
+/*
+ * This function retrieves network statistics from our peer.  It
+ * is used by the two previous functions.
  *
- * \brief It retrieves network statistics from the other peer.
+ * 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 function can be called in two modes:
- * - PCAP_STATS_STANDARD: if we want just standard statistics (i.e. the pcap_stats() )
- * - PCAP_STATS_EX: if we want extended statistics (i.e. the pcap_stats_ex() )
+ * This 'mode' parameter is needed because in 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.
  *
- * This 'mode' parameter is needed because in the standard pcap_stats() the variable that keeps the
- * statistics is allocated by the user. Unfortunately, this structure has been extended in order
- * to keep new stats. However, if the user has a smaller structure and it passes it to the pcap_stats,
- * thid function will try to fill in more data than the size of the structure, so that the application
- * goes in memory overflow.
- * So, we need to know it we have to copy just the standard fields, or the extended fields as well.
+ * So, we need to know it we have to copy just the standard fields, or the
+ * extended fields as well.
  *
- * In case we want to copy the extended fields as well, the problem of memory overflow does no
- * longer exist because the structure pcap_stat is no longer allocated by the program;
- * it is allocated by the library instead.
+ * 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 'pcap_stat' structure, needed for compatibility with pcap_stat(), in which
- * the structure is allocated by the user. In case of pcap_stats_ex, this structure and the
- * function return value point to the same variable.
+ * \param 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_remote(pcap_t *p, struct pcap_stat *ps, int mode)
+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 totread = 0;			/* number of bytes of the payload read from the socket */
-	int nread;
-	int retval;				/* temp variable which stores functions return value */
-	struct pcap_md *md;			/* structure used when doing a remote live capture */
+	uint32 plen;				/* data remaining in the message */
 
-	md = (struct pcap_md *) ((u_char*)p->priv + sizeof(struct pcap_win));
+#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 still to start, we cannot ask statistics to the other peer,
-	 * so we return a fake number
+	 * 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 (!md->rmt_capstarted)
+	if (!pr->rmt_capstarted)
 	{
-		if (mode == PCAP_STATS_STANDARD)
-		{
-			ps->ps_drop = 0;
-			ps->ps_ifdrop = 0;
-			ps->ps_recv = 0;
-		}
-		else
+		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_drop = 0;
-			ps->ps_ifdrop = 0;
-			ps->ps_netdrop = 0;
-			ps->ps_recv = 0;
 			ps->ps_sent = 0;
+			ps->ps_netdrop = 0;
 		}
+#endif /* _WIN32 */
 
 		return ps;
 	}
 
-	rpcap_createhdr(&header, RPCAP_MSG_STATS_REQ, 0, 0);
+	rpcap_createhdr(&header, pr->protocol_version,
+	    RPCAP_MSG_STATS_REQ, 0, 0);
 
 	/* Send the PCAP_STATS command */
-	if (sock_send(md->rmt_sockctrl, (char *)&header, sizeof(struct rpcap_header), p->errbuf, PCAP_ERRBUF_SIZE))
+	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;
 
-	/* Receive the RPCAP stats reply message */
-	if (sock_recv(md->rmt_sockctrl, (char *)&header, sizeof(struct rpcap_header), SOCK_RECEIVEALL_YES, p->errbuf, PCAP_ERRBUF_SIZE) == -1)
-		goto error;
-
-	/* Checks if the message is correct */
-	retval = rpcap_checkmsg(p->errbuf, md->rmt_sockctrl, &header, RPCAP_MSG_STATS_REPLY, RPCAP_MSG_ERROR, 0);
-
-	if (retval != RPCAP_MSG_STATS_REPLY)		/* the message is not the one expected */
+	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)
 	{
-		switch (retval)
-		{
-		case -3:		/* Unrecoverable network error */
-		case -2:		/* The other endpoint send a message that is not allowed here */
-		case -1:		/* The other endpoint has a version number that is not compatible with our */
-			goto error;
-
-		case RPCAP_MSG_ERROR:		/* The other endpoint reported an error */
-			/* Update totread, since the rpcap_checkmsg() already purged the buffer */
-			totread = ntohl(header.plen);
-
-			/* Do nothing; just exit; the error code is already into the errbuf */
-			goto error;
-
-		default:
-			pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "Internal error");
-			goto error;
-		}
-	}
-
-	nread = sock_recv(md->rmt_sockctrl, (char *)&netstats,
-	    sizeof(struct rpcap_stats), SOCK_RECEIVEALL_YES,
-	    p->errbuf, PCAP_ERRBUF_SIZE);
-	if (nread == -1)
-		goto error;
-	totread += nread;
-
-	if (mode == PCAP_STATS_STANDARD)
-	{
-		ps->ps_drop = ntohl(netstats.krnldrop);
-		ps->ps_ifdrop = ntohl(netstats.ifdrop);
-		ps->ps_recv = ntohl(netstats.ifrecv);
-	}
-	else
-	{
-		ps->ps_capt = md->TotCapt;
-		ps->ps_drop = ntohl(netstats.krnldrop);
-		ps->ps_ifdrop = ntohl(netstats.ifdrop);
-		ps->ps_netdrop = md->TotNetDrops;
-		ps->ps_recv = ntohl(netstats.ifrecv);
+		ps->ps_capt = pr->TotCapt;
+		ps->ps_netdrop = pr->TotNetDrops;
 		ps->ps_sent = ntohl(netstats.svrcapt);
 	}
+#endif /* _WIN32 */
 
-	/* Checks if all the data has been read; if not, discard the data in excess */
-	if (totread != ntohl(header.plen))
-	{
-		if (sock_discard(md->rmt_sockctrl, ntohl(header.plen) - totread, NULL, 0) == 1)
-			goto error;
-	}
+	/* Discard the rest of the message. */
+	if (rpcap_discard(pr->rmt_sockctrl, plen, p->errbuf) == -1)
+		goto error_nodiscard;
 
 	return ps;
 
 error:
-	if (totread != ntohl(header.plen))
-		sock_discard(md->rmt_sockctrl, ntohl(header.plen) - totread, NULL, 0);
+	/*
+	 * 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;
 }
 
-/* \ingroup remote_pri_func
+/*
+ * 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.
  *
- * \brief It opens a remote adapter by opening an RPCAP connection and so on.
+ * \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.
  *
- * This function does basically the job of pcap_open_live() for a remote interface.
- * In other words, we have a pcap_read for win32, which reads packets from NPF,
- * another for LINUX, and so on. Now, we have a pcap_opensource_remote() as well.
- * The difference, here, is the capture thread does not start until the
- * pcap_startcapture_remote() is called.
+ * \param error: a pointer to an int that is set to 1 if an error occurred
+ * and 0 otherwise.
  *
- * This is because, in remote capture, we cannot start capturing data as soon ad the
- * 'open adapter' command is sent. Suppose the remote adapter is already overloaded;
- * if we start a capture (which, by default, has a NULL filter) the new traffic can
- * saturate the network.
+ * \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).
  *
- * Instead, we want to "open" the adapter, then send a "start capture" command only
- * when we're ready to start the capture.
- * This funtion does this job: it sends a "open adapter" command (according to the
- * RPCAP protocol), but it does not start the capture.
- *
- * Since the other libpcap functions do not share this way of life, we have to make
- * some dirty things in order to make everyting working.
- *
- * \param fp: A pointer to a pcap_t structure that has been previously created with
- * \ref pcap_create().
- * \param source: see pcap_open().
- * \param auth: see pcap_open().
- *
- * \return 0 in case of success, -1 otherwise. In case of success, the pcap_t pointer in fp can be
- * used as a parameter to the following calls (pcap_compile() and so on). In case of
- * problems, fp->errbuf contains a text explanation of error.
- *
- * \warning In case we call the pcap_compile() and the capture is not started, the filter
- * will be saved into the pcap_t structure, and it will be sent to the other host later
- * (when the pcap_startcapture_remote() is called).
+ * \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.
  */
-int pcap_opensource_remote(pcap_t *fp, struct pcap_rmtauth *auth)
+static struct activehosts *
+rpcap_remoteact_getsock(const char *host, int *error, char *errbuf)
 {
-	char host[PCAP_BUF_SIZE], ctrlport[PCAP_BUF_SIZE], iface[PCAP_BUF_SIZE];
+	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;
 
-	char sendbuf[RPCAP_NETBUF_SIZE];	/* temporary buffer in which data to be sent is buffered */
-	int sendbufidx = 0;			/* index which keeps the number of bytes currently buffered */
-	uint32 totread = 0;			/* number of bytes of the payload read from the socket */
-	int nread;
-	int retval;				/* store the return value of the functions */
-	int active = 0;				/* '1' if we're in active mode */
-
-	/* socket-related variables */
-	struct addrinfo hints;			/* temp, needed to open a socket connection */
-	struct addrinfo *addrinfo;		/* temp, needed to open a socket connection */
-	SOCKET sockctrl = 0;			/* socket descriptor of the control connection */
-
-	/* RPCAP-related variables */
-	struct rpcap_header header;		/* header of the RPCAP packet */
-	struct rpcap_openreply openreply;	/* open reply message */
-
-	struct pcap_md *md;			/* structure used when doing a remote live capture */
-
-	md = (struct pcap_md *) ((u_char*)fp->priv + sizeof(struct pcap_win));
-
-
-	/*
-	 * determine the type of the source (NULL, file, local, remote)
-	 * You must have a valid source string even if we're in active mode, because otherwise
-	 * the call to the following function will fail.
-	 */
-	if (pcap_parsesrcstr(fp->opt.device, &retval, host, ctrlport, iface, fp->errbuf) == -1)
-		return -1;
-
-	if (retval != PCAP_SRC_IFREMOTE)
-	{
-		pcap_snprintf(fp->errbuf, PCAP_ERRBUF_SIZE, "This function is able to open only remote interfaces");
-		return -1;
-	}
-
+	/* 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;
 
-	/*
-	 * Warning: this call can be the first one called by the user.
-	 * For this reason, we have to initialize the WinSock support.
-	 */
-	if (sock_init(fp->errbuf, PCAP_ERRBUF_SIZE) == -1)
-		return -1;
-
-	sockctrl = rpcap_remoteact_getsock(host, &active, fp->errbuf);
-	if (sockctrl == INVALID_SOCKET)
-		return -1;
-
-	if (!active)
+	retval = getaddrinfo(host, "0", &hints, &addrinfo);
+	if (retval != 0)
 	{
-		/*
-		 * We're not in active mode; let's try to open a new
-		 * control connection.
-		 */
-		memset(&hints, 0, sizeof(struct addrinfo));
-		hints.ai_family = PF_UNSPEC;
-		hints.ai_socktype = SOCK_STREAM;
-
-		if ((ctrlport == NULL) || (ctrlport[0] == 0))
-		{
-			/* the user chose not to specify the port */
-			if (sock_initaddress(host, RPCAP_DEFAULT_NETPORT, &hints, &addrinfo, fp->errbuf, PCAP_ERRBUF_SIZE) == -1)
-				return -1;
-		}
-		else
-		{
-			/* the user chose not to specify the port */
-			if (sock_initaddress(host, ctrlport, &hints, &addrinfo, fp->errbuf, PCAP_ERRBUF_SIZE) == -1)
-				return -1;
-		}
-
-		if ((sockctrl = sock_open(addrinfo, SOCKOPEN_CLIENT, 0, fp->errbuf, PCAP_ERRBUF_SIZE)) == INVALID_SOCKET)
-			goto error;
-
-		freeaddrinfo(addrinfo);
-		addrinfo = NULL;
-
-		if (rpcap_sendauth(sockctrl, auth, fp->errbuf) == -1)
-			goto error;
+		pcap_snprintf(errbuf, PCAP_ERRBUF_SIZE, "getaddrinfo() %s",
+		    gai_strerror(retval));
+		*error = 1;
+		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, fp->errbuf, PCAP_ERRBUF_SIZE))
-		goto error;
+	temp = activeHosts;
 
-	rpcap_createhdr((struct rpcap_header *) sendbuf, RPCAP_MSG_OPEN_REQ, 0, (uint32) strlen(iface));
-
-	if (sock_bufferize(iface, (int) strlen(iface), sendbuf, &sendbufidx,
-		RPCAP_NETBUF_SIZE, SOCKBUF_BUFFERIZE, fp->errbuf, PCAP_ERRBUF_SIZE))
-		goto error;
-
-	if (sock_send(sockctrl, sendbuf, sendbufidx, fp->errbuf, PCAP_ERRBUF_SIZE))
-		goto error;
-
-	/* Receive the RPCAP open reply message */
-	if (sock_recv(sockctrl, (char *)&header, sizeof(struct rpcap_header), SOCK_RECEIVEALL_YES, fp->errbuf, PCAP_ERRBUF_SIZE) == -1)
-		goto error;
-
-	/* Checks if the message is correct */
-	retval = rpcap_checkmsg(fp->errbuf, sockctrl, &header, RPCAP_MSG_OPEN_REPLY, RPCAP_MSG_ERROR, 0);
-
-	if (retval != RPCAP_MSG_OPEN_REPLY)		/* the message is not the one expected */
+	while (temp)
 	{
-		switch (retval)
+		ai_next = addrinfo;
+		while (ai_next)
 		{
-		case -3:		/* Unrecoverable network error */
-		case -2:		/* The other endpoint send a message that is not allowed here */
-		case -1:		/* The other endpoint has a version number that is not compatible with our */
-			goto error;
+			if (sock_cmpaddr(&temp->host, (struct sockaddr_storage *) ai_next->ai_addr) == 0)
+			{
+				*error = 0;
+				freeaddrinfo(addrinfo);
+				return temp;
+			}
 
-		case RPCAP_MSG_ERROR:		/* The other endpoint reported an error */
-			/* Update totread, since the rpcap_checkmsg() already purged the buffer */
-			totread = ntohl(header.plen);
-			/* Do nothing; just exit; the error code is already into the errbuf */
-			goto error;
-
-		default:
-			pcap_snprintf(fp->errbuf, PCAP_ERRBUF_SIZE, "Internal error");
-			goto error;
+			ai_next = ai_next->ai_next;
 		}
+		temp = temp->next;
 	}
 
-	nread = sock_recv(sockctrl, (char *)&openreply,
-	    sizeof(struct rpcap_openreply), SOCK_RECEIVEALL_YES,
-	    fp->errbuf, PCAP_ERRBUF_SIZE);
-	if (nread == -1)
-		goto error;
-	totread += nread;
-
-	/* Set proper fields into the pcap_t struct */
-	fp->linktype = ntohl(openreply.linktype);
-	fp->tzoff = ntohl(openreply.tzoff);
-	md->rmt_sockctrl = sockctrl;
-	md->rmt_clientside = 1;
-
-
-	/* This code is duplicated from the end of this function */
-	fp->read_op = pcap_read_remote;
-	fp->setfilter_op = pcap_setfilter_remote;
-	fp->getnonblock_op = NULL;	/* This is not implemented in remote capture */
-	fp->setnonblock_op = NULL;	/* This is not implemented in remote capture */
-	fp->stats_op = pcap_stats_remote;
-#ifdef _WIN32
-	fp->stats_ex_op = pcap_stats_ex_remote;
-#endif
-	fp->cleanup_op = pcap_cleanup_remote;
-
-	/* Checks if all the data has been read; if not, discard the data in excess */
-	if (totread != ntohl(header.plen))
-	{
-		if (sock_discard(sockctrl, ntohl(header.plen) - totread, NULL, 0) == 1)
-			goto error;
-	}
-	return 0;
-
-error:
-	/*
-	 * When the connection has been established, we have to close it. So, at the
-	 * beginning of this function, if an error occur we return immediately with
-	 * a return NULL; when the connection is established, we have to come here
-	 * ('goto error;') in order to close everything properly.
-	 *
-	 * Checks if all the data has been read; if not, discard the data in excess
-	 */
-	if (totread != ntohl(header.plen))
-		sock_discard(sockctrl, ntohl(header.plen) - totread, NULL, 0);
-
 	if (addrinfo)
 		freeaddrinfo(addrinfo);
 
-	if (!active)
-		sock_close(sockctrl, NULL, 0);
-
-	return -1;
+	/*
+	 * The host for which you want to get the socket ID does not have an
+	 * active connection.
+	 */
+	*error = 0;
+	return NULL;
 }
 
-/* \ingroup remote_pri_func
+/*
+ * This function starts a remote capture.
  *
- * \brief It starts a remote capture.
- *
- * This function is requires since the RPCAP protocol decouples the 'open' from the
- * 'start capture' functions.
- * This function takes all the parameters needed (which have been stored into the pcap_t structure)
- * and sends them to the server.
- * If everything is fine, it creates a new child thread that reads data from the network
- * and puts data it into the user buffer.
- * The pcap_read() will read data from the user buffer, as usual.
- *
- * The remote capture acts like a new "kernel", which puts packets directly into
- * the buffer pointed by pcap_t.
- * In fact, this function does not rely on a kernel that reads packets and put them
- * into the user buffer; it has to do that on its own.
+ * 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.
+ * \return '0' if everything is fine, '-1' otherwise. The error message
+ * (if one) is returned into the 'errbuf' field of the pcap_t structure.
  */
-int pcap_startcapture_remote(pcap_t *fp)
+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 the data connection */
-	uint32 totread = 0;			/* number of bytes of the payload read from the socket */
-	int nread;
-	int retval;				/* store the return value of the functions */
+	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 */
@@ -928,12 +1033,10 @@
 	struct rpcap_startcapreply startcapreply;	/* start capture reply message */
 
 	/* Variables related to the buffer setting */
-	int res, itemp;
+	int res;
+	socklen_t itemp;
 	int sockbufsize = 0;
-
-	struct pcap_md *md;			/* structure used when doing a remote live capture */
-
-	md = (struct pcap_md *) ((u_char*)fp->priv + sizeof(struct pcap_win));
+	uint32 server_sockbufsize;
 
 	/*
 	 * Let's check if sampling has been required.
@@ -942,12 +1045,11 @@
 	if (pcap_setsampling_remote(fp) != 0)
 		return -1;
 
-
 	/* detect if we're in active mode */
 	temp = activeHosts;
 	while (temp)
 	{
-		if (temp->sockctrl == md->rmt_sockctrl)
+		if (temp->sockctrl == pr->rmt_sockctrl)
 		{
 			active = 1;
 			break;
@@ -965,10 +1067,10 @@
 	 * so I would have to call getpeername() anyway
 	 */
 	saddrlen = sizeof(struct sockaddr_storage);
-	if (getpeername(md->rmt_sockctrl, (struct sockaddr *) &saddr, &saddrlen) == -1)
+	if (getpeername(pr->rmt_sockctrl, (struct sockaddr *) &saddr, &saddrlen) == -1)
 	{
 		sock_geterror("getsockname(): ", fp->errbuf, PCAP_ERRBUF_SIZE);
-		goto error;
+		goto error_nodiscard;
 	}
 	ai_family = ((struct sockaddr_storage *) &saddr)->ss_family;
 
@@ -977,7 +1079,7 @@
 		sizeof(host), NULL, 0, NI_NUMERICHOST))
 	{
 		sock_geterror("getnameinfo(): ", fp->errbuf, PCAP_ERRBUF_SIZE);
-		goto error;
+		goto error_nodiscard;
 	}
 
 	/*
@@ -985,7 +1087,7 @@
 	 * - we're using TCP, and the user wants us to be in active mode
 	 * - we're using UDP
 	 */
-	if ((active) || (md->rmt_flags & PCAP_OPENFLAG_DATATX_UDP))
+	if ((active) || (pr->rmt_flags & PCAP_OPENFLAG_DATATX_UDP))
 	{
 		/*
 		 * We have to create a new socket to receive packets
@@ -995,16 +1097,16 @@
 		memset(&hints, 0, sizeof(struct addrinfo));
 		/* TEMP addrinfo is NULL in case of active */
 		hints.ai_family = ai_family;	/* Use the same address family of the control socket */
-		hints.ai_socktype = (md->rmt_flags & PCAP_OPENFLAG_DATATX_UDP) ? SOCK_DGRAM : SOCK_STREAM;
+		hints.ai_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;
+			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;
+			goto error_nodiscard;
 
 		/* addrinfo is no longer used */
 		freeaddrinfo(addrinfo);
@@ -1015,7 +1117,7 @@
 		if (getsockname(sockdata, (struct sockaddr *) &saddr, &saddrlen) == -1)
 		{
 			sock_geterror("getsockname(): ", fp->errbuf, PCAP_ERRBUF_SIZE);
-			goto error;
+			goto error_nodiscard;
 		}
 
 		/* Get the local port the system picked up */
@@ -1023,7 +1125,7 @@
 			0, portdata, sizeof(portdata), NI_NUMERICSERV))
 		{
 			sock_geterror("getnameinfo(): ", fp->errbuf, PCAP_ERRBUF_SIZE);
-			goto error;
+			goto error_nodiscard;
 		}
 	}
 
@@ -1033,17 +1135,18 @@
 	 */
 	if (sock_bufferize(NULL, sizeof(struct rpcap_header), NULL,
 		&sendbufidx, RPCAP_NETBUF_SIZE, SOCKBUF_CHECKONLY, fp->errbuf, PCAP_ERRBUF_SIZE))
-		goto error;
+		goto error_nodiscard;
 
-	rpcap_createhdr((struct rpcap_header *) sendbuf, RPCAP_MSG_STARTCAP_REQ, 0,
-		sizeof(struct rpcap_startcapreq) + sizeof(struct rpcap_filter) + fp->fcode.bf_len * sizeof(struct rpcap_filterbpf_insn));
+	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;
+		goto error_nodiscard;
 
 	memset(startcapreq, 0, sizeof(struct rpcap_startcapreq));
 
@@ -1052,7 +1155,7 @@
 	startcapreq->read_timeout = htonl(fp->opt.timeout);
 
 	/* portdata on the openreq is meaningful only if we're in active mode */
-	if ((active) || (md->rmt_flags & PCAP_OPENFLAG_DATATX_UDP))
+	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);
@@ -1061,9 +1164,9 @@
 	startcapreq->snaplen = htonl(fp->snapshot);
 	startcapreq->flags = 0;
 
-	if (md->rmt_flags & PCAP_OPENFLAG_PROMISCUOUS)
+	if (pr->rmt_flags & PCAP_OPENFLAG_PROMISCUOUS)
 		startcapreq->flags |= RPCAP_STARTCAPREQ_FLAG_PROMISC;
-	if (md->rmt_flags & PCAP_OPENFLAG_DATATX_UDP)
+	if (pr->rmt_flags & PCAP_OPENFLAG_DATATX_UDP)
 		startcapreq->flags |= RPCAP_STARTCAPREQ_FLAG_DGRAM;
 	if (active)
 		startcapreq->flags |= RPCAP_STARTCAPREQ_FLAG_SERVEROPEN;
@@ -1072,47 +1175,23 @@
 
 	/* 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;
 
-	if (sock_send(md->rmt_sockctrl, sendbuf, sendbufidx, fp->errbuf, PCAP_ERRBUF_SIZE))
-		goto error;
-
-
-	/* Receive the RPCAP start capture reply message */
-	if (sock_recv(md->rmt_sockctrl, (char *)&header, sizeof(struct rpcap_header), SOCK_RECEIVEALL_YES, fp->errbuf, PCAP_ERRBUF_SIZE) == -1)
-		goto error;
-
-	/* Checks if the message is correct */
-	retval = rpcap_checkmsg(fp->errbuf, md->rmt_sockctrl, &header, RPCAP_MSG_STARTCAP_REPLY, RPCAP_MSG_ERROR, 0);
-
-	if (retval != RPCAP_MSG_STARTCAP_REPLY)		/* the message is not the one expected */
-	{
-		switch (retval)
-		{
-		case -3:		/* Unrecoverable network error */
-		case -2:		/* The other endpoint send a message that is not allowed here */
-		case -1:		/* The other endpoint has a version number that is not compatible with our */
-			goto error;
-
-		case RPCAP_MSG_ERROR:		/* The other endpoint reported an error */
-			/* Update totread, since the rpcap_checkmsg() already purged the buffer */
-			totread = ntohl(header.plen);
-			/* Do nothing; just exit; the error code is already into the errbuf */
-			goto error;
-
-		default:
-			pcap_snprintf(fp->errbuf, PCAP_ERRBUF_SIZE, "Internal error");
-			goto error;
-		}
-	}
-
-	nread = sock_recv(md->rmt_sockctrl, (char *)&startcapreply,
-	    sizeof(struct rpcap_startcapreply), SOCK_RECEIVEALL_YES,
-	    fp->errbuf, PCAP_ERRBUF_SIZE);
-	if (nread == -1)
-		goto error;
-	totread += nread;
-
 	/*
 	 * In case of UDP data stream, the connection is always opened by the daemon
 	 * So, this case is already covered by the code above.
@@ -1124,14 +1203,13 @@
 	 * to tell the port we're using to the remote side; in case we're accepting a TCP
 	 * connection, we have to wait this info from the remote side.
 	 */
-
-	if (!(md->rmt_flags & PCAP_OPENFLAG_DATATX_UDP))
+	if (!(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 = (md->rmt_flags & PCAP_OPENFLAG_DATATX_UDP) ? SOCK_DGRAM : SOCK_STREAM;
+			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 */
@@ -1154,7 +1232,7 @@
 
 			socktemp = accept(sockdata, (struct sockaddr *) &saddr, &saddrlen);
 
-			if (socktemp == -1)
+			if (socktemp == INVALID_SOCKET)
 			{
 				sock_geterror("accept(): ", fp->errbuf, PCAP_ERRBUF_SIZE);
 				goto error;
@@ -1167,11 +1245,14 @@
 	}
 
 	/* Let's save the socket of the data connection */
-	md->rmt_sockdata = sockdata;
+	pr->rmt_sockdata = sockdata;
 
-	/* Allocates WinPcap/libpcap user buffer, which is a socket buffer in case of a remote capture */
-	/* It has the same size of the one used on the other side of the connection */
-	fp->bufsize = ntohl(startcapreply.bufsize);
+	/*
+	 * 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);
@@ -1180,66 +1261,81 @@
 	if (res == -1)
 	{
 		sock_geterror("pcap_startcapture_remote()", fp->errbuf, PCAP_ERRBUF_SIZE);
-		SOCK_ASSERT(fp->errbuf, 1);
+		SOCK_DEBUG_MESSAGE(fp->errbuf);
 	}
 
 	/*
-	 * 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.
+	 * Warning: on some kernels (e.g. Linux), the size of the user
+	 * buffer does not take into account the pcap_header and such,
+	 * and it is set equal to the snaplen.
+	 *
+	 * In my view, this is wrong (the meaning of the bufsize became
+	 * a bit strange).  So, here bufsize is the whole size of the
+	 * user buffer.  In case the bufsize returned is too small,
+	 * let's adjust it accordingly.
 	 */
-	if (fp->bufsize <= (u_int) fp->snapshot)
-		fp->bufsize += sizeof(struct pcap_pkthdr);
+	if (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 < fp->bufsize)
+	if ((u_int) sockbufsize < server_sockbufsize)
 	{
-		/* Loop until the buffer size is OK or the original socket buffer size is larger than this one */
-		while (1)
+		/*
+		 * 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 *)&(fp->bufsize), sizeof(fp->bufsize));
+			res = setsockopt(sockdata, SOL_SOCKET, SO_RCVBUF,
+			    (char *)&(server_sockbufsize),
+			    sizeof(server_sockbufsize));
 
 			if (res == 0)
 				break;
 
 			/*
-			 * If something goes wrong, half the buffer size (checking that it does not become smaller than
-			 * the current one)
+			 * If something goes wrong, halve the buffer size
+			 * (checking that it does not become smaller than
+			 * the current one).
 			 */
-			fp->bufsize /= 2;
+			server_sockbufsize /= 2;
 
-			if ((u_int) sockbufsize >= fp->bufsize)
+			if ((u_int) sockbufsize >= server_sockbufsize)
 			{
-				fp->bufsize = 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 pcap header plus the snapshot length
+	 * 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 = fp->snapshot + sizeof(struct pcap_pkthdr);
+	fp->bufsize = sizeof(struct rpcap_header) + sizeof(struct rpcap_pkthdr) + fp->snapshot;
 
 	fp->buffer = (u_char *)malloc(fp->bufsize);
 	if (fp->buffer == NULL)
 	{
-		pcap_snprintf(fp->errbuf, PCAP_ERRBUF_SIZE, "malloc: %s", pcap_strerror(errno));
+		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;
 
-	/* Checks if all the data has been read; if not, discard the data in excess */
-	if (totread != ntohl(header.plen))
-	{
-		if (sock_discard(md->rmt_sockctrl, ntohl(header.plen) - totread, NULL, 0) == 1)
-			goto error;
-	}
+	/* 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
@@ -1247,22 +1343,22 @@
 	 * because when we generate the 'start capture' we do not know (yet) all the ports
 	 * we're currently using.
 	 */
-	if (md->rmt_flags & PCAP_OPENFLAG_NOCAPTURE_RPCAP)
+	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_remote' because formally the capture has not been started yet */
-		/* (the 'fp->rmt_capstarted' variable will be updated some lines below) */
+		/* 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);
 	}
 
-	md->rmt_capstarted = 1;
+	pr->rmt_capstarted = 1;
 	return 0;
 
 error:
@@ -1271,42 +1367,52 @@
 	 * beginning of this function, if an error occur we return immediately with
 	 * a return NULL; when the connection is established, we have to come here
 	 * ('goto error;') in order to close everything properly.
-	 *
-	 * Checks if all the data has been read; if not, discard the data in excess
 	 */
-	if (totread != ntohl(header.plen))
-		sock_discard(md->rmt_sockctrl, ntohl(header.plen) - totread, NULL, 0);
 
+	/*
+	 * 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(md->rmt_sockctrl, NULL, 0);
+		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 (fp)
-	// 	{
-	// 		pcap_close(fp);
-	// 		fp= NULL;
-	// 	}
+#if 0
+	if (fp)
+	{
+		pcap_close(fp);
+		fp= NULL;
+	}
+#endif
 
 	return -1;
 }
 
 /*
- * \brief Takes a bpf program and sends it to the other host.
+ * This function takes a bpf program and sends it to the other host.
  *
  * This function can be called in two cases:
- * - the pcap_startcapture() is called (we have to send the filter along with
- * the 'start capture' command)
- * - we want to udpate the filter during a capture (i.e. the pcap_setfilter()
- * is called when the capture is still on)
+ * - 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.
+ * 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.
  *
@@ -1327,7 +1433,6 @@
 	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)
@@ -1366,99 +1471,107 @@
 	return 0;
 }
 
-/* \ingroup remote_pri_func
+/*
+ * This function updates a filter on a remote host.
  *
- * \brief Update a filter on a remote host.
- *
- * This function is called when the user wants to update a filter.
- * In case we're capturing from the network, it sends the filter to the other peer.
- * This function is *not* called automatically when the user calls the pcap_setfilter().
+ * 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 is already on: in this case, pcap_setfilter() calls pcap_updatefilter_remote()
- * - the capture has not started yet: in this case, pcap_setfilter() stores the filter into
- * the pcap_t structure, and then the filter is sent with the pcap_startcap().
+ * - 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().
  *
- * Parameters and return values are exactly the same of the pcap_setfilter().
+ * WARNING This function *does not* clear the packet currently into the
+ * buffers. Therefore, the user has to expect to receive some packets
+ * that are related to the previous filter.  If you want to discard all
+ * the packets before applying a new filter, you have to close the
+ * current capture session and start a new one.
  *
- * \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)
 {
-	int retval;						/* general variable used to keep the return value of other functions */
-	char sendbuf[RPCAP_NETBUF_SIZE];/* temporary buffer in which data to be sent is buffered */
-	int sendbufidx = 0;				/* index which keeps the number of bytes currently buffered */
+	struct 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 pcap_md *md;				/* structure used when doing a remote live capture */
-
-	md = (struct pcap_md *) ((u_char*)fp->priv + sizeof(struct pcap_win));
-
 
 	if (sock_bufferize(NULL, sizeof(struct rpcap_header), NULL, &sendbufidx,
 		RPCAP_NETBUF_SIZE, SOCKBUF_CHECKONLY, fp->errbuf, PCAP_ERRBUF_SIZE))
 		return -1;
 
-	rpcap_createhdr((struct rpcap_header *) sendbuf, RPCAP_MSG_UPDATEFILTER_REQ, 0,
-		sizeof(struct rpcap_filter) + prog->bf_len * sizeof(struct rpcap_filterbpf_insn));
+	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(md->rmt_sockctrl, sendbuf, sendbufidx, fp->errbuf, PCAP_ERRBUF_SIZE))
+	if (sock_send(pr->rmt_sockctrl, sendbuf, sendbufidx, fp->errbuf,
+	    PCAP_ERRBUF_SIZE) < 0)
 		return -1;
 
-	/* Waits for the answer */
-	if (sock_recv(md->rmt_sockctrl, (char *)&header, sizeof(struct rpcap_header), SOCK_RECEIVEALL_YES, fp->errbuf, PCAP_ERRBUF_SIZE) == -1)
+	/* 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;
 
-	/* Checks if the message is correct */
-	retval = rpcap_checkmsg(fp->errbuf, md->rmt_sockctrl, &header, RPCAP_MSG_UPDATEFILTER_REPLY, 0);
-
-	if (retval != RPCAP_MSG_UPDATEFILTER_REPLY)		/* the message is not the one expected */
-	{
-		switch (retval)
-		{
-		case -3:		/* Unrecoverable network error */
-		case -2:		/* The other endpoint sent a message that is not allowed here */
-		case -1:		/* The other endpoint has a version number that is not compatible with our */
-			/* Do nothing; just exit from here; the error code is already into the errbuf */
-			return -1;
-
-		default:
-			SOCK_ASSERT("Internal error", 0);
-			return -1;
-		}
-	}
-
-	if (ntohl(header.plen) != 0)	/* the message has an unexpected size */
-	{
-		if (sock_discard(md->rmt_sockctrl, ntohl(header.plen), fp->errbuf, PCAP_ERRBUF_SIZE) == -1)
-			return -1;
-	}
+	/*
+	 * 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);
+	}
+}
+
 /*
- * \ingroup remote_pri_func
- *
- * \brief Send a filter to a remote host.
+ * This function sends a filter to a remote host.
  *
  * This function is called when the user wants to set a filter.
- * In case we're capturing from the network, it sends the filter to the other peer.
- * This function is called automatically when the user calls the pcap_setfilter().
+ * 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 the pcap_setfilter().
+ * Parameters and return values are exactly the same of pcap_setfilter().
  */
-static int pcap_setfilter_remote(pcap_t *fp, struct bpf_program *prog)
+static int pcap_setfilter_rpcap(pcap_t *fp, struct bpf_program *prog)
 {
-	struct pcap_md *md;				/* structure used when doing a remote live capture */
+	struct pcap_rpcap *pr = fp->priv;	/* structure used when doing a remote live capture */
 
-	md = (struct pcap_md *) ((u_char*)fp->priv + sizeof(struct pcap_win));
-
-	if (!md->rmt_capstarted)
+	if (!pr->rmt_capstarted)
 	{
 		/* copy filter into the pcap_t structure */
 		if (install_bpf_program(fp, prog) == -1)
@@ -1474,9 +1587,8 @@
 }
 
 /*
- * \ingroup remote_pri_func
- *
- * \brief Update the current filter in order not to capture rpcap packets.
+ * 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.
@@ -1486,13 +1598,11 @@
  */
 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;
-	struct pcap_md *md;				/* structure used when doing a remote live capture */
-
-	md = (struct pcap_md *) ((u_char*)fp->priv + sizeof(struct pcap_win));
 
 	/* We do not want to capture our RPCAP traffic. So, let's update the filter */
-	if (md->rmt_flags & PCAP_OPENFLAG_NOCAPTURE_RPCAP)
+	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 */
@@ -1505,9 +1615,9 @@
 		const int newstringsize = 1024;
 		size_t currentfiltersize;
 
-		/* Get the name/port of the other peer */
+		/* Get the name/port of our peer */
 		saddrlen = sizeof(struct sockaddr_storage);
-		if (getpeername(md->rmt_sockctrl, (struct sockaddr *) &saddr, &saddrlen) == -1)
+		if (getpeername(pr->rmt_sockctrl, (struct sockaddr *) &saddr, &saddrlen) == -1)
 		{
 			sock_geterror("getpeername(): ", fp->errbuf, PCAP_ERRBUF_SIZE);
 			return -1;
@@ -1522,7 +1632,7 @@
 
 		/* We cannot check the data port, because this is available only in case of TCP sockets */
 		/* Get the name/port of the current host */
-		if (getsockname(md->rmt_sockctrl, (struct sockaddr *) &saddr, &saddrlen) == -1)
+		if (getsockname(pr->rmt_sockctrl, (struct sockaddr *) &saddr, &saddrlen) == -1)
 		{
 			sock_geterror("getsockname(): ", fp->errbuf, PCAP_ERRBUF_SIZE);
 			return -1;
@@ -1537,7 +1647,7 @@
 		}
 
 		/* Let's now check the data port */
-		if (getsockname(md->rmt_sockdata, (struct sockaddr *) &saddr, &saddrlen) == -1)
+		if (getsockname(pr->rmt_sockdata, (struct sockaddr *) &saddr, &saddrlen) == -1)
 		{
 			sock_geterror("getsockname(): ", fp->errbuf, PCAP_ERRBUF_SIZE);
 			return -1;
@@ -1550,7 +1660,7 @@
 			return -1;
 		}
 
-		currentfiltersize = strlen(md->currentfilter);
+		currentfiltersize = pr->currentfilter ? strlen(pr->currentfilter) : 0;
 
 		newfilter = (char *)malloc(currentfiltersize + newstringsize + 1);
 
@@ -1558,7 +1668,7 @@
 		{
 			pcap_snprintf(newfilter, currentfiltersize + newstringsize,
 				"(%s) and not (host %s and host %s and port %s and port %s) and not (host %s and host %s and port %s)",
-				md->currentfilter, myaddress, peeraddress, myctrlport, peerctrlport, myaddress, peeraddress, mydataport);
+				pr->currentfilter, myaddress, peeraddress, myctrlport, peerctrlport, myaddress, peeraddress, mydataport);
 		}
 		else
 		{
@@ -1569,14 +1679,18 @@
 
 		newfilter[currentfiltersize + newstringsize] = 0;
 
-		/* This is only an hack to make the pcap_compile() working properly */
-		md->rmt_clientside = 0;
+		/*
+		 * 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;
 
-		/* This is only an hack to make the pcap_compile() working properly */
-		md->rmt_clientside = 1;
+		/* Undo the hack. */
+		pr->rmt_clientside = 1;
 
 		free(newfilter);
 	}
@@ -1585,87 +1699,82 @@
 }
 
 /*
- * \ingroup remote_pri_func
+ * This function sets sampling parameters in the remote host.
  *
- * \brief Set sampling parameters in the remote host.
- *
- * This function is called when the user wants to set activate sampling on 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.
+ * \return '0' if everything is OK, '-1' is something goes wrong. The
+ * error message is returned in the 'errbuf' member of the pcap_t structure.
  */
-static int pcap_setsampling_remote(pcap_t *p)
+static int pcap_setsampling_remote(pcap_t *fp)
 {
-	int retval;						/* general variable used to keep the return value of other functions */
+	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 */
+	int sendbufidx = 0;			/* index which keeps the number of bytes currently buffered */
 	struct rpcap_header header;		/* To keep the reply message */
 	struct rpcap_sampling *sampling_pars;	/* Structure that is needed to send sampling parameters to the remote host */
-	struct pcap_md *md;				/* structure used when doing a remote live capture */
-
-	md = (struct pcap_md *) ((u_char*)p->priv + sizeof(struct pcap_win));
 
 	/* If no samping is requested, return 'ok' */
-	if (md->rmt_samp.method == PCAP_SAMP_NOSAMP)
+	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, p->errbuf, PCAP_ERRBUF_SIZE))
+		&sendbufidx, RPCAP_NETBUF_SIZE, SOCKBUF_CHECKONLY, fp->errbuf, PCAP_ERRBUF_SIZE))
 		return -1;
 
-	rpcap_createhdr((struct rpcap_header *) sendbuf, RPCAP_MSG_SETSAMPLING_REQ, 0, sizeof(struct rpcap_sampling));
+	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, p->errbuf, PCAP_ERRBUF_SIZE))
+		&sendbufidx, RPCAP_NETBUF_SIZE, SOCKBUF_CHECKONLY, fp->errbuf, PCAP_ERRBUF_SIZE))
 		return -1;
 
 	memset(sampling_pars, 0, sizeof(struct rpcap_sampling));
 
-	sampling_pars->method = md->rmt_samp.method;
-	sampling_pars->value = htonl(md->rmt_samp.value);
+	sampling_pars->method = (uint8)fp->rmt_samp.method;
+	sampling_pars->value = (uint16)htonl(fp->rmt_samp.value);
 
-	if (sock_send(md->rmt_sockctrl, sendbuf, sendbufidx, p->errbuf, PCAP_ERRBUF_SIZE))
+	if (sock_send(pr->rmt_sockctrl, sendbuf, sendbufidx, fp->errbuf,
+	    PCAP_ERRBUF_SIZE) < 0)
 		return -1;
 
-	/* Waits for the answer */
-	if (sock_recv(md->rmt_sockctrl, (char *)&header, sizeof(struct rpcap_header), SOCK_RECEIVEALL_YES, p->errbuf, PCAP_ERRBUF_SIZE) == -1)
+	/* 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;
 
-	/* Checks if the message is correct */
-	retval = rpcap_checkmsg(p->errbuf, md->rmt_sockctrl, &header, RPCAP_MSG_SETSAMPLING_REPLY, 0);
-
-	if (retval != RPCAP_MSG_SETSAMPLING_REPLY)		/* the message is not the one expected */
-	{
-		switch (retval)
-		{
-		case -3:		/* Unrecoverable network error */
-		case -2:		/* The other endpoint sent a message that is not allowed here */
-		case -1:		/* The other endpoint has a version number that is not compatible with our */
-		case RPCAP_MSG_ERROR:
-			/* Do nothing; just exit from here; the error code is already into the errbuf */
-			return -1;
-
-		default:
-			SOCK_ASSERT("Internal error", 0);
-			return -1;
-		}
-	}
-
-	if (ntohl(header.plen) != 0)	/* the message has an unexpected size */
-	{
-		if (sock_discard(md->rmt_sockctrl, ntohl(header.plen), p->errbuf, PCAP_ERRBUF_SIZE) == -1)
-			return -1;
-	}
+	/*
+	 * 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;
-
 }
 
 /*********************************************************
@@ -1674,90 +1783,123 @@
  *                                                       *
  *********************************************************/
 
-
-/* \ingroup remote_pri_func
- * \brief It sends a RPCAP error to the other peer.
- *
- * This function has to be called when the main program detects an error. This function
- * will send on the other peer the 'buffer' specified by the user.
- * This function *does not* request a RPCAP CLOSE connection. A CLOSE command must be sent
- * explicitly by the program, since we do not know it the error can be recovered in some
- * way or it is a non-recoverable one.
+/*
+ * This function performs authentication and protocol version
+ * negotiation.  It first tries to authenticate with the maximum
+ * version we support and, if that fails with an "I don't support
+ * that version" error from the server, and the version number in
+ * the reply from the server is one we support, tries again with
+ * that version.
  *
  * \param sock: the socket we are currently using.
  *
- * \param error: an user-allocated (and '0' terminated) buffer that contains the error
- * description that has to be transmitted on the other peer. The error message cannot
- * be longer than PCAP_ERRBUF_SIZE.
- *
- * \param errcode: a integer which tells the other party the type of error we had;
- * currently is is not too much used.
- *
- * \param errbuf: a pointer to a user-allocated buffer (of size PCAP_ERRBUF_SIZE)
- * that will contain the error message (in case there is one). It could be network problem.
- *
- * \return '0' if everything is fine, '-1' if some errors occurred. The error message is returned
- * in the 'errbuf' variable.
- */
-int rpcap_senderror(SOCKET sock, char *error, unsigned short errcode, char *errbuf)
-{
-	char sendbuf[RPCAP_NETBUF_SIZE];			/* temporary buffer in which data to be sent is buffered */
-	int sendbufidx = 0;							/* index which keeps the number of bytes currently buffered */
-	uint16 length;
-
-	length = (uint16)strlen(error);
-
-	if (length > PCAP_ERRBUF_SIZE)
-		length = PCAP_ERRBUF_SIZE;
-
-	rpcap_createhdr((struct rpcap_header *) sendbuf, RPCAP_MSG_ERROR, errcode, length);
-
-	if (sock_bufferize(NULL, sizeof(struct rpcap_header), NULL, &sendbufidx,
-		RPCAP_NETBUF_SIZE, SOCKBUF_CHECKONLY, errbuf, PCAP_ERRBUF_SIZE))
-		return -1;
-
-	if (sock_bufferize(error, length, sendbuf, &sendbufidx,
-		RPCAP_NETBUF_SIZE, SOCKBUF_BUFFERIZE, errbuf, PCAP_ERRBUF_SIZE))
-		return -1;
-
-	if (sock_send(sock, sendbuf, sendbufidx, errbuf, PCAP_ERRBUF_SIZE))
-		return -1;
-
-	return 0;
-}
-
-/* \ingroup remote_pri_func
- * \brief Sends the authentication message.
- *
- * It sends the authentication parameters on the control socket.
- * This function is required in order to open the connection with the other end party.
- *
- * \param sock: the socket we are currently using.
+ * \param ver: pointer to variable holding protocol version number to send
+ * and to set to the protocol version number in the reply.
  *
  * \param auth: authentication parameters that have to be sent.
  *
- * \param errbuf: a pointer to a user-allocated buffer (of size PCAP_ERRBUF_SIZE)
- * that will contain the error message (in case there is one). It could be network problem
- * of the fact that the authorization failed.
+ * \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' if some errors occurred. The error message is returned
- * in the 'errbuf' variable.
- * The error message could be also 'the authentication failed'.
+ * \return '0' if everything is fine, '-1' for an error.  For errors,
+ * an error message string is returned in the 'errbuf' variable.
  */
-int rpcap_sendauth(SOCKET sock, struct pcap_rmtauth *auth, char *errbuf)
+static int rpcap_doauth(SOCKET sockctrl, uint8 *ver, struct pcap_rmtauth *auth, char *errbuf)
+{
+	int status;
+
+	/*
+	 * Send authentication to the remote machine.
+	 *
+	 * First try with the maximum version number we support.
+	 */
+	*ver = RPCAP_MAX_VERSION;
+	status = rpcap_sendauth(sockctrl, ver, auth, errbuf);
+	if (status == 0)
+	{
+		//
+		// Success.
+		//
+		return 0;
+	}
+	if (status == -1)
+	{
+		/* Unrecoverable error. */
+		return -1;
+	}
+
+	/*
+	 * The server doesn't support the version we used in the initial
+	 * message, and it sent us back a reply either with the maximum
+	 * version they do support, or with the version we sent, and we
+	 * support that version.  *ver has been set to that version; try
+	 * authenticating again with that version.
+	 */
+	status = rpcap_sendauth(sockctrl, ver, auth, errbuf);
+	if (status == 0)
+	{
+		//
+		// Success.
+		//
+		return 0;
+	}
+	if (status == -1)
+	{
+		/* Unrecoverable error. */
+		return -1;
+	}
+	if (status == -2)
+	{
+		/*
+		 * The server doesn't support that version, which
+		 * means there is no version we both support, so
+		 * this is a fatal error.
+		 */
+		pcap_snprintf(errbuf, PCAP_ERRBUF_SIZE, "The server doesn't support any protocol version that we support");
+		return -1;
+	}
+	pcap_snprintf(errbuf, PCAP_ERRBUF_SIZE, "rpcap_sendauth() returned %d", status);
+	return -1;
+}
+
+/*
+ * This function sends the authentication message.
+ *
+ * It sends the authentication parameters on the control socket.
+ * It is required in order to open the connection with the other end party.
+ *
+ * \param sock: the socket we are currently using.
+ *
+ * \param ver: pointer to variable holding protocol version number to send
+ * and to set to the protocol version number in the reply.
+ *
+ * \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, '-2' if the server didn't reply with
+ * the protocol version we requested but replied with a version we do
+ * support, or '-1' for other errors.  For errors, an error message string
+ * is returned in the 'errbuf' variable.
+ */
+static int rpcap_sendauth(SOCKET sock, 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 */
+	int sendbufidx = 0;			/* index which keeps the number of bytes currently buffered */
+	uint16 length;				/* length of the payload of this message */
+	uint16 errcode;
 	struct rpcap_auth *rpauth;
 	uint16 auth_type;
 	struct rpcap_header header;
-	int retval;							/* temp variable which stores functions return value */
+	size_t str_length;
 
 	if (auth)
 	{
-		auth_type = auth->type;
-
 		switch (auth->type)
 		{
 		case RPCAP_RMTAUTH_NULL:
@@ -1766,14 +1908,34 @@
 
 		case RPCAP_RMTAUTH_PWD:
 			length = sizeof(struct rpcap_auth);
-			if (auth->username) length += (uint16) strlen(auth->username);
-			if (auth->password) length += (uint16) strlen(auth->password);
+			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
 	{
@@ -1786,7 +1948,8 @@
 		&sendbufidx, RPCAP_NETBUF_SIZE, SOCKBUF_CHECKONLY, errbuf, PCAP_ERRBUF_SIZE))
 		return -1;
 
-	rpcap_createhdr((struct rpcap_header *) sendbuf, RPCAP_MSG_AUTH_REQ, 0, length);
+	rpcap_createhdr((struct rpcap_header *) sendbuf, *ver,
+	    RPCAP_MSG_AUTH_REQ, 0, length);
 
 	rpauth = (struct rpcap_auth *) &sendbuf[sendbufidx];
 
@@ -1800,9 +1963,8 @@
 
 	if (auth_type == RPCAP_RMTAUTH_PWD)
 	{
-
 		if (auth->username)
-			rpauth->slen1 = (uint16) strlen(auth->username);
+			rpauth->slen1 = (uint16)strlen(auth->username);
 		else
 			rpauth->slen1 = 0;
 
@@ -1811,7 +1973,7 @@
 			return -1;
 
 		if (auth->password)
-			rpauth->slen2 = (uint16) strlen(auth->password);
+			rpauth->slen2 = (uint16)strlen(auth->password);
 		else
 			rpauth->slen2 = 0;
 
@@ -1823,267 +1985,872 @@
 		rpauth->slen2 = htons(rpauth->slen2);
 	}
 
-	if (sock_send(sock, sendbuf, sendbufidx, errbuf, PCAP_ERRBUF_SIZE))
+	if (sock_send(sock, sendbuf, sendbufidx, errbuf, PCAP_ERRBUF_SIZE) < 0)
 		return -1;
 
-	if (sock_recv(sock, (char *)&header, sizeof(struct rpcap_header), SOCK_RECEIVEALL_YES, errbuf, PCAP_ERRBUF_SIZE) == -1)
+	/* Receive the reply */
+	if (rpcap_recv_msg_header(sock, &header, errbuf) == -1)
 		return -1;
 
-	retval = rpcap_checkmsg(errbuf, sock, &header, RPCAP_MSG_AUTH_REPLY, RPCAP_MSG_ERROR, 0);
-
-	if (retval != RPCAP_MSG_AUTH_REPLY)		/* the message is not the one expected */
+	if (rpcap_check_msg_type(sock, RPCAP_MSG_AUTH_REQ, &header,
+	    &errcode, errbuf) == -1)
 	{
-		switch (retval)
+		/* Error message - or something else, which is a protocol error. */
+		if (header.type == RPCAP_MSG_ERROR &&
+		    errcode == PCAP_ERR_WRONGVER)
 		{
-		case -3:		/* Unrecoverable network error */
-		case -2:		/* The other endpoint sent a message that is not allowed here */
-		case -1:		/* The other endpoint has a version number that is not compatible with our */
-			/* Do nothing; just exit from here; the error code is already into the errbuf */
-			return -1;
+			/*
+			 * The server didn't support the version we sent,
+			 * and replied with the maximum version it supports
+			 * if our version was too big or with the version
+			 * we sent if out version was too small.
+			 *
+			 * Do we also support it?
+			 */
+			if (!RPCAP_VERSION_IS_SUPPORTED(header.ver))
+			{
+				/*
+				 * No, so there's no version we both support.
+				 * This is an unrecoverable error.
+				 */
+				pcap_snprintf(errbuf, PCAP_ERRBUF_SIZE, "The server doesn't support any protocol version that we support");
+				return -1;
+			}
 
-		case RPCAP_MSG_ERROR:
-			return -1;
-
-		default:
-			SOCK_ASSERT("Internal error", 0);
-			return -1;
+			/*
+			 * OK, use that version, and tell our caller to
+			 * try again.
+			 */
+			*ver = header.ver;
+			return -2;
 		}
+
+		/*
+		 * Other error - unrecoverable.
+		 */
+		return -1;
 	}
 
-	if (ntohl(header.plen))
-	{
-		if (sock_discard(sock, ntohl(header.plen), errbuf, PCAP_ERRBUF_SIZE))
-			return -1;
-	}
+	/*
+	 * OK, it's an authentication reply, so they're OK with the
+	 * protocol version we sent.
+	 *
+	 * Discard the rest of it.
+	 */
+	if (rpcap_discard(sock, header.plen, errbuf) == -1)
+		return -1;
 
 	return 0;
 }
 
-/* \ingroup remote_pri_func
- * \brief Creates a structure of type rpcap_header.
- *
- * This function is provided just because the creation of an rpcap header is quite a common
- * task. It accepts all the values that appears into an rpcap_header, and it puts them in
- * place using the proper hton() calls.
- *
- * \param header: a pointer to a user-allocated buffer which will contain the serialized
- * header, ready to be sent on the network.
- *
- * \param type: a value (in the host by order) which will be placed into the header.type
- * field and that represents the type of the current message.
- *
- * \param value: a value (in the host by order) which will be placed into the header.value
- * field and that has a message-dependent meaning.
- *
- * \param length: a value (in the host by order) which will be placed into the header.length
- * field and that represents the payload length of the message.
- *
- * \return Nothing. The serialized header is returned into the 'header' variable.
- */
-void rpcap_createhdr(struct rpcap_header *header, uint8 type, uint16 value, uint32 length)
+/* We don't currently support non-blocking mode. */
+static int
+pcap_getnonblock_rpcap(pcap_t *p)
 {
-	memset(header, 0, sizeof(struct rpcap_header));
-
-	header->ver = RPCAP_VERSION;
-	header->type = type;
-	header->value = htons(value);
-	header->plen = htonl(length);
+	pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
+	    "Non-blocking mode isn't supported for capturing remotely with rpcap");
+	return (-1);
 }
 
-/* ingroup remote_pri_func
- * \brief Checks if the header of the received message is correct.
- *
- * This function is a way to easily check if the message received, in a certain
- * state of the RPCAP protocol Finite State Machine, is valid. This function accepts,
- * as a parameter, the list of message types that are allowed in a certain situation,
- * and it returns the one which occurs.
- *
- * \param errbuf: a pointer to a user-allocated buffer (of size PCAP_ERRBUF_SIZE)
- * that will contain the error message (in case there is one). It could be either problem
- * occurred inside this function (e.g. a network problem in case it tries to send an
- * error on the other peer and the send() call fails), an error message which has been
- * sent to us from the other party, or a version error (the message receive has a version
- * number that is incompatible with our).
- *
- * \param sock: the socket that has to be used to receive data. This function can
- * read data from socket in case the version contained into the message is not compatible
- * with our. In that case, all the message is purged from the socket, so that the following
- * recv() calls will return a new message.
- *
- * \param header: a pointer to and 'rpcap_header' structure that keeps the data received from
- * the network (still in network byte order) and that has to be checked.
- *
- * \param first: this function has a variable number of parameters. From this point on,
- * all the messages that are valid in this context must be passed as parameters.
- * The message type list must be terminated with a '0' value, the null message type,
- * which means 'no more types to check'. The RPCAP protocol does not define anything with
- * message type equal to zero, so there is no ambiguity in using this value as a list terminator.
- *
- * \return The message type of the message that has been detected. In case of errors (e.g. the
- * header contains a type that is not listed among the allowed types), this function will
- * return the following codes:
- * - (-1) if the version is incompatible.
- * - (-2) if the code is not among the one listed into the parameters list
- * - (-3) if a network error (connection reset, ...)
- * - RPCAP_MSG_ERROR if the message is an error message (it follow that the RPCAP_MSG_ERROR
- * could not be present in the allowed message-types list, because this function checks
- * for errors anyway)
- *
- * In case either the version is incompatible or nothing matches (i.e. it returns '-1' or '-2'),
- * it discards the message body (i.e. it reads the remaining part of the message from the
- * network and it discards it) so that the application is ready to receive a new message.
- */
-int rpcap_checkmsg(char *errbuf, SOCKET sock, struct rpcap_header *header, uint8 first, ...)
+static int
+pcap_setnonblock_rpcap(pcap_t *p, int nonblock _U_)
 {
-	va_list ap;
-	uint8 type;
-	int32 len;
+	pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
+	    "Non-blocking mode isn't supported for capturing remotely with rpcap");
+	return (-1);
+}
 
-	va_start(ap, first);
+/*
+ * 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];
+	struct activehosts *activeconn;		/* active connection, if there is one */
+	int error;				/* '1' if rpcap_remoteact_getsock returned an error */
+	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 */
+	int retval;				/* store the return value of the functions */
 
-	/* Check if the present version of the protocol can handle this message */
-	if (rpcap_checkver(sock, header, errbuf))
+	/* 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)
 	{
-		SOCK_ASSERT(errbuf, 1);
-
-		va_end(ap);
-		return -1;
+		return NULL;
+	}
+	source_str = strdup(source);
+	if (source_str == NULL) {
+		pcap_fmt_errmsg_for_errno(errbuf, PCAP_ERRBUF_SIZE,
+		    errno, "malloc");
+		return NULL;
 	}
 
-	type = first;
+	/*
+	 * 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;
 
-	while (type != 0)
+	fp->opt.device = source_str;
+	fp->snapshot = snaplen;
+	fp->opt.timeout = read_timeout;
+	pr = fp->priv;
+	pr->rmt_flags = flags;
+
+	/*
+	 * determine the type of the source (NULL, file, local, remote)
+	 * You must have a valid source string even if we're in active mode, because otherwise
+	 * the call to the following function will fail.
+	 */
+	if (pcap_parsesrcstr(fp->opt.device, &retval, host, ctrlport, iface, errbuf) == -1)
 	{
-		/*
-		 * The message matches with one of the types listed
-		 * There is no need of conversions since both values are uint8
-		 *
-		 * Check if the other side reported an error.
-		 * If yes, it retrieves it and it returns it back to the caller
-		 */
-		if (header->type == RPCAP_MSG_ERROR)
+		pcap_close(fp);
+		return NULL;
+	}
+
+	if (retval != PCAP_SRC_IFREMOTE)
+	{
+		pcap_snprintf(errbuf, PCAP_ERRBUF_SIZE, "This function is able to open only remote interfaces");
+		pcap_close(fp);
+		return NULL;
+	}
+
+	/*
+	 * Warning: this call can be the first one called by the user.
+	 * For this reason, we have to initialize the WinSock support.
+	 */
+	if (sock_init(errbuf, PCAP_ERRBUF_SIZE) == -1)
+	{
+		pcap_close(fp);
+		return NULL;
+	}
+
+	/* Check for active mode */
+	activeconn = rpcap_remoteact_getsock(host, &error, errbuf);
+	if (activeconn != NULL)
+	{
+		sockctrl = activeconn->sockctrl;
+		protocol_version = activeconn->protocol_version;
+		active = 1;
+	}
+	else
+	{
+		struct addrinfo hints;			/* temp, needed to open a socket connection */
+		struct addrinfo *addrinfo;		/* temp, needed to open a socket connection */
+
+		if (error)
 		{
-			len = ntohl(header->plen);
+			/*
+			 * Call failed.
+			 */
+			pcap_close(fp);
+			return NULL;
+		}
 
-			if (len >= PCAP_ERRBUF_SIZE)
+		/*
+		 * We're not in active mode; let's try to open a new
+		 * control connection.
+		 */
+		memset(&hints, 0, sizeof(struct addrinfo));
+		hints.ai_family = PF_UNSPEC;
+		hints.ai_socktype = SOCK_STREAM;
+
+		if (ctrlport[0] == 0)
+		{
+			/* the user chose not to specify the port */
+			if (sock_initaddress(host, RPCAP_DEFAULT_NETPORT, &hints, &addrinfo, errbuf, PCAP_ERRBUF_SIZE) == -1)
 			{
-				if (sock_recv(sock, errbuf, PCAP_ERRBUF_SIZE - 1, SOCK_RECEIVEALL_YES, errbuf, PCAP_ERRBUF_SIZE))
-					return -3;
+				pcap_close(fp);
+				return NULL;
+			}
+		}
+		else
+		{
+			if (sock_initaddress(host, ctrlport, &hints, &addrinfo, errbuf, PCAP_ERRBUF_SIZE) == -1)
+			{
+				pcap_close(fp);
+				return NULL;
+			}
+		}
 
-				sock_discard(sock, len - (PCAP_ERRBUF_SIZE - 1), NULL, 0);
+		if ((sockctrl = sock_open(addrinfo, SOCKOPEN_CLIENT, 0, errbuf, PCAP_ERRBUF_SIZE)) == INVALID_SOCKET)
+		{
+			freeaddrinfo(addrinfo);
+			pcap_close(fp);
+			return NULL;
+		}
 
-				/* Put '\0' at the end of the string */
-				errbuf[PCAP_ERRBUF_SIZE - 1] = 0;
+		/* addrinfo is no longer used */
+		freeaddrinfo(addrinfo);
+
+		if (rpcap_doauth(sockctrl, &protocol_version, auth, errbuf) == -1)
+		{
+			sock_close(sockctrl, NULL, 0);
+			pcap_close(fp);
+			return NULL;
+		}
+		active = 0;
+	}
+
+	/*
+	 * 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(pr->rmt_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(pr->rmt_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"
+/* String identifier to be used in the pcap_findalldevs_ex() */
+#define PCAP_TEXT_SOURCE_ON_REMOTE_HOST "on remote node"
+
+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(char *source, struct pcap_rmtauth *auth, pcap_if_t **alldevs, char *errbuf)
+{
+	struct activehosts *activeconn;	/* active connection, if there is one */
+	int error;			/* '1' if rpcap_remoteact_getsock returned an error */
+	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 */
+	int type;
+	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;
+
+	/* Retrieve the needed data for getting adapter list */
+	if (pcap_parsesrcstr(source, &type, host, port, NULL, errbuf) == -1)
+		return -1;
+
+	/* Warning: this call can be the first one called by the user. */
+	/* For this reason, we have to initialize the WinSock support. */
+	if (sock_init(errbuf, PCAP_ERRBUF_SIZE) == -1)
+		return -1;
+
+	/* Check for active mode */
+	activeconn = rpcap_remoteact_getsock(host, &error, errbuf);
+	if (activeconn != NULL)
+	{
+		sockctrl = activeconn->sockctrl;
+		protocol_version = activeconn->protocol_version;
+		active = 1;
+	}
+	else
+	{
+		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 ((sockctrl = 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(sockctrl, &protocol_version, auth, errbuf) == -1)
+		{
+			sock_close(sockctrl, NULL, 0);
+			return -1;
+		}
+		active = 0;
+	}
+
+	/* 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 */
+		size_t stringlen;
+		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)
+				return -1;
+
+			stringlen = strlen(tmpstring2);
+
+			dev->name = (char *)malloc(stringlen + 1);
+			if (dev->name == NULL)
+			{
+				pcap_fmt_errmsg_for_errno(errbuf,
+				    PCAP_ERRBUF_SIZE, errno, "malloc() failed");
+				goto error;
+			}
+
+			/* Copy the new device name into the correct memory location */
+			strlcpy(dev->name, tmpstring2, stringlen + 1);
+		}
+
+		if (findalldevs_if.desclen)
+		{
+			if (findalldevs_if.desclen >= sizeof(tmpstring))
+			{
+				pcap_snprintf(errbuf, PCAP_ERRBUF_SIZE, "Interface description too long");
+				goto error;
+			}
+
+			/* Retrieve adapter description */
+			if (rpcap_recv(sockctrl, tmpstring,
+			    findalldevs_if.desclen, &plen, errbuf) == -1)
+				goto error;
+
+			tmpstring[findalldevs_if.desclen] = 0;
+
+			pcap_snprintf(tmpstring2, sizeof(tmpstring2) - 1, "%s '%s' %s %s", PCAP_TEXT_SOURCE_ADAPTER,
+				tmpstring, PCAP_TEXT_SOURCE_ON_REMOTE_HOST, host);
+
+			stringlen = strlen(tmpstring2);
+
+			dev->description = (char *)malloc(stringlen + 1);
+
+			if (dev->description == NULL)
+			{
+				pcap_fmt_errmsg_for_errno(errbuf,
+				    PCAP_ERRBUF_SIZE, errno, "malloc() failed");
+				goto error;
+			}
+
+			/* Copy the new device description into the correct memory location */
+			strlcpy(dev->description, tmpstring2, stringlen + 1);
+		}
+
+		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
 			{
-				if (sock_recv(sock, errbuf, len, SOCK_RECEIVEALL_YES, errbuf, PCAP_ERRBUF_SIZE) == -1)
-					return -3;
-
-				/* Put '\0' at the end of the string */
-				errbuf[len] = 0;
+				/*
+				 * Add this entry to the list.
+				 */
+				if (prevaddr == NULL)
+				{
+					dev->addresses = addr;
+				}
+				else
+				{
+					prevaddr->next = addr;
+				}
+				prevaddr = addr;
 			}
-
-
-			va_end(ap);
-			return header->type;
 		}
-
-		if (header->type == type)
-		{
-			va_end(ap);
-			return header->type;
-		}
-
-		/* get next argument */
-		type = va_arg(ap, int);
 	}
 
-	/* we already have an error, so please discard this one */
-	sock_discard(sock, ntohl(header->plen), NULL, 0);
+	/* Discard the rest of the message. */
+	if (rpcap_discard(sockctrl, plen, errbuf) == 1)
+		goto error_nodiscard;
 
-	pcap_snprintf(errbuf, PCAP_ERRBUF_SIZE, "The other endpoint sent a message that is not allowed here.");
-	SOCK_ASSERT(errbuf, 1);
-
-	va_end(ap);
-	return -2;
-}
-
-/* \ingroup remote_pri_func
- * \brief Checks if the version contained into the message is compatible with
- * the one handled by this implementation.
- *
- * Right now, this function does not have any sophisticated task: if the versions
- * are different, it returns -1 and it discards the message.
- * It is expected that in the future this message will become more complex.
- *
- * \param sock: the socket that has to be used to receive data. This function can
- * read data from socket in case the version contained into the message is not compatible
- * with our. In that case, all the message is purged from the socket, so that the following
- * recv() calls will return a new (clean) message.
- *
- * \param header: a pointer to and 'rpcap_header' structure that keeps the data received from
- * the network (still in network byte order) and that has to be checked.
- *
- * \param errbuf: a pointer to a user-allocated buffer (of size PCAP_ERRBUF_SIZE)
- * that will contain the error message (in case there is one). The error message is
- * "incompatible version".
- *
- * \return '0' if everything is fine, '-1' if some errors occurred. The error message is returned
- * in the 'errbuf' variable.
- */
-static int rpcap_checkver(SOCKET sock, struct rpcap_header *header, char *errbuf)
-{
-	/*
-	 * This is a sample function.
-	 *
-	 * In the real world, you have to check at the type code,
-	 * and decide accordingly.
-	 */
-
-	if (header->ver != RPCAP_VERSION)
+	/* Control connection has to be closed only in case the remote machine is in passive mode */
+	if (!active)
 	{
-		pcap_snprintf(errbuf, PCAP_ERRBUF_SIZE, "Incompatible version number: message discarded.");
-
-		/* we already have an error, so please discard this one */
-		sock_discard(sock, ntohl(header->plen), NULL, 0);
-		return -1;
+		/* 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;
 }
 
-/* \ingroup remote_pri_func
+/*
+ * Active mode routines.
  *
- * \brief It returns the socket currently used for this active connection
- * (active mode only) and provides an indication of whether this connection
- * is in active mode or not.
- *
- * This function is just for internal use; it returns the socket ID of the
- * active connection currently opened.
- *
- * \param host: a string that keeps the host name of the host for which we
- * want to get the socket ID for that active connection.
- *
- * \param isactive: a pointer to an int that is set to 1 if there's an
- * active connection to that host and 0 otherwise.
- *
- * \param errbuf: a pointer to a user-allocated buffer (of size
- * PCAP_ERRBUF_SIZE) that will contain the error message (in case
- * there is one).
- *
- * \return the socket identifier if everything is fine, '0' if this host
- * is not in the active host list. An indication of whether this host
- * is in the active host list is returned into the isactive variable.
- * It returns 'INVALID_SOCKET' in case of error. The error message is
- * returned into the errbuf variable.
+ * 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 rpcap_remoteact_getsock(const char *host, int *isactive, char *errbuf)
+
+SOCKET pcap_remoteact_accept(const char *address, const char *port, const char *hostlist, char *connectinghost, struct pcap_rmtauth *auth, char *errbuf)
 {
-	struct activehosts *temp;					/* temp var needed to scan the host list chain */
+	/* 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)
+		{
+			SOCK_DEBUG_MESSAGE(errbuf);
+			return (SOCKET)-2;
+		}
+	}
+	else
+	{
+		if (sock_initaddress(address, port, &hints, &addrinfo, errbuf, PCAP_ERRBUF_SIZE) == -1)
+		{
+			SOCK_DEBUG_MESSAGE(errbuf);
+			return (SOCKET)-2;
+		}
+	}
+
+
+	if ((sockmain = sock_open(addrinfo, SOCKOPEN_SERVER, 1, errbuf, PCAP_ERRBUF_SIZE)) == INVALID_SOCKET)
+	{
+		SOCK_DEBUG_MESSAGE(errbuf);
+		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));
@@ -2094,34 +2861,451 @@
 	if (retval != 0)
 	{
 		pcap_snprintf(errbuf, PCAP_ERRBUF_SIZE, "getaddrinfo() %s", gai_strerror(retval));
-		*isactive = 0;
-		return INVALID_SOCKET;
+		return -1;
 	}
 
-	temp = activeHosts;
-
 	while (temp)
 	{
 		ai_next = addrinfo;
 		while (ai_next)
 		{
-			if (sock_cmpaddr(&temp->host, (struct sockaddr_storage *) ai_next->ai_addr) == 0) {
-				*isactive = 1;
-				return (temp->sockctrl);
+			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;
+		}
+
+		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)
+{
 	/*
-	 * The host for which you want to get the socket ID does not have an
-	 * active connection.
+	 * Did the server specify the version we negotiated?
 	 */
-	*isactive = 0;
+	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
index f84e8ba..be31c40 100644
--- a/pcap-rpcap.h
+++ b/pcap-rpcap.h
@@ -1,465 +1,49 @@
 /*
- * Copyright (c) 2002 - 2005 NetGroup, Politecnico di Torino (Italy)
- * Copyright (c) 2005 - 2008 CACE Technologies, Davis (California)
- * 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.
+ *    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.
+ *    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 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.
- *
+ * 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__
-
-
-#include "pcap.h"
-#include "sockutils.h"	/* Needed for some structures (like SOCKET, sockaddr_in) which are used here */
-
+#ifndef pcap_rpcap_h
+#define	pcap_rpcap_h
 
 /*
- * \file pcap-pcap.h
- *
- * This file keeps all the new definitions and typedefs that are exported to the user and
- * that are needed for the RPCAP protocol.
- *
- * \warning All the RPCAP functions that are allowed to return a buffer containing
- * the error description can return max PCAP_ERRBUF_SIZE characters.
- * However there is no guarantees that the string will be zero-terminated.
- * Best practice is to define the errbuf variable as a char of size 'PCAP_ERRBUF_SIZE+1'
- * and to insert manually the termination char at the end of the buffer. This will
- * guarantee that no buffer overflows occur even if we use the printf() to show
- * the error on the screen.
- *
- * \warning This file declares some typedefs that MUST be of a specific size.
- * These definitions (i.e. typedefs) could need to be changed on other platforms than
- * Intel IA32.
- *
- * \warning This file defines some structures that are used to transfer data on the network.
- * Be careful that you compiler MUST not insert padding into these structures
- * for better alignment.
- * These structures have been created in order to be correctly aligned to a 32 bits
- * boundary, but be careful in any case.
+ * Internal interfaces for "pcap_open()".
  */
-
-
-
-
-
-
-
-
-/*********************************************************
- *                                                       *
- * General definitions / typedefs for the RPCAP protocol *
- *                                                       *
- *********************************************************/
-
-/* All the following structures and typedef belongs to the Private Documentation */
-/*
- * \addtogroup remote_pri_struct
- * \{
- */
-
-#define RPCAP_DEFAULT_NETPORT "2002" /* Default port on which the RPCAP daemon is waiting for connections. */
-/* Default port on which the client workstation is waiting for connections in case of active mode. */
-#define RPCAP_DEFAULT_NETPORT_ACTIVE "2003"
-#define RPCAP_DEFAULT_NETADDR ""	/* Default network address on which the RPCAP daemon binds to. */
-#define RPCAP_VERSION 0				/* Present version of the RPCAP protocol (0 = Experimental). */
-#define RPCAP_TIMEOUT_INIT 90		/* Initial timeout for RPCAP connections (default: 90 sec) */
-#define RPCAP_TIMEOUT_RUNTIME 180	/* Run-time timeout for RPCAP connections (default: 3 min) */
-#define RPCAP_ACTIVE_WAIT 30		/* Waiting time between two attempts to open a connection, in active mode (default: 30 sec) */
-#define RPCAP_SUSPEND_WRONGAUTH 1	/* If the authentication is wrong, stops 1 sec before accepting a new auth message */
+pcap_t	*pcap_open_rpcap(const char *source, int snaplen, int flags,
+    int read_timeout, struct pcap_rmtauth *auth, char *errbuf);
 
 /*
- * \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.
+ * Internal interfaces for "pcap_findalldevs_ex()".
  */
-#define RPCAP_NETBUF_SIZE 64000
-
-
-/*
- * \brief Separators used for the host list.
- *
- * It is used:
- * - by the rpcapd daemon, when you types a list of allowed connecting hosts
- * - by the rpcap in active mode, when the client waits for incoming connections from other hosts
- */
-#define RPCAP_HOSTLIST_SEP " ,;\n\r"
-
-
-
-
-/* WARNING: These could need to be changed on other platforms */
-typedef unsigned char uint8;		/* Provides an 8-bits unsigned integer */
-typedef unsigned short uint16;		/* Provides a 16-bits unsigned integer */
-typedef unsigned int uint32;		/* Provides a 32-bits unsigned integer */
-typedef int int32;					/* Provides a 32-bits integer */
-
-
-
-
-/*
- * \brief Keeps a list of all the opened connections in the active mode.
- *
- * This structure defines a linked list of items that are needed to keep the info required to
- * manage the active mode.
- * In other words, when a new connection in active mode starts, this structure is updated so that
- * it reflects the list of active mode connections currently opened.
- * This structure is required by findalldevs() and open_remote() to see if they have to open a new
- * control connection toward the host, or they already have a control connection in place.
- */
-struct activehosts
-{
-	struct sockaddr_storage host;
-	SOCKET sockctrl;
-	struct activehosts *next;
-};
-
-
-/*********************************************************
- *                                                       *
- * Protocol messages formats                             *
- *                                                       *
- *********************************************************/
-/* WARNING Take care you compiler does not insert padding for better alignments into these structs */
-
-
-/* Common header for all the RPCAP messages */
-struct rpcap_header
-{
-	uint8 ver;							/* RPCAP version number */
-	uint8 type;							/* RPCAP message type (error, findalldevs, ...) */
-	uint16 value;						/* Message-dependent value (not always used) */
-	uint32 plen;						/* Length of the payload of this RPCAP message */
-};
-
-
-/* Format of the message for the interface description (findalldevs command) */
-struct rpcap_findalldevs_if
-{
-	uint16 namelen;						/* Length of the interface name */
-	uint16 desclen;						/* Length of the interface description */
-	uint32 flags;						/* Interface flags */
-	uint16 naddr;						/* Number of addresses */
-	uint16 dummy;						/* Must be zero */
-};
-
-
-/* Format of the message for the address listing (findalldevs command) */
-struct rpcap_findalldevs_ifaddr
-{
-	struct sockaddr_storage addr;		/* Network address */
-	struct sockaddr_storage netmask;	/* Netmask for that address */
-	struct sockaddr_storage broadaddr;	/* Broadcast address for that address */
-	struct sockaddr_storage dstaddr;	/* P2P destination address for that address */
-};
-
-
-
-/*
- * \brief Format of the message of the connection opening reply (open command).
- *
- * This structure transfers over the network some of the values useful on the client side.
- */
-struct rpcap_openreply
-{
-	int32 linktype;						/* Link type */
-	int32 tzoff;						/* Timezone offset */
-};
-
-
-
-/* Format of the message that starts a remote capture (startcap command) */
-struct rpcap_startcapreq
-{
-	uint32 snaplen;						/* Length of the snapshot (number of bytes to capture for each packet) */
-	uint32 read_timeout;				/* Read timeout in milliseconds */
-	uint16 flags;						/* Flags (see RPCAP_STARTCAPREQ_FLAG_xxx) */
-	uint16 portdata;					/* Network port on which the client is waiting at (if 'serveropen') */
-};
-
-
-/* Format of the reply message that devoted to start a remote capture (startcap reply command) */
-struct rpcap_startcapreply
-{
-	int32 bufsize;						/* Size of the user buffer allocated by WinPcap; it can be different from the one we chose */
-	uint16 portdata;					/* Network port on which the server is waiting at (passive mode only) */
-	uint16 dummy;						/* Must be zero */
-};
-
-
-/*
- * \brief Format of the header which encapsulates captured packets when transmitted on the network.
- *
- * This message requires the general header as well, since we want to be able to exchange
- * more information across the network in the future (for example statistics, and kind like that).
- */
-struct rpcap_pkthdr
-{
-	uint32 timestamp_sec;	/* 'struct timeval' compatible, it represents the 'tv_sec' field */
-	uint32 timestamp_usec;	/* 'struct timeval' compatible, it represents the 'tv_usec' field */
-	uint32 caplen;			/* Length of portion present in the capture */
-	uint32 len;				/* Real length this packet (off wire) */
-	uint32 npkt;			/* Ordinal number of the packet (i.e. the first one captured has '1', the second one '2', etc) */
-};
-
-
-/* General header used for the pcap_setfilter() command; keeps just the number of BPF instructions */
-struct rpcap_filter
-{
-	uint16 filtertype;		/* type of the filter transferred (BPF instructions, ...) */
-	uint16 dummy;			/* Must be zero */
-	uint32 nitems;			/* Number of items contained into the filter (e.g. BPF instructions for BPF filters) */
-};
-
-
-/* Structure that keeps a single BPF instuction; it is repeated 'ninsn' times according to the 'rpcap_filterbpf' header */
-struct rpcap_filterbpf_insn
-{
-	uint16 code;			/* opcode of the instruction */
-	uint8 jt;				/* relative offset to jump to in case of 'true' */
-	uint8 jf;				/* relative offset to jump to in case of 'false' */
-	int32 k;				/* instruction-dependent value */
-};
-
-
-/* Structure that keeps the data required for the authentication on the remote host */
-struct rpcap_auth
-{
-	uint16 type;			/* Authentication type */
-	uint16 dummy;			/* Must be zero */
-	uint16 slen1;			/* Length of the first authentication item (e.g. username) */
-	uint16 slen2;			/* Length of the second authentication item (e.g. password) */
-};
-
-
-/* Structure that keeps the statistics about the number of packets captured, dropped, etc. */
-struct rpcap_stats
-{
-	uint32 ifrecv;		/* Packets received by the kernel filter (i.e. pcap_stats.ps_recv) */
-	uint32 ifdrop;		/* Packets dropped by the network interface (e.g. not enough buffers) (i.e. pcap_stats.ps_ifdrop) */
-	uint32 krnldrop;	/* Packets dropped by the kernel filter (i.e. pcap_stats.ps_drop) */
-	uint32 svrcapt;		/* Packets captured by the RPCAP daemon and sent on the network */
-};
-
-
-/* Structure that is needed to set sampling parameters */
-struct rpcap_sampling
-{
-	uint8 method;		/* Sampling method */
-	uint8 dummy1;		/* Must be zero */
-	uint16 dummy2;		/* Must be zero */
-	uint32 value;		/* Parameter related to the sampling method */
-};
-
-
-/*
- * Private data for doing a live capture.
- */
-struct pcap_md {
-	struct pcap_stat stat;
-	/* XXX */
-	int		use_bpf;		/* using kernel filter */
-	u_long	TotPkts;		/* can't overflow for 79 hrs on ether */
-	u_long	TotAccepted;	/* count accepted by filter */
-	u_long	TotDrops;		/* count of dropped packets */
-	long	TotMissed;		/* missed by i/f during this run */
-	long	OrigMissed;		/* missed by i/f before this run */
-	char	*device;		/* device name */
-	int		timeout;		/* timeout for buffering */
-	int		must_clear;		/* stuff we must clear when we close */
-	struct pcap *next;		/* list of open pcaps that need stuff cleared on close */
-#ifdef linux
-	int		sock_packet;	/* using Linux 2.0 compatible interface */
-	int		cooked;			/* using SOCK_DGRAM rather than SOCK_RAW */
-	int		ifindex;		/* interface index of device we're bound to */
-	int		lo_ifindex;		/* interface index of the loopback device */
-	u_int	packets_read;	/* count of packets read with recvfrom() */
-	bpf_u_int32 oldmode;	/* mode to restore when turning monitor mode off */
-	u_int	tp_version;		/* version of tpacket_hdr for mmaped ring */
-	u_int	tp_hdrlen;		/* hdrlen of tpacket_hdr for mmaped ring */
-#endif /* linux */
-
-#ifdef HAVE_DAG_API
-#ifdef HAVE_DAG_STREAMS_API
-	u_char	*dag_mem_bottom;/* DAG card current memory bottom pointer */
-	u_char	*dag_mem_top;	/* DAG card current memory top pointer */
-#else /* HAVE_DAG_STREAMS_API */
-	void	*dag_mem_base;	/* DAG card memory base address */
-	u_int	dag_mem_bottom;	/* DAG card current memory bottom offset */
-	u_int	dag_mem_top;	/* DAG card current memory top offset */
-#endif /* HAVE_DAG_STREAMS_API */
-	int	dag_fcs_bits;		/* Number of checksum bits from link layer */
-	int	dag_offset_flags;	/* Flags to pass to dag_offset(). */
-	int	dag_stream;			/* DAG stream number */
-	int	dag_timeout;		/* timeout specified to pcap_open_live.
-							 * Same as in linux above, introduce
-							 * generally?
-							 */
-#endif /* HAVE_DAG_API */
-#ifdef HAVE_ZEROCOPY_BPF
-	/*
-	 * Zero-copy read buffer -- for zero-copy BPF.  'buffer' above will
-	 * alternative between these two actual mmap'd buffers as required.
-	 * As there is a header on the front size of the mmap'd buffer, only
-	 * some of the buffer is exposed to libpcap as a whole via bufsize;
-	 * zbufsize is the true size.  zbuffer tracks the current zbuf
-	 * associated with buffer so that it can be used to decide which the
-	 * next buffer to read will be.
-	 */
-	u_char *zbuf1, *zbuf2, *zbuffer;
-	u_int zbufsize;
-	u_int zerocopy;
-	u_int interrupted;
-	struct timespec firstsel;
-	/*
-	 * If there's currently a buffer being actively processed, then it is
-	 * referenced here; 'buffer' is also pointed at it, but offset by the
-	 * size of the header.
-	 */
-	struct bpf_zbuf_header *bzh;
-#endif /* HAVE_ZEROCOPY_BPF */
-
-
-
-#ifdef HAVE_REMOTE
-	/*
-	 * There is really a mess with previous variables, and it seems to me that they are not used
-	 * (they are used in pcap_pf.c only). I think we have to start using them.
-	 * The meaning is the following:
-	 *
-	 * - TotPkts: the amount of packets received by the bpf filter, *before* applying the filter
-	 * - TotAccepted: the amount of packets that satisfies the filter
-	 * - TotDrops: the amount of packet that were dropped into the kernel buffer because of lack of space
-	 * - TotMissed: the amount of packets that were dropped by the physical interface; it is basically
-	 * the value of the hardware counter into the card. This number is never put to zero, so this number
-	 * takes into account the *total* number of interface drops starting from the interface power-on.
-	 * - OrigMissed: the amount of packets that were dropped by the interface *when the capture begins*.
-	 * This value is used to detect the number of packets dropped by the interface *during the present
-	 * capture*, so that (ps_ifdrops= TotMissed - OrigMissed).
-	 */
-	unsigned int TotNetDrops;		/* keeps the number of packets that have been dropped by the network */
-	/*
-	 * \brief It keeps the number of packets that have been received by the application.
-	 *
-	 * Packets dropped by the kernel buffer are not counted in this variable. The variable is always
-	 * equal to (TotAccepted - TotDrops), except for the case of remote capture, in which we have also
-	 * packets in flight, i.e. that have been transmitted by the remote host, but that have not been
-	 * received (yet) from the client. In this case, (TotAccepted - TotDrops - TotNetDrops) gives a
-	 * wrong result, since this number does not corresponds always to the number of packet received by
-	 * the application. For this reason, in the remote capture we need another variable that takes
-	 * into account of the number of packets actually received by the application.
-	 */
-	unsigned int TotCapt;
-
-	/*! \brief '1' if we're the network client; needed by several functions (like pcap_setfilter() ) to know if
-	they have to use the socket or they have to open the local adapter. */
-	int rmt_clientside;
-
-	SOCKET rmt_sockctrl;		//!< socket ID of the socket used for the control connection
-	SOCKET rmt_sockdata;		//!< socket ID of the socket used for the data connection
-	int rmt_flags;				//!< we have to save flags, since they are passed by the pcap_open_live(), but they are used by the pcap_startcapture()
-	int rmt_capstarted;			//!< 'true' if the capture is already started (needed to knoe if we have to call the pcap_startcapture()
-	struct pcap_samp rmt_samp;	//!< Keeps the parameters related to the sampling process.
-	char *currentfilter;		//!< Pointer to a buffer (allocated at run-time) that stores the current filter. Needed when flag PCAP_OPENFLAG_NOCAPTURE_RPCAP is turned on.
-#endif /* HAVE_REMOTE */
-
-};
-
-
-/* Messages field coding */
-#define RPCAP_MSG_ERROR 1				/* Message that keeps an error notification */
-#define RPCAP_MSG_FINDALLIF_REQ 2		/* Request to list all the remote interfaces */
-#define RPCAP_MSG_OPEN_REQ 3			/* Request to open a remote device */
-#define RPCAP_MSG_STARTCAP_REQ 4		/* Request to start a capture on a remote device */
-#define RPCAP_MSG_UPDATEFILTER_REQ 5	/* Send a compiled filter into the remote device */
-#define RPCAP_MSG_CLOSE 6				/* Close the connection with the remote peer */
-#define RPCAP_MSG_PACKET 7				/* This is a 'data' message, which carries a network packet */
-#define RPCAP_MSG_AUTH_REQ 8			/* Message that keeps the authentication parameters */
-#define RPCAP_MSG_STATS_REQ 9			/* It requires to have network statistics */
-#define RPCAP_MSG_ENDCAP_REQ 10			/* Stops the current capture, keeping the device open */
-#define RPCAP_MSG_SETSAMPLING_REQ 11	/* Set sampling parameters */
-
-#define RPCAP_MSG_FINDALLIF_REPLY	(128+RPCAP_MSG_FINDALLIF_REQ)		/* Keeps the list of all the remote interfaces */
-#define RPCAP_MSG_OPEN_REPLY		(128+RPCAP_MSG_OPEN_REQ)			/* The remote device has been opened correctly */
-#define RPCAP_MSG_STARTCAP_REPLY	(128+RPCAP_MSG_STARTCAP_REQ)		/* The capture is starting correctly */
-#define RPCAP_MSG_UPDATEFILTER_REPLY (128+RPCAP_MSG_UPDATEFILTER_REQ)	/* The filter has been applied correctly on the remote device */
-#define RPCAP_MSG_AUTH_REPLY		(128+RPCAP_MSG_AUTH_REQ)			/* Sends a message that says 'ok, authorization successful' */
-#define RPCAP_MSG_STATS_REPLY		(128+RPCAP_MSG_STATS_REQ)			/* Message that keeps the network statistics */
-#define RPCAP_MSG_ENDCAP_REPLY		(128+RPCAP_MSG_ENDCAP_REQ)			/* Confirms that the capture stopped successfully */
-#define RPCAP_MSG_SETSAMPLING_REPLY	(128+RPCAP_MSG_SETSAMPLING_REQ)		/* Confirms that the capture stopped successfully */
-
-#define RPCAP_STARTCAPREQ_FLAG_PROMISC 1	/* Enables promiscuous mode (default: disabled) */
-#define RPCAP_STARTCAPREQ_FLAG_DGRAM 2		/* Use a datagram (i.e. UDP) connection for the data stream (default: use TCP)*/
-#define RPCAP_STARTCAPREQ_FLAG_SERVEROPEN 4	/* The server has to open the data connection toward the client */
-#define RPCAP_STARTCAPREQ_FLAG_INBOUND 8	/* Capture only inbound packets (take care: the flag has no effects with promiscuous enabled) */
-#define RPCAP_STARTCAPREQ_FLAG_OUTBOUND 16	/* Capture only outbound packets (take care: the flag has no effects with promiscuous enabled) */
-
-#define RPCAP_UPDATEFILTER_BPF 1			/* This code tells us that the filter is encoded with the BPF/NPF syntax */
-
-
-/* Network error codes */
-#define PCAP_ERR_NETW 1					/* Network error */
-#define PCAP_ERR_INITTIMEOUT 2			/* The RPCAP initial timeout has expired */
-#define PCAP_ERR_AUTH 3					/* Generic authentication error */
-#define PCAP_ERR_FINDALLIF 4			/* Generic findalldevs error */
-#define PCAP_ERR_NOREMOTEIF 5			/* The findalldevs was ok, but the remote end had no interfaces to list */
-#define PCAP_ERR_OPEN 6					/* Generic pcap_open error */
-#define PCAP_ERR_UPDATEFILTER 7			/* Generic updatefilter error */
-#define PCAP_ERR_GETSTATS 8				/* Generic pcap_stats error */
-#define PCAP_ERR_READEX 9				/* Generic pcap_next_ex error */
-#define PCAP_ERR_HOSTNOAUTH 10			/* The host is not authorized to connect to this server */
-#define PCAP_ERR_REMOTEACCEPT 11		/* Generic pcap_remoteaccept error */
-#define PCAP_ERR_STARTCAPTURE 12		/* Generic pcap_startcapture error */
-#define PCAP_ERR_ENDCAPTURE 13			/* Generic pcap_endcapture error */
-#define PCAP_ERR_RUNTIMETIMEOUT	14		/* The RPCAP run-time timeout has expired */
-#define PCAP_ERR_SETSAMPLING 15			/* Error during the settings of sampling parameters */
-#define PCAP_ERR_WRONGMSG 16			/* The other end endpoint sent a message which has not been recognized */
-#define PCAP_ERR_WRONGVER 17			/* The other end endpoint has a version number that is not compatible with our */
-/*
- * \}
- * // end of private documentation
- */
-
-
-/*********************************************************
- *                                                       *
- * Exported function prototypes                          *
- *                                                       *
- *********************************************************/
-int pcap_opensource_remote(pcap_t *p, struct pcap_rmtauth *auth);
-int pcap_startcapture_remote(pcap_t *fp);
-
-void rpcap_createhdr(struct rpcap_header *header, uint8 type, uint16 value, uint32 length);
-int rpcap_deseraddr(struct sockaddr_storage *sockaddrin, struct sockaddr_storage **sockaddrout, char *errbuf);
-int rpcap_checkmsg(char *errbuf, SOCKET sock, struct rpcap_header *header, uint8 first, ...);
-int rpcap_senderror(SOCKET sock, char *error, unsigned short errcode, char *errbuf);
-int rpcap_sendauth(SOCKET sock, struct pcap_rmtauth *auth, char *errbuf);
-
-SOCKET rpcap_remoteact_getsock(const char *host, int *isactive, char *errbuf);
+int	pcap_findalldevs_ex_remote(char *source, struct pcap_rmtauth *auth,
+   pcap_if_t **alldevs, char *errbuf);
 
 #endif
-
diff --git a/pcap-septel.c b/pcap-septel.c
index 88dc89d..0471153 100644
--- a/pcap-septel.c
+++ b/pcap-septel.c
@@ -15,7 +15,7 @@
  */
 
 #ifdef HAVE_CONFIG_H
-#include "config.h"
+#include <config.h>
 #endif
 
 #include <sys/param.h>
@@ -43,7 +43,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.
@@ -197,6 +198,17 @@
   /* 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 +220,7 @@
   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;
 
@@ -237,6 +249,15 @@
 		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;
 }
 
@@ -252,10 +273,14 @@
 
 
 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,20 +300,29 @@
 
   /* Make our private copy of the filter */
 
-  if (install_bpf_program(p, fp) < 0) {
-    pcap_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);
 }
 
@@ -302,9 +336,8 @@
  * There are no regular interfaces, just Septel interfaces.
  */
 int
-pcap_platform_finddevs(pcap_if_t **alldevsp, char *errbuf)
+pcap_platform_finddevs(pcap_if_list_t *devlistp, char *errbuf)
 {
-  *alldevsp = NULL;
   return (0);
 }
 
@@ -318,4 +351,13 @@
                 "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
diff --git a/pcap-septel.h b/pcap-septel.h
index b6e1168..0e648b2 100644
--- a/pcap-septel.h
+++ b/pcap-septel.h
@@ -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);
diff --git a/pcap-sita.c b/pcap-sita.c
index 1cd5f75..7c42791 100644
--- a/pcap-sita.c
+++ b/pcap-sita.c
@@ -25,7 +25,7 @@
  */
 
 #ifdef HAVE_CONFIG_H
-#include "config.h"
+#include <config.h>
 #endif
 
 #include <stdio.h>
@@ -293,7 +293,8 @@
 			continue;																	/* and ignore the entry */
 		}
 		if ((ptr2 = (char *)malloc(strlen(ptr) + 1)) == NULL) {
-			pcap_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 */
@@ -582,7 +583,8 @@
 			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) {
-					pcap_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() */
@@ -591,7 +593,9 @@
 
 				if (*ptr) {													/* if there is a count for the name */
 					if ((iff->name = malloc(*ptr + 1)) == NULL) {			/* get that amount of space */
-						pcap_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 */
@@ -602,7 +606,9 @@
 
 				if (*ptr) {													/* if there is a count for the description */
 					if ((iff->description = malloc(*ptr + 1)) == NULL) {	/* get that amount of space */
-						pcap_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 */
@@ -622,7 +628,9 @@
 				prev_addr = 0;
 				while (address_count--) {
 					if ((addr = malloc(sizeof(pcap_addr_t))) == NULL) {
-						pcap_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() */
@@ -630,7 +638,9 @@
 					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 */
-							pcap_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() */
@@ -642,7 +652,9 @@
 					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) {
-							pcap_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() */
@@ -656,7 +668,9 @@
 					ptr++;
 					if (*ptr) {												/* process any broadcast address */
 						if ((s = malloc(sizeof(struct sockaddr_in))) == NULL) {
-							pcap_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() */
@@ -670,7 +684,9 @@
 					ptr++;
 					if (*ptr) {												/* process any destination address */
 						if ((s = malloc(sizeof(struct sockaddr_in))) == NULL) {
-							pcap_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() */
@@ -689,7 +705,8 @@
 				newname = translate_IOP_to_pcap_name(u, iff->name, interfaceType);		/* add a translation entry and get a point to the mangled name */
 				bigger_buffer = realloc(iff->name, strlen(newname) + 1));
 				if (bigger_buffer == NULL) {	/* we now re-write the name stored in the interface list */
-					pcap_snprintf(errbuf, PCAP_ERRBUF_SIZE, "realloc: %s", pcap_strerror(errno));
+					pcap_fmt_errmsg_for_errno(errbuf,
+					    PCAP_ERRBUF_SIZE, errno, "realloc");
 					return -1;
 				}
 				iff->name = bigger_buffer;
@@ -821,9 +838,9 @@
 	int			chassis, geoslot;
 	unit_t		*u;
 	iface_t		*p;
-	pcap_if_t	*alldevsp;
+	pcap_if_list_t	devlist;
 
-	pcap_platform_finddevs(&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];
@@ -992,6 +1009,18 @@
 	    &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;
 
@@ -999,8 +1028,8 @@
 
 	handle->buffer	 = malloc(handle->bufsize + handle->offset);
 	if (!handle->buffer) {
-	        pcap_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;
 	}
@@ -1025,7 +1054,7 @@
 	return (p);
 }
 
-int pcap_platform_finddevs(pcap_if_t **alldevsp, char *errbuf) {
+int pcap_platform_finddevs(pcap_if_list_t *devlistp, char *errbuf) {
 
 	//printf("pcap_findalldevs()\n");				// fulko
 
@@ -1042,8 +1071,17 @@
 		//printf("pcap_findalldevs() returning BAD after findalldevs\n");				// fulko
 		return -1;
 		}
-	*alldevsp = acn_if_list;
+	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)";
+}
diff --git a/pcap-snf.c b/pcap-snf.c
index 207c495..4eae0b3 100644
--- a/pcap-snf.c
+++ b/pcap-snf.c
@@ -1,19 +1,23 @@
 #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
@@ -30,10 +34,10 @@
 	snf_handle_t snf_handle; /* opaque device handle */
 	snf_ring_t   snf_ring;   /* opaque device ring handle */
 #ifdef SNF_HAVE_INJECT_API
-        snf_inject_t snf_inj;    /* inject handle, if inject is used */
+	snf_inject_t snf_inj;    /* inject handle, if inject is used */
 #endif
-        int          snf_timeout;
-        int          snf_boardnum;
+	int          snf_timeout;
+	int          snf_boardnum;
 };
 
 static int
@@ -51,8 +55,8 @@
 	int rc;
 
 	if ((rc = snf_ring_getstats(snfps->snf_ring, &stats))) {
-		pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "snf_get_stats: %s",
-			 pcap_strerror(rc));
+		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;
@@ -67,8 +71,8 @@
 	struct pcap_snf *ps = p->priv;
 
 #ifdef SNF_HAVE_INJECT_API
-        if (ps->snf_inj)
-                snf_inject_close(ps->snf_inj);
+	if (ps->snf_inj)
+		snf_inject_close(ps->snf_inj);
 #endif
 	snf_ring_close(ps->snf_ring);
 	snf_close(ps->snf_handle);
@@ -76,7 +80,7 @@
 }
 
 static int
-snf_getnonblock(pcap_t *p, char *errbuf)
+snf_getnonblock(pcap_t *p)
 {
 	struct pcap_snf *ps = p->priv;
 
@@ -84,7 +88,7 @@
 }
 
 static int
-snf_setnonblock(pcap_t *p, int nonblock, char *errbuf)
+snf_setnonblock(pcap_t *p, int nonblock)
 {
 	struct pcap_snf *ps = p->priv;
 
@@ -107,9 +111,10 @@
 {
 	struct timeval tv;
 	long tv_nsec;
+        const static struct timeval zero_timeval;
 
-	if (ts_nanosec == 0)
-		return (struct timeval) { 0, 0 };
+        if (ts_nanosec == 0)
+                return zero_timeval;
 
 	tv.tv_sec = ts_nanosec / _NSEC_PER_SEC;
 	tv_nsec = (ts_nanosec % _NSEC_PER_SEC);
@@ -161,8 +166,8 @@
 				continue;
 			}
 			else {
-				pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "snf_read: %s",
-				 	 pcap_strerror(err));
+				pcap_fmt_errmsg_for_errno(p->errbuf,
+				    PCAP_ERRBUF_SIZE, err, "snf_read");
 				return -1;
 			}
 		}
@@ -212,25 +217,25 @@
 {
 #ifdef SNF_HAVE_INJECT_API
 	struct pcap_snf *ps = p->priv;
-        int rc;
-        if (ps->snf_inj == NULL) {
-                rc = snf_inject_open(ps->snf_boardnum, 0, &ps->snf_inj);
-                if (rc) {
-                        pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
-                                "snf_inject_open: %s", pcap_strerror(rc));
-                        return (-1);
-                }
-        }
+	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_snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "snf_inject_send: %s",
-                         pcap_strerror(rc));
-                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
 	strlcpy(p->errbuf, "Sending packets isn't supported with this snf version",
 	    PCAP_ERRBUF_SIZE);
@@ -248,8 +253,7 @@
 	int flags = -1, ring_id = -1;
 
 	if (device == NULL) {
-		pcap_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;
 	}
 
@@ -262,15 +266,22 @@
 	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) {
-		pcap_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;
 	}
 
@@ -279,12 +290,22 @@
 	}
 	err = snf_ring_open_id(ps->snf_handle, ring_id, &ps->snf_ring);
 	if (err != 0) {
-		pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
-			 "snf_ring_open_id(ring=%d) failed: %s",
-			 ring_id, 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
@@ -292,15 +313,17 @@
 
 	err = snf_start(ps->snf_handle);
 	if (err != 0) {
-		pcap_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;
@@ -312,107 +335,177 @@
 	p->stats_op = snf_pcap_stats;
 	p->cleanup_op = snf_platform_cleanup;
 #ifdef SNF_HAVE_INJECT_API
-        ps->snf_inj = NULL;
+	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 *devlist = NULL,*curdev,*prevdev;
-	pcap_addr_t *curaddr;
+	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;
+	int ret, allports = 0, merge = 0;
+	const char *nr = NULL;
 
-	if (snf_init(SNF_VERSION_API))
+	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)
 	{
-		(void)pcap_snprintf(errbuf, PCAP_ERRBUF_SIZE,
-			"snf_getifaddrs: %s", pcap_strerror(errno));
+		pcap_fmt_errmsg_for_errno(errbuf, PCAP_ERRBUF_SIZE,
+		    errno, "snf_getifaddrs");
 		return (-1);
 	}
-	ifa = ifaddrs;
-	while (ifa)
-	{
-		/*
-		 * Allocate a new entry
-		 */
-		curdev = (pcap_if_t *)malloc(sizeof(pcap_if_t));
-		if (curdev == NULL) {
-		(void)pcap_snprintf(errbuf, PCAP_ERRBUF_SIZE,
-			"snf_findalldevs malloc: %s", pcap_strerror(errno));
-			return (-1);
-		}
-		if (devlist == NULL) /* save first entry */
-			devlist = curdev;
-		else
-			prevdev->next = curdev;
-		/*
-		 * Fill in the entry.
-		 */
-		curdev->next = NULL;
-		curdev->name = strdup(ifa->snf_ifa_name);
-		if (curdev->name == NULL) {
+	if ((nr = getenv("SNF_FLAGS")) && *nr) {
+		errno = 0;
+		merge = strtol(nr, NULL, 0);
+		if (errno) {
 			(void)pcap_snprintf(errbuf, PCAP_ERRBUF_SIZE,
-			    "snf_findalldevs strdup: %s", pcap_strerror(errno));
-			free(curdev);
+				"snf_getifaddrs: SNF_FLAGS is not a valid number");
 			return (-1);
 		}
-		(void)pcap_snprintf(desc,MAX_DESC_LENGTH,"Myricom snf%d",
-				ifa->snf_ifa_portnum);
-		curdev->description = strdup(desc);
-		if (curdev->description == NULL) {
-			(void)pcap_snprintf(errbuf, PCAP_ERRBUF_SIZE,
-			"snf_findalldevs strdup1: %s", pcap_strerror(errno));
-			free(curdev->name);
-			free(curdev);
-			return (-1);
-		}
-		curdev->addresses = NULL;
-		curdev->flags = 0;
+		merge = merge & SNF_F_AGGREGATE_PORTMASK;
+	}
 
-		curaddr = (pcap_addr_t *)malloc(sizeof(pcap_addr_t));
-		if (curaddr == NULL) {
-			(void)pcap_snprintf(errbuf, PCAP_ERRBUF_SIZE,
-			     "snf_findalldevs malloc1: %s", pcap_strerror(errno));
-			free(curdev->description);
-			free(curdev->name);
-			free(curdev);
-			return (-1);
-		}
-		curdev->addresses = curaddr;
-		curaddr->next = NULL;
-		curaddr->addr = (struct sockaddr*)malloc(sizeof(struct sockaddr_storage));
-		if (curaddr->addr == NULL) {
-			(void)pcap_snprintf(errbuf, PCAP_ERRBUF_SIZE,
-			    "malloc2: %s", pcap_strerror(errno));
-			free(curdev->description);
-			free(curdev->name);
-			free(curaddr);
-			free(curdev);
-			return (-1);
-		}
-		curaddr->addr->sa_family = AF_INET;
-		curaddr->netmask = NULL;
-		curaddr->broadaddr = NULL;
-		curaddr->dstaddr = NULL;
-		curaddr->next = NULL;
+	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;
 
-		prevdev = curdev;
-		ifa = ifa->snf_ifa_next;
+			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);
-	*devlistp = devlist;
-
 	/*
-	 * 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;
 }
 
@@ -443,7 +536,7 @@
 	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;
 		}
@@ -461,7 +554,7 @@
 			/* Nope, not a supported name */
 			*is_ours = 0;
 			return NULL;
-		    }
+		}
 	}
 
 	/* OK, it's probably ours. */
@@ -478,8 +571,8 @@
 	p->tstamp_precision_count = 2;
 	p->tstamp_precision_list = malloc(2 * sizeof(u_int));
 	if (p->tstamp_precision_list == NULL) {
-		pcap_snprintf(ebuf, PCAP_ERRBUF_SIZE, "malloc: %s",
-		    pcap_strerror(errno));
+		pcap_fmt_errmsg_for_errno(ebuf, PCAP_ERRBUF_SIZE, errno,
+		    "malloc");
 		pcap_close(p);
 		return NULL;
 	}
@@ -498,12 +591,11 @@
  */
 
 /*
- * There are no regular interfaces, just DAG interfaces.
+ * There are no regular interfaces, just SNF interfaces.
  */
 int
-pcap_platform_finddevs(pcap_if_t **alldevsp, char *errbuf)
+pcap_platform_finddevs(pcap_if_list_t *devlistp, char *errbuf)
 {
-	*alldevsp = NULL;
 	return (0);
 }
 
@@ -517,4 +609,13 @@
 	    "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
diff --git a/pcap-snf.h b/pcap-snf.h
index c9d7722..ffc64ad 100644
--- a/pcap-snf.h
+++ b/pcap-snf.h
@@ -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);
diff --git a/pcap-snit.c b/pcap-snit.c
index 7934945..9c6fbd4 100644
--- a/pcap-snit.c
+++ b/pcap-snit.c
@@ -24,7 +24,7 @@
  */
 
 #ifdef HAVE_CONFIG_H
-#include "config.h"
+#include <config.h>
 #endif
 
 #include <sys/types.h>
@@ -130,8 +130,8 @@
 		if (cc < 0) {
 			if (errno == EWOULDBLOCK)
 				return (0);
-			pcap_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 = (u_char *)p->buffer;
@@ -223,8 +223,8 @@
 	data.len = size;
 	ret = putmsg(p->fd, &ctl, &data);
 	if (ret == -1) {
-		pcap_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 @@
 		si.ic_len = sizeof(zero);
 		si.ic_dp = (char *)&zero;
 		if (ioctl(p->fd, I_STR, (char *)&si) < 0) {
-			pcap_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 @@
 		si.ic_len = sizeof(timeout);
 		si.ic_dp = (char *)&timeout;
 		if (ioctl(p->fd, I_STR, (char *)&si) < 0) {
-			pcap_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 @@
 	si.ic_len = sizeof(flags);
 	si.ic_dp = (char *)&flags;
 	if (ioctl(p->fd, I_STR, (char *)&si) < 0) {
-		pcap_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);
@@ -287,6 +287,7 @@
 	int chunksize = CHUNKSIZE;
 	int fd;
 	static const char dev[] = "/dev/nit";
+	int err;
 
 	if (p->opt.rfmon) {
 		/*
@@ -296,6 +297,17 @@
 		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 @@
 	if (fd < 0 && errno == EACCES)
 		p->fd = fd = open(dev, O_RDONLY);
 	if (fd < 0) {
-		pcap_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) {
-		pcap_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) {
-		pcap_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,8 +360,9 @@
 	si.ic_len = sizeof(chunksize);
 	si.ic_dp = (char *)&chunksize;
 	if (ioctl(fd, I_STR, (char *)&si) < 0) {
-		pcap_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;
 	}
 
@@ -359,8 +378,9 @@
 		 * Is there one that means "that device doesn't support
 		 * STREAMS NIT"?
 		 */
-		pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "NIOCBIND: %s: %s",
-			ifr.ifr_name, pcap_strerror(errno));
+		pcap_fmt_errmsg_for_errno(p->errbuf, PCAP_ERRBUF_SIZE,
+		    errno, "NIOCBIND: %s", ifr.ifr_name);
+		err = PCAP_ERROR;
 		goto bad;
 	}
 
@@ -369,12 +389,15 @@
 	si.ic_len = sizeof(p->snapshot);
 	si.ic_dp = (char *)&p->snapshot;
 	if (ioctl(fd, I_STR, (char *)&si) < 0) {
-		pcap_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);
 	/*
@@ -385,7 +408,9 @@
 	p->bufsize = BUFSPACE;
 	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;
 	}
 
@@ -427,7 +452,7 @@
 	return (0);
  bad:
 	pcap_cleanup_live_common(p);
-	return (PCAP_ERROR);
+	return (err);
 }
 
 pcap_t *
@@ -453,8 +478,29 @@
 	return (1);
 }
 
-int
-pcap_platform_finddevs(pcap_if_t **alldevsp, char *errbuf)
+static int
+get_if_flags(const char *name _U_, bpf_u_int32 *flags _U_, char *errbuf _U_)
 {
-	return (pcap_findalldevs_interfaces(alldevsp, errbuf, can_be_bound));
+	/*
+	 * 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-snoop.c b/pcap-snoop.c
index 687b1d9..a598bae 100644
--- a/pcap-snoop.c
+++ b/pcap-snoop.c
@@ -20,7 +20,7 @@
  */
 
 #ifdef HAVE_CONFIG_H
-#include "config.h"
+#include <config.h>
 #endif
 
 #include <sys/param.h>
@@ -95,8 +95,8 @@
 		case EWOULDBLOCK:
 			return (0);			/* XXX */
 		}
-		pcap_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;
@@ -150,8 +150,8 @@
 	 */
 	ret = write(p->fd, buf, size);
 	if (ret == -1) {
-		pcap_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);
@@ -167,8 +167,8 @@
 	rs = &rawstats;
 	memset(rs, 0, sizeof(*rs));
 	if (ioctl(p->fd, SIOCRAWSTATS, (char *)rs) < 0) {
-		pcap_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,8 +212,8 @@
 
 	fd = socket(PF_RAW, SOCK_RAW, RAWPROTO_SNOOP);
 	if (fd < 0) {
-		pcap_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;
@@ -228,14 +228,14 @@
 		 * they might be the same error, if they both end up
 		 * meaning "snoop doesn't know about that device".
 		 */
-		pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "snoop bind: %s",
-		    pcap_strerror(errno));
+		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) {
-		pcap_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)
@@ -323,6 +323,17 @@
 		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
@@ -332,8 +343,8 @@
 	 */
 	(void)strncpy(ifr.ifr_name, p->opt.device, sizeof(ifr.ifr_name));
 	if (ioctl(fd, SIOCGIFMTU, (char *)&ifr) < 0) {
-		pcap_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;
 	}
 	/*
@@ -366,22 +377,22 @@
 	if (snooplen < 0)
 		snooplen = 0;
 	if (ioctl(fd, SIOCSNOOPLEN, &snooplen) < 0) {
-		pcap_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) {
-		pcap_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 = malloc(p->bufsize);
 	if (p->buffer == NULL) {
-		pcap_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;
 	}
 
@@ -428,8 +439,29 @@
 	return (1);
 }
 
-int
-pcap_platform_finddevs(pcap_if_t **alldevsp, char *errbuf)
+static int
+get_if_flags(const char *name _U_, bpf_u_int32 *flags _U_, char *errbuf _U_)
 {
-	return (pcap_findalldevs_interfaces(alldevsp, errbuf, can_be_bound));
+	/*
+	 * 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-stdinc.h b/pcap-stdinc.h
deleted file mode 100644
index a1be680..0000000
--- a/pcap-stdinc.h
+++ /dev/null
@@ -1,126 +0,0 @@
-/*
- * 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.
- */
-
-/*
- * Copyright (C) 1999 WIDE Project.
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in the
- *    documentation and/or other materials provided with the distribution.
- * 3. Neither the name of the project nor the names of its contributors
- *    may be used to endorse or promote products derived from this software
- *    without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED.  IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE
- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
- * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
- * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- */
-#ifndef pcap_stdinc_h
-#define pcap_stdinc_h
-
-/*
- * 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')
- */
-#ifdef _WINSOCKAPI_
-#undef _WINSOCKAPI_
-#endif
-
-#include <winsock2.h>
-#include <fcntl.h>
-#include <time.h>
-#include <io.h>
-
-#include <ws2tcpip.h>
-
-#if defined(_MSC_VER)
-  /*
-   * MSVC.
-   */
-  #if _MSC_VER >= 1800
-    /*
-     * VS 2013 or newer; we have <inttypes.h>.
-     */
-    #include <inttypes.h>
-
-    #define u_int8_t uint8_t
-    #define u_int16_t uint16_t
-    #define u_int32_t uint32_t
-    #define u_int64_t uint64_t
-  #else
-    /*
-     * Earlier VS; we have to define this stuff ourselves.
-     */
-    #ifndef HAVE_U_INT8_T
-      typedef unsigned char u_int8_t;
-      typedef signed char int8_t;
-    #endif
-
-    #ifndef HAVE_U_INT16_T
-      typedef unsigned short u_int16_t;
-      typedef signed short int16_t;
-    #endif
-
-    #ifndef HAVE_U_INT32_T
-      typedef unsigned int u_int32_t;
-      typedef signed int int32_t;
-    #endif
-
-    #ifndef HAVE_U_INT64_T
-      #ifdef _MSC_EXTENSIONS
-        typedef unsigned _int64 u_int64_t;
-        typedef _int64 int64_t;
-      #else /* _MSC_EXTENSIONS */
-        typedef unsigned long long u_int64_t;
-        typedef long long int64_t;
-      #endif
-    #endif
-  #endif
-#elif defined(__MINGW32__)
-  #include <stdint.h>
-#endif
-
-#endif /* pcap_stdinc_h */
diff --git a/pcap-tc.c b/pcap-tc.c
index 768dbd7..38c7024 100644
--- a/pcap-tc.c
+++ b/pcap-tc.c
@@ -30,7 +30,7 @@
  */
 
 #ifdef HAVE_CONFIG_H
-#include "config.h"
+#include <config.h>
 #endif
 
 #include <pcap.h>
@@ -120,8 +120,8 @@
 
 static pcap_if_t* TcCreatePcapIfFromPort(TC_PORT port);
 static int TcSetDatalink(pcap_t *p, int dlt);
-static int TcGetNonBlock(pcap_t *p, char *errbuf);
-static int TcSetNonBlock(pcap_t *p, int nonblock, char *errbuf);
+static 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, size_t size);
 static int TcRead(pcap_t *p, int cnt, pcap_handler callback, u_char *user);
@@ -433,7 +433,7 @@
 };
 
 int
-TcFindAllDevs(pcap_if_t **alldevsp, char *errbuf)
+TcFindAllDevs(pcap_if_list_t *devlist, char *errbuf)
 {
 	TC_API_LOAD_STATUS loadStatus;
 	ULONG numPorts;
@@ -476,13 +476,15 @@
 				/*
 				 * append it at the end
 				 */
-				if (*alldevsp == NULL)
+				if (devlistp->beginning == NULL)
 				{
-					*alldevsp = dev;
+					devlistp->beginning = dev;
 				}
 				else
 				{
-					for(cursor = *alldevsp; cursor->next != NULL; cursor = cursor->next);
+					for (cursor = devlistp->beginning;
+					    cursor->next != NULL;
+					    cursor = cursor->next);
 					cursor->next = dev;
 				}
 			}
@@ -570,6 +572,17 @@
 	}
 
 	/*
+	 * 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;
@@ -763,36 +776,48 @@
 		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)
 {
 	/*
-	 * always return 0, as the check is done by pcap_set_datalink
+	 * 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, char *errbuf)
+static int TcGetNonBlock(pcap_t *p)
 {
 	pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
-		    "Getting the non blocking status is not available for TurboCap ports");
-	pcap_snprintf(errbuf, PCAP_ERRBUF_SIZE,
-		    "Getting the non blocking status is not available for TurboCap ports");
-		return -1;
-
+	    "Non-blocking mode isn't supported for TurboCap ports");
+	return -1;
 }
-static int TcSetNonBlock(pcap_t *p, int nonblock, char *errbuf)
+
+static int TcSetNonBlock(pcap_t *p, int nonblock)
 {
 	pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
-		    "Setting the non blocking status is not available for TurboCap ports");
-	pcap_snprintf(errbuf, PCAP_ERRBUF_SIZE,
-		    "Setting the non blocking status is not available for TurboCap ports");
-		return -1;
+	    "Non-blocking mode isn't supported for TurboCap ports");
+	return -1;
 }
 
-
 static void TcCleanup(pcap_t *p)
 {
 	struct pcap_tc *pt = p->priv;
@@ -1081,7 +1106,7 @@
 		s.ps_drop = 0xFFFFFFFF;
 	}
 
-#if defined(_WIN32) && defined(HAVE_REMOTE)
+#if defined(_WIN32) && defined(ENABLE_REMOTE)
 	s.ps_capt = pt->TcAcceptedCount;
 #endif
 	*ps = s;
@@ -1105,8 +1130,6 @@
 	/* Install a user level filter */
 	if (install_bpf_program(p, fp) < 0)
 	{
-		pcap_snprintf(p->errbuf, sizeof(p->errbuf),
-			"setfilter, unable to install the filter: %s", pcap_strerror(errno));
 		return -1;
 	}
 
@@ -1166,7 +1189,7 @@
 		p->stat.ps_drop = 0xFFFFFFFF;
 	}
 
-#ifdef HAVE_REMOTE
+#if defined(_WIN32) && defined(ENABLE_REMOTE)
 	p->stat.ps_capt = pt->TcAcceptedCount;
 #endif
 
diff --git a/pcap-tc.h b/pcap-tc.h
index 59ddec2..f7b2d12 100644
--- a/pcap-tc.h
+++ b/pcap-tc.h
@@ -49,6 +49,6 @@
 TcCreate(const char *device, char *ebuf, int *is_ours);
 
 int
-TcFindAllDevs(pcap_if_t **alldevsp, char *errbuf);
+TcFindAllDevs(pcap_if_list_t *devlistp, char *errbuf);
 
 #endif
diff --git a/pcap-tstamp.manmisc b/pcap-tstamp.manmisc
index 7d078fb..c8b7fed 100644
--- a/pcap-tstamp.manmisc
+++ b/pcap-tstamp.manmisc
@@ -165,11 +165,13 @@
 reading a savefile, this does not indicate the actual precision of time
 stamps in the file.
 .SH SEE ALSO
+.na
 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_set_tstamp_precision(3PCAP),
 pcap_open_offline_with_tstamp_precision(3PCAP),
-pcap_fopen_offline_with_tstamp_precision(3PCAP),
-pcap_get_tstamp_precision(3PCAP)
+\%pcap_fopen_offline_with_tstamp_precision(3PCAP),
+\%pcap_get_tstamp_precision(3PCAP)
+.ad
diff --git a/pcap-tstamp.manmisc.in b/pcap-tstamp.manmisc.in
index 2e1ef61..38c5651 100644
--- a/pcap-tstamp.manmisc.in
+++ b/pcap-tstamp.manmisc.in
@@ -165,11 +165,13 @@
 reading a savefile, this does not indicate the actual precision of time
 stamps in the file.
 .SH SEE ALSO
+.na
 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_set_tstamp_precision(3PCAP),
 pcap_open_offline_with_tstamp_precision(3PCAP),
-pcap_fopen_offline_with_tstamp_precision(3PCAP),
-pcap_get_tstamp_precision(3PCAP)
+\%pcap_fopen_offline_with_tstamp_precision(3PCAP),
+\%pcap_get_tstamp_precision(3PCAP)
+.ad
diff --git a/pcap-types.h b/pcap-types.h
new file mode 100644
index 0000000..9614f9f
--- /dev/null
+++ b/pcap-types.h
@@ -0,0 +1,50 @@
+/*
+ * 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_types_h
+#define pcap_types_h
+
+/*
+ * Get u_int defined, by hook or by crook.
+ */
+#ifdef _WIN32
+
+  /*
+   * This defines u_int.
+   */
+  #include <winsock2.h>
+#else /* _WIN32 */
+  /*
+   * This defines u_int, among other types.
+   */
+  #include <sys/types.h>
+#endif
+
+#endif /* pcap_types_h */
diff --git a/pcap-usb-linux.c b/pcap-usb-linux.c
index fb1188a..6f8adf6 100644
--- a/pcap-usb-linux.c
+++ b/pcap-usb-linux.c
@@ -34,7 +34,7 @@
  */
 
 #ifdef HAVE_CONFIG_H
-#include "config.h"
+#include <config.h>
 #endif
 
 #include "pcap-int.h"
@@ -56,6 +56,7 @@
 #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 +86,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,25 +139,131 @@
 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)
+usb_dev_add(pcap_if_list_t *devlistp, int n, char *err_str)
 {
 	char dev_name[10];
 	char dev_descr[30];
 	pcap_snprintf(dev_name, 10, USB_IFACE"%d", n);
-	pcap_snprintf(dev_descr, 30, "USB bus number %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,
+		    "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, "USB 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;
 }
 
 int
-usb_findalldevs(pcap_if_t **alldevsp, char *err_str)
+usb_findalldevs(pcap_if_list_t *devlistp, char *err_str)
 {
-	int fd;
+	char usb_mon_dir[PATH_MAX];
+	char *usb_mon_prefix;
+	size_t usb_mon_prefix_len;
 	struct dirent* data;
 	int ret = 0;
 	DIR* dir;
@@ -164,87 +271,113 @@
 	char* name;
 	size_t len;
 
-	/*
-	 * Do we have a "scan all buses" device?
-	 * First, try the binary device.
-	 */
-	fd = open(LINUX_USB_MON_DEV"0", O_RDONLY, 0);
-	if (fd >= 0) {
+	if (have_binary_usbmon()) {
 		/*
-		 * Yes.
+		 * 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.
 		 */
-		close(fd);
-		if (pcap_add_if(alldevsp, "usbmon0", 0, "All USB buses",
-		    err_str) < 0)
-			return -1;
+		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);
+
+		/*
+		 * 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;
+
+				/*
+				 * 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);
+			}
+
+			closedir(dir);
+		}
+		return 0;
 	} else {
 		/*
-		 * No binary device; do we have the text device?
+		 * 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.
 		 */
-		fd = open(USB_TEXT_DIR"/0t", O_RDONLY, 0);
-		if (fd < 0) {
-			/*
-			 * Not at the new location; try the old location.
-			 */
-			fd = open(USB_TEXT_DIR_OLD"/0t", O_RDONLY, 0);
+		dir = opendir(SYS_USB_BUS_DIR);
+		if (dir != NULL) {
+			while ((ret == 0) && ((data = readdir(dir)) != 0)) {
+				name = data->d_name;
+
+				if (strncmp(name, "usb", 3) != 0)
+					continue;
+
+				if (sscanf(&name[3], "%d", &n) == 0)
+					continue;
+
+				ret = usb_dev_add(devlistp, n, err_str);
+			}
+
+			closedir(dir);
+			return 0;
 		}
-		if (fd >= 0) {
-			/*
-			 * We found it.
-			 */
-			close(fd);
-			if (pcap_add_if(alldevsp, "usbmon0", 0, "All USB buses",
-			    err_str) < 0)
-				return -1;
+
+		/* 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;
 		}
+
+		/* neither of them worked */
+		return 0;
 	}
-
-	/*
-	 * Now look for individual USB buses.
-	 *
-	 * First, try scanning sysfs USB bus directory.
-	 */
-	dir = opendir(SYS_USB_BUS_DIR);
-	if (dir != NULL) {
-		while ((ret == 0) && ((data = readdir(dir)) != 0)) {
-			name = data->d_name;
-
-			if (strncmp(name, "usb", 3) != 0)
-				continue;
-
-			if (sscanf(&name[3], "%d", &n) == 0)
-				continue;
-
-			ret = usb_dev_add(alldevsp, n, err_str);
-		}
-
-		closedir(dir);
-		return ret;
-	}
-
-	/* 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(alldevsp, n, err_str);
-		}
-
-		closedir(dir);
-		return ret;
-	}
-
-	/* neither of them worked */
-	return 0;
 }
 
 static
@@ -283,7 +416,7 @@
 	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 */
@@ -309,7 +442,7 @@
 		 * 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;
@@ -382,6 +515,17 @@
 	struct pcap_usb_linux *handlep = handle->priv;
 	char 		full_path[USB_LINE_LEN];
 
+	/*
+	 * 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;
 	handle->offset = 0;
@@ -402,12 +546,54 @@
 		return PCAP_ERROR;
 	}
 
-	/*now select the read method: try to open 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)
+	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.
 			 */
@@ -415,8 +601,9 @@
 			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))
+		{
 			handle->linktype = DLT_USB_LINUX_MMAPPED;
 			handle->stats_op = usb_stats_linux_bin;
 			handle->read_op = usb_read_linux_mmap;
@@ -426,8 +613,8 @@
 #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;
@@ -441,7 +628,10 @@
 #endif
 	}
 	else {
-		/*Binary interface not available, try open text interface */
+		/*
+		 * 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)
@@ -456,14 +646,43 @@
 				handle->fd = open(full_path, O_RDONLY, 0);
 			}
 			if (handle->fd < 0) {
-				/* no more fallback, give it up*/
-				pcap_snprintf(handle->errbuf, PCAP_ERRBUF_SIZE,
-					"Can't open USB bus file %s: %s", full_path, strerror(errno));
-				return PCAP_ERROR;
+				/*
+				 * Is the problem that we didn't have
+				 * sufficient permission to open it?
+				 */
+				if (errno == EACCES) {
+					/*
+					 * Yes - return that error.
+					 */
+					return PCAP_ERROR_PERM_DENIED;
+				}
+
+				/*
+				 * No - was the problem something other
+				 * than "it doesn't exist"?
+				 */
+				if (errno != ENOENT) {
+					/*
+					 * Yes - return *that* error.
+					 */
+					pcap_fmt_errmsg_for_errno(handle->errbuf,
+					    PCAP_ERRBUF_SIZE, errno,
+					    "Can't open USB bus file %s",
+					    full_path);
+					return PCAP_ERROR;
+				}
+
+				/*
+				 * No.  Report that as "no such device".
+				 * (That could mean "no such USB bus"
+				 * or "monitoring not supported".)
+				 */
+				return PCAP_ERROR_NO_SUCH_DEVICE;
 			}
 		}
 
-		if (handle->opt.rfmon) {
+		if (handle->opt.rfmon)
+		{
 			/*
 			 * Monitor mode doesn't apply to USB devices.
 			 */
@@ -485,8 +704,8 @@
 	 * buffer */
 	handle->buffer = malloc(handle->bufsize);
 	if (!handle->buffer) {
-		pcap_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;
 	}
@@ -505,7 +724,7 @@
  * 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
@@ -536,8 +755,8 @@
 		if (errno == EAGAIN)
 			return 0;	/* no data there */
 
-		pcap_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;
 	}
 
@@ -563,9 +782,8 @@
 	/* don't use usbmon provided timestamp, since it have low precision*/
 	if (gettimeofday(&pkth.ts, NULL) < 0)
 	{
-		pcap_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;
@@ -703,7 +921,7 @@
 }
 
 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_)
 {
 	pcap_snprintf(handle->errbuf, PCAP_ERRBUF_SIZE, "inject not supported on "
 		"USB devices");
@@ -734,9 +952,9 @@
 			fd = open(string, O_RDONLY, 0);
 		}
 		if (fd < 0) {
-			pcap_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;
 		}
 	}
@@ -803,8 +1021,8 @@
 	ret = ioctl(handle->fd, MON_IOCG_STATS, &st);
 	if (ret < 0)
 	{
-		pcap_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;
 	}
 
@@ -819,7 +1037,7 @@
  * <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;
@@ -846,8 +1064,8 @@
 		if (errno == EAGAIN)
 			return 0;	/* no data there */
 
-		pcap_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;
 	}
 
@@ -917,8 +1135,9 @@
 			if (errno == EAGAIN)
 				return 0;	/* no data there */
 
-			pcap_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;
 		}
 
@@ -958,8 +1177,8 @@
 
 	/* flush pending events*/
 	if (ioctl(handle->fd, MON_IOCH_MFLUSH, nflush) == -1) {
-		pcap_snprintf(handle->errbuf, PCAP_ERRBUF_SIZE,
-		    "Can't mflush fd %d: %s", handle->fd, strerror(errno));
+		pcap_fmt_errmsg_for_errno(handle->errbuf, PCAP_ERRBUF_SIZE,
+		    errno, "Can't mflush fd %d", handle->fd);
 		return -1;
 	}
 	return packets;
diff --git a/pcap-usb-linux.h b/pcap-usb-linux.h
index 234a262..3ddc12f 100644
--- a/pcap-usb-linux.h
+++ b/pcap-usb-linux.h
@@ -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
index d998637..0000000
--- a/pcap-win32.c
+++ /dev/null
@@ -1,1548 +0,0 @@
-/*
- * 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.
- *
- */
-
-#define PCAP_DONT_INCLUDE_PCAP_BPF_H
-#include <Packet32.h>
-#include <pcap-int.h>
-#include <pcap/dlt.h>
-#ifdef __MINGW32__
-#ifdef __MINGW64__
-#include <ntddndis.h>
-#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__ */
-#ifdef HAVE_REMOTE
-#include "pcap-rpcap.h"
-#endif /* HAVE_REMOTE */
-
-static int pcap_setfilter_win32_npf(pcap_t *, struct bpf_program *);
-static int pcap_setfilter_win32_dag(pcap_t *, struct bpf_program *);
-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 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
-};
-
-BOOL WINAPI DllMain(
-  HANDLE hinstDLL,
-  DWORD dwReason,
-  LPVOID lpvReserved
-)
-{
-	return (TRUE);
-}
-
-/*
- * Define stub versions of the monitor-mode support routines if this
- * isn't Npcap. HAVE_NPCAP_PACKET_API is defined by Npcap but not
- * WinPcap.
- */
-#ifndef HAVE_NPCAP_PACKET_API
-static int
-PacketIsMonitorModeSupported(PCHAR AdapterName _U_)
-{
-	/*
-	 * We don't support monitor mode.
-	 */
-	return (0);
-}
-
-static int
-PacketSetMonitorMode(PCHAR AdapterName _U_, int mode _U_)
-{
-	/*
-	 * This should never be called, as PacketIsMonitorModeSupported()
-	 * will return 0, meaning "we don't support monitor mode, so
-	 * don't try to turn it on or off".
-	 */
-	return (0);
-}
-
-static int
-PacketGetMonitorMode(PCHAR AdapterName _U_)
-{
-	/*
-	 * This should fail, so that pcap_activate_win32() returns
-	 * PCAP_ERROR_RFMON_NOTSUP if our caller requested monitor
-	 * mode.
-	 */
-	return (-1);
-}
-#endif
-
-/* Start winsock */
-int
-wsockinit(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);
-}
-
-int
-pcap_wsockinit(void)
-{
-       return (wsockinit());
-}
-
-static int
-pcap_stats_win32(pcap_t *p, struct pcap_stat *ps)
-{
-	struct bpf_stat bstats;
-	char errbuf[PCAP_ERRBUF_SIZE+1];
-
-	/*
-	 * Try to get statistics.
-	 *
-	 * (Please note - "struct pcap_stat" is *not* the same as
-	 * WinPcap's "struct bpf_stat". It might currently have the
-	 * same layout, but let's not cheat.
-	 *
-	 * Note also that we don't fill in ps_capt, as we might have
-	 * been called by code compiled against an earlier version of
-	 * WinPcap that didn't have ps_capt, in which case filling it
-	 * in would stomp on whatever comes after the structure passed
-	 * to us.
-	 */
-	if (!PacketGetStats(p->adapter, &bstats)) {
-		pcap_win32_err_to_str(GetLastError(), errbuf);
-		pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
-		    "PacketGetStats error: %s", errbuf);
-		return (-1);
-	}
-	ps->ps_recv = bstats.bs_recv;
-	ps->ps_drop = bstats.bs_drop;
-
-	/*
-	 * XXX - PacketGetStats() doesn't fill this in, so we just
-	 * return 0.
-	 */
-#if 0
-	ps->ps_ifdrop = bstats.ps_ifdrop;
-#else
-	ps->ps_ifdrop = 0;
-#endif
-
-	return (0);
-}
-
-/*
- * Win32-only routine for getting statistics.
- *
- * This way is definitely safer than passing the pcap_stat * from the userland.
- * In fact, there could happen than the user allocates a variable which is not
- * big enough for the new structure, and the library will write in a zone
- * which is not allocated to this variable.
- *
- * In this way, we're pretty sure we are writing on memory allocated to this
- * variable.
- *
- * XXX - but this is the wrong way to handle statistics.  Instead, we should
- * have an API that returns data in a form like the Options section of a
- * pcapng Interface Statistics Block:
- *
- *    http://xml2rfc.tools.ietf.org/cgi-bin/xml2rfc.cgi?url=https://raw.githubusercontent.com/pcapng/pcapng/master/draft-tuexen-opsawg-pcapng.xml&modeAsFormat=html/ascii&type=ascii#rfc.section.4.6
- *
- * which would let us add new statistics straightforwardly and indicate which
- * statistics we are and are *not* providing, rather than having to provide
- * possibly-bogus values for statistics we can't provide.
- */
-struct pcap_stat *
-pcap_stats_ex_win32(pcap_t *p, int *pcap_stat_size)
-{
-	struct bpf_stat bstats;
-	char errbuf[PCAP_ERRBUF_SIZE+1];
-
-	*pcap_stat_size = sizeof (p->stat);
-
-	/*
-	 * Try to get statistics.
-	 *
-	 * (Please note - "struct pcap_stat" is *not* the same as
-	 * WinPcap's "struct bpf_stat". It might currently have the
-	 * same layout, but let's not cheat.)
-	 */
-	if (!PacketGetStatsEx(p->adapter, &bstats)) {
-		pcap_win32_err_to_str(GetLastError(), errbuf);
-		pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
-		    "PacketGetStatsEx error: %s", errbuf);
-		return (NULL);
-	}
-	p->stat.ps_recv = bstats.bs_recv;
-	p->stat.ps_drop = bstats.bs_drop;
-	p->stat.ps_ifdrop = bstats.ps_ifdrop;
-#ifdef HAVE_REMOTE
-	p->stat.ps_capt = bstats.bs_capt;
-#endif
-	return (&p->stat);
-}
-
-/* Set the dimension of the kernel-level capture buffer */
-static int
-pcap_setbuff_win32(pcap_t *p, int dim)
-{
-	if(PacketSetBuff(p->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_win32(pcap_t *p, int mode)
-{
-	if(PacketSetMode(p->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_win32(pcap_t *p, int size)
-{
-	if(PacketSetMinToCopy(p->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_win32(pcap_t *p)
-{
-	return (PacketGetReadEvent(p->adapter));
-}
-
-static int
-pcap_oid_get_request_win32(pcap_t *p, bpf_u_int32 oid, void *data, size_t *lenp)
-{
-	PACKET_OID_DATA *oid_data_arg;
-	char errbuf[PCAP_ERRBUF_SIZE+1];
-
-	/*
-	 * Allocate a PACKET_OID_DATA structure to hand to PacketRequest().
-	 * It should be big enough to hold "*lenp" bytes of data; it
-	 * will actually be slightly larger, as PACKET_OID_DATA has a
-	 * 1-byte data array at the end, standing in for the variable-length
-	 * data that's actually there.
-	 */
-	oid_data_arg = malloc(sizeof (PACKET_OID_DATA) + *lenp);
-	if (oid_data_arg == NULL) {
-		pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
-		    "Couldn't allocate argument buffer for PacketRequest");
-		return (PCAP_ERROR);
-	}
-
-	/*
-	 * No need to copy the data - we're doing a fetch.
-	 */
-	oid_data_arg->Oid = oid;
-	oid_data_arg->Length = (ULONG)(*lenp);	/* XXX - check for ridiculously large value? */
-	if (!PacketRequest(p->adapter, FALSE, oid_data_arg)) {
-		pcap_win32_err_to_str(GetLastError(), errbuf);
-		pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
-		    "Error calling PacketRequest: %s", errbuf);
-		free(oid_data_arg);
-		return (PCAP_ERROR);
-	}
-
-	/*
-	 * Get the length actually supplied.
-	 */
-	*lenp = oid_data_arg->Length;
-
-	/*
-	 * Copy back the data we fetched.
-	 */
-	memcpy(data, oid_data_arg->Data, *lenp);
-	free(oid_data_arg);
-	return (0);
-}
-
-static int
-pcap_oid_set_request_win32(pcap_t *p, bpf_u_int32 oid, const void *data,
-    size_t *lenp)
-{
-	PACKET_OID_DATA *oid_data_arg;
-	char errbuf[PCAP_ERRBUF_SIZE+1];
-
-	/*
-	 * Allocate a PACKET_OID_DATA structure to hand to PacketRequest().
-	 * It should be big enough to hold "*lenp" bytes of data; it
-	 * will actually be slightly larger, as PACKET_OID_DATA has a
-	 * 1-byte data array at the end, standing in for the variable-length
-	 * data that's actually there.
-	 */
-	oid_data_arg = malloc(sizeof (PACKET_OID_DATA) + *lenp);
-	if (oid_data_arg == NULL) {
-		pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
-		    "Couldn't allocate argument buffer for PacketRequest");
-		return (PCAP_ERROR);
-	}
-
-	oid_data_arg->Oid = oid;
-	oid_data_arg->Length = (ULONG)(*lenp);	/* XXX - check for ridiculously large value? */
-	memcpy(oid_data_arg->Data, data, *lenp);
-	if (!PacketRequest(p->adapter, TRUE, oid_data_arg)) {
-		pcap_win32_err_to_str(GetLastError(), errbuf);
-		pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
-		    "Error calling PacketRequest: %s", errbuf);
-		free(oid_data_arg);
-		return (PCAP_ERROR);
-	}
-
-	/*
-	 * Get the length actually copied.
-	 */
-	*lenp = oid_data_arg->Length;
-
-	/*
-	 * No need to copy the data - we're doing a set.
-	 */
-	free(oid_data_arg);
-	return (0);
-}
-
-static u_int
-pcap_sendqueue_transmit_win32(pcap_t *p, pcap_send_queue *queue, int sync)
-{
-	u_int res;
-	char errbuf[PCAP_ERRBUF_SIZE+1];
-
-	if (p->adapter==NULL) {
-		pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
-		    "Cannot transmit a queue to an offline capture or to a TurboCap port");
-		return (0);
-	}
-
-	res = PacketSendPackets(p->adapter,
-		queue->buffer,
-		queue->len,
-		(BOOLEAN)sync);
-
-	if(res != queue->len){
-		pcap_win32_err_to_str(GetLastError(), errbuf);
-		pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
-		    "Error opening adapter: %s", errbuf);
-	}
-
-	return (res);
-}
-
-static int
-pcap_setuserbuffer_win32(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_win32(pcap_t *p, char *filename, int maxsize, int maxpacks)
-{
-	BOOLEAN res;
-
-	/* Set the packet driver in dump mode */
-	res = PacketSetMode(p->adapter, PACKET_MODE_DUMP);
-	if(res == FALSE){
-		pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
-		    "Error setting dump mode");
-		return (-1);
-	}
-
-	/* Set the name of the dump file */
-	res = PacketSetDumpName(p->adapter, filename, (int)strlen(filename));
-	if(res == FALSE){
-		pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
-		    "Error setting kernel dump file name");
-		return (-1);
-	}
-
-	/* Set the limits of the dump file */
-	res = PacketSetDumpLimits(p->adapter, maxsize, maxpacks);
-
-	return (0);
-}
-
-static int
-pcap_live_dump_ended_win32(pcap_t *p, int sync)
-{
-	return (PacketIsDumpEnded(p->adapter, (BOOLEAN)sync));
-}
-
-static PAirpcapHandle
-pcap_get_airpcap_handle_win32(pcap_t *p)
-{
-#ifdef HAVE_AIRPCAP_API
-	return (PacketGetAirPcapHandle(p->adapter));
-#else
-	return (NULL);
-#endif /* HAVE_AIRPCAP_API */
-}
-
-static int
-pcap_read_win32_npf(pcap_t *p, int cnt, pcap_handler callback, u_char *user)
-{
-	PACKET Packet;
-	int cc;
-	int n = 0;
-	register u_char *bp, *ep;
-	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(p->adapter, &Packet, TRUE)) {
-			pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "read error: PacketReceivePacket failed");
-			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;
-	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 = (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)) {
-			/*
-			 * 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 = 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.
-		 *
-		 * The PACKET structure had a bunch of extra stuff for
-		 * Windows 9x/Me, but the only interesting data in it
-		 * in the versions of Windows that we support is just
-		 * a copy of p->buffer, a copy of p->buflen, and the
-		 * actual number of bytes read returned from
-		 * PacketReceivePacket(), none of which has to be
-		 * retained from call to call, so we just keep one on
-		 * the stack.
-		 */
-		PacketInitPacket(&Packet, (BYTE *)p->buffer, p->bufsize);
-		if (!PacketReceivePacket(p->adapter, &Packet, TRUE)) {
-			pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "read error: PacketReceivePacket failed");
-			return (-1);
-		}
-
-		cc = 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 */
-		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_win32(pcap_t *p, const void *buf, size_t size){
-	LPPACKET PacketToSend;
-
-	PacketToSend=PacketAllocatePacket();
-
-	if (PacketToSend == NULL)
-	{
-		pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "send error: PacketAllocatePacket failed");
-		return (-1);
-	}
-
-	PacketInitPacket(PacketToSend, (PVOID)buf, (UINT)size);
-	if(PacketSendPacket(p->adapter,PacketToSend,TRUE) == FALSE){
-		pcap_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 ((int)size);
-}
-
-static void
-pcap_cleanup_win32(pcap_t *p)
-{
-	struct pcap_win *pw = p->priv;
-	if (p->adapter != NULL) {
-		PacketCloseAdapter(p->adapter);
-		p->adapter = NULL;
-	}
-	if (pw->rfmon_selfstart)
-	{
-		PacketSetMonitorMode(p->opt.device, 0);
-	}
-	pcap_cleanup_live_common(p);
-}
-
-static int
-pcap_activate_win32(pcap_t *p)
-{
-	struct pcap_win *pw = p->priv;
-	NetType type;
-	int res;
-	char errbuf[PCAP_ERRBUF_SIZE+1];
-
-#ifdef HAVE_REMOTE
-	char host[PCAP_BUF_SIZE + 1];
-	char port[PCAP_BUF_SIZE + 1];
-	char name[PCAP_BUF_SIZE + 1];
-	int srctype;
-	int opensource_remote_result;
-
-	struct pcap_md *md;				/* structure used when doing a remote live capture */
-	md = (struct pcap_md *) ((u_char*)p->priv + sizeof(struct pcap_win));
-
-	/*
-	Retrofit; we have to make older applications compatible with the remote capture
-	So, we're calling the pcap_open_remote() from here, that is a very dirty thing.
-	Obviously, we cannot exploit all the new features; for instance, we cannot
-	send authentication, we cannot use a UDP data connection, and so on.
-	*/
-	if (pcap_parsesrcstr(p->opt.device, &srctype, host, port, name, p->errbuf))
-		return PCAP_ERROR;
-
-	if (srctype == PCAP_SRC_IFREMOTE)
-	{
-		opensource_remote_result = pcap_opensource_remote(p, NULL);
-
-		if (opensource_remote_result != 0)
-			return opensource_remote_result;
-
-		md->rmt_flags = (p->opt.promisc) ? PCAP_OPENFLAG_PROMISCUOUS : 0;
-
-		return 0;
-	}
-
-	if (srctype == PCAP_SRC_IFLOCAL)
-	{
-		/*
-		* If it starts with rpcap://, cut down the string
-		*/
-		if (strncmp(p->opt.device, PCAP_SRC_IF_STRING, strlen(PCAP_SRC_IF_STRING)) == 0)
-		{
-			size_t len = strlen(p->opt.device) - strlen(PCAP_SRC_IF_STRING) + 1;
-			char *new_string;
-			/*
-			* allocate a new string and free the old one
-			*/
-			if (len > 0)
-			{
-				new_string = (char*)malloc(len);
-				if (new_string != NULL)
-				{
-					char *tmp;
-					strcpy_s(new_string, len, p->opt.device + strlen(PCAP_SRC_IF_STRING));
-					tmp = p->opt.device;
-					p->opt.device = new_string;
-					free(tmp);
-				}
-			}
-		}
-	}
-
-#endif	/* HAVE_REMOTE */
-
-	if (p->opt.rfmon) {
-		/*
-		 * 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 */
-	wsockinit();
-
-	p->adapter = PacketOpenAdapter(p->opt.device);
-
-	if (p->adapter == NULL)
-	{
-		/* Adapter detected but we are not able to open it. Return failure. */
-		pcap_win32_err_to_str(GetLastError(), errbuf);
-		if (pw->rfmon_selfstart)
-		{
-			PacketSetMonitorMode(p->opt.device, 0);
-		}
-		pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
-		    "Error opening adapter: %s", errbuf);
-		return (PCAP_ERROR);
-	}
-
-	/*get network type*/
-	if(PacketGetNetType (p->adapter,&type) == FALSE)
-	{
-		pcap_win32_err_to_str(GetLastError(), errbuf);
-		pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
-		    "Cannot determine the network type: %s", errbuf);
-		goto bad;
-	}
-
-	/*Set the linktype*/
-	switch (type.LinkType)
-	{
-	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)
-		{
-			pcap_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)
-		{
-			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(!(p->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(p->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_snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "malloc: %s", pcap_strerror(errno));
-			goto bad;
-		}
-
-		if (p->opt.immediate)
-		{
-			/* tell the driver to copy the buffer as soon as data arrives */
-			if(PacketSetMinToCopy(p->adapter,0)==FALSE)
-			{
-				pcap_win32_err_to_str(GetLastError(), errbuf);
-				pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
-				    "Error calling PacketSetMinToCopy: %s",
-				    errbuf);
-				goto bad;
-			}
-		}
-		else
-		{
-			/* tell the driver to copy the buffer only if it contains at least 16K */
-			if(PacketSetMinToCopy(p->adapter,16000)==FALSE)
-			{
-				pcap_win32_err_to_str(GetLastError(), errbuf);
-				pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
-				    "Error calling PacketSetMinToCopy: %s",
-				    errbuf);
-				goto bad;
-			}
-		}
-	}
-	else
-#ifdef HAVE_DAG_API
-	{
-	/*
-	 * Dag Card
-	 */
-		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(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->stats_ex_op = pcap_stats_ex_win32;
-	p->setbuff_op = pcap_setbuff_win32;
-	p->setmode_op = pcap_setmode_win32;
-	p->setmintocopy_op = pcap_setmintocopy_win32;
-	p->getevent_op = pcap_getevent_win32;
-	p->oid_get_request_op = pcap_oid_get_request_win32;
-	p->oid_set_request_op = pcap_oid_set_request_win32;
-	p->sendqueue_transmit_op = pcap_sendqueue_transmit_win32;
-	p->setuserbuffer_op = pcap_setuserbuffer_win32;
-	p->live_dump_op = pcap_live_dump_win32;
-	p->live_dump_ended_op = pcap_live_dump_ended_win32;
-	p->get_airpcap_handle_op = pcap_get_airpcap_handle_win32;
-	p->cleanup_op = pcap_cleanup_win32;
-
-	return (0);
-bad:
-	pcap_cleanup_win32(p);
-	return (PCAP_ERROR);
-}
-
-/*
-* Check if rfmon mode is supported on the pcap_t for Windows systems.
-*/
-static int
-pcap_can_set_rfmon_win32(pcap_t *p)
-{
-	return (PacketIsMonitorModeSupported(p->opt.device) == 1);
-}
-
-pcap_t *
-pcap_create_interface(const char *device _U_, char *ebuf)
-{
-	pcap_t *p;
-
-#ifdef HAVE_REMOTE
-	p = pcap_create_common(ebuf, sizeof(struct pcap_win) + sizeof(struct pcap_md));
-#else
-	p = pcap_create_common(ebuf, sizeof(struct pcap_win));
-#endif /* HAVE_REMOTE */
-	if (p == NULL)
-		return (NULL);
-
-	p->activate_op = pcap_activate_win32;
-	p->can_set_rfmon_op = pcap_can_set_rfmon_win32;
-	return (p);
-}
-
-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)
-	{
-		strlcpy(p->errbuf, "setfilter: No filter specified", sizeof(p->errbuf));
-		return (-1);
-	}
-
-	/* Install a user level filter */
-	if (install_bpf_program(p, fp) < 0)
-	{
-		pcap_snprintf(p->errbuf, sizeof(p->errbuf),
-			"setfilter, unable to install the filter: %s", pcap_strerror(errno));
-		return (-1);
-	}
-
-	return (0);
-}
-
-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;
-	char win_errbuf[PCAP_ERRBUF_SIZE+1];
-
-	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.  However, although
-		 * the timeout argument to pcap_set_timeout() and
-		 * pcap_open_live() is an int, you're not supposed to
-		 * supply a negative value, so that "shouldn't happen".)
-		 */
-		newtimeout = p->opt.timeout;
-	}
-	if (!PacketSetReadTimeout(p->adapter, newtimeout)) {
-		pcap_win32_err_to_str(GetLastError(), win_errbuf);
-		pcap_snprintf(errbuf, PCAP_ERRBUF_SIZE,
-		    "PacketSetReadTimeout: %s", win_errbuf);
-		return (-1);
-	}
-	pw->nonblock = (newtimeout == -1);
-	return (0);
-}
-
-static int
-pcap_add_if_win32(pcap_if_t **devlist, char *name, bpf_u_int32 flags,
-    const char *description, char *errbuf)
-{
-	pcap_if_t *curdev;
-	npf_if_addr if_addrs[MAX_NETWORK_ADDRESSES];
-	LONG if_addr_size;
-	int res = 0;
-
-	if_addr_size = MAX_NETWORK_ADDRESSES;
-
-	/*
-	 * Add an entry for this interface, with no addresses.
-	 */
-	if (add_or_find_if(&curdev, devlist, name, flags, description,
-	    errbuf) == -1) {
-		/*
-		 * Failure.
-		 */
-		return (-1);
-	}
-
-	/*
-	 * Get the list of addresses for the interface.
-	 */
-	if (!PacketGetNetInfoEx((void *)name, if_addrs, &if_addr_size)) {
-		/*
-		 * Failure.
-		 *
-		 * We don't return an error, because this can happen with
-		 * NdisWan interfaces, and we want to supply them even
-		 * if we can't supply their addresses.
-		 *
-		 * We return an entry with an empty address list.
-		 */
-		return (0);
-	}
-
-	/*
-	 * Now add the addresses.
-	 */
-	while (if_addr_size-- > 0) {
-		/*
-		 * "curdev" is an entry for this interface; add an entry for
-		 * this address to its list of addresses.
-		 */
-		if(curdev == NULL)
-			break;
-		res = add_addr_to_dev(curdev,
-		    (struct sockaddr *)&if_addrs[if_addr_size].IPAddress,
-		    sizeof (struct sockaddr_storage),
-		    (struct sockaddr *)&if_addrs[if_addr_size].SubnetMask,
-		    sizeof (struct sockaddr_storage),
-		    (struct sockaddr *)&if_addrs[if_addr_size].Broadcast,
-		    sizeof (struct sockaddr_storage),
-		    NULL,
-		    0,
-		    errbuf);
-		if (res == -1) {
-			/*
-			 * Failure.
-			 */
-			break;
-		}
-	}
-
-	return (res);
-}
-
-int
-pcap_platform_finddevs(pcap_if_t **alldevsp, char *errbuf)
-{
-	pcap_if_t *devlist = NULL;
-	int ret = 0;
-	const char *desc;
-	char *AdaptersName;
-	ULONG NameLength;
-	char *name;
-	char our_errbuf[PCAP_ERRBUF_SIZE+1];
-
-	/*
-	 * Find out how big a buffer we need.
-	 *
-	 * This call should always return FALSE; if the error is
-	 * ERROR_INSUFFICIENT_BUFFER, NameLength will be set to
-	 * the size of the buffer we need, otherwise there's a
-	 * problem, and NameLength should be set to 0.
-	 *
-	 * It shouldn't require NameLength to be set, but,
-	 * at least as of WinPcap 4.1.3, it checks whether
-	 * NameLength is big enough before it checks for a
-	 * NULL buffer argument, so, while it'll still do
-	 * the right thing if NameLength is uninitialized and
-	 * whatever junk happens to be there is big enough
-	 * (because the pointer argument will be null), it's
-	 * still reading an uninitialized variable.
-	 */
-	NameLength = 0;
-	if (!PacketGetAdapterNames(NULL, &NameLength))
-	{
-		DWORD last_error = GetLastError();
-
-		if (last_error != ERROR_INSUFFICIENT_BUFFER)
-		{
-			pcap_win32_err_to_str(last_error, our_errbuf);
-			pcap_snprintf(errbuf, PCAP_ERRBUF_SIZE,
-			    "PacketGetAdapterNames: %s", our_errbuf);
-			return (-1);
-		}
-	}
-
-	if (NameLength > 0)
-		AdaptersName = (char*) malloc(NameLength);
-	else
-	{
-		*alldevsp = NULL;
-		return 0;
-	}
-	if (AdaptersName == NULL)
-	{
-		pcap_snprintf(errbuf, PCAP_ERRBUF_SIZE, "Cannot allocate enough memory to list the adapters.");
-		return (-1);
-	}
-
-	if (!PacketGetAdapterNames(AdaptersName, &NameLength)) {
-		pcap_win32_err_to_str(GetLastError(), our_errbuf);
-		pcap_snprintf(errbuf, PCAP_ERRBUF_SIZE, "PacketGetAdapterNames: %s",
-		    our_errbuf);
-		free(AdaptersName);
-		return (-1);
-	}
-
-	/*
-	 * "PacketGetAdapterNames()" returned a list of
-	 * null-terminated ASCII interface name strings,
-	 * terminated by a null string, followed by a list
-	 * of null-terminated ASCII interface description
-	 * strings, terminated by a null string.
-	 * This means there are two ASCII nulls at the end
-	 * of the first list.
-	 *
-	 * Find the end of the first list; that's the
-	 * beginning of the second list.
-	 */
-	desc = &AdaptersName[0];
-	while (*desc != '\0' || *(desc + 1) != '\0')
-		desc++;
-
-	/*
- 	 * Found it - "desc" points to the first of the two
-	 * nulls at the end of the list of names, so the
-	 * first byte of the list of descriptions is two bytes
-	 * after it.
-	 */
-	desc += 2;
-
-	/*
-	 * Loop over the elements in the first list.
-	 */
-	name = &AdaptersName[0];
-	while (*name != '\0') {
-		bpf_u_int32 flags = 0;
-#ifdef HAVE_PACKET_IS_LOOPBACK_ADAPTER
-		/*
-		 * Is this a loopback interface?
-		 */
-		if (PacketIsLoopbackAdapter(name)) {
-			/* Yes */
-			flags |= PCAP_IF_LOOPBACK;
-		}
-#endif
-
-		/*
-		 * Add an entry for this interface.
-		 */
-		if (pcap_add_if_win32(&devlist, name, flags, desc,
-		    errbuf) == -1) {
-			/*
-			 * Failure.
-			 */
-			ret = -1;
-			break;
-		}
-		name += strlen(name) + 1;
-		desc += strlen(desc) + 1;
-	}
-
-	if (ret == -1) {
-		/*
-		 * We had an error; free the list we've been constructing.
-		 */
-		if (devlist != NULL) {
-			pcap_freealldevs(devlist);
-			devlist = NULL;
-		}
-	}
-
-	*alldevsp = devlist;
-	free(AdaptersName);
-	return (ret);
-}
diff --git a/pcap.3pcap b/pcap.3pcap
index 9f408a0..c6b8891 100644
--- a/pcap.3pcap
+++ b/pcap.3pcap
@@ -17,7 +17,7 @@
 .\" WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
 .\" MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
 .\"
-.TH PCAP 3PCAP "8 March 2015"
+.TH PCAP 3PCAP "20 April 2018"
 .SH NAME
 pcap \- Packet Capture library
 .SH SYNOPSIS
@@ -150,45 +150,46 @@
 .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 "buffer size"
 Packets that arrive for a capture are stored in a buffer, so that they
@@ -244,7 +245,7 @@
 that privilege to the user's
 .B defaultpriv
 key with the
-.B usermod (1M)
+.B usermod (8)
 command.
 .TP
 .B Under HP-UX with DLPI:
@@ -282,13 +283,13 @@
 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 +304,7 @@
 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
@@ -395,6 +396,11 @@
 .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
@@ -406,7 +412,7 @@
 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
@@ -600,12 +606,13 @@
 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.  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.
+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
@@ -633,12 +640,12 @@
 .BR pcap_get_selectable_fd ()
 gives details.  Note that, just as an attempt to read packets from a
 .B pcap_t
-may not return any packets if the read timeout expires, a
+may not return any packets if the packet buffer timeout expires, a
 .BR select (),
 .BR poll (),
-or other such call may, if the read timeout expires, indicate that a
-descriptor is ready to read even if there are no packets available to
-read.
+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
@@ -915,7 +922,7 @@
 1.0 APIs are available and use them only if they are.
 .SH SEE ALSO
 autoconf(1), tcpdump(1), tcpslice(1), pcap-filter(7), pfconfig(8),
-usermod(1M)
+usermod(8)
 .SH AUTHORS
 The original authors of libpcap are:
 .LP
@@ -927,11 +934,12 @@
 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.3pcap.in b/pcap.3pcap.in
index 93478f1..4a222c7 100644
--- a/pcap.3pcap.in
+++ b/pcap.3pcap.in
@@ -17,7 +17,7 @@
 .\" WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
 .\" MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
 .\"
-.TH PCAP 3PCAP "8 March 2015"
+.TH PCAP 3PCAP "20 April 2018"
 .SH NAME
 pcap \- Packet Capture library
 .SH SYNOPSIS
@@ -150,45 +150,46 @@
 .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 "buffer size"
 Packets that arrive for a capture are stored in a buffer, so that they
@@ -244,7 +245,7 @@
 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 +283,13 @@
 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 +304,7 @@
 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
@@ -395,6 +396,11 @@
 .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
@@ -406,7 +412,7 @@
 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
@@ -600,12 +606,13 @@
 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.  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.
+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
@@ -633,12 +640,12 @@
 .BR pcap_get_selectable_fd ()
 gives details.  Note that, just as an attempt to read packets from a
 .B pcap_t
-may not return any packets if the read timeout expires, a
+may not return any packets if the packet buffer timeout expires, a
 .BR select (),
 .BR poll (),
-or other such call may, if the read timeout expires, indicate that a
-descriptor is ready to read even if there are no packets available to
-read.
+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
@@ -915,7 +922,7 @@
 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
@@ -927,11 +934,12 @@
 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 77a709f..942c472 100644
--- a/pcap.c
+++ b/pcap.c
@@ -32,23 +32,28 @@
  */
 
 #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>
+
+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>
@@ -57,6 +62,11 @@
 #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 */
@@ -100,13 +112,89 @@
 #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 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_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 int
 pcap_not_initialized(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 (PCAP_ERROR);
+	}
 	/* 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");
@@ -118,6 +206,12 @@
 static void *
 pcap_not_initialized_ptr(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 (NULL);
+	}
 	(void)pcap_snprintf(pcap->errbuf, sizeof(pcap->errbuf),
 	    "This handle hasn't been activated yet");
 	return (NULL);
@@ -126,6 +220,12 @@
 static HANDLE
 pcap_getevent_not_initialized(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 (INVALID_HANDLE_VALUE);
+	}
 	(void)pcap_snprintf(pcap->errbuf, sizeof(pcap->errbuf),
 	    "This handle hasn't been activated yet");
 	return (INVALID_HANDLE_VALUE);
@@ -134,6 +234,12 @@
 static u_int
 pcap_sendqueue_transmit_not_initialized(pcap_t *pcap, pcap_send_queue* queue, int sync)
 {
+	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 (0);
+	}
 	(void)pcap_snprintf(pcap->errbuf, sizeof(pcap->errbuf),
 	    "This handle hasn't been activated yet");
 	return (0);
@@ -142,6 +248,12 @@
 static PAirpcapHandle
 pcap_get_airpcap_handle_not_initialized(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 (NULL);
+	}
 	(void)pcap_snprintf(pcap->errbuf, sizeof(pcap->errbuf),
 	    "This handle hasn't been activated yet");
 	return (NULL);
@@ -190,8 +302,8 @@
 		*tstamp_typesp = (int*)calloc(sizeof(**tstamp_typesp),
 		    p->tstamp_type_count);
 		if (*tstamp_typesp == NULL) {
-			(void)pcap_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,
@@ -295,8 +407,15 @@
 	return (p->read_op(p, 1, p->oneshot_callback, (u_char *)&s));
 }
 
+/*
+ * Implementation of a pcap_if_list_t.
+ */
+struct pcap_if_list {
+	pcap_if_t *beginning;
+};
+
 static struct capture_source_type {
-	int (*findalldevs_op)(pcap_if_t **, char *);
+	int (*findalldevs_op)(pcap_if_list_t *, char *);
 	pcap_t *(*create_op)(const char *, char *, int *);
 } capture_source_types[] = {
 #ifdef HAVE_DAG_API
@@ -323,9 +442,15 @@
 #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 }
 };
 
@@ -339,35 +464,1503 @@
 pcap_findalldevs(pcap_if_t **alldevsp, char *errbuf)
 {
 	size_t i;
+	pcap_if_list_t devlist;
 
 	/*
 	 * 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) {
+		/*
+		 * Failed - free all of the entries we were given
+		 * before we failed.
+		 */
+		if (devlist.beginning != NULL)
+			pcap_freealldevs(devlist.beginning);
+		*alldevsp = NULL;
 		return (-1);
+	}
 
 	/*
 	 * Ask each of the non-local-network-interface capture
 	 * 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);
 }
 
+static struct sockaddr *
+dup_sockaddr(struct sockaddr *sa, size_t sa_length)
+{
+	struct sockaddr *newsa;
+
+	if ((newsa = malloc(sa_length)) == NULL)
+		return (NULL);
+	return (memcpy(newsa, sa, sa_length));
+}
+
+/*
+ * Construct a "figure of merit" for an interface, for use when sorting
+ * the list of interfaces, in which interfaces that are up are superior
+ * to interfaces that aren't up, interfaces that are up and running are
+ * superior to interfaces that are up but not running, and non-loopback
+ * interfaces that are up and running are superior to loopback interfaces,
+ * and interfaces with the same flags have a figure of merit that's higher
+ * the lower the instance number.
+ *
+ * The goal is to try to put the interfaces most likely to be useful for
+ * capture at the beginning of the list.
+ *
+ * The figure of merit, which is lower the "better" the interface is,
+ * has the uppermost bit set if the interface isn't running, the bit
+ * below that set if the interface isn't up, the bit below that set
+ * if the interface is a loopback interface, and the interface index
+ * in the 29 bits below that.  (Yes, we assume u_int is 32 bits.)
+ */
+static u_int
+get_figure_of_merit(pcap_if_t *dev)
+{
+	const char *cp;
+	u_int n;
+
+	if (strcmp(dev->name, "any") == 0) {
+		/*
+		 * Give the "any" device an artificially high instance
+		 * number, so it shows up after all other non-loopback
+		 * interfaces.
+		 */
+		n = 0x1FFFFFFF;	/* 29 all-1 bits */
+	} else {
+		/*
+		 * A number at the end of the device name string is
+		 * assumed to be 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;
+
+	/*
+	 * 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 (!(dev->flags & PCAP_IF_WIRELESS) &&
+	    (dev->flags & PCAP_IF_CONNECTION_STATUS) == PCAP_IF_CONNECTION_STATUS_DISCONNECTED)
+		n |= 0x20000000;
+
+	/*
+	 * Sort loopback devices after non-loopback devices, *except* for
+	 * disconnected devices.
+	 */
+	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);
+	strlcpy(ifrdesc.ifr_name, name, sizeof ifrdesc.ifr_name);
+	s = socket(AF_INET, SOCK_DGRAM, 0);
+	if (s >= 0) {
+#ifdef __FreeBSD__
+		/*
+		 * On FreeBSD, if the buffer isn't big enough for the
+		 * description, the ioctl succeeds, but the description
+		 * isn't copied, ifr_buffer.length is set to the description
+		 * length, and ifr_buffer.buffer is set to NULL.
+		 */
+		for (;;) {
+			free(description);
+			if ((description = malloc(descrlen)) != NULL) {
+				ifrdesc.ifr_buffer.buffer = description;
+				ifrdesc.ifr_buffer.length = descrlen;
+				if (ioctl(s, SIOCGIFDESCR, &ifrdesc) == 0) {
+					if (ifrdesc.ifr_buffer.buffer ==
+					    description)
+						break;
+					else
+						descrlen = ifrdesc.ifr_buffer.length;
+				} else {
+					/*
+					 * Failed to get interface description.
+					 */
+					free(description);
+					description = NULL;
+					break;
+				}
+			} else
+				break;
+		}
+#else /* __FreeBSD__ */
+		/*
+		 * The only other OS that currently supports
+		 * SIOCGIFDESCR is OpenBSD, and it has no way
+		 * to get the description length - it's clamped
+		 * to a maximum of IFDESCRSIZE.
+		 */
+		if ((description = malloc(descrlen)) != NULL) {
+			ifrdesc.ifr_data = (caddr_t)description;
+			if (ioctl(s, SIOCGIFDESCR, &ifrdesc) != 0) {
+				/*
+				 * Failed to get interface description.
+				 */
+				free(description);
+				description = NULL;
+			}
+		}
+#endif /* __FreeBSD__ */
+		close(s);
+		if (description != NULL && strlen(description) == 0) {
+			/*
+			 * Description is empty, so discard it.
+			 */
+			free(description);
+			description = NULL;
+		}
+	}
+
+#ifdef __FreeBSD__
+	/*
+	 * For FreeBSD, if we didn't get a description, and this is
+	 * a device with a name of the form usbusN, label it as a USB
+	 * bus.
+	 */
+	if (description == NULL) {
+		if (strncmp(name, "usbus", 5) == 0) {
+			/*
+			 * OK, it begins with "usbus".
+			 */
+			long busnum;
+			char *p;
+
+			errno = 0;
+			busnum = strtol(name + 5, &p, 10);
+			if (errno == 0 && p != name + 5 && *p == '\0' &&
+			    busnum >= 0 && busnum <= INT_MAX) {
+				/*
+				 * OK, it's a valid number that's not
+				 * bigger than INT_MAX.  Construct
+				 * a description from it.
+				 */
+				static const char descr_prefix[] = "USB bus number ";
+				size_t descr_size;
+
+				/*
+				 * Allow enough room for a 32-bit bus number.
+				 * sizeof (descr_prefix) includes the
+				 * terminating NUL.
+				 */
+				descr_size = sizeof (descr_prefix) + 10;
+				description = malloc(descr_size);
+				if (description != NULL) {
+					pcap_snprintf(description, descr_size,
+					    "%s%ld", descr_prefix, busnum);
+				}
+			}
+		}
+	}
+#endif
+	return (description);
+#else /* SIOCGIFDESCR */
+get_if_description(const char *name _U_)
+{
+	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)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);
+}
+#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)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)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) {
+		*schemep = scheme;
+		*pathp = strdup(colonp + 3);
+		if (*pathp == NULL) {
+			pcap_fmt_errmsg_for_errno(ebuf, PCAP_ERRBUF_SIZE,
+			    errno, "malloc");
+			return (-1);
+		}
+		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.
+			 */
+			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:
+		strlcpy(source, PCAP_SRC_FILE_STRING, PCAP_BUF_SIZE);
+		if (name != NULL && *name != '\0') {
+			strlcat(source, name, PCAP_BUF_SIZE);
+			return (0);
+		} else {
+			pcap_snprintf(errbuf, PCAP_ERRBUF_SIZE,
+			    "The file name cannot be NULL.");
+			return (-1);
+		}
+
+	case PCAP_SRC_IFREMOTE:
+		strlcpy(source, PCAP_SRC_IF_STRING, PCAP_BUF_SIZE);
+		if (host != 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.
+				 */
+				strlcat(source, "[", PCAP_BUF_SIZE);
+				strlcat(source, host, PCAP_BUF_SIZE);
+				strlcat(source, "]", PCAP_BUF_SIZE);
+			} else
+				strlcat(source, host, PCAP_BUF_SIZE);
+
+			if (port != NULL && *port != '\0') {
+				strlcat(source, ":", PCAP_BUF_SIZE);
+				strlcat(source, port, PCAP_BUF_SIZE);
+			}
+
+			strlcat(source, "/", PCAP_BUF_SIZE);
+		} else {
+			pcap_snprintf(errbuf, PCAP_ERRBUF_SIZE,
+			    "The host name cannot be NULL.");
+			return (-1);
+		}
+
+		if (name != NULL && *name != '\0')
+			strlcat(source, name, PCAP_BUF_SIZE);
+
+		return (0);
+
+	case PCAP_SRC_IFLOCAL:
+		strlcpy(source, PCAP_SRC_IF_STRING, PCAP_BUF_SIZE);
+
+		if (name != NULL && *name != '\0')
+			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)
+			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
+				strlcpy(host, tmphost, PCAP_BUF_SIZE);
+		}
+		if (port && tmpport)
+			strlcpy(port, tmpport, PCAP_BUF_SIZE);
+		if (name && tmppath)
+			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)
+			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)
+		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)
 {
@@ -400,8 +1993,9 @@
 			length = wcslen((wchar_t *)device);
 			device_str = (char *)malloc(length + 1);
 			if (device_str == NULL) {
-				pcap_snprintf(errbuf, PCAP_ERRBUF_SIZE,
-				    "malloc: %s", pcap_strerror(errno));
+				pcap_fmt_errmsg_for_errno(errbuf,
+				    PCAP_ERRBUF_SIZE, errno,
+				    "malloc");
 				return (NULL);
 			}
 
@@ -412,8 +2006,8 @@
 			device_str = strdup(device);
 	}
 	if (device_str == NULL) {
-		pcap_snprintf(errbuf, PCAP_ERRBUF_SIZE,
-		    "malloc: %s", pcap_strerror(errno));
+		pcap_fmt_errmsg_for_errno(errbuf, PCAP_ERRBUF_SIZE,
+		    errno, "malloc");
 		return (NULL);
 	}
 
@@ -463,6 +2057,18 @@
 	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)
 {
@@ -477,7 +2083,6 @@
 	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->stats_ex_op = (stats_ex_op_t)pcap_not_initialized_ptr;
@@ -519,24 +2124,38 @@
 	 * 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) + 7) & ~0x7)
+	chunk = malloc(PCAP_T_ALIGNED_SIZE + size);
 	if (chunk == NULL) {
-		pcap_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. */
@@ -546,7 +2165,7 @@
 		 * 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);
@@ -569,10 +2188,17 @@
 	 */
 	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*/
- 	p->snapshot = MAXIMUM_SNAPLEN;	/* max packet size */
+	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;
@@ -580,6 +2206,15 @@
 	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.
@@ -605,16 +2240,6 @@
 {
 	if (pcap_check_activated(p))
 		return (PCAP_ERROR_ACTIVATED);
-
-	/*
-	 * Turn invalid values, or excessively large values, into
-	 * the maximum allowed value.
-	 *
-	 * If some application really *needs* a bigger snapshot
-	 * length, we should just increase MAXIMUM_SNAPLEN.
-	 */
-	if (snaplen <= 0 || snaplen > MAXIMUM_SNAPLEN)
-		snaplen = MAXIMUM_SNAPLEN;
 	p->snapshot = snaplen;
 	return (0);
 }
@@ -785,9 +2410,25 @@
 	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;
@@ -813,6 +2454,53 @@
 {
 	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;
+
+	/*
+	 * 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(device, errbuf);
 	if (p == NULL)
@@ -946,8 +2634,8 @@
 		 */
 		*dlt_buffer = (int*)malloc(sizeof(**dlt_buffer));
 		if (*dlt_buffer == NULL) {
-			(void)pcap_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;
@@ -955,8 +2643,8 @@
 	} else {
 		*dlt_buffer = (int*)calloc(sizeof(**dlt_buffer), p->dlt_count);
 		if (*dlt_buffer == NULL) {
-			(void)pcap_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,
@@ -1271,6 +2959,15 @@
 	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_SENTINEL
 };
 
@@ -1393,6 +3090,14 @@
 	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)
 {
@@ -1405,8 +3110,8 @@
 #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
@@ -1418,6 +3123,12 @@
 {
 	return (p->selectable_fd);
 }
+
+struct timeval *
+pcap_get_required_select_timeout(pcap_t *p)
+{
+	return (p->required_select_timeout);
+}
 #endif
 
 void
@@ -1437,14 +3148,18 @@
 {
 	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);
+		strlcpy(errbuf, p->errbuf, PCAP_ERRBUF_SIZE);
 	}
 	return (ret);
 }
@@ -1455,14 +3170,14 @@
  */
 #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) {
-		pcap_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)
@@ -1477,14 +3192,18 @@
 {
 	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);
+		strlcpy(errbuf, p->errbuf, PCAP_ERRBUF_SIZE);
 	}
 	return (ret);
 }
@@ -1497,14 +3216,14 @@
  * 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) {
-		pcap_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)
@@ -1512,8 +3231,8 @@
 	else
 		fdflags &= ~O_NONBLOCK;
 	if (fcntl(p->fd, F_SETFL, fdflags) == -1) {
-		pcap_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);
@@ -1532,7 +3251,7 @@
 	size_t errlen;
 	char *p;
 
-	FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM, NULL, error, 0, errbuf,
+	FormatMessageA(FORMAT_MESSAGE_FROM_SYSTEM, NULL, error, 0, errbuf,
 	    PCAP_ERRBUF_SIZE, NULL);
 
 	/*
@@ -1617,9 +3336,9 @@
 #ifdef HAVE_STRERROR
 #ifdef _WIN32
 	static char errbuf[PCAP_ERRBUF_SIZE];
-	errno_t errno;
-	errno = strerror_s(errbuf, PCAP_ERRBUF_SIZE, errnum);
-	if (errno != 0) /* errno = 0 if successful */
+	errno_t err = strerror_s(errbuf, PCAP_ERRBUF_SIZE, errnum);
+
+	if (err != 0) /* err = 0 if successful */
 		strlcpy(errbuf, "strerror_s() error", PCAP_ERRBUF_SIZE);
 	return (errbuf);
 #else
@@ -1666,14 +3385,6 @@
 	return (p->stats_op(p, ps));
 }
 
-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(pcap_t *p, int *pcap_stat_size)
@@ -1687,86 +3398,36 @@
 	return (p->setbuff_op(p, dim));
 }
 
-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);
-}
-
 int
 pcap_setmode(pcap_t *p, int mode)
 {
 	return (p->setmode_op(p, mode));
 }
 
-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);
-}
-
 int
 pcap_setmintocopy(pcap_t *p, int size)
 {
 	return (p->setmintocopy_op(p, size));
 }
 
-static int
-pcap_setmintocopy_dead(pcap_t *p, int size)
-{
-	pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
-	    "The mintocopy parameter cannot be set on a pcap_open_dead pcap_t");
-	return (-1);
-}
-
 HANDLE
 pcap_getevent(pcap_t *p)
 {
 	return (p->getevent_op(p));
 }
 
-static HANDLE
-pcap_getevent_dead(pcap_t *p)
-{
-	pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
-	    "A pcap_open_dead pcap_t has no event handle");
-	return (INVALID_HANDLE_VALUE);
-}
-
 int
 pcap_oid_get_request(pcap_t *p, bpf_u_int32 oid, void *data, size_t *lenp)
 {
 	return (p->oid_get_request_op(p, oid, data, lenp));
 }
 
-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);
-}
-
 int
 pcap_oid_set_request(pcap_t *p, bpf_u_int32 oid, const void *data, size_t *lenp)
 {
 	return (p->oid_set_request_op(p, oid, data, lenp));
 }
 
-static int
-pcap_oid_set_request_dead(pcap_t *p, bpf_u_int32 oid _U_, const void *data _U_,
-    size_t *lenp _U_)
-{
-	pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
-	    "An OID set request cannot be performed on a pcap_open_dead pcap_t");
-	return (PCAP_ERROR);
-}
-
 pcap_send_queue *
 pcap_sendqueue_alloc(u_int memsize)
 {
@@ -1822,56 +3483,24 @@
 	return (p->sendqueue_transmit_op(p, queue, sync));
 }
 
-static u_int
-pcap_sendqueue_transmit_dead(pcap_t *p, pcap_send_queue *queue, int sync)
-{
-	pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
-	    "Packets cannot be transmitted on a pcap_open_dead pcap_t");
-	return (0);
-}
-
 int
 pcap_setuserbuffer(pcap_t *p, int size)
 {
 	return (p->setuserbuffer_op(p, size));
 }
 
-static int
-pcap_setuserbuffer_dead(pcap_t *p, int size)
-{
-	pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
-	    "The user buffer cannot be set on a pcap_open_dead pcap_t");
-	return (-1);
-}
-
 int
 pcap_live_dump(pcap_t *p, char *filename, int maxsize, int maxpacks)
 {
 	return (p->live_dump_op(p, filename, maxsize, maxpacks));
 }
 
-static int
-pcap_live_dump_dead(pcap_t *p, char *filename, int maxsize, int maxpacks)
-{
-	pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
-	    "Live packet dumping cannot be performed on a pcap_open_dead pcap_t");
-	return (-1);
-}
-
 int
 pcap_live_dump_ended(pcap_t *p, int sync)
 {
 	return (p->live_dump_ended_op(p, sync));
 }
 
-static int
-pcap_live_dump_ended_dead(pcap_t *p, int sync)
-{
-	pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
-	    "Live packet dumping cannot be performed on a pcap_open_dead pcap_t");
-	return (-1);
-}
-
 PAirpcapHandle
 pcap_get_airpcap_handle(pcap_t *p)
 {
@@ -1884,12 +3513,6 @@
 	}
 	return (handle);
 }
-
-static PAirpcapHandle
-pcap_get_airpcap_handle_dead(pcap_t *p)
-{
-	return (NULL);
-}
 #endif
 
 /*
@@ -2012,66 +3635,6 @@
 #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->stats_ex_op = (stats_ex_op_t)pcap_not_initialized_ptr;
-	p->setbuff_op = pcap_setbuff_dead;
-	p->setmode_op = pcap_setmode_dead;
-	p->setmintocopy_op = pcap_setmintocopy_dead;
-	p->getevent_op = pcap_getevent_dead;
-	p->oid_get_request_op = pcap_oid_get_request_dead;
-	p->oid_set_request_op = pcap_oid_set_request_dead;
-	p->sendqueue_transmit_op = pcap_sendqueue_transmit_dead;
-	p->setuserbuffer_op = pcap_setuserbuffer_dead;
-	p->live_dump_op = pcap_live_dump_dead;
-	p->live_dump_ended_op = pcap_live_dump_ended_dead;
-	p->get_airpcap_handle_op = pcap_get_airpcap_handle_dead;
-#endif
-	p->cleanup_op = pcap_cleanup_dead;
-
-	/*
-	 * A "dead" pcap_t never requires special BPF code generation.
-	 */
-	p->bpf_codegen_flags = 0;
-
-	p->activated = 1;
-	return (p);
-}
-
-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.
@@ -2123,160 +3686,251 @@
 		return (0);
 }
 
-#include "pcap_version.h"
+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);
+}
+
+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);
+}
+
+static int
+pcap_inject_dead(pcap_t *p, const void *buf _U_, size_t size _U_)
+{
+	pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
+	    "Packets can't be sent on a pcap_open_dead pcap_t");
+	return (-1);
+}
+
+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);
+}
+
+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 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);
+}
+
+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
-
-static char *full_pcap_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 version number
- * when building WinPcap.  (It'd be nice to do so for the packet.dll version
- * number as well.)
- */
-#include "../../version.h"
-
-static const char wpcap_version_string[] = WINPCAP_VER_STRING;
-static const char pcap_version_string_fmt[] =
-	WINPCAP_PRODUCT_NAME " version %s, based on %s";
-static const char pcap_version_string_packet_dll_fmt[] =
-	WINPCAP_PRODUCT_NAME " version %s (packet.dll version %s), based on %s";
-
-const char *
-pcap_lib_version(void)
+struct pcap_stat *
+pcap_stats_ex_dead(pcap_t *p, int *pcap_stat_size _U_)
 {
-	char *packet_version_string;
-	size_t full_pcap_version_string_len;
+	pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
+	    "Statistics aren't available from a pcap_open_dead pcap_t");
+	return (NULL);
+}
 
-	if (full_pcap_version_string == 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)
+{
+	pcap_t *p;
+
+	switch (precision) {
+
+	case PCAP_TSTAMP_PRECISION_MICRO:
+	case PCAP_TSTAMP_PRECISION_NANO:
+		break;
+
+	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.
 		 */
-		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);
-			pcap_snprintf(full_pcap_version_string,
-			    full_pcap_version_string_len,
-			    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);
-			pcap_snprintf(full_pcap_version_string,
-			    full_pcap_version_string_len,
-			    pcap_version_string_packet_dll_fmt,
-			    wpcap_version_string,
-			    packet_version_string,
-			    pcap_version_string);
-		}
+		precision = PCAP_TSTAMP_PRECISION_MICRO;
+		break;
 	}
-	return (full_pcap_version_string);
-}
-
-#else /* HAVE_VERSION_H */
-
-/*
- * libpcap being built for Windows, not as part of a WinPcap/Npcap source
- * tree.
- */
-static const char pcap_version_string_packet_dll_fmt[] =
-	"%s (packet.dll version %s)";
-const char *
-pcap_lib_version(void)
-{
-	char *packet_version_string;
-	size_t full_pcap_version_string_len;
-
-	if (full_pcap_version_string == NULL) {
-		/*
-		 * Generate the version string.  Report the packet.dll
-		 * version.
-		 */
-		packet_version_string = PacketGetVersion();
-		full_pcap_version_string_len =
-		    (sizeof pcap_version_string_packet_dll_fmt - 4) +
-		    strlen(pcap_version_string) +
-		    strlen(packet_version_string);
-		full_pcap_version_string = malloc(full_pcap_version_string_len);
-		if (full_pcap_version_string == NULL)
-			return (NULL);
-		pcap_snprintf(full_pcap_version_string,
-		    full_pcap_version_string_len,
-		    pcap_version_string_packet_dll_fmt,
-		    pcap_version_string,
-		    packet_version_string);
-	}
-	return (full_pcap_version_string);
-}
-
-#endif /* HAVE_VERSION_H */
-
-#elif defined(MSDOS)
-
-static char *full_pcap_version_string;
-
-const char *
-pcap_lib_version (void)
-{
-	char *packet_version_string;
-	size_t full_pcap_version_string_len;
-	static char dospfx[] = "DOS-";
-
-	if (full_pcap_version_string == NULL) {
-		/*
-		 * Generate the version string.
-		 */
-		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);
-	}
-	return (full_pcap_version_string);
-}
-
-#else /* UN*X */
-
-const char *
-pcap_lib_version(void)
-{
-	return (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));
+}
 
 #ifdef YYDEBUG
 /*
@@ -2296,32 +3950,6 @@
 PCAP_API_DEF void
 pcap_set_parser_debug(int value)
 {
-	extern int pcap_debug;
-
 	pcap_debug = value;
 }
 #endif
-
-#ifdef BDEBUG
-/*
- * Set the internal "debug printout" flag for the filter expression optimizer.
- * The code to print that stuff is present only if BDEBUG is defined, so
- * the flag, and the routine to set it, are defined only if BDEBUG is
- * defined.
- *
- * This is intended for libpcap developers, not for general use.
- * If you want to set these in a program, you'll have to declare this
- * routine yourself, with the appropriate DLL import attribute on Windows;
- * it's not declared in any header file, and won't be declared in any
- * header file provided by libpcap.
- */
-PCAP_API void pcap_set_optimizer_debug(int value);
-
-PCAP_API_DEF void
-pcap_set_optimizer_debug(int value)
-{
-	extern int pcap_optimizer_debug;
-
-	pcap_optimizer_debug = value;
-}
-#endif
diff --git a/pcap/bluetooth.h b/pcap/bluetooth.h
index c5f378a..15dc5a8 100644
--- a/pcap/bluetooth.h
+++ b/pcap/bluetooth.h
@@ -34,12 +34,14 @@
 #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 @@
  * 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
diff --git a/pcap/bpf.h b/pcap/bpf.h
index 78ad890..1a953a9 100644
--- a/pcap/bpf.h
+++ b/pcap/bpf.h
@@ -15,11 +15,7 @@
  * 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.
  *
@@ -72,7 +68,7 @@
 #if !defined(_NET_BPF_H_) && !defined(_NET_BPF_H_INCLUDED) && !defined(_BPF_H_) && !defined(_H_BPF) && !defined(lib_pcap_bpf_h)
 #define lib_pcap_bpf_h
 
-#include <pcap/export-defs.h>
+#include <pcap/funcattrs.h>
 
 #ifdef __cplusplus
 extern "C" {
@@ -258,15 +254,9 @@
 #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)
 PCAP_API int bpf_validate(const struct bpf_insn *, int);
 PCAP_API u_int bpf_filter(const struct bpf_insn *, const u_char *, u_int, u_int);
 extern u_int bpf_filter_with_aux_data(const struct bpf_insn *, const u_char *, u_int, u_int, const struct bpf_aux_data *);
-#else
-PCAP_API int bpf_validate();
-PCAP_API u_int bpf_filter();
-extern u_int bpf_filter_with_aux_data();
-#endif
 
 /*
  * Number of scratch memory words (for BPF_LD|BPF_MEM and BPF_ST).
diff --git a/pcap/can_socketcan.h b/pcap/can_socketcan.h
index 68d2a13..332d9ff 100644
--- a/pcap/can_socketcan.h
+++ b/pcap/can_socketcan.h
@@ -39,16 +39,18 @@
 #ifndef lib_pcap_can_socketcan_h
 #define lib_pcap_can_socketcan_h
 
+#include <pcap/pcap-inttypes.h>
+
 /*
  * SocketCAN header, as per Documentation/networking/can.txt in the
  * Linux source.
  */
 typedef struct {
-	u_int32_t can_id;
-	u_int8_t payload_length;
-	u_int8_t pad;
-	u_int8_t reserved1;
-	u_int8_t reserved2;
+	uint32_t can_id;
+	uint8_t payload_length;
+	uint8_t pad;
+	uint8_t reserved1;
+	uint8_t reserved2;
 } pcap_can_socketcan_hdr;
 
 #endif
diff --git a/pcap/compiler-tests.h b/pcap/compiler-tests.h
new file mode 100644
index 0000000..5e17853
--- /dev/null
+++ b/pcap/compiler-tests.h
@@ -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_funcattrs_h */
diff --git a/pcap/dlt.h b/pcap/dlt.h
index 2d74713..535fd50 100644
--- a/pcap/dlt.h
+++ b/pcap/dlt.h
@@ -15,11 +15,7 @@
  * 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.
  *
@@ -54,7 +50,7 @@
  *
  * See
  *
- *	http://www.tcpdump.org/linktypes.html
+ *	https://www.tcpdump.org/linktypes.html
  *
  * for detailed descriptions of some of these link-layer header types.
  */
@@ -124,9 +120,9 @@
 
 /*
  * 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.)
+ * 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
@@ -344,7 +340,7 @@
  *
  * FreeBSD's libpcap won't map a link-layer header type of 18 - i.e.,
  * DLT_PFSYNC files from OpenBSD and possibly older versions of NetBSD,
- * DragonFly BSD, and OS X - to DLT_PFSYNC, so code built with FreeBSD's
+ * 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;
@@ -744,8 +740,13 @@
  * 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	195
+#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
@@ -950,14 +951,14 @@
  * 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.
@@ -1233,7 +1234,7 @@
  * 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
@@ -1245,9 +1246,9 @@
  * 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
+ * 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 OS X, they define DLT_PKTAP to be DLT_USER2, so programs won't
+ * 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.
  *
@@ -1307,6 +1308,66 @@
 #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
+
+/*
  * 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
@@ -1316,7 +1377,7 @@
 #ifdef DLT_MATCHING_MAX
 #undef DLT_MATCHING_MAX
 #endif
-#define DLT_MATCHING_MAX	265	/* highest value in the "matching" range */
+#define DLT_MATCHING_MAX	275	/* highest value in the "matching" range */
 
 /*
  * DLT and savefile link type values are split into a class and
diff --git a/pcap/export-defs.h b/pcap/export-defs.h
deleted file mode 100644
index a235057..0000000
--- a/pcap/export-defs.h
+++ /dev/null
@@ -1,108 +0,0 @@
-/* -*- Mode: c; tab-width: 8; indent-tabs-mode: 1; c-basic-offset: 8; -*- */
-/*
- * Copyright (c) 1993, 1994, 1995, 1996, 1997
- *	The Regents of the University of California.  All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in the
- *    documentation and/or other materials provided with the distribution.
- * 3. All advertising materials mentioning features or use of this software
- *    must display the following acknowledgement:
- *	This product includes software developed by the Computer Systems
- *	Engineering Group at Lawrence Berkeley Laboratory.
- * 4. Neither the name of the University nor of the Laboratory may be used
- *    to endorse or promote products derived from this software without
- *    specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
- * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
- * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- */
-
-#ifndef lib_pcap_export_defs_h
-#define lib_pcap_export_defs_h
-
-/*
- * PCAP_API_DEF must be used when defining *data* exported from
- * libpcap.  It can be used when defining *functions* exported
- * from libpcap, but it doesn't have to be used there.  It
- * should not be used in declarations in headers.
- *
- * PCAP_API must be used when *declaring* data or functions
- * exported from libpcap; PCAP_API_DEF won't work on all platforms.
- */
-
-/*
- * Check whether this is GCC major.minor or a later release, or some
- * compiler that claims to be "just like GCC" of that version or a
- * later release.
- */
-#define IS_AT_LEAST_GNUC_VERSION(major, minor) \
-	(defined(__GNUC__) && \
-	    (__GNUC__ > (major) || \
-	     (__GNUC__ == (major) && __GNUC_MINOR__ >= (minor))))
-
-#if defined(_WIN32)
-  #ifdef BUILDING_PCAP
-    /*
-     * We're compiling libpcap, so we should export functions in our
-     * API.
-     */
-    #define PCAP_API_DEF	__declspec(dllexport)
-  #else
-    #define PCAP_API_DEF	__declspec(dllimport)
-  #endif
-#elif defined(MSDOS)
-  /* XXX - does this need special treatment? */
-  #define PCAP_API_DEF
-#else /* UN*X */
-  #ifdef BUILDING_PCAP
-    /*
-     * We're compiling libpcap, so we should export functions in our API.
-     * The compiler might be configured not to export functions from a
-     * shared library by default, so we might have to explicitly mark
-     * functions as exported.
-     */
-    #if IS_AT_LEAST_GNUC_VERSION(3, 4)
-      /*
-       * GCC 3.4 or later, or some compiler asserting compatibility with
-       * GCC 3.4 or later, so we have __attribute__((visibility()).
-       */
-      #define PCAP_API_DEF	__attribute__((visibility("default")))
-    #elif defined(__SUNPRO_C) && (__SUNPRO_C >= 0x550)
-      /*
-       * Sun C 5.5 or later, so we have __global.
-       * (Sun C 5.9 and later also have __attribute__((visibility()),
-       * but there's no reason to prefer it with Sun C.)
-       */
-      #define PCAP_API_DEF	__global
-    #else
-      /*
-       * We don't have anything to say.
-       */
-      #define PCAP_API_DEF
-    #endif
-  #else
-    /*
-     * We're not building libpcap.
-     */
-    #define PCAP_API_DEF
-  #endif
-#endif /* _WIN32/MSDOS/UN*X */
-
-#define PCAP_API	PCAP_API_DEF extern
-
-#endif /* lib_pcap_export_defs_h */
diff --git a/pcap/funcattrs.h b/pcap/funcattrs.h
new file mode 100644
index 0000000..a8b1932
--- /dev/null
+++ b/pcap/funcattrs.h
@@ -0,0 +1,261 @@
+/* -*- 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 and
+   * later, or Solaris Studio 12 (Sun C 5.9) and later, or IBM XL C 10.1
+   * and later (do any earlier versions of XL C support this?), or
+   * HP aCC A.06.10 and later.
+   */
+  #define PCAP_NORETURN __attribute((noreturn))
+  #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 and later, or IBM XL C 10.1
+   * and later (do any earlier versions of XL C support this?),
+   * or HP aCC A.06.10 and later.
+   */
+  #define PCAP_PRINTFLIKE(x,y) __attribute__((__format__(__printf__,x,y)))
+#else
+  #define PCAP_PRINTFLIKE(x,y)
+#endif
+
+/*
+ * 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 and 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 */
diff --git a/pcap/namedb.h b/pcap/namedb.h
index 73fb40a..c66846d 100644
--- a/pcap/namedb.h
+++ b/pcap/namedb.h
@@ -60,9 +60,7 @@
 PCAP_API u_char *pcap_ether_aton(const char *);
 
 PCAP_API bpf_u_int32 **pcap_nametoaddr(const char *);
-#ifdef INET6
 PCAP_API struct addrinfo *pcap_nametoaddrinfo(const char *);
-#endif
 PCAP_API bpf_u_int32 pcap_nametonetaddr(const char *);
 
 PCAP_API int	pcap_nametoport(const char *, int *, int *);
diff --git a/pcap/nflog.h b/pcap/nflog.h
index a3867cd..f7c85b5 100644
--- a/pcap/nflog.h
+++ b/pcap/nflog.h
@@ -28,9 +28,11 @@
 #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.
  *
@@ -40,32 +42,32 @@
  * 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
index 0000000..af2c23c
--- /dev/null
+++ b/pcap/pcap-inttypes.h
@@ -0,0 +1,117 @@
+/*
+ * 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
+#elif defined(__MINGW32__) || !defined(_WIN32)
+  /*
+   * Compiler is MinGW or target is UN*X or MS-DOS.  Just use
+   * <inttypes.h>.
+   */
+  #include <inttypes.h>
+#endif
+
+#endif /* pcap/pcap-inttypes.h */
diff --git a/pcap/pcap.h b/pcap/pcap.h
index 7f92a37..bc87b3f 100644
--- a/pcap/pcap.h
+++ b/pcap/pcap.h
@@ -32,18 +32,55 @@
  * 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
 
-#include <pcap/export-defs.h>
+#include <pcap/funcattrs.h>
+
+#include <pcap/pcap-inttypes.h>
 
 #if defined(_WIN32)
-  #include <pcap-stdinc.h>
+  #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 */
 
@@ -172,11 +209,11 @@
 	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 */
-#if defined(_WIN32) && defined(HAVE_REMOTE)
+#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 && HAVE_REMOTE */
+#endif /* _WIN32 */
 };
 
 #ifdef MSDOS
@@ -223,9 +260,15 @@
 	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.
@@ -275,7 +318,14 @@
  */
 #define PCAP_NETMASK_UNKNOWN	0xffffffff
 
-PCAP_API char	*pcap_lookupdev(char *);
+/*
+ * 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 *);
@@ -297,6 +347,10 @@
 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.
  * Not all systems and interfaces will necessarily support all of these.
@@ -360,7 +414,16 @@
   PCAP_API pcap_t  *pcap_hopen_offline(intptr_t, char *);
   /*
    * If we're building libpcap, these are internal routines in savefile.c,
-   * so we mustn't define them as macros.
+   * 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) \
@@ -409,6 +472,7 @@
 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 */
 PCAP_API FILE	*pcap_file(pcap_t *);
@@ -423,6 +487,7 @@
 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 *);
@@ -430,6 +495,21 @@
 PCAP_API int	pcap_findalldevs(pcap_if_t **, char *);
 PCAP_API void	pcap_freealldevs(pcap_if_t *);
 
+/*
+ * 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);
 
 /*
@@ -457,7 +537,7 @@
   */
   struct pcap_send_queue
   {
-	u_int maxlen;	/* Maximum size of the the queue, in bytes. This
+	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. */
@@ -523,13 +603,368 @@
    */
 
   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 */
 
-#ifdef HAVE_REMOTE
-  /* Includes most of the public stuff that is needed for the remote capture */
-  #include <remote-ext.h>
-#endif	 /* HAVE_REMOTE */
+/*
+ * Remote capture definitions.
+ *
+ * These routines are only present if libpcap has been configured to
+ * include remote capture support.
+ */
+
+/*
+ * 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
+
+/*
+ * 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 */
+
+/*
+ * 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]
+ */
+
+/*
+ * 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://"
+
+/*
+ * Flags to pass to pcap_open().
+ */
+
+/*
+ * Specifies whether promiscuous mode is to be used.
+ */
+#define PCAP_OPENFLAG_PROMISCUOUS		0x00000001
+
+/*
+ * 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(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);
+
+/*
+ * RPCAP active mode.
+ */
+
+/* Maximum length of an host name (needed for the RPCAP active mode) */
+#define RPCAP_HOSTLIST_SIZE 1024
+
+/*
+ * Some minor differences between UN*X sockets and and Winsock sockets.
+ */
+#ifndef _WIN32
+  /*!
+   * \brief In Winsock, a socket handle is of type SOCKET; in UN*X, it's
+   * a file descriptor, and therefore a signed integer.
+   * We define SOCKET to be a signed integer on UN*X, so that it can
+   * be used on both platforms.
+   */
+  #define SOCKET int
+
+  /*!
+   * \brief In Winsock, the error return if socket() fails is INVALID_SOCKET;
+   * in UN*X, it's -1.
+   * We define INVALID_SOCKET to be -1 on UN*X, so that it can be used on
+   * both platforms.
+   */
+  #define INVALID_SOCKET -1
+#endif
+
+PCAP_API SOCKET	pcap_remoteact_accept(const char *address, const char *port,
+	    const char *hostlist, char *connectinghost,
+	    struct pcap_rmtauth *auth, char *errbuf);
+PCAP_API int	pcap_remoteact_list(char *hostlist, char sep, int size,
+	    char *errbuf);
+PCAP_API int	pcap_remoteact_close(const char *host, char *errbuf);
+PCAP_API void	pcap_remoteact_cleanup(void);
 
 #ifdef __cplusplus
 }
diff --git a/pcap/sll.h b/pcap/sll.h
index b46d15f..c4d0886 100644
--- a/pcap/sll.h
+++ b/pcap/sll.h
@@ -80,12 +80,14 @@
 #define SLL_HDR_LEN	16		/* total header length */
 #define SLL_ADDRLEN	8		/* length of address field */
 
+#include <pcap/pcap-inttypes.h>
+
 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 */
 };
 
 /*
diff --git a/pcap/usb.h b/pcap/usb.h
index 26a9046..e485ec8 100644
--- a/pcap/usb.h
+++ b/pcap/usb.h
@@ -34,6 +34,8 @@
 #ifndef lib_pcap_usb_h
 #define lib_pcap_usb_h
 
+#include <pcap/pcap-inttypes.h>
+
 /*
  * possible transfer mode
  */
@@ -55,11 +57,11 @@
  * 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 @@
  * 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 @@
  * 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_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
diff --git a/pcap/vlan.h b/pcap/vlan.h
index 021f612..b29dd73 100644
--- a/pcap/vlan.h
+++ b/pcap/vlan.h
@@ -34,9 +34,11 @@
 #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
diff --git a/pcap_activate.3pcap b/pcap_activate.3pcap
index 8c89939..ceb2aa7 100644
--- a/pcap_activate.3pcap
+++ b/pcap_activate.3pcap
@@ -17,7 +17,7 @@
 .\" WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
 .\" MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
 .\"
-.TH PCAP_ACTIVATE 3PCAP "7 April 2014"
+.TH PCAP_ACTIVATE 3PCAP "31 July 2016"
 .SH NAME
 pcap_activate \- activate a capture handle
 .SH SYNOPSIS
diff --git a/pcap_breakloop.3pcap b/pcap_breakloop.3pcap
index 3f9327b..03b8d8d 100644
--- a/pcap_breakloop.3pcap
+++ b/pcap_breakloop.3pcap
@@ -17,7 +17,7 @@
 .\" WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
 .\" MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
 .\"
-.TH PCAP_BREAKLOOP 3PCAP "8 March 2015"
+.TH PCAP_BREAKLOOP 3PCAP "8 November 2017"
 .SH NAME
 pcap_breakloop \- force a pcap_dispatch() or pcap_loop() call to return
 .SH SYNOPSIS
@@ -62,9 +62,21 @@
 Note also that, in a multi-threaded application, if one thread is
 blocked in pcap_dispatch(), pcap_loop(), pcap_next(), or pcap_next_ex(),
 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
diff --git a/pcap_can_set_rfmon.3pcap b/pcap_can_set_rfmon.3pcap
index 389e50d..eee004d 100644
--- a/pcap_can_set_rfmon.3pcap
+++ b/pcap_can_set_rfmon.3pcap
@@ -17,7 +17,7 @@
 .\" WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
 .\" MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
 .\"
-.TH PCAP_CAN_SET_RFMON 3PCAP "3 January 2014"
+.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
diff --git a/pcap_compile.3pcap b/pcap_compile.3pcap
index 6eb20be..181814b 100644
--- a/pcap_compile.3pcap
+++ b/pcap_compile.3pcap
@@ -17,7 +17,7 @@
 .\" WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
 .\" MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
 .\"
-.TH PCAP_COMPILE 3PCAP "7 April 2014"
+.TH PCAP_COMPILE 3PCAP "24 March 2017"
 .SH NAME
 pcap_compile \- compile a filter expression
 .SH SYNOPSIS
@@ -55,6 +55,16 @@
 than one network, a value of 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.
diff --git a/pcap_compile.3pcap.in b/pcap_compile.3pcap.in
index 2bd0eb4..29ae8f8 100644
--- a/pcap_compile.3pcap.in
+++ b/pcap_compile.3pcap.in
@@ -17,7 +17,7 @@
 .\" WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
 .\" MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
 .\"
-.TH PCAP_COMPILE 3PCAP "7 April 2014"
+.TH PCAP_COMPILE 3PCAP "24 March 2017"
 .SH NAME
 pcap_compile \- compile a filter expression
 .SH SYNOPSIS
@@ -55,6 +55,16 @@
 than one network, a value of 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.
diff --git a/pcap_datalink.3pcap b/pcap_datalink.3pcap
index 4cb1007..50508f8 100644
--- a/pcap_datalink.3pcap
+++ b/pcap_datalink.3pcap
@@ -41,7 +41,7 @@
 that has not yet been activated by
 .BR pcap_activate() .
 .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
diff --git a/pcap_datalink.3pcap.in b/pcap_datalink.3pcap.in
index be50a64..a32f15e 100644
--- a/pcap_datalink.3pcap.in
+++ b/pcap_datalink.3pcap.in
@@ -41,7 +41,7 @@
 that has not yet been activated by
 .BR pcap_activate() .
 .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
diff --git a/pcap_datalink_name_to_val.3pcap b/pcap_datalink_name_to_val.3pcap
index 8a6905a..e6419f2 100644
--- a/pcap_datalink_name_to_val.3pcap
+++ b/pcap_datalink_name_to_val.3pcap
@@ -17,7 +17,7 @@
 .\" WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
 .\" MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
 .\"
-.TH PCAP_DATALINK_NAME_TO_VAL 3PCAP "5 December 2014"
+.TH PCAP_DATALINK_NAME_TO_VAL 3PCAP "12 October 2016"
 .SH NAME
 pcap_datalink_name_to_val \- get the link-layer header type value
 corresponding to a header type name
diff --git a/pcap_datalink_val_to_name.3pcap b/pcap_datalink_val_to_name.3pcap
index aa3e89a..fad350f 100644
--- a/pcap_datalink_val_to_name.3pcap
+++ b/pcap_datalink_val_to_name.3pcap
@@ -17,7 +17,7 @@
 .\" WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
 .\" MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
 .\"
-.TH PCAP_DATALINK_VAL_TO_NAME 3PCAP "3 January 2014"
+.TH PCAP_DATALINK_VAL_TO_NAME 3PCAP "12 October 2016"
 .SH NAME
 pcap_datalink_val_to_name, pcap_datalink_val_to_description \- get a
 name or description for a link-layer header type value
diff --git a/pcap_dump_ftell.3pcap b/pcap_dump_ftell.3pcap
index 757e948..ec621fb 100644
--- a/pcap_dump_ftell.3pcap
+++ b/pcap_dump_ftell.3pcap
@@ -17,9 +17,9 @@
 .\" WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
 .\" MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
 .\"
-.TH PCAP_DUMP_FTELL 3PCAP "3 January 2014"
+.TH PCAP_DUMP_FTELL 3PCAP "29 September 2017"
 .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,6 +28,8 @@
 .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
@@ -38,5 +40,18 @@
 and
 .BR pcap_dump() .
 \-1 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.
+\-1 is returned on error.
 .SH SEE ALSO
 pcap(3PCAP), pcap_dump_open(3PCAP), pcap_dump(3PCAP)
diff --git a/pcap_dump_open.3pcap b/pcap_dump_open.3pcap
index fd96aab..03956ba 100644
--- a/pcap_dump_open.3pcap
+++ b/pcap_dump_open.3pcap
@@ -17,7 +17,7 @@
 .\" WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
 .\" MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
 .\"
-.TH PCAP_DUMP_OPEN 3PCAP "16 February 2015"
+.TH PCAP_DUMP_OPEN 3PCAP "22 June 2018"
 .SH NAME
 pcap_dump_open, pcap_dump_fopen \- open a file to which to write packets
 .SH SYNOPSIS
@@ -48,7 +48,9 @@
 .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() .
 Note that on Windows, that stream should be opened in binary mode.
 .PP
 .I p
@@ -91,6 +93,6 @@
 can be used to get the error text.
 .SH SEE ALSO
 pcap(3PCAP), pcap_create(3PCAP), pcap_activate(3PCAP),
-pcap_open_offline(3PCAP), pcap_open_live(3PCAP), pcap_open_dead(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(5)
+\%pcap-savefile(5)
diff --git a/pcap_dump_open.3pcap.in b/pcap_dump_open.3pcap.in
index 3f91d13..5b37b47 100644
--- a/pcap_dump_open.3pcap.in
+++ b/pcap_dump_open.3pcap.in
@@ -17,7 +17,7 @@
 .\" WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
 .\" MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
 .\"
-.TH PCAP_DUMP_OPEN 3PCAP "16 February 2015"
+.TH PCAP_DUMP_OPEN 3PCAP "22 June 2018"
 .SH NAME
 pcap_dump_open, pcap_dump_fopen \- open a file to which to write packets
 .SH SYNOPSIS
@@ -48,7 +48,9 @@
 .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() .
 Note that on Windows, that stream should be opened in binary mode.
 .PP
 .I p
@@ -91,6 +93,6 @@
 can be used to get the error text.
 .SH SEE ALSO
 pcap(3PCAP), pcap_create(3PCAP), pcap_activate(3PCAP),
-pcap_open_offline(3PCAP), pcap_open_live(3PCAP), pcap_open_dead(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-savefile(@MAN_FILE_FORMATS@)
diff --git a/pcap_fileno.3pcap b/pcap_fileno.3pcap
index 7aeb069..e8c9ac4 100644
--- a/pcap_fileno.3pcap
+++ b/pcap_fileno.3pcap
@@ -63,4 +63,4 @@
 .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_fopen_offline(3PCAP), pcap_open_dead(3PCAP)
diff --git a/pcap_findalldevs.3pcap b/pcap_findalldevs.3pcap
index 2dd3e59..14825ad 100644
--- a/pcap_findalldevs.3pcap
+++ b/pcap_findalldevs.3pcap
@@ -17,7 +17,7 @@
 .\" WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
 .\" MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
 .\"
-.TH PCAP_FINDALLDEVS 3PCAP "7 April 2014"
+.TH PCAP_FINDALLDEVS 3PCAP "29 April 2018"
 .SH NAME
 pcap_findalldevs, pcap_freealldevs \- get a list of capture devices, and
 free that list
@@ -98,6 +98,30 @@
 .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
diff --git a/pcap_get_required_select_timeout.3pcap b/pcap_get_required_select_timeout.3pcap
new file mode 100644
index 0000000..bc33e5d
--- /dev/null
+++ b/pcap_get_required_select_timeout.3pcap
@@ -0,0 +1,84 @@
+.\" 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 "20 January 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() ,
+.BR poll() ,
+.BR epoll_wait() ,
+and
+.B kevent()
+calls if
+.B pcap_get_selectable_fd()
+returns \-1.
+.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 \-1 must be put in non-blocking mode with
+.BR pcap_setnonblock() ,
+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()
+or
+.B pcap_next_ex()
+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 SEE ALSO
+pcap(3PCAP), pcap_get_selectable_fd(3PCAP), select(2), poll(2),
+epoll_wait(2), kqueue(2)
diff --git a/pcap_get_selectable_fd.3pcap b/pcap_get_selectable_fd.3pcap
index 86b0c26..f1ddfe2 100644
--- a/pcap_get_selectable_fd.3pcap
+++ b/pcap_get_selectable_fd.3pcap
@@ -17,7 +17,7 @@
 .\" WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
 .\" MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
 .\"
-.TH PCAP_GET_SELECTABLE_FD 3PCAP "18 October 2014"
+.TH PCAP_GET_SELECTABLE_FD 3PCAP "20 January 2018"
 .SH NAME
 pcap_get_selectable_fd \- get a file descriptor on which a select() can
 be done for a live capture
@@ -38,26 +38,41 @@
 do a
 .BR select() ,
 .BR poll() ,
+.BR epoll_wait() ,
+.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
+a descriptor exists, or \-1, if no such descriptor exists.
+.PP
+Some network devices opened with
 .B pcap_create()
 and
 .BR pcap_activate() ,
 or with
 .BR pcap_open_live() ,
-do not support
-.B select()
-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.
+do not support those calls (for example, regular network devices on
+FreeBSD 4.3 and 4.4, and Endace DAG devices), so \-1 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()
+for the device for which
+.B pcap_get_selectable_fd()
+returned \-1, the device must be put in non-blocking mode with a call to
+.BR pcap_setnonblock() ,
+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 descriptor on which a read can be done without blocking may,
-on some platforms, not have any packets to read if the read timeout has
-expired.  A call to
+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()
+or
+.B pcap_next_ex()
 will return 0 in this case, but will not block.
 .PP
 Note that in:
@@ -70,59 +85,55 @@
 .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()
+.BR select() ,
+.BR poll() ,
 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()
-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.
@@ -130,4 +141,5 @@
 A selectable file descriptor is returned if one exists; otherwise, \-1
 is returned.
 .SH SEE ALSO
-pcap(3PCAP), select(2), poll(2)
+pcap(3PCAP), pcap_get_required_select_timeout(3PCAP),
+pcap_setnonblock(3PCAP), select(2), poll(2), epoll_wait(2), kqueue(2)
diff --git a/pcap_geterr.3pcap b/pcap_geterr.3pcap
index 2e99c37..ee681c8 100644
--- a/pcap_geterr.3pcap
+++ b/pcap_geterr.3pcap
@@ -17,7 +17,7 @@
 .\" WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
 .\" MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
 .\"
-.TH PCAP_GETERR 3PCAP "3 January 2014"
+.TH PCAP_GETERR 3PCAP "15 January 2016"
 .SH NAME
 pcap_geterr, pcap_perror \- get or print libpcap error message text
 .SH SYNOPSIS
diff --git a/pcap_is_swapped.3pcap b/pcap_is_swapped.3pcap
index c4e62ae..36691d3 100644
--- a/pcap_is_swapped.3pcap
+++ b/pcap_is_swapped.3pcap
@@ -43,7 +43,7 @@
 that has not yet been activated by
 .BR pcap_activate() .
 .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.
diff --git a/pcap_lookupdev.3pcap b/pcap_lookupdev.3pcap
index aaa3a20..eb493ba 100644
--- a/pcap_lookupdev.3pcap
+++ b/pcap_lookupdev.3pcap
@@ -17,7 +17,7 @@
 .\" WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
 .\" MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
 .\"
-.TH PCAP_LOOKUPDEV 3PCAP "3 January 2014"
+.TH PCAP_LOOKUPDEV 3PCAP "8 September 2017"
 .SH NAME
 pcap_lookupdev \- find the default device on which to capture
 .SH SYNOPSIS
@@ -32,10 +32,18 @@
 .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
@@ -58,3 +66,15 @@
 .SH SEE ALSO
 pcap(3PCAP), pcap_create(3PCAP), pcap_activate(3PCAP),
 pcap_open_live(3PCAP), pcap_lookupnet(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.
+
diff --git a/pcap_loop.3pcap b/pcap_loop.3pcap
index 0eaf6e5..4679b46 100644
--- a/pcap_loop.3pcap
+++ b/pcap_loop.3pcap
@@ -17,7 +17,7 @@
 .\" WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
 .\" MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
 .\"
-.TH PCAP_LOOP 3PCAP "18 October 2014"
+.TH PCAP_LOOP 3PCAP "20 January 2017"
 .SH NAME
 pcap_loop, pcap_dispatch \- process packets from a live capture or savefile
 .SH SYNOPSIS
@@ -51,7 +51,7 @@
 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
@@ -130,7 +130,7 @@
 .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
@@ -166,18 +166,18 @@
 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
+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 \-1 if an error occurs or \-2 if the loop
 terminated due to a call to
 .B pcap_breakloop()
 before any packets were processed.
diff --git a/pcap_major_version.3pcap b/pcap_major_version.3pcap
index 8334e16..2fedfd2 100644
--- a/pcap_major_version.3pcap
+++ b/pcap_major_version.3pcap
@@ -17,7 +17,7 @@
 .\" WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
 .\" MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
 .\"
-.TH PCAP_MAJOR_VERSION 3PCAP "7 April 2014"
+.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 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
diff --git a/pcap_next_ex.3pcap b/pcap_next_ex.3pcap
index d69e728..88e8314 100644
--- a/pcap_next_ex.3pcap
+++ b/pcap_next_ex.3pcap
@@ -17,7 +17,7 @@
 .\" WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
 .\" MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
 .\"
-.TH PCAP_NEXT_EX 3PCAP "7 April 2014"
+.TH PCAP_NEXT_EX 3PCAP "20 January 2017"
 .SH NAME
 pcap_next_ex, pcap_next \- read the next packet from a pcap_t
 .SH SYNOPSIS
@@ -85,7 +85,7 @@
 .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
@@ -112,12 +112,11 @@
 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,
+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,
+\-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()
 or
 .B pcap_perror()
@@ -128,14 +127,14 @@
 .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)
diff --git a/pcap_open_dead.3pcap b/pcap_open_dead.3pcap
index 4a75c32..118c533 100644
--- a/pcap_open_dead.3pcap
+++ b/pcap_open_dead.3pcap
@@ -76,4 +76,4 @@
 .BR pcap_compile() .
 .SH SEE ALSO
 pcap(3PCAP), pcap_compile(3PCAP), pcap_dump_open(3PCAP),
-pcap-linktype(7)
+\%pcap-linktype(7)
diff --git a/pcap_open_dead.3pcap.in b/pcap_open_dead.3pcap.in
index a3dc592..621e75b 100644
--- a/pcap_open_dead.3pcap.in
+++ b/pcap_open_dead.3pcap.in
@@ -76,4 +76,4 @@
 .BR pcap_compile() .
 .SH SEE ALSO
 pcap(3PCAP), pcap_compile(3PCAP), pcap_dump_open(3PCAP),
-pcap-linktype(@MAN_MISC_INFO@)
+\%pcap-linktype(@MAN_MISC_INFO@)
diff --git a/pcap_open_live.3pcap b/pcap_open_live.3pcap
index 8c5d474..942d4fc 100644
--- a/pcap_open_live.3pcap
+++ b/pcap_open_live.3pcap
@@ -17,7 +17,7 @@
 .\" WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
 .\" MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
 .\"
-.TH PCAP_OPEN_LIVE 3PCAP "3 January 2014"
+.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 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
diff --git a/pcap_open_offline.3pcap b/pcap_open_offline.3pcap
index 996572a..3c59372 100644
--- a/pcap_open_offline.3pcap
+++ b/pcap_open_offline.3pcap
@@ -17,7 +17,7 @@
 .\" WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
 .\" MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
 .\"
-.TH PCAP_OPEN_OFFLINE 3PCAP "3 January 2014"
+.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 @@
 .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 .
diff --git a/pcap_open_offline.3pcap.in b/pcap_open_offline.3pcap.in
index 7fe551e..d0cd161 100644
--- a/pcap_open_offline.3pcap.in
+++ b/pcap_open_offline.3pcap.in
@@ -17,7 +17,7 @@
 .\" WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
 .\" MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
 .\"
-.TH PCAP_OPEN_OFFLINE 3PCAP "3 January 2014"
+.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 @@
 .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 .
diff --git a/pcap_set_protocol_linux.3pcap b/pcap_set_protocol_linux.3pcap
new file mode 100644
index 0000000..40eb8d2
--- /dev/null
+++ b/pcap_set_protocol_linux.3pcap
@@ -0,0 +1,67 @@
+.\" 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() .
+.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 SEE ALSO
+pcap(3PCAP), pcap_create(3PCAP), pcap_activate(3PCAP), socket(2),
+pcap_setfilter(3PCAP)
diff --git a/pcap_set_timeout.3pcap b/pcap_set_timeout.3pcap
index a89327f..cacf603 100644
--- a/pcap_set_timeout.3pcap
+++ b/pcap_set_timeout.3pcap
@@ -17,10 +17,10 @@
 .\" WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
 .\" MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
 .\"
-.TH PCAP_SET_TIMEOUT 3PCAP "1 December 2015"
+.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,12 +32,15 @@
 .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.  We
+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
@@ -47,4 +50,4 @@
 if called on a capture handle that has been activated.
 .SH SEE ALSO
 pcap(3PCAP), pcap_create(3PCAP), pcap_activate(3PCAP),
-pcap_set_immediate_mode(3PCAP)
+\%pcap_set_immediate_mode(3PCAP)
diff --git a/pcap_set_tstamp_type.3pcap b/pcap_set_tstamp_type.3pcap
index 8a3bda0..b797c1a 100644
--- a/pcap_set_tstamp_type.3pcap
+++ b/pcap_set_tstamp_type.3pcap
@@ -34,7 +34,7 @@
 .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
diff --git a/pcap_set_tstamp_type.3pcap.in b/pcap_set_tstamp_type.3pcap.in
index e58cdd4..7899da3 100644
--- a/pcap_set_tstamp_type.3pcap.in
+++ b/pcap_set_tstamp_type.3pcap.in
@@ -34,7 +34,7 @@
 .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
diff --git a/pcap_version.h b/pcap_version.h
deleted file mode 100644
index 619c6d8..0000000
--- a/pcap_version.h
+++ /dev/null
@@ -1,13 +0,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).
- */
-static const char pcap_version_string[] = "libpcap version 1.8.1";
diff --git a/pcap_version.h.in b/pcap_version.h.in
deleted file mode 100644
index 3104c8e..0000000
--- a/pcap_version.h.in
+++ /dev/null
@@ -1,13 +0,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).
- */
-static const char pcap_version_string[] = "libpcap version %%LIBPCAP_VERSION%%";
diff --git a/portability.h b/portability.h
index 8a6bf40..b361254 100644
--- a/portability.h
+++ b/portability.h
@@ -39,6 +39,8 @@
  * flavors of UN*X.
  */
 
+#include "pcap/funcattrs.h"
+
 #ifdef __cplusplus
 extern "C" {
 #endif
@@ -47,7 +49,7 @@
  /*
   * Macro that does the same thing as strlcpy().
   */
- #ifdef _MSC_VER
+ #if defined(_MSC_VER) || defined(__MINGW32__)
   /*
    * strncpy_s() is supported at least back to Visual
    * Studio 2005.
@@ -63,44 +65,37 @@
  #endif
 #endif
 
-/*
- * For flagging arguments as format strings in MSVC.
- */
-#if _MSC_VER >= 1400
- #include <sal.h>
- #if _MSC_VER > 1400
-  #define FORMAT_STRING(p) _Printf_format_string_ p
- #else
-  #define FORMAT_STRING(p) __format_string p
- #endif
-#else
- #define FORMAT_STRING(p) p
-#endif
-
-#ifdef _MSC_VER
-  #define strdup	_strdup
-  #define sscanf	sscanf_s
-  #define setbuf(x, y) \
-	setvbuf((x), (y), _IONBF, 0)
-  #define fopen(x, y) \
-	fopen_safe((x), (y))
-  FILE *fopen_safe(const char *filename, const char* mode);
-#endif
-
-#if defined(_MSC_VER) || defined(__MINGW32__)
+#ifndef HAVE_STRLCAT
+ /*
+  * Macro that does the same thing as strlcat().
+  */
+ #if defined(_MSC_VER) || defined(__MINGW32__)
+  /*
+   * strncat_s() is supported at least back to Visual
+   * Studio 2005.
+   */
   #define strlcat(x, y, z) \
 	strncat_s((x), (z), (y), _TRUNCATE)
+ #else
+  /*
+   * ANSI C says strncat() always null-terminates its first argument,
+   * so 1) we don't need to explicitly null-terminate the string
+   * ourselves and 2) we need to leave room for the null terminator.
+   */
+  #define strlcat(x, y, z) \
+	strncat((x), (y), (z) - strlen((x)) - 1)
+ #endif
 #endif
 
 #ifdef _MSC_VER
   /*
-   * MSVC.
+   * 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.
    */
-  #if _MSC_VER >= 1900
-    /*
-     * VS 2015 or newer; we have snprintf() function.
-     */
-    #define HAVE_SNPRINTF
+  #ifndef strdup
+  #define strdup	_strdup
   #endif
 #endif
 
@@ -129,11 +124,8 @@
 #ifdef HAVE_SNPRINTF
 #define pcap_snprintf snprintf
 #else
-extern int pcap_snprintf(char *, size_t, FORMAT_STRING(const char *), ...)
-#ifdef __ATTRIBUTE___FORMAT_OK
-    __attribute__((format (printf, 3, 4)))
-#endif /* __ATTRIBUTE___FORMAT_OK */
-    ;
+extern int pcap_snprintf(char *, size_t, PCAP_FORMAT_STRING(const char *), ...)
+    PCAP_PRINTFLIKE(3, 4);
 #endif
 
 #ifdef HAVE_VSNPRINTF
@@ -145,7 +137,7 @@
 #ifdef HAVE_STRTOK_R
   #define pcap_strtok_r	strtok_r
 #else
-  #ifdef _MSC_VER
+  #ifdef _WIN32
     /*
      * Microsoft gives it a different name.
      */
@@ -155,55 +147,11 @@
      * Define it ourselves.
      */
     #define NEED_STRTOK_R
-    extern int pcap_strtok_r(char *, const char *, char **);
+    extern char *pcap_strtok_r(char *, const char *, char **);
   #endif
 #endif /* HAVE_STRTOK_R */
 
 #ifdef _WIN32
-  /*
-   * These may be defined by <inttypes.h>.
-   *
-   * XXX - for MSVC, we always want the _MSC_EXTENSIONS versions.
-   * What about other compilers?  If, as the MinGW Web site says MinGW
-   * does, the other compilers just use Microsoft's run-time library,
-   * then they should probably use the _MSC_EXTENSIONS even if the
-   * compiler doesn't define _MSC_EXTENSIONS.
-   *
-   * XXX - we currently aren't using any of these, but this allows
-   * their use in the future.
-   */
-  #ifndef PRId64
-    #ifdef _MSC_EXTENSIONS
-      #define PRId64	"I64d"
-    #else
-      #define PRId64	"lld"
-    #endif
-  #endif /* PRId64 */
-
-  #ifndef PRIo64
-    #ifdef _MSC_EXTENSIONS
-      #define PRIo64	"I64o"
-    #else
-      #define PRIo64	"llo"
-    #endif
-  #endif /* PRIo64 */
-
-  #ifndef PRIx64
-    #ifdef _MSC_EXTENSIONS
-      #define PRIx64	"I64x"
-    #else
-      #define PRIx64	"llx"
-    #endif
-  #endif
-
-  #ifndef PRIu64
-    #ifdef _MSC_EXTENSIONS
-      #define PRIu64	"I64u"
-    #else
-      #define PRIu64	"llu"
-    #endif
-  #endif
-
   #if !defined(__cplusplus)
     #define inline __inline
   #endif
diff --git a/remote-ext.h b/remote-ext.h
deleted file mode 100644
index ed2f9bb..0000000
--- a/remote-ext.h
+++ /dev/null
@@ -1,467 +0,0 @@
-/*
- * Copyright (c) 2002 - 2003
- * NetGroup, Politecnico di Torino (Italy)
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- * 3. Neither the name of the Politecnico di Torino nor the names of its
- * contributors may be used to endorse or promote products derived from
- * this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
- */
-
-
-#ifndef __REMOTE_EXT_H__
-#define __REMOTE_EXT_H__
-
-
-#ifndef HAVE_REMOTE
-#error Please do not include this file directly. Just define HAVE_REMOTE and then include pcap.h
-#endif
-
-/*// Definition for Microsoft Visual Studio */
-#if _MSC_VER > 1000
-#pragma once
-#endif
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-/*
- * \file remote-ext.h
- *
- * The goal of this file it to include most of the new definitions that should be
- * placed into the pcap.h file.
- *
- * It includes all new definitions (structures and functions like pcap_open().
- * Some of the functions are not really a remote feature, but, right now,
- * they are placed here.
- */
-
-
-
-/*// All this stuff is public */
-/*
- * \addtogroup remote_struct
- * \{
- */
-
-
-
-
-/*
- * \brief Defines the maximum buffer size in which address, port, interface names are kept.
- *
- * In case the adapter name or such is larger than this value, it is truncated.
- * This is not used by the user; however it must be aware that an hostname / interface
- * name longer than this value will be truncated.
- */
-#define PCAP_BUF_SIZE 1024
-
-
-/*
- * \addtogroup remote_source_ID
- * \{
- */
-
-
-/*
- * \brief Internal representation of the type of source in use (file,
- * remote/local interface).
- *
- * This indicates a file, i.e. the user want to open a capture from a local file.
- */
-#define PCAP_SRC_FILE 2
-/*
- * \brief Internal representation of the type of source in use (file,
- * remote/local interface).
- *
- * This indicates a local interface, i.e. the user want to open a capture from
- * a local interface. This does not involve the RPCAP protocol.
- */
-#define PCAP_SRC_IFLOCAL 3
-/*
- * \brief Internal representation of the type of source in use (file,
- * remote/local interface).
- *
- * This indicates a remote interface, i.e. the user want to open a capture from
- * an interface on a remote host. This does involve the RPCAP protocol.
- */
-#define PCAP_SRC_IFREMOTE 4
-
-/*
- * \}
- */
-
-
-
-/* \addtogroup remote_source_string
- *
- * The formats allowed by the pcap_open() are the following:
- * - file://path_and_filename [opens a local file]
- * - rpcap://devicename [opens the selected device devices available on the local host, without using the RPCAP protocol]
- * - rpcap://host/devicename [opens the selected device available on a remote host]
- * - rpcap://host:port/devicename [opens the selected device available on a remote host, using a non-standard port for RPCAP]
- * - adaptername [to open a local adapter; kept for compability, but it is strongly discouraged]
- * - (NULL) [to open the first local adapter; kept for compability, but it is strongly discouraged]
- *
- * The formats allowed by the pcap_findalldevs_ex() are the following:
- * - file://folder/ [lists all the files in the given folder]
- * - rpcap:// [lists all local adapters]
- * - rpcap://host:port/ [lists the devices available on a remote host]
- *
- * Referring to the 'host' and 'port' parameters, they can be either numeric or literal. Since
- * IPv6 is fully supported, these are the allowed formats:
- *
- * - host (literal): e.g. host.foo.bar
- * - host (numeric IPv4): e.g. 10.11.12.13
- * - host (numeric IPv4, IPv6 style): e.g. [10.11.12.13]
- * - host (numeric IPv6): e.g. [1:2:3::4]
- * - port: can be either numeric (e.g. '80') or literal (e.g. 'http')
- *
- * Here you find some allowed examples:
- * - rpcap://host.foo.bar/devicename [everything literal, no port number]
- * - rpcap://host.foo.bar:1234/devicename [everything literal, with port number]
- * - rpcap://10.11.12.13/devicename [IPv4 numeric, no port number]
- * - rpcap://10.11.12.13:1234/devicename [IPv4 numeric, with port number]
- * - rpcap://[10.11.12.13]:1234/devicename [IPv4 numeric with IPv6 format, with port number]
- * - rpcap://[1:2:3::4]/devicename [IPv6 numeric, no port number]
- * - rpcap://[1:2:3::4]:1234/devicename [IPv6 numeric, with port number]
- * - rpcap://[1:2:3::4]:http/devicename [IPv6 numeric, with literal port number]
- *
- * \{
- */
-
-
-/*
- * \brief String that will be used to determine the type of source in use (file,
- * remote/local interface).
- *
- * This string will be prepended to the interface name in order to create a string
- * that contains all the information required to open the source.
- *
- * This string indicates that the user wants to open a capture from a local file.
- */
-#define PCAP_SRC_FILE_STRING "file://"
-/*
- * \brief String that will be used to determine the type of source in use (file,
- * remote/local interface).
- *
- * This string will be prepended to the interface name in order to create a string
- * that contains all the information required to open the source.
- *
- * This string indicates that the user wants to open a capture from a network interface.
- * This string does not necessarily involve the use of the RPCAP protocol. If the
- * interface required resides on the local host, the RPCAP protocol is not involved
- * and the local functions are used.
- */
-#define PCAP_SRC_IF_STRING "rpcap://"
-
-/*
- * \}
- */
-
-
-
-
-
-/*
- * \addtogroup remote_open_flags
- * \{
- */
-
-/*
- * \brief Defines if the adapter has to go in promiscuous mode.
- *
- * It is '1' if you have to open the adapter in promiscuous mode, '0' otherwise.
- * Note that even if this parameter is false, the interface could well be in promiscuous
- * mode for some other reason (for example because another capture process with
- * promiscuous mode enabled is currently using that interface).
- * On on Linux systems with 2.2 or later kernels (that have the "any" device), this
- * flag does not work on the "any" device; if an argument of "any" is supplied,
- * the 'promisc' flag is ignored.
- */
-#define PCAP_OPENFLAG_PROMISCUOUS		1
-
-/*
- * \brief Defines if the data transfer (in case of a remote
- * capture) has to be done with UDP protocol.
- *
- * If it is '1' if you want a UDP data connection, '0' if you want
- * a TCP data connection; control connection is always TCP-based.
- * A UDP connection is much lighter, but it does not guarantee that all
- * the captured packets arrive to the client workstation. Moreover,
- * it could be harmful in case of network congestion.
- * This flag is meaningless if the source is not a remote interface.
- * In that case, it is simply ignored.
- */
-#define PCAP_OPENFLAG_DATATX_UDP			2
-
-
-/*
- * \brief Defines if the remote probe will capture its own generated traffic.
- *
- * In case the remote probe uses the same interface to capture traffic and to send
- * data back to the caller, the captured traffic includes the RPCAP traffic as well.
- * If this flag is turned on, the RPCAP traffic is excluded from the capture, so that
- * the trace returned back to the collector is does not include this traffic.
- */
-#define PCAP_OPENFLAG_NOCAPTURE_RPCAP	4
-
-/*
- * \brief Defines if the local adapter will capture its own generated traffic.
- *
- * This flag tells the underlying capture driver to drop the packets that were sent by itself.
- * This is useful when building applications like bridges, that should ignore the traffic
- * they just sent.
- */
-#define PCAP_OPENFLAG_NOCAPTURE_LOCAL	8
-
-/*
- * \brief This flag configures the adapter for maximum responsiveness.
- *
- * In presence of a large value for nbytes, WinPcap waits for the arrival of several packets before
- * copying the data to the user. This guarantees a low number of system calls, i.e. lower processor usage,
- * i.e. better performance, which is good for applications like sniffers. If the user sets the
- * PCAP_OPENFLAG_MAX_RESPONSIVENESS flag, the capture driver will copy the packets as soon as the application
- * is ready to receive them. This is suggested for real time applications (like, for example, a bridge)
- * that need the best responsiveness.
- */
-#define PCAP_OPENFLAG_MAX_RESPONSIVENESS	16
-
-/*
- * \}
- */
-
-
-/*
- * \addtogroup remote_samp_methods
- * \{
- */
-
-/*
- *\brief No sampling has to be done on the current capture.
- *
- * In this case, no sampling algorithms are applied to the current capture.
- */
-#define PCAP_SAMP_NOSAMP	0
-
-/*
- * \brief It defines that only 1 out of N packets must be returned to the user.
- *
- * In this case, the 'value' field of the 'pcap_samp' structure indicates the
- * number of packets (minus 1) that must be discarded before one packet got accepted.
- * In other words, if 'value = 10', the first packet is returned to the caller, while
- * the following 9 are discarded.
- */
-#define PCAP_SAMP_1_EVERY_N	1
-
-/*
- * \brief It defines that we have to return 1 packet every N milliseconds.
- *
- * In this case, the 'value' field of the 'pcap_samp' structure indicates the 'waiting
- * time' in milliseconds before one packet got accepted.
- * In other words, if 'value = 10', the first packet is returned to the caller; the next
- * returned one will be the first packet that arrives when 10ms have elapsed.
- */
-#define PCAP_SAMP_FIRST_AFTER_N_MS 2
-
-/*
- * \}
- */
-
-
-/*
- * \addtogroup remote_auth_methods
- * \{
- */
-
-/*
- * \brief It defines the NULL authentication.
- *
- * This value has to be used within the 'type' member of the pcap_rmtauth structure.
- * The 'NULL' authentication has to be equal to 'zero', so that old applications
- * can just put every field of struct pcap_rmtauth to zero, and it does work.
- */
-#define RPCAP_RMTAUTH_NULL 0
-/*
- * \brief It defines the username/password authentication.
- *
- * With this type of authentication, the RPCAP protocol will use the username/
- * password provided to authenticate the user on the remote machine. If the
- * authentication is successful (and the user has the right to open network devices)
- * the RPCAP connection will continue; otherwise it will be dropped.
- *
- * This value has to be used within the 'type' member of the pcap_rmtauth structure.
- */
-#define RPCAP_RMTAUTH_PWD 1
-
-/*
- * \}
- */
-
-
-
-
-/*
- * \brief This structure keeps the information needed to autheticate
- * the user on a remote machine.
- *
- * The remote machine can either grant or refuse the access according
- * to the information provided.
- * In case the NULL authentication is required, both 'username' and
- * 'password' can be NULL pointers.
- *
- * This structure is meaningless if the source is not a remote interface;
- * in that case, the functions which requires such a structure can accept
- * a NULL pointer as well.
- */
-struct pcap_rmtauth
-{
-	/*
-	 * \brief Type of the authentication required.
-	 *
-	 * In order to provide maximum flexibility, we can support different types
-	 * of authentication based on the value of this 'type' variable. The currently
-	 * supported authentication methods are defined into the
-	 * \link remote_auth_methods Remote Authentication Methods Section\endlink.
-	 */
-	int type;
-	/*
-	 * \brief Zero-terminated string containing the username that has to be
-	 * used on the remote machine for authentication.
-	 *
-	 * This field is meaningless in case of the RPCAP_RMTAUTH_NULL authentication
-	 * and it can be NULL.
-	 */
-	char *username;
-	/*
-	 * \brief Zero-terminated string containing the password that has to be
-	 * used on the remote machine for authentication.
-	 *
-	 * This field is meaningless in case of the RPCAP_RMTAUTH_NULL authentication
-	 * and it can be NULL.
-	 */
-	char *password;
-};
-
-
-/*
- * \brief This structure defines the information related to sampling.
- *
- * In case the sampling is requested, the capturing device should read
- * only a subset of the packets coming from the source. The returned packets depend
- * on the sampling parameters.
- *
- * \warning The sampling process is applied <strong>after</strong> the filtering process.
- * In other words, packets are filtered first, then the sampling process selects a
- * subset of the 'filtered' packets and it returns them to the caller.
- */
-struct pcap_samp
-{
-	/*
-	 * Method used for sampling. Currently, the supported methods are listed in the
-	 * \link remote_samp_methods Sampling Methods Section\endlink.
-	 */
-	int method;
-
-	/*
-	 * This value depends on the sampling method defined. For its meaning, please check
-	 * at the \link remote_samp_methods Sampling Methods Section\endlink.
-	 */
-	int value;
-};
-
-
-
-
-// Maximum length of an host name (needed for the RPCAP active mode)
-#define RPCAP_HOSTLIST_SIZE 1024
-
-
-/*
- * \}
- */ // end of public documentation
-
-
-// Exported functions
-
-
-
-/*
- * \name New WinPcap functions
- *
- * This section lists the new functions that are able to help considerably in writing
- * WinPcap programs because of their easiness of use.
- */
-// \{
-PCAP_API pcap_t *pcap_open(const char *source, int snaplen, int flags, int read_timeout, struct pcap_rmtauth *auth, char *errbuf);
-PCAP_API int pcap_createsrcstr(char *source, int type, const char *host, const char *port, const char *name, char *errbuf);
-PCAP_API int pcap_parsesrcstr(const char *source, int *type, char *host, char *port, char *name, char *errbuf);
-PCAP_API int pcap_findalldevs_ex(char *source, struct pcap_rmtauth *auth, pcap_if_t **alldevs, char *errbuf);
-PCAP_API struct pcap_samp *pcap_setsampling(pcap_t *p);
-
-// \}
-// End of new WinPcap functions
-
-/*
- * \name Remote Capture functions
- */
-
-/*
- * Some minor differences between UN*X sockets and and Winsock sockets.
- */
-#ifndef _WIN32
-  /*!
-   * \brief In Winsock, a socket handle is of type SOCKET; in UN*X, it's
-   * a file descriptor, and therefore a signed integer.
-   * We define SOCKET to be a signed integer on UN*X, so that it can
-   * be used on both platforms.
-   */
-  #define SOCKET int
-
-  /*!
-   * \brief In Winsock, the error return if socket() fails is INVALID_SOCKET;
-   * in UN*X, it's -1.
-   * We define INVALID_SOCKET to be -1 on UN*X, so that it can be used on
-   * both platforms.
-   */
-  #define INVALID_SOCKET -1
-#endif
-
-// \{
-PCAP_API SOCKET pcap_remoteact_accept(const char *address, const char *port, const char *hostlist, char *connectinghost, struct pcap_rmtauth *auth, char *errbuf);
-PCAP_API int pcap_remoteact_list(char *hostlist, char sep, int size, char *errbuf);
-PCAP_API int pcap_remoteact_close(const char *host, char *errbuf);
-PCAP_API void pcap_remoteact_cleanup();
-// \}
-// End of remote capture functions
-
-#ifdef __cplusplus
-}
-#endif
-
-
-#endif
-
diff --git a/rpcap-protocol.c b/rpcap-protocol.c
new file mode 100644
index 0000000..692f7c5
--- /dev/null
+++ b/rpcap-protocol.c
@@ -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
index 0000000..83ebdc5
--- /dev/null
+++ b/rpcap-protocol.h
@@ -0,0 +1,450 @@
+/*
+ * 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 the version number
+ * in the request being the maximum version it supports.
+ *
+ * If the server supports that version, it attempts to authenticate the
+ * client, and replies as appropriate, with the version number in the
+ * reply being that version.
+ *
+ * If the server doesn't support that version because it's too large,
+ * it replies with a RPCAP_MSG_ERROR message, with the maximum version
+ * they support as the version number in the reply, and with the error
+ * code being PCAP_ERR_WRONGVER.
+ *
+ * If the server doesn't support that version because it's too small,
+ * it replies with a RPCAP_MSG_ERROR message, with that version as
+ * the version number in the reply, and with the error code being
+ * PCAP_ERR_WRONGVER.
+ *
+ * If the client supports that version, it retries the authentication
+ * with that version and, if that fails for any reason, including
+ * PCAP_ERR_WRONGVER, fails.  Otherwise, it fails, telling its caller
+ * that there's no version that both support.
+ *
+ * This requires that the set of versions supported by a client or
+ * server be a range of integers, with no gaps.  Thus:
+ *
+ * the client's version set is [Cmin, Cmax], with Cmin <= Cmax;
+ *
+ * the server's version set is [Smin, Smax], with Smin <= Smax;
+ *
+ * the client sends Cmax as the version number in the initial
+ * authentication request;
+ *
+ * if the server doesn't support the version sent by the client,
+ * either Smax < Cmax or Smin > Cmax (because the client sent Cmax
+ * to the server, and the server doesn't support it);
+ *
+ * if Smax < Cmax:
+ *
+ *    the server sends Smax as the version number in the RPCAP_MSG_ERROR/
+ *    PCAP_ERR_WRONGVER message - the client will accept this because
+ *    Cmax != 0, as these numbers are unsigned, and this means that
+ *    this isn't an old client that rejects all messages with a non-zero
+ *    version number, it's a new client that accepts RPCAP_MSG_ERROR
+ *    messages no matter what the version is;
+ *
+ *    if Smax >= Cmin, both the client and the server can use it, and
+ *    the client retries with Smax;
+ *
+ *    if Smax < Cmin, there is no version the client and server can
+ *    both support.
+ *
+ * if Smin > Cmax:
+ *
+ *    the server sends Cmax as the version number in the RPCAP_MSG_ERROR/
+ *    PCAP_ERR_WRONGVER message - the client will accept this because
+ *    Cmax is a valid client version number.
+ *
+ *    the client will retry with Cmax, get the same version failure,
+ *    and report that there is no version the client and server can
+ *    both support (as the version sets are disjoint).
+ *
+ * Old negotiation-unaware clients just send version 0 and, if they
+ * get back PCAP_ERR_WRONGVER, treat it as a fatal error.  This
+ * means they'll fail to talk to any server that can't handle
+ * version 0, which is the appropriate thing to do, as they can
+ * only use version 0.
+ *
+ * Old negotiation-unaware servers fail if they get a version other
+ * than 0, sending back PCAP_ERR_WRONGVER with version 0, which is
+ * the only version, and thus both the minimum and maximum version,
+ * they support.  The client will either fail if it doesn't support
+ * version 0, or will retry with version 0 and succeed, so it will
+ * fail with servers that can't handle version 0 or will negotiate
+ * version 0 with servers that can handle version 0.
+ */
+#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.
+ */
+
+/*
+ * 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 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 */
+#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 */
+#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 */
+
+/*
+ * \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/.gitignore b/rpcapd/.gitignore
new file mode 100644
index 0000000..50c27ab
--- /dev/null
+++ b/rpcapd/.gitignore
@@ -0,0 +1,5 @@
+Makefile
+*~
+*.o
+rpcapd
+rpcapd.manadmin
diff --git a/rpcapd/CMakeLists.txt b/rpcapd/CMakeLists.txt
new file mode 100644
index 0000000..b3b16e3
--- /dev/null
+++ b/rpcapd/CMakeLists.txt
@@ -0,0 +1,118 @@
+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-stderr.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()
+
+  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)
+
+  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})
+  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
index 0000000..d3e02c1
--- /dev/null
+++ b/rpcapd/Makefile.in
@@ -0,0 +1,130 @@
+#  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) $(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-stderr.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
+
+rpcapd: $(OBJ) ../libpcap.a
+	$(CC) $(CCOPT) $(CFLAGS) $(LDFLAGS) -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=)
+	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@)
+	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
+
+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
+
+tags: $(TAGFILES)
+	ctags -wtd $(TAGFILES)
+
+depend:
+	../$(MKDEP) -c "$(CC)" -m "$(DEPENDENCY_CFLAG)" $(CFLAGS) $(DEFS) $(INCLS) $(SRC)
diff --git a/rpcapd/config_params.h b/rpcapd/config_params.h
new file mode 100644
index 0000000..c219ce1
--- /dev/null
+++ b/rpcapd/config_params.h
@@ -0,0 +1,56 @@
+/*
+ * 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 __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
+
+#endif
diff --git a/rpcapd/daemon.c b/rpcapd/daemon.c
new file mode 100644
index 0000000..4bf42fd
--- /dev/null
+++ b/rpcapd/daemon.c
@@ -0,0 +1,2554 @@
+/*
+ * 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 <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"
+
+#define RPCAP_TIMEOUT_INIT 90		/* Initial timeout for RPCAP connections (default: 90 sec) */
+#define RPCAP_TIMEOUT_RUNTIME 180	/* Run-time timeout for RPCAP connections (default: 3 min) */
+#define RPCAP_SUSPEND_WRONGAUTH 1	/* If the authentication is wrong, stops 1 sec before accepting a new auth message */
+
+// Parameters for the service loop.
+struct daemon_slpars
+{
+	SOCKET sockctrl_in;	//!< SOCKET ID of the input side of the control connection
+	SOCKET sockctrl_out;	//!< SOCKET ID of the output side of the control connection
+	uint8 protocol_version;	//!< negotiated protocol version
+	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.
+ */
+struct session {
+	SOCKET sockctrl_out;
+	SOCKET sockdata;
+	uint8 protocol_version;
+	pcap_t *fp;
+	unsigned int TotCapt;
+};
+
+//
+// Structure to refer to 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 thread_handle {
+	int	have_thread;
+#ifdef _WIN32
+	HANDLE thread;
+#else
+	pthread_t thread;
+#endif
+};
+
+// Locally defined functions
+static int daemon_msg_err(SOCKET sockctrl_in, 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(struct daemon_slpars *pars, uint32 plen);
+
+static int daemon_msg_open_req(struct daemon_slpars *pars, uint32 plen, char *source, size_t sourcelen);
+static int daemon_msg_startcap_req(struct daemon_slpars *pars, uint32 plen, struct thread_handle *threaddata, char *source, struct session **sessionp, struct rpcap_sampling *samp_param);
+static int daemon_msg_endcap_req(struct daemon_slpars *pars, struct session *session, struct thread_handle *threaddata);
+
+static int daemon_msg_updatefilter_req(struct daemon_slpars *pars, struct session *session, uint32 plen);
+static int daemon_unpackapplyfilter(SOCKET sockctrl_in, struct session *session, uint32 *plenp, char *errbuf);
+
+static int daemon_msg_stats_req(struct daemon_slpars *pars, struct session *session, uint32 plen, struct pcap_stat *stats, unsigned int svrcapt);
+
+static int daemon_msg_setsampling_req(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);
+#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);
+
+int
+daemon_serviceloop(SOCKET sockctrl_in, SOCKET sockctrl_out, int isactive, 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 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
+	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
+
+	struct thread_handle threaddata;	// 'read from daemon and send to client' thread
+
+	// 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
+
+	// Set parameters structure
+	pars.sockctrl_in = sockctrl_in;
+	pars.sockctrl_out = sockctrl_out;
+	pars.protocol_version = 0;		// not yet known
+	pars.isactive = isactive;		// active mode
+	pars.nullAuthAllowed = nullAuthAllowed;
+
+	// We don't have a thread yet.
+	threaddata.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
+	threaddata.thread = INVALID_HANDLE_VALUE;
+#else
+	memset(&threaddata.thread, 0, sizeof(threaddata.thread));
+#endif
+
+	*errbuf = 0;	// Initialize errbuf
+
+	//
+	// 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 in active mode, we have to check for the
+		// initial timeout.
+		//
+		// XXX - do this on *every* trip through the loop?
+		//
+		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_in, &rfds);
+
+			retval = select(pars.sockctrl_in + 1, &rfds, NULL, NULL, &tv);
+			if (retval == -1)
+			{
+				sock_geterror("select failed: ", errmsgbuf, PCAP_ERRBUF_SIZE);
+				if (rpcap_senderror(pars.sockctrl_out, 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_out, 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_in, &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 version we can handle?
+		//
+		if (!RPCAP_VERSION_IS_SUPPORTED(header.ver))
+		{
+			//
+			// Tell them it's not a valid protocol version.
+			//
+			uint8 reply_version;
+
+			//
+			// If RPCAP_MIN_VERSION is 0, no version is too
+			// old, as the oldest supported version is 0,
+			// and there are no negative versions.
+			//
+#if RPCAP_MIN_VERSION != 0
+			if (header.ver < RPCAP_MIN_VERSION)
+			{
+				//
+				// Their maximum version is too old;
+				// there *is* no version we can both
+				// handle, and they might reject
+				// an error with a version they don't
+				// understand, so reply with the
+				// version they sent.  That may
+				// make them retry with that version,
+				// but they'll give up on that
+				// failure.
+				//
+				reply_version = header.ver;
+			}
+			else
+#endif
+			{
+				//
+				// Their maximum version is too new,
+				// but they might be able to handle
+				// *our* maximum version, so reply
+				// with that version.
+				//
+				reply_version = RPCAP_MAX_VERSION;
+			}
+			if (rpcap_senderror(pars.sockctrl_out, reply_version,
+			    PCAP_ERR_WRONGVER, "RPCAP version number mismatch",
+			    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.
+			if (rpcapd_discard(pars.sockctrl_in, plen) == -1)
+			{
+				// Network error.
+				goto end;
+			}
+
+			// Let them try again.
+			continue;
+		}
+
+		//
+		// OK, we use the version the client specified.
+		//
+		pars.protocol_version = header.ver;
+
+		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_in, 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_in, 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_out,
+				    pars.protocol_version, 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_in, 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_out,
+				    pars.protocol_version, 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_in, 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_out,
+				    pars.protocol_version, 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_in, 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_in, &rfds);
+
+			retval = select(pars.sockctrl_in + 1, &rfds, NULL, NULL, &tv);
+			if (retval == -1)
+			{
+				sock_geterror("select failed: ", errmsgbuf, PCAP_ERRBUF_SIZE);
+				if (rpcap_senderror(pars.sockctrl_out,
+				    pars.protocol_version, 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_out,
+				    pars.protocol_version,
+				    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_in, &header);
+		if (nrecv == -1)
+		{
+			// Fatal error.
+			goto end;
+		}
+		if (nrecv == -2)
+		{
+			// Client closed the connection.
+			goto end;
+		}
+
+		plen = header.plen;
+
+		//
+		// Did the client specify the version we negotiated?
+		//
+		// For now, there's only one version.
+		//
+		if (header.ver != pars.protocol_version)
+		{
+			//
+			// Tell them it's not the negotiated version.
+			// Send the error message with their version,
+			// so they don't reject it as having the wrong
+			// version.
+			//
+			if (rpcap_senderror(pars.sockctrl_out,
+			    header.ver, PCAP_ERR_WRONGVER,
+			    "RPCAP version in message isn't the negotiated version",
+			    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_in, 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_in, 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(&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(&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_out,
+					    pars.protocol_version,
+					    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_in, plen) == -1)
+					{
+						goto end;
+					}
+					break;
+				}
+
+				if (daemon_msg_startcap_req(&pars, plen, &threaddata, 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(&pars, session, plen) == -1)
+					{
+						// Fatal error; a message has
+						// been logged, so just give up.
+						goto end;
+					}
+				}
+				else
+				{
+					if (rpcap_senderror(pars.sockctrl_out,
+					    pars.protocol_version,
+					    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;
+				SOCK_DEBUG_MESSAGE("The other end system asked to close the connection.");
+				goto end;
+			}
+
+			case RPCAP_MSG_STATS_REQ:
+			{
+				if (daemon_msg_stats_req(&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(&pars, session, &threaddata) == -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_out,
+					    pars.protocol_version,
+					    PCAP_ERR_ENDCAPTURE,
+					    "Device not opened. Cannot close the capture",
+					    errbuf);
+				}
+				break;
+			}
+
+			case RPCAP_MSG_SETSAMPLING_REQ:
+			{
+				if (daemon_msg_setsampling_req(&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_out,
+				    pars.protocol_version,
+				    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_in, 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_out,
+				    pars.protocol_version, 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_in, 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_out,
+				    pars.protocol_version, 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_in, plen) == -1)
+				{
+					// Fatal error.
+					goto end;
+				}
+				goto end;
+			}
+		}
+	}
+
+end:
+	// The child thread is about to end
+
+	// perform pcap_t cleanup, in case it has not been done
+	if (session)
+	{
+		if (threaddata.have_thread)
+		{
+#ifdef _WIN32
+			//
+			// Tell the data connection thread main capture
+			// loop to break out of that loop.
+			//
+			pcap_breakloop(session->fp);
+
+			//
+			// If it's currently blocked waiting for packets
+			// to arrive, try to wake it up, so it can see
+			// the "break out of the loop" indication.
+			//
+			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(threaddata.thread, INFINITE);
+
+			//
+			// Release the thread handle, as we're done with
+			// it.
+			//
+			CloseHandle(threaddata.thread);
+#else
+			pthread_cancel(threaddata.thread);
+#endif
+			threaddata.have_thread = 0;
+		}
+		if (session->sockdata)
+		{
+			sock_close(session->sockdata, NULL, 0);
+			session->sockdata = 0;
+		}
+		pcap_close(session->fp);
+		free(session);
+		session = NULL;
+	}
+
+	// Print message and return
+	SOCK_DEBUG_MESSAGE("I'm exiting from the child loop");
+	SOCK_DEBUG_MESSAGE(errbuf);
+
+	return client_told_us_to_close;
+}
+
+/*
+ * This handles the RPCAP_MSG_ERR message.
+ */
+static int
+daemon_msg_err(SOCKET sockctrl_in, 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_in, 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_in, 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_in, 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
+	struct rpcap_header header;		// RPCAP message general header
+	int status;
+	struct rpcap_auth auth;			// RPCAP authentication header
+
+	status = rpcapd_recv(pars->sockctrl_in, (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.");
+				goto error;
+			}
+			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_in, 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_in, 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_out,
+				    pars->protocol_version,
+				    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;
+				}
+
+				//
+				// 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.");
+			goto error;
+	}
+
+	// The authentication succeeded; let the client know.
+	rpcap_createhdr(&header, pars->protocol_version, RPCAP_MSG_AUTH_REPLY, 0, 0);
+
+	// Send the ok message back
+	if (sock_send(pars->sockctrl_out, (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;
+	}
+
+	// Check if all the data has been read; if not, discard the data in excess
+	if (rpcapd_discard(pars->sockctrl_in, plen) == -1)
+	{
+		return -1;
+	}
+
+	return 0;
+
+error:
+	if (rpcap_senderror(pars->sockctrl_out, pars->protocol_version,
+	    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_in, 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.
+	 */
+	HANDLE Token;
+	if (LogonUser(username, ".", password, LOGON32_LOGON_NETWORK, LOGON32_PROVIDER_DEFAULT, &Token) == 0)
+	{
+		int error;
+
+		error = GetLastError();
+		FormatMessageA(FORMAT_MESSAGE_FROM_SYSTEM, NULL, error, 0, errbuf,
+			PCAP_ERRBUF_SIZE, NULL);
+
+		return -1;
+	}
+
+	// This call should change the current thread to the selected user.
+	// I didn't test it.
+	if (ImpersonateLoggedOnUser(Token) == 0)
+	{
+		int error;
+
+		error = GetLastError();
+		FormatMessageA(FORMAT_MESSAGE_FROM_SYSTEM, NULL, error, 0, errbuf,
+			PCAP_ERRBUF_SIZE, NULL);
+
+		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.
+	 */
+	struct passwd *user;
+	char *user_password;
+#ifdef HAVE_GETSPNAM
+	struct spwd *usersp;
+#endif
+
+	// This call is needed to get the uid
+	if ((user = getpwnam(username)) == NULL)
+	{
+		pcap_snprintf(errbuf, PCAP_ERRBUF_SIZE, "Authentication failed: no such user");
+		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: no such user");
+		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
+
+	if (strcmp(user_password, (char *) crypt(password, user_password)) != 0)
+	{
+		pcap_snprintf(errbuf, PCAP_ERRBUF_SIZE, "Authentication failed: password incorrect");
+		return -1;
+	}
+
+	if (setuid(user->pw_uid))
+	{
+		pcap_fmt_errmsg_for_errno(errbuf, PCAP_ERRBUF_SIZE,
+		    errno, "setuid");
+		return -1;
+	}
+
+/*	if (setgid(user->pw_gid))
+	{
+		pcap_fmt_errmsg_for_errno(errbuf, PCAP_ERRBUF_SIZE,
+		    errno, "setgid");
+		return -1;
+	}
+*/
+	return 0;
+
+#endif
+
+}
+
+static int
+daemon_msg_findallif_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
+	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
+	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_in, 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_out, pars->protocol_version,
+			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;
+	}
+
+	// checks the number of interfaces and it computes the total length of the payload
+	for (d = alldevs; d != NULL; d = d->next)
+	{
+		nif++;
+
+		if (d->description)
+			plen+= strlen(d->description);
+		if (d->name)
+			plen+= strlen(d->name);
+
+		plen+= 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
+				plen+= (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, pars->protocol_version,
+	    RPCAP_MSG_FINDALLIF_REPLY, nif, plen);
+
+	// 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_out, 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_out, pars->protocol_version,
+	    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(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_in, 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;
+
+	// XXX - make sure it's *not* a URL; we don't support opening
+	// remote devices here.
+
+	// 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, pars->protocol_version,
+	    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_out, 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_out, pars->protocol_version,
+	    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_in, 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(struct daemon_slpars *pars, uint32 plen, struct thread_handle *threaddata, 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
+	SOCKET sockdata = INVALID_SOCKET;	// socket descriptor of the data connection
+	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
+
+#ifndef _WIN32
+	pthread_attr_t detachedAttribute;	// temp, needed to set the created thread as detached
+#endif
+
+	// 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_in, (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;
+	}
+
+	// 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_in, (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 ((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 ((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(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_out = pars->sockctrl_out;
+	session->protocol_version = pars->protocol_version;
+
+	// Now I can set the filter
+	ret = daemon_unpackapplyfilter(pars->sockctrl_in, 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, pars->protocol_version,
+	    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_out, 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(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(sockdata, NULL, 0);
+		sockdata = socktemp;
+	}
+
+	session->sockdata = sockdata;
+
+	// Now we have to create a new thread to receive packets
+#ifdef _WIN32
+	threaddata->thread = (HANDLE)_beginthreadex(NULL, 0, daemon_thrdatamain,
+	    (void *) session, 0, NULL);
+	if (threaddata->thread == 0)
+	{
+		pcap_snprintf(errbuf, PCAP_ERRBUF_SIZE, "Error creating the data thread");
+		goto error;
+	}
+#else
+	/* GV we need this to create the thread as detached. */
+	/* GV otherwise, the thread handle is not destroyed  */
+	pthread_attr_init(&detachedAttribute);
+	pthread_attr_setdetachstate(&detachedAttribute, PTHREAD_CREATE_DETACHED);
+	ret = pthread_create(&threaddata->thread, &detachedAttribute,
+	    daemon_thrdatamain, (void *) session);
+	if (ret != 0)
+	{
+		pcap_fmt_errmsg_for_errno(errbuf, PCAP_ERRBUF_SIZE,
+		    ret, "Error creating the data thread");
+		pthread_attr_destroy(&detachedAttribute);
+		goto error;
+	}
+	pthread_attr_destroy(&detachedAttribute);
+#endif
+	threaddata->have_thread = 1;
+
+	// Check if all the data has been read; if not, discard the data in excess
+	if (rpcapd_discard(pars->sockctrl_in, 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 (threaddata->have_thread)
+	{
+#ifdef _WIN32
+		if (session->fp)
+		{
+			pcap_breakloop(session->fp);
+			SetEvent(pcap_getevent(session->fp));
+		}
+		CloseHandle(threaddata->thread);
+#else
+		pthread_cancel(threaddata->thread);
+#endif
+		threaddata->have_thread = 0;
+	}
+
+	if (sockdata != INVALID_SOCKET)
+		sock_close(sockdata, NULL, 0);
+
+	if (session)
+	{
+		if (session->fp)
+			pcap_close(session->fp);
+		free(session);
+	}
+
+	if (rpcap_senderror(pars->sockctrl_out, pars->protocol_version,
+	    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_in, 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 (threaddata->have_thread)
+	{
+#ifdef _WIN32
+		if (session && session->fp)
+		{
+			//
+			// Tell the data connection thread main capture
+			// loop to break out of that loop.
+			//
+			pcap_breakloop(session->fp);
+
+			//
+			// If it's currently blocked waiting for packets
+			// to arrive, try to wake it up, so it can see
+			// the "break out of the loop" indication.
+			//
+			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(threaddata->thread, INFINITE);
+
+		//
+		// Release the thread handle, as we're done with
+		// it.
+		//
+		CloseHandle(threaddata->thread);
+#else
+		pthread_cancel(threaddata->thread);
+#endif
+		threaddata->have_thread = 0;
+	}
+
+	if (sockdata != INVALID_SOCKET)
+		sock_close(sockdata, NULL, 0);
+
+	if (session)
+	{
+		if (session->fp)
+			pcap_close(session->fp);
+		free(session);
+	}
+
+	return -1;
+}
+
+static int
+daemon_msg_endcap_req(struct daemon_slpars *pars, struct session *session, struct thread_handle *threaddata)
+{
+	char errbuf[PCAP_ERRBUF_SIZE];		// buffer for network errors
+	struct rpcap_header header;
+
+	if (threaddata->have_thread)
+	{
+#ifdef _WIN32
+		//
+		// Tell the data connection thread main capture loop to
+		// break out of that loop.
+		//
+		pcap_breakloop(session->fp);
+
+		//
+		// If it's currently blocked waiting for packets to
+		// arrive, try to wake it up, so it can see the "break
+		// out of the loop" indication.
+		//
+		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(threaddata->thread, INFINITE);
+
+		//
+		// Release the thread handle, as we're done with
+		// it.
+		//
+		CloseHandle(threaddata->thread);
+#else
+		pthread_cancel(threaddata->thread);
+#endif
+		threaddata->have_thread = 0;
+	}
+	if (session->sockdata)
+	{
+		sock_close(session->sockdata, NULL, 0);
+		session->sockdata = 0;
+	}
+
+	pcap_close(session->fp);
+
+	rpcap_createhdr(&header, pars->protocol_version,
+	    RPCAP_MSG_ENDCAP_REPLY, 0, 0);
+
+	if (sock_send(pars->sockctrl_out, (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;
+}
+
+static int
+daemon_unpackapplyfilter(SOCKET sockctrl_in, 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_in, (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;
+	}
+
+	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_in, (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(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_in, 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_in, plen) == -1)
+	{
+		// Network error.
+		return -1;
+	}
+
+	// A response is needed, otherwise the other host does not know that everything went well
+	rpcap_createhdr(&header, pars->protocol_version,
+	    RPCAP_MSG_UPDATEFILTER_REPLY, 0, 0);
+
+	if (sock_send(pars->sockctrl_out, (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_in, plen) == -1)
+	{
+		return -1;
+	}
+	rpcap_senderror(pars->sockctrl_out, pars->protocol_version,
+	    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(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_in, (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, pars->protocol_version,
+	    RPCAP_MSG_SETSAMPLING_REPLY, 0, 0);
+
+	if (sock_send(pars->sockctrl_out, (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_in, plen) == -1)
+	{
+		return -1;
+	}
+
+	return 0;
+
+error:
+	if (rpcap_senderror(pars->sockctrl_out, pars->protocol_version,
+	    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;
+	}
+
+	// Check if all the data has been read; if not, discard the data in excess
+	if (rpcapd_discard(pars->sockctrl_in, plen) == -1)
+	{
+		return -1;
+	}
+
+	return 0;
+}
+
+static int
+daemon_msg_stats_req(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_in, 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, pars->protocol_version,
+	    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_out, 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_out, pars->protocol_version,
+	    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;
+
+	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
+	// Modify thread params so that it can be killed at any time
+	retval = pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, NULL);
+	if (retval != 0)
+	{
+		pcap_fmt_errmsg_for_errno(errbuf, PCAP_ERRBUF_SIZE,
+		    retval, "pthread_setcancelstate");
+		rpcapd_log(LOGPRIO_ERROR,
+		    "Can't set cancel state on data thread: %s", errbuf);
+		goto error;
+	}
+	retval = pthread_setcanceltype(PTHREAD_CANCEL_ASYNCHRONOUS, NULL);
+	if (retval != 0)
+	{
+		pcap_fmt_errmsg_for_errno(errbuf, PCAP_ERRBUF_SIZE,
+		    retval, "pthread_setcanceltype");
+		rpcapd_log(LOGPRIO_ERROR,
+		    "Can't set cancel type on data thread: %s", errbuf);
+		goto error;
+	}
+#endif
+
+	// Retrieve the packets
+	while ((retval = pcap_next_ex(session->fp, &pkt_header, (const u_char **) &pkt_data)) >= 0)	// cast to avoid a compiler warning
+	{
+		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 == -1)
+	{
+		pcap_snprintf(errbuf, PCAP_ERRBUF_SIZE, "Error reading the packets: %s", pcap_geterr(session->fp));
+		rpcap_senderror(session->sockctrl_out, session->protocol_version,
+		    PCAP_ERR_READEX, errbuf, NULL);
+		goto error;
+	}
+
+error:
+ 	closesocket(session->sockdata);
+	session->sockdata = 0;
+
+	free(sendbuf);
+
+	return 0;
+}
+
+/*!
+	\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;
+}
diff --git a/rpcapd/daemon.h b/rpcapd/daemon.h
new file mode 100644
index 0000000..bd240b8
--- /dev/null
+++ b/rpcapd/daemon.h
@@ -0,0 +1,45 @@
+/*
+ * 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; used in active mode only.
+//
+int daemon_serviceloop(SOCKET sockctrl_in, SOCKET sockctrl_out, int isactive,
+    int nullAuthAllowed);
+
+void sleep_secs(int secs);
+
+#endif
diff --git a/rpcapd/fileconf.c b/rpcapd/fileconf.c
new file mode 100644
index 0000000..ab1e9dd
--- /dev/null
+++ b/rpcapd/fileconf.c
@@ -0,0 +1,216 @@
+/*
+ * 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 <signal.h>
+#include <pcap.h>		// for PCAP_ERRBUF_SIZE
+
+#include "sockutils.h"		// for SOCK_DEBUG_MESSAGE
+#include "portability.h"
+#include "rpcapd.h"
+#include "config_params.h"	// configuration file parameters
+#include "fileconf.h"
+#include "rpcap-protocol.h"
+
+static int strrem(char *string, char chr);
+
+void fileconf_read(void)
+{
+	FILE *fp;
+	char msg[PCAP_ERRBUF_SIZE + 1];
+	int i;
+
+	if ((fp = fopen(loadfile, "r")) != NULL)
+	{
+		char line[MAX_LINE + 1];
+		char *ptr;
+
+		hostlist[0] = 0;
+		i = 0;
+
+		while (fgets(line, MAX_LINE, fp) != NULL)
+		{
+			if (line[0] == '\n') continue;	// Blank line
+			if (line[0] == '\r') continue;	// Blank line
+			if (line[0] == '#') continue;	// Comment
+
+			ptr = strstr(line, "ActiveClient");
+			if (ptr)
+			{
+				char *address, *port;
+				char *lasts;
+
+				ptr = strchr(ptr, '=') + 1;
+				address = pcap_strtok_r(ptr, RPCAP_HOSTLIST_SEP, &lasts);
+
+				if ((address != NULL) && (i < MAX_ACTIVE_LIST))
+				{
+					port = pcap_strtok_r(NULL, RPCAP_HOSTLIST_SEP, &lasts);
+					strlcpy(activelist[i].address, address, MAX_LINE);
+
+					if (strcmp(port, "DEFAULT") == 0) // the user choose a custom port
+						strlcpy(activelist[i].port, RPCAP_DEFAULT_NETPORT_ACTIVE, MAX_LINE);
+					else
+						strlcpy(activelist[i].port, port, MAX_LINE);
+
+					activelist[i].address[MAX_LINE] = 0;
+					activelist[i].port[MAX_LINE] = 0;
+				}
+				else
+					SOCK_DEBUG_MESSAGE("Only MAX_ACTIVE_LIST active connections are currently supported.");
+
+				i++;
+				continue;
+			}
+
+			ptr = strstr(line, "PassiveClient");
+			if (ptr)
+			{
+				ptr = strchr(ptr, '=') + 1;
+				strlcat(hostlist, ptr, MAX_HOST_LIST);
+				strlcat(hostlist, ",", MAX_HOST_LIST);
+				continue;
+			}
+
+			ptr = strstr(line, "NullAuthPermit");
+			if (ptr)
+			{
+				ptr = strstr(ptr, "YES");
+				if (ptr)
+					nullAuthAllowed = 1;
+				else
+					nullAuthAllowed = 0;
+				continue;
+			}
+		}
+
+		// clear the remaining fields of the active list
+		while (i < MAX_ACTIVE_LIST)
+		{
+			activelist[i].address[0] = 0;
+			activelist[i].port[0] = 0;
+			i++;
+		}
+
+		// Remove all '\n' and '\r' from the strings
+		strrem(hostlist, '\r');
+		strrem(hostlist, '\n');
+
+		pcap_snprintf(msg, PCAP_ERRBUF_SIZE, "New passive host list: %s\n\n", hostlist);
+		SOCK_DEBUG_MESSAGE(msg);
+		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, "PassiveClient = %s\n", 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, "ActiveClient = %s, %s\n", 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 NOT\n\n");
+
+		if (nullAuthAllowed)
+			fprintf(fp, "NullAuthPermit = YES\n");
+		else
+			fprintf(fp, "NullAuthPermit = NO\n");
+
+		fclose(fp);
+		return 0;
+	}
+	else
+	{
+		return -1;
+	}
+
+}
+
+static int strrem(char *string, char chr)
+{
+	char *pos;
+	int num = 0;
+	int len, i;
+
+	while ((pos = strchr(string, chr)) != NULL)
+	{
+		num++;
+		len = strlen(pos);
+		for (i = 0; i < len; i++)
+			pos[i] = pos[i+1];
+	}
+
+	return num;
+}
diff --git a/rpcapd/fileconf.h b/rpcapd/fileconf.h
new file mode 100644
index 0000000..912dd32
--- /dev/null
+++ b/rpcapd/fileconf.h
@@ -0,0 +1,39 @@
+/*
+ * 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 __FILECONF_H__
+#define __FILECONF_H__
+
+void fileconf_read(void);
+int fileconf_save(const char *savefile);
+
+#endif
diff --git a/rpcapd/log-stderr.c b/rpcapd/log-stderr.c
new file mode 100644
index 0000000..5af6f2e
--- /dev/null
+++ b/rpcapd/log-stderr.c
@@ -0,0 +1,41 @@
+#include <stdio.h>
+#include <stdarg.h>
+#include <stdlib.h>
+#include "log.h"
+
+void
+rpcapd_log_init(void)
+{
+}
+
+void
+rpcapd_log(log_priority priority, const char *message, ...)
+{
+	const char *tag;
+	va_list ap;
+
+	switch (priority) {
+
+	case LOGPRIO_INFO:
+		tag = "";
+		break;
+
+	case LOGPRIO_WARNING:
+		tag = "warning: ";
+		break;
+
+	case LOGPRIO_ERROR:
+		tag = "error: ";
+		break;
+
+	default:
+		abort();
+		/* NOTREACHED */
+	}
+
+	fprintf(stderr, "rpcapd: %s", tag);
+	va_start(ap, message);
+	vfprintf(stderr, message, ap);
+	va_end(ap);
+	putc('\n', stderr);
+}
diff --git a/rpcapd/log.h b/rpcapd/log.h
new file mode 100644
index 0000000..b3806e1
--- /dev/null
+++ b/rpcapd/log.h
@@ -0,0 +1,12 @@
+#include "pcap/funcattrs.h"
+
+extern void rpcapd_log_init(void);
+
+typedef enum {
+	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
index 0000000..db3223a
--- /dev/null
+++ b/rpcapd/org.tcpdump.rpcapd.plist
@@ -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.c b/rpcapd/rpcapd.c
new file mode 100644
index 0000000..e8b3b1d
--- /dev/null
+++ b/rpcapd/rpcapd.c
@@ -0,0 +1,1309 @@
+/*
+ * 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
+	"[-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
+	"  -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 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 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));
+
+	if (sock_init(errbuf, PCAP_ERRBUF_SIZE) == -1)
+	{
+		SOCK_DEBUG_MESSAGE(errbuf);
+		exit(-1);
+	}
+
+	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:dhip:4l:na:s:f:v")) != -1)
+	{
+		switch (retval)
+		{
+			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;
+				break;
+			case 'i':
+#ifdef _WIN32
+				printusage();
+				exit(1);
+#else
+				isrunbyinetd = 1;
+#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);
+
+					strlcpy(activelist[i].address, tmpaddress, MAX_LINE);
+
+					if ((tmpport == NULL) || (strcmp(tmpport, "DEFAULT") == 0)) // the user choose a custom port
+						strlcpy(activelist[i].port, RPCAP_DEFAULT_NETPORT_ACTIVE, MAX_LINE);
+					else
+						strlcpy(activelist[i].port, tmpport, MAX_LINE);
+
+					tmpaddress = pcap_strtok_r(NULL, RPCAP_HOSTLIST_SEP, &lasts);
+
+					i++;
+				}
+
+				if (i > MAX_ACTIVE_LIST)
+					SOCK_DEBUG_MESSAGE("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':
+				strlcpy(loadfile, optarg, MAX_LINE);
+				break;
+			case 's':
+				strlcpy(savefile, optarg, MAX_LINE);
+				break;
+			case 'h':
+				printusage();
+				exit(0);
+				break;
+			default:
+				exit(1);
+				break;
+		}
+	}
+
+#ifndef _WIN32
+	if (isdaemon && isrunbyinetd)
+	{
+		fprintf(stderr, "rpcapd: -d and -i can't be used together\n");
+		exit(1);
+	}
+#endif
+
+	if (savefile[0] && fileconf_save(savefile))
+		SOCK_DEBUG_MESSAGE("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(NULL, errbuf, PCAP_ERRBUF_SIZE);
+		rpcapd_log(LOGPRIO_ERROR, "Can't create state change event: %s",
+		    errbuf);
+		exit(2);
+	}
+
+	//
+	// Catch control signals.
+	//
+	if (!SetConsoleCtrlHandler(main_ctrl_event, TRUE))
+	{
+		sock_geterror(NULL, errbuf, PCAP_ERRBUF_SIZE);
+		rpcapd_log(LOGPRIO_ERROR, "Can't set control handler: %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.).
+		//
+		// Our standard input is the input side of a connection,
+		// and our standard output is the output side of a
+		// connection.
+		//
+		int sockctrl_in, sockctrl_out;
+		int devnull_fd;
+
+		//
+		// Duplicate the standard input and output, making them
+		// the input and output side of the control connection.
+		//
+		sockctrl_in = dup(0);
+		if (sockctrl_in == -1)
+		{
+			sock_geterror(NULL, errbuf, PCAP_ERRBUF_SIZE);
+			rpcapd_log(LOGPRIO_ERROR, "Can't dup standard input: %s",
+			    errbuf);
+			exit(2);
+		}
+		sockctrl_out = dup(1);
+		if (sockctrl_out == -1)
+		{
+			sock_geterror(NULL, errbuf, PCAP_ERRBUF_SIZE);
+			rpcapd_log(LOGPRIO_ERROR, "Can't dup standard output: %s",
+			    errbuf);
+			exit(2);
+		}
+
+		//
+		// Try to set the standard input and output 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);
+			close(devnull_fd);
+		}
+
+		//
+		// Handle this client.
+		// This is passive mode, so we don't care whether we were
+		// told by the client to close.
+		//
+		(void)daemon_serviceloop(sockctrl_in, sockctrl_out, 0,
+		    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)
+			SOCK_DEBUG_MESSAGE("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)
+		{
+			SOCK_DEBUG_MESSAGE("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)
+		{
+			SOCK_DEBUG_MESSAGE(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.
+	//
+	SOCK_DEBUG_MESSAGE(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(NULL, errbuf, PCAP_ERRBUF_SIZE);
+		rpcapd_log(LOGPRIO_ERROR, "SetEvent on shutdown event failed: %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)
+		SOCK_DEBUG_MESSAGE("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(NULL, errbuf, PCAP_ERRBUF_SIZE);
+			rpcapd_log(LOGPRIO_ERROR, "Can't create socket event: %s", errbuf);
+			exit(2);
+		}
+		if (WSAEventSelect(sock_info->sock, event, FD_ACCEPT) == SOCKET_ERROR)
+		{
+			sock_geterror(NULL, errbuf, PCAP_ERRBUF_SIZE);
+			rpcapd_log(LOGPRIO_ERROR, "Can't setup socket event: %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(NULL, errbuf, PCAP_ERRBUF_SIZE);
+			rpcapd_log(LOGPRIO_ERROR, "WSAWaitForMultipleEvents failed: %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(NULL, errbuf, PCAP_ERRBUF_SIZE);
+				rpcapd_log(LOGPRIO_ERROR, "WSAEnumNetworkEvents failed: %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(NULL,
+					    network_events.iErrorCode[FD_ACCEPT_BIT],
+					    errbuf,
+					    PCAP_ERRBUF_SIZE);
+					rpcapd_log(LOGPRIO_ERROR, "Socket 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();
+}
+
+//
+// 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;
+	SOCKET *sockctrl_temp;
+#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;
+	}
+
+	//
+	// We have a connection.
+	// Check whether the connecting host is among the ones allowed.
+	//
+	if (sock_check_hostlist(hostlist, RPCAP_HOSTLIST_SEP, &from, errbuf, PCAP_ERRBUF_SIZE) < 0)
+	{
+		rpcap_senderror(sockctrl, 0, PCAP_ERR_HOSTNOAUTH, errbuf, NULL);
+		sock_close(sockctrl, NULL, 0);
+		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 (WSAEventSelect(sockctrl, NULL, 0) == SOCKET_ERROR)
+	{
+		sock_geterror("ioctlsocket(FIONBIO): ", errbuf, PCAP_ERRBUF_SIZE);
+		rpcap_senderror(sockctrl, 0, PCAP_ERR_HOSTNOAUTH, errbuf, NULL);
+		sock_close(sockctrl, NULL, 0);
+		return;
+	}
+	if (ioctlsocket(sockctrl, FIONBIO, &off) == SOCKET_ERROR)
+	{
+		sock_geterror("ioctlsocket(FIONBIO): ", errbuf, PCAP_ERRBUF_SIZE);
+		rpcap_senderror(sockctrl, 0, PCAP_ERR_HOSTNOAUTH, errbuf, NULL);
+		sock_close(sockctrl, NULL, 0);
+		return;
+	}
+
+	//
+	// Allocate a location to hold the value of sockctrl.
+	// It will be freed in the newly-created thread once it's
+	// finished with it.
+	// I guess we *could* just cast sockctrl to a void *, but that's
+	// a bit ugly.
+	//
+	sockctrl_temp = (SOCKET *)malloc(sizeof (SOCKET));
+	if (sockctrl_temp == NULL)
+	{
+		pcap_fmt_errmsg_for_errno(errbuf, PCAP_ERRBUF_SIZE,
+		    errno, "malloc() failed");
+		rpcap_senderror(sockctrl, 0, PCAP_ERR_OPEN, errbuf, NULL);
+		sock_close(sockctrl, NULL, 0);
+		return;
+	}
+	*sockctrl_temp = sockctrl;
+
+	threadId = (HANDLE)_beginthreadex(NULL, 0,
+	    main_passive_serviceloop_thread, (void *) sockctrl_temp, 0, NULL);
+	if (threadId == 0)
+	{
+		pcap_snprintf(errbuf, PCAP_ERRBUF_SIZE, "Error creating the child thread");
+		rpcap_senderror(sockctrl, 0, PCAP_ERR_OPEN, errbuf, NULL);
+		sock_close(sockctrl, NULL, 0);
+		free(sockctrl_temp);
+		return;
+	}
+	CloseHandle(threadId);
+#else
+	pid = fork();
+	if (pid == -1)
+	{
+		pcap_snprintf(errbuf, PCAP_ERRBUF_SIZE, "Error creating the child process");
+		rpcap_senderror(sockctrl, 0, PCAP_ERR_OPEN, errbuf, NULL);
+		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.
+		//
+		(void)daemon_serviceloop(sockctrl, sockctrl, 0,
+		    nullAuthAllowed);
+
+		close(sockctrl);
+
+		exit(0);
+	}
+
+	// I am the parent
+	// Close the socket for this session (must be open only in the child)
+	closesocket(sockctrl);
+#endif
+}
+
+/*!
+	\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;
+
+	pcap_snprintf(errbuf, PCAP_ERRBUF_SIZE, "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");
+	SOCK_DEBUG_MESSAGE(errbuf);
+
+	// Initialize errbuf
+	memset(errbuf, 0, sizeof(errbuf));
+
+	// Do the work
+	if (sock_initaddress(activepars->address, activepars->port, &hints, &addrinfo, errbuf, PCAP_ERRBUF_SIZE) == -1)
+	{
+		SOCK_DEBUG_MESSAGE(errbuf);
+		return 0;
+	}
+
+	for (;;)
+	{
+		int activeclose;
+
+		if ((sockctrl = sock_open(addrinfo, SOCKOPEN_CLIENT, 0, errbuf, PCAP_ERRBUF_SIZE)) == INVALID_SOCKET)
+		{
+			SOCK_DEBUG_MESSAGE(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");
+
+			SOCK_DEBUG_MESSAGE(errbuf);
+
+			sleep_secs(RPCAP_ACTIVE_WAIT);
+
+			continue;
+		}
+
+		activeclose = daemon_serviceloop(sockctrl, sockctrl, 1,
+		    nullAuthAllowed);
+
+		sock_close(sockctrl, NULL, 0);
+
+		// 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)
+{
+	SOCKET sockctrl;
+
+	sockctrl = *((SOCKET *)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(sockctrl, sockctrl, 0, nullAuthAllowed);
+
+	sock_close(sockctrl, NULL, 0);
+
+	return 0;
+}
+#endif
diff --git a/rpcapd/rpcapd.h b/rpcapd/rpcapd.h
new file mode 100644
index 0000000..90ba7ff
--- /dev/null
+++ b/rpcapd/rpcapd.h
@@ -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
index 0000000..e4fad5e
--- /dev/null
+++ b/rpcapd/rpcapd.inetd.conf
@@ -0,0 +1,2 @@
+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
index 0000000..92f676c
--- /dev/null
+++ b/rpcapd/rpcapd.manadmin.in
@@ -0,0 +1,223 @@
+.\"  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
+] [
+.B \-s
+.I config_file
+]
+.br
+.ti +8
+[
+.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
+file to connect to this server.
+Hosts are listed one per line.
+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
+.BI \-s " config_file"
+Save the current configuration to
+.IR config_file .
+.TP
+.BI \-f " config_file"
+Load the current configuration from
+.IR config_file ;
+all switches specified from the command line are ignored.
+.TP
+.B \-h
+Print this help screen.
+.br
+.ad
+.SH "SEE ALSO"
+pcap(3PCAP)
diff --git a/rpcapd/rpcapd.rc b/rpcapd/rpcapd.rc
new file mode 100644
index 0000000..695c00b
--- /dev/null
+++ b/rpcapd/rpcapd.rc
@@ -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
index 0000000..9d5a0bd
--- /dev/null
+++ b/rpcapd/rpcapd.socket
@@ -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
index 0000000..2c79348
--- /dev/null
+++ b/rpcapd/rpcapd.xinetd.conf
@@ -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
index 0000000..92d1171
--- /dev/null
+++ b/rpcapd/rpcapd@.service
@@ -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
index 0000000..8cc7dc9
--- /dev/null
+++ b/rpcapd/win32-svc.c
@@ -0,0 +1,182 @@
+/*
+ * 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 "sockutils.h"		// for SOCK_DEBUG_MESSAGE
+#include "portability.h"
+#include "fileconf.h"
+
+static SERVICE_STATUS_HANDLE service_status_handle;
+static SERVICE_STATUS service_status;
+
+void svc_geterr(char *str);
+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 }
+	};
+
+	// This call is blocking. A new thread is created which will launch
+	// the svc_main() function
+	if ( (rc = StartServiceCtrlDispatcher(ste)) == 0)
+		svc_geterr("StartServiceCtrlDispatcher()");
+
+	return rc; // FALSE if this is not started as a service
+}
+
+void svc_geterr(char *str)
+{
+	char message[PCAP_ERRBUF_SIZE];
+	char string[PCAP_ERRBUF_SIZE];
+	int val;
+
+	val = GetLastError();
+	FormatMessageA(FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS |
+				  FORMAT_MESSAGE_MAX_WIDTH_MASK,
+				  NULL, val, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
+				  (LPSTR) string, PCAP_ERRBUF_SIZE, NULL);
+
+	pcap_snprintf(message, PCAP_ERRBUF_SIZE, "%s failed with error %d: %s", str, val, string);
+
+	SOCK_DEBUG_MESSAGE(message);
+}
+
+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."
+*/
diff --git a/rpcapd/win32-svc.h b/rpcapd/win32-svc.h
new file mode 100644
index 0000000..3f511d2
--- /dev/null
+++ b/rpcapd/win32-svc.h
@@ -0,0 +1,33 @@
+/*
+ * 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.
+ *
+ */
+
+int svc_start(void);
diff --git a/savefile.c b/savefile.c
index 247338c..ec44ef4 100644
--- a/savefile.c
+++ b/savefile.c
@@ -29,21 +29,13 @@
  */
 
 #ifdef HAVE_CONFIG_H
-#include "config.h"
+#include <config.h>
 #endif
 
+#include <pcap-types.h>
 #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 <io.h>
+#include <fcntl.h>
 #endif /* _WIN32 */
 
 #include <errno.h>
@@ -59,7 +51,7 @@
 #endif
 
 #include "sf-pcap.h"
-#include "sf-pcap-ng.h"
+#include "sf-pcapng.h"
 
 #ifdef _WIN32
 /*
@@ -92,7 +84,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
@@ -102,7 +94,7 @@
 }
 
 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
@@ -118,7 +110,7 @@
 }
 
 static int
-sf_stats(pcap_t *p, struct pcap_stat *ps)
+sf_stats(pcap_t *p, struct pcap_stat *ps _U_)
 {
 	pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
 	    "Statistics aren't available from savefiles");
@@ -236,7 +228,7 @@
  * 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_)
 {
 	pcap_snprintf(p->errbuf, sizeof(p->errbuf),
 	    "Setting direction is not supported on savefiles");
@@ -253,22 +245,6 @@
 	pcap_freecode(&p->fcode);
 }
 
-/*
-* fopen's safe version on Windows.
-*/
-#ifdef _MSC_VER
-FILE *fopen_safe(const char *filename, const char* mode)
-{
-	FILE *fp = NULL;
-	errno_t errno;
-	errno = fopen_s(&fp, filename, mode);
-	if (errno == 0)
-		return fp;
-	else
-		return NULL;
-}
-#endif
-
 pcap_t *
 pcap_open_offline_with_tstamp_precision(const char *fname, u_int precision,
 					char *errbuf)
@@ -293,14 +269,16 @@
 #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) {
-			pcap_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);
 		}
 	}
@@ -329,14 +307,16 @@
 	fd = _open_osfhandle(osfd, _O_RDONLY);
 	if ( fd < 0 )
 	{
-		pcap_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 )
 	{
-		pcap_snprintf(errbuf, PCAP_ERRBUF_SIZE, pcap_strerror(errno));
+		pcap_fmt_errmsg_for_errno(errbuf, PCAP_ERRBUF_SIZE,
+		    errno, "_fdopen");
 		return NULL;
 	}
 
@@ -373,7 +353,7 @@
 
 	/*
 	 * 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.
@@ -381,9 +361,8 @@
 	amt_read = fread((char *)&magic, 1, sizeof(magic), fp);
 	if (amt_read != sizeof(magic)) {
 		if (ferror(fp)) {
-			pcap_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 {
 			pcap_snprintf(errbuf, PCAP_ERRBUF_SIZE,
 			    "truncated dump file; tried to read %lu file header bytes, only got %lu",
diff --git a/scanner.c b/scanner.c
index b36239a..2cf65c9 100644
--- a/scanner.c
+++ b/scanner.c
@@ -1,13 +1,32 @@
 #line 2 "scanner.c"
-#line 2 "scanner.l"
 /* Must come first for _LARGE_FILE_API on AIX. */
 #ifdef HAVE_CONFIG_H
-#include "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"
 
-#line 11 "scanner.c"
+#line 30 "scanner.c"
 
 #define  YY_INT_ALIGNED short int
 
@@ -15,8 +34,8 @@
 
 #define FLEX_SCANNER
 #define YY_FLEX_MAJOR_VERSION 2
-#define YY_FLEX_MINOR_VERSION 5
-#define YY_FLEX_SUBMINOR_VERSION 39
+#define YY_FLEX_MINOR_VERSION 6
+#define YY_FLEX_SUBMINOR_VERSION 1
 #if YY_FLEX_SUBMINOR_VERSION > 0
 #define FLEX_BETA
 #endif
@@ -95,25 +114,13 @@
 
 #endif /* ! FLEXINT_H */
 
-#ifdef __cplusplus
-
-/* The "const" storage-class-modifier is valid. */
-#define YY_USE_CONST
-
-#else	/* ! __cplusplus */
-
-/* C99 requires __STDC__ to be defined as 1. */
-#if defined (__STDC__)
-
-#define YY_USE_CONST
-
-#endif	/* defined (__STDC__) */
-#endif	/* ! __cplusplus */
-
-#ifdef YY_USE_CONST
+/* TODO: this is always defined, so inline it */
 #define yyconst const
+
+#if defined(__GNUC__) && __GNUC__ >= 3
+#define yynoreturn __attribute__((__noreturn__))
 #else
-#define yyconst
+#define yynoreturn
 #endif
 
 /* Returned upon end-of-file. */
@@ -226,12 +233,12 @@
 	/* Size of input buffer in bytes, not including room for EOB
 	 * characters.
 	 */
-	yy_size_t yy_buf_size;
+	int yy_buf_size;
 
 	/* Number of characters read into yy_ch_buf, not including EOB
 	 * characters.
 	 */
-	yy_size_t yy_n_chars;
+	int yy_n_chars;
 
 	/* Whether we "own" the buffer - i.e., we know we created it,
 	 * and can realloc() it to grow it, and should free() it to
@@ -254,7 +261,7 @@
 
     int yy_bs_lineno; /**< The line count. */
     int yy_bs_column; /**< The column count. */
-    
+
 	/* Whether to try to fill the input buffer when we reach the
 	 * end of it.
 	 */
@@ -310,7 +317,7 @@
 
 YY_BUFFER_STATE pcap__scan_buffer (char *base,yy_size_t size ,yyscan_t yyscanner );
 YY_BUFFER_STATE pcap__scan_string (yyconst char *yy_str ,yyscan_t yyscanner );
-YY_BUFFER_STATE pcap__scan_bytes (yyconst char *bytes,yy_size_t len ,yyscan_t yyscanner );
+YY_BUFFER_STATE pcap__scan_bytes (yyconst char *bytes,int len ,yyscan_t yyscanner );
 
 void *pcap_alloc (yy_size_t ,yyscan_t yyscanner );
 void *pcap_realloc (void *,yy_size_t ,yyscan_t yyscanner );
@@ -342,7 +349,7 @@
 
 /* Begin user sect3 */
 
-#define pcap_wrap(yyscanner) 1
+#define pcap_wrap(yyscanner) (/*CONSTCOND*/1)
 #define YY_SKIP_YYWRAP
 
 typedef unsigned char YY_CHAR;
@@ -354,20 +361,20 @@
 static yy_state_type yy_get_previous_state (yyscan_t yyscanner );
 static yy_state_type yy_try_NUL_trans (yy_state_type current_state  ,yyscan_t yyscanner);
 static int yy_get_next_buffer (yyscan_t yyscanner );
-static void yy_fatal_error (yyconst char msg[] ,yyscan_t yyscanner );
+static void yynoreturn yy_fatal_error (yyconst char* msg ,yyscan_t yyscanner );
 
 /* Done after the current pattern has been matched and before the
  * corresponding action - sets up yytext.
  */
 #define YY_DO_BEFORE_ACTION \
 	yyg->yytext_ptr = yy_bp; \
-	yyleng = (size_t) (yy_cp - yy_bp); \
+	yyleng = (int) (yy_cp - yy_bp); \
 	yyg->yy_hold_char = *yy_cp; \
 	*yy_cp = '\0'; \
 	yyg->yy_c_buf_p = yy_cp;
 
-#define YY_NUM_RULES 155
-#define YY_END_OF_BUFFER 156
+#define YY_NUM_RULES 184
+#define YY_END_OF_BUFFER 185
 /* This struct is not used in this scanner,
    but its presence is necessary. */
 struct yy_trans_info
@@ -375,172 +382,201 @@
 	flex_int32_t yy_verify;
 	flex_int32_t yy_nxt;
 	};
-static yyconst flex_int16_t yy_accept[1464] =
+static yyconst flex_int16_t yy_accept[1729] =
     {   0,
-        0,    0,  156,  153,  113,  113,  113,  114,  153,  114,
-      114,  114,  154,  123,  123,  114,  114,  114,  114,  151,
-      151,  153,  151,  151,  151,  151,  151,  151,  151,  151,
-      151,  151,  151,  151,  151,  151,  151,  151,  151,  151,
-      151,  151,  114,  153,  117,  121,   67,    0,  151,  123,
-        0,  151,  151,  151,    0,  125,  119,  116,  118,  115,
-      120,  151,  152,  152,  151,  151,  151,   20,  151,  151,
-      151,  151,  151,  151,  151,  151,  151,  151,  151,  151,
-      151,  151,  151,  151,  151,  151,  151,  151,  151,  151,
-      151,  151,  151,  151,  151,  151,  151,  151,  151,  151,
+        0,    0,  185,  182,  113,  113,  113,  114,  182,  114,
+      114,  114,  183,  123,  123,  114,  114,  114,  114,  180,
+      180,  182,  180,  180,  180,  180,  180,  180,  180,  180,
+      180,  180,  180,  180,  180,  180,  180,  180,  180,  180,
+      180,  180,  114,  182,  117,  121,   67,    0,  180,  123,
+        0,  180,  180,  180,    0,  125,  119,  116,  118,  115,
+      120,  180,  181,  181,  180,  180,  180,   20,  180,  180,
+      180,  180,  180,  180,  180,  180,  180,  180,  180,  180,
+      180,  180,  180,  180,  180,  180,  180,  180,  180,  180,
+      180,  180,  180,  180,  180,  180,  180,  180,  180,  180,
 
-      151,    7,  151,   34,   35,  151,  151,  151,  151,  151,
-      151,  151,  151,  151,  151,  151,  151,  151,  151,   92,
-      151,   68,  151,  151,  151,  151,  151,  151,   60,  151,
-      151,  151,  151,   86,  151,  151,  151,  151,  151,  151,
-       61,  151,    4,  151,  151,  151,  151,  151,  151,  151,
-       68,  121,  151,  124,  124,  151,  123,  151,    0,  125,
-      123,  125,  125,  125,  151,  151,  151,   67,    5,  151,
-       81,  151,  151,  151,  151,  151,  151,  151,   55,  107,
-        1,    0,  151,   21,  151,  151,  151,  151,  151,  151,
-      151,  151,  151,  151,  151,  151,  151,  151,  151,  151,
+      180,    7,  180,   34,   35,  180,  180,  180,  180,  180,
+      180,  180,  180,  180,  180,  180,  180,  180,  180,   92,
+      180,   68,  180,  180,  180,  180,  180,  180,   60,  180,
+      180,  180,  180,   86,  180,  180,  180,  180,  180,  180,
+       61,  180,    4,  180,  180,  180,  180,  180,  180,  180,
+       68,  121,  180,  124,  124,  180,  123,  180,    0,  125,
+      123,  125,  125,  125,  180,  180,  180,   67,    5,  180,
+       81,  180,  180,  180,  180,  180,  180,  180,   55,  107,
+        1,    0,  180,   21,  180,  180,  180,  180,  180,  180,
+      180,  180,  180,  180,  180,  180,  180,  180,  180,  180,
 
-      151,  151,   36,  151,  151,   18,   43,    0,  151,   29,
-      151,   25,   70,  151,  151,   79,   37,  151,  100,  151,
-      151,  151,  151,  101,  151,   46,   69,   82,  106,  151,
-       14,  151,    3,  151,  151,  151,  151,  151,   94,  151,
-      151,   26,  151,  105,  151,  108,   38,    2,  151,   42,
-      151,    9,  151,   10,   89,  151,   88,  151,  151,    0,
-      151,  151,  124,  151,  151,  151,  151,  123,    0,  151,
+      180,  180,   36,  180,  180,   18,   43,    0,  180,   29,
+      180,   25,   70,  180,  180,   79,   37,  180,  100,  180,
+      180,  180,  180,  101,  180,   46,   69,   82,  106,  180,
+       14,  180,    3,  180,  180,  180,  180,  180,   94,  180,
+      180,   26,  180,  105,  180,  108,   38,    2,  180,   42,
+      180,    9,  180,   10,   89,  180,   88,  180,  180,    0,
+      180,  180,  124,  180,  180,  180,  180,  123,    0,  180,
         0,  126,  125,  125,    0,  125,    0,  125,    0,  125,
-        0,   23,  151,  151,  151,  151,   64,   16,   41,  151,
-       39,  151,  151,  151,   30,  151,   98,  151,  151,  151,
+        0,   23,  180,  180,  180,  180,   64,   16,   41,  180,
+       39,  180,  180,  180,   30,  180,   98,  180,  180,  180,
 
-      111,  151,  151,  104,  110,   45,  109,  112,   11,  151,
-       12,   13,  151,  151,  151,   32,   78,  151,   62,    3,
-       99,   47,  151,  151,  151,   74,  151,  151,  151,  151,
-       48,  151,  151,   40,  151,    6,  151,   93,  151,    8,
-       95,  151,  151,    0,  151,   53,   73,   15,  151,  124,
-      124,  151,  124,  124,  124,  151,  123,  151,    0,  125,
-      151,    0,    0,  125,    0,  125,  126,  125,    0,    0,
-        0,    0,  125,  125,  125,  125,  125,    0,  151,   56,
-       57,   58,   59,  151,   22,  151,  151,  151,  151,   31,
-      151,  151,  151,  102,  103,    0,   19,  151,  151,  151,
+      111,  180,  180,  104,  110,   45,  109,  112,   11,  180,
+       12,   13,  180,  180,  180,   32,   78,  180,   62,    3,
+       99,   47,  180,  180,  180,   74,  180,  180,  180,  180,
+       48,  180,  180,   40,  180,    6,  180,   93,  180,    8,
+       95,  180,  180,    0,  180,   53,   73,   15,  180,  124,
+      124,  180,  124,  124,  124,  180,  123,  180,    0,  125,
+      180,    0,    0,  125,    0,  125,  126,  125,    0,    0,
+        0,    0,  125,  125,  125,  125,  125,    0,  180,   56,
+       57,   58,   59,  180,   22,  180,  180,  180,  180,   31,
+      180,  180,  180,  102,  103,    0,   19,  180,  180,  180,
 
-       87,  151,   33,  151,   80,   28,   27,  151,  151,   83,
-      151,  151,  151,   50,   17,  151,  151,  151,  151,  151,
-      151,  151,  151,  151,  151,  151,  151,    0,  151,  151,
-      124,  151,  151,  151,  151,  124,  124,  151,  123,  151,
-        0,    0,  125,  125,  125,    0,    0,  126,  125,  125,
-      126,  125,    0,    0,  125,  125,  125,  125,  125,    0,
-        0,    0,    0,  125,  125,    0,  125,    0,  125,    0,
-       97,  151,  151,  151,   24,  151,  151,   77,  151,  151,
-      151,  151,  151,  151,  151,  151,  151,  151,  151,  151,
-       70,  151,  151,  151,  151,  151,  151,  151,   75,   76,
+       87,  180,   33,  180,   80,   28,   27,  180,  180,   83,
+      180,  180,  180,   50,   17,  180,  180,  180,  180,  180,
+      180,  180,  180,  180,  180,  180,  180,  180,  180,    0,
+      180,  180,  124,  180,  180,  180,  180,  124,  124,  180,
+      123,  180,    0,    0,  125,  125,  125,    0,    0,  126,
+      125,  125,  126,  125,    0,    0,  125,  125,  125,  125,
+      125,    0,    0,    0,    0,  125,  125,    0,  125,    0,
+      125,    0,   97,  180,  180,  180,   24,  180,  180,   77,
+      180,  180,  180,  180,  180,  180,  180,  180,  180,    0,
+      180,  180,  180,  180,  180,   70,  180,  180,  180,  180,
 
-      151,   96,  151,  151,  151,  151,  151,  151,  151,  151,
-      151,  151,  151,  151,  124,  124,  151,  124,  124,  124,
-      124,  151,  123,  151,    0,  125,  125,    0,  125,    0,
-        0,  125,    0,  125,  126,  125,    0,    0,    0,  125,
-      125,    0,  125,  126,  125,    0,    0,    0,    0,    0,
-        0,    0,  125,  125,  125,  125,  125,    0,  151,  151,
-      151,  151,   52,   63,  151,  151,  151,  151,  151,  151,
-      151,  151,  151,  151,  151,  151,   71,  151,  151,   44,
-       84,   85,  151,  151,  151,  151,   54,  149,  145,  151,
-      147,  146,  150,  151,    0,  151,  151,  124,  151,  151,
+      180,  180,  180,   75,   76,  180,   96,  180,  180,  180,
+      180,  180,  180,  180,  180,  180,  180,  180,  180,  180,
+      180,  124,  124,  180,  124,  124,  124,  124,  180,  123,
+      180,    0,  125,  125,    0,  125,    0,    0,  125,    0,
+      125,  126,  125,    0,    0,    0,  125,  125,    0,  125,
+      126,  125,    0,    0,    0,    0,    0,    0,    0,  125,
+      125,  125,  125,  125,    0,  180,  180,  180,  180,   52,
+       63,  180,  180,  180,  180,  180,  180,  180,  180,  180,
+      180,  180,  180,  180,  180,  180,  180,  180,  180,  180,
+      180,  180,   71,  180,  180,   44,   84,   85,  180,  180,
 
-      151,  124,  151,  123,  151,    0,    0,  125,  125,  125,
-      125,  125,  125,    0,    0,  126,  125,  125,  125,    0,
+      180,  180,   54,  176,  179,  178,  172,  180,  174,  173,
+      177,  180,    0,  180,  180,  124,  180,  180,  180,  124,
+      180,  123,  180,    0,    0,  125,  125,  125,  125,  125,
+      125,    0,    0,  126,  125,  125,  125,    0,    0,  125,
+      125,  125,  125,  125,    0,    0,    0,    0,    0,    0,
         0,  125,  125,  125,  125,  125,    0,    0,    0,    0,
-        0,    0,    0,  125,  125,  125,  125,  125,    0,    0,
-        0,    0,    0,  125,  125,    0,  125,    0,  125,    0,
-      151,  151,  151,  151,  151,  151,  151,  151,  151,  151,
-      151,  151,  151,  128,  127,  151,  151,   72,  151,  151,
-      151,  148,  144,  151,  151,  124,  124,  124,  124,  151,
-      123,  151,    0,  125,  125,    0,  125,  125,    0,  125,
-        0,    0,  125,    0,  125,  126,  125,    0,    0,    0,
+        0,  125,  125,    0,  125,    0,  125,    0,  180,  180,
+      180,  180,  180,  180,  180,  180,  180,  180,  180,  180,
+      180,  180,  180,  180,  180,  180,  180,  180,  180,  180,
+      180,  180,  180,  128,  127,  180,  180,   72,  180,  180,
 
+      180,  175,  171,  180,  180,  124,  124,  124,  124,  180,
+      123,  180,    0,  125,  125,    0,  125,  125,    0,  125,
+        0,    0,  125,    0,  125,  126,  125,    0,    0,    0,
       125,  125,    0,  125,  126,  125,    0,    0,    0,    0,
         0,  125,  125,    0,  125,  126,  125,    0,  125,  125,
         0,    0,    0,    0,    0,    0,    0,  125,  125,  125,
-      125,  125,    0,   65,  151,   55,  133,  140,  151,  151,
-      151,  151,  151,  151,  151,  151,  151,   66,   49,  151,
-      151,    0,  151,  151,  151,  151,  151,  123,  151,    0,
-        0,  125,  125,  125,  125,  125,  125,  125,  125,  125,
-        0,    0,  126,  125,  125,  125,    0,    0,  125,  125,
-      125,  125,  125,    0,    0,    0,    0,    0,    0,    0,
-      125,  125,  125,  125,  125,    0,  125,  125,    0,    0,
+      125,  125,    0,   65,  180,   55,  133,  140,  180,  180,
+      180,  180,  180,  180,  180,  180,  180,  180,  180,  180,
+      180,  180,  180,  180,  180,  180,  145,  144,  180,   66,
+       49,  180,  180,    0,  180,  180,  180,  180,  180,  123,
 
-        0,    0,    0,    0,    0,  125,  125,  125,  125,  125,
-        0,    0,    0,    0,    0,    0,  125,  125,    0,  125,
-        0,  125,    0,   90,  151,  151,  151,  151,  151,  151,
-      151,  151,  151,  151,  151,   51,  122,  122,  124,  124,
-      151,  123,  151,    0,  125,  125,    0,  125,  125,    0,
-      125,  125,    0,  125,    0,  122,  125,    0,  125,  126,
-      125,    0,    0,    0,  125,  125,    0,  125,  126,  125,
-        0,    0,    0,    0,    0,  125,  125,    0,  125,  126,
-      125,    0,    0,    0,    0,    0,    0,  125,  125,    0,
-      125,  126,  125,    0,  125,  125,  125,    0,    0,    0,
+      180,    0,    0,  125,  125,  125,  125,  125,  125,  125,
+      125,  125,    0,    0,  126,  125,  125,  125,    0,    0,
+      125,  125,  125,  125,  125,    0,    0,    0,    0,    0,
+        0,    0,  125,  125,  125,  125,  125,    0,  125,  125,
+        0,    0,    0,    0,    0,    0,    0,  125,  125,  125,
+      125,  125,    0,    0,    0,    0,    0,    0,  125,  125,
+        0,  125,    0,  125,    0,   90,  180,  180,  180,  180,
+      180,  180,  180,  180,  180,  180,  180,  146,  180,  180,
+      180,  180,  180,  180,  180,  180,  180,   51,  122,  122,
+      124,  124,  180,  123,  180,    0,  125,  125,    0,  125,
 
-        0,    0,    0,    0,  125,  125,  125,  125,  125,    0,
-      151,  151,  151,  151,  151,  151,  151,  151,  138,  151,
-       91,  122,  122,  124,  151,  122,  122,    0,    0,  125,
-      125,  125,  125,  125,  125,  125,  125,  125,  125,  125,
-      125,    0,  122,  126,  125,  125,  125,    0,    0,  125,
-      125,  125,  125,  125,    0,    0,    0,    0,    0,    0,
-        0,  125,  125,  125,  125,  125,    0,  125,  125,    0,
+      125,    0,  125,  125,    0,  125,    0,  122,  125,    0,
+      125,  126,  125,    0,    0,    0,  125,  125,    0,  125,
+      126,  125,    0,    0,    0,    0,    0,  125,  125,    0,
+      125,  126,  125,    0,    0,    0,    0,    0,    0,  125,
+      125,    0,  125,  126,  125,    0,  125,  125,  125,    0,
         0,    0,    0,    0,    0,    0,  125,  125,  125,  125,
-      125,    0,  125,  125,  125,    0,    0,    0,    0,    0,
-        0,    0,  125,  125,  125,  125,  125,    0,    0,    0,
+      125,    0,  180,  180,  180,  180,  180,  180,  180,  180,
+      138,  180,  180,  180,  180,  180,  180,  180,  180,  180,
+      180,  180,   91,  122,  122,  124,  180,  122,  122,    0,
+        0,  125,  125,  125,  125,  125,  125,  125,  125,  125,
 
-        0,    0,    0,  125,  125,    0,  125,    0,  125,    0,
-      151,  151,  151,  142,  151,  151,  151,  151,  151,  151,
-      151,  130,  124,  151,  123,    0,  125,  125,    0,  125,
-      125,    0,  125,  125,    0,  125,  125,    0,  125,    0,
-        0,    0,  125,    0,    0,  125,  126,  125,    0,    0,
-        0,  125,  125,    0,  125,  126,  125,    0,    0,    0,
-        0,    0,  125,  125,    0,  125,  126,  125,    0,    0,
+      125,  125,  125,    0,  122,  126,  125,  125,  125,    0,
+        0,  125,  125,  125,  125,  125,    0,    0,    0,    0,
+        0,    0,    0,  125,  125,  125,  125,  125,    0,  125,
+      125,    0,    0,    0,    0,    0,    0,    0,  125,  125,
+      125,  125,  125,    0,  125,  125,  125,    0,    0,    0,
+        0,    0,    0,    0,  125,  125,  125,  125,  125,    0,
+        0,    0,    0,    0,    0,  125,  125,    0,  125,    0,
+      125,    0,  180,  180,  180,  142,  180,  180,  180,  180,
+      180,  180,  180,  130,  180,  180,  180,  180,  180,  180,
+      180,  180,  180,  180,  124,  180,  123,    0,  125,  125,
+
+        0,  125,  125,    0,  125,  125,    0,  125,  125,    0,
+      125,    0,    0,    0,  125,    0,    0,  125,  126,  125,
+        0,    0,    0,  125,  125,    0,  125,  126,  125,    0,
         0,    0,    0,    0,  125,  125,    0,  125,  126,  125,
         0,    0,    0,    0,    0,    0,  125,  125,    0,  125,
-      126,  125,    0,  125,  125,  125,    0,    0,    0,    0,
+      126,  125,    0,    0,    0,    0,    0,    0,  125,  125,
+        0,  125,  126,  125,    0,  125,  125,  125,    0,    0,
+        0,    0,    0,    0,    0,  125,  125,  125,  125,  125,
+        0,  180,  180,  180,  180,  132,  180,  180,  180,  136,
+      180,  180,  180,  180,  180,  180,  180,  180,  180,  180,
 
-        0,    0,    0,  125,  125,  125,  125,  125,    0,  151,
-      151,  151,  151,  132,  151,  151,  151,  136,  151,  122,
-        0,    0,  125,  125,  125,  125,  125,  125,  125,  125,
-      125,  125,  125,  125,  125,  125,  125,    0,    0,    0,
-      126,    0,    0,  125,    0,    0,  125,  125,  125,    0,
-        0,    0,    0,    0,    0,    0,  125,  125,  125,    0,
-      125,  125,    0,    0,    0,    0,    0,    0,    0,  125,
-      125,  125,    0,  125,  125,  125,    0,    0,    0,    0,
+      180,  180,  180,  122,    0,    0,  125,  125,  125,  125,
+      125,  125,  125,  125,  125,  125,  125,  125,  125,  125,
+      125,    0,    0,    0,  126,    0,    0,  125,    0,    0,
+      125,  125,  125,    0,    0,    0,    0,    0,    0,    0,
+      125,  125,  125,    0,  125,  125,    0,    0,    0,    0,
         0,    0,    0,  125,  125,  125,    0,  125,  125,  125,
         0,    0,    0,    0,    0,    0,    0,  125,  125,  125,
+        0,  125,  125,  125,    0,    0,    0,    0,    0,    0,
+        0,  125,  125,  125,    0,    0,    0,    0,    0,    0,
+      125,  125,    0,  125,    0,  125,    0,  129,  141,  143,
 
-        0,    0,    0,    0,    0,    0,  125,  125,    0,  125,
-        0,  125,    0,  129,  141,  143,  137,  151,  151,  151,
-      151,    0,    0,  125,    0,  125,    0,  125,  125,    0,
-      125,  125,    0,  125,  125,    0,  125,  125,    0,  125,
-        0,    0,    0,    0,  125,  125,    0,  125,    0,    0,
-      125,  125,  125,    0,    0,    0,    0,  125,  125,  125,
-        0,    0,    0,    0,    0,  125,  125,  125,    0,    0,
+      137,  180,  180,  180,  180,  180,  180,  180,  180,  180,
+      180,  180,  180,  155,  180,  180,  180,    0,    0,  125,
+        0,  125,    0,  125,  125,    0,  125,  125,    0,  125,
+      125,    0,  125,  125,    0,  125,    0,    0,    0,    0,
+      125,  125,    0,  125,    0,    0,  125,  125,  125,    0,
         0,    0,    0,  125,  125,  125,    0,    0,    0,    0,
-        0,  125,  125,  125,  125,  125,  125,    0,    0,    0,
-        0,    0,    0,    0,  125,  125,  125,    0,  151,  151,
-
-      151,  151,    0,    0,    0,  125,  125,  125,  125,  125,
-      125,    0,    0,    0,    0,  125,  125,    0,    0,    0,
         0,  125,  125,  125,    0,    0,    0,    0,    0,  125,
+      125,  125,    0,    0,    0,    0,    0,  125,  125,  125,
+      125,  125,  125,    0,    0,    0,    0,    0,    0,    0,
+      125,  125,  125,    0,  180,  180,  180,  180,  180,  180,
+
+      147,  180,  180,  180,  180,  180,  180,  180,  180,  180,
+      180,    0,    0,    0,  125,  125,  125,  125,  125,  125,
+        0,    0,    0,    0,  125,  125,    0,    0,    0,    0,
       125,  125,  125,    0,    0,    0,    0,    0,  125,  125,
       125,  125,    0,    0,    0,    0,    0,  125,  125,  125,
-      125,    0,    0,    0,    0,    0,  125,    0,    0,    0,
-        0,    0,  125,  125,  125,  151,  151,  151,  139,  125,
-      125,  125,  125,  125,  125,  125,  125,    0,    0,    0,
-        0,  125,  125,    0,    0,  125,    0,    0,    0,  125,
-        0,    0,    0,  125,    0,    0,    0,  125,    0,    0,
+      125,    0,    0,    0,    0,    0,  125,  125,  125,  125,
+        0,    0,    0,    0,    0,  125,    0,    0,    0,    0,
+        0,  125,  125,  125,  180,  180,  180,  139,  180,  180,
+      180,  180,  180,  180,  180,  180,  180,  180,  180,  180,
+      180,  125,  125,  125,  125,  125,  125,  125,  125,    0,
 
-        0,  125,  125,  125,  125,    0,    0,    0,    0,    0,
-      125,  134,  151,  131,  125,    0,    0,  125,  125,    0,
-      125,  125,  125,    0,  125,  125,  125,    0,  125,  125,
-      125,    0,  125,  125,  125,    0,    0,    0,    0,  125,
-      135,  125,  125,    0,    0,    0,    0,    0,    0,  125,
-      125,  125,    0,    0,  125,  125,  125,  125,  125,    0,
-      125,  125,    0
+        0,    0,    0,  125,  125,    0,    0,  125,    0,    0,
+        0,  125,    0,    0,    0,  125,    0,    0,    0,  125,
+        0,    0,    0,  125,  125,  125,  125,    0,    0,    0,
+        0,    0,  125,  134,  180,  131,  180,  180,  180,  180,
+      180,  180,  180,  180,  180,  180,  180,  156,  180,  125,
+        0,    0,  125,  125,    0,  125,  125,  125,    0,  125,
+      125,  125,    0,  125,  125,  125,    0,  125,  125,  125,
+        0,    0,    0,    0,  125,  135,  180,  180,  180,  180,
+      180,  180,  180,  180,  180,  180,  152,  180,  125,  125,
+        0,    0,    0,    0,    0,    0,  125,  125,  125,    0,
+
+      180,  180,  180,  180,  180,  180,  180,  180,  180,  180,
+      180,  151,    0,  125,  125,  125,  125,  125,    0,  167,
+      180,  180,  180,  180,  180,  180,  180,  154,  180,  180,
+      125,  125,  166,  180,  180,  180,  180,  180,  180,  153,
+      180,  180,  180,  180,  180,  180,  180,  180,  180,  180,
+      180,  180,  180,  180,  180,  180,  180,  180,  180,  180,
+      180,  180,  180,  165,  180,  180,  180,  180,  180,  180,
+      180,  180,  180,  180,  180,  180,  164,  180,  180,  180,
+      180,  180,  170,  180,  180,  180,  180,  180,  180,  180,
+      180,  180,  180,  157,  180,  180,  180,  180,  180,  150,
+
+      180,  180,  168,  180,  180,  180,  180,  180,  180,  148,
+      180,  169,  180,  163,  180,  180,  180,  180,  158,  180,
+      160,  180,  180,  162,  159,  149,  161,    0
     } ;
 
-static yyconst flex_int32_t yy_ec[256] =
+static yyconst YY_CHAR yy_ec[256] =
     {   0,
         1,    1,    1,    1,    1,    1,    1,    1,    2,    3,
         1,    1,    4,    1,    1,    1,    1,    1,    1,    1,
@@ -572,7 +608,7 @@
         1,    1,    1,    1,    1
     } ;
 
-static yyconst flex_int32_t yy_meta[54] =
+static yyconst YY_CHAR yy_meta[54] =
     {   0,
         1,    2,    2,    1,    2,    1,    1,    3,    2,    4,
         5,    6,    6,    6,    6,    6,    6,    6,    7,    3,
@@ -582,231 +618,259 @@
         9,    4,    3
     } ;
 
-static yyconst flex_int16_t yy_base[1924] =
+static yyconst flex_uint16_t yy_base[2189] =
     {   0,
-        0,    0, 3898,   53, 7420, 7420,   57, 3862,   64,   81,
-     3874, 7420, 7420,   99,   30,  151,   46, 3860,   52,  168,
+        0,    0, 5455,   53, 7856, 7856,   57, 5433,   64,   81,
+     5445, 7856, 7856,   99,   30,  151,   46, 5430,   52,  168,
       210,  168,  160,   44,  125,   60,   31,   58,  132,  170,
-      214,  217,  229,   59,  170,  222,  237,  243,  250, 3848,
-      255, 3840, 3824,  300, 7420,    0, 7420,  316,  339,  363,
-     3857,  387,    0,  394,    0,  428, 7420, 7420, 7420, 7420,
-     7420,  296,  316,    0, 3830, 3812, 3826,    0, 3825, 3813,
-     3826, 3822, 3810, 3804, 3791, 3794, 3793, 3792, 3801, 3785,
-     3798, 3781,  116, 3776, 3779, 3764, 3762, 3767, 3773, 3762,
-     3767, 3743, 3742,   56,   68, 3747, 3745,   80, 3749, 3743,
+      214,  217,  229,   59,  170,  222,  237,  243,  250, 5418,
+      255, 5410, 5380,  300, 7856,    0, 7856,  316,  339,  363,
+     5413,  387,    0,  394,    0,  428, 7856, 7856, 7856, 7856,
+     7856,  296,  316,    0, 5386, 5383, 5397,    0, 5395, 5383,
+     5396, 5378, 5366, 5360, 5361, 5362, 5360, 5344, 5352, 5337,
+     5350, 5331,  116, 5341, 5312, 5297, 5295, 5299, 5305, 5294,
+     5299, 5279, 5278,   56,   68, 5263, 5261,   80, 5265, 5259,
 
-     3752,   68,  166,    0,    0,   15,  122, 3740, 3734,  189,
-     3718, 3716, 3719, 3722, 3710, 3718, 3695, 3694, 3700,    0,
-     3708,    0, 3691, 3696, 3690, 3691, 3676, 3676,  128, 3687,
-     3670, 3680, 3672,  159, 3653,  201, 3651,   38, 3650, 3662,
-        0, 3648,    0, 3646, 3645, 3650, 3642, 3633, 3624, 3639,
-     7420, 7420,  453,  477,  236,  518,  542,  566, 3647,  573,
-     3653,  597,  248, 3629, 3604, 3609, 3600,    0,    0, 3605,
-        0, 3613, 3608, 3597, 3581, 3582, 3579, 3580, 3586,    0,
-        0, 3581, 3571,    0, 3568, 3563, 3551, 3565, 3564, 3566,
-     3563, 3547, 3546, 3522, 3538, 3520, 3524, 3518, 3520, 3533,
+     5267,   68,  166,    0,    0,   15,  122, 5255, 5264,  189,
+     5238, 5236, 5219, 5222, 5212, 5219, 5209, 5208, 5214,    0,
+     5212,    0, 5195, 5181, 5175, 5176, 5175, 5174,  128, 5185,
+     5168, 5167, 5160,  159, 5147,  201, 5144,   38, 5137, 5149,
+        0, 5133,    0, 5112, 5111, 5094, 5090, 5078, 5048, 5062,
+     7856, 7856,  453,  477,  236,  518,  542,  566, 5071,  573,
+     5078,  597,  248, 5054, 5029, 5034, 5025,    0,    0, 5030,
+        0, 5038, 5033, 5022, 5006, 5007, 5004, 5005, 5012,    0,
+        0, 5006, 4996,    0, 5008, 4988, 4976, 4990, 4989, 4992,
+     4988, 4972, 4971, 4953, 4969, 4952, 4956, 4951, 4952, 4965,
 
-     3518, 3503,    0, 3508, 3502,    0,    0, 3506, 3494,    0,
-     3506,    0, 3503, 3491, 3489,    0,    0, 3458,    0, 3467,
-     3475,  244, 3456,    0, 3453, 3469,    0, 3464,    0, 3467,
-        0, 3434, 3438, 3432, 3435, 3439, 3432, 3428,    0, 3426,
-     3425,    0, 3414,    0, 3412,    0,    0,    0, 3408,    0,
-      153,  156, 3419,    0,    0, 3409,    0, 3391, 3392,  637,
-     3422,  660,  684, 3420,  691,  500,  281,  715, 3409,  739,
-     3408, 3407,  747,  290, 3391, 3390,  507,  788,  811, 3389,
-        0,    0, 3363,  350, 3354, 3357,    0,    0,    0, 3346,
-        0, 3345, 3338, 3322,    0, 3321,    0, 3296, 3296, 3297,
+     4950, 4934,    0, 4939, 4933,    0,    0, 4937, 4927,    0,
+     4938,    0, 4935, 4907, 4912,    0,    0, 4901,    0, 4909,
+     4917,  244, 4899,    0, 4887, 4882,    0, 4877,    0, 4880,
+        0, 4861, 4864, 4857, 4845, 4850, 4843, 4839,    0, 4837,
+     4849,    0, 4838,    0, 4837,    0,    0,    0, 4819,    0,
+      153,  156, 4830,    0,    0, 4821,    0, 4818, 4818,  637,
+     4847,  660,  684, 4830,  691,  500,  281,  715, 4821,  739,
+     4820, 4819,  747,  290, 4818, 4816,  507,  788,  811, 4815,
+        0,    0, 4775,  350, 4778, 4783,    0,    0,    0, 4781,
+        0, 4777, 4762, 4746,    0, 4746,    0, 4740, 4739, 4740,
 
-        0, 3295, 3294,    0,    0,    0,    0,    0,  614, 3300,
-        0,    0, 3294, 3266, 3266,    0,    0, 3258,    0,    0,
-        0,    0, 3273, 3264, 3250,    0, 3243, 3246, 3262, 3235,
-     3229, 3240, 3220,    0, 3198,    0, 3197,    0,  275,    0,
-        0, 3190, 3181,  739, 3193,    0,    0,    0,  836,  860,
-      293,  901, 3205, 3203,  405,  924,  948,  972, 3194,  979,
-      621, 3193, 3190, 1002,  776, 1026, 1049, 3178,    0, 3173,
-      427,  428, 1073, 3172, 1097,  333, 3171, 3162, 3130,    0,
-        0,    0,    0, 3122,    0, 3125, 3121, 3104, 3103,    0,
-     3098, 3082, 3078,    0,    0, 1116,    0, 3068, 3057, 3075,
+        0, 4722, 4721,    0,    0,    0,    0,    0,  614, 4728,
+        0,    0, 4736, 4715, 4700,    0,    0, 4698,    0,    0,
+        0,    0, 4713, 4704, 4710,    0, 4703, 4706, 4707, 4679,
+     4675, 4667, 4639,    0, 4632,    0, 4607,    0,  275,    0,
+        0, 4599, 4592,  817, 4585,    0,    0,    0,  856,  880,
+      293,  921, 4610, 4608,  405,  944,  968,  992, 4598,  999,
+      621, 4581, 4579, 1022,  770, 1046, 1069, 4562,    0, 4553,
+      427,  428, 1093, 4552, 1117,  333, 4551, 4550, 4519,    0,
+        0,    0,    0, 4491,    0, 4504, 4502, 4469, 4460,    0,
+     4477, 4472, 4463,    0,    0, 1136,  293, 4453, 4420, 4437,
 
-        0, 3064,    0, 3068, 3061,    0,    0, 3071, 3053,  291,
-     3043, 3060,  294, 3054,    0, 3033, 3004, 3018, 3011, 3005,
-     3015, 3008, 2996, 2973, 2966, 2972, 2987, 1153, 3004, 1176,
-     1200, 3002, 1207,  883,  285, 1231,  334, 1271, 1294, 1318,
-     2993, 2977, 1326,  336, 2976, 2975, 2973, 2971, 1367,  363,
-     2970, 2969,  515,  631, 1408, 2968, 1432,  364, 2953, 2960,
-     2948,  890,    0,  371, 2947, 1120, 1473, 1496, 2946,    0,
-        0, 2918, 2920, 2901,    0, 2909, 2890,    0, 2896, 2877,
-     2862, 2877, 2875,  380, 2860,  427, 2860, 2868, 2841, 2851,
-        0, 2841, 2852, 2843, 2847, 2846, 2835, 2819,    0,    0,
+        0, 4427,    0, 4429, 4422,    0,    0, 4420, 4394,  292,
+     4393, 4411,  387, 4408,    0, 4390, 4382, 4394, 4368, 4362,
+     4372, 4350, 4357, 4338, 4317, 4318, 4310, 4278, 4292, 1173,
+     4310, 1196, 1220, 4305, 1227,  777,  285, 1251,  334, 1291,
+     1314, 1338, 4294, 4293, 1346,  336, 4291, 4256, 4255, 4254,
+     1387,  363, 4252, 4251,  515,  631, 1428, 4250, 1452,  364,
+     4240, 4247, 4218,  840,    0,  371, 4214,  903, 1493, 1516,
+     4212,    0,    0, 4184, 4200, 4149,    0, 4158, 4140,    0,
+     4145, 4158, 4143, 4126, 4125,  380, 4109,  427, 4108, 1121,
+     4106, 4095, 4082, 4067, 4076,    0, 4066, 4077, 4025, 4028,
 
-     2823,    0, 2818, 2810, 2823, 2821, 2815, 2811, 2791, 2789,
-     2794, 2799, 2798, 1521, 1545,  423, 1586, 2820, 2819,  633,
-     1610, 1634, 1641, 1665, 2810, 1672, 1696, 1719, 2794, 2793,
-     2792, 1742, 1127, 1766, 1789, 2791,    0, 1254,    0,  461,
-     2790, 1261, 1813, 1836, 2788,    0,  758,  785, 2795,  485,
-      805,  836, 1860, 2786, 1884,  424, 2771, 2778,  405, 2742,
-     2747, 2744,    0,    0, 2748, 2750, 2736, 2721, 2733, 2716,
-     2715, 2722, 2713, 2714, 2725, 2710,    0, 2701, 2695,    0,
-        0,    0, 2708, 2704, 2708, 2695,    0,    0,    0, 2699,
-        0,    0,    0, 2673, 1924, 2708, 1947, 1971, 2706, 1978,
+     4026, 4015, 4014,    0,    0, 4018,    0, 3981, 3973, 3986,
+     3984, 3976, 3949, 3960, 3929, 3923, 3918, 3909, 3888, 3885,
+     1541, 1565,  423, 1606, 3892, 3888,  633, 1630, 1654, 1661,
+     1685, 3877, 1692, 1716, 1739, 3876, 3857, 3856, 1762,  910,
+     1786, 1809, 3852,    0, 1274,    0,  461, 3837, 1281, 1833,
+     1856, 3833,    0,  785,  824, 3820,  485,  853,  856, 1880,
+     3810, 1904,  424, 3809, 3798,  529, 3762, 3765, 3739,    0,
+        0, 3742, 3729, 3715, 3691, 3703, 3683, 3666, 3672, 3664,
+     3643, 3632, 3633, 3619, 3601,   56,  504,  646, 3609, 3575,
+     3584, 3582,    0, 3573, 3567,    0,    0,    0, 3580, 3552,
 
-      425, 2002, 2026, 2033, 2057, 2697, 2696, 2065,  452, 2693,
-     2106,  476, 2692, 2677, 2676, 2675, 2147,  512, 2674,  898,
-      918, 2188, 2673, 2212,  513, 2671, 2678, 1147, 1149, 2677,
-     2661, 1270, 1336, 2253, 2652, 2277,  517, 2651, 2658, 1350,
-        0, 1357,    0,  486, 2648, 1390, 2318, 2341, 2646,    0,
-     2364,  452,   57,  497,  150,  641,  205,  610, 2602,  258,
-      291,  570, 1148, 2601, 2600, 1266, 2599, 2598, 1362,  873,
-      498, 2596, 2595, 2402, 2439, 2475, 2511,  518, 2535,  551,
-     2543, 2567, 2622, 2574, 2598, 2621, 2606, 2645, 2668, 2605,
-     2604, 2603, 2691, 1398, 2715, 2738, 2601,    0, 1455,    0,
+     3533, 3519,    0,    0,    0,    0,    0, 3523,    0,    0,
+        0, 3512, 1944, 3547, 1967, 1991, 3514, 1998,  325, 2022,
+     2046, 2053, 2077, 3505, 3474, 2085,  452, 3434, 2126,  476,
+     3393, 3386, 3385, 3365, 2167,  513, 3345,  918,  938, 2208,
+     3344, 2232,  542, 3343, 3348, 1142, 1149, 3347, 3314, 1167,
+     1169, 2273, 3305, 2297,  543, 3304, 3310, 1369,    0, 1376,
+        0,  486, 3282, 1410, 2338, 2361, 3278,    0, 2384,  374,
+      115,  389,  150,  672,  205,  610, 3235,  550,  403,  313,
+      783,  553,  761,  522,  800,  451,  578,  893,  633,  829,
+      571, 1108, 1112, 3231, 3228, 1123, 3206, 3189, 1130, 1128,
 
-      582, 2600, 1462, 2762, 2785, 2599,    0, 1568,    0, 1575,
-        0,  699, 2583, 1907, 2809, 2832, 2582,    0,  570, 1914,
-     2589, 1470, 1490, 2588, 2587, 1521, 1583, 2856, 2577, 2880,
-      572, 2576, 2583,  590,  652,  615,  636,  787, 1270, 2075,
-     1407,  706,  709,  827, 2102,  707,  829,  631,  785, 2100,
-     2104, 2922,  852, 2945,  853, 2968, 2133, 2992, 3016, 2574,
-     2552, 3024,  660, 2551, 3065,  661, 2550, 3106,  690, 2549,
-     2548, 2546, 2545, 3147,  761, 2544, 1713, 1923, 3188, 2543,
-     3212,  897, 2520, 2527, 2075, 2076, 2526, 2525, 2082, 2142,
-     3253, 2516, 3277,  900, 2514, 2521,  901, 2170, 2520, 2143,
+      593, 3186, 3185, 2422, 2459, 2495, 2531,  634, 2555,  258,
+     2563, 2587, 3194, 2594, 2618, 2641, 3193, 2665, 2688, 3191,
+     3188, 3185, 2711, 1417, 2735, 2758, 3184,    0, 1475,    0,
+      723, 3172, 1482, 2782, 2805, 3147,    0, 1588,    0, 1595,
+        0,  724, 3146, 1927, 2829, 2852, 3135,    0,  661, 1934,
+     3122, 1290, 1425, 3114, 3111, 1490, 1510, 2876, 3101, 2900,
+      662, 3090, 3061,  636,  803,  653, 1290, 1427, 1492, 2095,
+     1604,  708,  849,  937, 2122,  872, 1605, 1944,  804, 1187,
+     1242, 2099,  936,  960, 1532, 2101,  874,  938, 1015,  962,
+     1014, 2124, 2163, 2942, 1016, 2965, 1038, 2988, 2154, 3012,
 
-     2144, 2519, 2472, 2164, 2185, 3318, 2463, 3342,  919, 2462,
-     2456,    0, 2235,    0, 2242,    0,  756, 2447, 2300, 3383,
-     3406, 2446,    0,  917,  940,  994,  995, 1923,  996, 1472,
-     1020, 1041, 2295, 1042, 1585,  918, 3431, 3454, 3478,  947,
-     3518, 3542, 3566, 2445, 3573, 3597, 3620, 2394, 3644, 3667,
-     2366, 3691, 3714, 2365, 2364, 2350, 3737, 2387, 3761, 3784,
-     2349,    0, 2425,    0,  956, 2348, 2462, 3808, 3831, 2344,
-        0, 2482,    0, 2489,    0,  988, 2343, 2496, 3855, 3878,
-     2325,    0,    0, 2503,    0, 2903,    0, 1035, 2324, 2910,
-     3902, 3925, 2305,    0,    0,  949, 3047, 2310, 2250, 2314,
+     3036, 3052, 3051, 3044,  686, 3049, 3085,  967, 3047, 3126,
+      969, 3046, 3045, 3020, 3017, 3167,  970, 2967, 1541, 1733,
+     3208, 2966, 3232, 1022, 2947, 2953, 2096, 2163, 2951, 2950,
+     2164, 2182, 3273, 2909, 3297, 1042, 2908, 2915, 1043, 2255,
+     2913, 2183, 2184, 2911, 2892, 2205, 2249, 3338, 2882, 3362,
+     1045, 2881, 2886,    0, 2263,    0, 2320,    0,  756, 2857,
+     2327, 3403, 3426, 2853,    0, 1061, 1062, 1087, 1111, 2337,
+     1188, 1943, 1189, 1244, 2376, 1534, 2377, 2336, 1109, 1243,
+     2402, 2013, 1306, 2096, 2378, 1446, 2375, 1245, 3451, 3474,
+     3498, 1066, 3538, 3562, 3586, 2834, 3593, 3617, 3640, 2830,
 
-     2309, 2308, 2315, 2335, 3949, 2284, 3973, 1025, 2280, 2286,
-     2378, 2379, 2380, 2146, 1067, 2252, 2317, 1090, 2381, 1065,
-     1089, 1145, 1147, 4015, 4039, 4048, 1168, 2260, 2259, 4066,
-     1046, 2258, 4107, 1096, 2255, 4148, 1099, 2254, 4189, 1100,
-     2221, 2220, 2219, 4229, 4253, 1129, 2215, 2433, 2434, 4294,
-     2214, 4318, 1152, 2213, 2203, 2615, 2662, 2202, 2201, 2918,
-     2919, 4359, 2190, 4383, 1176, 2178, 2181, 1177, 3054, 2162,
-     2922, 3062, 2132, 2102, 3075, 3081, 4424, 2092, 4448, 1201,
-     2090, 2097,    0, 1204, 3129, 2095, 3082, 3103, 2094, 2093,
-     3123, 3142, 4489, 2083, 4513, 1206, 2073, 2080,    0, 3170,
+     3664, 3687, 2811, 3711, 3734, 2810, 2806, 2791, 3757, 2445,
+     3781, 3804, 2789,    0, 2482,    0, 1008, 2787, 2502, 3828,
+     3851, 2744,    0, 2509,    0, 2516,    0, 1153, 2741, 2523,
+     3875, 3898, 2740,    0,    0, 2923,    0, 2930,    0, 1300,
+     2718, 3067, 3922, 3945, 2717,    0,    0, 1198, 3074, 2724,
+     2399, 2417, 2721, 2701, 2453, 2454, 3969, 2670, 3993, 1285,
+     2649, 2655, 2401, 2438, 3083, 2398, 1558, 2457, 2940, 1708,
+     3084, 1557, 1385, 1709, 1508, 1754, 1710, 1755, 1778, 3120,
+     1779, 3118, 1801, 1803, 1825, 4035, 4059, 4068, 1826, 2646,
+     2643, 4086, 1287, 2624, 4127, 1288, 2600, 4168, 1315, 2599,
 
-        0, 3235,    0, 1239, 2070, 3242, 4554, 4577, 2042,    0,
-     3287, 3288, 3352, 1169, 2418, 2124, 1286, 2419, 2294, 1426,
-     1512, 1223, 4602, 4626, 4635, 2041, 4652, 4676, 4699, 2040,
-     4723, 4746, 2039, 4770, 4793, 2038, 4817, 4840, 2036, 2035,
-     4864, 1265, 2034, 2033, 3305, 4905, 2010, 2009,    0, 3369,
-        0, 1335, 2008, 3501, 4929, 2007, 2005,    0, 3508,    0,
-     3996,    0, 1505, 2004, 4003, 4953, 2003, 1987,    0,    0,
-     4055,    0, 4089,    0, 1554, 1985, 4096, 4977, 1983, 1981,
-        0,    0, 4130,    0, 4137,    0, 1595, 1980, 4171, 5001,
-     1979, 1954,    0,    0, 1268, 4178, 1938, 3144, 3164, 1895,
+     4209, 1345, 2597, 2596, 2595, 4249, 4273, 1427, 2594, 2635,
+     2682, 4314, 2572, 4338, 1429, 2571, 2578, 2938, 2942, 2577,
+     2576, 3096, 3142, 4379, 2566, 4403, 1489, 2540, 2544, 1600,
+     3156, 2542, 3151, 3164, 2541, 2540, 3183, 3184, 4444, 2531,
+     4468, 1603, 2468, 2469,    0, 1605, 3255, 2438, 3203, 3205,
+     2372, 2371, 3249, 3268, 4509, 2343, 4533, 1606, 2341, 2348,
+        0, 3320,    0, 3327,    0, 1396, 2306, 3385, 4574, 4597,
+     2299,    0, 3095, 3096, 3178, 1827, 3122, 2399, 1848, 3420,
+     2959, 1849, 1850, 1872, 3248, 3380, 1874, 1896, 3490, 2014,
+     3492, 1959, 2016, 3337, 4622, 4646, 4655, 2275, 4672, 4696,
 
-     1852, 3183, 3185, 5025, 1843, 5049, 1297, 1842, 1827, 1688,
-     1689, 1711, 1539, 1225, 1760, 4187, 1538, 1366, 2420, 5091,
-     1794, 5108, 5132, 1405, 1775, 5173, 1408, 1772, 5214, 1409,
-     1771, 5255, 1469, 1748, 5296, 1472, 1747, 1728, 4215, 5337,
-     1727, 1726,    0, 1724, 3250, 3288, 5361, 1650, 1644, 1651,
-     3313, 3352, 1618, 1601, 3379, 3400, 5385, 1588, 1545, 1536,
-     1580, 4276, 1532, 3431, 3517, 1531, 1507, 3614, 3661, 5409,
-     1480, 1479, 1482,    0, 1585, 4283, 1442, 3708, 4199, 1421,
-     1418, 4200, 4224, 5433, 1409, 1374, 1380,    0, 1586, 4341,
-     1378, 4228, 4291, 1377, 1342, 4335, 4354, 5457, 1333, 1331,
+     4719, 2263, 4743, 4766, 2239, 4790, 4813, 2234, 4837, 4860,
+     2198, 2194, 4884, 1630, 2192, 2145, 3523, 4925, 2144, 2107,
+        0, 3530,    0, 1615, 2106, 4016, 4949, 2103, 2060,    0,
+     4023,    0, 4075,    0, 1639, 2059, 4109, 4973, 2058, 2055,
+        0,    0, 4116,    0, 4150,    0, 1669, 2000, 4157, 4997,
+     1999, 1976,    0,    0, 4191,    0, 4198,    0, 1748, 1951,
+     4232, 5021, 1945, 1913,    0,    0, 1660, 4239, 1917, 3335,
+     3399, 1914, 1897, 3400, 3420, 5045, 1882, 5069, 1661, 1842,
+     1846, 2102, 2177, 2200, 2289, 2103, 2612, 4283, 2226, 2473,
+     4266, 2680, 4348, 4267, 4331, 3249, 3271, 4289, 4332, 3399,
 
-     1309,    0, 4406,    0, 4413,    0, 1619, 1278, 4471, 5481,
-        0, 1273,    0, 1690, 1734, 1758, 1759, 1782, 1993, 4507,
-     4523, 5505, 1610,    0, 1272, 5546,    0, 1240, 5570,    0,
-     1215, 5594,    0, 1213, 5618,    0, 1185, 5642,    0,   75,
-     4356, 4421, 5666,  102,  137,  143,  203,  198, 4478,    0,
-     1649,  217,  250, 4540,    0, 4642,    0, 1822,  306,  317,
-        0, 4887,    0, 4894,    0, 1845,  341,  348,    0, 5072,
-        0, 5079,    0, 1869,  372,  412,    0, 5098,    0, 5155,
-        0, 1893,  414,  431,    0, 1640, 5162,  443, 4486, 4550,
-      470,  556, 4571, 4651, 5690,  551,    0,  583, 2382, 1783,
+     2610, 2611, 4396, 5111, 1815, 5128, 5152, 1662, 1814, 5193,
+     1689, 1811, 5234, 1736, 1795, 5275, 1879, 1791, 5316, 1880,
+     1747, 1744, 4365, 5357, 1741, 1698,    0, 1697, 3634, 3681,
+     5381, 1670, 1664, 1671, 3728, 4289, 1616, 1580, 4374, 4418,
+     5405, 1568, 1565, 1552, 1938, 4432, 1527, 4441, 4478, 1508,
+     1506, 4479, 4483, 5429, 1494, 1454, 1442,    0, 1940, 4497,
+     1438, 4506, 4543, 1437, 1400, 4544, 4548, 5453, 1390, 1389,
+     1363,    0, 1941, 4562, 1362, 4571, 4591,   83,  110, 4666,
+     4667, 5477,  195,  198,  225,    0, 4907,    0, 4914,    0,
+     2006,  307, 5092, 5501,    0,  348,    0, 2474, 2635, 2657,
 
-     1806, 1829, 5714,  600,  621,    0,    0,    0,    0,    0,
-        0, 5196,    0, 1933,  644,  646,    0, 4693, 4740,  702,
-      731,    0, 1641, 5203,  732, 4787, 4834,  760,  763,    0,
-        0, 1642, 5237,  797, 4902, 5107,  803,  820,    0,    0,
-     1669, 5244,  822, 5252, 5265,  824,  827,    0,    0, 1671,
-     5279,  868, 5293, 5306,  871,  873,    0,    0, 5320,    0,
-     5528,    0, 1956,  867,    0, 3102, 2983, 2180, 1807,    0,
-     7420,    0,    0,    0,    0,    0,    0, 5334, 5522,  877,
-      910,    0, 7420, 5536,    0, 7420,    0, 5737,    0, 7420,
-        0, 5744,    0, 7420,    0, 5751,    0, 7420,    0, 5758,
+     2659, 2681, 3003, 5107, 5162, 4670, 2703, 4291, 4356, 2682,
+     4376, 4923, 4443, 2728, 2729, 5108, 5163, 5525, 1943,    0,
+      372, 5566,    0,  399, 5590,    0,  418, 5614,    0,  480,
+     5638,    0,  520, 5662,    0,  544, 4671, 4713, 5686,  551,
+      580,  582,  610,  604, 5180,    0, 2061,  624,  643, 5216,
+        0, 5223,    0, 2062,  696,  697,    0, 5257,    0, 5264,
+        0, 2109,  698,  720,    0, 5298,    0, 5305,    0, 2142,
+      721,  749,    0, 5339,    0, 5346,    0, 2193,  750,  752,
+        0, 1995, 5548,  762, 4760, 4807,  763,  798, 4854, 5086,
+     5710,  793,    0,  804, 4508, 2751, 2752, 2774, 2775, 5146,
 
-        0, 7420,    0, 1672, 5765,  965, 5773, 5774,  990, 1986,
-        0, 1830, 3360, 1877,    0, 5774,    0, 1835, 5788,  992,
-        0, 1857, 5795, 1015,    0, 1859, 5802, 1036,    0, 1860,
-     5814, 1083,    0, 1918, 5821, 1108,    0, 5828,    0, 7420,
-     1940, 1920, 5835, 1135,    0,    0,    0,    0,    0,    0,
-     1921, 5842, 1141,    0,    0,    0,    0,    0,    0,    0,
-        0,    0, 7420, 5860, 5868, 5872, 5875, 5878, 5881, 5884,
-     5887, 5890, 5893, 5896, 5899, 5902, 5905, 5908, 5911, 5914,
-     5917, 5920, 5924, 5928, 5931, 5934, 5937, 5940, 5943, 5946,
-     5949, 5952, 5956, 5960, 5963, 5966, 5970, 5972, 5975, 5978,
+     2776, 2799, 2822, 2823, 5720, 2845, 5703, 5722, 2846, 3270,
+     3489, 5755,  820,  864,    0,    0,    0,    0,    0,    0,
+     5555,    0, 2282,  880,  887,    0, 5127, 5354,  897,  930,
+        0, 1997, 5739,  931, 5563, 5724,  934,  976,    0,    0,
+     2024, 5778,  985, 5752, 5772, 1012, 1039,    0,    0, 2151,
+     5792, 1063, 5787, 5788, 1102, 1103,    0,    0, 2181, 5802,
+     1107, 5800, 5810, 1132, 1160,    0,    0, 5814,    0, 5828,
+        0, 2347, 1176,    0, 5085, 3553, 2868, 2870, 3103, 5824,
+     5827, 5837, 5838, 5839, 5826, 3379, 5843, 2892, 4573, 5736,
+     2981,    0, 7856,    0,    0,    0,    0,    0,    0, 5845,
 
-     5981, 5984, 5987, 5990, 5993, 5996, 6000, 6002, 6005, 6009,
-     6014, 6018, 6021, 6025, 6028, 6031, 6034, 6037, 6040, 6043,
-     6046, 6050, 6054, 6057, 6061, 6065, 6070, 6074, 6076, 6080,
-     6083, 6087, 6090, 6093, 6097, 6099, 6102, 6105, 6108, 6111,
-     6114, 6117, 6120, 6123, 6126, 6130, 6132, 6135, 6138, 6141,
-     6145, 6147, 6150, 6153, 6158, 6162, 6167, 6171, 6173, 6177,
-     6180, 6184, 6189, 6193, 6196, 6199, 6202, 6205, 6208, 6211,
-     6214, 6218, 6222, 6225, 6229, 6233, 6238, 6242, 6244, 6248,
-     6251, 6255, 6258, 6263, 6267, 6272, 6276, 6278, 6282, 6285,
-     6289, 6292, 6295, 6298, 6302, 6304, 6307, 6312, 6316, 6319,
+     5847, 1190, 1235,    0, 7856, 5871,    0, 7856,    0, 5887,
+        0, 7856,    0, 5894,    0, 7856,    0, 5901,    0, 7856,
+        0, 5908,    0, 7856,    0, 2270, 5915, 1236, 5923, 5924,
+     1237, 2414,    0, 2980, 5086, 2982, 3004, 5926, 5356, 5565,
+     3201, 5849, 4287, 3005, 5927, 5106, 5850, 3006, 5928,    0,
+     5927,    0, 2272, 5954, 1240,    0, 2273, 5964, 1264,    0,
+     2338, 5971, 1306,    0, 2396, 5978, 1322,    0, 2531, 5985,
+     1356,    0, 5992,    0, 7856, 3177, 6001, 3442, 3444, 3467,
+     6002, 6004, 6005, 6008, 3491, 6006, 3378, 6007, 2532, 6007,
+     1357,    0,    0,    0,    0,    0,    0, 2533, 6043, 1361,
 
-     6322, 6325, 6328, 6331, 6334, 6337, 6340, 6344, 6346, 6349,
-     6352, 6355, 6359, 6361, 6364, 6367, 6370, 6373, 6377, 6379,
-     6382, 6385, 6388, 6393, 6397, 6402, 6406, 6408, 6412, 6415,
-     6419, 6424, 6428, 6431, 6434, 6437, 6440, 6443, 6446, 6449,
-     6453, 6457, 6460, 6464, 6468, 6473, 6477, 6479, 6483, 6486,
-     6490, 6493, 6498, 6502, 6507, 6511, 6513, 6517, 6520, 6524,
-     6527, 6530, 6535, 6539, 6544, 6548, 6550, 6554, 6557, 6561,
-     6564, 6567, 6570, 6574, 6576, 6579, 6584, 6588, 6591, 6594,
-     6597, 6600, 6603, 6606, 6609, 6612, 6615, 6618, 6621, 6625,
-     6627, 6630, 6633, 6636, 6639, 6643, 6645, 6648, 6651, 6654,
+     6016, 6037, 5852, 6039, 3554, 6040, 3555, 3556, 6017, 6052,
+     6056, 3419,    0,    0,    0,    0,    0,    0,    0, 3466,
+     6059, 3611, 3658, 3705, 6060, 6062, 6063, 3468, 6065, 6066,
+        0,    0, 3609, 3610, 3634, 3656, 6067, 3680, 6068, 3681,
+     6073, 6082, 6092, 6095, 3727, 6101, 3728, 6103, 3749, 5102,
+     3773, 3774, 3797, 6106, 6111, 6115, 3775, 6116, 6122, 3820,
+     6123, 6126, 6128, 3822, 6114, 6142, 6148, 3844, 3845, 6152,
+     6153, 6154, 6155, 3869, 3890, 6158, 3891, 6162, 3914, 6163,
+     6167, 3915, 3916, 3938, 6169, 6177, 4737, 6191, 3939, 6182,
+     6194, 6197, 6198, 3961, 6204, 6203, 6205, 3963, 6206, 3985,
 
-     6657, 6660, 6664, 6666, 6669, 6672, 6675, 6678, 6681, 6685,
-     6687, 6690, 6693, 6696, 6699, 6704, 6708, 6713, 6717, 6719,
-     6723, 6726, 6730, 6735, 6739, 6742, 6745, 6748, 6751, 6754,
-     6757, 6760, 6763, 6766, 6770, 6774, 6777, 6781, 6785, 6790,
-     6794, 6796, 6800, 6803, 6807, 6810, 6815, 6819, 6824, 6828,
-     6830, 6834, 6837, 6841, 6844, 6847, 6852, 6856, 6861, 6865,
-     6867, 6871, 6874, 6878, 6881, 6884, 6889, 6893, 6898, 6902,
-     6904, 6908, 6911, 6915, 6918, 6921, 6924, 6928, 6930, 6933,
-     6936, 6941, 6945, 6948, 6951, 6954, 6957, 6960, 6963, 6966,
-     6969, 6972, 6975, 6978, 6982, 6986, 6989, 6992, 6996, 6999,
+     4084, 6213, 3987, 6218, 6227, 4125, 4613, 6219, 4308, 4032,
+     6228, 4033, 4615, 4085, 6238, 6229, 6240, 4784, 4166, 6239,
+     4207, 6241, 6268, 4208, 4665, 4666, 4669, 7856, 6296, 6304,
+     6308, 6311, 6314, 6317, 6320, 6323, 6326, 6329, 6332, 6335,
+     6338, 6341, 6344, 6347, 6350, 6353, 6356, 6360, 6364, 6367,
+     6370, 6373, 6376, 6379, 6382, 6385, 6388, 6392, 6396, 6399,
+     6402, 6406, 6408, 6411, 6414, 6417, 6420, 6423, 6426, 6429,
+     6432, 6436, 6438, 6441, 6445, 6450, 6454, 6457, 6461, 6464,
+     6467, 6470, 6473, 6476, 6479, 6482, 6486, 6490, 6493, 6497,
+     6501, 6506, 6510, 6512, 6516, 6519, 6523, 6526, 6529, 6533,
 
-     7002, 7006, 7008, 7011, 7014, 7018, 7020, 7023, 7026, 7029,
-     7033, 7035, 7038, 7041, 7044, 7048, 7050, 7053, 7056, 7059,
-     7063, 7065, 7068, 7071, 7076, 7080, 7085, 7089, 7091, 7095,
-     7098, 7102, 7107, 7111, 7114, 7117, 7120, 7123, 7126, 7129,
-     7132, 7135, 7139, 7141, 7144, 7148, 7153, 7157, 7158, 7161,
-     7166, 7170, 7175, 7179, 7180, 7183, 7186, 7191, 7195, 7200,
-     7204, 7205, 7208, 7211, 7216, 7220, 7225, 7229, 7230, 7233,
-     7236, 7241, 7245, 7250, 7254, 7255, 7258, 7261, 7264, 7268,
-     7270, 7275, 7279, 7282, 7285, 7288, 7291, 7294, 7297, 7301,
-     7306, 7310, 7311, 7314, 7317, 7320, 7323, 7326, 7329, 7332,
+     6535, 6538, 6541, 6544, 6547, 6550, 6553, 6556, 6559, 6562,
+     6566, 6568, 6571, 6574, 6577, 6581, 6583, 6586, 6589, 6594,
+     6598, 6603, 6607, 6609, 6613, 6616, 6620, 6625, 6629, 6632,
+     6635, 6638, 6641, 6644, 6647, 6650, 6654, 6658, 6661, 6665,
+     6669, 6674, 6678, 6680, 6684, 6687, 6691, 6694, 6699, 6703,
+     6708, 6712, 6714, 6718, 6721, 6725, 6728, 6731, 6734, 6738,
+     6740, 6743, 6748, 6752, 6755, 6758, 6761, 6764, 6767, 6770,
+     6773, 6776, 6780, 6782, 6785, 6788, 6791, 6795, 6797, 6800,
+     6803, 6806, 6809, 6813, 6815, 6818, 6821, 6824, 6829, 6833,
+     6838, 6842, 6844, 6848, 6851, 6855, 6860, 6864, 6867, 6870,
 
-     7335, 7338, 7341, 7346, 7350, 7353, 7356, 7359, 7363, 7367,
-     7371, 7375, 7379, 7382, 7385, 7389, 7392, 7395, 7398, 7401,
-     7404, 7408, 7411
+     6873, 6876, 6879, 6882, 6885, 6889, 6893, 6896, 6900, 6904,
+     6909, 6913, 6915, 6919, 6922, 6926, 6929, 6934, 6938, 6943,
+     6947, 6949, 6953, 6956, 6960, 6963, 6966, 6971, 6975, 6980,
+     6984, 6986, 6990, 6993, 6997, 7000, 7003, 7006, 7010, 7012,
+     7015, 7020, 7024, 7027, 7030, 7033, 7036, 7039, 7042, 7045,
+     7048, 7051, 7054, 7057, 7061, 7063, 7066, 7069, 7072, 7075,
+     7079, 7081, 7084, 7087, 7090, 7093, 7096, 7100, 7102, 7105,
+     7108, 7111, 7114, 7117, 7121, 7123, 7126, 7129, 7132, 7135,
+     7140, 7144, 7149, 7153, 7155, 7159, 7162, 7166, 7171, 7175,
+     7178, 7181, 7184, 7187, 7190, 7193, 7196, 7199, 7202, 7206,
+
+     7210, 7213, 7217, 7221, 7226, 7230, 7232, 7236, 7239, 7243,
+     7246, 7251, 7255, 7260, 7264, 7266, 7270, 7273, 7277, 7280,
+     7283, 7288, 7292, 7297, 7301, 7303, 7307, 7310, 7314, 7317,
+     7320, 7325, 7329, 7334, 7338, 7340, 7344, 7347, 7351, 7354,
+     7357, 7360, 7364, 7366, 7369, 7372, 7377, 7381, 7384, 7387,
+     7390, 7393, 7396, 7399, 7402, 7405, 7408, 7411, 7414, 7418,
+     7422, 7425, 7428, 7432, 7435, 7438, 7442, 7444, 7447, 7450,
+     7454, 7456, 7459, 7462, 7465, 7469, 7471, 7474, 7477, 7480,
+     7484, 7486, 7489, 7492, 7495, 7499, 7501, 7504, 7507, 7512,
+     7516, 7521, 7525, 7527, 7531, 7534, 7538, 7543, 7547, 7550,
+
+     7553, 7556, 7559, 7562, 7565, 7568, 7571, 7575, 7577, 7580,
+     7584, 7589, 7593, 7594, 7597, 7602, 7606, 7611, 7615, 7616,
+     7619, 7622, 7627, 7631, 7636, 7640, 7641, 7644, 7647, 7652,
+     7656, 7661, 7665, 7666, 7669, 7672, 7677, 7681, 7686, 7690,
+     7691, 7694, 7697, 7700, 7704, 7706, 7711, 7715, 7718, 7721,
+     7724, 7727, 7730, 7733, 7737, 7742, 7746, 7747, 7750, 7753,
+     7756, 7759, 7762, 7765, 7768, 7771, 7774, 7777, 7782, 7786,
+     7789, 7792, 7795, 7799, 7803, 7807, 7811, 7815, 7818, 7821,
+     7825, 7828, 7831, 7834, 7837, 7840, 7844, 7847
     } ;
 
-static yyconst flex_int16_t yy_def[1924] =
+static yyconst flex_int16_t yy_def[2189] =
     {   0,
-     1463,    1, 1463, 1463, 1463, 1463, 1463, 1463, 1464, 1463,
-     1463, 1463, 1463, 1463,   14, 1463, 1463, 1463, 1463,   14,
-       20, 1465,   20,   20,   20,   20,   20,   20,   21,   21,
+     1728,    1, 1728, 1728, 1728, 1728, 1728, 1728, 1729, 1728,
+     1728, 1728, 1728, 1728,   14, 1728, 1728, 1728, 1728,   14,
+       20, 1730,   20,   20,   20,   20,   20,   20,   21,   21,
        21,   21,   21,   21,   21,   21,   21,   21,   21,   21,
-       21,   21, 1463, 1463, 1463, 1466, 1463,   21,   21,   20,
-     1467,   50,   21,   21,   21, 1463, 1463, 1463, 1463, 1463,
-     1463,   49, 1465, 1465,   52,   52,   52,   21,   21,   21,
+       21,   21, 1728, 1728, 1728, 1731, 1728,   21,   21,   20,
+     1732,   50,   21,   21,   21, 1728, 1728, 1728, 1728, 1728,
+     1728,   49, 1730, 1730,   52,   52,   52,   21,   21,   21,
        21,   52,   21,   21,   52,   21,   21,   21,   52,   21,
        21,   21,   21,   21,   52,   21,   21,   21,   21,   21,
        21,   21,   21,   21,   21,   21,   21,   21,   21,   21,
@@ -816,8 +880,8 @@
        21,   21,   21,   21,   21,   21,   21,   21,   21,   21,
        21,   21,   21,   21,   21,   21,   21,   21,   21,   21,
        21,   21,   21,   21,   21,   21,   21,   21,   21,   21,
-     1463, 1463,   21,   21,  154,   21,   21,  157, 1468, 1463,
-       54, 1463,  162, 1469,   21,   21,  158,   21,   21,   21,
+     1728, 1728,   21,   21,  154,   21,   21,  157, 1733, 1728,
+       54, 1728,  162, 1734,   21,   21,  158,   21,   21,   21,
       158,   21,   21,   21,   21,   21,   21,  158,   21,   21,
        21,   21,   21,   21,   21,  158,   21,   21,   21,   21,
        21,   21,   21,   21,   21,   21,   21,   21,   21,   21,
@@ -828,9 +892,9 @@
        21,   21,   21,   21,   21,   21,   21,   21,   21,   21,
        21,   21,   21,   21,   21,   21,   21,   21,   21,   21,
        21,   21,   21,   21,   21,   21,   21,   21,   21,   21,
-       21,   21,   21,   21,   21,  262,  263,  158, 1470,  268,
-     1471, 1472, 1463,  273, 1473, 1474, 1463, 1463, 1463, 1475,
-     1476,   21,   21,   21,   21,   21,   21,   21,   21,   21,
+       21,   21,   21,   21,   21,  262,  263,  158, 1735,  268,
+     1736, 1737, 1728,  273, 1738, 1739, 1728, 1728, 1728, 1740,
+     1741,   21,   21,   21,   21,   21,   21,   21,   21,   21,
        21,   21,   21,   21,   21,   21,   21,   21,   21,   21,
 
        21,   21,   21,   21,   21,   21,   21,   21,   21,   21,
@@ -838,183 +902,211 @@
        21,   21,   21,   21,   21,   21,   21,   21,   21,   21,
        21,   21,   21,   21,   21,   21,   21,   21,   21,   21,
        21,   21,   21,   21,   21,   21,   21,   21,   21,   21,
-      350,   21,  263,  265,  263,  265,  265,  357, 1477, 1463,
-      356, 1478, 1479, 1463, 1463, 1463, 1463, 1480, 1481, 1482,
-     1483, 1483, 1463, 1484, 1463,  375, 1485, 1476,   21,   21,
+      350,   21,  263,  265,  263,  265,  265,  357, 1742, 1728,
+      356, 1743, 1744, 1728, 1728, 1728, 1728, 1745, 1746, 1747,
+     1748, 1748, 1728, 1749, 1728,  375, 1750, 1741,   21,   21,
        21,   21,   21,   21,   21,   21,   21,   21,   21,   21,
        21,   21,   21,   21,   21,   21,   21,   21,   21,   21,
 
        21,   21,   21,   21,   21,   21,   21,   21,   21,   21,
        21,   21,   21,   21,   21,   21,   21,   21,   21,   21,
        21,   21,   21,   21,   21,   21,   21,   21,   21,   21,
-       21,   21,   21,  430,  431,  431,  436,  430,  357,  439,
-     1486, 1487, 1463,  443, 1488, 1463, 1489, 1490, 1463,  449,
-     1491, 1492, 1493, 1493, 1463, 1494, 1463,  457, 1495, 1481,
-     1463, 1463, 1496, 1497, 1463, 1463, 1463, 1463, 1498, 1499,
+       21,   21,   21,   21,   21,  432,  433,  433,  438,  432,
+      357,  441, 1751, 1752, 1728,  445, 1753, 1728, 1754, 1755,
+     1728,  451, 1756, 1757, 1758, 1758, 1728, 1759, 1728,  459,
+     1760, 1746, 1728, 1728, 1761, 1762, 1728, 1728, 1728, 1728,
+     1763, 1764,   21,   21,   21,   21,   21,   21,   21,   21,
+       21,   21,   21,   21,   21,   21,   21,   21,   21,   21,
+       21,   21,   21,   21,   21,   21,   21,   21,   21,   21,
+
+       21,   21,   21,   21,   21,   21,   21,   21,   21,   21,
+       21,   21,   21,   21,   21,   21,   21,   21,   21,   21,
+       21,   21,  522,   21,  433,  435,  433,  433,  528,  441,
+      530, 1765, 1728, 1728, 1728, 1766, 1767, 1768, 1728, 1728,
+     1728, 1728, 1769, 1770, 1728, 1771, 1772, 1728, 1728, 1728,
+     1728, 1773, 1774, 1775, 1775, 1761, 1762, 1776, 1776, 1728,
+     1777, 1728,  562, 1778, 1779,   21,   21,   21,   21,   21,
        21,   21,   21,   21,   21,   21,   21,   21,   21,   21,
        21,   21,   21,   21,   21,   21,   21,   21,   21,   21,
        21,   21,   21,   21,   21,   21,   21,   21,   21,   21,
 
        21,   21,   21,   21,   21,   21,   21,   21,   21,   21,
-       21,   21,   21,   21,   21,  515,   21,  431,  433,  431,
-      431,  521,  439,  523, 1500, 1463, 1463, 1463, 1501, 1502,
-     1503, 1463, 1463, 1463, 1463, 1504, 1505, 1463, 1506, 1507,
-     1463, 1463, 1463, 1463, 1508, 1509, 1510, 1510, 1496, 1497,
-     1511, 1511, 1463, 1512, 1463,  555, 1513, 1514,   21,   21,
-       21,   21,   21,   21,   21,   21,   21,   21,   21,   21,
-       21,   21,   21,   21,   21,   21,   21,   21,   21,   21,
-       21,   21,   21,   21,   21,   21,   21,   21,   21,   21,
-       21,   21,   21,   21,   21,   21,   21,   21,   21,   21,
+       21,   21,   21,   21,   21,   21,   21,   21,  616,  616,
+      620,  530,  622, 1780, 1781, 1728,  626, 1782, 1728,  629,
+     1783, 1728, 1784, 1785, 1728,  635, 1786, 1787, 1787, 1728,
+     1788, 1728,  642, 1789, 1790, 1791, 1791, 1792, 1793, 1794,
+     1794, 1728, 1795, 1728,  654, 1796, 1797, 1728, 1798, 1728,
+     1799, 1800, 1728, 1728, 1728, 1728, 1801, 1802,  623,  669,
+      669,  669,  669,  669,  669,  669,  669,  669,  669,  669,
+      669,  669,  669,  669,  669,  669,  669,  669,  669,  669,
+      669,  669,  669,  669,  669,  669,  669,  669,  669,  669,
 
-      598,  598,  602,  523,  604, 1515, 1516, 1463,  608, 1517,
-     1463,  611, 1518, 1463, 1519, 1520, 1463,  617, 1521, 1522,
-     1522, 1463, 1523, 1463,  624, 1524, 1525, 1526, 1526, 1527,
-     1528, 1529, 1529, 1463, 1530, 1463,  636, 1531, 1532, 1463,
-     1533, 1463, 1534, 1535, 1463, 1463, 1463, 1463, 1536, 1537,
-      605,  651,  651,  651,  651,  651,  651,  651,  651,  651,
-      651,  651,  651,  651,  651,  651,  651,  651,  651,  651,
-      651,  651,  651,  651,  651,  651,  676,  676,  676,  651,
-      676,  681, 1538, 1463, 1463, 1463, 1539, 1463, 1463, 1540,
-     1541, 1542, 1463, 1463, 1463, 1463, 1543, 1544, 1463, 1545,
+      669,  669,  669,  669,  669,  669,  706,  706,  706,  669,
+      706,  711, 1803, 1728, 1728, 1728, 1804, 1728, 1728, 1805,
+     1806, 1807, 1728, 1728, 1728, 1728, 1808, 1809, 1728, 1810,
+     1811, 1728, 1728, 1728, 1728, 1812, 1813, 1728, 1814, 1728,
+     1815, 1816, 1728, 1728, 1728, 1728, 1817, 1818, 1819, 1728,
+     1820, 1821, 1821, 1822, 1823, 1824, 1824, 1728, 1825, 1728,
+      760, 1826, 1827, 1828, 1828, 1828, 1828, 1828, 1828, 1828,
+     1828, 1828, 1828, 1828, 1828, 1828, 1828, 1828, 1828, 1828,
+     1828, 1828, 1828, 1828, 1828, 1828, 1828, 1828, 1828, 1828,
+     1828, 1828, 1828, 1828, 1828,  794, 1828,  794,  798,  798,
 
-     1546, 1463, 1463, 1463, 1463, 1547, 1548, 1463, 1549, 1463,
-     1550, 1551, 1463, 1463, 1463, 1463, 1552, 1553, 1554, 1463,
-     1555, 1556, 1556, 1557, 1558, 1559, 1559, 1463, 1560, 1463,
-      730, 1561, 1562, 1563, 1563, 1563, 1563, 1563, 1563, 1563,
-     1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563, 1563,
-     1563, 1563, 1563,  752, 1563,  752,  756,  756,  758, 1564,
-     1565, 1463,  762, 1566, 1463,  765, 1567, 1463,  768, 1568,
-     1463, 1569, 1570, 1463,  774, 1571, 1572, 1572, 1463, 1573,
-     1463,  781, 1574, 1575, 1576, 1576, 1577, 1578, 1579, 1579,
-     1463, 1580, 1463,  793, 1581, 1582, 1583, 1463, 1584, 1585,
+      800, 1829, 1830, 1728,  804, 1831, 1728,  807, 1832, 1728,
+      810, 1833, 1728, 1834, 1835, 1728,  816, 1836, 1837, 1837,
+     1728, 1838, 1728,  823, 1839, 1840, 1841, 1841, 1842, 1843,
+     1844, 1844, 1728, 1845, 1728,  835, 1846, 1847, 1848, 1728,
+     1849, 1850, 1850, 1851, 1852, 1853, 1853, 1728, 1854, 1728,
+      850, 1855, 1856, 1857, 1728, 1858, 1728, 1859, 1860, 1728,
+     1728, 1728, 1728, 1861, 1862, 1863, 1863, 1863, 1863, 1863,
+     1863, 1863, 1863, 1863, 1863, 1863, 1863, 1863, 1863, 1863,
+     1863, 1863, 1863, 1863, 1863, 1863, 1863, 1863, 1863,  889,
+      889,  891,  889,  889,  894, 1864, 1728, 1728, 1728, 1865,
 
-     1585, 1586, 1587, 1588, 1588, 1463, 1589, 1463,  808, 1590,
-     1591, 1592, 1463, 1593, 1463, 1594, 1595, 1463, 1463, 1463,
-     1463, 1596, 1597, 1598, 1598, 1598, 1598, 1598, 1598, 1598,
-     1598, 1598, 1598, 1598, 1598, 1598, 1598,  837,  837,  839,
-      837,  837,  842, 1599, 1463, 1463, 1463, 1600, 1463, 1463,
-     1601, 1463, 1463, 1602, 1603, 1604, 1463, 1463, 1463, 1463,
-     1605, 1606, 1463, 1607, 1608, 1463, 1463, 1463, 1463, 1609,
-     1610, 1463, 1611, 1463, 1612, 1613, 1463, 1463, 1463, 1463,
-     1614, 1615, 1616, 1463, 1617, 1463, 1618, 1619, 1463, 1463,
-     1463, 1463, 1620, 1621, 1622, 1623, 1463, 1624, 1625, 1625,
+     1728, 1728, 1866, 1728, 1728, 1867, 1868, 1869, 1728, 1728,
+     1728, 1728, 1870, 1871, 1728, 1872, 1873, 1728, 1728, 1728,
+     1728, 1874, 1875, 1728, 1876, 1728, 1877, 1878, 1728, 1728,
+     1728, 1728, 1879, 1880, 1881, 1728, 1882, 1728, 1883, 1884,
+     1728, 1728, 1728, 1728, 1885, 1886, 1887, 1888, 1728, 1889,
+     1890, 1890, 1891, 1892, 1893, 1893, 1728, 1894, 1728,  959,
+     1895, 1896, 1897, 1897, 1897, 1897, 1897, 1897, 1897, 1897,
+     1897, 1897, 1897, 1897, 1897, 1897, 1897, 1897, 1897, 1897,
+     1897, 1897, 1897, 1897, 1897, 1897,  986, 1897, 1897, 1898,
+     1899, 1728,  992, 1900, 1728,  995, 1901, 1728,  998, 1902,
 
-     1626, 1627, 1628, 1628, 1463, 1629, 1463,  907, 1630, 1631,
-     1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632,
-     1632, 1632, 1632, 1632,  924, 1632, 1632, 1633, 1634, 1463,
-      930, 1635, 1463,  933, 1636, 1463,  936, 1637, 1463,  939,
-     1638, 1463, 1639, 1463, 1463,  945, 1640, 1641, 1641, 1463,
-     1642, 1463,  952, 1643, 1644, 1645, 1645, 1646, 1647, 1648,
-     1648, 1463, 1649, 1463,  964, 1650, 1651, 1652, 1463, 1653,
-     1654, 1654, 1655, 1656, 1657, 1657, 1463, 1658, 1463,  979,
-     1659, 1660, 1661, 1662, 1463, 1663, 1664, 1664, 1665, 1666,
-     1667, 1667, 1463, 1668, 1463,  995, 1669, 1670, 1671, 1463,
+     1728, 1001, 1903, 1728, 1904, 1728, 1728, 1007, 1905, 1906,
+     1906, 1728, 1907, 1728, 1014, 1908, 1909, 1910, 1910, 1911,
+     1912, 1913, 1913, 1728, 1914, 1728, 1026, 1915, 1916, 1917,
+     1728, 1918, 1919, 1919, 1920, 1921, 1922, 1922, 1728, 1923,
+     1728, 1041, 1924, 1925, 1926, 1927, 1728, 1928, 1929, 1929,
+     1930, 1931, 1932, 1932, 1728, 1933, 1728, 1057, 1934, 1935,
+     1936, 1728, 1937, 1728, 1938, 1939, 1728, 1728, 1728, 1728,
+     1940, 1941, 1942, 1942, 1942, 1942, 1942, 1942, 1942, 1942,
+     1942, 1942, 1942, 1942, 1942, 1942, 1942, 1942, 1942, 1942,
+     1942, 1942, 1942, 1942, 1942, 1095, 1942, 1943, 1728, 1728,
 
-     1672, 1463, 1673, 1674, 1463, 1463, 1463, 1463, 1675, 1676,
-     1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677,
-     1677, 1677, 1677, 1023, 1677, 1678, 1463, 1463, 1463, 1679,
-     1463, 1463, 1680, 1463, 1463, 1681, 1463, 1463, 1682, 1683,
-     1463, 1041, 1684, 1685, 1463, 1463, 1686, 1687, 1688, 1463,
-     1689, 1690, 1463, 1463, 1463, 1691, 1692, 1693, 1463, 1694,
-     1463, 1695, 1696, 1463, 1463, 1463, 1697, 1698, 1699, 1700,
-     1463, 1701, 1463, 1702, 1703, 1463, 1463, 1463, 1704, 1705,
-     1706, 1707, 1463, 1708, 1463, 1709, 1710, 1463, 1463, 1463,
-     1711, 1712, 1713, 1714, 1715, 1463, 1716, 1717, 1717, 1718,
+     1728, 1944, 1728, 1728, 1945, 1728, 1728, 1946, 1728, 1728,
+     1947, 1948, 1728, 1113, 1949, 1950, 1728, 1728, 1951, 1952,
+     1953, 1728, 1954, 1955, 1728, 1728, 1728, 1956, 1957, 1958,
+     1728, 1959, 1728, 1960, 1961, 1728, 1728, 1728, 1962, 1963,
+     1964, 1965, 1728, 1966, 1728, 1967, 1968, 1728, 1728, 1728,
+     1969, 1970, 1971, 1972, 1728, 1973, 1728, 1974, 1975, 1728,
+     1728, 1728, 1976, 1977, 1978, 1979, 1980, 1728, 1981, 1982,
+     1982, 1983, 1984, 1985, 1985, 1728, 1986, 1728, 1178, 1987,
+     1988, 1989, 1989, 1989, 1989, 1989, 1989, 1989, 1989, 1989,
+     1989, 1989, 1989, 1989, 1989, 1989, 1989, 1989, 1989, 1989,
 
-     1719, 1720, 1720, 1463, 1721, 1463, 1106, 1722, 1723, 1724,
-     1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724,
-     1725, 1463, 1463, 1123, 1726, 1463, 1126, 1727, 1463, 1129,
-     1728, 1463, 1132, 1729, 1463, 1135, 1730, 1463, 1463, 1463,
-     1731, 1732, 1733, 1734, 1735, 1735, 1463, 1736, 1737, 1738,
-     1739, 1739, 1740, 1741, 1742, 1742, 1463, 1743, 1744, 1745,
-     1746, 1463, 1747, 1748, 1748, 1749, 1750, 1751, 1751, 1463,
-     1752, 1753, 1754, 1755, 1756, 1463, 1757, 1758, 1758, 1759,
-     1760, 1761, 1761, 1463, 1762, 1763, 1764, 1765, 1766, 1463,
-     1767, 1768, 1768, 1769, 1770, 1771, 1771, 1463, 1772, 1773,
+     1989, 1989, 1989, 1989, 1990, 1728, 1728, 1207, 1991, 1728,
+     1210, 1992, 1728, 1213, 1993, 1728, 1216, 1994, 1728, 1219,
+     1995, 1728, 1728, 1728, 1996, 1997, 1998, 1999, 2000, 2000,
+     1728, 2001, 2002, 2003, 2004, 2004, 2005, 2006, 2007, 2007,
+     1728, 2008, 2009, 2010, 2011, 1728, 2012, 2013, 2013, 2014,
+     2015, 2016, 2016, 1728, 2017, 2018, 2019, 2020, 2021, 1728,
+     2022, 2023, 2023, 2024, 2025, 2026, 2026, 1728, 2027, 2028,
+     2029, 2030, 2031, 1728, 2032, 2033, 2033, 2034, 2035, 2036,
+     2036, 1728, 2037, 2038, 2039, 2040, 1728, 2041, 1728, 2042,
+     2043, 1728, 1728, 1728, 2044, 2045, 2046, 2047, 2047, 2047,
 
-     1774, 1775, 1463, 1776, 1463, 1777, 1778, 1463, 1463, 1463,
-     1779, 1780, 1781, 1782, 1782, 1782, 1782, 1782, 1782, 1782,
-     1782, 1463, 1222, 1783, 1784, 1463, 1785, 1786, 1463, 1787,
-     1788, 1463, 1789, 1790, 1463, 1791, 1792, 1463, 1793, 1794,
-     1795, 1795, 1463, 1796, 1797, 1798, 1799, 1800, 1463, 1801,
-     1802, 1463, 1803, 1463, 1804, 1463, 1805, 1806, 1463, 1807,
-     1808, 1463, 1809, 1463, 1810, 1811, 1463, 1812, 1813, 1463,
-     1814, 1463, 1815, 1816, 1463, 1817, 1818, 1463, 1819, 1463,
-     1820, 1821, 1463, 1822, 1823, 1824, 1463, 1825, 1826, 1826,
-     1827, 1828, 1829, 1829, 1463, 1830, 1831, 1832, 1833, 1833,
+     2047, 2047, 2047, 2047, 2047, 2047, 2047, 2047, 2047, 2047,
+     2047, 2047, 2047, 2047, 2047, 2047, 2047, 1728, 1318, 2048,
+     2049, 1728, 2050, 2051, 1728, 2052, 2053, 1728, 2054, 2055,
+     1728, 2056, 2057, 1728, 2058, 2059, 2060, 2060, 1728, 2061,
+     2062, 2063, 2064, 2065, 1728, 2066, 2067, 1728, 2068, 1728,
+     2069, 1728, 2070, 2071, 1728, 2072, 2073, 1728, 2074, 1728,
+     2075, 2076, 1728, 2077, 2078, 1728, 2079, 1728, 2080, 2081,
+     1728, 2082, 2083, 1728, 2084, 1728, 2085, 2086, 1728, 2087,
+     2088, 2089, 1728, 2090, 2091, 2091, 2092, 2093, 2094, 2094,
+     1728, 2095, 2096, 2097, 2098, 2098, 2098, 2098, 2098, 2098,
 
-     1833, 1833, 1463, 1834, 1835, 1836, 1837, 1838, 1839, 1840,
-     1841, 1463, 1842, 1843, 1463, 1844, 1845, 1846, 1846, 1847,
-     1848, 1849, 1850, 1463, 1851, 1852, 1852, 1853, 1854, 1855,
-     1856, 1857, 1463, 1858, 1859, 1859, 1860, 1861, 1862, 1863,
-     1864, 1463, 1865, 1866, 1866, 1867, 1868, 1869, 1870, 1871,
-     1463, 1872, 1873, 1873, 1874, 1875, 1876, 1877, 1463, 1878,
-     1463, 1879, 1880, 1463, 1881, 1882, 1882, 1882, 1882, 1883,
-     1463, 1884, 1885, 1886, 1887, 1888, 1889, 1890, 1890, 1891,
-     1892, 1893, 1463, 1463, 1894, 1463, 1895, 1463, 1896, 1463,
-     1897, 1463, 1898, 1463, 1899, 1463, 1900, 1463, 1901, 1463,
+     2098, 2098, 2098, 2098, 2098, 2098, 2098, 2098, 2098, 2098,
+     2098, 1728, 2099, 2100, 2101, 2102, 2103, 2104, 2105, 2106,
+     1728, 2107, 2108, 1728, 2109, 2110, 2111, 2111, 2112, 2113,
+     2114, 2115, 1728, 2116, 2117, 2117, 2118, 2119, 2120, 2121,
+     2122, 1728, 2123, 2124, 2124, 2125, 2126, 2127, 2128, 2129,
+     1728, 2130, 2131, 2131, 2132, 2133, 2134, 2135, 2136, 1728,
+     2137, 2138, 2138, 2139, 2140, 2141, 2142, 1728, 2143, 1728,
+     2144, 2145, 1728, 2146, 2147, 2147, 2147, 2147, 2147, 2147,
+     2147, 2147, 2147, 2147, 2147, 2147, 2147, 2147, 2147, 2147,
+     2147, 2148, 1728, 2149, 2150, 2151, 2152, 2153, 2154, 2155,
 
-     1902, 1463, 1877, 1903, 1463, 1878, 1904, 1904, 1879, 1880,
-     1905, 1882, 1882, 1882, 1906, 1463, 1907, 1908, 1463, 1894,
-     1895, 1909, 1463, 1896, 1897, 1910, 1463, 1898, 1899, 1911,
-     1463, 1900, 1901, 1912, 1463, 1902, 1913, 1463, 1914, 1463,
-     1882, 1915, 1463, 1907, 1916, 1917, 1918, 1919, 1920, 1913,
-     1921, 1463, 1914, 1922, 1916, 1917, 1918, 1919, 1920, 1923,
-     1922, 1923,    0, 1463, 1463, 1463, 1463, 1463, 1463, 1463,
-     1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463,
-     1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463,
-     1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463,
+     2155, 2156, 2157, 2158, 1728, 1728, 2159, 1728, 2160, 1728,
+     2161, 1728, 2162, 1728, 2163, 1728, 2164, 1728, 2165, 1728,
+     2166, 1728, 2167, 1728, 2142, 2168, 1728, 2143, 2169, 2169,
+     2144, 2145, 2170, 2147, 2147, 2147, 2147, 2147, 2147, 2147,
+     2147, 2147, 2147, 2147, 2147, 2147, 2147, 2147, 2147, 2171,
+     1728, 2172, 2173, 1728, 2159, 2160, 2174, 1728, 2161, 2162,
+     2175, 1728, 2163, 2164, 2176, 1728, 2165, 2166, 2177, 1728,
+     2167, 2178, 1728, 2179, 1728, 2147, 2147, 2147, 2147, 2147,
+     2147, 2147, 2147, 2147, 2147, 2147, 2147, 2147, 2180, 1728,
+     2172, 2181, 2182, 2183, 2184, 2185, 2178, 2186, 1728, 2179,
 
-     1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463,
-     1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463,
-     1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463,
-     1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463,
-     1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463,
-     1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463,
-     1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463,
-     1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463,
-     1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463,
-     1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463,
+     2147, 2147, 2147, 2147, 2147, 2147, 2147, 2147, 2147, 2147,
+     2147, 2147, 2187, 2181, 2182, 2183, 2184, 2185, 2188, 2147,
+     2147, 2147, 2147, 2147, 2147, 2147, 2147, 2147, 2147, 2147,
+     2187, 2188, 2147, 2147, 2147, 2147, 2147, 2147, 2147, 2147,
+     2147, 2147, 2147, 2147, 2147, 2147, 2147, 2147, 2147, 2147,
+     2147, 2147, 2147, 2147, 2147, 2147, 2147, 2147, 2147, 2147,
+     2147, 2147, 2147, 2147, 2147, 2147, 2147, 2147, 2147, 2147,
+     2147, 2147, 2147, 2147, 2147, 2147, 2147, 2147, 2147, 2147,
+     2147, 2147, 2147, 2147, 2147, 2147, 2147, 2147, 2147, 2147,
+     2147, 2147, 2147, 2147, 2147, 2147, 2147, 2147, 2147, 2147,
 
-     1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463,
-     1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463,
-     1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463,
-     1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463,
-     1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463,
-     1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463,
-     1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463,
-     1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463,
-     1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463,
-     1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463,
+     2147, 2147, 2147, 2147, 2147, 2147, 2147, 2147, 2147, 2147,
+     2147, 2147, 2147, 2147, 2147, 2147, 2147, 2147, 2147, 2147,
+     2147, 2147, 2147, 2147, 2147, 2147, 2147,    0, 1728, 1728,
+     1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728,
+     1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728,
+     1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728,
+     1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728,
+     1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728,
+     1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728,
+     1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728,
 
-     1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463,
-     1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463,
-     1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463,
-     1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463,
-     1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463,
-     1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463,
-     1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463,
-     1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463,
-     1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463,
-     1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463,
+     1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728,
+     1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728,
+     1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728,
+     1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728,
+     1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728,
+     1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728,
+     1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728,
+     1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728,
+     1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728,
+     1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728,
 
-     1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463,
-     1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463,
-     1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463,
-     1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463,
-     1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463,
-     1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463,
-     1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463,
-     1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463,
-     1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463,
-     1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463,
+     1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728,
+     1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728,
+     1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728,
+     1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728,
+     1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728,
+     1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728,
+     1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728,
+     1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728,
+     1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728,
+     1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728,
 
-     1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463,
-     1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463,
-     1463, 1463, 1463
+     1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728,
+     1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728,
+     1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728,
+     1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728,
+     1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728,
+     1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728,
+     1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728,
+     1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728,
+     1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728,
+     1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728,
+
+     1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728,
+     1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728,
+     1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728,
+     1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728,
+     1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728,
+     1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728,
+     1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728,
+     1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728,
+     1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728
     } ;
 
-static yyconst flex_int16_t yy_nxt[7474] =
+static yyconst flex_uint16_t yy_nxt[7910] =
     {   0,
         4,    5,    6,    7,    8,    9,   10,   11,   12,   12,
        13,   14,   15,   15,   15,   15,   15,   15,   16,   17,
@@ -1025,822 +1117,870 @@
        44,  212,   44,   44,   44,   57,   58,   44,  248,   44,
        44,   44,   60,   61,   72,   44,   83,   84,  249,   44,
        53,   44,   44,   44,   44,  206,   44,   44,   73,   85,
-       44,  117,   79, 1239,   86,   74,   80,  736,  195,   44,
+       44,  117,   79, 1157,   86,   74,   80,  686,  195,   44,
 
-      118,  196,   81,   53,  197,   82,  198,   44,   48,   49,
+      118,  196,   81,  687,  197,   82,  198,   44,   48,   49,
        50,   50,   50,   50,   50,   50,   50,   51,  207,  201,
-     1304,   52,   53,   54,  202,  182,   55,   52,   52,   52,
+      942,   52,   53,   54,  202,  182,   55,   52,   52,   52,
        52,   52,   52,   53,   53,   53,   53,   53,   53,   53,
        53,   53,   53,   53,   53,   53,   53,   53,   53,   54,
-       53,   44,  183,   75,   44,  451,   44,   44,  184,  236,
-       87,  451,  213,   76,   88,  344,   77,  214,   63,   56,
+       53,   44,  183,   75,   44,  766,   44,   44,  184,  236,
+       87,   53,  213,   76,   88,  344,   77,  214,   63,   56,
        78,   63,  237,   63,   63,  208,   89,   44,   62,   52,
        52,   52,   52,   52,   52,   52,   63,  242,   65,  345,
-       66,   67,   53,  738,   63,   68,   53,  342,  119,  343,
+       66,   67,   53,  768,   63,   68,   53,  342,  119,  343,
 
        69,   90,  209,   91,   70,  243,   71,  210,   92,   93,
-      120,   94,  121, 1139,  122,   95,  451,  123,   53,   55,
-       53,   53,   53,   53,   53,   53,   53,   53, 1463,  104,
-      105,  217,   53,  740,  218, 1227,  219,  245,   53,   53,
+      120,   94,  121, 1335,  122,   95,  453,  123,   53,   55,
+       53,   53,   53,   53,   53,   53,   53,   53, 1728,  104,
+      105,  217,   53,  770,  218, 1161,  219,  245,   53,   53,
        53,   53,   53,   53,   96,  106,  246,   97,   98,  107,
        99,   53,  100,  108,  101,  109,  102,  111,  124,  103,
-       53,  112,  110,  125,  126,  129,  127,  128,  451,  130,
-      113,  114, 1463,  134,  115,  324,  116,  131,  141,  135,
+       53,  112,  110,  125,  126,  129,  127,  128,  799,  130,
+      113,  114, 1728,  134,  115,  324,  116,  131,  141,  135,
       142,  136,  132,  137,  133,  146,   53,  138,  325,  139,
-      140,   53,  355,  147,  143,   53,  520,  148, 1463,  149,
+      140,   53,  355,  147,  143,   53,  527,  148, 1728,  149,
 
-       44,  144,  743,   44,   53,   44,   44,  156,  156,  156,
-      156,  156,  156,  156, 1463,  417,   63,   53,   44,   63,
-      418,   63,   63,  495, 1230,  499,   44,  153,  153,  153,
-      153,  153,  153,  153,   63,  451,  496,   53,  153,  500,
-     1463,  744,   63,   53,  153,  153,  153,  153,  153,  153,
-      154,  155,  155,  155,  155,  155,  155, 1463,   53, 1233,
-     1463,  156,  380,  381,  382,  383,  451,  156,  156,  156,
+       44,  144,  490,   44,   53,   44,   44,  156,  156,  156,
+      156,  156,  156,  156, 1728,  417,   63,   53,   44,   63,
+      418,   63,   63,  491,  500, 1070,   44,  153,  153,  153,
+      153,  153,  153,  153,   63,   53,  708,  501,  153,  492,
+     1728,  775,   63,   53,  153,  153,  153,  153,  153,  153,
+      154,  155,  155,  155,  155,  155,  155, 1728,   53,   53,
+     1728,  156,  380,  381,  382,  383, 1295,  156,  156,  156,
       156,  156,  156,   49,  157,  157,  157,  157,  157,  157,
-      157,  277,  384, 1463,   53,  158, 1463, 1463, 1463,  279,
-     1236,  158,  158,  158,  158,  158,  158,   62,  158,  158,
+      157,  277,  384, 1728,   53,  158, 1728, 1728, 1728,  279,
+     1413,  158,  158,  158,  158,  158,  158,   62,  158,  158,
 
       158,  158,  158,  158,  158,  161,  161,  161,  161,  161,
-      161,  161,  569, 1463, 1463,  435,  161,  380,  381,  382,
-      383,  570,  161,  161,  161,  161,  161,  161,   44,  265,
-      451,   44, 1239,   44,   44,   53,  678,  462,  462,  162,
-      163,  163,  163,  163,  163,  163,   44,   53, 1463,  451,
-      164,  463, 1463, 1203,   44,  265,  164,  164,  164,  164,
-      164,  164,  260,  572,  261,  261,  261,  261,  261,  261,
-      261,  365,  573,   53, 1463,  261, 1463,  463, 1463,  528,
-     1205,  261,  261,  261,  261,  261,  261,  262,  263,  263,
-      263,  263,  263,  263,  263,  277,  466,  735,   53,  264,
+      161,  161,  576, 1728, 1728,  437,  161, 1323,  504,  765,
+       53,  577,  161,  161,  161,  161,  161,  161,   44,  265,
+      767,   44,  505,   44,   44,   53, 1326,  464,  464,  162,
+      163,  163,  163,  163,  163,  163,   44,   53, 1728,   53,
+      164,  465, 1728,  774,   44,  265,  164,  164,  164,  164,
+      164,  164,  260,  579,  261,  261,  261,  261,  261,  261,
+      261,  365,  580,   53, 1728,  261, 1728,  465, 1728,  535,
+      781,  261,  261,  261,  261,  261,  261,  262,  263,  263,
+      263,  263,  263,  263,  263,  277,  468,   53, 1329,  264,
 
-     1463,  265, 1463, 1463,  468,  264,  264,  264,  264,  264,
+     1728,  265, 1728, 1728,  470,  264,  264,  264,  264,  264,
       264,  352,  352,  352,  352,  352,  352,  352,  371,  372,
-      372,  372,  372,  372,  372,  538, 1463,  265,  266,  264,
-      264,  264,  264,  264,  264,  264, 1463, 1463,  737,  539,
-      264, 1463,  600,   53,   53,  751,  264,  264,  264,  264,
+      372,  372,  372,  372,  372,  545, 1728,  265,  266,  264,
+      264,  264,  264,  264,  264,  264,  688, 1728, 1332,  546,
+      264,  380,  381,  382,  383,  689,  264,  264,  264,  264,
       264,  264,  267,  268,  268,  268,  268,  268,  268,  268,
-      269,  757, 1463, 1463,  270,  539, 1006, 1463,  600, 1211,
+      269,  779, 1335, 1728,  270,  546, 1728, 1728,   53, 1413,
       270,  270,  270,  270,  270,  270,   53,  270,  270,  270,
       270,  270,  270,  270,  273,  274,  274,  274,  274,  274,
-      274,  275,  533, 1209,  812,  276, 1463,   53,  745,   55,
+      274,  275, 1728, 1728,  773,  276,   53,  777,  453,   53,
 
-      686,  276,  276,  276,  276,  276,  276,  277,  278,  278,
-      278,  278,  278,  278,  278,  279,   53,   55, 1371,  280,
-      812,  281, 1463,  396,   55,  280,  280,  280,  280,  280,
-      280,  397,  438,  438,  438,  438,  438,  438,  438, 1304,
-       55,  538,   55,  601,  398,   55,  741,  281,  349,  349,
-      349,  349,  349,  349,  349, 1463,   53,  433,   55,  349,
-      399,   55, 1304,   55,  451,  349,  349,  349,  349,  349,
-      349,  350,  351,  351,  351,  351,  351,  351,  739,   55,
-      825, 1463,  352,  433, 1463, 1463,  824,   53,  352,  352,
+      453,  276,  276,  276,  276,  276,  276,  277,  278,  278,
+      278,  278,  278,  278,  278,  279,  782,   53,  786,  280,
+     1223,  281,  453,  396,   53,  280,  280,  280,  280,  280,
+      280,  397,  440,  440,  440,  440,  440,  440,  440,   53,
+      793,  545, 1323,  619,  398,   55,  771,  281,  349,  349,
+      349,  349,  349,  349,  349, 1728,   53,  435,  618,  349,
+      399,  453,   55,   55,  784,  349,  349,  349,  349,  349,
+      349,  350,  351,  351,  351,  351,  351,  351,  690,   53,
+       55, 1728,  352,  435,  618,  854, 1728,  691,  352,  352,
       352,  352,  352,  352,  262,  353,  353,  353,  353,  353,
 
-      353,  353,  354,  354,  354,  354,  354,  354,  354,  542,
-     1463, 1463, 1249,  354, 1463,   55,   55,  689,   55,  354,
+      353,  353,  354,  354,  354,  354,  354,  354,  354,  769,
+     1728,  854, 1728,  354, 1326,  453, 1329,   55,   53,  354,
       354,  354,  354,  354,  354,  356,  357,  357,  357,  357,
-      357,  357,  357,   55,   55,  834,   55,  358,  830,  831,
-     1463, 1045, 1254,  358,  358,  358,  358,  358,  358,  361,
+      357,  357,  357,  540,  549,   55, 1728,  358,  453, 1332,
+      872,  716,  719,  358,  358,  358,  358,  358,  358,  361,
       358,  358,  358,  358,  358,  358,  358,  365,  366,  366,
-      366,  366,  366,  366,  366,  367,  646,  421,  640,  368,
-     1256,  369,  422, 1054,  648,  368,  368,  368,  368,  368,
-      368,  423,  641,  424,  425, 1463,  426,  453,  454,  454,
-      454,  454,  454,  454,   55,  640,   55,  369,  277,  373,
+      366,  366,  366,  366,  366,  367,  664,  453, 1335,  368,
+      453,  369, 1287, 1289,  666,  368,  368,  368,  368,  368,
+      368,  455,  456,  456,  456,  456,  456,  456,  524,  524,
+      524,  524,  524,  524,  524,  658,  778,  369,  277,  373,
 
-      373,  373,  373,  373,  373,  373,  279, 1262,  641, 1463,
-      374, 1463,   55, 1264,   55,  642,  374,  374,  374,  374,
-      374,  374,  375,  376,  376,  376,  376,  376,  376,  643,
-     1065,  826, 1270,  377, 1272, 1463,   55, 1077,   55,  377,
-      377,  377,  377,  377,  377,  428,  642,  429,  429,  429,
-      429,  429,  429,  429,   55,  643,   55,  832,  429,  835,
-     1463,  752,   55,  754,  429,  429,  429,  429,  429,  429,
-      430,  431,  431,  431,  431,  431,  431,  431, 1278,   55,
-       55, 1280,  432, 1089,  433, 1211, 1463, 1312,  432,  432,
-      432,  432,  432,  432,  517,  517,  517,  517,  517,  517,
+      373,  373,  373,  373,  373,  373,  279,   53, 1068,  659,
+      374, 1295,   55,   55, 1293,  776,  374,  374,  374,  374,
+      374,  374,  375,  376,  376,  376,  376,  376,  376,   53,
+       55,   55,  780,  377,  658,  659,  879,  866, 1493,  377,
+      377,  377,  377,  377,  377,  421,   53,  422, 1728,  423,
+      424,  554,  555,  555,  555,  555,  555,  555,   55,  425,
+      785,  426,  427,  660,  428,  430,  660,  431,  431,  431,
+      431,  431,  431,  431, 1728,   53,   55,  661,  431,  873,
+     1728,   55, 1413,   55,  431,  431,  431,  431,  431,  431,
+      432,  433,  433,  433,  433,  433,  433,  433, 1413,   55,
 
-      517,  547,  548,  548,  548,  548,  548,  548,  699,  750,
-      433,  434,  432,  432,  432,  432,  432,  432,  432,   53,
-     1139, 1463,  700,  432, 1463,  883,   55,   55,  699,  432,
-      432,  432,  432,  432,  432,  436,  437,  437,  437,  437,
-      437,  437, 1463, 1463,   55,   55,  438, 1463,  700,   55,
-     1463,  883,  438,  438,  438,  438,  438,  438,  267,  439,
-      439,  439,  439,  439,  439,  439,  694,   55, 1463, 1463,
-      440,   53,  911,  999,  847, 1359,  440,  440,  440,  440,
-      440,  440,   53,  440,  440,  440,  440,  440,  440,  440,
-      443,  444,  444,  444,  444,  444,  444,   53,  703,  999,
+      876,   55,  434,  661,  435,  453, 1728, 1345,  434,  434,
+      434,  434,  434,  434,  558,  559,  559,  559,  559,  559,
+      559,  638,  639,  639,  639,  639,  639,  639,  729,  783,
+      435,  436,  434,  434,  434,  434,  434,  434,  434,   53,
+     1117, 1350,  730,  434, 1352,   55,   55,   55,  729,  434,
+      434,  434,  434,  434,  434,  438,  439,  439,  439,  439,
+      439,  439, 1728,   55,   55,   55,  440,  874,  730,   55,
+      883,   55,  440,  440,  440,  440,  440,  440,  267,  441,
+      441,  441,  441,  441,  441,  441, 1126,   55, 1728,   55,
+      442, 1728,  884, 1728, 1728, 1358,  442,  442,  442,  442,
 
-     1361,  445, 1384,   55,   55,   55,  850,  445,  445,  445,
-      445,  445,  445,  449,  450,  450,  450,  450,  450,  450,
-      451,   55,   55,   55,  452, 1388,  912,  913,  915,   55,
-      452,  452,  452,  452,  452,  452,  365,  455,  455,  455,
-      455,  455,  455,  455,  367,  714, 1392,   55,  456, 1463,
-       55,   55,  917,  853,  456,  456,  456,  456,  456,  456,
-      457,  458,  458,  458,  458,  458,  458,  451,   55,   55,
-     1463,  459,  920,  918,   55, 1463,   55,  459,  459,  459,
-      459,  459,  459,  277,  464,  464,  464,  464,  464,  464,
-      464,  279,   55, 1396,   55,  465, 1463, 1016,   55,   55,
+      442,  442,   53,  442,  442,  442,  442,  442,  442,  442,
+      445,  446,  446,  446,  446,  446,  446, 1728,  724, 1728,
+     1728,  447, 1360,   55,   55,  794,  899,  447,  447,  447,
+      447,  447,  447,  451,  452,  452,  452,  452,  452,  452,
+      453,   55,   55,   55,  454,  887, 1728,   55,  796, 1137,
+      454,  454,  454,  454,  454,  454,  365,  457,  457,  457,
+      457,  457,  457,  457,  367,   55, 1728,  935,  458, 1728,
+       55,   55, 1728, 1366,  458,  458,  458,  458,  458,  458,
+      459,  460,  460,  460,  460,  460,  460,  453,   55,   55,
+       53,  461, 1728,  935,  963, 1728,   55,  461,  461,  461,
 
-     1022,  465,  465,  465,  465,  465,  465,  466,  467,  467,
-      467,  467,  467,  467,  467,  468,   55,   55, 1400,  469,
-     1463,  470, 1020, 1463, 1463,  469,  469,  469,  469,  469,
-      469,  551,  552,  552,  552,  552,  552,  552,  620,  621,
-      621,  621,  621,  621,  621, 1416, 1463,  470,  480, 1463,
-     1463, 1438,  481, 1463,   55,  482,   55,  708,  483,  708,
-      484,  485,  486,  487,  514,  514,  514,  514,  514,  514,
-      514,  709,   55, 1463,   55,  514, 1463,   55,   55, 1463,
-      746,  514,  514,  514,  514,  514,  514,  515,  516,  516,
-      516,  516,  516,  516,   53,   55,   55,  709,  517, 1463,
+      461,  461,  461,  277,  466,  466,  466,  466,  466,  466,
+      466,  279, 1368, 1149,   55,  467,   53, 1374,   55,  964,
+       55,  467,  467,  467,  467,  467,  467,  468,  469,  469,
+      469,  469,  469,  469,  469,  470,   55,  975,   55,  471,
+      787,  472, 1376,  965,  788,  471,  471,  471,  471,  471,
+      471,  582,  738,  583,   53,  789,  584,  585,   53,  738,
+      586,  587,  791,  733,  792,  588,  739,  472,  482,   53,
+     1161,  902,  483, 1728,   53,  484,   53,  740,  485,  740,
+      486,  487,  488,  489,  521,  521,  521,  521,  521,  521,
+      521,  741,  739, 1728, 1295,  521,   55,   55,   55, 1728,
 
-     1463, 1070, 1463, 1236,  517,  517,  517,  517,  517,  517,
-      430,  518,  518,  518,  518,  518,  518,  518,  519,  519,
-      519,  519,  519,  519,  519, 1463, 1463, 1070, 1082,  519,
-     1463, 1233,   55, 1230,   55,  519,  519,  519,  519,  519,
-      519,  435,  521,  521,  521,  521,  521,  521,  521,  819,
-       55, 1463,   55,  522, 1082,  265, 1463,  821, 1227,  522,
-      522,  522,  522,  522,  522,  628,  629,  629,  629,  629,
-      629,  629,  632,  633,  633,  633,  633,  633,  633,   55,
-      710,  265,  522,  522,  522,  522,  522,  522,  522, 1463,
-     1304, 1211, 1202,  522,  711,   55, 1008,   55,  747,  522,
+     1421,  521,  521,  521,  521,  521,  521,  522,  523,  523,
+      523,  523,  523,  523,   55,   55,   55,  741,  524, 1728,
+      967,  969, 1061,  880,  524,  524,  524,  524,  524,  524,
+      432,  525,  525,  525,  525,  525,  525,  525,  526,  526,
+      526,  526,  526,  526,  526, 1223, 1468, 1470, 1061,  526,
+     1506,   55,   55,   55,   55,  526,  526,  526,  526,  526,
+      526,  437,  528,  528,  528,  528,  528,  528,  528,   55,
+       55,   55,   55,  529, 1510,  265,  970,  976,  881,  529,
+      529,  529,  529,  529,  529,  646,  647,  647,  647,  647,
+      647,  647,  650,  651,  651,  651,  651,  651,  651,   55,
 
-      522,  522,  522,  522,  522,  523,  523,  523,  523,  523,
-      523,  523,   53,   55,  827, 1463,  524, 1115, 1202, 1089,
-      711, 1463,  524,  524,  524,  524,  524,  524,   53,  524,
-      524,  524,  524,  524,  524,  524,  365,  527,  527,  527,
-      527,  527,  527,  527,  528,  858,  710, 1463,  529,  451,
-      369, 1239,  890, 1029,  529,  529,  529,  529,  529,  529,
-     1463,  719,  720,  720,  720,  720,  720,  720,  722,  723,
-      723,  723,  723,  723,  723,   55,  369,  533,  534,  534,
-      534,  534,  534,  534,  534,  535, 1463, 1085, 1083,  536,
-     1077,  537,  451,   55,  749,  536,  536,  536,  536,  536,
+      855,  265,  529,  529,  529,  529,  529,  529,  529, 1728,
+      744, 1728, 1728,  529,  856,   55, 1514,   55,  905,  529,
+      529,  529,  529,  529,  529,  530,  530,  530,  530,  530,
+      530,  530, 1518,   55,  867, 1728,  531, 1728, 1728, 1728,
+      856,  979,  531,  531,  531,  531,  531,  531,   53,  531,
+      531,  531,  531,  531,  531,  531,  365,  534,  534,  534,
+      534,  534,  534,  534,  535, 1728, 1522, 1551,  536, 1728,
+      369, 1573, 1155, 1149,  536,  536,  536,  536,  536,  536,
+      749,  750,  750,  750,  750,  750,  750,  752,  753,  753,
+      753,  753,  753,  753,   55, 1728,  369,  540,  541,  541,
 
-      536,  726,  727,  727,  727,  727,  727,  727,   53,  777,
-      778,  778,  778,  778,  778,  778,   55,  537,  365,  540,
-      540,  540,  540,  540,  540,  540,  528, 1236,  878, 1463,
-      541, 1073, 1463, 1463,   55,   55,  541,  541,  541,  541,
-      541,  541,  542,  543,  543,  543,  543,  543,  543,  543,
-      544,  829, 1071,   55,  545, 1463,  546, 1118, 1463, 1463,
-      545,  545,  545,  545,  545,  545,  785,  786,  786,  786,
-      786,  786,  786,  789,  790,  790,  790,  790,  790,  790,
-      813,   55,  546,  466,  553,  553,  553,  553,  553,  553,
-      553,  468, 1065, 1463,  814,  554, 1463,  451, 1233,   55,
+      541,  541,  541,  541,  541,  542,  861,  453, 1332,  543,
+      930,  544,   55, 1085,  863,  543,  543,  543,  543,  543,
+      543,  756,  757,  757,  757,  757,  757,  757,  819,  820,
+      820,  820,  820,  820,  820,  855,   55,  544,  365,  547,
+      547,  547,  547,  547,  547,  547,  535, 1145, 1143, 1728,
+      548, 1728, 1137, 1728,   55,   55,  548,  548,  548,  548,
+      548,  548,  549,  550,  550,  550,  550,  550,  550,  550,
+      551,  868,  453,   55,  552, 1728,  553, 1728,  982, 1728,
+      552,  552,  552,  552,  552,  552,  827,  828,  828,  828,
+      828,  828,  828,  831,  832,  832,  832,  832,  832,  832,
 
-      813,  554,  554,  554,  554,  554,  554,  555,  556,  556,
-      556,  556,  556,  556, 1463,  867,  916,  867,  557, 1463,
-      814,   55, 1463, 1032,  557,  557,  557,  557,  557,  557,
-      595,  815,  596,  596,  596,  596,  596,  596,  596,   55,
-     1463, 1061, 1059,  596, 1119,  816, 1054,   55,   55,  596,
-      596,  596,  596,  596,  596,  597,  598,  598,  598,  598,
-      598,  598,  598,  451,  878,   55,   55,  599, 1217,  600,
-     1220,  816, 1035,  599,  599,  599,  599,  599,  599,  797,
-      798,  798,  798,  798,  798,  798,  800,  801,  801,  801,
-      801,  801,  801,  815,   55,  600,  597,  599,  599,  599,
+      857,   55,  553,  468,  560,  560,  560,  560,  560,  560,
+      560,  470, 1329, 1728,  858,  561,  919,   55, 1133,   55,
+      857,  561,  561,  561,  561,  561,  561,  562,  563,  563,
+      563,  563,  563,  563, 1728,   55,  869, 1131,  564, 1728,
+      858,   55, 1087,   55,  564,  564,  564,  564,  564,  564,
+      613,  915,  614,  614,  614,  614,  614,  614,  614,   55,
+     1728,   55, 1126,  614,  972,  916,   55,   55,  885,  614,
+      614,  614,  614,  614,  614,  615,  616,  616,  616,  616,
+      616,  616,  616,  453,   55,   55, 1326,  617, 1078,  618,
+      910,  916, 1084,  617,  617,  617,  617,  617,  617,  839,
 
-      599,  599,  599,  599, 1261,  890, 1230, 1463,  599, 1269,
-     1277,  858,   55, 1038,  599,  599,  599,  599,  599,  599,
-      435,  602,  602,  602,  602,  602,  602,  602, 1050, 1006,
-     1261,  921,  603, 1463, 1463, 1269, 1277, 1008,  603,  603,
-      603,  603,  603,  603,   53,  603,  603,  603,  603,  603,
-      603,  603,  604,  604,  604,  604,  604,  604,  604, 1045,
-     1463, 1045,  451,  605, 1358, 1387, 1391, 1227, 1227,  605,
-      605,  605,  605,  605,  605,   53,  605,  605,  605,  605,
-      605,  605,  605,  608,  609,  609,  609,  609,  609,  609,
-     1358, 1387, 1391, 1395,  610, 1399, 1437,   55,   55,   55,
+      840,  840,  840,  840,  840,  840,  842,  843,  843,  843,
+      843,  843,  843,   55,   55,  618,  615,  617,  617,  617,
+      617,  617,  617,  617, 1142,  910, 1122, 1728,  617, 1154,
+     1728,   55,   55, 1101,  617,  617,  617,  617,  617,  617,
+      437,  620,  620,  620,  620,  620,  620,  620,  871,  919,
+     1142,  877,  621, 1728, 1728, 1154, 1728, 1104,  621,  621,
+      621,  621,  621,  621,   53,  621,  621,  621,  621,  621,
+      621,  621,  622,  622,  622,  622,  622,  622,  622,  930,
+     1728, 1117,  453,  623, 1286, 1728, 1728, 1107, 1323,  623,
+      623,  623,  623,  623,  623,   53,  623,  623,  623,  623,
 
-      610,  610,  610,  610,  610,  610,  365,  455,  455,  455,
-      455,  455,  455,  455,  528,   55,   55,   55,  456, 1395,
-       55, 1399, 1437,  863,  456,  456,  456,  456,  456,  456,
-      611,  612,  612,  612,  612,  612,  612,  864,   55, 1214,
-     1215,  613,  451,   55, 1141, 1246, 1122,  613,  613,  613,
-      613,  613,  613,  617,  618,  618,  618,  618,  618,  618,
-      451,   55, 1216,  864,  619, 1239, 1236,   55,   55,   55,
-      619,  619,  619,  619,  619,  619,  533,  622,  622,  622,
-      622,  622,  622,  622,  535,   55,   55,   55,  623, 1233,
-     1230,   55,   55, 1227,  623,  623,  623,  623,  623,  623,
+      623,  623,  623,  626,  627,  627,  627,  627,  627,  627,
+     1286, 1728, 1728, 1728,  628,  453, 1225,   55,   55,   55,
+      628,  628,  628,  628,  628,  628,  365,  457,  457,  457,
+      457,  457,  457,  457,  535,   55,   55,   55,  458, 1728,
+     1082, 1086, 1089,  915,  458,  458,  458,  458,  458,  458,
+      629,  630,  630,  630,  630,  630,  630, 1728,  942, 1342,
+     1728,  631, 1206,   55,   55, 1335, 1110,  631,  631,  631,
+      631,  631,  631,  635,  636,  636,  636,  636,  636,  636,
+      453,   55,   55, 1728,  637, 1090, 1728,   55,   55, 1088,
+      637,  637,  637,  637,  637,  637,  540,  640,  640,  640,
 
-      624,  625,  625,  625,  625,  625,  625,  451, 1218,   55,
-       55,  626, 1122, 1367, 1299,   55,   55,  626,  626,  626,
-      626,  626,  626,  542,  634,  634,  634,  634,  634,  634,
-      634,  544, 1054,   55,   55,  635, 1368, 1006,   55,   55,
-     1230,  635,  635,  635,  635,  635,  635,  636,  637,  637,
-      637,  637,  637,  637,  451, 1065,   55,   55,  638, 1445,
-     1211, 1008,  819, 1233,  638,  638,  638,  638,  638,  638,
-      466,  644,  644,  644,  644,  644,  644,  644,  468, 1077,
-     1369, 1446,  645, 1447, 1448, 1445,   55, 1236,  645,  645,
-      645,  645,  645,  645,  646,  647,  647,  647,  647,  647,
+      640,  640,  640,  640,  542,   55,   55, 1091,  641, 1332,
+       55, 1093,   55, 1329,  641,  641,  641,  641,  641,  641,
+      642,  643,  643,  643,  643,  643,  643,  453,   55, 1326,
+       55,  644, 1323, 1206,   55,   55,   55,  644,  644,  644,
+      644,  644,  644,  549,  652,  652,  652,  652,  652,  652,
+      652,  551,   55,   55,   55,  653, 1068,   55,   55,   55,
+     1295,  653,  653,  653,  653,  653,  653,  654,  655,  655,
+      655,  655,  655,  655,  453,   55,   55,   55,  656, 1187,
+     1190,   55, 1191,   55,  656,  656,  656,  656,  656,  656,
+      468,  662,  662,  662,  662,  662,  662,  662,  470,   55,
 
-      647,  647,  648, 1089,   55, 1002,  649, 1446,  650, 1447,
-     1448, 1239,  649,  649,  649,  649,  649,  649,  804,  805,
-      805,  805,  805,  805,  805,  720,  720,  720,  720,  720,
-      720,  720,   55,  863,  650,  674,  674,  674,  674,  674,
-      674,  674, 1449, 1139, 1454, 1460,  674, 1463, 1000,   55,
-       55, 1304,  674,  674,  674,  674,  674,  674,  675,  675,
-      675,  675,  675,  675,  675,  914, 1209,   55, 1449,  675,
-     1454, 1460, 1091, 1463, 1211,  675,  675,  675,  675,  675,
-      675,  597,  676,  676,  676,  676,  676,  676,  676,  677,
-      677,  677,  677,  677,  677,  677, 1209,  451, 1038, 1079,
+     1070,   55,  663, 1728, 1728,   55, 1194,  861,  663,  663,
+      663,  663,  663,  663,  664,  665,  665,  665,  665,  665,
+      665,  665,  666,   55, 1064, 1195,  667, 1062,  668, 1728,
+     1728, 1163,  667,  667,  667,  667,  667,  667,  846,  847,
+      847,  847,  847,  847,  847,  750,  750,  750,  750,  750,
+      750,  750,   55,   55,  668,  704,  704,  704,  704,  704,
+      704,  704, 1357,  453, 1365, 1373,  704, 1728,   55, 1110,
+       55,   55,  704,  704,  704,  704,  704,  704,  705,  705,
+      705,  705,  705,  705,  705,  878,   55,  968, 1357,  705,
+     1365, 1373, 1199, 1728, 1151,  705,  705,  705,  705,  705,
 
-      677,  451,   55, 1035, 1463, 1067,  677,  677,  677,  677,
-      677,  677,  435,  679,  679,  679,  679,  679,  679,  679,
-       55,  451, 1032, 1056,  680,  451, 1029, 1047,  451, 1300,
-      680,  680,  680,  680,  680,  680,   53,  680,  680,  680,
-      680,  680,  680,  680,  681,  681,  681,  681,  681,  681,
-      681, 1141,  451, 1122, 1038,  682, 1035, 1032, 1029, 1122,
-     1008,  682,  682,  682,  682,  682,  682,   53,  682,  682,
-      682,  682,  682,  682,  682,  533,  685,  685,  685,  685,
-      685,  685,  685,  686,   55,  872,  872,  687,  821,  537,
-      890, 1091,  874,  687,  687,  687,  687,  687,  687,  873,
+      705,  615,  706,  706,  706,  706,  706,  706,  706,  707,
+      707,  707,  707,  707,  707,  707, 1068,  453, 1107, 1467,
+      707, 1509,   55,   55, 1070,   55,  707,  707,  707,  707,
+      707,  707,  437,  709,  709,  709,  709,  709,  709,  709,
+       55,   55, 1197,   55,  710, 1467, 1200, 1509, 1513,  978,
+      710,  710,  710,  710,  710,  710,   53,  710,  710,  710,
+      710,  710,  710,  710,  711,  711,  711,  711,  711,  711,
+      711, 1117, 1126, 1139, 1513,  712,  453, 1104, 1128, 1323,
+     1326,  712,  712,  712,  712,  712,  712,   53,  712,  712,
+      712,  712,  712,  712,  712,  540,  715,  715,  715,  715,
 
-     1463, 1038,   55,  714,  886,  884,  875,  878, 1079,   55,
-     1035,   55,  703,   55,  828,  537,  542,  688,  688,  688,
-      688,  688,  688,  688,  689,  873, 1463,   55,  690,   55,
-      546,   55,  875,   55,  690,  690,  690,  690,  690,  690,
-      836,  833,  874,  341,  841,  841,  841,  841,  841,  841,
-      841,   55,  874,  884,  884,   55,  546,  694,  695,  695,
-      695,  695,  695,  695,  695,  696, 1463,  885, 1463,  697,
-     1114,  698,  872,   55,  886,  697,  697,  697,  697,  697,
-      697,  798,  798,  798,  798,  798,  798,  798,  887,   55,
-     1015,  867, 1463,  885, 1463,  886, 1067,  698,  533,  701,
+      715,  715,  715,  716,   55,   55,  924,  717,   55,  544,
+       55,   55,   55,  717,  717,  717,  717,  717,  717, 1137,
+      925,  453,   55,   55, 1101, 1119,   55, 1329,   55,   55,
+       55,   55,  980,   55,  870,  544,  549,  718,  718,  718,
+      718,  718,  718,  718,  719,  882,  925,  886,  720,   55,
+      553,   55, 1149, 1298,  720,  720,  720,  720,  720,  720,
+     1332,  875,  453, 1225,  888,  893,  893,  893,  893,  893,
+      893,  893,   55,  924,  926, 1517,  553,  724,  725,  725,
+      725,  725,  725,  725,  725,  726,   55, 1728,  927,  727,
+       55,  728,  926,  936,  936,  727,  727,  727,  727,  727,
 
-      701,  701,  701,  701,  701,  701,  686,   55, 1032, 1463,
-      702,  694,  863,  858,  887, 1414,  702,  702,  702,  702,
-      702,  702,  703,  704,  704,  704,  704,  704,  704,  704,
-      705, 1056, 1029, 1047,  706, 1463,  707,  944,  929, 1038,
-      706,  706,  706,  706,  706,  706,  896,  897,  897,  897,
-      897,  897,  897,  899,  900,  900,  900,  900,  900,  900,
-     1000,   55,  707,  542,  712,  712,  712,  712,  712,  712,
-      712,  689, 1035, 1032, 1001,  713, 1029, 1027,  929,   55,
-     1017,  713,  713,  713,  713,  713,  713,  714,  715,  715,
-      715,  715,  715,  715,  715,  716,  819, 1018, 1008,  717,
+      727, 1517,  341, 1161,   55, 1521, 1728,  937, 1728,   55,
+      453, 1335, 1206, 1728,  927,  938, 1110,  728,  540,  731,
+      731,  731,  731,  731,  731,  731,  716,   55, 1299,  939,
+      732, 1521, 1728,  937, 1728,   55,  732,  732,  732,  732,
+      732,  732,  733,  734,  734,  734,  734,  734,  734,  734,
+      735, 1300, 1107,   55,  736,  939,  737, 1104, 1304,  938,
+      736,  736,  736,  736,  736,  736,  840,  840,  840,  840,
+      840,  840,  840, 1728,  948,  949,  949,  949,  949,  949,
+      949, 1101,  737,  549,  742,  742,  742,  742,  742,  742,
+      742,  719, 1223, 1206, 1572,  743, 1592, 1593,   55, 1728,
 
-     1001,  718,  821,   55,   55,  717,  717,  717,  717,  717,
-      717,  903,  904,  904,  904,  904,  904,  904,  646,  815,
-      813,   55,   55,  892, 1000, 1002,   55,  718,  646,  728,
-      728,  728,  728,  728,  728,  728,  648,  919, 1463, 1003,
-      729, 1117,  853,  880,   55, 1002,  729,  729,  729,  729,
-      729,  729,  730,  731,  731,  731,  731,  731,  731, 1463,
-     1019,  850,  869,  732, 1463, 1003,  847,  860,  944,  732,
-      732,  732,  732,  732,  732,   53,   53,   53,   53,   53,
-       53,   53,  929,  853,  850, 1463,   53,   55,   55,   55,
-       55,   55,   53,   53,   53,   53,   53,   53,  948,  949,
+     1413,  743,  743,  743,  743,  743,  743,  744,  745,  745,
+      745,  745,  745,  745,  745,  746,   55, 1070, 1301,  747,
+     1572,  748, 1592, 1593,  863,  747,  747,  747,  747,  747,
+      747,  951,  952,  952,  952,  952,  952,  952,  955,  956,
+      956,  956,  956,  956,  956,   55,   55,  748,  664,  758,
+      758,  758,  758,  758,  758,  758,  666, 1293,  942, 1163,
+      759, 1110, 1594,   55,   55, 1295,  759,  759,  759,  759,
+      759,  759,  760,  761,  761,  761,  761,  761,  761,  966,
+      974,  744,  938,  762,   55,   55,   55,   55, 1594,  762,
+      762,  762,  762,  762,  762,   53,   53,   53,   53,   53,
 
-      949,  949,  949,  949,  949,   55,   55,   55,   55,   55,
-      734,  752,  847,  753,  753,  753,  753,  753,  753,  753,
-     1011, 1012, 1013, 1014,  753, 1021, 1366,   55,   55,   55,
-      753,  753,  753,  753,  753,  753,  956,  957,  957,  957,
-      957,  957,  957, 1050, 1050,   55,   55,   55,   53,  754,
-      755,  755,  755,  755,  755,  755,  755, 1051, 1463, 1113,
-     1116,  755, 1221,  929,  821,  648,  714,  755,  755,  755,
-      755,  755,  755,  960,  961,  961,  961,  961,  961,  961,
-      892,  853,  542, 1051, 1463,   53,  676,  676,  676,  676,
-      676,  676,  676,  968,  969,  969,  969,  969,  969,  969,
+       53,   53,   55,   55,   55,   55,   53,   55,   55, 1062,
+       55,   55,   53,   53,   53,   53,   53,   53,  971,  973,
+     1595,  983,  981, 1063, 1293,   55,   55, 1062,   55,   55,
+      764,  794, 1728,  795,  795,  795,  795,  795,  795,  795,
+      977, 1728, 1077, 1073,  795, 1186, 1595,   55,  936, 1063,
+      795,  795,  795,  795,  795,  795, 1010, 1011, 1011, 1011,
+     1011, 1011, 1011, 1064, 1064,   55,   55, 1728,   53,  796,
+      797,  797,  797,  797,  797,  797,  797, 1065, 1728,  930,
+     1074,  797,   55,   55,   55, 1079, 1151,  797,  797,  797,
+      797,  797,  797, 1018, 1019, 1019, 1019, 1019, 1019, 1019,
 
-      971,  972,  972,  972,  972,  972,  972,  975,  976,  976,
-      976,  976,  976,  976,  984,  985,  985,  985,  985,  985,
-      985,   53,  677,  677,  677,  677,  677,  677,  677,  710,
-      708,  703,  880,  677,  850,  533,  699,  694,  869,  677,
-      677,  677,  677,  677,  677,  756,  353,  353,  353,  353,
-      353,  353,  353,  267,  758,  758,  758,  758,  758,  758,
-      758,  847,  860,  857,  773,  759,  761,  853,  850,  847,
-      845,  759,  759,  759,  759,  759,  759,   53,  759,  759,
-      759,  759,  759,  759,  759,  762,  763,  763,  763,  763,
-      763,  763,  761,  646,  821,  648,  764,  466,  642,  640,
+       55,   55, 1080, 1065, 1728,   53,  706,  706,  706,  706,
+      706,  706,  706, 1022, 1023, 1023, 1023, 1023, 1023, 1023,
+     1030, 1031, 1031, 1031, 1031, 1031, 1031, 1033, 1034, 1034,
+     1034, 1034, 1034, 1034, 1037, 1038, 1038, 1038, 1038, 1038,
+     1038,   53,  707,  707,  707,  707,  707,  707,  707, 1107,
+      733,  926,  924,  707,  919, 1596, 1613, 1619, 1139,  707,
+      707,  707,  707,  707,  707,  798,  353,  353,  353,  353,
+      353,  353,  353,  267,  800,  800,  800,  800,  800,  800,
+      800, 1596, 1613, 1619, 1104,  801,  724,  915,  910, 1128,
+     1101,  801,  801,  801,  801,  801,  801,   53,  801,  801,
 
-      716,  689,  764,  764,  764,  764,  764,  764,  533,  622,
-      622,  622,  622,  622,  622,  622,  686,  705,  686,  696,
-      623,  773,  761,  689,  686, 1059,  623,  623,  623,  623,
-      623,  623,  765,  766,  766,  766,  766,  766,  766, 1060,
-      761,   53,   53,  767,   53,  748,   53,   53,  742,  767,
-      767,  767,  767,  767,  767,  542,  634,  634,  634,  634,
-      634,  634,  634,  689,  648, 1060,  468,  635,  542,  716,
-      689,  365, 1059,  635,  635,  635,  635,  635,  635,  768,
-      769,  769,  769,  769,  769,  769, 1463,  538,  533,  705,
-      770,  686,  696,  693,  616,  607,  770,  770,  770,  770,
+      801,  801,  801,  801,  801,  804,  805,  805,  805,  805,
+      805,  805, 1119, 1006,  991, 1110,  806, 1107, 1104,   55,
+       55,   55,  806,  806,  806,  806,  806,  806,  540,  640,
+      640,  640,  640,  640,  640,  640,  716,   55,   55,   55,
+      641, 1315, 1101, 1316,   55, 1122,  641,  641,  641,  641,
+      641,  641,  807,  808,  808,  808,  808,  808,  808, 1123,
+     1302, 1099,   55,  809,  991,  861,   55, 1070,   55,  809,
+      809,  809,  809,  809,  809,  549,  652,  652,  652,  652,
+      652,  652,  652,  719,   55, 1123,   55,  653,  863,   55,
+       55,   55, 1122,  653,  653,  653,  653,  653,  653,  810,
 
-      770,  770,  774,  775,  775,  775,  775,  775,  775,  451,
-      689,  686, 1463,  776,  684,  607,  597,  595,  673,  776,
-      776,  776,  776,  776,  776,  694,  779,  779,  779,  779,
-      779,  779,  779,  696,  672,  671,  670,  780,  669,  668,
-      667,  666,  665,  780,  780,  780,  780,  780,  780,  781,
-      782,  782,  782,  782,  782,  782,  451,  664,  663,  662,
-      783,  661,  660,  659,  658,  657,  783,  783,  783,  783,
-      783,  783,  703,  791,  791,  791,  791,  791,  791,  791,
-      705,  656,  655,  654,  792,  653,  652,  651,  466,  648,
-      792,  792,  792,  792,  792,  792,  793,  794,  794,  794,
+      811,  811,  811,  811,  811,  811, 1728,   55,   55,   55,
+      812,  664,   55, 1395, 1404, 1306,  812,  812,  812,  812,
+      812,  812,  816,  817,  817,  817,  817,  817,  817,  453,
+       55,  857, 1728,  818,  855,  944,  905,   55,   55,  818,
+      818,  818,  818,  818,  818,  724,  821,  821,  821,  821,
+      821,  821,  821,  726, 1401,   55,   55,  822,  932,  902,
+       55,   55,  921,  822,  822,  822,  822,  822,  822,  823,
+      824,  824,  824,  824,  824,  824,  453, 1409,   55,   55,
+      825, 1476, 1477,   55,   55,   55,  825,  825,  825,  825,
+      825,  825,  733,  833,  833,  833,  833,  833,  833,  833,
 
-      794,  794,  794,  451,  468,  462,  544,  795,  528,  535,
-      616,  607,  528,  795,  795,  795,  795,  795,  795,  714,
-      806,  806,  806,  806,  806,  806,  806,  716,  607,  601,
-      601,  807,  594,  593,  592,  591,  590,  807,  807,  807,
-      807,  807,  807,  808,  809,  809,  809,  809,  809,  809,
-      451,  589,  588,  587,  810,  586,  338,  239,  585,  584,
-      810,  810,  810,  810,  810,  810,  646,  817,  817,  817,
-      817,  817,  817,  817,  648,  583,  582,  581,  818,  580,
-      579,  578,  577,  576,  818,  818,  818,  818,  818,  818,
-      819,  820,  820,  820,  820,  820,  820,  820,  821,  575,
+      735,   55,   55,   55,  834,  899, 1479,  912,   55, 1006,
+      834,  834,  834,  834,  834,  834,  835,  836,  836,  836,
+      836,  836,  836,  453,  991, 1478,   55,  837,  905,  902,
+     1481,   55,   55,  837,  837,  837,  837,  837,  837,  744,
+      848,  848,  848,  848,  848,  848,  848,  746,  899,   55,
+       55,  849,  991, 1482,   55,   55, 1483,  849,  849,  849,
+      849,  849,  849,  850,  851,  851,  851,  851,  851,  851,
+      453,  863,   55,   55,  852,  666, 1486,   55, 1489,   55,
+      852,  852,  852,  852,  852,  852,  664,  859,  859,  859,
+      859,  859,  859,  859,  666,   55,  744,   55,  860,  944,
 
-      574,  571,  822,  568,  823,  567,  566,  565,  822,  822,
-      822,  822,  822,  822,  987,  988,  988,  988,  988,  988,
-      988,  991,  992,  992,  992,  992,  992,  992, 1061, 1061,
-      823,   55, 1071,  837,  837,  837,  837,  837,  837,  837,
-      564,  563, 1062, 1463,  837,  562, 1072,  561,  560,   55,
-      837,  837,  837,  837,  837,  837,  838,  838,  838,  838,
-      838,  838,  838,  559,  468,  279,  451,  838, 1062, 1463,
-      365,  544, 1072,  838,  838,  838,  838,  838,  838,  839,
-      840,  840,  840,  840,  840,  840,  528,  535,  451,  532,
-      841,  448,   55,  442,  528,  526,  841,  841,  841,  841,
+      905,   55,  549, 1536,  860,  860,  860,  860,  860,  860,
+      861,  862,  862,  862,  862,  862,  862,  862,  863,   55,
+     1546,  740,  864,  738,  865,  733,  932,  902,  864,  864,
+      864,  864,  864,  864, 1046, 1047, 1047, 1047, 1047, 1047,
+     1047, 1049, 1050, 1050, 1050, 1050, 1050, 1050, 1131,   55,
+      865,   55, 1131,  889,  889,  889,  889,  889,  889,  889,
+      540,  729, 1132,  724,  889,  921, 1728,   55,   55,   55,
+      889,  889,  889,  889,  889,  889,  890,  890,  890,  890,
+      890,  890,  890, 1081,  899,  912,   55,  890, 1132,   55,
+       55,   55, 1728,  890,  890,  890,  890,  890,  890,  891,
 
-      841,  841,  267,  842,  842,  842,  842,  842,  842,  842,
-       55,  442,  434,  428,  843,  513,  512,  511,  510, 1413,
-      843,  843,  843,  843,  843,  843,   53,  843,  843,  843,
-      843,  843,  843,  843,  694,  846,  846,  846,  846,  846,
-      846,  846,  847,  509,  508,  507,  848,  506,  698,  505,
-      504,  503,  848,  848,  848,  848,  848,  848,  897,  897,
-      897,  897,  897,  897,  897,  969,  969,  969,  969,  969,
-      969,  969, 1071,  502,  698,  703,  849,  849,  849,  849,
-      849,  849,  849,  850,  501, 1073, 1463,  851,  498,  707,
-      497, 1073, 1083,  851,  851,  851,  851,  851,  851, 1074,
+      892,  892,  892,  892,  892,  892, 1189,   55,   55,   55,
+      893, 1549,   55,   55,   55,   55,  893,  893,  893,  893,
+      893,  893,  267,  894,  894,  894,  894,  894,  894,  894,
+       55,   55,   55,   55,  895,  909, 1577, 1584,  815, 1396,
+      895,  895,  895,  895,  895,  895,   53,  895,  895,  895,
+      895,  895,  895,  895,  724,  898,  898,  898,  898,  898,
+      898,  898,  899,  803,  905,  902,  900,  899,  728,  897,
+      803,  664,  900,  900,  900,  900,  900,  900, 1053, 1054,
+     1054, 1054, 1054, 1054, 1054,  949,  949,  949,  949,  949,
+      949,  949,   55,   55,  728,  733,  901,  901,  901,  901,
 
-      494,  493,  492,  491,  490, 1463, 1084,  120,  489,  488,
-      479,   55, 1463, 1083,  478,  707,  714,  852,  852,  852,
-      852,  852,  852,  852,  853, 1074,  477, 1463,  854,   55,
-      718, 1463, 1084, 1085,  854,  854,  854,  854,  854,  854,
-      985,  985,  985,  985,  985,  985,  985, 1086, 1412,  476,
-      475,  474, 1085, 1463, 1203,  473,  718,  858,  859,  859,
-      859,  859,  859,  859,  859,  860, 1463,  472, 1204,  861,
-      471,  862,  277, 1086, 1203,  861,  861,  861,  861,  861,
-      861, 1095, 1096, 1096, 1096, 1096, 1096, 1096, 1463,  468,
-      279,  451, 1463, 1205, 1204, 1205,  367,  862,  694,  865,
+      901,  901,  901,  902,   55,   55, 1133,  903,  863,  737,
+       55,   55,   55,  903,  903,  903,  903,  903,  903,  666,
+     1134,  468,   55,   55,  660, 1075, 1076,   55, 1083,   55,
+       55,   55,  658, 1182, 1183,  737,  744,  904,  904,  904,
+      904,  904,  904,  904,  905,   55, 1134,   55,  906,   55,
+      748, 1537, 1133,  746,  906,  906,  906,  906,  906,  906,
+     1092, 1143, 1094, 1185,  719,  735, 1728, 1031, 1031, 1031,
+     1031, 1031, 1031, 1031, 1143, 1144,  748,  910,  911,  911,
+      911,  911,  911,  911,  911,  912,   55,   55, 1728,  913,
+      716,  914, 1728, 1145, 1145,  913,  913,  913,  913,  913,
 
-      865,  865,  865,  865,  865,  865,  847, 1206,  448, 1463,
-      866,  442,  442,  435, 1463,  435,  866,  866,  866,  866,
-      866,  866,  867,  868,  868,  868,  868,  868,  868,  868,
-      869,  427,  420, 1206,  870, 1463,  871,  419,  416,  415,
-      870,  870,  870,  870,  870,  870, 1098, 1099, 1099, 1099,
-     1099, 1099, 1099, 1102, 1103, 1103, 1103, 1103, 1103, 1103,
-     1249,  414,  871,  703,  876,  876,  876,  876,  876,  876,
-      876,  850,  413,  412, 1250,  877,  411,  410,  409,  408,
-      407,  877,  877,  877,  877,  877,  877,  878,  879,  879,
-      879,  879,  879,  879,  879,  880,   55,   55, 1249,  881,
+      913, 1144,  726,  815,   55,   55,  803, 1146, 1728,  719,
+       55,  716,  803, 1155, 1728, 1155, 1184,  914,  724,  917,
+      917,  917,  917,  917,  917,  917,  899, 1156,   55, 1728,
+      918,   53,   53, 1146, 1728,   53,  918,  918,  918,  918,
+      918,  918,  919,  920,  920,  920,  920,  920,  920,  920,
+      921, 1581,  790, 1156,  922, 1728,  923,   55,   55, 1157,
+      922,  922,  922,  922,  922,  922, 1047, 1047, 1047, 1047,
+     1047, 1047, 1047, 1158,   53,   55,   55,   53, 1157,   55,
+       55,  772,  923,  733,  928,  928,  928,  928,  928,  928,
+      928,  902, 1728, 1310, 1192,  929,  666,   55,   55, 1158,
 
-     1250,  882,  406,  405,  404,  881,  881,  881,  881,  881,
-      881,  403, 1463,  402,   55,   55, 1145, 1146, 1146, 1146,
-     1146, 1146, 1146, 1254,  401, 1110, 1111,  882,  714,  888,
-      888,  888,  888,  888,  888,  888,  853, 1255, 1463,  400,
-      889,  395,  394,  393,  392,  391,  889,  889,  889,  889,
-      889,  889,  890,  891,  891,  891,  891,  891,  891,  891,
-      892,   55, 1254, 1255,  893,  320,  894,  390,  389,   55,
-      893,  893,  893,  893,  893,  893, 1463,  388,  387,   55,
-     1151, 1152, 1152, 1152, 1152, 1152, 1152,   55,  386, 1256,
-     1112,  385,  894,  819,  905,  905,  905,  905,  905,  905,
+      470,  929,  929,  929,  929,  929,  929,  930,  931,  931,
+      931,  931,  931,  931,  931,  932, 1311, 1490, 1728,  933,
+      549,  934,  746,  719,  365,  933,  933,  933,  933,  933,
+      933, 1167, 1168, 1168, 1168, 1168, 1168, 1168, 1170, 1171,
+     1171, 1171, 1171, 1171, 1171, 1287,   55,  934,  744,  940,
+      940,  940,  940,  940,  940,  940,  905,  545,  540, 1288,
+      941,  735,  716,  726,   55, 1201,  941,  941,  941,  941,
+      941,  941,  942,  943,  943,  943,  943,  943,  943,  943,
+      944, 1202, 1203,  723,  945, 1288,  946,   55,   55,   55,
+      945,  945,  945,  945,  945,  945, 1174, 1175, 1175, 1175,
 
-      905,  821, 1463, 1257,  379,  906, 1441,  279,  367,  275,
-     1256,  906,  906,  906,  906,  906,  906,  907,  908,  908,
-      908,  908,  908,  908, 1463,  364,  272,  360,  909, 1257,
-      266,  260,  143,  348,  909,  909,  909,  909,  909,  909,
-       55, 1262,  922,  922,  922,  922,  922,  922,  922,  347,
-     1463,  346,  341,  922,  320, 1263,  340,  339,   55,  922,
-      922,  922,  922,  922,  922,  923,  923,  923,  923,  923,
-      923,  923,  338,  337,  336,  335,  923,  334,  333,  332,
-      331, 1263,  923,  923,  923,  923,  923,  923,  601,  924,
-      924,  924,  924,  924,  924,  924,  330,  329,  328,  327,
+     1175, 1175, 1175,  634,  625,   55,   55,   55,   55, 1287,
+     1289,  719,  946,  861,  957,  957,  957,  957,  957,  957,
+      957,  863, 1193, 1728, 1290,  958,   55, 1544,   55,   55,
+     1289,  958,  958,  958,  958,  958,  958,  959,  960,  960,
+      960,  960,  960,  960, 1728, 1314,   55,   55,  961, 1728,
+     1290,   55,  716,   55,  961,  961,  961,  961,  961,  961,
+       55, 1188,  984,  984,  984,  984,  984,  984,  984,   55,
+     1728,   55, 1602,  984, 1603,   55,   55,   55,   55,  984,
+      984,  984,  984,  984,  984,  985,  985,  985,  985,  985,
+      985,  985,  714,   55,   55,   55,  985, 1604,   55,   55,
 
-      925,  326,  433,  323,  322,  321,  925,  925,  925,  925,
-      925,  925, 1155, 1156, 1156, 1156, 1156, 1156, 1156, 1161,
-     1162, 1162, 1162, 1162, 1162, 1162,  320, 1262,  433,  925,
-      925,  925,  925,  925,  925,  925,  319,  318,  317,  316,
-      925, 1463,  315,  314,  313,  312,  925,  925,  925,  925,
-      925,  925,  267,  926,  926,  926,  926,  926,  926,  926,
-      311,  310,  309,  308,  927,  307,  306, 1463,  305,  304,
-      927,  927,  927,  927,  927,  927,   53,  927,  927,  927,
-      927,  927,  927,  927,  930,  931,  931,  931,  931,  931,
-      931,  303,  302,  301,  300,  932,  299,  298,  297,  143,
+       55,   55,  985,  985,  985,  985,  985,  985,  619,  986,
+      986,  986,  986,  986,  986,  986,   55,   55,   55,   55,
+      987, 1610,  435,  625,  615, 1491,  987,  987,  987,  987,
+      987,  987, 1196, 1198, 1229, 1230, 1230, 1230, 1230, 1230,
+     1230, 1235, 1236, 1236, 1236, 1236, 1236, 1236,  435,  987,
+      987,  987,  987,  987,  987,  987,  613,  703,  702,  701,
+      987,  700,   55,   55,   55,   55,  987,  987,  987,  987,
+      987,  987,  267,  988,  988,  988,  988,  988,  988,  988,
+       55,   55,   55,   55,  989, 1624,  699, 1626, 1627, 1535,
+      989,  989,  989,  989,  989,  989,   53,  989,  989,  989,
 
-      296,  932,  932,  932,  932,  932,  932,  694,  779,  779,
-      779,  779,  779,  779,  779,  847,  295,  294,  293,  780,
-      292,  291,  290,  289, 1264,  780,  780,  780,  780,  780,
-      780,  933,  934,  934,  934,  934,  934,  934, 1265,  288,
-      287,  286,  935,  285,  284,  283,  282,  279,  935,  935,
-      935,  935,  935,  935,  703,  791,  791,  791,  791,  791,
-      791,  791,  850,  267, 1265,  272,  792,  259,  258,  257,
-      256, 1264,  792,  792,  792,  792,  792,  792,  936,  937,
-      937,  937,  937,  937,  937, 1463,  255,  254,  253,  938,
-      252,  251,  250,  247,  244,  938,  938,  938,  938,  938,
+      989,  989,  989,  989,  992,  993,  993,  993,  993,  993,
+      993,  698,  697,  696,  695,  994,  694,  693,   55,   55,
+       55,  994,  994,  994,  994,  994,  994,  724,  821,  821,
+      821,  821,  821,  821,  821,  899,   55,   55,   55,  822,
+      692,  685, 1642,   55, 1345,  822,  822,  822,  822,  822,
+      822,  995,  996,  996,  996,  996,  996,  996, 1346, 1634,
+      684,   55,  997,  683,  682,   55, 1643,   55,  997,  997,
+      997,  997,  997,  997,  733,  833,  833,  833,  833,  833,
+      833,  833,  902,   55, 1346,   55,  834,  681, 1644,   55,
+       55, 1345,  834,  834,  834,  834,  834,  834,  998,  999,
 
-      938,  714,  806,  806,  806,  806,  806,  806,  806,  853,
-      241, 1463,  240,  807,  239,  238,  235,  234, 1270,  807,
-      807,  807,  807,  807,  807,  939,  940,  940,  940,  940,
-      940,  940, 1271,  233,  232,  231,  941,  230,  229,  228,
-      227,  226,  941,  941,  941,  941,  941,  941,  945,  946,
-      946,  946,  946,  946,  946,  451,  225,  224, 1271,  947,
-      223,  222,  221,  220,  216,  947,  947,  947,  947,  947,
-      947,  858,  950,  950,  950,  950,  950,  950,  950,  860,
-      215,  205,  204,  951,  203,  200,  199,  194,  193,  951,
-      951,  951,  951,  951,  951,  952,  953,  953,  953,  953,
+      999,  999,  999,  999,  999, 1728, 1635,   55,   55, 1000,
+      680,  679, 1646,  678,   55, 1000, 1000, 1000, 1000, 1000,
+     1000,  744,  848,  848,  848,  848,  848,  848,  848,  905,
+      677, 1728,   55,  849,  676,  675,   55,   55, 1350,  849,
+      849,  849,  849,  849,  849, 1001, 1002, 1002, 1002, 1002,
+     1002, 1002, 1351, 1636,   55,   55, 1003, 1655,   55, 1657,
+      674,  673, 1003, 1003, 1003, 1003, 1003, 1003, 1007, 1008,
+     1008, 1008, 1008, 1008, 1008,  453,   55,  672, 1351, 1009,
+      671, 1659,   55,   55,   55, 1009, 1009, 1009, 1009, 1009,
+     1009,  910, 1012, 1012, 1012, 1012, 1012, 1012, 1012,  912,
 
-      953,  953,  451,  192,  191,  190,  954,  189,  188,  187,
-      186,  185,  954,  954,  954,  954,  954,  954,  867,  962,
-      962,  962,  962,  962,  962,  962,  869,  181,  180,  179,
-      963,  178,  177,  176,  175,  174,  963,  963,  963,  963,
-      963,  963,  964,  965,  965,  965,  965,  965,  965,  451,
-      173,  172,  171,  966,  170,  169,  168,  167,  166,  966,
-      966,  966,  966,  966,  966,  878,  977,  977,  977,  977,
-      977,  977,  977,  880,  165,  160,  151,  978,  150,  145,
-       59,   47,   45,  978,  978,  978,  978,  978,  978,  979,
-      980,  980,  980,  980,  980,  980,  451, 1463, 1463, 1463,
+       55,   55,   55, 1013,  670, 1661,   55,  669,  468, 1013,
+     1013, 1013, 1013, 1013, 1013, 1014, 1015, 1015, 1015, 1015,
+     1015, 1015,  453, 1669,   55, 1662, 1016,  666,  470,   55,
+      464,   55, 1016, 1016, 1016, 1016, 1016, 1016,  919, 1024,
+     1024, 1024, 1024, 1024, 1024, 1024,  921,   55, 1663,   55,
+     1025,  551, 1672,   55,   55,  535, 1025, 1025, 1025, 1025,
+     1025, 1025, 1026, 1027, 1027, 1027, 1027, 1027, 1027,  453,
+      542,   55,   55, 1028,  634,  625, 1680, 1681,   55, 1028,
+     1028, 1028, 1028, 1028, 1028,  930, 1039, 1039, 1039, 1039,
+     1039, 1039, 1039,  932,  535,  625,   55, 1040,  619,   55,
 
-      981, 1463, 1463, 1463, 1463, 1463,  981,  981,  981,  981,
-      981,  981,  890,  993,  993,  993,  993,  993,  993,  993,
-      892, 1463, 1463, 1463,  994, 1463, 1463, 1463, 1463, 1463,
-      994,  994,  994,  994,  994,  994,  995,  996,  996,  996,
-      996,  996,  996,  451, 1463, 1463, 1463,  997, 1463, 1463,
-     1463, 1463, 1463,  997,  997,  997,  997,  997,  997,  819,
-     1004, 1004, 1004, 1004, 1004, 1004, 1004,  821, 1463, 1463,
-     1463, 1005, 1463, 1463, 1463, 1463, 1463, 1005, 1005, 1005,
-     1005, 1005, 1005, 1006, 1007, 1007, 1007, 1007, 1007, 1007,
-     1007, 1008, 1463, 1463, 1463, 1009, 1463, 1010, 1463, 1463,
+       55, 1686,  619, 1040, 1040, 1040, 1040, 1040, 1040, 1041,
+     1042, 1042, 1042, 1042, 1042, 1042,  453,   55,   55,  612,
+     1043, 1687,  611,   55,   55,   55, 1043, 1043, 1043, 1043,
+     1043, 1043,  942, 1055, 1055, 1055, 1055, 1055, 1055, 1055,
+      944,   55,   55,   55, 1056, 1693, 1690,   55,   55,  610,
+     1056, 1056, 1056, 1056, 1056, 1056, 1057, 1058, 1058, 1058,
+     1058, 1058, 1058,  453,  609,   55,   55, 1059,  608,  607,
+       55, 1700,   55, 1059, 1059, 1059, 1059, 1059, 1059,  861,
+     1066, 1066, 1066, 1066, 1066, 1066, 1066,  863,   55, 1694,
+       55, 1067,  606,  605,   55, 1708,   55, 1067, 1067, 1067,
+
+     1067, 1067, 1067, 1068, 1069, 1069, 1069, 1069, 1069, 1069,
+     1069, 1070,   55,  604,   55, 1071,  603, 1072,  602,  338,
+      239, 1071, 1071, 1071, 1071, 1071, 1071, 1239, 1240, 1240,
+     1240, 1240, 1240, 1240, 1245, 1246, 1246, 1246, 1246, 1246,
+     1246,   55,   55, 1072,   55,  619, 1095, 1095, 1095, 1095,
+     1095, 1095, 1095,  601,  600,  599,  598, 1096,  597,   55,
+       55,  596,   55, 1096, 1096, 1096, 1096, 1096, 1096,   53,
+     1096, 1096, 1096, 1096, 1096, 1096, 1096,   55,  267, 1097,
+     1097, 1097, 1097, 1097, 1097, 1097, 1248, 1249, 1249, 1249,
+     1249, 1249, 1249,   55,   55,   55,  910, 1100, 1100, 1100,
+
+     1100, 1100, 1100, 1100, 1101,  595,  594,  593, 1102,  592,
+      914,   55,   55,  591, 1102, 1102, 1102, 1102, 1102, 1102,
+     1252, 1253, 1253, 1253, 1253, 1253, 1253, 1259, 1260, 1260,
+     1260, 1260, 1260, 1260,   55, 1710,  914,  919, 1103, 1103,
+     1103, 1103, 1103, 1103, 1103, 1104,  590,  589,  581, 1105,
+      578,  923,   55,  575,  574, 1105, 1105, 1105, 1105, 1105,
+     1105, 1262, 1263, 1263, 1263, 1263, 1263, 1263, 1266, 1267,
+     1267, 1267, 1267, 1267, 1267,   55, 1714,  923,  930, 1106,
+     1106, 1106, 1106, 1106, 1106, 1106, 1107,  573,  572,  571,
+     1108,  570,  934,   55,  569,  568, 1108, 1108, 1108, 1108,
+
+     1108, 1108, 1273, 1274, 1274, 1274, 1274, 1274, 1274, 1276,
+     1277, 1277, 1277, 1277, 1277, 1277,   55,   55,  934,  942,
+     1109, 1109, 1109, 1109, 1109, 1109, 1109, 1110,  567,  566,
+      470, 1111,  279,  946,   55,   55,  453, 1111, 1111, 1111,
+     1111, 1111, 1111, 1280, 1281, 1281, 1281, 1281, 1281, 1281,
+     1168, 1168, 1168, 1168, 1168, 1168, 1168,  365,  551,  946,
+     1113, 1114, 1114, 1114, 1114, 1114, 1114, 1115,  535,  542,
+      453, 1116,  539,  450,  444,   55,   55, 1116, 1116, 1116,
+     1116, 1116, 1116, 1117, 1118, 1118, 1118, 1118, 1118, 1118,
+     1118, 1119,   55,   55,   55, 1120,   55, 1121,   55, 1350,
+
+       55, 1120, 1120, 1120, 1120, 1120, 1120, 1308, 1305,  535,
+       55,  533,  444, 1728,   55,  436,   55,   55,   55,  430,
+      520, 1303,  519, 1121,  910, 1124, 1124, 1124, 1124, 1124,
+     1124, 1124, 1101, 1312, 1583,   55, 1125, 1402, 1717, 1728,
+       55,   55, 1125, 1125, 1125, 1125, 1125, 1125, 1126, 1127,
+     1127, 1127, 1127, 1127, 1127, 1127, 1128,   55,   55,   55,
+     1129,  518, 1130,  517,  516,   55, 1129, 1129, 1129, 1129,
+     1129, 1129, 1309, 1313,  515,   55, 1337, 1338, 1338, 1338,
+     1338, 1338, 1338,   55, 1352,   55, 1307,  514, 1130,  919,
+     1135, 1135, 1135, 1135, 1135, 1135, 1135, 1104, 1353,  513,
+
+     1403, 1136,  512,   55,  511,   55,  510, 1136, 1136, 1136,
+     1136, 1136, 1136, 1137, 1138, 1138, 1138, 1138, 1138, 1138,
+     1138, 1139, 1405,   55, 1353, 1140,  509, 1141, 1352,  508,
+      507, 1140, 1140, 1140, 1140, 1140, 1140, 1317,  506,  503,
+      502,  499, 1728, 1246, 1246, 1246, 1246, 1246, 1246, 1246,
+      498, 1358,   55, 1141,  930, 1147, 1147, 1147, 1147, 1147,
+     1147, 1147, 1107,  497,  496, 1359, 1148,  495, 1728,  120,
+       55,  494, 1148, 1148, 1148, 1148, 1148, 1148, 1149, 1150,
+     1150, 1150, 1150, 1150, 1150, 1150, 1151, 1408, 1358, 1360,
+     1152, 1359, 1153, 1360,  493,  481, 1152, 1152, 1152, 1152,
 
-     1463, 1009, 1009, 1009, 1009, 1009, 1009, 1164, 1165, 1165,
-     1165, 1165, 1165, 1165, 1168, 1169, 1169, 1169, 1169, 1169,
-     1169, 1463, 1463, 1010,   55,  601, 1023, 1023, 1023, 1023,
-     1023, 1023, 1023, 1463, 1463, 1463, 1463, 1024, 1463, 1463,
-     1463, 1463,   55, 1024, 1024, 1024, 1024, 1024, 1024,   53,
-     1024, 1024, 1024, 1024, 1024, 1024, 1024,   55,  267, 1025,
-     1025, 1025, 1025, 1025, 1025, 1025, 1175, 1176, 1176, 1176,
-     1176, 1176, 1176, 1463, 1463,   55,  858, 1028, 1028, 1028,
-     1028, 1028, 1028, 1028, 1029, 1463, 1463, 1463, 1030, 1463,
-      862, 1463, 1463, 1463, 1030, 1030, 1030, 1030, 1030, 1030,
+     1152, 1152, 1728, 1361,  480,  479,  478, 1728, 1260, 1260,
+     1260, 1260, 1260, 1260, 1260,  477, 1366,   55, 1153,  942,
+     1159, 1159, 1159, 1159, 1159, 1159, 1159, 1110, 1728, 1361,
+     1367, 1160,  476, 1728,  475,   55,  474, 1160, 1160, 1160,
+     1160, 1160, 1160, 1161, 1162, 1162, 1162, 1162, 1162, 1162,
+     1162, 1163, 1475, 1366, 1368, 1164, 1367, 1165, 1368,  473,
+      277, 1164, 1164, 1164, 1164, 1164, 1164, 1728, 1369,  470,
+      279,  453, 1728, 1274, 1274, 1274, 1274, 1274, 1274, 1274,
+      367, 1374,   55, 1165, 1068, 1176, 1176, 1176, 1176, 1176,
+     1176, 1176, 1070, 1728, 1369, 1375, 1177,  450, 1728,  444,
 
-     1178, 1179, 1179, 1179, 1179, 1179, 1179, 1182, 1183, 1183,
-     1183, 1183, 1183, 1183, 1463, 1463,  862,  867, 1031, 1031,
-     1031, 1031, 1031, 1031, 1031, 1032, 1463, 1463, 1463, 1033,
-     1463,  871, 1463, 1463, 1463, 1033, 1033, 1033, 1033, 1033,
-     1033, 1189, 1190, 1190, 1190, 1190, 1190, 1190, 1192, 1193,
-     1193, 1193, 1193, 1193, 1193, 1463, 1463,  871,  878, 1034,
-     1034, 1034, 1034, 1034, 1034, 1034, 1035, 1463, 1463, 1463,
-     1036, 1463,  882, 1463, 1463, 1463, 1036, 1036, 1036, 1036,
-     1036, 1036, 1196, 1197, 1197, 1197, 1197, 1197, 1197, 1096,
-     1096, 1096, 1096, 1096, 1096, 1096,   55, 1463,  882,  890,
+       55, 1374, 1177, 1177, 1177, 1177, 1177, 1177, 1178, 1179,
+     1179, 1179, 1179, 1179, 1179, 1728,  444, 1547,  437, 1180,
+      437, 1375,   55,  429,   55, 1180, 1180, 1180, 1180, 1180,
+     1180,   55,  619, 1204, 1204, 1204, 1204, 1204, 1204, 1204,
+       55, 1728,   55,  420,  989, 1715,  419, 1719,  416,   55,
+      989,  989,  989,  989,  989,  989,   53,  989,  989,  989,
+      989,  989,  989,  989,   55,  267, 1097, 1097, 1097, 1097,
+     1097, 1097, 1097,  415,   55,   55, 1376, 1376,   55,   55,
+      414, 1421,   55, 1207, 1208, 1208, 1208, 1208, 1208, 1208,
+     1377, 1728,   55,   55, 1209, 1422,   55,   55, 1399,  413,
 
-     1037, 1037, 1037, 1037, 1037, 1037, 1037, 1038, 1463, 1270,
-     1272, 1039, 1463,  894,   55, 1463, 1463, 1039, 1039, 1039,
-     1039, 1039, 1039, 1463, 1273, 1219, 1241, 1242, 1242, 1242,
-     1242, 1242, 1242, 1463, 1272, 1463, 1463, 1463, 1278,  894,
-     1041, 1042, 1042, 1042, 1042, 1042, 1042, 1043, 1463, 1463,
-     1273, 1044, 1279, 1463, 1463, 1463, 1463, 1044, 1044, 1044,
-     1044, 1044, 1044, 1045, 1046, 1046, 1046, 1046, 1046, 1046,
-     1046, 1047, 1463, 1463, 1463, 1048, 1463, 1049, 1279, 1463,
-     1463, 1048, 1048, 1048, 1048, 1048, 1048, 1162, 1162, 1162,
-     1162, 1162, 1162, 1162, 1176, 1176, 1176, 1176, 1176, 1176,
+     1209, 1209, 1209, 1209, 1209, 1209,  910, 1012, 1012, 1012,
+     1012, 1012, 1012, 1012, 1101, 1400, 1377, 1728, 1013,  412,
+      411, 1422,  410, 1421, 1013, 1013, 1013, 1013, 1013, 1013,
+     1210, 1211, 1211, 1211, 1211, 1211, 1211, 1728,  409,  408,
+      407, 1212,  406,  405,  404,  403,   55, 1212, 1212, 1212,
+     1212, 1212, 1212,  919, 1024, 1024, 1024, 1024, 1024, 1024,
+     1024, 1104,  402, 1728,   55, 1025,  401,  400,  395,  394,
+     1468, 1025, 1025, 1025, 1025, 1025, 1025, 1213, 1214, 1214,
+     1214, 1214, 1214, 1214, 1469, 1698,  393,  392, 1215,  391,
+      320,  390,  389,   55, 1215, 1215, 1215, 1215, 1215, 1215,
 
-     1176, 1278, 1463, 1049,  858, 1052, 1052, 1052, 1052, 1052,
-     1052, 1052, 1029, 1463, 1463, 1463, 1053, 1463, 1463, 1463,
-     1463, 1463, 1053, 1053, 1053, 1053, 1053, 1053, 1054, 1055,
-     1055, 1055, 1055, 1055, 1055, 1055, 1056, 1463, 1463, 1463,
-     1057, 1463, 1058, 1463, 1463, 1280, 1057, 1057, 1057, 1057,
-     1057, 1057, 1190, 1190, 1190, 1190, 1190, 1190, 1190, 1281,
-     1463, 1463, 1463, 1463, 1280, 1463, 1312, 1463, 1058,  867,
-     1063, 1063, 1063, 1063, 1063, 1063, 1063, 1032, 1463, 1463,
-     1313, 1064, 1463, 1463, 1463, 1281, 1463, 1064, 1064, 1064,
-     1064, 1064, 1064, 1065, 1066, 1066, 1066, 1066, 1066, 1066,
+      930, 1039, 1039, 1039, 1039, 1039, 1039, 1039, 1107,  388,
+     1469,   55, 1040,  387,  386,  385,  379, 1468, 1040, 1040,
+     1040, 1040, 1040, 1040, 1216, 1217, 1217, 1217, 1217, 1217,
+     1217, 1728, 1723,  279,  367, 1218,  275,  364,  272,  360,
+      266, 1218, 1218, 1218, 1218, 1218, 1218,  942, 1055, 1055,
+     1055, 1055, 1055, 1055, 1055, 1110,  260, 1728,  143, 1056,
+      348,  347,  346,  341, 1470, 1056, 1056, 1056, 1056, 1056,
+     1056, 1219, 1220, 1220, 1220, 1220, 1220, 1220, 1471,  320,
+      340,  339, 1221,  338,  337,  336,  335,  334, 1221, 1221,
+     1221, 1221, 1221, 1221, 1223, 1224, 1224, 1224, 1224, 1224,
 
-     1066, 1067, 1463, 1463, 1463, 1068, 1313, 1069, 1463, 1463,
-     1463, 1068, 1068, 1068, 1068, 1068, 1068, 1286, 1287, 1287,
-     1287, 1287, 1287, 1287, 1289, 1290, 1290, 1290, 1290, 1290,
-     1290, 1312, 1463, 1069,  878, 1075, 1075, 1075, 1075, 1075,
-     1075, 1075, 1035, 1463, 1463, 1463, 1076, 1463, 1463, 1463,
-     1463, 1463, 1076, 1076, 1076, 1076, 1076, 1076, 1077, 1078,
-     1078, 1078, 1078, 1078, 1078, 1078, 1079, 1463, 1463, 1463,
-     1080, 1463, 1081, 1463, 1463, 1463, 1080, 1080, 1080, 1080,
-     1080, 1080, 1293, 1294, 1294, 1294, 1294, 1294, 1294, 1318,
-     1319, 1319, 1319, 1319, 1319, 1319, 1359, 1463, 1081,  890,
+     1224, 1224, 1225,  333, 1471,  332, 1226,  331, 1227,  330,
+      329,  328, 1226, 1226, 1226, 1226, 1226, 1226, 1382, 1383,
+     1383, 1383, 1383, 1383, 1383, 1385, 1386, 1386, 1386, 1386,
+     1386, 1386,   55,  327, 1227, 1117, 1231, 1231, 1231, 1231,
+     1231, 1231, 1231, 1119,  326,  323,  322, 1232,  321,  320,
+       55, 1406,  319, 1232, 1232, 1232, 1232, 1232, 1232, 1126,
+     1241, 1241, 1241, 1241, 1241, 1241, 1241, 1128, 1407,  318,
+      317, 1242,  316,  315,  314,  313,  312, 1242, 1242, 1242,
+     1242, 1242, 1242, 1137, 1254, 1254, 1254, 1254, 1254, 1254,
+     1254, 1139,  311,  310,  309, 1255,  308,  307,  306,  305,
 
-     1087, 1087, 1087, 1087, 1087, 1087, 1087, 1038, 1463, 1463,
-     1360, 1088, 1463, 1463, 1463, 1463,   55, 1088, 1088, 1088,
-     1088, 1088, 1088, 1089, 1090, 1090, 1090, 1090, 1090, 1090,
-     1090, 1091,   55, 1463,   55, 1092, 1360, 1093, 1463, 1463,
-     1463, 1092, 1092, 1092, 1092, 1092, 1092, 1301, 1463, 1463,
-       55, 1323, 1324, 1324, 1324, 1324, 1324, 1324, 1463, 1463,
-     1359, 1302, 1463, 1093, 1006, 1104, 1104, 1104, 1104, 1104,
-     1104, 1104, 1008, 1463, 1463, 1463, 1105, 1463, 1463, 1463,
-     1463, 1361, 1105, 1105, 1105, 1105, 1105, 1105, 1106, 1107,
-     1107, 1107, 1107, 1107, 1107, 1362, 1463, 1463, 1463, 1108,
+      304, 1255, 1255, 1255, 1255, 1255, 1255, 1149, 1268, 1268,
+     1268, 1268, 1268, 1268, 1268, 1151,  303,  302,  301, 1269,
+      300,  299,  298,  297,  143, 1269, 1269, 1269, 1269, 1269,
+     1269, 1161, 1282, 1282, 1282, 1282, 1282, 1282, 1282, 1163,
+      296,  295,  294, 1283,  293,  292,  291,  290,  289, 1283,
+     1283, 1283, 1283, 1283, 1283, 1068, 1291, 1291, 1291, 1291,
+     1291, 1291, 1291, 1070,  288,  287,  286, 1292,  285,  284,
+      283,  282,  279, 1292, 1292, 1292, 1292, 1292, 1292, 1293,
+     1294, 1294, 1294, 1294, 1294, 1294, 1294, 1295,  267,  272,
+      259, 1296,  258, 1297,   55,   55, 1470, 1296, 1296, 1296,
 
-     1463, 1463, 1463, 1463, 1463, 1108, 1108, 1108, 1108, 1108,
-     1108,   55,  601, 1120, 1120, 1120, 1120, 1120, 1120, 1120,
-     1463, 1362, 1463, 1463,  927, 1463, 1463, 1463, 1463,   55,
-      927,  927,  927,  927,  927,  927,   53,  927,  927,  927,
-      927,  927,  927,  927,   55,  267, 1025, 1025, 1025, 1025,
-     1025, 1025, 1025, 1326, 1327, 1327, 1327, 1327, 1327, 1327,
-     1463, 1361,   55, 1123, 1124, 1124, 1124, 1124, 1124, 1124,
-     1463, 1463, 1463, 1463, 1125, 1463, 1463, 1463, 1463, 1463,
-     1125, 1125, 1125, 1125, 1125, 1125,  858,  950,  950,  950,
-      950,  950,  950,  950, 1029, 1463, 1463, 1463,  951, 1463,
+     1296, 1296, 1296, 1389, 1390, 1390, 1390, 1390, 1390, 1390,
+     1728,   55,   55,   55,  257,   55,   55,   55,  256, 1297,
+       55,  619,  525,  525,  525,  525,  525,  525,  525,   55,
+      255, 1534, 1576,   55,   55,   55, 1728, 1506,   55, 1318,
+     1319, 1319, 1319, 1319, 1319, 1319, 1320, 1397, 1410, 1660,
+     1321, 1507, 1586,  254,  253,   55, 1321, 1321, 1321, 1321,
+     1321, 1321, 1117, 1322, 1322, 1322, 1322, 1322, 1322, 1322,
+     1323,   55,   55,   55, 1324,  252, 1121, 1507,  251,  250,
+     1324, 1324, 1324, 1324, 1324, 1324,  247, 1480,  244,   55,
+       55, 1427, 1428, 1428, 1428, 1428, 1428, 1428,  241,  240,
 
-     1463, 1463, 1463, 1384,  951,  951,  951,  951,  951,  951,
-     1126, 1127, 1127, 1127, 1127, 1127, 1127, 1385, 1463, 1463,
-     1463, 1128, 1463, 1463, 1463, 1463, 1463, 1128, 1128, 1128,
-     1128, 1128, 1128,  867,  962,  962,  962,  962,  962,  962,
-      962, 1032, 1463, 1385, 1463,  963, 1463, 1463, 1463, 1463,
-     1384,  963,  963,  963,  963,  963,  963, 1129, 1130, 1130,
-     1130, 1130, 1130, 1130, 1463, 1463, 1463, 1463, 1131, 1463,
-     1463, 1463, 1463, 1463, 1131, 1131, 1131, 1131, 1131, 1131,
-      878,  977,  977,  977,  977,  977,  977,  977, 1035, 1463,
-     1463, 1463,  978, 1463, 1463, 1463, 1463, 1388,  978,  978,
+     1398, 1411, 1121, 1126, 1325, 1325, 1325, 1325, 1325, 1325,
+     1325, 1326,  239,  238,  235, 1327,  234, 1130,  233,  232,
+      231, 1327, 1327, 1327, 1327, 1327, 1327, 1432, 1433, 1433,
+     1433, 1433, 1433, 1433, 1435, 1436, 1436, 1436, 1436, 1436,
+     1436,  230,  229, 1130, 1137, 1328, 1328, 1328, 1328, 1328,
+     1328, 1328, 1329,  228,  227,  226, 1330,  225, 1141,  224,
+      223,  222, 1330, 1330, 1330, 1330, 1330, 1330, 1441, 1442,
+     1442, 1442, 1442, 1442, 1442, 1444, 1445, 1445, 1445, 1445,
+     1445, 1445,  221,  220, 1141, 1149, 1331, 1331, 1331, 1331,
+     1331, 1331, 1331, 1332,  216,  215,  205, 1333,  204, 1153,
 
-      978,  978,  978,  978, 1132, 1133, 1133, 1133, 1133, 1133,
-     1133, 1389, 1463, 1463, 1463, 1134, 1463, 1463, 1463, 1463,
-     1463, 1134, 1134, 1134, 1134, 1134, 1134,  890,  993,  993,
-      993,  993,  993,  993,  993, 1038, 1463, 1389, 1463,  994,
-     1463, 1463, 1463, 1463, 1388,  994,  994,  994,  994,  994,
-      994, 1135, 1136, 1136, 1136, 1136, 1136, 1136, 1463, 1463,
-     1463, 1463, 1137, 1463, 1463, 1463, 1463, 1463, 1137, 1137,
-     1137, 1137, 1137, 1137, 1139, 1140, 1140, 1140, 1140, 1140,
-     1140, 1140, 1141, 1463, 1463, 1463, 1142, 1463, 1143, 1463,
-     1463, 1463, 1142, 1142, 1142, 1142, 1142, 1142, 1332, 1333,
+      203,  200,  199, 1333, 1333, 1333, 1333, 1333, 1333, 1450,
+     1451, 1451, 1451, 1451, 1451, 1451, 1453, 1454, 1454, 1454,
+     1454, 1454, 1454,  194,  193, 1153, 1161, 1334, 1334, 1334,
+     1334, 1334, 1334, 1334, 1335,  192,  191,  190, 1336,  189,
+     1165,  188,  187,  186, 1336, 1336, 1336, 1336, 1336, 1336,
+     1459, 1460, 1460, 1460, 1460, 1460, 1460, 1462, 1463, 1463,
+     1463, 1463, 1463, 1463, 1506,   55, 1165, 1223, 1339, 1339,
+     1339, 1339, 1339, 1339, 1339, 1225,  185,  181, 1728, 1340,
+      180,  179,  178,   55,  177, 1340, 1340, 1340, 1340, 1340,
+     1340, 1117, 1347, 1347, 1347, 1347, 1347, 1347, 1347, 1323,
 
-     1333, 1333, 1333, 1333, 1333, 1335, 1336, 1336, 1336, 1336,
-     1336, 1336, 1392, 1463, 1143, 1045, 1147, 1147, 1147, 1147,
-     1147, 1147, 1147, 1047, 1463, 1463, 1393, 1148, 1463, 1463,
-     1463, 1463, 1463, 1148, 1148, 1148, 1148, 1148, 1148, 1054,
-     1157, 1157, 1157, 1157, 1157, 1157, 1157, 1056, 1463, 1463,
-     1463, 1158, 1393, 1463, 1463, 1463, 1463, 1158, 1158, 1158,
-     1158, 1158, 1158, 1065, 1170, 1170, 1170, 1170, 1170, 1170,
-     1170, 1067, 1463, 1463, 1463, 1171, 1463, 1463, 1463, 1463,
-     1463, 1171, 1171, 1171, 1171, 1171, 1171, 1077, 1184, 1184,
-     1184, 1184, 1184, 1184, 1184, 1079, 1463, 1463, 1463, 1185,
+      176, 1579,  175, 1348, 1728,  174,  173,  172,  171, 1348,
+     1348, 1348, 1348, 1348, 1348, 1126, 1354, 1354, 1354, 1354,
+     1354, 1354, 1354, 1326,  170,  169,  168, 1355,  167,  166,
+      165,  160,  151, 1355, 1355, 1355, 1355, 1355, 1355, 1137,
+     1362, 1362, 1362, 1362, 1362, 1362, 1362, 1329,  150,  145,
+       59, 1363,   47,   45, 1728, 1728, 1728, 1363, 1363, 1363,
+     1363, 1363, 1363, 1149, 1370, 1370, 1370, 1370, 1370, 1370,
+     1370, 1332, 1728, 1728, 1728, 1371, 1728, 1728, 1728, 1728,
+     1728, 1371, 1371, 1371, 1371, 1371, 1371, 1161, 1378, 1378,
+     1378, 1378, 1378, 1378, 1378, 1335, 1728, 1728, 1728, 1379,
 
-     1463, 1463, 1463, 1463, 1463, 1185, 1185, 1185, 1185, 1185,
-     1185, 1089, 1198, 1198, 1198, 1198, 1198, 1198, 1198, 1091,
-     1463, 1463, 1463, 1199, 1463, 1463, 1463, 1463, 1463, 1199,
-     1199, 1199, 1199, 1199, 1199, 1006, 1207, 1207, 1207, 1207,
-     1207, 1207, 1207, 1008, 1463, 1463, 1463, 1208, 1463, 1463,
-     1463, 1463, 1463, 1208, 1208, 1208, 1208, 1208, 1208, 1209,
-     1210, 1210, 1210, 1210, 1210, 1210, 1210, 1211, 1463, 1463,
-     1463, 1212, 1463, 1213, 1463, 1463, 1463, 1212, 1212, 1212,
-     1212, 1212, 1212, 1341, 1342, 1342, 1342, 1342, 1342, 1342,
-     1344, 1345, 1345, 1345, 1345, 1345, 1345, 1463, 1463, 1213,
+     1728, 1728, 1728, 1728, 1728, 1379, 1379, 1379, 1379, 1379,
+     1379, 1293, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1295,
+     1728, 1728, 1728, 1392, 1728, 1728, 1728, 1728, 1728, 1392,
+     1392, 1392, 1392, 1392, 1392, 1223, 1412, 1412, 1412, 1412,
+     1412, 1412, 1412, 1413, 1728, 1728, 1728, 1414, 1728, 1227,
+     1728, 1728, 1728, 1414, 1414, 1414, 1414, 1414, 1414, 1383,
+     1383, 1383, 1383, 1383, 1383, 1383, 1500, 1501, 1501, 1501,
+     1501, 1501, 1501, 1510,   55, 1227, 1117, 1231, 1231, 1231,
+     1231, 1231, 1231, 1231, 1323, 1728, 1728, 1511, 1232, 1728,
+     1728, 1728,   55, 1728, 1232, 1232, 1232, 1232, 1232, 1232,
 
-       55,  601,  518,  518,  518,  518,  518,  518,  518, 1350,
-     1351, 1351, 1351, 1351, 1351, 1351, 1463, 1392,   55, 1222,
-     1223, 1223, 1223, 1223, 1223, 1223, 1224, 1463, 1463, 1463,
-     1225, 1463, 1463, 1463, 1463, 1463, 1225, 1225, 1225, 1225,
-     1225, 1225, 1045, 1226, 1226, 1226, 1226, 1226, 1226, 1226,
-     1227, 1463, 1463, 1463, 1228, 1463, 1049, 1463, 1463, 1463,
-     1228, 1228, 1228, 1228, 1228, 1228, 1353, 1354, 1354, 1354,
-     1354, 1354, 1354, 1287, 1287, 1287, 1287, 1287, 1287, 1287,
-     1463, 1463, 1049, 1054, 1229, 1229, 1229, 1229, 1229, 1229,
-     1229, 1230, 1463, 1463, 1463, 1231, 1463, 1058, 1463, 1463,
+     1126, 1241, 1241, 1241, 1241, 1241, 1241, 1241, 1326, 1728,
+     1580, 1728, 1242, 1511, 1728, 1728, 1728, 1728, 1242, 1242,
+     1242, 1242, 1242, 1242, 1137, 1254, 1254, 1254, 1254, 1254,
+     1254, 1254, 1329, 1728, 1728, 1728, 1255, 1728, 1728, 1728,
+     1728, 1728, 1255, 1255, 1255, 1255, 1255, 1255, 1149, 1268,
+     1268, 1268, 1268, 1268, 1268, 1268, 1332, 1728, 1728, 1728,
+     1269, 1728, 1728, 1728, 1728, 1728, 1269, 1269, 1269, 1269,
+     1269, 1269, 1161, 1282, 1282, 1282, 1282, 1282, 1282, 1282,
+     1335, 1728, 1728, 1728, 1283, 1728, 1728, 1728, 1728, 1728,
+     1283, 1283, 1283, 1283, 1283, 1283, 1223, 1423, 1423, 1423,
 
-     1463, 1231, 1231, 1231, 1231, 1231, 1231, 1378, 1379, 1379,
-     1379, 1379, 1379, 1379, 1324, 1324, 1324, 1324, 1324, 1324,
-     1324, 1463, 1463, 1058, 1065, 1232, 1232, 1232, 1232, 1232,
-     1232, 1232, 1233, 1463, 1463, 1463, 1234, 1463, 1069, 1463,
-     1463, 1463, 1234, 1234, 1234, 1234, 1234, 1234, 1333, 1333,
-     1333, 1333, 1333, 1333, 1333, 1342, 1342, 1342, 1342, 1342,
-     1342, 1342, 1396, 1463, 1069, 1077, 1235, 1235, 1235, 1235,
-     1235, 1235, 1235, 1236, 1463, 1396, 1397, 1237, 1463, 1081,
-     1463, 1463, 1463, 1237, 1237, 1237, 1237, 1237, 1237, 1463,
-     1351, 1351, 1351, 1351, 1351, 1351, 1351, 1463, 1463, 1463,
+     1423, 1423, 1423, 1423, 1413, 1728, 1728, 1728, 1424, 1728,
+     1728, 1728,   55, 1728, 1424, 1424, 1424, 1424, 1424, 1424,
+     1293, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1295,   55,
+       55,   55, 1473, 1728, 1510, 1728, 1728, 1728, 1473, 1473,
+     1473, 1473, 1473, 1473, 1487,   55, 1728,   55, 1728,   55,
+     1433, 1433, 1433, 1433, 1433, 1433, 1433, 1728, 1484, 1728,
+     1728, 1488, 1514,   55, 1485, 1223, 1339, 1339, 1339, 1339,
+     1339, 1339, 1339, 1413, 1728, 1548, 1515, 1340, 1728, 1728,
+     1728, 1728, 1514, 1340, 1340, 1340, 1340, 1340, 1340, 1442,
+     1442, 1442, 1442, 1442, 1442, 1442, 1728, 1518, 1518, 1728,
 
-     1463, 1463, 1397, 1400, 1463, 1081, 1089, 1238, 1238, 1238,
-     1238, 1238, 1238, 1238, 1239, 1463, 1400, 1401, 1240, 1463,
-     1093, 1463, 1463, 1463, 1240, 1240, 1240, 1240, 1240, 1240,
-     1463, 1404, 1405, 1405, 1405, 1405, 1405, 1405, 1463, 1463,
-     1463, 1463, 1463, 1401, 1416, 1463, 1093, 1139, 1243, 1243,
-     1243, 1243, 1243, 1243, 1243, 1141, 1463, 1463, 1417, 1244,
-     1463, 1463, 1463, 1463, 1463, 1244, 1244, 1244, 1244, 1244,
-     1244, 1045, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1227,
-     1463, 1463, 1463, 1252, 1417, 1463, 1463, 1463, 1463, 1252,
-     1252, 1252, 1252, 1252, 1252, 1054, 1258, 1258, 1258, 1258,
+     1728, 1728, 1515, 1451, 1451, 1451, 1451, 1451, 1451, 1451,
+     1522, 1519, 1728, 1460, 1460, 1460, 1460, 1460, 1460, 1460,
+     1522, 1728, 1728, 1728, 1523, 1526, 1527, 1527, 1527, 1527,
+     1527, 1527, 1728,   55, 1728,   55,   55, 1519, 1728, 1529,
+     1530, 1530, 1530, 1530, 1530, 1530,   55,   55,   55, 1728,
+     1523,   55,   55,   55,   55, 1551, 1728, 1551,   55,   55,
+     1728,   55, 1538, 1539,   55,   55,   55, 1543, 1728, 1552,
+       55, 1728, 1728, 1540, 1541, 1542,   55,   55, 1728,   55,
+     1728, 1545, 1553, 1554, 1554, 1554, 1554, 1554, 1554, 1728,
+     1728, 1728, 1728, 1622, 1582, 1552, 1587, 1728, 1557, 1558,
 
-     1258, 1258, 1258, 1230, 1463, 1463, 1463, 1259, 1463, 1463,
-     1463, 1463, 1463, 1259, 1259, 1259, 1259, 1259, 1259, 1065,
-     1266, 1266, 1266, 1266, 1266, 1266, 1266, 1233, 1463, 1463,
-     1463, 1267, 1463, 1463, 1463, 1463, 1463, 1267, 1267, 1267,
-     1267, 1267, 1267, 1077, 1274, 1274, 1274, 1274, 1274, 1274,
-     1274, 1236, 1463, 1463, 1463, 1275, 1463, 1463, 1463, 1463,
-     1463, 1275, 1275, 1275, 1275, 1275, 1275, 1089, 1282, 1282,
-     1282, 1282, 1282, 1282, 1282, 1239, 1463, 1463, 1463, 1283,
-     1463, 1463, 1463, 1463, 1463, 1283, 1283, 1283, 1283, 1283,
-     1283, 1209, 1295, 1295, 1295, 1295, 1295, 1295, 1295, 1211,
+     1558, 1558, 1558, 1558, 1558, 1561, 1562, 1562, 1562, 1562,
+     1562, 1562, 1565, 1566, 1566, 1566, 1566, 1566, 1566, 1569,
+     1570, 1570, 1570, 1570, 1570, 1570, 1527, 1527, 1527, 1527,
+     1527, 1527, 1527, 1573, 1573,   55,   55,   55, 1589, 1590,
+     1590, 1590, 1590, 1590, 1590, 1728, 1728, 1574, 1728, 1728,
+     1728, 1728, 1728,   55,   55,   55, 1728, 1728, 1728, 1728,
+     1728, 1728, 1578, 1585, 1588, 1554, 1554, 1554, 1554, 1554,
+     1554, 1554, 1728, 1574, 1728, 1558, 1558, 1558, 1558, 1558,
+     1558, 1558, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1566,
+     1566, 1566, 1566, 1566, 1566, 1566, 1570, 1570, 1570, 1570,
 
-     1463, 1463, 1463, 1296, 1463, 1463, 1463, 1463, 1463, 1296,
-     1296, 1296, 1296, 1296, 1296, 1139, 1303, 1303, 1303, 1303,
-     1303, 1303, 1303, 1304, 1463, 1463, 1463, 1305, 1463, 1143,
-     1463, 1463, 1416, 1305, 1305, 1305, 1305, 1305, 1305, 1407,
-     1408, 1408, 1408, 1408, 1408, 1408, 1463, 1418, 1419, 1419,
-     1419, 1419, 1419, 1419, 1463, 1143, 1045, 1147, 1147, 1147,
-     1147, 1147, 1147, 1147, 1227, 1463, 1463, 1463, 1148, 1463,
-     1463, 1463, 1463, 1463, 1148, 1148, 1148, 1148, 1148, 1148,
-     1054, 1157, 1157, 1157, 1157, 1157, 1157, 1157, 1230, 1463,
-     1463, 1463, 1158, 1463, 1463, 1463, 1463, 1463, 1158, 1158,
+     1570, 1570, 1570, 1598, 1599, 1599, 1599, 1599, 1599, 1599,
+       55,   55, 1728,   55,   55,   55,   55,   55, 1590, 1590,
+     1590, 1590, 1590, 1590, 1590,   55,   55, 1728,   55,   55,
+     1605,   55,   55,   55,   55,   55, 1728, 1728, 1728, 1728,
+     1728, 1728, 1611,   55,   55, 1601,   55, 1606,   55,   55,
+     1607, 1608, 1609, 1612, 1599, 1599, 1599, 1599, 1599, 1599,
+     1599,   55, 1620, 1628,   55,   55,   55,   55,   55,   55,
+     1728,   55,   55, 1621,   55,   55,   55,   55, 1728,   55,
+     1623, 1625,   55,   55, 1728, 1728,   55,   55, 1629,   55,
+       55,   55,   55,   55,   55,   55, 1647, 1630, 1637, 1728,
 
-     1158, 1158, 1158, 1158, 1065, 1170, 1170, 1170, 1170, 1170,
-     1170, 1170, 1233, 1463, 1463, 1463, 1171, 1463, 1463, 1463,
-     1463, 1463, 1171, 1171, 1171, 1171, 1171, 1171, 1077, 1184,
-     1184, 1184, 1184, 1184, 1184, 1184, 1236, 1463, 1463, 1463,
-     1185, 1463, 1463, 1463, 1463, 1463, 1185, 1185, 1185, 1185,
-     1185, 1185, 1089, 1198, 1198, 1198, 1198, 1198, 1198, 1198,
-     1239, 1463, 1463, 1463, 1199, 1463, 1463, 1463, 1463, 1463,
-     1199, 1199, 1199, 1199, 1199, 1199, 1139, 1314, 1314, 1314,
-     1314, 1314, 1314, 1314, 1304, 1463, 1463, 1463, 1315, 1463,
-     1463, 1463, 1463, 1463, 1315, 1315, 1315, 1315, 1315, 1315,
+       55,   55, 1638, 1645,   55, 1633, 1641, 1639, 1728,   55,
+       55, 1640,   55, 1648, 1649,   55, 1650, 1651, 1728,   55,
+       55, 1728,   55,   55,   55,   55, 1652, 1728,   55, 1728,
+       55,   55,   55,   55, 1728,   55, 1653,   55,   55, 1654,
+     1728,   55,   55,   55, 1658, 1656, 1666, 1665, 1728,   55,
+       55,   55, 1664,   55, 1670,   55, 1675,   55, 1667, 1668,
+     1677,   55,   55,   55,   55, 1728, 1671,   55, 1673,   55,
+     1674,   55,   55, 1676, 1728,   55,   55, 1728,   55,   55,
+       55,   55,   55, 1678, 1728,   55,   55, 1728, 1682,   55,
+       55,   55, 1683, 1728,   55, 1679,   55, 1685, 1684, 1688,
 
-     1209, 1363, 1363, 1363, 1363, 1363, 1363, 1363, 1211, 1463,
-     1463, 1463, 1364, 1463, 1463, 1463, 1463, 1463, 1364, 1364,
-     1364, 1364, 1364, 1364, 1139, 1243, 1243, 1243, 1243, 1243,
-     1243, 1243, 1304, 1463, 1463, 1463, 1244, 1463, 1463, 1463,
-     1463, 1463, 1244, 1244, 1244, 1244, 1244, 1244, 1422, 1423,
-     1423, 1423, 1423, 1423, 1423, 1426, 1427, 1427, 1427, 1427,
-     1427, 1427, 1430, 1431, 1431, 1431, 1431, 1431, 1431, 1434,
-     1435, 1435, 1435, 1435, 1435, 1435, 1405, 1405, 1405, 1405,
-     1405, 1405, 1405, 1438, 1438, 1442, 1443, 1443, 1443, 1443,
-     1443, 1443, 1463, 1463, 1463, 1463, 1463, 1439, 1463, 1419,
+       55, 1728, 1689,   55,   55, 1691,   55,   55, 1728,   55,
+     1695, 1692,   55,   55,   55,   55, 1728, 1728,   55, 1696,
+     1697,   55,   55, 1728,   55,   55, 1701,   55,   55, 1699,
+       55,   55,   55,   55, 1704, 1702,   55,   55,   55, 1728,
+       55, 1706, 1709, 1703, 1705,   55,   55,   55,   55,   55,
+       55, 1728, 1707, 1728,   55,   55,   55, 1711, 1728, 1728,
+     1728, 1728, 1728, 1716, 1712,   55,   55,   55,   55, 1728,
+     1728, 1728, 1713, 1728, 1718, 1721, 1722,   55, 1728, 1728,
+     1726, 1727, 1728, 1720, 1728, 1724, 1728, 1725, 1728, 1728,
+     1728, 1728, 1728, 1728, 1728,   55,   46, 1728, 1728, 1728,
 
-     1419, 1419, 1419, 1419, 1419, 1419, 1423, 1423, 1423, 1423,
-     1423, 1423, 1423, 1427, 1427, 1427, 1427, 1427, 1427, 1427,
-     1463, 1463, 1463, 1439, 1463, 1431, 1431, 1431, 1431, 1431,
-     1431, 1431, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1451,
-     1452, 1452, 1452, 1452, 1452, 1452, 1443, 1443, 1443, 1443,
-     1443, 1443, 1443, 1452, 1452, 1452, 1452, 1452, 1452, 1452,
-       46, 1463, 1463, 1463, 1463,   46,   46,   46,   64, 1463,
-       64,   64,   64,   64,   64,   64,   64,  152, 1463,  152,
-      159,  159,  159,  271,  271,  271,  280,  280,  280,  359,
-      359,  359,  362,  362,  362,  363,  363,  363,  370,  370,
+     1728,   46,   46,   46,   64, 1728,   64,   64,   64,   64,
+       64,   64,   64,  152, 1728,  152,  159,  159,  159,  271,
+      271,  271,  280,  280,  280,  359,  359,  359,  362,  362,
+      362,  363,  363,  363,  370,  370,  370,  368,  368,  368,
+      374,  374,  374,  378, 1728,  378,  443,  443,  443,  448,
+      448,  448,  449,  449,  449,  458,  458,  458,  462, 1728,
+      462,  463,  463,  463,  372,  372, 1728, 1728,  372,  467,
+      467,  467,  471,  471,  471,  362,  362,  362,  532,  532,
+      532,  536,  536,  536,  537,  537,  537,  538,  538,  538,
+      370,  370,  370,  543,  543,  543,  456,  456, 1728, 1728,
 
-      370,  368,  368,  368,  374,  374,  374,  378, 1463,  378,
-      441,  441,  441,  446,  446,  446,  447,  447,  447,  456,
-      456,  456,  460, 1463,  460,  461,  461,  461,  372,  372,
-     1463, 1463,  372,  465,  465,  465,  469,  469,  469,  362,
-      362,  362,  525,  525,  525,  529,  529,  529,  530,  530,
-      530,  531,  531,  531,  370,  370,  370,  536,  536,  536,
-      454,  454, 1463, 1463,  454,  541,  541,  541,  545,  545,
-      545,  549, 1463,  549,  550,  550,  550,  554,  554,  554,
-      558, 1463,  558,  606,  606,  606,  456,  456,  456,  614,
-      614,  614,  615,  615,  615,  623,  623,  623,  627, 1463,
+      456,  548,  548,  548,  552,  552,  552,  556, 1728,  556,
+      557,  557,  557,  561,  561,  561,  565, 1728,  565,  624,
+      624,  624,  458,  458,  458,  632,  632,  632,  633,  633,
+      633,  641,  641,  641,  645, 1728,  645,  648, 1728,  648,
+      649,  649,  649,  653,  653,  653,  657, 1728,  657,  555,
+      555, 1728, 1728,  555,  559,  559, 1728, 1728,  559,  663,
+      663,  663,  667,  667,  667,  565,  565, 1728,  565,  537,
+      537,  537,  713,  713,  713,  717,  717,  717,  720,  720,
+      720,  721,  721,  721,  722,  722,  722,  727,  727,  727,
+      639,  639, 1728, 1728,  639,  732,  732,  732,  736,  736,
 
-      627,  630, 1463,  630,  631,  631,  631,  635,  635,  635,
-      639, 1463,  639,  548,  548, 1463, 1463,  548,  552,  552,
-     1463, 1463,  552,  645,  645,  645,  649,  649,  649,  558,
-      558, 1463,  558,  530,  530,  530,  683,  683,  683,  687,
-      687,  687,  690,  690,  690,  691,  691,  691,  692,  692,
-      692,  697,  697,  697,  621,  621, 1463, 1463,  621,  702,
-      702,  702,  706,  706,  706,  627,  627, 1463,  627,  629,
-      629, 1463, 1463,  629,  630,  630, 1463,  630,  631,  631,
-      633,  633, 1463, 1463,  633,  713,  713,  713,  717,  717,
-      717,  639,  639, 1463,  639,  721, 1463,  721,  724, 1463,
+      736,  645,  645, 1728,  645,  647,  647, 1728, 1728,  647,
+      648,  648, 1728,  648,  649,  649,  651,  651, 1728, 1728,
+      651,  743,  743,  743,  747,  747,  747,  657,  657, 1728,
+      657,  751, 1728,  751,  754, 1728,  754,  755,  755,  755,
+      759,  759,  759,  763, 1728,  763,  802,  802,  802,  641,
+      641,  641,  653,  653,  653,  813,  813,  813,  814,  814,
+      814,  822,  822,  822,  826, 1728,  826,  829, 1728,  829,
+      830,  830,  830,  834,  834,  834,  838, 1728,  838,  841,
+     1728,  841,  844, 1728,  844,  845,  845,  845,  849,  849,
+      849,  853, 1728,  853,  750, 1728, 1728,  750,  751,  751,
 
-      724,  725,  725,  725,  729,  729,  729,  733, 1463,  733,
-      760,  760,  760,  623,  623,  623,  635,  635,  635,  771,
-      771,  771,  772,  772,  772,  780,  780,  780,  784, 1463,
-      784,  787, 1463,  787,  788,  788,  788,  792,  792,  792,
-      796, 1463,  796,  799, 1463,  799,  802, 1463,  802,  803,
-      803,  803,  807,  807,  807,  811, 1463,  811,  720, 1463,
-     1463,  720,  721,  721, 1463,  721,  723,  723, 1463, 1463,
-      723,  724,  724, 1463,  724,  725,  725,  727,  727, 1463,
-     1463,  727,  818,  818,  818,  822,  822,  822,  733,  733,
-     1463,  733,   53,   53,   53, 1463,   53,   53,  691,  691,
+     1728,  751,  753,  753, 1728, 1728,  753,  754,  754, 1728,
+      754,  755,  755,  757,  757, 1728, 1728,  757,  860,  860,
+      860,  864,  864,  864,  763,  763, 1728,  763,   53,   53,
+       53, 1728,   53,   53,  721,  721,  721,  896,  896,  896,
+      900,  900,  900,  903,  903,  903,  906,  906,  906,  907,
+      907,  907,  908,  908,  908,  913,  913,  913,  820,  820,
+     1728, 1728,  820,  918,  918,  918,  922,  922,  922,  826,
+      826, 1728,  826,  828,  828, 1728, 1728,  828,  829,  829,
+     1728,  829,  830,  830,  832,  832, 1728, 1728,  832,  929,
+      929,  929,  933,  933,  933,  838,  838, 1728,  838,  840,
 
-      691,  844,  844,  844,  848,  848,  848,  851,  851,  851,
-      854,  854,  854,  855,  855,  855,  856,  856,  856,  861,
-      861,  861,  778,  778, 1463, 1463,  778,  866,  866,  866,
-      870,  870,  870,  784,  784, 1463,  784,  786,  786, 1463,
-     1463,  786,  787,  787, 1463,  787,  788,  788,  790,  790,
-     1463, 1463,  790,  877,  877,  877,  881,  881,  881,  796,
-      796, 1463,  796,  798, 1463, 1463,  798,  799,  799, 1463,
-      799,  801,  801, 1463, 1463,  801,  802,  802, 1463,  802,
-      803,  803,  805,  805, 1463, 1463,  805,  889,  889,  889,
-      893,  893,  893,  811,  811, 1463,  811,  895, 1463,  895,
+     1728, 1728,  840,  841,  841, 1728,  841,  843,  843, 1728,
+     1728,  843,  844,  844, 1728,  844,  845,  845,  847,  847,
+     1728, 1728,  847,  941,  941,  941,  945,  945,  945,  853,
+      853, 1728,  853,  947, 1728,  947,  950, 1728,  950,  953,
+     1728,  953,  954,  954,  954,  958,  958,  958,  962, 1728,
+      962,   53,   53,   53, 1728,   53,   53,  990,  990,  990,
+      822,  822,  822,  834,  834,  834,  849,  849,  849, 1004,
+     1004, 1004, 1005, 1005, 1005, 1013, 1013, 1013, 1017, 1728,
+     1017, 1020, 1728, 1020, 1021, 1021, 1021, 1025, 1025, 1025,
+     1029, 1728, 1029, 1032, 1728, 1032, 1035, 1728, 1035, 1036,
 
-      898, 1463,  898,  901, 1463,  901,  902,  902,  902,  906,
-      906,  906,  910, 1463,  910,   53,   53,   53, 1463,   53,
-       53,  928,  928,  928,  780,  780,  780,  792,  792,  792,
-      807,  807,  807,  942,  942,  942,  943,  943,  943,  951,
-      951,  951,  955, 1463,  955,  958, 1463,  958,  959,  959,
-      959,  963,  963,  963,  967, 1463,  967,  970, 1463,  970,
-      973, 1463,  973,  974,  974,  974,  978,  978,  978,  982,
-     1463,  982,  983, 1463,  983,  986, 1463,  986,  989, 1463,
-      989,  990,  990,  990,  994,  994,  994,  998, 1463,  998,
-      895, 1463,  895,  897, 1463, 1463,  897,  898,  898, 1463,
+     1036, 1036, 1040, 1040, 1040, 1044, 1728, 1044, 1045, 1728,
+     1045, 1048, 1728, 1048, 1051, 1728, 1051, 1052, 1052, 1052,
+     1056, 1056, 1056, 1060, 1728, 1060,  947, 1728,  947,  949,
+     1728, 1728,  949,  950,  950, 1728,  950,  952,  952, 1728,
+     1728,  952,  953,  953, 1728,  953,  954,  954,  956,  956,
+     1728, 1728,  956, 1067, 1067, 1067, 1071, 1071, 1071,  962,
+      962, 1728,  962,   53,   53,   53, 1728,   53,   53,  907,
+      907,  907, 1098, 1098, 1098, 1102, 1102, 1102, 1105, 1105,
+     1105, 1108, 1108, 1108, 1111, 1111, 1111, 1112, 1112, 1112,
+     1120, 1120, 1120, 1011, 1011, 1728, 1728, 1011, 1125, 1125,
 
-      898,  900,  900, 1463, 1463,  900,  901,  901, 1463,  901,
-      902,  902,  904,  904, 1463, 1463,  904, 1005, 1005, 1005,
-     1009, 1009, 1009,  910,  910, 1463,  910,   53,   53,   53,
-     1463,   53,   53,  855,  855,  855, 1026, 1026, 1026, 1030,
-     1030, 1030, 1033, 1033, 1033, 1036, 1036, 1036, 1039, 1039,
-     1039, 1040, 1040, 1040, 1048, 1048, 1048,  949,  949, 1463,
-     1463,  949, 1053, 1053, 1053, 1057, 1057, 1057,  955,  955,
-     1463,  955,  957,  957, 1463, 1463,  957,  958,  958, 1463,
-      958,  959,  959,  961,  961, 1463, 1463,  961, 1064, 1064,
-     1064, 1068, 1068, 1068,  967,  967, 1463,  967,  969, 1463,
+     1125, 1129, 1129, 1129, 1017, 1017, 1728, 1017, 1019, 1019,
+     1728, 1728, 1019, 1020, 1020, 1728, 1020, 1021, 1021, 1023,
+     1023, 1728, 1728, 1023, 1136, 1136, 1136, 1140, 1140, 1140,
+     1029, 1029, 1728, 1029, 1031, 1728, 1728, 1031, 1032, 1032,
+     1728, 1032, 1034, 1034, 1728, 1728, 1034, 1035, 1035, 1728,
+     1035, 1036, 1036, 1038, 1038, 1728, 1728, 1038, 1148, 1148,
+     1148, 1152, 1152, 1152, 1044, 1044, 1728, 1044, 1045, 1728,
+     1045, 1047, 1728, 1728, 1047, 1048, 1048, 1728, 1048, 1050,
+     1050, 1728, 1728, 1050, 1051, 1051, 1728, 1051, 1052, 1052,
+     1054, 1054, 1728, 1728, 1054, 1160, 1160, 1160, 1164, 1164,
 
-     1463,  969,  970,  970, 1463,  970,  972,  972, 1463, 1463,
-      972,  973,  973, 1463,  973,  974,  974,  976,  976, 1463,
-     1463,  976, 1076, 1076, 1076, 1080, 1080, 1080,  982,  982,
-     1463,  982,  983, 1463,  983,  985, 1463, 1463,  985,  986,
-      986, 1463,  986,  988,  988, 1463, 1463,  988,  989,  989,
-     1463,  989,  990,  990,  992,  992, 1463, 1463,  992, 1088,
-     1088, 1088, 1092, 1092, 1092,  998,  998, 1463,  998, 1094,
-     1463, 1094, 1097, 1463, 1097, 1100, 1463, 1100, 1101, 1101,
-     1101, 1105, 1105, 1105, 1109, 1463, 1109,   53,   53,   53,
-     1463,   53,   53, 1121, 1121, 1121,  951,  951,  951,  963,
+     1164, 1060, 1060, 1728, 1060, 1166, 1728, 1166, 1169, 1728,
+     1169, 1172, 1728, 1172, 1173, 1173, 1173, 1177, 1177, 1177,
+     1181, 1728, 1181,   53,   53,   53, 1728,   53,   53, 1205,
+     1205, 1205, 1013, 1013, 1013, 1025, 1025, 1025, 1040, 1040,
+     1040, 1056, 1056, 1056, 1222, 1222, 1222, 1228, 1228, 1228,
+     1226, 1226, 1226, 1233, 1233, 1233, 1232, 1232, 1232, 1234,
+     1728, 1234, 1237, 1728, 1237, 1238, 1238, 1238, 1243, 1243,
+     1243, 1242, 1242, 1242, 1244, 1728, 1244, 1247, 1728, 1247,
+     1250, 1728, 1250, 1251, 1251, 1251, 1256, 1256, 1256, 1255,
+     1255, 1255, 1257, 1728, 1257, 1258, 1728, 1258, 1261, 1728,
 
-      963,  963,  978,  978,  978,  994,  994,  994, 1138, 1138,
-     1138, 1144, 1144, 1144, 1142, 1142, 1142, 1149, 1149, 1149,
-     1148, 1148, 1148, 1150, 1463, 1150, 1153, 1463, 1153, 1154,
-     1154, 1154, 1159, 1159, 1159, 1158, 1158, 1158, 1160, 1463,
-     1160, 1163, 1463, 1163, 1166, 1463, 1166, 1167, 1167, 1167,
-     1172, 1172, 1172, 1171, 1171, 1171, 1173, 1463, 1173, 1174,
-     1463, 1174, 1177, 1463, 1177, 1180, 1463, 1180, 1181, 1181,
-     1181, 1186, 1186, 1186, 1185, 1185, 1185, 1187, 1463, 1187,
-     1188, 1463, 1188, 1191, 1463, 1191, 1194, 1463, 1194, 1195,
-     1195, 1195, 1200, 1200, 1200, 1199, 1199, 1199, 1201, 1463,
+     1261, 1264, 1728, 1264, 1265, 1265, 1265, 1270, 1270, 1270,
+     1269, 1269, 1269, 1271, 1728, 1271, 1272, 1728, 1272, 1275,
+     1728, 1275, 1278, 1728, 1278, 1279, 1279, 1279, 1284, 1284,
+     1284, 1283, 1283, 1283, 1285, 1728, 1285, 1166, 1728, 1166,
+     1168, 1728, 1728, 1168, 1169, 1169, 1728, 1169, 1171, 1171,
+     1728, 1728, 1171, 1172, 1172, 1728, 1172, 1173, 1173, 1175,
+     1175, 1728, 1728, 1175, 1292, 1292, 1292, 1296, 1296, 1296,
+     1181, 1181, 1728, 1181,   53,   53,   53, 1728,   53,   53,
+     1112, 1112, 1112, 1324, 1324, 1324, 1327, 1327, 1327, 1330,
+     1330, 1330, 1333, 1333, 1333, 1336, 1336, 1336, 1341, 1341,
 
-     1201, 1094, 1463, 1094, 1096, 1463, 1463, 1096, 1097, 1097,
-     1463, 1097, 1099, 1099, 1463, 1463, 1099, 1100, 1100, 1463,
-     1100, 1101, 1101, 1103, 1103, 1463, 1463, 1103, 1208, 1208,
-     1208, 1212, 1212, 1212, 1109, 1109, 1463, 1109,   53,   53,
-       53, 1463,   53,   53, 1040, 1040, 1040, 1228, 1228, 1228,
-     1231, 1231, 1231, 1234, 1234, 1234, 1237, 1237, 1237, 1240,
-     1240, 1240, 1245, 1245, 1245, 1244, 1244, 1244, 1247, 1463,
-     1247, 1248, 1248, 1248, 1146, 1146, 1463, 1463, 1146, 1252,
-     1252, 1252, 1253, 1253, 1253, 1150, 1150, 1463, 1150, 1152,
-     1152, 1463, 1463, 1152, 1153, 1153, 1463, 1153, 1154, 1154,
+     1341, 1340, 1340, 1340, 1343, 1728, 1343, 1344, 1344, 1344,
+     1230, 1230, 1728, 1728, 1230, 1348, 1348, 1348, 1349, 1349,
+     1349, 1234, 1234, 1728, 1234, 1236, 1236, 1728, 1728, 1236,
+     1237, 1237, 1728, 1237, 1238, 1238, 1240, 1240, 1728, 1728,
+     1240, 1355, 1355, 1355, 1356, 1356, 1356, 1244, 1244, 1728,
+     1244, 1246, 1728, 1728, 1246, 1247, 1247, 1728, 1247, 1249,
+     1249, 1728, 1728, 1249, 1250, 1250, 1728, 1250, 1251, 1251,
+     1253, 1253, 1728, 1728, 1253, 1363, 1363, 1363, 1364, 1364,
+     1364, 1257, 1257, 1728, 1257, 1258, 1728, 1258, 1260, 1728,
+     1728, 1260, 1261, 1261, 1728, 1261, 1263, 1263, 1728, 1728,
 
-     1156, 1156, 1463, 1463, 1156, 1259, 1259, 1259, 1260, 1260,
-     1260, 1160, 1160, 1463, 1160, 1162, 1463, 1463, 1162, 1163,
-     1163, 1463, 1163, 1165, 1165, 1463, 1463, 1165, 1166, 1166,
-     1463, 1166, 1167, 1167, 1169, 1169, 1463, 1463, 1169, 1267,
-     1267, 1267, 1268, 1268, 1268, 1173, 1173, 1463, 1173, 1174,
-     1463, 1174, 1176, 1463, 1463, 1176, 1177, 1177, 1463, 1177,
-     1179, 1179, 1463, 1463, 1179, 1180, 1180, 1463, 1180, 1181,
-     1181, 1183, 1183, 1463, 1463, 1183, 1275, 1275, 1275, 1276,
-     1276, 1276, 1187, 1187, 1463, 1187, 1188, 1463, 1188, 1190,
-     1463, 1463, 1190, 1191, 1191, 1463, 1191, 1193, 1193, 1463,
+     1263, 1264, 1264, 1728, 1264, 1265, 1265, 1267, 1267, 1728,
+     1728, 1267, 1371, 1371, 1371, 1372, 1372, 1372, 1271, 1271,
+     1728, 1271, 1272, 1728, 1272, 1274, 1728, 1728, 1274, 1275,
+     1275, 1728, 1275, 1277, 1277, 1728, 1728, 1277, 1278, 1278,
+     1728, 1278, 1279, 1279, 1281, 1281, 1728, 1728, 1281, 1379,
+     1379, 1379, 1380, 1380, 1380, 1285, 1285, 1728, 1285, 1381,
+     1728, 1381, 1384, 1728, 1384, 1387, 1728, 1387, 1388, 1388,
+     1388, 1393, 1728, 1393, 1392, 1392, 1392, 1394, 1728, 1394,
+       53,   53,   53, 1728,   53,   53, 1415, 1728, 1415, 1414,
+     1414, 1414, 1416, 1728, 1416, 1232, 1232, 1232, 1417, 1728,
 
-     1463, 1193, 1194, 1194, 1463, 1194, 1195, 1195, 1197, 1197,
-     1463, 1463, 1197, 1283, 1283, 1283, 1284, 1284, 1284, 1201,
-     1201, 1463, 1201, 1285, 1463, 1285, 1288, 1463, 1288, 1291,
-     1463, 1291, 1292, 1292, 1292, 1297, 1463, 1297, 1296, 1296,
-     1296, 1298, 1463, 1298,   53,   53,   53, 1463,   53,   53,
-     1306, 1463, 1306, 1305, 1305, 1305, 1307, 1463, 1307, 1148,
-     1148, 1148, 1308, 1463, 1308, 1158, 1158, 1158, 1309, 1463,
-     1309, 1171, 1171, 1171, 1310, 1463, 1310, 1185, 1185, 1185,
-     1311, 1463, 1311, 1199, 1199, 1199, 1242, 1242, 1463, 1463,
-     1242, 1315, 1315, 1315, 1316, 1316, 1316,  370,  370,  370,
+     1417, 1242, 1242, 1242, 1418, 1728, 1418, 1255, 1255, 1255,
+     1419, 1728, 1419, 1269, 1269, 1269, 1420, 1728, 1420, 1283,
+     1283, 1283, 1338, 1338, 1728, 1728, 1338, 1424, 1424, 1424,
+     1425, 1425, 1425,  370,  370,  370, 1343, 1343, 1728, 1343,
+     1426, 1426, 1426, 1429, 1728, 1429, 1430, 1430, 1430, 1431,
+     1431, 1431, 1434, 1728, 1434, 1437, 1728, 1437, 1438, 1438,
+     1438, 1439, 1439, 1439, 1440, 1728, 1440, 1443, 1728, 1443,
+     1446, 1728, 1446, 1447, 1447, 1447, 1448, 1448, 1448, 1449,
+     1728, 1449, 1452, 1728, 1452, 1455, 1728, 1455, 1456, 1456,
+     1456, 1457, 1457, 1457, 1458, 1728, 1458, 1461, 1728, 1461,
 
-     1247, 1247, 1463, 1247, 1317, 1317, 1317, 1320, 1463, 1320,
-     1321, 1321, 1321, 1322, 1322, 1322, 1325, 1463, 1325, 1328,
-     1463, 1328, 1329, 1329, 1329, 1330, 1330, 1330, 1331, 1463,
-     1331, 1334, 1463, 1334, 1337, 1463, 1337, 1338, 1338, 1338,
-     1339, 1339, 1339, 1340, 1463, 1340, 1343, 1463, 1343, 1346,
-     1463, 1346, 1347, 1347, 1347, 1348, 1348, 1348, 1349, 1463,
-     1349, 1352, 1463, 1352, 1355, 1463, 1355, 1356, 1356, 1356,
-     1357, 1357, 1357, 1285, 1463, 1285, 1287, 1463, 1463, 1287,
-     1288, 1288, 1463, 1288, 1290, 1290, 1463, 1463, 1290, 1291,
-     1291, 1463, 1291, 1292, 1292, 1294, 1294, 1463, 1463, 1294,
+     1464, 1728, 1464, 1465, 1465, 1465, 1466, 1466, 1466, 1381,
+     1728, 1381, 1383, 1728, 1728, 1383, 1384, 1384, 1728, 1384,
+     1386, 1386, 1728, 1728, 1386, 1387, 1387, 1728, 1387, 1388,
+     1388, 1390, 1390, 1728, 1728, 1390, 1473, 1473, 1473, 1474,
+     1728, 1474, 1394, 1394, 1728, 1394,   53,   53,   53, 1728,
+       53,   53, 1492, 1492, 1492, 1340, 1340, 1340, 1494, 1728,
+     1494, 1495, 1728, 1495, 1496, 1728, 1496, 1497, 1728, 1497,
+     1498, 1728, 1498, 1499, 1728, 1499, 1502, 1728, 1502, 1503,
+     1503, 1503, 1504, 1504, 1504, 1505, 1728, 1505, 1428, 1428,
+     1728, 1728, 1428, 1429, 1429, 1728, 1429, 1430, 1430, 1508,
 
-     1364, 1364, 1364, 1365, 1463, 1365, 1298, 1298, 1463, 1298,
-       53,   53,   53, 1463,   53,   53, 1370, 1370, 1370, 1244,
-     1244, 1244, 1372, 1463, 1372, 1373, 1463, 1373, 1374, 1463,
-     1374, 1375, 1463, 1375, 1376, 1463, 1376, 1377, 1463, 1377,
-     1380, 1463, 1380, 1381, 1381, 1381, 1382, 1382, 1382, 1383,
-     1463, 1383, 1319, 1319, 1463, 1463, 1319, 1320, 1320, 1463,
-     1320, 1321, 1321, 1386, 1463, 1386, 1324, 1463, 1463, 1324,
-     1325, 1325, 1463, 1325, 1327, 1327, 1463, 1463, 1327, 1328,
-     1328, 1463, 1328, 1329, 1329, 1390, 1463, 1390, 1331, 1463,
-     1331, 1333, 1463, 1463, 1333, 1334, 1334, 1463, 1334, 1336,
+     1728, 1508, 1433, 1728, 1728, 1433, 1434, 1434, 1728, 1434,
+     1436, 1436, 1728, 1728, 1436, 1437, 1437, 1728, 1437, 1438,
+     1438, 1512, 1728, 1512, 1440, 1728, 1440, 1442, 1728, 1728,
+     1442, 1443, 1443, 1728, 1443, 1445, 1445, 1728, 1728, 1445,
+     1446, 1446, 1728, 1446, 1447, 1447, 1516, 1728, 1516, 1449,
+     1728, 1449, 1451, 1728, 1728, 1451, 1452, 1452, 1728, 1452,
+     1454, 1454, 1728, 1728, 1454, 1455, 1455, 1728, 1455, 1456,
+     1456, 1520, 1728, 1520, 1458, 1728, 1458, 1460, 1728, 1728,
+     1460, 1461, 1461, 1728, 1461, 1463, 1463, 1728, 1728, 1463,
+     1464, 1464, 1728, 1464, 1465, 1465, 1524, 1728, 1524, 1525,
 
-     1336, 1463, 1463, 1336, 1337, 1337, 1463, 1337, 1338, 1338,
-     1394, 1463, 1394, 1340, 1463, 1340, 1342, 1463, 1463, 1342,
-     1343, 1343, 1463, 1343, 1345, 1345, 1463, 1463, 1345, 1346,
-     1346, 1463, 1346, 1347, 1347, 1398, 1463, 1398, 1349, 1463,
-     1349, 1351, 1463, 1463, 1351, 1352, 1352, 1463, 1352, 1354,
-     1354, 1463, 1463, 1354, 1355, 1355, 1463, 1355, 1356, 1356,
-     1402, 1463, 1402, 1403, 1463, 1403, 1406, 1463, 1406, 1409,
-     1463, 1409, 1410, 1410, 1410, 1411, 1463, 1411,   53,   53,
-       53, 1463,   53,   53, 1415, 1463, 1415, 1317, 1463, 1317,
-     1322, 1463, 1322, 1330, 1463, 1330, 1339, 1463, 1339, 1348,
+     1728, 1525, 1528, 1728, 1528, 1531, 1728, 1531, 1532, 1532,
+     1532, 1533, 1728, 1533,   53,   53,   53, 1728,   53,   53,
+     1550, 1728, 1550, 1426, 1728, 1426, 1431, 1728, 1431, 1439,
+     1728, 1439, 1448, 1728, 1448, 1457, 1728, 1457, 1466, 1728,
+     1466, 1501, 1501, 1728, 1728, 1501, 1502, 1502, 1728, 1502,
+     1503, 1503, 1493, 1728, 1493, 1555, 1728, 1555, 1556, 1728,
+     1556, 1559, 1728, 1559, 1560, 1728, 1560, 1563, 1728, 1563,
+     1564, 1728, 1564, 1567, 1728, 1567, 1568, 1728, 1568, 1571,
+     1728, 1571, 1527, 1728, 1728, 1527, 1530, 1530, 1728, 1728,
+     1530, 1575, 1728, 1575, 1504, 1728, 1504, 1591, 1728, 1591,
 
-     1463, 1348, 1357, 1463, 1357, 1379, 1379, 1463, 1463, 1379,
-     1380, 1380, 1463, 1380, 1381, 1381, 1371, 1463, 1371, 1420,
-     1463, 1420, 1421, 1463, 1421, 1424, 1463, 1424, 1425, 1463,
-     1425, 1428, 1463, 1428, 1429, 1463, 1429, 1432, 1463, 1432,
-     1433, 1463, 1433, 1436, 1463, 1436, 1405, 1463, 1463, 1405,
-     1408, 1408, 1463, 1463, 1408, 1440, 1463, 1440, 1382, 1463,
-     1382, 1444, 1463, 1444, 1419, 1463, 1463, 1419, 1423, 1463,
-     1463, 1423, 1427, 1463, 1463, 1427, 1431, 1463, 1463, 1431,
-     1435, 1463, 1463, 1435, 1450, 1463, 1450, 1453, 1463, 1453,
-     1443, 1463, 1463, 1443, 1455, 1463, 1455, 1456, 1463, 1456,
+     1554, 1728, 1728, 1554, 1558, 1728, 1728, 1558, 1562, 1728,
+     1728, 1562, 1566, 1728, 1728, 1566, 1570, 1728, 1728, 1570,
+     1597, 1728, 1597, 1600, 1728, 1600, 1590, 1728, 1728, 1590,
+     1614, 1728, 1614, 1615, 1728, 1615, 1616, 1728, 1616, 1617,
+     1728, 1617, 1618, 1728, 1618, 1599, 1728, 1728, 1599, 1631,
+     1728, 1631, 1632, 1728, 1632,    3, 1728, 1728, 1728, 1728,
+     1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728,
+     1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728,
+     1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728,
+     1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728,
 
-     1457, 1463, 1457, 1458, 1463, 1458, 1459, 1463, 1459, 1452,
-     1463, 1463, 1452, 1461, 1463, 1461, 1462, 1463, 1462,    3,
-     1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463,
-     1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463,
-     1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463,
-     1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463,
-     1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463,
-     1463, 1463, 1463
+     1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728
     } ;
 
-static yyconst flex_int16_t yy_chk[7474] =
+static yyconst flex_int16_t yy_chk[7910] =
     {   0,
         1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
         1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
@@ -1851,819 +1991,867 @@
         7,  106,    7,    7,    9,   17,   17,    9,  138,    9,
         9,    4,   19,   19,   24,    7,   27,   27,  138,    4,
        15,   10,    9,    7,   10,  102,   10,   10,   24,   28,
-        9,   34,   26, 1240,   28,   24,   26,  653,   94,   10,
+        9,   34,   26, 1278,   28,   24,   26,  586,   94,   10,
 
-       34,   94,   26,  653,   95,   26,   95,   10,   14,   14,
+       34,   94,   26,  586,   95,   26,   95,   10,   14,   14,
        14,   14,   14,   14,   14,   14,   14,   14,  102,   98,
-     1244,   14,   14,   14,   98,   83,   14,   14,   14,   14,
+     1279,   14,   14,   14,   98,   83,   14,   14,   14,   14,
        14,   14,   14,   14,   14,   14,   14,   14,   14,   14,
        14,   14,   14,   14,   14,   14,   14,   14,   14,   14,
-       14,   16,   83,   25,   16, 1245,   16,   16,   83,  129,
-       29, 1246,  107,   25,   29,  252,   25,  107,   22,   16,
+       14,   16,   83,   25,   16,  671,   16,   16,   83,  129,
+       29,  671,  107,   25,   29,  252,   25,  107,   22,   16,
        25,   22,  129,   22,   22,  103,   29,   16,   20,   20,
        20,   20,   20,   20,   20,   20,   22,  134,   23,  252,
-       23,   23,   20,  655,   22,   23,  655,  251,   35,  251,
+       23,   23,   20,  673,   22,   23,  673,  251,   35,  251,
 
        23,   30,  103,   30,   23,  134,   23,  103,   30,   30,
-       35,   30,   35, 1247,   35,   30, 1248,   35,   20,   21,
+       35,   30,   35, 1283,   35,   30, 1284,   35,   20,   21,
        21,   21,   21,   21,   21,   21,   21,   21,   21,   32,
-       32,  110,   21,  657,  110, 1252,  110,  136,   21,   21,
+       32,  110,   21,  675,  110, 1285,  110,  136,   21,   21,
        21,   21,   21,   21,   31,   32,  136,   31,   31,   32,
-       31,  657,   31,   32,   31,   32,   31,   33,   36,   31,
-      155,   33,   32,   36,   36,   37,   36,   36, 1253,   37,
+       31,  675,   31,   32,   31,   32,   31,   33,   36,   31,
+      155,   33,   32,   36,   36,   37,   36,   36,  710,   37,
        33,   33,  163,   38,   33,  222,   33,   37,   39,   38,
        39,   38,   37,   38,   37,   41,  155,   38,  222,   38,
-       38,  267,  267,   41,   39,  435,  435,   41,  163,   41,
+       38,  267,  267,   41,   39,  437,  437,   41,  163,   41,
 
-       44,   39,  660,   44,  660,   44,   44,   62,   62,   62,
+       44,   39,  397,   44,  710,   44,   44,   62,   62,   62,
        62,   62,   62,   62,  274,  339,   63,  351,   44,   63,
-      339,   63,   63,  410, 1259,  413,   44,   48,   48,   48,
-       48,   48,   48,   48,   63, 1260,  410,  661,   48,  413,
-      274,  661,   63,  351,   48,   48,   48,   48,   48,   48,
-       49,   49,   49,   49,   49,   49,   49,  376,  437, 1267,
-      444,   49,  284,  284,  284,  284, 1268,   49,   49,   49,
+      339,   63,   63,  397,  410, 1292,   44,   48,   48,   48,
+       48,   48,   48,   48,   63,  619,  619,  410,   48,  397,
+      274,  680,   63,  351,   48,   48,   48,   48,   48,   48,
+       49,   49,   49,   49,   49,   49,   49,  376,  439,  680,
+      446,   49,  284,  284,  284,  284, 1296,   49,   49,   49,
        49,   49,   49,   50,   50,   50,   50,   50,   50,   50,
-       50,  464,  284,  376,  437,   50,  444,  450,  458,  464,
-     1275,   50,   50,   50,   50,   50,   50,   52,   52,   52,
+       50,  466,  284,  376,  439,   50,  446,  452,  460,  466,
+     1321,   50,   50,   50,   50,   50,   50,   52,   52,   52,
 
        52,   52,   52,   52,   52,   54,   54,   54,   54,   54,
-       54,   54,  484,  450,  458,  355,   54,  559,  559,  559,
-      559,  484,   54,   54,   54,   54,   54,   54,   56,  355,
-     1276,   56, 1283,   56,   56,  601,  601,  371,  372,   56,
-       56,   56,   56,   56,   56,   56,   56,  516,  556, 1284,
-       56,  371,  372, 1288,   56,  355,   56,   56,   56,   56,
-       56,   56,  153,  486,  153,  153,  153,  153,  153,  153,
-      153,  540,  486,  516,  556,  153,  609,  371,  372,  540,
-     1291,  153,  153,  153,  153,  153,  153,  154,  154,  154,
-      154,  154,  154,  154,  154,  550,  644,  652,  652,  154,
+       54,   54,  486,  452,  460,  355,   54, 1324,  413,  670,
+      670,  486,   54,   54,   54,   54,   54,   54,   56,  355,
+      672,   56,  413,   56,   56,  672, 1327,  371,  372,   56,
+       56,   56,   56,   56,   56,   56,   56,  523,  563,  679,
+       56,  371,  372,  679,   56,  355,   56,   56,   56,   56,
+       56,   56,  153,  488,  153,  153,  153,  153,  153,  153,
+      153,  547,  488,  523,  563,  153,  627,  371,  372,  547,
+      686,  153,  153,  153,  153,  153,  153,  154,  154,  154,
+      154,  154,  154,  154,  154,  557,  662,  686, 1330,  154,
 
-      612,  154,  609,  550,  644,  154,  154,  154,  154,  154,
+      630,  154,  627,  557,  662,  154,  154,  154,  154,  154,
       154,  266,  266,  266,  266,  266,  266,  266,  277,  277,
-      277,  277,  277,  277,  277,  453,  612,  154,  156,  156,
-      156,  156,  156,  156,  156,  156,  618,  625,  654,  453,
-      156,  637,  678,  654,  671,  671,  156,  156,  156,  156,
+      277,  277,  277,  277,  277,  455,  630,  154,  156,  156,
+      156,  156,  156,  156,  156,  156,  587,  636, 1333,  455,
+      156,  566,  566,  566,  566,  587,  156,  156,  156,  156,
       156,  156,  157,  157,  157,  157,  157,  157,  157,  157,
-      157,  680,  618,  625,  157,  453, 1292,  637,  678, 1296,
+      157,  684, 1336,  636,  157,  455,  643,  655,  684, 1340,
       157,  157,  157,  157,  157,  157,  158,  158,  158,  158,
       158,  158,  158,  158,  160,  160,  160,  160,  160,  160,
-      160,  160,  701, 1298,  719,  160,  731,  680,  662,  734,
+      160,  160,  643,  655,  678,  160,  678,  682, 1341,  682,
 
-      701,  160,  160,  160,  160,  160,  160,  162,  162,  162,
-      162,  162,  162,  162,  162,  162,  662,  734, 1304,  162,
-      719,  162,  731,  309,  736,  162,  162,  162,  162,  162,
-      162,  309,  361,  361,  361,  361,  361,  361,  361, 1305,
-      748,  454,  736,  520,  309,  737,  658,  162,  260,  260,
-      260,  260,  260,  260,  260,  454,  658,  520,  748,  260,
-      309,  735, 1315,  737, 1316,  260,  260,  260,  260,  260,
-      260,  262,  262,  262,  262,  262,  262,  262,  656,  735,
-      737,  454,  262,  520,  763,  766,  735,  656,  262,  262,
+     1342,  160,  160,  160,  160,  160,  160,  162,  162,  162,
+      162,  162,  162,  162,  162,  162,  687,  691,  691,  162,
+     1343,  162, 1344,  309,  687,  162,  162,  162,  162,  162,
+      162,  309,  361,  361,  361,  361,  361,  361,  361,  701,
+      701,  456, 1348,  527,  309,  764,  676,  162,  260,  260,
+      260,  260,  260,  260,  260,  456,  676,  527,  708,  260,
+      309, 1349,  766,  764,  689,  260,  260,  260,  260,  260,
+      260,  262,  262,  262,  262,  262,  262,  262,  588,  689,
+      766,  456,  262,  527,  708,  749,  761,  588,  262,  262,
       262,  262,  262,  262,  263,  263,  263,  263,  263,  263,
 
-      263,  263,  265,  265,  265,  265,  265,  265,  265,  712,
-      763,  766, 1320,  265,  769,  742,  746,  712,  743,  265,
+      263,  263,  265,  265,  265,  265,  265,  265,  265,  674,
+      805,  749,  761,  265, 1355, 1356, 1363,  772,  674,  265,
       265,  265,  265,  265,  265,  268,  268,  268,  268,  268,
-      268,  268,  268,  742,  746,  746,  743,  268,  742,  743,
-      769, 1321, 1325,  268,  268,  268,  268,  268,  268,  270,
+      268,  268,  268,  731,  742,  772,  805,  268, 1364, 1371,
+      772,  731,  742,  268,  268,  268,  268,  268,  268,  270,
       270,  270,  270,  270,  270,  270,  270,  273,  273,  273,
-      273,  273,  273,  273,  273,  273,  817,  344,  547,  273,
-     1328,  273,  344, 1329,  817,  273,  273,  273,  273,  273,
-      273,  344,  547,  344,  344,  775,  344,  365,  365,  365,
-      365,  365,  365,  365,  749,  548,  738,  273,  278,  278,
+      273,  273,  273,  273,  273,  273,  859, 1372, 1379,  273,
+     1380,  273, 1384, 1387,  859,  273,  273,  273,  273,  273,
+      273,  365,  365,  365,  365,  365,  365,  365,  436,  436,
+      436,  436,  436,  436,  436,  554,  683,  273,  278,  278,
 
-      278,  278,  278,  278,  278,  278,  278, 1334,  547,  548,
-      278,  775,  749, 1337,  738,  551,  278,  278,  278,  278,
-      278,  278,  279,  279,  279,  279,  279,  279,  279,  551,
-     1338,  738, 1343,  279, 1346,  548,  744, 1347,  747,  279,
-      279,  279,  279,  279,  279,  349,  552,  349,  349,  349,
-      349,  349,  349,  349,  744,  551,  747,  744,  349,  747,
-      552,  753,  755,  755,  349,  349,  349,  349,  349,  349,
-      350,  350,  350,  350,  350,  350,  350,  350, 1352,  753,
-      755, 1355,  350, 1356,  350, 1364,  552, 1380,  350,  350,
-      350,  350,  350,  350,  434,  434,  434,  434,  434,  434,
+      278,  278,  278,  278,  278,  278,  278,  683, 1388,  554,
+      278, 1392,  765,  779, 1394,  681,  278,  278,  278,  278,
+      278,  278,  279,  279,  279,  279,  279,  279,  279,  681,
+      765,  779,  685,  279,  555,  554,  779,  765, 1413,  279,
+      279,  279,  279,  279,  279,  344,  685,  344,  555,  344,
+      344,  464,  464,  464,  464,  464,  464,  464,  773,  344,
+      690,  344,  344,  558,  344,  349,  559,  349,  349,  349,
+      349,  349,  349,  349,  555,  690,  773,  558,  349,  773,
+      559,  776, 1414,  787,  349,  349,  349,  349,  349,  349,
+      350,  350,  350,  350,  350,  350,  350,  350, 1424,  776,
 
-      434,  462,  462,  462,  462,  462,  462,  462,  620,  670,
-      350,  352,  352,  352,  352,  352,  352,  352,  352,  670,
-     1381,  782,  620,  352,  794,  797,  824,  836,  621,  352,
+      776,  787,  350,  558,  350, 1425,  559, 1429,  350,  350,
+      350,  350,  350,  350,  468,  468,  468,  468,  468,  468,
+      468,  540,  540,  540,  540,  540,  540,  540,  638,  688,
+      350,  352,  352,  352,  352,  352,  352,  352,  352,  688,
+     1430, 1434,  638,  352, 1437,  783,  774,  788,  639,  352,
       352,  352,  352,  352,  352,  356,  356,  356,  356,  356,
-      356,  356,  621,  809,  824,  836,  356,  782,  620,  825,
-      794,  797,  356,  356,  356,  356,  356,  356,  357,  357,
-      357,  357,  357,  357,  357,  357,  865,  825,  621,  809,
-      357,  840,  825,  896,  865, 1406,  357,  357,  357,  357,
+      356,  356,  639,  783,  774,  788,  356,  774,  638,  784,
+      783,  790,  356,  356,  356,  356,  356,  356,  357,  357,
+      357,  357,  357,  357,  357,  357, 1438,  784,  639,  790,
+      357,  808,  784,  811,  817, 1443,  357,  357,  357,  357,
+
       357,  357,  358,  358,  358,  358,  358,  358,  358,  358,
-      360,  360,  360,  360,  360,  360,  360,  840,  876,  896,
-
-     1409,  360, 1420,  826,  827,  829,  876,  360,  360,  360,
+      360,  360,  360,  360,  360,  360,  360,  808,  917,  811,
+      817,  360, 1446,  791,  789,  795,  917,  360,  360,  360,
       360,  360,  360,  364,  364,  364,  364,  364,  364,  364,
-      364,  826,  827,  829,  364, 1424,  826,  827,  829,  831,
+      364,  791,  789,  795,  364,  789,  824,  797,  797, 1447,
       364,  364,  364,  364,  364,  364,  366,  366,  366,  366,
-      366,  366,  366,  366,  366,  888, 1428,  831,  366,  908,
-      832,  834,  831,  888,  366,  366,  366,  366,  366,  366,
-      367,  367,  367,  367,  367,  367,  367,  367,  832,  834,
-      931,  367,  834,  832,  920,  908,  915,  367,  367,  367,
+      366,  366,  366,  366,  366,  797,  836,  839,  366,  851,
+      866,  867,  824, 1452,  366,  366,  366,  366,  366,  366,
+      367,  367,  367,  367,  367,  367,  367,  367,  866,  867,
+      892,  367,  836,  839,  867,  851,  868,  367,  367,  367,
+
       367,  367,  367,  373,  373,  373,  373,  373,  373,  373,
-      373,  373,  920, 1432,  915,  373,  931,  915,  921,  918,
+      373,  373, 1455, 1456,  868,  373,  892, 1461,  879,  868,
+      869,  373,  373,  373,  373,  373,  373,  375,  375,  375,
+      375,  375,  375,  375,  375,  375,  879,  879,  869,  375,
+      692,  375, 1464,  869,  693,  375,  375,  375,  375,  375,
+      375,  490,  646,  490,  692,  696,  490,  490,  693,  647,
+      490,  490,  699,  928,  700,  490,  646,  375,  396,  696,
+     1465,  928,  396,  647,  700,  396,  699,  650,  396,  651,
+      396,  396,  396,  396,  430,  430,  430,  430,  430,  430,
+      430,  650,  646,  651, 1473,  430,  780,  871,  873,  647,
 
-      920,  373,  373,  373,  373,  373,  373,  375,  375,  375,
-      375,  375,  375,  375,  375,  375,  921,  918, 1436,  375,
-      934,  375,  918,  937,  940,  375,  375,  375,  375,  375,
-      375,  466,  466,  466,  466,  466,  466,  466,  533,  533,
-      533,  533,  533,  533,  533, 1444,  934,  375,  396,  937,
-      940, 1453,  396,  946,  922,  396,  923,  628,  396,  629,
-      396,  396,  396,  396,  428,  428,  428,  428,  428,  428,
-      428,  628,  922,  629,  923,  428,  953,  927, 1014,  946,
-      663,  428,  428,  428,  428,  428,  428,  430,  430,  430,
-      430,  430,  430,  430,  663,  927, 1014,  628,  430,  629,
+     1502,  430,  430,  430,  430,  430,  430,  432,  432,  432,
+      432,  432,  432,  432,  780,  871,  873,  650,  432,  651,
+      871,  873,  948,  780,  432,  432,  432,  432,  432,  432,
+      433,  433,  433,  433,  433,  433,  433,  433,  435,  435,
+      435,  435,  435,  435,  435, 1503, 1528, 1531,  948,  435,
+     1555,  781,  880,  874,  888,  435,  435,  435,  435,  435,
+      435,  438,  438,  438,  438,  438,  438,  438,  438,  781,
+      880,  874,  888,  438, 1559,  438,  874,  880,  781,  438,
+      438,  438,  438,  438,  438,  545,  545,  545,  545,  545,
+      545,  545,  549,  549,  549,  549,  549,  549,  549,  767,
 
-      965,  968,  953, 1237,  430,  430,  430,  430,  430,  430,
-      431,  431,  431,  431,  431,  431,  431,  431,  433,  433,
-      433,  433,  433,  433,  433,  980,  965,  968,  984,  433,
-      996, 1234, 1022, 1231, 1114,  433,  433,  433,  433,  433,
-      433,  436,  436,  436,  436,  436,  436,  436,  436, 1004,
-     1022,  980, 1114,  436,  984,  436,  996, 1004, 1228,  436,
-      436,  436,  436,  436,  436,  538,  538,  538,  538,  538,
-      538,  538,  542,  542,  542,  542,  542,  542,  542,  739,
-      632,  436,  438,  438,  438,  438,  438,  438,  438, 1042,
-     1225, 1212, 1095,  438,  632, 1017, 1208,  739,  666,  438,
+      752,  438,  440,  440,  440,  440,  440,  440,  440,  960,
+      940,  993,  996,  440,  752,  883, 1563,  767,  940,  440,
+      440,  440,  440,  440,  440,  441,  441,  441,  441,  441,
+      441,  441, 1567,  883,  767,  960,  441,  993,  996,  999,
+      752,  883,  441,  441,  441,  441,  441,  441,  442,  442,
+      442,  442,  442,  442,  442,  442,  445,  445,  445,  445,
+      445,  445,  445,  445,  445,  999, 1571, 1591,  445, 1002,
+      445, 1600, 1275, 1271,  445,  445,  445,  445,  445,  445,
+      658,  658,  658,  658,  658,  658,  658,  660,  660,  660,
+      660,  660,  660,  660,  973, 1002,  445,  451,  451,  451,
 
-      438,  438,  438,  438,  438,  439,  439,  439,  439,  439,
-      439,  439,  666, 1017,  739, 1042,  439, 1017, 1095, 1201,
-      632, 1107,  439,  439,  439,  439,  439,  439,  440,  440,
-      440,  440,  440,  440,  440,  440,  443,  443,  443,  443,
-      443,  443,  443,  443,  443, 1052,  633, 1107,  443, 1200,
-      443, 1199, 1195, 1052,  443,  443,  443,  443,  443,  443,
-      633,  640,  640,  640,  640,  640,  640,  640,  642,  642,
-      642,  642,  642,  642,  642, 1118,  443,  449,  449,  449,
-      449,  449,  449,  449,  449,  449,  633, 1194, 1191,  449,
-     1187,  449, 1186, 1118,  669,  449,  449,  449,  449,  449,
+      451,  451,  451,  451,  451,  451, 1066, 1270, 1269,  451,
+     1265,  451,  973,  973, 1066,  451,  451,  451,  451,  451,
+      451,  664,  664,  664,  664,  664,  664,  664,  724,  724,
+      724,  724,  724,  724,  724,  753,  768,  451,  457,  457,
+      457,  457,  457,  457,  457,  457,  457, 1264, 1261,  753,
+      457, 1008, 1257, 1015,  768,  886,  457,  457,  457,  457,
+      457,  457,  459,  459,  459,  459,  459,  459,  459,  459,
+      459,  768, 1256,  886,  459,  753,  459, 1008,  886, 1015,
+      459,  459,  459,  459,  459,  459,  729,  729,  729,  729,
+      729,  729,  729,  733,  733,  733,  733,  733,  733,  733,
 
-      449,  646,  646,  646,  646,  646,  646,  646,  669,  694,
-      694,  694,  694,  694,  694,  694,  741,  449,  455,  455,
-      455,  455,  455,  455,  455,  455,  455, 1185, 1181, 1124,
-      455, 1180, 1127, 1130,  741, 1020,  455,  455,  455,  455,
-      455,  455,  457,  457,  457,  457,  457,  457,  457,  457,
-      457,  741, 1177, 1020,  457, 1124,  457, 1020, 1127, 1130,
-      457,  457,  457,  457,  457,  457,  699,  699,  699,  699,
-      699,  699,  699,  703,  703,  703,  703,  703,  703,  703,
-      722,  830,  457,  467,  467,  467,  467,  467,  467,  467,
-      467,  467, 1173, 1133,  722,  467, 1136, 1172, 1171,  830,
+      756,  769,  459,  469,  469,  469,  469,  469,  469,  469,
+      469,  469, 1255, 1027,  756,  469, 1251,  975, 1250,  769,
+      757,  469,  469,  469,  469,  469,  469,  470,  470,  470,
+      470,  470,  470,  470,  757,  975,  769, 1247,  470, 1027,
+      756,  785,  975,  876,  470,  470,  470,  470,  470,  470,
+      521,  819,  521,  521,  521,  521,  521,  521,  521,  785,
+      757,  876, 1244,  521,  876,  819,  972,  967,  785,  521,
+      521,  521,  521,  521,  521,  522,  522,  522,  522,  522,
+      522,  522,  522, 1243,  972,  967, 1242,  522,  967,  522,
+     1238,  819,  972,  522,  522,  522,  522,  522,  522,  738,
 
-      723,  467,  467,  467,  467,  467,  467,  468,  468,  468,
-      468,  468,  468,  468,  723, 1063,  830, 1167,  468, 1133,
-      722, 1021, 1136, 1063,  468,  468,  468,  468,  468,  468,
-      514,  726,  514,  514,  514,  514,  514,  514,  514, 1021,
-      723, 1166, 1163,  514, 1021,  726, 1160, 1117, 1113,  514,
-      514,  514,  514,  514,  514,  515,  515,  515,  515,  515,
-      515,  515,  515, 1159, 1075, 1117, 1113,  515, 1113,  515,
-     1117,  726, 1075,  515,  515,  515,  515,  515,  515,  708,
-      708,  708,  708,  708,  708,  708,  710,  710,  710,  710,
-      710,  710,  710,  727,  835,  515,  517,  517,  517,  517,
+      738,  738,  738,  738,  738,  738,  740,  740,  740,  740,
+      740,  740,  740,  771,  777,  522,  524,  524,  524,  524,
+      524,  524,  524,  524, 1030, 1124, 1237, 1042,  524, 1046,
+     1058,  771,  777, 1124,  524,  524,  524,  524,  524,  524,
+      528,  528,  528,  528,  528,  528,  528,  528,  771, 1135,
+     1030,  777,  528, 1042, 1114, 1046, 1058, 1135,  528,  528,
+      528,  528,  528,  528,  529,  529,  529,  529,  529,  529,
+      529,  529,  530,  530,  530,  530,  530,  530,  530, 1147,
+     1114, 1234, 1233,  530, 1167, 1179, 1208, 1147, 1232,  530,
+      530,  530,  530,  530,  530,  531,  531,  531,  531,  531,
 
-      517,  517,  517,  517, 1161, 1087, 1158,  727,  517, 1175,
-     1189, 1154,  835, 1087,  517,  517,  517,  517,  517,  517,
-      521,  521,  521,  521,  521,  521,  521,  521, 1153, 1207,
-     1161,  835,  521,  727, 1223, 1175, 1189, 1207,  521,  521,
-      521,  521,  521,  521,  522,  522,  522,  522,  522,  522,
-      522,  522,  523,  523,  523,  523,  523,  523,  523, 1251,
-     1223, 1150, 1149,  523, 1286, 1323, 1332, 1251, 1148,  523,
-      523,  523,  523,  523,  523,  524,  524,  524,  524,  524,
-      524,  524,  524,  526,  526,  526,  526,  526,  526,  526,
-     1286, 1323, 1332, 1341,  526, 1350, 1404, 1110, 1111, 1214,
+      531,  531,  531,  533,  533,  533,  533,  533,  533,  533,
+     1167, 1179, 1208, 1211,  533, 1228, 1226,  970,  974,  977,
+      533,  533,  533,  533,  533,  533,  534,  534,  534,  534,
+      534,  534,  534,  534,  534,  970,  974,  977,  534, 1211,
+      970,  974,  977,  820,  534,  534,  534,  534,  534,  534,
+      535,  535,  535,  535,  535,  535,  535,  820, 1159, 1225,
+     1214,  535, 1222,  976,  978, 1221, 1159,  535,  535,  535,
+      535,  535,  535,  539,  539,  539,  539,  539,  539,  539,
+      539,  976,  978,  820,  539,  978, 1214,  979,  981,  976,
+      539,  539,  539,  539,  539,  539,  541,  541,  541,  541,
 
-      526,  526,  526,  526,  526,  526,  527,  527,  527,  527,
-      527,  527,  527,  527,  527, 1110, 1111, 1214,  527, 1341,
-     1112, 1350, 1404,  777,  527,  527,  527,  527,  527,  527,
-      528,  528,  528,  528,  528,  528,  528,  777, 1112, 1110,
-     1111,  528, 1144, 1215, 1142, 1141, 1138,  528,  528,  528,
-      528,  528,  528,  532,  532,  532,  532,  532,  532,  532,
-      532, 1215, 1112,  777,  532, 1137, 1134, 1216, 1217, 1115,
-      532,  532,  532,  532,  532,  532,  534,  534,  534,  534,
-      534,  534,  534,  534,  534, 1216, 1217, 1115,  534, 1131,
-     1128, 1218, 1300, 1125,  534,  534,  534,  534,  534,  534,
+      541,  541,  541,  541,  541,  979,  981,  979,  541, 1218,
+      983,  981,  984, 1215,  541,  541,  541,  541,  541,  541,
+      542,  542,  542,  542,  542,  542,  542,  542,  983, 1212,
+      984,  542, 1209, 1205,  985,  989, 1076,  542,  542,  542,
+      542,  542,  542,  550,  550,  550,  550,  550,  550,  550,
+      550,  550,  985,  989, 1076,  550, 1181, 1079, 1082, 1083,
+     1180,  550,  550,  550,  550,  550,  550,  551,  551,  551,
+      551,  551,  551,  551,  551, 1079, 1082, 1083,  551, 1079,
+     1082, 1084, 1083, 1087,  551,  551,  551,  551,  551,  551,
+      560,  560,  560,  560,  560,  560,  560,  560,  560, 1084,
 
-      535,  535,  535,  535,  535,  535,  535,  535, 1115, 1218,
-     1300,  535, 1121, 1300, 1218, 1301, 1369,  535,  535,  535,
-      535,  535,  535,  543,  543,  543,  543,  543,  543,  543,
-      543,  543, 1258, 1301, 1369,  543, 1301, 1109, 1302, 1412,
-     1258,  543,  543,  543,  543,  543,  543,  544,  544,  544,
-      544,  544,  544,  544,  544, 1266, 1302, 1412,  544, 1418,
-     1108, 1105, 1101, 1266,  544,  544,  544,  544,  544,  544,
-      553,  553,  553,  553,  553,  553,  553,  553,  553, 1274,
-     1302, 1422,  553, 1426, 1430, 1418, 1414, 1274,  553,  553,
-      553,  553,  553,  553,  555,  555,  555,  555,  555,  555,
+     1177, 1087,  560, 1217, 1220, 1088, 1087, 1173,  560,  560,
+      560,  560,  560,  560,  562,  562,  562,  562,  562,  562,
+      562,  562,  562, 1088, 1172, 1088,  562, 1169,  562, 1217,
+     1220, 1164,  562,  562,  562,  562,  562,  562,  744,  744,
+      744,  744,  744,  744,  744,  750,  750,  750,  750,  750,
+      750,  750,  872,  778,  562,  613,  613,  613,  613,  613,
+      613,  613, 1245, 1163, 1259, 1273,  613, 1319, 1092, 1160,
+      872,  778,  613,  613,  613,  613,  613,  613,  615,  615,
+      615,  615,  615,  615,  615,  778, 1092,  872, 1245,  615,
+     1259, 1273, 1092, 1319, 1152,  615,  615,  615,  615,  615,
 
-      555,  555,  555, 1282, 1414, 1100,  555, 1422,  555, 1426,
-     1430, 1282,  555,  555,  555,  555,  555,  555,  714,  714,
-      714,  714,  714,  714,  714,  720,  720,  720,  720,  720,
-      720,  720,  828,  778,  555,  595,  595,  595,  595,  595,
-      595,  595, 1434, 1314, 1442, 1451,  595,  778, 1097, 1441,
-      828, 1314,  595,  595,  595,  595,  595,  595,  597,  597,
-      597,  597,  597,  597,  597,  828, 1363, 1441, 1434,  597,
-     1442, 1451, 1092,  778, 1363,  597,  597,  597,  597,  597,
-      597,  598,  598,  598,  598,  598,  598,  598,  598,  600,
-      600,  600,  600,  600,  600,  600, 1410, 1091, 1088, 1080,
+      615,  616,  616,  616,  616,  616,  616,  616,  616,  618,
+      618,  618,  618,  618,  618,  618, 1291, 1151, 1148, 1382,
+      618, 1432,  882, 1090, 1291, 1093,  618,  618,  618,  618,
+      618,  618,  620,  620,  620,  620,  620,  620,  620,  620,
+      882, 1090, 1090, 1093,  620, 1382, 1093, 1432, 1441,  882,
+      620,  620,  620,  620,  620,  620,  621,  621,  621,  621,
+      621,  621,  621,  621,  622,  622,  622,  622,  622,  622,
+      622, 1347, 1354, 1140, 1441,  622, 1139, 1136, 1129, 1347,
+     1354,  622,  622,  622,  622,  622,  622,  623,  623,  623,
+      623,  623,  623,  623,  623,  626,  626,  626,  626,  626,
 
-      600, 1079, 1219, 1076, 1410, 1068,  600,  600,  600,  600,
-      600,  600,  602,  602,  602,  602,  602,  602,  602,  602,
-     1219, 1067, 1064, 1057,  602, 1056, 1053, 1048, 1047, 1219,
-      602,  602,  602,  602,  602,  602,  603,  603,  603,  603,
-      603,  603,  603,  603,  604,  604,  604,  604,  604,  604,
-      604, 1044, 1043, 1040, 1039,  604, 1036, 1033, 1030, 1026,
-     1009,  604,  604,  604,  604,  604,  604,  605,  605,  605,
-      605,  605,  605,  605,  605,  608,  608,  608,  608,  608,
-      608,  608,  608,  608,  740,  785,  786,  608, 1005,  608,
-      998,  997,  789,  608,  608,  608,  608,  608,  608,  785,
+      626,  626,  626,  626,  770,  884,  827,  626,  782,  626,
+      786, 1182, 1186,  626,  626,  626,  626,  626,  626, 1362,
+      827, 1128,  770,  884, 1125, 1120,  782, 1362,  786, 1182,
+     1186,  775,  884,  792,  770,  626,  629,  629,  629,  629,
+      629,  629,  629,  629,  629,  782,  827,  786,  629,  775,
+      629,  792, 1370, 1182,  629,  629,  629,  629,  629,  629,
+     1370,  775, 1119, 1116,  792,  799,  799,  799,  799,  799,
+      799,  799,  793,  828,  831, 1450,  629,  635,  635,  635,
+      635,  635,  635,  635,  635,  635, 1183,  828,  831,  635,
+      793,  635,  832,  842,  843,  635,  635,  635,  635,  635,
 
-      786,  994,  740,  990,  989,  986,  789,  982,  981,  750,
-      978,  745,  974,  751,  740,  608,  611,  611,  611,  611,
-      611,  611,  611,  611,  611,  785,  786,  750,  611,  745,
-      611,  751,  789, 1016,  611,  611,  611,  611,  611,  611,
-      750,  745,  973,  751,  757,  757,  757,  757,  757,  757,
-      757, 1016,  790,  800,  801,  914,  611,  617,  617,  617,
-      617,  617,  617,  617,  617,  617,  790,  800,  801,  617,
-     1016,  617,  970,  914,  804,  617,  617,  617,  617,  617,
-      617,  798,  798,  798,  798,  798,  798,  798,  804, 1368,
-      914,  967,  790,  800,  801,  805,  966,  617,  622,  622,
+      635, 1450,  793, 1378, 1183, 1459,  832,  842,  843, 1184,
+     1115, 1378, 1112,  828,  831,  846, 1111,  635,  640,  640,
+      640,  640,  640,  640,  640,  640,  640, 1184, 1183,  846,
+      640, 1459,  832,  842,  843, 1189,  640,  640,  640,  640,
+      640,  640,  642,  642,  642,  642,  642,  642,  642,  642,
+      642, 1184, 1108, 1189,  642,  846,  642, 1105, 1189,  847,
+      642,  642,  642,  642,  642,  642,  840,  840,  840,  840,
+      840,  840,  840,  847,  855,  855,  855,  855,  855,  855,
+      855, 1102,  642,  652,  652,  652,  652,  652,  652,  652,
+      652,  652, 1423, 1098, 1526,  652, 1553, 1557, 1185,  847,
 
-      622,  622,  622,  622,  622,  622,  622, 1368,  963,  805,
-      622,  959,  958,  955,  804, 1368,  622,  622,  622,  622,
-      622,  622,  624,  624,  624,  624,  624,  624,  624,  624,
-      624,  954,  951,  947,  624,  805,  624,  943,  942,  941,
-      624,  624,  624,  624,  624,  624,  813,  813,  813,  813,
-      813,  813,  813,  815,  815,  815,  815,  815,  815,  815,
-      899,  916,  624,  634,  634,  634,  634,  634,  634,  634,
-      634,  634,  938,  935,  899,  634,  932,  929,  928,  916,
-      916,  634,  634,  634,  634,  634,  634,  636,  636,  636,
-      636,  636,  636,  636,  636,  636,  910,  916,  909,  636,
+     1423,  652,  652,  652,  652,  652,  652,  654,  654,  654,
+      654,  654,  654,  654,  654,  654, 1185, 1071, 1185,  654,
+     1526,  654, 1553, 1557, 1067,  654,  654,  654,  654,  654,
+      654,  857,  857,  857,  857,  857,  857,  857,  861,  861,
+      861,  861,  861,  861,  861,  878,  870,  654,  665,  665,
+      665,  665,  665,  665,  665,  665,  665, 1472, 1060, 1059,
+      665, 1056, 1561,  878,  870, 1472,  665,  665,  665,  665,
+      665,  665,  666,  666,  666,  666,  666,  666,  666,  870,
+      878, 1052, 1051,  666,  887,  875,  877,  885, 1561,  666,
+      666,  666,  666,  666,  666,  669,  669,  669,  669,  669,
 
-      899,  636,  906, 1019,  833,  636,  636,  636,  636,  636,
-      636,  819,  819,  819,  819,  819,  819,  819,  902,  901,
-      898, 1019,  833,  893,  900,  903,  917,  636,  647,  647,
-      647,  647,  647,  647,  647,  647,  647,  833,  900,  903,
-      647, 1019,  889,  881,  917,  904,  647,  647,  647,  647,
-      647,  647,  648,  648,  648,  648,  648,  648,  648,  904,
-      917,  877,  870,  648,  900,  903,  866,  861,  856,  648,
-      648,  648,  648,  648,  648,  651,  651,  651,  651,  651,
-      651,  651,  855,  854,  851,  904,  651,  911,  912,  913,
-      919, 1299,  651,  651,  651,  651,  651,  651,  858,  858,
+      669,  669,  887,  875,  877,  885,  669,  966, 1078,  951,
+      963,  881,  669,  669,  669,  669,  669,  669,  875,  877,
+     1565,  887,  885,  951, 1532,  966, 1078,  952,  963,  881,
+      669,  704, 1532,  704,  704,  704,  704,  704,  704,  704,
+      881,  952,  966,  963,  704, 1078, 1565,  964, 1048,  951,
+      704,  704,  704,  704,  704,  704,  910,  910,  910,  910,
+      910,  910,  910,  955,  956,  964,  968,  952,  704,  705,
+      705,  705,  705,  705,  705,  705,  705,  955,  956, 1044,
+      964,  705, 1190, 1298,  968,  968, 1043,  705,  705,  705,
+      705,  705,  705,  915,  915,  915,  915,  915,  915,  915,
 
-      858,  858,  858,  858,  858,  911,  912,  913,  919, 1299,
-      651,  674,  848,  674,  674,  674,  674,  674,  674,  674,
-      911,  912,  913,  913,  674,  919, 1299, 1015, 1018, 1119,
-      674,  674,  674,  674,  674,  674,  863,  863,  863,  863,
-      863,  863,  863,  948,  949, 1015, 1018, 1119,  674,  675,
-      675,  675,  675,  675,  675,  675,  675,  948,  949, 1015,
-     1018,  675, 1119,  844,  822,  818,  811,  675,  675,  675,
-      675,  675,  675,  867,  867,  867,  867,  867,  867,  867,
-      810,  807,  803,  948,  949,  675,  676,  676,  676,  676,
-      676,  676,  676,  872,  872,  872,  872,  872,  872,  872,
+     1190, 1298,  968,  955,  956,  705,  706,  706,  706,  706,
+      706,  706,  706,  919,  919,  919,  919,  919,  919,  919,
+      924,  924,  924,  924,  924,  924,  924,  926,  926,  926,
+      926,  926,  926,  926,  930,  930,  930,  930,  930,  930,
+      930,  706,  707,  707,  707,  707,  707,  707,  707, 1040,
+     1036, 1035, 1032,  707, 1029, 1569, 1589, 1598, 1028,  707,
+      707,  707,  707,  707,  707,  709,  709,  709,  709,  709,
+      709,  709,  709,  711,  711,  711,  711,  711,  711,  711,
+      711, 1569, 1589, 1598, 1025,  711, 1021, 1020, 1017, 1016,
+     1013,  711,  711,  711,  711,  711,  711,  712,  712,  712,
 
-      874,  874,  874,  874,  874,  874,  874,  878,  878,  878,
-      878,  878,  878,  878,  884,  884,  884,  884,  884,  884,
-      884,  676,  677,  677,  677,  677,  677,  677,  677,  802,
-      799,  796,  795,  677,  792,  788,  787,  784,  783,  677,
-      677,  677,  677,  677,  677,  679,  679,  679,  679,  679,
-      679,  679,  679,  681,  681,  681,  681,  681,  681,  681,
-      681,  780,  776,  773,  772,  681,  771,  770,  767,  764,
-      761,  681,  681,  681,  681,  681,  681,  682,  682,  682,
-      682,  682,  682,  682,  682,  684,  684,  684,  684,  684,
-      684,  684,  760,  733,  732,  729,  684,  725,  724,  721,
+      712,  712,  712,  712,  712,  714,  714,  714,  714,  714,
+      714,  714, 1009, 1005, 1004, 1003,  714, 1000,  997, 1201,
+     1202, 1187,  714,  714,  714,  714,  714,  714,  715,  715,
+      715,  715,  715,  715,  715,  715,  715, 1201, 1202, 1187,
+      715, 1201,  994, 1202, 1299, 1010,  715,  715,  715,  715,
+      715,  715,  716,  716,  716,  716,  716,  716,  716, 1010,
+     1187,  991, 1299,  716,  990,  962, 1300,  961, 1301,  716,
+      716,  716,  716,  716,  716,  718,  718,  718,  718,  718,
+      718,  718,  718,  718, 1300, 1010, 1301,  718,  958, 1192,
+     1302, 1310, 1011,  718,  718,  718,  718,  718,  718,  719,
 
-      717,  713,  684,  684,  684,  684,  684,  684,  685,  685,
-      685,  685,  685,  685,  685,  685,  685,  706,  702,  697,
-      685,  692,  691,  690,  687,  956,  685,  685,  685,  685,
-      685,  685,  686,  686,  686,  686,  686,  686,  686,  956,
-      683,  673,  672,  686,  668,  667,  665,  664,  659,  686,
-      686,  686,  686,  686,  686,  688,  688,  688,  688,  688,
-      688,  688,  688,  688,  649,  956,  645,  688,  639,  638,
-      635,  631,  957,  688,  688,  688,  688,  688,  688,  689,
-      689,  689,  689,  689,  689,  689,  957,  630,  627,  626,
-      689,  623,  619,  616,  615,  614,  689,  689,  689,  689,
+      719,  719,  719,  719,  719,  719, 1011, 1192, 1302, 1310,
+      719,  954, 1307, 1302, 1310, 1192,  719,  719,  719,  719,
+      719,  719,  723,  723,  723,  723,  723,  723,  723,  723,
+     1307,  953, 1011,  723,  950,  945,  941, 1314, 1315,  723,
+      723,  723,  723,  723,  723,  725,  725,  725,  725,  725,
+      725,  725,  725,  725, 1307, 1314, 1315,  725,  933,  929,
+     1396, 1397,  922,  725,  725,  725,  725,  725,  725,  726,
+      726,  726,  726,  726,  726,  726,  726, 1315, 1396, 1397,
+      726, 1396, 1397, 1398, 1399, 1401,  726,  726,  726,  726,
+      726,  726,  734,  734,  734,  734,  734,  734,  734,  734,
 
-      689,  689,  693,  693,  693,  693,  693,  693,  693,  693,
-      613,  610,  957,  693,  607,  606,  599,  596,  594,  693,
-      693,  693,  693,  693,  693,  695,  695,  695,  695,  695,
-      695,  695,  695,  695,  590,  586,  585,  695,  584,  583,
-      579,  578,  576,  695,  695,  695,  695,  695,  695,  696,
-      696,  696,  696,  696,  696,  696,  696,  575,  574,  573,
-      696,  572,  571,  570,  569,  568,  696,  696,  696,  696,
-      696,  696,  704,  704,  704,  704,  704,  704,  704,  704,
-      704,  567,  566,  565,  704,  562,  561,  560,  558,  557,
-      704,  704,  704,  704,  704,  704,  705,  705,  705,  705,
+      734, 1398, 1399, 1401,  734,  918, 1399,  913, 1402,  908,
+      734,  734,  734,  734,  734,  734,  735,  735,  735,  735,
+      735,  735,  735,  735,  907, 1398, 1402,  735,  906,  903,
+     1402, 1403, 1404,  735,  735,  735,  735,  735,  735,  745,
+      745,  745,  745,  745,  745,  745,  745,  745,  900, 1403,
+     1404,  745,  896, 1403, 1406, 1409, 1404,  745,  745,  745,
+      745,  745,  745,  746,  746,  746,  746,  746,  746,  746,
+      746,  864, 1406, 1409,  746,  860, 1406, 1477, 1409, 1478,
+      746,  746,  746,  746,  746,  746,  758,  758,  758,  758,
+      758,  758,  758,  758,  758, 1477,  853, 1478,  758,  852,
 
-      705,  705,  705,  705,  554,  549,  545,  705,  541,  536,
-      531,  530,  529,  705,  705,  705,  705,  705,  705,  715,
-      715,  715,  715,  715,  715,  715,  715,  715,  525,  519,
-      518,  715,  513,  512,  511,  510,  509,  715,  715,  715,
-      715,  715,  715,  716,  716,  716,  716,  716,  716,  716,
-      716,  508,  507,  506,  716,  505,  504,  503,  501,  498,
-      716,  716,  716,  716,  716,  716,  728,  728,  728,  728,
-      728,  728,  728,  728,  728,  497,  496,  495,  728,  494,
-      493,  492,  490,  489,  728,  728,  728,  728,  728,  728,
-      730,  730,  730,  730,  730,  730,  730,  730,  730,  488,
+      849, 1488,  845, 1477,  758,  758,  758,  758,  758,  758,
+      760,  760,  760,  760,  760,  760,  760,  760,  760, 1488,
+     1488,  844,  760,  841,  760,  838,  837,  834,  760,  760,
+      760,  760,  760,  760,  936,  936,  936,  936,  936,  936,
+      936,  938,  938,  938,  938,  938,  938,  938, 1018,  969,
+      760,  794, 1019,  794,  794,  794,  794,  794,  794,  794,
+      830,  829, 1018,  826,  794,  825, 1019,  969, 1081,  794,
+      794,  794,  794,  794,  794,  794,  796,  796,  796,  796,
+      796,  796,  796,  969,  822,  818, 1081,  796, 1018, 1534,
+     1491, 1536, 1019,  796,  796,  796,  796,  796,  796,  798,
 
-      487,  485,  730,  483,  730,  482,  481,  480,  730,  730,
-      730,  730,  730,  730,  886,  886,  886,  886,  886,  886,
-      886,  890,  890,  890,  890,  890,  890,  890,  960,  961,
-      730,  752,  971,  752,  752,  752,  752,  752,  752,  752,
-      479,  477,  960,  961,  752,  476,  971,  474,  473,  752,
-      752,  752,  752,  752,  752,  752,  754,  754,  754,  754,
-      754,  754,  754,  472,  469,  465,  461,  754,  960,  961,
-      460,  459,  971,  754,  754,  754,  754,  754,  754,  756,
-      756,  756,  756,  756,  756,  756,  456,  452,  451,  448,
-      756,  447, 1367,  446,  445,  442,  756,  756,  756,  756,
+      798,  798,  798,  798,  798,  798, 1081, 1534, 1491, 1536,
+      798, 1491, 1303, 1537, 1544, 1548,  798,  798,  798,  798,
+      798,  798,  800,  800,  800,  800,  800,  800,  800,  800,
+     1303, 1537, 1544, 1548,  800,  815, 1537, 1544,  814, 1303,
+      800,  800,  800,  800,  800,  800,  801,  801,  801,  801,
+      801,  801,  801,  801,  804,  804,  804,  804,  804,  804,
+      804,  804,  804,  813,  812,  809,  804,  806,  804,  803,
+      802,  763,  804,  804,  804,  804,  804,  804,  942,  942,
+      942,  942,  942,  942,  942,  949,  949,  949,  949,  949,
+      949,  949,  965,  971,  804,  807,  807,  807,  807,  807,
 
-      756,  756,  758,  758,  758,  758,  758,  758,  758,  758,
-     1367,  441,  432,  429,  758,  427,  426,  425,  424, 1367,
-      758,  758,  758,  758,  758,  758,  759,  759,  759,  759,
-      759,  759,  759,  759,  762,  762,  762,  762,  762,  762,
-      762,  762,  762,  423,  422,  421,  762,  420,  762,  419,
-      418,  417,  762,  762,  762,  762,  762,  762,  897,  897,
-      897,  897,  897,  897,  897,  969,  969,  969,  969,  969,
-      969,  969,  972,  416,  762,  765,  765,  765,  765,  765,
-      765,  765,  765,  765,  414,  975,  972,  765,  412,  765,
-      411,  976,  987,  765,  765,  765,  765,  765,  765,  975,
+      807,  807,  807,  807, 1073, 1074, 1022,  807,  762,  807,
+      965,  971, 1479,  807,  807,  807,  807,  807,  807,  759,
+     1022,  755, 1073, 1074,  754,  965,  965,  982,  971,  980,
+     1479, 1077,  751, 1073, 1074,  807,  810,  810,  810,  810,
+      810,  810,  810,  810,  810,  982, 1022,  980,  810, 1077,
+      810, 1479, 1023,  747,  810,  810,  810,  810,  810,  810,
+      980, 1033,  982, 1077,  743,  736, 1023, 1031, 1031, 1031,
+     1031, 1031, 1031, 1031, 1034, 1033,  810,  816,  816,  816,
+      816,  816,  816,  816,  816,  816, 1576, 1075, 1034,  816,
+      732,  816, 1023, 1037, 1038,  816,  816,  816,  816,  816,
 
-      409,  408,  405,  404,  402,  976,  987,  400,  399,  398,
-      393, 1366,  972,  988,  392,  765,  768,  768,  768,  768,
-      768,  768,  768,  768,  768,  975,  391,  988,  768, 1366,
-      768,  976,  987,  991,  768,  768,  768,  768,  768,  768,
-      985,  985,  985,  985,  985,  985,  985,  991, 1366,  389,
-      388,  387,  992,  988, 1098,  386,  768,  774,  774,  774,
-      774,  774,  774,  774,  774,  774,  992,  384, 1098,  774,
-      379,  774,  378,  991, 1099,  774,  774,  774,  774,  774,
-      774, 1000, 1000, 1000, 1000, 1000, 1000, 1000, 1099,  377,
-      374,  370,  992, 1102, 1098, 1103,  368,  774,  779,  779,
+      816, 1033,  727,  722, 1576, 1075,  721, 1037, 1038,  720,
+     1541,  717,  713, 1049, 1034, 1050, 1075,  816,  821,  821,
+      821,  821,  821,  821,  821,  821,  821, 1049, 1541, 1050,
+      821,  703,  702, 1037, 1038,  698,  821,  821,  821,  821,
+      821,  821,  823,  823,  823,  823,  823,  823,  823,  823,
+      823, 1541,  697, 1049,  823, 1050,  823, 1085, 1196, 1053,
+      823,  823,  823,  823,  823,  823, 1047, 1047, 1047, 1047,
+     1047, 1047, 1047, 1053,  695, 1085, 1196,  694, 1054, 1410,
+     1197,  677,  823,  833,  833,  833,  833,  833,  833,  833,
+      833,  833, 1054, 1196, 1085,  833,  667, 1410, 1197, 1053,
 
-      779,  779,  779,  779,  779,  779,  779, 1102,  363, 1103,
-      779,  362,  359,  354, 1099,  353,  779,  779,  779,  779,
-      779,  779,  781,  781,  781,  781,  781,  781,  781,  781,
-      781,  345,  343, 1102,  781, 1103,  781,  342,  337,  335,
-      781,  781,  781,  781,  781,  781, 1002, 1002, 1002, 1002,
-     1002, 1002, 1002, 1006, 1006, 1006, 1006, 1006, 1006, 1006,
-     1145,  333,  781,  791,  791,  791,  791,  791,  791,  791,
-      791,  791,  332,  331, 1145,  791,  330,  329,  328,  327,
-      325,  791,  791,  791,  791,  791,  791,  793,  793,  793,
-      793,  793,  793,  793,  793,  793, 1011, 1012, 1146,  793,
+      663,  833,  833,  833,  833,  833,  833,  835,  835,  835,
+      835,  835,  835,  835,  835,  835, 1197, 1410, 1054,  835,
+      657,  835,  656,  653,  649,  835,  835,  835,  835,  835,
+      835, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1064, 1064,
+     1064, 1064, 1064, 1064, 1064, 1170, 1094,  835,  848,  848,
+      848,  848,  848,  848,  848,  848,  848,  648,  645, 1170,
+      848,  644,  641,  637, 1094, 1094,  848,  848,  848,  848,
+      848,  848,  850,  850,  850,  850,  850,  850,  850,  850,
+      850, 1094, 1094,  634,  850, 1170,  850, 1587, 1486, 1086,
+      850,  850,  850,  850,  850,  850, 1068, 1068, 1068, 1068,
 
-     1145,  793,  324,  323,  318,  793,  793,  793,  793,  793,
-      793,  315, 1146,  314, 1011, 1012, 1045, 1045, 1045, 1045,
-     1045, 1045, 1045, 1151,  313, 1011, 1012,  793,  806,  806,
-      806,  806,  806,  806,  806,  806,  806, 1151, 1146,  310,
-      806,  303,  302,  300,  299,  298,  806,  806,  806,  806,
-      806,  806,  808,  808,  808,  808,  808,  808,  808,  808,
-      808, 1013, 1152, 1151,  808,  296,  808,  294,  293, 1413,
-      808,  808,  808,  808,  808,  808, 1152,  292,  290, 1013,
-     1050, 1050, 1050, 1050, 1050, 1050, 1050, 1413,  286, 1155,
-     1013,  285,  808,  820,  820,  820,  820,  820,  820,  820,
+     1068, 1068, 1068,  633,  632, 1587, 1486, 1086, 1200, 1171,
+     1174,  631,  850,  862,  862,  862,  862,  862,  862,  862,
+      862,  862, 1086, 1171, 1174,  862, 1200, 1486, 1612, 1080,
+     1175,  862,  862,  862,  862,  862,  862,  863,  863,  863,
+      863,  863,  863,  863, 1175, 1200, 1612, 1080,  863, 1171,
+     1174, 1578,  628, 1579,  863,  863,  863,  863,  863,  863,
+      889, 1080,  889,  889,  889,  889,  889,  889,  889, 1578,
+     1175, 1579, 1578,  889, 1579, 1620, 1580, 1628,  889,  889,
+      889,  889,  889,  889,  889,  890,  890,  890,  890,  890,
+      890,  890,  625, 1620, 1580, 1628,  890, 1580, 1411, 1089,
 
-      820,  820, 1152, 1155,  283,  820, 1413,  280,  276,  275,
-     1156,  820,  820,  820,  820,  820,  820,  821,  821,  821,
-      821,  821,  821,  821, 1156,  272,  271,  269,  821, 1155,
-      264,  261,  259,  258,  821,  821,  821,  821,  821,  821,
-      837, 1164,  837,  837,  837,  837,  837,  837,  837,  256,
-     1156,  253,  249,  837,  245, 1164,  243,  241,  837,  837,
-      837,  837,  837,  837,  837,  838,  838,  838,  838,  838,
-      838,  838,  240,  238,  237,  236,  838,  235,  234,  233,
-      232, 1164,  838,  838,  838,  838,  838,  838,  839,  839,
-      839,  839,  839,  839,  839,  839,  230,  228,  226,  225,
+     1585, 1091,  890,  890,  890,  890,  890,  890,  891,  891,
+      891,  891,  891,  891,  891,  891, 1411, 1089, 1585, 1091,
+      891, 1585,  891,  624,  617, 1411,  891,  891,  891,  891,
+      891,  891, 1089, 1091, 1117, 1117, 1117, 1117, 1117, 1117,
+     1117, 1122, 1122, 1122, 1122, 1122, 1122, 1122,  891,  893,
+      893,  893,  893,  893,  893,  893,  614,  612,  608,  602,
+      893,  601, 1476, 1605, 1607, 1608,  893,  893,  893,  893,
+      893,  893,  894,  894,  894,  894,  894,  894,  894,  894,
+     1476, 1605, 1607, 1608,  894, 1605,  600, 1607, 1608, 1476,
+      894,  894,  894,  894,  894,  894,  895,  895,  895,  895,
 
-      839,  223,  839,  221,  220,  218,  839,  839,  839,  839,
-      839,  839, 1054, 1054, 1054, 1054, 1054, 1054, 1054, 1059,
-     1059, 1059, 1059, 1059, 1059, 1059,  215, 1165,  839,  841,
-      841,  841,  841,  841,  841,  841,  214,  213,  211,  209,
-      841, 1165,  208,  205,  204,  202,  841,  841,  841,  841,
-      841,  841,  842,  842,  842,  842,  842,  842,  842,  842,
-      201,  200,  199,  198,  842,  197,  196, 1165,  195,  194,
-      842,  842,  842,  842,  842,  842,  843,  843,  843,  843,
-      843,  843,  843,  843,  845,  845,  845,  845,  845,  845,
-      845,  193,  192,  191,  190,  845,  189,  188,  187,  186,
+      895,  895,  895,  895,  897,  897,  897,  897,  897,  897,
+      897,  599,  595,  594,  592,  897,  591,  590, 1633, 1634,
+     1622,  897,  897,  897,  897,  897,  897,  898,  898,  898,
+      898,  898,  898,  898,  898,  898, 1633, 1634, 1622,  898,
+      589,  585, 1634, 1635, 1229,  898,  898,  898,  898,  898,
+      898,  899,  899,  899,  899,  899,  899,  899, 1229, 1622,
+      584, 1635,  899,  583,  582, 1636, 1635, 1623,  899,  899,
+      899,  899,  899,  899,  901,  901,  901,  901,  901,  901,
+      901,  901,  901, 1636, 1229, 1623,  901,  581, 1636, 1638,
+     1640, 1230,  901,  901,  901,  901,  901,  901,  902,  902,
 
-      185,  845,  845,  845,  845,  845,  845,  846,  846,  846,
-      846,  846,  846,  846,  846,  846,  183,  182,  179,  846,
-      178,  177,  176,  175, 1168,  846,  846,  846,  846,  846,
-      846,  847,  847,  847,  847,  847,  847,  847, 1168,  174,
-      173,  172,  847,  170,  167,  166,  165,  164,  847,  847,
-      847,  847,  847,  847,  849,  849,  849,  849,  849,  849,
-      849,  849,  849,  161, 1168,  159,  849,  150,  149,  148,
-      147, 1169,  849,  849,  849,  849,  849,  849,  850,  850,
-      850,  850,  850,  850,  850, 1169,  146,  145,  144,  850,
-      142,  140,  139,  137,  135,  850,  850,  850,  850,  850,
+      902,  902,  902,  902,  902, 1230, 1623, 1638, 1640,  902,
+      580,  579, 1638,  578, 1624,  902,  902,  902,  902,  902,
+      902,  904,  904,  904,  904,  904,  904,  904,  904,  904,
+      577, 1230, 1624,  904,  576,  575, 1645, 1647, 1235,  904,
+      904,  904,  904,  904,  904,  905,  905,  905,  905,  905,
+      905,  905, 1235, 1624, 1645, 1647,  905, 1645, 1649, 1647,
+      574,  573,  905,  905,  905,  905,  905,  905,  909,  909,
+      909,  909,  909,  909,  909,  909, 1649,  572, 1235,  909,
+      569, 1649, 1651, 1652, 1657,  909,  909,  909,  909,  909,
+      909,  911,  911,  911,  911,  911,  911,  911,  911,  911,
 
-      850,  852,  852,  852,  852,  852,  852,  852,  852,  852,
-      133, 1169,  132,  852,  131,  130,  128,  127, 1178,  852,
-      852,  852,  852,  852,  852,  853,  853,  853,  853,  853,
-      853,  853, 1178,  126,  125,  124,  853,  123,  121,  119,
-      118,  117,  853,  853,  853,  853,  853,  853,  857,  857,
-      857,  857,  857,  857,  857,  857,  116,  115, 1178,  857,
-      114,  113,  112,  111,  109,  857,  857,  857,  857,  857,
-      857,  859,  859,  859,  859,  859,  859,  859,  859,  859,
-      108,  101,  100,  859,   99,   97,   96,   93,   92,  859,
-      859,  859,  859,  859,  859,  860,  860,  860,  860,  860,
+     1651, 1652, 1657,  911,  568, 1651, 1653,  567,  565,  911,
+      911,  911,  911,  911,  911,  912,  912,  912,  912,  912,
+      912,  912,  912, 1657, 1653, 1652,  912,  564,  561, 1660,
+      556, 1664,  912,  912,  912,  912,  912,  912,  920,  920,
+      920,  920,  920,  920,  920,  920,  920, 1660, 1653, 1664,
+      920,  552, 1660, 1668, 1669,  548,  920,  920,  920,  920,
+      920,  920,  921,  921,  921,  921,  921,  921,  921,  921,
+      543, 1668, 1669,  921,  538,  537, 1668, 1669, 1674,  921,
+      921,  921,  921,  921,  921,  931,  931,  931,  931,  931,
+      931,  931,  931,  931,  536,  532, 1674,  931,  526, 1675,
 
-      860,  860,  860,   91,   90,   89,  860,   88,   87,   86,
-       85,   84,  860,  860,  860,  860,  860,  860,  868,  868,
-      868,  868,  868,  868,  868,  868,  868,   82,   81,   80,
-      868,   79,   78,   77,   76,   75,  868,  868,  868,  868,
-      868,  868,  869,  869,  869,  869,  869,  869,  869,  869,
-       74,   73,   72,  869,   71,   70,   69,   67,   66,  869,
-      869,  869,  869,  869,  869,  879,  879,  879,  879,  879,
-      879,  879,  879,  879,   65,   51,   43,  879,   42,   40,
-       18,   11,    8,  879,  879,  879,  879,  879,  879,  880,
-      880,  880,  880,  880,  880,  880,  880,    3,    0,    0,
+     1677, 1674,  525,  931,  931,  931,  931,  931,  931,  932,
+      932,  932,  932,  932,  932,  932,  932, 1675, 1677,  520,
+      932, 1675,  519, 1679, 1682, 1683,  932,  932,  932,  932,
+      932,  932,  943,  943,  943,  943,  943,  943,  943,  943,
+      943, 1679, 1682, 1683,  943, 1682, 1679, 1684, 1689,  518,
+      943,  943,  943,  943,  943,  943,  944,  944,  944,  944,
+      944,  944,  944,  944,  517, 1684, 1689,  944,  516,  515,
+     1694, 1689, 1698,  944,  944,  944,  944,  944,  944,  957,
+      957,  957,  957,  957,  957,  957,  957,  957, 1694, 1684,
+     1698,  957,  514,  513, 1700, 1698, 1703,  957,  957,  957,
 
-      880,    0,    0,    0,    0,    0,  880,  880,  880,  880,
-      880,  880,  891,  891,  891,  891,  891,  891,  891,  891,
-      891,    0,    0,    0,  891,    0,    0,    0,    0,    0,
-      891,  891,  891,  891,  891,  891,  892,  892,  892,  892,
-      892,  892,  892,  892,    0,    0,    0,  892,    0,    0,
-        0,    0,    0,  892,  892,  892,  892,  892,  892,  905,
-      905,  905,  905,  905,  905,  905,  905,  905,    0,    0,
-        0,  905,    0,    0,    0,    0,    0,  905,  905,  905,
-      905,  905,  905,  907,  907,  907,  907,  907,  907,  907,
-      907,  907,    0,    0,    0,  907,    0,  907,    0,    0,
+      957,  957,  957,  959,  959,  959,  959,  959,  959,  959,
+      959,  959, 1700,  512, 1703,  959,  511,  959,  510,  509,
+      508,  959,  959,  959,  959,  959,  959, 1126, 1126, 1126,
+     1126, 1126, 1126, 1126, 1131, 1131, 1131, 1131, 1131, 1131,
+     1131, 1710, 1712,  959,  986,  986,  986,  986,  986,  986,
+      986,  986,  986,  506,  503,  502,  501,  986,  500, 1710,
+     1712,  499,  986,  986,  986,  986,  986,  986,  986,  987,
+      987,  987,  987,  987,  987,  987,  987,  988,  988,  988,
+      988,  988,  988,  988,  988,  988, 1133, 1133, 1133, 1133,
+     1133, 1133, 1133, 1701, 1714,  988,  992,  992,  992,  992,
 
-        0,  907,  907,  907,  907,  907,  907, 1061, 1061, 1061,
-     1061, 1061, 1061, 1061, 1065, 1065, 1065, 1065, 1065, 1065,
-     1065,    0,    0,  907,  924,  924,  924,  924,  924,  924,
-      924,  924,  924,    0,    0,    0,    0,  924,    0,    0,
-        0,    0,  924,  924,  924,  924,  924,  924,  924,  925,
-      925,  925,  925,  925,  925,  925,  925,  926,  926,  926,
-      926,  926,  926,  926,  926,  926, 1071, 1071, 1071, 1071,
-     1071, 1071, 1071,    0,    0,  926,  930,  930,  930,  930,
-      930,  930,  930,  930,  930,    0,    0,    0,  930,    0,
-      930,    0,    0,    0,  930,  930,  930,  930,  930,  930,
+      992,  992,  992,  992,  992,  498,  497,  495,  992,  494,
+      992, 1701, 1714,  493,  992,  992,  992,  992,  992,  992,
+     1137, 1137, 1137, 1137, 1137, 1137, 1137, 1143, 1143, 1143,
+     1143, 1143, 1143, 1143, 1706, 1701,  992,  995,  995,  995,
+      995,  995,  995,  995,  995,  995,  492,  491,  489,  995,
+      487,  995, 1706,  485,  484,  995,  995,  995,  995,  995,
+      995, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1149, 1149,
+     1149, 1149, 1149, 1149, 1149, 1719, 1706,  995,  998,  998,
+      998,  998,  998,  998,  998,  998,  998,  483,  482,  481,
+      998,  479,  998, 1719,  478,  476,  998,  998,  998,  998,
 
-     1073, 1073, 1073, 1073, 1073, 1073, 1073, 1077, 1077, 1077,
-     1077, 1077, 1077, 1077,    0,    0,  930,  933,  933,  933,
-      933,  933,  933,  933,  933,  933,    0,    0,    0,  933,
-        0,  933,    0,    0,    0,  933,  933,  933,  933,  933,
-      933, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1085, 1085,
-     1085, 1085, 1085, 1085, 1085,    0,    0,  933,  936,  936,
-      936,  936,  936,  936,  936,  936,  936,    0,    0,    0,
-      936,    0,  936,    0,    0,    0,  936,  936,  936,  936,
-      936,  936, 1089, 1089, 1089, 1089, 1089, 1089, 1089, 1096,
-     1096, 1096, 1096, 1096, 1096, 1096, 1116,    0,  936,  939,
+      998,  998, 1155, 1155, 1155, 1155, 1155, 1155, 1155, 1157,
+     1157, 1157, 1157, 1157, 1157, 1157, 1721, 1724,  998, 1001,
+     1001, 1001, 1001, 1001, 1001, 1001, 1001, 1001,  475,  474,
+      471, 1001,  467, 1001, 1721, 1724,  463, 1001, 1001, 1001,
+     1001, 1001, 1001, 1161, 1161, 1161, 1161, 1161, 1161, 1161,
+     1168, 1168, 1168, 1168, 1168, 1168, 1168,  462,  461, 1001,
+     1006, 1006, 1006, 1006, 1006, 1006, 1006, 1006,  458,  454,
+      453, 1006,  450,  449,  448, 1191, 1194, 1006, 1006, 1006,
+     1006, 1006, 1006, 1007, 1007, 1007, 1007, 1007, 1007, 1007,
+     1007, 1007, 1188, 1191, 1194, 1007, 1543, 1007, 1198, 1236,
 
-      939,  939,  939,  939,  939,  939,  939,  939,    0, 1179,
-     1182,  939,    0,  939, 1116,    0,    0,  939,  939,  939,
-      939,  939,  939, 1179, 1182, 1116, 1139, 1139, 1139, 1139,
-     1139, 1139, 1139,    0, 1183,    0,    0,    0, 1192,  939,
-      944,  944,  944,  944,  944,  944,  944,  944, 1183, 1179,
-     1182,  944, 1192,    0,    0,    0,    0,  944,  944,  944,
-      944,  944,  944,  945,  945,  945,  945,  945,  945,  945,
-      945,  945,    0,    0, 1183,  945,    0,  945, 1192,    0,
-        0,  945,  945,  945,  945,  945,  945, 1162, 1162, 1162,
-     1162, 1162, 1162, 1162, 1176, 1176, 1176, 1176, 1176, 1176,
+     1308, 1007, 1007, 1007, 1007, 1007, 1007, 1194, 1191,  447,
+     1188,  444,  443, 1236, 1543,  434, 1198, 1709, 1308,  431,
+      429, 1188,  428, 1007, 1012, 1012, 1012, 1012, 1012, 1012,
+     1012, 1012, 1012, 1198, 1543, 1709, 1012, 1308, 1709, 1236,
+     1195, 1199, 1012, 1012, 1012, 1012, 1012, 1012, 1014, 1014,
+     1014, 1014, 1014, 1014, 1014, 1014, 1014, 1193, 1195, 1199,
+     1014,  427, 1014,  426,  425, 1309, 1014, 1014, 1014, 1014,
+     1014, 1014, 1195, 1199,  424, 1193, 1223, 1223, 1223, 1223,
+     1223, 1223, 1223, 1309, 1239, 1311, 1193,  423, 1014, 1024,
+     1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1239,  422,
 
-     1176, 1193,    0,  945,  950,  950,  950,  950,  950,  950,
-      950,  950,  950,    0,    0, 1193,  950,    0,    0,    0,
-        0,    0,  950,  950,  950,  950,  950,  950,  952,  952,
-      952,  952,  952,  952,  952,  952,  952,    0,    0,    0,
-      952, 1193,  952,    0,    0, 1196,  952,  952,  952,  952,
-      952,  952, 1190, 1190, 1190, 1190, 1190, 1190, 1190, 1196,
-        0,    0,    0,    0, 1197,    0, 1241,    0,  952,  962,
-      962,  962,  962,  962,  962,  962,  962,  962, 1197,    0,
-     1241,  962,    0,    0,    0, 1196,    0,  962,  962,  962,
-      962,  962,  962,  964,  964,  964,  964,  964,  964,  964,
+     1309, 1024,  421, 1311,  420, 1203,  419, 1024, 1024, 1024,
+     1024, 1024, 1024, 1026, 1026, 1026, 1026, 1026, 1026, 1026,
+     1026, 1026, 1311, 1203, 1239, 1026,  418, 1026, 1240,  417,
+      416, 1026, 1026, 1026, 1026, 1026, 1026, 1203,  414,  412,
+      411,  409, 1240, 1246, 1246, 1246, 1246, 1246, 1246, 1246,
+      408, 1248, 1313, 1026, 1039, 1039, 1039, 1039, 1039, 1039,
+     1039, 1039, 1039,  405,  404, 1248, 1039,  402, 1240,  400,
+     1313,  399, 1039, 1039, 1039, 1039, 1039, 1039, 1041, 1041,
+     1041, 1041, 1041, 1041, 1041, 1041, 1041, 1313, 1249, 1252,
+     1041, 1248, 1041, 1253,  398,  393, 1041, 1041, 1041, 1041,
 
-      964,  964,    0,    0, 1197,  964, 1241,  964,    0,    0,
-        0,  964,  964,  964,  964,  964,  964, 1203, 1203, 1203,
-     1203, 1203, 1203, 1203, 1205, 1205, 1205, 1205, 1205, 1205,
-     1205, 1242,    0,  964,  977,  977,  977,  977,  977,  977,
-      977,  977,  977,    0,    0, 1242,  977,    0,    0,    0,
-        0,    0,  977,  977,  977,  977,  977,  977,  979,  979,
-      979,  979,  979,  979,  979,  979,  979,    0,    0,    0,
-      979, 1242,  979,    0,    0,    0,  979,  979,  979,  979,
-      979,  979, 1209, 1209, 1209, 1209, 1209, 1209, 1209, 1249,
-     1249, 1249, 1249, 1249, 1249, 1249, 1289,    0,  979,  993,
+     1041, 1041, 1249, 1252,  392,  391,  389, 1253, 1260, 1260,
+     1260, 1260, 1260, 1260, 1260,  388, 1262, 1395, 1041, 1055,
+     1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1249, 1252,
+     1262, 1055,  387, 1253,  386, 1395,  384, 1055, 1055, 1055,
+     1055, 1055, 1055, 1057, 1057, 1057, 1057, 1057, 1057, 1057,
+     1057, 1057, 1395, 1263, 1266, 1057, 1262, 1057, 1267,  379,
+      378, 1057, 1057, 1057, 1057, 1057, 1057, 1263, 1266,  377,
+      374,  370, 1267, 1274, 1274, 1274, 1274, 1274, 1274, 1274,
+      368, 1276, 1489, 1057, 1069, 1069, 1069, 1069, 1069, 1069,
+     1069, 1069, 1069, 1263, 1266, 1276, 1069,  363, 1267,  362,
 
-      993,  993,  993,  993,  993,  993,  993,  993,    0,    0,
-     1289,  993,    0,    0,    0,    0, 1220,  993,  993,  993,
-      993,  993,  993,  995,  995,  995,  995,  995,  995,  995,
-      995,  995, 1221,    0, 1220,  995, 1289,  995,    0,    0,
-        0,  995,  995,  995,  995,  995,  995, 1220,    0,    0,
-     1221, 1254, 1254, 1254, 1254, 1254, 1254, 1254,    0,    0,
-     1290, 1221,    0,  995, 1007, 1007, 1007, 1007, 1007, 1007,
-     1007, 1007, 1007,    0, 1290,    0, 1007,    0,    0,    0,
-        0, 1293, 1007, 1007, 1007, 1007, 1007, 1007, 1008, 1008,
-     1008, 1008, 1008, 1008, 1008, 1293,    0,    0,    0, 1008,
+     1489, 1277, 1069, 1069, 1069, 1069, 1069, 1069, 1070, 1070,
+     1070, 1070, 1070, 1070, 1070, 1277,  359, 1489,  354, 1070,
+      353, 1276, 1707,  345, 1713, 1070, 1070, 1070, 1070, 1070,
+     1070, 1095, 1095, 1095, 1095, 1095, 1095, 1095, 1095, 1095,
+     1707, 1277, 1713,  343, 1095, 1707,  342, 1713,  337, 1095,
+     1095, 1095, 1095, 1095, 1095, 1095, 1096, 1096, 1096, 1096,
+     1096, 1096, 1096, 1096, 1097, 1097, 1097, 1097, 1097, 1097,
+     1097, 1097, 1097,  335, 1725, 1726, 1280, 1281, 1727, 1306,
+      333, 1337, 1097, 1099, 1099, 1099, 1099, 1099, 1099, 1099,
+     1280, 1281, 1725, 1726, 1099, 1337, 1727, 1306, 1306,  332,
 
-     1290,    0,    0,    0,    0, 1008, 1008, 1008, 1008, 1008,
-     1008, 1023, 1023, 1023, 1023, 1023, 1023, 1023, 1023, 1023,
-        0, 1293,    0,    0, 1023,    0,    0,    0,    0, 1023,
-     1023, 1023, 1023, 1023, 1023, 1023, 1024, 1024, 1024, 1024,
-     1024, 1024, 1024, 1024, 1025, 1025, 1025, 1025, 1025, 1025,
-     1025, 1025, 1025, 1256, 1256, 1256, 1256, 1256, 1256, 1256,
-        0, 1294, 1025, 1027, 1027, 1027, 1027, 1027, 1027, 1027,
-        0,    0,    0,    0, 1027, 1294,    0,    0,    0,    0,
-     1027, 1027, 1027, 1027, 1027, 1027, 1028, 1028, 1028, 1028,
-     1028, 1028, 1028, 1028, 1028,    0,    0,    0, 1028,    0,
+     1099, 1099, 1099, 1099, 1099, 1099, 1100, 1100, 1100, 1100,
+     1100, 1100, 1100, 1100, 1100, 1306, 1280, 1281, 1100,  331,
+      330, 1337,  329, 1338, 1100, 1100, 1100, 1100, 1100, 1100,
+     1101, 1101, 1101, 1101, 1101, 1101, 1101, 1338,  328,  327,
+      325, 1101,  324,  323,  318,  315, 1687, 1101, 1101, 1101,
+     1101, 1101, 1101, 1103, 1103, 1103, 1103, 1103, 1103, 1103,
+     1103, 1103,  314, 1338, 1687, 1103,  313,  310,  303,  302,
+     1385, 1103, 1103, 1103, 1103, 1103, 1103, 1104, 1104, 1104,
+     1104, 1104, 1104, 1104, 1385, 1687,  300,  299, 1104,  298,
+      296,  294,  293, 1718, 1104, 1104, 1104, 1104, 1104, 1104,
 
-        0, 1294,    0, 1318, 1028, 1028, 1028, 1028, 1028, 1028,
-     1029, 1029, 1029, 1029, 1029, 1029, 1029, 1318,    0,    0,
-        0, 1029,    0,    0,    0,    0,    0, 1029, 1029, 1029,
-     1029, 1029, 1029, 1031, 1031, 1031, 1031, 1031, 1031, 1031,
-     1031, 1031,    0, 1318,    0, 1031,    0,    0,    0,    0,
-     1319, 1031, 1031, 1031, 1031, 1031, 1031, 1032, 1032, 1032,
-     1032, 1032, 1032, 1032, 1319,    0,    0,    0, 1032,    0,
-        0,    0,    0,    0, 1032, 1032, 1032, 1032, 1032, 1032,
-     1034, 1034, 1034, 1034, 1034, 1034, 1034, 1034, 1034,    0,
-     1319,    0, 1034,    0,    0,    0,    0, 1326, 1034, 1034,
+     1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106,  292,
+     1385, 1718, 1106,  290,  286,  285,  283, 1386, 1106, 1106,
+     1106, 1106, 1106, 1106, 1107, 1107, 1107, 1107, 1107, 1107,
+     1107, 1386, 1718,  280,  276, 1107,  275,  272,  271,  269,
+      264, 1107, 1107, 1107, 1107, 1107, 1107, 1109, 1109, 1109,
+     1109, 1109, 1109, 1109, 1109, 1109,  261, 1386,  259, 1109,
+      258,  256,  253,  249, 1389, 1109, 1109, 1109, 1109, 1109,
+     1109, 1110, 1110, 1110, 1110, 1110, 1110, 1110, 1389,  245,
+      243,  241, 1110,  240,  238,  237,  236,  235, 1110, 1110,
+     1110, 1110, 1110, 1110, 1113, 1113, 1113, 1113, 1113, 1113,
 
-     1034, 1034, 1034, 1034, 1035, 1035, 1035, 1035, 1035, 1035,
-     1035, 1326,    0,    0,    0, 1035,    0,    0,    0,    0,
-        0, 1035, 1035, 1035, 1035, 1035, 1035, 1037, 1037, 1037,
-     1037, 1037, 1037, 1037, 1037, 1037,    0, 1326,    0, 1037,
-        0,    0,    0,    0, 1327, 1037, 1037, 1037, 1037, 1037,
-     1037, 1038, 1038, 1038, 1038, 1038, 1038, 1038, 1327,    0,
-        0,    0, 1038,    0,    0,    0,    0,    0, 1038, 1038,
-     1038, 1038, 1038, 1038, 1041, 1041, 1041, 1041, 1041, 1041,
-     1041, 1041, 1041,    0, 1327,    0, 1041,    0, 1041,    0,
-        0,    0, 1041, 1041, 1041, 1041, 1041, 1041, 1262, 1262,
+     1113, 1113, 1113,  234, 1389,  233, 1113,  232, 1113,  230,
+      228,  226, 1113, 1113, 1113, 1113, 1113, 1113, 1287, 1287,
+     1287, 1287, 1287, 1287, 1287, 1289, 1289, 1289, 1289, 1289,
+     1289, 1289, 1312,  225, 1113, 1118, 1118, 1118, 1118, 1118,
+     1118, 1118, 1118, 1118,  223,  221,  220, 1118,  218,  215,
+     1312, 1312,  214, 1118, 1118, 1118, 1118, 1118, 1118, 1127,
+     1127, 1127, 1127, 1127, 1127, 1127, 1127, 1127, 1312,  213,
+      211, 1127,  209,  208,  205,  204,  202, 1127, 1127, 1127,
+     1127, 1127, 1127, 1138, 1138, 1138, 1138, 1138, 1138, 1138,
+     1138, 1138,  201,  200,  199, 1138,  198,  197,  196,  195,
 
-     1262, 1262, 1262, 1262, 1262, 1264, 1264, 1264, 1264, 1264,
-     1264, 1264, 1335,    0, 1041, 1046, 1046, 1046, 1046, 1046,
-     1046, 1046, 1046, 1046,    0,    0, 1335, 1046,    0,    0,
-        0,    0,    0, 1046, 1046, 1046, 1046, 1046, 1046, 1055,
-     1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055,    0,    0,
-        0, 1055, 1335,    0,    0,    0,    0, 1055, 1055, 1055,
-     1055, 1055, 1055, 1066, 1066, 1066, 1066, 1066, 1066, 1066,
-     1066, 1066,    0,    0,    0, 1066,    0,    0,    0,    0,
-        0, 1066, 1066, 1066, 1066, 1066, 1066, 1078, 1078, 1078,
-     1078, 1078, 1078, 1078, 1078, 1078,    0,    0,    0, 1078,
+      194, 1138, 1138, 1138, 1138, 1138, 1138, 1150, 1150, 1150,
+     1150, 1150, 1150, 1150, 1150, 1150,  193,  192,  191, 1150,
+      190,  189,  188,  187,  186, 1150, 1150, 1150, 1150, 1150,
+     1150, 1162, 1162, 1162, 1162, 1162, 1162, 1162, 1162, 1162,
+      185,  183,  182, 1162,  179,  178,  177,  176,  175, 1162,
+     1162, 1162, 1162, 1162, 1162, 1176, 1176, 1176, 1176, 1176,
+     1176, 1176, 1176, 1176,  174,  173,  172, 1176,  170,  167,
+      166,  165,  164, 1176, 1176, 1176, 1176, 1176, 1176, 1178,
+     1178, 1178, 1178, 1178, 1178, 1178, 1178, 1178,  161,  159,
+      150, 1178,  149, 1178, 1475, 1535, 1390, 1178, 1178, 1178,
 
-        0,    0,    0,    0,    0, 1078, 1078, 1078, 1078, 1078,
-     1078, 1090, 1090, 1090, 1090, 1090, 1090, 1090, 1090, 1090,
-        0,    0,    0, 1090,    0,    0,    0,    0,    0, 1090,
-     1090, 1090, 1090, 1090, 1090, 1104, 1104, 1104, 1104, 1104,
-     1104, 1104, 1104, 1104,    0,    0,    0, 1104,    0,    0,
-        0,    0,    0, 1104, 1104, 1104, 1104, 1104, 1104, 1106,
-     1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106,    0,    0,
-        0, 1106,    0, 1106,    0,    0,    0, 1106, 1106, 1106,
-     1106, 1106, 1106, 1270, 1270, 1270, 1270, 1270, 1270, 1270,
-     1272, 1272, 1272, 1272, 1272, 1272, 1272,    0,    0, 1106,
+     1178, 1178, 1178, 1293, 1293, 1293, 1293, 1293, 1293, 1293,
+     1390, 1650, 1475, 1535,  148, 1546, 1304, 1316,  147, 1178,
+     1204, 1204, 1204, 1204, 1204, 1204, 1204, 1204, 1204, 1650,
+      146, 1475, 1535, 1546, 1304, 1316, 1390, 1427, 1204, 1206,
+     1206, 1206, 1206, 1206, 1206, 1206, 1206, 1304, 1316, 1650,
+     1206, 1427, 1546,  145,  144, 1400, 1206, 1206, 1206, 1206,
+     1206, 1206, 1207, 1207, 1207, 1207, 1207, 1207, 1207, 1207,
+     1207, 1305, 1317, 1400, 1207,  142, 1207, 1427,  140,  139,
+     1207, 1207, 1207, 1207, 1207, 1207,  137, 1400,  135, 1305,
+     1317, 1345, 1345, 1345, 1345, 1345, 1345, 1345,  133,  132,
 
-     1120, 1120, 1120, 1120, 1120, 1120, 1120, 1120, 1120, 1278,
-     1278, 1278, 1278, 1278, 1278, 1278,    0, 1336, 1120, 1122,
-     1122, 1122, 1122, 1122, 1122, 1122, 1122,    0,    0,    0,
-     1122, 1336,    0,    0,    0,    0, 1122, 1122, 1122, 1122,
-     1122, 1122, 1123, 1123, 1123, 1123, 1123, 1123, 1123, 1123,
-     1123,    0,    0,    0, 1123,    0, 1123, 1336,    0,    0,
-     1123, 1123, 1123, 1123, 1123, 1123, 1280, 1280, 1280, 1280,
-     1280, 1280, 1280, 1287, 1287, 1287, 1287, 1287, 1287, 1287,
-        0,    0, 1123, 1126, 1126, 1126, 1126, 1126, 1126, 1126,
-     1126, 1126,    0,    0,    0, 1126,    0, 1126,    0,    0,
+     1305, 1317, 1207, 1210, 1210, 1210, 1210, 1210, 1210, 1210,
+     1210, 1210,  131,  130,  128, 1210,  127, 1210,  126,  125,
+      124, 1210, 1210, 1210, 1210, 1210, 1210, 1350, 1350, 1350,
+     1350, 1350, 1350, 1350, 1352, 1352, 1352, 1352, 1352, 1352,
+     1352,  123,  121, 1210, 1213, 1213, 1213, 1213, 1213, 1213,
+     1213, 1213, 1213,  119,  118,  117, 1213,  116, 1213,  115,
+      114,  113, 1213, 1213, 1213, 1213, 1213, 1213, 1358, 1358,
+     1358, 1358, 1358, 1358, 1358, 1360, 1360, 1360, 1360, 1360,
+     1360, 1360,  112,  111, 1213, 1216, 1216, 1216, 1216, 1216,
+     1216, 1216, 1216, 1216,  109,  108,  101, 1216,  100, 1216,
 
-        0, 1126, 1126, 1126, 1126, 1126, 1126, 1312, 1312, 1312,
-     1312, 1312, 1312, 1312, 1324, 1324, 1324, 1324, 1324, 1324,
-     1324,    0,    0, 1126, 1129, 1129, 1129, 1129, 1129, 1129,
-     1129, 1129, 1129,    0,    0,    0, 1129,    0, 1129,    0,
-        0,    0, 1129, 1129, 1129, 1129, 1129, 1129, 1333, 1333,
-     1333, 1333, 1333, 1333, 1333, 1342, 1342, 1342, 1342, 1342,
-     1342, 1342, 1344,    0, 1129, 1132, 1132, 1132, 1132, 1132,
-     1132, 1132, 1132, 1132,    0, 1345, 1344, 1132,    0, 1132,
-        0,    0,    0, 1132, 1132, 1132, 1132, 1132, 1132, 1345,
-     1351, 1351, 1351, 1351, 1351, 1351, 1351,    0,    0,    0,
+       99,   97,   96, 1216, 1216, 1216, 1216, 1216, 1216, 1366,
+     1366, 1366, 1366, 1366, 1366, 1366, 1368, 1368, 1368, 1368,
+     1368, 1368, 1368,   93,   92, 1216, 1219, 1219, 1219, 1219,
+     1219, 1219, 1219, 1219, 1219,   91,   90,   89, 1219,   88,
+     1219,   87,   86,   85, 1219, 1219, 1219, 1219, 1219, 1219,
+     1374, 1374, 1374, 1374, 1374, 1374, 1374, 1376, 1376, 1376,
+     1376, 1376, 1376, 1376, 1428, 1539, 1219, 1224, 1224, 1224,
+     1224, 1224, 1224, 1224, 1224, 1224,   84,   82, 1428, 1224,
+       81,   80,   79, 1539,   78, 1224, 1224, 1224, 1224, 1224,
+     1224, 1231, 1231, 1231, 1231, 1231, 1231, 1231, 1231, 1231,
 
-        0,    0, 1344, 1353,    0, 1132, 1135, 1135, 1135, 1135,
-     1135, 1135, 1135, 1135, 1135, 1345, 1354, 1353, 1135,    0,
-     1135,    0,    0,    0, 1135, 1135, 1135, 1135, 1135, 1135,
-     1354, 1359, 1359, 1359, 1359, 1359, 1359, 1359,    0,    0,
-        0,    0,    0, 1353, 1378,    0, 1135, 1140, 1140, 1140,
-     1140, 1140, 1140, 1140, 1140, 1140, 1354,    0, 1378, 1140,
-        0,    0,    0,    0,    0, 1140, 1140, 1140, 1140, 1140,
-     1140, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147,
-        0,    0,    0, 1147, 1378,    0,    0,    0,    0, 1147,
-     1147, 1147, 1147, 1147, 1147, 1157, 1157, 1157, 1157, 1157,
+       77, 1539,   76, 1231, 1428,   75,   74,   73,   72, 1231,
+     1231, 1231, 1231, 1231, 1231, 1241, 1241, 1241, 1241, 1241,
+     1241, 1241, 1241, 1241,   71,   70,   69, 1241,   67,   66,
+       65,   51,   43, 1241, 1241, 1241, 1241, 1241, 1241, 1254,
+     1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254,   42,   40,
+       18, 1254,   11,    8,    3,    0,    0, 1254, 1254, 1254,
+     1254, 1254, 1254, 1268, 1268, 1268, 1268, 1268, 1268, 1268,
+     1268, 1268,    0,    0,    0, 1268,    0,    0,    0,    0,
+        0, 1268, 1268, 1268, 1268, 1268, 1268, 1282, 1282, 1282,
+     1282, 1282, 1282, 1282, 1282, 1282,    0,    0,    0, 1282,
 
-     1157, 1157, 1157, 1157,    0,    0,    0, 1157,    0,    0,
-        0,    0,    0, 1157, 1157, 1157, 1157, 1157, 1157, 1170,
-     1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170,    0,    0,
-        0, 1170,    0,    0,    0,    0,    0, 1170, 1170, 1170,
-     1170, 1170, 1170, 1184, 1184, 1184, 1184, 1184, 1184, 1184,
-     1184, 1184,    0,    0,    0, 1184,    0,    0,    0,    0,
-        0, 1184, 1184, 1184, 1184, 1184, 1184, 1198, 1198, 1198,
-     1198, 1198, 1198, 1198, 1198, 1198,    0,    0,    0, 1198,
-        0,    0,    0,    0,    0, 1198, 1198, 1198, 1198, 1198,
-     1198, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210,
+        0,    0,    0,    0,    0, 1282, 1282, 1282, 1282, 1282,
+     1282, 1294, 1294, 1294, 1294, 1294, 1294, 1294, 1294, 1294,
+        0,    0,    0, 1294,    0,    0,    0,    0,    0, 1294,
+     1294, 1294, 1294, 1294, 1294, 1318, 1318, 1318, 1318, 1318,
+     1318, 1318, 1318, 1318,    0,    0,    0, 1318,    0, 1318,
+        0,    0,    0, 1318, 1318, 1318, 1318, 1318, 1318, 1383,
+     1383, 1383, 1383, 1383, 1383, 1383, 1421, 1421, 1421, 1421,
+     1421, 1421, 1421, 1435, 1540, 1318, 1322, 1322, 1322, 1322,
+     1322, 1322, 1322, 1322, 1322,    0,    0, 1435, 1322,    0,
+        0,    0, 1540,    0, 1322, 1322, 1322, 1322, 1322, 1322,
 
-        0,    0,    0, 1210,    0,    0,    0,    0,    0, 1210,
-     1210, 1210, 1210, 1210, 1210, 1222, 1222, 1222, 1222, 1222,
-     1222, 1222, 1222, 1222,    0,    0,    0, 1222,    0, 1222,
-        0,    0, 1379, 1222, 1222, 1222, 1222, 1222, 1222, 1361,
-     1361, 1361, 1361, 1361, 1361, 1361, 1379, 1384, 1384, 1384,
-     1384, 1384, 1384, 1384,    0, 1222, 1226, 1226, 1226, 1226,
-     1226, 1226, 1226, 1226, 1226,    0,    0,    0, 1226,    0,
-        0,    0, 1379,    0, 1226, 1226, 1226, 1226, 1226, 1226,
-     1229, 1229, 1229, 1229, 1229, 1229, 1229, 1229, 1229,    0,
-        0,    0, 1229,    0,    0,    0,    0,    0, 1229, 1229,
+     1325, 1325, 1325, 1325, 1325, 1325, 1325, 1325, 1325,    0,
+     1540,    0, 1325, 1435,    0,    0,    0,    0, 1325, 1325,
+     1325, 1325, 1325, 1325, 1328, 1328, 1328, 1328, 1328, 1328,
+     1328, 1328, 1328,    0,    0,    0, 1328,    0,    0,    0,
+        0,    0, 1328, 1328, 1328, 1328, 1328, 1328, 1331, 1331,
+     1331, 1331, 1331, 1331, 1331, 1331, 1331,    0,    0,    0,
+     1331,    0,    0,    0,    0,    0, 1331, 1331, 1331, 1331,
+     1331, 1331, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334,
+     1334,    0,    0,    0, 1334,    0,    0,    0,    0,    0,
+     1334, 1334, 1334, 1334, 1334, 1334, 1339, 1339, 1339, 1339,
 
-     1229, 1229, 1229, 1229, 1232, 1232, 1232, 1232, 1232, 1232,
-     1232, 1232, 1232,    0,    0,    0, 1232,    0,    0,    0,
-        0,    0, 1232, 1232, 1232, 1232, 1232, 1232, 1235, 1235,
-     1235, 1235, 1235, 1235, 1235, 1235, 1235,    0,    0,    0,
-     1235,    0,    0,    0,    0,    0, 1235, 1235, 1235, 1235,
-     1235, 1235, 1238, 1238, 1238, 1238, 1238, 1238, 1238, 1238,
-     1238,    0,    0,    0, 1238,    0,    0,    0,    0,    0,
-     1238, 1238, 1238, 1238, 1238, 1238, 1243, 1243, 1243, 1243,
-     1243, 1243, 1243, 1243, 1243,    0,    0,    0, 1243,    0,
-        0,    0,    0,    0, 1243, 1243, 1243, 1243, 1243, 1243,
+     1339, 1339, 1339, 1339, 1339,    0,    0,    0, 1339,    0,
+        0,    0, 1407,    0, 1339, 1339, 1339, 1339, 1339, 1339,
+     1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1405,
+     1407, 1408, 1391,    0, 1436,    0,    0,    0, 1391, 1391,
+     1391, 1391, 1391, 1391, 1407, 1490,    0, 1405, 1436, 1408,
+     1433, 1433, 1433, 1433, 1433, 1433, 1433,    0, 1405,    0,
+        0, 1408, 1444, 1490, 1405, 1412, 1412, 1412, 1412, 1412,
+     1412, 1412, 1412, 1412, 1436, 1490, 1444, 1412,    0,    0,
+        0,    0, 1445, 1412, 1412, 1412, 1412, 1412, 1412, 1442,
+     1442, 1442, 1442, 1442, 1442, 1442, 1445, 1453, 1454,    0,
 
-     1295, 1295, 1295, 1295, 1295, 1295, 1295, 1295, 1295,    0,
-        0,    0, 1295,    0,    0,    0,    0,    0, 1295, 1295,
-     1295, 1295, 1295, 1295, 1303, 1303, 1303, 1303, 1303, 1303,
-     1303, 1303, 1303,    0,    0,    0, 1303,    0,    0,    0,
-        0,    0, 1303, 1303, 1303, 1303, 1303, 1303, 1388, 1388,
-     1388, 1388, 1388, 1388, 1388, 1392, 1392, 1392, 1392, 1392,
-     1392, 1392, 1396, 1396, 1396, 1396, 1396, 1396, 1396, 1400,
-     1400, 1400, 1400, 1400, 1400, 1400, 1405, 1405, 1405, 1405,
-     1405, 1405, 1405, 1407, 1408, 1416, 1416, 1416, 1416, 1416,
-     1416, 1416,    0,    0,    0,    0,    0, 1407, 1408, 1419,
+        0,    0, 1444, 1451, 1451, 1451, 1451, 1451, 1451, 1451,
+     1462, 1453, 1454, 1460, 1460, 1460, 1460, 1460, 1460, 1460,
+     1463,    0, 1445,    0, 1462, 1468, 1468, 1468, 1468, 1468,
+     1468, 1468,    0, 1480, 1463, 1485, 1481, 1453, 1454, 1470,
+     1470, 1470, 1470, 1470, 1470, 1470, 1482, 1483, 1484,    0,
+     1462, 1480, 1487, 1485, 1481, 1500,    0, 1501, 1542, 1547,
+     1463, 1603, 1480, 1481, 1482, 1483, 1484, 1485,    0, 1500,
+     1487, 1501,    0, 1482, 1483, 1484, 1542, 1547,    0, 1603,
+        0, 1487, 1506, 1506, 1506, 1506, 1506, 1506, 1506,    0,
+        0,    0,    0, 1603, 1542, 1500, 1547, 1501, 1510, 1510,
 
-     1419, 1419, 1419, 1419, 1419, 1419, 1423, 1423, 1423, 1423,
-     1423, 1423, 1423, 1427, 1427, 1427, 1427, 1427, 1427, 1427,
-        0,    0,    0, 1407, 1408, 1431, 1431, 1431, 1431, 1431,
-     1431, 1431, 1435, 1435, 1435, 1435, 1435, 1435, 1435, 1438,
-     1438, 1438, 1438, 1438, 1438, 1438, 1443, 1443, 1443, 1443,
-     1443, 1443, 1443, 1452, 1452, 1452, 1452, 1452, 1452, 1452,
-     1464,    0,    0,    0,    0, 1464, 1464, 1464, 1465,    0,
-     1465, 1465, 1465, 1465, 1465, 1465, 1465, 1466,    0, 1466,
-     1467, 1467, 1467, 1468, 1468, 1468, 1469, 1469, 1469, 1470,
-     1470, 1470, 1471, 1471, 1471, 1472, 1472, 1472, 1473, 1473,
+     1510, 1510, 1510, 1510, 1510, 1514, 1514, 1514, 1514, 1514,
+     1514, 1514, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1522,
+     1522, 1522, 1522, 1522, 1522, 1522, 1527, 1527, 1527, 1527,
+     1527, 1527, 1527, 1529, 1530, 1538, 1545, 1549, 1551, 1551,
+     1551, 1551, 1551, 1551, 1551,    0,    0, 1529, 1530,    0,
+        0,    0,    0, 1538, 1545, 1549,    0,    0,    0,    0,
+        0,    0, 1538, 1545, 1549, 1554, 1554, 1554, 1554, 1554,
+     1554, 1554,    0, 1529, 1530, 1558, 1558, 1558, 1558, 1558,
+     1558, 1558, 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1566,
+     1566, 1566, 1566, 1566, 1566, 1566, 1570, 1570, 1570, 1570,
 
-     1473, 1474, 1474, 1474, 1475, 1475, 1475, 1476,    0, 1476,
-     1477, 1477, 1477, 1478, 1478, 1478, 1479, 1479, 1479, 1480,
-     1480, 1480, 1481,    0, 1481, 1482, 1482, 1482, 1483, 1483,
-        0,    0, 1483, 1484, 1484, 1484, 1485, 1485, 1485, 1486,
-     1486, 1486, 1487, 1487, 1487, 1488, 1488, 1488, 1489, 1489,
-     1489, 1490, 1490, 1490, 1491, 1491, 1491, 1492, 1492, 1492,
-     1493, 1493,    0,    0, 1493, 1494, 1494, 1494, 1495, 1495,
-     1495, 1496,    0, 1496, 1497, 1497, 1497, 1498, 1498, 1498,
-     1499,    0, 1499, 1500, 1500, 1500, 1501, 1501, 1501, 1502,
-     1502, 1502, 1503, 1503, 1503, 1504, 1504, 1504, 1505,    0,
+     1570, 1570, 1570, 1573, 1573, 1573, 1573, 1573, 1573, 1573,
+     1577, 1581,    0, 1582, 1583, 1586, 1588, 1584, 1590, 1590,
+     1590, 1590, 1590, 1590, 1590, 1601, 1609,    0, 1577, 1581,
+     1581, 1582, 1583, 1586, 1588, 1584,    0,    0,    0,    0,
+        0,    0, 1586, 1601, 1609, 1577, 1602, 1581, 1604, 1606,
+     1582, 1583, 1584, 1588, 1599, 1599, 1599, 1599, 1599, 1599,
+     1599, 1610, 1601, 1609, 1602, 1611, 1604, 1606, 1621, 1625,
+        0, 1626, 1627, 1602, 1629, 1630, 1637, 1639,    0, 1610,
+     1604, 1606, 1641, 1611,    0,    0, 1621, 1625, 1610, 1626,
+     1627, 1642, 1629, 1630, 1637, 1639, 1639, 1611, 1625,    0,
 
-     1505, 1506,    0, 1506, 1507, 1507, 1507, 1508, 1508, 1508,
-     1509,    0, 1509, 1510, 1510,    0,    0, 1510, 1511, 1511,
-        0,    0, 1511, 1512, 1512, 1512, 1513, 1513, 1513, 1514,
-     1514,    0, 1514, 1515, 1515, 1515, 1516, 1516, 1516, 1517,
-     1517, 1517, 1518, 1518, 1518, 1519, 1519, 1519, 1520, 1520,
-     1520, 1521, 1521, 1521, 1522, 1522,    0,    0, 1522, 1523,
-     1523, 1523, 1524, 1524, 1524, 1525, 1525,    0, 1525, 1526,
-     1526,    0,    0, 1526, 1527, 1527,    0, 1527, 1528, 1528,
-     1529, 1529,    0,    0, 1529, 1530, 1530, 1530, 1531, 1531,
-     1531, 1532, 1532,    0, 1532, 1533,    0, 1533, 1534,    0,
+     1641, 1643, 1626, 1637, 1644, 1621, 1630, 1627,    0, 1642,
+     1646, 1629, 1648, 1639, 1639, 1654, 1641, 1641,    0, 1643,
+     1655,    0, 1644, 1665, 1656, 1658, 1642,    0, 1646,    0,
+     1648, 1659, 1661, 1654,    0, 1662, 1643, 1663, 1655, 1644,
+        0, 1665, 1656, 1658, 1648, 1646, 1656, 1655,    0, 1659,
+     1661, 1666, 1654, 1662, 1658, 1663, 1663, 1667, 1656, 1656,
+     1665, 1670, 1671, 1672, 1673,    0, 1659, 1676, 1661, 1666,
+     1662, 1678, 1680, 1663,    0, 1667, 1681,    0, 1685, 1670,
+     1671, 1672, 1673, 1666,    0, 1676, 1686,    0, 1670, 1678,
+     1680, 1690, 1671,    0, 1681, 1667, 1685, 1673, 1672, 1676,
 
-     1534, 1535, 1535, 1535, 1536, 1536, 1536, 1537,    0, 1537,
-     1538, 1538, 1538, 1539, 1539, 1539, 1540, 1540, 1540, 1541,
-     1541, 1541, 1542, 1542, 1542, 1543, 1543, 1543, 1544,    0,
-     1544, 1545,    0, 1545, 1546, 1546, 1546, 1547, 1547, 1547,
-     1548,    0, 1548, 1549,    0, 1549, 1550,    0, 1550, 1551,
-     1551, 1551, 1552, 1552, 1552, 1553,    0, 1553, 1554,    0,
-        0, 1554, 1555, 1555,    0, 1555, 1556, 1556,    0,    0,
-     1556, 1557, 1557,    0, 1557, 1558, 1558, 1559, 1559,    0,
-        0, 1559, 1560, 1560, 1560, 1561, 1561, 1561, 1562, 1562,
-        0, 1562, 1563, 1563, 1563,    0, 1563, 1563, 1564, 1564,
+     1688,    0, 1678, 1691, 1686, 1680, 1692, 1693,    0, 1690,
+     1685, 1681, 1696, 1695, 1697, 1699,    0,    0, 1688, 1686,
+     1686, 1691, 1702,    0, 1692, 1693, 1690, 1704, 1708, 1688,
+     1696, 1695, 1697, 1699, 1693, 1691, 1705, 1711, 1716,    0,
+     1702, 1696, 1699, 1692, 1695, 1704, 1708, 1715, 1720, 1717,
+     1722,    0, 1697,    0, 1705, 1711, 1716, 1702,    0,    0,
+        0,    0,    0, 1708, 1704, 1715, 1720, 1717, 1722,    0,
+        0,    0, 1705,    0, 1711, 1716, 1717, 1723,    0,    0,
+     1723, 1723,    0, 1715,    0, 1720,    0, 1722,    0,    0,
+        0,    0,    0,    0,    0, 1723, 1729,    0,    0,    0,
 
-     1564, 1565, 1565, 1565, 1566, 1566, 1566, 1567, 1567, 1567,
-     1568, 1568, 1568, 1569, 1569, 1569, 1570, 1570, 1570, 1571,
-     1571, 1571, 1572, 1572,    0,    0, 1572, 1573, 1573, 1573,
-     1574, 1574, 1574, 1575, 1575,    0, 1575, 1576, 1576,    0,
-        0, 1576, 1577, 1577,    0, 1577, 1578, 1578, 1579, 1579,
-        0,    0, 1579, 1580, 1580, 1580, 1581, 1581, 1581, 1582,
-     1582,    0, 1582, 1583,    0,    0, 1583, 1584, 1584,    0,
-     1584, 1585, 1585,    0,    0, 1585, 1586, 1586,    0, 1586,
-     1587, 1587, 1588, 1588,    0,    0, 1588, 1589, 1589, 1589,
-     1590, 1590, 1590, 1591, 1591,    0, 1591, 1592,    0, 1592,
+        0, 1729, 1729, 1729, 1730,    0, 1730, 1730, 1730, 1730,
+     1730, 1730, 1730, 1731,    0, 1731, 1732, 1732, 1732, 1733,
+     1733, 1733, 1734, 1734, 1734, 1735, 1735, 1735, 1736, 1736,
+     1736, 1737, 1737, 1737, 1738, 1738, 1738, 1739, 1739, 1739,
+     1740, 1740, 1740, 1741,    0, 1741, 1742, 1742, 1742, 1743,
+     1743, 1743, 1744, 1744, 1744, 1745, 1745, 1745, 1746,    0,
+     1746, 1747, 1747, 1747, 1748, 1748,    0,    0, 1748, 1749,
+     1749, 1749, 1750, 1750, 1750, 1751, 1751, 1751, 1752, 1752,
+     1752, 1753, 1753, 1753, 1754, 1754, 1754, 1755, 1755, 1755,
+     1756, 1756, 1756, 1757, 1757, 1757, 1758, 1758,    0,    0,
 
-     1593,    0, 1593, 1594,    0, 1594, 1595, 1595, 1595, 1596,
-     1596, 1596, 1597,    0, 1597, 1598, 1598, 1598,    0, 1598,
-     1598, 1599, 1599, 1599, 1600, 1600, 1600, 1601, 1601, 1601,
-     1602, 1602, 1602, 1603, 1603, 1603, 1604, 1604, 1604, 1605,
-     1605, 1605, 1606,    0, 1606, 1607,    0, 1607, 1608, 1608,
-     1608, 1609, 1609, 1609, 1610,    0, 1610, 1611,    0, 1611,
-     1612,    0, 1612, 1613, 1613, 1613, 1614, 1614, 1614, 1615,
-        0, 1615, 1616,    0, 1616, 1617,    0, 1617, 1618,    0,
-     1618, 1619, 1619, 1619, 1620, 1620, 1620, 1621,    0, 1621,
-     1622,    0, 1622, 1623,    0,    0, 1623, 1624, 1624,    0,
+     1758, 1759, 1759, 1759, 1760, 1760, 1760, 1761,    0, 1761,
+     1762, 1762, 1762, 1763, 1763, 1763, 1764,    0, 1764, 1765,
+     1765, 1765, 1766, 1766, 1766, 1767, 1767, 1767, 1768, 1768,
+     1768, 1769, 1769, 1769, 1770,    0, 1770, 1771,    0, 1771,
+     1772, 1772, 1772, 1773, 1773, 1773, 1774,    0, 1774, 1775,
+     1775,    0,    0, 1775, 1776, 1776,    0,    0, 1776, 1777,
+     1777, 1777, 1778, 1778, 1778, 1779, 1779,    0, 1779, 1780,
+     1780, 1780, 1781, 1781, 1781, 1782, 1782, 1782, 1783, 1783,
+     1783, 1784, 1784, 1784, 1785, 1785, 1785, 1786, 1786, 1786,
+     1787, 1787,    0,    0, 1787, 1788, 1788, 1788, 1789, 1789,
 
-     1624, 1625, 1625,    0,    0, 1625, 1626, 1626,    0, 1626,
-     1627, 1627, 1628, 1628,    0,    0, 1628, 1629, 1629, 1629,
-     1630, 1630, 1630, 1631, 1631,    0, 1631, 1632, 1632, 1632,
-        0, 1632, 1632, 1633, 1633, 1633, 1634, 1634, 1634, 1635,
-     1635, 1635, 1636, 1636, 1636, 1637, 1637, 1637, 1638, 1638,
-     1638, 1639, 1639, 1639, 1640, 1640, 1640, 1641, 1641,    0,
-        0, 1641, 1642, 1642, 1642, 1643, 1643, 1643, 1644, 1644,
-        0, 1644, 1645, 1645,    0,    0, 1645, 1646, 1646,    0,
-     1646, 1647, 1647, 1648, 1648,    0,    0, 1648, 1649, 1649,
-     1649, 1650, 1650, 1650, 1651, 1651,    0, 1651, 1652,    0,
+     1789, 1790, 1790,    0, 1790, 1791, 1791,    0,    0, 1791,
+     1792, 1792,    0, 1792, 1793, 1793, 1794, 1794,    0,    0,
+     1794, 1795, 1795, 1795, 1796, 1796, 1796, 1797, 1797,    0,
+     1797, 1798,    0, 1798, 1799,    0, 1799, 1800, 1800, 1800,
+     1801, 1801, 1801, 1802,    0, 1802, 1803, 1803, 1803, 1804,
+     1804, 1804, 1805, 1805, 1805, 1806, 1806, 1806, 1807, 1807,
+     1807, 1808, 1808, 1808, 1809,    0, 1809, 1810,    0, 1810,
+     1811, 1811, 1811, 1812, 1812, 1812, 1813,    0, 1813, 1814,
+        0, 1814, 1815,    0, 1815, 1816, 1816, 1816, 1817, 1817,
+     1817, 1818,    0, 1818, 1819,    0,    0, 1819, 1820, 1820,
 
-        0, 1652, 1653, 1653,    0, 1653, 1654, 1654,    0,    0,
-     1654, 1655, 1655,    0, 1655, 1656, 1656, 1657, 1657,    0,
-        0, 1657, 1658, 1658, 1658, 1659, 1659, 1659, 1660, 1660,
-        0, 1660, 1661,    0, 1661, 1662,    0,    0, 1662, 1663,
-     1663,    0, 1663, 1664, 1664,    0,    0, 1664, 1665, 1665,
-        0, 1665, 1666, 1666, 1667, 1667,    0,    0, 1667, 1668,
-     1668, 1668, 1669, 1669, 1669, 1670, 1670,    0, 1670, 1671,
-        0, 1671, 1672,    0, 1672, 1673,    0, 1673, 1674, 1674,
-     1674, 1675, 1675, 1675, 1676,    0, 1676, 1677, 1677, 1677,
-        0, 1677, 1677, 1678, 1678, 1678, 1679, 1679, 1679, 1680,
+        0, 1820, 1821, 1821,    0,    0, 1821, 1822, 1822,    0,
+     1822, 1823, 1823, 1824, 1824,    0,    0, 1824, 1825, 1825,
+     1825, 1826, 1826, 1826, 1827, 1827,    0, 1827, 1828, 1828,
+     1828,    0, 1828, 1828, 1829, 1829, 1829, 1830, 1830, 1830,
+     1831, 1831, 1831, 1832, 1832, 1832, 1833, 1833, 1833, 1834,
+     1834, 1834, 1835, 1835, 1835, 1836, 1836, 1836, 1837, 1837,
+        0,    0, 1837, 1838, 1838, 1838, 1839, 1839, 1839, 1840,
+     1840,    0, 1840, 1841, 1841,    0,    0, 1841, 1842, 1842,
+        0, 1842, 1843, 1843, 1844, 1844,    0,    0, 1844, 1845,
+     1845, 1845, 1846, 1846, 1846, 1847, 1847,    0, 1847, 1848,
 
-     1680, 1680, 1681, 1681, 1681, 1682, 1682, 1682, 1683, 1683,
-     1683, 1684, 1684, 1684, 1685, 1685, 1685, 1686, 1686, 1686,
-     1687, 1687, 1687, 1688,    0, 1688, 1689,    0, 1689, 1690,
-     1690, 1690, 1691, 1691, 1691, 1692, 1692, 1692, 1693,    0,
-     1693, 1694,    0, 1694, 1695,    0, 1695, 1696, 1696, 1696,
-     1697, 1697, 1697, 1698, 1698, 1698, 1699,    0, 1699, 1700,
-        0, 1700, 1701,    0, 1701, 1702,    0, 1702, 1703, 1703,
-     1703, 1704, 1704, 1704, 1705, 1705, 1705, 1706,    0, 1706,
-     1707,    0, 1707, 1708,    0, 1708, 1709,    0, 1709, 1710,
-     1710, 1710, 1711, 1711, 1711, 1712, 1712, 1712, 1713,    0,
+        0,    0, 1848, 1849, 1849,    0, 1849, 1850, 1850,    0,
+        0, 1850, 1851, 1851,    0, 1851, 1852, 1852, 1853, 1853,
+        0,    0, 1853, 1854, 1854, 1854, 1855, 1855, 1855, 1856,
+     1856,    0, 1856, 1857,    0, 1857, 1858,    0, 1858, 1859,
+        0, 1859, 1860, 1860, 1860, 1861, 1861, 1861, 1862,    0,
+     1862, 1863, 1863, 1863,    0, 1863, 1863, 1864, 1864, 1864,
+     1865, 1865, 1865, 1866, 1866, 1866, 1867, 1867, 1867, 1868,
+     1868, 1868, 1869, 1869, 1869, 1870, 1870, 1870, 1871,    0,
+     1871, 1872,    0, 1872, 1873, 1873, 1873, 1874, 1874, 1874,
+     1875,    0, 1875, 1876,    0, 1876, 1877,    0, 1877, 1878,
 
-     1713, 1714,    0, 1714, 1715,    0,    0, 1715, 1716, 1716,
-        0, 1716, 1717, 1717,    0,    0, 1717, 1718, 1718,    0,
-     1718, 1719, 1719, 1720, 1720,    0,    0, 1720, 1721, 1721,
-     1721, 1722, 1722, 1722, 1723, 1723,    0, 1723, 1724, 1724,
-     1724,    0, 1724, 1724, 1725, 1725, 1725, 1726, 1726, 1726,
-     1727, 1727, 1727, 1728, 1728, 1728, 1729, 1729, 1729, 1730,
-     1730, 1730, 1731, 1731, 1731, 1732, 1732, 1732, 1733,    0,
-     1733, 1734, 1734, 1734, 1735, 1735,    0,    0, 1735, 1736,
-     1736, 1736, 1737, 1737, 1737, 1738, 1738,    0, 1738, 1739,
-     1739,    0,    0, 1739, 1740, 1740,    0, 1740, 1741, 1741,
+     1878, 1878, 1879, 1879, 1879, 1880,    0, 1880, 1881,    0,
+     1881, 1882,    0, 1882, 1883,    0, 1883, 1884, 1884, 1884,
+     1885, 1885, 1885, 1886,    0, 1886, 1887,    0, 1887, 1888,
+        0,    0, 1888, 1889, 1889,    0, 1889, 1890, 1890,    0,
+        0, 1890, 1891, 1891,    0, 1891, 1892, 1892, 1893, 1893,
+        0,    0, 1893, 1894, 1894, 1894, 1895, 1895, 1895, 1896,
+     1896,    0, 1896, 1897, 1897, 1897,    0, 1897, 1897, 1898,
+     1898, 1898, 1899, 1899, 1899, 1900, 1900, 1900, 1901, 1901,
+     1901, 1902, 1902, 1902, 1903, 1903, 1903, 1904, 1904, 1904,
+     1905, 1905, 1905, 1906, 1906,    0,    0, 1906, 1907, 1907,
 
-     1742, 1742,    0,    0, 1742, 1743, 1743, 1743, 1744, 1744,
-     1744, 1745, 1745,    0, 1745, 1746,    0,    0, 1746, 1747,
-     1747,    0, 1747, 1748, 1748,    0,    0, 1748, 1749, 1749,
-        0, 1749, 1750, 1750, 1751, 1751,    0,    0, 1751, 1752,
-     1752, 1752, 1753, 1753, 1753, 1754, 1754,    0, 1754, 1755,
-        0, 1755, 1756,    0,    0, 1756, 1757, 1757,    0, 1757,
-     1758, 1758,    0,    0, 1758, 1759, 1759,    0, 1759, 1760,
-     1760, 1761, 1761,    0,    0, 1761, 1762, 1762, 1762, 1763,
-     1763, 1763, 1764, 1764,    0, 1764, 1765,    0, 1765, 1766,
-        0,    0, 1766, 1767, 1767,    0, 1767, 1768, 1768,    0,
+     1907, 1908, 1908, 1908, 1909, 1909,    0, 1909, 1910, 1910,
+        0,    0, 1910, 1911, 1911,    0, 1911, 1912, 1912, 1913,
+     1913,    0,    0, 1913, 1914, 1914, 1914, 1915, 1915, 1915,
+     1916, 1916,    0, 1916, 1917,    0,    0, 1917, 1918, 1918,
+        0, 1918, 1919, 1919,    0,    0, 1919, 1920, 1920,    0,
+     1920, 1921, 1921, 1922, 1922,    0,    0, 1922, 1923, 1923,
+     1923, 1924, 1924, 1924, 1925, 1925,    0, 1925, 1926,    0,
+     1926, 1927,    0,    0, 1927, 1928, 1928,    0, 1928, 1929,
+     1929,    0,    0, 1929, 1930, 1930,    0, 1930, 1931, 1931,
+     1932, 1932,    0,    0, 1932, 1933, 1933, 1933, 1934, 1934,
 
-        0, 1768, 1769, 1769,    0, 1769, 1770, 1770, 1771, 1771,
-        0,    0, 1771, 1772, 1772, 1772, 1773, 1773, 1773, 1774,
-     1774,    0, 1774, 1775,    0, 1775, 1776,    0, 1776, 1777,
-        0, 1777, 1778, 1778, 1778, 1779,    0, 1779, 1780, 1780,
-     1780, 1781,    0, 1781, 1782, 1782, 1782,    0, 1782, 1782,
-     1783,    0, 1783, 1784, 1784, 1784, 1785,    0, 1785, 1786,
-     1786, 1786, 1787,    0, 1787, 1788, 1788, 1788, 1789,    0,
-     1789, 1790, 1790, 1790, 1791,    0, 1791, 1792, 1792, 1792,
-     1793,    0, 1793, 1794, 1794, 1794, 1795, 1795,    0,    0,
-     1795, 1796, 1796, 1796, 1797, 1797, 1797, 1798, 1798, 1798,
+     1934, 1935, 1935,    0, 1935, 1936,    0, 1936, 1937,    0,
+     1937, 1938,    0, 1938, 1939, 1939, 1939, 1940, 1940, 1940,
+     1941,    0, 1941, 1942, 1942, 1942,    0, 1942, 1942, 1943,
+     1943, 1943, 1944, 1944, 1944, 1945, 1945, 1945, 1946, 1946,
+     1946, 1947, 1947, 1947, 1948, 1948, 1948, 1949, 1949, 1949,
+     1950, 1950, 1950, 1951, 1951, 1951, 1952, 1952, 1952, 1953,
+        0, 1953, 1954,    0, 1954, 1955, 1955, 1955, 1956, 1956,
+     1956, 1957, 1957, 1957, 1958,    0, 1958, 1959,    0, 1959,
+     1960,    0, 1960, 1961, 1961, 1961, 1962, 1962, 1962, 1963,
+     1963, 1963, 1964,    0, 1964, 1965,    0, 1965, 1966,    0,
 
-     1799, 1799,    0, 1799, 1800, 1800, 1800, 1801,    0, 1801,
-     1802, 1802, 1802, 1803, 1803, 1803, 1804,    0, 1804, 1805,
-        0, 1805, 1806, 1806, 1806, 1807, 1807, 1807, 1808,    0,
-     1808, 1809,    0, 1809, 1810,    0, 1810, 1811, 1811, 1811,
-     1812, 1812, 1812, 1813,    0, 1813, 1814,    0, 1814, 1815,
-        0, 1815, 1816, 1816, 1816, 1817, 1817, 1817, 1818,    0,
-     1818, 1819,    0, 1819, 1820,    0, 1820, 1821, 1821, 1821,
-     1822, 1822, 1822, 1823,    0, 1823, 1824,    0,    0, 1824,
-     1825, 1825,    0, 1825, 1826, 1826,    0,    0, 1826, 1827,
-     1827,    0, 1827, 1828, 1828, 1829, 1829,    0,    0, 1829,
+     1966, 1967,    0, 1967, 1968, 1968, 1968, 1969, 1969, 1969,
+     1970, 1970, 1970, 1971,    0, 1971, 1972,    0, 1972, 1973,
+        0, 1973, 1974,    0, 1974, 1975, 1975, 1975, 1976, 1976,
+     1976, 1977, 1977, 1977, 1978,    0, 1978, 1979,    0, 1979,
+     1980,    0,    0, 1980, 1981, 1981,    0, 1981, 1982, 1982,
+        0,    0, 1982, 1983, 1983,    0, 1983, 1984, 1984, 1985,
+     1985,    0,    0, 1985, 1986, 1986, 1986, 1987, 1987, 1987,
+     1988, 1988,    0, 1988, 1989, 1989, 1989,    0, 1989, 1989,
+     1990, 1990, 1990, 1991, 1991, 1991, 1992, 1992, 1992, 1993,
+     1993, 1993, 1994, 1994, 1994, 1995, 1995, 1995, 1996, 1996,
 
-     1830, 1830, 1830, 1831,    0, 1831, 1832, 1832,    0, 1832,
-     1833, 1833, 1833,    0, 1833, 1833, 1834, 1834, 1834, 1835,
-     1835, 1835, 1836,    0, 1836, 1837,    0, 1837, 1838,    0,
-     1838, 1839,    0, 1839, 1840,    0, 1840, 1841,    0, 1841,
-     1842,    0, 1842, 1843, 1843, 1843, 1844, 1844, 1844, 1845,
-        0, 1845, 1846, 1846,    0,    0, 1846, 1847, 1847,    0,
-     1847, 1848, 1848, 1849,    0, 1849, 1850,    0,    0, 1850,
-     1851, 1851,    0, 1851, 1852, 1852,    0,    0, 1852, 1853,
-     1853,    0, 1853, 1854, 1854, 1855,    0, 1855, 1856,    0,
-     1856, 1857,    0,    0, 1857, 1858, 1858,    0, 1858, 1859,
+     1996, 1997, 1997, 1997, 1998,    0, 1998, 1999, 1999, 1999,
+     2000, 2000,    0,    0, 2000, 2001, 2001, 2001, 2002, 2002,
+     2002, 2003, 2003,    0, 2003, 2004, 2004,    0,    0, 2004,
+     2005, 2005,    0, 2005, 2006, 2006, 2007, 2007,    0,    0,
+     2007, 2008, 2008, 2008, 2009, 2009, 2009, 2010, 2010,    0,
+     2010, 2011,    0,    0, 2011, 2012, 2012,    0, 2012, 2013,
+     2013,    0,    0, 2013, 2014, 2014,    0, 2014, 2015, 2015,
+     2016, 2016,    0,    0, 2016, 2017, 2017, 2017, 2018, 2018,
+     2018, 2019, 2019,    0, 2019, 2020,    0, 2020, 2021,    0,
+        0, 2021, 2022, 2022,    0, 2022, 2023, 2023,    0,    0,
 
-     1859,    0,    0, 1859, 1860, 1860,    0, 1860, 1861, 1861,
-     1862,    0, 1862, 1863,    0, 1863, 1864,    0,    0, 1864,
-     1865, 1865,    0, 1865, 1866, 1866,    0,    0, 1866, 1867,
-     1867,    0, 1867, 1868, 1868, 1869,    0, 1869, 1870,    0,
-     1870, 1871,    0,    0, 1871, 1872, 1872,    0, 1872, 1873,
-     1873,    0,    0, 1873, 1874, 1874,    0, 1874, 1875, 1875,
-     1876,    0, 1876, 1877,    0, 1877, 1878,    0, 1878, 1879,
-        0, 1879, 1880, 1880, 1880, 1881,    0, 1881, 1882, 1882,
-     1882,    0, 1882, 1882, 1883,    0, 1883, 1884,    0, 1884,
-     1885,    0, 1885, 1886,    0, 1886, 1887,    0, 1887, 1888,
+     2023, 2024, 2024,    0, 2024, 2025, 2025, 2026, 2026,    0,
+        0, 2026, 2027, 2027, 2027, 2028, 2028, 2028, 2029, 2029,
+        0, 2029, 2030,    0, 2030, 2031,    0,    0, 2031, 2032,
+     2032,    0, 2032, 2033, 2033,    0,    0, 2033, 2034, 2034,
+        0, 2034, 2035, 2035, 2036, 2036,    0,    0, 2036, 2037,
+     2037, 2037, 2038, 2038, 2038, 2039, 2039,    0, 2039, 2040,
+        0, 2040, 2041,    0, 2041, 2042,    0, 2042, 2043, 2043,
+     2043, 2044,    0, 2044, 2045, 2045, 2045, 2046,    0, 2046,
+     2047, 2047, 2047,    0, 2047, 2047, 2048,    0, 2048, 2049,
+     2049, 2049, 2050,    0, 2050, 2051, 2051, 2051, 2052,    0,
 
-        0, 1888, 1889,    0, 1889, 1890, 1890,    0,    0, 1890,
-     1891, 1891,    0, 1891, 1892, 1892, 1893,    0, 1893, 1894,
-        0, 1894, 1895,    0, 1895, 1896,    0, 1896, 1897,    0,
-     1897, 1898,    0, 1898, 1899,    0, 1899, 1900,    0, 1900,
-     1901,    0, 1901, 1902,    0, 1902, 1903,    0,    0, 1903,
-     1904, 1904,    0,    0, 1904, 1905,    0, 1905, 1906,    0,
-     1906, 1907,    0, 1907, 1908,    0,    0, 1908, 1909,    0,
-        0, 1909, 1910,    0,    0, 1910, 1911,    0,    0, 1911,
-     1912,    0,    0, 1912, 1913,    0, 1913, 1914,    0, 1914,
-     1915,    0,    0, 1915, 1916,    0, 1916, 1917,    0, 1917,
+     2052, 2053, 2053, 2053, 2054,    0, 2054, 2055, 2055, 2055,
+     2056,    0, 2056, 2057, 2057, 2057, 2058,    0, 2058, 2059,
+     2059, 2059, 2060, 2060,    0,    0, 2060, 2061, 2061, 2061,
+     2062, 2062, 2062, 2063, 2063, 2063, 2064, 2064,    0, 2064,
+     2065, 2065, 2065, 2066,    0, 2066, 2067, 2067, 2067, 2068,
+     2068, 2068, 2069,    0, 2069, 2070,    0, 2070, 2071, 2071,
+     2071, 2072, 2072, 2072, 2073,    0, 2073, 2074,    0, 2074,
+     2075,    0, 2075, 2076, 2076, 2076, 2077, 2077, 2077, 2078,
+        0, 2078, 2079,    0, 2079, 2080,    0, 2080, 2081, 2081,
+     2081, 2082, 2082, 2082, 2083,    0, 2083, 2084,    0, 2084,
 
-     1918,    0, 1918, 1919,    0, 1919, 1920,    0, 1920, 1921,
-        0,    0, 1921, 1922,    0, 1922, 1923,    0, 1923, 1463,
-     1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463,
-     1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463,
-     1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463,
-     1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463,
-     1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463, 1463,
-     1463, 1463, 1463
+     2085,    0, 2085, 2086, 2086, 2086, 2087, 2087, 2087, 2088,
+        0, 2088, 2089,    0,    0, 2089, 2090, 2090,    0, 2090,
+     2091, 2091,    0,    0, 2091, 2092, 2092,    0, 2092, 2093,
+     2093, 2094, 2094,    0,    0, 2094, 2095, 2095, 2095, 2096,
+        0, 2096, 2097, 2097,    0, 2097, 2098, 2098, 2098,    0,
+     2098, 2098, 2099, 2099, 2099, 2100, 2100, 2100, 2101,    0,
+     2101, 2102,    0, 2102, 2103,    0, 2103, 2104,    0, 2104,
+     2105,    0, 2105, 2106,    0, 2106, 2107,    0, 2107, 2108,
+     2108, 2108, 2109, 2109, 2109, 2110,    0, 2110, 2111, 2111,
+        0,    0, 2111, 2112, 2112,    0, 2112, 2113, 2113, 2114,
+
+        0, 2114, 2115,    0,    0, 2115, 2116, 2116,    0, 2116,
+     2117, 2117,    0,    0, 2117, 2118, 2118,    0, 2118, 2119,
+     2119, 2120,    0, 2120, 2121,    0, 2121, 2122,    0,    0,
+     2122, 2123, 2123,    0, 2123, 2124, 2124,    0,    0, 2124,
+     2125, 2125,    0, 2125, 2126, 2126, 2127,    0, 2127, 2128,
+        0, 2128, 2129,    0,    0, 2129, 2130, 2130,    0, 2130,
+     2131, 2131,    0,    0, 2131, 2132, 2132,    0, 2132, 2133,
+     2133, 2134,    0, 2134, 2135,    0, 2135, 2136,    0,    0,
+     2136, 2137, 2137,    0, 2137, 2138, 2138,    0,    0, 2138,
+     2139, 2139,    0, 2139, 2140, 2140, 2141,    0, 2141, 2142,
+
+        0, 2142, 2143,    0, 2143, 2144,    0, 2144, 2145, 2145,
+     2145, 2146,    0, 2146, 2147, 2147, 2147,    0, 2147, 2147,
+     2148,    0, 2148, 2149,    0, 2149, 2150,    0, 2150, 2151,
+        0, 2151, 2152,    0, 2152, 2153,    0, 2153, 2154,    0,
+     2154, 2155, 2155,    0,    0, 2155, 2156, 2156,    0, 2156,
+     2157, 2157, 2158,    0, 2158, 2159,    0, 2159, 2160,    0,
+     2160, 2161,    0, 2161, 2162,    0, 2162, 2163,    0, 2163,
+     2164,    0, 2164, 2165,    0, 2165, 2166,    0, 2166, 2167,
+        0, 2167, 2168,    0,    0, 2168, 2169, 2169,    0,    0,
+     2169, 2170,    0, 2170, 2171,    0, 2171, 2172,    0, 2172,
+
+     2173,    0,    0, 2173, 2174,    0,    0, 2174, 2175,    0,
+        0, 2175, 2176,    0,    0, 2176, 2177,    0,    0, 2177,
+     2178,    0, 2178, 2179,    0, 2179, 2180,    0,    0, 2180,
+     2181,    0, 2181, 2182,    0, 2182, 2183,    0, 2183, 2184,
+        0, 2184, 2185,    0, 2185, 2186,    0,    0, 2186, 2187,
+        0, 2187, 2188,    0, 2188, 1728, 1728, 1728, 1728, 1728,
+     1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728,
+     1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728,
+     1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728,
+     1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728,
+
+     1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728
     } ;
 
 /* The intent behind this definition is that it'll catch
@@ -2698,7 +2886,7 @@
  * We want to generate code that can be used by a reentrant parser
  * generated by Bison or Berkeley YACC.
  */
-#line 45 "scanner.l"
+#line 67 "scanner.l"
 /*
  * Copyright (c) 1988, 1989, 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1997
  *	The Regents of the University of California.  All rights reserved.
@@ -2720,20 +2908,6 @@
  * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
  */
 
-#ifdef _WIN32
-  #include <pcap-stdinc.h>
-#else
-  #if HAVE_INTTYPES_H
-    #include <inttypes.h>
-  #elif HAVE_STDINT_H
-    #include <stdint.h>
-  #endif
-  #ifdef HAVE_SYS_BITYPES_H
-    #include <sys/bitypes.h>
-  #endif
-  #include <sys/types.h>
-#endif
-
 #include <ctype.h>
 #include <string.h>
 
@@ -2753,6 +2927,8 @@
 #ifdef INET6
 
 #ifdef _WIN32
+#include <winsock2.h>
+#include <ws2tcpip.h>
 /*
  * To quote the MSDN page for getaddrinfo() at
  *
@@ -2772,10 +2948,9 @@
  * Wspiapi.h header file. This inline code will be used on older Windows
  * platforms that do not natively support the getaddrinfo function."
  *
- * We use getaddrinfo(), so we include Wspiapi.h here.  pcap-stdinc.h
- * includes Ws2tcpip.h, so we don't need to include it ourselves.
+ * We use getaddrinfo(), so we include Wspiapi.h here.
  */
-#include <Wspiapi.h>
+#include <wspiapi.h>
 #else /* _WIN32 */
 #include <sys/socket.h>	/* for "struct sockaddr" in "struct addrinfo" */
 #include <netdb.h>	/* for "struct addrinfo" */
@@ -2798,7 +2973,12 @@
 static int stoi(char *);
 static inline int xdtoi(int);
 
-#line 2802 "scanner.c"
+/*
+ * Disable diagnostics in the code generated by Flex.
+ */
+DIAG_OFF_FLEX
+
+#line 2982 "scanner.c"
 
 #define INITIAL 0
 
@@ -2825,8 +3005,8 @@
     size_t yy_buffer_stack_max; /**< capacity of stack. */
     YY_BUFFER_STATE * yy_buffer_stack; /**< Stack as an array. */
     char yy_hold_char;
-    yy_size_t yy_n_chars;
-    yy_size_t yyleng_r;
+    int yy_n_chars;
+    int yyleng_r;
     char *yy_c_buf_p;
     int yy_init;
     int yy_start;
@@ -2873,23 +3053,23 @@
 
 FILE *pcap_get_in (yyscan_t yyscanner );
 
-void pcap_set_in  (FILE * in_str ,yyscan_t yyscanner );
+void pcap_set_in  (FILE * _in_str ,yyscan_t yyscanner );
 
 FILE *pcap_get_out (yyscan_t yyscanner );
 
-void pcap_set_out  (FILE * out_str ,yyscan_t yyscanner );
+void pcap_set_out  (FILE * _out_str ,yyscan_t yyscanner );
 
-yy_size_t pcap_get_leng (yyscan_t yyscanner );
+			int pcap_get_leng (yyscan_t yyscanner );
 
 char *pcap_get_text (yyscan_t yyscanner );
 
 int pcap_get_lineno (yyscan_t yyscanner );
 
-void pcap_set_lineno (int line_number ,yyscan_t yyscanner );
+void pcap_set_lineno (int _line_number ,yyscan_t yyscanner );
 
 int pcap_get_column  (yyscan_t yyscanner );
 
-void pcap_set_column (int column_no ,yyscan_t yyscanner );
+void pcap_set_column (int _column_no ,yyscan_t yyscanner );
 
 YYSTYPE * pcap_get_lval (yyscan_t yyscanner );
 
@@ -2907,6 +3087,10 @@
 #endif
 #endif
 
+#ifndef YY_NO_UNPUT
+    
+#endif
+
 #ifndef yytext_ptr
 static void yy_flex_strncpy (char *,yyconst char *,int ,yyscan_t yyscanner);
 #endif
@@ -2940,7 +3124,7 @@
 /* This used to be an fputs(), but since the string might contain NUL's,
  * we now use fwrite().
  */
-#define ECHO do { if (fwrite( yytext, yyleng, 1, yyout )) {} } while (0)
+#define ECHO do { if (fwrite( yytext, (size_t) yyleng, 1, yyout )) {} } while (0)
 #endif
 
 /* Gets input and stuffs it into "buf".  number of characters read, or YY_NULL,
@@ -2964,7 +3148,7 @@
 	else \
 		{ \
 		errno=0; \
-		while ( (result = fread(buf, 1, max_size, yyin))==0 && ferror(yyin)) \
+		while ( (result = (int) fread(buf, 1, max_size, yyin))==0 && ferror(yyin)) \
 			{ \
 			if( errno != EINTR) \
 				{ \
@@ -3021,7 +3205,7 @@
 
 /* Code executed at the end of each rule. */
 #ifndef YY_BREAK
-#define YY_BREAK break;
+#define YY_BREAK /*LINTED*/break;
 #endif
 
 #define YY_RULE_SETUP \
@@ -3031,9 +3215,9 @@
  */
 YY_DECL
 {
-	register yy_state_type yy_current_state;
-	register char *yy_cp, *yy_bp;
-	register int yy_act;
+	yy_state_type yy_current_state;
+	char *yy_cp, *yy_bp;
+	int yy_act;
     struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
 
     yylval = yylval_param;
@@ -3065,11 +3249,11 @@
 		}
 
 	{
-#line 240 "scanner.l"
+#line 254 "scanner.l"
 
-#line 3071 "scanner.c"
+#line 3255 "scanner.c"
 
-	while ( 1 )		/* loops until end-of-file is reached */
+	while ( /*CONSTCOND*/1 )		/* loops until end-of-file is reached */
 		{
 		yy_cp = yyg->yy_c_buf_p;
 
@@ -3085,7 +3269,7 @@
 yy_match:
 		do
 			{
-			register YY_CHAR yy_c = yy_ec[YY_SC_TO_UI(*yy_cp)] ;
+			YY_CHAR yy_c = yy_ec[YY_SC_TO_UI(*yy_cp)] ;
 			if ( yy_accept[yy_current_state] )
 				{
 				yyg->yy_last_accepting_state = yy_current_state;
@@ -3094,13 +3278,13 @@
 			while ( yy_chk[yy_base[yy_current_state] + yy_c] != yy_current_state )
 				{
 				yy_current_state = (int) yy_def[yy_current_state];
-				if ( yy_current_state >= 1464 )
+				if ( yy_current_state >= 1729 )
 					yy_c = yy_meta[(unsigned int) yy_c];
 				}
-			yy_current_state = yy_nxt[yy_base[yy_current_state] + (unsigned int) yy_c];
+			yy_current_state = yy_nxt[yy_base[yy_current_state] + (flex_int16_t) yy_c];
 			++yy_cp;
 			}
-		while ( yy_current_state != 1463 );
+		while ( yy_current_state != 1728 );
 		yy_cp = yyg->yy_last_accepting_cpos;
 		yy_current_state = yyg->yy_last_accepting_state;
 
@@ -3122,257 +3306,257 @@
 
 case 1:
 YY_RULE_SETUP
-#line 241 "scanner.l"
+#line 255 "scanner.l"
 return DST;
 	YY_BREAK
 case 2:
 YY_RULE_SETUP
-#line 242 "scanner.l"
+#line 256 "scanner.l"
 return SRC;
 	YY_BREAK
 case 3:
 YY_RULE_SETUP
-#line 244 "scanner.l"
+#line 258 "scanner.l"
 return LINK;
 	YY_BREAK
 case 4:
 YY_RULE_SETUP
-#line 245 "scanner.l"
+#line 259 "scanner.l"
 return LINK;
 	YY_BREAK
 case 5:
 YY_RULE_SETUP
-#line 246 "scanner.l"
+#line 260 "scanner.l"
 return ARP;
 	YY_BREAK
 case 6:
 YY_RULE_SETUP
-#line 247 "scanner.l"
+#line 261 "scanner.l"
 return RARP;
 	YY_BREAK
 case 7:
 YY_RULE_SETUP
-#line 248 "scanner.l"
+#line 262 "scanner.l"
 return IP;
 	YY_BREAK
 case 8:
 YY_RULE_SETUP
-#line 249 "scanner.l"
+#line 263 "scanner.l"
 return SCTP;
 	YY_BREAK
 case 9:
 YY_RULE_SETUP
-#line 250 "scanner.l"
+#line 264 "scanner.l"
 return TCP;
 	YY_BREAK
 case 10:
 YY_RULE_SETUP
-#line 251 "scanner.l"
+#line 265 "scanner.l"
 return UDP;
 	YY_BREAK
 case 11:
 YY_RULE_SETUP
-#line 252 "scanner.l"
+#line 266 "scanner.l"
 return ICMP;
 	YY_BREAK
 case 12:
 YY_RULE_SETUP
-#line 253 "scanner.l"
+#line 267 "scanner.l"
 return IGMP;
 	YY_BREAK
 case 13:
 YY_RULE_SETUP
-#line 254 "scanner.l"
+#line 268 "scanner.l"
 return IGRP;
 	YY_BREAK
 case 14:
 YY_RULE_SETUP
-#line 255 "scanner.l"
+#line 269 "scanner.l"
 return PIM;
 	YY_BREAK
 case 15:
 YY_RULE_SETUP
-#line 256 "scanner.l"
+#line 270 "scanner.l"
 return VRRP;
 	YY_BREAK
 case 16:
 YY_RULE_SETUP
-#line 257 "scanner.l"
+#line 271 "scanner.l"
 return CARP;
 	YY_BREAK
 case 17:
 YY_RULE_SETUP
-#line 258 "scanner.l"
+#line 272 "scanner.l"
 return RADIO;
 	YY_BREAK
 case 18:
 YY_RULE_SETUP
-#line 260 "scanner.l"
+#line 274 "scanner.l"
 return IPV6;
 	YY_BREAK
 case 19:
 YY_RULE_SETUP
-#line 261 "scanner.l"
+#line 275 "scanner.l"
 return ICMPV6;
 	YY_BREAK
 case 20:
 YY_RULE_SETUP
-#line 262 "scanner.l"
+#line 276 "scanner.l"
 return AH;
 	YY_BREAK
 case 21:
 YY_RULE_SETUP
-#line 263 "scanner.l"
+#line 277 "scanner.l"
 return ESP;
 	YY_BREAK
 case 22:
 YY_RULE_SETUP
-#line 265 "scanner.l"
+#line 279 "scanner.l"
 return ATALK;
 	YY_BREAK
 case 23:
 YY_RULE_SETUP
-#line 266 "scanner.l"
+#line 280 "scanner.l"
 return AARP;
 	YY_BREAK
 case 24:
 YY_RULE_SETUP
-#line 267 "scanner.l"
+#line 281 "scanner.l"
 return DECNET;
 	YY_BREAK
 case 25:
 YY_RULE_SETUP
-#line 268 "scanner.l"
+#line 282 "scanner.l"
 return LAT;
 	YY_BREAK
 case 26:
 YY_RULE_SETUP
-#line 269 "scanner.l"
+#line 283 "scanner.l"
 return SCA;
 	YY_BREAK
 case 27:
 YY_RULE_SETUP
-#line 270 "scanner.l"
+#line 284 "scanner.l"
 return MOPRC;
 	YY_BREAK
 case 28:
 YY_RULE_SETUP
-#line 271 "scanner.l"
+#line 285 "scanner.l"
 return MOPDL;
 	YY_BREAK
 case 29:
 YY_RULE_SETUP
-#line 273 "scanner.l"
+#line 287 "scanner.l"
 return ISO;
 	YY_BREAK
 case 30:
 YY_RULE_SETUP
-#line 274 "scanner.l"
+#line 288 "scanner.l"
 return ESIS;
 	YY_BREAK
 case 31:
 YY_RULE_SETUP
-#line 275 "scanner.l"
+#line 289 "scanner.l"
 return ESIS;
 	YY_BREAK
 case 32:
 YY_RULE_SETUP
-#line 276 "scanner.l"
+#line 290 "scanner.l"
 return ISIS;
 	YY_BREAK
 case 33:
 YY_RULE_SETUP
-#line 277 "scanner.l"
+#line 291 "scanner.l"
 return ISIS;
 	YY_BREAK
 case 34:
 YY_RULE_SETUP
-#line 278 "scanner.l"
+#line 292 "scanner.l"
 return L1;
 	YY_BREAK
 case 35:
 YY_RULE_SETUP
-#line 279 "scanner.l"
+#line 293 "scanner.l"
 return L2;
 	YY_BREAK
 case 36:
 YY_RULE_SETUP
-#line 280 "scanner.l"
+#line 294 "scanner.l"
 return IIH;
 	YY_BREAK
 case 37:
 YY_RULE_SETUP
-#line 281 "scanner.l"
+#line 295 "scanner.l"
 return LSP;
 	YY_BREAK
 case 38:
 YY_RULE_SETUP
-#line 282 "scanner.l"
+#line 296 "scanner.l"
 return SNP;
 	YY_BREAK
 case 39:
 YY_RULE_SETUP
-#line 283 "scanner.l"
+#line 297 "scanner.l"
 return CSNP;
 	YY_BREAK
 case 40:
 YY_RULE_SETUP
-#line 284 "scanner.l"
+#line 298 "scanner.l"
 return PSNP;
 	YY_BREAK
 case 41:
 YY_RULE_SETUP
-#line 286 "scanner.l"
+#line 300 "scanner.l"
 return CLNP;
 	YY_BREAK
 case 42:
 YY_RULE_SETUP
-#line 288 "scanner.l"
+#line 302 "scanner.l"
 return STP;
 	YY_BREAK
 case 43:
 YY_RULE_SETUP
-#line 290 "scanner.l"
+#line 304 "scanner.l"
 return IPX;
 	YY_BREAK
 case 44:
 YY_RULE_SETUP
-#line 292 "scanner.l"
+#line 306 "scanner.l"
 return NETBEUI;
 	YY_BREAK
 case 45:
 YY_RULE_SETUP
-#line 294 "scanner.l"
+#line 308 "scanner.l"
 return HOST;
 	YY_BREAK
 case 46:
 YY_RULE_SETUP
-#line 295 "scanner.l"
+#line 309 "scanner.l"
 return NET;
 	YY_BREAK
 case 47:
 YY_RULE_SETUP
-#line 296 "scanner.l"
+#line 310 "scanner.l"
 return NETMASK;
 	YY_BREAK
 case 48:
 YY_RULE_SETUP
-#line 297 "scanner.l"
+#line 311 "scanner.l"
 return PORT;
 	YY_BREAK
 case 49:
 YY_RULE_SETUP
-#line 298 "scanner.l"
+#line 312 "scanner.l"
 return PORTRANGE;
 	YY_BREAK
 case 50:
 YY_RULE_SETUP
-#line 299 "scanner.l"
+#line 313 "scanner.l"
 return PROTO;
 	YY_BREAK
 case 51:
 YY_RULE_SETUP
-#line 300 "scanner.l"
+#line 314 "scanner.l"
 {
 #ifdef NO_PROTOCHAIN
 		  bpf_error(yyextra, "%s not supported", yytext);
@@ -3383,353 +3567,353 @@
 	YY_BREAK
 case 52:
 YY_RULE_SETUP
-#line 308 "scanner.l"
+#line 322 "scanner.l"
 return GATEWAY;
 	YY_BREAK
 case 53:
 YY_RULE_SETUP
-#line 310 "scanner.l"
+#line 324 "scanner.l"
 return TYPE;
 	YY_BREAK
 case 54:
 YY_RULE_SETUP
-#line 311 "scanner.l"
+#line 325 "scanner.l"
 return SUBTYPE;
 	YY_BREAK
 case 55:
 YY_RULE_SETUP
-#line 312 "scanner.l"
+#line 326 "scanner.l"
 return DIR;
 	YY_BREAK
 case 56:
 YY_RULE_SETUP
-#line 313 "scanner.l"
+#line 327 "scanner.l"
 return ADDR1;
 	YY_BREAK
 case 57:
 YY_RULE_SETUP
-#line 314 "scanner.l"
+#line 328 "scanner.l"
 return ADDR2;
 	YY_BREAK
 case 58:
 YY_RULE_SETUP
-#line 315 "scanner.l"
+#line 329 "scanner.l"
 return ADDR3;
 	YY_BREAK
 case 59:
 YY_RULE_SETUP
-#line 316 "scanner.l"
+#line 330 "scanner.l"
 return ADDR4;
 	YY_BREAK
 case 60:
 YY_RULE_SETUP
-#line 317 "scanner.l"
+#line 331 "scanner.l"
 return RA;
 	YY_BREAK
 case 61:
 YY_RULE_SETUP
-#line 318 "scanner.l"
+#line 332 "scanner.l"
 return TA;
 	YY_BREAK
 case 62:
 YY_RULE_SETUP
-#line 320 "scanner.l"
+#line 334 "scanner.l"
 return LESS;
 	YY_BREAK
 case 63:
 YY_RULE_SETUP
-#line 321 "scanner.l"
+#line 335 "scanner.l"
 return GREATER;
 	YY_BREAK
 case 64:
 YY_RULE_SETUP
-#line 322 "scanner.l"
+#line 336 "scanner.l"
 return CBYTE;
 	YY_BREAK
 case 65:
 YY_RULE_SETUP
-#line 323 "scanner.l"
+#line 337 "scanner.l"
 return TK_BROADCAST;
 	YY_BREAK
 case 66:
 YY_RULE_SETUP
-#line 324 "scanner.l"
+#line 338 "scanner.l"
 return TK_MULTICAST;
 	YY_BREAK
 case 67:
 YY_RULE_SETUP
-#line 326 "scanner.l"
+#line 340 "scanner.l"
 return AND;
 	YY_BREAK
 case 68:
 YY_RULE_SETUP
-#line 327 "scanner.l"
+#line 341 "scanner.l"
 return OR;
 	YY_BREAK
 case 69:
 YY_RULE_SETUP
-#line 328 "scanner.l"
+#line 342 "scanner.l"
 return '!';
 	YY_BREAK
 case 70:
 YY_RULE_SETUP
-#line 330 "scanner.l"
+#line 344 "scanner.l"
 return LEN;
 	YY_BREAK
 case 71:
 YY_RULE_SETUP
-#line 331 "scanner.l"
+#line 345 "scanner.l"
 return INBOUND;
 	YY_BREAK
 case 72:
 YY_RULE_SETUP
-#line 332 "scanner.l"
+#line 346 "scanner.l"
 return OUTBOUND;
 	YY_BREAK
 case 73:
 YY_RULE_SETUP
-#line 334 "scanner.l"
+#line 348 "scanner.l"
 return VLAN;
 	YY_BREAK
 case 74:
 YY_RULE_SETUP
-#line 335 "scanner.l"
+#line 349 "scanner.l"
 return MPLS;
 	YY_BREAK
 case 75:
 YY_RULE_SETUP
-#line 336 "scanner.l"
+#line 350 "scanner.l"
 return PPPOED;
 	YY_BREAK
 case 76:
 YY_RULE_SETUP
-#line 337 "scanner.l"
+#line 351 "scanner.l"
 return PPPOES;
 	YY_BREAK
 case 77:
 YY_RULE_SETUP
-#line 338 "scanner.l"
+#line 352 "scanner.l"
 return GENEVE;
 	YY_BREAK
 case 78:
 YY_RULE_SETUP
-#line 340 "scanner.l"
+#line 354 "scanner.l"
 return LANE;
 	YY_BREAK
 case 79:
 YY_RULE_SETUP
-#line 341 "scanner.l"
+#line 355 "scanner.l"
 return LLC;
 	YY_BREAK
 case 80:
 YY_RULE_SETUP
-#line 342 "scanner.l"
+#line 356 "scanner.l"
 return METAC;
 	YY_BREAK
 case 81:
 YY_RULE_SETUP
-#line 343 "scanner.l"
+#line 357 "scanner.l"
 return BCC;
 	YY_BREAK
 case 82:
 YY_RULE_SETUP
-#line 344 "scanner.l"
+#line 358 "scanner.l"
 return OAM;
 	YY_BREAK
 case 83:
 YY_RULE_SETUP
-#line 345 "scanner.l"
+#line 359 "scanner.l"
 return OAMF4;
 	YY_BREAK
 case 84:
 YY_RULE_SETUP
-#line 346 "scanner.l"
+#line 360 "scanner.l"
 return OAMF4EC;
 	YY_BREAK
 case 85:
 YY_RULE_SETUP
-#line 347 "scanner.l"
+#line 361 "scanner.l"
 return OAMF4SC;
 	YY_BREAK
 case 86:
 YY_RULE_SETUP
-#line 348 "scanner.l"
+#line 362 "scanner.l"
 return SC;
 	YY_BREAK
 case 87:
 YY_RULE_SETUP
-#line 349 "scanner.l"
+#line 363 "scanner.l"
 return ILMIC;
 	YY_BREAK
 case 88:
 YY_RULE_SETUP
-#line 350 "scanner.l"
+#line 364 "scanner.l"
 return VPI;
 	YY_BREAK
 case 89:
 YY_RULE_SETUP
-#line 351 "scanner.l"
+#line 365 "scanner.l"
 return VCI;
 	YY_BREAK
 case 90:
 YY_RULE_SETUP
-#line 352 "scanner.l"
+#line 366 "scanner.l"
 return CONNECTMSG;
 	YY_BREAK
 case 91:
 YY_RULE_SETUP
-#line 353 "scanner.l"
+#line 367 "scanner.l"
 return METACONNECT;
 	YY_BREAK
 case 92:
 YY_RULE_SETUP
-#line 355 "scanner.l"
+#line 369 "scanner.l"
 return PF_IFNAME;
 	YY_BREAK
 case 93:
 YY_RULE_SETUP
-#line 356 "scanner.l"
+#line 370 "scanner.l"
 return PF_RSET;
 	YY_BREAK
 case 94:
 YY_RULE_SETUP
-#line 357 "scanner.l"
+#line 371 "scanner.l"
 return PF_RNR;
 	YY_BREAK
 case 95:
 YY_RULE_SETUP
-#line 358 "scanner.l"
+#line 372 "scanner.l"
 return PF_SRNR;
 	YY_BREAK
 case 96:
 YY_RULE_SETUP
-#line 359 "scanner.l"
+#line 373 "scanner.l"
 return PF_REASON;
 	YY_BREAK
 case 97:
 YY_RULE_SETUP
-#line 360 "scanner.l"
+#line 374 "scanner.l"
 return PF_ACTION;
 	YY_BREAK
 case 98:
 YY_RULE_SETUP
-#line 362 "scanner.l"
+#line 376 "scanner.l"
 return FISU;
 	YY_BREAK
 case 99:
 YY_RULE_SETUP
-#line 363 "scanner.l"
+#line 377 "scanner.l"
 return LSSU;
 	YY_BREAK
 case 100:
 YY_RULE_SETUP
-#line 364 "scanner.l"
+#line 378 "scanner.l"
 return LSSU;
 	YY_BREAK
 case 101:
 YY_RULE_SETUP
-#line 365 "scanner.l"
+#line 379 "scanner.l"
 return MSU;
 	YY_BREAK
 case 102:
 YY_RULE_SETUP
-#line 366 "scanner.l"
+#line 380 "scanner.l"
 return HFISU;
 	YY_BREAK
 case 103:
 YY_RULE_SETUP
-#line 367 "scanner.l"
+#line 381 "scanner.l"
 return HLSSU;
 	YY_BREAK
 case 104:
 YY_RULE_SETUP
-#line 368 "scanner.l"
+#line 382 "scanner.l"
 return HMSU;
 	YY_BREAK
 case 105:
 YY_RULE_SETUP
-#line 369 "scanner.l"
+#line 383 "scanner.l"
 return SIO;
 	YY_BREAK
 case 106:
 YY_RULE_SETUP
-#line 370 "scanner.l"
+#line 384 "scanner.l"
 return OPC;
 	YY_BREAK
 case 107:
 YY_RULE_SETUP
-#line 371 "scanner.l"
+#line 385 "scanner.l"
 return DPC;
 	YY_BREAK
 case 108:
 YY_RULE_SETUP
-#line 372 "scanner.l"
+#line 386 "scanner.l"
 return SLS;
 	YY_BREAK
 case 109:
 YY_RULE_SETUP
-#line 373 "scanner.l"
+#line 387 "scanner.l"
 return HSIO;
 	YY_BREAK
 case 110:
 YY_RULE_SETUP
-#line 374 "scanner.l"
+#line 388 "scanner.l"
 return HOPC;
 	YY_BREAK
 case 111:
 YY_RULE_SETUP
-#line 375 "scanner.l"
+#line 389 "scanner.l"
 return HDPC;
 	YY_BREAK
 case 112:
 YY_RULE_SETUP
-#line 376 "scanner.l"
+#line 390 "scanner.l"
 return HSLS;
 	YY_BREAK
 case 113:
 /* rule 113 can match eol */
 YY_RULE_SETUP
-#line 378 "scanner.l"
+#line 392 "scanner.l"
 ;
 	YY_BREAK
 case 114:
 YY_RULE_SETUP
-#line 379 "scanner.l"
+#line 393 "scanner.l"
 return yytext[0];
 	YY_BREAK
 case 115:
 YY_RULE_SETUP
-#line 380 "scanner.l"
+#line 394 "scanner.l"
 return GEQ;
 	YY_BREAK
 case 116:
 YY_RULE_SETUP
-#line 381 "scanner.l"
+#line 395 "scanner.l"
 return LEQ;
 	YY_BREAK
 case 117:
 YY_RULE_SETUP
-#line 382 "scanner.l"
+#line 396 "scanner.l"
 return NEQ;
 	YY_BREAK
 case 118:
 YY_RULE_SETUP
-#line 383 "scanner.l"
+#line 397 "scanner.l"
 return '=';
 	YY_BREAK
 case 119:
 YY_RULE_SETUP
-#line 384 "scanner.l"
+#line 398 "scanner.l"
 return LSH;
 	YY_BREAK
 case 120:
 YY_RULE_SETUP
-#line 385 "scanner.l"
+#line 399 "scanner.l"
 return RSH;
 	YY_BREAK
 case 121:
 YY_RULE_SETUP
-#line 386 "scanner.l"
+#line 400 "scanner.l"
 { yylval->e = pcap_ether_aton(((char *)yytext)+1);
 			  if (yylval->e == NULL)
 				bpf_error(yyextra, "malloc");
@@ -3737,7 +3921,7 @@
 	YY_BREAK
 case 122:
 YY_RULE_SETUP
-#line 390 "scanner.l"
+#line 404 "scanner.l"
 { yylval->e = pcap_ether_aton((char *)yytext);
 			  if (yylval->e == NULL)
 				bpf_error(yyextra, "malloc");
@@ -3745,18 +3929,18 @@
 	YY_BREAK
 case 123:
 YY_RULE_SETUP
-#line 394 "scanner.l"
+#line 408 "scanner.l"
 { yylval->i = stoi((char *)yytext); return NUM; }
 	YY_BREAK
 case 124:
 YY_RULE_SETUP
-#line 395 "scanner.l"
+#line 409 "scanner.l"
 {
 			yylval->s = sdup(yyextra, (char *)yytext); return HID; }
 	YY_BREAK
 case 125:
 YY_RULE_SETUP
-#line 397 "scanner.l"
+#line 411 "scanner.l"
 {
 #ifdef INET6
 			  struct addrinfo hints, *res;
@@ -3776,157 +3960,302 @@
 	YY_BREAK
 case 126:
 YY_RULE_SETUP
-#line 413 "scanner.l"
+#line 427 "scanner.l"
 { bpf_error(yyextra, "bogus ethernet address %s", yytext); }
 	YY_BREAK
 case 127:
 YY_RULE_SETUP
-#line 414 "scanner.l"
+#line 428 "scanner.l"
 { yylval->i = 0; return NUM; }
 	YY_BREAK
 case 128:
 YY_RULE_SETUP
-#line 415 "scanner.l"
+#line 429 "scanner.l"
 { yylval->i = 1; return NUM; }
 	YY_BREAK
 case 129:
 YY_RULE_SETUP
-#line 416 "scanner.l"
+#line 430 "scanner.l"
 { yylval->i = 0; return NUM; }
 	YY_BREAK
 case 130:
 YY_RULE_SETUP
-#line 417 "scanner.l"
+#line 431 "scanner.l"
 { yylval->i = 3; return NUM; }
 	YY_BREAK
 case 131:
 YY_RULE_SETUP
-#line 418 "scanner.l"
+#line 432 "scanner.l"
 { yylval->i = 4; return NUM; }
 	YY_BREAK
 case 132:
 YY_RULE_SETUP
-#line 419 "scanner.l"
+#line 433 "scanner.l"
 { yylval->i = 5; return NUM; }
 	YY_BREAK
 case 133:
 YY_RULE_SETUP
-#line 420 "scanner.l"
+#line 434 "scanner.l"
 { yylval->i = 8; return NUM; }
 	YY_BREAK
 case 134:
 YY_RULE_SETUP
-#line 421 "scanner.l"
+#line 435 "scanner.l"
 { yylval->i = 9; return NUM; }
 	YY_BREAK
 case 135:
 YY_RULE_SETUP
-#line 422 "scanner.l"
+#line 436 "scanner.l"
 { yylval->i = 10; return NUM; }
 	YY_BREAK
 case 136:
 YY_RULE_SETUP
-#line 423 "scanner.l"
+#line 437 "scanner.l"
 { yylval->i = 11; return NUM; }
 	YY_BREAK
 case 137:
 YY_RULE_SETUP
-#line 424 "scanner.l"
+#line 438 "scanner.l"
 { yylval->i = 12; return NUM; }
 	YY_BREAK
 case 138:
 YY_RULE_SETUP
-#line 425 "scanner.l"
+#line 439 "scanner.l"
 { yylval->i = 13; return NUM; }
 	YY_BREAK
 case 139:
 YY_RULE_SETUP
-#line 426 "scanner.l"
+#line 440 "scanner.l"
 { yylval->i = 14; return NUM; }
 	YY_BREAK
 case 140:
 YY_RULE_SETUP
-#line 427 "scanner.l"
+#line 441 "scanner.l"
 { yylval->i = 15; return NUM; }
 	YY_BREAK
 case 141:
 YY_RULE_SETUP
-#line 428 "scanner.l"
+#line 442 "scanner.l"
 { yylval->i = 16; return NUM; }
 	YY_BREAK
 case 142:
 YY_RULE_SETUP
-#line 429 "scanner.l"
+#line 443 "scanner.l"
 { yylval->i = 17; return NUM; }
 	YY_BREAK
 case 143:
 YY_RULE_SETUP
-#line 430 "scanner.l"
+#line 444 "scanner.l"
 { yylval->i = 18; return NUM; }
 	YY_BREAK
 case 144:
 YY_RULE_SETUP
-#line 431 "scanner.l"
-{ yylval->i = 13; return NUM; }
+#line 446 "scanner.l"
+{ yylval->i = 0; return NUM; }
 	YY_BREAK
 case 145:
 YY_RULE_SETUP
-#line 432 "scanner.l"
-{ yylval->i = 0x01; return NUM; }
+#line 447 "scanner.l"
+{ yylval->i = 1; return NUM; }
 	YY_BREAK
 case 146:
 YY_RULE_SETUP
-#line 433 "scanner.l"
-{ yylval->i = 0x02; return NUM; }
+#line 449 "scanner.l"
+{ yylval->i = 128; return NUM; }
 	YY_BREAK
 case 147:
 YY_RULE_SETUP
-#line 434 "scanner.l"
-{ yylval->i = 0x04; return NUM; }
+#line 450 "scanner.l"
+{ yylval->i = 129; return NUM; }
 	YY_BREAK
 case 148:
 YY_RULE_SETUP
-#line 435 "scanner.l"
-{ yylval->i = 0x08; return NUM; }
+#line 451 "scanner.l"
+{ yylval->i = 130; return NUM; }
 	YY_BREAK
 case 149:
 YY_RULE_SETUP
-#line 436 "scanner.l"
-{ yylval->i = 0x10; return NUM; }
+#line 452 "scanner.l"
+{ yylval->i = 131; return NUM; }
 	YY_BREAK
 case 150:
 YY_RULE_SETUP
-#line 437 "scanner.l"
-{ yylval->i = 0x20; return NUM; }
+#line 453 "scanner.l"
+{ yylval->i = 132; return NUM; }
 	YY_BREAK
 case 151:
 YY_RULE_SETUP
-#line 438 "scanner.l"
-{
-			 yylval->s = sdup(yyextra, (char *)yytext); return ID; }
+#line 454 "scanner.l"
+{ yylval->i = 133; return NUM; }
 	YY_BREAK
 case 152:
 YY_RULE_SETUP
-#line 440 "scanner.l"
-{ yylval->s = sdup(yyextra, (char *)yytext + 1); return ID; }
+#line 455 "scanner.l"
+{ yylval->i = 134; return NUM; }
 	YY_BREAK
 case 153:
 YY_RULE_SETUP
-#line 441 "scanner.l"
-{
-			bpf_error(yyextra, "illegal token: %s", yytext); }
+#line 456 "scanner.l"
+{ yylval->i = 135; return NUM; }
 	YY_BREAK
 case 154:
 YY_RULE_SETUP
-#line 443 "scanner.l"
-{ bpf_error(yyextra, "illegal char '%c'", *yytext); }
+#line 457 "scanner.l"
+{ yylval->i = 136; return NUM; }
 	YY_BREAK
 case 155:
 YY_RULE_SETUP
-#line 444 "scanner.l"
+#line 458 "scanner.l"
+{ yylval->i = 137; return NUM; }
+	YY_BREAK
+case 156:
+YY_RULE_SETUP
+#line 459 "scanner.l"
+{ yylval->i = 138; return NUM; }
+	YY_BREAK
+case 157:
+YY_RULE_SETUP
+#line 460 "scanner.l"
+{ yylval->i = 139; return NUM; }
+	YY_BREAK
+case 158:
+YY_RULE_SETUP
+#line 461 "scanner.l"
+{ yylval->i = 140; return NUM; }
+	YY_BREAK
+case 159:
+YY_RULE_SETUP
+#line 462 "scanner.l"
+{ yylval->i = 141; return NUM; }
+	YY_BREAK
+case 160:
+YY_RULE_SETUP
+#line 463 "scanner.l"
+{ yylval->i = 142; return NUM; }
+	YY_BREAK
+case 161:
+YY_RULE_SETUP
+#line 464 "scanner.l"
+{ yylval->i = 143; return NUM; }
+	YY_BREAK
+case 162:
+YY_RULE_SETUP
+#line 465 "scanner.l"
+{ yylval->i = 144; return NUM; }
+	YY_BREAK
+case 163:
+YY_RULE_SETUP
+#line 466 "scanner.l"
+{ yylval->i = 145; return NUM; }
+	YY_BREAK
+case 164:
+YY_RULE_SETUP
+#line 467 "scanner.l"
+{ yylval->i = 146; return NUM; }
+	YY_BREAK
+case 165:
+YY_RULE_SETUP
+#line 468 "scanner.l"
+{ yylval->i = 147; return NUM; }
+	YY_BREAK
+case 166:
+YY_RULE_SETUP
+#line 469 "scanner.l"
+{ yylval->i = 148; return NUM; }
+	YY_BREAK
+case 167:
+YY_RULE_SETUP
+#line 470 "scanner.l"
+{ yylval->i = 149; return NUM; }
+	YY_BREAK
+case 168:
+YY_RULE_SETUP
+#line 471 "scanner.l"
+{ yylval->i = 151; return NUM; }
+	YY_BREAK
+case 169:
+YY_RULE_SETUP
+#line 472 "scanner.l"
+{ yylval->i = 152; return NUM; }
+	YY_BREAK
+case 170:
+YY_RULE_SETUP
+#line 473 "scanner.l"
+{ yylval->i = 153; return NUM; }
+	YY_BREAK
+case 171:
+YY_RULE_SETUP
+#line 475 "scanner.l"
+{ yylval->i = 13; return NUM; }
+	YY_BREAK
+case 172:
+YY_RULE_SETUP
+#line 476 "scanner.l"
+{ yylval->i = 0x01; return NUM; }
+	YY_BREAK
+case 173:
+YY_RULE_SETUP
+#line 477 "scanner.l"
+{ yylval->i = 0x02; return NUM; }
+	YY_BREAK
+case 174:
+YY_RULE_SETUP
+#line 478 "scanner.l"
+{ yylval->i = 0x04; return NUM; }
+	YY_BREAK
+case 175:
+YY_RULE_SETUP
+#line 479 "scanner.l"
+{ yylval->i = 0x08; return NUM; }
+	YY_BREAK
+case 176:
+YY_RULE_SETUP
+#line 480 "scanner.l"
+{ yylval->i = 0x10; return NUM; }
+	YY_BREAK
+case 177:
+YY_RULE_SETUP
+#line 481 "scanner.l"
+{ yylval->i = 0x20; return NUM; }
+	YY_BREAK
+case 178:
+YY_RULE_SETUP
+#line 482 "scanner.l"
+{ yylval->i = 0x40; return NUM; }
+	YY_BREAK
+case 179:
+YY_RULE_SETUP
+#line 483 "scanner.l"
+{ yylval->i = 0x80; return NUM; }
+	YY_BREAK
+case 180:
+YY_RULE_SETUP
+#line 484 "scanner.l"
+{
+			 yylval->s = sdup(yyextra, (char *)yytext); return ID; }
+	YY_BREAK
+case 181:
+YY_RULE_SETUP
+#line 486 "scanner.l"
+{ yylval->s = sdup(yyextra, (char *)yytext + 1); return ID; }
+	YY_BREAK
+case 182:
+YY_RULE_SETUP
+#line 487 "scanner.l"
+{
+			bpf_error(yyextra, "illegal token: %s", yytext); }
+	YY_BREAK
+case 183:
+YY_RULE_SETUP
+#line 489 "scanner.l"
+{ bpf_error(yyextra, "illegal char '%c'", *yytext); }
+	YY_BREAK
+case 184:
+YY_RULE_SETUP
+#line 490 "scanner.l"
 ECHO;
 	YY_BREAK
-#line 3930 "scanner.c"
+#line 4259 "scanner.c"
 case YY_STATE_EOF(INITIAL):
 	yyterminate();
 
@@ -4071,9 +4400,9 @@
 static int yy_get_next_buffer (yyscan_t yyscanner)
 {
     struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
-	register char *dest = YY_CURRENT_BUFFER_LVALUE->yy_ch_buf;
-	register char *source = yyg->yytext_ptr;
-	register int number_to_move, i;
+	char *dest = YY_CURRENT_BUFFER_LVALUE->yy_ch_buf;
+	char *source = yyg->yytext_ptr;
+	int number_to_move, i;
 	int ret_val;
 
 	if ( yyg->yy_c_buf_p > &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[yyg->yy_n_chars + 1] )
@@ -4102,7 +4431,7 @@
 	/* Try to read more data. */
 
 	/* First move last chars to start of buffer. */
-	number_to_move = (int) (yyg->yy_c_buf_p - yyg->yytext_ptr) - 1;
+	number_to_move = (int) (yyg->yy_c_buf_p - yyg->yytext_ptr - 1);
 
 	for ( i = 0; i < number_to_move; ++i )
 		*(dest++) = *(source++);
@@ -4115,7 +4444,7 @@
 
 	else
 		{
-			yy_size_t num_to_read =
+			int num_to_read =
 			YY_CURRENT_BUFFER_LVALUE->yy_buf_size - number_to_move - 1;
 
 		while ( num_to_read <= 0 )
@@ -4129,7 +4458,7 @@
 
 			if ( b->yy_is_our_buffer )
 				{
-				yy_size_t new_size = b->yy_buf_size * 2;
+				int new_size = b->yy_buf_size * 2;
 
 				if ( new_size <= 0 )
 					b->yy_buf_size += b->yy_buf_size / 8;
@@ -4142,7 +4471,7 @@
 				}
 			else
 				/* Can't grow it, we don't own it. */
-				b->yy_ch_buf = 0;
+				b->yy_ch_buf = NULL;
 
 			if ( ! b->yy_ch_buf )
 				YY_FATAL_ERROR(
@@ -4184,9 +4513,9 @@
 	else
 		ret_val = EOB_ACT_CONTINUE_SCAN;
 
-	if ((yy_size_t) (yyg->yy_n_chars + number_to_move) > YY_CURRENT_BUFFER_LVALUE->yy_buf_size) {
+	if ((yyg->yy_n_chars + number_to_move) > YY_CURRENT_BUFFER_LVALUE->yy_buf_size) {
 		/* Extend the array by 50%, plus the number we really need. */
-		yy_size_t new_size = yyg->yy_n_chars + number_to_move + (yyg->yy_n_chars >> 1);
+		int new_size = yyg->yy_n_chars + number_to_move + (yyg->yy_n_chars >> 1);
 		YY_CURRENT_BUFFER_LVALUE->yy_ch_buf = (char *) pcap_realloc((void *) YY_CURRENT_BUFFER_LVALUE->yy_ch_buf,new_size ,yyscanner );
 		if ( ! YY_CURRENT_BUFFER_LVALUE->yy_ch_buf )
 			YY_FATAL_ERROR( "out of dynamic memory in yy_get_next_buffer()" );
@@ -4205,15 +4534,15 @@
 
     static yy_state_type yy_get_previous_state (yyscan_t yyscanner)
 {
-	register yy_state_type yy_current_state;
-	register char *yy_cp;
+	yy_state_type yy_current_state;
+	char *yy_cp;
     struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
 
 	yy_current_state = yyg->yy_start;
 
 	for ( yy_cp = yyg->yytext_ptr + YY_MORE_ADJ; yy_cp < yyg->yy_c_buf_p; ++yy_cp )
 		{
-		register YY_CHAR yy_c = (*yy_cp ? yy_ec[YY_SC_TO_UI(*yy_cp)] : 1);
+		YY_CHAR yy_c = (*yy_cp ? yy_ec[YY_SC_TO_UI(*yy_cp)] : 1);
 		if ( yy_accept[yy_current_state] )
 			{
 			yyg->yy_last_accepting_state = yy_current_state;
@@ -4222,10 +4551,10 @@
 		while ( yy_chk[yy_base[yy_current_state] + yy_c] != yy_current_state )
 			{
 			yy_current_state = (int) yy_def[yy_current_state];
-			if ( yy_current_state >= 1464 )
+			if ( yy_current_state >= 1729 )
 				yy_c = yy_meta[(unsigned int) yy_c];
 			}
-		yy_current_state = yy_nxt[yy_base[yy_current_state] + (unsigned int) yy_c];
+		yy_current_state = yy_nxt[yy_base[yy_current_state] + (flex_int16_t) yy_c];
 		}
 
 	return yy_current_state;
@@ -4238,11 +4567,11 @@
  */
     static yy_state_type yy_try_NUL_trans  (yy_state_type yy_current_state , yyscan_t yyscanner)
 {
-	register int yy_is_jam;
+	int yy_is_jam;
     struct yyguts_t * yyg = (struct yyguts_t*)yyscanner; /* This var may be unused depending upon options. */
-	register char *yy_cp = yyg->yy_c_buf_p;
+	char *yy_cp = yyg->yy_c_buf_p;
 
-	register YY_CHAR yy_c = 1;
+	YY_CHAR yy_c = 1;
 	if ( yy_accept[yy_current_state] )
 		{
 		yyg->yy_last_accepting_state = yy_current_state;
@@ -4251,16 +4580,20 @@
 	while ( yy_chk[yy_base[yy_current_state] + yy_c] != yy_current_state )
 		{
 		yy_current_state = (int) yy_def[yy_current_state];
-		if ( yy_current_state >= 1464 )
+		if ( yy_current_state >= 1729 )
 			yy_c = yy_meta[(unsigned int) yy_c];
 		}
-	yy_current_state = yy_nxt[yy_base[yy_current_state] + (unsigned int) yy_c];
-	yy_is_jam = (yy_current_state == 1463);
+	yy_current_state = yy_nxt[yy_base[yy_current_state] + (flex_int16_t) yy_c];
+	yy_is_jam = (yy_current_state == 1728);
 
 	(void)yyg;
 	return yy_is_jam ? 0 : yy_current_state;
 }
 
+#ifndef YY_NO_UNPUT
+
+#endif
+
 #ifndef YY_NO_INPUT
 #ifdef __cplusplus
     static int yyinput (yyscan_t yyscanner)
@@ -4286,7 +4619,7 @@
 
 		else
 			{ /* need more input */
-			yy_size_t offset = yyg->yy_c_buf_p - yyg->yytext_ptr;
+			int offset = yyg->yy_c_buf_p - yyg->yytext_ptr;
 			++yyg->yy_c_buf_p;
 
 			switch ( yy_get_next_buffer( yyscanner ) )
@@ -4310,7 +4643,7 @@
 				case EOB_ACT_END_OF_FILE:
 					{
 					if ( pcap_wrap(yyscanner ) )
-						return EOF;
+						return 0;
 
 					if ( ! yyg->yy_did_buffer_switch_on_eof )
 						YY_NEW_FILE;
@@ -4414,7 +4747,7 @@
 	if ( ! b )
 		YY_FATAL_ERROR( "out of dynamic memory in pcap__create_buffer()" );
 
-	b->yy_buf_size = size;
+	b->yy_buf_size = (yy_size_t)size;
 
 	/* yy_ch_buf has to be 2 characters longer than the size given because
 	 * we need to put in 2 end-of-buffer characters.
@@ -4566,7 +4899,7 @@
  */
 static void pcap_ensure_buffer_stack (yyscan_t yyscanner)
 {
-	yy_size_t num_to_alloc;
+	int num_to_alloc;
     struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
 
 	if (!yyg->yy_buffer_stack) {
@@ -4575,15 +4908,15 @@
 		 * scanner will even need a stack. We use 2 instead of 1 to avoid an
 		 * immediate realloc on the next call.
          */
-		num_to_alloc = 1;
+      num_to_alloc = 1; /* After all that talk, this was set to 1 anyways... */
 		yyg->yy_buffer_stack = (struct yy_buffer_state**)pcap_alloc
 								(num_to_alloc * sizeof(struct yy_buffer_state*)
 								, yyscanner);
 		if ( ! yyg->yy_buffer_stack )
 			YY_FATAL_ERROR( "out of dynamic memory in pcap_ensure_buffer_stack()" );
-								  
+
 		memset(yyg->yy_buffer_stack, 0, num_to_alloc * sizeof(struct yy_buffer_state*));
-				
+
 		yyg->yy_buffer_stack_max = num_to_alloc;
 		yyg->yy_buffer_stack_top = 0;
 		return;
@@ -4592,7 +4925,7 @@
 	if (yyg->yy_buffer_stack_top >= (yyg->yy_buffer_stack_max) - 1){
 
 		/* Increase the buffer to prepare for a possible push. */
-		int grow_size = 8 /* arbitrary grow size */;
+		yy_size_t grow_size = 8 /* arbitrary grow size */;
 
 		num_to_alloc = yyg->yy_buffer_stack_max + grow_size;
 		yyg->yy_buffer_stack = (struct yy_buffer_state**)pcap_realloc
@@ -4612,7 +4945,7 @@
  * @param base the character buffer
  * @param size the size in bytes of the character buffer
  * @param yyscanner The scanner object.
- * @return the newly allocated buffer state object. 
+ * @return the newly allocated buffer state object.
  */
 YY_BUFFER_STATE pcap__scan_buffer  (char * base, yy_size_t  size , yyscan_t yyscanner)
 {
@@ -4622,7 +4955,7 @@
 	     base[size-2] != YY_END_OF_BUFFER_CHAR ||
 	     base[size-1] != YY_END_OF_BUFFER_CHAR )
 		/* They forgot to leave room for the EOB's. */
-		return 0;
+		return NULL;
 
 	b = (YY_BUFFER_STATE) pcap_alloc(sizeof( struct yy_buffer_state ) ,yyscanner );
 	if ( ! b )
@@ -4631,7 +4964,7 @@
 	b->yy_buf_size = size - 2;	/* "- 2" to take care of EOB's */
 	b->yy_buf_pos = b->yy_ch_buf = base;
 	b->yy_is_our_buffer = 0;
-	b->yy_input_file = 0;
+	b->yy_input_file = NULL;
 	b->yy_n_chars = b->yy_buf_size;
 	b->yy_is_interactive = 0;
 	b->yy_at_bol = 1;
@@ -4654,7 +4987,7 @@
 YY_BUFFER_STATE pcap__scan_string (yyconst char * yystr , yyscan_t yyscanner)
 {
     
-	return pcap__scan_bytes(yystr,strlen(yystr) ,yyscanner);
+	return pcap__scan_bytes(yystr,(int) strlen(yystr) ,yyscanner);
 }
 
 /** Setup the input buffer state to scan the given bytes. The next call to pcap_lex() will
@@ -4664,15 +4997,15 @@
  * @param yyscanner The scanner object.
  * @return the newly allocated buffer state object.
  */
-YY_BUFFER_STATE pcap__scan_bytes  (yyconst char * yybytes, yy_size_t  _yybytes_len , yyscan_t yyscanner)
+YY_BUFFER_STATE pcap__scan_bytes  (yyconst char * yybytes, int  _yybytes_len , yyscan_t yyscanner)
 {
 	YY_BUFFER_STATE b;
 	char *buf;
 	yy_size_t n;
-	yy_size_t i;
+	int i;
     
 	/* Get memory for full buffer, including space for trailing EOB's. */
-	n = _yybytes_len + 2;
+	n = (yy_size_t) (_yybytes_len + 2);
 	buf = (char *) pcap_alloc(n ,yyscanner );
 	if ( ! buf )
 		YY_FATAL_ERROR( "out of dynamic memory in pcap__scan_bytes()" );
@@ -4698,9 +5031,11 @@
 #define YY_EXIT_FAILURE 2
 #endif
 
-static void yy_fatal_error (yyconst char* msg , yyscan_t yyscanner)
+static void yynoreturn yy_fatal_error (yyconst char* msg , yyscan_t yyscanner)
 {
-    	(void) fprintf( stderr, "%s\n", msg );
+	struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
+	(void)yyg;
+	(void) fprintf( stderr, "%s\n", msg );
 	exit( YY_EXIT_FAILURE );
 }
 
@@ -4738,7 +5073,7 @@
 int pcap_get_lineno  (yyscan_t yyscanner)
 {
     struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
-    
+
         if (! YY_CURRENT_BUFFER)
             return 0;
     
@@ -4751,7 +5086,7 @@
 int pcap_get_column  (yyscan_t yyscanner)
 {
     struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
-    
+
         if (! YY_CURRENT_BUFFER)
             return 0;
     
@@ -4779,7 +5114,7 @@
 /** Get the length of the current token.
  * @param yyscanner The scanner object.
  */
-yy_size_t pcap_get_leng  (yyscan_t yyscanner)
+int pcap_get_leng  (yyscan_t yyscanner)
 {
     struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
     return yyleng;
@@ -4806,10 +5141,10 @@
 }
 
 /** Set the current line number.
- * @param line_number
+ * @param _line_number line number
  * @param yyscanner The scanner object.
  */
-void pcap_set_lineno (int  line_number , yyscan_t yyscanner)
+void pcap_set_lineno (int  _line_number , yyscan_t yyscanner)
 {
     struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
 
@@ -4817,14 +5152,14 @@
         if (! YY_CURRENT_BUFFER )
            YY_FATAL_ERROR( "pcap_set_lineno called with no buffer" );
     
-    yylineno = line_number;
+    yylineno = _line_number;
 }
 
 /** Set the current column.
- * @param line_number
+ * @param _column_no column number
  * @param yyscanner The scanner object.
  */
-void pcap_set_column (int  column_no , yyscan_t yyscanner)
+void pcap_set_column (int  _column_no , yyscan_t yyscanner)
 {
     struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
 
@@ -4832,25 +5167,25 @@
         if (! YY_CURRENT_BUFFER )
            YY_FATAL_ERROR( "pcap_set_column called with no buffer" );
     
-    yycolumn = column_no;
+    yycolumn = _column_no;
 }
 
 /** Set the input stream. This does not discard the current
  * input buffer.
- * @param in_str A readable stream.
+ * @param _in_str A readable stream.
  * @param yyscanner The scanner object.
  * @see pcap__switch_to_buffer
  */
-void pcap_set_in (FILE *  in_str , yyscan_t yyscanner)
+void pcap_set_in (FILE *  _in_str , yyscan_t yyscanner)
 {
     struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
-    yyin = in_str ;
+    yyin = _in_str ;
 }
 
-void pcap_set_out (FILE *  out_str , yyscan_t yyscanner)
+void pcap_set_out (FILE *  _out_str , yyscan_t yyscanner)
 {
     struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
-    yyout = out_str ;
+    yyout = _out_str ;
 }
 
 int pcap_get_debug  (yyscan_t yyscanner)
@@ -4859,10 +5194,10 @@
     return yy_flex_debug;
 }
 
-void pcap_set_debug (int  bdebug , yyscan_t yyscanner)
+void pcap_set_debug (int  _bdebug , yyscan_t yyscanner)
 {
     struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
-    yy_flex_debug = bdebug ;
+    yy_flex_debug = _bdebug ;
 }
 
 /* Accessor methods for yylval and yylloc */
@@ -4926,20 +5261,20 @@
         errno = EINVAL;
         return 1;
     }
-	
+
     *ptr_yy_globals = (yyscan_t) pcap_alloc ( sizeof( struct yyguts_t ), &dummy_yyguts );
-	
+
     if (*ptr_yy_globals == NULL){
         errno = ENOMEM;
         return 1;
     }
-    
+
     /* By setting to 0xAA, we expose bugs in
     yy_init_globals. Leave at 0x00 for releases. */
     memset(*ptr_yy_globals,0x00,sizeof(struct yyguts_t));
-    
+
     pcap_set_extra (yy_user_defined, *ptr_yy_globals);
-    
+
     return yy_init_globals ( *ptr_yy_globals );
 }
 
@@ -4950,10 +5285,10 @@
      * This function is called from pcap_lex_destroy(), so don't allocate here.
      */
 
-    yyg->yy_buffer_stack = 0;
+    yyg->yy_buffer_stack = NULL;
     yyg->yy_buffer_stack_top = 0;
     yyg->yy_buffer_stack_max = 0;
-    yyg->yy_c_buf_p = (char *) 0;
+    yyg->yy_c_buf_p = NULL;
     yyg->yy_init = 0;
     yyg->yy_start = 0;
 
@@ -4966,8 +5301,8 @@
     yyin = stdin;
     yyout = stdout;
 #else
-    yyin = (FILE *) 0;
-    yyout = (FILE *) 0;
+    yyin = NULL;
+    yyout = NULL;
 #endif
 
     /* For future reference: Set errno on error, since we are called by
@@ -5013,7 +5348,10 @@
 #ifndef yytext_ptr
 static void yy_flex_strncpy (char* s1, yyconst char * s2, int n , yyscan_t yyscanner)
 {
-	register int i;
+	struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
+	(void)yyg;
+
+	int i;
 	for ( i = 0; i < n; ++i )
 		s1[i] = s2[i];
 }
@@ -5022,7 +5360,7 @@
 #ifdef YY_NEED_STRLEN
 static int yy_flex_strlen (yyconst char * s , yyscan_t yyscanner)
 {
-	register int n;
+	int n;
 	for ( n = 0; s[n]; ++n )
 		;
 
@@ -5032,11 +5370,16 @@
 
 void *pcap_alloc (yy_size_t  size , yyscan_t yyscanner)
 {
-	return (void *) malloc( size );
+	struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
+	(void)yyg;
+	return malloc(size);
 }
 
 void *pcap_realloc  (void * ptr, yy_size_t  size , yyscan_t yyscanner)
 {
+	struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
+	(void)yyg;
+
 	/* The cast to (char *) in the following accommodates both
 	 * implementations that use char* generic pointers, and those
 	 * that use void* generic pointers.  It works with the latter
@@ -5044,24 +5387,30 @@
 	 * any pointer type to void*, and deal with argument conversions
 	 * as though doing an assignment.
 	 */
-	return (void *) realloc( (char *) ptr, size );
+	return realloc(ptr, size);
 }
 
 void pcap_free (void * ptr , yyscan_t yyscanner)
 {
+	struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
+	(void)yyg;
 	free( (char *) ptr );	/* see pcap_realloc() for (char *) cast */
 }
 
 #define YYTABLES_NAME "yytables"
 
-#line 443 "scanner.l"
+#line 490 "scanner.l"
 
 
 
+/*
+ * Turn diagnostics back on, so we check the code that we've written.
+ */
+DIAG_ON_FLEX
+
 /* Hex digit to integer. */
 static inline int
-xdtoi(c)
-	register int c;
+xdtoi(int c)
 {
 	if (isdigit(c))
 		return c - '0';
@@ -5076,8 +5425,7 @@
  * 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;
diff --git a/scanner.h b/scanner.h
index a8e5b0a..dc464bd 100644
--- a/scanner.h
+++ b/scanner.h
@@ -3,15 +3,34 @@
 #define pcap_IN_HEADER 1
 
 #line 6 "scanner.h"
-#line 2 "scanner.l"
 /* Must come first for _LARGE_FILE_API on AIX. */
 #ifdef HAVE_CONFIG_H
-#include "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"
 
-#line 15 "scanner.h"
+#line 34 "scanner.h"
 
 #define  YY_INT_ALIGNED short int
 
@@ -19,8 +38,8 @@
 
 #define FLEX_SCANNER
 #define YY_FLEX_MAJOR_VERSION 2
-#define YY_FLEX_MINOR_VERSION 5
-#define YY_FLEX_SUBMINOR_VERSION 39
+#define YY_FLEX_MINOR_VERSION 6
+#define YY_FLEX_SUBMINOR_VERSION 1
 #if YY_FLEX_SUBMINOR_VERSION > 0
 #define FLEX_BETA
 #endif
@@ -99,25 +118,13 @@
 
 #endif /* ! FLEXINT_H */
 
-#ifdef __cplusplus
-
-/* The "const" storage-class-modifier is valid. */
-#define YY_USE_CONST
-
-#else	/* ! __cplusplus */
-
-/* C99 requires __STDC__ to be defined as 1. */
-#if defined (__STDC__)
-
-#define YY_USE_CONST
-
-#endif	/* defined (__STDC__) */
-#endif	/* ! __cplusplus */
-
-#ifdef YY_USE_CONST
+/* TODO: this is always defined, so inline it */
 #define yyconst const
+
+#if defined(__GNUC__) && __GNUC__ >= 3
+#define yynoreturn __attribute__((__noreturn__))
 #else
-#define yyconst
+#define yynoreturn
 #endif
 
 /* An opaque pointer. */
@@ -172,12 +179,12 @@
 	/* Size of input buffer in bytes, not including room for EOB
 	 * characters.
 	 */
-	yy_size_t yy_buf_size;
+	int yy_buf_size;
 
 	/* Number of characters read into yy_ch_buf, not including EOB
 	 * characters.
 	 */
-	yy_size_t yy_n_chars;
+	int yy_n_chars;
 
 	/* Whether we "own" the buffer - i.e., we know we created it,
 	 * and can realloc() it to grow it, and should free() it to
@@ -200,7 +207,7 @@
 
     int yy_bs_lineno; /**< The line count. */
     int yy_bs_column; /**< The column count. */
-    
+
 	/* Whether to try to fill the input buffer when we reach the
 	 * end of it.
 	 */
@@ -221,7 +228,7 @@
 
 YY_BUFFER_STATE pcap__scan_buffer (char *base,yy_size_t size ,yyscan_t yyscanner );
 YY_BUFFER_STATE pcap__scan_string (yyconst char *yy_str ,yyscan_t yyscanner );
-YY_BUFFER_STATE pcap__scan_bytes (yyconst char *bytes,yy_size_t len ,yyscan_t yyscanner );
+YY_BUFFER_STATE pcap__scan_bytes (yyconst char *bytes,int len ,yyscan_t yyscanner );
 
 void *pcap_alloc (yy_size_t ,yyscan_t yyscanner );
 void *pcap_realloc (void *,yy_size_t ,yyscan_t yyscanner );
@@ -229,7 +236,7 @@
 
 /* Begin user sect3 */
 
-#define pcap_wrap(yyscanner) 1
+#define pcap_wrap(yyscanner) (/*CONSTCOND*/1)
 #define YY_SKIP_YYWRAP
 
 #define yytext_ptr yytext_r
@@ -268,23 +275,23 @@
 
 FILE *pcap_get_in (yyscan_t yyscanner );
 
-void pcap_set_in  (FILE * in_str ,yyscan_t yyscanner );
+void pcap_set_in  (FILE * _in_str ,yyscan_t yyscanner );
 
 FILE *pcap_get_out (yyscan_t yyscanner );
 
-void pcap_set_out  (FILE * out_str ,yyscan_t yyscanner );
+void pcap_set_out  (FILE * _out_str ,yyscan_t yyscanner );
 
-yy_size_t pcap_get_leng (yyscan_t yyscanner );
+			int pcap_get_leng (yyscan_t yyscanner );
 
 char *pcap_get_text (yyscan_t yyscanner );
 
 int pcap_get_lineno (yyscan_t yyscanner );
 
-void pcap_set_lineno (int line_number ,yyscan_t yyscanner );
+void pcap_set_lineno (int _line_number ,yyscan_t yyscanner );
 
 int pcap_get_column  (yyscan_t yyscanner );
 
-void pcap_set_column (int column_no ,yyscan_t yyscanner );
+void pcap_set_column (int _column_no ,yyscan_t yyscanner );
 
 YYSTYPE * pcap_get_lval (yyscan_t yyscanner );
 
@@ -356,9 +363,9 @@
 #undef YY_DECL
 #endif
 
-#line 443 "scanner.l"
+#line 490 "scanner.l"
 
 
-#line 363 "scanner.h"
+#line 370 "scanner.h"
 #undef pcap_IN_HEADER
 #endif /* pcap_HEADER_H */
diff --git a/scanner.l b/scanner.l
index 1000b7a..e0890b4 100644
--- a/scanner.l
+++ b/scanner.l
@@ -1,8 +1,30 @@
 %top {
 /* Must come first for _LARGE_FILE_API on AIX. */
 #ifdef HAVE_CONFIG_H
-#include "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"
 }
 
 /*
@@ -63,20 +85,6 @@
  * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
  */
 
-#ifdef _WIN32
-  #include <pcap-stdinc.h>
-#else
-  #if HAVE_INTTYPES_H
-    #include <inttypes.h>
-  #elif HAVE_STDINT_H
-    #include <stdint.h>
-  #endif
-  #ifdef HAVE_SYS_BITYPES_H
-    #include <sys/bitypes.h>
-  #endif
-  #include <sys/types.h>
-#endif
-
 #include <ctype.h>
 #include <string.h>
 
@@ -96,6 +104,8 @@
 #ifdef INET6
 
 #ifdef _WIN32
+#include <winsock2.h>
+#include <ws2tcpip.h>
 /*
  * To quote the MSDN page for getaddrinfo() at
  *
@@ -115,10 +125,9 @@
  * Wspiapi.h header file. This inline code will be used on older Windows
  * platforms that do not natively support the getaddrinfo function."
  *
- * We use getaddrinfo(), so we include Wspiapi.h here.  pcap-stdinc.h
- * includes Ws2tcpip.h, so we don't need to include it ourselves.
+ * We use getaddrinfo(), so we include Wspiapi.h here.
  */
-#include <Wspiapi.h>
+#include <wspiapi.h>
 #else /* _WIN32 */
 #include <sys/socket.h>	/* for "struct sockaddr" in "struct addrinfo" */
 #include <netdb.h>	/* for "struct addrinfo" */
@@ -141,6 +150,11 @@
 static int stoi(char *);
 static inline int xdtoi(int);
 
+/*
+ * Disable diagnostics in the code generated by Flex.
+ */
+DIAG_OFF_FLEX
+
 %}
 
 N		([0-9]+|(0X|0x)[0-9A-Fa-f]+)
@@ -428,6 +442,36 @@
 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; }
@@ -435,6 +479,8 @@
 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(yyextra, (char *)yytext); return ID; }
 "\\"[^ !()\n\t]+	{ yylval->s = sdup(yyextra, (char *)yytext + 1); return ID; }
@@ -443,10 +489,14 @@
 .			{ bpf_error(yyextra, "illegal char '%c'", *yytext); }
 %%
 
+/*
+ * Turn diagnostics back on, so we check the code that we've written.
+ */
+DIAG_ON_FLEX
+
 /* Hex digit to integer. */
 static inline int
-xdtoi(c)
-	register int c;
+xdtoi(int c)
 {
 	if (isdigit(c))
 		return c - '0';
@@ -461,8 +511,7 @@
  * 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;
diff --git a/sf-pcap.c b/sf-pcap.c
index ac305d4..96cb308 100644
--- a/sf-pcap.c
+++ b/sf-pcap.c
@@ -28,27 +28,14 @@
  * 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
 
+#include <pcap-types.h>
 #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 <io.h>
+#include <fcntl.h>
 #endif /* _WIN32 */
 
 #include <errno.h>
@@ -185,9 +172,8 @@
 	    sizeof(hdr) - sizeof(hdr.magic), fp);
 	if (amt_read != sizeof(hdr) - sizeof(hdr.magic)) {
 		if (ferror(fp)) {
-			pcap_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 {
 			pcap_snprintf(errbuf, PCAP_ERRBUF_SIZE,
 			    "truncated dump file; tried to read %lu file header bytes, only got %lu",
@@ -232,14 +218,6 @@
 		return NULL;
 	}
 
-	if (hdr.snaplen > MAXIMUM_SNAPLEN) {
-		pcap_snprintf(errbuf, PCAP_ERRBUF_SIZE,
-			 "invalid file capture length %u, bigger than "
-			 "maximum of %u", hdr.snaplen, MAXIMUM_SNAPLEN);
-		*err = 1;
-		return NULL;
-	}
-
 	/*
 	 * OK, this is a good pcap file.
 	 * Allocate a pcap_t for it.
@@ -255,6 +233,17 @@
 	p->version_minor = hdr.version_minor;
 	p->tzoff = hdr.thiszone;
 	p->snapshot = hdr.snaplen;
+	if (p->snapshot <= 0) {
+		/*
+		 * Bogus snapshot length; use the maximum for this
+		 * link-layer type as a fallback.
+		 *
+		 * XXX - the only reason why snapshot is signed is
+		 * that pcap_snapshot() returns an int, not an
+		 * unsigned int.
+		 */
+		p->snapshot = max_snaplen_for_dlt(hdr.linktype);
+	}
 	p->linktype = linktype_to_dlt(LT_LINKTYPE(hdr.linktype));
 	p->linktype_ext = LT_LINKTYPE_EXT(hdr.linktype);
 
@@ -390,14 +379,16 @@
 
 	/*
 	 * 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) {
 		pcap_snprintf(errbuf, PCAP_ERRBUF_SIZE, "out of memory");
@@ -412,6 +403,24 @@
 }
 
 /*
+ * 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.
@@ -435,9 +444,8 @@
 	amt_read = fread(&sf_hdr, 1, ps->hdrsize, fp);
 	if (amt_read != ps->hdrsize) {
 		if (ferror(fp)) {
-			pcap_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) {
@@ -513,41 +521,87 @@
 		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.
-		 * This can also happen with a corrupted savefile or a
-		 * savefile built/modified by a fuzz tester.
-		 * If the caplen isn't grossly wrong, try to salvage.
+		 * 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.
 		 */
 		size_t bytes_to_discard;
 		size_t bytes_to_read, bytes_read;
 		char discard_buf[4096];
 
-		if (hdr->caplen > MAXIMUM_SNAPLEN) {
-			pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
-			    "invalid packet capture length %u, bigger than "
-			    "maximum of %u", hdr->caplen, MAXIMUM_SNAPLEN);
-			return (-1);
+		if (hdr->caplen > p->bufsize) {
+			/*
+			 * Grow the buffer to the snapshot length.
+			 */
+			if (!grow_buffer(p, p->snapshot))
+				return (-1);
 		}
 
 		/*
-		 * XXX - we don't grow the buffer here because some
-		 * program might assume that it will never get packets
-		 * bigger than the snapshot length; for example, it might
-		 * copy data from our buffer to a buffer of its own,
-		 * allocated based on the return value of pcap_snapshot().
-		 *
-		 * Read the first p->bufsize bytes into the buffer.
+		 * Read the first p->snapshot bytes into the buffer.
 		 */
-		amt_read = fread(p->buffer, 1, p->bufsize, fp);
-		if (amt_read != p->bufsize) {
+		amt_read = fread(p->buffer, 1, p->snapshot, fp);
+		if (amt_read != (bpf_u_int32)p->snapshot) {
 			if (ferror(fp)) {
-				pcap_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 {
 				/*
 				 * Yes, this uses hdr->caplen; technically,
@@ -558,7 +612,7 @@
 				 */
 				pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
 				    "truncated dump file; tried to read %u captured bytes, only got %lu",
-				    hdr->caplen, (unsigned long)amt_read);
+				    p->snapshot, (unsigned long)amt_read);
 			}
 			return (-1);
 		}
@@ -566,7 +620,7 @@
 		/*
 		 * Now read and discard what's left.
 		 */
-		bytes_to_discard = hdr->caplen - p->bufsize;
+		bytes_to_discard = hdr->caplen - p->snapshot;
 		bytes_read = amt_read;
 		while (bytes_to_discard != 0) {
 			bytes_to_read = bytes_to_discard;
@@ -576,9 +630,9 @@
 			bytes_read += amt_read;
 			if (amt_read != bytes_to_read) {
 				if (ferror(fp)) {
-					pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
-					    "error reading dump file: %s",
-					    pcap_strerror(errno));
+					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 %lu",
@@ -593,15 +647,41 @@
 		 * Adjust caplen accordingly, so we don't get confused later
 		 * as to how many bytes we have to play with.
 		 */
-		hdr->caplen = p->bufsize;
+		hdr->caplen = p->snapshot;
 	} else {
+		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)) {
-				pcap_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 {
 				pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
 				    "truncated dump file; tried to read %u captured bytes, only got %lu",
@@ -672,11 +752,11 @@
 	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) {
-		pcap_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);
@@ -721,14 +801,16 @@
 		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) {
-			pcap_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);
 		}
 	}
@@ -779,14 +861,15 @@
 	if (fname[0] == '-' && fname[1] == '\0')
 		return (pcap_setup_dump(p, linktype, stdout, "standard output"));
 
-#if !defined(_WIN32) && !defined(MSDOS)
-	f = fopen(fname, "r+");
-#else
+	/*
+	 * "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, "rb+");
-#endif
 	if (f == NULL) {
-		pcap_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);
 	}
 
@@ -796,8 +879,8 @@
 	amt_read = fread(&ph, 1, sizeof (ph), f);
 	if (amt_read != sizeof (ph)) {
 		if (ferror(f)) {
-			pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "%s: %s",
-			    fname, pcap_strerror(errno));
+			pcap_fmt_errmsg_for_errno(p->errbuf, PCAP_ERRBUF_SIZE,
+			    errno, "%s", fname);
 			fclose(f);
 			return (NULL);
 		} else if (feof(f) && amt_read > 0) {
@@ -813,7 +896,7 @@
 	 * We turn off buffering.
 	 * XXX - why?  And why not on the standard output?
 	 */
-	setbuf(f, NULL);
+	setvbuf(f, NULL, _IONBF, 0);
 #endif
 
 	/*
@@ -904,8 +987,8 @@
 		 * A header isn't present; attempt to write it.
 		 */
 		if (sf_write_header(p, f, linktype, p->tzoff, p->snapshot) == -1) {
-			pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "Can't write to %s: %s",
-			    fname, pcap_strerror(errno));
+			pcap_fmt_errmsg_for_errno(p->errbuf, PCAP_ERRBUF_SIZE,
+			    errno, "Can't write to %s", fname);
 			(void)fclose(f);
 			return (NULL);
 		}
@@ -915,8 +998,8 @@
 	 * Start writing at the end of the file.
 	 */
 	if (fseek(f, 0, SEEK_END) == -1) {
-		pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "Can't seek to end of %s: %s",
-		    fname, pcap_strerror(errno));
+		pcap_fmt_errmsg_for_errno(p->errbuf, PCAP_ERRBUF_SIZE,
+		    errno, "Can't seek to end of %s", fname);
 		(void)fclose(f);
 		return (NULL);
 	}
@@ -935,6 +1018,45 @@
 	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)
 {
diff --git a/sf-pcap-ng.c b/sf-pcapng.c
similarity index 86%
rename from sf-pcap-ng.c
rename to sf-pcapng.c
index 0c02829..8c8e93e 100644
--- a/sf-pcap-ng.c
+++ b/sf-pcapng.c
@@ -18,31 +18,14 @@
  * 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 @@
 #include "os-proto.h"
 #endif
 
-#include "sf-pcap-ng.h"
+#include "sf-pcapng.h"
 
 /*
  * Block types.
@@ -107,7 +90,7 @@
 	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 */
 };
 
@@ -214,19 +197,51 @@
  * Per-interface information.
  */
 struct pcap_ng_if {
-	u_int tsresol;			/* time stamp resolution */
+	uint64_t tsresol;		/* time stamp resolution */
 	tstamp_scale_type_t scale_type;	/* how to scale */
-	u_int scale_factor;		/* time stamp scale factor for power-of-10 tsresol */
-	u_int64_t tsoffset;		/* time stamp offset */
+	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 array below */
 	struct pcap_ng_if *ifaces;	/* array of interface information */
 };
 
+/*
+ * Maximum block size for a given maximum snapshot length; we calculate
+ * this based
+ *
+ * We define it as the size of an EPB with a max_snaplen-sized
+ * packet and 128KB of options.
+ */
+#define MAX_BLOCKSIZE(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);
@@ -240,9 +255,8 @@
 	amt_read = fread(buf, 1, bytes_to_read, fp);
 	if (amt_read != bytes_to_read) {
 		if (ferror(fp)) {
-			pcap_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 */
@@ -259,11 +273,14 @@
 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;
 	u_char *bdata;
 	size_t data_remaining;
 
+	ps = p->priv;
+
 	status = read_bytes(fp, &bhdr, sizeof(bhdr), 0, errbuf);
 	if (status <= 0)
 		return (status);	/* error or EOF */
@@ -282,7 +299,7 @@
 	 */
 	if (bhdr.total_length > 16*1024*1024) {
 		pcap_snprintf(errbuf, PCAP_ERRBUF_SIZE,
-		    "pcap-ng block size %u > maximum %u",
+		    "pcapng block size %u > maximum %u",
 		    bhdr.total_length, 16*1024*1024);
 		    return (-1);
 	}
@@ -294,7 +311,7 @@
 	if (bhdr.total_length < sizeof(struct block_header) +
 	    sizeof(struct block_trailer)) {
 		pcap_snprintf(errbuf, PCAP_ERRBUF_SIZE,
-		    "block in pcap-ng dump file has a length of %u < %lu",
+		    "block in pcapng dump file has a length of %u < %lu",
 		    bhdr.total_length,
 		    (unsigned long)(sizeof(struct block_header) + sizeof(struct block_trailer)));
 		return (-1);
@@ -305,10 +322,15 @@
 	 */
 	if (p->bufsize < bhdr.total_length) {
 		/*
-		 * No - make it big enough.
+		 * No - make it big enough, unless it's too big.
 		 */
 		void *bigger_buffer;
 
+		if (bhdr.total_length > ps->max_blocksize) {
+			pcap_snprintf(errbuf, PCAP_ERRBUF_SIZE, "block is larger than maximum block size %u",
+			    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");
@@ -348,7 +370,7 @@
 	 */
 	if (cursor->data_remaining < chunk_size) {
 		pcap_snprintf(errbuf, PCAP_ERRBUF_SIZE,
-		    "block of type %u in pcap-ng dump file is too short",
+		    "block of type %u in pcapng dump file is too short",
 		    cursor->block_type);
 		return (NULL);
 	}
@@ -409,13 +431,13 @@
 }
 
 static int
-process_idb_options(pcap_t *p, struct block_cursor *cursor, u_int *tsresol,
-    u_int64_t *tsoffset, int *is_binary, 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;
@@ -473,32 +495,43 @@
 				/*
 				 * Resolution is negative power of 2.
 				 */
+				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 = 1 << (tsresol_opt & 0x7F);
+				*tsresol = ((uint64_t)1) << tsresol_shift;
 			} else {
 				/*
 				 * Resolution is negative power of 10.
 				 */
+				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);
+				}
 				*is_binary = 0;
 				*tsresol = 1;
 				for (i = 0; i < tsresol_opt; i++)
 					*tsresol *= 10;
 			}
-			if (*tsresol == 0) {
-				/*
-				 * Resolution is too high.
-				 */
-				if (tsresol_opt & 0x80) {
-					pcap_snprintf(errbuf, PCAP_ERRBUF_SIZE,
-					    "Interface Description Block if_tsresol option resolution 2^-%u is too high",
-					    tsresol_opt & 0x7F);
-				} else {
-					pcap_snprintf(errbuf, PCAP_ERRBUF_SIZE,
-					    "Interface Description Block if_tsresol option resolution 10^-%u is too high",
-					    tsresol_opt);
-				}
-				return (-1);
-			}
 			break;
 
 		case IF_TSOFFSET:
@@ -532,8 +565,8 @@
 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;
@@ -567,7 +600,7 @@
 			 * However, it doesn't complain that one of the
 			 * multiplications below could overflow, which is
 			 * a real, albeit extremely unlikely, problem (you'd
-			 * need a pcap-ng file with tens of millions of
+			 * need a pcapng file with tens of millions of
 			 * interfaces).)
 			 */
 			new_ifaces_size = 1;
@@ -699,7 +732,7 @@
 }
 
 /*
- * 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 *
@@ -725,7 +758,7 @@
 
 	/*
 	 * 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) {
 		/*
@@ -734,7 +767,7 @@
 		 * 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 */
@@ -754,32 +787,30 @@
 	amt_read = fread(&total_length, 1, sizeof(total_length), fp);
 	if (amt_read < sizeof(total_length)) {
 		if (ferror(fp)) {
-			pcap_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)) {
-			pcap_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);
 	}
@@ -787,7 +818,7 @@
 		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);
 		}
@@ -800,7 +831,7 @@
 	 */
 	if (total_length < sizeof(*bhdrp) + sizeof(*shbp) + sizeof(struct block_trailer)) {
 		pcap_snprintf(errbuf, PCAP_ERRBUF_SIZE,
-		    "Section Header Block in pcap-ng dump file has a length of %u < %lu",
+		    "Section Header Block in pcapng dump file has a length of %u < %lu",
 		    total_length,
 		    (unsigned long)(sizeof(*bhdrp) + sizeof(*shbp) + sizeof(struct block_trailer)));
 		*err = 1;
@@ -808,7 +839,7 @@
 	}
 
 	/*
-	 * 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));
@@ -853,7 +884,11 @@
 	 *	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 based
+	 * on a maximum snapshot length of MAXIMUM_SNAPLEN; if we see
+	 * any link-layer header types with a larger maximum snapshot
+	 * length, we boost the maximum.
 	 */
 	p->bufsize = 2048;
 	if (p->bufsize < total_length)
@@ -865,6 +900,7 @@
 		*err = 1;
 		return (NULL);
 	}
+	ps->max_blocksize = MAX_BLOCKSIZE(MAXIMUM_SNAPLEN);
 
 	/*
 	 * Copy the stuff we've read to the buffer, and read the rest
@@ -896,7 +932,7 @@
 	if (! (shbp->major_version == PCAP_NG_VERSION_MAJOR &&
 	       shbp->minor_version == PCAP_NG_VERSION_MINOR)) {
 		pcap_snprintf(errbuf, PCAP_ERRBUF_SIZE,
-		    "unsupported pcap-ng savefile version %u.%u",
+		    "unsupported pcapng savefile version %u.%u",
 		    shbp->major_version, shbp->minor_version);
 		goto fail;
 	}
@@ -945,17 +981,6 @@
 			}
 
 			/*
-			 * Interface capture length sanity check
-			 */
-			if (idbp->snaplen > MAXIMUM_SNAPLEN) {
-				pcap_snprintf(errbuf, PCAP_ERRBUF_SIZE,
-				    "invalid interface capture length %u, "
-				    "bigger than maximum of %u",
-				    idbp->snaplen, MAXIMUM_SNAPLEN);
-				goto fail;
-			}
-
-			/*
 			 * Try to add this interface.
 			 */
 			if (!add_interface(p, &cursor, errbuf))
@@ -986,9 +1011,28 @@
 done:
 	p->tzoff = 0;	/* XXX - not used in pcap */
 	p->snapshot = idbp->snaplen;
+	if (p->snapshot <= 0) {
+		/*
+		 * Bogus snapshot length; use the maximum for this
+		 * link-layer type as a fallback.
+		 *
+		 * XXX - the only reason why snapshot is signed is
+		 * that pcap_snapshot() returns an int, not an
+		 * unsigned int.
+		 */
+		p->snapshot = max_snaplen_for_dlt(idbp->linktype);
+	}
 	p->linktype = linktype_to_dlt(idbp->linktype);
 	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(max_snaplen_for_dlt(p->linktype)) > ps->max_blocksize)
+		ps->max_blocksize = MAX_BLOCKSIZE(max_snaplen_for_dlt(p->linktype));
+
 	p->next_packet_op = pcap_ng_next_packet;
 	p->cleanup_op = pcap_ng_cleanup;
 
@@ -1029,7 +1073,7 @@
 	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,
@@ -1065,13 +1109,13 @@
 				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;
@@ -1130,13 +1174,13 @@
 				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;
@@ -1245,7 +1289,7 @@
 			 */
 			if (shbp->major_version != PCAP_NG_VERSION_MAJOR) {
 				pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
-				    "unknown pcap-ng savefile major version number %u",
+				    "unknown pcapng savefile major version number %u",
 				    shbp->major_version);
 				return (-1);
 			}
@@ -1284,6 +1328,13 @@
 		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 seconds and fractions of a second,
 	 * with the fractions being in units of the file-supplied resolution.
diff --git a/sf-pcap-ng.h b/sf-pcapng.h
similarity index 90%
rename from sf-pcap-ng.h
rename to sf-pcapng.h
index 3c93498..d99b0d4 100644
--- a/sf-pcap-ng.h
+++ b/sf-pcapng.h
@@ -18,13 +18,13 @@
  * 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,
     u_int precision, char *errbuf, int *err);
diff --git a/sockutils.c b/sockutils.c
index c05ff1a..ef3fe76 100644
--- a/sockutils.c
+++ b/sockutils.c
@@ -31,7 +31,7 @@
  */
 
 #ifdef HAVE_CONFIG_H
-#include "config.h"
+#include <config.h>
 #endif
 
 /*
@@ -50,7 +50,9 @@
  * ways.
  */
 
-#include <string.h>	/* for strerror() */
+#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() */
@@ -60,8 +62,10 @@
 #define INT_MAX		2147483647
 #endif
 
-#include "portability.h"
+#include "pcap-int.h"
+
 #include "sockutils.h"
+#include "portability.h"
 
 #ifdef _WIN32
   /*
@@ -88,6 +92,24 @@
 #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                        *
@@ -103,6 +125,53 @@
  ****************************************************/
 
 /*
+ * 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)
+{
+#ifdef _WIN32
+	int retval;
+	char message[SOCK_ERRBUF_SIZE];	/* We're forcing "ANSI" */
+
+	if (errbuf == NULL)
+		return;
+
+	retval = FormatMessageA(FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS |
+		FORMAT_MESSAGE_MAX_WIDTH_MASK,
+		NULL, errcode, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
+		message, sizeof(message) / sizeof(TCHAR), NULL);
+
+	if (retval == 0)
+	{
+		if ((caller) && (*caller))
+			pcap_snprintf(errbuf, errbuflen, "%sUnable to get the exact error message", caller);
+		else
+			pcap_snprintf(errbuf, errbuflen, "Unable to get the exact error message");
+	}
+	else
+	{
+		if ((caller) && (*caller))
+			pcap_snprintf(errbuf, errbuflen, "%s%s (code %d)", caller, message, errcode);
+		else
+			pcap_snprintf(errbuf, errbuflen, "%s (code %d)", message, errcode);
+	}
+#else
+	char *message;
+
+	if (errbuf == NULL)
+		return;
+
+	message = strerror(errcode);
+
+	if ((caller) && (*caller))
+		pcap_snprintf(errbuf, errbuflen, "%s%s (code %d)", caller, message, errcode);
+	else
+		pcap_snprintf(errbuf, errbuflen, "%s (code %d)", message, errcode);
+#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
@@ -125,47 +194,13 @@
 void sock_geterror(const char *caller, char *errbuf, int errbuflen)
 {
 #ifdef _WIN32
-	int retval;
-	int code;
-	TCHAR message[SOCK_ERRBUF_SIZE];	/* It will be char (if we're using ascii) or wchar_t (if we're using unicode) */
-
 	if (errbuf == NULL)
 		return;
-
-	code = GetLastError();
-
-	retval = FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS |
-		FORMAT_MESSAGE_MAX_WIDTH_MASK,
-		NULL, code, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
-		message, sizeof(message) / sizeof(TCHAR), NULL);
-
-	if (retval == 0)
-	{
-		if ((caller) && (*caller))
-			pcap_snprintf(errbuf, errbuflen, "%sUnable to get the exact error message", caller);
-		else
-			pcap_snprintf(errbuf, errbuflen, "Unable to get the exact error message");
-		return;
-	}
-	else
-	{
-		if ((caller) && (*caller))
-			pcap_snprintf(errbuf, errbuflen, "%s%s (code %d)", caller, message, code);
-		else
-			pcap_snprintf(errbuf, errbuflen, "%s (code %d)", message, code);
-	}
+	sock_fmterror(caller, GetLastError(), errbuf, errbuflen);
 #else
-	char *message;
-
 	if (errbuf == NULL)
 		return;
-
-	message = strerror(errno);
-
-	if ((caller) && (*caller))
-		pcap_snprintf(errbuf, errbuflen, "%s%s (code %d)", caller, message, errno);
-	else
-		pcap_snprintf(errbuf, errbuflen, "%s (code %d)", message, errno);
+	sock_fmterror(caller, errno, errbuf, errbuflen);
 #endif
 }
 
@@ -185,9 +220,9 @@
  * \return '0' if everything is fine, '-1' if some errors occurred. The error message is returned
  * in the 'errbuf' variable.
  */
+#ifdef _WIN32
 int sock_init(char *errbuf, int errbuflen)
 {
-#ifdef _WIN32
 	if (sockcount == 0)
 	{
 		WSADATA wsaData;			/* helper variable needed to initialize Winsock */
@@ -205,8 +240,10 @@
 	}
 
 	sockcount++;
+#else
+int sock_init(char *errbuf _U_, int errbuflen _U_)
+{
 #endif
-
 	return 0;
 }
 
@@ -277,56 +314,102 @@
  * larger than 'errbuflen - 1' because the last char is reserved for the string terminator.
  *
  * \return the socket that has been opened (that has to be used in the following sockets calls)
- * if everything is fine, '0' if some errors occurred. The error message is returned
+ * 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 == -1)
+	if (sock == INVALID_SOCKET)
 	{
 		sock_geterror("socket(): ", errbuf, errbuflen);
-		return -1;
+		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)
 	{
-#ifdef BSD
+#if defined(IPV6_V6ONLY) || defined(IPV6_BINDV6ONLY)
 		/*
-		 * Force the use of IPv6-only addresses; in BSD you can accept both v4 and v6
-		 * connections if you have a "NULL" pointer as the nodename in the getaddrinfo()
-		 * This behavior is not clear in the RFC 2553, so each system implements the
-		 * bind() differently from this point of view
+		 * 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)
 		{
-			int on;
-
-			if (setsockopt(sock, IPPROTO_IPV6, IPV6_BINDV6ONLY, (char *)&on, sizeof (int)) == -1)
+			if (setsockopt(sock, IPPROTO_IPV6, IPV6_V6ONLY,
+			    (char *)&on, sizeof (int)) == -1)
 			{
 				if (errbuf)
-					pcap_snprintf(errbuf, errbuflen, "setsockopt(IPV6_BINDV6ONLY)");
-				return -1;
+					pcap_snprintf(errbuf, errbuflen, "setsockopt(IPV6_V6ONLY)");
+				closesocket(sock);
+				return INVALID_SOCKET;
 			}
 		}
-#endif
+#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);
-			return -1;
+			closesocket(sock);
+			return INVALID_SOCKET;
 		}
 
 		if (addrinfo->ai_socktype == SOCK_STREAM)
 			if (listen(sock, nconn) == -1)
 			{
 				sock_geterror("listen(): ", errbuf, errbuflen);
-				return -1;
+				closesocket(sock);
+				return INVALID_SOCKET;
 			}
 
 		/* server side ended */
@@ -391,7 +474,7 @@
 		if (tempaddrinfo == NULL)
 		{
 			closesocket(sock);
-			return -1;
+			return INVALID_SOCKET;
 		}
 		else
 			return sock;
@@ -513,6 +596,8 @@
 	{
 		if (errbuf)
 			pcap_snprintf(errbuf, errbuflen, "getaddrinfo(): socket type not supported");
+		freeaddrinfo(*addrinfo);
+		*addrinfo = NULL;
 		return -1;
 	}
 
@@ -524,6 +609,8 @@
 	{
 		if (errbuf)
 			pcap_snprintf(errbuf, errbuflen, "getaddrinfo(): multicast addresses are not valid when using TCP streams");
+		freeaddrinfo(*addrinfo);
+		*addrinfo = NULL;
 		return -1;
 	}
 
@@ -552,39 +639,84 @@
  * \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.
+ * \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 socket, const char *buffer, int size, char *errbuf, int errbuflen)
+int sock_send(SOCKET sock, const char *buffer, size_t size,
+    char *errbuf, int errbuflen)
 {
-	int nsent;
+	int remaining;
+	ssize_t nsent;
 
-send:
-#ifdef linux
-	/*
-	 * Another pain... in Linux there's this flag
-	 * MSG_NOSIGNAL
-	 * Requests not to send SIGPIPE on errors on stream-oriented
-	 * sockets when the other end breaks the connection.
-	 * The EPIPE error is still returned.
-	 */
-	nsent = send(socket, buffer, size, MSG_NOSIGNAL);
-#else
-	nsent = send(socket, buffer, size, 0);
-#endif
-
-	if (nsent == -1)
+	if (size > INT_MAX)
 	{
-		sock_geterror("send(): ", errbuf, errbuflen);
+		if (errbuf)
+		{
+			pcap_snprintf(errbuf, errbuflen,
+			    "Can't send more than %u bytes with sock_recv",
+			    INT_MAX);
+		}
 		return -1;
 	}
+	remaining = (int)size;
 
-	if (nsent != size)
-	{
-		size -= nsent;
+	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;
-		goto send;
-	}
+	} while (remaining != 0);
 
 	return 0;
 }
@@ -682,9 +814,19 @@
  * \param size: size of the allocated buffer. WARNING: this indicates the number of bytes
  * that we are expecting to be read.
  *
- * \param receiveall: if '0' (or SOCK_RECEIVEALL_NO), it returns as soon as some data
- * is ready; otherwise, (or SOCK_RECEIVEALL_YES) it waits until 'size' data has been
- * received (in case the socket does not have enough data available).
+ * \param 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.
@@ -697,17 +839,7 @@
  * The error message is returned in the 'errbuf' variable.
  */
 
-/*
- * On UN*X, recv() returns ssize_t.
- * On Windows, there *is* no ssize_t, and it returns an int.
- * Define ssize_t as int on Windows so we can use it as the return value
- * from recv().
- */
-#ifdef _WIN32
-typedef int ssize_t;
-#endif
-
-int sock_recv(SOCKET sock, void *buffer, size_t size, int receiveall,
+int sock_recv(SOCKET sock, void *buffer, size_t size, int flags,
     char *errbuf, int errbuflen)
 {
 	char *bufp = buffer;
@@ -716,13 +848,17 @@
 
 	if (size == 0)
 	{
-		SOCK_ASSERT("I have been requested to read zero bytes", 1);
+		SOCK_DEBUG_MESSAGE("I have been requested to read zero bytes");
 		return 0;
 	}
 	if (size > INT_MAX)
 	{
-		pcap_snprintf(errbuf, errbuflen, "Can't read more than %u bytes with sock_recv",
-		    INT_MAX);
+		if (errbuf)
+		{
+			pcap_snprintf(errbuf, errbuflen,
+			    "Can't read more than %u bytes with sock_recv",
+			    INT_MAX);
+		}
 		return -1;
 	}
 
@@ -748,19 +884,30 @@
 
 		if (nread == 0)
 		{
-			if (errbuf)
+			if ((flags & SOCK_EOF_IS_ERROR) ||
+			    (remaining != (int) size))
 			{
-				pcap_snprintf(errbuf, errbuflen,
-				    "The other host terminated the connection.");
+				/*
+				 * 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;
 			}
-			return -1;
+			else
+				return 0;
 		}
 
 		/*
 		 * Do we want to read the amount requested, or just return
 		 * what we got?
 		 */
-		if (!receiveall)
+		if (!(flags & SOCK_RECEIVEALL_YES))
 		{
 			/*
 			 * Just return what we got.
@@ -777,6 +924,121 @@
 }
 
 /*
+ * 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)
+	{
+		SOCK_DEBUG_MESSAGE("I have been requested to read zero bytes");
+		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.
@@ -833,7 +1095,7 @@
 			return -1;
 	}
 
-	SOCK_ASSERT("I'm currently discarding data\n", 1);
+	SOCK_DEBUG_MESSAGE("I'm currently discarding data\n");
 
 	return 0;
 }
@@ -908,7 +1170,7 @@
 				if (errbuf)
 					pcap_snprintf(errbuf, errbuflen, "getaddrinfo() %s", gai_strerror(retval));
 
-				SOCK_ASSERT(errbuf, 1);
+				SOCK_DEBUG_MESSAGE(errbuf);
 
 				/* Get next token */
 				token = pcap_strtok_r(NULL, sep, &lasts);
@@ -922,6 +1184,7 @@
 				if (sock_cmpaddr(from, (struct sockaddr_storage *) ai_next->ai_addr) == 0)
 				{
 					free(temphostlist);
+					freeaddrinfo(addrinfo);
 					return 0;
 				}
 
@@ -1051,13 +1314,9 @@
 		sock_geterror("getsockname(): ", errbuf, errbuflen);
 		return 0;
 	}
-	else
-	{
-		/* Returns the numeric address of the host that triggered the error */
-		return sock_getascii_addrport(&mysockaddr, address, addrlen, port, portlen, flags, errbuf, errbuflen);
-	}
 
-	return 0;
+	/* Returns the numeric address of the host that triggered the error */
+	return sock_getascii_addrport(&mysockaddr, address, addrlen, port, portlen, flags, errbuf, errbuflen);
 }
 
 /*
diff --git a/sockutils.h b/sockutils.h
index f50bbce..1df1ef7 100644
--- a/sockutils.h
+++ b/sockutils.h
@@ -33,25 +33,26 @@
 #ifndef __SOCKUTILS_H__
 #define __SOCKUTILS_H__
 
-#if _MSC_VER > 1000
+#ifdef _MSC_VER
 #pragma once
 #endif
 
 #ifdef _WIN32
-  /* Windows */
-  /*
-   * Prevents a compiler warning in case this was already defined (to
-   * avoid that windows.h includes winsock.h)
-   */
-  #ifdef _WINSOCKAPI_
-    #undef _WINSOCKAPI_
-  #endif
   /* Need windef.h for defines used in winsock2.h under MingW32 */
   #ifdef __MINGW32__
     #include <windef.h>
   #endif
   #include <winsock2.h>
   #include <ws2tcpip.h>
+
+  /*
+   * 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;
 #else
   /* UN*X */
   #include <stdio.h>
@@ -84,6 +85,14 @@
   #ifndef INVALID_SOCKET
     #define INVALID_SOCKET -1
   #endif
+
+  /*!
+   * \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
 
 /*
@@ -114,28 +123,6 @@
  */
 
 /*
- * Some minor differences between UN*X sockets and and Winsock sockets.
- */
-#ifdef _WIN32
-  /*
-   * Winsock doesn't have these UN*X types; they're used in the UN*X
-   * sockets API.
-   *
-   * XXX - do we need to worry about UN*Xes so old that *they* don't
-   * have them, either?
-   */
-  typedef int socklen_t;
-#else
-  /*!
-   * \brief In Winsock, the close() call cannot be used on a socket;
-   * closesocket() must be used.
-   * We define closesocket() to be a wrapper around close() on UN*X,
-   * so that it can be used on both platforms.
-   */
-  #define closesocket(a) close(a)
-#endif
-
-/*
  * \brief DEBUG facility: it prints an error message on the screen (stderr)
  *
  * This macro prints the error on the standard error stream (stderr);
@@ -152,16 +139,15 @@
  * \return No return values.
  */
 #ifdef NDEBUG
-  #define SOCK_ASSERT(msg, expr) ((void)0)
+  #define SOCK_DEBUG_MESSAGE(msg) ((void)0)
 #else
-  #include <assert.h>
   #if (defined(_WIN32) && defined(_MSC_VER))
     #include <crtdbg.h>				/* for _CrtDbgReport */
     /* Use MessageBox(NULL, msg, "warning", MB_OK)' instead of the other calls if you want to debug a Win32 service */
     /* Remember to activate the 'allow service to interact with desktop' flag of the service */
-    #define SOCK_ASSERT(msg, expr) { _CrtDbgReport(_CRT_WARN, NULL, 0, NULL, "%s\n", msg); fprintf(stderr, "%s\n", msg); assert(expr); }
+    #define SOCK_DEBUG_MESSAGE(msg) { _CrtDbgReport(_CRT_WARN, NULL, 0, NULL, "%s\n", msg); fprintf(stderr, "%s\n", msg); }
   #else
-    #define SOCK_ASSERT(msg, expr) { fprintf(stderr, "%s\n", msg); assert(expr); }
+    #define SOCK_DEBUG_MESSAGE(msg) { fprintf(stderr, "%s\n", msg); }
   #endif
 #endif
 
@@ -181,10 +167,14 @@
 /* 'server' flag; it opens a server socket */
 #define SOCKOPEN_SERVER 1
 
-/* Changes the behaviour of the sock_recv(); it does not wait to receive all data */
-#define SOCK_RECEIVEALL_NO 0
-/* Changes the behaviour of the sock_recv(); it waits to receive all data */
-#define SOCK_RECEIVEALL_YES 1
+/*
+ * 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 */
 
 /*
  * \}
@@ -205,19 +195,22 @@
 
 int sock_init(char *errbuf, int errbuflen);
 void sock_cleanup(void);
-/* It is 'public' because there are calls (like accept() ) which are not managed from inside the sockutils files */
+void sock_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 socket, void *buffer, size_t size, int receiveall,
+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 socket, const char *buffer, int size, 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 socket, int size, 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);
 
diff --git a/testprogs/.gitignore b/testprogs/.gitignore
new file mode 100644
index 0000000..b9178b4
--- /dev/null
+++ b/testprogs/.gitignore
@@ -0,0 +1,13 @@
+Makefile
+*~
+*.dSYM
+*.o
+valgrindtest
+capturetest
+can_set_rfmon_test
+filtertest
+findalldevstest
+opentest
+reactivatetest
+selpolltest
+threadsignaltest
diff --git a/testprogs/BPF/1.txt b/testprogs/BPF/1.txt
new file mode 100644
index 0000000..6608695
--- /dev/null
+++ b/testprogs/BPF/1.txt
@@ -0,0 +1,2 @@
+# common block merging, same block elimination, result propogation
+host 192.168.1.1
diff --git a/testprogs/BPF/2.txt b/testprogs/BPF/2.txt
new file mode 100644
index 0000000..e9bc116
--- /dev/null
+++ b/testprogs/BPF/2.txt
@@ -0,0 +1,2 @@
+# common block merging
+port 80
diff --git a/testprogs/BPF/3.txt b/testprogs/BPF/3.txt
new file mode 100644
index 0000000..6c08d3d
--- /dev/null
+++ b/testprogs/BPF/3.txt
@@ -0,0 +1 @@
+tcp[tcpflags]&tcp-syn != 0 or tcp[tcpflags]&tcp-fin != 0 or tcp[tcpflags]&tcp-rst != 0
diff --git a/testprogs/BPF/4.txt b/testprogs/BPF/4.txt
new file mode 100644
index 0000000..3fd2e66
--- /dev/null
+++ b/testprogs/BPF/4.txt
@@ -0,0 +1,2 @@
+# or pullup
+ether[12:2] = 0x800 or ether[12:2] = 0x8100 or ether[0] & 0x80 != 0 or ether[12:2] = 0x9100
diff --git a/testprogs/BPF/5.txt b/testprogs/BPF/5.txt
new file mode 100644
index 0000000..23fc0ca
--- /dev/null
+++ b/testprogs/BPF/5.txt
@@ -0,0 +1 @@
+vlan 186 and ip
diff --git a/testprogs/BPF/6.txt b/testprogs/BPF/6.txt
new file mode 100644
index 0000000..694c185
--- /dev/null
+++ b/testprogs/BPF/6.txt
@@ -0,0 +1 @@
+ip and ((icmp and dst host 1.1.1.1 and not host 2.2.2.2) or (host 1.1.1.1 and src host 3.3.3.3))
diff --git a/testprogs/BPF/7.txt b/testprogs/BPF/7.txt
new file mode 100644
index 0000000..33978a4
--- /dev/null
+++ b/testprogs/BPF/7.txt
@@ -0,0 +1 @@
+not vlan and tcp port 80
diff --git a/testprogs/CMakeLists.txt b/testprogs/CMakeLists.txt
new file mode 100644
index 0000000..b8ef9b7
--- /dev/null
+++ b/testprogs/CMakeLists.txt
@@ -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
index 0000000..ec0a472
--- /dev/null
+++ b/testprogs/Makefile.in
@@ -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/tests/can_set_rfmon_test.c b/testprogs/can_set_rfmon_test.c
similarity index 94%
rename from tests/can_set_rfmon_test.c
rename to testprogs/can_set_rfmon_test.c
index f1644e6..f6188ba 100644
--- a/tests/can_set_rfmon_test.c
+++ b/testprogs/can_set_rfmon_test.c
@@ -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\
@@ -32,10 +34,12 @@
 
 #include <pcap.h>
 
+#include "pcap/funcattrs.h"
+
 static const char *program_name;
 
 /* Forwards */
-static void error(const char *, ...);
+static void PCAP_NORETURN error(PCAP_FORMAT_STRING(const char *), ...) PCAP_PRINTFLIKE(1,2);
 
 int
 main(int argc, char **argv)
diff --git a/tests/capturetest.c b/testprogs/capturetest.c
similarity index 78%
rename from tests/capturetest.c
rename to testprogs/capturetest.c
index 14b1554..d625cb4 100644
--- a/tests/capturetest.c
+++ b/testprogs/capturetest.c
@@ -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\
@@ -31,66 +33,23 @@
 #include <stdarg.h>
 #include <limits.h>
 #ifdef _WIN32
-#include "getopt.h"
+  #include "getopt.h"
 #else
-#include <unistd.h>
+  #include <unistd.h>
 #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;
 
-/*
- * This was introduced by Clang:
- *
- *     http://clang.llvm.org/docs/LanguageExtensions.html#has-attribute
- *
- * in some version (which version?); it has been picked up by GCC 5.0.
- */
-#ifndef __has_attribute
-  /*
-   * It's a macro, so you can check whether it's defined to check
-   * whether it's supported.
-   *
-   * If it's not, define it to always return 0, so that we move on to
-   * the fallback checks.
-   */
-  #define __has_attribute(x) 0
-#endif
-
-#if __has_attribute(noreturn) \
-    || (defined(__GNUC__) && ((__GNUC__ * 100 + __GNUC_MINOR__) >= 205)) \
-    || (defined(__SUNPRO_C) && (__SUNPRO_C >= 0x590)) \
-    || (defined(__xlC__) && __xlC__ >= 0x0A01) \
-    || (defined(__HP_aCC) && __HP_aCC >= 61000)
-  /*
-   * Compiler with support for it, or GCC 2.5 and later, or Solaris Studio 12
-   * (Sun C 5.9) and later, or IBM XL C 10.1 and later (do any earlier
-   * versions of XL C support this?), or HP aCC A.06.10 and later.
-   */
-  #define PCAP_NORETURN __attribute((noreturn))
-#elif defined( _MSC_VER )
-  #define PCAP_NORETURN __declspec(noreturn)
-#else
-  #define PCAP_NORETURN
-#endif
-
-#if __has_attribute(__format__) \
-    || (defined(__GNUC__) && ((__GNUC__ * 100 + __GNUC_MINOR__) >= 203)) \
-    || (defined(__xlC__) && __xlC__ >= 0x0A01) \
-    || (defined(__HP_aCC) && __HP_aCC >= 61000)
-  /*
-   * Compiler with support for it, or GCC 2.3 and later, or IBM XL C 10.1
-   * and later (do any earlier versions of XL C support this?),
-   * or HP aCC A.06.10 and later.
-   */
-  #define PCAP_PRINTFLIKE(x,y) __attribute__((__format__(__printf__,x,y)))
-#else
-  #define PCAP_PRINTFLIKE(x,y)
-#endif
-
 /* Forwards */
 static void countme(u_char *, const struct pcap_pkthdr *, const u_char *);
 static void PCAP_NORETURN usage(void);
@@ -110,6 +69,7 @@
 	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];
@@ -164,9 +124,12 @@
 	}
 
 	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);
@@ -244,11 +207,13 @@
 		    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;
 
diff --git a/tests/filtertest.c b/testprogs/filtertest.c
similarity index 72%
rename from tests/filtertest.c
rename to testprogs/filtertest.c
index d4440eb..7e2d6d6 100644
--- a/tests/filtertest.c
+++ b/testprogs/filtertest.c
@@ -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 @@
 #endif
 
 #ifdef HAVE_CONFIG_H
-#include "config.h"
+#include <config.h>
 #endif
 
 #include <pcap.h>
@@ -35,68 +37,35 @@
 #include <string.h>
 #include <stdarg.h>
 #ifdef _WIN32
-#include "getopt.h"
+  #include "getopt.h"
+  #include "unix.h"
 #else
-#include <unistd.h>
+  #include <unistd.h>
 #endif
 #include <fcntl.h>
 #include <errno.h>
 #ifdef _WIN32
   #include <winsock2.h>
-  typedef unsigned __int32 in_addr_t;
+  #include <ws2tcpip.h>
 #else
+  #include <sys/socket.h>
   #include <arpa/inet.h>
 #endif
 #include <sys/types.h>
 #include <sys/stat.h>
 
+#include "pcap/funcattrs.h"
+
+#ifdef BDEBUG
 /*
- * 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.
+ * 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).
  */
-#ifndef __has_attribute
-  /*
-   * It's a macro, so you can check whether it's defined to check
-   * whether it's supported.
-   *
-   * If it's not, define it to always return 0, so that we move on to
-   * the fallback checks.
-   */
-  #define __has_attribute(x) 0
-#endif
-
-#if __has_attribute(noreturn) \
-    || (defined(__GNUC__) && ((__GNUC__ * 100 + __GNUC_MINOR__) >= 205)) \
-    || (defined(__SUNPRO_C) && (__SUNPRO_C >= 0x590)) \
-    || (defined(__xlC__) && __xlC__ >= 0x0A01) \
-    || (defined(__HP_aCC) && __HP_aCC >= 61000)
-  /*
-   * Compiler with support for it, or GCC 2.5 and later, or Solaris Studio 12
-   * (Sun C 5.9) and later, or IBM XL C 10.1 and later (do any earlier
-   * versions of XL C support this?), or HP aCC A.06.10 and later.
-   */
-  #define PCAP_NORETURN __attribute((noreturn))
-#elif defined( _MSC_VER )
-  #define PCAP_NORETURN __declspec(noreturn)
-#else
-  #define PCAP_NORETURN
-#endif
-
-#if __has_attribute(__format__) \
-    || (defined(__GNUC__) && ((__GNUC__ * 100 + __GNUC_MINOR__) >= 203)) \
-    || (defined(__xlC__) && __xlC__ >= 0x0A01) \
-    || (defined(__HP_aCC) && __HP_aCC >= 61000)
-  /*
-   * Compiler with support for it, or GCC 2.3 and later, or IBM XL C 10.1
-   * and later (do any earlier versions of XL C support this?),
-   * or HP aCC A.06.10 and later.
-   */
-  #define PCAP_PRINTFLIKE(x,y) __attribute__((__format__(__printf__,x,y)))
-#else
-  #define PCAP_PRINTFLIKE(x,y)
+PCAP_API void pcap_set_optimizer_debug(int);
+PCAP_API void pcap_set_print_dot_graph(int);
 #endif
 
 static char *program_name;
@@ -106,10 +75,6 @@
 static void PCAP_NORETURN error(const char *, ...) PCAP_PRINTFLIKE(1, 2);
 static void warn(const char *, ...) PCAP_PRINTFLIKE(1, 2);
 
-#ifdef BDEBUG
-int dflag;
-#endif
-
 /*
  * On Windows, we need to open the file in binary mode, so that
  * we get all the bytes specified by the size we get from "fstat()".
@@ -230,32 +195,27 @@
 {
 	char *cp;
 	int op;
-#ifndef BDEBUG
 	int dflag;
-#endif
+	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;
+	if (pcap_wsockinit() != 0)
+		return 1;
 #endif /* _WIN32 */
 
-#ifndef BDEBUG
 	dflag = 1;
-#else
-	/* if optimizer debugging is enabled, output DOT graph
-	 * `dflag=4' is equivalent to -dddd to follow -d/-dd/-ddd
-	 * convention in tcpdump command line
-	 */
-	dflag = 4;
-#endif
+	gflag = 0;
+
 	infile = NULL;
 	Oflag = 1;
 	snaplen = 68;
@@ -266,13 +226,21 @@
 		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;
@@ -282,12 +250,23 @@
 			break;
 
 		case 'm': {
-			in_addr_t addr;
+			bpf_u_int32 addr;
 
-			addr = inet_addr(optarg);
-			if (addr == (in_addr_t)(-1))
+			switch (inet_pton(AF_INET, optarg, &addr)) {
+
+			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;
 		}
 
@@ -326,6 +305,11 @@
 	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");
@@ -333,21 +317,28 @@
 	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
-	// replace line feed with space
-	for (cp = cmdbuf; *cp != '\0'; ++cp) {
-		if (*cp == '\r' || *cp == '\n') {
-			*cp = ' ';
+	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);
+		// 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);
 }
@@ -358,7 +349,11 @@
 	(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
index 0000000..e535e25
--- /dev/null
+++ b/testprogs/findalldevstest.c
@@ -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];
+}
diff --git a/tests/opentest.c b/testprogs/opentest.c
similarity index 75%
rename from tests/opentest.c
rename to testprogs/opentest.c
index b6d634f..bad38eb 100644
--- a/tests/opentest.c
+++ b/testprogs/opentest.c
@@ -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\
@@ -31,65 +33,22 @@
 #include <string.h>
 #include <stdarg.h>
 #ifdef _WIN32
-#include "getopt.h"
+  #include "getopt.h"
 #else
-#include <unistd.h>
+  #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;
 
-/*
- * This was introduced by Clang:
- *
- *     http://clang.llvm.org/docs/LanguageExtensions.html#has-attribute
- *
- * in some version (which version?); it has been picked up by GCC 5.0.
- */
-#ifndef __has_attribute
-  /*
-   * It's a macro, so you can check whether it's defined to check
-   * whether it's supported.
-   *
-   * If it's not, define it to always return 0, so that we move on to
-   * the fallback checks.
-   */
-  #define __has_attribute(x) 0
-#endif
-
-#if __has_attribute(noreturn) \
-    || (defined(__GNUC__) && ((__GNUC__ * 100 + __GNUC_MINOR__) >= 205)) \
-    || (defined(__SUNPRO_C) && (__SUNPRO_C >= 0x590)) \
-    || (defined(__xlC__) && __xlC__ >= 0x0A01) \
-    || (defined(__HP_aCC) && __HP_aCC >= 61000)
-  /*
-   * Compiler with support for it, or GCC 2.5 and later, or Solaris Studio 12
-   * (Sun C 5.9) and later, or IBM XL C 10.1 and later (do any earlier
-   * versions of XL C support this?), or HP aCC A.06.10 and later.
-   */
-  #define PCAP_NORETURN __attribute((noreturn))
-#elif defined( _MSC_VER )
-  #define PCAP_NORETURN __declspec(noreturn)
-#else
-  #define PCAP_NORETURN
-#endif
-
-#if __has_attribute(__format__) \
-    || (defined(__GNUC__) && ((__GNUC__ * 100 + __GNUC_MINOR__) >= 203)) \
-    || (defined(__xlC__) && __xlC__ >= 0x0A01) \
-    || (defined(__HP_aCC) && __HP_aCC >= 61000)
-  /*
-   * Compiler with support for it, or GCC 2.3 and later, or IBM XL C 10.1
-   * and later (do any earlier versions of XL C support this?),
-   * or HP aCC A.06.10 and later.
-   */
-  #define PCAP_PRINTFLIKE(x,y) __attribute__((__format__(__printf__,x,y)))
-#else
-  #define PCAP_PRINTFLIKE(x,y)
-#endif
-
 /* Forwards */
 static void PCAP_NORETURN usage(void);
 static void PCAP_NORETURN error(const char *, ...) PCAP_PRINTFLIKE(1, 2);
@@ -102,6 +61,7 @@
 	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;
 
@@ -163,9 +123,12 @@
 	}
 
 	if (device == NULL) {
-		device = pcap_lookupdev(ebuf);
-		if (device == NULL)
-			error("pcap_lookupdev failed: %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 (useactivate) {
 		pd = pcap_create(device, ebuf);
diff --git a/testprogs/pcap_compile_test.c b/testprogs/pcap_compile_test.c
new file mode 100644
index 0000000..924ec73
--- /dev/null
+++ b/testprogs/pcap_compile_test.c
@@ -0,0 +1,11 @@
+   pcap = pcap_open_dead(link, snaplen);
+   /* todo: hook together argv to a single string */
+   prog = argv[0];
+   if (pcap_compile(pcap, &p, prog, optimize, 0) < 0) {
+      fprintf(stderr, pcap_geterr(pcap));
+      exit(1);
+   }
+   bpf_dump(&p, option);
+   pcap_freecode(&p);
+   pcap_close(pcap);
+
diff --git a/tests/reactivatetest.c b/testprogs/reactivatetest.c
similarity index 94%
rename from tests/reactivatetest.c
rename to testprogs/reactivatetest.c
index 2e1b7b6..d7f3e32 100644
--- a/tests/reactivatetest.c
+++ b/testprogs/reactivatetest.c
@@ -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\
@@ -31,8 +33,10 @@
 #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)
diff --git a/tests/selpolltest.c b/testprogs/selpolltest.c
similarity index 62%
rename from tests/selpolltest.c
rename to testprogs/selpolltest.c
index 4c1415b..329281d 100644
--- a/tests/selpolltest.c
+++ b/testprogs/selpolltest.c
@@ -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\
@@ -48,56 +50,9 @@
 #endif
 #include <poll.h>
 
-char *program_name;
+#include "pcap/funcattrs.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
-
-#if __has_attribute(noreturn) \
-    || (defined(__GNUC__) && ((__GNUC__ * 100 + __GNUC_MINOR__) >= 205)) \
-    || (defined(__SUNPRO_C) && (__SUNPRO_C >= 0x590)) \
-    || (defined(__xlC__) && __xlC__ >= 0x0A01) \
-    || (defined(__HP_aCC) && __HP_aCC >= 61000)
-  /*
-   * Compiler with support for it, or GCC 2.5 and later, or Solaris Studio 12
-   * (Sun C 5.9) and later, or IBM XL C 10.1 and later (do any earlier
-   * versions of XL C support this?), or HP aCC A.06.10 and later.
-   */
-  #define PCAP_NORETURN __attribute((noreturn))
-#elif defined( _MSC_VER )
-  #define PCAP_NORETURN __declspec(noreturn)
-#else
-  #define PCAP_NORETURN
-#endif
-
-#if __has_attribute(__format__) \
-    || (defined(__GNUC__) && ((__GNUC__ * 100 + __GNUC_MINOR__) >= 203)) \
-    || (defined(__xlC__) && __xlC__ >= 0x0A01) \
-    || (defined(__HP_aCC) && __HP_aCC >= 61000)
-  /*
-   * Compiler with support for it, or GCC 2.3 and later, or IBM XL C 10.1
-   * and later (do any earlier versions of XL C support this?),
-   * or HP aCC A.06.10 and later.
-   */
-  #define PCAP_PRINTFLIKE(x,y) __attribute__((__format__(__printf__,x,y)))
-#else
-  #define PCAP_PRINTFLIKE(x,y)
-#endif
+static char *program_name;
 
 /* Forwards */
 static void countme(u_char *, const struct pcap_pkthdr *, const u_char *);
@@ -115,15 +70,19 @@
 	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)
@@ -141,10 +100,12 @@
 
 		case 's':
 			doselect = 1;
+			mechanism = "select() and pcap_dispatch()";
 			break;
 
 		case 'p':
 			dopoll = 1;
+			mechanism = "poll() and pcap_dispatch()";
 			break;
 
 		case 't':
@@ -170,9 +131,12 @@
 		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);
@@ -189,58 +153,112 @@
 
 	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 if (required_timeout != NULL) {
+				seltimeout = *required_timeout;
 				status = select(selectable_fd + 1, &setread,
 				    NULL, &setexcept, &seltimeout);
 			} else {
-				status = select(selectable_fd + 1, &setread,
+				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) {
@@ -252,41 +270,59 @@
 			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 {
@@ -321,7 +357,7 @@
 }
 
 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/tests/capturetest.c b/testprogs/threadsignaltest.c
similarity index 61%
copy from tests/capturetest.c
copy to testprogs/threadsignaltest.c
index 14b1554..a60bb49 100644
--- a/tests/capturetest.c
+++ b/testprogs/threadsignaltest.c
@@ -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\
@@ -31,66 +33,36 @@
 #include <stdarg.h>
 #include <limits.h>
 #ifdef _WIN32
-#include "getopt.h"
+  #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 <unistd.h>
+  #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;
 
-/*
- * This was introduced by Clang:
- *
- *     http://clang.llvm.org/docs/LanguageExtensions.html#has-attribute
- *
- * in some version (which version?); it has been picked up by GCC 5.0.
- */
-#ifndef __has_attribute
-  /*
-   * It's a macro, so you can check whether it's defined to check
-   * whether it's supported.
-   *
-   * If it's not, define it to always return 0, so that we move on to
-   * the fallback checks.
-   */
-  #define __has_attribute(x) 0
-#endif
-
-#if __has_attribute(noreturn) \
-    || (defined(__GNUC__) && ((__GNUC__ * 100 + __GNUC_MINOR__) >= 205)) \
-    || (defined(__SUNPRO_C) && (__SUNPRO_C >= 0x590)) \
-    || (defined(__xlC__) && __xlC__ >= 0x0A01) \
-    || (defined(__HP_aCC) && __HP_aCC >= 61000)
-  /*
-   * Compiler with support for it, or GCC 2.5 and later, or Solaris Studio 12
-   * (Sun C 5.9) and later, or IBM XL C 10.1 and later (do any earlier
-   * versions of XL C support this?), or HP aCC A.06.10 and later.
-   */
-  #define PCAP_NORETURN __attribute((noreturn))
-#elif defined( _MSC_VER )
-  #define PCAP_NORETURN __declspec(noreturn)
-#else
-  #define PCAP_NORETURN
-#endif
-
-#if __has_attribute(__format__) \
-    || (defined(__GNUC__) && ((__GNUC__ * 100 + __GNUC_MINOR__) >= 203)) \
-    || (defined(__xlC__) && __xlC__ >= 0x0A01) \
-    || (defined(__HP_aCC) && __HP_aCC >= 61000)
-  /*
-   * Compiler with support for it, or GCC 2.3 and later, or IBM XL C 10.1
-   * and later (do any earlier versions of XL C support this?),
-   * or HP aCC A.06.10 and later.
-   */
-  #define PCAP_PRINTFLIKE(x,y) __attribute__((__format__(__printf__,x,y)))
-#else
-  #define PCAP_PRINTFLIKE(x,y)
-#endif
-
 /* Forwards */
 static void countme(u_char *, const struct pcap_pkthdr *, const u_char *);
 static void PCAP_NORETURN usage(void);
@@ -100,21 +72,126 @@
 
 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;
-	long longarg;
-	char *p;
-	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];
 	int status;
-	int packet_count;
+	THREAD_HANDLE capture_thread;
+#ifndef _WIN32
+	void *retval;
+#endif
 
 	device = NULL;
 	if ((cp = strrchr(argv[0], '/')) != NULL)
@@ -123,40 +200,13 @@
 		program_name = argv[0];
 
 	opterr = 0;
-	while ((op = getopt(argc, argv, "i:mnt:")) != -1) {
+	while ((op = getopt(argc, argv, "i:")) != -1) {
 		switch (op) {
 
 		case 'i':
 			device = optarg;
 			break;
 
-		case 'm':
-			immediate = 1;
-			break;
-
-		case 'n':
-			nonblock = 1;
-			break;
-
-		case 't':
-			longarg = strtol(optarg, &p, 10);
-			if (p == optarg || *p != '\0') {
-				error("Timeout value \"%s\" is not a number",
-				    optarg);
-				/* NOTREACHED */
-			}
-			if (longarg < 0) {
-				error("Timeout value %ld is negative", longarg);
-				/* NOTREACHED */
-			}
-			if (longarg > INT_MAX) {
-				error("Timeout value %ld is too large (> %d)",
-				    longarg, INT_MAX);
-				/* NOTREACHED */
-			}
-			timeout = (int)longarg;
-			break;
-
 		default:
 			usage();
 			/* NOTREACHED */
@@ -164,9 +214,12 @@
 	}
 
 	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);
@@ -182,7 +235,7 @@
 			error("%s: pcap_set_immediate_mode failed: %s",
 			    device, pcap_statustostr(status));
 	}
-	status = pcap_set_timeout(pd, timeout);
+	status = pcap_set_timeout(pd, 5*60*1000);
 	if (status != 0)
 		error("%s: pcap_set_timeout failed: %s",
 		    device, pcap_statustostr(status));
@@ -213,42 +266,48 @@
 
 	if (pcap_setfilter(pd, &fcode) < 0)
 		error("%s", pcap_geterr(pd));
-	if (pcap_setnonblock(pd, nonblock, ebuf) == -1)
-		error("pcap_setnonblock failed: %s", ebuf);
-	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);
-		}
-	}
-	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');
-	}
-	(void)fflush(stdout);
-	if (status == -1) {
-		/*
-		 * Error.  Report it.
-		 */
-		(void)fprintf(stderr, "%s: pcap_loop: %s\n",
-		    program_name, 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, const u_char *sp)
+countme(u_char *user, const struct pcap_pkthdr *h _U_, const u_char *sp _U_)
 {
 	int *counterp = (int *)user;
 
@@ -258,7 +317,7 @@
 static void
 usage(void)
 {
-	(void)fprintf(stderr, "Usage: %s [ -mn ] [ -i interface ] [ -t timeout] [expression]\n",
+	(void)fprintf(stderr, "Usage: %s [ -m ] [ -i interface ] [ -t timeout] [expression]\n",
 	    program_name);
 	exit(1);
 }
diff --git a/testprogs/unix.h b/testprogs/unix.h
new file mode 100644
index 0000000..68ef4cb
--- /dev/null
+++ b/testprogs/unix.h
@@ -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
diff --git a/tests/valgrindtest.c b/testprogs/valgrindtest.c
similarity index 84%
rename from tests/valgrindtest.c
rename to testprogs/valgrindtest.c
index 011fe11..104ef6a 100644
--- a/tests/valgrindtest.c
+++ b/testprogs/valgrindtest.c
@@ -19,6 +19,8 @@
  * 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,
@@ -33,14 +35,14 @@
  *
  *	https://bugs.kde.org/show_bug.cgi?id=318203
  *
- * and valgrind bug 312989 for OS X:
+ * 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 OS X
+ * The unofficial FreeBSD port has similar issues to the official macOS
  * port, for similar reasons.
  */
 #ifndef lint
@@ -50,7 +52,7 @@
 #endif
 
 #ifdef HAVE_CONFIG_H
-#include "config.h"
+#include <config.h>
 #endif
 
 #include <stdio.h>
@@ -64,8 +66,10 @@
 #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 */
@@ -99,55 +103,6 @@
 
 static char *program_name;
 
-/*
- * This was introduced by Clang:
- *
- *     http://clang.llvm.org/docs/LanguageExtensions.html#has-attribute
- *
- * in some version (which version?); it has been picked up by GCC 5.0.
- */
-#ifndef __has_attribute
-  /*
-   * It's a macro, so you can check whether it's defined to check
-   * whether it's supported.
-   *
-   * If it's not, define it to always return 0, so that we move on to
-   * the fallback checks.
-   */
-  #define __has_attribute(x) 0
-#endif
-
-#if __has_attribute(noreturn) \
-    || (defined(__GNUC__) && ((__GNUC__ * 100 + __GNUC_MINOR__) >= 205)) \
-    || (defined(__SUNPRO_C) && (__SUNPRO_C >= 0x590)) \
-    || (defined(__xlC__) && __xlC__ >= 0x0A01) \
-    || (defined(__HP_aCC) && __HP_aCC >= 61000)
-  /*
-   * Compiler with support for it, or GCC 2.5 and later, or Solaris Studio 12
-   * (Sun C 5.9) and later, or IBM XL C 10.1 and later (do any earlier
-   * versions of XL C support this?), or HP aCC A.06.10 and later.
-   */
-  #define PCAP_NORETURN __attribute((noreturn))
-#elif defined( _MSC_VER )
-  #define PCAP_NORETURN __declspec(noreturn)
-#else
-  #define PCAP_NORETURN
-#endif
-
-#if __has_attribute(__format__) \
-    || (defined(__GNUC__) && ((__GNUC__ * 100 + __GNUC_MINOR__) >= 203)) \
-    || (defined(__xlC__) && __xlC__ >= 0x0A01) \
-    || (defined(__HP_aCC) && __HP_aCC >= 61000)
-  /*
-   * Compiler with support for it, or GCC 2.3 and later, or IBM XL C 10.1
-   * and later (do any earlier versions of XL C support this?),
-   * or HP aCC A.06.10 and later.
-   */
-  #define PCAP_PRINTFLIKE(x,y) __attribute__((__format__(__printf__,x,y)))
-#else
-  #define PCAP_PRINTFLIKE(x,y)
-#endif
-
 /* Forwards */
 static void PCAP_NORETURN usage(void);
 static void PCAP_NORETURN error(const char *, ...) PCAP_PRINTFLIKE(1, 2);
@@ -278,7 +233,8 @@
 	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;
@@ -333,11 +289,12 @@
 		 * 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/testprogs/visopts.py b/testprogs/visopts.py
new file mode 100755
index 0000000..03aa804
--- /dev/null
+++ b/testprogs/visopts.py
@@ -0,0 +1,310 @@
+#!/usr/bin/env python
+
+"""
+This program parse the output from pcap_compile() to visualize the CFG after
+each optimize phase.
+
+Usage guide:
+1. Enable optimizier debugging code when configure libpcap,
+   and build libpcap & the test programs
+       ./configure --enable-optimizer-dbg
+       make
+       make testprogs
+2. Run filtertest to compile BPF expression and produce the CFG as a
+   DOT graph, save to output a.txt
+       testprogs/filtertest -g EN10MB host 192.168.1.1 > a.txt
+3. Send a.txt to this program's standard input
+       cat a.txt | testprogs/visopts.py
+4. Step 2&3 can be merged:
+       testprogs/filtertest -g EN10MB host 192.168.1.1 | testprogs/visopts.py
+5. The standard output is something like this:
+       generated files under directory: /tmp/visopts-W9ekBw
+         the directory will be removed when this programs finished.
+       open this link: http://localhost:39062/expr1.html
+6. Using open link at the 3rd line `http://localhost:39062/expr1.html'
+
+Note:
+1. The CFG is translated to SVG an document, expr1.html embeded them as external
+   document. If you open expr1.html as local file using file:// protocol, some
+   browsers will deny such requests so the web pages will not shown properly.
+   For chrome, you can run it using following command to avoid this:
+       chromium --disable-web-security
+   That's why this program start a localhost http server.
+2. expr1.html use jquery from http://ajax.googleapis.com, so you need internet
+   access to show the web page.
+"""
+
+import sys, os
+import string
+import subprocess
+import json
+
+html_template = string.Template("""
+<html>
+  <head>
+    <title>BPF compiler optimization phases for $expr </title>
+    <style type="text/css">
+      .hc {
+         /* half width container */
+         display: inline-block;
+         float: left;
+         width: 50%;
+      }
+    </style>
+
+    <script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jquery/1.10.2/jquery.min.js"/></script>
+    <!--script type="text/javascript" src="./jquery.min.js"/></script-->
+    <script type="text/javascript">
+      var expr = '$expr';
+      var exprid = 1;
+      var gcount = $gcount;
+      var logs = JSON.parse('$logs');
+      logs[gcount] = "";
+
+      var leftsvg = null;
+      var rightsvg = null;
+
+      function gurl(index) {
+         index += 1;
+         if (index < 10)
+           s = "00" + index;
+         else if (index < 100)
+           s = "0" + index;
+         else
+           s = "" + index;
+         return "./expr" + exprid + "_g" + s + ".svg"
+      }
+
+      function annotate_svgs() {
+         if (!leftsvg || !rightsvg) return;
+
+         $$.each([$$(leftsvg), $$(rightsvg)], function() {
+           $$(this).find("[id|='block'][opacity]").each(function() {
+             $$(this).removeAttr('opacity');
+            });
+          });
+
+         $$(leftsvg).find("[id|='block']").each(function() {
+           var has = $$(rightsvg).find("#" + this.id).length != 0;
+           if (!has) $$(this).attr("opacity", "0.4");
+           else {
+             $$(this).click(function() {
+                var target = $$(rightsvg).find("#" + this.id);
+                var offset = $$("#rightsvgc").offset().top + target.position().top;
+                window.scrollTo(0, offset);
+                target.focus();
+             });
+           }
+          });
+         $$(rightsvg).find("[id|='block']").each(function() {
+           var has = $$(leftsvg).find("#" + this.id).length != 0;
+           if (!has) $$(this).attr("opacity", "0.4");
+           else {
+             $$(this).click(function() {
+                var target = $$(leftsvg).find("#" + this.id);
+                var offset = $$("#leftsvgc").offset().top + target.position().top;
+                window.scrollTo(0, offset);
+                target.focus();
+             });
+           }
+          });
+      }
+
+      function init_svgroot(svg) {
+         svg.setAttribute("width", "100%");
+         svg.setAttribute("height", "100%");
+      }
+      function wait_leftsvg() {
+         if (leftsvg) return;
+         var doc = document.getElementById("leftsvgc").getSVGDocument();
+         if (doc == null) {
+            setTimeout(wait_leftsvg, 500);
+            return;
+         }
+         leftsvg = doc.documentElement;
+         //console.log(leftsvg);
+         // initialize it
+         init_svgroot(leftsvg);
+         annotate_svgs();
+      }
+      function wait_rightsvg() {
+         if (rightsvg) return;
+         var doc = document.getElementById("rightsvgc").getSVGDocument();
+         if (doc == null) {
+            setTimeout(wait_rightsvg, 500);
+            return;
+         }
+         rightsvg = doc.documentElement;
+         //console.log(rightsvg);
+         // initialize it
+         init_svgroot(rightsvg);
+         annotate_svgs();
+      }
+      function load_left(index) {
+        var url = gurl(index);
+        var frag = "<embed id='leftsvgc'  type='image/svg+xml' pluginspage='http://www.adobe.com/svg/viewer/install/' src='" + url + "'/>";
+        $$("#lsvg").html(frag);
+        $$("#lcomment").html(logs[index]);
+        $$("#lsvglink").attr("href", url);
+        leftsvg = null;
+        wait_leftsvg();
+      }
+      function load_right(index) {
+        var url = gurl(index);
+        var frag = "<embed id='rightsvgc' type='image/svg+xml' pluginspage='http://www.adobe.com/svg/viewer/install/' src='" + url + "'/>";
+        $$("#rsvg").html(frag);
+        $$("#rcomment").html(logs[index]);
+        $$("#rsvglink").attr("href", url);
+        rightsvg = null;
+        wait_rightsvg();
+      }
+
+      $$(document).ready(function() {
+        for (var i = 0; i < gcount; i++) {
+          var opt = "<option value='" + i + "'>loop" + i + " -- " + logs[i] + "</option>";
+          $$("#lselect").append(opt);
+          $$("#rselect").append(opt);
+        }
+        var on_selected = function() {
+          var index = parseInt($$(this).children("option:selected").val());
+          if (this.id == "lselect")
+             load_left(index);
+          else
+             load_right(index);
+        }
+        $$("#lselect").change(on_selected);
+        $$("#rselect").change(on_selected);
+
+        $$("#backward").click(function() {
+          var index = parseInt($$("#lselect option:selected").val());
+          if (index <= 0) return;
+          $$("#lselect").val(index - 1).change();
+          $$("#rselect").val(index).change();
+        });
+        $$("#forward").click(function() {
+          var index = parseInt($$("#rselect option:selected").val());
+          if (index >= gcount - 1) return;
+          $$("#lselect").val(index).change();
+          $$("#rselect").val(index + 1).change();
+        });
+
+        if (gcount >= 1) $$("#lselect").val(0).change();
+        if (gcount >= 2) $$("#rselect").val(1).change();
+      });
+    </script>
+  </head>
+  <body style="width: 96%">
+    <div>
+      <h1>$expr</h1>
+      <div style="text-align: center;">
+        <button id="backward" type="button">&lt;&lt;</button>
+          &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
+        <button id="forward" type="button">&gt;&gt;</button>
+      </div>
+    </div>
+    <br/>
+    <div style="clear: both;">
+       <div class="hc lc">
+        <select id="lselect"></select>
+        <a id="lsvglink" target="_blank">open this svg in browser</a>
+        <p id="lcomment"></p>
+       </div>
+       <div class="hc rc">
+        <select id="rselect"></select>
+        <a id="rsvglink" target="_blank">open this svg in browser</a>
+        <p id="rcomment"></p>
+       </div>
+    </div>
+    <br/>
+    <div style="clear: both;">
+       <div id="lsvg"  class="hc lc"></div>
+       <div id="rsvg" class="hc rc"></div>
+    </div>
+  </body>
+</html>
+""")
+
+def write_html(expr, gcount, logs):
+    logs = map(lambda s: s.strip().replace("\n", "<br/>"), logs)
+
+    global html_template
+    html = html_template.safe_substitute(expr=expr.encode("string-escape"), gcount=gcount, logs=json.dumps(logs).encode("string-escape"))
+    with file("expr1.html", "wt") as f:
+        f.write(html)
+
+def render_on_html(infile):
+    expr = None
+    gid = 1
+    log = ""
+    dot = ""
+    indot = 0
+    logs = []
+
+    for line in infile:
+        if line.startswith("machine codes for filter:"):
+            expr = line[len("machine codes for filter:"):].strip()
+            break
+        elif line.startswith("digraph BPF {"):
+            indot = 1
+            dot = line
+        elif indot:
+            dot += line
+            if line.startswith("}"):
+                indot = 2
+        else:
+            log += line
+
+        if indot == 2:
+            p = subprocess.Popen(['dot', '-Tsvg'], stdin=subprocess.PIPE, stdout=subprocess.PIPE)
+            svg = p.communicate(dot)[0]
+            with file("expr1_g%03d.svg" % (gid), "wt") as f:
+                f.write(svg)
+
+            logs.append(log)
+            gid += 1
+            log = ""
+            dot = ""
+            indot = 0
+
+    if indot != 0:
+        #unterminated dot graph for expression
+        return False
+    if expr is None:
+        # BPF parser encounter error(s)
+        return False
+    write_html(expr, gid - 1, logs)
+    return True
+
+def run_httpd():
+    import SimpleHTTPServer
+    import SocketServer
+
+    class MySocketServer(SocketServer.TCPServer):
+        allow_reuse_address = True
+    Handler = SimpleHTTPServer.SimpleHTTPRequestHandler
+    httpd = MySocketServer(("localhost", 0), Handler)
+    print "open this link: http://localhost:%d/expr1.html" % (httpd.server_address[1])
+    try:
+        httpd.serve_forever()
+    except KeyboardInterrupt as e:
+        pass
+
+def main():
+    import tempfile
+    import atexit
+    import shutil
+    os.chdir(tempfile.mkdtemp(prefix="visopts-"))
+    atexit.register(shutil.rmtree, os.getcwd())
+    print "generated files under directory: %s" % os.getcwd()
+    print "  the directory will be removed when this programs finished."
+
+    if not render_on_html(sys.stdin):
+        return 1
+    run_httpd()
+    return 0
+
+if __name__ == "__main__":
+    if '-h' in sys.argv or '--help' in sys.argv:
+        print __doc__
+        exit(0)
+    exit(main())
diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt
deleted file mode 100644
index fc7919e..0000000
--- a/tests/CMakeLists.txt
+++ /dev/null
@@ -1,42 +0,0 @@
-cmake_minimum_required( VERSION 2.8.8 )
-
-project( pcap_tests )
-
-######################################
-# Register targets
-######################################
-
-if( MSVC )
-    file(GLOB PROJECT_SOURCE_LIST_WIN32_C
-        ${pcap_SOURCE_DIR}/missing/getopt.c
-    )
-endif( MSVC )
-
-ADD_EXECUTABLE (can_set_rfmon_test can_set_rfmon_test.c ${PROJECT_SOURCE_LIST_WIN32_C} )
-target_link_libraries ( can_set_rfmon_test pcap )
-
-ADD_EXECUTABLE (capturetest capturetest.c ${PROJECT_SOURCE_LIST_WIN32_C} )
-target_link_libraries ( capturetest pcap )
-
-ADD_EXECUTABLE (filtertest filtertest.c ${PROJECT_SOURCE_LIST_WIN32_C} )
-target_link_libraries ( filtertest pcap )
-
-ADD_EXECUTABLE (indalldevstest findalldevstest.c ${PROJECT_SOURCE_LIST_WIN32_C} )
-target_link_libraries ( indalldevstest pcap )
-
-ADD_EXECUTABLE (opentest opentest.c ${PROJECT_SOURCE_LIST_WIN32_C} )
-target_link_libraries ( opentest pcap )
-
-#ADD_EXECUTABLE (pcap_compile_test pcap_compile_test.c ${PROJECT_SOURCE_LIST_WIN32_C} )
-#target_link_libraries ( pcap_compile_test pcap )
-
-ADD_EXECUTABLE (reactivatetest reactivatetest.c ${PROJECT_SOURCE_LIST_WIN32_C} )
-target_link_libraries ( reactivatetest pcap )
-
-if( NOT WIN32 )
-    ADD_EXECUTABLE (selpolltest selpolltest.c ${PROJECT_SOURCE_LIST_WIN32_C} )
-    target_link_libraries ( selpolltest pcap )
-endif()
-
-ADD_EXECUTABLE (valgrindtest valgrindtest.c ${PROJECT_SOURCE_LIST_WIN32_C} )
-target_link_libraries ( valgrindtest pcap )
diff --git a/tests/findalldevstest.c b/tests/findalldevstest.c
deleted file mode 100644
index 5925bf6..0000000
--- a/tests/findalldevstest.c
+++ /dev/null
@@ -1,161 +0,0 @@
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-
-#include <stdlib.h>
-#include <sys/types.h>
-#ifdef _WIN32
-  #include <winsock2.h>
-#else
-  #include <sys/socket.h>
-  #include <netinet/in.h>
-  #include <arpa/inet.h>
-  #include <netdb.h>
-#endif
-
-#include <pcap.h>
-
-static int 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;
-  int exit_status = 0;
-
-  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)
-  {
-    if (!ifprint(d))
-      exit_status = 2;
-  }
-
-  if ( (s = pcap_lookupdev(errbuf)) == NULL)
-  {
-    fprintf(stderr,"Error in pcap_lookupdev: %s\n",errbuf);
-    exit_status = 2;
-  }
-  else
-  {
-    printf("Preferred device name: %s\n",s);
-  }
-
-  if (pcap_lookupnet(s, &net, &mask, errbuf) < 0)
-  {
-    fprintf(stderr,"Error in pcap_lookupnet: %s\n",errbuf);
-    exit_status = 2;
-  }
-  else
-  {
-    printf("Preferred device is on network: %s/%s\n",iptos(net), iptos(mask));
-  }
-
-  exit(exit_status);
-}
-
-static int ifprint(pcap_if_t *d)
-{
-  pcap_addr_t *a;
-#ifdef INET6
-  char ntop_buf[INET6_ADDRSTRLEN];
-#endif
-  const char *sep;
-  int status = 1; /* success */
-
-  printf("%s\n",d->name);
-  if (d->description)
-    printf("\tDescription: %s\n",d->description);
-  printf("\tFlags: ");
-  sep = "";
-  if (d->flags & PCAP_IF_UP) {
-    printf("%sUP", sep);
-    sep = ", ";
-  }
-  if (d->flags & PCAP_IF_RUNNING) {
-    printf("%sRUNNING", sep);
-    sep = ", ";
-  }
-  if (d->flags & PCAP_IF_LOOPBACK) {
-    printf("%sLOOPBACK", sep);
-    sep = ", ";
-  }
-  printf("\n");
-
-  for(a=d->addresses;a;a=a->next) {
-    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_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;
-      }
-    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];
-}
diff --git a/tests/shb-option-too-long.pcapng b/tests/shb-option-too-long.pcapng
new file mode 100644
index 0000000..f773974
--- /dev/null
+++ b/tests/shb-option-too-long.pcapng
Binary files differ
diff --git a/varattrs.h b/varattrs.h
new file mode 100644
index 0000000..05bfe8c
--- /dev/null
+++ b/varattrs.h
@@ -0,0 +1,59 @@
+/* -*- 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 varattrs_h
+#define varattrs_h
+
+#include <pcap/compiler-tests.h>
+
+/*
+ * Attributes to apply to variables, using various compiler-specific
+ * extensions.
+ */
+
+#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
diff --git a/version.c b/version.c
deleted file mode 100644
index 15f6baf..0000000
--- a/version.c
+++ /dev/null
@@ -1,3 +0,0 @@
-#include <pcap/export-defs.h>
-PCAP_API_DEF
-char pcap_version[] = "1.8.1";