Merge "Upgrade to libpcap 1.8.1."
diff --git a/.gitignore b/.gitignore
index d6d58ac..06a62e5 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,44 +1,10 @@
 Makefile
 *~
+*.a
 *.o
-bpf_filter.c
-config.h
 config.log
 config.cache
 config.status
 stamp-h
 stamp-h.in
 autom4te.cache/
-.devel
-filtertest
-findalldevstest
-grammar.c
-libpcap.a
-libpcap.*.dylib
-libpcap.sl
-libpcap.so.*
-libpcap-*.tar.gz
-net
-os-proto.h
-pcap-config
-pcap-filter.manmisc
-pcap-linktype.manmisc
-pcap-savefile.manfile
-pcap-tstamp.manmisc
-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
-scanner.c
-scanner.h
-selpolltest
-tokdefs.h
-version.c
-version.h
diff --git a/.travis.yml b/.travis.yml
deleted file mode 100644
index 3a7fac1..0000000
--- a/.travis.yml
+++ /dev/null
@@ -1,5 +0,0 @@
-language: c
-
-script:
-  - ./configure
-  - make
diff --git a/Android.mk b/Android.mk
index 8c691bf..971916d 100644
--- a/Android.mk
+++ b/Android.mk
@@ -1,6 +1,9 @@
 LOCAL_PATH:= $(call my-dir)
 
 libpcap_cflags := \
+  -Wno-macro-redefined \
+  -Wno-pointer-arith \
+  -Wno-sign-compare \
   -Wno-unused-parameter \
   -D_BSD_SOURCE \
   -D_U_="__attribute__((unused))" \
@@ -8,22 +11,17 @@
 
 include $(CLEAR_VARS)
 
+# (Matches order in libpcap's Makefile.)
 LOCAL_SRC_FILES := \
-  pcap-linux.c pcap-usb-linux.c pcap-can-linux.c pcap-netfilter-linux-android.c \
-  fad-gifc.c \
-  pcap.c inet.c gencode.c optimize.c nametoaddr.c etherent.c \
-  savefile.c sf-pcap.c sf-pcap-ng.c pcap-common.c \
-  bpf/net/bpf_filter.c bpf_image.c bpf_dump.c \
-  version.c \
-
-# Generated on the host with `configure && make` and copied across.
-LOCAL_SRC_FILES += grammar.c
-LOCAL_SRC_FILES += scanner.c
+  pcap-linux.c pcap-usb-linux.c pcap-netfilter-linux-android.c \
+  fad-getad.c \
+  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 \
+  scanner.c grammar.c bpf_filter.c version.c \
 
 LOCAL_CFLAGS += $(libpcap_cflags)
-LOCAL_CFLAGS += -Wno-sign-compare
 LOCAL_CFLAGS += -DHAVE_CONFIG_H
-LOCAL_CFLAGS += -include strings.h # For ffs(3).
 
 LOCAL_EXPORT_C_INCLUDE_DIRS := $(LOCAL_PATH)
 
@@ -38,14 +36,16 @@
 
 include $(BUILD_SHARED_LIBRARY)
 
+# (Matches order in libpcap's Makefile.)
 libpcap_tests :=  \
+  tests/valgrindtest.c \
   tests/capturetest.c \
+  tests/can_set_rfmon_test.c \
   tests/filtertest.c \
   tests/findalldevstest.c \
   tests/opentest.c \
   tests/reactivatetest.c \
   tests/selpolltest.c \
-  tests/valgrindtest.c \
 
 $(foreach test,$(libpcap_tests), \
   $(eval include $(CLEAR_VARS)) \
diff --git a/CHANGES b/CHANGES
index ef90bbc..1784096 100644
--- a/CHANGES
+++ b/CHANGES
@@ -1,3 +1,49 @@
+Tuesday, Oct. 25, 2016 mcr@sandelman.ca
+  Summary for 1.8.1 libpcap release
+    Add a target in Makefile.in for Exuberant Ctags use: 'extags'.
+    Rename configure.in to configure.ac: autoconf 2.59
+    Clean up the name-to-DLT mapping table.
+    Add some newer DLT_ values: IPMI_HPM_2,ZWAVE_R1_R2,ZWAVE_R3,WATTSTOPPER_DLM,ISO_14443,RDS
+    Clarify what the return values are for both success and failure.
+    Many changes to build on windows
+    Check for the "break the loop" condition in the inner loop for TPACKET_V3.
+    Fix handling of packet count in the TPACKET_V3 inner loop: GitHub issue #493.
+    Filter out duplicate looped back CAN frames.
+    Fix the handling of loopback filters for IPv6 packets.
+    Add a link-layer header type for RDS (IEC 62106) groups.
+    Use different intermediate folders for x86 and x64 builds on Windows.
+    On Linux, handle all CAN captures with pcap-linux.c, in cooked mode.
+    Removes the need for the "host-endian" link-layer header type.
+    Compile with '-Wused-but-marked-unused' in devel mode if supported
+    Have separate DLTs for big-endian and host-endian SocketCAN headers.
+    Reflect version.h being renamed to pcap_version.h.
+    Require that version.h be generated: all build procedures we support generate version.h (autoconf, CMake, MSVC)!
+    Properly check for sock_recv() errors.
+    Re-impose some of Winsock's limitations on sock_recv().
+    Replace sprintf() with pcap_snprintf().
+    Fix signature of pcap_stats_ex_remote().
+    Initial cmake support for remote packet capture.
+    Have rpcap_remoteact_getsock() return a SOCKET and supply an "is active" flag.
+    Clean up {DAG, Septel, Myricom SNF}-only builds.
+    Do UTF-16-to-ASCII conversion into the right place.
+    pcap_create_interface() needs the interface name on Linux.
+    Clean up hardware time stamp support: the "any" device does not support any time stamp types.
+    Add support for capturing on FreeBSD usbusN interfaces.
+    Add a LINKTYPE/DLT_ value for FreeBSD USB.
+    Go back to using PCAP_API on Windows.
+    CMake support
+    Add TurboCap support from WinPcap.
+    Recognize 802.1ad nested VLAN tag in vlan filter.
+
+Thursday Sep. 3, 2015 guy@alum.mit.edu
+  Summary for 1.7.5 libpcap release
+	Man page cleanups.
+	Add some allocation failure checks.
+	Fix a number of Linux/ucLinux configure/build issues.
+	Fix some memory leaks.
+	Recognize 802.1ad nested VLAN tag in vlan filter.
+	Fix building Bluetooth Linux Monitor support with BlueZ 5.1+
+
 Saturday Jun. 27, 2015 mcr@sandelman.ca
   Summary for 1.7.4 libpcap release
 	Include fix for GitHub issue #424 -- out of tree builds.
diff --git a/CMakeLists.txt b/CMakeLists.txt
new file mode 100644
index 0000000..0ed8b61
--- /dev/null
+++ b/CMakeLists.txt
@@ -0,0 +1,520 @@
+cmake_minimum_required( VERSION 2.8.8 )
+
+project( pcap )
+#
+# Call the library "wpcap" on Windows, for backwards compatibility.
+#
+if( WIN32 )
+    set( LIBRARY_NAME wpcap )
+else()
+    set( LIBRARY_NAME pcap )
+endif()
+
+###################################################################
+#   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 )
+    set(PACKET_DLL_DIR "" CACHE PATH "Path to directory with include and lib subdirectories for packet.dll")
+endif( WIN32 )
+
+#
+# XXX - this should be an option, defaulting to "yes" for Windows and to
+# "no", for now, on UN*X.
+#
+if( WIN32 )
+    set( HAVE_REMOTE 1 )
+endif( WIN32 )
+
+######################################
+# Project settings
+######################################
+
+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)
+
+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( 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")
+
+        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")
+
+        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 )
+
+###################################################################
+#   Detect available platform features
+###################################################################
+
+include(CheckIncludeFile)
+include(CheckFunctionExists)
+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 )
+
+#
+# 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 )
+
+if (WIN32)
+    #
+    # Check for Windows-only functions, such as packet.dll functions.
+    #
+    check_function_exists( PacketIsLoopbackAdapter HAVE_PACKET_IS_LOOPBACK_ADAPTER )
+endif()
+
+#
+# Data types.
+#
+# XXX - there's no check_struct() macro that's like check_struct_has_member()
+# except that it only checks for the existence of the structure type,
+# so we use check_struct_has_member() and look for ss_family.
+#
+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)
+check_type_size("socklen_t" SOCKLEN_T)
+set(CMAKE_EXTRA_INCLUDE_FILES unistd.h)
+
+#
+# Structure fields.
+#
+check_struct_has_member("struct sockaddr" sa_len sys/socket.h HAVE_SOCKADDR_SA_LEN )
+
+if( INET6 )
+    MESSAGE( STATUS "Use IPv6" )
+endif( INET6 )
+
+if( WIN32 )
+    add_definitions( -DHAVE_ADDRINFO )
+endif( WIN32 )
+
+######################################
+# External dependencies
+######################################
+
+######################################
+# Input files
+######################################
+
+set(PROJECT_SOURCE_LIST_C
+    bpf_dump.c
+    bpf_image.c
+    etherent.c
+    fad-helpers.c
+    gencode.c
+    inet.c
+    nametoaddr.c
+    optimize.c
+    pcap-common.c
+    pcap.c
+    savefile.c
+    sf-pcap-ng.c
+    sf-pcap.c
+    bpf/net/bpf_filter.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 )
+
+#
+# Determine the main pcap-XXX.c file to use.
+#
+if( WIN32 )
+    #
+    # WinPcap.
+    #
+    set( PCAP_TYPE win32 )
+else()
+    #
+    # 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 )
+
+        #
+        # XXX - many more BPF checks.
+        #
+    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 )
+    endif()
+endif( WIN32 )
+message(STATUS "Packet capture mechanism type: ${PCAP_TYPE}")
+set(PROJECT_SOURCE_LIST_C ${PROJECT_SOURCE_LIST_C} pcap-${PCAP_TYPE}.c)
+
+#
+# Now figure out how we get a list of interfaces and addresses,
+# if we support capturing.  Don't bother if we don't support
+# capturing.
+#
+if( NOT WIN32 )
+    #
+    # UN*X - figure out what type of interface list mechanism we
+    # have.
+    #
+    if( ${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} )
+            #
+            # We have "getifaddrs()"; make sure we have <ifaddrs.h>
+            # as well, just in case some platform is really weird.
+            #
+            check_include_file( ifaddrs.h HAVE_IFADDRS_H )
+            if( ${HAVE_IFADDRS_H} )
+                #
+                # We have the header, so we use "getifaddrs()" to
+                # get the list of interfaces.
+                #
+                set( FINDALLDEVS_TYPE getad )
+            else()
+                #
+                # We don't have the header - give up.
+                # XXX - we could also fall back on some other
+                # mechanism, but, for now, this'll catch this
+                # problem so that we can at least try to figure
+                # out something to do on systems with "getifaddrs()"
+                # but without "ifaddrs.h", if there is something
+                # we can do on those systems.
+                #
+                message(FATAL_ERROR "Your system has getifaddrs() but doesn't have a usable <ifaddrs.h>." )
+            endif()
+        else()
+            #
+            # Well, we don't have "getifaddrs()", so we have to use
+            # some other mechanism; determine what that mechanism is.
+            #
+            # The first thing we use is the type of capture mechanism,
+            # which is somewhat of a proxy for the OS we're using.
+            #
+            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()
+            else()
+                #
+                # Assume we just have SIOCGIFCONF.
+                # (XXX - on at least later Linux kernels, there's
+                # another mechanism, and we should be using that
+                # instead.)
+                #
+                set( FINDALLDEVS_TYPE gifc )
+            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
+    *.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.
+# From a mail message to the CMake mailing list by Andy Cedilnik of
+# Kitware.
+#
+
+#
+# Try to find Flex, a Windows version of Flex, or Lex.
+#
+find_program(LEX_EXECUTABLE NAMES flex win_flex lex)
+if( ${LEX_EXECUTABLE} STREQUAL "LEX_EXECUTABLE-NOTFOUND" )
+    message(FATAL_ERROR "Neither flex nor win_flex nor lex was found." )
+endif()
+message(STATUS "Lexical analyzer generator: ${LEX_EXECUTABLE}")
+
+add_custom_command(
+    OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/scanner.c ${CMAKE_CURRENT_BINARY_DIR}/scanner.h
+    SOURCE ${pcap_SOURCE_DIR}/scanner.l
+    COMMAND ${LEX_EXECUTABLE} -P pcap_ --header-file=scanner.h --nounput -o${CMAKE_CURRENT_BINARY_DIR}/scanner.c ${pcap_SOURCE_DIR}/scanner.l
+    DEPENDS ${pcap_SOURCE_DIR}/scanner.l
+)
+
+#
+# Since scanner.c does not exist yet when cmake is run, mark
+# it as generated.
+#
+# Since scanner.c includes grammar.h, mark that as a dependency.
+#
+set_source_files_properties(${CMAKE_CURRENT_BINARY_DIR}/scanner.c PROPERTIES
+    GENERATED TRUE
+    OBJECT_DEPENDS ${CMAKE_CURRENT_BINARY_DIR}/scanner.h
+)
+
+#
+# Add scanner.c to the list of sources.
+#
+#set(PROJECT_SOURCE_LIST_C ${PROJECT_SOURCE_LIST_C} ${CMAKE_CURRENT_BINARY_DIR}/scanner.c)
+
+#
+# Try to find YACC or Bison.
+#
+find_program(YACC_EXECUTABLE NAMES bison win_bison byacc yacc)
+if( ${YACC_EXECUTABLE} STREQUAL "YACC_EXECUTABLE-NOTFOUND" )
+    message(FATAL_ERROR "Neither bison nor win_bison nor byacc nor yacc was found." )
+endif()
+message(STATUS "Parser generator: ${YACC_EXECUTABLE}")
+
+#
+# Create custom command for the scanner.
+# Find out whether it's Bison or notby looking at the last component
+# of the path (without a .exe extension, if this is Windows).
+#
+get_filename_component(YACC_NAME ${YACC_EXECUTABLE} NAME_WE)
+if( "${YACC_NAME}" STREQUAL "bison" OR "${YACC_NAME}" STREQUAL "win_bison" )
+    set( YACC_COMPATIBILITY_FLAG "-y" )
+endif()
+add_custom_command(
+    OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/grammar.c ${CMAKE_CURRENT_BINARY_DIR}/grammar.h
+    SOURCE ${pcap_SOURCE_DIR}/grammar.y
+    COMMAND ${YACC_EXECUTABLE} ${YACC_COMPATIBILITY_FLAG} -p pcap_ -o ${CMAKE_CURRENT_BINARY_DIR}/grammar.c -d ${pcap_SOURCE_DIR}/grammar.y
+    DEPENDS ${pcap_SOURCE_DIR}/grammar.y
+)
+
+#
+# Since grammar.c does not exists yet when cmake is run, mark
+# it as generated.
+#
+set_source_files_properties(${CMAKE_CURRENT_BINARY_DIR}/grammar.c PROPERTIES
+    GENERATED TRUE
+)
+
+#
+# Add grammar.c to the list of sources.
+#
+#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
+    )
+
+    #
+    # Since version.c does not exists yet when cmake is run, mark
+    # it as generated.
+    #
+    set_source_files_properties(${CMAKE_CURRENT_BINARY_DIR}/version.c PROPERTIES
+        GENERATED TRUE
+    )
+
+    #
+    # Add version.c to the list of sources.
+    #
+    set(PROJECT_SOURCE_LIST_C ${PROJECT_SOURCE_LIST_C} ${CMAKE_CURRENT_BINARY_DIR}/version.c)
+endif( WIN32 )
+
+#
+# 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)
+
+source_group("Source Files" FILES ${PROJECT_SOURCE_LIST_C})
+source_group("Header Files" FILES ${PROJECT_SOURCE_LIST_H})
+
+######################################
+# Register targets
+######################################
+
+add_library(${LIBRARY_NAME}
+    ${PROJECT_SOURCE_LIST_C}
+    ${CMAKE_CURRENT_BINARY_DIR}/grammar.c
+    ${CMAKE_CURRENT_BINARY_DIR}/scanner.c
+    ${PROJECT_SOURCE_LIST_H}
+)
+
+if( WIN32 )
+    target_link_libraries ( ${LIBRARY_NAME}
+        packet
+        ws2_32
+    )
+endif( WIN32 )
+
+######################################
+# Write out the config.h file
+######################################
+
+configure_file(${CMAKE_CURRENT_SOURCE_DIR}/cmakeconfig.h.in ${CMAKE_CURRENT_BINARY_DIR}/config.h)
diff --git a/GenVersion.bat b/GenVersion.bat
new file mode 100644
index 0000000..babf373
--- /dev/null
+++ b/GenVersion.bat
@@ -0,0 +1,23 @@
+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.txt
index 18b489a..f305aa2 100644
--- a/INSTALL.txt
+++ b/INSTALL.txt
@@ -16,7 +16,7 @@
 particular type. (If you have HP-UX, see below.) If your system uses a
 packet capture not supported by libpcap, please send us patches; don't
 forget to include an autoconf fragment suitable for use in
-configure.in.
+configure.ac.
 
 It is possible to override the default packet capture type, although
 the circumstance where this works are limited. For example if you have
@@ -31,40 +31,22 @@
 will abort if your compiler is not ANSI compliant. If this happens, use
 the generally available GNU C compiler (GCC).
 
-If you use flex, you must use version 2.4.6 or higher. The configure
-script automatically detects the version of flex and will not use it
-unless it is new enough. You can use "flex -V" to see what version you
-have (unless it's really old). The current version of flex is available
-at flex.sourceforge.net and often comes packaged by means of the OS.
-As of this writing, the current version is 2.5.37.
+You will need either Flex 2.5.31 or later, or a version of Lex
+compatible with it (if any exist), to build libpcap.  The configure
+script will abort if there isn't any such program.  If you have an older
+version of Flex, or don't have a compatible version of Lex, the current
+version of flex is available at flex.sourceforge.net.
 
-If you use bison, you must use flex (and visa versa). The configure
-script automatically falls back to lex and yacc if both flex and bison
-are not found.
+You will need either Bison, Berkeley YACC, or a version of YACC
+compatible with them (if any exist), to build libpcap.  The configure
+script will abort if there isn't any such program.  If you don't have
+any such program, the current version of Bison can be found at
+http://ftp.gnu.org/gnu/bison/ and the current version of Berkeley YACC
+can be found at http://invisible-island.net/byacc/.
 
-Sometimes the stock C compiler does not interact well with flex and
-bison. The list of problems includes undefined references for alloca.
-You can get around this by installing gcc or manually disabling flex
-and bison with:
-
-    ./configure --without-flex --without-bison
-
-If your system only has AT&T lex, this is okay unless your libpcap
-program uses other lex/yacc generated code. (Although it's possible to
-map the yy* identifiers with a script, we use flex and bison so we
-don't feel this is necessary.)
-
-Some systems support the Berkeley Packet Filter natively; for example
-out of the box OSF and BSD/OS have bpf. If your system does not support
-bpf, you will need to pick up:
-
-	ftp://ftp.ee.lbl.gov/bpf-*.tar.Z
-
-Note well: you MUST have kernel source for your operating system in
-order to install bpf. An exception is SunOS 4; the bpf distribution
-includes replacement kernel objects for some of the standard SunOS 4
-network device drivers. See the bpf INSTALL document for more
-information.
+Sometimes the stock C compiler does not interact well with Flex and
+Bison. The list of problems includes undefined references for alloca.
+You can get around this by installing GCC.
 
 If you use Solaris, there is a bug with bufmod(7) that is fixed in
 Solaris 2.3.2 (aka SunOS 5.3.2). Setting a snapshot length with the
@@ -239,11 +221,11 @@
 build without changes on UnixWare 7.
 
 If linking tcpdump fails with "Undefined: _alloca" when using bison on
-a Sun4, your version of bison is broken. In any case version 1.16 or
+a Sun4, your version of Bison is broken. In any case version 1.16 or
 higher is recommended (1.14 is known to cause problems 1.16 is known to
 work). Either pick up a current version from:
 
-	ftp://ftp.gnu.org/pub/gnu/bison
+	http://ftp.gnu.org/gnu/bison/
 
 or hack around it by inserting the lines:
 
@@ -289,6 +271,7 @@
 CHANGES		- description of differences between releases
 ChmodBPF/*	- Mac OS X startup item to set ownership and permissions
 		  on /dev/bpf*
+CMakeLists.txt	- CMake file
 CREDITS		- people that have helped libpcap along
 INSTALL.txt	- this file
 LICENSE		- the license under which tcpdump is distributed
@@ -317,7 +300,7 @@
 config.h.in	- autoconf input
 config.sub	- autoconf support
 configure	- configure script (run this first)
-configure.in	- configure script source
+configure.ac	- configure script source
 dlpisubs.c	- DLPI-related functions for pcap-dlpi.c and pcap-libdlpi.c
 dlpisubs.h	- DLPI-related function declarations
 etherent.c	- /etc/ethers support routines
@@ -325,9 +308,6 @@
 fad-getad.c	- pcap_findalldevs() for systems with getifaddrs()
 fad-gifc.c	- pcap_findalldevs() for systems with only SIOCGIFLIST
 fad-glifc.c	- pcap_findalldevs() for systems with SIOCGLIFCONF
-fad-null.c	- pcap_findalldevs() for systems without capture support
-fad-sita.c	- pcap_findalldevs() for systems with SITA support
-fad-win32.c	- pcap_findalldevs() for WinPcap
 filtertest.c	- test program for BPF compiler
 findalldevstest.c - test program for pcap_findalldevs()
 gencode.c	- BPF code generation routines
@@ -388,7 +368,6 @@
 pcap-filter.4	- manual entry for filter syntax
 pcap-linktype.4	- manual entry for link-layer header types
 ppp.h		- Point to Point Protocol definitions
-runlex.sh	- wrapper for Lex/Flex
 savefile.c	- offline support
 scanner.l	- filter string scanner
 sunatmpos.h	- definitions for SunATM capturing
diff --git a/Makefile-devel-adds b/Makefile-devel-adds
index 7bf6420..fea63bb 100644
--- a/Makefile-devel-adds
+++ b/Makefile-devel-adds
@@ -2,12 +2,12 @@
 # Auto-regenerate configure script or Makefile when things change.
 # From autoconf.info .  Works best with GNU Make.
 #
-${srcdir}/configure: configure.in aclocal.m4
+${srcdir}/configure: configure.ac aclocal.m4
 	cd ${srcdir} && autoconf
 
 # autoheader might not change config.h.in, so touch a stamp file.
 ${srcdir}/config.h.in: ${srcdir}/stamp-h.in
-${srcdir}/stamp-h.in: configure.in aclocal.m4
+${srcdir}/stamp-h.in: configure.ac aclocal.m4
 	cd ${srcdir} && autoheader
 	echo timestamp > ${srcdir}/stamp-h.in
 
diff --git a/Makefile.in b/Makefile.in
index 4c35bde..e71d973 100644
--- a/Makefile.in
+++ b/Makefile.in
@@ -49,7 +49,7 @@
 MKDEP = @MKDEP@
 CCOPT = @V_CCOPT@
 INCLS = -I. @V_INCLS@
-DEFS = @DEFS@ @V_DEFS@
+DEFS = -DBUILDING_PCAP @DEFS@ @V_DEFS@
 ADDLOBJS = @ADDLOBJS@
 ADDLARCHIVEOBJS = @ADDLARCHIVEOBJS@
 LIBS = @LIBS@
@@ -69,13 +69,8 @@
 INSTALL_DATA = @INSTALL_DATA@
 RANLIB = @RANLIB@
 
-#
-# Flex and bison allow you to specify the prefixes of the global symbols
-# used by the generated parser.  This allows programs to use lex/yacc
-# and link against libpcap.  If you don't have flex or bison, get them.
-#
-LEX = @V_LEX@
-YACC = @V_YACC@
+LEX = @LEX@
+YACC = @YACC@
 
 # Explicitly define compilation rule since SunOS 4's make doesn't like gcc.
 # Also, gcc does not remove the .o before forking 'as', which can be a
@@ -84,11 +79,11 @@
 	@rm -f $@
 	$(CC) $(FULL_CFLAGS) -c $(srcdir)/$*.c
 
-PSRC =	pcap-@V_PCAP@.c @USB_SRC@ @BT_SRC@ @BT_MONITOR_SRC@ @CAN_SRC@ @NETFILTER_SRC@ @CANUSB_SRC@ @DBUS_SRC@
-FSRC =  fad-@V_FINDALLDEVS@.c
+PSRC =	pcap-@V_PCAP@.c @USB_SRC@ @BT_SRC@ @BT_MONITOR_SRC@ @NETFILTER_SRC@ @DBUS_SRC@
+FSRC =  @V_FINDALLDEVS@
 SSRC =  @SSRC@
-CSRC =	pcap.c inet.c gencode.c optimize.c nametoaddr.c etherent.c \
-	savefile.c sf-pcap.c sf-pcap-ng.c pcap-common.c \
+CSRC =	pcap.c inet.c fad-helpers.c gencode.c optimize.c nametoaddr.c \
+	etherent.c savefile.c sf-pcap.c sf-pcap-ng.c pcap-common.c \
 	bpf_image.c bpf_dump.c
 GENSRC = scanner.c grammar.c bpf_filter.c version.c
 LIBOBJS = @LIBOBJS@
@@ -104,6 +99,9 @@
 	pcap-namedb.h \
 	pcap/bpf.h \
 	pcap/bluetooth.h \
+	pcap/can_socketcan.h \
+	pcap/dlt.h \
+	pcap/export-defs.h \
 	pcap/ipnet.h \
 	pcap/namedb.h \
 	pcap/nflog.h \
@@ -116,37 +114,43 @@
 	arcnet.h \
 	atmuni31.h \
 	ethertype.h \
+	extract.h \
 	gencode.h \
 	ieee80211.h \
 	llc.h \
+	nametoaddr.h \
 	nlpid.h \
 	pcap-common.h \
 	pcap-int.h \
 	pcap-stdinc.h \
+	portability.h \
 	ppp.h \
 	sf-pcap.h \
 	sf-pcap-ng.h \
 	sunatmpos.h
 
 TESTS = \
+	@VALGRINDTEST@ \
 	capturetest \
+	can_set_rfmon_test \
 	filtertest \
 	findalldevstest \
 	opentest \
-	selpolltest \
-	valgrindtest
+	reactivatetest \
+	selpolltest
 
 TESTS_SRC = \
+	tests/valgrindtest.c \
 	tests/capturetest.c \
+	tests/can_set_rfmon_test.c \
 	tests/filtertest.c \
 	tests/findalldevstest.c \
 	tests/opentest.c \
 	tests/reactivatetest.c \
-	tests/selpolltest.c \
-	tests/valgrindtest.c
+	tests/selpolltest.c
 
 GENHDR = \
-	scanner.h tokdefs.h version.h
+	scanner.h grammar.h pcap_version.h
 
 TAGFILES = \
 	$(SRC) $(HDR)
@@ -232,6 +236,8 @@
 	ChmodBPF/ChmodBPF \
 	ChmodBPF/StartupParameters.plist \
 	CREDITS \
+	CMakeLists.txt \
+	GenVersion.bat \
 	INSTALL.txt \
 	LICENSE \
 	Makefile.in \
@@ -254,29 +260,37 @@
 	aclocal.m4 \
 	bpf/net/bpf_filter.c \
 	chmod_bpf \
+	cmakeconfig.h.in \
+	cmake/preconfigure.cmake \
+	config/have_siocglifconf.c \
 	config.guess \
 	config.h.in \
 	config.sub \
 	configure \
-	configure.in \
+	configure.ac \
 	dlpisubs.c \
 	dlpisubs.h \
 	fad-getad.c \
 	fad-gifc.c \
 	fad-glifc.c \
-	fad-null.c \
-	fad-sita.c \
-	fad-win32.c \
+	fad-helpers.c \
+	gen_version_c.sh \
+	gen_version_header.sh \
 	grammar.y \
 	install-sh \
 	lbl/os-aix4.h \
+	lbl/os-aix7.h \
 	lbl/os-hpux11.h \
 	lbl/os-osf4.h \
 	lbl/os-osf5.h \
 	lbl/os-solaris2.h \
 	lbl/os-sunos4.h \
 	lbl/os-ultrix4.h \
+	missing/getopt.c \
+	missing/getopt.h \
 	missing/snprintf.c \
+	missing/strtok_r.c \
+	missing/win_snprintf.c \
 	mkdep \
 	msdos/bin2c.c \
 	msdos/common.dj \
@@ -297,10 +311,6 @@
 	pcap-bt-linux.h \
 	pcap-bt-monitor-linux.c \
 	pcap-bt-monitor-linux.h \
-	pcap-can-linux.c \
-	pcap-can-linux.h \
-	pcap-canusb-linux.c \
-	pcap-canusb-linux.h \
 	pcap-config.in \
 	pcap-dag.c \
 	pcap-dag.h \
@@ -314,11 +324,14 @@
 	pcap-libdlpi.c \
 	pcap-linux.c \
 	pcap-namedb.h \
+	pcap-new.c \
 	pcap-netfilter-linux.c \
 	pcap-netfilter-linux.h \
 	pcap-nit.c \
 	pcap-null.c \
 	pcap-pf.c \
+	pcap-rpcap.c \
+	pcap-rpcap.h \
 	pcap-septel.c \
 	pcap-septel.h \
 	pcap-sita.h \
@@ -328,35 +341,22 @@
 	pcap-snf.h \
 	pcap-snit.c \
 	pcap-snoop.c \
+	pcap-tc.c \
+	pcap-tc.h \
 	pcap-usb-linux.c \
 	pcap-usb-linux.h \
 	pcap-win32.c \
-	runlex.sh \
-	scanner.c.top \
+	remote-ext.h \
+	sockutils.c \
+	sockutils.h \
 	scanner.l \
+	tests/CMakeLists.txt \
+	pcap_version.h.in \
 	Win32/Include/Gnuc.h \
-	Win32/Include/addrinfo.h \
-	Win32/Include/bittypes.h \
-	Win32/Include/cdecl_ext.h \
-	Win32/Include/inetprivate.h \
-	Win32/Include/ip6_misc.h \
-	Win32/Include/sockstorage.h \
-	Win32/Include/arpa/nameser.h \
 	Win32/Include/net/if.h \
-	Win32/Include/net/netdb.h \
-	Win32/Include/net/paths.h \
-	Win32/Prj/libpcap.dsp \
-	Win32/Prj/libpcap.dsw \
-	Win32/Src/ffs.c \
-	Win32/Src/gai_strerror.c \
-	Win32/Src/getaddrinfo.c \
-	Win32/Src/getnetbynm.c \
-	Win32/Src/getnetent.c \
-	Win32/Src/getopt.c \
-	Win32/Src/getservent.c \
-	Win32/Src/inet_aton.c \
-	Win32/Src/inet_net.c \
-	Win32/Src/inet_pton.c
+	Win32/Prj/wpcap.sln \
+	Win32/Prj/wpcap.vcxproj \
+	Win32/Prj/wpcap.vcxproj.filters
 
 all: libpcap.a shared pcap-config
 
@@ -444,27 +444,33 @@
 libpcap.none:
 
 scanner.c: $(srcdir)/scanner.l
-	@rm -f $@ $@.bottom
-	$(srcdir)/runlex.sh $(LEX) -o$@ $<
-	mv $@ $@.bottom
-	cat $(srcdir)/$@.top $@.bottom > $@
-	@rm $@.bottom
+	$(LEX) -P pcap_ --header-file=scanner.h --nounput -o scanner.c $<
+scanner.h: scanner.c
+## Recover from the removal of $@
+	@if test -f $@; then :; else \
+		rm -f scanner.c; \
+		$(MAKE) $(MAKEFLAGS) scanner.c; \
+	fi
 
-scanner.o: scanner.c tokdefs.h
+scanner.o: scanner.c grammar.h
 	$(CC) $(FULL_CFLAGS) -c scanner.c
 
-pcap.o: version.h
+pcap.o: pcap_version.h
 
-tokdefs.h: grammar.c
 grammar.c: $(srcdir)/grammar.y
-	@rm -f grammar.c tokdefs.h
-	$(YACC) -d $<
-	mv y.tab.c grammar.c
-	mv y.tab.h tokdefs.h
+	$(YACC) -p pcap_ -o grammar.c -d $<
+grammar.h: grammar.c
+## Recover from the removal of $@
+	@if test -f $@; then :; else \
+		rm -f grammar.c; \
+		$(MAKE) $(MAKEFLAGS) grammar.c; \
+	fi
 
 grammar.o: grammar.c
-	@rm -f $@
-	$(CC) $(FULL_CFLAGS) -Dyylval=pcap_lval -c grammar.c
+	$(CC) $(FULL_CFLAGS) -c grammar.c
+
+gencode.o: $(srcdir)/gencode.c grammar.h scanner.h
+	$(CC) $(FULL_CFLAGS) -c $(srcdir)/gencode.c
 
 version.o: version.c
 	$(CC) $(FULL_CFLAGS) -c version.c
@@ -472,32 +478,21 @@
 snprintf.o: $(srcdir)/missing/snprintf.c
 	$(CC) $(FULL_CFLAGS) -o $@ -c $(srcdir)/missing/snprintf.c
 
-version.c: $(srcdir)/VERSION
-	@rm -f $@
-	if grep GIT ${srcdir}/VERSION >/dev/null; then \
-		read ver <${srcdir}/VERSION; \
-		echo $$ver | tr -d '\012'; \
-		date +_%Y_%m_%d; \
-	else \
-		cat ${srcdir}/VERSION; \
-	fi | sed -e 's/.*/char pcap_version[] = "&";/' > $@
+strtok_r.o: $(srcdir)/missing/strtok_r.c
+	$(CC) $(FULL_CFLAGS) -o $@ -c $(srcdir)/missing/strtok_r.c
 
-#
-# NOTE: this really is supposed to be static; importing a string
-# from a shared library does not work very well on many
-# versions of UNIX (Solaris, Linux, and the BSDs, for example),
-# so we make the version string static and return it from
-# a function, which does work.
-#
-version.h: $(srcdir)/VERSION
+version.c: $(srcdir)/VERSION $(srcdir)/gen_version_c.sh
+	#
+	# Older programs import this if they want to show the
+	# libpcap version number, rather than calling
+	# pcap_lib_version(), so we need to export it.
+	#
 	@rm -f $@
-	if grep GIT ${srcdir}/VERSION >/dev/null; then \
-		read ver <${srcdir}/VERSION; \
-		echo $$ver | tr -d '\012'; \
-		date +_%Y_%m_%d; \
-	else \
-		cat ${srcdir}/VERSION; \
-	fi | sed -e 's/.*/static const char pcap_version_string[] = "libpcap version &";/' > $@
+	$(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
@@ -534,6 +529,9 @@
 capturetest: tests/capturetest.c libpcap.a
 	$(CC) $(FULL_CFLAGS) -I. -L. -o capturetest $(srcdir)/tests/capturetest.c libpcap.a $(LIBS)
 
+can_set_rfmon_test: tests/can_set_rfmon_test.c libpcap.a
+	$(CC) $(FULL_CFLAGS) -I. -L. -o can_set_rfmon_test $(srcdir)/tests/can_set_rfmon_test.c libpcap.a $(LIBS)
+
 filtertest: tests/filtertest.c libpcap.a
 	$(CC) $(FULL_CFLAGS) -I. -L. -o filtertest $(srcdir)/tests/filtertest.c libpcap.a $(LIBS)
 
@@ -543,6 +541,9 @@
 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)
 
@@ -732,6 +733,9 @@
 	rm -f $(MAN3PCAP_EXPAND:.in=) $(MANFILE:.in=) $(MANMISC:.in=)
 	rm -rf autom4te.cache
 
+extags: $(TAGFILES)
+	ctags $(TAGFILES)
+
 tags: $(TAGFILES)
 	ctags -wtd $(TAGFILES)
 
diff --git a/README.sita b/README.sita
index ee7a426..014d51d 100644
--- a/README.sita
+++ b/README.sita
@@ -12,7 +12,7 @@
 capture packets from a SITA ACN device (and potentially others).
 
 To enable its support you need to ensure that the distribution has
-a correct configure.in file; that can be created if neccessay by
+a correct configure.ac file; that can be created if neccessay by
 using the normal autoconf procedure of:
 
 aclocal
diff --git a/README.version b/README.version
index 93bdae8..256063e 100644
--- a/README.version
+++ b/README.version
@@ -1,2 +1,2 @@
-URL: http://www.tcpdump.org/release/libpcap-1.5.2.tar.gz
-Version: 1.5.2
+URL: http://www.tcpdump.org/release/libpcap-1.8.1.tar.gz
+Version: 1.8.1
diff --git a/VERSION b/VERSION
index 10c0880..a8fdfda 100644
--- a/VERSION
+++ b/VERSION
@@ -1 +1 @@
-1.7.4
+1.8.1
diff --git a/Win32/Include/Gnuc.h b/Win32/Include/Gnuc.h
index aa49598..e1b5951 100644
--- a/Win32/Include/Gnuc.h
+++ b/Win32/Include/Gnuc.h
@@ -1,13 +1,3 @@
-/* Define __P() macro, if necessary */
-
-#ifndef __P
-#if __STDC__
-#define __P(protos) protos
-#else
-#define __P(protos) ()
-#endif
-#endif
-
 /* inline foo */
 #ifndef __cplusplus
 #ifdef __GNUC__
@@ -16,29 +6,3 @@
 #define inline
 #endif
 #endif
-
-/*
- * Handle new and old "dead" routine prototypes
- *
- * For example:
- *
- *	__dead void foo(void) __attribute__((volatile));
- *
- */
-#ifdef __GNUC__
-#ifndef __dead
-#define __dead volatile
-#endif
-#if __GNUC__ < 2  || (__GNUC__ == 2 && __GNUC_MINOR__ < 5)
-#ifndef __attribute__
-#define __attribute__(args)
-#endif
-#endif
-#else
-#ifndef __dead
-#define __dead
-#endif
-#ifndef __attribute__
-#define __attribute__(args)
-#endif
-#endif
diff --git a/Win32/Include/addrinfo.h b/Win32/Include/addrinfo.h
deleted file mode 100644
index ac4fcce..0000000
--- a/Win32/Include/addrinfo.h
+++ /dev/null
@@ -1,144 +0,0 @@
-/*
- * Copyright (C) 1995, 1996, 1997, 1998, and 1999 WIDE Project.
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in the
- *    documentation and/or other materials provided with the distribution.
- * 3. Neither the name of the project nor the names of its contributors
- *    may be used to endorse or promote products derived from this software
- *    without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED.  IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE
- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
- * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
- * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- */
-
-#ifndef HAVE_ADDRINFO
-
-/*
- * Error return codes from getaddrinfo()
- */
-#define	EAI_ADDRFAMILY	 1	/* address family for hostname not supported */
-#define	EAI_AGAIN	 2	/* temporary failure in name resolution */
-#define	EAI_BADFLAGS	 3	/* invalid value for ai_flags */
-#define	EAI_FAIL	 4	/* non-recoverable failure in name resolution */
-#define	EAI_FAMILY	 5	/* ai_family not supported */
-#define	EAI_MEMORY	 6	/* memory allocation failure */
-#define	EAI_NODATA	 7	/* no address associated with hostname */
-#define	EAI_NONAME	 8	/* hostname nor servname provided, or not known */
-#define	EAI_SERVICE	 9	/* servname not supported for ai_socktype */
-#define	EAI_SOCKTYPE	10	/* ai_socktype not supported */
-#define	EAI_SYSTEM	11	/* system error returned in errno */
-#define EAI_BADHINTS	12
-#define EAI_PROTOCOL	13
-#define EAI_MAX		14
-
-/* internal error */
-#define	NETDB_INTERNAL	-1	/* see errno */
-
-/*
- * Flag values for getaddrinfo()
- */
-#define	AI_PASSIVE	0x00000001 /* get address to use bind() */
-#define	AI_CANONNAME	0x00000002 /* fill ai_canonname */
-#define	AI_NUMERICHOST	0x00000004 /* prevent name resolution */
-/* valid flags for addrinfo */
-#define	AI_MASK		(AI_PASSIVE | AI_CANONNAME | AI_NUMERICHOST)
-
-#define	AI_ALL		0x00000100 /* IPv6 and IPv4-mapped (with AI_V4MAPPED) */
-#define	AI_V4MAPPED_CFG	0x00000200 /* accept IPv4-mapped if kernel supports */
-#define	AI_ADDRCONFIG	0x00000400 /* only if any address is assigned */
-#define	AI_V4MAPPED	0x00000800 /* accept IPv4-mapped IPv6 address */
-/* special recommended flags for getipnodebyname */
-#define	AI_DEFAULT	(AI_V4MAPPED_CFG | AI_ADDRCONFIG)
-
-struct addrinfo {
-	int	ai_flags;	/* AI_PASSIVE, AI_CANONNAME */
-	int	ai_family;	/* PF_xxx */
-	int	ai_socktype;	/* SOCK_xxx */
-	int	ai_protocol;	/* 0 or IPPROTO_xxx for IPv4 and IPv6 */
-	size_t	ai_addrlen;	/* length of ai_addr */
-	char	*ai_canonname;	/* canonical name for hostname */
-	struct sockaddr *ai_addr;	/* binary address */
-	struct addrinfo *ai_next;	/* next structure in linked list */
-};
-
-extern void freeaddrinfo (struct addrinfo *);
-extern void freehostent (struct hostent *);
-extern char *gai_strerror (int);
-extern int getaddrinfo (const char *, const char *,
-			    const struct addrinfo *, struct addrinfo **);
-extern int getnameinfo (const struct sockaddr *, size_t, char *,
-			    size_t, char *, size_t, int);
-extern struct hostent *getipnodebyaddr (const void *, size_t, int, int *);
-extern struct hostent *getipnodebyname (const char *, int, int, int *);
-extern int inet_pton (int, const char *, void *);
-extern const char *inet_ntop (int, const void *, char *, size_t);
-#else
-
-#ifndef EAI_BADHINTS
-#define EAI_BADHINTS	12
-#endif
-
-#ifndef EAI_PROTOCOL
-#define EAI_PROTOCOL	13
-#endif
-
-#ifndef EAI_MAX
-#define EAI_MAX		14
-#endif
-
-#ifndef NETDB_INTERNAL
-#define	NETDB_INTERNAL	-1	/* see errno */
-#endif
-
-#ifndef AI_MASK
-/* valid flags for addrinfo */
-#define	AI_MASK		(AI_PASSIVE | AI_CANONNAME | AI_NUMERICHOST)
-#endif
-
-#endif /* HAVE_ADDRINFO */
-
-/*
- * Constants for getnameinfo()
- */
-#ifndef NI_MAXHOST
-#define	NI_MAXHOST	1025
-#endif
-#ifndef NI_MAXSERV
-#define	NI_MAXSERV	32
-#endif
-
-/*
- * Flag values for getnameinfo()
- */
-#ifndef NI_NOFQDN
-#define	NI_NOFQDN	0x00000001
-#endif
-#ifndef NI_NUMERICHOST
-#define	NI_NUMERICHOST	0x00000002
-#endif
-#ifndef NI_NAMEREQD
-#define	NI_NAMEREQD	0x00000004
-#endif
-#ifndef NI_NUMERICSERV
-#define	NI_NUMERICSERV	0x00000008
-#endif
-#ifndef NI_DGRAM
-#define	NI_DGRAM	0x00000010
-#endif
-
diff --git a/Win32/Include/arpa/nameser.h b/Win32/Include/arpa/nameser.h
deleted file mode 100644
index b20dc1e..0000000
--- a/Win32/Include/arpa/nameser.h
+++ /dev/null
@@ -1,349 +0,0 @@
-/*
- * ++Copyright++ 1983, 1989, 1993
- * -
- * Copyright (c) 1983, 1989, 1993
- *    The Regents of the University of California.  All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in the
- *    documentation and/or other materials provided with the distribution.
- * 3. All advertising materials mentioning features or use of this software
- *    must display the following acknowledgement:
- * 	This product includes software developed by the University of
- * 	California, Berkeley and its contributors.
- * 4. Neither the name of the University nor the names of its contributors
- *    may be used to endorse or promote products derived from this software
- *    without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
- * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
- * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- * -
- * Portions Copyright (c) 1993 by Digital Equipment Corporation.
- *
- * Permission to use, copy, modify, and distribute this software for any
- * purpose with or without fee is hereby granted, provided that the above
- * copyright notice and this permission notice appear in all copies, and that
- * the name of Digital Equipment Corporation not be used in advertising or
- * publicity pertaining to distribution of the document or software without
- * specific, written prior permission.
- *
- * THE SOFTWARE IS PROVIDED "AS IS" AND DIGITAL EQUIPMENT CORP. DISCLAIMS ALL
- * WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS.   IN NO EVENT SHALL DIGITAL EQUIPMENT
- * CORPORATION BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
- * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
- * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS
- * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
- * SOFTWARE.
- * -
- * --Copyright--
- */
-
-/*
- *      @(#)nameser.h	8.1 (Berkeley) 6/2/93
- *	nameser.h,v 1.2 1995/05/06 14:23:54 hjl Exp
- */
-
-#ifndef _NAMESER_H_
-#define	_NAMESER_H_
-
-#ifndef WIN32
-#include <sys/param.h>
-#if (!defined(BSD)) || (BSD < 199306)
-# include <sys/bitypes.h>
-#else
-# include <sys/types.h>
-#endif
-#include <sys/cdefs.h>
-#else
-#include <pcap-stdinc.h>
-#define __LITTLE_ENDIAN 1
-#define __BYTE_ORDER __LITTLE_ENDIAN
-#endif
-
-/*
- * revision information.  this is the release date in YYYYMMDD format.
- * it can change every day so the right thing to do with it is use it
- * in preprocessor commands such as "#if (__BIND > 19931104)".  do not
- * compare for equality; rather, use it to determine whether your resolver
- * is new enough to contain a certain feature.
- */
-
-#define	__BIND		19940417	/* interface version stamp */
-
-/*
- * Define constants based on rfc883
- */
-#define PACKETSZ	512		/* maximum packet size */
-#define MAXDNAME	256		/* maximum domain name */
-#define MAXCDNAME	255		/* maximum compressed domain name */
-#define MAXLABEL	63		/* maximum length of domain label */
-#define	HFIXEDSZ	12		/* #/bytes of fixed data in header */
-#define QFIXEDSZ	4		/* #/bytes of fixed data in query */
-#define RRFIXEDSZ	10		/* #/bytes of fixed data in r record */
-#define	INT32SZ		4		/* for systems without 32-bit ints */
-#define	INT16SZ		2		/* for systems without 16-bit ints */
-#define	INADDRSZ	4		/* for sizeof(struct inaddr) != 4 */
-
-/*
- * Internet nameserver port number
- */
-#define NAMESERVER_PORT	53
-
-/*
- * Currently defined opcodes
- */
-#define QUERY		0x0		/* standard query */
-#define IQUERY		0x1		/* inverse query */
-#define STATUS		0x2		/* nameserver status query */
-/*#define xxx		0x3		*//* 0x3 reserved */
-#define	NS_NOTIFY_OP	0x4		/* notify secondary of SOA change */
-#ifdef ALLOW_UPDATES
-	/* non standard - supports ALLOW_UPDATES stuff from Mike Schwartz */
-# define UPDATEA	0x9		/* add resource record */
-# define UPDATED	0xa		/* delete a specific resource record */
-# define UPDATEDA	0xb		/* delete all named resource record */
-# define UPDATEM	0xc		/* modify a specific resource record */
-# define UPDATEMA	0xd		/* modify all named resource record */
-# define ZONEINIT	0xe		/* initial zone transfer */
-# define ZONEREF	0xf		/* incremental zone referesh */
-#endif
-
-/*
- * Currently defined response codes
- */
-#ifdef HAVE_ADDRINFO
-#define NOERROR		0		/* no error */
-#endif /* HAVE_ADDRINFO */
-#define FORMERR		1		/* format error */
-#define SERVFAIL	2		/* server failure */
-#define NXDOMAIN	3		/* non existent domain */
-#define NOTIMP		4		/* not implemented */
-#define REFUSED		5		/* query refused */
-#ifdef ALLOW_UPDATES
-	/* non standard */
-# define NOCHANGE	0xf		/* update failed to change db */
-#endif
-
-/*
- * Type values for resources and queries
- */
-#define T_A		1		/* host address */
-#define T_NS		2		/* authoritative server */
-#define T_MD		3		/* mail destination */
-#define T_MF		4		/* mail forwarder */
-#define T_CNAME		5		/* canonical name */
-#define T_SOA		6		/* start of authority zone */
-#define T_MB		7		/* mailbox domain name */
-#define T_MG		8		/* mail group member */
-#define T_MR		9		/* mail rename name */
-#define T_NULL		10		/* null resource record */
-#define T_WKS		11		/* well known service */
-#define T_PTR		12		/* domain name pointer */
-#define T_HINFO		13		/* host information */
-#define T_MINFO		14		/* mailbox information */
-#define T_MX		15		/* mail routing information */
-#define T_TXT		16		/* text strings */
-#define	T_RP		17		/* responsible person */
-#define T_AFSDB		18		/* AFS cell database */
-#define T_X25		19		/* X_25 calling address */
-#define T_ISDN		20		/* ISDN calling address */
-#define T_RT		21		/* router */
-#define T_NSAP		22		/* NSAP address */
-#define T_NSAP_PTR	23		/* reverse NSAP lookup (deprecated) */
-#define	T_SIG		24		/* security signature */
-#define	T_KEY		25		/* security key */
-#define	T_PX		26		/* X.400 mail mapping */
-#define	T_GPOS		27		/* geographical position (withdrawn) */
-#define	T_AAAA		28		/* IP6 Address */
-#define	T_LOC		29		/* Location Information */
-	/* non standard */
-#define T_UINFO		100		/* user (finger) information */
-#define T_UID		101		/* user ID */
-#define T_GID		102		/* group ID */
-#define T_UNSPEC	103		/* Unspecified format (binary data) */
-	/* Query type values which do not appear in resource records */
-#define T_AXFR		252		/* transfer zone of authority */
-#define T_MAILB		253		/* transfer mailbox records */
-#define T_MAILA		254		/* transfer mail agent records */
-#define T_ANY		255		/* wildcard match */
-
-/*
- * Values for class field
- */
-
-#define C_IN		1		/* the arpa internet */
-#define C_CHAOS		3		/* for chaos net (MIT) */
-#define C_HS		4		/* for Hesiod name server (MIT) (XXX) */
-	/* Query class values which do not appear in resource records */
-#define C_ANY		255		/* wildcard match */
-
-/*
- * Status return codes for T_UNSPEC conversion routines
- */
-#define CONV_SUCCESS	0
-#define CONV_OVERFLOW	(-1)
-#define CONV_BADFMT	(-2)
-#define CONV_BADCKSUM	(-3)
-#define CONV_BADBUFLEN	(-4)
-
-#ifndef __BYTE_ORDER
-#if (BSD >= 199103)
-# include <machine/endian.h>
-#else
-#ifdef linux
-# include <endian.h>
-#else
-#define	__LITTLE_ENDIAN	1234	/* least-significant byte first (vax, pc) */
-#define	__BIG_ENDIAN	4321	/* most-significant byte first (IBM, net) */
-#define	__PDP_ENDIAN	3412	/* LSB first in word, MSW first in long (pdp)*/
-
-#if defined(vax) || defined(ns32000) || defined(sun386) || defined(i386) || \
-    defined(MIPSEL) || defined(_MIPSEL) || defined(BIT_ZERO_ON_RIGHT) || \
-    defined(__alpha__) || defined(__alpha)
-#define __BYTE_ORDER	__LITTLE_ENDIAN
-#endif
-
-#if defined(sel) || defined(pyr) || defined(mc68000) || defined(sparc) || \
-    defined(is68k) || defined(tahoe) || defined(ibm032) || defined(ibm370) || \
-    defined(MIPSEB) || defined(_MIPSEB) || defined(_IBMR2) || defined(DGUX) ||\
-    defined(apollo) || defined(__convex__) || defined(_CRAY) || \
-    defined(__hppa) || defined(__hp9000) || \
-    defined(__hp9000s300) || defined(__hp9000s700) || \
-    defined (BIT_ZERO_ON_LEFT) || defined(m68k)
-#define __BYTE_ORDER	__BIG_ENDIAN
-#endif
-#endif /* linux */
-#endif /* BSD */
-#endif /* __BYTE_ORDER */
-
-#if !defined(__BYTE_ORDER) || \
-    (__BYTE_ORDER != __BIG_ENDIAN && __BYTE_ORDER != __LITTLE_ENDIAN && \
-    __BYTE_ORDER != __PDP_ENDIAN)
-	/* you must determine what the correct bit order is for
-	 * your compiler - the next line is an intentional error
-	 * which will force your compiles to bomb until you fix
-	 * the above macros.
-	 */
-  error "Undefined or invalid __BYTE_ORDER";
-#endif
-
-/*
- * Structure for query header.  The order of the fields is machine- and
- * compiler-dependent, depending on the byte/bit order and the layout
- * of bit fields.  We use bit fields only in int variables, as this
- * is all ANSI requires.  This requires a somewhat confusing rearrangement.
- */
-
-typedef struct {
-	unsigned	id :16;		/* query identification number */
-#if __BYTE_ORDER == __BIG_ENDIAN
-			/* fields in third byte */
-	unsigned	qr: 1;		/* response flag */
-	unsigned	opcode: 4;	/* purpose of message */
-	unsigned	aa: 1;		/* authoritive answer */
-	unsigned	tc: 1;		/* truncated message */
-	unsigned	rd: 1;		/* recursion desired */
-			/* fields in fourth byte */
-	unsigned	ra: 1;		/* recursion available */
-	unsigned	pr: 1;		/* primary server req'd (!standard) */
-	unsigned	unused :2;	/* unused bits (MBZ as of 4.9.3a3) */
-	unsigned	rcode :4;	/* response code */
-#endif
-#if __BYTE_ORDER == __LITTLE_ENDIAN || __BYTE_ORDER == __PDP_ENDIAN
-			/* fields in third byte */
-	unsigned	rd :1;		/* recursion desired */
-	unsigned	tc :1;		/* truncated message */
-	unsigned	aa :1;		/* authoritive answer */
-	unsigned	opcode :4;	/* purpose of message */
-	unsigned	qr :1;		/* response flag */
-			/* fields in fourth byte */
-	unsigned	rcode :4;	/* response code */
-	unsigned	unused :2;	/* unused bits (MBZ as of 4.9.3a3) */
-	unsigned	pr :1;		/* primary server req'd (!standard) */
-	unsigned	ra :1;		/* recursion available */
-#endif
-			/* remaining bytes */
-	unsigned	qdcount :16;	/* number of question entries */
-	unsigned	ancount :16;	/* number of answer entries */
-	unsigned	nscount :16;	/* number of authority entries */
-	unsigned	arcount :16;	/* number of resource entries */
-} HEADER;
-
-/*
- * Defines for handling compressed domain names
- */
-#define INDIR_MASK	0xc0
-
-/*
- * Structure for passing resource records around.
- */
-struct rrec {
-	int16_t		r_zone;			/* zone number */
-	int16_t		r_class;		/* class number */
-	int16_t		r_type;			/* type number */
-	u_int32_t	r_ttl;			/* time to live */
-	int		r_size;			/* size of data area */
-	char		*r_data;		/* pointer to data */
-};
-
-//extern	u_int16_t	_getshort __P((const u_char *));
-//extern	u_int32_t	_getlong __P((const u_char *));
-
-/*
- * Inline versions of get/put short/long.  Pointer is advanced.
- *
- * These macros demonstrate the property of C whereby it can be
- * portable or it can be elegant but rarely both.
- */
-#define GETSHORT(s, cp) { \
-	register u_char *t_cp = (u_char *)(cp); \
-	(s) = ((u_int16_t)t_cp[0] << 8) \
-	    | ((u_int16_t)t_cp[1]) \
-	    ; \
-	(cp) += INT16SZ; \
-}
-
-#define GETLONG(l, cp) { \
-	register u_char *t_cp = (u_char *)(cp); \
-	(l) = ((u_int32_t)t_cp[0] << 24) \
-	    | ((u_int32_t)t_cp[1] << 16) \
-	    | ((u_int32_t)t_cp[2] << 8) \
-	    | ((u_int32_t)t_cp[3]) \
-	    ; \
-	(cp) += INT32SZ; \
-}
-
-#define PUTSHORT(s, cp) { \
-	register u_int16_t t_s = (u_int16_t)(s); \
-	register u_char *t_cp = (u_char *)(cp); \
-	*t_cp++ = t_s >> 8; \
-	*t_cp   = t_s; \
-	(cp) += INT16SZ; \
-}
-
-#define PUTLONG(l, cp) { \
-	register u_int32_t t_l = (u_int32_t)(l); \
-	register u_char *t_cp = (u_char *)(cp); \
-	*t_cp++ = t_l >> 24; \
-	*t_cp++ = t_l >> 16; \
-	*t_cp++ = t_l >> 8; \
-	*t_cp   = t_l; \
-	(cp) += INT32SZ; \
-}
-
-#endif /* !_NAMESER_H_ */
diff --git a/Win32/Include/bittypes.h b/Win32/Include/bittypes.h
deleted file mode 100644
index 95aa9fa..0000000
--- a/Win32/Include/bittypes.h
+++ /dev/null
@@ -1,89 +0,0 @@
-/*
- * Copyright (C) 1999 WIDE Project.
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in the
- *    documentation and/or other materials provided with the distribution.
- * 3. Neither the name of the project nor the names of its contributors
- *    may be used to endorse or promote products derived from this software
- *    without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED.  IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE
- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
- * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
- * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- */
-#ifndef _BITTYPES_H
-#define _BITTYPES_H
-
-#ifndef HAVE_U_INT8_T
-typedef unsigned char u_int8_t;
-typedef signed char int8_t;
-#endif /* HAVE_U_INT8_T */
-
-#ifndef HAVE_U_INT16_T
-typedef unsigned short u_int16_t;
-typedef signed short int16_t;
-#endif /* HAVE_U_INT16_T */
-
-#ifndef HAVE_U_INT32_T
-typedef unsigned int u_int32_t;
-typedef signed int int32_t;
-#endif /* HAVE_U_INT32_T */
-
-#ifndef HAVE_U_INT64_T
-#ifdef _MSC_EXTENSIONS
-typedef unsigned _int64 u_int64_t;
-typedef _int64 int64_t;
-#else /* _MSC_EXTENSIONS */
-typedef unsigned long long u_int64_t;
-typedef long long int64_t;
-#endif /* _MSC_EXTENSIONS */
-#endif /* HAVE_U_INT64_T */
-
-#ifndef PRId64
-#ifdef _MSC_EXTENSIONS
-#define PRId64	"I64d"
-#else /* _MSC_EXTENSIONS */
-#define PRId64	"lld"
-#endif /* _MSC_EXTENSIONS */
-#endif /* PRId64 */
-
-#ifndef PRIo64
-#ifdef _MSC_EXTENSIONS
-#define PRIo64	"I64o"
-#else /* _MSC_EXTENSIONS */
-#define PRIo64	"llo"
-#endif /* _MSC_EXTENSIONS */
-#endif /* PRIo64 */
-
-#ifndef PRIx64
-#ifdef _MSC_EXTENSIONS
-#define PRIx64	"I64x"
-#else /* _MSC_EXTENSIONS */
-#define PRIx64	"llx"
-#endif /* _MSC_EXTENSIONS */
-#endif /* PRIx64 */
-
-#ifndef PRIu64
-#ifdef _MSC_EXTENSIONS
-#define PRIu64	"I64u"
-#else /* _MSC_EXTENSIONS */
-#define PRIu64	"llu"
-#endif /* _MSC_EXTENSIONS */
-#endif /* PRIu64 */
-
-#endif /* _BITTYPES_H */
diff --git a/Win32/Include/cdecl_ext.h b/Win32/Include/cdecl_ext.h
deleted file mode 100644
index 9d40b84..0000000
--- a/Win32/Include/cdecl_ext.h
+++ /dev/null
@@ -1,37 +0,0 @@
-/*
- * Copyright (C) 1999 WIDE Project.
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in the
- *    documentation and/or other materials provided with the distribution.
- * 3. Neither the name of the project nor the names of its contributors
- *    may be used to endorse or promote products derived from this software
- *    without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED.  IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE
- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
- * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
- * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- */
-#ifndef HAVE_PORTABLE_PROTOTYPE
-
-#if defined(__STDC__) || defined(__cplusplus)
-#define	__P(protos)	protos		/* full-blown ANSI C */
-#else
-#define	__P(protos)	()		/* traditional C preprocessor */
-#endif
-
-#endif /* !HAVE_PORTABLE_PROTOTYPE */
diff --git a/Win32/Include/inetprivate.h b/Win32/Include/inetprivate.h
deleted file mode 100644
index e25ed3d..0000000
--- a/Win32/Include/inetprivate.h
+++ /dev/null
@@ -1,67 +0,0 @@
-/*
- * Copyright (c) 1999 - 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 <sys/types.h>
-#include <string.h>
-#include <stdlib.h>
-#include <ctype.h>
-#include <net/netdb.h>
-#include <stdio.h>
-#include <errno.h>
-#include <arpa/nameser.h>
-
-extern void _sethtent(int f);
-extern void _endhtent(void);
-extern struct hostent *_gethtent(void);
-extern struct hostent *_gethtbyname(const char *name);
-extern struct hostent *_gethtbyaddr(const char *addr, int len,
-		 int type);
-extern int _validuser(FILE *hostf, const char *rhost,
-		 const char *luser, const char *ruser, int baselen);
-extern int _checkhost(const char *rhost, const char *lhost, int len);
-#if 0
-extern void putlong(u_long l, u_char *msgp);
-extern void putshort(u_short l, u_char *msgp);
-extern u_int32_t _getlong(register const u_char *msgp);
-extern u_int16_t _getshort(register const u_char *msgp);
-extern void p_query(char *msg);
-extern void fp_query(char *msg, FILE *file);
-extern char *p_cdname(char *cp, char *msg, FILE *file);
-extern char *p_rr(char *cp, char *msg, FILE *file);
-extern char *p_type(int type);
-extern char * p_class(int class);
-extern char *p_time(u_long value);
-#endif
-extern char * hostalias(const char *name);
-extern void sethostfile(char *name);
-extern void _res_close (void);
-extern void ruserpass(const char *host, char **aname, char **apass);
diff --git a/Win32/Include/ip6_misc.h b/Win32/Include/ip6_misc.h
deleted file mode 100644
index 0b578c3..0000000
--- a/Win32/Include/ip6_misc.h
+++ /dev/null
@@ -1,161 +0,0 @@
-/*
- * Copyright (c) 1993, 1994, 1997
- *	The Regents of the University of California.  All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that: (1) source code distributions
- * retain the above copyright notice and this paragraph in its entirety, (2)
- * distributions including binary code include the above copyright notice and
- * this paragraph in its entirety in the documentation or other materials
- * provided with the distribution, and (3) all advertising materials mentioning
- * features or use of this software display the following acknowledgement:
- * ``This product includes software developed by the University of California,
- * Lawrence Berkeley Laboratory and its contributors.'' Neither the name of
- * the University nor the names of its contributors may be used to endorse
- * or promote products derived from this software without specific prior
- * written permission.
- * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
- * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
- * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
- */
-
-/*
- * This file contains a collage of declarations for IPv6 from FreeBSD not present in Windows
- */
-
-#include <winsock2.h>
-
-#include <ws2tcpip.h>
-
-#ifndef __MINGW32__
-#define	IN_MULTICAST(a)		IN_CLASSD(a)
-#endif
-
-#define	IN_EXPERIMENTAL(a)	((((u_int32_t) (a)) & 0xf0000000) == 0xf0000000)
-
-#define	IN_LOOPBACKNET		127
-
-#if defined(__MINGW32__) && defined(DEFINE_ADDITIONAL_IPV6_STUFF)
-/* IPv6 address */
-struct in6_addr
-  {
-    union
-      {
-	u_int8_t		u6_addr8[16];
-	u_int16_t	u6_addr16[8];
-	u_int32_t	u6_addr32[4];
-      } in6_u;
-#define s6_addr			in6_u.u6_addr8
-#define s6_addr16		in6_u.u6_addr16
-#define s6_addr32		in6_u.u6_addr32
-#define s6_addr64		in6_u.u6_addr64
-  };
-
-#define IN6ADDR_ANY_INIT { 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 }
-#define IN6ADDR_LOOPBACK_INIT { 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1 }
-#endif /* __MINGW32__ */
-
-
-#if (defined _MSC_VER) || (defined(__MINGW32__) && defined(DEFINE_ADDITIONAL_IPV6_STUFF))
-typedef unsigned short	sa_family_t;
-#endif
-
-
-#if defined(__MINGW32__) && defined(DEFINE_ADDITIONAL_IPV6_STUFF)
-
-#define	__SOCKADDR_COMMON(sa_prefix) \
-  sa_family_t sa_prefix##family
-
-/* Ditto, for IPv6.  */
-struct sockaddr_in6
-  {
-    __SOCKADDR_COMMON (sin6_);
-    u_int16_t sin6_port;		/* Transport layer port # */
-    u_int32_t sin6_flowinfo;	/* IPv6 flow information */
-    struct in6_addr sin6_addr;	/* IPv6 address */
-  };
-
-#define IN6_IS_ADDR_V4MAPPED(a) \
-	((((u_int32_t *) (a))[0] == 0) && (((u_int32_t *) (a))[1] == 0) && \
-	 (((u_int32_t *) (a))[2] == htonl (0xffff)))
-
-#define IN6_IS_ADDR_MULTICAST(a) (((u_int8_t *) (a))[0] == 0xff)
-
-#define IN6_IS_ADDR_LINKLOCAL(a) \
-	((((u_int32_t *) (a))[0] & htonl (0xffc00000)) == htonl (0xfe800000))
-
-#define IN6_IS_ADDR_LOOPBACK(a) \
-	(((u_int32_t *) (a))[0] == 0 && ((u_int32_t *) (a))[1] == 0 && \
-	 ((u_int32_t *) (a))[2] == 0 && ((u_int32_t *) (a))[3] == htonl (1))
-#endif /* __MINGW32__ */
-
-#define ip6_vfc   ip6_ctlun.ip6_un2_vfc
-#define ip6_flow  ip6_ctlun.ip6_un1.ip6_un1_flow
-#define ip6_plen  ip6_ctlun.ip6_un1.ip6_un1_plen
-#define ip6_nxt   ip6_ctlun.ip6_un1.ip6_un1_nxt
-#define ip6_hlim  ip6_ctlun.ip6_un1.ip6_un1_hlim
-#define ip6_hops  ip6_ctlun.ip6_un1.ip6_un1_hlim
-
-#define nd_rd_type               nd_rd_hdr.icmp6_type
-#define nd_rd_code               nd_rd_hdr.icmp6_code
-#define nd_rd_cksum              nd_rd_hdr.icmp6_cksum
-#define nd_rd_reserved           nd_rd_hdr.icmp6_data32[0]
-
-/*
- *	IPV6 extension headers
- */
-#define IPPROTO_HOPOPTS		0	/* IPv6 hop-by-hop options	*/
-#define IPPROTO_IPV6		41  /* IPv6 header.  */
-#define IPPROTO_ROUTING		43	/* IPv6 routing header		*/
-#define IPPROTO_FRAGMENT	44	/* IPv6 fragmentation header	*/
-#define IPPROTO_ESP		50	/* encapsulating security payload */
-#define IPPROTO_AH		51	/* authentication header	*/
-#define IPPROTO_ICMPV6		58	/* ICMPv6			*/
-#define IPPROTO_NONE		59	/* IPv6 no next header		*/
-#define IPPROTO_DSTOPTS		60	/* IPv6 destination options	*/
-#define IPPROTO_PIM			103 /* Protocol Independent Multicast.  */
-
-#define	 IPV6_RTHDR_TYPE_0 0
-
-/* Option types and related macros */
-#define IP6OPT_PAD1		0x00	/* 00 0 00000 */
-#define IP6OPT_PADN		0x01	/* 00 0 00001 */
-#define IP6OPT_JUMBO		0xC2	/* 11 0 00010 = 194 */
-#define IP6OPT_JUMBO_LEN	6
-#define IP6OPT_ROUTER_ALERT	0x05	/* 00 0 00101 */
-
-#define IP6OPT_RTALERT_LEN	4
-#define IP6OPT_RTALERT_MLD	0	/* Datagram contains an MLD message */
-#define IP6OPT_RTALERT_RSVP	1	/* Datagram contains an RSVP message */
-#define IP6OPT_RTALERT_ACTNET	2 	/* contains an Active Networks msg */
-#define IP6OPT_MINLEN		2
-
-#define IP6OPT_BINDING_UPDATE	0xc6	/* 11 0 00110 */
-#define IP6OPT_BINDING_ACK	0x07	/* 00 0 00111 */
-#define IP6OPT_BINDING_REQ	0x08	/* 00 0 01000 */
-#define IP6OPT_HOME_ADDRESS	0xc9	/* 11 0 01001 */
-#define IP6OPT_EID		0x8a	/* 10 0 01010 */
-
-#define IP6OPT_TYPE(o)		((o) & 0xC0)
-#define IP6OPT_TYPE_SKIP	0x00
-#define IP6OPT_TYPE_DISCARD	0x40
-#define IP6OPT_TYPE_FORCEICMP	0x80
-#define IP6OPT_TYPE_ICMP	0xC0
-
-#define IP6OPT_MUTABLE		0x20
-
-
-#if defined(__MINGW32__) && defined(DEFINE_ADDITIONAL_IPV6_STUFF)
-#ifndef EAI_ADDRFAMILY
-struct addrinfo {
-	int	ai_flags;	/* AI_PASSIVE, AI_CANONNAME */
-	int	ai_family;	/* PF_xxx */
-	int	ai_socktype;	/* SOCK_xxx */
-	int	ai_protocol;	/* 0 or IPPROTO_xxx for IPv4 and IPv6 */
-	size_t	ai_addrlen;	/* length of ai_addr */
-	char	*ai_canonname;	/* canonical name for hostname */
-	struct sockaddr *ai_addr;	/* binary address */
-	struct addrinfo *ai_next;	/* next structure in linked list */
-};
-#endif
-#endif /* __MINGW32__ */
diff --git a/Win32/Include/net/netdb.h b/Win32/Include/net/netdb.h
deleted file mode 100644
index f7685d2..0000000
--- a/Win32/Include/net/netdb.h
+++ /dev/null
@@ -1,166 +0,0 @@
-/*-
- * Copyright (c) 1980, 1983, 1988, 1993
- *     The Regents of the University of California.  All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in the
- *    documentation and/or other materials provided with the distribution.
- * 3. All advertising materials mentioning features or use of this software
- *    must display the following acknowledgement:
- *	This product includes software developed by the University of
- *	California, Berkeley and its contributors.
- * 4. Neither the name of the University nor the names of its contributors
- *    may be used to endorse or promote products derived from this software
- *    without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
- * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
- * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- *
- *	@(#)netdb.h	8.1 (Berkeley) 6/2/93
- *      netdb.h,v 1.4 1995/08/14 04:05:04 hjl Exp
- * -
- * Portions Copyright (c) 1993 by Digital Equipment Corporation.
- *
- * Permission to use, copy, modify and distribute this software for any
- * purpose with or without fee is hereby granted, provided that the above
- * copyright notice and this permission notice appear in all copies, and that
- * the name of Digital Equipment Corporation not be used in advertising or
- * publicity pertaining to distribution of the document or software without
- * specific, written prior permission.
- *
- * THE SOFTWARE IS PROVIDED "AS IS" AND DIGITAL EQUIPMENT CORP. DISCLAIMS ALL
- * WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS.   IN NO EVENT SHALL DIGITAL EQUIPMENT
- * CORPORATION BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
- * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
- * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS
- * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
- * SOFTWARE.
- * -
- * --Copyright--
- */
-
-#ifndef _NETDB_H_
-#define _NETDB_H_
-
-/* MingW64 defines _POSIX_THREAD_SAFE_FUNCTIONS.
- */
-#if defined(_POSIX_THREAD_SAFE_FUNCTIONS) || defined(_REENTRANT) && !defined(__MINGW64_VERSION_MAJOR)
-#include <stdio.h>
-#include <netinet/in.h>
-#endif
-
-#include <winsock2.h>
-#include <net/paths.h>
-
-#define _PATH_HEQUIV	__PATH_ETC_INET"/hosts.equiv"
-#define _PATH_HOSTS	__PATH_ETC_INET"/hosts"
-#define _PATH_NETWORKS	__PATH_ETC_INET"/networks"
-#define _PATH_PROTOCOLS	__PATH_ETC_INET"/protocols"
-#define _PATH_SERVICES	__PATH_ETC_INET"/services"
-#define _PATH_RESCONF	__PATH_ETC_INET"/resolv.conf"
-#define _PATH_RPC	__PATH_ETC_INET"/rpc"
-
-struct rpcent {
-	char	*r_name;	/* name of server for this rpc program */
-	char	**r_aliases;	/* alias list */
-	int	r_number;	/* rpc program number */
-};
-
-#ifndef WIN32
-#if defined(_POSIX_THREAD_SAFE_FUNCTIONS) || defined(_REENTRANT)
-
-#define __NETDB_MAXALIASES	35
-#define __NETDB_MAXADDRS	35
-
-/*
- * Error return codes from gethostbyname() and gethostbyaddr()
- * (left in extern int h_errno).
- */
-#define h_errno		(*__h_errno_location ())
-#else
-extern int h_errno;
-#endif
-#endif
-
-#define	NETDB_INTERNAL -1 /* see errno */
-#define	NETDB_SUCCESS   0 /* no problem */
-
-//#include <features.h>
-
-void		endhostent (void);
-void		endnetent (void);
-void		endprotoent (void);
-void		endservent (void);
-void		endrpcent (void);
-struct hostent	*gethostent (void);
-struct netent	*getnetbyaddr (long, int); /* u_long? */
-struct netent	*getnetbyname (const char *);
-struct netent	*getnetent (void);
-struct protoent	*getprotoent (void);
-struct servent	*getservent (void);
-struct rpcent	*getrpcent (void);
-struct rpcent	*getrpcbyname (const char *);
-struct rpcent	*getrpcbynumber (int);
-void		herror (const char *);
-void		sethostent (int);
-/* void		sethostfile (const char *); */
-void		setnetent (int);
-void		setprotoent (int);
-void		setservent (int);
-void		setrpcent (int);
-
-#if defined(_POSIX_THREAD_SAFE_FUNCTIONS) || defined(_REENTRANT)
-struct hostent	*gethostbyaddr_r (const char *__addr,
-			int __length, int __type,
-			struct hostent *__result,
-			char *__buffer, int __buflen, int *__h_errnop);
-struct hostent	*gethostbyname_r (const char * __name,
-			struct hostent *__result, char *__buffer,
-			int __buflen, int *__h_errnop);
-struct hostent	*gethostent_r (struct hostent *__result,
-			char *__buffer, int __buflen, int *__h_errnop);
-struct netent	*getnetbyaddr_r (long __net, int __type,
-			struct netent *__result, char *__buffer,
-			int __buflen);
-struct netent	*getnetbyname_r (const char * __name,
-			struct netent *__result, char *__buffer,
-			int __buflen);
-struct netent	*getnetent_r (struct netent *__result,
-			char *__buffer, int __buflen);
-struct protoent	*getprotobyname_r (const char * __name,
-			struct protoent *__result, char *__buffer,
-			int __buflen);
-struct protoent	*getprotobynumber_r (int __proto,
-			struct protoent *__result, char *__buffer,
-			int __buflen);
-struct protoent	*getprotoent_r (struct protoent *__result,
-			char *__buffer, int __buflen);
-struct servent	*getservbyname_r (const char * __name,
-			const char *__proto, struct servent *__result,
-			char *__buffer, int __buflen);
-struct servent	*getservbyport_r (int __port,
-			const char *__proto, struct servent *__result,
-			char *__buffer, int __buflen);
-struct servent	*getservent_r (struct servent *__result,
-			char *__buffer, int __buflen);
-
-int *__h_errno_location (void);
-
-#endif
-
-#endif /* !_NETDB_H_ */
diff --git a/Win32/Include/net/paths.h b/Win32/Include/net/paths.h
deleted file mode 100644
index 987de4f..0000000
--- a/Win32/Include/net/paths.h
+++ /dev/null
@@ -1,105 +0,0 @@
-/*
- * Copyright (c) 1989 The Regents of the University of California.
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in the
- *    documentation and/or other materials provided with the distribution.
- * 3. All advertising materials mentioning features or use of this software
- *    must display the following acknowledgement:
- *	This product includes software developed by the University of
- *	California, Berkeley and its contributors.
- * 4. Neither the name of the University nor the names of its contributors
- *    may be used to endorse or promote products derived from this software
- *    without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
- * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
- * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- *
- *	@(#)paths.h	5.15 (Berkeley) 5/29/91
- */
-
-#ifndef _PATHS_H_
-#define	_PATHS_H_
-
-#if 0
-#define	__PATH_ETC_INET	"/usr/etc/inet"
-#else
-#define	__PATH_ETC_INET	"/etc"
-#endif
-
-/* Default search path. */
-#define	_PATH_DEFPATH		"/usr/local/bin:/usr/bin:/bin:."
-#define _PATH_DEFPATH_ROOT	"/sbin:/bin:/usr/sbin:/usr/bin"
-
-#define	_PATH_BSHELL	"/bin/sh"
-#define	_PATH_CONSOLE	"/dev/console"
-#define	_PATH_CSHELL	"/bin/csh"
-#define	_PATH_DEVDB	"/var/run/dev.db"
-#define	_PATH_DEVNULL	"/dev/null"
-#define	_PATH_DRUM	"/dev/drum"
-#define	_PATH_HEQUIV	__PATH_ETC_INET"/hosts.equiv"
-#define	_PATH_KMEM	"/dev/kmem"
-#define	_PATH_MAILDIR	"/var/spool/mail"
-#define	_PATH_MAN	"/usr/man"
-#define	_PATH_MEM	"/dev/mem"
-#define	_PATH_LOGIN	"/bin/login"
-#define	_PATH_NOLOGIN	"/etc/nologin"
-#define	_PATH_SENDMAIL	"/usr/sbin/sendmail"
-#define	_PATH_SHELLS	"/etc/shells"
-#define	_PATH_TTY	"/dev/tty"
-#define	_PATH_UNIX	"/vmlinux"
-#define	_PATH_VI	"/usr/bin/vi"
-
-/* Provide trailing slash, since mostly used for building pathnames. */
-#define	_PATH_DEV	"/dev/"
-#define	_PATH_TMP	"/tmp/"
-#define	_PATH_VARRUN	"/var/run/"
-#define	_PATH_VARTMP	"/var/tmp/"
-
-#define _PATH_KLOG	"/proc/kmsg"
-#define _PATH_LOGCONF	__PATH_ETC_INET"/syslog.conf"
-#if 0
-#define _PATH_LOGPID	__PATH_ETC_INET"/syslog.pid"
-#else
-#define _PATH_LOGPID	"/var/run/syslog.pid"
-#endif
-#define _PATH_LOG	"/dev/log"
-#define _PATH_CONSOLE	"/dev/console"
-
-#if 0
-#define _PATH_UTMP	"/var/adm/utmp"
-#define _PATH_WTMP	"/var/adm/wtmp"
-#define _PATH_LASTLOG	"/var/adm/lastlog"
-#else
-#define _PATH_UTMP	"/var/run/utmp"
-#define _PATH_WTMP	"/var/log/wtmp"
-#define _PATH_LASTLOG	"/var/log/lastlog"
-#endif
-
-#define _PATH_LOCALE	"/usr/lib/locale"
-
-#define _PATH_RWHODIR	"/var/spool/rwho"
-
-#if _MIT_POSIX_THREADS
-/* For the MIT pthreads */
-#define _PATH_PTY	"/dev/"
-#define _PATH_TZDIR	"/usr/lib/zoneinfo"
-#define _PATH_TZFILE	"/usr/lib/zoneinfo/localtime"
-#endif
-
-#endif /* !_PATHS_H_ */
diff --git a/Win32/Include/sockstorage.h b/Win32/Include/sockstorage.h
deleted file mode 100644
index cbad190..0000000
--- a/Win32/Include/sockstorage.h
+++ /dev/null
@@ -1,38 +0,0 @@
-/*
- * Copyright (C) 1999 WIDE Project.
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in the
- *    documentation and/or other materials provided with the distribution.
- * 3. Neither the name of the project nor the names of its contributors
- *    may be used to endorse or promote products derived from this software
- *    without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED.  IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE
- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
- * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
- * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- */
-struct sockaddr_storage {
-#ifdef HAVE_SOCKADDR_SA_LEN
-	u_int8_t __ss_len;
-	u_int8_t __ss_family;
-	u_int8_t fill[126];
-#else
-	u_int8_t __ss_family;
-	u_int8_t fill[127];
-#endif /* HAVE_SOCKADDR_SA_LEN */
-};
diff --git a/Win32/Prj/libpcap.dsp b/Win32/Prj/libpcap.dsp
deleted file mode 100644
index 7082122..0000000
--- a/Win32/Prj/libpcap.dsp
+++ /dev/null
@@ -1,168 +0,0 @@
-# Microsoft Developer Studio Project File - Name="libpcap" - Package Owner=<4>
-# Microsoft Developer Studio Generated Build File, Format Version 6.00
-# ** DO NOT EDIT **
-
-# TARGTYPE "Win32 (x86) Static Library" 0x0104
-
-CFG=libpcap - Win32 Debug
-!MESSAGE This is not a valid makefile. To build this project using NMAKE,
-!MESSAGE use the Export Makefile command and run
-!MESSAGE
-!MESSAGE NMAKE /f "libpcap.mak".
-!MESSAGE
-!MESSAGE You can specify a configuration when running NMAKE
-!MESSAGE by defining the macro CFG on the command line. For example:
-!MESSAGE
-!MESSAGE NMAKE /f "libpcap.mak" CFG="libpcap - Win32 Debug"
-!MESSAGE
-!MESSAGE Possible choices for configuration are:
-!MESSAGE
-!MESSAGE "libpcap - Win32 Release" (based on "Win32 (x86) Static Library")
-!MESSAGE "libpcap - Win32 Debug" (based on "Win32 (x86) Static Library")
-!MESSAGE
-
-# Begin Project
-# PROP AllowPerConfigDependencies 0
-# PROP Scc_ProjName ""
-# PROP Scc_LocalPath ""
-CPP=cl.exe
-RSC=rc.exe
-
-!IF  "$(CFG)" == "libpcap - Win32 Release"
-
-# PROP BASE Use_MFC 0
-# PROP BASE Use_Debug_Libraries 0
-# PROP BASE Output_Dir "Release"
-# PROP BASE Intermediate_Dir "Release"
-# PROP BASE Target_Dir ""
-# PROP Use_MFC 0
-# PROP Use_Debug_Libraries 0
-# PROP Output_Dir "Release"
-# PROP Intermediate_Dir "Release"
-# PROP Target_Dir ""
-# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_MBCS" /D "_LIB" /YX /FD /c
-# ADD CPP /nologo /MT /W3 /GX /O2 /I "../../" /I "../../lbl/" /I "../../bpf/" /I "../include/" /I "../../../../common" /I "../../../../dag/include" /I "../../../../dag/drv/windows" /D "NDEBUG" /D "YY_NEVER_INTERACTIVE" /D yylval=pcap_lval /D "_USRDLL" /D "LIBPCAP_EXPORTS" /D "HAVE_STRERROR" /D "__STDC__" /D "INET6" /D "_WINDOWS" /D "_MBCS" /D "HAVE_ADDRINFO" /D "WIN32" /D _U_= /D "HAVE_SNPRINTF" /D "HAVE_VSNPRINTF" /YX /FD /c
-# ADD BASE RSC /l 0x409 /d "NDEBUG"
-# ADD RSC /l 0x409 /d "NDEBUG"
-BSC32=bscmake.exe
-# ADD BASE BSC32 /nologo
-# ADD BSC32 /nologo
-LIB32=link.exe -lib
-# ADD BASE LIB32 /nologo
-# ADD LIB32 /nologo
-
-!ELSEIF  "$(CFG)" == "libpcap - Win32 Debug"
-
-# PROP BASE Use_MFC 0
-# PROP BASE Use_Debug_Libraries 1
-# PROP BASE Output_Dir "Debug"
-# PROP BASE Intermediate_Dir "Debug"
-# PROP BASE Target_Dir ""
-# PROP Use_MFC 0
-# PROP Use_Debug_Libraries 1
-# PROP Output_Dir "Debug"
-# PROP Intermediate_Dir "Debug"
-# PROP Target_Dir ""
-# ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_MBCS" /D "_LIB" /YX /FD /GZ /c
-# ADD CPP /nologo /MTd /W3 /Gm /GX /ZI /Od /I "../../" /I "../../lbl/" /I "../../bpf/" /I "../include/" /I "../../../../common" /I "../../../../dag/include" /I "../../../../dag/drv/windows" /D "_DEBUG" /D "YY_NEVER_INTERACTIVE" /D yylval=pcap_lval /D "_USRDLL" /D "LIBPCAP_EXPORTS" /D "HAVE_STRERROR" /D "__STDC__" /D "INET6" /D "_WINDOWS" /D "_MBCS" /D "HAVE_ADDRINFO" /D "WIN32" /D _U_= /D "HAVE_SNPRINTF" /D "HAVE_VSNPRINTF" /YX /FD /GZ /c
-# ADD BASE RSC /l 0x409 /d "_DEBUG"
-# ADD RSC /l 0x409 /d "_DEBUG"
-BSC32=bscmake.exe
-# ADD BASE BSC32 /nologo
-# ADD BSC32 /nologo
-LIB32=link.exe -lib
-# ADD BASE LIB32 /nologo
-# ADD LIB32 /nologo
-
-!ENDIF
-
-# Begin Target
-
-# Name "libpcap - Win32 Release"
-# Name "libpcap - Win32 Debug"
-# Begin Source File
-
-SOURCE=..\..\bpf_dump.c
-# End Source File
-# Begin Source File
-
-SOURCE=..\..\bpf\net\bpf_filter.c
-# End Source File
-# Begin Source File
-
-SOURCE=..\..\bpf_image.c
-# End Source File
-# Begin Source File
-
-SOURCE=..\..\etherent.c
-# End Source File
-# Begin Source File
-
-SOURCE="..\..\fad-win32.c"
-# End Source File
-# Begin Source File
-
-SOURCE=..\Src\ffs.c
-# End Source File
-# Begin Source File
-
-SOURCE=..\..\gencode.c
-# End Source File
-# Begin Source File
-
-SOURCE=..\Src\getnetbynm.c
-# End Source File
-# Begin Source File
-
-SOURCE=..\Src\getnetent.c
-# End Source File
-# Begin Source File
-
-SOURCE=..\Src\getservent.c
-# End Source File
-# Begin Source File
-
-SOURCE=..\..\grammar.c
-# End Source File
-# Begin Source File
-
-SOURCE=..\..\inet.c
-# End Source File
-# Begin Source File
-
-SOURCE=..\Src\inet_aton.c
-# End Source File
-# Begin Source File
-
-SOURCE=..\Src\inet_net.c
-# End Source File
-# Begin Source File
-
-SOURCE=..\Src\inet_pton.c
-# End Source File
-# Begin Source File
-
-SOURCE=..\..\nametoaddr.c
-# End Source File
-# Begin Source File
-
-SOURCE=..\..\optimize.c
-# End Source File
-# Begin Source File
-
-SOURCE="..\..\Pcap-win32.c"
-# End Source File
-# Begin Source File
-
-SOURCE=..\..\pcap.c
-# End Source File
-# Begin Source File
-
-SOURCE=..\..\savefile.c
-# End Source File
-# Begin Source File
-
-SOURCE=..\..\scanner.c
-# End Source File
-# End Target
-# End Project
diff --git a/Win32/Prj/libpcap.dsw b/Win32/Prj/libpcap.dsw
deleted file mode 100644
index 8cdff2d..0000000
--- a/Win32/Prj/libpcap.dsw
+++ /dev/null
@@ -1,29 +0,0 @@
-Microsoft Developer Studio Workspace File, Format Version 6.00
-# WARNING: DO NOT EDIT OR DELETE THIS WORKSPACE FILE!
-
-###############################################################################
-
-Project: "libpcap"=".\libpcap.dsp" - Package Owner=<4>
-
-Package=<5>
-{{{
-}}}
-
-Package=<4>
-{{{
-}}}
-
-###############################################################################
-
-Global:
-
-Package=<5>
-{{{
-}}}
-
-Package=<3>
-{{{
-}}}
-
-###############################################################################
-
diff --git a/Win32/Prj/wpcap.sln b/Win32/Prj/wpcap.sln
new file mode 100644
index 0000000..5a9fce9
--- /dev/null
+++ b/Win32/Prj/wpcap.sln
@@ -0,0 +1,28 @@
+
+Microsoft Visual Studio Solution File, Format Version 12.00
+# Visual Studio 2013
+VisualStudioVersion = 12.0.40629.0
+MinimumVisualStudioVersion = 10.0.40219.1
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "wpcap", "wpcap.vcxproj", "{8E92D840-6A36-452A-A13C-6E1BA5A2C5A9}"
+EndProject
+Global
+	GlobalSection(SolutionConfigurationPlatforms) = preSolution
+		Debug|Win32 = Debug|Win32
+		Debug|x64 = Debug|x64
+		Release|Win32 = Release|Win32
+		Release|x64 = Release|x64
+	EndGlobalSection
+	GlobalSection(ProjectConfigurationPlatforms) = postSolution
+		{8E92D840-6A36-452A-A13C-6E1BA5A2C5A9}.Debug|Win32.ActiveCfg = Debug|Win32
+		{8E92D840-6A36-452A-A13C-6E1BA5A2C5A9}.Debug|Win32.Build.0 = Debug|Win32
+		{8E92D840-6A36-452A-A13C-6E1BA5A2C5A9}.Debug|x64.ActiveCfg = Debug|x64
+		{8E92D840-6A36-452A-A13C-6E1BA5A2C5A9}.Debug|x64.Build.0 = Debug|x64
+		{8E92D840-6A36-452A-A13C-6E1BA5A2C5A9}.Release|Win32.ActiveCfg = Release|Win32
+		{8E92D840-6A36-452A-A13C-6E1BA5A2C5A9}.Release|Win32.Build.0 = Release|Win32
+		{8E92D840-6A36-452A-A13C-6E1BA5A2C5A9}.Release|x64.ActiveCfg = Release|x64
+		{8E92D840-6A36-452A-A13C-6E1BA5A2C5A9}.Release|x64.Build.0 = Release|x64
+	EndGlobalSection
+	GlobalSection(SolutionProperties) = preSolution
+		HideSolutionNode = FALSE
+	EndGlobalSection
+EndGlobal
diff --git a/Win32/Prj/wpcap.vcxproj b/Win32/Prj/wpcap.vcxproj
new file mode 100644
index 0000000..c923357
--- /dev/null
+++ b/Win32/Prj/wpcap.vcxproj
@@ -0,0 +1,234 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project DefaultTargets="Build" ToolsVersion="12.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+  <ItemGroup Label="ProjectConfigurations">
+    <ProjectConfiguration Include="Debug|Win32">
+      <Configuration>Debug</Configuration>
+      <Platform>Win32</Platform>
+    </ProjectConfiguration>
+    <ProjectConfiguration Include="Debug|x64">
+      <Configuration>Debug</Configuration>
+      <Platform>x64</Platform>
+    </ProjectConfiguration>
+    <ProjectConfiguration Include="Release|Win32">
+      <Configuration>Release</Configuration>
+      <Platform>Win32</Platform>
+    </ProjectConfiguration>
+    <ProjectConfiguration Include="Release|x64">
+      <Configuration>Release</Configuration>
+      <Platform>x64</Platform>
+    </ProjectConfiguration>
+  </ItemGroup>
+  <PropertyGroup Label="Globals">
+    <SccProjectName />
+    <SccLocalPath />
+    <ProjectGuid>{8E92D840-6A36-452A-A13C-6E1BA5A2C5A9}</ProjectGuid>
+  </PropertyGroup>
+  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
+    <ConfigurationType>DynamicLibrary</ConfigurationType>
+    <PlatformToolset>v120</PlatformToolset>
+    <UseOfMfc>false</UseOfMfc>
+    <CharacterSet>MultiByte</CharacterSet>
+  </PropertyGroup>
+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
+    <ConfigurationType>DynamicLibrary</ConfigurationType>
+    <PlatformToolset>v120</PlatformToolset>
+    <UseOfMfc>false</UseOfMfc>
+    <CharacterSet>MultiByte</CharacterSet>
+  </PropertyGroup>
+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
+    <ConfigurationType>DynamicLibrary</ConfigurationType>
+    <PlatformToolset>v120</PlatformToolset>
+    <UseOfMfc>false</UseOfMfc>
+    <CharacterSet>MultiByte</CharacterSet>
+    <WholeProgramOptimization>true</WholeProgramOptimization>
+  </PropertyGroup>
+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
+    <ConfigurationType>DynamicLibrary</ConfigurationType>
+    <PlatformToolset>v120</PlatformToolset>
+    <UseOfMfc>false</UseOfMfc>
+    <CharacterSet>MultiByte</CharacterSet>
+    <WholeProgramOptimization>true</WholeProgramOptimization>
+  </PropertyGroup>
+  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
+  <ImportGroup Label="ExtensionSettings">
+  </ImportGroup>
+  <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="PropertySheets">
+    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+    <Import Project="$(VCTargetsPath)Microsoft.Cpp.UpgradeFromVC60.props" />
+  </ImportGroup>
+  <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="PropertySheets">
+    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+    <Import Project="$(VCTargetsPath)Microsoft.Cpp.UpgradeFromVC60.props" />
+  </ImportGroup>
+  <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="PropertySheets">
+    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+    <Import Project="$(VCTargetsPath)Microsoft.Cpp.UpgradeFromVC60.props" />
+  </ImportGroup>
+  <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="PropertySheets">
+    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+    <Import Project="$(VCTargetsPath)Microsoft.Cpp.UpgradeFromVC60.props" />
+  </ImportGroup>
+  <PropertyGroup Label="UserMacros" />
+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
+    <OutDir>.\Release\</OutDir>
+    <IntDir>.\Release\</IntDir>
+    <LinkIncremental>false</LinkIncremental>
+    <IncludePath>../../../;$(IncludePath)</IncludePath>
+  </PropertyGroup>
+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
+    <LinkIncremental>false</LinkIncremental>
+    <IncludePath>../../../;$(IncludePath)</IncludePath>
+  </PropertyGroup>
+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
+    <OutDir>.\Debug\</OutDir>
+    <IntDir>.\Debug\</IntDir>
+    <LinkIncremental>true</LinkIncremental>
+    <IncludePath>../../../;$(IncludePath)</IncludePath>
+  </PropertyGroup>
+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
+    <LinkIncremental>true</LinkIncremental>
+    <IncludePath>../../../;$(IncludePath)</IncludePath>
+  </PropertyGroup>
+  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
+    <ClCompile>
+      <RuntimeLibrary>MultiThreaded</RuntimeLibrary>
+      <InlineFunctionExpansion>Default</InlineFunctionExpansion>
+      <StringPooling>true</StringPooling>
+      <FunctionLevelLinking>true</FunctionLevelLinking>
+      <Optimization>MaxSpeed</Optimization>
+      <SuppressStartupBanner>true</SuppressStartupBanner>
+      <WarningLevel>Level3</WarningLevel>
+      <AdditionalIncludeDirectories>../../;../../lbl/;../../bpf/;../include/;../../../../common;../../../../dag/include;../../../../dag/drv/windows;../../../Win32-Extensions;./;Win32-Extensions;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+      <PreprocessorDefinitions>HAVE_VERSION_H;__STDC_VERSION__=199901L;HAVE_PACKET_IS_LOOPBACK_ADAPTER;NDEBUG;YY_NEVER_INTERACTIVE;_USRDLL;BUILDING_PCAP;HAVE_STRERROR;__STDC__;INET6;_WINDOWS;HAVE_ADDRINFO;HAVE_REMOTE;WIN32;_U_=;YY_NO_UNISTD_H;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+    </ClCompile>
+    <ResourceCompile>
+      <Culture>0x0409</Culture>
+      <PreprocessorDefinitions>NDEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+    </ResourceCompile>
+    <Link>
+      <AdditionalDependencies>ws2_32.lib;..\..\..\..\packetWin7\Dll\Project\Release No NetMon and AirPcap\Packet.lib;%(AdditionalDependencies)</AdditionalDependencies>
+    </Link>
+    <PreBuildEvent>
+      <Command>call ..\..\GenVersion.bat ..\..\VERSION ..\..\pcap_version.h.in ..\..\pcap_version.h
+win_flex -Ppcap_ -7 --outfile=..\..\scanner.c --header-file=..\..\scanner.h ..\..\scanner.l
+win_bison -ppcap_ --yacc --output=..\..\grammar.c --defines ..\..\grammar.y</Command>
+    </PreBuildEvent>
+  </ItemDefinitionGroup>
+  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
+    <ClCompile>
+      <RuntimeLibrary>MultiThreaded</RuntimeLibrary>
+      <InlineFunctionExpansion>Default</InlineFunctionExpansion>
+      <StringPooling>true</StringPooling>
+      <FunctionLevelLinking>true</FunctionLevelLinking>
+      <Optimization>MaxSpeed</Optimization>
+      <SuppressStartupBanner>true</SuppressStartupBanner>
+      <WarningLevel>Level3</WarningLevel>
+      <AdditionalIncludeDirectories>../../;../../lbl/;../../bpf/;../include/;../../../../common;../../../../dag/include;../../../../dag/drv/windows;../../../Win32-Extensions;./;Win32-Extensions;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+      <PreprocessorDefinitions>HAVE_VERSION_H;__STDC_VERSION__=199901L;HAVE_PACKET_IS_LOOPBACK_ADAPTER;NDEBUG;YY_NEVER_INTERACTIVE;_USRDLL;BUILDING_PCAP;HAVE_STRERROR;__STDC__;INET6;_WINDOWS;HAVE_ADDRINFO;HAVE_REMOTE;WIN32;_U_=;YY_NO_UNISTD_H;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+    </ClCompile>
+    <ResourceCompile>
+      <Culture>0x0409</Culture>
+      <PreprocessorDefinitions>NDEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+    </ResourceCompile>
+    <Link>
+      <AdditionalDependencies>ws2_32.lib;..\..\..\..\packetWin7\Dll\Project\x64\Release No NetMon and AirPcap\Packet.lib;%(AdditionalDependencies)</AdditionalDependencies>
+    </Link>
+    <PreBuildEvent>
+      <Command>call ..\..\GenVersion.bat ..\..\VERSION ..\..\pcap_version.h.in ..\..\pcap_version.h
+win_flex -Ppcap_ -7 --outfile=..\..\scanner.c --header-file=..\..\scanner.h ..\..\scanner.l
+win_bison -ppcap_ --yacc --output=..\..\grammar.c --defines ..\..\grammar.y</Command>
+    </PreBuildEvent>
+  </ItemDefinitionGroup>
+  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
+    <ClCompile>
+      <RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary>
+      <InlineFunctionExpansion>Default</InlineFunctionExpansion>
+      <FunctionLevelLinking>false</FunctionLevelLinking>
+      <Optimization>Disabled</Optimization>
+      <SuppressStartupBanner>true</SuppressStartupBanner>
+      <WarningLevel>Level3</WarningLevel>
+      <MinimalRebuild>true</MinimalRebuild>
+      <DebugInformationFormat>EditAndContinue</DebugInformationFormat>
+      <AdditionalIncludeDirectories>../../;../../lbl/;../../bpf/;../include/;../../../../common;../../../../dag/include;../../../../dag/drv/windows;../../../Win32-Extensions;./;Win32-Extensions;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+      <PreprocessorDefinitions>HAVE_VERSION_H;__STDC_VERSION__=199901L;HAVE_PACKET_IS_LOOPBACK_ADAPTER;_DEBUG;YY_NEVER_INTERACTIVE;_USRDLL;BUILDING_PCAP;HAVE_STRERROR;__STDC__;INET6;_WINDOWS;HAVE_ADDRINFO;HAVE_REMOTE;WIN32;_U_=;YY_NO_UNISTD_H;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+      <BasicRuntimeChecks>EnableFastChecks</BasicRuntimeChecks>
+    </ClCompile>
+    <ResourceCompile>
+      <Culture>0x0409</Culture>
+      <PreprocessorDefinitions>_DEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+    </ResourceCompile>
+    <Link>
+      <AdditionalDependencies>ws2_32.lib;..\..\..\..\packetWin7\Dll\Project\Release No NetMon and AirPcap\Packet.lib;%(AdditionalDependencies)</AdditionalDependencies>
+    </Link>
+    <PreBuildEvent>
+      <Command>call ..\..\GenVersion.bat ..\..\VERSION ..\..\pcap_version.h.in ..\..\pcap_version.h
+win_flex -Ppcap_ -7 --outfile=..\..\scanner.c --header-file=..\..\scanner.h ..\..\scanner.l
+win_bison -ppcap_ --yacc --output=..\..\grammar.c --defines ..\..\grammar.y</Command>
+    </PreBuildEvent>
+  </ItemDefinitionGroup>
+  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
+    <ClCompile>
+      <RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary>
+      <InlineFunctionExpansion>Default</InlineFunctionExpansion>
+      <FunctionLevelLinking>false</FunctionLevelLinking>
+      <Optimization>Disabled</Optimization>
+      <SuppressStartupBanner>true</SuppressStartupBanner>
+      <WarningLevel>Level3</WarningLevel>
+      <DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
+      <AdditionalIncludeDirectories>../../;../../lbl/;../../bpf/;../include/;../../../../common;../../../../dag/include;../../../../dag/drv/windows;../../../Win32-Extensions;./;Win32-Extensions;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+      <PreprocessorDefinitions>HAVE_VERSION_H;__STDC_VERSION__=199901L;HAVE_PACKET_IS_LOOPBACK_ADAPTER;_DEBUG;YY_NEVER_INTERACTIVE;_USRDLL;BUILDING_PCAP;HAVE_STRERROR;__STDC__;INET6;_WINDOWS;HAVE_ADDRINFO;HAVE_REMOTE;WIN32;_U_=;YY_NO_UNISTD_H;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+      <BasicRuntimeChecks>EnableFastChecks</BasicRuntimeChecks>
+    </ClCompile>
+    <ResourceCompile>
+      <Culture>0x0409</Culture>
+      <PreprocessorDefinitions>_DEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+    </ResourceCompile>
+    <Link>
+      <AdditionalDependencies>ws2_32.lib;..\..\..\..\packetWin7\Dll\Project\x64\Release No NetMon and AirPcap\Packet.lib;%(AdditionalDependencies)</AdditionalDependencies>
+    </Link>
+    <PreBuildEvent>
+      <Command>call ..\..\GenVersion.bat ..\..\VERSION ..\..\pcap_version.h.in ..\..\pcap_version.h
+win_flex -Ppcap_ -7 --outfile=..\..\scanner.c --header-file=..\..\scanner.h ..\..\scanner.l
+win_bison -ppcap_ --yacc --output=..\..\grammar.c --defines ..\..\grammar.y</Command>
+    </PreBuildEvent>
+  </ItemDefinitionGroup>
+  <ItemGroup>
+    <ClCompile Include="..\..\bpf\net\bpf_filter.c" />
+    <ClCompile Include="..\..\bpf_dump.c" />
+    <ClCompile Include="..\..\bpf_image.c" />
+    <ClCompile Include="..\..\etherent.c" />
+    <ClCompile Include="..\..\fad-helpers.c" />
+    <ClCompile Include="..\..\gencode.c" />
+    <ClCompile Include="..\..\grammar.c" />
+    <ClCompile Include="..\..\inet.c" />
+    <ClCompile Include="..\..\missing\win_snprintf.c" />
+    <ClCompile Include="..\..\nametoaddr.c" />
+    <ClCompile Include="..\..\optimize.c" />
+    <ClCompile Include="..\..\pcap-common.c" />
+    <ClCompile Include="..\..\pcap-new.c" />
+    <ClCompile Include="..\..\pcap-rpcap.c" />
+    <ClCompile Include="..\..\pcap-win32.c" />
+    <ClCompile Include="..\..\pcap.c" />
+    <ClCompile Include="..\..\savefile.c" />
+    <ClCompile Include="..\..\scanner.c" />
+    <ClCompile Include="..\..\sf-pcap-ng.c" />
+    <ClCompile Include="..\..\sf-pcap.c" />
+    <ClCompile Include="..\..\sockutils.c" />
+  </ItemGroup>
+  <ItemGroup>
+    <ClInclude Include="..\..\pcap-common.h" />
+    <ClInclude Include="..\..\pcap-int.h" />
+    <ClInclude Include="..\..\pcap-rpcap.h" />
+    <ClInclude Include="..\..\pcap-stdinc.h" />
+    <ClInclude Include="..\..\pcap.h" />
+    <ClInclude Include="..\..\remote-ext.h" />
+    <ClInclude Include="..\..\sockutils.h" />
+  </ItemGroup>
+  <ItemGroup>
+    <ResourceCompile Include="..\..\..\Win32-Extensions\version.rc" />
+  </ItemGroup>
+  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
+  <ImportGroup Label="ExtensionTargets">
+  </ImportGroup>
+</Project>
\ No newline at end of file
diff --git a/Win32/Prj/wpcap.vcxproj.filters b/Win32/Prj/wpcap.vcxproj.filters
new file mode 100644
index 0000000..72f1492
--- /dev/null
+++ b/Win32/Prj/wpcap.vcxproj.filters
@@ -0,0 +1,107 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+  <ItemGroup>
+    <ClCompile Include="..\..\bpf_dump.c">
+      <Filter>Source Files</Filter>
+    </ClCompile>
+    <ClCompile Include="..\..\bpf\net\bpf_filter.c">
+      <Filter>Source Files</Filter>
+    </ClCompile>
+    <ClCompile Include="..\..\bpf_image.c">
+      <Filter>Source Files</Filter>
+    </ClCompile>
+    <ClCompile Include="..\..\etherent.c">
+      <Filter>Source Files</Filter>
+    </ClCompile>
+    <ClCompile Include="..\..\gencode.c">
+      <Filter>Source Files</Filter>
+    </ClCompile>
+    <ClCompile Include="..\..\grammar.c">
+      <Filter>Source Files</Filter>
+    </ClCompile>
+    <ClCompile Include="..\..\inet.c">
+      <Filter>Source Files</Filter>
+    </ClCompile>
+    <ClCompile Include="..\..\nametoaddr.c">
+      <Filter>Source Files</Filter>
+    </ClCompile>
+    <ClCompile Include="..\..\optimize.c">
+      <Filter>Source Files</Filter>
+    </ClCompile>
+    <ClCompile Include="..\..\pcap.c">
+      <Filter>Source Files</Filter>
+    </ClCompile>
+    <ClCompile Include="..\..\pcap-win32.c">
+      <Filter>Source Files</Filter>
+    </ClCompile>
+    <ClCompile Include="..\..\savefile.c">
+      <Filter>Source Files</Filter>
+    </ClCompile>
+    <ClCompile Include="..\..\scanner.c">
+      <Filter>Source Files</Filter>
+    </ClCompile>
+    <ClCompile Include="..\..\sf-pcap.c">
+      <Filter>Source Files</Filter>
+    </ClCompile>
+    <ClCompile Include="..\..\sf-pcap-ng.c">
+      <Filter>Source Files</Filter>
+    </ClCompile>
+    <ClCompile Include="..\..\pcap-common.c">
+      <Filter>Source Files</Filter>
+    </ClCompile>
+    <ClCompile Include="..\..\fad-helpers.c">
+      <Filter>Source Files</Filter>
+    </ClCompile>
+    <ClCompile Include="..\..\missing\win_snprintf.c">
+      <Filter>Source Files</Filter>
+    </ClCompile>
+    <ClCompile Include="..\..\pcap-new.c">
+      <Filter>Source Files</Filter>
+    </ClCompile>
+    <ClCompile Include="..\..\pcap-rpcap.c">
+      <Filter>Source Files</Filter>
+    </ClCompile>
+    <ClCompile Include="..\..\sockutils.c">
+      <Filter>Source Files</Filter>
+    </ClCompile>
+  </ItemGroup>
+  <ItemGroup>
+    <Filter Include="Header Files">
+      <UniqueIdentifier>{c51dce5e-0da9-4e33-a235-d5c76c76485c}</UniqueIdentifier>
+    </Filter>
+    <Filter Include="Source Files">
+      <UniqueIdentifier>{5ec9fd4b-10b5-4527-b249-56b53d844fb1}</UniqueIdentifier>
+    </Filter>
+    <Filter Include="Resource Files">
+      <UniqueIdentifier>{c90886f0-8973-436b-a7a1-b9e881544f9a}</UniqueIdentifier>
+    </Filter>
+  </ItemGroup>
+  <ItemGroup>
+    <ClInclude Include="..\..\pcap-stdinc.h">
+      <Filter>Header Files</Filter>
+    </ClInclude>
+    <ClInclude Include="..\..\pcap-common.h">
+      <Filter>Header Files</Filter>
+    </ClInclude>
+    <ClInclude Include="..\..\pcap.h">
+      <Filter>Header Files</Filter>
+    </ClInclude>
+    <ClInclude Include="..\..\pcap-int.h">
+      <Filter>Header Files</Filter>
+    </ClInclude>
+    <ClInclude Include="..\..\pcap-rpcap.h">
+      <Filter>Header Files</Filter>
+    </ClInclude>
+    <ClInclude Include="..\..\remote-ext.h">
+      <Filter>Header Files</Filter>
+    </ClInclude>
+    <ClInclude Include="..\..\sockutils.h">
+      <Filter>Header Files</Filter>
+    </ClInclude>
+  </ItemGroup>
+  <ItemGroup>
+    <ResourceCompile Include="..\..\..\Win32-Extensions\version.rc">
+      <Filter>Resource Files</Filter>
+    </ResourceCompile>
+  </ItemGroup>
+</Project>
diff --git a/Win32/Src/gai_strerror.c b/Win32/Src/gai_strerror.c
deleted file mode 100644
index a36c35d..0000000
--- a/Win32/Src/gai_strerror.c
+++ /dev/null
@@ -1,83 +0,0 @@
-/*
- * Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project.
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in the
- *    documentation and/or other materials provided with the distribution.
- * 3. Neither the name of the project nor the names of its contributors
- *    may be used to endorse or promote products derived from this software
- *    without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED.  IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE
- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
- * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
- * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- */
-
-/*
-#include <sys/cdefs.h>
-
-__FBSDID("$FreeBSD: /repoman/r/ncvs/src/lib/libc/net/gai_strerror.c,v 1.1 2005/04/06 12:45:51 ume Exp $");
-
-*/
-
-#ifdef WIN32
-
-#include <ws2tcpip.h>
-
-#else
-
-#include <netdb.h>
-
-#endif
-
-/* Entries EAI_ADDRFAMILY (1) and EAI_NODATA (7) are obsoleted, but left */
-/* for backward compatibility with userland code prior to 2553bis-02 */
-static char *ai_errlist[] = {
-	"Success",					/* 0 */
-	"Address family for hostname not supported",	/* 1 */
-	"Temporary failure in name resolution",		/* EAI_AGAIN */
-	"Invalid value for ai_flags",			/* EAI_BADFLAGS */
-	"Non-recoverable failure in name resolution",	/* EAI_FAIL */
-	"ai_family not supported",			/* EAI_FAMILY */
-	"Memory allocation failure", 			/* EAI_MEMORY */
-	"No address associated with hostname",		/* 7 */
-	"hostname nor servname provided, or not known",	/* EAI_NONAME */
-	"servname not supported for ai_socktype",	/* EAI_SERVICE */
-	"ai_socktype not supported", 			/* EAI_SOCKTYPE */
-	"System error returned in errno", 		/* EAI_SYSTEM */
-	"Invalid value for hints",			/* EAI_BADHINTS */
-	"Resolved protocol is unknown"			/* EAI_PROTOCOL */
-};
-
-#ifndef EAI_MAX
-#define EAI_MAX (sizeof(ai_errlist)/sizeof(ai_errlist[0]))
-#endif
-
-/* on MingW, gai_strerror is available.
-   We need to compile gai_strerrorA only for Cygwin
- */
-#ifndef gai_strerror
-
-char *
-WSAAPI gai_strerrorA(int ecode)
-{
-	if (ecode >= 0 && ecode < EAI_MAX)
-		return ai_errlist[ecode];
-	return "Unknown error";
-}
-
-#endif /* gai_strerror */
\ No newline at end of file
diff --git a/Win32/Src/getaddrinfo.c b/Win32/Src/getaddrinfo.c
deleted file mode 100644
index d3ebda0..0000000
--- a/Win32/Src/getaddrinfo.c
+++ /dev/null
@@ -1,1124 +0,0 @@
-/*
- * Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project.
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in the
- *    documentation and/or other materials provided with the distribution.
- * 3. Neither the name of the project nor the names of its contributors
- *    may be used to endorse or promote products derived from this software
- *    without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED.  IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE
- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
- * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
- * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- */
-
-/*
- * "#ifdef FAITH" part is local hack for supporting IPv4-v6 translator.
- *
- * Issues to be discussed:
- * - Thread safe-ness must be checked.
- * - Return values.  There are nonstandard return values defined and used
- *   in the source code.  This is because RFC2553 is silent about which error
- *   code must be returned for which situation.
- * Note:
- * - We use getipnodebyname() just for thread-safeness.  There's no intent
- *   to let it do PF_UNSPEC (actually we never pass PF_UNSPEC to
- *   getipnodebyname().
- * - The code filters out AFs that are not supported by the kernel,
- *   when globbing NULL hostname (to loopback, or wildcard).  Is it the right
- *   thing to do?  What is the relationship with post-RFC2553 AI_ADDRCONFIG
- *   in ai_flags?
- */
-
-/*
- * Mingw64 has its own implementation of getaddrinfo, mingw32 no
- */
-#ifndef __MINGW64__
-
-
-#ifdef HAVE_CONFIG_H
-#include <config.h>
-#endif
-
-#include <pcap-stdinc.h>
-#if 0
-#include <sys/sysctl.h>
-#endif
-#ifndef __MINGW32__
-#include <arpa/nameser.h>
-#endif
-#include <string.h>
-#include <stdlib.h>
-#include <stddef.h>
-#include <ctype.h>
-#include <stdio.h>
-#include <errno.h>
-
-#ifndef HAVE_PORTABLE_PROTOTYPE
-#include "cdecl_ext.h"
-#endif
-
-#ifndef HAVE_U_INT32_T
-#include "bittypes.h"
-#endif
-
-#ifndef HAVE_SOCKADDR_STORAGE
-#ifndef __MINGW32__
-#include "sockstorage.h"
-#endif
-#endif
-
-#ifdef NEED_ADDRINFO_H
-#include "addrinfo.h"
-#ifdef WIN32
-#include "ip6_misc.h"
-#endif
-#endif
-
-
-#if defined(__KAME__) && defined(INET6)
-# define FAITH
-#endif
-
-#define SUCCESS 0
-#define ANY 0
-#define YES 1
-#define NO  0
-
-#ifdef FAITH
-static int translate = NO;
-static struct in6_addr faith_prefix = IN6ADDR_ANY_INIT;
-#endif
-
-static const char in_addrany[] = { 0, 0, 0, 0 };
-static const char in6_addrany[] = {
-	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
-};
-static const char in_loopback[] = { 127, 0, 0, 1 };
-static const char in6_loopback[] = {
-	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1
-};
-
-struct sockinet {
-	u_char	si_len;
-	u_char	si_family;
-	u_short	si_port;
-	u_int32_t si_scope_id;
-};
-
-static const struct afd {
-	int a_af;
-	int a_addrlen;
-	int a_socklen;
-	int a_off;
-	const char *a_addrany;
-	const char *a_loopback;
-	int a_scoped;
-} afdl [] = {
-#ifdef INET6
-	{PF_INET6, sizeof(struct in6_addr),
-	 sizeof(struct sockaddr_in6),
-	 offsetof(struct sockaddr_in6, sin6_addr),
-	 in6_addrany, in6_loopback, 1},
-#endif
-	{PF_INET, sizeof(struct in_addr),
-	 sizeof(struct sockaddr_in),
-	 offsetof(struct sockaddr_in, sin_addr),
-	 in_addrany, in_loopback, 0},
-	{0, 0, 0, 0, NULL, NULL, 0},
-};
-
-struct explore {
-	int e_af;
-	int e_socktype;
-	int e_protocol;
-	const char *e_protostr;
-	int e_wild;
-#define WILD_AF(ex)		((ex)->e_wild & 0x01)
-#define WILD_SOCKTYPE(ex)	((ex)->e_wild & 0x02)
-#define WILD_PROTOCOL(ex)	((ex)->e_wild & 0x04)
-};
-
-static const struct explore explore[] = {
-#if 0
-	{ PF_LOCAL, 0, ANY, ANY, NULL, 0x01 },
-#endif
-#ifdef INET6
-	{ PF_INET6, SOCK_DGRAM, IPPROTO_UDP, "udp", 0x07 },
-	{ PF_INET6, SOCK_STREAM, IPPROTO_TCP, "tcp", 0x07 },
-	{ PF_INET6, SOCK_RAW, ANY, NULL, 0x05 },
-#endif
-	{ PF_INET, SOCK_DGRAM, IPPROTO_UDP, "udp", 0x07 },
-	{ PF_INET, SOCK_STREAM, IPPROTO_TCP, "tcp", 0x07 },
-	{ PF_INET, SOCK_RAW, ANY, NULL, 0x05 },
-	{ -1, 0, 0, NULL, 0 },
-};
-
-#ifdef INET6
-#define PTON_MAX	16
-#else
-#define PTON_MAX	4
-#endif
-
-
-static int str_isnumber __P((const char *));
-static int explore_fqdn __P((const struct addrinfo *, const char *,
-	const char *, struct addrinfo **));
-static int explore_null __P((const struct addrinfo *, const char *,
-	const char *, struct addrinfo **));
-static int explore_numeric __P((const struct addrinfo *, const char *,
-	const char *, struct addrinfo **));
-static int explore_numeric_scope __P((const struct addrinfo *, const char *,
-	const char *, struct addrinfo **));
-static int get_name __P((const char *, const struct afd *, struct addrinfo **,
-	char *, const struct addrinfo *, const char *));
-static int get_canonname __P((const struct addrinfo *,
-	struct addrinfo *, const char *));
-static struct addrinfo *get_ai __P((const struct addrinfo *,
-	const struct afd *, const char *));
-static int get_portmatch __P((const struct addrinfo *, const char *));
-static int get_port __P((struct addrinfo *, const char *, int));
-static const struct afd *find_afd __P((int));
-
-static char *ai_errlist[] = {
-	"Success",
-	"Address family for hostname not supported",	/* EAI_ADDRFAMILY */
-	"Temporary failure in name resolution",		/* EAI_AGAIN      */
-	"Invalid value for ai_flags",		       	/* EAI_BADFLAGS   */
-	"Non-recoverable failure in name resolution", 	/* EAI_FAIL       */
-	"ai_family not supported",			/* EAI_FAMILY     */
-	"Memory allocation failure", 			/* EAI_MEMORY     */
-	"No address associated with hostname", 		/* EAI_NODATA     */
-	"hostname nor servname provided, or not known",	/* EAI_NONAME     */
-	"servname not supported for ai_socktype",	/* EAI_SERVICE    */
-	"ai_socktype not supported", 			/* EAI_SOCKTYPE   */
-	"System error returned in errno", 		/* EAI_SYSTEM     */
-	"Invalid value for hints",			/* EAI_BADHINTS	  */
-	"Resolved protocol is unknown",			/* EAI_PROTOCOL   */
-	"Unknown error", 				/* EAI_MAX        */
-};
-
-/* XXX macros that make external reference is BAD. */
-
-#define GET_AI(ai, afd, addr) \
-do { \
-	/* external reference: pai, error, and label free */ \
-	(ai) = get_ai(pai, (afd), (addr)); \
-	if ((ai) == NULL) { \
-		error = EAI_MEMORY; \
-		goto free; \
-	} \
-} while (0)
-
-#define GET_PORT(ai, serv) \
-do { \
-	/* external reference: error and label free */ \
-	error = get_port((ai), (serv), 0); \
-	if (error != 0) \
-		goto free; \
-} while (0)
-
-#define GET_CANONNAME(ai, str) \
-do { \
-	/* external reference: pai, error and label free */ \
-	error = get_canonname(pai, (ai), (str)); \
-	if (error != 0) \
-		goto free; \
-} while (0)
-
-#define ERR(err) \
-do { \
-	/* external reference: error, and label bad */ \
-	error = (err); \
-	goto bad; \
-} while (0)
-
-#define MATCH_FAMILY(x, y, w) \
-	((x) == (y) || ((w) && ((x) == PF_UNSPEC || (y) == PF_UNSPEC)))
-#define MATCH(x, y, w) \
-	((x) == (y) || ((w) && ((x) == ANY || (y) == ANY)))
-
-#if  defined(DEFINE_ADDITIONAL_IPV6_STUFF)
-char *
-gai_strerror(ecode)
-	int ecode;
-{
-	if (ecode < 0 || ecode > EAI_MAX)
-		ecode = EAI_MAX;
-	return ai_errlist[ecode];
-}
-#endif
-
-void
-freeaddrinfo(ai)
-	struct addrinfo *ai;
-{
-	struct addrinfo *next;
-
-	do {
-		next = ai->ai_next;
-		if (ai->ai_canonname)
-			free(ai->ai_canonname);
-		/* no need to free(ai->ai_addr) */
-		free(ai);
-	} while ((ai = next) != NULL);
-}
-
-static int
-str_isnumber(p)
-	const char *p;
-{
-	char *q = (char *)p;
-	while (*q) {
-		if (! isdigit(*q))
-			return NO;
-		q++;
-	}
-	return YES;
-}
-
-int
-getaddrinfo(hostname, servname, hints, res)
-	const char *hostname, *servname;
-	const struct addrinfo *hints;
-	struct addrinfo **res;
-{
-	struct addrinfo sentinel;
-	struct addrinfo *cur;
-	int error = 0;
-	struct addrinfo ai;
-	struct addrinfo ai0;
-	struct addrinfo *pai;
-	const struct afd *afd;
-	const struct explore *ex;
-
-#ifdef FAITH
-	static int firsttime = 1;
-
-	if (firsttime) {
-		/* translator hack */
-		char *q = getenv("GAI");
-		if (q && inet_pton(AF_INET6, q, &faith_prefix) == 1)
-			translate = YES;
-		firsttime = 0;
-	}
-#endif
-
-	sentinel.ai_next = NULL;
-	cur = &sentinel;
-	pai = &ai;
-	pai->ai_flags = 0;
-	pai->ai_family = PF_UNSPEC;
-	pai->ai_socktype = ANY;
-	pai->ai_protocol = ANY;
-	pai->ai_addrlen = 0;
-	pai->ai_canonname = NULL;
-	pai->ai_addr = NULL;
-	pai->ai_next = NULL;
-
-	if (hostname == NULL && servname == NULL)
-		return EAI_NONAME;
-	if (hints) {
-		/* error check for hints */
-		if (hints->ai_addrlen || hints->ai_canonname ||
-		    hints->ai_addr || hints->ai_next)
-			ERR(EAI_BADHINTS); /* xxx */
-		if (hints->ai_flags & ~AI_MASK)
-			ERR(EAI_BADFLAGS);
-		switch (hints->ai_family) {
-		case PF_UNSPEC:
-		case PF_INET:
-#ifdef INET6
-		case PF_INET6:
-#endif
-			break;
-		default:
-			ERR(EAI_FAMILY);
-		}
-		memcpy(pai, hints, sizeof(*pai));
-
-		/*
-		 * if both socktype/protocol are specified, check if they
-		 * are meaningful combination.
-		 */
-		if (pai->ai_socktype != ANY && pai->ai_protocol != ANY) {
-			for (ex = explore; ex->e_af >= 0; ex++) {
-				if (pai->ai_family != ex->e_af)
-					continue;
-				if (ex->e_socktype == ANY)
-					continue;
-				if (ex->e_protocol == ANY)
-					continue;
-				if (pai->ai_socktype == ex->e_socktype
-				 && pai->ai_protocol != ex->e_protocol) {
-					ERR(EAI_BADHINTS);
-				}
-			}
-		}
-	}
-
-	/*
-	 * check for special cases.  (1) numeric servname is disallowed if
-	 * socktype/protocol are left unspecified. (2) servname is disallowed
-	 * for raw and other inet{,6} sockets.
-	 */
-	if (MATCH_FAMILY(pai->ai_family, PF_INET, 1)
-#ifdef PF_INET6
-	 || MATCH_FAMILY(pai->ai_family, PF_INET6, 1)
-#endif
-	    ) {
-		ai0 = *pai;
-
-		if (pai->ai_family == PF_UNSPEC) {
-#ifdef PF_INET6
-			pai->ai_family = PF_INET6;
-#else
-			pai->ai_family = PF_INET;
-#endif
-		}
-		error = get_portmatch(pai, servname);
-		if (error)
-			ERR(error);
-
-		*pai = ai0;
-	}
-
-	ai0 = *pai;
-
-	/* NULL hostname, or numeric hostname */
-	for (ex = explore; ex->e_af >= 0; ex++) {
-		*pai = ai0;
-
-		if (!MATCH_FAMILY(pai->ai_family, ex->e_af, WILD_AF(ex)))
-			continue;
-		if (!MATCH(pai->ai_socktype, ex->e_socktype, WILD_SOCKTYPE(ex)))
-			continue;
-		if (!MATCH(pai->ai_protocol, ex->e_protocol, WILD_PROTOCOL(ex)))
-			continue;
-
-		if (pai->ai_family == PF_UNSPEC)
-			pai->ai_family = ex->e_af;
-		if (pai->ai_socktype == ANY && ex->e_socktype != ANY)
-			pai->ai_socktype = ex->e_socktype;
-		if (pai->ai_protocol == ANY && ex->e_protocol != ANY)
-			pai->ai_protocol = ex->e_protocol;
-
-		if (hostname == NULL)
-			error = explore_null(pai, hostname, servname, &cur->ai_next);
-		else
-			error = explore_numeric_scope(pai, hostname, servname, &cur->ai_next);
-
-		if (error)
-			goto free;
-
-		while (cur && cur->ai_next)
-			cur = cur->ai_next;
-	}
-
-	/*
-	 * XXX
-	 * If numreic representation of AF1 can be interpreted as FQDN
-	 * representation of AF2, we need to think again about the code below.
-	 */
-	if (sentinel.ai_next)
-		goto good;
-
-	if (pai->ai_flags & AI_NUMERICHOST)
-		ERR(EAI_NONAME);
-	if (hostname == NULL)
-		ERR(EAI_NONAME);
-
-	/*
-	 * hostname as alphabetical name.
-	 * we would like to prefer AF_INET6 than AF_INET, so we'll make a
-	 * outer loop by AFs.
-	 */
-	for (afd = afdl; afd->a_af; afd++) {
-		*pai = ai0;
-
-		if (!MATCH_FAMILY(pai->ai_family, afd->a_af, 1))
-			continue;
-
-		for (ex = explore; ex->e_af >= 0; ex++) {
-			*pai = ai0;
-
-			if (pai->ai_family == PF_UNSPEC)
-				pai->ai_family = afd->a_af;
-
-			if (!MATCH_FAMILY(pai->ai_family, ex->e_af, WILD_AF(ex)))
-				continue;
-			if (!MATCH(pai->ai_socktype, ex->e_socktype,
-					WILD_SOCKTYPE(ex))) {
-				continue;
-			}
-			if (!MATCH(pai->ai_protocol, ex->e_protocol,
-					WILD_PROTOCOL(ex))) {
-				continue;
-			}
-
-			if (pai->ai_family == PF_UNSPEC)
-				pai->ai_family = ex->e_af;
-			if (pai->ai_socktype == ANY && ex->e_socktype != ANY)
-				pai->ai_socktype = ex->e_socktype;
-			if (pai->ai_protocol == ANY && ex->e_protocol != ANY)
-				pai->ai_protocol = ex->e_protocol;
-
-			error = explore_fqdn(pai, hostname, servname,
-				&cur->ai_next);
-
-			while (cur && cur->ai_next)
-				cur = cur->ai_next;
-		}
-	}
-
-	/* XXX */
-	if (sentinel.ai_next)
-		error = 0;
-
-	if (error)
-		goto free;
-	if (error == 0) {
-		if (sentinel.ai_next) {
- good:
-			*res = sentinel.ai_next;
-			return SUCCESS;
-		} else
-			error = EAI_FAIL;
-	}
- free:
- bad:
-	if (sentinel.ai_next)
-		freeaddrinfo(sentinel.ai_next);
-	*res = NULL;
-	return error;
-}
-
-/*
- * FQDN hostname, DNS lookup
- */
-static int
-explore_fqdn(pai, hostname, servname, res)
-	const struct addrinfo *pai;
-	const char *hostname;
-	const char *servname;
-	struct addrinfo **res;
-{
-	struct hostent *hp;
-	int h_error;
-	int af;
-	char **aplist = NULL, *apbuf = NULL;
-	char *ap;
-	struct addrinfo sentinel, *cur;
-	int i;
-#ifndef USE_GETIPNODEBY
-	int naddrs;
-#endif
-	const struct afd *afd;
-	int error;
-
-	*res = NULL;
-	sentinel.ai_next = NULL;
-	cur = &sentinel;
-
-	/*
-	 * Do not filter unsupported AFs here.  We need to honor content of
-	 * databases (/etc/hosts, DNS and others).  Otherwise we cannot
-	 * replace gethostbyname() by getaddrinfo().
-	 */
-
-	/*
-	 * if the servname does not match socktype/protocol, ignore it.
-	 */
-	if (get_portmatch(pai, servname) != 0)
-		return 0;
-
-	afd = find_afd(pai->ai_family);
-
-	/*
-	 * post-RFC2553: should look at (pai->ai_flags & AI_ADDRCONFIG)
-	 * rather than hardcoding it.  we may need to add AI_ADDRCONFIG
-	 * handling code by ourselves in case we don't have getipnodebyname().
-	 */
-#ifdef USE_GETIPNODEBY
-	hp = getipnodebyname(hostname, pai->ai_family, AI_ADDRCONFIG, &h_error);
-#else
-#ifdef HAVE_GETHOSTBYNAME2
-	hp = gethostbyname2(hostname, pai->ai_family);
-#else
-	if (pai->ai_family != AF_INET)
-		return 0;
-	hp = gethostbyname(hostname);
-#ifdef HAVE_H_ERRNO
-	h_error = h_errno;
-#else
-	h_error = EINVAL;
-#endif
-#endif /*HAVE_GETHOSTBYNAME2*/
-#endif /*USE_GETIPNODEBY*/
-
-	if (hp == NULL) {
-		switch (h_error) {
-		case HOST_NOT_FOUND:
-		case NO_DATA:
-			error = EAI_NODATA;
-			break;
-		case TRY_AGAIN:
-			error = EAI_AGAIN;
-			break;
-		case NO_RECOVERY:
-		case NETDB_INTERNAL:
-		default:
-			error = EAI_FAIL;
-			break;
-		}
-	} else if ((hp->h_name == NULL) || (hp->h_name[0] == 0)
-			|| (hp->h_addr_list[0] == NULL)) {
-#ifdef USE_GETIPNODEBY
-		freehostent(hp);
-#endif
-		hp = NULL;
-		error = EAI_FAIL;
-	}
-
-	if (hp == NULL)
-		goto free;
-
-#ifdef USE_GETIPNODEBY
-	aplist = hp->h_addr_list;
-#else
-	/*
-	 * hp will be overwritten if we use gethostbyname2().
-	 * always deep copy for simplification.
-	 */
-	for (naddrs = 0; hp->h_addr_list[naddrs] != NULL; naddrs++)
-		;
-	naddrs++;
-	aplist = (char **)malloc(sizeof(aplist[0]) * naddrs);
-	apbuf = (char *)malloc(hp->h_length * naddrs);
-	if (aplist == NULL || apbuf == NULL) {
-		error = EAI_MEMORY;
-		goto free;
-	}
-	memset(aplist, 0, sizeof(aplist[0]) * naddrs);
-	for (i = 0; i < naddrs; i++) {
-		if (hp->h_addr_list[i] == NULL) {
-			aplist[i] = NULL;
-			continue;
-		}
-		memcpy(&apbuf[i * hp->h_length], hp->h_addr_list[i],
-			hp->h_length);
-		aplist[i] = &apbuf[i * hp->h_length];
-	}
-#endif
-
-	for (i = 0; aplist[i] != NULL; i++) {
-		af = hp->h_addrtype;
-		ap = aplist[i];
-#ifdef AF_INET6
-		if (af == AF_INET6
-		 && IN6_IS_ADDR_V4MAPPED((struct in6_addr *)ap)) {
-			af = AF_INET;
-			ap = ap + sizeof(struct in6_addr)
-				- sizeof(struct in_addr);
-		}
-#endif
-
-		if (af != pai->ai_family)
-			continue;
-
-		if ((pai->ai_flags & AI_CANONNAME) == 0) {
-			GET_AI(cur->ai_next, afd, ap);
-			GET_PORT(cur->ai_next, servname);
-		} else {
-			/*
-			 * if AI_CANONNAME and if reverse lookup
-			 * fail, return ai anyway to pacify
-			 * calling application.
-			 *
-			 * XXX getaddrinfo() is a name->address
-			 * translation function, and it looks
-			 * strange that we do addr->name
-			 * translation here.
-			 */
-			get_name(ap, afd, &cur->ai_next,
-				ap, pai, servname);
-		}
-
-		while (cur && cur->ai_next)
-			cur = cur->ai_next;
-	}
-
-	*res = sentinel.ai_next;
-	return 0;
-
-free:
-#ifdef USE_GETIPNODEBY
-	if (hp)
-		freehostent(hp);
-#endif
-	if (aplist)
-		free(aplist);
-	if (apbuf)
-		free(apbuf);
-	if (sentinel.ai_next)
-		freeaddrinfo(sentinel.ai_next);
-	return error;
-}
-
-/*
- * hostname == NULL.
- * passive socket -> anyaddr (0.0.0.0 or ::)
- * non-passive socket -> localhost (127.0.0.1 or ::1)
- */
-static int
-explore_null(pai, hostname, servname, res)
-	const struct addrinfo *pai;
-	const char *hostname;
-	const char *servname;
-	struct addrinfo **res;
-{
-	int s;
-	const struct afd *afd;
-	struct addrinfo *cur;
-	struct addrinfo sentinel;
-	int error;
-
-	*res = NULL;
-	sentinel.ai_next = NULL;
-	cur = &sentinel;
-
-	/*
-	 * filter out AFs that are not supported by the kernel
-	 * XXX errno?
-	 */
-	s = socket(pai->ai_family, SOCK_DGRAM, 0);
-	if (s < 0) {
-		if (errno != EMFILE)
-			return 0;
-	} else
-		close(s);
-
-	/*
-	 * if the servname does not match socktype/protocol, ignore it.
-	 */
-	if (get_portmatch(pai, servname) != 0)
-		return 0;
-
-	afd = find_afd(pai->ai_family);
-
-	if (pai->ai_flags & AI_PASSIVE) {
-		GET_AI(cur->ai_next, afd, afd->a_addrany);
-		/* xxx meaningless?
-		 * GET_CANONNAME(cur->ai_next, "anyaddr");
-		 */
-		GET_PORT(cur->ai_next, servname);
-	} else {
-		GET_AI(cur->ai_next, afd, afd->a_loopback);
-		/* xxx meaningless?
-		 * GET_CANONNAME(cur->ai_next, "localhost");
-		 */
-		GET_PORT(cur->ai_next, servname);
-	}
-	cur = cur->ai_next;
-
-	*res = sentinel.ai_next;
-	return 0;
-
-free:
-	if (sentinel.ai_next)
-		freeaddrinfo(sentinel.ai_next);
-	return error;
-}
-
-/*
- * numeric hostname
- */
-static int
-explore_numeric(pai, hostname, servname, res)
-	const struct addrinfo *pai;
-	const char *hostname;
-	const char *servname;
-	struct addrinfo **res;
-{
-	const struct afd *afd;
-	struct addrinfo *cur;
-	struct addrinfo sentinel;
-	int error;
-	char pton[PTON_MAX];
-	int flags;
-
-	*res = NULL;
-	sentinel.ai_next = NULL;
-	cur = &sentinel;
-
-	/*
-	 * if the servname does not match socktype/protocol, ignore it.
-	 */
-	if (get_portmatch(pai, servname) != 0)
-		return 0;
-
-	afd = find_afd(pai->ai_family);
-	flags = pai->ai_flags;
-
-	if (inet_pton(afd->a_af, hostname, pton) == 1) {
-		u_int32_t v4a;
-#ifdef INET6
-		u_char pfx;
-#endif
-
-		switch (afd->a_af) {
-		case AF_INET:
-			v4a = (u_int32_t)ntohl(((struct in_addr *)pton)->s_addr);
-			if (IN_MULTICAST(v4a) || IN_EXPERIMENTAL(v4a))
-				flags &= ~AI_CANONNAME;
-			v4a >>= IN_CLASSA_NSHIFT;
-			if (v4a == 0 || v4a == IN_LOOPBACKNET)
-				flags &= ~AI_CANONNAME;
-			break;
-#ifdef INET6
-		case AF_INET6:
-			pfx = ((struct in6_addr *)pton)->s6_addr[0];
-			if (pfx == 0 || pfx == 0xfe || pfx == 0xff)
-				flags &= ~AI_CANONNAME;
-			break;
-#endif
-		}
-
-		if (pai->ai_family == afd->a_af ||
-		    pai->ai_family == PF_UNSPEC /*?*/) {
-			if ((flags & AI_CANONNAME) == 0) {
-				GET_AI(cur->ai_next, afd, pton);
-				GET_PORT(cur->ai_next, servname);
-			} else {
-				/*
-				 * if AI_CANONNAME and if reverse lookup
-				 * fail, return ai anyway to pacify
-				 * calling application.
-				 *
-				 * XXX getaddrinfo() is a name->address
-				 * translation function, and it looks
-				 * strange that we do addr->name
-				 * translation here.
-				 */
-				get_name(pton, afd, &cur->ai_next,
-					pton, pai, servname);
-			}
-			while (cur && cur->ai_next)
-				cur = cur->ai_next;
-		} else
-			ERR(EAI_FAMILY);	/*xxx*/
-	}
-
-	*res = sentinel.ai_next;
-	return 0;
-
-free:
-bad:
-	if (sentinel.ai_next)
-		freeaddrinfo(sentinel.ai_next);
-	return error;
-}
-
-/*
- * numeric hostname with scope
- */
-static int
-explore_numeric_scope(pai, hostname, servname, res)
-	const struct addrinfo *pai;
-	const char *hostname;
-	const char *servname;
-	struct addrinfo **res;
-{
-#ifndef SCOPE_DELIMITER
-	return explore_numeric(pai, hostname, servname, res);
-#else
-	const struct afd *afd;
-	struct addrinfo *cur;
-	int error;
-	char *cp, *hostname2 = NULL;
-	int scope;
-	struct sockaddr_in6 *sin6;
-
-	/*
-	 * if the servname does not match socktype/protocol, ignore it.
-	 */
-	if (get_portmatch(pai, servname) != 0)
-		return 0;
-
-	afd = find_afd(pai->ai_family);
-	if (!afd->a_scoped)
-		return explore_numeric(pai, hostname, servname, res);
-
-	cp = strchr(hostname, SCOPE_DELIMITER);
-	if (cp == NULL)
-		return explore_numeric(pai, hostname, servname, res);
-
-	/*
-	 * Handle special case of <scoped_address><delimiter><scope id>
-	 */
-	hostname2 = strdup(hostname);
-	if (hostname2 == NULL)
-		return EAI_MEMORY;
-	/* terminate at the delimiter */
-	hostname2[cp - hostname] = '\0';
-
-	cp++;
-	switch (pai->ai_family) {
-#ifdef INET6
-	case AF_INET6:
-		scope = if_nametoindex(cp);
-		if (scope == 0) {
-			free(hostname2);
-			return (EAI_NONAME);
-		}
-		break;
-#endif
-	}
-
-	error = explore_numeric(pai, hostname2, servname, res);
-	if (error == 0) {
-		for (cur = *res; cur; cur = cur->ai_next) {
-			if (cur->ai_family != AF_INET6)
-				continue;
-			sin6 = (struct sockaddr_in6 *)cur->ai_addr;
-			if (IN6_IS_ADDR_LINKLOCAL(&sin6->sin6_addr) ||
-			    IN6_IS_ADDR_MC_LINKLOCAL(&sin6->sin6_addr))
-				sin6->sin6_scope_id = scope;
-		}
-	}
-
-	free(hostname2);
-
-	return error;
-#endif
-}
-
-static int
-get_name(addr, afd, res, numaddr, pai, servname)
-	const char *addr;
-	const struct afd *afd;
-	struct addrinfo **res;
-	char *numaddr;
-	const struct addrinfo *pai;
-	const char *servname;
-{
-	struct hostent *hp = NULL;
-	struct addrinfo *cur = NULL;
-	int error = 0;
-	char *ap = NULL, *cn = NULL;
-#ifdef USE_GETIPNODEBY
-	int h_error;
-
-	hp = getipnodebyaddr(addr, afd->a_addrlen, afd->a_af, &h_error);
-#else
-	hp = gethostbyaddr(addr, afd->a_addrlen, afd->a_af);
-#endif
-	if (hp && hp->h_name && hp->h_name[0] && hp->h_addr_list[0]) {
-#ifdef USE_GETIPNODEBY
-		GET_AI(cur, afd, hp->h_addr_list[0]);
-		GET_PORT(cur, servname);
-		GET_CANONNAME(cur, hp->h_name);
-#else
-		/* hp will be damaged if we use gethostbyaddr() */
-		if ((ap = (char *)malloc(hp->h_length)) == NULL) {
-			error = EAI_MEMORY;
-			goto free;
-		}
-		memcpy(ap, hp->h_addr_list[0], hp->h_length);
-		if ((cn = strdup(hp->h_name)) == NULL) {
-			error = EAI_MEMORY;
-			goto free;
-		}
-
-		GET_AI(cur, afd, ap);
-		GET_PORT(cur, servname);
-		GET_CANONNAME(cur, cn);
-		free(ap); ap = NULL;
-		free(cn); cn = NULL;
-#endif
-	} else {
-		GET_AI(cur, afd, numaddr);
-		GET_PORT(cur, servname);
-	}
-
-#ifdef USE_GETIPNODEBY
-	if (hp)
-		freehostent(hp);
-#endif
-	*res = cur;
-	return SUCCESS;
- free:
-	if (cur)
-		freeaddrinfo(cur);
-	if (ap)
-		free(ap);
-	if (cn)
-		free(cn);
-#ifdef USE_GETIPNODEBY
-	if (hp)
-		freehostent(hp);
-#endif
-	*res = NULL;
-	return error;
-}
-
-static int
-get_canonname(pai, ai, str)
-	const struct addrinfo *pai;
-	struct addrinfo *ai;
-	const char *str;
-{
-	if ((pai->ai_flags & AI_CANONNAME) != 0) {
-		ai->ai_canonname = strdup(str);
-		if (ai->ai_canonname == NULL)
-			return EAI_MEMORY;
-	}
-	return 0;
-}
-
-static struct addrinfo *
-get_ai(pai, afd, addr)
-	const struct addrinfo *pai;
-	const struct afd *afd;
-	const char *addr;
-{
-	char *p;
-	struct addrinfo *ai;
-
-	ai = (struct addrinfo *)malloc(sizeof(struct addrinfo)
-		+ (afd->a_socklen));
-	if (ai == NULL)
-		return NULL;
-
-	memcpy(ai, pai, sizeof(struct addrinfo));
-	ai->ai_addr = (struct sockaddr *)(ai + 1);
-	memset(ai->ai_addr, 0, afd->a_socklen);
-#ifdef HAVE_SOCKADDR_SA_LEN
-	ai->ai_addr->sa_len = afd->a_socklen;
-#endif
-	ai->ai_addrlen = afd->a_socklen;
-	ai->ai_addr->sa_family = ai->ai_family = afd->a_af;
-	p = (char *)(ai->ai_addr);
-	memcpy(p + afd->a_off, addr, afd->a_addrlen);
-	return ai;
-}
-
-static int
-get_portmatch(ai, servname)
-	const struct addrinfo *ai;
-	const char *servname;
-{
-
-	/* get_port does not touch first argument. when matchonly == 1. */
-	return get_port((struct addrinfo *)ai, servname, 1);
-}
-
-static int
-get_port(ai, servname, matchonly)
-	struct addrinfo *ai;
-	const char *servname;
-	int matchonly;
-{
-	const char *proto;
-	struct servent *sp;
-	int port;
-	int allownumeric;
-
-	if (servname == NULL)
-		return 0;
-	switch (ai->ai_family) {
-	case AF_INET:
-#ifdef AF_INET6
-	case AF_INET6:
-#endif
-		break;
-	default:
-		return 0;
-	}
-
-	switch (ai->ai_socktype) {
-	case SOCK_RAW:
-		return EAI_SERVICE;
-	case SOCK_DGRAM:
-	case SOCK_STREAM:
-		allownumeric = 1;
-		break;
-	case ANY:
-		allownumeric = 0;
-		break;
-	default:
-		return EAI_SOCKTYPE;
-	}
-
-	if (str_isnumber(servname)) {
-		if (!allownumeric)
-			return EAI_SERVICE;
-		port = htons(atoi(servname));
-		if (port < 0 || port > 65535)
-			return EAI_SERVICE;
-	} else {
-		switch (ai->ai_socktype) {
-		case SOCK_DGRAM:
-			proto = "udp";
-			break;
-		case SOCK_STREAM:
-			proto = "tcp";
-			break;
-		default:
-			proto = NULL;
-			break;
-		}
-
-		if ((sp = getservbyname(servname, proto)) == NULL)
-			return EAI_SERVICE;
-		port = sp->s_port;
-	}
-
-	if (!matchonly) {
-		switch (ai->ai_family) {
-		case AF_INET:
-			((struct sockaddr_in *)ai->ai_addr)->sin_port = port;
-			break;
-#ifdef INET6
-		case AF_INET6:
-			((struct sockaddr_in6 *)ai->ai_addr)->sin6_port = port;
-			break;
-#endif
-		}
-	}
-
-	return 0;
-}
-
-static const struct afd *
-find_afd(af)
-	int af;
-{
-	const struct afd *afd;
-
-	if (af == PF_UNSPEC)
-		return NULL;
-	for (afd = afdl; afd->a_af; afd++) {
-		if (afd->a_af == af)
-			return afd;
-	}
-	return NULL;
-}
-
-
-#endif /*__MING64__*/
diff --git a/Win32/Src/getnetbynm.c b/Win32/Src/getnetbynm.c
deleted file mode 100644
index fa4d398..0000000
--- a/Win32/Src/getnetbynm.c
+++ /dev/null
@@ -1,44 +0,0 @@
-/*
- * Copyright (c) 1983 Regents of the University of California.
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms are permitted
- * provided that the above copyright notice and this paragraph are
- * duplicated in all such forms and that any documentation,
- * advertising materials, and other materials related to such
- * distribution and use acknowledge that the software was developed
- * by the University of California, Berkeley.  The name of the
- * University may not be used to endorse or promote products derived
- * from this software without specific prior written permission.
- * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
- * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
- * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
- */
-
-#if defined(LIBC_SCCS) && !defined(lint)
-static char sccsid[] = "@(#)getnetbyname.c	5.5 (Berkeley) 6/27/88";
-#endif /* LIBC_SCCS and not lint */
-
-#include "inetprivate.h"
-
-extern int _net_stayopen;
-
-struct netent *
-getnetbyname(const char *name)
-{
-	register struct netent *p;
-	register char **cp;
-
-	setnetent(_net_stayopen);
-	while (p = getnetent()) {
-		if (strcmp(p->n_name, name) == 0)
-			break;
-		for (cp = p->n_aliases; *cp != 0; cp++)
-			if (strcmp(*cp, name) == 0)
-				goto found;
-	}
-found:
-	if (!_net_stayopen)
-		endnetent();
-	return (p);
-}
diff --git a/Win32/Src/getnetent.c b/Win32/Src/getnetent.c
deleted file mode 100644
index 95281a5..0000000
--- a/Win32/Src/getnetent.c
+++ /dev/null
@@ -1,119 +0,0 @@
-/*
- * Copyright (c) 1983 Regents of the University of California.
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms are permitted
- * provided that the above copyright notice and this paragraph are
- * duplicated in all such forms and that any documentation,
- * advertising materials, and other materials related to such
- * distribution and use acknowledge that the software was developed
- * by the University of California, Berkeley.  The name of the
- * University may not be used to endorse or promote products derived
- * from this software without specific prior written permission.
- * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
- * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
- * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
- */
-
-#if defined(LIBC_SCCS) && !defined(lint)
-static char sccsid[] = "@(#)getnetent.c	5.5 (Berkeley) 6/27/88";
-#endif /* LIBC_SCCS and not lint */
-
-#include "inetprivate.h"
-
-#define	MAXALIASES	35
-
-static char NETDB[] = _PATH_NETWORKS;
-static FILE *netf = NULL;
-static char line[BUFSIZ+1];
-static struct netent net;
-static char *net_aliases[MAXALIASES];
-static char *any(char *, char *);
-
-int _net_stayopen;
-extern u_int32_t inet_network(const char *cp);
-
-void
-setnetent(f)
-	int f;
-{
-	if (netf == NULL)
-		netf = fopen(NETDB, "r" );
-	else
-		rewind(netf);
-	_net_stayopen |= f;
-}
-
-void
-endnetent()
-{
-	if (netf) {
-		fclose(netf);
-		netf = NULL;
-	}
-	_net_stayopen = 0;
-}
-
-struct netent *
-getnetent()
-{
-	char *p;
-	register char *cp, **q;
-
-	if (netf == NULL && (netf = fopen(NETDB, "r" )) == NULL)
-		return (NULL);
-again:
-	p = fgets(line, BUFSIZ, netf);
-	if (p == NULL)
-		return (NULL);
-	if (*p == '#')
-		goto again;
-	cp = any(p, "#\n");
-	if (cp == NULL)
-		goto again;
-	*cp = '\0';
-	net.n_name = p;
-	cp = any(p, " \t");
-	if (cp == NULL)
-		goto again;
-	*cp++ = '\0';
-	while (*cp == ' ' || *cp == '\t')
-		cp++;
-	p = any(cp, " \t");
-	if (p != NULL)
-		*p++ = '\0';
-	net.n_net = inet_network(cp);
-	net.n_addrtype = AF_INET;
-	q = net.n_aliases = net_aliases;
-	if (p != NULL)
-		cp = p;
-	while (cp && *cp) {
-		if (*cp == ' ' || *cp == '\t') {
-			cp++;
-			continue;
-		}
-		if (q < &net_aliases[MAXALIASES - 1])
-			*q++ = cp;
-		cp = any(cp, " \t");
-		if (cp != NULL)
-			*cp++ = '\0';
-	}
-	*q = NULL;
-	return (&net);
-}
-
-static char *
-any(cp, match)
-	register char *cp;
-	char *match;
-{
-	register char *mp, c;
-
-	while (c = *cp) {
-		for (mp = match; *mp; mp++)
-			if (*mp == c)
-				return (cp);
-		cp++;
-	}
-	return ((char *)0);
-}
diff --git a/Win32/Src/getservent.c b/Win32/Src/getservent.c
deleted file mode 100644
index 61b8cb0..0000000
--- a/Win32/Src/getservent.c
+++ /dev/null
@@ -1,125 +0,0 @@
-/*
- * Copyright (c) 1983, 1993
- *	The Regents of the University of California.  All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in the
- *    documentation and/or other materials provided with the distribution.
- * 3. All advertising materials mentioning features or use of this software
- *    must display the following acknowledgement:
- *	This product includes software developed by the University of
- *	California, Berkeley and its contributors.
- * 4. Neither the name of the University nor the names of its contributors
- *    may be used to endorse or promote products derived from this software
- *    without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
- * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
- * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- */
-
-#if defined(LIBC_SCCS) && !defined(lint)
-static char sccsid[] = "@(#)getservent.c	8.1 (Berkeley) 6/4/93";
-#endif /* LIBC_SCCS and not lint */
-
-#include <sys/types.h>
-#include <string.h>
-
-#include <stdlib.h>
-#include <ctype.h>
-#include <net/netdb.h>
-#include <stdio.h>
-#include <errno.h>
-#include <arpa/nameser.h>
-
-#define	MAXALIASES	35
-
-static char SERVDB[] = _PATH_SERVICES;
-static FILE *servf = NULL;
-static char line[BUFSIZ+1];
-static struct servent serv;
-static char *serv_aliases[MAXALIASES];
-int _serv_stayopen;
-
-void
-setservent(f)
-	int f;
-{
-	if (servf == NULL)
-		servf = fopen(SERVDB, "r" );
-	else
-		rewind(servf);
-	_serv_stayopen |= f;
-}
-
-void
-endservent()
-{
-	if (servf) {
-		fclose(servf);
-		servf = NULL;
-	}
-	_serv_stayopen = 0;
-}
-
-struct servent *
-getservent()
-{
-	char *p;
-	register char *cp, **q;
-
-	if (servf == NULL && (servf = fopen(SERVDB, "r" )) == NULL)
-		return (NULL);
-again:
-	if ((p = fgets(line, BUFSIZ, servf)) == NULL)
-		return (NULL);
-	if (*p == '#')
-		goto again;
-	cp = strpbrk(p, "#\n");
-	if (cp == NULL)
-		goto again;
-	*cp = '\0';
-	serv.s_name = p;
-	p = strpbrk(p, " \t");
-	if (p == NULL)
-		goto again;
-	*p++ = '\0';
-	while (*p == ' ' || *p == '\t')
-		p++;
-	cp = strpbrk(p, ",/");
-	if (cp == NULL)
-		goto again;
-	*cp++ = '\0';
-	serv.s_port = htons((u_short)atoi(p));
-	serv.s_proto = cp;
-	q = serv.s_aliases = serv_aliases;
-	cp = strpbrk(cp, " \t");
-	if (cp != NULL)
-		*cp++ = '\0';
-	while (cp && *cp) {
-		if (*cp == ' ' || *cp == '\t') {
-			cp++;
-			continue;
-		}
-		if (q < &serv_aliases[MAXALIASES - 1])
-			*q++ = cp;
-		cp = strpbrk(cp, " \t");
-		if (cp != NULL)
-			*cp++ = '\0';
-	}
-	*q = NULL;
-	return (&serv);
-}
diff --git a/Win32/Src/inet_aton.c b/Win32/Src/inet_aton.c
deleted file mode 100644
index db97bce..0000000
--- a/Win32/Src/inet_aton.c
+++ /dev/null
@@ -1,54 +0,0 @@
-/*
- * Copyright (c) 1995, 1996, 1997 Kungliga Tekniska Högskolan
- * (Royal Institute of Technology, Stockholm, Sweden).
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- *
- * 2. Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in the
- *    documentation and/or other materials provided with the distribution.
- *
- * 3. All advertising materials mentioning features or use of this software
- *    must display the following acknowledgement:
- *      This product includes software developed by the Kungliga Tekniska
- *      Högskolan and its contributors.
- *
- * 4. Neither the name of the Institute nor the names of its contributors
- *    may be used to endorse or promote products derived from this software
- *    without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED.  IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
- * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
- * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- */
-
-#include <sys/types.h>
-#include <pcap-stdinc.h>
-
-/* Minimal implementation of inet_aton.
- * Cannot distinguish between failure and a local broadcast address. */
-
-#ifndef INADDR_NONE
-#define INADDR_NONE 0xffffffff
-#endif
-
-int
-inet_aton(const char *cp, struct in_addr *addr)
-{
-  addr->s_addr = inet_addr(cp);
-  return (addr->s_addr == INADDR_NONE) ? 0 : 1;
-}
diff --git a/Win32/Src/inet_net.c b/Win32/Src/inet_net.c
deleted file mode 100644
index 5bbe391..0000000
--- a/Win32/Src/inet_net.c
+++ /dev/null
@@ -1,101 +0,0 @@
-/*
- * Copyright (c) 1983, 1993
- *	The Regents of the University of California.  All rights reserved.
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in the
- *    documentation and/or other materials provided with the distribution.
- * 3. All advertising materials mentioning features or use of this software
- *    must display the following acknowledgement:
- *	This product includes software developed by the University of
- *	California, Berkeley and its contributors.
- * 4. Neither the name of the University nor the names of its contributors
- *    may be used to endorse or promote products derived from this software
- *    without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
- * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
- * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- */
-
-#if defined(LIBC_SCCS) && !defined(lint)
-static char sccsid[] = "@(#)inet_network.c	8.1 (Berkeley) 6/4/93";
-#endif /* LIBC_SCCS and not lint */
-
-#include "inetprivate.h"
-
-/*
- * Internet network address interpretation routine.
- * The library routines call this routine to interpret
- * network numbers.
- */
-u_int32_t
-inet_network(const char *cp)
-{
-	register u_long val, base, n;
-	register char c;
-	u_long parts[4], *pp = parts;
-	register int i;
-
-again:
-	/*
-	 * Collect number up to ``.''.
-	 * Values are specified as for C:
-	 * 0x=hex, 0=octal, other=decimal.
-	 */
-	val = 0; base = 10;
-	/*
-	 * The 4.4BSD version of this file also accepts 'x__' as a hexa
-	 * number.  I don't think this is correct.  -- Uli
-	 */
-	if (*cp == '0') {
-		if (*++cp == 'x' || *cp == 'X')
-			base = 16, cp++;
-		else
-			base = 8;
-	}
-	while ((c = *cp)) {
-		if (isdigit(c)) {
-			val = (val * base) + (c - '0');
-			cp++;
-			continue;
-		}
-		if (base == 16 && isxdigit(c)) {
-			val = (val << 4) + (c + 10 - (islower(c) ? 'a' : 'A'));
-			cp++;
-			continue;
-		}
-		break;
-	}
-	if (*cp == '.') {
-		if (pp >= parts + 4)
-			return (INADDR_NONE);
-		*pp++ = val, cp++;
-		goto again;
-	}
-	if (*cp && !isspace(*cp))
-		return (INADDR_NONE);
-	*pp++ = val;
-	n = pp - parts;
-	if (n > 4)
-		return (INADDR_NONE);
-	for (val = 0, i = 0; i < (int)n; i++) {
-		val <<= 8;
-		val |= parts[i] & 0xff;
-	}
-	return (val);
-}
diff --git a/Win32/Src/inet_pton.c b/Win32/Src/inet_pton.c
deleted file mode 100644
index 7fe3813..0000000
--- a/Win32/Src/inet_pton.c
+++ /dev/null
@@ -1,64 +0,0 @@
-/*
- * Copyright (c) 1999 Kungliga Tekniska Högskolan
- * (Royal Institute of Technology, Stockholm, Sweden).
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- *
- * 2. Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in the
- *    documentation and/or other materials provided with the distribution.
- *
- * 3. All advertising materials mentioning features or use of this software
- *    must display the following acknowledgement:
- *      This product includes software developed by the Kungliga Tekniska
- *      Högskolan and its contributors.
- *
- * 4. Neither the name of the Institute nor the names of its contributors
- *    may be used to endorse or promote products derived from this software
- *    without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED.  IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
- * 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 <errno.h>
-
-#ifdef WIN32
-#ifndef EAFNOSUPPORT
-#define	EAFNOSUPPORT	97	/* not present in errno.h provided with VC */
-#endif
-#endif
-
-#ifdef __MINGW32__
-int* _errno();
-#define errno (*_errno())
-#endif /* __MINGW32__ */
-
-#include <pcap-stdinc.h>
-
-int inet_aton(const char *cp, struct in_addr *addr);
-
-int
-inet_pton(int af, const char *src, void *dst)
-{
-    if (af != AF_INET) {
-	errno = EAFNOSUPPORT;
-	return -1;
-    }
-    return inet_aton (src, dst);
-}
diff --git a/aclocal.m4 b/aclocal.m4
index 02502b2..83f5761 100644
--- a/aclocal.m4
+++ b/aclocal.m4
@@ -102,6 +102,13 @@
 	    # -Werror forces warnings to be errors.
 	    #
 	    ac_lbl_cc_force_warning_errors=-Werror
+
+	    #
+	    # Try to have the compiler default to hiding symbols,
+	    # so that only symbols explicitly exported with
+	    # PCAP_API will be visible outside (shared) libraries.
+	    #
+	    AC_LBL_CHECK_COMPILER_OPT($1, -fvisibility=hidden)
     else
 	    $2="$$2 -I/usr/local/include"
 	    LDFLAGS="$LDFLAGS -L/usr/local/lib"
@@ -114,6 +121,13 @@
 		    # of which use -Werror to force warnings to be errors.
 		    #
 		    ac_lbl_cc_force_warning_errors=-Werror
+
+		    #
+		    # Try to have the compiler default to hiding symbols,
+		    # so that only symbols explicitly exported with
+		    # PCAP_API will be visible outside (shared) libraries.
+		    #
+		    AC_LBL_CHECK_COMPILER_OPT($1, -fvisibility=hidden)
 		    ;;
 
 	    hpux*)
@@ -188,6 +202,13 @@
 		    # warnings to be treated as errors.
 		    #
 		    ac_lbl_cc_force_warning_errors=-errwarn
+
+		    #
+		    # Try to have the compiler default to hiding symbols,
+		    # so that only symbols explicitly exported with
+		    # PCAP_API will be visible outside (shared) libraries.
+		    #
+		    AC_LBL_CHECK_COMPILER_OPT($1, -xldscope=hidden)
 		    ;;
 
 	    ultrix*)
@@ -249,7 +270,18 @@
     [
 	AC_MSG_CHECKING([whether the compiler supports the $2 option])
 	save_CFLAGS="$CFLAGS"
-	CFLAGS="$CFLAGS $ac_lbl_unknown_warning_option_error $2"
+	if expr "x$2" : "x-W.*" >/dev/null
+	then
+	    CFLAGS="$CFLAGS $ac_lbl_unknown_warning_option_error $2"
+	elif expr "x$2" : "x-f.*" >/dev/null
+	then
+	    CFLAGS="$CFLAGS -Werror $2"
+	elif expr "x$2" : "x-m.*" >/dev/null
+	then
+	    CFLAGS="$CFLAGS -Werror $2"
+	else
+	    CFLAGS="$CFLAGS $2"
+	fi
 	AC_TRY_COMPILE(
 	    [],
 	    [return 0],
@@ -630,82 +662,6 @@
     fi])
 
 dnl
-dnl Check for flex, default to lex
-dnl Require flex 2.4 or higher
-dnl Check for bison, default to yacc
-dnl Default to lex/yacc if both flex and bison are not available
-dnl
-dnl If we're using flex and bison, pass -P to flex and -p to bison
-dnl to define a prefix string for the lexer and parser
-dnl
-dnl If we're not using flex and bison, don't pass those options
-dnl (as they might not work - although if "lex" is a wrapper for
-dnl Flex and "yacc" is a wrapper for Bison, they will work), and
-dnl define NEED_YYPARSE_WRAPPER (we *CANNOT* use YYBISON to check
-dnl whether the wrapper is needed, as some people apparently, for
-dnl some unknown reason, choose to use --without-flex and
-dnl --without-bison on systems that have Flex and Bison, which
-dnl means that the "yacc" they end up using is a wrapper that
-dnl runs "bison -y", and at least some versions of Bison define
-dnl YYBISON even if run with "-y", so we end up not compiling
-dnl the yyparse wrapper and end up with a libpcap that doesn't
-dnl define pcap_parse())
-dnl
-dnl usage:
-dnl
-dnl	AC_LBL_LEX_AND_YACC(lex, yacc, yyprefix)
-dnl
-dnl results:
-dnl
-dnl	$1 (lex set)
-dnl	$2 (yacc appended)
-dnl	$3 (optional flex and bison -P prefix)
-dnl
-AC_DEFUN(AC_LBL_LEX_AND_YACC,
-    [AC_ARG_WITH(flex, [  --without-flex          don't use flex])
-    AC_ARG_WITH(bison, [  --without-bison         don't use bison])
-    if test "$with_flex" = no ; then
-	    $1=lex
-    else
-	    AC_CHECK_PROGS($1, flex, lex)
-    fi
-    if test "$$1" = flex ; then
-	    # The -V flag was added in 2.4
-	    AC_MSG_CHECKING(for flex 2.4 or higher)
-	    AC_CACHE_VAL(ac_cv_lbl_flex_v24,
-		if flex -V >/dev/null 2>&1; then
-			ac_cv_lbl_flex_v24=yes
-		else
-			ac_cv_lbl_flex_v24=no
-		fi)
-	    AC_MSG_RESULT($ac_cv_lbl_flex_v24)
-	    if test $ac_cv_lbl_flex_v24 = no ; then
-		    s="2.4 or higher required"
-		    AC_MSG_WARN(ignoring obsolete flex executable ($s))
-		    $1=lex
-	    fi
-    fi
-    if test "$with_bison" = no ; then
-	    $2=yacc
-    else
-	    AC_CHECK_PROGS($2, bison, yacc)
-    fi
-    if test "$$2" = bison ; then
-	    $2="$$2 -y"
-    fi
-    if test "$$1" != lex -a "$$2" = yacc -o "$$1" = lex -a "$$2" != yacc ; then
-	    AC_MSG_WARN(don't have both flex and bison; reverting to lex/yacc)
-	    $1=lex
-	    $2=yacc
-    fi
-    if test "$$1" = flex -a -n "$3" ; then
-	    $1="$$1 -P$3"
-	    $2="$$2 -p $3"
-    else
-	    AC_DEFINE(NEED_YYPARSE_WRAPPER,1,[if we need a pcap_parse wrapper around yyparse])
-    fi])
-
-dnl
 dnl Checks to see if union wait is used with WEXITSTATUS()
 dnl
 dnl usage:
@@ -970,8 +926,12 @@
 	    if test "$ac_lbl_cc_dont_try_gcc_dashW" != yes; then
 		    AC_LBL_CHECK_UNKNOWN_WARNING_OPTION_ERROR()
 		    AC_LBL_CHECK_COMPILER_OPT($1, -Wall)
+		    AC_LBL_CHECK_COMPILER_OPT($1, -Wsign-compare)
 		    AC_LBL_CHECK_COMPILER_OPT($1, -Wmissing-prototypes)
 		    AC_LBL_CHECK_COMPILER_OPT($1, -Wstrict-prototypes)
+		    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)
 	    fi
 	    AC_LBL_CHECK_DEPENDENCY_GENERATION_OPT()
 	    #
diff --git a/bpf/net/bpf_filter.c b/bpf/net/bpf_filter.c
index ffe04ce..01a1b64 100644
--- a/bpf/net/bpf_filter.c
+++ b/bpf/net/bpf_filter.c
@@ -42,11 +42,11 @@
 #include "config.h"
 #endif
 
-#ifdef WIN32
+#ifdef _WIN32
 
 #include <pcap-stdinc.h>
 
-#else /* WIN32 */
+#else /* _WIN32 */
 
 #if HAVE_INTTYPES_H
 #include <inttypes.h>
@@ -73,7 +73,7 @@
 # define	MLEN(m)	((m)->m_len)
 #endif /* defined(__hpux) || SOLARIS */
 
-#endif /* WIN32 */
+#endif /* _WIN32 */
 
 #include <pcap/bpf.h>
 
@@ -99,7 +99,7 @@
 #endif
 
 #ifndef LBL_ALIGN
-#ifndef WIN32
+#ifndef _WIN32
 #include <netinet/in.h>
 #endif
 
@@ -216,6 +216,8 @@
  * rejects the filter; it contains VLAN tag information
  * For the kernel, p is assumed to be a pointer to an mbuf if buflen is 0,
  * in all other cases, p is a pointer to a buffer and buflen is its size.
+ *
+ * Thanks to Ani Sinha <ani@arista.com> for providing initial implementation
  */
 u_int
 bpf_filter_with_aux_data(pc, p, wirelen, buflen, aux_data)
@@ -577,7 +579,12 @@
 			continue;
 
 		case BPF_ALU|BPF_NEG:
-			A = -A;
+			/*
+			 * Most BPF arithmetic is unsigned, but negation
+			 * can't be unsigned; throw some casts to
+			 * specify what we're trying to do.
+			 */
+			A = (u_int32)(-(int32)A);
 			continue;
 
 		case BPF_MISC|BPF_TAX:
@@ -631,7 +638,7 @@
 		return 0;
 #endif
 
-	for (i = 0; i < len; ++i) {
+	for (i = 0; i < (u_int)len; ++i) {
 		p = &f[i];
 		switch (BPF_CLASS(p->code)) {
 		/*
@@ -732,7 +739,7 @@
 #if defined(KERNEL) || defined(_KERNEL)
 				if (from + p->k < from || from + p->k >= len)
 #else
-				if (from + p->k >= len)
+				if (from + p->k >= (u_int)len)
 #endif
 					return 0;
 				break;
@@ -740,7 +747,7 @@
 			case BPF_JGT:
 			case BPF_JGE:
 			case BPF_JSET:
-				if (from + p->jt >= len || from + p->jf >= len)
+				if (from + p->jt >= (u_int)len || from + p->jf >= (u_int)len)
 					return 0;
 				break;
 			default:
diff --git a/bpf_dump.c b/bpf_dump.c
index 5eaadc0..d5ab61e 100644
--- a/bpf_dump.c
+++ b/bpf_dump.c
@@ -51,7 +51,10 @@
 	for (i = 0; i < n; ++insn, ++i) {
 #ifdef BDEBUG
 		extern int bids[];
-		printf(bids[i] > 0 ? "[%02d]" : " -- ", bids[i] - 1);
+		if (bids[i] > 0)
+			printf("[%02d]", bids[i] - 1);
+		else
+			printf(" -- ");
 #endif
 		puts(bpf_image(insn, i));
 	}
diff --git a/bpf_filter.c b/bpf_filter.c
new file mode 120000
index 0000000..0605488
--- /dev/null
+++ b/bpf_filter.c
@@ -0,0 +1 @@
+./bpf/net/bpf_filter.c
\ No newline at end of file
diff --git a/bpf_image.c b/bpf_image.c
index 3e9a23f..01ec536 100644
--- a/bpf_image.c
+++ b/bpf_image.c
@@ -23,9 +23,9 @@
 #include "config.h"
 #endif
 
-#ifdef WIN32
+#ifdef _WIN32
 #include <pcap-stdinc.h>
-#else /* WIN32 */
+#else /* _WIN32 */
 #if HAVE_INTTYPES_H
 #include <inttypes.h>
 #elif HAVE_STDINT_H
@@ -35,7 +35,7 @@
 #include <sys/bitypes.h>
 #endif
 #include <sys/types.h>
-#endif /* WIN32 */
+#endif /* _WIN32 */
 
 #include <stdio.h>
 #include <string.h>
@@ -306,13 +306,13 @@
 		fmt = "";
 		break;
 	}
-	(void)snprintf(operand, sizeof operand, fmt, v);
+	(void)pcap_snprintf(operand, sizeof operand, fmt, v);
 	if (BPF_CLASS(p->code) == BPF_JMP && BPF_OP(p->code) != BPF_JA) {
-		(void)snprintf(image, sizeof image,
+		(void)pcap_snprintf(image, sizeof image,
 			      "(%03d) %-8s %-16s jt %d\tjf %d",
 			      n, op, operand, n + 1 + p->jt, n + 1 + p->jf);
 	} else {
-		(void)snprintf(image, sizeof image,
+		(void)pcap_snprintf(image, sizeof image,
 			      "(%03d) %-8s %s",
 			      n, op, operand);
 	}
diff --git a/cmake/preconfigure.cmake b/cmake/preconfigure.cmake
new file mode 100644
index 0000000..c8c92a4
--- /dev/null
+++ b/cmake/preconfigure.cmake
@@ -0,0 +1,55 @@
+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/cmakeconfig.h.in b/cmakeconfig.h.in
new file mode 100644
index 0000000..94edb5f
--- /dev/null
+++ b/cmakeconfig.h.in
@@ -0,0 +1,345 @@
+/* cmakeconfig.h.in */
+
+/* Enable optimizer debugging */
+#cmakedefine BDEBUG 1
+
+/* define if you have a cloning BPF device */
+#cmakedefine HAVE_CLONING_BPF 1
+
+/* define if you have the DAG API */
+#cmakedefine HAVE_DAG_API 1
+
+/* define if you have dag_get_erf_types() */
+#cmakedefine HAVE_DAG_GET_ERF_TYPES 1
+
+/* define if you have dag_get_stream_erf_types() */
+#cmakedefine HAVE_DAG_GET_STREAM_ERF_TYPES 1
+
+/* define if you have streams capable DAG API */
+#cmakedefine HAVE_DAG_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. */
+#cmakedefine HAVE_DECL_ETHER_HOSTTON 1
+
+/* define if you have a /dev/dlpi */
+#cmakedefine HAVE_DEV_DLPI 1
+
+/* if passive_req_t primitive exists */
+#cmakedefine HAVE_DLPI_PASSIVE 1
+
+/* Define to 1 if you have the `ether_hostton' function. */
+#cmakedefine HAVE_ETHER_HOSTTON 1
+
+/* Define to 1 if fseeko (and presumably ftello) exists and is declared. */
+#cmakedefine HAVE_FSEEKO 1
+
+/* 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
+
+/* if libdlpi exists */
+#cmakedefine HAVE_LIBDLPI 1
+
+/* if libnl exists */
+#cmakedefine HAVE_LIBNL 1
+
+/* if libnl exists and is version 2.x */
+#cmakedefine HAVE_LIBNL_2_x 1
+
+/* if libnl exists and is version 3.x */
+#cmakedefine HAVE_LIBNL_3_x 1
+
+/* libnl has NLE_FAILURE */
+#cmakedefine HAVE_LIBNL_NLE 1
+
+/* libnl has new-style socket api */
+#cmakedefine HAVE_LIBNL_SOCKETS 1
+
+/* Define to 1 if you have the <limits.h> header file. */
+#cmakedefine HAVE_LIMITS_H 1
+
+/* Define to 1 if you have the <linux/compiler.h> header file. */
+#cmakedefine HAVE_LINUX_COMPILER_H 1
+
+/* Define to 1 if you have the <linux/ethtool.h> header file. */
+#cmakedefine HAVE_LINUX_ETHTOOL_H 1
+
+/* Define 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/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
+
+/* Define to 1 if you have the <linux/wireless.h> header file. */
+#cmakedefine HAVE_LINUX_WIRELESS_H 1
+
+/* Define to 1 if you have the <memory.h> header file. */
+#cmakedefine HAVE_MEMORY_H 1
+
+/* Define to 1 if you have the <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/if_media.h> header file. */
+#cmakedefine HAVE_NET_IF_MEDIA_H 1
+
+/* Define to 1 if you have the <net/pfvar.h> header file. */
+#cmakedefine HAVE_NET_PFVAR_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 if net/pfvar.h defines PF_NAT through PF_NORDR */
+#cmakedefine HAVE_PF_NAT_THROUGH_PF_NORDR 1
+
+/* define if you have the Septel API */
+#cmakedefine HAVE_SEPTEL_API 1
+
+/* define if you have the Myricom SNF API */
+#cmakedefine HAVE_SNF_API 1
+
+/* Define to 1 if you have the `snprintf' function. */
+#cmakedefine HAVE_SNPRINTF 1
+
+/* 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 */
+#cmakedefine HAVE_SOCKLEN_T 1
+
+/* On solaris */
+#cmakedefine HAVE_SOLARIS 1
+
+/* Define to 1 if you have the <stdint.h> header file. */
+#cmakedefine HAVE_STDINT_H 1
+
+/* Define to 1 if you have the <stdlib.h> header file. */
+#cmakedefine HAVE_STDLIB_H 1
+
+/* Define to 1 if you have the `strerror' function. */
+#cmakedefine HAVE_STRERROR 1
+
+/* Define to 1 if you have the `strlcpy' function. */
+#cmakedefine HAVE_STRLCPY 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 you have the <sys/bufmod.h> header file. */
+#cmakedefine HAVE_SYS_BUFMOD_H 1
+
+/* Define to 1 if you have the <sys/dlpi_ext.h> header file. */
+#cmakedefine HAVE_SYS_DLPI_EXT_H 1
+
+/* Define to 1 if you have the <sys/ioccom.h> header file. */
+#cmakedefine HAVE_SYS_IOCCOM_H 1
+
+/* Define to 1 if you have the <sys/sockio.h> header file. */
+#cmakedefine HAVE_SYS_SOCKIO_H 1
+
+/* Define to 1 if you have the <sys/stat.h> header file. */
+#cmakedefine HAVE_SYS_STAT_H 1
+
+/* Define to 1 if you have the <sys/types.h> header file. */
+#cmakedefine HAVE_SYS_TYPES_H 1
+
+/* define if you have the TurboCap API */
+#cmakedefine HAVE_TC_API 1
+
+/* 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
+
+/* if unaligned access fails */
+#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
+
+/* Define to 1 if netinet/ether.h declares `ether_hostton' */
+#cmakedefine NETINET_ETHER_H_DECLARES_ETHER_HOSTTON 1
+
+/* Define to 1 if netinet/if_ether.h declares `ether_hostton' */
+#cmakedefine NETINET_IF_ETHER_H_DECLARES_ETHER_HOSTTON 1
+
+/* 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 full name of this package. */
+#cmakedefine PACKAGE_NAME 1
+
+/* Define to the full name and version of this package. */
+#cmakedefine PACKAGE_STRING 1
+
+/* Define to the one symbol short name of this package. */
+#cmakedefine PACKAGE_TARNAME 1
+
+/* Define to the home page for this package. */
+#cmakedefine PACKAGE_URL 1
+
+/* Define to the version of this package. */
+#cmakedefine PACKAGE_VERSION 1
+
+/* /dev/dlpi directory */
+#cmakedefine PCAP_DEV_PREFIX 1
+
+/* target host supports Bluetooth sniffing */
+#cmakedefine PCAP_SUPPORT_BT 1
+
+/* target host supports Bluetooth Monitor */
+#cmakedefine PCAP_SUPPORT_BT_MONITOR 1
+
+/* support D-Bus sniffing */
+#cmakedefine PCAP_SUPPORT_DBUS 1
+
+/* target host supports netfilter sniffing */
+#cmakedefine PCAP_SUPPORT_NETFILTER 1
+
+/* use Linux packet ring capture if available */
+#cmakedefine PCAP_SUPPORT_PACKET_RING 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
+
+/* Enable parser debugging */
+#cmakedefine YYDEBUG 1
+
+/* Enable large inode numbers on Mac OS X 10.5.  */
+#ifndef _DARWIN_USE_64_BIT_INODE
+# define _DARWIN_USE_64_BIT_INODE 1
+#endif
+
+/* Number of bits in a file offset, on hosts where this is settable. */
+#cmakedefine _FILE_OFFSET_BITS 1
+
+/* Define to 1 to make fseeko visible on some hosts (e.g. glibc 2.2). */
+#cmakedefine _LARGEFILE_SOURCE 1
+
+/* Define for large files, on AIX-style hosts. */
+#cmakedefine _LARGE_FILES 1
+
+/* define on AIX to get certain functions */
+#cmakedefine _SUN 1
+
+/* 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.h b/config.h
index 680bfd8..a605068 100644
--- a/config.h
+++ b/config.h
@@ -1,5 +1,5 @@
 /* config.h.  Generated from config.h.in by configure.  */
-/* config.h.in.  Generated from configure.in by autoheader.  */
+/* config.h.in.  Generated from configure.ac by autoheader.  */
 
 /* Enable optimizer debugging */
 /* #undef BDEBUG */
@@ -24,7 +24,7 @@
 
 /* Define to 1 if you have the declaration of `ether_hostton', and to 0 if you
    don't. */
-/* #undef HAVE_DECL_ETHER_HOSTTON */
+#define HAVE_DECL_ETHER_HOSTTON 1
 
 /* define if you have a /dev/dlpi */
 /* #undef HAVE_DEV_DLPI */
@@ -86,6 +86,9 @@
 /* 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/sockios.h> header file. */
+#define HAVE_LINUX_SOCKIOS_H 1
+
 /* if tp_vlan_tci exists */
 #define HAVE_LINUX_TPACKET_AUXDATA_TP_VLAN_TCI 1
 
@@ -122,16 +125,13 @@
 /* if there's an os_proto.h for this platform, to use additional prototypes */
 /* #undef HAVE_OS_PROTO_H */
 
-/* Define to 1 if you have the <paths.h> header file. */
-#define HAVE_PATHS_H 1
-
 /* define if net/pfvar.h defines PF_NAT through PF_NORDR */
 /* #undef HAVE_PF_NAT_THROUGH_PF_NORDR */
 
-/* define if you have a Septel API */
+/* define if you have the Septel API */
 /* #undef HAVE_SEPTEL_API */
 
-/* define if you have Myricom SNF API */
+/* define if you have the Myricom SNF API */
 /* #undef HAVE_SNF_API */
 
 /* Define to 1 if you have the `snprintf' function. */
@@ -165,7 +165,10 @@
 #define HAVE_STRING_H 1
 
 /* Define to 1 if you have the `strlcpy' function. */
-#define HAVE_STRLCPY 1
+/* #undef HAVE_STRLCPY */
+
+/* Define to 1 if you have the `strtok_r' function. */
+#define HAVE_STRTOK_R 1
 
 /* Define to 1 if the system has the type `struct BPF_TIMEVAL'. */
 /* #undef HAVE_STRUCT_BPF_TIMEVAL */
@@ -185,6 +188,9 @@
 /* Define to 1 if you have the <sys/ioccom.h> header file. */
 /* #undef HAVE_SYS_IOCCOM_H */
 
+/* Define to 1 if you have the <sys/select.h> header file. */
+#define HAVE_SYS_SELECT_H 1
+
 /* Define to 1 if you have the <sys/sockio.h> header file. */
 /* #undef HAVE_SYS_SOCKIO_H */
 
@@ -194,6 +200,9 @@
 /* Define to 1 if you have the <sys/types.h> header file. */
 #define HAVE_SYS_TYPES_H 1
 
+/* define if you have the TurboCap API */
+/* #undef HAVE_TC_API */
+
 /* if if_packet.h has tpacket_stats defined */
 #define HAVE_TPACKET_STATS 1
 
@@ -203,9 +212,6 @@
 /* if struct usbdevfs_ctrltransfer has bRequestType */
 #define HAVE_USBDEVFS_CTRLTRANSFER_BREQUESTTYPE 1
 
-/* define if version.h is generated in the build procedure */
-#define HAVE_VERSION_H 1
-
 /* Define to 1 if you have the `vsnprintf' function. */
 #define HAVE_VSNPRINTF 1
 
@@ -224,11 +230,8 @@
 /* path for device for USB sniffing */
 #define LINUX_USB_MON_DEV "/dev/usbmon"
 
-/* if we need a pcap_parse wrapper around yyparse */
-/* #undef NEED_YYPARSE_WRAPPER */
-
 /* Define to 1 if netinet/ether.h declares `ether_hostton' */
-/* #undef NETINET_ETHER_H_DECLARES_ETHER_HOSTTON */
+#define NETINET_ETHER_H_DECLARES_ETHER_HOSTTON /**/
 
 /* Define to 1 if netinet/if_ether.h declares `ether_hostton' */
 /* #undef NETINET_IF_ETHER_H_DECLARES_ETHER_HOSTTON */
@@ -260,11 +263,8 @@
 /* target host supports Bluetooth sniffing */
 /* #undef PCAP_SUPPORT_BT */
 
-/* target host supports CAN sniffing */
-#define PCAP_SUPPORT_CAN 1
-
-/* target host supports canusb */
-/* #undef PCAP_SUPPORT_CANUSB */
+/* target host supports Bluetooth Monitor */
+/* #undef PCAP_SUPPORT_BT_MONITOR */
 
 /* support D-Bus sniffing */
 /* #undef PCAP_SUPPORT_DBUS */
@@ -272,6 +272,9 @@
 /* target host supports netfilter sniffing */
 #define PCAP_SUPPORT_NETFILTER 1
 
+/* use Linux packet ring capture if available */
+#define PCAP_SUPPORT_PACKET_RING 1
+
 /* target host supports USB sniffing */
 #define PCAP_SUPPORT_USB 1
 
@@ -287,6 +290,10 @@
 /* Enable parser debugging */
 /* #undef YYDEBUG */
 
+/* Define to 1 if `lex' declares `yytext' as a `char *' by default, not a
+   `char[]'. */
+#define YYTEXT_POINTER 1
+
 /* Enable large inode numbers on Mac OS X 10.5.  */
 #ifndef _DARWIN_USE_64_BIT_INODE
 # define _DARWIN_USE_64_BIT_INODE 1
diff --git a/config.h.in b/config.h.in
index 3b9f90a..e85b2a3 100644
--- a/config.h.in
+++ b/config.h.in
@@ -1,4 +1,4 @@
-/* config.h.in.  Generated from configure.in by autoheader.  */
+/* config.h.in.  Generated from configure.ac by autoheader.  */
 
 /* Enable optimizer debugging */
 #undef BDEBUG
@@ -124,16 +124,13 @@
 /* if there's an os_proto.h for this platform, to use additional prototypes */
 #undef HAVE_OS_PROTO_H
 
-/* Define to 1 if you have the <paths.h> header file. */
-#undef HAVE_PATHS_H
-
 /* define if net/pfvar.h defines PF_NAT through PF_NORDR */
 #undef HAVE_PF_NAT_THROUGH_PF_NORDR
 
-/* define if you have a Septel API */
+/* define if you have the Septel API */
 #undef HAVE_SEPTEL_API
 
-/* define if you have Myricom SNF API */
+/* define if you have the Myricom SNF API */
 #undef HAVE_SNF_API
 
 /* Define to 1 if you have the `snprintf' function. */
@@ -169,6 +166,9 @@
 /* Define to 1 if you have the `strlcpy' function. */
 #undef HAVE_STRLCPY
 
+/* Define to 1 if you have the `strtok_r' function. */
+#undef HAVE_STRTOK_R
+
 /* Define to 1 if the system has the type `struct BPF_TIMEVAL'. */
 #undef HAVE_STRUCT_BPF_TIMEVAL
 
@@ -187,6 +187,9 @@
 /* Define to 1 if you have the <sys/ioccom.h> header file. */
 #undef HAVE_SYS_IOCCOM_H
 
+/* Define to 1 if you have the <sys/select.h> header file. */
+#undef HAVE_SYS_SELECT_H
+
 /* Define to 1 if you have the <sys/sockio.h> header file. */
 #undef HAVE_SYS_SOCKIO_H
 
@@ -196,6 +199,9 @@
 /* Define to 1 if you have the <sys/types.h> header file. */
 #undef HAVE_SYS_TYPES_H
 
+/* define if you have the TurboCap API */
+#undef HAVE_TC_API
+
 /* if if_packet.h has tpacket_stats defined */
 #undef HAVE_TPACKET_STATS
 
@@ -205,9 +211,6 @@
 /* if struct usbdevfs_ctrltransfer has bRequestType */
 #undef HAVE_USBDEVFS_CTRLTRANSFER_BREQUESTTYPE
 
-/* define if version.h is generated in the build procedure */
-#undef HAVE_VERSION_H
-
 /* Define to 1 if you have the `vsnprintf' function. */
 #undef HAVE_VSNPRINTF
 
@@ -226,9 +229,6 @@
 /* path for device for USB sniffing */
 #undef LINUX_USB_MON_DEV
 
-/* if we need a pcap_parse wrapper around yyparse */
-#undef NEED_YYPARSE_WRAPPER
-
 /* Define to 1 if netinet/ether.h declares `ether_hostton' */
 #undef NETINET_ETHER_H_DECLARES_ETHER_HOSTTON
 
@@ -265,12 +265,6 @@
 /* target host supports Bluetooth Monitor */
 #undef PCAP_SUPPORT_BT_MONITOR
 
-/* target host supports CAN sniffing */
-#undef PCAP_SUPPORT_CAN
-
-/* target host supports canusb */
-#undef PCAP_SUPPORT_CANUSB
-
 /* support D-Bus sniffing */
 #undef PCAP_SUPPORT_DBUS
 
@@ -295,6 +289,10 @@
 /* Enable parser debugging */
 #undef YYDEBUG
 
+/* Define to 1 if `lex' declares `yytext' as a `char *' by default, not a
+   `char[]'. */
+#undef YYTEXT_POINTER
+
 /* Enable large inode numbers on Mac OS X 10.5.  */
 #ifndef _DARWIN_USE_64_BIT_INODE
 # define _DARWIN_USE_64_BIT_INODE 1
diff --git a/config/have_siocglifconf.c b/config/have_siocglifconf.c
new file mode 100644
index 0000000..5a67abc
--- /dev/null
+++ b/config/have_siocglifconf.c
@@ -0,0 +1,6 @@
+#include <sys/ioctl.h>
+#include <sys/socket.h>
+#include <sys/sockio.h>
+int main() {
+    ioctl(0, SIOCGLIFCONF, (char *)0);
+}
diff --git a/configure b/configure
index 2b69b6d..4c64875 100755
--- a/configure
+++ b/configure
@@ -627,10 +627,6 @@
 DBUS_SRC
 PCAP_SUPPORT_DBUS
 PKGCONFIG
-CAN_SRC
-PCAP_SUPPORT_CAN
-CANUSB_SRC
-PCAP_SUPPORT_CANUSB
 BT_MONITOR_SRC
 BT_SRC
 PCAP_SUPPORT_BT
@@ -644,11 +640,13 @@
 SSRC
 ADDLARCHIVEOBJS
 ADDLOBJS
+V_YACC
 V_RPATH_OPT
 V_SONAME_OPT
 V_SHLIB_OPT
 V_SHLIB_CMD
 V_PCAP
+V_LEX
 V_INCLS
 V_FINDALLDEVS
 V_DEFS
@@ -658,9 +656,13 @@
 LN_S
 AR
 RANLIB
-V_YACC
-V_LEX
+YFLAGS
+YACC
+LEXLIB
+LEX_OUTPUT_ROOT
+LEX
 HAVE_LINUX_TPACKET_AUXDATA
+VALGRINDTEST
 LIBOBJS
 EGREP
 GREP
@@ -742,14 +744,11 @@
 with_snf
 with_snf_includes
 with_snf_libraries
-with_flex
-with_bison
+with_turbocap
 enable_universal
 enable_shared
 enable_usb
 enable_bluetooth
-enable_canusb
-enable_can
 enable_dbus
 enable_packet_ring
 '
@@ -761,7 +760,9 @@
 LDFLAGS
 LIBS
 CPPFLAGS
-CPP'
+CPP
+YACC
+YFLAGS'
 
 
 # Initialize some variables set by options.
@@ -1387,10 +1388,6 @@
                           available]
   --enable-bluetooth      enable Bluetooth support [default=yes, if support
                           available]
-  --enable-canusb         enable canusb support [default=yes, if support
-                          available]
-  --enable-can            enable CAN 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]
@@ -1403,20 +1400,23 @@
   --with-pcap=TYPE        use packet capture TYPE
   --without-libnl         disable libnl support [default=yes, on Linux, if
                           present]
-  --with-dag[=DIR]        include Endace DAG support ["yes", "no" or DIR;
-                          default="yes" on BSD and Linux if present]
-  --with-dag-includes=DIR Endace DAG include directory
-  --with-dag-libraries=DIR
-                          Endace DAG library directory
+  --with-dag[=DIR]        include Endace DAG support (located in directory
+                          DIR, if supplied). [default=yes, if present]
+  --with-dag-includes=IDIR
+                          Endace DAG include directory, if not DIR/include
+  --with-dag-libraries=LDIR
+                          Endace DAG library directory, if not DIR/lib
   --with-septel[=DIR]     include Septel support (located in directory DIR, if
-                          supplied). [default=yes, on Linux, if present]
-  --with-snf[=DIR]        include Myricom SNF support ["yes", "no" or DIR;
-                          default="yes" on BSD and Linux if present]
-  --with-snf-includes=DIR Myricom SNF include directory
-  --with-snf-libraries=DIR
-                          Myricom SNF library directory
-  --without-flex          don't use flex
-  --without-bison         don't use bison
+                          supplied). [default=yes, if present]
+  --with-snf[=DIR]        include Myricom SNF support (located in directory
+                          DIR, if supplied). [default=yes, if present]
+  --with-snf-includes=IDIR
+                          Myricom SNF include directory, if not DIR/include
+  --with-snf-libraries=LDIR
+                          Myricom SNF library directory, if not DIR/lib
+  --with-turbocap[=DIR]   include Riverbed TurboCap support (located in
+                          directory DIR, if supplied). [default=yes, if
+                          present]
 
 Some influential environment variables:
   CC          C compiler command
@@ -1427,6 +1427,12 @@
   CPPFLAGS    (Objective) C/C++ preprocessor flags, e.g. -I<include dir> if
               you have headers in a nonstandard directory <include dir>
   CPP         C preprocessor
+  YACC        The `Yet Another Compiler Compiler' implementation to use.
+              Defaults to the first program found out of: `bison -y', `byacc',
+              `yacc'.
+  YFLAGS      The list of arguments that will be passed by default to $YACC.
+              This script will default YFLAGS to the empty string to avoid a
+              default value of `-d' given by some make applications.
 
 Use these variables to override the choices made by `configure' or to help
 it to find libraries and programs with nonstandard names/locations.
@@ -3314,11 +3320,61 @@
 
 
 
+
     if test "$GCC" = yes ; then
 	    #
 	    # -Werror forces warnings to be errors.
 	    #
 	    ac_lbl_cc_force_warning_errors=-Werror
+
+	    #
+	    # Try to have the compiler default to hiding symbols,
+	    # so that only symbols explicitly exported with
+	    # PCAP_API will be visible outside (shared) libraries.
+	    #
+
+	{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether the compiler supports the -fvisibility=hidden option" >&5
+$as_echo_n "checking whether the compiler supports the -fvisibility=hidden option... " >&6; }
+	save_CFLAGS="$CFLAGS"
+	if expr "x-fvisibility=hidden" : "x-W.*" >/dev/null
+	then
+	    CFLAGS="$CFLAGS $ac_lbl_unknown_warning_option_error -fvisibility=hidden"
+	elif expr "x-fvisibility=hidden" : "x-f.*" >/dev/null
+	then
+	    CFLAGS="$CFLAGS -Werror -fvisibility=hidden"
+	elif expr "x-fvisibility=hidden" : "x-m.*" >/dev/null
+	then
+	    CFLAGS="$CFLAGS -Werror -fvisibility=hidden"
+	else
+	    CFLAGS="$CFLAGS -fvisibility=hidden"
+	fi
+	cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+
+int
+main ()
+{
+return 0
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+
+		{ $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
+$as_echo "yes" >&6; }
+		CFLAGS="$save_CFLAGS"
+		V_CCOPT="$V_CCOPT -fvisibility=hidden"
+
+else
+
+		{ $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+		CFLAGS="$save_CFLAGS"
+
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+
     else
 	    V_INCLS="$V_INCLS -I/usr/local/include"
 	    LDFLAGS="$LDFLAGS -L/usr/local/lib"
@@ -3331,6 +3387,55 @@
 		    # of which use -Werror to force warnings to be errors.
 		    #
 		    ac_lbl_cc_force_warning_errors=-Werror
+
+		    #
+		    # Try to have the compiler default to hiding symbols,
+		    # so that only symbols explicitly exported with
+		    # PCAP_API will be visible outside (shared) libraries.
+		    #
+
+	{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether the compiler supports the -fvisibility=hidden option" >&5
+$as_echo_n "checking whether the compiler supports the -fvisibility=hidden option... " >&6; }
+	save_CFLAGS="$CFLAGS"
+	if expr "x-fvisibility=hidden" : "x-W.*" >/dev/null
+	then
+	    CFLAGS="$CFLAGS $ac_lbl_unknown_warning_option_error -fvisibility=hidden"
+	elif expr "x-fvisibility=hidden" : "x-f.*" >/dev/null
+	then
+	    CFLAGS="$CFLAGS -Werror -fvisibility=hidden"
+	elif expr "x-fvisibility=hidden" : "x-m.*" >/dev/null
+	then
+	    CFLAGS="$CFLAGS -Werror -fvisibility=hidden"
+	else
+	    CFLAGS="$CFLAGS -fvisibility=hidden"
+	fi
+	cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+
+int
+main ()
+{
+return 0
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+
+		{ $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
+$as_echo "yes" >&6; }
+		CFLAGS="$save_CFLAGS"
+		V_CCOPT="$V_CCOPT -fvisibility=hidden"
+
+else
+
+		{ $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+		CFLAGS="$save_CFLAGS"
+
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+
 		    ;;
 
 	    hpux*)
@@ -3405,6 +3510,55 @@
 		    # warnings to be treated as errors.
 		    #
 		    ac_lbl_cc_force_warning_errors=-errwarn
+
+		    #
+		    # Try to have the compiler default to hiding symbols,
+		    # so that only symbols explicitly exported with
+		    # PCAP_API will be visible outside (shared) libraries.
+		    #
+
+	{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether the compiler supports the -xldscope=hidden option" >&5
+$as_echo_n "checking whether the compiler supports the -xldscope=hidden option... " >&6; }
+	save_CFLAGS="$CFLAGS"
+	if expr "x-xldscope=hidden" : "x-W.*" >/dev/null
+	then
+	    CFLAGS="$CFLAGS $ac_lbl_unknown_warning_option_error -xldscope=hidden"
+	elif expr "x-xldscope=hidden" : "x-f.*" >/dev/null
+	then
+	    CFLAGS="$CFLAGS -Werror -xldscope=hidden"
+	elif expr "x-xldscope=hidden" : "x-m.*" >/dev/null
+	then
+	    CFLAGS="$CFLAGS -Werror -xldscope=hidden"
+	else
+	    CFLAGS="$CFLAGS -xldscope=hidden"
+	fi
+	cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+
+int
+main ()
+{
+return 0
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+
+		{ $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
+$as_echo "yes" >&6; }
+		CFLAGS="$save_CFLAGS"
+		V_CCOPT="$V_CCOPT -xldscope=hidden"
+
+else
+
+		{ $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+		CFLAGS="$save_CFLAGS"
+
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+
 		    ;;
 
 	    ultrix*)
@@ -3413,8 +3567,7 @@
 		    if ${ac_cv_lbl_cc_const_proto+:} false; then :
   $as_echo_n "(cached) " >&6
 else
-
-cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+  cat confdefs.h - <<_ACEOF >conftest.$ac_ext
 /* end confdefs.h.  */
 #include <sys/types.h>
 int
@@ -4578,7 +4731,7 @@
 fi
 
 
-for ac_header in sys/ioccom.h sys/sockio.h limits.h paths.h
+for ac_header in sys/ioccom.h sys/select.h sys/sockio.h limits.h
 do :
   as_ac_Header=`$as_echo "ac_cv_header_$ac_header" | $as_tr_sh`
 ac_fn_c_check_header_mongrel "$LINENO" "$ac_header" "$as_ac_Header" "$ac_includes_default"
@@ -4711,7 +4864,7 @@
 fi
 
 case "$host_os" in
-linux*)
+linux*|uclinux*)
 	for ac_header in linux/sockios.h linux/if_bonding.h
 do :
   as_ac_Header=`$as_echo "ac_cv_header_$ac_header" | $as_tr_sh`
@@ -4815,6 +4968,29 @@
 
 fi
 
+needstrtok_r=no
+for ac_func in strtok_r
+do :
+  ac_fn_c_check_func "$LINENO" "strtok_r" "ac_cv_func_strtok_r"
+if test "x$ac_cv_func_strtok_r" = xyes; then :
+  cat >>confdefs.h <<_ACEOF
+#define HAVE_STRTOK_R 1
+_ACEOF
+
+else
+  needstrtok_r=yes
+fi
+done
+
+if test $needstrtok_r = yes; then
+	case " $LIBOBJS " in
+  *" strtok_r.$ac_objext "* ) ;;
+  *) LIBOBJS="$LIBOBJS strtok_r.$ac_objext"
+ ;;
+esac
+
+fi
+
 #
 # Do this before checking for ether_hostton(), as it's a
 # "gethostbyname() -ish function".
@@ -5232,6 +5408,13 @@
 $as_echo "${enable_protochain}" >&6; }
 
 #
+# valgrindtest directly uses the native capture mechanism, but
+# only tests with BPF and PF_PACKET sockets; only enable it if
+# we have BPF or PF_PACKET sockets.
+#
+VALGRINDTEST=
+
+#
 # SITA support is mutually exclusive with native capture support;
 # "--with-sita" selects SITA support.
 #
@@ -5246,7 +5429,6 @@
 		{ $as_echo "$as_me:${as_lineno-$LINENO}: Enabling SITA ACN support" >&5
 $as_echo "$as_me: Enabling SITA ACN support" >&6;}
 		V_PCAP=sita
-		V_FINDALLDEVS=sita
 	fi
 
 else
@@ -5272,8 +5454,18 @@
 
 $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
@@ -5284,6 +5476,12 @@
 	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
@@ -5295,6 +5493,11 @@
 	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
@@ -5307,6 +5510,7 @@
 { $as_echo "$as_me:${as_lineno-$LINENO}: result: $V_PCAP" >&5
 $as_echo "$V_PCAP" >&6; }
 
+
 #
 # Do capture-mechanism-dependent tests.
 #
@@ -5895,15 +6099,30 @@
 	;;
 
 dag)
+	#
+	# --with-pcap=dag is the only way to get here, and it means
+	# "DAG support but nothing else"
+	#
 	V_DEFS="$V_DEFS -DDAG_ONLY"
+	xxx_only=yes
 	;;
 
 septel)
+	#
+	# --with-pcap=septel is the only way to get here, and it means
+	# "Septel support but nothing else"
+	#
 	V_DEFS="$V_DEFS -DSEPTEL_ONLY"
+	xxx_only=yes
 	;;
 
 snf)
+	#
+	# --with-pcap=snf is the only way to get here, and it means
+	# "SNF support but nothing else"
+	#
 	V_DEFS="$V_DEFS -DSNF_ONLY"
+	xxx_only=yes
 	;;
 
 null)
@@ -5914,14 +6133,8 @@
 	;;
 esac
 
-if test "$V_PCAP" = null
+if test "$V_PCAP" != null
 then
-	#
-	# We can't capture, so we can't open any capture
-	# devices, so we won't return any interfaces.
-	#
-	V_FINDALLDEVS=null
-else
 	ac_fn_c_check_func "$LINENO" "getifaddrs" "ac_cv_func_getifaddrs"
 if test "x$ac_cv_func_getifaddrs" = xyes; then :
 
@@ -5936,7 +6149,7 @@
 		    # We have the header, so we use "getifaddrs()" to
 		    # get the list of interfaces.
 		    #
-		    V_FINDALLDEVS=getad
+		    V_FINDALLDEVS=fad-getad.c
 
 else
 
@@ -6004,9 +6217,9 @@
 			{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lbl_have_siocglifconf" >&5
 $as_echo "$ac_cv_lbl_have_siocglifconf" >&6; }
 			if test $ac_cv_lbl_have_siocglifconf = yes ; then
-				V_FINDALLDEVS=glifc
+				V_FINDALLDEVS=fad-glifc.c
 			else
-				V_FINDALLDEVS=gifc
+				V_FINDALLDEVS=fad-gifc.c
 			fi
 			;;
 
@@ -6017,7 +6230,7 @@
 			# another mechanism, and we should be using that
 			# instead.)
 			#
-			V_FINDALLDEVS=gifc
+			V_FINDALLDEVS=fad-gifc.c
 			;;
 		esac
 fi
@@ -6136,10 +6349,20 @@
 
 else
 
-	#
-	# Use DAG API if present, otherwise don't
-	#
-	want_dag=ifpresent
+	if test "$V_PCAP" = dag; then
+		# User requested DAG-only libpcap, so we'd better have
+		# the DAG API.
+		want_dag=yes
+	elif test "xxx_only" = yes; then
+		# User requested something-else-only pcap, so they don't
+		# want DAG support.
+		want_dag=no
+	else
+		#
+		# Use DAG API if present, otherwise don't
+		#
+		want_dag=ifpresent
+	fi
 
 fi
 
@@ -6166,28 +6389,6 @@
 fi
 
 
-case "$V_PCAP" in
-linux|bpf|dag)
-	#
-	# We support the DAG API if we're on Linux or BSD, or if we're
-	# building a DAG-only libpcap.
-	#
-	;;
-*)
-	#
-	# If the user explicitly requested DAG, tell them it's not
-	# supported.
-	#
-	# If they expressed no preference, don't include it.
-	#
-	if test $want_dag = yes; then
-		as_fn_error $? "DAG support is only available with 'linux' 'bpf' and 'dag' packet capture types" "$LINENO" 5
-	elif test $want_dag = yes; then
-		want_dag=no
-	fi
-	;;
-esac
-
 ac_cv_lbl_dag_api=no
 if test "$want_dag" != no; then
 
@@ -6196,7 +6397,7 @@
 
 	# If necessary, set default paths for DAG API headers and libraries.
 	if test -z "$dag_root"; then
-	    dag_root=/usr/local
+		dag_root=/usr/local
 	fi
 
 	if test -z "$dag_include_dir"; then
@@ -6204,33 +6405,33 @@
 	fi
 
 	if test -z "$dag_lib_dir"; then
-	    dag_lib_dir="$dag_root/lib"
+		dag_lib_dir="$dag_root/lib"
 	fi
 
 	if test -z "$dag_tools_dir"; then
-	    dag_tools_dir="$dag_root/tools"
+		dag_tools_dir="$dag_root/tools"
 	fi
 
 	if test -r $dag_include_dir/dagapi.h; then
 		ac_cv_lbl_dag_api=yes
 	fi
-	{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lbl_dag_api ($dag_include_dir)" >&5
-$as_echo "$ac_cv_lbl_dag_api ($dag_include_dir)" >&6; }
-fi
 
-if test $ac_cv_lbl_dag_api = yes; then
-	V_INCLS="$V_INCLS -I$dag_include_dir"
+	if test "$ac_cv_lbl_dag_api" = yes; then
+		{ $as_echo "$as_me:${as_lineno-$LINENO}: result: yes ($dag_include_dir)" >&5
+$as_echo "yes ($dag_include_dir)" >&6; }
 
-	if test $V_PCAP != dag ; then
-		 SSRC="pcap-dag.c"
-	fi
+		V_INCLS="$V_INCLS -I$dag_include_dir"
 
-	# See if we can find a general version string.
-	# Don't need to save and restore LIBS to prevent -ldag being
-	# included if there's a found-action (arg 3).
-	saved_ldflags=$LDFLAGS
-	LDFLAGS="-L$dag_lib_dir"
-	{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for dag_attach_stream in -ldag" >&5
+		if test $V_PCAP != dag ; then
+			 SSRC="$SSRC pcap-dag.c"
+		fi
+
+		# See if we can find a general version string.
+		# Don't need to save and restore LIBS to prevent -ldag being
+		# included if there's a found-action (arg 3).
+		saved_ldflags=$LDFLAGS
+		LDFLAGS="-L$dag_lib_dir"
+		{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for dag_attach_stream in -ldag" >&5
 $as_echo_n "checking for dag_attach_stream in -ldag... " >&6; }
 if ${ac_cv_lib_dag_dag_attach_stream+:} false; then :
   $as_echo_n "(cached) " >&6
@@ -6272,7 +6473,7 @@
   dag_streams="0"
 fi
 
-	{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for dag_get_erf_types in -ldag" >&5
+		{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for dag_get_erf_types in -ldag" >&5
 $as_echo_n "checking for dag_get_erf_types in -ldag... " >&6; }
 if ${ac_cv_lib_dag_dag_get_erf_types+:} false; then :
   $as_echo_n "(cached) " >&6
@@ -6315,7 +6516,7 @@
 
 fi
 
-	{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for dag_get_stream_erf_types in -ldag" >&5
+		{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for dag_get_stream_erf_types in -ldag" >&5
 $as_echo_n "checking for dag_get_stream_erf_types in -ldag... " >&6; }
 if ${ac_cv_lib_dag_dag_get_stream_erf_types+:} false; then :
   $as_echo_n "(cached) " >&6
@@ -6359,16 +6560,16 @@
 fi
 
 
-	LDFLAGS=$saved_ldflags
+		LDFLAGS=$saved_ldflags
 
-	if test "$dag_streams" = 1; then
+		if test "$dag_streams" = 1; then
 
 $as_echo "#define HAVE_DAG_STREAMS_API 1" >>confdefs.h
 
-		LIBS="$LIBS -ldag"
-		LDFLAGS="$LDFLAGS -L$dag_lib_dir"
+			LIBS="$LIBS -ldag"
+			LDFLAGS="$LDFLAGS -L$dag_lib_dir"
 
-		{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for vdag_set_device_info in -lvdag" >&5
+			{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for vdag_set_device_info in -lvdag" >&5
 $as_echo_n "checking for vdag_set_device_info in -lvdag... " >&6; }
 if ${ac_cv_lib_vdag_vdag_set_device_info+:} false; then :
   $as_echo_n "(cached) " >&6
@@ -6410,38 +6611,32 @@
   ac_dag_have_vdag="0"
 fi
 
-		if test "$ac_dag_have_vdag" = 1; then
+			if test "$ac_dag_have_vdag" = 1; then
 
 $as_echo "#define HAVE_DAG_VDAG 1" >>confdefs.h
 
-			LIBS="$LIBS -lpthread"
+				LIBS="$LIBS -lpthread"
+			fi
 		fi
-	fi
 
 
 $as_echo "#define HAVE_DAG_API 1" >>confdefs.h
 
-fi
-
-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether we have the DAG API" >&5
-$as_echo_n "checking whether we have the DAG API... " >&6; }
-
-if test $ac_cv_lbl_dag_api = no; then
-	{ $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+	else
+		{ $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
 $as_echo "no" >&6; }
-	if test "$want_dag" = yes; then
-        	# User wanted DAG support but we couldn't find it.
-		as_fn_error $? "DAG API requested, but not found at $dag_root: use --without-dag" "$LINENO" 5
-	fi
 
-	if test "$V_PCAP" = dag; then
-		# User requested "dag" capture type but the DAG API wasn't
-		# found.
-		as_fn_error $? "Specifying the capture type as \"dag\" requires the DAG API to be present; use the --with-dag options to specify the location. (Try \"./configure --help\" for more information.)" "$LINENO" 5
+		if test "$V_PCAP" = dag; then
+			# User requested "dag" capture type but we couldn't
+			# find the DAG API support.
+			as_fn_error $? "DAG support requested with --with-pcap=dag, but the DAG headers weren't found at $dag_include_dir: make sure the DAG support is installed, specify a different path or paths if necessary, or don't request DAG support" "$LINENO" 5
+		fi
+
+		if test "$want_dag" = yes; then
+	        	# User wanted DAG support but we couldn't find it.
+			as_fn_error $? "DAG support requested with --with-dag, but the DAG headers weren't found at $dag_include_dir: make sure the DAG support is installed, specify a different path or paths if necessary, or don't request DAG support" "$LINENO" 5
+		fi
 	fi
-else
-	{ $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
-$as_echo "yes" >&6; }
 fi
 
 
@@ -6462,41 +6657,31 @@
 
 else
 
-	#
-	# Use Septel API if present, otherwise don't
-	#
-	want_septel=ifpresent
-	septel_root=./../septel
+	if test "$V_PCAP" = septel; then
+		# User requested Septel-only libpcap, so we'd better have
+		# the Septel API.
+		want_septel=yes
+	elif test "xxx_only" = yes; then
+		# User requested something-else-only pcap, so they don't
+		# want Septel support.
+		want_septel=no
+	else
+		#
+		# Use Septel API if present, otherwise don't
+		#
+		want_septel=ifpresent
+	fi
 
 fi
 
+
 ac_cv_lbl_septel_api=no
-case "$V_PCAP" in
-linux|septel)
-	#
-	# We support the Septel API if we're on Linux, or if we're building
-	# a Septel-only libpcap.
-	#
-	;;
-*)
-	#
-	# If the user explicitly requested Septel, tell them it's not
-	# supported.
-	#
-	# If they expressed no preference, don't include it.
-	#
-	if test $want_septel = yes; then
-		as_fn_error $? "Septel support only available with 'linux' and 'septel' packet capture types" "$LINENO" 5
-	elif test $want_septel = yes; then
-		want_septel=no
-	fi
-	;;
-esac
-
 if test "$with_septel" != no; then
-	{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether we have Septel API" >&5
-$as_echo_n "checking whether we have Septel API... " >&6; }
 
+	{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether we have Septel API headers" >&5
+$as_echo_n "checking whether we have Septel API headers... " >&6; }
+
+	# If necessary, set default paths for Septel API headers and libraries.
 	if test -z "$septel_root"; then
 		septel_root=$srcdir/../septel
 	fi
@@ -6504,33 +6689,40 @@
 	septel_tools_dir="$septel_root"
 	septel_include_dir="$septel_root/INC"
 
-	ac_cv_lbl_septel_api=no
 	if test -r "$septel_include_dir/msg.h"; then
+		ac_cv_lbl_septel_api=yes
+	fi
+
+	if test "$ac_cv_lbl_septel_api" = yes; then
+		{ $as_echo "$as_me:${as_lineno-$LINENO}: result: yes ($septel_include_dir)" >&5
+$as_echo "yes ($septel_include_dir)" >&6; }
+
 		V_INCLS="$V_INCLS -I$septel_include_dir"
 		ADDLOBJS="$ADDLOBJS $septel_tools_dir/asciibin.o $septel_tools_dir/bit2byte.o $septel_tools_dir/confirm.o $septel_tools_dir/fmtmsg.o $septel_tools_dir/gct_unix.o $septel_tools_dir/hqueue.o $septel_tools_dir/ident.o $septel_tools_dir/mem.o $septel_tools_dir/pack.o $septel_tools_dir/parse.o $septel_tools_dir/pool.o $septel_tools_dir/sdlsig.o $septel_tools_dir/strtonum.o $septel_tools_dir/timer.o $septel_tools_dir/trace.o"
 		ADDLARCHIVEOBJS="$ADDLARCHIVEOBJS $septel_tools_dir/asciibin.o $septel_tools_dir/bit2byte.o $septel_tools_dir/confirm.o $septel_tools_dir/fmtmsg.o $septel_tools_dir/gct_unix.o $septel_tools_dir/hqueue.o $septel_tools_dir/ident.o $septel_tools_dir/mem.o $septel_tools_dir/pack.o $septel_tools_dir/parse.o $septel_tools_dir/pool.o $septel_tools_dir/sdlsig.o $septel_tools_dir/strtonum.o $septel_tools_dir/timer.o $septel_tools_dir/trace.o"
 
 		if test "$V_PCAP" != septel ; then
-			 SSRC="pcap-septel.c"
+			 SSRC="$SSRC pcap-septel.c"
 		fi
-		ac_cv_lbl_septel_api=yes
-	fi
 
-	{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lbl_septel_api" >&5
-$as_echo "$ac_cv_lbl_septel_api" >&6; }
-	if test $ac_cv_lbl_septel_api = no; then
-		if test "$want_septel" = yes; then
-			as_fn_error $? "Septel API not found under directory $septel_root; use --without-septel" "$LINENO" 5
-		fi
-	else
 
 $as_echo "#define HAVE_SEPTEL_API 1" >>confdefs.h
 
-	fi
-fi
+	else
+		{ $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
 
-if test "$V_PCAP" = septel -a "$ac_cv_lbl_septel_api" = no; then
-	as_fn_error $? "Specifying the capture type as 'septel' requires the Septel API to be present; use --with-septel=DIR" "$LINENO" 5
+		if test "$V_PCAP" = septel; then
+			# User requested "septel" capture type but
+			# we couldn't find the Septel API support.
+			as_fn_error $? "Septel support requested with --with-pcap=septel, but the Septel headers weren't found at $septel_include_dir: make sure the Septel support is installed, specify a different path or paths if necessary, or don't request Septel support" "$LINENO" 5
+		fi
+
+		if test "$want_septel" = yes; then
+	        	# User wanted Septel support but we couldn't find it.
+			as_fn_error $? "Septel support requested with --with-septel, but the Septel headers weren't found at $septel_include_dir: make sure the Septel support is installed, specify a different path or paths if necessary, or don't request Septel support" "$LINENO" 5
+		fi
+	fi
 fi
 
 # Check for Myricom SNF support.
@@ -6544,7 +6736,7 @@
 		want_snf=no
 	elif test "$withval" = yes
 	then
-		# User wants SNF support but hasn't specific a directory.
+		# User wants SNF support but hasn't specified a directory.
 		want_snf=yes
 	else
 		# User wants SNF support with a specified directory.
@@ -6554,10 +6746,20 @@
 
 else
 
-	#
-	# Use Sniffer API if present, otherwise don't
-	#
-	want_snf=ifpresent
+	if test "$V_PCAP" = snf; then
+		# User requested Sniffer-only libpcap, so we'd better have
+		# the Sniffer API.
+		want_snf=yes
+	elif test "xxx_only" = yes; then
+		# User requested something-else-only pcap, so they don't
+		# want SNF support.
+		want_snf=no
+	else
+		#
+		# Use Sniffer API if present, otherwise don't
+		#
+		want_snf=ifpresent
+	fi
 
 fi
 
@@ -6584,34 +6786,13 @@
 fi
 
 
-case "$V_PCAP" in
-bpf|linux|snf)
-	#
-	# We support the Sniffer API if we're on BSD, Linux, or if we're
-	# building a Sniffer-only libpcap.
-	#
-	;;
-*)
-	#
-	# If the user explicitly requested Sniffer, tell them it's not
-	# supported.
-	#
-	# If they expressed no preference, don't include it.
-	#
-	if test $want_snf = yes; then
-		as_fn_error $? "Myricom SNF support only available with 'bpf' 'linux' and 'snf' packet capture types" "$LINENO" 5
-	elif test $want_snf = yes; then
-		want_snf=no
-	fi
-	;;
-esac
-
 ac_cv_lbl_snf_api=no
 if test "$with_snf" != no; then
 
 	{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether we have Myricom Sniffer API" >&5
 $as_echo_n "checking whether we have Myricom Sniffer API... " >&6; }
 
+	# If necessary, set default paths for Sniffer headers and libraries.
 	if test -z "$snf_root"; then
 		snf_root=/opt/snf
 	fi
@@ -6625,16 +6806,7 @@
 	fi
 
 	if test -f "$snf_include_dir/snf.h"; then
-		ac_cv_lbl_snf_api=yes
-	fi
-	{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lbl_snf_api ($snf_root)" >&5
-$as_echo "$ac_cv_lbl_snf_api ($snf_root)" >&6; }
-
-	if test $ac_cv_lbl_snf_api = no; then
-		if test "$want_snf" = yes; then
-			as_fn_error $? "SNF API headers not found under $snf_include_dir; use --without-snf" "$LINENO" 5
-		fi
-	else
+		# We found a header; make sure we can link with the library
 		saved_ldflags=$LDFLAGS
 		LDFLAGS="$LDFLAGS -L$snf_lib_dir"
 		{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for snf_init in -lsnf" >&5
@@ -6675,130 +6847,153 @@
 $as_echo "$ac_cv_lib_snf_snf_init" >&6; }
 if test "x$ac_cv_lib_snf_snf_init" = xyes; then :
   ac_cv_lbl_snf_api="yes"
-else
-  ac_cv_lbl_snf_api="no"
 fi
 
 		LDFLAGS="$saved_ldflags"
+		if test "$ac_cv_lbl_snf_api" = no; then
+			as_fn_error $? "SNF API cannot correctly be linked; check config.log" "$LINENO" 5
+		fi
+	fi
 
-		if test $ac_cv_lbl_snf_api = no; then
-			if test "$want_snf" = yes; then
-				as_fn_error $? "SNF API cannot correctly be linked check config.log; use --without-snf" "$LINENO" 5
-			fi
-		else
-			V_INCLS="$V_INCLS -I$snf_include_dir"
-			LIBS="$LIBS -lsnf"
-			LDFLAGS="$LDFLAGS -L$snf_lib_dir"
-			if test "$V_PCAP" != snf ; then
-				SSRC="pcap-snf.c"
-			fi
+	if test "$ac_cv_lbl_snf_api" = yes; then
+		{ $as_echo "$as_me:${as_lineno-$LINENO}: result: yes ($snf_root)" >&5
+$as_echo "yes ($snf_root)" >&6; }
+
+		V_INCLS="$V_INCLS -I$snf_include_dir"
+		LIBS="$LIBS -lsnf"
+		LDFLAGS="$LDFLAGS -L$snf_lib_dir"
+
+		if test "$V_PCAP" != snf ; then
+			SSRC="$SSRC pcap-snf.c"
+		fi
+
 
 $as_echo "#define HAVE_SNF_API 1" >>confdefs.h
 
+	else
+		{ $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+
+		if test "$want_snf" = yes; then
+			# User requested "snf" capture type but
+			# we couldn't find the Sniffer API support.
+			as_fn_error $? "Myricom Sniffer support requested with --with-pcap=snf, but the Sniffer headers weren't found at $snf_include_dir: make sure the Sniffer support is installed, specify a different path or paths if necessary, or don't request Sniffer support" "$LINENO" 5
+		fi
+
+		if test "$want_snf" = yes; then
+			as_fn_error $? "Myricom Sniffer support requested with --with-snf, but the Sniffer headers weren't found at $snf_include_dir: make sure the Sniffer support is installed, specify a different path or paths if necessary, or don't request Sniffer support" "$LINENO" 5
 		fi
 	fi
 fi
 
-if test "$V_PCAP" = snf -a "$ac_cv_lbl_snf_api" = no; then
-	as_fn_error $? "Specifying the capture type as 'snf' requires the Myricom Sniffer API to be present; use --with-snf=DIR" "$LINENO" 5
-fi
+# Check for Riverbed TurboCap support.
 
+# Check whether --with-turbocap was given.
+if test "${with_turbocap+set}" = set; then :
+  withval=$with_turbocap;
+	if test "$withval" = no
+	then
+		# User explicitly doesn't want TurboCap
+		want_turbocap=no
+	elif test "$withval" = yes
+	then
+		# User wants TurboCap support but hasn't specified a directory.
+		want_turbocap=yes
+	else
+		# User wants TurboCap support with a specified directory.
+		want_turbocap=yes
+		turbocap_root=$withval
+	fi
 
-# Check whether --with-flex was given.
-if test "${with_flex+set}" = set; then :
-  withval=$with_flex;
-fi
-
-
-# Check whether --with-bison was given.
-if test "${with_bison+set}" = set; then :
-  withval=$with_bison;
-fi
-
-    if test "$with_flex" = no ; then
-	    V_LEX=lex
-    else
-	    for ac_prog in flex
-do
-  # Extract the first word of "$ac_prog", so it can be a program name with args.
-set dummy $ac_prog; ac_word=$2
-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
-$as_echo_n "checking for $ac_word... " >&6; }
-if ${ac_cv_prog_V_LEX+:} false; then :
-  $as_echo_n "(cached) " >&6
 else
-  if test -n "$V_LEX"; then
-  ac_cv_prog_V_LEX="$V_LEX" # Let the user override the test.
-else
-as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
-for as_dir in $PATH
-do
-  IFS=$as_save_IFS
-  test -z "$as_dir" && as_dir=.
-    for ac_exec_ext in '' $ac_executable_extensions; do
-  if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
-    ac_cv_prog_V_LEX="$ac_prog"
-    $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
-    break 2
-  fi
-done
-  done
-IFS=$as_save_IFS
+
+	if test "xxx_only" = yes; then
+		# User requested something-else-only pcap, so they don't
+		# want TurboCap support.
+		want_turbocap=no
+	else
+		#
+		# Use TurboCap API if present, otherwise don't
+		#
+		want_turbocap=ifpresent
+	fi
 
 fi
+
+
+ac_cv_lbl_turbocap_api=no
+if test "$want_turbocap" != no; then
+
+	{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether TurboCap is supported" >&5
+$as_echo_n "checking whether TurboCap is supported... " >&6; }
+
+	save_CFLAGS="$CFLAGS"
+	save_LIBS="$LIBS"
+	if test ! -z "$turbocap_root"; then
+		TURBOCAP_CFLAGS="-I$turbocap_root/include"
+		TURBOCAP_LIBS="-L$turbocap_root/lib"
+		CFLAGS="$CFLAGS $TURBOCAP_CFLAGS"
+	fi
+
+	cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+
+	    #include <TcApi.h>
+
+int
+main ()
+{
+
+	    TC_INSTANCE a; TC_PORT b; TC_BOARD c;
+	    TC_INSTANCE i;
+	    (void)TcInstanceCreateByName("foo", &i);
+
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+  ac_cv_lbl_turbocap_api=yes
 fi
-V_LEX=$ac_cv_prog_V_LEX
-if test -n "$V_LEX"; then
-  { $as_echo "$as_me:${as_lineno-$LINENO}: result: $V_LEX" >&5
-$as_echo "$V_LEX" >&6; }
-else
-  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+
+	CFLAGS="$save_CFLAGS"
+	if test $ac_cv_lbl_turbocap_api = yes; then
+		{ $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
+$as_echo "yes" >&6; }
+
+		SSRC="$SSRC pcap-tc.c"
+		V_INCLS="$V_INCLS $TURBOCAP_CFLAGS"
+		LIBS="$LIBS $TURBOCAP_LIBS -lTcApi -lpthread -lstdc++"
+
+
+$as_echo "#define HAVE_TC_API 1" >>confdefs.h
+
+	else
+		{ $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
 $as_echo "no" >&6; }
-fi
 
-
-  test -n "$V_LEX" && break
-done
-test -n "$V_LEX" || V_LEX="lex"
-
-    fi
-    if test "$V_LEX" = flex ; then
-	    # The -V flag was added in 2.4
-	    { $as_echo "$as_me:${as_lineno-$LINENO}: checking for flex 2.4 or higher" >&5
-$as_echo_n "checking for flex 2.4 or higher... " >&6; }
-	    if ${ac_cv_lbl_flex_v24+:} false; then :
-  $as_echo_n "(cached) " >&6
-else
-  if flex -V >/dev/null 2>&1; then
-			ac_cv_lbl_flex_v24=yes
-		else
-			ac_cv_lbl_flex_v24=no
+		if test "$want_turbocap" = yes; then
+	        	# User wanted Turbo support but we couldn't find it.
+			as_fn_error $? "TurboCap support requested with --with-turbocap, but the TurboCap headers weren't found: make sure the TurboCap support is installed or don't request TurboCap support" "$LINENO" 5
 		fi
+	fi
 fi
 
-	    { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lbl_flex_v24" >&5
-$as_echo "$ac_cv_lbl_flex_v24" >&6; }
-	    if test $ac_cv_lbl_flex_v24 = no ; then
-		    s="2.4 or higher required"
-		    { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: ignoring obsolete flex executable ($s)" >&5
-$as_echo "$as_me: WARNING: ignoring obsolete flex executable ($s)" >&2;}
-		    V_LEX=lex
-	    fi
-    fi
-    if test "$with_bison" = no ; then
-	    V_YACC=yacc
-    else
-	    for ac_prog in bison
+#
+# Look for {f}lex.
+#
+for ac_prog in flex lex
 do
   # Extract the first word of "$ac_prog", so it can be a program name with args.
 set dummy $ac_prog; ac_word=$2
 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
 $as_echo_n "checking for $ac_word... " >&6; }
-if ${ac_cv_prog_V_YACC+:} false; then :
+if ${ac_cv_prog_LEX+:} false; then :
   $as_echo_n "(cached) " >&6
 else
-  if test -n "$V_YACC"; then
-  ac_cv_prog_V_YACC="$V_YACC" # Let the user override the test.
+  if test -n "$LEX"; then
+  ac_cv_prog_LEX="$LEX" # Let the user override the test.
 else
 as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
 for as_dir in $PATH
@@ -6807,7 +7002,7 @@
   test -z "$as_dir" && as_dir=.
     for ac_exec_ext in '' $ac_executable_extensions; do
   if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
-    ac_cv_prog_V_YACC="$ac_prog"
+    ac_cv_prog_LEX="$ac_prog"
     $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
     break 2
   fi
@@ -6817,61 +7012,230 @@
 
 fi
 fi
-V_YACC=$ac_cv_prog_V_YACC
-if test -n "$V_YACC"; then
-  { $as_echo "$as_me:${as_lineno-$LINENO}: result: $V_YACC" >&5
-$as_echo "$V_YACC" >&6; }
+LEX=$ac_cv_prog_LEX
+if test -n "$LEX"; then
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: $LEX" >&5
+$as_echo "$LEX" >&6; }
 else
   { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
 $as_echo "no" >&6; }
 fi
 
 
-  test -n "$V_YACC" && break
+  test -n "$LEX" && break
 done
-test -n "$V_YACC" || V_YACC="yacc"
+test -n "$LEX" || LEX=":"
 
-    fi
-    if test "$V_YACC" = bison ; then
-	    V_YACC="$V_YACC -y"
-    fi
-    if test "$V_LEX" != lex -a "$V_YACC" = yacc -o "$V_LEX" = lex -a "$V_YACC" != yacc ; then
-	    { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: don't have both flex and bison; reverting to lex/yacc" >&5
-$as_echo "$as_me: WARNING: don't have both flex and bison; reverting to lex/yacc" >&2;}
-	    V_LEX=lex
-	    V_YACC=yacc
-    fi
-    if test "$V_LEX" = flex -a -n "pcap_" ; then
-	    V_LEX="$V_LEX -Ppcap_"
-	    V_YACC="$V_YACC -p pcap_"
-    else
+if test "x$LEX" != "x:"; then
+  cat >conftest.l <<_ACEOF
+%%
+a { ECHO; }
+b { REJECT; }
+c { yymore (); }
+d { yyless (1); }
+e { /* IRIX 6.5 flex 2.5.4 underquotes its yyless argument.  */
+    yyless ((input () != 0)); }
+f { unput (yytext[0]); }
+. { BEGIN INITIAL; }
+%%
+#ifdef YYTEXT_POINTER
+extern char *yytext;
+#endif
+int
+main (void)
+{
+  return ! yylex () + ! yywrap ();
+}
+_ACEOF
+{ { ac_try="$LEX conftest.l"
+case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\""
+$as_echo "$ac_try_echo"; } >&5
+  (eval "$LEX conftest.l") 2>&5
+  ac_status=$?
+  $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+  test $ac_status = 0; }
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking lex output file root" >&5
+$as_echo_n "checking lex output file root... " >&6; }
+if ${ac_cv_prog_lex_root+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
 
-$as_echo "#define NEED_YYPARSE_WRAPPER 1" >>confdefs.h
+if test -f lex.yy.c; then
+  ac_cv_prog_lex_root=lex.yy
+elif test -f lexyy.c; then
+  ac_cv_prog_lex_root=lexyy
+else
+  as_fn_error $? "cannot find output from $LEX; giving up" "$LINENO" 5
+fi
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_prog_lex_root" >&5
+$as_echo "$ac_cv_prog_lex_root" >&6; }
+LEX_OUTPUT_ROOT=$ac_cv_prog_lex_root
 
-    fi
-if test "$V_LEX" = lex ; then
-# Some versions of lex can't handle the definitions section of scanner.l .
-# Try lexing it and complain if it can't deal.
-	{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for capable lex" >&5
+if test -z "${LEXLIB+set}"; then
+  { $as_echo "$as_me:${as_lineno-$LINENO}: checking lex library" >&5
+$as_echo_n "checking lex library... " >&6; }
+if ${ac_cv_lib_lex+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+
+    ac_save_LIBS=$LIBS
+    ac_cv_lib_lex='none needed'
+    for ac_lib in '' -lfl -ll; do
+      LIBS="$ac_lib $ac_save_LIBS"
+      cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+`cat $LEX_OUTPUT_ROOT.c`
+_ACEOF
+if ac_fn_c_try_link "$LINENO"; then :
+  ac_cv_lib_lex=$ac_lib
+fi
+rm -f core conftest.err conftest.$ac_objext \
+    conftest$ac_exeext conftest.$ac_ext
+      test "$ac_cv_lib_lex" != 'none needed' && break
+    done
+    LIBS=$ac_save_LIBS
+
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_lex" >&5
+$as_echo "$ac_cv_lib_lex" >&6; }
+  test "$ac_cv_lib_lex" != 'none needed' && LEXLIB=$ac_cv_lib_lex
+fi
+
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether yytext is a pointer" >&5
+$as_echo_n "checking whether yytext is a pointer... " >&6; }
+if ${ac_cv_prog_lex_yytext_pointer+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  # POSIX says lex can declare yytext either as a pointer or an array; the
+# default is implementation-dependent.  Figure out which it is, since
+# not all implementations provide the %pointer and %array declarations.
+ac_cv_prog_lex_yytext_pointer=no
+ac_save_LIBS=$LIBS
+LIBS="$LEXLIB $ac_save_LIBS"
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+
+  #define YYTEXT_POINTER 1
+`cat $LEX_OUTPUT_ROOT.c`
+_ACEOF
+if ac_fn_c_try_link "$LINENO"; then :
+  ac_cv_prog_lex_yytext_pointer=yes
+fi
+rm -f core conftest.err conftest.$ac_objext \
+    conftest$ac_exeext conftest.$ac_ext
+LIBS=$ac_save_LIBS
+
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_prog_lex_yytext_pointer" >&5
+$as_echo "$ac_cv_prog_lex_yytext_pointer" >&6; }
+if test $ac_cv_prog_lex_yytext_pointer = yes; then
+
+$as_echo "#define YYTEXT_POINTER 1" >>confdefs.h
+
+fi
+rm -f conftest.l $LEX_OUTPUT_ROOT.c
+
+fi
+if test "$LEX" = ":"; then
+	as_fn_error $? "Neither flex nor lex was found." "$LINENO" 5
+fi
+
+#
+# Make sure {f}lex supports the -P, --header-file, and --nounput flags
+# and supports processing our scanner.l.
+#
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for capable lex" >&5
 $as_echo_n "checking for capable lex... " >&6; }
 if ${tcpdump_cv_capable_lex+:} false; then :
   $as_echo_n "(cached) " >&6
 else
-  if lex -t scanner.l > /dev/null 2>&1; then
-			tcpdump_cv_capable_lex=yes
-		else
-			tcpdump_cv_capable_lex=insufficient
-		fi
+  if $LEX -P pcap_ --header-file=/dev/null --nounput -t $srcdir/scanner.l > /dev/null 2>&1; then
+	    tcpdump_cv_capable_lex=yes
+	else
+	    tcpdump_cv_capable_lex=insufficient
+	fi
 fi
 { $as_echo "$as_me:${as_lineno-$LINENO}: result: $tcpdump_cv_capable_lex" >&5
 $as_echo "$tcpdump_cv_capable_lex" >&6; }
-	if test $tcpdump_cv_capable_lex = insufficient ; then
-		as_fn_error $? "Your operating system's lex is insufficient to compile
- libpcap.  flex is a lex replacement that has many advantages, including
- being able to compile libpcap.  For more information, see
- http://www.gnu.org/software/flex/flex.html ." "$LINENO" 5
+if test $tcpdump_cv_capable_lex = insufficient ; then
+	as_fn_error $? "$LEX is insufficient to compile libpcap.
+ libpcap requires Flex 2.5.31 or later, or a compatible version of lex." "$LINENO" 5
+fi
+
+#
+# Look for yacc/bison/byacc.
+#
+for ac_prog in 'bison -y' byacc
+do
+  # Extract the first word of "$ac_prog", so it can be a program name with args.
+set dummy $ac_prog; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if ${ac_cv_prog_YACC+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  if test -n "$YACC"; then
+  ac_cv_prog_YACC="$YACC" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+    for ac_exec_ext in '' $ac_executable_extensions; do
+  if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+    ac_cv_prog_YACC="$ac_prog"
+    $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+    break 2
+  fi
+done
+  done
+IFS=$as_save_IFS
+
+fi
+fi
+YACC=$ac_cv_prog_YACC
+if test -n "$YACC"; then
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: $YACC" >&5
+$as_echo "$YACC" >&6; }
+else
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+
+  test -n "$YACC" && break
+done
+test -n "$YACC" || YACC="yacc"
+
+
+#
+# Make sure it supports the -p flag and supports processing our
+# grammar.y.
+#
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for capable yacc/bison" >&5
+$as_echo_n "checking for capable yacc/bison... " >&6; }
+if ${tcpdump_cv_capable_yacc+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  if $YACC -p pcap_ -o /dev/null $srcdir/grammar.y >/dev/null 2>&1; then
+	    tcpdump_cv_capable_yacc=yes
+	else
+	    tcpdump_cv_capable_yacc=insufficient
 	fi
 fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $tcpdump_cv_capable_yacc" >&5
+$as_echo "$tcpdump_cv_capable_yacc" >&6; }
+if test $tcpdump_cv_capable_yacc = insufficient ; then
+	as_fn_error $? "$YACC is insufficient to compile libpcap.
+ libpcap requires Bison, Berkeley YACC, or another YACC compatible with them." "$LINENO" 5
+fi
 
 #
 # Assume, by default, no support for shared libraries and V7/BSD convention
@@ -7402,7 +7766,18 @@
 	{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether the compiler supports the -Wall option" >&5
 $as_echo_n "checking whether the compiler supports the -Wall option... " >&6; }
 	save_CFLAGS="$CFLAGS"
-	CFLAGS="$CFLAGS $ac_lbl_unknown_warning_option_error -Wall"
+	if expr "x-Wall" : "x-W.*" >/dev/null
+	then
+	    CFLAGS="$CFLAGS $ac_lbl_unknown_warning_option_error -Wall"
+	elif expr "x-Wall" : "x-f.*" >/dev/null
+	then
+	    CFLAGS="$CFLAGS -Werror -Wall"
+	elif expr "x-Wall" : "x-m.*" >/dev/null
+	then
+	    CFLAGS="$CFLAGS -Werror -Wall"
+	else
+	    CFLAGS="$CFLAGS -Wall"
+	fi
 	cat confdefs.h - <<_ACEOF >conftest.$ac_ext
 /* end confdefs.h.  */
 
@@ -7431,10 +7806,64 @@
 rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
 
 
+	{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether the compiler supports the -Wsign-compare option" >&5
+$as_echo_n "checking whether the compiler supports the -Wsign-compare option... " >&6; }
+	save_CFLAGS="$CFLAGS"
+	if expr "x-Wsign-compare" : "x-W.*" >/dev/null
+	then
+	    CFLAGS="$CFLAGS $ac_lbl_unknown_warning_option_error -Wsign-compare"
+	elif expr "x-Wsign-compare" : "x-f.*" >/dev/null
+	then
+	    CFLAGS="$CFLAGS -Werror -Wsign-compare"
+	elif expr "x-Wsign-compare" : "x-m.*" >/dev/null
+	then
+	    CFLAGS="$CFLAGS -Werror -Wsign-compare"
+	else
+	    CFLAGS="$CFLAGS -Wsign-compare"
+	fi
+	cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+
+int
+main ()
+{
+return 0
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+
+		{ $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
+$as_echo "yes" >&6; }
+		CFLAGS="$save_CFLAGS"
+		V_CCOPT="$V_CCOPT -Wsign-compare"
+
+else
+
+		{ $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+		CFLAGS="$save_CFLAGS"
+
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+
+
 	{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether the compiler supports the -Wmissing-prototypes option" >&5
 $as_echo_n "checking whether the compiler supports the -Wmissing-prototypes option... " >&6; }
 	save_CFLAGS="$CFLAGS"
-	CFLAGS="$CFLAGS $ac_lbl_unknown_warning_option_error -Wmissing-prototypes"
+	if expr "x-Wmissing-prototypes" : "x-W.*" >/dev/null
+	then
+	    CFLAGS="$CFLAGS $ac_lbl_unknown_warning_option_error -Wmissing-prototypes"
+	elif expr "x-Wmissing-prototypes" : "x-f.*" >/dev/null
+	then
+	    CFLAGS="$CFLAGS -Werror -Wmissing-prototypes"
+	elif expr "x-Wmissing-prototypes" : "x-m.*" >/dev/null
+	then
+	    CFLAGS="$CFLAGS -Werror -Wmissing-prototypes"
+	else
+	    CFLAGS="$CFLAGS -Wmissing-prototypes"
+	fi
 	cat confdefs.h - <<_ACEOF >conftest.$ac_ext
 /* end confdefs.h.  */
 
@@ -7466,7 +7895,18 @@
 	{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether the compiler supports the -Wstrict-prototypes option" >&5
 $as_echo_n "checking whether the compiler supports the -Wstrict-prototypes option... " >&6; }
 	save_CFLAGS="$CFLAGS"
-	CFLAGS="$CFLAGS $ac_lbl_unknown_warning_option_error -Wstrict-prototypes"
+	if expr "x-Wstrict-prototypes" : "x-W.*" >/dev/null
+	then
+	    CFLAGS="$CFLAGS $ac_lbl_unknown_warning_option_error -Wstrict-prototypes"
+	elif expr "x-Wstrict-prototypes" : "x-f.*" >/dev/null
+	then
+	    CFLAGS="$CFLAGS -Werror -Wstrict-prototypes"
+	elif expr "x-Wstrict-prototypes" : "x-m.*" >/dev/null
+	then
+	    CFLAGS="$CFLAGS -Werror -Wstrict-prototypes"
+	else
+	    CFLAGS="$CFLAGS -Wstrict-prototypes"
+	fi
 	cat confdefs.h - <<_ACEOF >conftest.$ac_ext
 /* end confdefs.h.  */
 
@@ -7494,6 +7934,135 @@
 fi
 rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
 
+
+	{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether the compiler supports the -Wshadow option" >&5
+$as_echo_n "checking whether the compiler supports the -Wshadow option... " >&6; }
+	save_CFLAGS="$CFLAGS"
+	if expr "x-Wshadow" : "x-W.*" >/dev/null
+	then
+	    CFLAGS="$CFLAGS $ac_lbl_unknown_warning_option_error -Wshadow"
+	elif expr "x-Wshadow" : "x-f.*" >/dev/null
+	then
+	    CFLAGS="$CFLAGS -Werror -Wshadow"
+	elif expr "x-Wshadow" : "x-m.*" >/dev/null
+	then
+	    CFLAGS="$CFLAGS -Werror -Wshadow"
+	else
+	    CFLAGS="$CFLAGS -Wshadow"
+	fi
+	cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+
+int
+main ()
+{
+return 0
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+
+		{ $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
+$as_echo "yes" >&6; }
+		CFLAGS="$save_CFLAGS"
+		V_CCOPT="$V_CCOPT -Wshadow"
+
+else
+
+		{ $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+		CFLAGS="$save_CFLAGS"
+
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+
+
+	{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether the compiler supports the -Wdeclaration-after-statement option" >&5
+$as_echo_n "checking whether the compiler supports the -Wdeclaration-after-statement option... " >&6; }
+	save_CFLAGS="$CFLAGS"
+	if expr "x-Wdeclaration-after-statement" : "x-W.*" >/dev/null
+	then
+	    CFLAGS="$CFLAGS $ac_lbl_unknown_warning_option_error -Wdeclaration-after-statement"
+	elif expr "x-Wdeclaration-after-statement" : "x-f.*" >/dev/null
+	then
+	    CFLAGS="$CFLAGS -Werror -Wdeclaration-after-statement"
+	elif expr "x-Wdeclaration-after-statement" : "x-m.*" >/dev/null
+	then
+	    CFLAGS="$CFLAGS -Werror -Wdeclaration-after-statement"
+	else
+	    CFLAGS="$CFLAGS -Wdeclaration-after-statement"
+	fi
+	cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+
+int
+main ()
+{
+return 0
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+
+		{ $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
+$as_echo "yes" >&6; }
+		CFLAGS="$save_CFLAGS"
+		V_CCOPT="$V_CCOPT -Wdeclaration-after-statement"
+
+else
+
+		{ $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+		CFLAGS="$save_CFLAGS"
+
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+
+
+	{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether the compiler supports the -Wused-but-marked-unused option" >&5
+$as_echo_n "checking whether the compiler supports the -Wused-but-marked-unused option... " >&6; }
+	save_CFLAGS="$CFLAGS"
+	if expr "x-Wused-but-marked-unused" : "x-W.*" >/dev/null
+	then
+	    CFLAGS="$CFLAGS $ac_lbl_unknown_warning_option_error -Wused-but-marked-unused"
+	elif expr "x-Wused-but-marked-unused" : "x-f.*" >/dev/null
+	then
+	    CFLAGS="$CFLAGS -Werror -Wused-but-marked-unused"
+	elif expr "x-Wused-but-marked-unused" : "x-m.*" >/dev/null
+	then
+	    CFLAGS="$CFLAGS -Werror -Wused-but-marked-unused"
+	else
+	    CFLAGS="$CFLAGS -Wused-but-marked-unused"
+	fi
+	cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+
+int
+main ()
+{
+return 0
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+
+		{ $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
+$as_echo "yes" >&6; }
+		CFLAGS="$save_CFLAGS"
+		V_CCOPT="$V_CCOPT -Wused-but-marked-unused"
+
+else
+
+		{ $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+		CFLAGS="$save_CFLAGS"
+
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+
 	    fi
 
 	{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether the compiler supports generating dependencies" >&5
@@ -7813,14 +8382,6 @@
 
     fi
 
-#
-# Makefile.in includes rules to generate version.h, so we assume
-# that it will be generated if autoconf is used.
-#
-
-$as_echo "#define HAVE_VERSION_H 1" >>confdefs.h
-
-
 rm -f net
 ln -s ${srcdir}/bpf/net net
 
@@ -7850,6 +8411,12 @@
 fi
 
 
+if test "xxx_only" = yes; then
+	# User requested something-else-only pcap, so they don't
+	# want USB support.
+	enable_usb=no
+fi
+
 if test "x$enable_usb" != "xno" ; then
       { $as_echo "$as_me:${as_lineno-$LINENO}: checking for USB sniffing support" >&5
 $as_echo_n "checking for USB sniffing support... " >&6; }
@@ -7967,6 +8534,15 @@
 	    fi
 	fi
 	;;
+    freebsd*)
+	#
+	# This just uses BPF in FreeBSD 8.4 and later; we don't need
+	# to check for anything special for capturing.
+	#
+	{ $as_echo "$as_me:${as_lineno-$LINENO}: result: yes, in FreeBSD 8.4 and later" >&5
+$as_echo "yes, in FreeBSD 8.4 and later" >&6; }
+	;;
+
     *)
 	{ $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
 $as_echo "no" >&6; }
@@ -7976,23 +8552,24 @@
 
 
 
-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether the platform could support netfilter sniffing" >&5
+if test "xxx_only" != yes; then
+	{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether the platform could support netfilter sniffing" >&5
 $as_echo_n "checking whether the platform could support netfilter sniffing... " >&6; }
-case "$host_os" in
-linux*)
-	{ $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
+	case "$host_os" in
+	linux*)
+		{ $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
 $as_echo "yes" >&6; }
-	#
-	# Life's too short to deal with trying to get this to compile
-	# if you don't get the right types defined with
-	# __KERNEL_STRICT_NAMES getting defined by some other include.
-	#
-	# Check whether the includes Just Work.  If not, don't turn on
-	# netfilter support.
-	#
-	{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether we can compile the netfilter support" >&5
+		#
+		# Life's too short to deal with trying to get this to compile
+		# if you don't get the right types defined with
+		# __KERNEL_STRICT_NAMES getting defined by some other include.
+		#
+		# Check whether the includes Just Work.  If not, don't turn on
+		# netfilter support.
+		#
+		{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether we can compile the netfilter support" >&5
 $as_echo_n "checking whether we can compile the netfilter support... " >&6; }
-	if ${ac_cv_netfilter_can_compile+:} false; then :
+		if ${ac_cv_netfilter_can_compile+:} false; then :
   $as_echo_n "(cached) " >&6
 else
   cat confdefs.h - <<_ACEOF >conftest.$ac_ext
@@ -8024,20 +8601,21 @@
 rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
 fi
 
-	{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_netfilter_can_compile" >&5
+		{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_netfilter_can_compile" >&5
 $as_echo "$ac_cv_netfilter_can_compile" >&6; }
-	if test $ac_cv_netfilter_can_compile = yes ; then
+		if test $ac_cv_netfilter_can_compile = yes ; then
 
 $as_echo "#define PCAP_SUPPORT_NETFILTER 1" >>confdefs.h
 
-	  NETFILTER_SRC=pcap-netfilter-linux.c
-	fi
-	;;
-*)
-	{ $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+		  NETFILTER_SRC=pcap-netfilter-linux.c
+		fi
+		;;
+	*)
+		{ $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
 $as_echo "no" >&6; }
-	;;
-esac
+		;;
+	esac
+fi
 
 
 
@@ -8049,6 +8627,12 @@
 fi
 
 
+if test "xxx_only" = yes; then
+	# User requested something-else-only pcap, so they don't
+	# want Bluetooth support.
+	enable_bluetooth=no
+fi
+
 if test "x$enable_bluetooth" != "xno" ; then
 		case "$host_os" in
 	linux*)
@@ -8170,151 +8754,6 @@
 
 fi
 
-# Check whether --enable-canusb was given.
-if test "${enable_canusb+set}" = set; then :
-  enableval=$enable_canusb;
-else
-  enable_canusb=ifsupportavailable
-fi
-
-
-if test "x$enable_canusb" != "xno" ; then
-		case "$host_os" in
-	linux*|uclinux*)
-		ac_fn_c_check_header_mongrel "$LINENO" "libusb-1.0/libusb.h" "ac_cv_header_libusb_1_0_libusb_h" "$ac_includes_default"
-if test "x$ac_cv_header_libusb_1_0_libusb_h" = xyes; then :
-
-		    { $as_echo "$as_me:${as_lineno-$LINENO}: checking for libusb_init in -lusb-1.0" >&5
-$as_echo_n "checking for libusb_init in -lusb-1.0... " >&6; }
-if ${ac_cv_lib_usb_1_0_libusb_init+:} false; then :
-  $as_echo_n "(cached) " >&6
-else
-  ac_check_lib_save_LIBS=$LIBS
-LIBS="-lusb-1.0 -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 libusb_init ();
-int
-main ()
-{
-return libusb_init ();
-  ;
-  return 0;
-}
-_ACEOF
-if ac_fn_c_try_link "$LINENO"; then :
-  ac_cv_lib_usb_1_0_libusb_init=yes
-else
-  ac_cv_lib_usb_1_0_libusb_init=no
-fi
-rm -f core conftest.err conftest.$ac_objext \
-    conftest$ac_exeext conftest.$ac_ext
-LIBS=$ac_check_lib_save_LIBS
-fi
-{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_usb_1_0_libusb_init" >&5
-$as_echo "$ac_cv_lib_usb_1_0_libusb_init" >&6; }
-if test "x$ac_cv_lib_usb_1_0_libusb_init" = xyes; then :
-
-
-$as_echo "#define PCAP_SUPPORT_CANUSB 1" >>confdefs.h
-
-			CANUSB_SRC=pcap-canusb-linux.c
-			LIBS="-lusb-1.0 -lpthread $LIBS"
-			ac_lbl_has_libusb=yes
-
-else
-  ac_lbl_has_libusb=no
-fi
-
-
-else
-  ac_lbl_has_libusb=no
-
-fi
-
-
-		if test "x$ac_lbl_has_libusb" = "xyes" ; then
-		    { $as_echo "$as_me:${as_lineno-$LINENO}: canusb sniffing is supported" >&5
-$as_echo "$as_me: canusb sniffing is supported" >&6;}
-		else
-		    if test "x$enable_canusb" = "xyes" ; then
-			as_fn_error $? "canusb sniffing is not supported; install libusb1.0 lib devel to enable it" "$LINENO" 5
-		    else
-			{ $as_echo "$as_me:${as_lineno-$LINENO}: canusb sniffing is not supported; install libusb1.0 lib devel to enable it" >&5
-$as_echo "$as_me: canusb sniffing is not supported; install libusb1.0 lib devel to enable it" >&6;}
-		    fi
-		fi
-		;;
-	*)
-		if test "x$enable_canusb" = "xyes" ; then
-		    as_fn_error $? "no canusb support implemented for $host_os" "$LINENO" 5
-		else
-		    { $as_echo "$as_me:${as_lineno-$LINENO}: no canusb support implemented for $host_os" >&5
-$as_echo "$as_me: no canusb support implemented for $host_os" >&6;}
-		fi
-		;;
-	esac
-
-
-fi
-
-# Check whether --enable-can was given.
-if test "${enable_can+set}" = set; then :
-  enableval=$enable_can;
-else
-  enable_can=ifsupportavailable
-fi
-
-
-if test "x$enable_can" != "xno" ; then
-		case "$host_os" in
-	linux*)
-		ac_fn_c_check_header_compile "$LINENO" "linux/can.h" "ac_cv_header_linux_can_h" "#include <sys/socket.h>
-
-"
-if test "x$ac_cv_header_linux_can_h" = xyes; then :
-
-
-$as_echo "#define PCAP_SUPPORT_CAN 1" >>confdefs.h
-
-			    CAN_SRC=pcap-can-linux.c
-			    { $as_echo "$as_me:${as_lineno-$LINENO}: CAN sniffing is supported" >&5
-$as_echo "$as_me: CAN sniffing is supported" >&6;}
-
-else
-
-			    if test "x$enable_can" = "xyes" ; then
-				as_fn_error $? "CAN sniffing is not supported" "$LINENO" 5
-			    else
-				{ $as_echo "$as_me:${as_lineno-$LINENO}: CAN sniffing is not supported" >&5
-$as_echo "$as_me: CAN sniffing is not supported" >&6;}
-			    fi
-
-fi
-
-
-		;;
-	*)
-		if test "x$enable_can" = "xyes" ; then
-		    as_fn_error $? "no CAN sniffing support implemented for $host_os" "$LINENO" 5
-		else
-		    { $as_echo "$as_me:${as_lineno-$LINENO}: no CAN sniffing support implemented for $host_os" >&5
-$as_echo "$as_me: no CAN sniffing support implemented for $host_os" >&6;}
-		fi
-		;;
-	esac
-
-
-fi
-
 # Check whether --enable-dbus was given.
 if test "${enable_dbus+set}" = set; then :
   enableval=$enable_dbus;
@@ -8323,6 +8762,12 @@
 fi
 
 
+if test "xxx_only" = yes; then
+	# User requested something-else-only pcap, so they don't
+	# want D-Bus support.
+	enable_dbus=no
+fi
+
 if test "x$enable_dbus" != "xno"; then
 	if test "x$enable_dbus" = "xyes"; then
 		case "$host_os" in
diff --git a/configure.in b/configure.ac
similarity index 76%
rename from configure.in
rename to configure.ac
index be4b29e..da2f940 100644
--- a/configure.in
+++ b/configure.ac
@@ -104,7 +104,7 @@
 dnl and set "HAVE_SYS_IOCCOM_H" if we have it, otherwise
 dnl "AC_LBL_FIXINCLUDES" wouldn't work on some platforms such as Solaris.
 dnl
-AC_CHECK_HEADERS(sys/ioccom.h sys/sockio.h limits.h paths.h)
+AC_CHECK_HEADERS(sys/ioccom.h sys/select.h sys/sockio.h limits.h)
 AC_CHECK_HEADERS(linux/types.h)
 AC_CHECK_HEADERS(linux/if_packet.h netpacket/packet.h netpacket/if_packet.h)
 AC_CHECK_HEADERS(net/pfvar.h, , , [#include <sys/types.h>
@@ -149,7 +149,7 @@
 fi
 
 case "$host_os" in
-linux*)
+linux*|uclinux*)
 	AC_CHECK_HEADERS(linux/sockios.h linux/if_bonding.h,,,
 	[
 #include <sys/socket.h>
@@ -169,6 +169,13 @@
 	AC_LIBOBJ([snprintf])
 fi
 
+needstrtok_r=no
+AC_CHECK_FUNCS(strtok_r,,
+	[needstrtok_r=yes])
+if test $needstrtok_r = yes; then
+	AC_LIBOBJ([strtok_r])
+fi
+
 #
 # Do this before checking for ether_hostton(), as it's a
 # "gethostbyname() -ish function".
@@ -282,6 +289,13 @@
 AC_MSG_RESULT(${enable_protochain})
 
 #
+# valgrindtest directly uses the native capture mechanism, but
+# only tests with BPF and PF_PACKET sockets; only enable it if
+# we have BPF or PF_PACKET sockets.
+#
+VALGRINDTEST=
+
+#
 # SITA support is mutually exclusive with native capture support;
 # "--with-sita" selects SITA support.
 #
@@ -292,7 +306,6 @@
 		AC_DEFINE(SITA,1,[include ACN support])
 		AC_MSG_NOTICE(Enabling SITA ACN support)
 		V_PCAP=sita
-		V_FINDALLDEVS=sita
 	fi
 ],
 [
@@ -318,8 +331,18 @@
 	#
 	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
@@ -330,6 +353,12 @@
 	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
@@ -341,6 +370,11 @@
 	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
@@ -351,6 +385,7 @@
 	V_PCAP=null
 fi
 AC_MSG_RESULT($V_PCAP)
+AC_SUBST(VALGRINDTEST)
 
 #
 # Do capture-mechanism-dependent tests.
@@ -567,15 +602,30 @@
 	;;
 
 dag)
+	#
+	# --with-pcap=dag is the only way to get here, and it means
+	# "DAG support but nothing else"
+	#
 	V_DEFS="$V_DEFS -DDAG_ONLY"
+	xxx_only=yes
 	;;
 
 septel)
+	#
+	# --with-pcap=septel is the only way to get here, and it means
+	# "Septel support but nothing else"
+	#
 	V_DEFS="$V_DEFS -DSEPTEL_ONLY"
+	xxx_only=yes
 	;;
 
 snf)
+	#
+	# --with-pcap=snf is the only way to get here, and it means
+	# "SNF support but nothing else"
+	#
 	V_DEFS="$V_DEFS -DSNF_ONLY"
+	xxx_only=yes
 	;;
 
 null)
@@ -589,14 +639,8 @@
 dnl if we support capturing.  Don't bother if we don't support
 dnl capturing.
 dnl
-if test "$V_PCAP" = null
+if test "$V_PCAP" != null
 then
-	#
-	# We can't capture, so we can't open any capture
-	# devices, so we won't return any interfaces.
-	#
-	V_FINDALLDEVS=null
-else
 	AC_CHECK_FUNC(getifaddrs,[
 		#
 		# We have "getifaddrs()"; make sure we have <ifaddrs.h>
@@ -607,7 +651,7 @@
 		    # We have the header, so we use "getifaddrs()" to
 		    # get the list of interfaces.
 		    #
-		    V_FINDALLDEVS=getad
+		    V_FINDALLDEVS=fad-getad.c
 		],[
 		    #
 		    # We don't have the header - give up.
@@ -650,9 +694,9 @@
 				ac_cv_lbl_have_siocglifconf=no))
 			AC_MSG_RESULT($ac_cv_lbl_have_siocglifconf)
 			if test $ac_cv_lbl_have_siocglifconf = yes ; then
-				V_FINDALLDEVS=glifc
+				V_FINDALLDEVS=fad-glifc.c
 			else
-				V_FINDALLDEVS=gifc
+				V_FINDALLDEVS=fad-gifc.c
 			fi
 			;;
 
@@ -663,7 +707,7 @@
 			# another mechanism, and we should be using that
 			# instead.)
 			#
-			V_FINDALLDEVS=gifc
+			V_FINDALLDEVS=fad-gifc.c
 			;;
 		esac])
 fi
@@ -716,7 +760,7 @@
 
 # Check for Endace DAG card support.
 AC_ARG_WITH([dag],
-AC_HELP_STRING([--with-dag@<:@=DIR@:>@],[include Endace DAG support @<:@"yes", "no" or DIR; default="yes" on BSD and Linux if present@:>@]),
+AC_HELP_STRING([--with-dag@<:@=DIR@:>@],[include Endace DAG support (located in directory DIR, if supplied).  @<:@default=yes, if present@:>@]),
 [
 	if test "$withval" = no
 	then
@@ -732,14 +776,24 @@
 		dag_root=$withval
 	fi
 ],[
-	#
-	# Use DAG API if present, otherwise don't
-	#
-	want_dag=ifpresent
+	if test "$V_PCAP" = dag; then
+		# User requested DAG-only libpcap, so we'd better have
+		# the DAG API.
+		want_dag=yes
+	elif test "xxx_only" = yes; then
+		# User requested something-else-only pcap, so they don't
+		# want DAG support.
+		want_dag=no
+	else
+		#
+		# Use DAG API if present, otherwise don't
+		#
+		want_dag=ifpresent
+	fi
 ])
 
 AC_ARG_WITH([dag-includes],
-AC_HELP_STRING([--with-dag-includes=DIR],[Endace DAG include directory]),
+AC_HELP_STRING([--with-dag-includes=IDIR],[Endace DAG include directory, if not DIR/include]),
 [
 	# User wants DAG support and has specified a header directory, so use the provided value.
 	want_dag=yes
@@ -747,35 +801,13 @@
 ],[])
 
 AC_ARG_WITH([dag-libraries],
-AC_HELP_STRING([--with-dag-libraries=DIR],[Endace DAG library directory]),
+AC_HELP_STRING([--with-dag-libraries=LDIR],[Endace DAG library directory, if not DIR/lib]),
 [
 	# User wants DAG support and has specified a library directory, so use the provided value.
 	want_dag=yes
 	dag_lib_dir=$withval
 ],[])
 
-case "$V_PCAP" in
-linux|bpf|dag)
-	#
-	# We support the DAG API if we're on Linux or BSD, or if we're
-	# building a DAG-only libpcap.
-	#
-	;;
-*)
-	#
-	# If the user explicitly requested DAG, tell them it's not
-	# supported.
-	#
-	# If they expressed no preference, don't include it.
-	#
-	if test $want_dag = yes; then
-		AC_MSG_ERROR([DAG support is only available with 'linux' 'bpf' and 'dag' packet capture types])
-	elif test $want_dag = yes; then
-		want_dag=no
-	fi
-	;;
-esac
-
 ac_cv_lbl_dag_api=no
 if test "$want_dag" != no; then
 
@@ -783,7 +815,7 @@
 
 	# If necessary, set default paths for DAG API headers and libraries.
 	if test -z "$dag_root"; then
-	    dag_root=/usr/local
+		dag_root=/usr/local
 	fi
 
 	if test -z "$dag_include_dir"; then
@@ -791,74 +823,70 @@
 	fi
 
 	if test -z "$dag_lib_dir"; then
-	    dag_lib_dir="$dag_root/lib"
+		dag_lib_dir="$dag_root/lib"
 	fi
 
 	if test -z "$dag_tools_dir"; then
-	    dag_tools_dir="$dag_root/tools"
+		dag_tools_dir="$dag_root/tools"
 	fi
 
 	if test -r $dag_include_dir/dagapi.h; then
 		ac_cv_lbl_dag_api=yes
 	fi
-	AC_MSG_RESULT([$ac_cv_lbl_dag_api ($dag_include_dir)])
-fi
 
-if test $ac_cv_lbl_dag_api = yes; then
-	V_INCLS="$V_INCLS -I$dag_include_dir"
+	if test "$ac_cv_lbl_dag_api" = yes; then
+		AC_MSG_RESULT([yes ($dag_include_dir)])
 
-	if test $V_PCAP != dag ; then
-		 SSRC="pcap-dag.c"
-	fi
+		V_INCLS="$V_INCLS -I$dag_include_dir"
 
-	# See if we can find a general version string.
-	# Don't need to save and restore LIBS to prevent -ldag being
-	# included if there's a found-action (arg 3).
-	saved_ldflags=$LDFLAGS
-	LDFLAGS="-L$dag_lib_dir"
-	AC_CHECK_LIB([dag], [dag_attach_stream], [dag_streams="1"], [dag_streams="0"])
-	AC_CHECK_LIB([dag],[dag_get_erf_types], [
-		AC_DEFINE(HAVE_DAG_GET_ERF_TYPES, 1, [define if you have dag_get_erf_types()])])
-	AC_CHECK_LIB([dag],[dag_get_stream_erf_types], [
-		AC_DEFINE(HAVE_DAG_GET_STREAM_ERF_TYPES, 1, [define if you have dag_get_stream_erf_types()])])
+		if test $V_PCAP != dag ; then
+			 SSRC="$SSRC pcap-dag.c"
+		fi
 
-	LDFLAGS=$saved_ldflags
+		# See if we can find a general version string.
+		# Don't need to save and restore LIBS to prevent -ldag being
+		# included if there's a found-action (arg 3).
+		saved_ldflags=$LDFLAGS
+		LDFLAGS="-L$dag_lib_dir"
+		AC_CHECK_LIB([dag], [dag_attach_stream], [dag_streams="1"], [dag_streams="0"])
+		AC_CHECK_LIB([dag],[dag_get_erf_types], [
+			AC_DEFINE(HAVE_DAG_GET_ERF_TYPES, 1, [define if you have dag_get_erf_types()])])
+		AC_CHECK_LIB([dag],[dag_get_stream_erf_types], [
+			AC_DEFINE(HAVE_DAG_GET_STREAM_ERF_TYPES, 1, [define if you have dag_get_stream_erf_types()])])
 
-	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"
+		LDFLAGS=$saved_ldflags
 
-		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 "$dag_streams" = 1; then
+			AC_DEFINE(HAVE_DAG_STREAMS_API, 1, [define if you have streams capable DAG API])
+			LIBS="$LIBS -ldag"
+			LDFLAGS="$LDFLAGS -L$dag_lib_dir"
+
+			AC_CHECK_LIB([vdag],[vdag_set_device_info], [ac_dag_have_vdag="1"], [ac_dag_have_vdag="0"])
+			if test "$ac_dag_have_vdag" = 1; then
+				AC_DEFINE(HAVE_DAG_VDAG, 1, [define if you have vdag_set_device_info()])
+				LIBS="$LIBS -lpthread"
+			fi
+		fi
+
+		AC_DEFINE(HAVE_DAG_API, 1, [define if you have the DAG API])
+	else
+		AC_MSG_RESULT(no)
+
+		if test "$V_PCAP" = dag; then
+			# User requested "dag" capture type but we couldn't
+			# find the DAG API support.
+			AC_MSG_ERROR([DAG support requested with --with-pcap=dag, but the DAG headers weren't found at $dag_include_dir: make sure the DAG support is installed, specify a different path or paths if necessary, or don't request DAG support])
+		fi
+
+		if test "$want_dag" = yes; then
+	        	# User wanted DAG support but we couldn't find it.
+			AC_MSG_ERROR([DAG support requested with --with-dag, but the DAG headers weren't found at $dag_include_dir: make sure the DAG support is installed, specify a different path or paths if necessary, or don't request DAG support])
 		fi
 	fi
-
-	AC_DEFINE(HAVE_DAG_API, 1, [define if you have the DAG API])
-fi
-
-AC_MSG_CHECKING(whether we have the DAG API)
-
-if test $ac_cv_lbl_dag_api = no; then
-	AC_MSG_RESULT(no)
-	if test "$want_dag" = yes; then
-        	# User wanted DAG support but we couldn't find it.
-		AC_MSG_ERROR([DAG API requested, but not found at $dag_root: use --without-dag])
-	fi
-
-	if test "$V_PCAP" = dag; then
-		# User requested "dag" capture type but the DAG API wasn't
-		# found.
-		AC_MSG_ERROR([Specifying the capture type as "dag" requires the DAG API to be present; use the --with-dag options to specify the location. (Try "./configure --help" for more information.)])
-	fi
-else
-	AC_MSG_RESULT(yes)
 fi
 
 AC_ARG_WITH(septel,
-AC_HELP_STRING([--with-septel@<:@=DIR@:>@],[include Septel support (located in directory DIR, if supplied).  @<:@default=yes, on Linux, if present@:>@]),
+AC_HELP_STRING([--with-septel@<:@=DIR@:>@],[include Septel support (located in directory DIR, if supplied).  @<:@default=yes, if present@:>@]),
 [
 	if test "$withval" = no
 	then
@@ -872,38 +900,28 @@
 		septel_root=$withval
 	fi
 ],[
-	#
-	# Use Septel API if present, otherwise don't
-	#
-	want_septel=ifpresent
-	septel_root=./../septel
-])
-ac_cv_lbl_septel_api=no
-case "$V_PCAP" in
-linux|septel)
-	#
-	# We support the Septel API if we're on Linux, or if we're building
-	# a Septel-only libpcap.
-	#
-	;;
-*)
-	#
-	# If the user explicitly requested Septel, tell them it's not
-	# supported.
-	#
-	# If they expressed no preference, don't include it.
-	#
-	if test $want_septel = yes; then
-		AC_MSG_ERROR(Septel support only available with 'linux' and 'septel' packet capture types)
-	elif test $want_septel = yes; then
+	if test "$V_PCAP" = septel; then
+		# User requested Septel-only libpcap, so we'd better have
+		# the Septel API.
+		want_septel=yes
+	elif test "xxx_only" = yes; then
+		# User requested something-else-only pcap, so they don't
+		# want Septel support.
 		want_septel=no
+	else
+		#
+		# Use Septel API if present, otherwise don't
+		#
+		want_septel=ifpresent
 	fi
-	;;
-esac
+])
 
+ac_cv_lbl_septel_api=no
 if test "$with_septel" != no; then
-	AC_MSG_CHECKING(whether we have Septel API)
 
+	AC_MSG_CHECKING([whether we have Septel API headers])
+
+	# If necessary, set default paths for Septel API headers and libraries.
 	if test -z "$septel_root"; then
 		septel_root=$srcdir/../septel
 	fi
@@ -911,35 +929,41 @@
 	septel_tools_dir="$septel_root"
 	septel_include_dir="$septel_root/INC"
 
-	ac_cv_lbl_septel_api=no
 	if test -r "$septel_include_dir/msg.h"; then
+		ac_cv_lbl_septel_api=yes
+	fi
+
+	if test "$ac_cv_lbl_septel_api" = yes; then
+		AC_MSG_RESULT([yes ($septel_include_dir)])
+
 		V_INCLS="$V_INCLS -I$septel_include_dir"
 		ADDLOBJS="$ADDLOBJS $septel_tools_dir/asciibin.o $septel_tools_dir/bit2byte.o $septel_tools_dir/confirm.o $septel_tools_dir/fmtmsg.o $septel_tools_dir/gct_unix.o $septel_tools_dir/hqueue.o $septel_tools_dir/ident.o $septel_tools_dir/mem.o $septel_tools_dir/pack.o $septel_tools_dir/parse.o $septel_tools_dir/pool.o $septel_tools_dir/sdlsig.o $septel_tools_dir/strtonum.o $septel_tools_dir/timer.o $septel_tools_dir/trace.o"
 		ADDLARCHIVEOBJS="$ADDLARCHIVEOBJS $septel_tools_dir/asciibin.o $septel_tools_dir/bit2byte.o $septel_tools_dir/confirm.o $septel_tools_dir/fmtmsg.o $septel_tools_dir/gct_unix.o $septel_tools_dir/hqueue.o $septel_tools_dir/ident.o $septel_tools_dir/mem.o $septel_tools_dir/pack.o $septel_tools_dir/parse.o $septel_tools_dir/pool.o $septel_tools_dir/sdlsig.o $septel_tools_dir/strtonum.o $septel_tools_dir/timer.o $septel_tools_dir/trace.o"
 
 		if test "$V_PCAP" != septel ; then
-			 SSRC="pcap-septel.c"
+			 SSRC="$SSRC pcap-septel.c"
 		fi
-		ac_cv_lbl_septel_api=yes
-	fi
 
-	AC_MSG_RESULT($ac_cv_lbl_septel_api)
-	if test $ac_cv_lbl_septel_api = no; then
-		if test "$want_septel" = yes; then
-			AC_MSG_ERROR(Septel API not found under directory $septel_root; use --without-septel)
-		fi
+		AC_DEFINE(HAVE_SEPTEL_API, 1, [define if you have the Septel API])
 	else
-		AC_DEFINE(HAVE_SEPTEL_API, 1, [define if you have a Septel API])
-	fi
-fi
+		AC_MSG_RESULT(no)
 
-if test "$V_PCAP" = septel -a "$ac_cv_lbl_septel_api" = no; then
-	AC_MSG_ERROR(Specifying the capture type as 'septel' requires the Septel API to be present; use --with-septel=DIR)
+		if test "$V_PCAP" = septel; then
+			# User requested "septel" capture type but
+			# we couldn't find the Septel API support.
+			AC_MSG_ERROR([Septel support requested with --with-pcap=septel, but the Septel headers weren't found at $septel_include_dir: make sure the Septel support is installed, specify a different path or paths if necessary, or don't request Septel support])
+		fi
+
+		if test "$want_septel" = yes; then
+	        	# User wanted Septel support but we couldn't find it.
+			AC_MSG_ERROR([Septel support requested with --with-septel, but the Septel headers weren't found at $septel_include_dir: make sure the Septel support is installed, specify a different path or paths if necessary, or don't request Septel support])
+		fi
+	fi
 fi
 
 # Check for Myricom SNF support.
 AC_ARG_WITH([snf],
-AC_HELP_STRING([--with-snf@<:@=DIR@:>@],[include Myricom SNF support @<:@"yes", "no" or DIR; default="yes" on BSD and Linux if present@:>@]),
+AC_HELP_STRING([--with-snf@<:@=DIR@:>@],[include Myricom SNF support (located in directory DIR, if supplied).  @<:@default=yes, if present@:>@]),
 [
 	if test "$withval" = no
 	then
@@ -947,7 +971,7 @@
 		want_snf=no
 	elif test "$withval" = yes
 	then
-		# User wants SNF support but hasn't specific a directory.
+		# User wants SNF support but hasn't specified a directory.
 		want_snf=yes
 	else
 		# User wants SNF support with a specified directory.
@@ -955,14 +979,24 @@
 		snf_root=$withval
 	fi
 ],[
-	#
-	# Use Sniffer API if present, otherwise don't
-	#
-	want_snf=ifpresent
+	if test "$V_PCAP" = snf; then
+		# User requested Sniffer-only libpcap, so we'd better have
+		# the Sniffer API.
+		want_snf=yes
+	elif test "xxx_only" = yes; then
+		# User requested something-else-only pcap, so they don't
+		# want SNF support.
+		want_snf=no
+	else
+		#
+		# Use Sniffer API if present, otherwise don't
+		#
+		want_snf=ifpresent
+	fi
 ])
 
 AC_ARG_WITH([snf-includes],
-AC_HELP_STRING([--with-snf-includes=DIR],[Myricom SNF include directory]),
+AC_HELP_STRING([--with-snf-includes=IDIR],[Myricom SNF include directory, if not DIR/include]),
 [
 	# User wants SNF with specific header directory
 	want_snf=yes
@@ -970,40 +1004,19 @@
 ],[])
 
 AC_ARG_WITH([snf-libraries],
-AC_HELP_STRING([--with-snf-libraries=DIR],[Myricom SNF library directory]),
+AC_HELP_STRING([--with-snf-libraries=LDIR],[Myricom SNF library directory, if not DIR/lib]),
 [
 	# User wants SNF with specific lib directory
 	want_snf=yes
 	snf_lib_dir=$withval
 ],[])
 
-case "$V_PCAP" in
-bpf|linux|snf)
-	#
-	# We support the Sniffer API if we're on BSD, Linux, or if we're
-	# building a Sniffer-only libpcap.
-	#
-	;;
-*)
-	#
-	# If the user explicitly requested Sniffer, tell them it's not
-	# supported.
-	#
-	# If they expressed no preference, don't include it.
-	#
-	if test $want_snf = yes; then
-		AC_MSG_ERROR(Myricom SNF support only available with 'bpf' 'linux' and 'snf' packet capture types)
-	elif test $want_snf = yes; then
-		want_snf=no
-	fi
-	;;
-esac
-
 ac_cv_lbl_snf_api=no
 if test "$with_snf" != no; then
 
 	AC_MSG_CHECKING(whether we have Myricom Sniffer API)
 
+	# If necessary, set default paths for Sniffer headers and libraries.
 	if test -z "$snf_root"; then
 		snf_root=/opt/snf
 	fi
@@ -1017,56 +1030,157 @@
 	fi
 
 	if test -f "$snf_include_dir/snf.h"; then
-		ac_cv_lbl_snf_api=yes
-	fi
-	AC_MSG_RESULT([$ac_cv_lbl_snf_api ($snf_root)])
-
-	if test $ac_cv_lbl_snf_api = no; then
-		if test "$want_snf" = yes; then
-			AC_MSG_ERROR(SNF API headers not found under $snf_include_dir; use --without-snf)
-		fi
-	else
+		# We found a header; make sure we can link with the library
 		saved_ldflags=$LDFLAGS
 		LDFLAGS="$LDFLAGS -L$snf_lib_dir"
-		AC_CHECK_LIB([snf], [snf_init], [ac_cv_lbl_snf_api="yes"], [ac_cv_lbl_snf_api="no"])
+		AC_CHECK_LIB([snf], [snf_init], [ac_cv_lbl_snf_api="yes"])
 		LDFLAGS="$saved_ldflags"
+		if test "$ac_cv_lbl_snf_api" = no; then
+			AC_MSG_ERROR(SNF API cannot correctly be linked; check config.log)
+		fi
+	fi
 
-		if test $ac_cv_lbl_snf_api = no; then
-			if test "$want_snf" = yes; then
-				AC_MSG_ERROR(SNF API cannot correctly be linked check config.log; use --without-snf)
-			fi
-		else
-			V_INCLS="$V_INCLS -I$snf_include_dir"
-			LIBS="$LIBS -lsnf"
-			LDFLAGS="$LDFLAGS -L$snf_lib_dir"
-			if test "$V_PCAP" != snf ; then
-				SSRC="pcap-snf.c"
-			fi
-			AC_DEFINE(HAVE_SNF_API, 1, [define if you have Myricom SNF API])
+	if test "$ac_cv_lbl_snf_api" = yes; then
+		AC_MSG_RESULT([yes ($snf_root)])
+
+		V_INCLS="$V_INCLS -I$snf_include_dir"
+		LIBS="$LIBS -lsnf"
+		LDFLAGS="$LDFLAGS -L$snf_lib_dir"
+
+		if test "$V_PCAP" != snf ; then
+			SSRC="$SSRC pcap-snf.c"
+		fi
+
+		AC_DEFINE(HAVE_SNF_API, 1, [define if you have the Myricom SNF API])
+	else
+		AC_MSG_RESULT(no)
+
+		if test "$want_snf" = yes; then
+			# User requested "snf" capture type but
+			# we couldn't find the Sniffer API support.
+			AC_MSG_ERROR([Myricom Sniffer support requested with --with-pcap=snf, but the Sniffer headers weren't found at $snf_include_dir: make sure the Sniffer support is installed, specify a different path or paths if necessary, or don't request Sniffer support])
+		fi
+
+		if test "$want_snf" = yes; then
+			AC_MSG_ERROR([Myricom Sniffer support requested with --with-snf, but the Sniffer headers weren't found at $snf_include_dir: make sure the Sniffer support is installed, specify a different path or paths if necessary, or don't request Sniffer support])
 		fi
 	fi
 fi
 
-if test "$V_PCAP" = snf -a "$ac_cv_lbl_snf_api" = no; then
-	AC_MSG_ERROR(Specifying the capture type as 'snf' requires the Myricom Sniffer API to be present; use --with-snf=DIR)
+# Check for Riverbed TurboCap support.
+AC_ARG_WITH([turbocap],
+AC_HELP_STRING([--with-turbocap@<:@=DIR@:>@],[include Riverbed TurboCap support (located in directory DIR, if supplied).  @<:@default=yes, if present@:>@]),
+[
+	if test "$withval" = no
+	then
+		# User explicitly doesn't want TurboCap
+		want_turbocap=no
+	elif test "$withval" = yes
+	then
+		# User wants TurboCap support but hasn't specified a directory.
+		want_turbocap=yes
+	else
+		# User wants TurboCap support with a specified directory.
+		want_turbocap=yes
+		turbocap_root=$withval
+	fi
+],[
+	if test "xxx_only" = yes; then
+		# User requested something-else-only pcap, so they don't
+		# want TurboCap support.
+		want_turbocap=no
+	else
+		#
+		# Use TurboCap API if present, otherwise don't
+		#
+		want_turbocap=ifpresent
+	fi
+])
+
+ac_cv_lbl_turbocap_api=no
+if test "$want_turbocap" != no; then
+
+	AC_MSG_CHECKING(whether TurboCap is supported)
+
+	save_CFLAGS="$CFLAGS"
+	save_LIBS="$LIBS"
+	if test ! -z "$turbocap_root"; then
+		TURBOCAP_CFLAGS="-I$turbocap_root/include"
+		TURBOCAP_LIBS="-L$turbocap_root/lib"
+		CFLAGS="$CFLAGS $TURBOCAP_CFLAGS"
+	fi
+
+	AC_TRY_COMPILE(
+	[
+	    #include <TcApi.h>
+	],
+	[
+	    TC_INSTANCE a; TC_PORT b; TC_BOARD c;
+	    TC_INSTANCE i;
+	    (void)TcInstanceCreateByName("foo", &i);
+	],
+	ac_cv_lbl_turbocap_api=yes)
+
+	CFLAGS="$save_CFLAGS"
+	if test $ac_cv_lbl_turbocap_api = yes; then
+		AC_MSG_RESULT(yes)
+
+		SSRC="$SSRC pcap-tc.c"
+		V_INCLS="$V_INCLS $TURBOCAP_CFLAGS"
+		LIBS="$LIBS $TURBOCAP_LIBS -lTcApi -lpthread -lstdc++"
+
+		AC_DEFINE(HAVE_TC_API, 1, [define if you have the TurboCap API])
+	else
+		AC_MSG_RESULT(no)
+
+		if test "$want_turbocap" = yes; then
+	        	# User wanted Turbo support but we couldn't find it.
+			AC_MSG_ERROR([TurboCap support requested with --with-turbocap, but the TurboCap headers weren't found: make sure the TurboCap support is installed or don't request TurboCap support])
+		fi
+	fi
 fi
 
-AC_LBL_LEX_AND_YACC(V_LEX, V_YACC, pcap_)
-if test "$V_LEX" = lex ; then
-# Some versions of lex can't handle the definitions section of scanner.l .
-# Try lexing it and complain if it can't deal.
-	AC_CACHE_CHECK([for capable lex], tcpdump_cv_capable_lex,
-		if lex -t scanner.l > /dev/null 2>&1; then
-			tcpdump_cv_capable_lex=yes
-		else
-			tcpdump_cv_capable_lex=insufficient
-		fi)
-	if test $tcpdump_cv_capable_lex = insufficient ; then
-		AC_MSG_ERROR([Your operating system's lex is insufficient to compile
- libpcap.  flex is a lex replacement that has many advantages, including
- being able to compile libpcap.  For more information, see
- http://www.gnu.org/software/flex/flex.html .])
-	fi
+#
+# Look for {f}lex.
+#
+AC_PROG_LEX
+if test "$LEX" = ":"; then
+	AC_MSG_ERROR([Neither flex nor lex was found.])
+fi
+
+#
+# Make sure {f}lex supports the -P, --header-file, and --nounput flags
+# and supports processing our scanner.l.
+#
+AC_CACHE_CHECK([for capable lex], tcpdump_cv_capable_lex,
+	if $LEX -P pcap_ --header-file=/dev/null --nounput -t $srcdir/scanner.l > /dev/null 2>&1; then
+	    tcpdump_cv_capable_lex=yes
+	else
+	    tcpdump_cv_capable_lex=insufficient
+	fi)
+if test $tcpdump_cv_capable_lex = insufficient ; then
+	AC_MSG_ERROR([$LEX is insufficient to compile libpcap.
+ libpcap requires Flex 2.5.31 or later, or a compatible version of lex.])
+fi
+
+#
+# Look for yacc/bison/byacc.
+#
+AC_PROG_YACC
+
+#
+# Make sure it supports the -p flag and supports processing our
+# grammar.y.
+#
+AC_CACHE_CHECK([for capable yacc/bison], tcpdump_cv_capable_yacc,
+	if $YACC -p pcap_ -o /dev/null $srcdir/grammar.y >/dev/null 2>&1; then
+	    tcpdump_cv_capable_yacc=yes
+	else
+	    tcpdump_cv_capable_yacc=insufficient
+	fi)
+if test $tcpdump_cv_capable_yacc = insufficient ; then
+	AC_MSG_ERROR([$YACC is insufficient to compile libpcap.
+ libpcap requires Bison, Berkeley YACC, or another YACC compatible with them.])
 fi
 
 #
@@ -1338,12 +1452,6 @@
 
 AC_LBL_UNALIGNED_ACCESS
 
-#
-# Makefile.in includes rules to generate version.h, so we assume
-# that it will be generated if autoconf is used.
-#
-AC_DEFINE(HAVE_VERSION_H, 1, [define if version.h is generated in the build procedure])
-
 rm -f net
 ln -s ${srcdir}/bpf/net net
 
@@ -1370,6 +1478,12 @@
     [],
     [enable_usb=yes])
 
+if test "xxx_only" = yes; then
+	# User requested something-else-only pcap, so they don't
+	# want USB support.
+	enable_usb=no
+fi
+
 if test "x$enable_usb" != "xno" ; then
    dnl check for USB sniffing support
    AC_MSG_CHECKING(for USB sniffing support)
@@ -1425,6 +1539,14 @@
 	    fi
 	fi
 	;;
+    freebsd*)
+	#
+	# This just uses BPF in FreeBSD 8.4 and later; we don't need
+	# to check for anything special for capturing.
+	#
+	AC_MSG_RESULT([yes, in FreeBSD 8.4 and later])
+	;;
+
     *)
 	AC_MSG_RESULT(no)
 	;;
@@ -1434,21 +1556,22 @@
 AC_SUBST(USB_SRC)
 
 dnl check for netfilter sniffing support
-AC_MSG_CHECKING(whether the platform could support netfilter sniffing)
-case "$host_os" in
-linux*)
-	AC_MSG_RESULT(yes)
-	#
-	# Life's too short to deal with trying to get this to compile
-	# if you don't get the right types defined with
-	# __KERNEL_STRICT_NAMES getting defined by some other include.
-	#
-	# Check whether the includes Just Work.  If not, don't turn on
-	# netfilter support.
-	#
-	AC_MSG_CHECKING(whether we can compile the netfilter support)
-	AC_CACHE_VAL(ac_cv_netfilter_can_compile,
-	  AC_TRY_COMPILE([
+if test "xxx_only" != yes; then
+	AC_MSG_CHECKING(whether the platform could support netfilter sniffing)
+	case "$host_os" in
+	linux*)
+		AC_MSG_RESULT(yes)
+		#
+		# Life's too short to deal with trying to get this to compile
+		# if you don't get the right types defined with
+		# __KERNEL_STRICT_NAMES getting defined by some other include.
+		#
+		# Check whether the includes Just Work.  If not, don't turn on
+		# netfilter support.
+		#
+		AC_MSG_CHECKING(whether we can compile the netfilter support)
+		AC_CACHE_VAL(ac_cv_netfilter_can_compile,
+		  AC_TRY_COMPILE([
 AC_INCLUDES_DEFAULT
 #include <sys/socket.h>
 #include <netinet/in.h>
@@ -1462,17 +1585,18 @@
 	    [],
 	    ac_cv_netfilter_can_compile=yes,
 	    ac_cv_netfilter_can_compile=no))
-	AC_MSG_RESULT($ac_cv_netfilter_can_compile)
-	if test $ac_cv_netfilter_can_compile = yes ; then
-	  AC_DEFINE(PCAP_SUPPORT_NETFILTER, 1,
-	    [target host supports netfilter sniffing])
-	  NETFILTER_SRC=pcap-netfilter-linux.c
-	fi
-	;;
-*)
-	AC_MSG_RESULT(no)
-	;;
-esac
+		AC_MSG_RESULT($ac_cv_netfilter_can_compile)
+		if test $ac_cv_netfilter_can_compile = yes ; then
+		  AC_DEFINE(PCAP_SUPPORT_NETFILTER, 1,
+		    [target host supports netfilter sniffing])
+		  NETFILTER_SRC=pcap-netfilter-linux.c
+		fi
+		;;
+	*)
+		AC_MSG_RESULT(no)
+		;;
+	esac
+fi
 AC_SUBST(PCAP_SUPPORT_NETFILTER)
 AC_SUBST(NETFILTER_SRC)
 
@@ -1481,6 +1605,12 @@
     [],
     [enable_bluetooth=ifsupportavailable])
 
+if test "xxx_only" = yes; then
+	# User requested something-else-only pcap, so they don't
+	# want Bluetooth support.
+	enable_bluetooth=no
+fi
+
 if test "x$enable_bluetooth" != "xno" ; then
 	dnl check for Bluetooth sniffing support
 	case "$host_os" in
@@ -1555,94 +1685,17 @@
 	AC_SUBST(BT_MONITOR_SRC)
 fi
 
-AC_ARG_ENABLE([canusb],
-[AC_HELP_STRING([--enable-canusb],[enable canusb support @<:@default=yes, if support available@:>@])],
-    [],
-    [enable_canusb=ifsupportavailable])
-
-if test "x$enable_canusb" != "xno" ; then
-	dnl check for canusb support
-	case "$host_os" in
-	linux*|uclinux*)
-		AC_CHECK_HEADER(libusb-1.0/libusb.h,
-		[
-		    AC_CHECK_LIB(usb-1.0, libusb_init,
-		    [
-			AC_DEFINE(PCAP_SUPPORT_CANUSB, 1, [target host supports canusb])
-			CANUSB_SRC=pcap-canusb-linux.c
-			LIBS="-lusb-1.0 -lpthread $LIBS"
-			ac_lbl_has_libusb=yes
-		    ],
-		    ac_lbl_has_libusb=no,
-		    -lpthread
-		    )
-		],
-		ac_lbl_has_libusb=no
-		)
-		if test "x$ac_lbl_has_libusb" = "xyes" ; then
-		    AC_MSG_NOTICE(canusb sniffing is supported)
-		else
-		    if test "x$enable_canusb" = "xyes" ; then
-			AC_MSG_ERROR(canusb sniffing is not supported; install libusb1.0 lib devel to enable it)
-		    else
-			AC_MSG_NOTICE(canusb sniffing is not supported; install libusb1.0 lib devel to enable it)
-		    fi
-		fi
-		;;
-	*)
-		if test "x$enable_canusb" = "xyes" ; then
-		    AC_MSG_ERROR(no canusb support implemented for $host_os)
-		else
-		    AC_MSG_NOTICE(no canusb support implemented for $host_os)
-		fi
-		;;
-	esac
-	AC_SUBST(PCAP_SUPPORT_CANUSB)
-	AC_SUBST(CANUSB_SRC)
-fi
-
-AC_ARG_ENABLE([can],
-[AC_HELP_STRING([--enable-can],[enable CAN support @<:@default=yes, if support available@:>@])],
-    [],
-    [enable_can=ifsupportavailable])
-
-if test "x$enable_can" != "xno" ; then
-	dnl check for CAN sniffing support
-	case "$host_os" in
-	linux*)
-		AC_CHECK_HEADER(linux/can.h,
-			[
-			    AC_DEFINE(PCAP_SUPPORT_CAN, 1, [target host supports CAN sniffing])
-			    CAN_SRC=pcap-can-linux.c
-			    AC_MSG_NOTICE(CAN sniffing is supported)
-			],
-			[
-			    if test "x$enable_can" = "xyes" ; then
-				AC_MSG_ERROR(CAN sniffing is not supported)
-			    else
-				AC_MSG_NOTICE(CAN sniffing is not supported)
-			    fi
-			],
-			[#include <sys/socket.h>]
-		   )
-		;;
-	*)
-		if test "x$enable_can" = "xyes" ; then
-		    AC_MSG_ERROR(no CAN sniffing support implemented for $host_os)
-		else
-		    AC_MSG_NOTICE(no CAN sniffing support implemented for $host_os)
-		fi
-		;;
-	esac
-	AC_SUBST(PCAP_SUPPORT_CAN)
-	AC_SUBST(CAN_SRC)
-fi
-
 AC_ARG_ENABLE([dbus],
 [AC_HELP_STRING([--enable-dbus],[enable D-Bus capture support @<:@default=yes, if support available@:>@])],
     [],
     [enable_dbus=ifavailable])
 
+if test "xxx_only" = yes; then
+	# User requested something-else-only pcap, so they don't
+	# want D-Bus support.
+	enable_dbus=no
+fi
+
 if test "x$enable_dbus" != "xno"; then
 	if test "x$enable_dbus" = "xyes"; then
 		case "$host_os" in
diff --git a/dlpisubs.c b/dlpisubs.c
index 131fa27..fb94a60 100644
--- a/dlpisubs.c
+++ b/dlpisubs.c
@@ -186,8 +186,8 @@
 			pkthdr.len = origlen;
 			pkthdr.caplen = caplen;
 			/* Insure caplen does not exceed snapshot */
-			if (pkthdr.caplen > p->snapshot)
-				pkthdr.caplen = p->snapshot;
+			if (pkthdr.caplen > (bpf_u_int32)p->snapshot)
+				pkthdr.caplen = (bpf_u_int32)p->snapshot;
 			(*callback)(user, &pkthdr, pk);
 			if (++n >= count && !PACKET_COUNT_IS_UNLIMITED(count)) {
 				p->cc = ep - bufp;
@@ -255,8 +255,29 @@
 		break;
 #endif
 
+#ifdef DL_IPV4
+	case DL_IPV4:
+		p->linktype = DLT_IPV4;
+		p->offset = 0;
+		break;
+#endif
+
+#ifdef DL_IPV6
+	case DL_IPV6:
+		p->linktype = DLT_IPV6;
+		p->offset = 0;
+		break;
+#endif
+
+#ifdef DL_IPNET
+	case DL_IPNET:
+		p->linktype = DLT_IPNET;
+		p->offset = 0;
+		break;
+#endif
+
 	default:
-		snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "unknown mactype %u",
+		pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "unknown mactype 0x%x",
 		    mactype);
 		retv = -1;
 	}
@@ -326,7 +347,7 @@
 pcap_alloc_databuf(pcap_t *p)
 {
 	p->bufsize = PKTBUFSIZE;
-	p->buffer = (u_char *)malloc(p->bufsize + p->offset);
+	p->buffer = malloc(p->bufsize + p->offset);
 	if (p->buffer == NULL) {
 		strlcpy(p->errbuf, pcap_strerror(errno), PCAP_ERRBUF_SIZE);
 		return (-1);
@@ -362,6 +383,6 @@
 static void
 pcap_stream_err(const char *func, int err, char *errbuf)
 {
-	snprintf(errbuf, PCAP_ERRBUF_SIZE, "%s: %s", func, pcap_strerror(err));
+	pcap_snprintf(errbuf, PCAP_ERRBUF_SIZE, "%s: %s", func, pcap_strerror(err));
 }
 #endif
diff --git a/etherent.c b/etherent.c
index 707fd9d..5cfd1b4 100644
--- a/etherent.c
+++ b/etherent.c
@@ -23,9 +23,9 @@
 #include "config.h"
 #endif
 
-#ifdef WIN32
+#ifdef _WIN32
 #include <pcap-stdinc.h>
-#else /* WIN32 */
+#else /* _WIN32 */
 #if HAVE_INTTYPES_H
 #include <inttypes.h>
 #elif HAVE_STDINT_H
@@ -35,7 +35,7 @@
 #include <sys/bitypes.h>
 #endif
 #include <sys/types.h>
-#endif /* WIN32 */
+#endif /* _WIN32 */
 
 #include <ctype.h>
 #include <memory.h>
diff --git a/ethertype.h b/ethertype.h
index 8bab881..51f6308 100644
--- a/ethertype.h
+++ b/ethertype.h
@@ -112,6 +112,9 @@
 #ifndef ETHERTYPE_PPPOES
 #define ETHERTYPE_PPPOES	0x8864
 #endif
+#ifndef ETHERTYPE_8021AD
+#define ETHERTYPE_8021AD	0x88a8
+#endif
 #ifndef	ETHERTYPE_LOOPBACK
 #define	ETHERTYPE_LOOPBACK	0x9000
 #endif
diff --git a/extract.h b/extract.h
new file mode 100644
index 0000000..face5b7
--- /dev/null
+++ b/extract.h
@@ -0,0 +1,221 @@
+/*
+ * Copyright (c) 1992, 1993, 1994, 1995, 1996
+ *	The Regents of the University of California.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that: (1) source code distributions
+ * retain the above copyright notice and this paragraph in its entirety, (2)
+ * distributions including binary code include the above copyright notice and
+ * this paragraph in its entirety in the documentation or other materials
+ * provided with the distribution, and (3) all advertising materials mentioning
+ * features or use of this software display the following acknowledgement:
+ * ``This product includes software developed by the University of California,
+ * Lawrence Berkeley Laboratory and its contributors.'' Neither the name of
+ * the University nor the names of its contributors may be used to endorse
+ * or promote products derived from this software without specific prior
+ * written permission.
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+ */
+
+#ifndef _WIN32
+#include <arpa/inet.h>
+#endif
+
+/*
+ * Macros to extract possibly-unaligned big-endian integral values.
+ */
+#ifdef LBL_ALIGN
+/*
+ * The processor doesn't natively handle unaligned loads.
+ */
+#if defined(__GNUC__) && defined(HAVE___ATTRIBUTE__) && \
+    (defined(__alpha) || defined(__alpha__) || \
+     defined(__mips) || defined(__mips__))
+
+/*
+ * This is a GCC-compatible compiler and we have __attribute__, which
+ * we assume that mean we have __attribute__((packed)), and this is
+ * MIPS or Alpha, which has instructions that can help when doing
+ * unaligned loads.
+ *
+ * Declare packed structures containing a uint16_t and a uint32_t,
+ * cast the pointer to point to one of those, and fetch through it;
+ * the GCC manual doesn't appear to explicitly say that
+ * __attribute__((packed)) causes the compiler to generate unaligned-safe
+ * code, but it apppears to do so.
+ *
+ * We do this in case the compiler can generate code using those
+ * instructions to do an unaligned load and pass stuff to "ntohs()" or
+ * "ntohl()", which might be better than than the code to fetch the
+ * bytes one at a time and assemble them.  (That might not be the
+ * case on a little-endian platform, such as DEC's MIPS machines and
+ * Alpha machines, where "ntohs()" and "ntohl()" might not be done
+ * inline.)
+ *
+ * We do this only for specific architectures because, for example,
+ * at least some versions of GCC, when compiling for 64-bit SPARC,
+ * generate code that assumes alignment if we do this.
+ *
+ * XXX - add other architectures and compilers as possible and
+ * appropriate.
+ *
+ * HP's C compiler, indicated by __HP_cc being defined, supports
+ * "#pragma unaligned N" in version A.05.50 and later, where "N"
+ * specifies a number of bytes at which the typedef on the next
+ * line is aligned, e.g.
+ *
+ *	#pragma unalign 1
+ *	typedef uint16_t unaligned_uint16_t;
+ *
+ * to define unaligned_uint16_t as a 16-bit unaligned data type.
+ * This could be presumably used, in sufficiently recent versions of
+ * the compiler, with macros similar to those below.  This would be
+ * useful only if that compiler could generate better code for PA-RISC
+ * or Itanium than would be generated by a bunch of shifts-and-ORs.
+ *
+ * DEC C, indicated by __DECC being defined, has, at least on Alpha,
+ * an __unaligned qualifier that can be applied to pointers to get the
+ * compiler to generate code that does unaligned loads and stores when
+ * dereferencing the pointer in question.
+ *
+ * XXX - what if the native C compiler doesn't support
+ * __attribute__((packed))?  How can we get it to generate unaligned
+ * accesses for *specific* items?
+ */
+typedef struct {
+	uint16_t	val;
+} __attribute__((packed)) unaligned_uint16_t;
+
+typedef struct {
+	uint32_t	val;
+} __attribute__((packed)) unaligned_uint32_t;
+
+static inline uint16_t
+EXTRACT_16BITS(const void *p)
+{
+	return ((uint16_t)ntohs(((const unaligned_uint16_t *)(p))->val));
+}
+
+static inline uint32_t
+EXTRACT_32BITS(const void *p)
+{
+	return ((uint32_t)ntohl(((const unaligned_uint32_t *)(p))->val));
+}
+
+static inline uint64_t
+EXTRACT_64BITS(const void *p)
+{
+	return ((uint64_t)(((uint64_t)ntohl(((const unaligned_uint32_t *)(p) + 0)->val)) << 32 | \
+		((uint64_t)ntohl(((const unaligned_uint32_t *)(p) + 1)->val)) << 0));
+}
+
+#else /* have to do it a byte at a time */
+/*
+ * This isn't a GCC-compatible compiler, we don't have __attribute__,
+ * or we do but we don't know of any better way with this instruction
+ * set to do unaligned loads, so do unaligned loads of big-endian
+ * quantities the hard way - fetch the bytes one at a time and
+ * assemble them.
+ */
+#define EXTRACT_16BITS(p) \
+	((uint16_t)(((uint16_t)(*((const uint8_t *)(p) + 0)) << 8) | \
+	            ((uint16_t)(*((const uint8_t *)(p) + 1)) << 0)))
+#define EXTRACT_32BITS(p) \
+	((uint32_t)(((uint32_t)(*((const uint8_t *)(p) + 0)) << 24) | \
+	            ((uint32_t)(*((const uint8_t *)(p) + 1)) << 16) | \
+	            ((uint32_t)(*((const uint8_t *)(p) + 2)) << 8) | \
+	            ((uint32_t)(*((const uint8_t *)(p) + 3)) << 0)))
+#define EXTRACT_64BITS(p) \
+	((uint64_t)(((uint64_t)(*((const uint8_t *)(p) + 0)) << 56) | \
+	            ((uint64_t)(*((const uint8_t *)(p) + 1)) << 48) | \
+	            ((uint64_t)(*((const uint8_t *)(p) + 2)) << 40) | \
+	            ((uint64_t)(*((const uint8_t *)(p) + 3)) << 32) | \
+	            ((uint64_t)(*((const uint8_t *)(p) + 4)) << 24) | \
+	            ((uint64_t)(*((const uint8_t *)(p) + 5)) << 16) | \
+	            ((uint64_t)(*((const uint8_t *)(p) + 6)) << 8) | \
+	            ((uint64_t)(*((const uint8_t *)(p) + 7)) << 0)))
+#endif /* must special-case unaligned accesses */
+#else /* LBL_ALIGN */
+/*
+ * The processor natively handles unaligned loads, so we can just
+ * cast the pointer and fetch through it.
+ */
+static inline uint16_t
+EXTRACT_16BITS(const void *p)
+{
+	return ((uint16_t)ntohs(*(const uint16_t *)(p)));
+}
+
+static inline uint32_t
+EXTRACT_32BITS(const void *p)
+{
+	return ((uint32_t)ntohl(*(const uint32_t *)(p)));
+}
+
+static inline uint64_t
+EXTRACT_64BITS(const void *p)
+{
+	return ((uint64_t)(((uint64_t)ntohl(*((const uint32_t *)(p) + 0))) << 32 | \
+		((uint64_t)ntohl(*((const uint32_t *)(p) + 1))) << 0));
+
+}
+
+#endif /* LBL_ALIGN */
+
+#define EXTRACT_24BITS(p) \
+	((uint32_t)(((uint32_t)(*((const uint8_t *)(p) + 0)) << 16) | \
+	            ((uint32_t)(*((const uint8_t *)(p) + 1)) << 8) | \
+	            ((uint32_t)(*((const uint8_t *)(p) + 2)) << 0)))
+
+#define EXTRACT_40BITS(p) \
+	((uint64_t)(((uint64_t)(*((const uint8_t *)(p) + 0)) << 32) | \
+	            ((uint64_t)(*((const uint8_t *)(p) + 1)) << 24) | \
+	            ((uint64_t)(*((const uint8_t *)(p) + 2)) << 16) | \
+	            ((uint64_t)(*((const uint8_t *)(p) + 3)) << 8) | \
+	            ((uint64_t)(*((const uint8_t *)(p) + 4)) << 0)))
+
+#define EXTRACT_48BITS(p) \
+	((uint64_t)(((uint64_t)(*((const uint8_t *)(p) + 0)) << 40) | \
+	            ((uint64_t)(*((const uint8_t *)(p) + 1)) << 32) | \
+	            ((uint64_t)(*((const uint8_t *)(p) + 2)) << 24) | \
+	            ((uint64_t)(*((const uint8_t *)(p) + 3)) << 16) | \
+	            ((uint64_t)(*((const uint8_t *)(p) + 4)) << 8) | \
+	            ((uint64_t)(*((const uint8_t *)(p) + 5)) << 0)))
+
+#define EXTRACT_56BITS(p) \
+	((uint64_t)(((uint64_t)(*((const uint8_t *)(p) + 0)) << 48) | \
+	            ((uint64_t)(*((const uint8_t *)(p) + 1)) << 40) | \
+	            ((uint64_t)(*((const uint8_t *)(p) + 2)) << 32) | \
+	            ((uint64_t)(*((const uint8_t *)(p) + 3)) << 24) | \
+	            ((uint64_t)(*((const uint8_t *)(p) + 4)) << 16) | \
+	            ((uint64_t)(*((const uint8_t *)(p) + 5)) << 8) | \
+	            ((uint64_t)(*((const uint8_t *)(p) + 6)) << 0)))
+
+/*
+ * Macros to extract possibly-unaligned little-endian integral values.
+ * XXX - do loads on little-endian machines that support unaligned loads?
+ */
+#define EXTRACT_LE_8BITS(p) (*(p))
+#define EXTRACT_LE_16BITS(p) \
+	((uint16_t)(((uint16_t)(*((const uint8_t *)(p) + 1)) << 8) | \
+	            ((uint16_t)(*((const uint8_t *)(p) + 0)) << 0)))
+#define EXTRACT_LE_32BITS(p) \
+	((uint32_t)(((uint32_t)(*((const uint8_t *)(p) + 3)) << 24) | \
+	            ((uint32_t)(*((const uint8_t *)(p) + 2)) << 16) | \
+	            ((uint32_t)(*((const uint8_t *)(p) + 1)) << 8) | \
+	            ((uint32_t)(*((const uint8_t *)(p) + 0)) << 0)))
+#define EXTRACT_LE_24BITS(p) \
+	((uint32_t)(((uint32_t)(*((const uint8_t *)(p) + 2)) << 16) | \
+	            ((uint32_t)(*((const uint8_t *)(p) + 1)) << 8) | \
+	            ((uint32_t)(*((const uint8_t *)(p) + 0)) << 0)))
+#define EXTRACT_LE_64BITS(p) \
+	((uint64_t)(((uint64_t)(*((const uint8_t *)(p) + 7)) << 56) | \
+	            ((uint64_t)(*((const uint8_t *)(p) + 6)) << 48) | \
+	            ((uint64_t)(*((const uint8_t *)(p) + 5)) << 40) | \
+	            ((uint64_t)(*((const uint8_t *)(p) + 4)) << 32) | \
+	            ((uint64_t)(*((const uint8_t *)(p) + 3)) << 24) | \
+	            ((uint64_t)(*((const uint8_t *)(p) + 2)) << 16) | \
+	            ((uint64_t)(*((const uint8_t *)(p) + 1)) << 8) | \
+	            ((uint64_t)(*((const uint8_t *)(p) + 0)) << 0)))
diff --git a/fad-getad.c b/fad-getad.c
index 6fd3360..b67b5cd 100644
--- a/fad-getad.c
+++ b/fad-getad.c
@@ -144,7 +144,8 @@
  * could be opened.
  */
 int
-pcap_findalldevs_interfaces(pcap_if_t **alldevsp, char *errbuf)
+pcap_findalldevs_interfaces(pcap_if_t **alldevsp, char *errbuf,
+    int (*check_usable)(const char *))
 {
 	pcap_if_t *devlist = NULL;
 	struct ifaddrs *ifap, *ifa;
@@ -168,12 +169,51 @@
 	 * those.
 	 */
 	if (getifaddrs(&ifap) != 0) {
-		(void)snprintf(errbuf, PCAP_ERRBUF_SIZE,
+		(void)pcap_snprintf(errbuf, PCAP_ERRBUF_SIZE,
 		    "getifaddrs: %s", pcap_strerror(errno));
 		return (-1);
 	}
 	for (ifa = ifap; ifa != NULL; ifa = ifa->ifa_next) {
 		/*
+		 * If this entry has a colon followed by a number at
+		 * the end, we assume it's a logical interface.  Those
+		 * are just the way you assign multiple IP addresses to
+		 * a real interface on Linux, so an entry for a logical
+		 * interface should be treated like the entry for the
+		 * real interface; we do that by stripping off the ":"
+		 * and the number.
+		 *
+		 * XXX - should we do this only on Linux?
+		 */
+		p = strchr(ifa->ifa_name, ':');
+		if (p != NULL) {
+			/*
+			 * We have a ":"; is it followed by a number?
+			 */
+			q = p + 1;
+			while (isdigit((unsigned char)*q))
+				q++;
+			if (*q == '\0') {
+				/*
+				 * All digits after the ":" until the end.
+				 * Strip off the ":" and everything after
+				 * it.
+				 */
+			       *p = '\0';
+			}
+		}
+
+		/*
+		 * Can we capture on this device?
+		 */
+		if (!(*check_usable)(ifa->ifa_name)) {
+			/*
+			 * No.
+			 */
+			continue;
+		}
+
+		/*
 		 * "ifa_addr" was apparently null on at least one
 		 * interface on some system.  Therefore, we supply
 		 * the address and netmask only if "ifa_addr" is
@@ -223,39 +263,11 @@
 		}
 
 		/*
-		 * If this entry has a colon followed by a number at
-		 * the end, we assume it's a logical interface.  Those
-		 * are just the way you assign multiple IP addresses to
-		 * a real interface on Linux, so an entry for a logical
-		 * interface should be treated like the entry for the
-		 * real interface; we do that by stripping off the ":"
-		 * and the number.
-		 *
-		 * XXX - should we do this only on Linux?
-		 */
-		p = strchr(ifa->ifa_name, ':');
-		if (p != NULL) {
-			/*
-			 * We have a ":"; is it followed by a number?
-			 */
-			q = p + 1;
-			while (isdigit((unsigned char)*q))
-				q++;
-			if (*q == '\0') {
-				/*
-				 * All digits after the ":" until the end.
-				 * Strip off the ":" and everything after
-				 * it.
-				 */
-			       *p = '\0';
-			}
-		}
-
-		/*
 		 * Add information for this address to the list.
 		 */
 		if (add_addr_to_iflist(&devlist, ifa->ifa_name,
-		    ifa->ifa_flags, addr, addr_size, netmask, addr_size,
+		    if_flags_to_pcap_flags(ifa->ifa_name, ifa->ifa_flags),
+		    addr, addr_size, netmask, addr_size,
 		    broadaddr, broadaddr_size, dstaddr, dstaddr_size,
 		    errbuf) < 0) {
 			ret = -1;
diff --git a/fad-gifc.c b/fad-gifc.c
index b0a4105..1b24af2 100644
--- a/fad-gifc.c
+++ b/fad-gifc.c
@@ -132,12 +132,13 @@
  * we already have that.
  */
 int
-pcap_findalldevs_interfaces(pcap_if_t **alldevsp, char *errbuf)
+pcap_findalldevs_interfaces(pcap_if_t **alldevsp, char *errbuf,
+    int (*check_usable)(const char *))
 {
 	pcap_if_t *devlist = NULL;
 	register int fd;
 	register struct ifreq *ifrp, *ifend, *ifnext;
-	int n;
+	size_t n;
 	struct ifconf ifc;
 	char *buf = NULL;
 	unsigned buf_size;
@@ -154,7 +155,7 @@
 	 */
 	fd = socket(AF_INET, SOCK_DGRAM, 0);
 	if (fd < 0) {
-		(void)snprintf(errbuf, PCAP_ERRBUF_SIZE,
+		(void)pcap_snprintf(errbuf, PCAP_ERRBUF_SIZE,
 		    "socket: %s", pcap_strerror(errno));
 		return (-1);
 	}
@@ -170,7 +171,7 @@
 	for (;;) {
 		buf = malloc(buf_size);
 		if (buf == NULL) {
-			(void)snprintf(errbuf, PCAP_ERRBUF_SIZE,
+			(void)pcap_snprintf(errbuf, PCAP_ERRBUF_SIZE,
 			    "malloc: %s", pcap_strerror(errno));
 			(void)close(fd);
 			return (-1);
@@ -181,7 +182,7 @@
 		memset(buf, 0, buf_size);
 		if (ioctl(fd, SIOCGIFCONF, (char *)&ifc) < 0
 		    && errno != EINVAL) {
-			(void)snprintf(errbuf, PCAP_ERRBUF_SIZE,
+			(void)pcap_snprintf(errbuf, PCAP_ERRBUF_SIZE,
 			    "SIOCGIFCONF: %s", pcap_strerror(errno));
 			(void)close(fd);
 			free(buf);
@@ -237,6 +238,16 @@
 			continue;
 
 		/*
+		 * Can we capture on this device?
+		 */
+		if (!(*check_usable)(ifrp->ifr_name)) {
+			/*
+			 * No.
+			 */
+			continue;
+		}
+
+		/*
 		 * Get the flags for this interface.
 		 */
 		strncpy(ifrflags.ifr_name, ifrp->ifr_name,
@@ -244,7 +255,7 @@
 		if (ioctl(fd, SIOCGIFFLAGS, (char *)&ifrflags) < 0) {
 			if (errno == ENXIO)
 				continue;
-			(void)snprintf(errbuf, PCAP_ERRBUF_SIZE,
+			(void)pcap_snprintf(errbuf, PCAP_ERRBUF_SIZE,
 			    "SIOCGIFFLAGS: %.*s: %s",
 			    (int)sizeof(ifrflags.ifr_name),
 			    ifrflags.ifr_name,
@@ -268,7 +279,7 @@
 				netmask = NULL;
 				netmask_size = 0;
 			} else {
-				(void)snprintf(errbuf, PCAP_ERRBUF_SIZE,
+				(void)pcap_snprintf(errbuf, PCAP_ERRBUF_SIZE,
 				    "SIOCGIFNETMASK: %.*s: %s",
 				    (int)sizeof(ifrnetmask.ifr_name),
 				    ifrnetmask.ifr_name,
@@ -299,7 +310,7 @@
 					broadaddr = NULL;
 					broadaddr_size = 0;
 				} else {
-					(void)snprintf(errbuf, PCAP_ERRBUF_SIZE,
+					(void)pcap_snprintf(errbuf, PCAP_ERRBUF_SIZE,
 					    "SIOCGIFBRDADDR: %.*s: %s",
 					    (int)sizeof(ifrbroadaddr.ifr_name),
 					    ifrbroadaddr.ifr_name,
@@ -338,7 +349,7 @@
 					dstaddr = NULL;
 					dstaddr_size = 0;
 				} else {
-					(void)snprintf(errbuf, PCAP_ERRBUF_SIZE,
+					(void)pcap_snprintf(errbuf, PCAP_ERRBUF_SIZE,
 					    "SIOCGIFDSTADDR: %.*s: %s",
 					    (int)sizeof(ifrdstaddr.ifr_name),
 					    ifrdstaddr.ifr_name,
@@ -391,10 +402,10 @@
 		 * Add information for this address to the list.
 		 */
 		if (add_addr_to_iflist(&devlist, ifrp->ifr_name,
-		    ifrflags.ifr_flags, &ifrp->ifr_addr,
-		    SA_LEN(&ifrp->ifr_addr), netmask, netmask_size,
-		    broadaddr, broadaddr_size, dstaddr, dstaddr_size,
-		    errbuf) < 0) {
+		    if_flags_to_pcap_flags(ifrp->ifr_name, ifrflags.ifr_flags),
+		    &ifrp->ifr_addr, SA_LEN(&ifrp->ifr_addr),
+		    netmask, netmask_size, broadaddr, broadaddr_size,
+		    dstaddr, dstaddr_size, errbuf) < 0) {
 			ret = -1;
 			break;
 		}
diff --git a/fad-glifc.c b/fad-glifc.c
index 1a820ad..511481c 100644
--- a/fad-glifc.c
+++ b/fad-glifc.c
@@ -75,7 +75,8 @@
  * SIOCGLIFCONF rather than SIOCGIFCONF in order to get IPv6 addresses.)
  */
 int
-pcap_findalldevs_interfaces(pcap_if_t **alldevsp, char *errbuf)
+pcap_findalldevs_interfaces(pcap_if_t **alldevsp, char *errbuf,
+    int (*check_usable)(const char *))
 {
 	pcap_if_t *devlist = NULL;
 	register int fd4, fd6, fd;
@@ -97,7 +98,7 @@
 	 */
 	fd4 = socket(AF_INET, SOCK_DGRAM, 0);
 	if (fd4 < 0) {
-		(void)snprintf(errbuf, PCAP_ERRBUF_SIZE,
+		(void)pcap_snprintf(errbuf, PCAP_ERRBUF_SIZE,
 		    "socket: %s", pcap_strerror(errno));
 		return (-1);
 	}
@@ -107,7 +108,7 @@
 	 */
 	fd6 = socket(AF_INET6, SOCK_DGRAM, 0);
 	if (fd6 < 0) {
-		(void)snprintf(errbuf, PCAP_ERRBUF_SIZE,
+		(void)pcap_snprintf(errbuf, PCAP_ERRBUF_SIZE,
 		    "socket: %s", pcap_strerror(errno));
 		(void)close(fd4);
 		return (-1);
@@ -120,7 +121,7 @@
 	ifn.lifn_flags = 0;
 	ifn.lifn_count = 0;
 	if (ioctl(fd4, SIOCGLIFNUM, (char *)&ifn) < 0) {
-		(void)snprintf(errbuf, PCAP_ERRBUF_SIZE,
+		(void)pcap_snprintf(errbuf, PCAP_ERRBUF_SIZE,
 		    "SIOCGLIFNUM: %s", pcap_strerror(errno));
 		(void)close(fd6);
 		(void)close(fd4);
@@ -133,7 +134,7 @@
 	buf_size = ifn.lifn_count * sizeof (struct lifreq);
 	buf = malloc(buf_size);
 	if (buf == NULL) {
-		(void)snprintf(errbuf, PCAP_ERRBUF_SIZE,
+		(void)pcap_snprintf(errbuf, PCAP_ERRBUF_SIZE,
 		    "malloc: %s", pcap_strerror(errno));
 		(void)close(fd6);
 		(void)close(fd4);
@@ -149,7 +150,7 @@
 	ifc.lifc_flags = 0;
 	memset(buf, 0, buf_size);
 	if (ioctl(fd4, SIOCGLIFCONF, (char *)&ifc) < 0) {
-		(void)snprintf(errbuf, PCAP_ERRBUF_SIZE,
+		(void)pcap_snprintf(errbuf, PCAP_ERRBUF_SIZE,
 		    "SIOCGLIFCONF: %s", pcap_strerror(errno));
 		(void)close(fd6);
 		(void)close(fd4);
@@ -165,14 +166,6 @@
 
 	for (; ifrp < ifend; ifrp++) {
 		/*
-		 * IPv6 or not?
-		 */
-		if (((struct sockaddr *)&ifrp->lifr_addr)->sa_family == AF_INET6)
-			fd = fd6;
-		else
-			fd = fd4;
-
-		/*
 		 * Skip entries that begin with "dummy".
 		 * XXX - what are these?  Is this Linux-specific?
 		 * Are there platforms on which we shouldn't do this?
@@ -180,27 +173,23 @@
 		if (strncmp(ifrp->lifr_name, "dummy", 5) == 0)
 			continue;
 
-#ifdef HAVE_SOLARIS
 		/*
-		 * Skip entries that have a ":" followed by a number
-		 * at the end - those are Solaris virtual interfaces
-		 * on which you can't capture.
+		 * Can we capture on this device?
 		 */
-		p = strchr(ifrp->lifr_name, ':');
-		if (p != NULL) {
+		if (!(*check_usable)(ifrp->lifr_name)) {
 			/*
-			 * We have a ":"; is it followed by a number?
+			 * No.
 			 */
-			while (isdigit((unsigned char)*p))
-				p++;
-			if (*p == '\0') {
-				/*
-				 * All digits after the ":" until the end.
-				 */
-				continue;
-			}
+			continue;
 		}
-#endif
+
+		/*
+		 * IPv6 or not?
+		 */
+		if (((struct sockaddr *)&ifrp->lifr_addr)->sa_family == AF_INET6)
+			fd = fd6;
+		else
+			fd = fd4;
 
 		/*
 		 * Get the flags for this interface.
@@ -210,7 +199,7 @@
 		if (ioctl(fd, SIOCGLIFFLAGS, (char *)&ifrflags) < 0) {
 			if (errno == ENXIO)
 				continue;
-			(void)snprintf(errbuf, PCAP_ERRBUF_SIZE,
+			(void)pcap_snprintf(errbuf, PCAP_ERRBUF_SIZE,
 			    "SIOCGLIFFLAGS: %.*s: %s",
 			    (int)sizeof(ifrflags.lifr_name),
 			    ifrflags.lifr_name,
@@ -233,7 +222,7 @@
 				 */
 				netmask = NULL;
 			} else {
-				(void)snprintf(errbuf, PCAP_ERRBUF_SIZE,
+				(void)pcap_snprintf(errbuf, PCAP_ERRBUF_SIZE,
 				    "SIOCGLIFNETMASK: %.*s: %s",
 				    (int)sizeof(ifrnetmask.lifr_name),
 				    ifrnetmask.lifr_name,
@@ -261,7 +250,7 @@
 					 */
 					broadaddr = NULL;
 				} else {
-					(void)snprintf(errbuf, PCAP_ERRBUF_SIZE,
+					(void)pcap_snprintf(errbuf, PCAP_ERRBUF_SIZE,
 					    "SIOCGLIFBRDADDR: %.*s: %s",
 					    (int)sizeof(ifrbroadaddr.lifr_name),
 					    ifrbroadaddr.lifr_name,
@@ -296,7 +285,7 @@
 					 */
 					dstaddr = NULL;
 				} else {
-					(void)snprintf(errbuf, PCAP_ERRBUF_SIZE,
+					(void)pcap_snprintf(errbuf, PCAP_ERRBUF_SIZE,
 					    "SIOCGLIFDSTADDR: %.*s: %s",
 					    (int)sizeof(ifrdstaddr.lifr_name),
 					    ifrdstaddr.lifr_name,
@@ -341,7 +330,8 @@
 		 * Add information for this address to the list.
 		 */
 		if (add_addr_to_iflist(&devlist, ifrp->lifr_name,
-		    ifrflags.lifr_flags, (struct sockaddr *)&ifrp->lifr_addr,
+		    if_flags_to_pcap_flags(ifrp->lifr_name, ifrflags.lifr_flags),
+		    (struct sockaddr *)&ifrp->lifr_addr,
 		    sizeof (struct sockaddr_storage),
 		    netmask, sizeof (struct sockaddr_storage),
 		    broadaddr, sizeof (struct sockaddr_storage),
diff --git a/fad-helpers.c b/fad-helpers.c
new file mode 100644
index 0000000..4860bc5
--- /dev/null
+++ b/fad-helpers.c
@@ -0,0 +1,884 @@
+/* -*- Mode: c; tab-width: 8; indent-tabs-mode: 1; c-basic-offset: 8; -*- */
+/*
+ * Copyright (c) 1994, 1995, 1996, 1997, 1998
+ *	The Regents of the University of California.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *	This product includes software developed by the Computer Systems
+ *	Engineering Group at Lawrence Berkeley Laboratory.
+ * 4. Neither the name of the University nor of the Laboratory may be used
+ *    to endorse or promote products derived from this software without
+ *    specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#ifdef _WIN32
+#include <pcap-stdinc.h>
+#else /* _WIN32 */
+
+#include <sys/param.h>
+#ifndef MSDOS
+#include <sys/file.h>
+#endif
+#include <sys/ioctl.h>
+#include <sys/socket.h>
+#ifdef HAVE_SYS_SOCKIO_H
+#include <sys/sockio.h>
+#endif
+
+struct mbuf;		/* Squelch compiler warnings on some platforms for */
+struct rtentry;		/* declarations in <net/if.h> */
+#include <net/if.h>
+#include <netinet/in.h>
+#endif /* _WIN32 */
+
+#include <ctype.h>
+#include <errno.h>
+#include <memory.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#if !defined(_WIN32) && !defined(__BORLANDC__)
+#include <unistd.h>
+#endif /* !_WIN32 && !__BORLANDC__ */
+#ifdef HAVE_LIMITS_H
+#include <limits.h>
+#else
+#define INT_MAX		2147483647
+#endif
+
+#include "pcap-int.h"
+
+#ifdef HAVE_OS_PROTO_H
+#include "os-proto.h"
+#endif
+
+#ifndef _WIN32
+/* Not all systems have IFF_LOOPBACK */
+#ifdef IFF_LOOPBACK
+#define ISLOOPBACK(name, flags) ((flags) & IFF_LOOPBACK)
+#else
+#define ISLOOPBACK(name, flags) ((name)[0] == 'l' && (name)[1] == 'o' && \
+    (isdigit((unsigned char)((name)[2])) || (name)[2] == '\0'))
+#endif
+
+#ifdef IFF_UP
+#define ISUP(flags) ((flags) & IFF_UP)
+#else
+#define ISUP(flags) 0
+#endif
+
+#ifdef IFF_RUNNING
+#define ISRUNNING(flags) ((flags) & IFF_RUNNING)
+#else
+#define ISRUNNING(flags) 0
+#endif
+
+/*
+ * Map UN*X-style interface flags to libpcap flags.
+ */
+bpf_u_int32
+if_flags_to_pcap_flags(const char *name _U_, u_int if_flags)
+{
+	bpf_u_int32 pcap_flags;
+
+	pcap_flags = 0;
+	if (ISLOOPBACK(name, if_flags))
+		pcap_flags |= PCAP_IF_LOOPBACK;
+	if (ISUP(if_flags))
+		pcap_flags |= PCAP_IF_UP;
+	if (ISRUNNING(if_flags))
+		pcap_flags |= PCAP_IF_RUNNING;
+	return (pcap_flags);
+}
+#endif
+
+static struct sockaddr *
+dup_sockaddr(struct sockaddr *sa, size_t sa_length)
+{
+	struct sockaddr *newsa;
+
+	if ((newsa = malloc(sa_length)) == NULL)
+		return (NULL);
+	return (memcpy(newsa, sa, sa_length));
+}
+
+/*
+ * Construct a "figure of merit" for an interface, for use when sorting
+ * the list of interfaces, in which interfaces that are up are superior
+ * to interfaces that aren't up, interfaces that are up and running are
+ * superior to interfaces that are up but not running, and non-loopback
+ * interfaces that are up and running are superior to loopback interfaces,
+ * and interfaces with the same flags have a figure of merit that's higher
+ * the lower the instance number.
+ *
+ * The goal is to try to put the interfaces most likely to be useful for
+ * capture at the beginning of the list.
+ *
+ * The figure of merit, which is lower the "better" the interface is,
+ * has the uppermost bit set if the interface isn't running, the bit
+ * below that set if the interface isn't up, the bit below that set
+ * if the interface is a loopback interface, and the interface index
+ * in the 29 bits below that.  (Yes, we assume u_int is 32 bits.)
+ */
+static u_int
+get_figure_of_merit(pcap_if_t *dev)
+{
+	const char *cp;
+	u_int n;
+
+	if (strcmp(dev->name, "any") == 0) {
+		/*
+		 * Give the "any" device an artificially high instance
+		 * number, so it shows up after all other non-loopback
+		 * interfaces.
+		 */
+		n = 0x1FFFFFFF;	/* 29 all-1 bits */
+	} else {
+		/*
+		 * A number at the end of the device name string is
+		 * assumed to be a unit number.
+		 */
+		cp = dev->name + strlen(dev->name) - 1;
+		while (cp-1 >= dev->name && *(cp-1) >= '0' && *(cp-1) <= '9')
+			cp--;
+		if (*cp >= '0' && *cp <= '9')
+			n = atoi(cp);
+		else
+			n = 0;
+	}
+	if (!(dev->flags & PCAP_IF_RUNNING))
+		n |= 0x80000000;
+	if (!(dev->flags & PCAP_IF_UP))
+		n |= 0x40000000;
+	if (dev->flags & PCAP_IF_LOOPBACK)
+		n |= 0x20000000;
+	return (n);
+}
+
+/*
+ * Try to get a description for a given device.
+ * Returns a mallocated description if it could and NULL if it couldn't.
+ *
+ * XXX - on FreeBSDs that support it, should it get the sysctl named
+ * "dev.{adapter family name}.{adapter unit}.%desc" to get a description
+ * of the adapter?  Note that "dev.an.0.%desc" is "Aironet PC4500/PC4800"
+ * with my Cisco 350 card, so the name isn't entirely descriptive.  The
+ * "dev.an.0.%pnpinfo" has a better description, although one might argue
+ * that the problem is really a driver bug - if it can find out that it's
+ * a Cisco 340 or 350, rather than an old Aironet card, it should use
+ * that in the description.
+ *
+ * Do NetBSD, DragonflyBSD, or OpenBSD support this as well?  FreeBSD
+ * and OpenBSD let you get a description, but it's not generated by the OS,
+ * it's set with another ioctl that ifconfig supports; we use that to get
+ * a description in FreeBSD and OpenBSD, but if there is no such
+ * description available, it still might be nice to get some description
+ * string based on the device type or something such as that.
+ *
+ * In OS X, the System Configuration framework can apparently return
+ * names in 10.4 and later.
+ *
+ * It also appears that freedesktop.org's HAL offers an "info.product"
+ * string, but the HAL specification says it "should not be used in any
+ * UI" and "subsystem/capability specific properties" should be used
+ * instead and, in any case, I think HAL is being deprecated in
+ * favor of other stuff such as DeviceKit.  DeviceKit doesn't appear
+ * to have any obvious product information for devices, but maybe
+ * I haven't looked hard enough.
+ *
+ * Using the System Configuration framework, or HAL, or DeviceKit, or
+ * whatever, would require that libpcap applications be linked with
+ * the frameworks/libraries in question.  That shouldn't be a problem
+ * for programs linking with the shared version of libpcap (unless
+ * you're running on AIX - which I think is the only UN*X that doesn't
+ * support linking a shared library with other libraries on which it
+ * depends, and having an executable linked only with the first shared
+ * library automatically pick up the other libraries when started -
+ * and using HAL or whatever).  Programs linked with the static
+ * version of libpcap would have to use pcap-config with the --static
+ * flag in order to get the right linker flags in order to pick up
+ * the additional libraries/frameworks; those programs need that anyway
+ * for libpcap 1.1 and beyond on Linux, as, by default, it requires
+ * -lnl.
+ *
+ * Do any other UN*Xes, or desktop environments support getting a
+ * description?
+ */
+static char *
+get_if_description(const char *name)
+{
+#ifdef SIOCGIFDESCR
+	char *description = NULL;
+	int s;
+	struct ifreq ifrdesc;
+#ifndef IFDESCRSIZE
+	size_t descrlen = 64;
+#else
+	size_t descrlen = IFDESCRSIZE;
+#endif /* IFDESCRSIZE */
+
+	/*
+	 * Get the description for the interface.
+	 */
+	memset(&ifrdesc, 0, sizeof ifrdesc);
+	strlcpy(ifrdesc.ifr_name, name, sizeof ifrdesc.ifr_name);
+	s = socket(AF_INET, SOCK_DGRAM, 0);
+	if (s >= 0) {
+#ifdef __FreeBSD__
+		/*
+		 * On FreeBSD, if the buffer isn't big enough for the
+		 * description, the ioctl succeeds, but the description
+		 * isn't copied, ifr_buffer.length is set to the description
+		 * length, and ifr_buffer.buffer is set to NULL.
+		 */
+		for (;;) {
+			free(description);
+			if ((description = malloc(descrlen)) != NULL) {
+				ifrdesc.ifr_buffer.buffer = description;
+				ifrdesc.ifr_buffer.length = descrlen;
+				if (ioctl(s, SIOCGIFDESCR, &ifrdesc) == 0) {
+					if (ifrdesc.ifr_buffer.buffer ==
+					    description)
+						break;
+					else
+						descrlen = ifrdesc.ifr_buffer.length;
+				} else {
+					/*
+					 * Failed to get interface description.
+					 */
+					free(description);
+					description = NULL;
+					break;
+				}
+			} else
+				break;
+		}
+#else /* __FreeBSD__ */
+		/*
+		 * The only other OS that currently supports
+		 * SIOCGIFDESCR is OpenBSD, and it has no way
+		 * to get the description length - it's clamped
+		 * to a maximum of IFDESCRSIZE.
+		 */
+		if ((description = malloc(descrlen)) != NULL) {
+			ifrdesc.ifr_data = (caddr_t)description;
+			if (ioctl(s, SIOCGIFDESCR, &ifrdesc) != 0) {
+				/*
+				 * Failed to get interface description.
+				 */
+				free(description);
+				description = NULL;
+			}
+		}
+#endif /* __FreeBSD__ */
+		close(s);
+		if (description != NULL && strlen(description) == 0) {
+			/*
+			 * Description is empty, so discard it.
+			 */
+			free(description);
+			description = NULL;
+		}
+	}
+
+#ifdef __FreeBSD__
+	/*
+	 * For FreeBSD, if we didn't get a description, and this is
+	 * a device with a name of the form usbusN, label it as a USB
+	 * bus.
+	 */
+	if (description == NULL) {
+		if (strncmp(name, "usbus", 5) == 0) {
+			/*
+			 * OK, it begins with "usbus".
+			 */
+			long busnum;
+			char *p;
+
+			errno = 0;
+			busnum = strtol(name + 5, &p, 10);
+			if (errno == 0 && p != name + 5 && *p == '\0' &&
+			    busnum >= 0 && busnum <= INT_MAX) {
+				/*
+				 * OK, it's a valid number that's not
+				 * bigger than INT_MAX.  Construct
+				 * a description from it.
+				 */
+				static const char descr_prefix[] = "USB bus number ";
+				size_t descr_size;
+
+				/*
+				 * Allow enough room for a 32-bit bus number.
+				 * sizeof (descr_prefix) includes the
+				 * terminating NUL.
+				 */
+				descr_size = sizeof (descr_prefix) + 10;
+				description = malloc(descr_size);
+				if (description != NULL) {
+					pcap_snprintf(description, descr_size,
+					    "%s%ld", descr_prefix, busnum);
+				}
+			}
+		}
+	}
+#endif
+	return (description);
+#else /* SIOCGIFDESCR */
+	return (NULL);
+#endif /* SIOCGIFDESCR */
+}
+
+/*
+ * Look for a given device in the specified list of devices.
+ *
+ * If we find it, return 0 and set *curdev_ret to point to it.
+ *
+ * If we don't find it, check whether we can open it:
+ *
+ *     If that fails with PCAP_ERROR_NO_SUCH_DEVICE or
+ *     PCAP_ERROR_IFACE_NOT_UP, don't attempt to add an entry for
+ *     it, as that probably means it exists but doesn't support
+ *     packet capture.
+ *
+ *     Otherwise, attempt to add an entry for it, with the specified
+ *     ifnet flags and description, and, if that succeeds, return 0
+ *     and set *curdev_ret to point to the new entry, otherwise
+ *     return PCAP_ERROR and set errbuf to an error message.  If we
+ *     weren't given a description, try to get one.
+ */
+int
+add_or_find_if(pcap_if_t **curdev_ret, pcap_if_t **alldevs, const char *name,
+    bpf_u_int32 flags, const char *description, char *errbuf)
+{
+	pcap_t *p;
+	pcap_if_t *curdev, *prevdev, *nextdev;
+	u_int this_figure_of_merit, nextdev_figure_of_merit;
+	char open_errbuf[PCAP_ERRBUF_SIZE];
+	int ret;
+
+	/*
+	 * Is there already an entry in the list for this interface?
+	 */
+	for (curdev = *alldevs; curdev != NULL; curdev = curdev->next) {
+		if (strcmp(name, curdev->name) == 0)
+			break;	/* yes, we found it */
+	}
+
+	if (curdev == NULL) {
+		/*
+		 * No, we didn't find it.
+		 *
+		 * Can we open this interface for live capture?
+		 *
+		 * We do this check so that interfaces that are
+		 * supplied by the interface enumeration mechanism
+		 * we're using but that don't support packet capture
+		 * aren't included in the list.  Loopback interfaces
+		 * on Solaris are an example of this; we don't just
+		 * omit loopback interfaces on all platforms because
+		 * you *can* capture on loopback interfaces on some
+		 * OSes.
+		 *
+		 * On OS X, we don't do this check if the device
+		 * name begins with "wlt"; at least some versions
+		 * of OS X offer monitor mode capturing by having
+		 * a separate "monitor mode" device for each wireless
+		 * adapter, rather than by implementing the ioctls
+		 * that {Free,Net,Open,DragonFly}BSD provide.
+		 * Opening that device puts the adapter into monitor
+		 * mode, which, at least for some adapters, causes
+		 * them to deassociate from the network with which
+		 * they're associated.
+		 *
+		 * Instead, we try to open the corresponding "en"
+		 * device (so that we don't end up with, for users
+		 * without sufficient privilege to open capture
+		 * devices, a list of adapters that only includes
+		 * the wlt devices).
+		 */
+#ifdef __APPLE__
+		if (strncmp(name, "wlt", 3) == 0) {
+			char *en_name;
+			size_t en_name_len;
+
+			/*
+			 * Try to allocate a buffer for the "en"
+			 * device's name.
+			 */
+			en_name_len = strlen(name) - 1;
+			en_name = malloc(en_name_len + 1);
+			if (en_name == NULL) {
+				(void)pcap_snprintf(errbuf, PCAP_ERRBUF_SIZE,
+				    "malloc: %s", pcap_strerror(errno));
+				return (-1);
+			}
+			strcpy(en_name, "en");
+			strcat(en_name, name + 3);
+			p = pcap_create(en_name, open_errbuf);
+			free(en_name);
+		} else
+#endif /* __APPLE */
+		p = pcap_create(name, open_errbuf);
+		if (p == NULL) {
+			/*
+			 * The attempt to create the pcap_t failed;
+			 * that's probably an indication that we're
+			 * out of memory.
+			 *
+			 * Don't bother including this interface,
+			 * but don't treat it as an error.
+			 */
+			*curdev_ret = NULL;
+			return (0);
+		}
+		/* Small snaplen, so we don't try to allocate much memory. */
+		pcap_set_snaplen(p, 68);
+		ret = pcap_activate(p);
+		pcap_close(p);
+		switch (ret) {
+
+		case PCAP_ERROR_NO_SUCH_DEVICE:
+		case PCAP_ERROR_IFACE_NOT_UP:
+			/*
+			 * We expect these two errors - they're the
+			 * reason we try to open the device.
+			 *
+			 * PCAP_ERROR_NO_SUCH_DEVICE typically means
+			 * "there's no such device *known to the
+			 * OS's capture mechanism*", so, even though
+			 * it might be a valid network interface, you
+			 * can't capture on it (e.g., the loopback
+			 * device in Solaris up to Solaris 10, or
+			 * the vmnet devices in OS X with VMware
+			 * Fusion).  We don't include those devices
+			 * in our list of devices, as there's no
+			 * point in doing so - they're not available
+			 * for capture.
+			 *
+			 * PCAP_ERROR_IFACE_NOT_UP means that the
+			 * OS's capture mechanism doesn't work on
+			 * interfaces not marked as up; some capture
+			 * mechanisms *do* support that, so we no
+			 * longer reject those interfaces out of hand,
+			 * but we *do* want to reject them if they
+			 * can't be opened for capture.
+			 */
+			*curdev_ret = NULL;
+			return (0);
+		}
+
+		/*
+		 * Yes, we can open it, or we can't, for some other
+		 * reason.
+		 *
+		 * If we can open it, we want to offer it for
+		 * capture, as you can capture on it.  If we can't,
+		 * we want to offer it for capture, so that, if
+		 * the user tries to capture on it, they'll get
+		 * an error and they'll know why they can't
+		 * capture on it (e.g., insufficient permissions)
+		 * or they'll report it as a problem (and then
+		 * have the error message to provide as information).
+		 *
+		 * Allocate a new entry.
+		 */
+		curdev = malloc(sizeof(pcap_if_t));
+		if (curdev == NULL) {
+			(void)pcap_snprintf(errbuf, PCAP_ERRBUF_SIZE,
+			    "malloc: %s", pcap_strerror(errno));
+			return (-1);
+		}
+
+		/*
+		 * Fill in the entry.
+		 */
+		curdev->next = NULL;
+		curdev->name = strdup(name);
+		if (curdev->name == NULL) {
+			(void)pcap_snprintf(errbuf, PCAP_ERRBUF_SIZE,
+			    "malloc: %s", pcap_strerror(errno));
+			free(curdev);
+			return (-1);
+		}
+		if (description == NULL) {
+			/*
+			 * We weren't handed a description for the
+			 * interface, so see if we can generate one
+			 * ourselves.
+			 */
+			curdev->description = get_if_description(name);
+		} else {
+			/*
+			 * We were handed a description; make a copy.
+			 */
+			curdev->description = strdup(description);
+			if (curdev->description == NULL) {
+				(void)pcap_snprintf(errbuf, PCAP_ERRBUF_SIZE,
+				    "malloc: %s", pcap_strerror(errno));
+				free(curdev->name);
+				free(curdev);
+				return (-1);
+			}
+		}
+		curdev->addresses = NULL;	/* list starts out as empty */
+		curdev->flags = flags;
+
+		/*
+		 * Add it to the list, in the appropriate location.
+		 * First, get the "figure of merit" for this
+		 * interface.
+		 */
+		this_figure_of_merit = get_figure_of_merit(curdev);
+
+		/*
+		 * Now look for the last interface with an figure of merit
+		 * less than or equal to the new interface's figure of
+		 * merit.
+		 *
+		 * We start with "prevdev" being NULL, meaning we're before
+		 * the first element in the list.
+		 */
+		prevdev = NULL;
+		for (;;) {
+			/*
+			 * Get the interface after this one.
+			 */
+			if (prevdev == NULL) {
+				/*
+				 * The next element is the first element.
+				 */
+				nextdev = *alldevs;
+			} else
+				nextdev = prevdev->next;
+
+			/*
+			 * Are we at the end of the list?
+			 */
+			if (nextdev == NULL) {
+				/*
+				 * Yes - we have to put the new entry
+				 * after "prevdev".
+				 */
+				break;
+			}
+
+			/*
+			 * Is the new interface's figure of merit less
+			 * than the next interface's figure of merit,
+			 * meaning that the new interface is better
+			 * than the next interface?
+			 */
+			nextdev_figure_of_merit = get_figure_of_merit(nextdev);
+			if (this_figure_of_merit < nextdev_figure_of_merit) {
+				/*
+				 * Yes - we should put the new entry
+				 * before "nextdev", i.e. after "prevdev".
+				 */
+				break;
+			}
+
+			prevdev = nextdev;
+		}
+
+		/*
+		 * Insert before "nextdev".
+		 */
+		curdev->next = nextdev;
+
+		/*
+		 * Insert after "prevdev" - unless "prevdev" is null,
+		 * in which case this is the first interface.
+		 */
+		if (prevdev == NULL) {
+			/*
+			 * This is the first interface.  Pass back a
+			 * pointer to it, and put "curdev" before
+			 * "nextdev".
+			 */
+			*alldevs = curdev;
+		} else
+			prevdev->next = curdev;
+	}
+
+	*curdev_ret = curdev;
+	return (0);
+}
+
+/*
+ * Try to get a description for a given device, and then look for that
+ * device in the specified list of devices.
+ *
+ * If we find it, then, if the specified address isn't null, add it to
+ * the list of addresses for the device and return 0.
+ *
+ * If we don't find it, check whether we can open it:
+ *
+ *     If that fails with PCAP_ERROR_NO_SUCH_DEVICE or
+ *     PCAP_ERROR_IFACE_NOT_UP, don't attempt to add an entry for
+ *     it, as that probably means it exists but doesn't support
+ *     packet capture.
+ *
+ *     Otherwise, attempt to add an entry for it, with the specified
+ *     ifnet flags, and, if that succeeds, add the specified address
+ *     to its list of addresses if that address is non-null, set
+ *     *curdev_ret to point to the new entry, and return 0, otherwise
+ *     return PCAP_ERROR and set errbuf to an error message.
+ *
+ * (We can get called with a null address because we might get a list
+ * of interface name/address combinations from the underlying OS, with
+ * the address being absent in some cases, rather than a list of
+ * interfaces with each interface having a list of addresses, so this
+ * call may be the only call made to add to the list, and we want to
+ * add interfaces even if they have no addresses.)
+ */
+int
+add_addr_to_iflist(pcap_if_t **alldevs, const char *name, bpf_u_int32 flags,
+    struct sockaddr *addr, size_t addr_size,
+    struct sockaddr *netmask, size_t netmask_size,
+    struct sockaddr *broadaddr, size_t broadaddr_size,
+    struct sockaddr *dstaddr, size_t dstaddr_size,
+    char *errbuf)
+{
+	pcap_if_t *curdev;
+
+	if (add_or_find_if(&curdev, alldevs, name, flags, NULL, errbuf) == -1) {
+		/*
+		 * Error - give up.
+		 */
+		return (-1);
+	}
+	if (curdev == NULL) {
+		/*
+		 * Device wasn't added because it can't be opened.
+		 * Not a fatal error.
+		 */
+		return (0);
+	}
+
+	if (addr == NULL) {
+		/*
+		 * There's no address to add; this entry just meant
+		 * "here's a new interface".
+		 */
+		return (0);
+	}
+
+	/*
+	 * "curdev" is an entry for this interface, and we have an
+	 * address for it; add an entry for that address to the
+	 * interface's list of addresses.
+	 *
+	 * Allocate the new entry and fill it in.
+	 */
+	return (add_addr_to_dev(curdev, addr, addr_size, netmask,
+	    netmask_size, broadaddr, broadaddr_size, dstaddr,
+	    dstaddr_size, errbuf));
+}
+
+/*
+ * Add an entry to the list of addresses for an interface.
+ * "curdev" is the entry for that interface.
+ * If this is the first IP address added to the interface, move it
+ * in the list as appropriate.
+ */
+int
+add_addr_to_dev(pcap_if_t *curdev,
+    struct sockaddr *addr, size_t addr_size,
+    struct sockaddr *netmask, size_t netmask_size,
+    struct sockaddr *broadaddr, size_t broadaddr_size,
+    struct sockaddr *dstaddr, size_t dstaddr_size,
+    char *errbuf)
+{
+	pcap_addr_t *curaddr, *prevaddr, *nextaddr;
+
+	curaddr = malloc(sizeof(pcap_addr_t));
+	if (curaddr == NULL) {
+		(void)pcap_snprintf(errbuf, PCAP_ERRBUF_SIZE,
+		    "malloc: %s", pcap_strerror(errno));
+		return (-1);
+	}
+
+	curaddr->next = NULL;
+	if (addr != NULL) {
+		curaddr->addr = dup_sockaddr(addr, addr_size);
+		if (curaddr->addr == NULL) {
+			(void)pcap_snprintf(errbuf, PCAP_ERRBUF_SIZE,
+			    "malloc: %s", pcap_strerror(errno));
+			free(curaddr);
+			return (-1);
+		}
+	} else
+		curaddr->addr = NULL;
+
+	if (netmask != NULL) {
+		curaddr->netmask = dup_sockaddr(netmask, netmask_size);
+		if (curaddr->netmask == NULL) {
+			(void)pcap_snprintf(errbuf, PCAP_ERRBUF_SIZE,
+			    "malloc: %s", pcap_strerror(errno));
+			if (curaddr->addr != NULL)
+				free(curaddr->addr);
+			free(curaddr);
+			return (-1);
+		}
+	} else
+		curaddr->netmask = NULL;
+
+	if (broadaddr != NULL) {
+		curaddr->broadaddr = dup_sockaddr(broadaddr, broadaddr_size);
+		if (curaddr->broadaddr == NULL) {
+			(void)pcap_snprintf(errbuf, PCAP_ERRBUF_SIZE,
+			    "malloc: %s", pcap_strerror(errno));
+			if (curaddr->netmask != NULL)
+				free(curaddr->netmask);
+			if (curaddr->addr != NULL)
+				free(curaddr->addr);
+			free(curaddr);
+			return (-1);
+		}
+	} else
+		curaddr->broadaddr = NULL;
+
+	if (dstaddr != NULL) {
+		curaddr->dstaddr = dup_sockaddr(dstaddr, dstaddr_size);
+		if (curaddr->dstaddr == NULL) {
+			(void)pcap_snprintf(errbuf, PCAP_ERRBUF_SIZE,
+			    "malloc: %s", pcap_strerror(errno));
+			if (curaddr->broadaddr != NULL)
+				free(curaddr->broadaddr);
+			if (curaddr->netmask != NULL)
+				free(curaddr->netmask);
+			if (curaddr->addr != NULL)
+				free(curaddr->addr);
+			free(curaddr);
+			return (-1);
+		}
+	} else
+		curaddr->dstaddr = NULL;
+
+	/*
+	 * Find the end of the list of addresses.
+	 */
+	for (prevaddr = curdev->addresses; prevaddr != NULL; prevaddr = nextaddr) {
+		nextaddr = prevaddr->next;
+		if (nextaddr == NULL) {
+			/*
+			 * This is the end of the list.
+			 */
+			break;
+		}
+	}
+
+	if (prevaddr == NULL) {
+		/*
+		 * The list was empty; this is the first member.
+		 */
+		curdev->addresses = curaddr;
+	} else {
+		/*
+		 * "prevaddr" is the last member of the list; append
+		 * this member to it.
+		 */
+		prevaddr->next = curaddr;
+	}
+
+	return (0);
+}
+
+/*
+ * Look for a given device in the specified list of devices.
+ *
+ * If we find it, return 0.
+ *
+ * If we don't find it, check whether we can open it:
+ *
+ *     If that fails with PCAP_ERROR_NO_SUCH_DEVICE or
+ *     PCAP_ERROR_IFACE_NOT_UP, don't attempt to add an entry for
+ *     it, as that probably means it exists but doesn't support
+ *     packet capture.
+ *
+ *     Otherwise, attempt to add an entry for it, with the specified
+ *     ifnet flags and description, and, if that succeeds, return 0
+ *     and set *curdev_ret to point to the new entry, otherwise
+ *     return PCAP_ERROR and set errbuf to an error message.
+ */
+int
+pcap_add_if(pcap_if_t **devlist, const char *name, u_int flags,
+    const char *description, char *errbuf)
+{
+	pcap_if_t *curdev;
+
+	return (add_or_find_if(&curdev, devlist, name, flags, description,
+	    errbuf));
+}
+
+
+/*
+ * Free a list of interfaces.
+ */
+void
+pcap_freealldevs(pcap_if_t *alldevs)
+{
+	pcap_if_t *curdev, *nextdev;
+	pcap_addr_t *curaddr, *nextaddr;
+
+	for (curdev = alldevs; curdev != NULL; curdev = nextdev) {
+		nextdev = curdev->next;
+
+		/*
+		 * Free all addresses.
+		 */
+		for (curaddr = curdev->addresses; curaddr != NULL; curaddr = nextaddr) {
+			nextaddr = curaddr->next;
+			if (curaddr->addr)
+				free(curaddr->addr);
+			if (curaddr->netmask)
+				free(curaddr->netmask);
+			if (curaddr->broadaddr)
+				free(curaddr->broadaddr);
+			if (curaddr->dstaddr)
+				free(curaddr->dstaddr);
+			free(curaddr);
+		}
+
+		/*
+		 * Free the name string.
+		 */
+		free(curdev->name);
+
+		/*
+		 * Free the description string, if any.
+		 */
+		if (curdev->description != NULL)
+			free(curdev->description);
+
+		/*
+		 * Free the interface.
+		 */
+		free(curdev);
+	}
+}
diff --git a/fad-sita.c b/fad-sita.c
deleted file mode 100644
index 34ddf1d..0000000
--- a/fad-sita.c
+++ /dev/null
@@ -1,59 +0,0 @@
-/*
- *  fad-sita.c: Packet capture interface additions for SITA ACN devices
- *
- *  Copyright (c) 2007 Fulko Hew, SITA INC Canada, Inc <fulko.hew@sita.aero>
- *
- *  License: BSD
- *
- *  Redistribution and use in source and binary forms, with or without
- *  modification, are permitted provided that the following conditions
- *  are met:
- *
- *  1. Redistributions of source code must retain the above copyright
- *     notice, this list of conditions and the following disclaimer.
- *  2. Redistributions in binary form must reproduce the above copyright
- *     notice, this list of conditions and the following disclaimer in
- *     the documentation and/or other materials provided with the
- *     distribution.
- *  3. The names of the authors may not be used to endorse or promote
- *     products derived from this software without specific prior
- *     written permission.
- *
- *  THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
- *  IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
- *  WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
- */
-
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-
-#include <string.h>
-#include "pcap-int.h"
-
-#include "pcap-sita.h"
-
-extern pcap_if_t	*acn_if_list;								/* pcap's list of available interfaces */
-
-int pcap_findalldevs_interfaces(pcap_if_t **alldevsp, char *errbuf) {
-
-	//printf("pcap_findalldevs()\n");				// fulko
-
-	*alldevsp = 0;												/* initialize the returned variables before we do anything */
-	strcpy(errbuf, "");
-	if (acn_parse_hosts_file(errbuf))							/* scan the hosts file for potential IOPs */
-		{
-		//printf("pcap_findalldevs() returning BAD after parsehosts\n");				// fulko
-		return -1;
-		}
-	//printf("pcap_findalldevs() got hostlist now finding devs\n");				// fulko
-	if (acn_findalldevs(errbuf))								/* then ask the IOPs for their monitorable devices */
-		{
-		//printf("pcap_findalldevs() returning BAD after findalldevs\n");				// fulko
-		return -1;
-		}
-	*alldevsp = acn_if_list;
-	acn_if_list = 0;											/* then forget our list head, because someone will call pcap_freealldevs() to empty the malloc'ed stuff */
-	//printf("pcap_findalldevs() returning ZERO OK\n");				// fulko
-	return 0;
-}
diff --git a/fad-win32.c b/fad-win32.c
deleted file mode 100644
index 0c856b1..0000000
--- a/fad-win32.c
+++ /dev/null
@@ -1,248 +0,0 @@
-/*
- * Copyright (c) 2002 - 2005 NetGroup, Politecnico di Torino (Italy)
- * Copyright (c) 2005 - 2006 CACE Technologies, Davis (California)
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- * 3. Neither the name of the Politecnico di Torino, CACE Technologies
- * nor the names of its contributors may be used to endorse or promote
- * products derived from this software without specific prior written
- * permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
- */
-
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-
-#include <pcap.h>
-#include <pcap-int.h>
-#include <Packet32.h>
-
-#include <errno.h>
-
-static int
-pcap_add_if_win32(pcap_if_t **devlist, char *name, const char *desc,
-    char *errbuf)
-{
-	pcap_if_t *curdev;
-	npf_if_addr if_addrs[MAX_NETWORK_ADDRESSES];
-	LONG if_addr_size;
-	int res = 0;
-
-	if_addr_size = MAX_NETWORK_ADDRESSES;
-
-	/*
-	 * Add an entry for this interface, with no addresses.
-	 */
-	if (add_or_find_if(&curdev, devlist, name, 0, desc, errbuf) == -1) {
-		/*
-		 * Failure.
-		 */
-		return (-1);
-	}
-
-	/*
-	 * Get the list of addresses for the interface.
-	 */
-	if (!PacketGetNetInfoEx((void *)name, if_addrs, &if_addr_size)) {
-		/*
-		 * Failure.
-		 *
-		 * We don't return an error, because this can happen with
-		 * NdisWan interfaces, and we want to supply them even
-		 * if we can't supply their addresses.
-		 *
-		 * We return an entry with an empty address list.
-		 */
-		return (0);
-	}
-
-	/*
-	 * Now add the addresses.
-	 */
-	while (if_addr_size-- > 0) {
-		/*
-		 * "curdev" is an entry for this interface; add an entry for
-		 * this address to its list of addresses.
-		 */
-		if(curdev == NULL)
-			break;
-		res = add_addr_to_dev(curdev,
-		    (struct sockaddr *)&if_addrs[if_addr_size].IPAddress,
-		    sizeof (struct sockaddr_storage),
-		    (struct sockaddr *)&if_addrs[if_addr_size].SubnetMask,
-		    sizeof (struct sockaddr_storage),
-		    (struct sockaddr *)&if_addrs[if_addr_size].Broadcast,
-		    sizeof (struct sockaddr_storage),
-		    NULL,
-		    0,
-		    errbuf);
-		if (res == -1) {
-			/*
-			 * Failure.
-			 */
-			break;
-		}
-	}
-
-	return (res);
-}
-
-
-/*
- * Get a list of all interfaces that are up and that we can open.
- * Returns -1 on error, 0 otherwise.
- * The list, as returned through "alldevsp", may be null if no interfaces
- * were up and could be opened.
- *
- * Win32 implementation, based on WinPcap
- */
-int
-pcap_findalldevs_interfaces(pcap_if_t **alldevsp, char *errbuf)
-{
-	pcap_if_t *devlist = NULL;
-	int ret = 0;
-	const char *desc;
-	char *AdaptersName;
-	ULONG NameLength;
-	char *name;
-
-	/*
-	 * Find out how big a buffer we need.
-	 *
-	 * This call should always return FALSE; if the error is
-	 * ERROR_INSUFFICIENT_BUFFER, NameLength will be set to
-	 * the size of the buffer we need, otherwise there's a
-	 * problem, and NameLength should be set to 0.
-	 *
-	 * It shouldn't require NameLength to be set, but,
-	 * at least as of WinPcap 4.1.3, it checks whether
-	 * NameLength is big enough before it checks for a
-	 * NULL buffer argument, so, while it'll still do
-	 * the right thing if NameLength is uninitialized and
-	 * whatever junk happens to be there is big enough
-	 * (because the pointer argument will be null), it's
-	 * still reading an uninitialized variable.
-	 */
-	NameLength = 0;
-	if (!PacketGetAdapterNames(NULL, &NameLength))
-	{
-		DWORD last_error = GetLastError();
-
-		if (last_error != ERROR_INSUFFICIENT_BUFFER)
-		{
-			snprintf(errbuf, PCAP_ERRBUF_SIZE,
-				"PacketGetAdapterNames: %s",
-				pcap_win32strerror());
-			return (-1);
-		}
-	}
-
-	if (NameLength > 0)
-		AdaptersName = (char*) malloc(NameLength);
-	else
-	{
-		*alldevsp = NULL;
-		return 0;
-	}
-	if (AdaptersName == NULL)
-	{
-		snprintf(errbuf, PCAP_ERRBUF_SIZE, "Cannot allocate enough memory to list the adapters.");
-		return (-1);
-	}
-
-	if (!PacketGetAdapterNames(AdaptersName, &NameLength)) {
-		snprintf(errbuf, PCAP_ERRBUF_SIZE,
-			"PacketGetAdapterNames: %s",
-			pcap_win32strerror());
-		free(AdaptersName);
-		return (-1);
-	}
-
-	/*
-	 * "PacketGetAdapterNames()" returned a list of
-	 * null-terminated ASCII interface name strings,
-	 * terminated by a null string, followed by a list
-	 * of null-terminated ASCII interface description
-	 * strings, terminated by a null string.
-	 * This means there are two ASCII nulls at the end
-	 * of the first list.
-	 *
-	 * Find the end of the first list; that's the
-	 * beginning of the second list.
-	 */
-	desc = &AdaptersName[0];
-	while (*desc != '\0' || *(desc + 1) != '\0')
-		desc++;
-
-	/*
- 	 * Found it - "desc" points to the first of the two
-	 * nulls at the end of the list of names, so the
-	 * first byte of the list of descriptions is two bytes
-	 * after it.
-	 */
-	desc += 2;
-
-	/*
-	 * Loop over the elements in the first list.
-	 */
-	name = &AdaptersName[0];
-	while (*name != '\0') {
-		/*
-		 * Add an entry for this interface.
-		 */
-		if (pcap_add_if_win32(&devlist, name, desc, errbuf) == -1) {
-			/*
-			 * Failure.
-			 */
-			ret = -1;
-			break;
-		}
-		name += strlen(name) + 1;
-		desc += strlen(desc) + 1;
-	}
-
-	if (ret != -1) {
-		/*
-		 * We haven't had any errors yet; do any platform-specific
-		 * operations to add devices.
-		 */
-		if (pcap_platform_finddevs(&devlist, errbuf) < 0)
-			ret = -1;
-	}
-
-	if (ret == -1) {
-		/*
-		 * We had an error; free the list we've been constructing.
-		 */
-		if (devlist != NULL) {
-			pcap_freealldevs(devlist);
-			devlist = NULL;
-		}
-	}
-
-	*alldevsp = devlist;
-	free(AdaptersName);
-	return (ret);
-}
diff --git a/gen_version_c.sh b/gen_version_c.sh
new file mode 100755
index 0000000..d5a5e75
--- /dev/null
+++ b/gen_version_c.sh
@@ -0,0 +1,11 @@
+#! /bin/sh
+echo '#include <pcap/export-defs.h>' > "$2"
+echo 'PCAP_API_DEF' >> "$2"
+if grep GIT "$1" >/dev/null; then
+	read ver <"$1"
+	echo $ver | tr -d '\012'
+	date +_%Y_%m_%d
+else
+	cat "$1"
+fi | sed -e 's/.*/char pcap_version[] = "&";/' >> "$2"
+
diff --git a/gen_version_header.sh b/gen_version_header.sh
new file mode 100755
index 0000000..6b4b82d
--- /dev/null
+++ b/gen_version_header.sh
@@ -0,0 +1,19 @@
+#! /bin/sh
+print_version_string()
+{
+	if grep GIT "$1" >/dev/null
+	then
+		read ver <"$1"
+		echo $ver | tr -d '\012'
+		date +_%Y_%m_%d
+	else
+		cat "$1"
+	fi
+}
+if test $# != 3
+then
+	echo "Usage: gen_version_header.sh <version file> <template> <output file>" 1>&2
+	exit 1
+fi
+version_string=`print_version_string "$1"`
+sed "s/%%LIBPCAP_VERSION%%/$version_string/" "$2" >"$3"
diff --git a/gencode.c b/gencode.c
index ad938d4..a887f27 100644
--- a/gencode.c
+++ b/gencode.c
@@ -24,9 +24,9 @@
 #include "config.h"
 #endif
 
-#ifdef WIN32
+#ifdef _WIN32
 #include <pcap-stdinc.h>
-#else /* WIN32 */
+#else /* _WIN32 */
 #if HAVE_INTTYPES_H
 #include <inttypes.h>
 #elif HAVE_STDINT_H
@@ -37,16 +37,9 @@
 #endif
 #include <sys/types.h>
 #include <sys/socket.h>
-#endif /* WIN32 */
+#endif /* _WIN32 */
 
-/*
- * XXX - why was this included even on UNIX?
- */
-#ifdef __MINGW32__
-#include "ip6_misc.h"
-#endif
-
-#ifndef WIN32
+#ifndef _WIN32
 
 #ifdef __NetBSD__
 #include <sys/param.h>
@@ -55,7 +48,7 @@
 #include <netinet/in.h>
 #include <arpa/inet.h>
 
-#endif /* WIN32 */
+#endif /* _WIN32 */
 
 #include <stdlib.h>
 #include <string.h>
@@ -80,27 +73,80 @@
 #include "pcap/sll.h"
 #include "pcap/ipnet.h"
 #include "arcnet.h"
+
+#include "grammar.h"
+#include "scanner.h"
+
 #if defined(linux) && defined(PF_PACKET) && defined(SO_ATTACH_FILTER)
 #include <linux/types.h>
 #include <linux/if_packet.h>
 #include <linux/filter.h>
 #endif
+
 #ifdef HAVE_NET_PFVAR_H
 #include <sys/socket.h>
 #include <net/if.h>
 #include <net/pfvar.h>
 #include <net/if_pflog.h>
 #endif
+
 #ifndef offsetof
 #define offsetof(s, e) ((size_t)&((s *)0)->e)
 #endif
+
 #ifdef INET6
-#ifndef WIN32
+#ifdef _WIN32
+#if defined(__MINGW32__) && defined(DEFINE_ADDITIONAL_IPV6_STUFF)
+/* IPv6 address */
+struct in6_addr
+  {
+    union
+      {
+	u_int8_t		u6_addr8[16];
+	u_int16_t	u6_addr16[8];
+	u_int32_t	u6_addr32[4];
+      } in6_u;
+#define s6_addr			in6_u.u6_addr8
+#define s6_addr16		in6_u.u6_addr16
+#define s6_addr32		in6_u.u6_addr32
+#define s6_addr64		in6_u.u6_addr64
+  };
+
+typedef unsigned short	sa_family_t;
+
+#define	__SOCKADDR_COMMON(sa_prefix) \
+  sa_family_t sa_prefix##family
+
+/* Ditto, for IPv6.  */
+struct sockaddr_in6
+  {
+    __SOCKADDR_COMMON (sin6_);
+    u_int16_t sin6_port;		/* Transport layer port # */
+    u_int32_t sin6_flowinfo;	/* IPv6 flow information */
+    struct in6_addr sin6_addr;	/* IPv6 address */
+  };
+
+#ifndef EAI_ADDRFAMILY
+struct addrinfo {
+	int	ai_flags;	/* AI_PASSIVE, AI_CANONNAME */
+	int	ai_family;	/* PF_xxx */
+	int	ai_socktype;	/* SOCK_xxx */
+	int	ai_protocol;	/* 0 or IPPROTO_xxx for IPv4 and IPv6 */
+	size_t	ai_addrlen;	/* length of ai_addr */
+	char	*ai_canonname;	/* canonical name for hostname */
+	struct sockaddr *ai_addr;	/* binary address */
+	struct addrinfo *ai_next;	/* next structure in linked list */
+};
+#endif /* EAI_ADDRFAMILY */
+#endif /* defined(__MINGW32__) && defined(DEFINE_ADDITIONAL_IPV6_STUFF) */
+#else /* _WIN32 */
 #include <netdb.h>	/* for "struct addrinfo" */
-#endif /* WIN32 */
-#endif /*INET6*/
+#endif /* _WIN32 */
+#endif /* INET6 */
 #include <pcap/namedb.h>
 
+#include "nametoaddr.h"
+
 #define ETHERMTU	1500
 
 #ifndef ETHERTYPE_TEB
@@ -131,42 +177,26 @@
 
 #define JMP(c) ((c)|BPF_JMP|BPF_K)
 
-/* Locals */
-static jmp_buf top_ctx;
-static pcap_t *bpf_pcap;
-
-/* Hack for handling VLAN and MPLS stacks. */
-#ifdef WIN32
-static u_int	label_stack_depth = (u_int)-1, vlan_stack_depth = (u_int)-1;
-#else
-static u_int	label_stack_depth = -1U, vlan_stack_depth = -1U;
-#endif
-
-/* XXX */
-static int	pcap_fddipad;
-
-/* VARARGS */
-void
-bpf_error(const char *fmt, ...)
-{
-	va_list ap;
-
-	va_start(ap, fmt);
-	if (bpf_pcap != NULL)
-		(void)vsnprintf(pcap_geterr(bpf_pcap), PCAP_ERRBUF_SIZE,
-		    fmt, ap);
-	va_end(ap);
-	longjmp(top_ctx, 1);
-	/* NOTREACHED */
+/*
+ * "Push" the current value of the link-layer header type and link-layer
+ * header offset onto a "stack", and set a new value.  (It's not a
+ * full-blown stack; we keep only the top two items.)
+ */
+#define PUSH_LINKHDR(cs, new_linktype, new_is_variable, new_constant_part, new_reg) \
+{ \
+	(cs)->prevlinktype = (cs)->linktype; \
+	(cs)->off_prevlinkhdr = (cs)->off_linkhdr; \
+	(cs)->linktype = (new_linktype); \
+	(cs)->off_linkhdr.is_variable = (new_is_variable); \
+	(cs)->off_linkhdr.constant_part = (new_constant_part); \
+	(cs)->off_linkhdr.reg = (new_reg); \
+	(cs)->is_geneve = 0; \
 }
 
-static void init_linktype(pcap_t *);
-
-static void init_regs(void);
-static int alloc_reg(void);
-static void free_reg(int);
-
-static struct block *root;
+/*
+ * Offset "not set" value.
+ */
+#define OFFSET_NOT_SET	0xffffffffU
 
 /*
  * Absolute offsets, which are offsets from the beginning of the raw
@@ -208,17 +238,6 @@
 	OR_TRAN_IPV6		/* transport-layer header, with IPv6 network layer */
 };
 
-#ifdef INET6
-/*
- * As errors are handled by a longjmp, anything allocated must be freed
- * in the longjmp handler, so it must be reachable from that handler.
- * One thing that's allocated is the result of pcap_nametoaddrinfo();
- * it must be freed with freeaddrinfo().  This variable points to any
- * addrinfo structure that would need to be freed.
- */
-static struct addrinfo *ai;
-#endif
-
 /*
  * We divy out chunks of memory rather than call malloc each time so
  * we don't have to worry about leaking memory.  It's probably
@@ -230,99 +249,324 @@
 #define NCHUNKS 16
 #define CHUNK0SIZE 1024
 struct chunk {
-	u_int n_left;
+	size_t n_left;
 	void *m;
 };
 
-static struct chunk chunks[NCHUNKS];
-static int cur_chunk;
+/* Code generator state */
 
-static void *newchunk(u_int);
-static void freechunks(void);
-static inline struct block *new_block(int);
-static inline struct slist *new_stmt(int);
-static struct block *gen_retblk(int);
-static inline void syntax(void);
+struct _compiler_state {
+	jmp_buf top_ctx;
+	pcap_t *bpf_pcap;
+
+	struct icode ic;
+
+	int snaplen;
+
+	int linktype;
+	int prevlinktype;
+	int outermostlinktype;
+
+	bpf_u_int32 netmask;
+	int no_optimize;
+
+	/* Hack for handling VLAN and MPLS stacks. */
+	u_int label_stack_depth;
+	u_int vlan_stack_depth;
+
+	/* XXX */
+	u_int pcap_fddipad;
+
+#ifdef INET6
+	/*
+	 * As errors are handled by a longjmp, anything allocated must
+	 * be freed in the longjmp handler, so it must be reachable
+	 * from that handler.
+	 *
+	 * One thing that's allocated is the result of pcap_nametoaddrinfo();
+	 * it must be freed with freeaddrinfo().  This variable points to
+	 * any addrinfo structure that would need to be freed.
+	 */
+	struct addrinfo *ai;
+#endif
+
+	/*
+	 * Various code constructs need to know the layout of the packet.
+	 * These values give the necessary offsets from the beginning
+	 * of the packet data.
+	 */
+
+	/*
+	 * Absolute offset of the beginning of the link-layer header.
+	 */
+	bpf_abs_offset off_linkhdr;
+
+	/*
+	 * If we're checking a link-layer header for a packet encapsulated
+	 * in another protocol layer, this is the equivalent information
+	 * for the previous layers' link-layer header from the beginning
+	 * of the raw packet data.
+	 */
+	bpf_abs_offset off_prevlinkhdr;
+
+	/*
+	 * This is the equivalent information for the outermost layers'
+	 * link-layer header.
+	 */
+	bpf_abs_offset off_outermostlinkhdr;
+
+	/*
+	 * Absolute offset of the beginning of the link-layer payload.
+	 */
+	bpf_abs_offset off_linkpl;
+
+	/*
+	 * "off_linktype" is the offset to information in the link-layer
+	 * header giving the packet type. This is an absolute offset
+	 * from the beginning of the packet.
+	 *
+	 * For Ethernet, it's the offset of the Ethernet type field; this
+	 * means that it must have a value that skips VLAN tags.
+	 *
+	 * For link-layer types that always use 802.2 headers, it's the
+	 * offset of the LLC header; this means that it must have a value
+	 * that skips VLAN tags.
+	 *
+	 * For PPP, it's the offset of the PPP type field.
+	 *
+	 * For Cisco HDLC, it's the offset of the CHDLC type field.
+	 *
+	 * For BSD loopback, it's the offset of the AF_ value.
+	 *
+	 * For Linux cooked sockets, it's the offset of the type field.
+	 *
+	 * off_linktype.constant_part is set to OFFSET_NOT_SET for no
+	 * encapsulation, in which case, IP is assumed.
+	 */
+	bpf_abs_offset off_linktype;
+
+	/*
+	 * TRUE if the link layer includes an ATM pseudo-header.
+	 */
+	int is_atm;
+
+	/*
+	 * TRUE if "geneve" appeared in the filter; it causes us to
+	 * generate code that checks for a Geneve header and assume
+	 * that later filters apply to the encapsulated payload.
+	 */
+	int is_geneve;
+
+	/*
+	 * These are offsets for the ATM pseudo-header.
+	 */
+	u_int off_vpi;
+	u_int off_vci;
+	u_int off_proto;
+
+	/*
+	 * These are offsets for the MTP2 fields.
+	 */
+	u_int off_li;
+	u_int off_li_hsl;
+
+	/*
+	 * These are offsets for the MTP3 fields.
+	 */
+	u_int off_sio;
+	u_int off_opc;
+	u_int off_dpc;
+	u_int off_sls;
+
+	/*
+	 * This is the offset of the first byte after the ATM pseudo_header,
+	 * or -1 if there is no ATM pseudo-header.
+	 */
+	u_int off_payload;
+
+	/*
+	 * These are offsets to the beginning of the network-layer header.
+	 * They are relative to the beginning of the link-layer payload
+	 * (i.e., they don't include off_linkhdr.constant_part or
+	 * off_linkpl.constant_part).
+	 *
+	 * If the link layer never uses 802.2 LLC:
+	 *
+	 *	"off_nl" and "off_nl_nosnap" are the same.
+	 *
+	 * If the link layer always uses 802.2 LLC:
+	 *
+	 *	"off_nl" is the offset if there's a SNAP header following
+	 *	the 802.2 header;
+	 *
+	 *	"off_nl_nosnap" is the offset if there's no SNAP header.
+	 *
+	 * If the link layer is Ethernet:
+	 *
+	 *	"off_nl" is the offset if the packet is an Ethernet II packet
+	 *	(we assume no 802.3+802.2+SNAP);
+	 *
+	 *	"off_nl_nosnap" is the offset if the packet is an 802.3 packet
+	 *	with an 802.2 header following it.
+	 */
+	u_int off_nl;
+	u_int off_nl_nosnap;
+
+	/*
+	 * Here we handle simple allocation of the scratch registers.
+	 * If too many registers are alloc'd, the allocator punts.
+	 */
+	int regused[BPF_MEMWORDS];
+	int curreg;
+
+	/*
+	 * Memory chunks.
+	 */
+	struct chunk chunks[NCHUNKS];
+	int cur_chunk;
+};
+
+void
+bpf_syntax_error(compiler_state_t *cstate, const char *msg)
+{
+	bpf_error(cstate, "syntax error in filter expression: %s", msg);
+	/* NOTREACHED */
+}
+
+/* VARARGS */
+void
+bpf_error(compiler_state_t *cstate, const char *fmt, ...)
+{
+	va_list ap;
+
+	va_start(ap, fmt);
+	if (cstate->bpf_pcap != NULL)
+		(void)pcap_vsnprintf(pcap_geterr(cstate->bpf_pcap),
+		    PCAP_ERRBUF_SIZE, fmt, ap);
+	va_end(ap);
+	longjmp(cstate->top_ctx, 1);
+	/* NOTREACHED */
+}
+
+static void init_linktype(compiler_state_t *, pcap_t *);
+
+static void init_regs(compiler_state_t *);
+static int alloc_reg(compiler_state_t *);
+static void free_reg(compiler_state_t *, int);
+
+static void initchunks(compiler_state_t *cstate);
+static void *newchunk(compiler_state_t *cstate, size_t);
+static void freechunks(compiler_state_t *cstate);
+static inline struct block *new_block(compiler_state_t *cstate, int);
+static inline struct slist *new_stmt(compiler_state_t *cstate, int);
+static struct block *gen_retblk(compiler_state_t *cstate, int);
+static inline void syntax(compiler_state_t *cstate);
 
 static void backpatch(struct block *, struct block *);
 static void merge(struct block *, struct block *);
-static struct block *gen_cmp(enum e_offrel, u_int, u_int, bpf_int32);
-static struct block *gen_cmp_gt(enum e_offrel, u_int, u_int, bpf_int32);
-static struct block *gen_cmp_ge(enum e_offrel, u_int, u_int, bpf_int32);
-static struct block *gen_cmp_lt(enum e_offrel, u_int, u_int, bpf_int32);
-static struct block *gen_cmp_le(enum e_offrel, u_int, u_int, bpf_int32);
-static struct block *gen_mcmp(enum e_offrel, u_int, u_int, bpf_int32,
-    bpf_u_int32);
-static struct block *gen_bcmp(enum e_offrel, u_int, u_int, const u_char *);
-static struct block *gen_ncmp(enum e_offrel, bpf_u_int32, bpf_u_int32,
-    bpf_u_int32, bpf_u_int32, int, bpf_int32);
-static struct slist *gen_load_absoffsetrel(bpf_abs_offset *, u_int, u_int);
-static struct slist *gen_load_a(enum e_offrel, u_int, u_int);
-static struct slist *gen_loadx_iphdrlen(void);
-static struct block *gen_uncond(int);
-static inline struct block *gen_true(void);
-static inline struct block *gen_false(void);
-static struct block *gen_ether_linktype(int);
-static struct block *gen_ipnet_linktype(int);
-static struct block *gen_linux_sll_linktype(int);
-static struct slist *gen_load_prism_llprefixlen(void);
-static struct slist *gen_load_avs_llprefixlen(void);
-static struct slist *gen_load_radiotap_llprefixlen(void);
-static struct slist *gen_load_ppi_llprefixlen(void);
-static void insert_compute_vloffsets(struct block *);
-static struct slist *gen_abs_offset_varpart(bpf_abs_offset *);
+static struct block *gen_cmp(compiler_state_t *, enum e_offrel, u_int,
+    u_int, bpf_int32);
+static struct block *gen_cmp_gt(compiler_state_t *, enum e_offrel, u_int,
+    u_int, bpf_int32);
+static struct block *gen_cmp_ge(compiler_state_t *, enum e_offrel, u_int,
+    u_int, bpf_int32);
+static struct block *gen_cmp_lt(compiler_state_t *, enum e_offrel, u_int,
+    u_int, bpf_int32);
+static struct block *gen_cmp_le(compiler_state_t *, enum e_offrel, u_int,
+    u_int, bpf_int32);
+static struct block *gen_mcmp(compiler_state_t *, enum e_offrel, u_int,
+    u_int, bpf_int32, bpf_u_int32);
+static struct block *gen_bcmp(compiler_state_t *, enum e_offrel, u_int,
+    u_int, const u_char *);
+static struct block *gen_ncmp(compiler_state_t *, enum e_offrel, bpf_u_int32,
+    bpf_u_int32, bpf_u_int32, bpf_u_int32, int, bpf_int32);
+static struct slist *gen_load_absoffsetrel(compiler_state_t *, bpf_abs_offset *,
+    u_int, u_int);
+static struct slist *gen_load_a(compiler_state_t *, enum e_offrel, u_int,
+    u_int);
+static struct slist *gen_loadx_iphdrlen(compiler_state_t *);
+static struct block *gen_uncond(compiler_state_t *, int);
+static inline struct block *gen_true(compiler_state_t *);
+static inline struct block *gen_false(compiler_state_t *);
+static struct block *gen_ether_linktype(compiler_state_t *, int);
+static struct block *gen_ipnet_linktype(compiler_state_t *, int);
+static struct block *gen_linux_sll_linktype(compiler_state_t *, int);
+static struct slist *gen_load_prism_llprefixlen(compiler_state_t *);
+static struct slist *gen_load_avs_llprefixlen(compiler_state_t *);
+static struct slist *gen_load_radiotap_llprefixlen(compiler_state_t *);
+static struct slist *gen_load_ppi_llprefixlen(compiler_state_t *);
+static void insert_compute_vloffsets(compiler_state_t *, struct block *);
+static struct slist *gen_abs_offset_varpart(compiler_state_t *,
+    bpf_abs_offset *);
 static int ethertype_to_ppptype(int);
-static struct block *gen_linktype(int);
-static struct block *gen_snap(bpf_u_int32, bpf_u_int32);
-static struct block *gen_llc_linktype(int);
-static struct block *gen_hostop(bpf_u_int32, bpf_u_int32, int, int, u_int, u_int);
+static struct block *gen_linktype(compiler_state_t *, int);
+static struct block *gen_snap(compiler_state_t *, bpf_u_int32, bpf_u_int32);
+static struct block *gen_llc_linktype(compiler_state_t *, int);
+static struct block *gen_hostop(compiler_state_t *, bpf_u_int32, bpf_u_int32,
+    int, int, u_int, u_int);
 #ifdef INET6
-static struct block *gen_hostop6(struct in6_addr *, struct in6_addr *, int, int, u_int, u_int);
+static struct block *gen_hostop6(compiler_state_t *, struct in6_addr *,
+    struct in6_addr *, int, int, u_int, u_int);
 #endif
-static struct block *gen_ahostop(const u_char *, int);
-static struct block *gen_ehostop(const u_char *, int);
-static struct block *gen_fhostop(const u_char *, int);
-static struct block *gen_thostop(const u_char *, int);
-static struct block *gen_wlanhostop(const u_char *, int);
-static struct block *gen_ipfchostop(const u_char *, int);
-static struct block *gen_dnhostop(bpf_u_int32, int);
-static struct block *gen_mpls_linktype(int);
-static struct block *gen_host(bpf_u_int32, bpf_u_int32, int, int, int);
+static struct block *gen_ahostop(compiler_state_t *, const u_char *, int);
+static struct block *gen_ehostop(compiler_state_t *, const u_char *, int);
+static struct block *gen_fhostop(compiler_state_t *, const u_char *, int);
+static struct block *gen_thostop(compiler_state_t *, const u_char *, int);
+static struct block *gen_wlanhostop(compiler_state_t *, const u_char *, int);
+static struct block *gen_ipfchostop(compiler_state_t *, const u_char *, int);
+static struct block *gen_dnhostop(compiler_state_t *, bpf_u_int32, int);
+static struct block *gen_mpls_linktype(compiler_state_t *, int);
+static struct block *gen_host(compiler_state_t *, bpf_u_int32, bpf_u_int32,
+    int, int, int);
 #ifdef INET6
-static struct block *gen_host6(struct in6_addr *, struct in6_addr *, int, int, int);
+static struct block *gen_host6(compiler_state_t *, struct in6_addr *,
+    struct in6_addr *, int, int, int);
 #endif
 #ifndef INET6
 static struct block *gen_gateway(const u_char *, bpf_u_int32 **, int, int);
 #endif
-static struct block *gen_ipfrag(void);
-static struct block *gen_portatom(int, bpf_int32);
-static struct block *gen_portrangeatom(int, bpf_int32, bpf_int32);
-static struct block *gen_portatom6(int, bpf_int32);
-static struct block *gen_portrangeatom6(int, bpf_int32, bpf_int32);
-struct block *gen_portop(int, int, int);
-static struct block *gen_port(int, int, int);
-struct block *gen_portrangeop(int, int, int, int);
-static struct block *gen_portrange(int, int, int, int);
-struct block *gen_portop6(int, int, int);
-static struct block *gen_port6(int, int, int);
-struct block *gen_portrangeop6(int, int, int, int);
-static struct block *gen_portrange6(int, int, int, int);
-static int lookup_proto(const char *, int);
-static struct block *gen_protochain(int, int, int);
-static struct block *gen_proto(int, int, int);
-static struct slist *xfer_to_x(struct arth *);
-static struct slist *xfer_to_a(struct arth *);
-static struct block *gen_mac_multicast(int);
-static struct block *gen_len(int, int);
-static struct block *gen_check_802_11_data_frame(void);
-static struct block *gen_geneve_ll_check(void);
+static struct block *gen_ipfrag(compiler_state_t *);
+static struct block *gen_portatom(compiler_state_t *, int, bpf_int32);
+static struct block *gen_portrangeatom(compiler_state_t *, int, bpf_int32,
+    bpf_int32);
+static struct block *gen_portatom6(compiler_state_t *, int, bpf_int32);
+static struct block *gen_portrangeatom6(compiler_state_t *, int, bpf_int32,
+    bpf_int32);
+struct block *gen_portop(compiler_state_t *, int, int, int);
+static struct block *gen_port(compiler_state_t *, int, int, int);
+struct block *gen_portrangeop(compiler_state_t *, int, int, int, int);
+static struct block *gen_portrange(compiler_state_t *, int, int, int, int);
+struct block *gen_portop6(compiler_state_t *, int, int, int);
+static struct block *gen_port6(compiler_state_t *, int, int, int);
+struct block *gen_portrangeop6(compiler_state_t *, int, int, int, int);
+static struct block *gen_portrange6(compiler_state_t *, int, int, int, int);
+static int lookup_proto(compiler_state_t *, const char *, int);
+static struct block *gen_protochain(compiler_state_t *, int, int, int);
+static struct block *gen_proto(compiler_state_t *, int, int, int);
+static struct slist *xfer_to_x(compiler_state_t *, struct arth *);
+static struct slist *xfer_to_a(compiler_state_t *, struct arth *);
+static struct block *gen_mac_multicast(compiler_state_t *, int);
+static struct block *gen_len(compiler_state_t *, int, int);
+static struct block *gen_check_802_11_data_frame(compiler_state_t *);
+static struct block *gen_geneve_ll_check(compiler_state_t *cstate);
 
-static struct block *gen_ppi_dlt_check(void);
-static struct block *gen_msg_abbrev(int type);
+static struct block *gen_ppi_dlt_check(compiler_state_t *);
+static struct block *gen_msg_abbrev(compiler_state_t *, int type);
+
+static void
+initchunks(compiler_state_t *cstate)
+{
+	int i;
+
+	for (i = 0; i < NCHUNKS; i++) {
+		cstate->chunks[i].n_left = 0;
+		cstate->chunks[i].m = NULL;
+	}
+	cstate->cur_chunk = 0;
+}
 
 static void *
-newchunk(n)
-	u_int n;
+newchunk(compiler_state_t *cstate, size_t n)
 {
 	struct chunk *cp;
 	int k;
@@ -336,58 +580,53 @@
 	n = ALIGN(n);
 #endif
 
-	cp = &chunks[cur_chunk];
+	cp = &cstate->chunks[cstate->cur_chunk];
 	if (n > cp->n_left) {
-		++cp, k = ++cur_chunk;
+		++cp, k = ++cstate->cur_chunk;
 		if (k >= NCHUNKS)
-			bpf_error("out of memory");
+			bpf_error(cstate, "out of memory");
 		size = CHUNK0SIZE << k;
 		cp->m = (void *)malloc(size);
 		if (cp->m == NULL)
-			bpf_error("out of memory");
+			bpf_error(cstate, "out of memory");
 		memset((char *)cp->m, 0, size);
 		cp->n_left = size;
 		if (n > size)
-			bpf_error("out of memory");
+			bpf_error(cstate, "out of memory");
 	}
 	cp->n_left -= n;
 	return (void *)((char *)cp->m + cp->n_left);
 }
 
 static void
-freechunks()
+freechunks(compiler_state_t *cstate)
 {
 	int i;
 
-	cur_chunk = 0;
 	for (i = 0; i < NCHUNKS; ++i)
-		if (chunks[i].m != NULL) {
-			free(chunks[i].m);
-			chunks[i].m = NULL;
-		}
+		if (cstate->chunks[i].m != NULL)
+			free(cstate->chunks[i].m);
 }
 
 /*
  * A strdup whose allocations are freed after code generation is over.
  */
 char *
-sdup(s)
-	register const char *s;
+sdup(compiler_state_t *cstate, const char *s)
 {
-	int n = strlen(s) + 1;
-	char *cp = newchunk(n);
+	size_t n = strlen(s) + 1;
+	char *cp = newchunk(cstate, n);
 
 	strlcpy(cp, s, n);
 	return (cp);
 }
 
 static inline struct block *
-new_block(code)
-	int code;
+new_block(compiler_state_t *cstate, int code)
 {
 	struct block *p;
 
-	p = (struct block *)newchunk(sizeof(*p));
+	p = (struct block *)newchunk(cstate, sizeof(*p));
 	p->s.code = code;
 	p->head = p;
 
@@ -395,59 +634,48 @@
 }
 
 static inline struct slist *
-new_stmt(code)
-	int code;
+new_stmt(compiler_state_t *cstate, int code)
 {
 	struct slist *p;
 
-	p = (struct slist *)newchunk(sizeof(*p));
+	p = (struct slist *)newchunk(cstate, sizeof(*p));
 	p->s.code = code;
 
 	return p;
 }
 
 static struct block *
-gen_retblk(v)
-	int v;
+gen_retblk(compiler_state_t *cstate, int v)
 {
-	struct block *b = new_block(BPF_RET|BPF_K);
+	struct block *b = new_block(cstate, BPF_RET|BPF_K);
 
 	b->s.k = v;
 	return b;
 }
 
 static inline void
-syntax()
+syntax(compiler_state_t *cstate)
 {
-	bpf_error("syntax error in filter expression");
+	bpf_error(cstate, "syntax error in filter expression");
 }
 
-static bpf_u_int32 netmask;
-static int snaplen;
-int no_optimize;
-
 int
 pcap_compile(pcap_t *p, struct bpf_program *program,
 	     const char *buf, int optimize, bpf_u_int32 mask)
 {
-	extern int n_errors;
+	compiler_state_t cstate;
 	const char * volatile xbuf = buf;
+	yyscan_t scanner = NULL;
+	YY_BUFFER_STATE in_buffer = NULL;
 	u_int len;
 	int  rc;
 
-	/*
-	 * XXX - single-thread this code path with pthread calls on
-	 * UN*X, if the platform supports pthreads?  If that requires
-	 * a separate -lpthread, we might not want to do that.
-	 */
-#ifdef WIN32
-	extern int wsockinit (void);
+#ifdef _WIN32
 	static int done = 0;
 
 	if (!done)
-		wsockinit();
+		pcap_wsockinit();
 	done = 1;
-	EnterCriticalSection(&g_PcapCompileCriticalSection);
 #endif
 
 	/*
@@ -455,69 +683,78 @@
 	 * link-layer type, so we can't use it.
 	 */
 	if (!p->activated) {
-		snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
+		pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
 		    "not-yet-activated pcap_t passed to pcap_compile");
 		rc = -1;
 		goto quit;
 	}
-	no_optimize = 0;
-	n_errors = 0;
-	root = NULL;
-	bpf_pcap = p;
-	init_regs();
+	initchunks(&cstate);
+	cstate.no_optimize = 0;
+	cstate.ai = NULL;
+	cstate.ic.root = NULL;
+	cstate.ic.cur_mark = 0;
+	cstate.bpf_pcap = p;
+	init_regs(&cstate);
 
-	if (setjmp(top_ctx)) {
+	if (setjmp(cstate.top_ctx)) {
 #ifdef INET6
-		if (ai != NULL) {
-			freeaddrinfo(ai);
-			ai = NULL;
-		}
+		if (cstate.ai != NULL)
+			freeaddrinfo(cstate.ai);
 #endif
-		lex_cleanup();
-		freechunks();
 		rc = -1;
 		goto quit;
 	}
 
-	netmask = mask;
+	cstate.netmask = mask;
 
-	snaplen = pcap_snapshot(p);
-	if (snaplen == 0) {
-		snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
+	cstate.snaplen = pcap_snapshot(p);
+	if (cstate.snaplen == 0) {
+		pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
 			 "snaplen of 0 rejects all packets");
 		rc = -1;
 		goto quit;
 	}
 
-	lex_init(xbuf ? xbuf : "");
-	init_linktype(p);
-	(void)pcap_parse();
+	if (pcap_lex_init(&scanner) != 0)
+		bpf_error(&cstate, "can't initialize scanner: %s", pcap_strerror(errno));
+	in_buffer = pcap__scan_string(xbuf ? xbuf : "", scanner);
 
-	if (n_errors)
-		syntax();
+	/*
+	 * Associate the compiler state with the lexical analyzer
+	 * state.
+	 */
+	pcap_set_extra(&cstate, scanner);
 
-	if (root == NULL)
-		root = gen_retblk(snaplen);
+	init_linktype(&cstate, p);
+	(void)pcap_parse(scanner, &cstate);
 
-	if (optimize && !no_optimize) {
-		bpf_optimize(&root);
-		if (root == NULL ||
-		    (root->s.code == (BPF_RET|BPF_K) && root->s.k == 0))
-			bpf_error("expression rejects all packets");
+	if (cstate.ic.root == NULL)
+		cstate.ic.root = gen_retblk(&cstate, cstate.snaplen);
+
+	if (optimize && !cstate.no_optimize) {
+		bpf_optimize(&cstate, &cstate.ic);
+		if (cstate.ic.root == NULL ||
+		    (cstate.ic.root->s.code == (BPF_RET|BPF_K) && cstate.ic.root->s.k == 0))
+			bpf_error(&cstate, "expression rejects all packets");
 	}
-	program->bf_insns = icode_to_fcode(root, &len);
+	program->bf_insns = icode_to_fcode(&cstate, &cstate.ic, cstate.ic.root, &len);
 	program->bf_len = len;
 
-	lex_cleanup();
-	freechunks();
-
 	rc = 0;  /* We're all okay */
 
 quit:
+	/*
+	 * Clean up everything for the lexical analyzer.
+	 */
+	if (in_buffer != NULL)
+		pcap__delete_buffer(in_buffer, scanner);
+	if (scanner != NULL)
+		pcap_lex_destroy(scanner);
 
-#ifdef WIN32
-	LeaveCriticalSection(&g_PcapCompileCriticalSection);
-#endif
+	/*
+	 * Clean up our own allocated memory.
+	 */
+	freechunks(&cstate);
 
 	return (rc);
 }
@@ -599,8 +836,7 @@
 }
 
 void
-finish_parse(p)
-	struct block *p;
+finish_parse(compiler_state_t *cstate, struct block *p)
 {
 	struct block *ppi_dlt_check;
 
@@ -623,20 +859,29 @@
 	 * for tests that fail early, and it's not clear that's
 	 * worth the effort.
 	 */
-	insert_compute_vloffsets(p->head);
+	insert_compute_vloffsets(cstate, p->head);
 
 	/*
 	 * For DLT_PPI captures, generate a check of the per-packet
 	 * DLT value to make sure it's DLT_IEEE802_11.
+	 *
+	 * XXX - TurboCap cards use DLT_PPI for Ethernet.
+	 * Can we just define some DLT_ETHERNET_WITH_PHDR pseudo-header
+	 * with appropriate Ethernet information and use that rather
+	 * than using something such as DLT_PPI where you don't know
+	 * the link-layer header type until runtime, which, in the
+	 * general case, would force us to generate both Ethernet *and*
+	 * 802.11 code (*and* anything else for which PPI is used)
+	 * and choose between them early in the BPF program?
 	 */
-	ppi_dlt_check = gen_ppi_dlt_check();
+	ppi_dlt_check = gen_ppi_dlt_check(cstate);
 	if (ppi_dlt_check != NULL)
 		gen_and(ppi_dlt_check, p);
 
-	backpatch(p, gen_retblk(snaplen));
+	backpatch(p, gen_retblk(cstate, cstate->snaplen));
 	p->sense = !p->sense;
-	backpatch(p, gen_retblk(0));
-	root = p->head;
+	backpatch(p, gen_retblk(cstate, 0));
+	cstate->ic.root = p->head;
 }
 
 void
@@ -670,65 +915,50 @@
 }
 
 static struct block *
-gen_cmp(offrel, offset, size, v)
-	enum e_offrel offrel;
-	u_int offset, size;
-	bpf_int32 v;
+gen_cmp(compiler_state_t *cstate, enum e_offrel offrel, u_int offset,
+    u_int size, bpf_int32 v)
 {
-	return gen_ncmp(offrel, offset, size, 0xffffffff, BPF_JEQ, 0, v);
+	return gen_ncmp(cstate, offrel, offset, size, 0xffffffff, BPF_JEQ, 0, v);
 }
 
 static struct block *
-gen_cmp_gt(offrel, offset, size, v)
-	enum e_offrel offrel;
-	u_int offset, size;
-	bpf_int32 v;
+gen_cmp_gt(compiler_state_t *cstate, enum e_offrel offrel, u_int offset,
+    u_int size, bpf_int32 v)
 {
-	return gen_ncmp(offrel, offset, size, 0xffffffff, BPF_JGT, 0, v);
+	return gen_ncmp(cstate, offrel, offset, size, 0xffffffff, BPF_JGT, 0, v);
 }
 
 static struct block *
-gen_cmp_ge(offrel, offset, size, v)
-	enum e_offrel offrel;
-	u_int offset, size;
-	bpf_int32 v;
+gen_cmp_ge(compiler_state_t *cstate, enum e_offrel offrel, u_int offset,
+    u_int size, bpf_int32 v)
 {
-	return gen_ncmp(offrel, offset, size, 0xffffffff, BPF_JGE, 0, v);
+	return gen_ncmp(cstate, offrel, offset, size, 0xffffffff, BPF_JGE, 0, v);
 }
 
 static struct block *
-gen_cmp_lt(offrel, offset, size, v)
-	enum e_offrel offrel;
-	u_int offset, size;
-	bpf_int32 v;
+gen_cmp_lt(compiler_state_t *cstate, enum e_offrel offrel, u_int offset,
+    u_int size, bpf_int32 v)
 {
-	return gen_ncmp(offrel, offset, size, 0xffffffff, BPF_JGE, 1, v);
+	return gen_ncmp(cstate, offrel, offset, size, 0xffffffff, BPF_JGE, 1, v);
 }
 
 static struct block *
-gen_cmp_le(offrel, offset, size, v)
-	enum e_offrel offrel;
-	u_int offset, size;
-	bpf_int32 v;
+gen_cmp_le(compiler_state_t *cstate, enum e_offrel offrel, u_int offset,
+    u_int size, bpf_int32 v)
 {
-	return gen_ncmp(offrel, offset, size, 0xffffffff, BPF_JGT, 1, v);
+	return gen_ncmp(cstate, offrel, offset, size, 0xffffffff, BPF_JGT, 1, v);
 }
 
 static struct block *
-gen_mcmp(offrel, offset, size, v, mask)
-	enum e_offrel offrel;
-	u_int offset, size;
-	bpf_int32 v;
-	bpf_u_int32 mask;
+gen_mcmp(compiler_state_t *cstate, enum e_offrel offrel, u_int offset,
+    u_int size, bpf_int32 v, bpf_u_int32 mask)
 {
-	return gen_ncmp(offrel, offset, size, mask, BPF_JEQ, 0, v);
+	return gen_ncmp(cstate, offrel, offset, size, mask, BPF_JEQ, 0, v);
 }
 
 static struct block *
-gen_bcmp(offrel, offset, size, v)
-	enum e_offrel offrel;
-	register u_int offset, size;
-	register const u_char *v;
+gen_bcmp(compiler_state_t *cstate, enum e_offrel offrel, u_int offset,
+    u_int size, const u_char *v)
 {
 	register struct block *b, *tmp;
 
@@ -738,7 +968,7 @@
 		bpf_int32 w = ((bpf_int32)p[0] << 24) |
 		    ((bpf_int32)p[1] << 16) | ((bpf_int32)p[2] << 8) | p[3];
 
-		tmp = gen_cmp(offrel, offset + size - 4, BPF_W, w);
+		tmp = gen_cmp(cstate, offrel, offset + size - 4, BPF_W, w);
 		if (b != NULL)
 			gen_and(b, tmp);
 		b = tmp;
@@ -748,14 +978,14 @@
 		register const u_char *p = &v[size - 2];
 		bpf_int32 w = ((bpf_int32)p[0] << 8) | p[1];
 
-		tmp = gen_cmp(offrel, offset + size - 2, BPF_H, w);
+		tmp = gen_cmp(cstate, offrel, offset + size - 2, BPF_H, w);
 		if (b != NULL)
 			gen_and(b, tmp);
 		b = tmp;
 		size -= 2;
 	}
 	if (size > 0) {
-		tmp = gen_cmp(offrel, offset, BPF_B, (bpf_int32)v[0]);
+		tmp = gen_cmp(cstate, offrel, offset, BPF_B, (bpf_int32)v[0]);
 		if (b != NULL)
 			gen_and(b, tmp);
 		b = tmp;
@@ -770,24 +1000,22 @@
  * should test the opposite of "jtype".
  */
 static struct block *
-gen_ncmp(offrel, offset, size, mask, jtype, reverse, v)
-	enum e_offrel offrel;
-	bpf_int32 v;
-	bpf_u_int32 offset, size, mask, jtype;
-	int reverse;
+gen_ncmp(compiler_state_t *cstate, enum e_offrel offrel, bpf_u_int32 offset,
+    bpf_u_int32 size, bpf_u_int32 mask, bpf_u_int32 jtype, int reverse,
+    bpf_int32 v)
 {
 	struct slist *s, *s2;
 	struct block *b;
 
-	s = gen_load_a(offrel, offset, size);
+	s = gen_load_a(cstate, offrel, offset, size);
 
 	if (mask != 0xffffffff) {
-		s2 = new_stmt(BPF_ALU|BPF_AND|BPF_K);
+		s2 = new_stmt(cstate, BPF_ALU|BPF_AND|BPF_K);
 		s2->s.k = mask;
 		sappend(s, s2);
 	}
 
-	b = new_block(JMP(jtype));
+	b = new_block(cstate, JMP(jtype));
 	b->stmts = s;
 	b->s.k = v;
 	if (reverse && (jtype == BPF_JGT || jtype == BPF_JGE))
@@ -795,230 +1023,88 @@
 	return b;
 }
 
-/*
- * Various code constructs need to know the layout of the packet.
- * These variables give the necessary offsets from the beginning
- * of the packet data.
- */
-
-/*
- * Absolute offset of the beginning of the link-layer header.
- */
-static bpf_abs_offset off_linkhdr;
-
-/*
- * If we're checking a link-layer header for a packet encapsulated in
- * another protocol layer, this is the equivalent information for the
- * previous layers' link-layer header from the beginning of the raw
- * packet data.
- */
-static bpf_abs_offset off_prevlinkhdr;
-
-/*
- * This is the equivalent information for the outermost layers' link-layer
- * header.
- */
-static bpf_abs_offset off_outermostlinkhdr;
-
-/*
- * "Push" the current value of the link-layer header type and link-layer
- * header offset onto a "stack", and set a new value.  (It's not a
- * full-blown stack; we keep only the top two items.)
- */
-#define PUSH_LINKHDR(new_linktype, new_is_variable, new_constant_part, new_reg) \
-{ \
-	prevlinktype = new_linktype; \
-	off_prevlinkhdr = off_linkhdr; \
-	linktype = new_linktype; \
-	off_linkhdr.is_variable = new_is_variable; \
-	off_linkhdr.constant_part = new_constant_part; \
-	off_linkhdr.reg = new_reg; \
-	is_geneve = 0; \
-}
-
-/*
- * Absolute offset of the beginning of the link-layer payload.
- */
-static bpf_abs_offset off_linkpl;
-
-/*
- * "off_linktype" is the offset to information in the link-layer header
- * giving the packet type. This is an absolute offset from the beginning
- * of the packet.
- *
- * For Ethernet, it's the offset of the Ethernet type field; this
- * means that it must have a value that skips VLAN tags.
- *
- * For link-layer types that always use 802.2 headers, it's the
- * offset of the LLC header; this means that it must have a value
- * that skips VLAN tags.
- *
- * For PPP, it's the offset of the PPP type field.
- *
- * For Cisco HDLC, it's the offset of the CHDLC type field.
- *
- * For BSD loopback, it's the offset of the AF_ value.
- *
- * For Linux cooked sockets, it's the offset of the type field.
- *
- * off_linktype.constant_part is set to -1 for no encapsulation,
- * in which case, IP is assumed.
- */
-static bpf_abs_offset off_linktype;
-
-/*
- * TRUE if the link layer includes an ATM pseudo-header.
- */
-static int is_atm = 0;
-
-/*
- * TRUE if "geneve" appeared in the filter; it causes us to generate
- * code that checks for a Geneve header and assume that later filters
- * apply to the encapsulated payload.
- */
-static int is_geneve = 0;
-
-/*
- * These are offsets for the ATM pseudo-header.
- */
-static u_int off_vpi;
-static u_int off_vci;
-static u_int off_proto;
-
-/*
- * These are offsets for the MTP2 fields.
- */
-static u_int off_li;
-static u_int off_li_hsl;
-
-/*
- * These are offsets for the MTP3 fields.
- */
-static u_int off_sio;
-static u_int off_opc;
-static u_int off_dpc;
-static u_int off_sls;
-
-/*
- * This is the offset of the first byte after the ATM pseudo_header,
- * or -1 if there is no ATM pseudo-header.
- */
-static u_int off_payload;
-
-/*
- * These are offsets to the beginning of the network-layer header.
- * They are relative to the beginning of the link-layer payload (i.e.,
- * they don't include off_linkhdr.constant_part or off_linkpl.constant_part).
- *
- * If the link layer never uses 802.2 LLC:
- *
- *	"off_nl" and "off_nl_nosnap" are the same.
- *
- * If the link layer always uses 802.2 LLC:
- *
- *	"off_nl" is the offset if there's a SNAP header following
- *	the 802.2 header;
- *
- *	"off_nl_nosnap" is the offset if there's no SNAP header.
- *
- * If the link layer is Ethernet:
- *
- *	"off_nl" is the offset if the packet is an Ethernet II packet
- *	(we assume no 802.3+802.2+SNAP);
- *
- *	"off_nl_nosnap" is the offset if the packet is an 802.3 packet
- *	with an 802.2 header following it.
- */
-static u_int off_nl;
-static u_int off_nl_nosnap;
-
-static int linktype;
-static int prevlinktype;
-static int outermostlinktype;
-
 static void
-init_linktype(p)
-	pcap_t *p;
+init_linktype(compiler_state_t *cstate, pcap_t *p)
 {
-	pcap_fddipad = p->fddipad;
+	cstate->pcap_fddipad = p->fddipad;
 
 	/*
 	 * We start out with only one link-layer header.
 	 */
-	outermostlinktype = pcap_datalink(p);
-	off_outermostlinkhdr.constant_part = 0;
-	off_outermostlinkhdr.is_variable = 0;
-	off_outermostlinkhdr.reg = -1;
+	cstate->outermostlinktype = pcap_datalink(p);
+	cstate->off_outermostlinkhdr.constant_part = 0;
+	cstate->off_outermostlinkhdr.is_variable = 0;
+	cstate->off_outermostlinkhdr.reg = -1;
 
-	prevlinktype = outermostlinktype;
-	off_prevlinkhdr.constant_part = 0;
-	off_prevlinkhdr.is_variable = 0;
-	off_prevlinkhdr.reg = -1;
+	cstate->prevlinktype = cstate->outermostlinktype;
+	cstate->off_prevlinkhdr.constant_part = 0;
+	cstate->off_prevlinkhdr.is_variable = 0;
+	cstate->off_prevlinkhdr.reg = -1;
 
-	linktype = outermostlinktype;
-	off_linkhdr.constant_part = 0;
-	off_linkhdr.is_variable = 0;
-	off_linkhdr.reg = -1;
+	cstate->linktype = cstate->outermostlinktype;
+	cstate->off_linkhdr.constant_part = 0;
+	cstate->off_linkhdr.is_variable = 0;
+	cstate->off_linkhdr.reg = -1;
 
 	/*
 	 * XXX
 	 */
-	off_linkpl.constant_part = 0;
-	off_linkpl.is_variable = 0;
-	off_linkpl.reg = -1;
+	cstate->off_linkpl.constant_part = 0;
+	cstate->off_linkpl.is_variable = 0;
+	cstate->off_linkpl.reg = -1;
 
-	off_linktype.constant_part = 0;
-	off_linktype.is_variable = 0;
-	off_linktype.reg = -1;
+	cstate->off_linktype.constant_part = 0;
+	cstate->off_linktype.is_variable = 0;
+	cstate->off_linktype.reg = -1;
 
 	/*
 	 * Assume it's not raw ATM with a pseudo-header, for now.
 	 */
-	is_atm = 0;
-	off_vpi = -1;
-	off_vci = -1;
-	off_proto = -1;
-	off_payload = -1;
+	cstate->is_atm = 0;
+	cstate->off_vpi = -1;
+	cstate->off_vci = -1;
+	cstate->off_proto = -1;
+	cstate->off_payload = -1;
 
 	/*
 	 * And not Geneve.
 	 */
-	is_geneve = 0;
+	cstate->is_geneve = 0;
 
 	/*
 	 * And assume we're not doing SS7.
 	 */
-	off_li = -1;
-	off_li_hsl = -1;
-	off_sio = -1;
-	off_opc = -1;
-	off_dpc = -1;
-	off_sls = -1;
+	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;
 
-        label_stack_depth = 0;
-        vlan_stack_depth = 0;
+	cstate->label_stack_depth = 0;
+	cstate->vlan_stack_depth = 0;
 
-	switch (linktype) {
+	switch (cstate->linktype) {
 
 	case DLT_ARCNET:
-		off_linktype.constant_part = 2;
-		off_linkpl.constant_part = 6;
-		off_nl = 0;		/* XXX in reality, variable! */
-		off_nl_nosnap = 0;	/* no 802.2 LLC */
+		cstate->off_linktype.constant_part = 2;
+		cstate->off_linkpl.constant_part = 6;
+		cstate->off_nl = 0;	/* XXX in reality, variable! */
+		cstate->off_nl_nosnap = 0;	/* no 802.2 LLC */
 		break;
 
 	case DLT_ARCNET_LINUX:
-		off_linktype.constant_part = 4;
-		off_linkpl.constant_part = 8;
-		off_nl = 0;		/* XXX in reality, variable! */
-		off_nl_nosnap = 0;	/* no 802.2 LLC */
+		cstate->off_linktype.constant_part = 4;
+		cstate->off_linkpl.constant_part = 8;
+		cstate->off_nl = 0;		/* XXX in reality, variable! */
+		cstate->off_nl_nosnap = 0;	/* no 802.2 LLC */
 		break;
 
 	case DLT_EN10MB:
-		off_linktype.constant_part = 12;
-		off_linkpl.constant_part = 14;	/* Ethernet header length */
-		off_nl = 0;		/* Ethernet II */
-		off_nl_nosnap = 3;	/* 802.3+802.2 */
+		cstate->off_linktype.constant_part = 12;
+		cstate->off_linkpl.constant_part = 14;	/* Ethernet header length */
+		cstate->off_nl = 0;		/* Ethernet II */
+		cstate->off_nl_nosnap = 3;	/* 802.3+802.2 */
 		break;
 
 	case DLT_SLIP:
@@ -1026,44 +1112,44 @@
 		 * SLIP doesn't have a link level type.  The 16 byte
 		 * header is hacked into our SLIP driver.
 		 */
-		off_linktype.constant_part = -1;
-		off_linkpl.constant_part = 16;
-		off_nl = 0;
-		off_nl_nosnap = 0;	/* no 802.2 LLC */
+		cstate->off_linktype.constant_part = OFFSET_NOT_SET;
+		cstate->off_linkpl.constant_part = 16;
+		cstate->off_nl = 0;
+		cstate->off_nl_nosnap = 0;	/* no 802.2 LLC */
 		break;
 
 	case DLT_SLIP_BSDOS:
 		/* XXX this may be the same as the DLT_PPP_BSDOS case */
-		off_linktype.constant_part = -1;
+		cstate->off_linktype.constant_part = OFFSET_NOT_SET;
 		/* XXX end */
-		off_linkpl.constant_part = 24;
-		off_nl = 0;
-		off_nl_nosnap = 0;	/* no 802.2 LLC */
+		cstate->off_linkpl.constant_part = 24;
+		cstate->off_nl = 0;
+		cstate->off_nl_nosnap = 0;	/* no 802.2 LLC */
 		break;
 
 	case DLT_NULL:
 	case DLT_LOOP:
-		off_linktype.constant_part = 0;
-		off_linkpl.constant_part = 4;
-		off_nl = 0;
-		off_nl_nosnap = 0;	/* no 802.2 LLC */
+		cstate->off_linktype.constant_part = 0;
+		cstate->off_linkpl.constant_part = 4;
+		cstate->off_nl = 0;
+		cstate->off_nl_nosnap = 0;	/* no 802.2 LLC */
 		break;
 
 	case DLT_ENC:
-		off_linktype.constant_part = 0;
-		off_linkpl.constant_part = 12;
-		off_nl = 0;
-		off_nl_nosnap = 0;	/* no 802.2 LLC */
+		cstate->off_linktype.constant_part = 0;
+		cstate->off_linkpl.constant_part = 12;
+		cstate->off_nl = 0;
+		cstate->off_nl_nosnap = 0;	/* no 802.2 LLC */
 		break;
 
 	case DLT_PPP:
 	case DLT_PPP_PPPD:
 	case DLT_C_HDLC:		/* BSD/OS Cisco HDLC */
 	case DLT_PPP_SERIAL:		/* NetBSD sync/async serial PPP */
-		off_linktype.constant_part = 2;	/* skip HDLC-like framing */
-		off_linkpl.constant_part = 4;	/* skip HDLC-like framing and protocol field */
-		off_nl = 0;
-		off_nl_nosnap = 0;	/* no 802.2 LLC */
+		cstate->off_linktype.constant_part = 2;	/* skip HDLC-like framing */
+		cstate->off_linkpl.constant_part = 4;	/* skip HDLC-like framing and protocol field */
+		cstate->off_nl = 0;
+		cstate->off_nl_nosnap = 0;	/* no 802.2 LLC */
 		break;
 
 	case DLT_PPP_ETHER:
@@ -1071,17 +1157,17 @@
 		 * This does no include the Ethernet header, and
 		 * only covers session state.
 		 */
-		off_linktype.constant_part = 6;
-		off_linkpl.constant_part = 8;
-		off_nl = 0;
-		off_nl_nosnap = 0;	/* no 802.2 LLC */
+		cstate->off_linktype.constant_part = 6;
+		cstate->off_linkpl.constant_part = 8;
+		cstate->off_nl = 0;
+		cstate->off_nl_nosnap = 0;	/* no 802.2 LLC */
 		break;
 
 	case DLT_PPP_BSDOS:
-		off_linktype.constant_part = 5;
-		off_linkpl.constant_part = 24;
-		off_nl = 0;
-		off_nl_nosnap = 0;	/* no 802.2 LLC */
+		cstate->off_linktype.constant_part = 5;
+		cstate->off_linkpl.constant_part = 24;
+		cstate->off_nl = 0;
+		cstate->off_nl_nosnap = 0;	/* no 802.2 LLC */
 		break;
 
 	case DLT_FDDI:
@@ -1093,12 +1179,12 @@
 		 * is being used and pick out the encapsulated Ethernet type.
 		 * XXX - should we generate code to check for SNAP?
 		 */
-		off_linktype.constant_part = 13;
-		off_linktype.constant_part += pcap_fddipad;
-		off_linkpl.constant_part = 13;	/* FDDI MAC header length */
-		off_linkpl.constant_part += pcap_fddipad;
-		off_nl = 8;		/* 802.2+SNAP */
-		off_nl_nosnap = 3;	/* 802.2 */
+		cstate->off_linktype.constant_part = 13;
+		cstate->off_linktype.constant_part += cstate->pcap_fddipad;
+		cstate->off_linkpl.constant_part = 13;	/* FDDI MAC header length */
+		cstate->off_linkpl.constant_part += cstate->pcap_fddipad;
+		cstate->off_nl = 8;		/* 802.2+SNAP */
+		cstate->off_nl_nosnap = 3;	/* 802.2 */
 		break;
 
 	case DLT_IEEE802:
@@ -1125,16 +1211,16 @@
 		 * the 16-bit value at an offset of 14 (shifted right
 		 * 8 - figure out which byte that is).
 		 */
-		off_linktype.constant_part = 14;
-		off_linkpl.constant_part = 14;	/* Token Ring MAC header length */
-		off_nl = 8;		/* 802.2+SNAP */
-		off_nl_nosnap = 3;	/* 802.2 */
+		cstate->off_linktype.constant_part = 14;
+		cstate->off_linkpl.constant_part = 14;	/* Token Ring MAC header length */
+		cstate->off_nl = 8;		/* 802.2+SNAP */
+		cstate->off_nl_nosnap = 3;	/* 802.2 */
 		break;
 
 	case DLT_PRISM_HEADER:
 	case DLT_IEEE802_11_RADIO_AVS:
 	case DLT_IEEE802_11_RADIO:
-		off_linkhdr.is_variable = 1;
+		cstate->off_linkhdr.is_variable = 1;
 		/* Fall through, 802.11 doesn't have a variable link
 		 * prefix but is otherwise the same. */
 
@@ -1157,11 +1243,11 @@
 		 * header or an AVS header, so, in practice, it's
 		 * variable-length.
 		 */
-		off_linktype.constant_part = 24;
-		off_linkpl.constant_part = 0;	/* link-layer header is variable-length */
-		off_linkpl.is_variable = 1;
-		off_nl = 8;		/* 802.2+SNAP */
-		off_nl_nosnap = 3;	/* 802.2 */
+		cstate->off_linktype.constant_part = 24;
+		cstate->off_linkpl.constant_part = 0;	/* link-layer header is variable-length */
+		cstate->off_linkpl.is_variable = 1;
+		cstate->off_nl = 8;		/* 802.2+SNAP */
+		cstate->off_nl_nosnap = 3;	/* 802.2 */
 		break;
 
 	case DLT_PPI:
@@ -1174,12 +1260,12 @@
 		 * the encapsulated DLT should be DLT_IEEE802_11) we
 		 * generate code to check for this too.
 		 */
-		off_linktype.constant_part = 24;
-		off_linkpl.constant_part = 0;	/* link-layer header is variable-length */
-		off_linkpl.is_variable = 1;
-		off_linkhdr.is_variable = 1;
-		off_nl = 8;		/* 802.2+SNAP */
-		off_nl_nosnap = 3;	/* 802.2 */
+		cstate->off_linktype.constant_part = 24;
+		cstate->off_linkpl.constant_part = 0;	/* link-layer header is variable-length */
+		cstate->off_linkpl.is_variable = 1;
+		cstate->off_linkhdr.is_variable = 1;
+		cstate->off_nl = 8;		/* 802.2+SNAP */
+		cstate->off_nl_nosnap = 3;	/* 802.2 */
 		break;
 
 	case DLT_ATM_RFC1483:
@@ -1195,10 +1281,10 @@
 		 * or "pppoa and tcp port 80" and have it check for
 		 * PPPo{A,E} and a PPP protocol of IP and....
 		 */
-		off_linktype.constant_part = 0;
-		off_linkpl.constant_part = 0;	/* packet begins with LLC header */
-		off_nl = 8;		/* 802.2+SNAP */
-		off_nl_nosnap = 3;	/* 802.2 */
+		cstate->off_linktype.constant_part = 0;
+		cstate->off_linkpl.constant_part = 0;	/* packet begins with LLC header */
+		cstate->off_nl = 8;		/* 802.2+SNAP */
+		cstate->off_nl_nosnap = 3;	/* 802.2 */
 		break;
 
 	case DLT_SUNATM:
@@ -1206,31 +1292,31 @@
 		 * Full Frontal ATM; you get AALn PDUs with an ATM
 		 * pseudo-header.
 		 */
-		is_atm = 1;
-		off_vpi = SUNATM_VPI_POS;
-		off_vci = SUNATM_VCI_POS;
-		off_proto = PROTO_POS;
-		off_payload = SUNATM_PKT_BEGIN_POS;
-		off_linktype.constant_part = off_payload;
-		off_linkpl.constant_part = off_payload;	/* if LLC-encapsulated */
-		off_nl = 8;		/* 802.2+SNAP */
-		off_nl_nosnap = 3;	/* 802.2 */
+		cstate->is_atm = 1;
+		cstate->off_vpi = SUNATM_VPI_POS;
+		cstate->off_vci = SUNATM_VCI_POS;
+		cstate->off_proto = PROTO_POS;
+		cstate->off_payload = SUNATM_PKT_BEGIN_POS;
+		cstate->off_linktype.constant_part = cstate->off_payload;
+		cstate->off_linkpl.constant_part = cstate->off_payload;	/* if LLC-encapsulated */
+		cstate->off_nl = 8;		/* 802.2+SNAP */
+		cstate->off_nl_nosnap = 3;	/* 802.2 */
 		break;
 
 	case DLT_RAW:
 	case DLT_IPV4:
 	case DLT_IPV6:
-		off_linktype.constant_part = -1;
-		off_linkpl.constant_part = 0;
-		off_nl = 0;
-		off_nl_nosnap = 0;	/* no 802.2 LLC */
+		cstate->off_linktype.constant_part = OFFSET_NOT_SET;
+		cstate->off_linkpl.constant_part = 0;
+		cstate->off_nl = 0;
+		cstate->off_nl_nosnap = 0;	/* no 802.2 LLC */
 		break;
 
 	case DLT_LINUX_SLL:	/* fake header for Linux cooked socket */
-		off_linktype.constant_part = 14;
-		off_linkpl.constant_part = 16;
-		off_nl = 0;
-		off_nl_nosnap = 0;	/* no 802.2 LLC */
+		cstate->off_linktype.constant_part = 14;
+		cstate->off_linkpl.constant_part = 16;
+		cstate->off_nl = 0;
+		cstate->off_nl_nosnap = 0;	/* no 802.2 LLC */
 		break;
 
 	case DLT_LTALK:
@@ -1239,10 +1325,10 @@
 		 * but really it just indicates whether there is a "short" or
 		 * "long" DDP packet following.
 		 */
-		off_linktype.constant_part = -1;
-		off_linkpl.constant_part = 0;
-		off_nl = 0;
-		off_nl_nosnap = 0;	/* no 802.2 LLC */
+		cstate->off_linktype.constant_part = OFFSET_NOT_SET;
+		cstate->off_linkpl.constant_part = 0;
+		cstate->off_nl = 0;
+		cstate->off_nl_nosnap = 0;	/* no 802.2 LLC */
 		break;
 
 	case DLT_IP_OVER_FC:
@@ -1256,10 +1342,10 @@
 		 * XXX - should we generate code to check for SNAP? RFC
 		 * 2625 says SNAP should be used.
 		 */
-		off_linktype.constant_part = 16;
-		off_linkpl.constant_part = 16;
-		off_nl = 8;		/* 802.2+SNAP */
-		off_nl_nosnap = 3;	/* 802.2 */
+		cstate->off_linktype.constant_part = 16;
+		cstate->off_linkpl.constant_part = 16;
+		cstate->off_nl = 8;		/* 802.2+SNAP */
+		cstate->off_nl_nosnap = 3;	/* 802.2 */
 		break;
 
 	case DLT_FRELAY:
@@ -1267,10 +1353,10 @@
 		 * XXX - we should set this to handle SNAP-encapsulated
 		 * frames (NLPID of 0x80).
 		 */
-		off_linktype.constant_part = -1;
-		off_linkpl.constant_part = 0;
-		off_nl = 0;
-		off_nl_nosnap = 0;	/* no 802.2 LLC */
+		cstate->off_linktype.constant_part = OFFSET_NOT_SET;
+		cstate->off_linkpl.constant_part = 0;
+		cstate->off_nl = 0;
+		cstate->off_nl_nosnap = 0;	/* no 802.2 LLC */
 		break;
 
                 /*
@@ -1279,32 +1365,32 @@
                  * so lets start with offset 4 for now and increments later on (FIXME);
                  */
 	case DLT_MFR:
-		off_linktype.constant_part = -1;
-		off_linkpl.constant_part = 0;
-		off_nl = 4;
-		off_nl_nosnap = 0;	/* XXX - for now -> no 802.2 LLC */
+		cstate->off_linktype.constant_part = OFFSET_NOT_SET;
+		cstate->off_linkpl.constant_part = 0;
+		cstate->off_nl = 4;
+		cstate->off_nl_nosnap = 0;	/* XXX - for now -> no 802.2 LLC */
 		break;
 
 	case DLT_APPLE_IP_OVER_IEEE1394:
-		off_linktype.constant_part = 16;
-		off_linkpl.constant_part = 18;
-		off_nl = 0;
-		off_nl_nosnap = 0;	/* no 802.2 LLC */
+		cstate->off_linktype.constant_part = 16;
+		cstate->off_linkpl.constant_part = 18;
+		cstate->off_nl = 0;
+		cstate->off_nl_nosnap = 0;	/* no 802.2 LLC */
 		break;
 
 	case DLT_SYMANTEC_FIREWALL:
-		off_linktype.constant_part = 6;
-		off_linkpl.constant_part = 44;
-		off_nl = 0;		/* Ethernet II */
-		off_nl_nosnap = 0;	/* XXX - what does it do with 802.3 packets? */
+		cstate->off_linktype.constant_part = 6;
+		cstate->off_linkpl.constant_part = 44;
+		cstate->off_nl = 0;		/* Ethernet II */
+		cstate->off_nl_nosnap = 0;	/* XXX - what does it do with 802.3 packets? */
 		break;
 
 #ifdef HAVE_NET_PFVAR_H
 	case DLT_PFLOG:
-		off_linktype.constant_part = 0;
-		off_linkpl.constant_part = PFLOG_HDRLEN;
-		off_nl = 0;
-		off_nl_nosnap = 0;	/* no 802.2 LLC */
+		cstate->off_linktype.constant_part = 0;
+		cstate->off_linkpl.constant_part = PFLOG_HDRLEN;
+		cstate->off_nl = 0;
+		cstate->off_nl_nosnap = 0;	/* no 802.2 LLC */
 		break;
 #endif
 
@@ -1314,186 +1400,186 @@
         case DLT_JUNIPER_PPP:
         case DLT_JUNIPER_CHDLC:
         case DLT_JUNIPER_FRELAY:
-                off_linktype.constant_part = 4;
-		off_linkpl.constant_part = 4;
-		off_nl = 0;
-		off_nl_nosnap = -1;	/* no 802.2 LLC */
+		cstate->off_linktype.constant_part = 4;
+		cstate->off_linkpl.constant_part = 4;
+		cstate->off_nl = 0;
+		cstate->off_nl_nosnap = -1;	/* no 802.2 LLC */
                 break;
 
 	case DLT_JUNIPER_ATM1:
-		off_linktype.constant_part = 4;		/* in reality variable between 4-8 */
-		off_linkpl.constant_part = 4;	/* in reality variable between 4-8 */
-		off_nl = 0;
-		off_nl_nosnap = 10;
+		cstate->off_linktype.constant_part = 4;		/* in reality variable between 4-8 */
+		cstate->off_linkpl.constant_part = 4;	/* in reality variable between 4-8 */
+		cstate->off_nl = 0;
+		cstate->off_nl_nosnap = 10;
 		break;
 
 	case DLT_JUNIPER_ATM2:
-		off_linktype.constant_part = 8;		/* in reality variable between 8-12 */
-		off_linkpl.constant_part = 8;	/* in reality variable between 8-12 */
-		off_nl = 0;
-		off_nl_nosnap = 10;
+		cstate->off_linktype.constant_part = 8;		/* in reality variable between 8-12 */
+		cstate->off_linkpl.constant_part = 8;	/* in reality variable between 8-12 */
+		cstate->off_nl = 0;
+		cstate->off_nl_nosnap = 10;
 		break;
 
 		/* frames captured on a Juniper PPPoE service PIC
 		 * contain raw ethernet frames */
 	case DLT_JUNIPER_PPPOE:
         case DLT_JUNIPER_ETHER:
-        	off_linkpl.constant_part = 14;
-		off_linktype.constant_part = 16;
-		off_nl = 18;		/* Ethernet II */
-		off_nl_nosnap = 21;	/* 802.3+802.2 */
+		cstate->off_linkpl.constant_part = 14;
+		cstate->off_linktype.constant_part = 16;
+		cstate->off_nl = 18;		/* Ethernet II */
+		cstate->off_nl_nosnap = 21;	/* 802.3+802.2 */
 		break;
 
 	case DLT_JUNIPER_PPPOE_ATM:
-		off_linktype.constant_part = 4;
-		off_linkpl.constant_part = 6;
-		off_nl = 0;
-		off_nl_nosnap = -1;	/* no 802.2 LLC */
+		cstate->off_linktype.constant_part = 4;
+		cstate->off_linkpl.constant_part = 6;
+		cstate->off_nl = 0;
+		cstate->off_nl_nosnap = -1;	/* no 802.2 LLC */
 		break;
 
 	case DLT_JUNIPER_GGSN:
-		off_linktype.constant_part = 6;
-		off_linkpl.constant_part = 12;
-		off_nl = 0;
-		off_nl_nosnap = -1;	/* no 802.2 LLC */
+		cstate->off_linktype.constant_part = 6;
+		cstate->off_linkpl.constant_part = 12;
+		cstate->off_nl = 0;
+		cstate->off_nl_nosnap = -1;	/* no 802.2 LLC */
 		break;
 
 	case DLT_JUNIPER_ES:
-		off_linktype.constant_part = 6;
-		off_linkpl.constant_part = -1;	/* not really a network layer but raw IP addresses */
-		off_nl = -1;		/* not really a network layer but raw IP addresses */
-		off_nl_nosnap = -1;	/* no 802.2 LLC */
+		cstate->off_linktype.constant_part = 6;
+		cstate->off_linkpl.constant_part = OFFSET_NOT_SET;	/* not really a network layer but raw IP addresses */
+		cstate->off_nl = -1;		/* not really a network layer but raw IP addresses */
+		cstate->off_nl_nosnap = -1;	/* no 802.2 LLC */
 		break;
 
 	case DLT_JUNIPER_MONITOR:
-		off_linktype.constant_part = 12;
-		off_linkpl.constant_part = 12;
-		off_nl = 0;		/* raw IP/IP6 header */
-		off_nl_nosnap = -1;	/* no 802.2 LLC */
+		cstate->off_linktype.constant_part = 12;
+		cstate->off_linkpl.constant_part = 12;
+		cstate->off_nl = 0;		/* raw IP/IP6 header */
+		cstate->off_nl_nosnap = -1;	/* no 802.2 LLC */
 		break;
 
 	case DLT_BACNET_MS_TP:
-		off_linktype.constant_part = -1;
-		off_linkpl.constant_part = -1;
-		off_nl = -1;
-		off_nl_nosnap = -1;
+		cstate->off_linktype.constant_part = OFFSET_NOT_SET;
+		cstate->off_linkpl.constant_part = OFFSET_NOT_SET;
+		cstate->off_nl = -1;
+		cstate->off_nl_nosnap = -1;
 		break;
 
 	case DLT_JUNIPER_SERVICES:
-		off_linktype.constant_part = 12;
-		off_linkpl.constant_part = -1;	/* L3 proto location dep. on cookie type */
-		off_nl = -1;		/* L3 proto location dep. on cookie type */
-		off_nl_nosnap = -1;	/* no 802.2 LLC */
+		cstate->off_linktype.constant_part = 12;
+		cstate->off_linkpl.constant_part = OFFSET_NOT_SET;	/* L3 proto location dep. on cookie type */
+		cstate->off_nl = -1;		/* L3 proto location dep. on cookie type */
+		cstate->off_nl_nosnap = -1;	/* no 802.2 LLC */
 		break;
 
 	case DLT_JUNIPER_VP:
-		off_linktype.constant_part = 18;
-		off_linkpl.constant_part = -1;
-		off_nl = -1;
-		off_nl_nosnap = -1;
+		cstate->off_linktype.constant_part = 18;
+		cstate->off_linkpl.constant_part = OFFSET_NOT_SET;
+		cstate->off_nl = -1;
+		cstate->off_nl_nosnap = -1;
 		break;
 
 	case DLT_JUNIPER_ST:
-		off_linktype.constant_part = 18;
-		off_linkpl.constant_part = -1;
-		off_nl = -1;
-		off_nl_nosnap = -1;
+		cstate->off_linktype.constant_part = 18;
+		cstate->off_linkpl.constant_part = OFFSET_NOT_SET;
+		cstate->off_nl = -1;
+		cstate->off_nl_nosnap = -1;
 		break;
 
 	case DLT_JUNIPER_ISM:
-		off_linktype.constant_part = 8;
-		off_linkpl.constant_part = -1;
-		off_nl = -1;
-		off_nl_nosnap = -1;
+		cstate->off_linktype.constant_part = 8;
+		cstate->off_linkpl.constant_part = OFFSET_NOT_SET;
+		cstate->off_nl = -1;
+		cstate->off_nl_nosnap = -1;
 		break;
 
 	case DLT_JUNIPER_VS:
 	case DLT_JUNIPER_SRX_E2E:
 	case DLT_JUNIPER_FIBRECHANNEL:
 	case DLT_JUNIPER_ATM_CEMIC:
-		off_linktype.constant_part = 8;
-		off_linkpl.constant_part = -1;
-		off_nl = -1;
-		off_nl_nosnap = -1;
+		cstate->off_linktype.constant_part = 8;
+		cstate->off_linkpl.constant_part = OFFSET_NOT_SET;
+		cstate->off_nl = -1;
+		cstate->off_nl_nosnap = -1;
 		break;
 
 	case DLT_MTP2:
-		off_li = 2;
-		off_li_hsl = 4;
-		off_sio = 3;
-		off_opc = 4;
-		off_dpc = 4;
-		off_sls = 7;
-		off_linktype.constant_part = -1;
-		off_linkpl.constant_part = -1;
-		off_nl = -1;
-		off_nl_nosnap = -1;
+		cstate->off_li = 2;
+		cstate->off_li_hsl = 4;
+		cstate->off_sio = 3;
+		cstate->off_opc = 4;
+		cstate->off_dpc = 4;
+		cstate->off_sls = 7;
+		cstate->off_linktype.constant_part = OFFSET_NOT_SET;
+		cstate->off_linkpl.constant_part = OFFSET_NOT_SET;
+		cstate->off_nl = -1;
+		cstate->off_nl_nosnap = -1;
 		break;
 
 	case DLT_MTP2_WITH_PHDR:
-		off_li = 6;
-		off_li_hsl = 8;
-		off_sio = 7;
-		off_opc = 8;
-		off_dpc = 8;
-		off_sls = 11;
-		off_linktype.constant_part = -1;
-		off_linkpl.constant_part = -1;
-		off_nl = -1;
-		off_nl_nosnap = -1;
+		cstate->off_li = 6;
+		cstate->off_li_hsl = 8;
+		cstate->off_sio = 7;
+		cstate->off_opc = 8;
+		cstate->off_dpc = 8;
+		cstate->off_sls = 11;
+		cstate->off_linktype.constant_part = OFFSET_NOT_SET;
+		cstate->off_linkpl.constant_part = OFFSET_NOT_SET;
+		cstate->off_nl = -1;
+		cstate->off_nl_nosnap = -1;
 		break;
 
 	case DLT_ERF:
-		off_li = 22;
-		off_li_hsl = 24;
-		off_sio = 23;
-		off_opc = 24;
-		off_dpc = 24;
-		off_sls = 27;
-		off_linktype.constant_part = -1;
-		off_linkpl.constant_part = -1;
-		off_nl = -1;
-		off_nl_nosnap = -1;
+		cstate->off_li = 22;
+		cstate->off_li_hsl = 24;
+		cstate->off_sio = 23;
+		cstate->off_opc = 24;
+		cstate->off_dpc = 24;
+		cstate->off_sls = 27;
+		cstate->off_linktype.constant_part = OFFSET_NOT_SET;
+		cstate->off_linkpl.constant_part = OFFSET_NOT_SET;
+		cstate->off_nl = -1;
+		cstate->off_nl_nosnap = -1;
 		break;
 
 	case DLT_PFSYNC:
-		off_linktype.constant_part = -1;
-		off_linkpl.constant_part = 4;
-		off_nl = 0;
-		off_nl_nosnap = 0;
+		cstate->off_linktype.constant_part = OFFSET_NOT_SET;
+		cstate->off_linkpl.constant_part = 4;
+		cstate->off_nl = 0;
+		cstate->off_nl_nosnap = 0;
 		break;
 
 	case DLT_AX25_KISS:
 		/*
 		 * Currently, only raw "link[N:M]" filtering is supported.
 		 */
-		off_linktype.constant_part = -1;	/* variable, min 15, max 71 steps of 7 */
-		off_linkpl.constant_part = -1;
-		off_nl = -1;		/* variable, min 16, max 71 steps of 7 */
-		off_nl_nosnap = -1;	/* no 802.2 LLC */
+		cstate->off_linktype.constant_part = OFFSET_NOT_SET;	/* variable, min 15, max 71 steps of 7 */
+		cstate->off_linkpl.constant_part = OFFSET_NOT_SET;
+		cstate->off_nl = -1;		/* variable, min 16, max 71 steps of 7 */
+		cstate->off_nl_nosnap = -1;	/* no 802.2 LLC */
 		break;
 
 	case DLT_IPNET:
-		off_linktype.constant_part = 1;
-		off_linkpl.constant_part = 24;	/* ipnet header length */
-		off_nl = 0;
-		off_nl_nosnap = -1;
+		cstate->off_linktype.constant_part = 1;
+		cstate->off_linkpl.constant_part = 24;	/* ipnet header length */
+		cstate->off_nl = 0;
+		cstate->off_nl_nosnap = -1;
 		break;
 
 	case DLT_NETANALYZER:
-		off_linkhdr.constant_part = 4;	/* Ethernet header is past 4-byte pseudo-header */
-		off_linktype.constant_part = off_linkhdr.constant_part + 12;
-		off_linkpl.constant_part = off_linkhdr.constant_part + 14;	/* pseudo-header+Ethernet header length */
-		off_nl = 0;		/* Ethernet II */
-		off_nl_nosnap = 3;	/* 802.3+802.2 */
+		cstate->off_linkhdr.constant_part = 4;	/* Ethernet header is past 4-byte pseudo-header */
+		cstate->off_linktype.constant_part = cstate->off_linkhdr.constant_part + 12;
+		cstate->off_linkpl.constant_part = cstate->off_linkhdr.constant_part + 14;	/* pseudo-header+Ethernet header length */
+		cstate->off_nl = 0;		/* Ethernet II */
+		cstate->off_nl_nosnap = 3;	/* 802.3+802.2 */
 		break;
 
 	case DLT_NETANALYZER_TRANSPARENT:
-		off_linkhdr.constant_part = 12;	/* MAC header is past 4-byte pseudo-header, preamble, and SFD */
-		off_linktype.constant_part = off_linkhdr.constant_part + 12;
-		off_linkpl.constant_part = off_linkhdr.constant_part + 14;	/* pseudo-header+preamble+SFD+Ethernet header length */
-		off_nl = 0;		/* Ethernet II */
-		off_nl_nosnap = 3;	/* 802.3+802.2 */
+		cstate->off_linkhdr.constant_part = 12;	/* MAC header is past 4-byte pseudo-header, preamble, and SFD */
+		cstate->off_linktype.constant_part = cstate->off_linkhdr.constant_part + 12;
+		cstate->off_linkpl.constant_part = cstate->off_linkhdr.constant_part + 14;	/* pseudo-header+preamble+SFD+Ethernet header length */
+		cstate->off_nl = 0;		/* Ethernet II */
+		cstate->off_nl_nosnap = 3;	/* 802.3+802.2 */
 		break;
 
 	default:
@@ -1501,30 +1587,31 @@
 		 * For values in the range in which we've assigned new
 		 * DLT_ values, only raw "link[N:M]" filtering is supported.
 		 */
-		if (linktype >= DLT_MATCHING_MIN &&
-		    linktype <= DLT_MATCHING_MAX) {
-			off_linktype.constant_part = -1;
-			off_linkpl.constant_part = -1;
-			off_nl = -1;
-			off_nl_nosnap = -1;
+		if (cstate->linktype >= DLT_MATCHING_MIN &&
+		    cstate->linktype <= DLT_MATCHING_MAX) {
+			cstate->off_linktype.constant_part = OFFSET_NOT_SET;
+			cstate->off_linkpl.constant_part = OFFSET_NOT_SET;
+			cstate->off_nl = -1;
+			cstate->off_nl_nosnap = -1;
 		} else {
-			bpf_error("unknown data link type %d", linktype);
+			bpf_error(cstate, "unknown data link type %d", cstate->linktype);
 		}
 		break;
 	}
 
-	off_outermostlinkhdr = off_prevlinkhdr = off_linkhdr;
+	cstate->off_outermostlinkhdr = cstate->off_prevlinkhdr = cstate->off_linkhdr;
 }
 
 /*
  * Load a value relative to the specified absolute offset.
  */
 static struct slist *
-gen_load_absoffsetrel(bpf_abs_offset *abs_offset, u_int offset, u_int size)
+gen_load_absoffsetrel(compiler_state_t *cstate, bpf_abs_offset *abs_offset,
+    u_int offset, u_int size)
 {
 	struct slist *s, *s2;
 
-	s = gen_abs_offset_varpart(abs_offset);
+	s = gen_abs_offset_varpart(cstate, abs_offset);
 
 	/*
 	 * If "s" is non-null, it has code to arrange that the X register
@@ -1541,7 +1628,7 @@
 		 * variable part of the absolute offset into the X register.
 		 * Do an indirect load, to use the X register as an offset.
 		 */
-		s2 = new_stmt(BPF_LD|BPF_IND|size);
+		s2 = new_stmt(cstate, BPF_LD|BPF_IND|size);
 		s2->s.k = abs_offset->constant_part + offset;
 		sappend(s, s2);
 	} else {
@@ -1549,7 +1636,7 @@
 		 * There is no variable part of the absolute offset, so
 		 * just do an absolute load.
 		 */
-		s = new_stmt(BPF_LD|BPF_ABS|size);
+		s = new_stmt(cstate, BPF_LD|BPF_ABS|size);
 		s->s.k = abs_offset->constant_part + offset;
 	}
 	return s;
@@ -1559,45 +1646,44 @@
  * Load a value relative to the beginning of the specified header.
  */
 static struct slist *
-gen_load_a(offrel, offset, size)
-	enum e_offrel offrel;
-	u_int offset, size;
+gen_load_a(compiler_state_t *cstate, enum e_offrel offrel, u_int offset,
+    u_int size)
 {
 	struct slist *s, *s2;
 
 	switch (offrel) {
 
 	case OR_PACKET:
-                s = new_stmt(BPF_LD|BPF_ABS|size);
+                s = new_stmt(cstate, BPF_LD|BPF_ABS|size);
                 s->s.k = offset;
 		break;
 
 	case OR_LINKHDR:
-		s = gen_load_absoffsetrel(&off_linkhdr, offset, size);
+		s = gen_load_absoffsetrel(cstate, &cstate->off_linkhdr, offset, size);
 		break;
 
 	case OR_PREVLINKHDR:
-		s = gen_load_absoffsetrel(&off_prevlinkhdr, offset, size);
+		s = gen_load_absoffsetrel(cstate, &cstate->off_prevlinkhdr, offset, size);
 		break;
 
 	case OR_LLC:
-		s = gen_load_absoffsetrel(&off_linkpl, offset, size);
+		s = gen_load_absoffsetrel(cstate, &cstate->off_linkpl, offset, size);
 		break;
 
 	case OR_PREVMPLSHDR:
-		s = gen_load_absoffsetrel(&off_linkpl, off_nl - 4 + offset, size);
+		s = gen_load_absoffsetrel(cstate, &cstate->off_linkpl, cstate->off_nl - 4 + offset, size);
 		break;
 
 	case OR_LINKPL:
-		s = gen_load_absoffsetrel(&off_linkpl, off_nl + offset, size);
+		s = gen_load_absoffsetrel(cstate, &cstate->off_linkpl, cstate->off_nl + offset, size);
 		break;
 
 	case OR_LINKPL_NOSNAP:
-		s = gen_load_absoffsetrel(&off_linkpl, off_nl_nosnap + offset, size);
+		s = gen_load_absoffsetrel(cstate, &cstate->off_linkpl, cstate->off_nl_nosnap + offset, size);
 		break;
 
 	case OR_LINKTYPE:
-		s = gen_load_absoffsetrel(&off_linktype, offset, size);
+		s = gen_load_absoffsetrel(cstate, &cstate->off_linktype, offset, size);
 		break;
 
 	case OR_TRAN_IPV4:
@@ -1607,7 +1693,7 @@
 		 * preceded by a variable-length header such as a radio
 		 * header), in bytes.
 		 */
-		s = gen_loadx_iphdrlen();
+		s = gen_loadx_iphdrlen(cstate);
 
 		/*
 		 * Load the item at {offset of the link-layer payload} +
@@ -1620,13 +1706,13 @@
 		 * value in the X register, and we include the constant
 		 * part in the offset of the load.
 		 */
-		s2 = new_stmt(BPF_LD|BPF_IND|size);
-		s2->s.k = off_linkpl.constant_part + off_nl + offset;
+		s2 = new_stmt(cstate, BPF_LD|BPF_IND|size);
+		s2->s.k = cstate->off_linkpl.constant_part + cstate->off_nl + offset;
 		sappend(s, s2);
 		break;
 
 	case OR_TRAN_IPV6:
-		s = gen_load_absoffsetrel(&off_linkpl, off_nl + 40 + offset, size);
+		s = gen_load_absoffsetrel(cstate, &cstate->off_linkpl, cstate->off_nl + 40 + offset, size);
 		break;
 
 	default:
@@ -1642,11 +1728,11 @@
  * payload.
  */
 static struct slist *
-gen_loadx_iphdrlen()
+gen_loadx_iphdrlen(compiler_state_t *cstate)
 {
 	struct slist *s, *s2;
 
-	s = gen_abs_offset_varpart(&off_linkpl);
+	s = gen_abs_offset_varpart(cstate, &cstate->off_linkpl);
 	if (s != NULL) {
 		/*
 		 * The offset of the link-layer payload has a variable
@@ -1658,13 +1744,13 @@
 		 * value in question into the A register and add to it
 		 * the value from the X register.
 		 */
-		s2 = new_stmt(BPF_LD|BPF_IND|BPF_B);
-		s2->s.k = off_linkpl.constant_part + off_nl;
+		s2 = new_stmt(cstate, BPF_LD|BPF_IND|BPF_B);
+		s2->s.k = cstate->off_linkpl.constant_part + cstate->off_nl;
 		sappend(s, s2);
-		s2 = new_stmt(BPF_ALU|BPF_AND|BPF_K);
+		s2 = new_stmt(cstate, BPF_ALU|BPF_AND|BPF_K);
 		s2->s.k = 0xf;
 		sappend(s, s2);
-		s2 = new_stmt(BPF_ALU|BPF_LSH|BPF_K);
+		s2 = new_stmt(cstate, BPF_ALU|BPF_LSH|BPF_K);
 		s2->s.k = 2;
 		sappend(s, s2);
 
@@ -1674,8 +1760,8 @@
 		 * the link-layer payload, which is still in the X
 		 * register, and move the result into the X register.
 		 */
-		sappend(s, new_stmt(BPF_ALU|BPF_ADD|BPF_X));
-		sappend(s, new_stmt(BPF_MISC|BPF_TAX));
+		sappend(s, new_stmt(cstate, BPF_ALU|BPF_ADD|BPF_X));
+		sappend(s, new_stmt(cstate, BPF_MISC|BPF_TAX));
 	} else {
 		/*
 		 * The offset of the link-layer payload is a constant,
@@ -1684,42 +1770,41 @@
 		 *
 		 * This means we can use the 4*([k]&0xf) addressing
 		 * mode.  Load the length of the IPv4 header, which
-		 * is at an offset of off_nl from the beginning of
+		 * is at an offset of cstate->off_nl from the beginning of
 		 * the link-layer payload, and thus at an offset of
-		 * off_linkpl.constant_part + off_nl from the beginning
+		 * cstate->off_linkpl.constant_part + cstate->off_nl from the beginning
 		 * of the raw packet data, using that addressing mode.
 		 */
-		s = new_stmt(BPF_LDX|BPF_MSH|BPF_B);
-		s->s.k = off_linkpl.constant_part + off_nl;
+		s = new_stmt(cstate, BPF_LDX|BPF_MSH|BPF_B);
+		s->s.k = cstate->off_linkpl.constant_part + cstate->off_nl;
 	}
 	return s;
 }
 
 static struct block *
-gen_uncond(rsense)
-	int rsense;
+gen_uncond(compiler_state_t *cstate, int rsense)
 {
 	struct block *b;
 	struct slist *s;
 
-	s = new_stmt(BPF_LD|BPF_IMM);
+	s = new_stmt(cstate, BPF_LD|BPF_IMM);
 	s->s.k = !rsense;
-	b = new_block(JMP(BPF_JEQ));
+	b = new_block(cstate, JMP(BPF_JEQ));
 	b->stmts = s;
 
 	return b;
 }
 
 static inline struct block *
-gen_true()
+gen_true(compiler_state_t *cstate)
 {
-	return gen_uncond(1);
+	return gen_uncond(cstate, 1);
 }
 
 static inline struct block *
-gen_false()
+gen_false(compiler_state_t *cstate)
 {
-	return gen_uncond(0);
+	return gen_uncond(cstate, 0);
 }
 
 /*
@@ -1740,8 +1825,7 @@
  * the appropriate test.
  */
 static struct block *
-gen_ether_linktype(proto)
-	register int proto;
+gen_ether_linktype(compiler_state_t *cstate, int proto)
 {
 	struct block *b0, *b1;
 
@@ -1762,9 +1846,9 @@
 		 * DSAP, as we do for other types <= ETHERMTU
 		 * (i.e., other SAP values)?
 		 */
-		b0 = gen_cmp_gt(OR_LINKTYPE, 0, BPF_H, ETHERMTU);
+		b0 = gen_cmp_gt(cstate, OR_LINKTYPE, 0, BPF_H, ETHERMTU);
 		gen_not(b0);
-		b1 = gen_cmp(OR_LLC, 0, BPF_H, (bpf_int32)
+		b1 = gen_cmp(cstate, OR_LLC, 0, BPF_H, (bpf_int32)
 			     ((proto << 8) | proto));
 		gen_and(b0, b1);
 		return b1;
@@ -1802,22 +1886,22 @@
 		 * This generates code to check both for the
 		 * IPX LSAP (Ethernet_802.2) and for Ethernet_802.3.
 		 */
-		b0 = gen_cmp(OR_LLC, 0, BPF_B, (bpf_int32)LLCSAP_IPX);
-		b1 = gen_cmp(OR_LLC, 0, BPF_H, (bpf_int32)0xFFFF);
+		b0 = gen_cmp(cstate, OR_LLC, 0, BPF_B, (bpf_int32)LLCSAP_IPX);
+		b1 = gen_cmp(cstate, OR_LLC, 0, BPF_H, (bpf_int32)0xFFFF);
 		gen_or(b0, b1);
 
 		/*
 		 * Now we add code to check for SNAP frames with
 		 * ETHERTYPE_IPX, i.e. Ethernet_SNAP.
 		 */
-		b0 = gen_snap(0x000000, ETHERTYPE_IPX);
+		b0 = gen_snap(cstate, 0x000000, ETHERTYPE_IPX);
 		gen_or(b0, b1);
 
 		/*
 		 * Now we generate code to check for 802.3
 		 * frames in general.
 		 */
-		b0 = gen_cmp_gt(OR_LINKTYPE, 0, BPF_H, ETHERMTU);
+		b0 = gen_cmp_gt(cstate, OR_LINKTYPE, 0, BPF_H, ETHERMTU);
 		gen_not(b0);
 
 		/*
@@ -1833,7 +1917,7 @@
 		 * do that before checking for the other frame
 		 * types.
 		 */
-		b0 = gen_cmp(OR_LINKTYPE, 0, BPF_H, (bpf_int32)ETHERTYPE_IPX);
+		b0 = gen_cmp(cstate, OR_LINKTYPE, 0, BPF_H, (bpf_int32)ETHERTYPE_IPX);
 		gen_or(b0, b1);
 		return b1;
 
@@ -1849,7 +1933,7 @@
 		 * we check for an Ethernet type field less than
 		 * 1500, which means it's an 802.3 length field.
 		 */
-		b0 = gen_cmp_gt(OR_LINKTYPE, 0, BPF_H, ETHERMTU);
+		b0 = gen_cmp_gt(cstate, OR_LINKTYPE, 0, BPF_H, ETHERMTU);
 		gen_not(b0);
 
 		/*
@@ -1864,9 +1948,9 @@
 		 * type of ETHERTYPE_AARP (Appletalk ARP).
 		 */
 		if (proto == ETHERTYPE_ATALK)
-			b1 = gen_snap(0x080007, ETHERTYPE_ATALK);
+			b1 = gen_snap(cstate, 0x080007, ETHERTYPE_ATALK);
 		else	/* proto == ETHERTYPE_AARP */
-			b1 = gen_snap(0x000000, ETHERTYPE_AARP);
+			b1 = gen_snap(cstate, 0x000000, ETHERTYPE_AARP);
 		gen_and(b0, b1);
 
 		/*
@@ -1874,7 +1958,7 @@
 		 * phase 1?); we just check for the Ethernet
 		 * protocol type.
 		 */
-		b0 = gen_cmp(OR_LINKTYPE, 0, BPF_H, (bpf_int32)proto);
+		b0 = gen_cmp(cstate, OR_LINKTYPE, 0, BPF_H, (bpf_int32)proto);
 
 		gen_or(b0, b1);
 		return b1;
@@ -1889,9 +1973,9 @@
 			 * a length field, <= ETHERMTU) and
 			 * then check the DSAP.
 			 */
-			b0 = gen_cmp_gt(OR_LINKTYPE, 0, BPF_H, ETHERMTU);
+			b0 = gen_cmp_gt(cstate, OR_LINKTYPE, 0, BPF_H, ETHERMTU);
 			gen_not(b0);
-			b1 = gen_cmp(OR_LINKTYPE, 2, BPF_B, (bpf_int32)proto);
+			b1 = gen_cmp(cstate, OR_LINKTYPE, 2, BPF_B, (bpf_int32)proto);
 			gen_and(b0, b1);
 			return b1;
 		} else {
@@ -1904,28 +1988,62 @@
 			 * will fail and the frame won't match,
 			 * which is what we want).
 			 */
-			return gen_cmp(OR_LINKTYPE, 0, BPF_H,
+			return gen_cmp(cstate, OR_LINKTYPE, 0, BPF_H,
 			    (bpf_int32)proto);
 		}
 	}
 }
 
+static struct block *
+gen_loopback_linktype(compiler_state_t *cstate, int proto)
+{
+	/*
+	 * For DLT_NULL, the link-layer header is a 32-bit word
+	 * containing an AF_ value in *host* byte order, and for
+	 * DLT_ENC, the link-layer header begins with a 32-bit
+	 * word containing an AF_ value in host byte order.
+	 *
+	 * In addition, if we're reading a saved capture file,
+	 * the host byte order in the capture may not be the
+	 * same as the host byte order on this machine.
+	 *
+	 * For DLT_LOOP, the link-layer header is a 32-bit
+	 * word containing an AF_ value in *network* byte order.
+	 */
+	if (cstate->linktype == DLT_NULL || cstate->linktype == DLT_ENC) {
+		/*
+		 * The AF_ value is in host byte order, but the BPF
+		 * interpreter will convert it to network byte order.
+		 *
+		 * If this is a save file, and it's from a machine
+		 * with the opposite byte order to ours, we byte-swap
+		 * the AF_ value.
+		 *
+		 * Then we run it through "htonl()", and generate
+		 * code to compare against the result.
+		 */
+		if (cstate->bpf_pcap->rfile != NULL && cstate->bpf_pcap->swapped)
+			proto = SWAPLONG(proto);
+		proto = htonl(proto);
+	}
+	return (gen_cmp(cstate, OR_LINKHDR, 0, BPF_W, (bpf_int32)proto));
+}
+
 /*
  * "proto" is an Ethernet type value and for IPNET, if it is not IPv4
  * or IPv6 then we have an error.
  */
 static struct block *
-gen_ipnet_linktype(proto)
-	register int proto;
+gen_ipnet_linktype(compiler_state_t *cstate, int proto)
 {
 	switch (proto) {
 
 	case ETHERTYPE_IP:
-		return gen_cmp(OR_LINKTYPE, 0, BPF_B, (bpf_int32)IPH_AF_INET);
+		return gen_cmp(cstate, OR_LINKTYPE, 0, BPF_B, (bpf_int32)IPH_AF_INET);
 		/* NOTREACHED */
 
 	case ETHERTYPE_IPV6:
-		return gen_cmp(OR_LINKTYPE, 0, BPF_B,
+		return gen_cmp(cstate, OR_LINKTYPE, 0, BPF_B,
 		    (bpf_int32)IPH_AF_INET6);
 		/* NOTREACHED */
 
@@ -1933,7 +2051,7 @@
 		break;
 	}
 
-	return gen_false();
+	return gen_false(cstate);
 }
 
 /*
@@ -1945,8 +2063,7 @@
  * LINUX_SLL_P_802_2 value and then do the appropriate test.
  */
 static struct block *
-gen_linux_sll_linktype(proto)
-	register int proto;
+gen_linux_sll_linktype(compiler_state_t *cstate, int proto)
 {
 	struct block *b0, *b1;
 
@@ -1967,8 +2084,8 @@
 		 * DSAP, as we do for other types <= ETHERMTU
 		 * (i.e., other SAP values)?
 		 */
-		b0 = gen_cmp(OR_LINKTYPE, 0, BPF_H, LINUX_SLL_P_802_2);
-		b1 = gen_cmp(OR_LLC, 0, BPF_H, (bpf_int32)
+		b0 = gen_cmp(cstate, OR_LINKTYPE, 0, BPF_H, LINUX_SLL_P_802_2);
+		b1 = gen_cmp(cstate, OR_LLC, 0, BPF_H, (bpf_int32)
 			     ((proto << 8) | proto));
 		gen_and(b0, b1);
 		return b1;
@@ -1999,17 +2116,17 @@
 		 * then put a check for LINUX_SLL_P_802_2 frames
 		 * before it.
 		 */
-		b0 = gen_cmp(OR_LLC, 0, BPF_B, (bpf_int32)LLCSAP_IPX);
-		b1 = gen_snap(0x000000, ETHERTYPE_IPX);
+		b0 = gen_cmp(cstate, OR_LLC, 0, BPF_B, (bpf_int32)LLCSAP_IPX);
+		b1 = gen_snap(cstate, 0x000000, ETHERTYPE_IPX);
 		gen_or(b0, b1);
-		b0 = gen_cmp(OR_LINKTYPE, 0, BPF_H, LINUX_SLL_P_802_2);
+		b0 = gen_cmp(cstate, OR_LINKTYPE, 0, BPF_H, LINUX_SLL_P_802_2);
 		gen_and(b0, b1);
 
 		/*
 		 * Now check for 802.3 frames and OR that with
 		 * the previous test.
 		 */
-		b0 = gen_cmp(OR_LINKTYPE, 0, BPF_H, LINUX_SLL_P_802_3);
+		b0 = gen_cmp(cstate, OR_LINKTYPE, 0, BPF_H, LINUX_SLL_P_802_3);
 		gen_or(b0, b1);
 
 		/*
@@ -2017,7 +2134,7 @@
 		 * do that before checking for the other frame
 		 * types.
 		 */
-		b0 = gen_cmp(OR_LINKTYPE, 0, BPF_H, (bpf_int32)ETHERTYPE_IPX);
+		b0 = gen_cmp(cstate, OR_LINKTYPE, 0, BPF_H, (bpf_int32)ETHERTYPE_IPX);
 		gen_or(b0, b1);
 		return b1;
 
@@ -2033,7 +2150,7 @@
 		 * we check for the 802.2 protocol type in the
 		 * "Ethernet type" field.
 		 */
-		b0 = gen_cmp(OR_LINKTYPE, 0, BPF_H, LINUX_SLL_P_802_2);
+		b0 = gen_cmp(cstate, OR_LINKTYPE, 0, BPF_H, LINUX_SLL_P_802_2);
 
 		/*
 		 * 802.2-encapsulated ETHERTYPE_ATALK packets are
@@ -2047,9 +2164,9 @@
 		 * type of ETHERTYPE_AARP (Appletalk ARP).
 		 */
 		if (proto == ETHERTYPE_ATALK)
-			b1 = gen_snap(0x080007, ETHERTYPE_ATALK);
+			b1 = gen_snap(cstate, 0x080007, ETHERTYPE_ATALK);
 		else	/* proto == ETHERTYPE_AARP */
-			b1 = gen_snap(0x000000, ETHERTYPE_AARP);
+			b1 = gen_snap(cstate, 0x000000, ETHERTYPE_AARP);
 		gen_and(b0, b1);
 
 		/*
@@ -2057,7 +2174,7 @@
 		 * phase 1?); we just check for the Ethernet
 		 * protocol type.
 		 */
-		b0 = gen_cmp(OR_LINKTYPE, 0, BPF_H, (bpf_int32)proto);
+		b0 = gen_cmp(cstate, OR_LINKTYPE, 0, BPF_H, (bpf_int32)proto);
 
 		gen_or(b0, b1);
 		return b1;
@@ -2071,8 +2188,8 @@
 			 * in the "Ethernet type" field, and
 			 * then check the DSAP.
 			 */
-			b0 = gen_cmp(OR_LINKTYPE, 0, BPF_H, LINUX_SLL_P_802_2);
-			b1 = gen_cmp(OR_LINKHDR, off_linkpl.constant_part, BPF_B,
+			b0 = gen_cmp(cstate, OR_LINKTYPE, 0, BPF_H, LINUX_SLL_P_802_2);
+			b1 = gen_cmp(cstate, OR_LINKHDR, cstate->off_linkpl.constant_part, BPF_B,
 			     (bpf_int32)proto);
 			gen_and(b0, b1);
 			return b1;
@@ -2086,13 +2203,13 @@
 			 * will fail and the frame won't match,
 			 * which is what we want).
 			 */
-			return gen_cmp(OR_LINKTYPE, 0, BPF_H, (bpf_int32)proto);
+			return gen_cmp(cstate, OR_LINKTYPE, 0, BPF_H, (bpf_int32)proto);
 		}
 	}
 }
 
 static struct slist *
-gen_load_prism_llprefixlen()
+gen_load_prism_llprefixlen(compiler_state_t *cstate)
 {
 	struct slist *s1, *s2;
 	struct slist *sjeq_avs_cookie;
@@ -2103,7 +2220,7 @@
 	 * we are generating jmp instructions within a normal
 	 * slist of instructions
 	 */
-	no_optimize = 1;
+	cstate->no_optimize = 1;
 
 	/*
 	 * Generate code to load the length of the radio header into
@@ -2124,24 +2241,24 @@
 	 * but no known software generates headers that aren't 144
 	 * bytes long.
 	 */
-	if (off_linkhdr.reg != -1) {
+	if (cstate->off_linkhdr.reg != -1) {
 		/*
 		 * Load the cookie.
 		 */
-		s1 = new_stmt(BPF_LD|BPF_W|BPF_ABS);
+		s1 = new_stmt(cstate, BPF_LD|BPF_W|BPF_ABS);
 		s1->s.k = 0;
 
 		/*
 		 * AND it with 0xFFFFF000.
 		 */
-		s2 = new_stmt(BPF_ALU|BPF_AND|BPF_K);
+		s2 = new_stmt(cstate, BPF_ALU|BPF_AND|BPF_K);
 		s2->s.k = 0xFFFFF000;
 		sappend(s1, s2);
 
 		/*
 		 * Compare with 0x80211000.
 		 */
-		sjeq_avs_cookie = new_stmt(JMP(BPF_JEQ));
+		sjeq_avs_cookie = new_stmt(cstate, JMP(BPF_JEQ));
 		sjeq_avs_cookie->s.k = 0x80211000;
 		sappend(s1, sjeq_avs_cookie);
 
@@ -2152,7 +2269,7 @@
 		 * the AVS header are the length of the AVS header.
 		 * That field is big-endian.
 		 */
-		s2 = new_stmt(BPF_LD|BPF_W|BPF_ABS);
+		s2 = new_stmt(cstate, BPF_LD|BPF_W|BPF_ABS);
 		s2->s.k = 4;
 		sappend(s1, s2);
 		sjeq_avs_cookie->s.jt = s2;
@@ -2165,7 +2282,7 @@
 		 * it's added to the PC, so, as we're jumping
 		 * over a single instruction, it should be 1.)
 		 */
-		sjcommon = new_stmt(JMP(BPF_JA));
+		sjcommon = new_stmt(cstate, JMP(BPF_JA));
 		sjcommon->s.k = 1;
 		sappend(s1, sjcommon);
 
@@ -2175,7 +2292,7 @@
 		 * into the A register.  Have the test for an AVS
 		 * header branch here if we don't have an AVS header.
 		 */
-		s2 = new_stmt(BPF_LD|BPF_W|BPF_IMM);
+		s2 = new_stmt(cstate, BPF_LD|BPF_W|BPF_IMM);
 		s2->s.k = 144;
 		sappend(s1, s2);
 		sjeq_avs_cookie->s.jf = s2;
@@ -2185,15 +2302,15 @@
 		 * it.  The code for the AVS header will jump here after
 		 * loading the length of the AVS header.
 		 */
-		s2 = new_stmt(BPF_ST);
-		s2->s.k = off_linkhdr.reg;
+		s2 = new_stmt(cstate, BPF_ST);
+		s2->s.k = cstate->off_linkhdr.reg;
 		sappend(s1, s2);
 		sjcommon->s.jf = s2;
 
 		/*
 		 * Now move it into the X register.
 		 */
-		s2 = new_stmt(BPF_MISC|BPF_TAX);
+		s2 = new_stmt(cstate, BPF_MISC|BPF_TAX);
 		sappend(s1, s2);
 
 		return (s1);
@@ -2202,7 +2319,7 @@
 }
 
 static struct slist *
-gen_load_avs_llprefixlen()
+gen_load_avs_llprefixlen(compiler_state_t *cstate)
 {
 	struct slist *s1, *s2;
 
@@ -2213,27 +2330,27 @@
 	 * generated uses that prefix, so we don't need to generate any
 	 * code to load it.)
 	 */
-	if (off_linkhdr.reg != -1) {
+	if (cstate->off_linkhdr.reg != -1) {
 		/*
 		 * The 4 bytes at an offset of 4 from the beginning of
 		 * the AVS header are the length of the AVS header.
 		 * That field is big-endian.
 		 */
-		s1 = new_stmt(BPF_LD|BPF_W|BPF_ABS);
+		s1 = new_stmt(cstate, BPF_LD|BPF_W|BPF_ABS);
 		s1->s.k = 4;
 
 		/*
 		 * Now allocate a register to hold that value and store
 		 * it.
 		 */
-		s2 = new_stmt(BPF_ST);
-		s2->s.k = off_linkhdr.reg;
+		s2 = new_stmt(cstate, BPF_ST);
+		s2->s.k = cstate->off_linkhdr.reg;
 		sappend(s1, s2);
 
 		/*
 		 * Now move it into the X register.
 		 */
-		s2 = new_stmt(BPF_MISC|BPF_TAX);
+		s2 = new_stmt(cstate, BPF_MISC|BPF_TAX);
 		sappend(s1, s2);
 
 		return (s1);
@@ -2242,7 +2359,7 @@
 }
 
 static struct slist *
-gen_load_radiotap_llprefixlen()
+gen_load_radiotap_llprefixlen(compiler_state_t *cstate)
 {
 	struct slist *s1, *s2;
 
@@ -2253,7 +2370,7 @@
 	 * generated uses that prefix, so we don't need to generate any
 	 * code to load it.)
 	 */
-	if (off_linkhdr.reg != -1) {
+	if (cstate->off_linkhdr.reg != -1) {
 		/*
 		 * The 2 bytes at offsets of 2 and 3 from the beginning
 		 * of the radiotap header are the length of the radiotap
@@ -2265,36 +2382,36 @@
 		 * Load the high-order byte, at an offset of 3, shift it
 		 * left a byte, and put the result in the X register.
 		 */
-		s1 = new_stmt(BPF_LD|BPF_B|BPF_ABS);
+		s1 = new_stmt(cstate, BPF_LD|BPF_B|BPF_ABS);
 		s1->s.k = 3;
-		s2 = new_stmt(BPF_ALU|BPF_LSH|BPF_K);
+		s2 = new_stmt(cstate, BPF_ALU|BPF_LSH|BPF_K);
 		sappend(s1, s2);
 		s2->s.k = 8;
-		s2 = new_stmt(BPF_MISC|BPF_TAX);
+		s2 = new_stmt(cstate, BPF_MISC|BPF_TAX);
 		sappend(s1, s2);
 
 		/*
 		 * Load the next byte, at an offset of 2, and OR the
 		 * value from the X register into it.
 		 */
-		s2 = new_stmt(BPF_LD|BPF_B|BPF_ABS);
+		s2 = new_stmt(cstate, BPF_LD|BPF_B|BPF_ABS);
 		sappend(s1, s2);
 		s2->s.k = 2;
-		s2 = new_stmt(BPF_ALU|BPF_OR|BPF_X);
+		s2 = new_stmt(cstate, BPF_ALU|BPF_OR|BPF_X);
 		sappend(s1, s2);
 
 		/*
 		 * Now allocate a register to hold that value and store
 		 * it.
 		 */
-		s2 = new_stmt(BPF_ST);
-		s2->s.k = off_linkhdr.reg;
+		s2 = new_stmt(cstate, BPF_ST);
+		s2->s.k = cstate->off_linkhdr.reg;
 		sappend(s1, s2);
 
 		/*
 		 * Now move it into the X register.
 		 */
-		s2 = new_stmt(BPF_MISC|BPF_TAX);
+		s2 = new_stmt(cstate, BPF_MISC|BPF_TAX);
 		sappend(s1, s2);
 
 		return (s1);
@@ -2312,7 +2429,7 @@
  * that's done in finish_parse().
  */
 static struct slist *
-gen_load_ppi_llprefixlen()
+gen_load_ppi_llprefixlen(compiler_state_t *cstate)
 {
 	struct slist *s1, *s2;
 
@@ -2321,7 +2438,7 @@
 	 * into the register assigned to hold that length, if one has
 	 * been assigned.
 	 */
-	if (off_linkhdr.reg != -1) {
+	if (cstate->off_linkhdr.reg != -1) {
 		/*
 		 * The 2 bytes at offsets of 2 and 3 from the beginning
 		 * of the radiotap header are the length of the radiotap
@@ -2333,36 +2450,36 @@
 		 * Load the high-order byte, at an offset of 3, shift it
 		 * left a byte, and put the result in the X register.
 		 */
-		s1 = new_stmt(BPF_LD|BPF_B|BPF_ABS);
+		s1 = new_stmt(cstate, BPF_LD|BPF_B|BPF_ABS);
 		s1->s.k = 3;
-		s2 = new_stmt(BPF_ALU|BPF_LSH|BPF_K);
+		s2 = new_stmt(cstate, BPF_ALU|BPF_LSH|BPF_K);
 		sappend(s1, s2);
 		s2->s.k = 8;
-		s2 = new_stmt(BPF_MISC|BPF_TAX);
+		s2 = new_stmt(cstate, BPF_MISC|BPF_TAX);
 		sappend(s1, s2);
 
 		/*
 		 * Load the next byte, at an offset of 2, and OR the
 		 * value from the X register into it.
 		 */
-		s2 = new_stmt(BPF_LD|BPF_B|BPF_ABS);
+		s2 = new_stmt(cstate, BPF_LD|BPF_B|BPF_ABS);
 		sappend(s1, s2);
 		s2->s.k = 2;
-		s2 = new_stmt(BPF_ALU|BPF_OR|BPF_X);
+		s2 = new_stmt(cstate, BPF_ALU|BPF_OR|BPF_X);
 		sappend(s1, s2);
 
 		/*
 		 * Now allocate a register to hold that value and store
 		 * it.
 		 */
-		s2 = new_stmt(BPF_ST);
-		s2->s.k = off_linkhdr.reg;
+		s2 = new_stmt(cstate, BPF_ST);
+		s2->s.k = cstate->off_linkhdr.reg;
 		sappend(s1, s2);
 
 		/*
 		 * Now move it into the X register.
 		 */
-		s2 = new_stmt(BPF_MISC|BPF_TAX);
+		s2 = new_stmt(cstate, BPF_MISC|BPF_TAX);
 		sappend(s1, s2);
 
 		return (s1);
@@ -2378,18 +2495,19 @@
  * radio information.
  */
 static struct slist *
-gen_load_802_11_header_len(struct slist *s, struct slist *snext)
+gen_load_802_11_header_len(compiler_state_t *cstate, struct slist *s, struct slist *snext)
 {
 	struct slist *s2;
 	struct slist *sjset_data_frame_1;
 	struct slist *sjset_data_frame_2;
 	struct slist *sjset_qos;
-	struct slist *sjset_radiotap_flags;
-	struct slist *sjset_radiotap_tsft;
+	struct slist *sjset_radiotap_flags_present;
+	struct slist *sjset_radiotap_ext_present;
+	struct slist *sjset_radiotap_tsft_present;
 	struct slist *sjset_tsft_datapad, *sjset_notsft_datapad;
 	struct slist *s_roundup;
 
-	if (off_linkpl.reg == -1) {
+	if (cstate->off_linkpl.reg == -1) {
 		/*
 		 * No register has been assigned to the offset of
 		 * the link-layer payload, which means nobody needs
@@ -2404,7 +2522,7 @@
 	 * we are generating jmp instructions within a normal
 	 * slist of instructions
 	 */
-	no_optimize = 1;
+	cstate->no_optimize = 1;
 
 	/*
 	 * If "s" is non-null, it has code to arrange that the X register
@@ -2421,30 +2539,30 @@
 		 *
 		 * Load the length of the fixed-length prefix preceding
 		 * the link-layer header (if any) into the X register,
-		 * and store it in the off_linkpl.reg register.
+		 * and store it in the cstate->off_linkpl.reg register.
 		 * That length is off_outermostlinkhdr.constant_part.
 		 */
-		s = new_stmt(BPF_LDX|BPF_IMM);
-		s->s.k = off_outermostlinkhdr.constant_part;
+		s = new_stmt(cstate, BPF_LDX|BPF_IMM);
+		s->s.k = cstate->off_outermostlinkhdr.constant_part;
 	}
 
 	/*
 	 * The X register contains the offset of the beginning of the
 	 * link-layer header; add 24, which is the minimum length
 	 * of the MAC header for a data frame, to that, and store it
-	 * in off_linkpl.reg, and then load the Frame Control field,
+	 * in cstate->off_linkpl.reg, and then load the Frame Control field,
 	 * which is at the offset in the X register, with an indexed load.
 	 */
-	s2 = new_stmt(BPF_MISC|BPF_TXA);
+	s2 = new_stmt(cstate, BPF_MISC|BPF_TXA);
 	sappend(s, s2);
-	s2 = new_stmt(BPF_ALU|BPF_ADD|BPF_K);
+	s2 = new_stmt(cstate, BPF_ALU|BPF_ADD|BPF_K);
 	s2->s.k = 24;
 	sappend(s, s2);
-	s2 = new_stmt(BPF_ST);
-	s2->s.k = off_linkpl.reg;
+	s2 = new_stmt(cstate, BPF_ST);
+	s2->s.k = cstate->off_linkpl.reg;
 	sappend(s, s2);
 
-	s2 = new_stmt(BPF_LD|BPF_IND|BPF_B);
+	s2 = new_stmt(cstate, BPF_LD|BPF_IND|BPF_B);
 	s2->s.k = 0;
 	sappend(s, s2);
 
@@ -2453,7 +2571,7 @@
 	 * a data frame has the 0x08 bit (b3) in that field set and the
 	 * 0x04 bit (b2) clear.
 	 */
-	sjset_data_frame_1 = new_stmt(JMP(BPF_JSET));
+	sjset_data_frame_1 = new_stmt(cstate, JMP(BPF_JSET));
 	sjset_data_frame_1->s.k = 0x08;
 	sappend(s, sjset_data_frame_1);
 
@@ -2461,7 +2579,7 @@
 	 * If b3 is set, test b2, otherwise go to the first statement of
 	 * the rest of the program.
 	 */
-	sjset_data_frame_1->s.jt = sjset_data_frame_2 = new_stmt(JMP(BPF_JSET));
+	sjset_data_frame_1->s.jt = sjset_data_frame_2 = new_stmt(cstate, JMP(BPF_JSET));
 	sjset_data_frame_2->s.k = 0x04;
 	sappend(s, sjset_data_frame_2);
 	sjset_data_frame_1->s.jf = snext;
@@ -2472,24 +2590,24 @@
 	 * program.
 	 */
 	sjset_data_frame_2->s.jt = snext;
-	sjset_data_frame_2->s.jf = sjset_qos = new_stmt(JMP(BPF_JSET));
+	sjset_data_frame_2->s.jf = sjset_qos = new_stmt(cstate, JMP(BPF_JSET));
 	sjset_qos->s.k = 0x80;	/* QoS bit */
 	sappend(s, sjset_qos);
 
 	/*
-	 * If it's set, add 2 to off_linkpl.reg, to skip the QoS
+	 * If it's set, add 2 to cstate->off_linkpl.reg, to skip the QoS
 	 * field.
 	 * Otherwise, go to the first statement of the rest of the
 	 * program.
 	 */
-	sjset_qos->s.jt = s2 = new_stmt(BPF_LD|BPF_MEM);
-	s2->s.k = off_linkpl.reg;
+	sjset_qos->s.jt = s2 = new_stmt(cstate, BPF_LD|BPF_MEM);
+	s2->s.k = cstate->off_linkpl.reg;
 	sappend(s, s2);
-	s2 = new_stmt(BPF_ALU|BPF_ADD|BPF_IMM);
+	s2 = new_stmt(cstate, BPF_ALU|BPF_ADD|BPF_IMM);
 	s2->s.k = 2;
 	sappend(s, s2);
-	s2 = new_stmt(BPF_ST);
-	s2->s.k = off_linkpl.reg;
+	s2 = new_stmt(cstate, BPF_ST);
+	s2->s.k = cstate->off_linkpl.reg;
 	sappend(s, s2);
 
 	/*
@@ -2501,32 +2619,54 @@
 	 * little-endian, so we byte-swap all of the values
 	 * we test against, as they will be loaded as big-endian
 	 * values.
+	 *
+	 * XXX - in the general case, we would have to scan through
+	 * *all* the presence bits, if there's more than one word of
+	 * presence bits.  That would require a loop, meaning that
+	 * we wouldn't be able to run the filter in the kernel.
+	 *
+	 * We assume here that the Atheros adapters that insert the
+	 * annoying padding don't have multiple antennae and therefore
+	 * do not generate radiotap headers with multiple presence words.
 	 */
-	if (linktype == DLT_IEEE802_11_RADIO) {
+	if (cstate->linktype == DLT_IEEE802_11_RADIO) {
 		/*
 		 * Is the IEEE80211_RADIOTAP_FLAGS bit (0x0000002) set
-		 * in the presence flag?
+		 * in the first presence flag word?
 		 */
-		sjset_qos->s.jf = s2 = new_stmt(BPF_LD|BPF_ABS|BPF_W);
+		sjset_qos->s.jf = s2 = new_stmt(cstate, BPF_LD|BPF_ABS|BPF_W);
 		s2->s.k = 4;
 		sappend(s, s2);
 
-		sjset_radiotap_flags = new_stmt(JMP(BPF_JSET));
-		sjset_radiotap_flags->s.k = SWAPLONG(0x00000002);
-		sappend(s, sjset_radiotap_flags);
+		sjset_radiotap_flags_present = new_stmt(cstate, JMP(BPF_JSET));
+		sjset_radiotap_flags_present->s.k = SWAPLONG(0x00000002);
+		sappend(s, sjset_radiotap_flags_present);
 
 		/*
 		 * If not, skip all of this.
 		 */
-		sjset_radiotap_flags->s.jf = snext;
+		sjset_radiotap_flags_present->s.jf = snext;
+
+		/*
+		 * Otherwise, is the "extension" bit set in that word?
+		 */
+		sjset_radiotap_ext_present = new_stmt(cstate, JMP(BPF_JSET));
+		sjset_radiotap_ext_present->s.k = SWAPLONG(0x80000000);
+		sappend(s, sjset_radiotap_ext_present);
+		sjset_radiotap_flags_present->s.jt = sjset_radiotap_ext_present;
+
+		/*
+		 * If so, skip all of this.
+		 */
+		sjset_radiotap_ext_present->s.jt = snext;
 
 		/*
 		 * Otherwise, is the IEEE80211_RADIOTAP_TSFT bit set?
 		 */
-		sjset_radiotap_tsft = sjset_radiotap_flags->s.jt =
-		    new_stmt(JMP(BPF_JSET));
-		sjset_radiotap_tsft->s.k = SWAPLONG(0x00000001);
-		sappend(s, sjset_radiotap_tsft);
+		sjset_radiotap_tsft_present = new_stmt(cstate, JMP(BPF_JSET));
+		sjset_radiotap_tsft_present->s.k = SWAPLONG(0x00000001);
+		sappend(s, sjset_radiotap_tsft_present);
+		sjset_radiotap_ext_present->s.jf = sjset_radiotap_tsft_present;
 
 		/*
 		 * If IEEE80211_RADIOTAP_TSFT is set, the flags field is
@@ -2537,11 +2677,12 @@
 		 * Test whether the IEEE80211_RADIOTAP_F_DATAPAD bit (0x20)
 		 * is set.
 		 */
-		sjset_radiotap_tsft->s.jt = s2 = new_stmt(BPF_LD|BPF_ABS|BPF_B);
+		s2 = new_stmt(cstate, BPF_LD|BPF_ABS|BPF_B);
 		s2->s.k = 16;
 		sappend(s, s2);
+		sjset_radiotap_tsft_present->s.jt = s2;
 
-		sjset_tsft_datapad = new_stmt(JMP(BPF_JSET));
+		sjset_tsft_datapad = new_stmt(cstate, JMP(BPF_JSET));
 		sjset_tsft_datapad->s.k = 0x20;
 		sappend(s, sjset_tsft_datapad);
 
@@ -2553,11 +2694,12 @@
 		 * Test whether the IEEE80211_RADIOTAP_F_DATAPAD bit (0x20)
 		 * is set.
 		 */
-		sjset_radiotap_tsft->s.jf = s2 = new_stmt(BPF_LD|BPF_ABS|BPF_B);
+		s2 = new_stmt(cstate, BPF_LD|BPF_ABS|BPF_B);
 		s2->s.k = 8;
 		sappend(s, s2);
+		sjset_radiotap_tsft_present->s.jf = s2;
 
-		sjset_notsft_datapad = new_stmt(JMP(BPF_JSET));
+		sjset_notsft_datapad = new_stmt(cstate, JMP(BPF_JSET));
 		sjset_notsft_datapad->s.k = 0x20;
 		sappend(s, sjset_notsft_datapad);
 
@@ -2568,17 +2710,17 @@
 		 * dividing by and multiplying by 4, which we do by
 		 * ANDing with ~3.
 		 */
-		s_roundup = new_stmt(BPF_LD|BPF_MEM);
-		s_roundup->s.k = off_linkpl.reg;
+		s_roundup = new_stmt(cstate, BPF_LD|BPF_MEM);
+		s_roundup->s.k = cstate->off_linkpl.reg;
 		sappend(s, s_roundup);
-		s2 = new_stmt(BPF_ALU|BPF_ADD|BPF_IMM);
+		s2 = new_stmt(cstate, BPF_ALU|BPF_ADD|BPF_IMM);
 		s2->s.k = 3;
 		sappend(s, s2);
-		s2 = new_stmt(BPF_ALU|BPF_AND|BPF_IMM);
+		s2 = new_stmt(cstate, BPF_ALU|BPF_AND|BPF_IMM);
 		s2->s.k = ~3;
 		sappend(s, s2);
-		s2 = new_stmt(BPF_ST);
-		s2->s.k = off_linkpl.reg;
+		s2 = new_stmt(cstate, BPF_ST);
+		s2->s.k = cstate->off_linkpl.reg;
 		sappend(s, s2);
 
 		sjset_tsft_datapad->s.jt = s_roundup;
@@ -2592,8 +2734,7 @@
 }
 
 static void
-insert_compute_vloffsets(b)
-	struct block *b;
+insert_compute_vloffsets(compiler_state_t *cstate, struct block *b)
 {
 	struct slist *s;
 
@@ -2602,9 +2743,9 @@
 	 * includes the variable part of the header. Therefore,
 	 * if nobody else has allocated a register for the link
 	 * header and we need it, do it now. */
-	if (off_linkpl.reg != -1 && off_linkhdr.is_variable &&
-	    off_linkhdr.reg == -1)
-		off_linkhdr.reg = alloc_reg();
+	if (cstate->off_linkpl.reg != -1 && cstate->off_linkhdr.is_variable &&
+	    cstate->off_linkhdr.reg == -1)
+		cstate->off_linkhdr.reg = alloc_reg(cstate);
 
 	/*
 	 * For link-layer types that have a variable-length header
@@ -2617,22 +2758,22 @@
 	 * some other protocol stack.  That's significantly more
 	 * complicated.
 	 */
-	switch (outermostlinktype) {
+	switch (cstate->outermostlinktype) {
 
 	case DLT_PRISM_HEADER:
-		s = gen_load_prism_llprefixlen();
+		s = gen_load_prism_llprefixlen(cstate);
 		break;
 
 	case DLT_IEEE802_11_RADIO_AVS:
-		s = gen_load_avs_llprefixlen();
+		s = gen_load_avs_llprefixlen(cstate);
 		break;
 
 	case DLT_IEEE802_11_RADIO:
-		s = gen_load_radiotap_llprefixlen();
+		s = gen_load_radiotap_llprefixlen(cstate);
 		break;
 
 	case DLT_PPI:
-		s = gen_load_ppi_llprefixlen();
+		s = gen_load_ppi_llprefixlen(cstate);
 		break;
 
 	default:
@@ -2645,14 +2786,14 @@
 	 * header, generate code to load the offset of the link-layer
 	 * payload into the register assigned to that offset, if any.
 	 */
-	switch (outermostlinktype) {
+	switch (cstate->outermostlinktype) {
 
 	case DLT_IEEE802_11:
 	case DLT_PRISM_HEADER:
 	case DLT_IEEE802_11_RADIO_AVS:
 	case DLT_IEEE802_11_RADIO:
 	case DLT_PPI:
-		s = gen_load_802_11_header_len(s, b->stmts);
+		s = gen_load_802_11_header_len(cstate, s, b->stmts);
 		break;
 	}
 
@@ -2669,19 +2810,19 @@
 }
 
 static struct block *
-gen_ppi_dlt_check(void)
+gen_ppi_dlt_check(compiler_state_t *cstate)
 {
 	struct slist *s_load_dlt;
 	struct block *b;
 
-	if (linktype == DLT_PPI)
+	if (cstate->linktype == DLT_PPI)
 	{
 		/* Create the statements that check for the DLT
 		 */
-		s_load_dlt = new_stmt(BPF_LD|BPF_W|BPF_ABS);
+		s_load_dlt = new_stmt(cstate, BPF_LD|BPF_W|BPF_ABS);
 		s_load_dlt->s.k = 4;
 
-		b = new_block(JMP(BPF_JEQ));
+		b = new_block(cstate, JMP(BPF_JEQ));
 
 		b->stmts = s_load_dlt;
 		b->s.k = SWAPLONG(DLT_IEEE802_11);
@@ -2708,7 +2849,7 @@
  * be placed earlier in the code sequence.)
  */
 static struct slist *
-gen_abs_offset_varpart(bpf_abs_offset *off)
+gen_abs_offset_varpart(compiler_state_t *cstate, bpf_abs_offset *off)
 {
 	struct slist *s;
 
@@ -2719,14 +2860,14 @@
 			 * variable part of the offset of the link-layer
 			 * header; allocate one.
 			 */
-			off->reg = alloc_reg();
+			off->reg = alloc_reg(cstate);
 		}
 
 		/*
 		 * Load the register containing the variable part of the
 		 * offset of the link-layer header into the X register.
 		 */
-		s = new_stmt(BPF_LDX|BPF_MEM);
+		s = new_stmt(cstate, BPF_LDX|BPF_MEM);
 		s->s.k = off->reg;
 		return s;
 	} else {
@@ -2794,14 +2935,14 @@
  * for that encapsulation).
  */
 static struct block *
-gen_prevlinkhdr_check(void)
+gen_prevlinkhdr_check(compiler_state_t *cstate)
 {
 	struct block *b0;
 
-	if (is_geneve)
-		return gen_geneve_ll_check();
+	if (cstate->is_geneve)
+		return gen_geneve_ll_check(cstate);
 
-	switch (prevlinktype) {
+	switch (cstate->prevlinktype) {
 
 	case DLT_SUNATM:
 		/*
@@ -2811,7 +2952,7 @@
 		 *
 		 * (We've already generated a test for LANE.)
 		 */
-		b0 = gen_cmp(OR_PREVLINKHDR, SUNATM_PKT_BEGIN_POS, BPF_H, 0xFF00);
+		b0 = gen_cmp(cstate, OR_PREVLINKHDR, SUNATM_PKT_BEGIN_POS, BPF_H, 0xFF00);
 		gen_not(b0);
 		return b0;
 
@@ -2825,6 +2966,14 @@
 }
 
 /*
+ * The three different values we should check for when checking for an
+ * IPv6 packet with DLT_NULL.
+ */
+#define BSD_AFNUM_INET6_BSD	24	/* NetBSD, OpenBSD, BSD/OS, Npcap */
+#define BSD_AFNUM_INET6_FREEBSD	28	/* FreeBSD */
+#define BSD_AFNUM_INET6_DARWIN	30	/* OS X, iOS, other Darwin-based OSes */
+
+/*
  * Generate code to match a particular packet type by matching the
  * link-layer type field or fields in the 802.2 LLC header.
  *
@@ -2832,44 +2981,43 @@
  * value, if <= ETHERMTU.
  */
 static struct block *
-gen_linktype(proto)
-	register int proto;
+gen_linktype(compiler_state_t *cstate, int proto)
 {
 	struct block *b0, *b1, *b2;
 	const char *description;
 
 	/* are we checking MPLS-encapsulated packets? */
-	if (label_stack_depth > 0) {
+	if (cstate->label_stack_depth > 0) {
 		switch (proto) {
 		case ETHERTYPE_IP:
 		case PPP_IP:
 			/* FIXME add other L3 proto IDs */
-			return gen_mpls_linktype(Q_IP);
+			return gen_mpls_linktype(cstate, Q_IP);
 
 		case ETHERTYPE_IPV6:
 		case PPP_IPV6:
 			/* FIXME add other L3 proto IDs */
-			return gen_mpls_linktype(Q_IPV6);
+			return gen_mpls_linktype(cstate, Q_IPV6);
 
 		default:
-			bpf_error("unsupported protocol over mpls");
+			bpf_error(cstate, "unsupported protocol over mpls");
 			/* NOTREACHED */
 		}
 	}
 
-	switch (linktype) {
+	switch (cstate->linktype) {
 
 	case DLT_EN10MB:
 	case DLT_NETANALYZER:
 	case DLT_NETANALYZER_TRANSPARENT:
 		/* Geneve has an EtherType regardless of whether there is an
 		 * L2 header. */
-		if (!is_geneve)
-			b0 = gen_prevlinkhdr_check();
+		if (!cstate->is_geneve)
+			b0 = gen_prevlinkhdr_check(cstate);
 		else
 			b0 = NULL;
 
-		b1 = gen_ether_linktype(proto);
+		b1 = gen_ether_linktype(cstate, proto);
 		if (b0 != NULL)
 			gen_and(b0, b1);
 		return b1;
@@ -2884,7 +3032,7 @@
 			/* fall through */
 
 		default:
-			return gen_cmp(OR_LINKTYPE, 0, BPF_H, (bpf_int32)proto);
+			return gen_cmp(cstate, OR_LINKTYPE, 0, BPF_H, (bpf_int32)proto);
 			/*NOTREACHED*/
 			break;
 		}
@@ -2898,12 +3046,12 @@
 		/*
 		 * Check that we have a data frame.
 		 */
-		b0 = gen_check_802_11_data_frame();
+		b0 = gen_check_802_11_data_frame(cstate);
 
 		/*
 		 * Now check for the specified link-layer type.
 		 */
-		b1 = gen_llc_linktype(proto);
+		b1 = gen_llc_linktype(cstate, proto);
 		gen_and(b0, b1);
 		return b1;
 		/*NOTREACHED*/
@@ -2913,7 +3061,7 @@
 		/*
 		 * XXX - check for LLC frames.
 		 */
-		return gen_llc_linktype(proto);
+		return gen_llc_linktype(cstate, proto);
 		/*NOTREACHED*/
 		break;
 
@@ -2921,14 +3069,14 @@
 		/*
 		 * XXX - check for LLC PDUs, as per IEEE 802.5.
 		 */
-		return gen_llc_linktype(proto);
+		return gen_llc_linktype(cstate, proto);
 		/*NOTREACHED*/
 		break;
 
 	case DLT_ATM_RFC1483:
 	case DLT_ATM_CLIP:
 	case DLT_IP_OVER_FC:
-		return gen_llc_linktype(proto);
+		return gen_llc_linktype(cstate, proto);
 		/*NOTREACHED*/
 		break;
 
@@ -2940,15 +3088,15 @@
 		 *
 		 * Check for LLC encapsulation and then check the protocol.
 		 */
-		b0 = gen_atmfield_code(A_PROTOTYPE, PT_LLC, BPF_JEQ, 0);
-		b1 = gen_llc_linktype(proto);
+		b0 = gen_atmfield_code(cstate, A_PROTOTYPE, PT_LLC, BPF_JEQ, 0);
+		b1 = gen_llc_linktype(cstate, proto);
 		gen_and(b0, b1);
 		return b1;
 		/*NOTREACHED*/
 		break;
 
 	case DLT_LINUX_SLL:
-		return gen_linux_sll_linktype(proto);
+		return gen_linux_sll_linktype(cstate, proto);
 		/*NOTREACHED*/
 		break;
 
@@ -2966,14 +3114,14 @@
 
 		case ETHERTYPE_IP:
 			/* Check for a version number of 4. */
-			return gen_mcmp(OR_LINKHDR, 0, BPF_B, 0x40, 0xF0);
+			return gen_mcmp(cstate, OR_LINKHDR, 0, BPF_B, 0x40, 0xF0);
 
 		case ETHERTYPE_IPV6:
 			/* Check for a version number of 6. */
-			return gen_mcmp(OR_LINKHDR, 0, BPF_B, 0x60, 0xF0);
+			return gen_mcmp(cstate, OR_LINKHDR, 0, BPF_B, 0x60, 0xF0);
 
 		default:
-			return gen_false();		/* always false */
+			return gen_false(cstate);	/* always false */
 		}
 		/*NOTREACHED*/
 		break;
@@ -2983,10 +3131,10 @@
 		 * Raw IPv4, so no type field.
 		 */
 		if (proto == ETHERTYPE_IP)
-			return gen_true();		/* always true */
+			return gen_true(cstate);	/* always true */
 
 		/* Checking for something other than IPv4; always false */
-		return gen_false();
+		return gen_false(cstate);
 		/*NOTREACHED*/
 		break;
 
@@ -2995,10 +3143,10 @@
 		 * Raw IPv6, so no type field.
 		 */
 		if (proto == ETHERTYPE_IPV6)
-			return gen_true();		/* always true */
+			return gen_true(cstate);	/* always true */
 
 		/* Checking for something other than IPv6; always false */
-		return gen_false();
+		return gen_false(cstate);
 		/*NOTREACHED*/
 		break;
 
@@ -3011,7 +3159,7 @@
 		 * map them to the corresponding PPP protocol types.
 		 */
 		proto = ethertype_to_ppptype(proto);
-		return gen_cmp(OR_LINKTYPE, 0, BPF_H, (bpf_int32)proto);
+		return gen_cmp(cstate, OR_LINKTYPE, 0, BPF_H, (bpf_int32)proto);
 		/*NOTREACHED*/
 		break;
 
@@ -3027,16 +3175,16 @@
 			 * Also check for Van Jacobson-compressed IP.
 			 * XXX - do this for other forms of PPP?
 			 */
-			b0 = gen_cmp(OR_LINKTYPE, 0, BPF_H, PPP_IP);
-			b1 = gen_cmp(OR_LINKTYPE, 0, BPF_H, PPP_VJC);
+			b0 = gen_cmp(cstate, OR_LINKTYPE, 0, BPF_H, PPP_IP);
+			b1 = gen_cmp(cstate, OR_LINKTYPE, 0, BPF_H, PPP_VJC);
 			gen_or(b0, b1);
-			b0 = gen_cmp(OR_LINKTYPE, 0, BPF_H, PPP_VJNC);
+			b0 = gen_cmp(cstate, OR_LINKTYPE, 0, BPF_H, PPP_VJNC);
 			gen_or(b1, b0);
 			return b0;
 
 		default:
 			proto = ethertype_to_ppptype(proto);
-			return gen_cmp(OR_LINKTYPE, 0, BPF_H,
+			return gen_cmp(cstate, OR_LINKTYPE, 0, BPF_H,
 				(bpf_int32)proto);
 		}
 		/*NOTREACHED*/
@@ -3045,39 +3193,71 @@
 	case DLT_NULL:
 	case DLT_LOOP:
 	case DLT_ENC:
-		/*
-		 * For DLT_NULL, the link-layer header is a 32-bit
-		 * word containing an AF_ value in *host* byte order,
-		 * and for DLT_ENC, the link-layer header begins
-		 * with a 32-bit work containing an AF_ value in
-		 * host byte order.
-		 *
-		 * In addition, if we're reading a saved capture file,
-		 * the host byte order in the capture may not be the
-		 * same as the host byte order on this machine.
-		 *
-		 * For DLT_LOOP, the link-layer header is a 32-bit
-		 * word containing an AF_ value in *network* byte order.
-		 *
-		 * XXX - AF_ values may, unfortunately, be platform-
-		 * dependent; for example, FreeBSD's AF_INET6 is 24
-		 * whilst NetBSD's and OpenBSD's is 26.
-		 *
-		 * This means that, when reading a capture file, just
-		 * checking for our AF_INET6 value won't work if the
-		 * capture file came from another OS.
-		 */
 		switch (proto) {
 
 		case ETHERTYPE_IP:
-			proto = AF_INET;
-			break;
+			return (gen_loopback_linktype(cstate, AF_INET));
 
-#ifdef INET6
 		case ETHERTYPE_IPV6:
-			proto = AF_INET6;
-			break;
-#endif
+			/*
+			 * AF_ values may, unfortunately, be platform-
+			 * dependent; AF_INET isn't, because everybody
+			 * used 4.2BSD's value, but AF_INET6 is, because
+			 * 4.2BSD didn't have a value for it (given that
+			 * IPv6 didn't exist back in the early 1980's),
+			 * and they all picked their own values.
+			 *
+			 * This means that, if we're reading from a
+			 * savefile, we need to check for all the
+			 * possible values.
+			 *
+			 * If we're doing a live capture, we only need
+			 * to check for this platform's value; however,
+			 * Npcap uses 24, which isn't Windows's AF_INET6
+			 * value.  (Given the multiple different values,
+			 * programs that read pcap files shouldn't be
+			 * checking for their platform's AF_INET6 value
+			 * anyway, they should check for all of the
+			 * possible values. and they might as well do
+			 * that even for live captures.)
+			 */
+			if (cstate->bpf_pcap->rfile != NULL) {
+				/*
+				 * Savefile - check for all three
+				 * possible IPv6 values.
+				 */
+				b0 = gen_loopback_linktype(cstate, BSD_AFNUM_INET6_BSD);
+				b1 = gen_loopback_linktype(cstate, BSD_AFNUM_INET6_FREEBSD);
+				gen_or(b0, b1);
+				b0 = gen_loopback_linktype(cstate, BSD_AFNUM_INET6_DARWIN);
+				gen_or(b0, b1);
+				return (b1);
+			} else {
+				/*
+				 * Live capture, so we only need to
+				 * check for the value used on this
+				 * platform.
+				 */
+#ifdef _WIN32
+				/*
+				 * Npcap doesn't use Windows's AF_INET6,
+				 * as that collides with AF_IPX on
+				 * some BSDs (both have the value 23).
+				 * Instead, it uses 24.
+				 */
+				return (gen_loopback_linktype(cstate, 24));
+#else /* _WIN32 */
+#ifdef AF_INET6
+				return (gen_loopback_linktype(cstate, AF_INET6));
+#else /* AF_INET6 */
+				/*
+				 * I guess this platform doesn't support
+				 * IPv6, so we just reject all packets.
+				 */
+				return gen_false(cstate);
+#endif /* AF_INET6 */
+#endif /* _WIN32 */
+			}
 
 		default:
 			/*
@@ -3085,28 +3265,9 @@
 			 * XXX - support those that have AF_ values
 			 * #defined on this platform, at least?
 			 */
-			return gen_false();
+			return gen_false(cstate);
 		}
 
-		if (linktype == DLT_NULL || linktype == DLT_ENC) {
-			/*
-			 * The AF_ value is in host byte order, but
-			 * the BPF interpreter will convert it to
-			 * network byte order.
-			 *
-			 * If this is a save file, and it's from a
-			 * machine with the opposite byte order to
-			 * ours, we byte-swap the AF_ value.
-			 *
-			 * Then we run it through "htonl()", and
-			 * generate code to compare against the result.
-			 */
-			if (bpf_pcap->rfile != NULL && bpf_pcap->swapped)
-				proto = SWAPLONG(proto);
-			proto = htonl(proto);
-		}
-		return (gen_cmp(OR_LINKHDR, 0, BPF_W, (bpf_int32)proto));
-
 #ifdef HAVE_NET_PFVAR_H
 	case DLT_PFLOG:
 		/*
@@ -3114,13 +3275,13 @@
 		 * the packet.
 		 */
 		if (proto == ETHERTYPE_IP)
-			return (gen_cmp(OR_LINKHDR, offsetof(struct pfloghdr, af),
+			return (gen_cmp(cstate, OR_LINKHDR, offsetof(struct pfloghdr, af),
 			    BPF_B, (bpf_int32)AF_INET));
 		else if (proto == ETHERTYPE_IPV6)
-			return (gen_cmp(OR_LINKHDR, offsetof(struct pfloghdr, af),
+			return (gen_cmp(cstate, OR_LINKHDR, offsetof(struct pfloghdr, af),
 			    BPF_B, (bpf_int32)AF_INET6));
 		else
-			return gen_false();
+			return gen_false(cstate);
 		/*NOTREACHED*/
 		break;
 #endif /* HAVE_NET_PFVAR_H */
@@ -3134,34 +3295,34 @@
 		switch (proto) {
 
 		default:
-			return gen_false();
+			return gen_false(cstate);
 
 		case ETHERTYPE_IPV6:
-			return (gen_cmp(OR_LINKTYPE, 0, BPF_B,
+			return (gen_cmp(cstate, OR_LINKTYPE, 0, BPF_B,
 				(bpf_int32)ARCTYPE_INET6));
 
 		case ETHERTYPE_IP:
-			b0 = gen_cmp(OR_LINKTYPE, 0, BPF_B,
+			b0 = gen_cmp(cstate, OR_LINKTYPE, 0, BPF_B,
 				     (bpf_int32)ARCTYPE_IP);
-			b1 = gen_cmp(OR_LINKTYPE, 0, BPF_B,
+			b1 = gen_cmp(cstate, OR_LINKTYPE, 0, BPF_B,
 				     (bpf_int32)ARCTYPE_IP_OLD);
 			gen_or(b0, b1);
 			return (b1);
 
 		case ETHERTYPE_ARP:
-			b0 = gen_cmp(OR_LINKTYPE, 0, BPF_B,
+			b0 = gen_cmp(cstate, OR_LINKTYPE, 0, BPF_B,
 				     (bpf_int32)ARCTYPE_ARP);
-			b1 = gen_cmp(OR_LINKTYPE, 0, BPF_B,
+			b1 = gen_cmp(cstate, OR_LINKTYPE, 0, BPF_B,
 				     (bpf_int32)ARCTYPE_ARP_OLD);
 			gen_or(b0, b1);
 			return (b1);
 
 		case ETHERTYPE_REVARP:
-			return (gen_cmp(OR_LINKTYPE, 0, BPF_B,
+			return (gen_cmp(cstate, OR_LINKTYPE, 0, BPF_B,
 					(bpf_int32)ARCTYPE_REVARP));
 
 		case ETHERTYPE_ATALK:
-			return (gen_cmp(OR_LINKTYPE, 0, BPF_B,
+			return (gen_cmp(cstate, OR_LINKTYPE, 0, BPF_B,
 					(bpf_int32)ARCTYPE_ATALK));
 		}
 		/*NOTREACHED*/
@@ -3170,9 +3331,9 @@
 	case DLT_LTALK:
 		switch (proto) {
 		case ETHERTYPE_ATALK:
-			return gen_true();
+			return gen_true(cstate);
 		default:
-			return gen_false();
+			return gen_false(cstate);
 		}
 		/*NOTREACHED*/
 		break;
@@ -3188,13 +3349,13 @@
 			/*
 			 * Check for the special NLPID for IP.
 			 */
-			return gen_cmp(OR_LINKHDR, 2, BPF_H, (0x03<<8) | 0xcc);
+			return gen_cmp(cstate, OR_LINKHDR, 2, BPF_H, (0x03<<8) | 0xcc);
 
 		case ETHERTYPE_IPV6:
 			/*
 			 * Check for the special NLPID for IPv6.
 			 */
-			return gen_cmp(OR_LINKHDR, 2, BPF_H, (0x03<<8) | 0x8e);
+			return gen_cmp(cstate, OR_LINKHDR, 2, BPF_H, (0x03<<8) | 0x8e);
 
 		case LLCSAP_ISONS:
 			/*
@@ -3208,21 +3369,21 @@
 			 * control field of UI, i.e. 0x03 followed
 			 * by the NLPID.
 			 */
-			b0 = gen_cmp(OR_LINKHDR, 2, BPF_H, (0x03<<8) | ISO8473_CLNP);
-			b1 = gen_cmp(OR_LINKHDR, 2, BPF_H, (0x03<<8) | ISO9542_ESIS);
-			b2 = gen_cmp(OR_LINKHDR, 2, BPF_H, (0x03<<8) | ISO10589_ISIS);
+			b0 = gen_cmp(cstate, OR_LINKHDR, 2, BPF_H, (0x03<<8) | ISO8473_CLNP);
+			b1 = gen_cmp(cstate, OR_LINKHDR, 2, BPF_H, (0x03<<8) | ISO9542_ESIS);
+			b2 = gen_cmp(cstate, OR_LINKHDR, 2, BPF_H, (0x03<<8) | ISO10589_ISIS);
 			gen_or(b1, b2);
 			gen_or(b0, b2);
 			return b2;
 
 		default:
-			return gen_false();
+			return gen_false(cstate);
 		}
 		/*NOTREACHED*/
 		break;
 
 	case DLT_MFR:
-		bpf_error("Multi-link Frame Relay link-layer type filtering not implemented");
+		bpf_error(cstate, "Multi-link Frame Relay link-layer type filtering not implemented");
 
         case DLT_JUNIPER_MFR:
         case DLT_JUNIPER_MLFR:
@@ -3254,99 +3415,100 @@
 		 *
 		 * FIXME encapsulation specific BPF_ filters
 		 */
-		return gen_mcmp(OR_LINKHDR, 0, BPF_W, 0x4d474300, 0xffffff00); /* compare the magic number */
+		return gen_mcmp(cstate, OR_LINKHDR, 0, BPF_W, 0x4d474300, 0xffffff00); /* compare the magic number */
 
 	case DLT_BACNET_MS_TP:
-		return gen_mcmp(OR_LINKHDR, 0, BPF_W, 0x55FF0000, 0xffff0000);
+		return gen_mcmp(cstate, OR_LINKHDR, 0, BPF_W, 0x55FF0000, 0xffff0000);
 
 	case DLT_IPNET:
-		return gen_ipnet_linktype(proto);
+		return gen_ipnet_linktype(cstate, proto);
 
 	case DLT_LINUX_IRDA:
-		bpf_error("IrDA link-layer type filtering not implemented");
+		bpf_error(cstate, "IrDA link-layer type filtering not implemented");
 
 	case DLT_DOCSIS:
-		bpf_error("DOCSIS link-layer type filtering not implemented");
+		bpf_error(cstate, "DOCSIS link-layer type filtering not implemented");
 
 	case DLT_MTP2:
 	case DLT_MTP2_WITH_PHDR:
-		bpf_error("MTP2 link-layer type filtering not implemented");
+		bpf_error(cstate, "MTP2 link-layer type filtering not implemented");
 
 	case DLT_ERF:
-		bpf_error("ERF link-layer type filtering not implemented");
+		bpf_error(cstate, "ERF link-layer type filtering not implemented");
 
 	case DLT_PFSYNC:
-		bpf_error("PFSYNC link-layer type filtering not implemented");
+		bpf_error(cstate, "PFSYNC link-layer type filtering not implemented");
 
 	case DLT_LINUX_LAPD:
-		bpf_error("LAPD link-layer type filtering not implemented");
+		bpf_error(cstate, "LAPD link-layer type filtering not implemented");
 
-	case DLT_USB:
+	case DLT_USB_FREEBSD:
 	case DLT_USB_LINUX:
 	case DLT_USB_LINUX_MMAPPED:
-		bpf_error("USB link-layer type filtering not implemented");
+	case DLT_USBPCAP:
+		bpf_error(cstate, "USB link-layer type filtering not implemented");
 
 	case DLT_BLUETOOTH_HCI_H4:
 	case DLT_BLUETOOTH_HCI_H4_WITH_PHDR:
-		bpf_error("Bluetooth link-layer type filtering not implemented");
+		bpf_error(cstate, "Bluetooth link-layer type filtering not implemented");
 
 	case DLT_CAN20B:
 	case DLT_CAN_SOCKETCAN:
-		bpf_error("CAN link-layer type filtering not implemented");
+		bpf_error(cstate, "CAN link-layer type filtering not implemented");
 
 	case DLT_IEEE802_15_4:
 	case DLT_IEEE802_15_4_LINUX:
 	case DLT_IEEE802_15_4_NONASK_PHY:
 	case DLT_IEEE802_15_4_NOFCS:
-		bpf_error("IEEE 802.15.4 link-layer type filtering not implemented");
+		bpf_error(cstate, "IEEE 802.15.4 link-layer type filtering not implemented");
 
 	case DLT_IEEE802_16_MAC_CPS_RADIO:
-		bpf_error("IEEE 802.16 link-layer type filtering not implemented");
+		bpf_error(cstate, "IEEE 802.16 link-layer type filtering not implemented");
 
 	case DLT_SITA:
-		bpf_error("SITA link-layer type filtering not implemented");
+		bpf_error(cstate, "SITA link-layer type filtering not implemented");
 
 	case DLT_RAIF1:
-		bpf_error("RAIF1 link-layer type filtering not implemented");
+		bpf_error(cstate, "RAIF1 link-layer type filtering not implemented");
 
 	case DLT_IPMB:
-		bpf_error("IPMB link-layer type filtering not implemented");
+		bpf_error(cstate, "IPMB link-layer type filtering not implemented");
 
 	case DLT_AX25_KISS:
-		bpf_error("AX.25 link-layer type filtering not implemented");
+		bpf_error(cstate, "AX.25 link-layer type filtering not implemented");
 
 	case DLT_NFLOG:
 		/* Using the fixed-size NFLOG header it is possible to tell only
 		 * the address family of the packet, other meaningful data is
 		 * either missing or behind TLVs.
 		 */
-		bpf_error("NFLOG link-layer type filtering not implemented");
+		bpf_error(cstate, "NFLOG link-layer type filtering not implemented");
 
 	default:
 		/*
 		 * Does this link-layer header type have a field
 		 * indicating the type of the next protocol?  If
 		 * so, off_linktype.constant_part will be the offset of that
-		 * field in the packet; if not, it will be -1.
+		 * field in the packet; if not, it will be OFFSET_NOT_SET.
 		 */
-		if (off_linktype.constant_part != (u_int)-1) {
+		if (cstate->off_linktype.constant_part != OFFSET_NOT_SET) {
 			/*
 			 * Yes; assume it's an Ethernet type.  (If
 			 * it's not, it needs to be handled specially
 			 * above.)
 			 */
-			return gen_cmp(OR_LINKTYPE, 0, BPF_H, (bpf_int32)proto);
+			return gen_cmp(cstate, OR_LINKTYPE, 0, BPF_H, (bpf_int32)proto);
 		} else {
 			/*
 			 * No; report an error.
 			 */
-			description = pcap_datalink_val_to_description(linktype);
+			description = pcap_datalink_val_to_description(cstate->linktype);
 			if (description != NULL) {
-				bpf_error("%s link-layer type filtering not implemented",
+				bpf_error(cstate, "%s link-layer type filtering not implemented",
 				    description);
 			} else {
-				bpf_error("DLT %u link-layer type filtering not implemented",
-				    linktype);
+				bpf_error(cstate, "DLT %u link-layer type filtering not implemented",
+				    cstate->linktype);
 			}
 		}
 		break;
@@ -3361,9 +3523,7 @@
  * code and protocol type in the SNAP header.
  */
 static struct block *
-gen_snap(orgcode, ptype)
-	bpf_u_int32 orgcode;
-	bpf_u_int32 ptype;
+gen_snap(compiler_state_t *cstate, bpf_u_int32 orgcode, bpf_u_int32 ptype)
 {
 	u_char snapblock[8];
 
@@ -3375,32 +3535,32 @@
 	snapblock[5] = (orgcode >> 0);	/* lower 8 bits of organization code */
 	snapblock[6] = (ptype >> 8);	/* upper 8 bits of protocol type */
 	snapblock[7] = (ptype >> 0);	/* lower 8 bits of protocol type */
-	return gen_bcmp(OR_LLC, 0, 8, snapblock);
+	return gen_bcmp(cstate, OR_LLC, 0, 8, snapblock);
 }
 
 /*
  * Generate code to match frames with an LLC header.
  */
 struct block *
-gen_llc(void)
+gen_llc(compiler_state_t *cstate)
 {
 	struct block *b0, *b1;
 
-	switch (linktype) {
+	switch (cstate->linktype) {
 
 	case DLT_EN10MB:
 		/*
 		 * We check for an Ethernet type field less than
 		 * 1500, which means it's an 802.3 length field.
 		 */
-		b0 = gen_cmp_gt(OR_LINKTYPE, 0, BPF_H, ETHERMTU);
+		b0 = gen_cmp_gt(cstate, OR_LINKTYPE, 0, BPF_H, ETHERMTU);
 		gen_not(b0);
 
 		/*
 		 * Now check for the purported DSAP and SSAP not being
 		 * 0xFF, to rule out NetWare-over-802.3.
 		 */
-		b1 = gen_cmp(OR_LLC, 0, BPF_H, (bpf_int32)0xFFFF);
+		b1 = gen_cmp(cstate, OR_LLC, 0, BPF_H, (bpf_int32)0xFFFF);
 		gen_not(b1);
 		gen_and(b0, b1);
 		return b1;
@@ -3409,20 +3569,20 @@
 		/*
 		 * We check for LLC traffic.
 		 */
-		b0 = gen_atmtype_abbrev(A_LLC);
+		b0 = gen_atmtype_abbrev(cstate, A_LLC);
 		return b0;
 
 	case DLT_IEEE802:	/* Token Ring */
 		/*
 		 * XXX - check for LLC frames.
 		 */
-		return gen_true();
+		return gen_true(cstate);
 
 	case DLT_FDDI:
 		/*
 		 * XXX - check for LLC frames.
 		 */
-		return gen_true();
+		return gen_true(cstate);
 
 	case DLT_ATM_RFC1483:
 		/*
@@ -3433,7 +3593,7 @@
 		 * way to check for that; the protocol used on the VC
 		 * is negotiated out of band.
 		 */
-		return gen_true();
+		return gen_true(cstate);
 
 	case DLT_IEEE802_11:
 	case DLT_PRISM_HEADER:
@@ -3443,17 +3603,17 @@
 		/*
 		 * Check that we have a data frame.
 		 */
-		b0 = gen_check_802_11_data_frame();
+		b0 = gen_check_802_11_data_frame(cstate);
 		return b0;
 
 	default:
-		bpf_error("'llc' not supported for linktype %d", linktype);
+		bpf_error(cstate, "'llc' not supported for linktype %d", cstate->linktype);
 		/* NOTREACHED */
 	}
 }
 
 struct block *
-gen_llc_i(void)
+gen_llc_i(compiler_state_t *cstate)
 {
 	struct block *b0, *b1;
 	struct slist *s;
@@ -3461,14 +3621,14 @@
 	/*
 	 * Check whether this is an LLC frame.
 	 */
-	b0 = gen_llc();
+	b0 = gen_llc(cstate);
 
 	/*
 	 * Load the control byte and test the low-order bit; it must
 	 * be clear for I frames.
 	 */
-	s = gen_load_a(OR_LLC, 2, BPF_B);
-	b1 = new_block(JMP(BPF_JSET));
+	s = gen_load_a(cstate, OR_LLC, 2, BPF_B);
+	b1 = new_block(cstate, JMP(BPF_JSET));
 	b1->s.k = 0x01;
 	b1->stmts = s;
 	gen_not(b1);
@@ -3477,75 +3637,75 @@
 }
 
 struct block *
-gen_llc_s(void)
+gen_llc_s(compiler_state_t *cstate)
 {
 	struct block *b0, *b1;
 
 	/*
 	 * Check whether this is an LLC frame.
 	 */
-	b0 = gen_llc();
+	b0 = gen_llc(cstate);
 
 	/*
 	 * Now compare the low-order 2 bit of the control byte against
 	 * the appropriate value for S frames.
 	 */
-	b1 = gen_mcmp(OR_LLC, 2, BPF_B, LLC_S_FMT, 0x03);
+	b1 = gen_mcmp(cstate, OR_LLC, 2, BPF_B, LLC_S_FMT, 0x03);
 	gen_and(b0, b1);
 	return b1;
 }
 
 struct block *
-gen_llc_u(void)
+gen_llc_u(compiler_state_t *cstate)
 {
 	struct block *b0, *b1;
 
 	/*
 	 * Check whether this is an LLC frame.
 	 */
-	b0 = gen_llc();
+	b0 = gen_llc(cstate);
 
 	/*
 	 * Now compare the low-order 2 bit of the control byte against
 	 * the appropriate value for U frames.
 	 */
-	b1 = gen_mcmp(OR_LLC, 2, BPF_B, LLC_U_FMT, 0x03);
+	b1 = gen_mcmp(cstate, OR_LLC, 2, BPF_B, LLC_U_FMT, 0x03);
 	gen_and(b0, b1);
 	return b1;
 }
 
 struct block *
-gen_llc_s_subtype(bpf_u_int32 subtype)
+gen_llc_s_subtype(compiler_state_t *cstate, bpf_u_int32 subtype)
 {
 	struct block *b0, *b1;
 
 	/*
 	 * Check whether this is an LLC frame.
 	 */
-	b0 = gen_llc();
+	b0 = gen_llc(cstate);
 
 	/*
 	 * Now check for an S frame with the appropriate type.
 	 */
-	b1 = gen_mcmp(OR_LLC, 2, BPF_B, subtype, LLC_S_CMD_MASK);
+	b1 = gen_mcmp(cstate, OR_LLC, 2, BPF_B, subtype, LLC_S_CMD_MASK);
 	gen_and(b0, b1);
 	return b1;
 }
 
 struct block *
-gen_llc_u_subtype(bpf_u_int32 subtype)
+gen_llc_u_subtype(compiler_state_t *cstate, bpf_u_int32 subtype)
 {
 	struct block *b0, *b1;
 
 	/*
 	 * Check whether this is an LLC frame.
 	 */
-	b0 = gen_llc();
+	b0 = gen_llc(cstate);
 
 	/*
 	 * Now check for a U frame with the appropriate type.
 	 */
-	b1 = gen_mcmp(OR_LLC, 2, BPF_B, subtype, LLC_U_CMD_MASK);
+	b1 = gen_mcmp(cstate, OR_LLC, 2, BPF_B, subtype, LLC_U_CMD_MASK);
 	gen_and(b0, b1);
 	return b1;
 }
@@ -3563,8 +3723,7 @@
  * protocol ID in a SNAP header.
  */
 static struct block *
-gen_llc_linktype(proto)
-	int proto;
+gen_llc_linktype(compiler_state_t *cstate, int proto)
 {
 	/*
 	 * XXX - handle token-ring variable-length header.
@@ -3579,7 +3738,7 @@
 		 * SSAP, like this, or should we check just the
 		 * DSAP, as we do for other SAP values?
 		 */
-		return gen_cmp(OR_LLC, 0, BPF_H, (bpf_u_int32)
+		return gen_cmp(cstate, OR_LLC, 0, BPF_H, (bpf_u_int32)
 			     ((proto << 8) | proto));
 
 	case LLCSAP_IPX:
@@ -3587,7 +3746,7 @@
 		 * XXX - are there ever SNAP frames for IPX on
 		 * non-Ethernet 802.x networks?
 		 */
-		return gen_cmp(OR_LLC, 0, BPF_B,
+		return gen_cmp(cstate, OR_LLC, 0, BPF_B,
 		    (bpf_int32)LLCSAP_IPX);
 
 	case ETHERTYPE_ATALK:
@@ -3600,7 +3759,7 @@
 		 * XXX - check for an organization code of
 		 * encapsulated Ethernet as well?
 		 */
-		return gen_snap(0x080007, ETHERTYPE_ATALK);
+		return gen_snap(cstate, 0x080007, ETHERTYPE_ATALK);
 
 	default:
 		/*
@@ -3612,7 +3771,7 @@
 			 * This is an LLC SAP value, so check
 			 * the DSAP.
 			 */
-			return gen_cmp(OR_LLC, 0, BPF_B, (bpf_int32)proto);
+			return gen_cmp(cstate, OR_LLC, 0, BPF_B, (bpf_int32)proto);
 		} else {
 			/*
 			 * This is an Ethernet type; we assume that it's
@@ -3627,23 +3786,20 @@
 			 * organization code of 0x000000 (encapsulated
 			 * Ethernet), we'd do
 			 *
-			 *	return gen_snap(0x000000, proto);
+			 *	return gen_snap(cstate, 0x000000, proto);
 			 *
 			 * here; for now, we don't, as per the above.
 			 * I don't know whether it's worth the extra CPU
 			 * time to do the right check or not.
 			 */
-			return gen_cmp(OR_LLC, 6, BPF_H, (bpf_int32)proto);
+			return gen_cmp(cstate, OR_LLC, 6, BPF_H, (bpf_int32)proto);
 		}
 	}
 }
 
 static struct block *
-gen_hostop(addr, mask, dir, proto, src_off, dst_off)
-	bpf_u_int32 addr;
-	bpf_u_int32 mask;
-	int dir, proto;
-	u_int src_off, dst_off;
+gen_hostop(compiler_state_t *cstate, bpf_u_int32 addr, bpf_u_int32 mask,
+    int dir, int proto, u_int src_off, u_int dst_off)
 {
 	struct block *b0, *b1;
 	u_int offset;
@@ -3659,34 +3815,31 @@
 		break;
 
 	case Q_AND:
-		b0 = gen_hostop(addr, mask, Q_SRC, proto, src_off, dst_off);
-		b1 = gen_hostop(addr, mask, Q_DST, proto, src_off, dst_off);
+		b0 = gen_hostop(cstate, addr, mask, Q_SRC, proto, src_off, dst_off);
+		b1 = gen_hostop(cstate, addr, mask, Q_DST, proto, src_off, dst_off);
 		gen_and(b0, b1);
 		return b1;
 
 	case Q_OR:
 	case Q_DEFAULT:
-		b0 = gen_hostop(addr, mask, Q_SRC, proto, src_off, dst_off);
-		b1 = gen_hostop(addr, mask, Q_DST, proto, src_off, dst_off);
+		b0 = gen_hostop(cstate, addr, mask, Q_SRC, proto, src_off, dst_off);
+		b1 = gen_hostop(cstate, addr, mask, Q_DST, proto, src_off, dst_off);
 		gen_or(b0, b1);
 		return b1;
 
 	default:
 		abort();
 	}
-	b0 = gen_linktype(proto);
-	b1 = gen_mcmp(OR_LINKPL, offset, BPF_W, (bpf_int32)addr, mask);
+	b0 = gen_linktype(cstate, proto);
+	b1 = gen_mcmp(cstate, OR_LINKPL, offset, BPF_W, (bpf_int32)addr, mask);
 	gen_and(b0, b1);
 	return b1;
 }
 
 #ifdef INET6
 static struct block *
-gen_hostop6(addr, mask, dir, proto, src_off, dst_off)
-	struct in6_addr *addr;
-	struct in6_addr *mask;
-	int dir, proto;
-	u_int src_off, dst_off;
+gen_hostop6(compiler_state_t *cstate, struct in6_addr *addr,
+    struct in6_addr *mask, int dir, int proto, u_int src_off, u_int dst_off)
 {
 	struct block *b0, *b1;
 	u_int offset;
@@ -3703,15 +3856,15 @@
 		break;
 
 	case Q_AND:
-		b0 = gen_hostop6(addr, mask, Q_SRC, proto, src_off, dst_off);
-		b1 = gen_hostop6(addr, mask, Q_DST, proto, src_off, dst_off);
+		b0 = gen_hostop6(cstate, addr, mask, Q_SRC, proto, src_off, dst_off);
+		b1 = gen_hostop6(cstate, addr, mask, Q_DST, proto, src_off, dst_off);
 		gen_and(b0, b1);
 		return b1;
 
 	case Q_OR:
 	case Q_DEFAULT:
-		b0 = gen_hostop6(addr, mask, Q_SRC, proto, src_off, dst_off);
-		b1 = gen_hostop6(addr, mask, Q_DST, proto, src_off, dst_off);
+		b0 = gen_hostop6(cstate, addr, mask, Q_SRC, proto, src_off, dst_off);
+		b1 = gen_hostop6(cstate, addr, mask, Q_DST, proto, src_off, dst_off);
 		gen_or(b0, b1);
 		return b1;
 
@@ -3721,68 +3874,66 @@
 	/* this order is important */
 	a = (u_int32_t *)addr;
 	m = (u_int32_t *)mask;
-	b1 = gen_mcmp(OR_LINKPL, offset + 12, BPF_W, ntohl(a[3]), ntohl(m[3]));
-	b0 = gen_mcmp(OR_LINKPL, offset + 8, BPF_W, ntohl(a[2]), ntohl(m[2]));
+	b1 = gen_mcmp(cstate, OR_LINKPL, offset + 12, BPF_W, ntohl(a[3]), ntohl(m[3]));
+	b0 = gen_mcmp(cstate, OR_LINKPL, offset + 8, BPF_W, ntohl(a[2]), ntohl(m[2]));
 	gen_and(b0, b1);
-	b0 = gen_mcmp(OR_LINKPL, offset + 4, BPF_W, ntohl(a[1]), ntohl(m[1]));
+	b0 = gen_mcmp(cstate, OR_LINKPL, offset + 4, BPF_W, ntohl(a[1]), ntohl(m[1]));
 	gen_and(b0, b1);
-	b0 = gen_mcmp(OR_LINKPL, offset + 0, BPF_W, ntohl(a[0]), ntohl(m[0]));
+	b0 = gen_mcmp(cstate, OR_LINKPL, offset + 0, BPF_W, ntohl(a[0]), ntohl(m[0]));
 	gen_and(b0, b1);
-	b0 = gen_linktype(proto);
+	b0 = gen_linktype(cstate, proto);
 	gen_and(b0, b1);
 	return b1;
 }
 #endif
 
 static struct block *
-gen_ehostop(eaddr, dir)
-	register const u_char *eaddr;
-	register int dir;
+gen_ehostop(compiler_state_t *cstate, const u_char *eaddr, int dir)
 {
 	register struct block *b0, *b1;
 
 	switch (dir) {
 	case Q_SRC:
-		return gen_bcmp(OR_LINKHDR, 6, 6, eaddr);
+		return gen_bcmp(cstate, OR_LINKHDR, 6, 6, eaddr);
 
 	case Q_DST:
-		return gen_bcmp(OR_LINKHDR, 0, 6, eaddr);
+		return gen_bcmp(cstate, OR_LINKHDR, 0, 6, eaddr);
 
 	case Q_AND:
-		b0 = gen_ehostop(eaddr, Q_SRC);
-		b1 = gen_ehostop(eaddr, Q_DST);
+		b0 = gen_ehostop(cstate, eaddr, Q_SRC);
+		b1 = gen_ehostop(cstate, eaddr, Q_DST);
 		gen_and(b0, b1);
 		return b1;
 
 	case Q_DEFAULT:
 	case Q_OR:
-		b0 = gen_ehostop(eaddr, Q_SRC);
-		b1 = gen_ehostop(eaddr, Q_DST);
+		b0 = gen_ehostop(cstate, eaddr, Q_SRC);
+		b1 = gen_ehostop(cstate, eaddr, Q_DST);
 		gen_or(b0, b1);
 		return b1;
 
 	case Q_ADDR1:
-		bpf_error("'addr1' is only supported on 802.11 with 802.11 headers");
+		bpf_error(cstate, "'addr1' is only supported on 802.11 with 802.11 headers");
 		break;
 
 	case Q_ADDR2:
-		bpf_error("'addr2' is only supported on 802.11 with 802.11 headers");
+		bpf_error(cstate, "'addr2' is only supported on 802.11 with 802.11 headers");
 		break;
 
 	case Q_ADDR3:
-		bpf_error("'addr3' is only supported on 802.11 with 802.11 headers");
+		bpf_error(cstate, "'addr3' is only supported on 802.11 with 802.11 headers");
 		break;
 
 	case Q_ADDR4:
-		bpf_error("'addr4' is only supported on 802.11 with 802.11 headers");
+		bpf_error(cstate, "'addr4' is only supported on 802.11 with 802.11 headers");
 		break;
 
 	case Q_RA:
-		bpf_error("'ra' is only supported on 802.11 with 802.11 headers");
+		bpf_error(cstate, "'ra' is only supported on 802.11 with 802.11 headers");
 		break;
 
 	case Q_TA:
-		bpf_error("'ta' is only supported on 802.11 with 802.11 headers");
+		bpf_error(cstate, "'ta' is only supported on 802.11 with 802.11 headers");
 		break;
 	}
 	abort();
@@ -3793,54 +3944,52 @@
  * Like gen_ehostop, but for DLT_FDDI
  */
 static struct block *
-gen_fhostop(eaddr, dir)
-	register const u_char *eaddr;
-	register int dir;
+gen_fhostop(compiler_state_t *cstate, const u_char *eaddr, int dir)
 {
 	struct block *b0, *b1;
 
 	switch (dir) {
 	case Q_SRC:
-		return gen_bcmp(OR_LINKHDR, 6 + 1 + pcap_fddipad, 6, eaddr);
+		return gen_bcmp(cstate, OR_LINKHDR, 6 + 1 + cstate->pcap_fddipad, 6, eaddr);
 
 	case Q_DST:
-		return gen_bcmp(OR_LINKHDR, 0 + 1 + pcap_fddipad, 6, eaddr);
+		return gen_bcmp(cstate, OR_LINKHDR, 0 + 1 + cstate->pcap_fddipad, 6, eaddr);
 
 	case Q_AND:
-		b0 = gen_fhostop(eaddr, Q_SRC);
-		b1 = gen_fhostop(eaddr, Q_DST);
+		b0 = gen_fhostop(cstate, eaddr, Q_SRC);
+		b1 = gen_fhostop(cstate, eaddr, Q_DST);
 		gen_and(b0, b1);
 		return b1;
 
 	case Q_DEFAULT:
 	case Q_OR:
-		b0 = gen_fhostop(eaddr, Q_SRC);
-		b1 = gen_fhostop(eaddr, Q_DST);
+		b0 = gen_fhostop(cstate, eaddr, Q_SRC);
+		b1 = gen_fhostop(cstate, eaddr, Q_DST);
 		gen_or(b0, b1);
 		return b1;
 
 	case Q_ADDR1:
-		bpf_error("'addr1' is only supported on 802.11");
+		bpf_error(cstate, "'addr1' is only supported on 802.11");
 		break;
 
 	case Q_ADDR2:
-		bpf_error("'addr2' is only supported on 802.11");
+		bpf_error(cstate, "'addr2' is only supported on 802.11");
 		break;
 
 	case Q_ADDR3:
-		bpf_error("'addr3' is only supported on 802.11");
+		bpf_error(cstate, "'addr3' is only supported on 802.11");
 		break;
 
 	case Q_ADDR4:
-		bpf_error("'addr4' is only supported on 802.11");
+		bpf_error(cstate, "'addr4' is only supported on 802.11");
 		break;
 
 	case Q_RA:
-		bpf_error("'ra' is only supported on 802.11");
+		bpf_error(cstate, "'ra' is only supported on 802.11");
 		break;
 
 	case Q_TA:
-		bpf_error("'ta' is only supported on 802.11");
+		bpf_error(cstate, "'ta' is only supported on 802.11");
 		break;
 	}
 	abort();
@@ -3851,54 +4000,52 @@
  * Like gen_ehostop, but for DLT_IEEE802 (Token Ring)
  */
 static struct block *
-gen_thostop(eaddr, dir)
-	register const u_char *eaddr;
-	register int dir;
+gen_thostop(compiler_state_t *cstate, const u_char *eaddr, int dir)
 {
 	register struct block *b0, *b1;
 
 	switch (dir) {
 	case Q_SRC:
-		return gen_bcmp(OR_LINKHDR, 8, 6, eaddr);
+		return gen_bcmp(cstate, OR_LINKHDR, 8, 6, eaddr);
 
 	case Q_DST:
-		return gen_bcmp(OR_LINKHDR, 2, 6, eaddr);
+		return gen_bcmp(cstate, OR_LINKHDR, 2, 6, eaddr);
 
 	case Q_AND:
-		b0 = gen_thostop(eaddr, Q_SRC);
-		b1 = gen_thostop(eaddr, Q_DST);
+		b0 = gen_thostop(cstate, eaddr, Q_SRC);
+		b1 = gen_thostop(cstate, eaddr, Q_DST);
 		gen_and(b0, b1);
 		return b1;
 
 	case Q_DEFAULT:
 	case Q_OR:
-		b0 = gen_thostop(eaddr, Q_SRC);
-		b1 = gen_thostop(eaddr, Q_DST);
+		b0 = gen_thostop(cstate, eaddr, Q_SRC);
+		b1 = gen_thostop(cstate, eaddr, Q_DST);
 		gen_or(b0, b1);
 		return b1;
 
 	case Q_ADDR1:
-		bpf_error("'addr1' is only supported on 802.11");
+		bpf_error(cstate, "'addr1' is only supported on 802.11");
 		break;
 
 	case Q_ADDR2:
-		bpf_error("'addr2' is only supported on 802.11");
+		bpf_error(cstate, "'addr2' is only supported on 802.11");
 		break;
 
 	case Q_ADDR3:
-		bpf_error("'addr3' is only supported on 802.11");
+		bpf_error(cstate, "'addr3' is only supported on 802.11");
 		break;
 
 	case Q_ADDR4:
-		bpf_error("'addr4' is only supported on 802.11");
+		bpf_error(cstate, "'addr4' is only supported on 802.11");
 		break;
 
 	case Q_RA:
-		bpf_error("'ra' is only supported on 802.11");
+		bpf_error(cstate, "'ra' is only supported on 802.11");
 		break;
 
 	case Q_TA:
-		bpf_error("'ta' is only supported on 802.11");
+		bpf_error(cstate, "'ta' is only supported on 802.11");
 		break;
 	}
 	abort();
@@ -3910,9 +4057,7 @@
  * various 802.11 + radio headers.
  */
 static struct block *
-gen_wlanhostop(eaddr, dir)
-	register const u_char *eaddr;
-	register int dir;
+gen_wlanhostop(compiler_state_t *cstate, const u_char *eaddr, int dir)
 {
 	register struct block *b0, *b1, *b2;
 	register struct slist *s;
@@ -3924,7 +4069,7 @@
 	 * and wipes out some LD instructions generated by the below
 	 * code to validate the Frame Control bits
 	 */
-	no_optimize = 1;
+	cstate->no_optimize = 1;
 #endif /* ENABLE_WLAN_FILTERING_PATCH */
 
 	switch (dir) {
@@ -3954,23 +4099,23 @@
 		 *
 		 * First, check for To DS set, i.e. check "link[1] & 0x01".
 		 */
-		s = gen_load_a(OR_LINKHDR, 1, BPF_B);
-		b1 = new_block(JMP(BPF_JSET));
+		s = gen_load_a(cstate, OR_LINKHDR, 1, BPF_B);
+		b1 = new_block(cstate, JMP(BPF_JSET));
 		b1->s.k = 0x01;	/* To DS */
 		b1->stmts = s;
 
 		/*
 		 * If To DS is set, the SA is at 24.
 		 */
-		b0 = gen_bcmp(OR_LINKHDR, 24, 6, eaddr);
+		b0 = gen_bcmp(cstate, OR_LINKHDR, 24, 6, eaddr);
 		gen_and(b1, b0);
 
 		/*
 		 * Now, check for To DS not set, i.e. check
 		 * "!(link[1] & 0x01)".
 		 */
-		s = gen_load_a(OR_LINKHDR, 1, BPF_B);
-		b2 = new_block(JMP(BPF_JSET));
+		s = gen_load_a(cstate, OR_LINKHDR, 1, BPF_B);
+		b2 = new_block(cstate, JMP(BPF_JSET));
 		b2->s.k = 0x01;	/* To DS */
 		b2->stmts = s;
 		gen_not(b2);
@@ -3978,7 +4123,7 @@
 		/*
 		 * If To DS is not set, the SA is at 16.
 		 */
-		b1 = gen_bcmp(OR_LINKHDR, 16, 6, eaddr);
+		b1 = gen_bcmp(cstate, OR_LINKHDR, 16, 6, eaddr);
 		gen_and(b2, b1);
 
 		/*
@@ -3992,8 +4137,8 @@
 		 * Now check for From DS being set, and AND that with
 		 * the ORed-together checks.
 		 */
-		s = gen_load_a(OR_LINKHDR, 1, BPF_B);
-		b1 = new_block(JMP(BPF_JSET));
+		s = gen_load_a(cstate, OR_LINKHDR, 1, BPF_B);
+		b1 = new_block(cstate, JMP(BPF_JSET));
 		b1->s.k = 0x02;	/* From DS */
 		b1->stmts = s;
 		gen_and(b1, b0);
@@ -4001,8 +4146,8 @@
 		/*
 		 * Now check for data frames with From DS not set.
 		 */
-		s = gen_load_a(OR_LINKHDR, 1, BPF_B);
-		b2 = new_block(JMP(BPF_JSET));
+		s = gen_load_a(cstate, OR_LINKHDR, 1, BPF_B);
+		b2 = new_block(cstate, JMP(BPF_JSET));
 		b2->s.k = 0x02;	/* From DS */
 		b2->stmts = s;
 		gen_not(b2);
@@ -4010,7 +4155,7 @@
 		/*
 		 * If From DS isn't set, the SA is at 10.
 		 */
-		b1 = gen_bcmp(OR_LINKHDR, 10, 6, eaddr);
+		b1 = gen_bcmp(cstate, OR_LINKHDR, 10, 6, eaddr);
 		gen_and(b2, b1);
 
 		/*
@@ -4024,8 +4169,8 @@
 		 * Now check for a data frame.
 		 * I.e, check "link[0] & 0x08".
 		 */
-		s = gen_load_a(OR_LINKHDR, 0, BPF_B);
-		b1 = new_block(JMP(BPF_JSET));
+		s = gen_load_a(cstate, OR_LINKHDR, 0, BPF_B);
+		b1 = new_block(cstate, JMP(BPF_JSET));
 		b1->s.k = 0x08;
 		b1->stmts = s;
 
@@ -4039,8 +4184,8 @@
 		 * is a management frame.
 		 * I.e, check "!(link[0] & 0x08)".
 		 */
-		s = gen_load_a(OR_LINKHDR, 0, BPF_B);
-		b2 = new_block(JMP(BPF_JSET));
+		s = gen_load_a(cstate, OR_LINKHDR, 0, BPF_B);
+		b2 = new_block(cstate, JMP(BPF_JSET));
 		b2->s.k = 0x08;
 		b2->stmts = s;
 		gen_not(b2);
@@ -4048,7 +4193,7 @@
 		/*
 		 * For management frames, the SA is at 10.
 		 */
-		b1 = gen_bcmp(OR_LINKHDR, 10, 6, eaddr);
+		b1 = gen_bcmp(cstate, OR_LINKHDR, 10, 6, eaddr);
 		gen_and(b2, b1);
 
 		/*
@@ -4066,8 +4211,8 @@
 		 *
 		 * I.e., check "!(link[0] & 0x04)".
 		 */
-		s = gen_load_a(OR_LINKHDR, 0, BPF_B);
-		b1 = new_block(JMP(BPF_JSET));
+		s = gen_load_a(cstate, OR_LINKHDR, 0, BPF_B);
+		b1 = new_block(cstate, JMP(BPF_JSET));
 		b1->s.k = 0x04;
 		b1->stmts = s;
 		gen_not(b1);
@@ -4101,23 +4246,23 @@
 		 *
 		 * First, check for To DS set, i.e. "link[1] & 0x01".
 		 */
-		s = gen_load_a(OR_LINKHDR, 1, BPF_B);
-		b1 = new_block(JMP(BPF_JSET));
+		s = gen_load_a(cstate, OR_LINKHDR, 1, BPF_B);
+		b1 = new_block(cstate, JMP(BPF_JSET));
 		b1->s.k = 0x01;	/* To DS */
 		b1->stmts = s;
 
 		/*
 		 * If To DS is set, the DA is at 16.
 		 */
-		b0 = gen_bcmp(OR_LINKHDR, 16, 6, eaddr);
+		b0 = gen_bcmp(cstate, OR_LINKHDR, 16, 6, eaddr);
 		gen_and(b1, b0);
 
 		/*
 		 * Now, check for To DS not set, i.e. check
 		 * "!(link[1] & 0x01)".
 		 */
-		s = gen_load_a(OR_LINKHDR, 1, BPF_B);
-		b2 = new_block(JMP(BPF_JSET));
+		s = gen_load_a(cstate, OR_LINKHDR, 1, BPF_B);
+		b2 = new_block(cstate, JMP(BPF_JSET));
 		b2->s.k = 0x01;	/* To DS */
 		b2->stmts = s;
 		gen_not(b2);
@@ -4125,7 +4270,7 @@
 		/*
 		 * If To DS is not set, the DA is at 4.
 		 */
-		b1 = gen_bcmp(OR_LINKHDR, 4, 6, eaddr);
+		b1 = gen_bcmp(cstate, OR_LINKHDR, 4, 6, eaddr);
 		gen_and(b2, b1);
 
 		/*
@@ -4138,8 +4283,8 @@
 		 * Now check for a data frame.
 		 * I.e, check "link[0] & 0x08".
 		 */
-		s = gen_load_a(OR_LINKHDR, 0, BPF_B);
-		b1 = new_block(JMP(BPF_JSET));
+		s = gen_load_a(cstate, OR_LINKHDR, 0, BPF_B);
+		b1 = new_block(cstate, JMP(BPF_JSET));
 		b1->s.k = 0x08;
 		b1->stmts = s;
 
@@ -4153,8 +4298,8 @@
 		 * is a management frame.
 		 * I.e, check "!(link[0] & 0x08)".
 		 */
-		s = gen_load_a(OR_LINKHDR, 0, BPF_B);
-		b2 = new_block(JMP(BPF_JSET));
+		s = gen_load_a(cstate, OR_LINKHDR, 0, BPF_B);
+		b2 = new_block(cstate, JMP(BPF_JSET));
 		b2->s.k = 0x08;
 		b2->stmts = s;
 		gen_not(b2);
@@ -4162,7 +4307,7 @@
 		/*
 		 * For management frames, the DA is at 4.
 		 */
-		b1 = gen_bcmp(OR_LINKHDR, 4, 6, eaddr);
+		b1 = gen_bcmp(cstate, OR_LINKHDR, 4, 6, eaddr);
 		gen_and(b2, b1);
 
 		/*
@@ -4180,8 +4325,8 @@
 		 *
 		 * I.e., check "!(link[0] & 0x04)".
 		 */
-		s = gen_load_a(OR_LINKHDR, 0, BPF_B);
-		b1 = new_block(JMP(BPF_JSET));
+		s = gen_load_a(cstate, OR_LINKHDR, 0, BPF_B);
+		b1 = new_block(cstate, JMP(BPF_JSET));
 		b1->s.k = 0x04;
 		b1->stmts = s;
 		gen_not(b1);
@@ -4204,15 +4349,15 @@
 		 * is a management frame.
 		 * I.e, check "(link[0] & 0x08)".
 		 */
-		s = gen_load_a(OR_LINKHDR, 0, BPF_B);
-		b1 = new_block(JMP(BPF_JSET));
+		s = gen_load_a(cstate, OR_LINKHDR, 0, BPF_B);
+		b1 = new_block(cstate, JMP(BPF_JSET));
 		b1->s.k = 0x08;
 		b1->stmts = s;
 
 		/*
 		 * Check addr1.
 		 */
-		b0 = gen_bcmp(OR_LINKHDR, 4, 6, eaddr);
+		b0 = gen_bcmp(cstate, OR_LINKHDR, 4, 6, eaddr);
 
 		/*
 		 * AND that with the check of addr1.
@@ -4229,13 +4374,13 @@
 		/*
 		 * Not present in CTS or ACK control frames.
 		 */
-		b0 = gen_mcmp(OR_LINKHDR, 0, BPF_B, IEEE80211_FC0_TYPE_CTL,
+		b0 = gen_mcmp(cstate, OR_LINKHDR, 0, BPF_B, IEEE80211_FC0_TYPE_CTL,
 			IEEE80211_FC0_TYPE_MASK);
 		gen_not(b0);
-		b1 = gen_mcmp(OR_LINKHDR, 0, BPF_B, IEEE80211_FC0_SUBTYPE_CTS,
+		b1 = gen_mcmp(cstate, OR_LINKHDR, 0, BPF_B, IEEE80211_FC0_SUBTYPE_CTS,
 			IEEE80211_FC0_SUBTYPE_MASK);
 		gen_not(b1);
-		b2 = gen_mcmp(OR_LINKHDR, 0, BPF_B, IEEE80211_FC0_SUBTYPE_ACK,
+		b2 = gen_mcmp(cstate, OR_LINKHDR, 0, BPF_B, IEEE80211_FC0_SUBTYPE_ACK,
 			IEEE80211_FC0_SUBTYPE_MASK);
 		gen_not(b2);
 		gen_and(b1, b2);
@@ -4246,8 +4391,8 @@
 		 * is a management frame.
 		 * I.e, check "(link[0] & 0x08)".
 		 */
-		s = gen_load_a(OR_LINKHDR, 0, BPF_B);
-		b1 = new_block(JMP(BPF_JSET));
+		s = gen_load_a(cstate, OR_LINKHDR, 0, BPF_B);
+		b1 = new_block(cstate, JMP(BPF_JSET));
 		b1->s.k = 0x08;
 		b1->stmts = s;
 
@@ -4260,7 +4405,7 @@
 		/*
 		 * Check addr2.
 		 */
-		b1 = gen_bcmp(OR_LINKHDR, 10, 6, eaddr);
+		b1 = gen_bcmp(cstate, OR_LINKHDR, 10, 6, eaddr);
 		gen_and(b2, b1);
 		return b1;
 
@@ -4268,24 +4413,24 @@
 	 * XXX - add BSSID keyword?
 	 */
 	case Q_ADDR1:
-		return (gen_bcmp(OR_LINKHDR, 4, 6, eaddr));
+		return (gen_bcmp(cstate, OR_LINKHDR, 4, 6, eaddr));
 
 	case Q_ADDR2:
 		/*
 		 * Not present in CTS or ACK control frames.
 		 */
-		b0 = gen_mcmp(OR_LINKHDR, 0, BPF_B, IEEE80211_FC0_TYPE_CTL,
+		b0 = gen_mcmp(cstate, OR_LINKHDR, 0, BPF_B, IEEE80211_FC0_TYPE_CTL,
 			IEEE80211_FC0_TYPE_MASK);
 		gen_not(b0);
-		b1 = gen_mcmp(OR_LINKHDR, 0, BPF_B, IEEE80211_FC0_SUBTYPE_CTS,
+		b1 = gen_mcmp(cstate, OR_LINKHDR, 0, BPF_B, IEEE80211_FC0_SUBTYPE_CTS,
 			IEEE80211_FC0_SUBTYPE_MASK);
 		gen_not(b1);
-		b2 = gen_mcmp(OR_LINKHDR, 0, BPF_B, IEEE80211_FC0_SUBTYPE_ACK,
+		b2 = gen_mcmp(cstate, OR_LINKHDR, 0, BPF_B, IEEE80211_FC0_SUBTYPE_ACK,
 			IEEE80211_FC0_SUBTYPE_MASK);
 		gen_not(b2);
 		gen_and(b1, b2);
 		gen_or(b0, b2);
-		b1 = gen_bcmp(OR_LINKHDR, 10, 6, eaddr);
+		b1 = gen_bcmp(cstate, OR_LINKHDR, 10, 6, eaddr);
 		gen_and(b2, b1);
 		return b1;
 
@@ -4293,10 +4438,10 @@
 		/*
 		 * Not present in control frames.
 		 */
-		b0 = gen_mcmp(OR_LINKHDR, 0, BPF_B, IEEE80211_FC0_TYPE_CTL,
+		b0 = gen_mcmp(cstate, OR_LINKHDR, 0, BPF_B, IEEE80211_FC0_TYPE_CTL,
 			IEEE80211_FC0_TYPE_MASK);
 		gen_not(b0);
-		b1 = gen_bcmp(OR_LINKHDR, 16, 6, eaddr);
+		b1 = gen_bcmp(cstate, OR_LINKHDR, 16, 6, eaddr);
 		gen_and(b0, b1);
 		return b1;
 
@@ -4307,22 +4452,22 @@
 		 * frames should have both of those set, so we don't
 		 * check the frame type.
 		 */
-		b0 = gen_mcmp(OR_LINKHDR, 1, BPF_B,
+		b0 = gen_mcmp(cstate, OR_LINKHDR, 1, BPF_B,
 			IEEE80211_FC1_DIR_DSTODS, IEEE80211_FC1_DIR_MASK);
-		b1 = gen_bcmp(OR_LINKHDR, 24, 6, eaddr);
+		b1 = gen_bcmp(cstate, OR_LINKHDR, 24, 6, eaddr);
 		gen_and(b0, b1);
 		return b1;
 
 	case Q_AND:
-		b0 = gen_wlanhostop(eaddr, Q_SRC);
-		b1 = gen_wlanhostop(eaddr, Q_DST);
+		b0 = gen_wlanhostop(cstate, eaddr, Q_SRC);
+		b1 = gen_wlanhostop(cstate, eaddr, Q_DST);
 		gen_and(b0, b1);
 		return b1;
 
 	case Q_DEFAULT:
 	case Q_OR:
-		b0 = gen_wlanhostop(eaddr, Q_SRC);
-		b1 = gen_wlanhostop(eaddr, Q_DST);
+		b0 = gen_wlanhostop(cstate, eaddr, Q_SRC);
+		b1 = gen_wlanhostop(cstate, eaddr, Q_DST);
 		gen_or(b0, b1);
 		return b1;
 	}
@@ -4336,54 +4481,52 @@
  * as the RFC states.)
  */
 static struct block *
-gen_ipfchostop(eaddr, dir)
-	register const u_char *eaddr;
-	register int dir;
+gen_ipfchostop(compiler_state_t *cstate, const u_char *eaddr, int dir)
 {
 	register struct block *b0, *b1;
 
 	switch (dir) {
 	case Q_SRC:
-		return gen_bcmp(OR_LINKHDR, 10, 6, eaddr);
+		return gen_bcmp(cstate, OR_LINKHDR, 10, 6, eaddr);
 
 	case Q_DST:
-		return gen_bcmp(OR_LINKHDR, 2, 6, eaddr);
+		return gen_bcmp(cstate, OR_LINKHDR, 2, 6, eaddr);
 
 	case Q_AND:
-		b0 = gen_ipfchostop(eaddr, Q_SRC);
-		b1 = gen_ipfchostop(eaddr, Q_DST);
+		b0 = gen_ipfchostop(cstate, eaddr, Q_SRC);
+		b1 = gen_ipfchostop(cstate, eaddr, Q_DST);
 		gen_and(b0, b1);
 		return b1;
 
 	case Q_DEFAULT:
 	case Q_OR:
-		b0 = gen_ipfchostop(eaddr, Q_SRC);
-		b1 = gen_ipfchostop(eaddr, Q_DST);
+		b0 = gen_ipfchostop(cstate, eaddr, Q_SRC);
+		b1 = gen_ipfchostop(cstate, eaddr, Q_DST);
 		gen_or(b0, b1);
 		return b1;
 
 	case Q_ADDR1:
-		bpf_error("'addr1' is only supported on 802.11");
+		bpf_error(cstate, "'addr1' is only supported on 802.11");
 		break;
 
 	case Q_ADDR2:
-		bpf_error("'addr2' is only supported on 802.11");
+		bpf_error(cstate, "'addr2' is only supported on 802.11");
 		break;
 
 	case Q_ADDR3:
-		bpf_error("'addr3' is only supported on 802.11");
+		bpf_error(cstate, "'addr3' is only supported on 802.11");
 		break;
 
 	case Q_ADDR4:
-		bpf_error("'addr4' is only supported on 802.11");
+		bpf_error(cstate, "'addr4' is only supported on 802.11");
 		break;
 
 	case Q_RA:
-		bpf_error("'ra' is only supported on 802.11");
+		bpf_error(cstate, "'ra' is only supported on 802.11");
 		break;
 
 	case Q_TA:
-		bpf_error("'ta' is only supported on 802.11");
+		bpf_error(cstate, "'ta' is only supported on 802.11");
 		break;
 	}
 	abort();
@@ -4409,9 +4552,7 @@
  * and not generate masking instructions if the mask is 0xFFFF.
  */
 static struct block *
-gen_dnhostop(addr, dir)
-	bpf_u_int32 addr;
-	int dir;
+gen_dnhostop(compiler_state_t *cstate, bpf_u_int32 addr, int dir)
 {
 	struct block *b0, *b1, *b2, *tmp;
 	u_int offset_lh;	/* offset if long header is received */
@@ -4431,50 +4572,50 @@
 
 	case Q_AND:
 		/* Inefficient because we do our Calvinball dance twice */
-		b0 = gen_dnhostop(addr, Q_SRC);
-		b1 = gen_dnhostop(addr, Q_DST);
+		b0 = gen_dnhostop(cstate, addr, Q_SRC);
+		b1 = gen_dnhostop(cstate, addr, Q_DST);
 		gen_and(b0, b1);
 		return b1;
 
 	case Q_OR:
 	case Q_DEFAULT:
 		/* Inefficient because we do our Calvinball dance twice */
-		b0 = gen_dnhostop(addr, Q_SRC);
-		b1 = gen_dnhostop(addr, Q_DST);
+		b0 = gen_dnhostop(cstate, addr, Q_SRC);
+		b1 = gen_dnhostop(cstate, addr, Q_DST);
 		gen_or(b0, b1);
 		return b1;
 
 	case Q_ISO:
-		bpf_error("ISO host filtering not implemented");
+		bpf_error(cstate, "ISO host filtering not implemented");
 
 	default:
 		abort();
 	}
-	b0 = gen_linktype(ETHERTYPE_DN);
+	b0 = gen_linktype(cstate, ETHERTYPE_DN);
 	/* Check for pad = 1, long header case */
-	tmp = gen_mcmp(OR_LINKPL, 2, BPF_H,
+	tmp = gen_mcmp(cstate, OR_LINKPL, 2, BPF_H,
 	    (bpf_int32)ntohs(0x0681), (bpf_int32)ntohs(0x07FF));
-	b1 = gen_cmp(OR_LINKPL, 2 + 1 + offset_lh,
+	b1 = gen_cmp(cstate, OR_LINKPL, 2 + 1 + offset_lh,
 	    BPF_H, (bpf_int32)ntohs((u_short)addr));
 	gen_and(tmp, b1);
 	/* Check for pad = 0, long header case */
-	tmp = gen_mcmp(OR_LINKPL, 2, BPF_B, (bpf_int32)0x06, (bpf_int32)0x7);
-	b2 = gen_cmp(OR_LINKPL, 2 + offset_lh, BPF_H, (bpf_int32)ntohs((u_short)addr));
+	tmp = gen_mcmp(cstate, OR_LINKPL, 2, BPF_B, (bpf_int32)0x06, (bpf_int32)0x7);
+	b2 = gen_cmp(cstate, OR_LINKPL, 2 + offset_lh, BPF_H, (bpf_int32)ntohs((u_short)addr));
 	gen_and(tmp, b2);
 	gen_or(b2, b1);
 	/* Check for pad = 1, short header case */
-	tmp = gen_mcmp(OR_LINKPL, 2, BPF_H,
+	tmp = gen_mcmp(cstate, OR_LINKPL, 2, BPF_H,
 	    (bpf_int32)ntohs(0x0281), (bpf_int32)ntohs(0x07FF));
-	b2 = gen_cmp(OR_LINKPL, 2 + 1 + offset_sh, BPF_H, (bpf_int32)ntohs((u_short)addr));
+	b2 = gen_cmp(cstate, OR_LINKPL, 2 + 1 + offset_sh, BPF_H, (bpf_int32)ntohs((u_short)addr));
 	gen_and(tmp, b2);
 	gen_or(b2, b1);
 	/* Check for pad = 0, short header case */
-	tmp = gen_mcmp(OR_LINKPL, 2, BPF_B, (bpf_int32)0x02, (bpf_int32)0x7);
-	b2 = gen_cmp(OR_LINKPL, 2 + offset_sh, BPF_H, (bpf_int32)ntohs((u_short)addr));
+	tmp = gen_mcmp(cstate, OR_LINKPL, 2, BPF_B, (bpf_int32)0x02, (bpf_int32)0x7);
+	b2 = gen_cmp(cstate, OR_LINKPL, 2 + offset_sh, BPF_H, (bpf_int32)ntohs((u_short)addr));
 	gen_and(tmp, b2);
 	gen_or(b2, b1);
 
-	/* Combine with test for linktype */
+	/* Combine with test for cstate->linktype */
 	gen_and(b0, b1);
 	return b1;
 }
@@ -4485,8 +4626,7 @@
  * field in the IP header.
  */
 static struct block *
-gen_mpls_linktype(proto)
-	int proto;
+gen_mpls_linktype(compiler_state_t *cstate, int proto)
 {
 	struct block *b0, *b1;
 
@@ -4494,17 +4634,17 @@
 
         case Q_IP:
                 /* match the bottom-of-stack bit */
-                b0 = gen_mcmp(OR_LINKPL, -2, BPF_B, 0x01, 0x01);
+                b0 = gen_mcmp(cstate, OR_LINKPL, -2, BPF_B, 0x01, 0x01);
                 /* match the IPv4 version number */
-                b1 = gen_mcmp(OR_LINKPL, 0, BPF_B, 0x40, 0xf0);
+                b1 = gen_mcmp(cstate, OR_LINKPL, 0, BPF_B, 0x40, 0xf0);
                 gen_and(b0, b1);
                 return b1;
 
        case Q_IPV6:
                 /* match the bottom-of-stack bit */
-                b0 = gen_mcmp(OR_LINKPL, -2, BPF_B, 0x01, 0x01);
+                b0 = gen_mcmp(cstate, OR_LINKPL, -2, BPF_B, 0x01, 0x01);
                 /* match the IPv4 version number */
-                b1 = gen_mcmp(OR_LINKPL, 0, BPF_B, 0x60, 0xf0);
+                b1 = gen_mcmp(cstate, OR_LINKPL, 0, BPF_B, 0x60, 0xf0);
                 gen_and(b0, b1);
                 return b1;
 
@@ -4514,12 +4654,8 @@
 }
 
 static struct block *
-gen_host(addr, mask, proto, dir, type)
-	bpf_u_int32 addr;
-	bpf_u_int32 mask;
-	int proto;
-	int dir;
-	int type;
+gen_host(compiler_state_t *cstate, bpf_u_int32 addr, bpf_u_int32 mask,
+    int proto, int dir, int type)
 {
 	struct block *b0, *b1;
 	const char *typestr;
@@ -4532,111 +4668,111 @@
 	switch (proto) {
 
 	case Q_DEFAULT:
-		b0 = gen_host(addr, mask, Q_IP, dir, type);
+		b0 = gen_host(cstate, addr, mask, Q_IP, dir, type);
 		/*
 		 * Only check for non-IPv4 addresses if we're not
 		 * checking MPLS-encapsulated packets.
 		 */
-		if (label_stack_depth == 0) {
-			b1 = gen_host(addr, mask, Q_ARP, dir, type);
+		if (cstate->label_stack_depth == 0) {
+			b1 = gen_host(cstate, addr, mask, Q_ARP, dir, type);
 			gen_or(b0, b1);
-			b0 = gen_host(addr, mask, Q_RARP, dir, type);
+			b0 = gen_host(cstate, addr, mask, Q_RARP, dir, type);
 			gen_or(b1, b0);
 		}
 		return b0;
 
 	case Q_IP:
-		return gen_hostop(addr, mask, dir, ETHERTYPE_IP, 12, 16);
+		return gen_hostop(cstate, addr, mask, dir, ETHERTYPE_IP, 12, 16);
 
 	case Q_RARP:
-		return gen_hostop(addr, mask, dir, ETHERTYPE_REVARP, 14, 24);
+		return gen_hostop(cstate, addr, mask, dir, ETHERTYPE_REVARP, 14, 24);
 
 	case Q_ARP:
-		return gen_hostop(addr, mask, dir, ETHERTYPE_ARP, 14, 24);
+		return gen_hostop(cstate, addr, mask, dir, ETHERTYPE_ARP, 14, 24);
 
 	case Q_TCP:
-		bpf_error("'tcp' modifier applied to %s", typestr);
+		bpf_error(cstate, "'tcp' modifier applied to %s", typestr);
 
 	case Q_SCTP:
-		bpf_error("'sctp' modifier applied to %s", typestr);
+		bpf_error(cstate, "'sctp' modifier applied to %s", typestr);
 
 	case Q_UDP:
-		bpf_error("'udp' modifier applied to %s", typestr);
+		bpf_error(cstate, "'udp' modifier applied to %s", typestr);
 
 	case Q_ICMP:
-		bpf_error("'icmp' modifier applied to %s", typestr);
+		bpf_error(cstate, "'icmp' modifier applied to %s", typestr);
 
 	case Q_IGMP:
-		bpf_error("'igmp' modifier applied to %s", typestr);
+		bpf_error(cstate, "'igmp' modifier applied to %s", typestr);
 
 	case Q_IGRP:
-		bpf_error("'igrp' modifier applied to %s", typestr);
+		bpf_error(cstate, "'igrp' modifier applied to %s", typestr);
 
 	case Q_PIM:
-		bpf_error("'pim' modifier applied to %s", typestr);
+		bpf_error(cstate, "'pim' modifier applied to %s", typestr);
 
 	case Q_VRRP:
-		bpf_error("'vrrp' modifier applied to %s", typestr);
+		bpf_error(cstate, "'vrrp' modifier applied to %s", typestr);
 
 	case Q_CARP:
-		bpf_error("'carp' modifier applied to %s", typestr);
+		bpf_error(cstate, "'carp' modifier applied to %s", typestr);
 
 	case Q_ATALK:
-		bpf_error("ATALK host filtering not implemented");
+		bpf_error(cstate, "ATALK host filtering not implemented");
 
 	case Q_AARP:
-		bpf_error("AARP host filtering not implemented");
+		bpf_error(cstate, "AARP host filtering not implemented");
 
 	case Q_DECNET:
-		return gen_dnhostop(addr, dir);
+		return gen_dnhostop(cstate, addr, dir);
 
 	case Q_SCA:
-		bpf_error("SCA host filtering not implemented");
+		bpf_error(cstate, "SCA host filtering not implemented");
 
 	case Q_LAT:
-		bpf_error("LAT host filtering not implemented");
+		bpf_error(cstate, "LAT host filtering not implemented");
 
 	case Q_MOPDL:
-		bpf_error("MOPDL host filtering not implemented");
+		bpf_error(cstate, "MOPDL host filtering not implemented");
 
 	case Q_MOPRC:
-		bpf_error("MOPRC host filtering not implemented");
+		bpf_error(cstate, "MOPRC host filtering not implemented");
 
 	case Q_IPV6:
-		bpf_error("'ip6' modifier applied to ip host");
+		bpf_error(cstate, "'ip6' modifier applied to ip host");
 
 	case Q_ICMPV6:
-		bpf_error("'icmp6' modifier applied to %s", typestr);
+		bpf_error(cstate, "'icmp6' modifier applied to %s", typestr);
 
 	case Q_AH:
-		bpf_error("'ah' modifier applied to %s", typestr);
+		bpf_error(cstate, "'ah' modifier applied to %s", typestr);
 
 	case Q_ESP:
-		bpf_error("'esp' modifier applied to %s", typestr);
+		bpf_error(cstate, "'esp' modifier applied to %s", typestr);
 
 	case Q_ISO:
-		bpf_error("ISO host filtering not implemented");
+		bpf_error(cstate, "ISO host filtering not implemented");
 
 	case Q_ESIS:
-		bpf_error("'esis' modifier applied to %s", typestr);
+		bpf_error(cstate, "'esis' modifier applied to %s", typestr);
 
 	case Q_ISIS:
-		bpf_error("'isis' modifier applied to %s", typestr);
+		bpf_error(cstate, "'isis' modifier applied to %s", typestr);
 
 	case Q_CLNP:
-		bpf_error("'clnp' modifier applied to %s", typestr);
+		bpf_error(cstate, "'clnp' modifier applied to %s", typestr);
 
 	case Q_STP:
-		bpf_error("'stp' modifier applied to %s", typestr);
+		bpf_error(cstate, "'stp' modifier applied to %s", typestr);
 
 	case Q_IPX:
-		bpf_error("IPX host filtering not implemented");
+		bpf_error(cstate, "IPX host filtering not implemented");
 
 	case Q_NETBEUI:
-		bpf_error("'netbeui' modifier applied to %s", typestr);
+		bpf_error(cstate, "'netbeui' modifier applied to %s", typestr);
 
 	case Q_RADIO:
-		bpf_error("'radio' modifier applied to %s", typestr);
+		bpf_error(cstate, "'radio' modifier applied to %s", typestr);
 
 	default:
 		abort();
@@ -4646,12 +4782,8 @@
 
 #ifdef INET6
 static struct block *
-gen_host6(addr, mask, proto, dir, type)
-	struct in6_addr *addr;
-	struct in6_addr *mask;
-	int proto;
-	int dir;
-	int type;
+gen_host6(compiler_state_t *cstate, struct in6_addr *addr,
+    struct in6_addr *mask, int proto, int dir, int type)
 {
 	const char *typestr;
 
@@ -4663,103 +4795,103 @@
 	switch (proto) {
 
 	case Q_DEFAULT:
-		return gen_host6(addr, mask, Q_IPV6, dir, type);
+		return gen_host6(cstate, addr, mask, Q_IPV6, dir, type);
 
 	case Q_LINK:
-		bpf_error("link-layer modifier applied to ip6 %s", typestr);
+		bpf_error(cstate, "link-layer modifier applied to ip6 %s", typestr);
 
 	case Q_IP:
-		bpf_error("'ip' modifier applied to ip6 %s", typestr);
+		bpf_error(cstate, "'ip' modifier applied to ip6 %s", typestr);
 
 	case Q_RARP:
-		bpf_error("'rarp' modifier applied to ip6 %s", typestr);
+		bpf_error(cstate, "'rarp' modifier applied to ip6 %s", typestr);
 
 	case Q_ARP:
-		bpf_error("'arp' modifier applied to ip6 %s", typestr);
+		bpf_error(cstate, "'arp' modifier applied to ip6 %s", typestr);
 
 	case Q_SCTP:
-		bpf_error("'sctp' modifier applied to %s", typestr);
+		bpf_error(cstate, "'sctp' modifier applied to %s", typestr);
 
 	case Q_TCP:
-		bpf_error("'tcp' modifier applied to %s", typestr);
+		bpf_error(cstate, "'tcp' modifier applied to %s", typestr);
 
 	case Q_UDP:
-		bpf_error("'udp' modifier applied to %s", typestr);
+		bpf_error(cstate, "'udp' modifier applied to %s", typestr);
 
 	case Q_ICMP:
-		bpf_error("'icmp' modifier applied to %s", typestr);
+		bpf_error(cstate, "'icmp' modifier applied to %s", typestr);
 
 	case Q_IGMP:
-		bpf_error("'igmp' modifier applied to %s", typestr);
+		bpf_error(cstate, "'igmp' modifier applied to %s", typestr);
 
 	case Q_IGRP:
-		bpf_error("'igrp' modifier applied to %s", typestr);
+		bpf_error(cstate, "'igrp' modifier applied to %s", typestr);
 
 	case Q_PIM:
-		bpf_error("'pim' modifier applied to %s", typestr);
+		bpf_error(cstate, "'pim' modifier applied to %s", typestr);
 
 	case Q_VRRP:
-		bpf_error("'vrrp' modifier applied to %s", typestr);
+		bpf_error(cstate, "'vrrp' modifier applied to %s", typestr);
 
 	case Q_CARP:
-		bpf_error("'carp' modifier applied to %s", typestr);
+		bpf_error(cstate, "'carp' modifier applied to %s", typestr);
 
 	case Q_ATALK:
-		bpf_error("ATALK host filtering not implemented");
+		bpf_error(cstate, "ATALK host filtering not implemented");
 
 	case Q_AARP:
-		bpf_error("AARP host filtering not implemented");
+		bpf_error(cstate, "AARP host filtering not implemented");
 
 	case Q_DECNET:
-		bpf_error("'decnet' modifier applied to ip6 %s", typestr);
+		bpf_error(cstate, "'decnet' modifier applied to ip6 %s", typestr);
 
 	case Q_SCA:
-		bpf_error("SCA host filtering not implemented");
+		bpf_error(cstate, "SCA host filtering not implemented");
 
 	case Q_LAT:
-		bpf_error("LAT host filtering not implemented");
+		bpf_error(cstate, "LAT host filtering not implemented");
 
 	case Q_MOPDL:
-		bpf_error("MOPDL host filtering not implemented");
+		bpf_error(cstate, "MOPDL host filtering not implemented");
 
 	case Q_MOPRC:
-		bpf_error("MOPRC host filtering not implemented");
+		bpf_error(cstate, "MOPRC host filtering not implemented");
 
 	case Q_IPV6:
-		return gen_hostop6(addr, mask, dir, ETHERTYPE_IPV6, 8, 24);
+		return gen_hostop6(cstate, addr, mask, dir, ETHERTYPE_IPV6, 8, 24);
 
 	case Q_ICMPV6:
-		bpf_error("'icmp6' modifier applied to %s", typestr);
+		bpf_error(cstate, "'icmp6' modifier applied to %s", typestr);
 
 	case Q_AH:
-		bpf_error("'ah' modifier applied to %s", typestr);
+		bpf_error(cstate, "'ah' modifier applied to %s", typestr);
 
 	case Q_ESP:
-		bpf_error("'esp' modifier applied to %s", typestr);
+		bpf_error(cstate, "'esp' modifier applied to %s", typestr);
 
 	case Q_ISO:
-		bpf_error("ISO host filtering not implemented");
+		bpf_error(cstate, "ISO host filtering not implemented");
 
 	case Q_ESIS:
-		bpf_error("'esis' modifier applied to %s", typestr);
+		bpf_error(cstate, "'esis' modifier applied to %s", typestr);
 
 	case Q_ISIS:
-		bpf_error("'isis' modifier applied to %s", typestr);
+		bpf_error(cstate, "'isis' modifier applied to %s", typestr);
 
 	case Q_CLNP:
-		bpf_error("'clnp' modifier applied to %s", typestr);
+		bpf_error(cstate, "'clnp' modifier applied to %s", typestr);
 
 	case Q_STP:
-		bpf_error("'stp' modifier applied to %s", typestr);
+		bpf_error(cstate, "'stp' modifier applied to %s", typestr);
 
 	case Q_IPX:
-		bpf_error("IPX host filtering not implemented");
+		bpf_error(cstate, "IPX host filtering not implemented");
 
 	case Q_NETBEUI:
-		bpf_error("'netbeui' modifier applied to %s", typestr);
+		bpf_error(cstate, "'netbeui' modifier applied to %s", typestr);
 
 	case Q_RADIO:
-		bpf_error("'radio' modifier applied to %s", typestr);
+		bpf_error(cstate, "'radio' modifier applied to %s", typestr);
 
 	default:
 		abort();
@@ -4779,54 +4911,54 @@
 	struct block *b0, *b1, *tmp;
 
 	if (dir != 0)
-		bpf_error("direction applied to 'gateway'");
+		bpf_error(cstate, "direction applied to 'gateway'");
 
 	switch (proto) {
 	case Q_DEFAULT:
 	case Q_IP:
 	case Q_ARP:
 	case Q_RARP:
-		switch (linktype) {
+		switch (cstate->linktype) {
 		case DLT_EN10MB:
 		case DLT_NETANALYZER:
 		case DLT_NETANALYZER_TRANSPARENT:
-			b1 = gen_prevlinkhdr_check();
-			b0 = gen_ehostop(eaddr, Q_OR);
+			b1 = gen_prevlinkhdr_check(cstate);
+			b0 = gen_ehostop(cstate, eaddr, Q_OR);
 			if (b1 != NULL)
 				gen_and(b1, b0);
 			break;
 		case DLT_FDDI:
-			b0 = gen_fhostop(eaddr, Q_OR);
+			b0 = gen_fhostop(cstate, eaddr, Q_OR);
 			break;
 		case DLT_IEEE802:
-			b0 = gen_thostop(eaddr, Q_OR);
+			b0 = gen_thostop(cstate, eaddr, Q_OR);
 			break;
 		case DLT_IEEE802_11:
 		case DLT_PRISM_HEADER:
 		case DLT_IEEE802_11_RADIO_AVS:
 		case DLT_IEEE802_11_RADIO:
 		case DLT_PPI:
-			b0 = gen_wlanhostop(eaddr, Q_OR);
+			b0 = gen_wlanhostop(cstate, eaddr, Q_OR);
 			break;
 		case DLT_SUNATM:
 			/*
 			 * This is LLC-multiplexed traffic; if it were
-			 * LANE, linktype would have been set to
+			 * LANE, cstate->linktype would have been set to
 			 * DLT_EN10MB.
 			 */
-			bpf_error(
+			bpf_error(cstate,
 			    "'gateway' supported only on ethernet/FDDI/token ring/802.11/ATM LANE/Fibre Channel");
 			break;
 		case DLT_IP_OVER_FC:
-			b0 = gen_ipfchostop(eaddr, Q_OR);
+			b0 = gen_ipfchostop(cstate, eaddr, Q_OR);
 			break;
 		default:
-			bpf_error(
+			bpf_error(cstate,
 			    "'gateway' supported only on ethernet/FDDI/token ring/802.11/ATM LANE/Fibre Channel");
 		}
-		b1 = gen_host(**alist++, 0xffffffff, proto, Q_OR, Q_HOST);
+		b1 = gen_host(cstate, **alist++, 0xffffffff, proto, Q_OR, Q_HOST);
 		while (*alist) {
-			tmp = gen_host(**alist++, 0xffffffff, proto, Q_OR,
+			tmp = gen_host(cstate, **alist++, 0xffffffff, proto, Q_OR,
 			    Q_HOST);
 			gen_or(b1, tmp);
 			b1 = tmp;
@@ -4835,14 +4967,13 @@
 		gen_and(b0, b1);
 		return b1;
 	}
-	bpf_error("illegal modifier of 'gateway'");
+	bpf_error(cstate, "illegal modifier of 'gateway'");
 	/* NOTREACHED */
 }
 #endif
 
 struct block *
-gen_proto_abbrev(proto)
-	int proto;
+gen_proto_abbrev(compiler_state_t *cstate, int proto)
 {
 	struct block *b0;
 	struct block *b1;
@@ -4850,25 +4981,25 @@
 	switch (proto) {
 
 	case Q_SCTP:
-		b1 = gen_proto(IPPROTO_SCTP, Q_IP, Q_DEFAULT);
-		b0 = gen_proto(IPPROTO_SCTP, Q_IPV6, Q_DEFAULT);
+		b1 = gen_proto(cstate, IPPROTO_SCTP, Q_IP, Q_DEFAULT);
+		b0 = gen_proto(cstate, IPPROTO_SCTP, Q_IPV6, Q_DEFAULT);
 		gen_or(b0, b1);
 		break;
 
 	case Q_TCP:
-		b1 = gen_proto(IPPROTO_TCP, Q_IP, Q_DEFAULT);
-		b0 = gen_proto(IPPROTO_TCP, Q_IPV6, Q_DEFAULT);
+		b1 = gen_proto(cstate, IPPROTO_TCP, Q_IP, Q_DEFAULT);
+		b0 = gen_proto(cstate, IPPROTO_TCP, Q_IPV6, Q_DEFAULT);
 		gen_or(b0, b1);
 		break;
 
 	case Q_UDP:
-		b1 = gen_proto(IPPROTO_UDP, Q_IP, Q_DEFAULT);
-		b0 = gen_proto(IPPROTO_UDP, Q_IPV6, Q_DEFAULT);
+		b1 = gen_proto(cstate, IPPROTO_UDP, Q_IP, Q_DEFAULT);
+		b0 = gen_proto(cstate, IPPROTO_UDP, Q_IPV6, Q_DEFAULT);
 		gen_or(b0, b1);
 		break;
 
 	case Q_ICMP:
-		b1 = gen_proto(IPPROTO_ICMP, Q_IP, Q_DEFAULT);
+		b1 = gen_proto(cstate, IPPROTO_ICMP, Q_IP, Q_DEFAULT);
 		break;
 
 #ifndef	IPPROTO_IGMP
@@ -4876,14 +5007,14 @@
 #endif
 
 	case Q_IGMP:
-		b1 = gen_proto(IPPROTO_IGMP, Q_IP, Q_DEFAULT);
+		b1 = gen_proto(cstate, IPPROTO_IGMP, Q_IP, Q_DEFAULT);
 		break;
 
 #ifndef	IPPROTO_IGRP
 #define	IPPROTO_IGRP	9
 #endif
 	case Q_IGRP:
-		b1 = gen_proto(IPPROTO_IGRP, Q_IP, Q_DEFAULT);
+		b1 = gen_proto(cstate, IPPROTO_IGRP, Q_IP, Q_DEFAULT);
 		break;
 
 #ifndef IPPROTO_PIM
@@ -4891,8 +5022,8 @@
 #endif
 
 	case Q_PIM:
-		b1 = gen_proto(IPPROTO_PIM, Q_IP, Q_DEFAULT);
-		b0 = gen_proto(IPPROTO_PIM, Q_IPV6, Q_DEFAULT);
+		b1 = gen_proto(cstate, IPPROTO_PIM, Q_IP, Q_DEFAULT);
+		b0 = gen_proto(cstate, IPPROTO_PIM, Q_IPV6, Q_DEFAULT);
 		gen_or(b0, b1);
 		break;
 
@@ -4901,7 +5032,7 @@
 #endif
 
 	case Q_VRRP:
-		b1 = gen_proto(IPPROTO_VRRP, Q_IP, Q_DEFAULT);
+		b1 = gen_proto(cstate, IPPROTO_VRRP, Q_IP, Q_DEFAULT);
 		break;
 
 #ifndef IPPROTO_CARP
@@ -4909,69 +5040,69 @@
 #endif
 
 	case Q_CARP:
-		b1 = gen_proto(IPPROTO_CARP, Q_IP, Q_DEFAULT);
+		b1 = gen_proto(cstate, IPPROTO_CARP, Q_IP, Q_DEFAULT);
 		break;
 
 	case Q_IP:
-		b1 =  gen_linktype(ETHERTYPE_IP);
+		b1 = gen_linktype(cstate, ETHERTYPE_IP);
 		break;
 
 	case Q_ARP:
-		b1 =  gen_linktype(ETHERTYPE_ARP);
+		b1 = gen_linktype(cstate, ETHERTYPE_ARP);
 		break;
 
 	case Q_RARP:
-		b1 =  gen_linktype(ETHERTYPE_REVARP);
+		b1 = gen_linktype(cstate, ETHERTYPE_REVARP);
 		break;
 
 	case Q_LINK:
-		bpf_error("link layer applied in wrong context");
+		bpf_error(cstate, "link layer applied in wrong context");
 
 	case Q_ATALK:
-		b1 =  gen_linktype(ETHERTYPE_ATALK);
+		b1 = gen_linktype(cstate, ETHERTYPE_ATALK);
 		break;
 
 	case Q_AARP:
-		b1 =  gen_linktype(ETHERTYPE_AARP);
+		b1 = gen_linktype(cstate, ETHERTYPE_AARP);
 		break;
 
 	case Q_DECNET:
-		b1 =  gen_linktype(ETHERTYPE_DN);
+		b1 = gen_linktype(cstate, ETHERTYPE_DN);
 		break;
 
 	case Q_SCA:
-		b1 =  gen_linktype(ETHERTYPE_SCA);
+		b1 = gen_linktype(cstate, ETHERTYPE_SCA);
 		break;
 
 	case Q_LAT:
-		b1 =  gen_linktype(ETHERTYPE_LAT);
+		b1 = gen_linktype(cstate, ETHERTYPE_LAT);
 		break;
 
 	case Q_MOPDL:
-		b1 =  gen_linktype(ETHERTYPE_MOPDL);
+		b1 = gen_linktype(cstate, ETHERTYPE_MOPDL);
 		break;
 
 	case Q_MOPRC:
-		b1 =  gen_linktype(ETHERTYPE_MOPRC);
+		b1 = gen_linktype(cstate, ETHERTYPE_MOPRC);
 		break;
 
 	case Q_IPV6:
-		b1 = gen_linktype(ETHERTYPE_IPV6);
+		b1 = gen_linktype(cstate, ETHERTYPE_IPV6);
 		break;
 
 #ifndef IPPROTO_ICMPV6
 #define IPPROTO_ICMPV6	58
 #endif
 	case Q_ICMPV6:
-		b1 = gen_proto(IPPROTO_ICMPV6, Q_IPV6, Q_DEFAULT);
+		b1 = gen_proto(cstate, IPPROTO_ICMPV6, Q_IPV6, Q_DEFAULT);
 		break;
 
 #ifndef IPPROTO_AH
 #define IPPROTO_AH	51
 #endif
 	case Q_AH:
-		b1 = gen_proto(IPPROTO_AH, Q_IP, Q_DEFAULT);
-		b0 = gen_proto(IPPROTO_AH, Q_IPV6, Q_DEFAULT);
+		b1 = gen_proto(cstate, IPPROTO_AH, Q_IP, Q_DEFAULT);
+		b0 = gen_proto(cstate, IPPROTO_AH, Q_IPV6, Q_DEFAULT);
 		gen_or(b0, b1);
 		break;
 
@@ -4979,101 +5110,101 @@
 #define IPPROTO_ESP	50
 #endif
 	case Q_ESP:
-		b1 = gen_proto(IPPROTO_ESP, Q_IP, Q_DEFAULT);
-		b0 = gen_proto(IPPROTO_ESP, Q_IPV6, Q_DEFAULT);
+		b1 = gen_proto(cstate, IPPROTO_ESP, Q_IP, Q_DEFAULT);
+		b0 = gen_proto(cstate, IPPROTO_ESP, Q_IPV6, Q_DEFAULT);
 		gen_or(b0, b1);
 		break;
 
 	case Q_ISO:
-		b1 = gen_linktype(LLCSAP_ISONS);
+		b1 = gen_linktype(cstate, LLCSAP_ISONS);
 		break;
 
 	case Q_ESIS:
-		b1 = gen_proto(ISO9542_ESIS, Q_ISO, Q_DEFAULT);
+		b1 = gen_proto(cstate, ISO9542_ESIS, Q_ISO, Q_DEFAULT);
 		break;
 
 	case Q_ISIS:
-		b1 = gen_proto(ISO10589_ISIS, Q_ISO, Q_DEFAULT);
+		b1 = gen_proto(cstate, ISO10589_ISIS, Q_ISO, Q_DEFAULT);
 		break;
 
 	case Q_ISIS_L1: /* all IS-IS Level1 PDU-Types */
-		b0 = gen_proto(ISIS_L1_LAN_IIH, Q_ISIS, Q_DEFAULT);
-		b1 = gen_proto(ISIS_PTP_IIH, Q_ISIS, Q_DEFAULT); /* FIXME extract the circuit-type bits */
+		b0 = gen_proto(cstate, ISIS_L1_LAN_IIH, Q_ISIS, Q_DEFAULT);
+		b1 = gen_proto(cstate, ISIS_PTP_IIH, Q_ISIS, Q_DEFAULT); /* FIXME extract the circuit-type bits */
 		gen_or(b0, b1);
-		b0 = gen_proto(ISIS_L1_LSP, Q_ISIS, Q_DEFAULT);
+		b0 = gen_proto(cstate, ISIS_L1_LSP, Q_ISIS, Q_DEFAULT);
 		gen_or(b0, b1);
-		b0 = gen_proto(ISIS_L1_CSNP, Q_ISIS, Q_DEFAULT);
+		b0 = gen_proto(cstate, ISIS_L1_CSNP, Q_ISIS, Q_DEFAULT);
 		gen_or(b0, b1);
-		b0 = gen_proto(ISIS_L1_PSNP, Q_ISIS, Q_DEFAULT);
+		b0 = gen_proto(cstate, ISIS_L1_PSNP, Q_ISIS, Q_DEFAULT);
 		gen_or(b0, b1);
 		break;
 
 	case Q_ISIS_L2: /* all IS-IS Level2 PDU-Types */
-		b0 = gen_proto(ISIS_L2_LAN_IIH, Q_ISIS, Q_DEFAULT);
-		b1 = gen_proto(ISIS_PTP_IIH, Q_ISIS, Q_DEFAULT); /* FIXME extract the circuit-type bits */
+		b0 = gen_proto(cstate, ISIS_L2_LAN_IIH, Q_ISIS, Q_DEFAULT);
+		b1 = gen_proto(cstate, ISIS_PTP_IIH, Q_ISIS, Q_DEFAULT); /* FIXME extract the circuit-type bits */
 		gen_or(b0, b1);
-		b0 = gen_proto(ISIS_L2_LSP, Q_ISIS, Q_DEFAULT);
+		b0 = gen_proto(cstate, ISIS_L2_LSP, Q_ISIS, Q_DEFAULT);
 		gen_or(b0, b1);
-		b0 = gen_proto(ISIS_L2_CSNP, Q_ISIS, Q_DEFAULT);
+		b0 = gen_proto(cstate, ISIS_L2_CSNP, Q_ISIS, Q_DEFAULT);
 		gen_or(b0, b1);
-		b0 = gen_proto(ISIS_L2_PSNP, Q_ISIS, Q_DEFAULT);
+		b0 = gen_proto(cstate, ISIS_L2_PSNP, Q_ISIS, Q_DEFAULT);
 		gen_or(b0, b1);
 		break;
 
 	case Q_ISIS_IIH: /* all IS-IS Hello PDU-Types */
-		b0 = gen_proto(ISIS_L1_LAN_IIH, Q_ISIS, Q_DEFAULT);
-		b1 = gen_proto(ISIS_L2_LAN_IIH, Q_ISIS, Q_DEFAULT);
+		b0 = gen_proto(cstate, ISIS_L1_LAN_IIH, Q_ISIS, Q_DEFAULT);
+		b1 = gen_proto(cstate, ISIS_L2_LAN_IIH, Q_ISIS, Q_DEFAULT);
 		gen_or(b0, b1);
-		b0 = gen_proto(ISIS_PTP_IIH, Q_ISIS, Q_DEFAULT);
+		b0 = gen_proto(cstate, ISIS_PTP_IIH, Q_ISIS, Q_DEFAULT);
 		gen_or(b0, b1);
 		break;
 
 	case Q_ISIS_LSP:
-		b0 = gen_proto(ISIS_L1_LSP, Q_ISIS, Q_DEFAULT);
-		b1 = gen_proto(ISIS_L2_LSP, Q_ISIS, Q_DEFAULT);
+		b0 = gen_proto(cstate, ISIS_L1_LSP, Q_ISIS, Q_DEFAULT);
+		b1 = gen_proto(cstate, ISIS_L2_LSP, Q_ISIS, Q_DEFAULT);
 		gen_or(b0, b1);
 		break;
 
 	case Q_ISIS_SNP:
-		b0 = gen_proto(ISIS_L1_CSNP, Q_ISIS, Q_DEFAULT);
-		b1 = gen_proto(ISIS_L2_CSNP, Q_ISIS, Q_DEFAULT);
+		b0 = gen_proto(cstate, ISIS_L1_CSNP, Q_ISIS, Q_DEFAULT);
+		b1 = gen_proto(cstate, ISIS_L2_CSNP, Q_ISIS, Q_DEFAULT);
 		gen_or(b0, b1);
-		b0 = gen_proto(ISIS_L1_PSNP, Q_ISIS, Q_DEFAULT);
+		b0 = gen_proto(cstate, ISIS_L1_PSNP, Q_ISIS, Q_DEFAULT);
 		gen_or(b0, b1);
-		b0 = gen_proto(ISIS_L2_PSNP, Q_ISIS, Q_DEFAULT);
+		b0 = gen_proto(cstate, ISIS_L2_PSNP, Q_ISIS, Q_DEFAULT);
 		gen_or(b0, b1);
 		break;
 
 	case Q_ISIS_CSNP:
-		b0 = gen_proto(ISIS_L1_CSNP, Q_ISIS, Q_DEFAULT);
-		b1 = gen_proto(ISIS_L2_CSNP, Q_ISIS, Q_DEFAULT);
+		b0 = gen_proto(cstate, ISIS_L1_CSNP, Q_ISIS, Q_DEFAULT);
+		b1 = gen_proto(cstate, ISIS_L2_CSNP, Q_ISIS, Q_DEFAULT);
 		gen_or(b0, b1);
 		break;
 
 	case Q_ISIS_PSNP:
-		b0 = gen_proto(ISIS_L1_PSNP, Q_ISIS, Q_DEFAULT);
-		b1 = gen_proto(ISIS_L2_PSNP, Q_ISIS, Q_DEFAULT);
+		b0 = gen_proto(cstate, ISIS_L1_PSNP, Q_ISIS, Q_DEFAULT);
+		b1 = gen_proto(cstate, ISIS_L2_PSNP, Q_ISIS, Q_DEFAULT);
 		gen_or(b0, b1);
 		break;
 
 	case Q_CLNP:
-		b1 = gen_proto(ISO8473_CLNP, Q_ISO, Q_DEFAULT);
+		b1 = gen_proto(cstate, ISO8473_CLNP, Q_ISO, Q_DEFAULT);
 		break;
 
 	case Q_STP:
-		b1 = gen_linktype(LLCSAP_8021D);
+		b1 = gen_linktype(cstate, LLCSAP_8021D);
 		break;
 
 	case Q_IPX:
-		b1 = gen_linktype(LLCSAP_IPX);
+		b1 = gen_linktype(cstate, LLCSAP_IPX);
 		break;
 
 	case Q_NETBEUI:
-		b1 = gen_linktype(LLCSAP_NETBEUI);
+		b1 = gen_linktype(cstate, LLCSAP_NETBEUI);
 		break;
 
 	case Q_RADIO:
-		bpf_error("'radio' is not a valid protocol type");
+		bpf_error(cstate, "'radio' is not a valid protocol type");
 
 	default:
 		abort();
@@ -5082,14 +5213,14 @@
 }
 
 static struct block *
-gen_ipfrag()
+gen_ipfrag(compiler_state_t *cstate)
 {
 	struct slist *s;
 	struct block *b;
 
 	/* not IPv4 frag other than the first frag */
-	s = gen_load_a(OR_LINKPL, 6, BPF_H);
-	b = new_block(JMP(BPF_JSET));
+	s = gen_load_a(cstate, OR_LINKPL, 6, BPF_H);
+	b = new_block(cstate, JMP(BPF_JSET));
 	b->s.k = 0x1fff;
 	b->stmts = s;
 	gen_not(b);
@@ -5107,51 +5238,46 @@
  * headers).
  */
 static struct block *
-gen_portatom(off, v)
-	int off;
-	bpf_int32 v;
+gen_portatom(compiler_state_t *cstate, int off, bpf_int32 v)
 {
-	return gen_cmp(OR_TRAN_IPV4, off, BPF_H, v);
+	return gen_cmp(cstate, OR_TRAN_IPV4, off, BPF_H, v);
 }
 
 static struct block *
-gen_portatom6(off, v)
-	int off;
-	bpf_int32 v;
+gen_portatom6(compiler_state_t *cstate, int off, bpf_int32 v)
 {
-	return gen_cmp(OR_TRAN_IPV6, off, BPF_H, v);
+	return gen_cmp(cstate, OR_TRAN_IPV6, off, BPF_H, v);
 }
 
 struct block *
-gen_portop(port, proto, dir)
-	int port, proto, dir;
+gen_portop(compiler_state_t *cstate, int port, int proto, int dir)
 {
 	struct block *b0, *b1, *tmp;
 
 	/* ip proto 'proto' and not a fragment other than the first fragment */
-	tmp = gen_cmp(OR_LINKPL, 9, BPF_B, (bpf_int32)proto);
-	b0 = gen_ipfrag();
+	tmp = gen_cmp(cstate, OR_LINKPL, 9, BPF_B, (bpf_int32)proto);
+	b0 = gen_ipfrag(cstate);
 	gen_and(tmp, b0);
 
 	switch (dir) {
 	case Q_SRC:
-		b1 = gen_portatom(0, (bpf_int32)port);
+		b1 = gen_portatom(cstate, 0, (bpf_int32)port);
 		break;
 
 	case Q_DST:
-		b1 = gen_portatom(2, (bpf_int32)port);
+		b1 = gen_portatom(cstate, 2, (bpf_int32)port);
 		break;
 
 	case Q_OR:
 	case Q_DEFAULT:
-		tmp = gen_portatom(0, (bpf_int32)port);
-		b1 = gen_portatom(2, (bpf_int32)port);
+		tmp = gen_portatom(cstate, 0, (bpf_int32)port);
+		b1 = gen_portatom(cstate, 2, (bpf_int32)port);
 		gen_or(tmp, b1);
 		break;
 
 	case Q_AND:
-		tmp = gen_portatom(0, (bpf_int32)port);
-		b1 = gen_portatom(2, (bpf_int32)port);
+		tmp = gen_portatom(cstate, 0, (bpf_int32)port);
+		b1 = gen_portatom(cstate, 2, (bpf_int32)port);
 		gen_and(tmp, b1);
 		break;
 
@@ -5164,10 +5290,7 @@
 }
 
 static struct block *
-gen_port(port, ip_proto, dir)
-	int port;
-	int ip_proto;
-	int dir;
+gen_port(compiler_state_t *cstate, int port, int ip_proto, int dir)
 {
 	struct block *b0, *b1, *tmp;
 
@@ -5188,20 +5311,20 @@
 	 *
 	 * So we always check for ETHERTYPE_IP.
 	 */
-	b0 =  gen_linktype(ETHERTYPE_IP);
+	b0 = gen_linktype(cstate, ETHERTYPE_IP);
 
 	switch (ip_proto) {
 	case IPPROTO_UDP:
 	case IPPROTO_TCP:
 	case IPPROTO_SCTP:
-		b1 = gen_portop(port, ip_proto, dir);
+		b1 = gen_portop(cstate, port, ip_proto, dir);
 		break;
 
 	case PROTO_UNDEF:
-		tmp = gen_portop(port, IPPROTO_TCP, dir);
-		b1 = gen_portop(port, IPPROTO_UDP, dir);
+		tmp = gen_portop(cstate, port, IPPROTO_TCP, dir);
+		b1 = gen_portop(cstate, port, IPPROTO_UDP, dir);
 		gen_or(tmp, b1);
-		tmp = gen_portop(port, IPPROTO_SCTP, dir);
+		tmp = gen_portop(cstate, port, IPPROTO_SCTP, dir);
 		gen_or(tmp, b1);
 		break;
 
@@ -5213,34 +5336,33 @@
 }
 
 struct block *
-gen_portop6(port, proto, dir)
-	int port, proto, dir;
+gen_portop6(compiler_state_t *cstate, int port, int proto, int dir)
 {
 	struct block *b0, *b1, *tmp;
 
 	/* ip6 proto 'proto' */
 	/* XXX - catch the first fragment of a fragmented packet? */
-	b0 = gen_cmp(OR_LINKPL, 6, BPF_B, (bpf_int32)proto);
+	b0 = gen_cmp(cstate, OR_LINKPL, 6, BPF_B, (bpf_int32)proto);
 
 	switch (dir) {
 	case Q_SRC:
-		b1 = gen_portatom6(0, (bpf_int32)port);
+		b1 = gen_portatom6(cstate, 0, (bpf_int32)port);
 		break;
 
 	case Q_DST:
-		b1 = gen_portatom6(2, (bpf_int32)port);
+		b1 = gen_portatom6(cstate, 2, (bpf_int32)port);
 		break;
 
 	case Q_OR:
 	case Q_DEFAULT:
-		tmp = gen_portatom6(0, (bpf_int32)port);
-		b1 = gen_portatom6(2, (bpf_int32)port);
+		tmp = gen_portatom6(cstate, 0, (bpf_int32)port);
+		b1 = gen_portatom6(cstate, 2, (bpf_int32)port);
 		gen_or(tmp, b1);
 		break;
 
 	case Q_AND:
-		tmp = gen_portatom6(0, (bpf_int32)port);
-		b1 = gen_portatom6(2, (bpf_int32)port);
+		tmp = gen_portatom6(cstate, 0, (bpf_int32)port);
+		b1 = gen_portatom6(cstate, 2, (bpf_int32)port);
 		gen_and(tmp, b1);
 		break;
 
@@ -5253,28 +5375,25 @@
 }
 
 static struct block *
-gen_port6(port, ip_proto, dir)
-	int port;
-	int ip_proto;
-	int dir;
+gen_port6(compiler_state_t *cstate, int port, int ip_proto, int dir)
 {
 	struct block *b0, *b1, *tmp;
 
 	/* link proto ip6 */
-	b0 =  gen_linktype(ETHERTYPE_IPV6);
+	b0 = gen_linktype(cstate, ETHERTYPE_IPV6);
 
 	switch (ip_proto) {
 	case IPPROTO_UDP:
 	case IPPROTO_TCP:
 	case IPPROTO_SCTP:
-		b1 = gen_portop6(port, ip_proto, dir);
+		b1 = gen_portop6(cstate, port, ip_proto, dir);
 		break;
 
 	case PROTO_UNDEF:
-		tmp = gen_portop6(port, IPPROTO_TCP, dir);
-		b1 = gen_portop6(port, IPPROTO_UDP, dir);
+		tmp = gen_portop6(cstate, port, IPPROTO_TCP, dir);
+		b1 = gen_portop6(cstate, port, IPPROTO_UDP, dir);
 		gen_or(tmp, b1);
-		tmp = gen_portop6(port, IPPROTO_SCTP, dir);
+		tmp = gen_portop6(cstate, port, IPPROTO_SCTP, dir);
 		gen_or(tmp, b1);
 		break;
 
@@ -5287,9 +5406,8 @@
 
 /* gen_portrange code */
 static struct block *
-gen_portrangeatom(off, v1, v2)
-	int off;
-	bpf_int32 v1, v2;
+gen_portrangeatom(compiler_state_t *cstate, int off, bpf_int32 v1,
+    bpf_int32 v2)
 {
 	struct block *b1, *b2;
 
@@ -5304,8 +5422,8 @@
 		v2 = vtemp;
 	}
 
-	b1 = gen_cmp_ge(OR_TRAN_IPV4, off, BPF_H, v1);
-	b2 = gen_cmp_le(OR_TRAN_IPV4, off, BPF_H, v2);
+	b1 = gen_cmp_ge(cstate, OR_TRAN_IPV4, off, BPF_H, v1);
+	b2 = gen_cmp_le(cstate, OR_TRAN_IPV4, off, BPF_H, v2);
 
 	gen_and(b1, b2);
 
@@ -5313,37 +5431,35 @@
 }
 
 struct block *
-gen_portrangeop(port1, port2, proto, dir)
-	int port1, port2;
-	int proto;
-	int dir;
+gen_portrangeop(compiler_state_t *cstate, int port1, int port2, int proto,
+    int dir)
 {
 	struct block *b0, *b1, *tmp;
 
 	/* ip proto 'proto' and not a fragment other than the first fragment */
-	tmp = gen_cmp(OR_LINKPL, 9, BPF_B, (bpf_int32)proto);
-	b0 = gen_ipfrag();
+	tmp = gen_cmp(cstate, OR_LINKPL, 9, BPF_B, (bpf_int32)proto);
+	b0 = gen_ipfrag(cstate);
 	gen_and(tmp, b0);
 
 	switch (dir) {
 	case Q_SRC:
-		b1 = gen_portrangeatom(0, (bpf_int32)port1, (bpf_int32)port2);
+		b1 = gen_portrangeatom(cstate, 0, (bpf_int32)port1, (bpf_int32)port2);
 		break;
 
 	case Q_DST:
-		b1 = gen_portrangeatom(2, (bpf_int32)port1, (bpf_int32)port2);
+		b1 = gen_portrangeatom(cstate, 2, (bpf_int32)port1, (bpf_int32)port2);
 		break;
 
 	case Q_OR:
 	case Q_DEFAULT:
-		tmp = gen_portrangeatom(0, (bpf_int32)port1, (bpf_int32)port2);
-		b1 = gen_portrangeatom(2, (bpf_int32)port1, (bpf_int32)port2);
+		tmp = gen_portrangeatom(cstate, 0, (bpf_int32)port1, (bpf_int32)port2);
+		b1 = gen_portrangeatom(cstate, 2, (bpf_int32)port1, (bpf_int32)port2);
 		gen_or(tmp, b1);
 		break;
 
 	case Q_AND:
-		tmp = gen_portrangeatom(0, (bpf_int32)port1, (bpf_int32)port2);
-		b1 = gen_portrangeatom(2, (bpf_int32)port1, (bpf_int32)port2);
+		tmp = gen_portrangeatom(cstate, 0, (bpf_int32)port1, (bpf_int32)port2);
+		b1 = gen_portrangeatom(cstate, 2, (bpf_int32)port1, (bpf_int32)port2);
 		gen_and(tmp, b1);
 		break;
 
@@ -5356,28 +5472,26 @@
 }
 
 static struct block *
-gen_portrange(port1, port2, ip_proto, dir)
-	int port1, port2;
-	int ip_proto;
-	int dir;
+gen_portrange(compiler_state_t *cstate, int port1, int port2, int ip_proto,
+    int dir)
 {
 	struct block *b0, *b1, *tmp;
 
 	/* link proto ip */
-	b0 =  gen_linktype(ETHERTYPE_IP);
+	b0 = gen_linktype(cstate, ETHERTYPE_IP);
 
 	switch (ip_proto) {
 	case IPPROTO_UDP:
 	case IPPROTO_TCP:
 	case IPPROTO_SCTP:
-		b1 = gen_portrangeop(port1, port2, ip_proto, dir);
+		b1 = gen_portrangeop(cstate, port1, port2, ip_proto, dir);
 		break;
 
 	case PROTO_UNDEF:
-		tmp = gen_portrangeop(port1, port2, IPPROTO_TCP, dir);
-		b1 = gen_portrangeop(port1, port2, IPPROTO_UDP, dir);
+		tmp = gen_portrangeop(cstate, port1, port2, IPPROTO_TCP, dir);
+		b1 = gen_portrangeop(cstate, port1, port2, IPPROTO_UDP, dir);
 		gen_or(tmp, b1);
-		tmp = gen_portrangeop(port1, port2, IPPROTO_SCTP, dir);
+		tmp = gen_portrangeop(cstate, port1, port2, IPPROTO_SCTP, dir);
 		gen_or(tmp, b1);
 		break;
 
@@ -5389,9 +5503,8 @@
 }
 
 static struct block *
-gen_portrangeatom6(off, v1, v2)
-	int off;
-	bpf_int32 v1, v2;
+gen_portrangeatom6(compiler_state_t *cstate, int off, bpf_int32 v1,
+    bpf_int32 v2)
 {
 	struct block *b1, *b2;
 
@@ -5406,8 +5519,8 @@
 		v2 = vtemp;
 	}
 
-	b1 = gen_cmp_ge(OR_TRAN_IPV6, off, BPF_H, v1);
-	b2 = gen_cmp_le(OR_TRAN_IPV6, off, BPF_H, v2);
+	b1 = gen_cmp_ge(cstate, OR_TRAN_IPV6, off, BPF_H, v1);
+	b2 = gen_cmp_le(cstate, OR_TRAN_IPV6, off, BPF_H, v2);
 
 	gen_and(b1, b2);
 
@@ -5415,36 +5528,34 @@
 }
 
 struct block *
-gen_portrangeop6(port1, port2, proto, dir)
-	int port1, port2;
-	int proto;
-	int dir;
+gen_portrangeop6(compiler_state_t *cstate, int port1, int port2, int proto,
+    int dir)
 {
 	struct block *b0, *b1, *tmp;
 
 	/* ip6 proto 'proto' */
 	/* XXX - catch the first fragment of a fragmented packet? */
-	b0 = gen_cmp(OR_LINKPL, 6, BPF_B, (bpf_int32)proto);
+	b0 = gen_cmp(cstate, OR_LINKPL, 6, BPF_B, (bpf_int32)proto);
 
 	switch (dir) {
 	case Q_SRC:
-		b1 = gen_portrangeatom6(0, (bpf_int32)port1, (bpf_int32)port2);
+		b1 = gen_portrangeatom6(cstate, 0, (bpf_int32)port1, (bpf_int32)port2);
 		break;
 
 	case Q_DST:
-		b1 = gen_portrangeatom6(2, (bpf_int32)port1, (bpf_int32)port2);
+		b1 = gen_portrangeatom6(cstate, 2, (bpf_int32)port1, (bpf_int32)port2);
 		break;
 
 	case Q_OR:
 	case Q_DEFAULT:
-		tmp = gen_portrangeatom6(0, (bpf_int32)port1, (bpf_int32)port2);
-		b1 = gen_portrangeatom6(2, (bpf_int32)port1, (bpf_int32)port2);
+		tmp = gen_portrangeatom6(cstate, 0, (bpf_int32)port1, (bpf_int32)port2);
+		b1 = gen_portrangeatom6(cstate, 2, (bpf_int32)port1, (bpf_int32)port2);
 		gen_or(tmp, b1);
 		break;
 
 	case Q_AND:
-		tmp = gen_portrangeatom6(0, (bpf_int32)port1, (bpf_int32)port2);
-		b1 = gen_portrangeatom6(2, (bpf_int32)port1, (bpf_int32)port2);
+		tmp = gen_portrangeatom6(cstate, 0, (bpf_int32)port1, (bpf_int32)port2);
+		b1 = gen_portrangeatom6(cstate, 2, (bpf_int32)port1, (bpf_int32)port2);
 		gen_and(tmp, b1);
 		break;
 
@@ -5457,28 +5568,26 @@
 }
 
 static struct block *
-gen_portrange6(port1, port2, ip_proto, dir)
-	int port1, port2;
-	int ip_proto;
-	int dir;
+gen_portrange6(compiler_state_t *cstate, int port1, int port2, int ip_proto,
+    int dir)
 {
 	struct block *b0, *b1, *tmp;
 
 	/* link proto ip6 */
-	b0 =  gen_linktype(ETHERTYPE_IPV6);
+	b0 = gen_linktype(cstate, ETHERTYPE_IPV6);
 
 	switch (ip_proto) {
 	case IPPROTO_UDP:
 	case IPPROTO_TCP:
 	case IPPROTO_SCTP:
-		b1 = gen_portrangeop6(port1, port2, ip_proto, dir);
+		b1 = gen_portrangeop6(cstate, port1, port2, ip_proto, dir);
 		break;
 
 	case PROTO_UNDEF:
-		tmp = gen_portrangeop6(port1, port2, IPPROTO_TCP, dir);
-		b1 = gen_portrangeop6(port1, port2, IPPROTO_UDP, dir);
+		tmp = gen_portrangeop6(cstate, port1, port2, IPPROTO_TCP, dir);
+		b1 = gen_portrangeop6(cstate, port1, port2, IPPROTO_UDP, dir);
 		gen_or(tmp, b1);
-		tmp = gen_portrangeop6(port1, port2, IPPROTO_SCTP, dir);
+		tmp = gen_portrangeop6(cstate, port1, port2, IPPROTO_SCTP, dir);
 		gen_or(tmp, b1);
 		break;
 
@@ -5490,9 +5599,7 @@
 }
 
 static int
-lookup_proto(name, proto)
-	register const char *name;
-	register int proto;
+lookup_proto(compiler_state_t *cstate, const char *name, int proto)
 {
 	register int v;
 
@@ -5503,16 +5610,16 @@
 	case Q_IPV6:
 		v = pcap_nametoproto(name);
 		if (v == PROTO_UNDEF)
-			bpf_error("unknown ip proto '%s'", name);
+			bpf_error(cstate, "unknown ip proto '%s'", name);
 		break;
 
 	case Q_LINK:
-		/* XXX should look up h/w protocol type based on linktype */
+		/* XXX should look up h/w protocol type based on cstate->linktype */
 		v = pcap_nametoeproto(name);
 		if (v == PROTO_UNDEF) {
 			v = pcap_nametollc(name);
 			if (v == PROTO_UNDEF)
-				bpf_error("unknown ether proto '%s'", name);
+				bpf_error(cstate, "unknown ether proto '%s'", name);
 		}
 		break;
 
@@ -5524,7 +5631,7 @@
 		else if (strcmp(name, "clnp") == 0)
 			v = ISO8473_CLNP;
 		else
-			bpf_error("unknown osi proto '%s'", name);
+			bpf_error(cstate, "unknown osi proto '%s'", name);
 		break;
 
 	default:
@@ -5545,35 +5652,32 @@
 #endif
 
 static struct block *
-gen_protochain(v, proto, dir)
-	int v;
-	int proto;
-	int dir;
+gen_protochain(compiler_state_t *cstate, int v, int proto, int dir)
 {
 #ifdef NO_PROTOCHAIN
-	return gen_proto(v, proto, dir);
+	return gen_proto(cstate, v, proto, dir);
 #else
 	struct block *b0, *b;
 	struct slist *s[100];
 	int fix2, fix3, fix4, fix5;
 	int ahcheck, again, end;
 	int i, max;
-	int reg2 = alloc_reg();
+	int reg2 = alloc_reg(cstate);
 
 	memset(s, 0, sizeof(s));
-	fix2 = fix3 = fix4 = fix5 = 0;
+	fix3 = fix4 = fix5 = 0;
 
 	switch (proto) {
 	case Q_IP:
 	case Q_IPV6:
 		break;
 	case Q_DEFAULT:
-		b0 = gen_protochain(v, Q_IP, dir);
-		b = gen_protochain(v, Q_IPV6, dir);
+		b0 = gen_protochain(cstate, v, Q_IP, dir);
+		b = gen_protochain(cstate, v, Q_IPV6, dir);
 		gen_or(b0, b);
 		return b;
 	default:
-		bpf_error("bad protocol applied for 'protochain'");
+		bpf_error(cstate, "bad protocol applied for 'protochain'");
 		/*NOTREACHED*/
 	}
 
@@ -5588,10 +5692,10 @@
 	 * branches, and backward branch support is unlikely to appear
 	 * in kernel BPF engines.)
 	 */
-	if (off_linkpl.is_variable)
-		bpf_error("'protochain' not supported with variable length headers");
+	if (cstate->off_linkpl.is_variable)
+		bpf_error(cstate, "'protochain' not supported with variable length headers");
 
-	no_optimize = 1; /*this code is not compatible with optimzer yet */
+	cstate->no_optimize = 1; /*this code is not compatible with optimzer yet */
 
 	/*
 	 * s[0] is a dummy entry to protect other BPF insn from damage
@@ -5599,44 +5703,44 @@
 	 * hard to find interdependency made by jump table fixup.
 	 */
 	i = 0;
-	s[i] = new_stmt(0);	/*dummy*/
+	s[i] = new_stmt(cstate, 0);	/*dummy*/
 	i++;
 
 	switch (proto) {
 	case Q_IP:
-		b0 = gen_linktype(ETHERTYPE_IP);
+		b0 = gen_linktype(cstate, ETHERTYPE_IP);
 
 		/* A = ip->ip_p */
-		s[i] = new_stmt(BPF_LD|BPF_ABS|BPF_B);
-		s[i]->s.k = off_linkpl.constant_part + off_nl + 9;
+		s[i] = new_stmt(cstate, BPF_LD|BPF_ABS|BPF_B);
+		s[i]->s.k = cstate->off_linkpl.constant_part + cstate->off_nl + 9;
 		i++;
 		/* X = ip->ip_hl << 2 */
-		s[i] = new_stmt(BPF_LDX|BPF_MSH|BPF_B);
-		s[i]->s.k = off_linkpl.constant_part + off_nl;
+		s[i] = new_stmt(cstate, BPF_LDX|BPF_MSH|BPF_B);
+		s[i]->s.k = cstate->off_linkpl.constant_part + cstate->off_nl;
 		i++;
 		break;
 
 	case Q_IPV6:
-		b0 = gen_linktype(ETHERTYPE_IPV6);
+		b0 = gen_linktype(cstate, ETHERTYPE_IPV6);
 
 		/* A = ip6->ip_nxt */
-		s[i] = new_stmt(BPF_LD|BPF_ABS|BPF_B);
-		s[i]->s.k = off_linkpl.constant_part + off_nl + 6;
+		s[i] = new_stmt(cstate, BPF_LD|BPF_ABS|BPF_B);
+		s[i]->s.k = cstate->off_linkpl.constant_part + cstate->off_nl + 6;
 		i++;
 		/* X = sizeof(struct ip6_hdr) */
-		s[i] = new_stmt(BPF_LDX|BPF_IMM);
+		s[i] = new_stmt(cstate, BPF_LDX|BPF_IMM);
 		s[i]->s.k = 40;
 		i++;
 		break;
 
 	default:
-		bpf_error("unsupported proto to gen_protochain");
+		bpf_error(cstate, "unsupported proto to gen_protochain");
 		/*NOTREACHED*/
 	}
 
 	/* again: if (A == v) goto end; else fall through; */
 	again = i;
-	s[i] = new_stmt(BPF_JMP|BPF_JEQ|BPF_K);
+	s[i] = new_stmt(cstate, BPF_JMP|BPF_JEQ|BPF_K);
 	s[i]->s.k = v;
 	s[i]->s.jt = NULL;		/*later*/
 	s[i]->s.jf = NULL;		/*update in next stmt*/
@@ -5647,7 +5751,7 @@
 #define IPPROTO_NONE	59
 #endif
 	/* if (A == IPPROTO_NONE) goto end */
-	s[i] = new_stmt(BPF_JMP|BPF_JEQ|BPF_K);
+	s[i] = new_stmt(cstate, BPF_JMP|BPF_JEQ|BPF_K);
 	s[i]->s.jt = NULL;	/*later*/
 	s[i]->s.jf = NULL;	/*update in next stmt*/
 	s[i]->s.k = IPPROTO_NONE;
@@ -5660,26 +5764,26 @@
 
 		v6start = i;
 		/* if (A == IPPROTO_HOPOPTS) goto v6advance */
-		s[i] = new_stmt(BPF_JMP|BPF_JEQ|BPF_K);
+		s[i] = new_stmt(cstate, BPF_JMP|BPF_JEQ|BPF_K);
 		s[i]->s.jt = NULL;	/*later*/
 		s[i]->s.jf = NULL;	/*update in next stmt*/
 		s[i]->s.k = IPPROTO_HOPOPTS;
 		s[fix2]->s.jf = s[i];
 		i++;
 		/* if (A == IPPROTO_DSTOPTS) goto v6advance */
-		s[i - 1]->s.jf = s[i] = new_stmt(BPF_JMP|BPF_JEQ|BPF_K);
+		s[i - 1]->s.jf = s[i] = new_stmt(cstate, BPF_JMP|BPF_JEQ|BPF_K);
 		s[i]->s.jt = NULL;	/*later*/
 		s[i]->s.jf = NULL;	/*update in next stmt*/
 		s[i]->s.k = IPPROTO_DSTOPTS;
 		i++;
 		/* if (A == IPPROTO_ROUTING) goto v6advance */
-		s[i - 1]->s.jf = s[i] = new_stmt(BPF_JMP|BPF_JEQ|BPF_K);
+		s[i - 1]->s.jf = s[i] = new_stmt(cstate, BPF_JMP|BPF_JEQ|BPF_K);
 		s[i]->s.jt = NULL;	/*later*/
 		s[i]->s.jf = NULL;	/*update in next stmt*/
 		s[i]->s.k = IPPROTO_ROUTING;
 		i++;
 		/* if (A == IPPROTO_FRAGMENT) goto v6advance; else goto ahcheck; */
-		s[i - 1]->s.jf = s[i] = new_stmt(BPF_JMP|BPF_JEQ|BPF_K);
+		s[i - 1]->s.jf = s[i] = new_stmt(cstate, BPF_JMP|BPF_JEQ|BPF_K);
 		s[i]->s.jt = NULL;	/*later*/
 		s[i]->s.jf = NULL;	/*later*/
 		s[i]->s.k = IPPROTO_FRAGMENT;
@@ -5696,39 +5800,39 @@
 		 * X = X + (P[X + packet head + 1] + 1) * 8;
 		 */
 		/* A = P[X + packet head] */
-		s[i] = new_stmt(BPF_LD|BPF_IND|BPF_B);
-		s[i]->s.k = off_linkpl.constant_part + off_nl;
+		s[i] = new_stmt(cstate, BPF_LD|BPF_IND|BPF_B);
+		s[i]->s.k = cstate->off_linkpl.constant_part + cstate->off_nl;
 		i++;
 		/* MEM[reg2] = A */
-		s[i] = new_stmt(BPF_ST);
+		s[i] = new_stmt(cstate, BPF_ST);
 		s[i]->s.k = reg2;
 		i++;
 		/* A = P[X + packet head + 1]; */
-		s[i] = new_stmt(BPF_LD|BPF_IND|BPF_B);
-		s[i]->s.k = off_linkpl.constant_part + off_nl + 1;
+		s[i] = new_stmt(cstate, BPF_LD|BPF_IND|BPF_B);
+		s[i]->s.k = cstate->off_linkpl.constant_part + cstate->off_nl + 1;
 		i++;
 		/* A += 1 */
-		s[i] = new_stmt(BPF_ALU|BPF_ADD|BPF_K);
+		s[i] = new_stmt(cstate, BPF_ALU|BPF_ADD|BPF_K);
 		s[i]->s.k = 1;
 		i++;
 		/* A *= 8 */
-		s[i] = new_stmt(BPF_ALU|BPF_MUL|BPF_K);
+		s[i] = new_stmt(cstate, BPF_ALU|BPF_MUL|BPF_K);
 		s[i]->s.k = 8;
 		i++;
 		/* A += X */
-		s[i] = new_stmt(BPF_ALU|BPF_ADD|BPF_X);
+		s[i] = new_stmt(cstate, BPF_ALU|BPF_ADD|BPF_X);
 		s[i]->s.k = 0;
 		i++;
 		/* X = A; */
-		s[i] = new_stmt(BPF_MISC|BPF_TAX);
+		s[i] = new_stmt(cstate, BPF_MISC|BPF_TAX);
 		i++;
 		/* A = MEM[reg2] */
-		s[i] = new_stmt(BPF_LD|BPF_MEM);
+		s[i] = new_stmt(cstate, BPF_LD|BPF_MEM);
 		s[i]->s.k = reg2;
 		i++;
 
 		/* goto again; (must use BPF_JA for backward jump) */
-		s[i] = new_stmt(BPF_JMP|BPF_JA);
+		s[i] = new_stmt(cstate, BPF_JMP|BPF_JA);
 		s[i]->s.k = again - i - 1;
 		s[i - 1]->s.jf = s[i];
 		i++;
@@ -5738,7 +5842,7 @@
 			s[j]->s.jt = s[v6advance];
 	} else {
 		/* nop */
-		s[i] = new_stmt(BPF_ALU|BPF_ADD|BPF_K);
+		s[i] = new_stmt(cstate, BPF_ALU|BPF_ADD|BPF_K);
 		s[i]->s.k = 0;
 		s[fix2]->s.jf = s[i];
 		i++;
@@ -5747,7 +5851,7 @@
 	/* ahcheck: */
 	ahcheck = i;
 	/* if (A == IPPROTO_AH) then fall through; else goto end; */
-	s[i] = new_stmt(BPF_JMP|BPF_JEQ|BPF_K);
+	s[i] = new_stmt(cstate, BPF_JMP|BPF_JEQ|BPF_K);
 	s[i]->s.jt = NULL;	/*later*/
 	s[i]->s.jf = NULL;	/*later*/
 	s[i]->s.k = IPPROTO_AH;
@@ -5762,54 +5866,54 @@
 	 * X = X + (P[X + 1] + 2) * 4;
 	 */
 	/* A = X */
-	s[i - 1]->s.jt = s[i] = new_stmt(BPF_MISC|BPF_TXA);
+	s[i - 1]->s.jt = s[i] = new_stmt(cstate, BPF_MISC|BPF_TXA);
 	i++;
 	/* A = P[X + packet head]; */
-	s[i] = new_stmt(BPF_LD|BPF_IND|BPF_B);
-	s[i]->s.k = off_linkpl.constant_part + off_nl;
+	s[i] = new_stmt(cstate, BPF_LD|BPF_IND|BPF_B);
+	s[i]->s.k = cstate->off_linkpl.constant_part + cstate->off_nl;
 	i++;
 	/* MEM[reg2] = A */
-	s[i] = new_stmt(BPF_ST);
+	s[i] = new_stmt(cstate, BPF_ST);
 	s[i]->s.k = reg2;
 	i++;
 	/* A = X */
-	s[i - 1]->s.jt = s[i] = new_stmt(BPF_MISC|BPF_TXA);
+	s[i - 1]->s.jt = s[i] = new_stmt(cstate, BPF_MISC|BPF_TXA);
 	i++;
 	/* A += 1 */
-	s[i] = new_stmt(BPF_ALU|BPF_ADD|BPF_K);
+	s[i] = new_stmt(cstate, BPF_ALU|BPF_ADD|BPF_K);
 	s[i]->s.k = 1;
 	i++;
 	/* X = A */
-	s[i] = new_stmt(BPF_MISC|BPF_TAX);
+	s[i] = new_stmt(cstate, BPF_MISC|BPF_TAX);
 	i++;
 	/* A = P[X + packet head] */
-	s[i] = new_stmt(BPF_LD|BPF_IND|BPF_B);
-	s[i]->s.k = off_linkpl.constant_part + off_nl;
+	s[i] = new_stmt(cstate, BPF_LD|BPF_IND|BPF_B);
+	s[i]->s.k = cstate->off_linkpl.constant_part + cstate->off_nl;
 	i++;
 	/* A += 2 */
-	s[i] = new_stmt(BPF_ALU|BPF_ADD|BPF_K);
+	s[i] = new_stmt(cstate, BPF_ALU|BPF_ADD|BPF_K);
 	s[i]->s.k = 2;
 	i++;
 	/* A *= 4 */
-	s[i] = new_stmt(BPF_ALU|BPF_MUL|BPF_K);
+	s[i] = new_stmt(cstate, BPF_ALU|BPF_MUL|BPF_K);
 	s[i]->s.k = 4;
 	i++;
 	/* X = A; */
-	s[i] = new_stmt(BPF_MISC|BPF_TAX);
+	s[i] = new_stmt(cstate, BPF_MISC|BPF_TAX);
 	i++;
 	/* A = MEM[reg2] */
-	s[i] = new_stmt(BPF_LD|BPF_MEM);
+	s[i] = new_stmt(cstate, BPF_LD|BPF_MEM);
 	s[i]->s.k = reg2;
 	i++;
 
 	/* goto again; (must use BPF_JA for backward jump) */
-	s[i] = new_stmt(BPF_JMP|BPF_JA);
+	s[i] = new_stmt(cstate, BPF_JMP|BPF_JA);
 	s[i]->s.k = again - i - 1;
 	i++;
 
 	/* end: nop */
 	end = i;
-	s[i] = new_stmt(BPF_ALU|BPF_ADD|BPF_K);
+	s[i] = new_stmt(cstate, BPF_ALU|BPF_ADD|BPF_K);
 	s[i]->s.k = 0;
 	s[fix2]->s.jt = s[end];
 	s[fix4]->s.jf = s[end];
@@ -5827,11 +5931,11 @@
 	/*
 	 * emit final check
 	 */
-	b = new_block(JMP(BPF_JEQ));
+	b = new_block(cstate, JMP(BPF_JEQ));
 	b->stmts = s[1];	/*remember, s[0] is dummy*/
 	b->s.k = v;
 
-	free_reg(reg2);
+	free_reg(cstate, reg2);
 
 	gen_and(b0, b);
 	return b;
@@ -5839,7 +5943,7 @@
 }
 
 static struct block *
-gen_check_802_11_data_frame()
+gen_check_802_11_data_frame(compiler_state_t *cstate)
 {
 	struct slist *s;
 	struct block *b0, *b1;
@@ -5848,13 +5952,13 @@
 	 * A data frame has the 0x08 bit (b3) in the frame control field set
 	 * and the 0x04 bit (b2) clear.
 	 */
-	s = gen_load_a(OR_LINKHDR, 0, BPF_B);
-	b0 = new_block(JMP(BPF_JSET));
+	s = gen_load_a(cstate, OR_LINKHDR, 0, BPF_B);
+	b0 = new_block(cstate, JMP(BPF_JSET));
 	b0->s.k = 0x08;
 	b0->stmts = s;
 
-	s = gen_load_a(OR_LINKHDR, 0, BPF_B);
-	b1 = new_block(JMP(BPF_JSET));
+	s = gen_load_a(cstate, OR_LINKHDR, 0, BPF_B);
+	b1 = new_block(cstate, JMP(BPF_JSET));
 	b1->s.k = 0x04;
 	b1->stmts = s;
 	gen_not(b1);
@@ -5874,10 +5978,7 @@
  * against Q_IP and Q_IPV6.
  */
 static struct block *
-gen_proto(v, proto, dir)
-	int v;
-	int proto;
-	int dir;
+gen_proto(compiler_state_t *cstate, int v, int proto, int dir)
 {
 	struct block *b0, *b1;
 #ifndef CHASE_CHAIN
@@ -5885,12 +5986,12 @@
 #endif
 
 	if (dir != Q_DEFAULT)
-		bpf_error("direction applied to 'proto'");
+		bpf_error(cstate, "direction applied to 'proto'");
 
 	switch (proto) {
 	case Q_DEFAULT:
-		b0 = gen_proto(v, Q_IP, dir);
-		b1 = gen_proto(v, Q_IPV6, dir);
+		b0 = gen_proto(cstate, v, Q_IP, dir);
+		b1 = gen_proto(cstate, v, Q_IPV6, dir);
 		gen_or(b0, b1);
 		return b1;
 
@@ -5910,22 +6011,22 @@
 		 *
 		 * So we always check for ETHERTYPE_IP.
 		 */
-		b0 = gen_linktype(ETHERTYPE_IP);
+		b0 = gen_linktype(cstate, ETHERTYPE_IP);
 #ifndef CHASE_CHAIN
-		b1 = gen_cmp(OR_LINKPL, 9, BPF_B, (bpf_int32)v);
+		b1 = gen_cmp(cstate, OR_LINKPL, 9, BPF_B, (bpf_int32)v);
 #else
-		b1 = gen_protochain(v, Q_IP);
+		b1 = gen_protochain(cstate, v, Q_IP);
 #endif
 		gen_and(b0, b1);
 		return b1;
 
 	case Q_ISO:
-		switch (linktype) {
+		switch (cstate->linktype) {
 
 		case DLT_FRELAY:
 			/*
 			 * Frame Relay packets typically have an OSI
-			 * NLPID at the beginning; "gen_linktype(LLCSAP_ISONS)"
+			 * NLPID at the beginning; "gen_linktype(cstate, LLCSAP_ISONS)"
 			 * generates code to check for all the OSI
 			 * NLPIDs, so calling it and then adding a check
 			 * for the particular NLPID for which we're
@@ -5941,7 +6042,7 @@
 			 *
 			 * XXX - what about SNAP-encapsulated frames?
 			 */
-			return gen_cmp(OR_LINKHDR, 2, BPF_H, (0x03<<8) | v);
+			return gen_cmp(cstate, OR_LINKHDR, 2, BPF_H, (0x03<<8) | v);
 			/*NOTREACHED*/
 			break;
 
@@ -5950,138 +6051,138 @@
 			 * Cisco uses an Ethertype lookalike - for OSI,
 			 * it's 0xfefe.
 			 */
-			b0 = gen_linktype(LLCSAP_ISONS<<8 | LLCSAP_ISONS);
+			b0 = gen_linktype(cstate, LLCSAP_ISONS<<8 | LLCSAP_ISONS);
 			/* OSI in C-HDLC is stuffed with a fudge byte */
-			b1 = gen_cmp(OR_LINKPL_NOSNAP, 1, BPF_B, (long)v);
+			b1 = gen_cmp(cstate, OR_LINKPL_NOSNAP, 1, BPF_B, (long)v);
 			gen_and(b0, b1);
 			return b1;
 
 		default:
-			b0 = gen_linktype(LLCSAP_ISONS);
-			b1 = gen_cmp(OR_LINKPL_NOSNAP, 0, BPF_B, (long)v);
+			b0 = gen_linktype(cstate, LLCSAP_ISONS);
+			b1 = gen_cmp(cstate, OR_LINKPL_NOSNAP, 0, BPF_B, (long)v);
 			gen_and(b0, b1);
 			return b1;
 		}
 
 	case Q_ISIS:
-		b0 = gen_proto(ISO10589_ISIS, Q_ISO, Q_DEFAULT);
+		b0 = gen_proto(cstate, ISO10589_ISIS, Q_ISO, Q_DEFAULT);
 		/*
 		 * 4 is the offset of the PDU type relative to the IS-IS
 		 * header.
 		 */
-		b1 = gen_cmp(OR_LINKPL_NOSNAP, 4, BPF_B, (long)v);
+		b1 = gen_cmp(cstate, OR_LINKPL_NOSNAP, 4, BPF_B, (long)v);
 		gen_and(b0, b1);
 		return b1;
 
 	case Q_ARP:
-		bpf_error("arp does not encapsulate another protocol");
+		bpf_error(cstate, "arp does not encapsulate another protocol");
 		/* NOTREACHED */
 
 	case Q_RARP:
-		bpf_error("rarp does not encapsulate another protocol");
+		bpf_error(cstate, "rarp does not encapsulate another protocol");
 		/* NOTREACHED */
 
 	case Q_ATALK:
-		bpf_error("atalk encapsulation is not specifiable");
+		bpf_error(cstate, "atalk encapsulation is not specifiable");
 		/* NOTREACHED */
 
 	case Q_DECNET:
-		bpf_error("decnet encapsulation is not specifiable");
+		bpf_error(cstate, "decnet encapsulation is not specifiable");
 		/* NOTREACHED */
 
 	case Q_SCA:
-		bpf_error("sca does not encapsulate another protocol");
+		bpf_error(cstate, "sca does not encapsulate another protocol");
 		/* NOTREACHED */
 
 	case Q_LAT:
-		bpf_error("lat does not encapsulate another protocol");
+		bpf_error(cstate, "lat does not encapsulate another protocol");
 		/* NOTREACHED */
 
 	case Q_MOPRC:
-		bpf_error("moprc does not encapsulate another protocol");
+		bpf_error(cstate, "moprc does not encapsulate another protocol");
 		/* NOTREACHED */
 
 	case Q_MOPDL:
-		bpf_error("mopdl does not encapsulate another protocol");
+		bpf_error(cstate, "mopdl does not encapsulate another protocol");
 		/* NOTREACHED */
 
 	case Q_LINK:
-		return gen_linktype(v);
+		return gen_linktype(cstate, v);
 
 	case Q_UDP:
-		bpf_error("'udp proto' is bogus");
+		bpf_error(cstate, "'udp proto' is bogus");
 		/* NOTREACHED */
 
 	case Q_TCP:
-		bpf_error("'tcp proto' is bogus");
+		bpf_error(cstate, "'tcp proto' is bogus");
 		/* NOTREACHED */
 
 	case Q_SCTP:
-		bpf_error("'sctp proto' is bogus");
+		bpf_error(cstate, "'sctp proto' is bogus");
 		/* NOTREACHED */
 
 	case Q_ICMP:
-		bpf_error("'icmp proto' is bogus");
+		bpf_error(cstate, "'icmp proto' is bogus");
 		/* NOTREACHED */
 
 	case Q_IGMP:
-		bpf_error("'igmp proto' is bogus");
+		bpf_error(cstate, "'igmp proto' is bogus");
 		/* NOTREACHED */
 
 	case Q_IGRP:
-		bpf_error("'igrp proto' is bogus");
+		bpf_error(cstate, "'igrp proto' is bogus");
 		/* NOTREACHED */
 
 	case Q_PIM:
-		bpf_error("'pim proto' is bogus");
+		bpf_error(cstate, "'pim proto' is bogus");
 		/* NOTREACHED */
 
 	case Q_VRRP:
-		bpf_error("'vrrp proto' is bogus");
+		bpf_error(cstate, "'vrrp proto' is bogus");
 		/* NOTREACHED */
 
 	case Q_CARP:
-		bpf_error("'carp proto' is bogus");
+		bpf_error(cstate, "'carp proto' is bogus");
 		/* NOTREACHED */
 
 	case Q_IPV6:
-		b0 = gen_linktype(ETHERTYPE_IPV6);
+		b0 = gen_linktype(cstate, ETHERTYPE_IPV6);
 #ifndef CHASE_CHAIN
 		/*
 		 * Also check for a fragment header before the final
 		 * header.
 		 */
-		b2 = gen_cmp(OR_LINKPL, 6, BPF_B, IPPROTO_FRAGMENT);
-		b1 = gen_cmp(OR_LINKPL, 40, BPF_B, (bpf_int32)v);
+		b2 = gen_cmp(cstate, OR_LINKPL, 6, BPF_B, IPPROTO_FRAGMENT);
+		b1 = gen_cmp(cstate, OR_LINKPL, 40, BPF_B, (bpf_int32)v);
 		gen_and(b2, b1);
-		b2 = gen_cmp(OR_LINKPL, 6, BPF_B, (bpf_int32)v);
+		b2 = gen_cmp(cstate, OR_LINKPL, 6, BPF_B, (bpf_int32)v);
 		gen_or(b2, b1);
 #else
-		b1 = gen_protochain(v, Q_IPV6);
+		b1 = gen_protochain(cstate, v, Q_IPV6);
 #endif
 		gen_and(b0, b1);
 		return b1;
 
 	case Q_ICMPV6:
-		bpf_error("'icmp6 proto' is bogus");
+		bpf_error(cstate, "'icmp6 proto' is bogus");
 
 	case Q_AH:
-		bpf_error("'ah proto' is bogus");
+		bpf_error(cstate, "'ah proto' is bogus");
 
 	case Q_ESP:
-		bpf_error("'ah proto' is bogus");
+		bpf_error(cstate, "'ah proto' is bogus");
 
 	case Q_STP:
-		bpf_error("'stp proto' is bogus");
+		bpf_error(cstate, "'stp proto' is bogus");
 
 	case Q_IPX:
-		bpf_error("'ipx proto' is bogus");
+		bpf_error(cstate, "'ipx proto' is bogus");
 
 	case Q_NETBEUI:
-		bpf_error("'netbeui proto' is bogus");
+		bpf_error(cstate, "'netbeui proto' is bogus");
 
 	case Q_RADIO:
-		bpf_error("'radio proto' is bogus");
+		bpf_error(cstate, "'radio proto' is bogus");
 
 	default:
 		abort();
@@ -6091,9 +6192,7 @@
 }
 
 struct block *
-gen_scode(name, q)
-	register const char *name;
-	struct qual q;
+gen_scode(compiler_state_t *cstate, const char *name, struct qual q)
 {
 	int proto = q.proto;
 	int dir = q.dir;
@@ -6118,29 +6217,29 @@
 	case Q_NET:
 		addr = pcap_nametonetaddr(name);
 		if (addr == 0)
-			bpf_error("unknown network '%s'", name);
+			bpf_error(cstate, "unknown network '%s'", name);
 		/* Left justify network addr and calculate its network mask */
 		mask = 0xffffffff;
 		while (addr && (addr & 0xff000000) == 0) {
 			addr <<= 8;
 			mask <<= 8;
 		}
-		return gen_host(addr, mask, proto, dir, q.addr);
+		return gen_host(cstate, addr, mask, proto, dir, q.addr);
 
 	case Q_DEFAULT:
 	case Q_HOST:
 		if (proto == Q_LINK) {
-			switch (linktype) {
+			switch (cstate->linktype) {
 
 			case DLT_EN10MB:
 			case DLT_NETANALYZER:
 			case DLT_NETANALYZER_TRANSPARENT:
 				eaddr = pcap_ether_hostton(name);
 				if (eaddr == NULL)
-					bpf_error(
+					bpf_error(cstate,
 					    "unknown ether host '%s'", name);
-				tmp = gen_prevlinkhdr_check();
-				b = gen_ehostop(eaddr, dir);
+				tmp = gen_prevlinkhdr_check(cstate);
+				b = gen_ehostop(cstate, eaddr, dir);
 				if (tmp != NULL)
 					gen_and(tmp, b);
 				free(eaddr);
@@ -6149,18 +6248,18 @@
 			case DLT_FDDI:
 				eaddr = pcap_ether_hostton(name);
 				if (eaddr == NULL)
-					bpf_error(
+					bpf_error(cstate,
 					    "unknown FDDI host '%s'", name);
-				b = gen_fhostop(eaddr, dir);
+				b = gen_fhostop(cstate, eaddr, dir);
 				free(eaddr);
 				return b;
 
 			case DLT_IEEE802:
 				eaddr = pcap_ether_hostton(name);
 				if (eaddr == NULL)
-					bpf_error(
+					bpf_error(cstate,
 					    "unknown token ring host '%s'", name);
-				b = gen_thostop(eaddr, dir);
+				b = gen_thostop(cstate, eaddr, dir);
 				free(eaddr);
 				return b;
 
@@ -6171,42 +6270,51 @@
 			case DLT_PPI:
 				eaddr = pcap_ether_hostton(name);
 				if (eaddr == NULL)
-					bpf_error(
+					bpf_error(cstate,
 					    "unknown 802.11 host '%s'", name);
-				b = gen_wlanhostop(eaddr, dir);
+				b = gen_wlanhostop(cstate, eaddr, dir);
 				free(eaddr);
 				return b;
 
 			case DLT_IP_OVER_FC:
 				eaddr = pcap_ether_hostton(name);
 				if (eaddr == NULL)
-					bpf_error(
+					bpf_error(cstate,
 					    "unknown Fibre Channel host '%s'", name);
-				b = gen_ipfchostop(eaddr, dir);
+				b = gen_ipfchostop(cstate, eaddr, dir);
 				free(eaddr);
 				return b;
 			}
 
-			bpf_error("only ethernet/FDDI/token ring/802.11/ATM LANE/Fibre Channel supports link-level host name");
+			bpf_error(cstate, "only ethernet/FDDI/token ring/802.11/ATM LANE/Fibre Channel supports link-level host name");
 		} else if (proto == Q_DECNET) {
-			unsigned short dn_addr = __pcap_nametodnaddr(name);
+			unsigned short dn_addr;
+
+			if (!__pcap_nametodnaddr(name, &dn_addr)) {
+#ifdef	DECNETLIB
+				bpf_error(cstate, "unknown decnet host name '%s'\n", name);
+#else
+				bpf_error(cstate, "decnet name support not included, '%s' cannot be translated\n",
+					name);
+#endif
+			}
 			/*
 			 * I don't think DECNET hosts can be multihomed, so
 			 * there is no need to build up a list of addresses
 			 */
-			return (gen_host(dn_addr, 0, proto, dir, q.addr));
+			return (gen_host(cstate, dn_addr, 0, proto, dir, q.addr));
 		} else {
 #ifndef INET6
 			alist = pcap_nametoaddr(name);
 			if (alist == NULL || *alist == NULL)
-				bpf_error("unknown host '%s'", name);
+				bpf_error(cstate, "unknown host '%s'", name);
 			tproto = proto;
-			if (off_linktype.constant_part == (u_int)-1 &&
+			if (cstate->off_linktype.constant_part == OFFSET_NOT_SET &&
 			    tproto == Q_DEFAULT)
 				tproto = Q_IP;
-			b = gen_host(**alist++, 0xffffffff, tproto, dir, q.addr);
+			b = gen_host(cstate, **alist++, 0xffffffff, tproto, dir, q.addr);
 			while (*alist) {
-				tmp = gen_host(**alist++, 0xffffffff,
+				tmp = gen_host(cstate, **alist++, 0xffffffff,
 					       tproto, dir, q.addr);
 				gen_or(b, tmp);
 				b = tmp;
@@ -6216,11 +6324,11 @@
 			memset(&mask128, 0xff, sizeof(mask128));
 			res0 = res = pcap_nametoaddrinfo(name);
 			if (res == NULL)
-				bpf_error("unknown host '%s'", name);
-			ai = res;
+				bpf_error(cstate, "unknown host '%s'", name);
+			cstate->ai = res;
 			b = tmp = NULL;
 			tproto = tproto6 = proto;
-			if (off_linktype.constant_part == -1 &&
+			if (cstate->off_linktype.constant_part == OFFSET_NOT_SET &&
 			    tproto == Q_DEFAULT) {
 				tproto = Q_IP;
 				tproto6 = Q_IPV6;
@@ -6233,7 +6341,7 @@
 
 					sin4 = (struct sockaddr_in *)
 						res->ai_addr;
-					tmp = gen_host(ntohl(sin4->sin_addr.s_addr),
+					tmp = gen_host(cstate, ntohl(sin4->sin_addr.s_addr),
 						0xffffffff, tproto, dir, q.addr);
 					break;
 				case AF_INET6:
@@ -6242,7 +6350,7 @@
 
 					sin6 = (struct sockaddr_in6 *)
 						res->ai_addr;
-					tmp = gen_host6(&sin6->sin6_addr,
+					tmp = gen_host6(cstate, &sin6->sin6_addr,
 						&mask128, tproto6, dir, q.addr);
 					break;
 				default:
@@ -6252,10 +6360,10 @@
 					gen_or(b, tmp);
 				b = tmp;
 			}
-			ai = NULL;
+			cstate->ai = NULL;
 			freeaddrinfo(res0);
 			if (b == NULL) {
-				bpf_error("unknown host '%s'%s", name,
+				bpf_error(cstate, "unknown host '%s'%s", name,
 				    (proto == Q_DEFAULT)
 					? ""
 					: " for specified address family");
@@ -6267,124 +6375,124 @@
 	case Q_PORT:
 		if (proto != Q_DEFAULT &&
 		    proto != Q_UDP && proto != Q_TCP && proto != Q_SCTP)
-			bpf_error("illegal qualifier of 'port'");
+			bpf_error(cstate, "illegal qualifier of 'port'");
 		if (pcap_nametoport(name, &port, &real_proto) == 0)
-			bpf_error("unknown port '%s'", name);
+			bpf_error(cstate, "unknown port '%s'", name);
 		if (proto == Q_UDP) {
 			if (real_proto == IPPROTO_TCP)
-				bpf_error("port '%s' is tcp", name);
+				bpf_error(cstate, "port '%s' is tcp", name);
 			else if (real_proto == IPPROTO_SCTP)
-				bpf_error("port '%s' is sctp", name);
+				bpf_error(cstate, "port '%s' is sctp", name);
 			else
 				/* override PROTO_UNDEF */
 				real_proto = IPPROTO_UDP;
 		}
 		if (proto == Q_TCP) {
 			if (real_proto == IPPROTO_UDP)
-				bpf_error("port '%s' is udp", name);
+				bpf_error(cstate, "port '%s' is udp", name);
 
 			else if (real_proto == IPPROTO_SCTP)
-				bpf_error("port '%s' is sctp", name);
+				bpf_error(cstate, "port '%s' is sctp", name);
 			else
 				/* override PROTO_UNDEF */
 				real_proto = IPPROTO_TCP;
 		}
 		if (proto == Q_SCTP) {
 			if (real_proto == IPPROTO_UDP)
-				bpf_error("port '%s' is udp", name);
+				bpf_error(cstate, "port '%s' is udp", name);
 
 			else if (real_proto == IPPROTO_TCP)
-				bpf_error("port '%s' is tcp", name);
+				bpf_error(cstate, "port '%s' is tcp", name);
 			else
 				/* override PROTO_UNDEF */
 				real_proto = IPPROTO_SCTP;
 		}
 		if (port < 0)
-			bpf_error("illegal port number %d < 0", port);
+			bpf_error(cstate, "illegal port number %d < 0", port);
 		if (port > 65535)
-			bpf_error("illegal port number %d > 65535", port);
-		b = gen_port(port, real_proto, dir);
-		gen_or(gen_port6(port, real_proto, dir), b);
+			bpf_error(cstate, "illegal port number %d > 65535", port);
+		b = gen_port(cstate, port, real_proto, dir);
+		gen_or(gen_port6(cstate, port, real_proto, dir), b);
 		return b;
 
 	case Q_PORTRANGE:
 		if (proto != Q_DEFAULT &&
 		    proto != Q_UDP && proto != Q_TCP && proto != Q_SCTP)
-			bpf_error("illegal qualifier of 'portrange'");
+			bpf_error(cstate, "illegal qualifier of 'portrange'");
 		if (pcap_nametoportrange(name, &port1, &port2, &real_proto) == 0)
-			bpf_error("unknown port in range '%s'", name);
+			bpf_error(cstate, "unknown port in range '%s'", name);
 		if (proto == Q_UDP) {
 			if (real_proto == IPPROTO_TCP)
-				bpf_error("port in range '%s' is tcp", name);
+				bpf_error(cstate, "port in range '%s' is tcp", name);
 			else if (real_proto == IPPROTO_SCTP)
-				bpf_error("port in range '%s' is sctp", name);
+				bpf_error(cstate, "port in range '%s' is sctp", name);
 			else
 				/* override PROTO_UNDEF */
 				real_proto = IPPROTO_UDP;
 		}
 		if (proto == Q_TCP) {
 			if (real_proto == IPPROTO_UDP)
-				bpf_error("port in range '%s' is udp", name);
+				bpf_error(cstate, "port in range '%s' is udp", name);
 			else if (real_proto == IPPROTO_SCTP)
-				bpf_error("port in range '%s' is sctp", name);
+				bpf_error(cstate, "port in range '%s' is sctp", name);
 			else
 				/* override PROTO_UNDEF */
 				real_proto = IPPROTO_TCP;
 		}
 		if (proto == Q_SCTP) {
 			if (real_proto == IPPROTO_UDP)
-				bpf_error("port in range '%s' is udp", name);
+				bpf_error(cstate, "port in range '%s' is udp", name);
 			else if (real_proto == IPPROTO_TCP)
-				bpf_error("port in range '%s' is tcp", name);
+				bpf_error(cstate, "port in range '%s' is tcp", name);
 			else
 				/* override PROTO_UNDEF */
 				real_proto = IPPROTO_SCTP;
 		}
 		if (port1 < 0)
-			bpf_error("illegal port number %d < 0", port1);
+			bpf_error(cstate, "illegal port number %d < 0", port1);
 		if (port1 > 65535)
-			bpf_error("illegal port number %d > 65535", port1);
+			bpf_error(cstate, "illegal port number %d > 65535", port1);
 		if (port2 < 0)
-			bpf_error("illegal port number %d < 0", port2);
+			bpf_error(cstate, "illegal port number %d < 0", port2);
 		if (port2 > 65535)
-			bpf_error("illegal port number %d > 65535", port2);
+			bpf_error(cstate, "illegal port number %d > 65535", port2);
 
-		b = gen_portrange(port1, port2, real_proto, dir);
-		gen_or(gen_portrange6(port1, port2, real_proto, dir), b);
+		b = gen_portrange(cstate, port1, port2, real_proto, dir);
+		gen_or(gen_portrange6(cstate, port1, port2, real_proto, dir), b);
 		return b;
 
 	case Q_GATEWAY:
 #ifndef INET6
 		eaddr = pcap_ether_hostton(name);
 		if (eaddr == NULL)
-			bpf_error("unknown ether host: %s", name);
+			bpf_error(cstate, "unknown ether host: %s", name);
 
 		alist = pcap_nametoaddr(name);
 		if (alist == NULL || *alist == NULL)
-			bpf_error("unknown host '%s'", name);
+			bpf_error(cstate, "unknown host '%s'", name);
 		b = gen_gateway(eaddr, alist, proto, dir);
 		free(eaddr);
 		return b;
 #else
-		bpf_error("'gateway' not supported in this configuration");
+		bpf_error(cstate, "'gateway' not supported in this configuration");
 #endif /*INET6*/
 
 	case Q_PROTO:
-		real_proto = lookup_proto(name, proto);
+		real_proto = lookup_proto(cstate, name, proto);
 		if (real_proto >= 0)
-			return gen_proto(real_proto, proto, dir);
+			return gen_proto(cstate, real_proto, proto, dir);
 		else
-			bpf_error("unknown protocol: %s", name);
+			bpf_error(cstate, "unknown protocol: %s", name);
 
 	case Q_PROTOCHAIN:
-		real_proto = lookup_proto(name, proto);
+		real_proto = lookup_proto(cstate, name, proto);
 		if (real_proto >= 0)
-			return gen_protochain(real_proto, proto, dir);
+			return gen_protochain(cstate, real_proto, proto, dir);
 		else
-			bpf_error("unknown protocol: %s", name);
+			bpf_error(cstate, "unknown protocol: %s", name);
 
 	case Q_UNDEF:
-		syntax();
+		syntax(cstate);
 		/* NOTREACHED */
 	}
 	abort();
@@ -6392,10 +6500,8 @@
 }
 
 struct block *
-gen_mcode(s1, s2, masklen, q)
-	register const char *s1, *s2;
-	register unsigned int masklen;
-	struct qual q;
+gen_mcode(compiler_state_t *cstate, const char *s1, const char *s2,
+    unsigned int masklen, struct qual q)
 {
 	register int nlen, mlen;
 	bpf_u_int32 n, m;
@@ -6409,12 +6515,12 @@
 		/* Promote short ipaddr */
 		m <<= 32 - mlen;
 		if ((n & ~m) != 0)
-			bpf_error("non-network bits set in \"%s mask %s\"",
+			bpf_error(cstate, "non-network bits set in \"%s mask %s\"",
 			    s1, s2);
 	} else {
 		/* Convert mask len to mask */
 		if (masklen > 32)
-			bpf_error("mask length must be <= 32");
+			bpf_error(cstate, "mask length must be <= 32");
 		if (masklen == 0) {
 			/*
 			 * X << 32 is not guaranteed by C to be 0; it's
@@ -6424,17 +6530,17 @@
 		} else
 			m = 0xffffffff << (32 - masklen);
 		if ((n & ~m) != 0)
-			bpf_error("non-network bits set in \"%s/%d\"",
+			bpf_error(cstate, "non-network bits set in \"%s/%d\"",
 			    s1, masklen);
 	}
 
 	switch (q.addr) {
 
 	case Q_NET:
-		return gen_host(n, m, q.proto, q.dir, q.addr);
+		return gen_host(cstate, n, m, q.proto, q.dir, q.addr);
 
 	default:
-		bpf_error("Mask syntax for networks only");
+		bpf_error(cstate, "Mask syntax for networks only");
 		/* NOTREACHED */
 	}
 	/* NOTREACHED */
@@ -6442,10 +6548,7 @@
 }
 
 struct block *
-gen_ncode(s, v, q)
-	register const char *s;
-	bpf_u_int32 v;
-	struct qual q;
+gen_ncode(compiler_state_t *cstate, const char *s, bpf_u_int32 v, struct qual q)
 {
 	bpf_u_int32 mask;
 	int proto = q.proto;
@@ -6454,9 +6557,11 @@
 
 	if (s == NULL)
 		vlen = 32;
-	else if (q.proto == Q_DECNET)
+	else if (q.proto == Q_DECNET) {
 		vlen = __pcap_atodn(s, &v);
-	else
+		if (vlen == 0)
+			bpf_error(cstate, "malformed decnet address '%s'", s);
+	} else
 		vlen = __pcap_atoin(s, &v);
 
 	switch (q.addr) {
@@ -6465,9 +6570,9 @@
 	case Q_HOST:
 	case Q_NET:
 		if (proto == Q_DECNET)
-			return gen_host(v, 0, proto, dir, q.addr);
+			return gen_host(cstate, v, 0, proto, dir, q.addr);
 		else if (proto == Q_LINK) {
-			bpf_error("illegal link layer address");
+			bpf_error(cstate, "illegal link layer address");
 		} else {
 			mask = 0xffffffff;
 			if (s == NULL && q.addr == Q_NET) {
@@ -6479,9 +6584,9 @@
 			} else {
 				/* Promote short ipaddr */
 				v <<= 32 - vlen;
-				mask <<= 32 - vlen;
+				mask <<= 32 - vlen ;
 			}
-			return gen_host(v, mask, proto, dir, q.addr);
+			return gen_host(cstate, v, mask, proto, dir, q.addr);
 		}
 
 	case Q_PORT:
@@ -6494,15 +6599,15 @@
 		else if (proto == Q_DEFAULT)
 			proto = PROTO_UNDEF;
 		else
-			bpf_error("illegal qualifier of 'port'");
+			bpf_error(cstate, "illegal qualifier of 'port'");
 
 		if (v > 65535)
-			bpf_error("illegal port number %u > 65535", v);
+			bpf_error(cstate, "illegal port number %u > 65535", v);
 
 	    {
 		struct block *b;
-		b = gen_port((int)v, proto, dir);
-		gen_or(gen_port6((int)v, proto, dir), b);
+		b = gen_port(cstate, (int)v, proto, dir);
+		gen_or(gen_port6(cstate, (int)v, proto, dir), b);
 		return b;
 	    }
 
@@ -6516,30 +6621,30 @@
 		else if (proto == Q_DEFAULT)
 			proto = PROTO_UNDEF;
 		else
-			bpf_error("illegal qualifier of 'portrange'");
+			bpf_error(cstate, "illegal qualifier of 'portrange'");
 
 		if (v > 65535)
-			bpf_error("illegal port number %u > 65535", v);
+			bpf_error(cstate, "illegal port number %u > 65535", v);
 
 	    {
 		struct block *b;
-		b = gen_portrange((int)v, (int)v, proto, dir);
-		gen_or(gen_portrange6((int)v, (int)v, proto, dir), b);
+		b = gen_portrange(cstate, (int)v, (int)v, proto, dir);
+		gen_or(gen_portrange6(cstate, (int)v, (int)v, proto, dir), b);
 		return b;
 	    }
 
 	case Q_GATEWAY:
-		bpf_error("'gateway' requires a name");
+		bpf_error(cstate, "'gateway' requires a name");
 		/* NOTREACHED */
 
 	case Q_PROTO:
-		return gen_proto((int)v, proto, dir);
+		return gen_proto(cstate, (int)v, proto, dir);
 
 	case Q_PROTOCHAIN:
-		return gen_protochain((int)v, proto, dir);
+		return gen_protochain(cstate, (int)v, proto, dir);
 
 	case Q_UNDEF:
-		syntax();
+		syntax(cstate);
 		/* NOTREACHED */
 
 	default:
@@ -6551,10 +6656,8 @@
 
 #ifdef INET6
 struct block *
-gen_mcode6(s1, s2, masklen, q)
-	register const char *s1, *s2;
-	register unsigned int masklen;
-	struct qual q;
+gen_mcode6(compiler_state_t *cstate, const char *s1, const char *s2,
+    unsigned int masklen, struct qual q)
 {
 	struct addrinfo *res;
 	struct in6_addr *addr;
@@ -6563,18 +6666,18 @@
 	u_int32_t *a, *m;
 
 	if (s2)
-		bpf_error("no mask %s supported", s2);
+		bpf_error(cstate, "no mask %s supported", s2);
 
 	res = pcap_nametoaddrinfo(s1);
 	if (!res)
-		bpf_error("invalid ip6 address %s", s1);
-	ai = res;
+		bpf_error(cstate, "invalid ip6 address %s", s1);
+	cstate->ai = res;
 	if (res->ai_next)
-		bpf_error("%s resolved to multiple address", s1);
+		bpf_error(cstate, "%s resolved to multiple address", s1);
 	addr = &((struct sockaddr_in6 *)res->ai_addr)->sin6_addr;
 
 	if (sizeof(mask) * 8 < masklen)
-		bpf_error("mask length must be <= %u", (unsigned int)(sizeof(mask) * 8));
+		bpf_error(cstate, "mask length must be <= %u", (unsigned int)(sizeof(mask) * 8));
 	memset(&mask, 0, sizeof(mask));
 	memset(&mask, 0xff, masklen / 8);
 	if (masklen % 8) {
@@ -6586,7 +6689,7 @@
 	m = (u_int32_t *)&mask;
 	if ((a[0] & ~m[0]) || (a[1] & ~m[1])
 	 || (a[2] & ~m[2]) || (a[3] & ~m[3])) {
-		bpf_error("non-network bits set in \"%s/%d\"", s1, masklen);
+		bpf_error(cstate, "non-network bits set in \"%s/%d\"", s1, masklen);
 	}
 
 	switch (q.addr) {
@@ -6594,17 +6697,17 @@
 	case Q_DEFAULT:
 	case Q_HOST:
 		if (masklen != 128)
-			bpf_error("Mask syntax for networks only");
+			bpf_error(cstate, "Mask syntax for networks only");
 		/* FALLTHROUGH */
 
 	case Q_NET:
-		b = gen_host6(addr, &mask, q.proto, q.dir, q.addr);
-		ai = NULL;
+		b = gen_host6(cstate, addr, &mask, q.proto, q.dir, q.addr);
+		cstate->ai = NULL;
 		freeaddrinfo(res);
 		return b;
 
 	default:
-		bpf_error("invalid qualifier against IPv6 address");
+		bpf_error(cstate, "invalid qualifier against IPv6 address");
 		/* NOTREACHED */
 	}
 	return NULL;
@@ -6612,40 +6715,38 @@
 #endif /*INET6*/
 
 struct block *
-gen_ecode(eaddr, q)
-	register const u_char *eaddr;
-	struct qual q;
+gen_ecode(compiler_state_t *cstate, const u_char *eaddr, struct qual q)
 {
 	struct block *b, *tmp;
 
 	if ((q.addr == Q_HOST || q.addr == Q_DEFAULT) && q.proto == Q_LINK) {
-		switch (linktype) {
+		switch (cstate->linktype) {
 		case DLT_EN10MB:
 		case DLT_NETANALYZER:
 		case DLT_NETANALYZER_TRANSPARENT:
-			tmp = gen_prevlinkhdr_check();
-			b = gen_ehostop(eaddr, (int)q.dir);
+			tmp = gen_prevlinkhdr_check(cstate);
+			b = gen_ehostop(cstate, eaddr, (int)q.dir);
 			if (tmp != NULL)
 				gen_and(tmp, b);
 			return b;
 		case DLT_FDDI:
-			return gen_fhostop(eaddr, (int)q.dir);
+			return gen_fhostop(cstate, eaddr, (int)q.dir);
 		case DLT_IEEE802:
-			return gen_thostop(eaddr, (int)q.dir);
+			return gen_thostop(cstate, eaddr, (int)q.dir);
 		case DLT_IEEE802_11:
 		case DLT_PRISM_HEADER:
 		case DLT_IEEE802_11_RADIO_AVS:
 		case DLT_IEEE802_11_RADIO:
 		case DLT_PPI:
-			return gen_wlanhostop(eaddr, (int)q.dir);
+			return gen_wlanhostop(cstate, eaddr, (int)q.dir);
 		case DLT_IP_OVER_FC:
-			return gen_ipfchostop(eaddr, (int)q.dir);
+			return gen_ipfchostop(cstate, eaddr, (int)q.dir);
 		default:
-			bpf_error("ethernet addresses supported only on ethernet/FDDI/token ring/802.11/ATM LANE/Fibre Channel");
+			bpf_error(cstate, "ethernet addresses supported only on ethernet/FDDI/token ring/802.11/ATM LANE/Fibre Channel");
 			break;
 		}
 	}
-	bpf_error("ethernet address used in non-ether expression");
+	bpf_error(cstate, "ethernet address used in non-ether expression");
 	/* NOTREACHED */
 	return NULL;
 }
@@ -6664,23 +6765,21 @@
 }
 
 static struct slist *
-xfer_to_x(a)
-	struct arth *a;
+xfer_to_x(compiler_state_t *cstate, struct arth *a)
 {
 	struct slist *s;
 
-	s = new_stmt(BPF_LDX|BPF_MEM);
+	s = new_stmt(cstate, BPF_LDX|BPF_MEM);
 	s->s.k = a->regno;
 	return s;
 }
 
 static struct slist *
-xfer_to_a(a)
-	struct arth *a;
+xfer_to_a(compiler_state_t *cstate, struct arth *a)
 {
 	struct slist *s;
 
-	s = new_stmt(BPF_LD|BPF_MEM);
+	s = new_stmt(cstate, BPF_LD|BPF_MEM);
 	s->s.k = a->regno;
 	return s;
 }
@@ -6693,20 +6792,17 @@
  * for "index".
  */
 struct arth *
-gen_load(proto, inst, size)
-	int proto;
-	struct arth *inst;
-	int size;
+gen_load(compiler_state_t *cstate, int proto, struct arth *inst, int size)
 {
 	struct slist *s, *tmp;
 	struct block *b;
-	int regno = alloc_reg();
+	int regno = alloc_reg(cstate);
 
-	free_reg(inst->regno);
+	free_reg(cstate, inst->regno);
 	switch (size) {
 
 	default:
-		bpf_error("data size must be 1, 2, or 4");
+		bpf_error(cstate, "data size must be 1, 2, or 4");
 
 	case 1:
 		size = BPF_B;
@@ -6722,7 +6818,7 @@
 	}
 	switch (proto) {
 	default:
-		bpf_error("unsupported index operation");
+		bpf_error(cstate, "unsupported index operation");
 
 	case Q_RADIO:
 		/*
@@ -6730,21 +6826,21 @@
 		 * data, if we have a radio header.  (If we don't, this
 		 * is an error.)
 		 */
-		if (linktype != DLT_IEEE802_11_RADIO_AVS &&
-		    linktype != DLT_IEEE802_11_RADIO &&
-		    linktype != DLT_PRISM_HEADER)
-			bpf_error("radio information not present in capture");
+		if (cstate->linktype != DLT_IEEE802_11_RADIO_AVS &&
+		    cstate->linktype != DLT_IEEE802_11_RADIO &&
+		    cstate->linktype != DLT_PRISM_HEADER)
+			bpf_error(cstate, "radio information not present in capture");
 
 		/*
 		 * Load into the X register the offset computed into the
 		 * register specified by "index".
 		 */
-		s = xfer_to_x(inst);
+		s = xfer_to_x(cstate, inst);
 
 		/*
 		 * Load the item at that offset.
 		 */
-		tmp = new_stmt(BPF_LD|BPF_IND|size);
+		tmp = new_stmt(cstate, BPF_LD|BPF_IND|size);
 		sappend(s, tmp);
 		sappend(inst->s, s);
 		break;
@@ -6761,7 +6857,7 @@
 		 * frame, so that 0 refers, for Ethernet LANE, to
 		 * the beginning of the destination address?
 		 */
-		s = gen_abs_offset_varpart(&off_linkhdr);
+		s = gen_abs_offset_varpart(cstate, &cstate->off_linkhdr);
 
 		/*
 		 * If "s" is non-null, it has code to arrange that the
@@ -6773,11 +6869,11 @@
 		 * by "index".
 		 */
 		if (s != NULL) {
-			sappend(s, xfer_to_a(inst));
-			sappend(s, new_stmt(BPF_ALU|BPF_ADD|BPF_X));
-			sappend(s, new_stmt(BPF_MISC|BPF_TAX));
+			sappend(s, xfer_to_a(cstate, inst));
+			sappend(s, new_stmt(cstate, BPF_ALU|BPF_ADD|BPF_X));
+			sappend(s, new_stmt(cstate, BPF_MISC|BPF_TAX));
 		} else
-			s = xfer_to_x(inst);
+			s = xfer_to_x(cstate, inst);
 
 		/*
 		 * Load the item at the sum of the offset we've put in the
@@ -6786,8 +6882,8 @@
 		 * variable-length; that header length is what we put
 		 * into the X register and then added to the index).
 		 */
-		tmp = new_stmt(BPF_LD|BPF_IND|size);
-		tmp->s.k = off_linkhdr.constant_part;
+		tmp = new_stmt(cstate, BPF_LD|BPF_IND|size);
+		tmp->s.k = cstate->off_linkhdr.constant_part;
 		sappend(s, tmp);
 		sappend(inst->s, s);
 		break;
@@ -6806,9 +6902,9 @@
 		 * The offset is relative to the beginning of
 		 * the network-layer header.
 		 * XXX - are there any cases where we want
-		 * off_nl_nosnap?
+		 * cstate->off_nl_nosnap?
 		 */
-		s = gen_abs_offset_varpart(&off_linkpl);
+		s = gen_abs_offset_varpart(cstate, &cstate->off_linkpl);
 
 		/*
 		 * If "s" is non-null, it has code to arrange that the
@@ -6820,11 +6916,11 @@
 		 * the register specified by "index".
 		 */
 		if (s != NULL) {
-			sappend(s, xfer_to_a(inst));
-			sappend(s, new_stmt(BPF_ALU|BPF_ADD|BPF_X));
-			sappend(s, new_stmt(BPF_MISC|BPF_TAX));
+			sappend(s, xfer_to_a(cstate, inst));
+			sappend(s, new_stmt(cstate, BPF_ALU|BPF_ADD|BPF_X));
+			sappend(s, new_stmt(cstate, BPF_MISC|BPF_TAX));
 		} else
-			s = xfer_to_x(inst);
+			s = xfer_to_x(cstate, inst);
 
 		/*
 		 * Load the item at the sum of the offset we've put in the
@@ -6833,8 +6929,8 @@
 		 * payload, and the constant part of the offset of the
 		 * start of the link-layer payload.
 		 */
-		tmp = new_stmt(BPF_LD|BPF_IND|size);
-		tmp->s.k = off_linkpl.constant_part + off_nl;
+		tmp = new_stmt(cstate, BPF_LD|BPF_IND|size);
+		tmp->s.k = cstate->off_linkpl.constant_part + cstate->off_nl;
 		sappend(s, tmp);
 		sappend(inst->s, s);
 
@@ -6842,7 +6938,7 @@
 		 * Do the computation only if the packet contains
 		 * the protocol in question.
 		 */
-		b = gen_proto_abbrev(proto);
+		b = gen_proto_abbrev(cstate, proto);
 		if (inst->b)
 			gen_and(inst->b, b);
 		inst->b = b;
@@ -6866,12 +6962,12 @@
 		 * a variable-length header), in bytes.
 		 *
 		 * XXX - are there any cases where we want
-		 * off_nl_nosnap?
+		 * cstate->off_nl_nosnap?
 		 * XXX - we should, if we're built with
 		 * IPv6 support, generate code to load either
 		 * IPv4, IPv6, or both, as appropriate.
 		 */
-		s = gen_loadx_iphdrlen();
+		s = gen_loadx_iphdrlen(cstate);
 
 		/*
 		 * The X register now contains the sum of the variable
@@ -6887,11 +6983,11 @@
 		 * relative to the beginning of the link-layer payload,
 		 * of the network-layer header.
 		 */
-		sappend(s, xfer_to_a(inst));
-		sappend(s, new_stmt(BPF_ALU|BPF_ADD|BPF_X));
-		sappend(s, new_stmt(BPF_MISC|BPF_TAX));
-		sappend(s, tmp = new_stmt(BPF_LD|BPF_IND|size));
-		tmp->s.k = off_linkpl.constant_part + off_nl;
+		sappend(s, xfer_to_a(cstate, inst));
+		sappend(s, new_stmt(cstate, BPF_ALU|BPF_ADD|BPF_X));
+		sappend(s, new_stmt(cstate, BPF_MISC|BPF_TAX));
+		sappend(s, tmp = new_stmt(cstate, BPF_LD|BPF_IND|size));
+		tmp->s.k = cstate->off_linkpl.constant_part + cstate->off_nl;
 		sappend(inst->s, s);
 
 		/*
@@ -6900,18 +6996,18 @@
 		 * if this is an IP datagram and is the first or
 		 * only fragment of that datagram.
 		 */
-		gen_and(gen_proto_abbrev(proto), b = gen_ipfrag());
+		gen_and(gen_proto_abbrev(cstate, proto), b = gen_ipfrag(cstate));
 		if (inst->b)
 			gen_and(inst->b, b);
-		gen_and(gen_proto_abbrev(Q_IP), b);
+		gen_and(gen_proto_abbrev(cstate, Q_IP), b);
 		inst->b = b;
 		break;
 	case Q_ICMPV6:
-		bpf_error("IPv6 upper-layer protocol is not supported by proto[x]");
+		bpf_error(cstate, "IPv6 upper-layer protocol is not supported by proto[x]");
 		/*NOTREACHED*/
 	}
 	inst->regno = regno;
-	s = new_stmt(BPF_ST);
+	s = new_stmt(cstate, BPF_ST);
 	s->s.k = regno;
 	sappend(inst->s, s);
 
@@ -6919,23 +7015,21 @@
 }
 
 struct block *
-gen_relation(code, a0, a1, reversed)
-	int code;
-	struct arth *a0, *a1;
-	int reversed;
+gen_relation(compiler_state_t *cstate, int code, struct arth *a0,
+    struct arth *a1, int reversed)
 {
 	struct slist *s0, *s1, *s2;
 	struct block *b, *tmp;
 
-	s0 = xfer_to_x(a1);
-	s1 = xfer_to_a(a0);
+	s0 = xfer_to_x(cstate, a1);
+	s1 = xfer_to_a(cstate, a0);
 	if (code == BPF_JEQ) {
-		s2 = new_stmt(BPF_ALU|BPF_SUB|BPF_X);
-		b = new_block(JMP(code));
+		s2 = new_stmt(cstate, BPF_ALU|BPF_SUB|BPF_X);
+		b = new_block(cstate, JMP(code));
 		sappend(s1, s2);
 	}
 	else
-		b = new_block(BPF_JMP|code|BPF_X);
+		b = new_block(cstate, BPF_JMP|code|BPF_X);
 	if (reversed)
 		gen_not(b);
 
@@ -6945,8 +7039,8 @@
 
 	b->stmts = a0->s;
 
-	free_reg(a0->regno);
-	free_reg(a1->regno);
+	free_reg(cstate, a0->regno);
+	free_reg(cstate, a1->regno);
 
 	/* 'and' together protocol checks */
 	if (a0->b) {
@@ -6965,14 +7059,14 @@
 }
 
 struct arth *
-gen_loadlen()
+gen_loadlen(compiler_state_t *cstate)
 {
-	int regno = alloc_reg();
-	struct arth *a = (struct arth *)newchunk(sizeof(*a));
+	int regno = alloc_reg(cstate);
+	struct arth *a = (struct arth *)newchunk(cstate, sizeof(*a));
 	struct slist *s;
 
-	s = new_stmt(BPF_LD|BPF_LEN);
-	s->next = new_stmt(BPF_ST);
+	s = new_stmt(cstate, BPF_LD|BPF_LEN);
+	s->next = new_stmt(cstate, BPF_ST);
 	s->next->s.k = regno;
 	a->s = s;
 	a->regno = regno;
@@ -6981,20 +7075,19 @@
 }
 
 struct arth *
-gen_loadi(val)
-	int val;
+gen_loadi(compiler_state_t *cstate, int val)
 {
 	struct arth *a;
 	struct slist *s;
 	int reg;
 
-	a = (struct arth *)newchunk(sizeof(*a));
+	a = (struct arth *)newchunk(cstate, sizeof(*a));
 
-	reg = alloc_reg();
+	reg = alloc_reg(cstate);
 
-	s = new_stmt(BPF_LD|BPF_IMM);
+	s = new_stmt(cstate, BPF_LD|BPF_IMM);
 	s->s.k = val;
-	s->next = new_stmt(BPF_ST);
+	s->next = new_stmt(cstate, BPF_ST);
 	s->next->s.k = reg;
 	a->s = s;
 	a->regno = reg;
@@ -7003,17 +7096,16 @@
 }
 
 struct arth *
-gen_neg(a)
-	struct arth *a;
+gen_neg(compiler_state_t *cstate, struct arth *a)
 {
 	struct slist *s;
 
-	s = xfer_to_a(a);
+	s = xfer_to_a(cstate, a);
 	sappend(a->s, s);
-	s = new_stmt(BPF_ALU|BPF_NEG);
+	s = new_stmt(cstate, BPF_ALU|BPF_NEG);
 	s->s.k = 0;
 	sappend(a->s, s);
-	s = new_stmt(BPF_ST);
+	s = new_stmt(cstate, BPF_ST);
 	s->s.k = a->regno;
 	sappend(a->s, s);
 
@@ -7021,65 +7113,68 @@
 }
 
 struct arth *
-gen_arth(code, a0, a1)
-	int code;
-	struct arth *a0, *a1;
+gen_arth(compiler_state_t *cstate, int code, struct arth *a0,
+    struct arth *a1)
 {
 	struct slist *s0, *s1, *s2;
 
-	s0 = xfer_to_x(a1);
-	s1 = xfer_to_a(a0);
-	s2 = new_stmt(BPF_ALU|BPF_X|code);
+	/*
+	 * Disallow division by, or modulus by, zero; we do this here
+	 * so that it gets done even if the optimizer is disabled.
+	 */
+	if (code == BPF_DIV) {
+		if (a1->s->s.code == (BPF_LD|BPF_IMM) && a1->s->s.k == 0)
+			bpf_error(cstate, "division by zero");
+	} else if (code == BPF_MOD) {
+		if (a1->s->s.code == (BPF_LD|BPF_IMM) && a1->s->s.k == 0)
+			bpf_error(cstate, "modulus by zero");
+	}
+	s0 = xfer_to_x(cstate, a1);
+	s1 = xfer_to_a(cstate, a0);
+	s2 = new_stmt(cstate, BPF_ALU|BPF_X|code);
 
 	sappend(s1, s2);
 	sappend(s0, s1);
 	sappend(a1->s, s0);
 	sappend(a0->s, a1->s);
 
-	free_reg(a0->regno);
-	free_reg(a1->regno);
+	free_reg(cstate, a0->regno);
+	free_reg(cstate, a1->regno);
 
-	s0 = new_stmt(BPF_ST);
-	a0->regno = s0->s.k = alloc_reg();
+	s0 = new_stmt(cstate, BPF_ST);
+	a0->regno = s0->s.k = alloc_reg(cstate);
 	sappend(a0->s, s0);
 
 	return a0;
 }
 
 /*
- * Here we handle simple allocation of the scratch registers.
- * If too many registers are alloc'd, the allocator punts.
- */
-static int regused[BPF_MEMWORDS];
-static int curreg;
-
-/*
  * Initialize the table of used registers and the current register.
  */
 static void
-init_regs()
+init_regs(compiler_state_t *cstate)
 {
-	curreg = 0;
-	memset(regused, 0, sizeof regused);
+	cstate->curreg = 0;
+	memset(cstate->regused, 0, sizeof cstate->regused);
 }
 
 /*
  * Return the next free register.
  */
 static int
-alloc_reg()
+alloc_reg(compiler_state_t *cstate)
 {
 	int n = BPF_MEMWORDS;
 
 	while (--n >= 0) {
-		if (regused[curreg])
-			curreg = (curreg + 1) % BPF_MEMWORDS;
+		if (cstate->regused[cstate->curreg])
+			cstate->curreg = (cstate->curreg + 1) % BPF_MEMWORDS;
 		else {
-			regused[curreg] = 1;
-			return curreg;
+			cstate->regused[cstate->curreg] = 1;
+			return cstate->curreg;
 		}
 	}
-	bpf_error("too many registers needed to evaluate expression");
+	bpf_error(cstate, "too many registers needed to evaluate expression");
 	/* NOTREACHED */
 	return 0;
 }
@@ -7089,21 +7184,19 @@
  * be used later.
  */
 static void
-free_reg(n)
-	int n;
+free_reg(compiler_state_t *cstate, int n)
 {
-	regused[n] = 0;
+	cstate->regused[n] = 0;
 }
 
 static struct block *
-gen_len(jmp, n)
-	int jmp, n;
+gen_len(compiler_state_t *cstate, int jmp, int n)
 {
 	struct slist *s;
 	struct block *b;
 
-	s = new_stmt(BPF_LD|BPF_LEN);
-	b = new_block(JMP(jmp));
+	s = new_stmt(cstate, BPF_LD|BPF_LEN);
+	b = new_block(cstate, JMP(jmp));
 	b->stmts = s;
 	b->s.k = n;
 
@@ -7111,22 +7204,20 @@
 }
 
 struct block *
-gen_greater(n)
-	int n;
+gen_greater(compiler_state_t *cstate, int n)
 {
-	return gen_len(BPF_JGE, n);
+	return gen_len(cstate, BPF_JGE, n);
 }
 
 /*
  * Actually, this is less than or equal.
  */
 struct block *
-gen_less(n)
-	int n;
+gen_less(compiler_state_t *cstate, int n)
 {
 	struct block *b;
 
-	b = gen_len(BPF_JGT, n);
+	b = gen_len(cstate, BPF_JGT, n);
 	gen_not(b);
 
 	return b;
@@ -7143,8 +7234,7 @@
  * would generate code appropriate to the radio header in question.
  */
 struct block *
-gen_byteop(op, idx, val)
-	int op, idx, val;
+gen_byteop(compiler_state_t *cstate, int op, int idx, int val)
 {
 	struct block *b;
 	struct slist *s;
@@ -7154,72 +7244,71 @@
 		abort();
 
 	case '=':
-		return gen_cmp(OR_LINKHDR, (u_int)idx, BPF_B, (bpf_int32)val);
+		return gen_cmp(cstate, OR_LINKHDR, (u_int)idx, BPF_B, (bpf_int32)val);
 
 	case '<':
-		b = gen_cmp_lt(OR_LINKHDR, (u_int)idx, BPF_B, (bpf_int32)val);
+		b = gen_cmp_lt(cstate, OR_LINKHDR, (u_int)idx, BPF_B, (bpf_int32)val);
 		return b;
 
 	case '>':
-		b = gen_cmp_gt(OR_LINKHDR, (u_int)idx, BPF_B, (bpf_int32)val);
+		b = gen_cmp_gt(cstate, OR_LINKHDR, (u_int)idx, BPF_B, (bpf_int32)val);
 		return b;
 
 	case '|':
-		s = new_stmt(BPF_ALU|BPF_OR|BPF_K);
+		s = new_stmt(cstate, BPF_ALU|BPF_OR|BPF_K);
 		break;
 
 	case '&':
-		s = new_stmt(BPF_ALU|BPF_AND|BPF_K);
+		s = new_stmt(cstate, BPF_ALU|BPF_AND|BPF_K);
 		break;
 	}
 	s->s.k = val;
-	b = new_block(JMP(BPF_JEQ));
+	b = new_block(cstate, JMP(BPF_JEQ));
 	b->stmts = s;
 	gen_not(b);
 
 	return b;
 }
 
-static u_char abroadcast[] = { 0x0 };
+static const u_char abroadcast[] = { 0x0 };
 
 struct block *
-gen_broadcast(proto)
-	int proto;
+gen_broadcast(compiler_state_t *cstate, int proto)
 {
 	bpf_u_int32 hostmask;
 	struct block *b0, *b1, *b2;
-	static u_char ebroadcast[] = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff };
+	static const u_char ebroadcast[] = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff };
 
 	switch (proto) {
 
 	case Q_DEFAULT:
 	case Q_LINK:
-		switch (linktype) {
+		switch (cstate->linktype) {
 		case DLT_ARCNET:
 		case DLT_ARCNET_LINUX:
-			return gen_ahostop(abroadcast, Q_DST);
+			return gen_ahostop(cstate, abroadcast, Q_DST);
 		case DLT_EN10MB:
 		case DLT_NETANALYZER:
 		case DLT_NETANALYZER_TRANSPARENT:
-			b1 = gen_prevlinkhdr_check();
-			b0 = gen_ehostop(ebroadcast, Q_DST);
+			b1 = gen_prevlinkhdr_check(cstate);
+			b0 = gen_ehostop(cstate, ebroadcast, Q_DST);
 			if (b1 != NULL)
 				gen_and(b1, b0);
 			return b0;
 		case DLT_FDDI:
-			return gen_fhostop(ebroadcast, Q_DST);
+			return gen_fhostop(cstate, ebroadcast, Q_DST);
 		case DLT_IEEE802:
-			return gen_thostop(ebroadcast, Q_DST);
+			return gen_thostop(cstate, ebroadcast, Q_DST);
 		case DLT_IEEE802_11:
 		case DLT_PRISM_HEADER:
 		case DLT_IEEE802_11_RADIO_AVS:
 		case DLT_IEEE802_11_RADIO:
 		case DLT_PPI:
-			return gen_wlanhostop(ebroadcast, Q_DST);
+			return gen_wlanhostop(cstate, ebroadcast, Q_DST);
 		case DLT_IP_OVER_FC:
-			return gen_ipfchostop(ebroadcast, Q_DST);
+			return gen_ipfchostop(cstate, ebroadcast, Q_DST);
 		default:
-			bpf_error("not a broadcast link");
+			bpf_error(cstate, "not a broadcast link");
 		}
 		break;
 
@@ -7229,18 +7318,18 @@
 		 * as an indication that we don't know the netmask, and fail
 		 * in that case.
 		 */
-		if (netmask == PCAP_NETMASK_UNKNOWN)
-			bpf_error("netmask not known, so 'ip broadcast' not supported");
-		b0 = gen_linktype(ETHERTYPE_IP);
-		hostmask = ~netmask;
-		b1 = gen_mcmp(OR_LINKPL, 16, BPF_W, (bpf_int32)0, hostmask);
-		b2 = gen_mcmp(OR_LINKPL, 16, BPF_W,
+		if (cstate->netmask == PCAP_NETMASK_UNKNOWN)
+			bpf_error(cstate, "netmask not known, so 'ip broadcast' not supported");
+		b0 = gen_linktype(cstate, ETHERTYPE_IP);
+		hostmask = ~cstate->netmask;
+		b1 = gen_mcmp(cstate, OR_LINKPL, 16, BPF_W, (bpf_int32)0, hostmask);
+		b2 = gen_mcmp(cstate, OR_LINKPL, 16, BPF_W,
 			      (bpf_int32)(~0 & hostmask), hostmask);
 		gen_or(b1, b2);
 		gen_and(b0, b2);
 		return b2;
 	}
-	bpf_error("only link-layer/IP broadcast filters supported");
+	bpf_error(cstate, "only link-layer/IP broadcast filters supported");
 	/* NOTREACHED */
 	return NULL;
 }
@@ -7250,23 +7339,21 @@
  * the bottom bit of the *first* byte).
  */
 static struct block *
-gen_mac_multicast(offset)
-	int offset;
+gen_mac_multicast(compiler_state_t *cstate, int offset)
 {
 	register struct block *b0;
 	register struct slist *s;
 
 	/* link[offset] & 1 != 0 */
-	s = gen_load_a(OR_LINKHDR, offset, BPF_B);
-	b0 = new_block(JMP(BPF_JSET));
+	s = gen_load_a(cstate, OR_LINKHDR, offset, BPF_B);
+	b0 = new_block(cstate, JMP(BPF_JSET));
 	b0->s.k = 1;
 	b0->stmts = s;
 	return b0;
 }
 
 struct block *
-gen_multicast(proto)
-	int proto;
+gen_multicast(compiler_state_t *cstate, int proto)
 {
 	register struct block *b0, *b1, *b2;
 	register struct slist *s;
@@ -7275,17 +7362,17 @@
 
 	case Q_DEFAULT:
 	case Q_LINK:
-		switch (linktype) {
+		switch (cstate->linktype) {
 		case DLT_ARCNET:
 		case DLT_ARCNET_LINUX:
 			/* all ARCnet multicasts use the same address */
-			return gen_ahostop(abroadcast, Q_DST);
+			return gen_ahostop(cstate, abroadcast, Q_DST);
 		case DLT_EN10MB:
 		case DLT_NETANALYZER:
 		case DLT_NETANALYZER_TRANSPARENT:
-			b1 = gen_prevlinkhdr_check();
+			b1 = gen_prevlinkhdr_check(cstate);
 			/* ether[0] & 1 != 0 */
-			b0 = gen_mac_multicast(0);
+			b0 = gen_mac_multicast(cstate, 0);
 			if (b1 != NULL)
 				gen_and(b1, b0);
 			return b0;
@@ -7296,10 +7383,10 @@
 			 * XXX - was that referring to bit-order issues?
 			 */
 			/* fddi[1] & 1 != 0 */
-			return gen_mac_multicast(1);
+			return gen_mac_multicast(cstate, 1);
 		case DLT_IEEE802:
 			/* tr[2] & 1 != 0 */
-			return gen_mac_multicast(2);
+			return gen_mac_multicast(cstate, 2);
 		case DLT_IEEE802_11:
 		case DLT_PRISM_HEADER:
 		case DLT_IEEE802_11_RADIO_AVS:
@@ -7326,23 +7413,23 @@
 			 *
 			 * First, check for To DS set, i.e. "link[1] & 0x01".
 			 */
-			s = gen_load_a(OR_LINKHDR, 1, BPF_B);
-			b1 = new_block(JMP(BPF_JSET));
+			s = gen_load_a(cstate, OR_LINKHDR, 1, BPF_B);
+			b1 = new_block(cstate, JMP(BPF_JSET));
 			b1->s.k = 0x01;	/* To DS */
 			b1->stmts = s;
 
 			/*
 			 * If To DS is set, the DA is at 16.
 			 */
-			b0 = gen_mac_multicast(16);
+			b0 = gen_mac_multicast(cstate, 16);
 			gen_and(b1, b0);
 
 			/*
 			 * Now, check for To DS not set, i.e. check
 			 * "!(link[1] & 0x01)".
 			 */
-			s = gen_load_a(OR_LINKHDR, 1, BPF_B);
-			b2 = new_block(JMP(BPF_JSET));
+			s = gen_load_a(cstate, OR_LINKHDR, 1, BPF_B);
+			b2 = new_block(cstate, JMP(BPF_JSET));
 			b2->s.k = 0x01;	/* To DS */
 			b2->stmts = s;
 			gen_not(b2);
@@ -7350,7 +7437,7 @@
 			/*
 			 * If To DS is not set, the DA is at 4.
 			 */
-			b1 = gen_mac_multicast(4);
+			b1 = gen_mac_multicast(cstate, 4);
 			gen_and(b2, b1);
 
 			/*
@@ -7363,8 +7450,8 @@
 			 * Now check for a data frame.
 			 * I.e, check "link[0] & 0x08".
 			 */
-			s = gen_load_a(OR_LINKHDR, 0, BPF_B);
-			b1 = new_block(JMP(BPF_JSET));
+			s = gen_load_a(cstate, OR_LINKHDR, 0, BPF_B);
+			b1 = new_block(cstate, JMP(BPF_JSET));
 			b1->s.k = 0x08;
 			b1->stmts = s;
 
@@ -7378,8 +7465,8 @@
 			 * is a management frame.
 			 * I.e, check "!(link[0] & 0x08)".
 			 */
-			s = gen_load_a(OR_LINKHDR, 0, BPF_B);
-			b2 = new_block(JMP(BPF_JSET));
+			s = gen_load_a(cstate, OR_LINKHDR, 0, BPF_B);
+			b2 = new_block(cstate, JMP(BPF_JSET));
 			b2->s.k = 0x08;
 			b2->stmts = s;
 			gen_not(b2);
@@ -7387,7 +7474,7 @@
 			/*
 			 * For management frames, the DA is at 4.
 			 */
-			b1 = gen_mac_multicast(4);
+			b1 = gen_mac_multicast(cstate, 4);
 			gen_and(b2, b1);
 
 			/*
@@ -7405,8 +7492,8 @@
 			 *
 			 * I.e., check "!(link[0] & 0x04)".
 			 */
-			s = gen_load_a(OR_LINKHDR, 0, BPF_B);
-			b1 = new_block(JMP(BPF_JSET));
+			s = gen_load_a(cstate, OR_LINKHDR, 0, BPF_B);
+			b1 = new_block(cstate, JMP(BPF_JSET));
 			b1->s.k = 0x04;
 			b1->stmts = s;
 			gen_not(b1);
@@ -7418,7 +7505,7 @@
 			gen_and(b1, b0);
 			return b0;
 		case DLT_IP_OVER_FC:
-			b0 = gen_mac_multicast(2);
+			b0 = gen_mac_multicast(cstate, 2);
 			return b0;
 		default:
 			break;
@@ -7427,18 +7514,18 @@
 		break;
 
 	case Q_IP:
-		b0 = gen_linktype(ETHERTYPE_IP);
-		b1 = gen_cmp_ge(OR_LINKPL, 16, BPF_B, (bpf_int32)224);
+		b0 = gen_linktype(cstate, ETHERTYPE_IP);
+		b1 = gen_cmp_ge(cstate, OR_LINKPL, 16, BPF_B, (bpf_int32)224);
 		gen_and(b0, b1);
 		return b1;
 
 	case Q_IPV6:
-		b0 = gen_linktype(ETHERTYPE_IPV6);
-		b1 = gen_cmp(OR_LINKPL, 24, BPF_B, (bpf_int32)255);
+		b0 = gen_linktype(cstate, ETHERTYPE_IPV6);
+		b1 = gen_cmp(cstate, OR_LINKPL, 24, BPF_B, (bpf_int32)255);
 		gen_and(b0, b1);
 		return b1;
 	}
-	bpf_error("link-layer multicast filters supported only on ethernet/FDDI/token ring/ARCNET/802.11/ATM LANE/Fibre Channel");
+	bpf_error(cstate, "link-layer multicast filters supported only on ethernet/FDDI/token ring/ARCNET/802.11/ATM LANE/Fibre Channel");
 	/* NOTREACHED */
 	return NULL;
 }
@@ -7453,35 +7540,34 @@
  * better accomplished using a higher-layer filter.
  */
 struct block *
-gen_inbound(dir)
-	int dir;
+gen_inbound(compiler_state_t *cstate, int dir)
 {
 	register struct block *b0;
 
 	/*
 	 * Only some data link types support inbound/outbound qualifiers.
 	 */
-	switch (linktype) {
+	switch (cstate->linktype) {
 	case DLT_SLIP:
-		b0 = gen_relation(BPF_JEQ,
-			  gen_load(Q_LINK, gen_loadi(0), 1),
-			  gen_loadi(0),
+		b0 = gen_relation(cstate, BPF_JEQ,
+			  gen_load(cstate, Q_LINK, gen_loadi(cstate, 0), 1),
+			  gen_loadi(cstate, 0),
 			  dir);
 		break;
 
 	case DLT_IPNET:
 		if (dir) {
 			/* match outgoing packets */
-			b0 = gen_cmp(OR_LINKHDR, 2, BPF_H, IPNET_OUTBOUND);
+			b0 = gen_cmp(cstate, OR_LINKHDR, 2, BPF_H, IPNET_OUTBOUND);
 		} else {
 			/* match incoming packets */
-			b0 = gen_cmp(OR_LINKHDR, 2, BPF_H, IPNET_INBOUND);
+			b0 = gen_cmp(cstate, OR_LINKHDR, 2, BPF_H, IPNET_INBOUND);
 		}
 		break;
 
 	case DLT_LINUX_SLL:
 		/* match outgoing packets */
-		b0 = gen_cmp(OR_LINKHDR, 0, BPF_H, LINUX_SLL_OUTGOING);
+		b0 = gen_cmp(cstate, OR_LINKHDR, 0, BPF_H, LINUX_SLL_OUTGOING);
 		if (!dir) {
 			/* to filter on inbound traffic, invert the match */
 			gen_not(b0);
@@ -7490,7 +7576,7 @@
 
 #ifdef HAVE_NET_PFVAR_H
 	case DLT_PFLOG:
-		b0 = gen_cmp(OR_LINKHDR, offsetof(struct pfloghdr, dir), BPF_B,
+		b0 = gen_cmp(cstate, OR_LINKHDR, offsetof(struct pfloghdr, dir), BPF_B,
 		    (bpf_int32)((dir == 0) ? PF_IN : PF_OUT));
 		break;
 #endif
@@ -7498,10 +7584,10 @@
 	case DLT_PPP_PPPD:
 		if (dir) {
 			/* match outgoing packets */
-			b0 = gen_cmp(OR_LINKHDR, 0, BPF_B, PPP_PPPD_OUT);
+			b0 = gen_cmp(cstate, OR_LINKHDR, 0, BPF_B, PPP_PPPD_OUT);
 		} else {
 			/* match incoming packets */
-			b0 = gen_cmp(OR_LINKHDR, 0, BPF_B, PPP_PPPD_IN);
+			b0 = gen_cmp(cstate, OR_LINKHDR, 0, BPF_B, PPP_PPPD_IN);
 		}
 		break;
 
@@ -7532,10 +7618,10 @@
 		 * the byte after the 3-byte magic number */
 		if (dir) {
 			/* match outgoing packets */
-			b0 = gen_mcmp(OR_LINKHDR, 3, BPF_B, 0, 0x01);
+			b0 = gen_mcmp(cstate, OR_LINKHDR, 3, BPF_B, 0, 0x01);
 		} else {
 			/* match incoming packets */
-			b0 = gen_mcmp(OR_LINKHDR, 3, BPF_B, 1, 0x01);
+			b0 = gen_mcmp(cstate, OR_LINKHDR, 3, BPF_B, 1, 0x01);
 		}
 		break;
 
@@ -7552,23 +7638,23 @@
 		 * special meta-data in the filter expression;
 		 * if it's a savefile, we can't.
 		 */
-		if (bpf_pcap->rfile != NULL) {
+		if (cstate->bpf_pcap->rfile != NULL) {
 			/* We have a FILE *, so this is a savefile */
-			bpf_error("inbound/outbound not supported on linktype %d when reading savefiles",
-			    linktype);
+			bpf_error(cstate, "inbound/outbound not supported on linktype %d when reading savefiles",
+			    cstate->linktype);
 			b0 = NULL;
 			/* NOTREACHED */
 		}
 		/* match outgoing packets */
-		b0 = gen_cmp(OR_LINKHDR, SKF_AD_OFF + SKF_AD_PKTTYPE, BPF_H,
+		b0 = gen_cmp(cstate, OR_LINKHDR, SKF_AD_OFF + SKF_AD_PKTTYPE, BPF_H,
 		             PACKET_OUTGOING);
 		if (!dir) {
 			/* to filter on inbound traffic, invert the match */
 			gen_not(b0);
 		}
 #else /* defined(linux) && defined(PF_PACKET) && defined(SO_ATTACH_FILTER) */
-		bpf_error("inbound/outbound not supported on linktype %d",
-		    linktype);
+		bpf_error(cstate, "inbound/outbound not supported on linktype %d",
+		    cstate->linktype);
 		b0 = NULL;
 		/* NOTREACHED */
 #endif /* defined(linux) && defined(PF_PACKET) && defined(SO_ATTACH_FILTER) */
@@ -7579,156 +7665,156 @@
 #ifdef HAVE_NET_PFVAR_H
 /* PF firewall log matched interface */
 struct block *
-gen_pf_ifname(const char *ifname)
+gen_pf_ifname(compiler_state_t *cstate, const char *ifname)
 {
 	struct block *b0;
 	u_int len, off;
 
-	if (linktype != DLT_PFLOG) {
-		bpf_error("ifname supported only on PF linktype");
+	if (cstate->linktype != DLT_PFLOG) {
+		bpf_error(cstate, "ifname supported only on PF linktype");
 		/* NOTREACHED */
 	}
 	len = sizeof(((struct pfloghdr *)0)->ifname);
 	off = offsetof(struct pfloghdr, ifname);
 	if (strlen(ifname) >= len) {
-		bpf_error("ifname interface names can only be %d characters",
+		bpf_error(cstate, "ifname interface names can only be %d characters",
 		    len-1);
 		/* NOTREACHED */
 	}
-	b0 = gen_bcmp(OR_LINKHDR, off, strlen(ifname), (const u_char *)ifname);
+	b0 = gen_bcmp(cstate, OR_LINKHDR, off, strlen(ifname), (const u_char *)ifname);
 	return (b0);
 }
 
 /* PF firewall log ruleset name */
 struct block *
-gen_pf_ruleset(char *ruleset)
+gen_pf_ruleset(compiler_state_t *cstate, char *ruleset)
 {
 	struct block *b0;
 
-	if (linktype != DLT_PFLOG) {
-		bpf_error("ruleset supported only on PF linktype");
+	if (cstate->linktype != DLT_PFLOG) {
+		bpf_error(cstate, "ruleset supported only on PF linktype");
 		/* NOTREACHED */
 	}
 
 	if (strlen(ruleset) >= sizeof(((struct pfloghdr *)0)->ruleset)) {
-		bpf_error("ruleset names can only be %ld characters",
+		bpf_error(cstate, "ruleset names can only be %ld characters",
 		    (long)(sizeof(((struct pfloghdr *)0)->ruleset) - 1));
 		/* NOTREACHED */
 	}
 
-	b0 = gen_bcmp(OR_LINKHDR, offsetof(struct pfloghdr, ruleset),
+	b0 = gen_bcmp(cstate, OR_LINKHDR, offsetof(struct pfloghdr, ruleset),
 	    strlen(ruleset), (const u_char *)ruleset);
 	return (b0);
 }
 
 /* PF firewall log rule number */
 struct block *
-gen_pf_rnr(int rnr)
+gen_pf_rnr(compiler_state_t *cstate, int rnr)
 {
 	struct block *b0;
 
-	if (linktype != DLT_PFLOG) {
-		bpf_error("rnr supported only on PF linktype");
+	if (cstate->linktype != DLT_PFLOG) {
+		bpf_error(cstate, "rnr supported only on PF linktype");
 		/* NOTREACHED */
 	}
 
-	b0 = gen_cmp(OR_LINKHDR, offsetof(struct pfloghdr, rulenr), BPF_W,
+	b0 = gen_cmp(cstate, OR_LINKHDR, offsetof(struct pfloghdr, rulenr), BPF_W,
 		 (bpf_int32)rnr);
 	return (b0);
 }
 
 /* PF firewall log sub-rule number */
 struct block *
-gen_pf_srnr(int srnr)
+gen_pf_srnr(compiler_state_t *cstate, int srnr)
 {
 	struct block *b0;
 
-	if (linktype != DLT_PFLOG) {
-		bpf_error("srnr supported only on PF linktype");
+	if (cstate->linktype != DLT_PFLOG) {
+		bpf_error(cstate, "srnr supported only on PF linktype");
 		/* NOTREACHED */
 	}
 
-	b0 = gen_cmp(OR_LINKHDR, offsetof(struct pfloghdr, subrulenr), BPF_W,
+	b0 = gen_cmp(cstate, OR_LINKHDR, offsetof(struct pfloghdr, subrulenr), BPF_W,
 	    (bpf_int32)srnr);
 	return (b0);
 }
 
 /* PF firewall log reason code */
 struct block *
-gen_pf_reason(int reason)
+gen_pf_reason(compiler_state_t *cstate, int reason)
 {
 	struct block *b0;
 
-	if (linktype != DLT_PFLOG) {
-		bpf_error("reason supported only on PF linktype");
+	if (cstate->linktype != DLT_PFLOG) {
+		bpf_error(cstate, "reason supported only on PF linktype");
 		/* NOTREACHED */
 	}
 
-	b0 = gen_cmp(OR_LINKHDR, offsetof(struct pfloghdr, reason), BPF_B,
+	b0 = gen_cmp(cstate, OR_LINKHDR, offsetof(struct pfloghdr, reason), BPF_B,
 	    (bpf_int32)reason);
 	return (b0);
 }
 
 /* PF firewall log action */
 struct block *
-gen_pf_action(int action)
+gen_pf_action(compiler_state_t *cstate, int action)
 {
 	struct block *b0;
 
-	if (linktype != DLT_PFLOG) {
-		bpf_error("action supported only on PF linktype");
+	if (cstate->linktype != DLT_PFLOG) {
+		bpf_error(cstate, "action supported only on PF linktype");
 		/* NOTREACHED */
 	}
 
-	b0 = gen_cmp(OR_LINKHDR, offsetof(struct pfloghdr, action), BPF_B,
+	b0 = gen_cmp(cstate, OR_LINKHDR, offsetof(struct pfloghdr, action), BPF_B,
 	    (bpf_int32)action);
 	return (b0);
 }
 #else /* !HAVE_NET_PFVAR_H */
 struct block *
-gen_pf_ifname(const char *ifname)
+gen_pf_ifname(compiler_state_t *cstate, const char *ifname)
 {
-	bpf_error("libpcap was compiled without pf support");
+	bpf_error(cstate, "libpcap was compiled without pf support");
 	/* NOTREACHED */
 	return (NULL);
 }
 
 struct block *
-gen_pf_ruleset(char *ruleset)
+gen_pf_ruleset(compiler_state_t *cstate, char *ruleset)
 {
-	bpf_error("libpcap was compiled on a machine without pf support");
+	bpf_error(cstate, "libpcap was compiled on a machine without pf support");
 	/* NOTREACHED */
 	return (NULL);
 }
 
 struct block *
-gen_pf_rnr(int rnr)
+gen_pf_rnr(compiler_state_t *cstate, int rnr)
 {
-	bpf_error("libpcap was compiled on a machine without pf support");
+	bpf_error(cstate, "libpcap was compiled on a machine without pf support");
 	/* NOTREACHED */
 	return (NULL);
 }
 
 struct block *
-gen_pf_srnr(int srnr)
+gen_pf_srnr(compiler_state_t *cstate, int srnr)
 {
-	bpf_error("libpcap was compiled on a machine without pf support");
+	bpf_error(cstate, "libpcap was compiled on a machine without pf support");
 	/* NOTREACHED */
 	return (NULL);
 }
 
 struct block *
-gen_pf_reason(int reason)
+gen_pf_reason(compiler_state_t *cstate, int reason)
 {
-	bpf_error("libpcap was compiled on a machine without pf support");
+	bpf_error(cstate, "libpcap was compiled on a machine without pf support");
 	/* NOTREACHED */
 	return (NULL);
 }
 
 struct block *
-gen_pf_action(int action)
+gen_pf_action(compiler_state_t *cstate, int action)
 {
-	bpf_error("libpcap was compiled on a machine without pf support");
+	bpf_error(cstate, "libpcap was compiled on a machine without pf support");
 	/* NOTREACHED */
 	return (NULL);
 }
@@ -7736,22 +7822,22 @@
 
 /* IEEE 802.11 wireless header */
 struct block *
-gen_p80211_type(int type, int mask)
+gen_p80211_type(compiler_state_t *cstate, int type, int mask)
 {
 	struct block *b0;
 
-	switch (linktype) {
+	switch (cstate->linktype) {
 
 	case DLT_IEEE802_11:
 	case DLT_PRISM_HEADER:
 	case DLT_IEEE802_11_RADIO_AVS:
 	case DLT_IEEE802_11_RADIO:
-		b0 = gen_mcmp(OR_LINKHDR, 0, BPF_B, (bpf_int32)type,
+		b0 = gen_mcmp(cstate, OR_LINKHDR, 0, BPF_B, (bpf_int32)type,
 		    (bpf_int32)mask);
 		break;
 
 	default:
-		bpf_error("802.11 link-layer types supported only on 802.11");
+		bpf_error(cstate, "802.11 link-layer types supported only on 802.11");
 		/* NOTREACHED */
 	}
 
@@ -7759,11 +7845,11 @@
 }
 
 struct block *
-gen_p80211_fcdir(int fcdir)
+gen_p80211_fcdir(compiler_state_t *cstate, int fcdir)
 {
 	struct block *b0;
 
-	switch (linktype) {
+	switch (cstate->linktype) {
 
 	case DLT_IEEE802_11:
 	case DLT_PRISM_HEADER:
@@ -7772,93 +7858,89 @@
 		break;
 
 	default:
-		bpf_error("frame direction supported only with 802.11 headers");
+		bpf_error(cstate, "frame direction supported only with 802.11 headers");
 		/* NOTREACHED */
 	}
 
-	b0 = gen_mcmp(OR_LINKHDR, 1, BPF_B, (bpf_int32)fcdir,
+	b0 = gen_mcmp(cstate, OR_LINKHDR, 1, BPF_B, (bpf_int32)fcdir,
 		(bpf_u_int32)IEEE80211_FC1_DIR_MASK);
 
 	return (b0);
 }
 
 struct block *
-gen_acode(eaddr, q)
-	register const u_char *eaddr;
-	struct qual q;
+gen_acode(compiler_state_t *cstate, const u_char *eaddr, struct qual q)
 {
-	switch (linktype) {
+	switch (cstate->linktype) {
 
 	case DLT_ARCNET:
 	case DLT_ARCNET_LINUX:
 		if ((q.addr == Q_HOST || q.addr == Q_DEFAULT) &&
 		    q.proto == Q_LINK)
-			return (gen_ahostop(eaddr, (int)q.dir));
+			return (gen_ahostop(cstate, eaddr, (int)q.dir));
 		else {
-			bpf_error("ARCnet address used in non-arc expression");
+			bpf_error(cstate, "ARCnet address used in non-arc expression");
 			/* NOTREACHED */
 		}
 		break;
 
 	default:
-		bpf_error("aid supported only on ARCnet");
+		bpf_error(cstate, "aid supported only on ARCnet");
 		/* NOTREACHED */
 	}
-	bpf_error("ARCnet address used in non-arc expression");
+	bpf_error(cstate, "ARCnet address used in non-arc expression");
 	/* NOTREACHED */
 	return NULL;
 }
 
 static struct block *
-gen_ahostop(eaddr, dir)
-	register const u_char *eaddr;
-	register int dir;
+gen_ahostop(compiler_state_t *cstate, const u_char *eaddr, int dir)
 {
 	register struct block *b0, *b1;
 
 	switch (dir) {
 	/* src comes first, different from Ethernet */
 	case Q_SRC:
-		return gen_bcmp(OR_LINKHDR, 0, 1, eaddr);
+		return gen_bcmp(cstate, OR_LINKHDR, 0, 1, eaddr);
 
 	case Q_DST:
-		return gen_bcmp(OR_LINKHDR, 1, 1, eaddr);
+		return gen_bcmp(cstate, OR_LINKHDR, 1, 1, eaddr);
 
 	case Q_AND:
-		b0 = gen_ahostop(eaddr, Q_SRC);
-		b1 = gen_ahostop(eaddr, Q_DST);
+		b0 = gen_ahostop(cstate, eaddr, Q_SRC);
+		b1 = gen_ahostop(cstate, eaddr, Q_DST);
 		gen_and(b0, b1);
 		return b1;
 
 	case Q_DEFAULT:
 	case Q_OR:
-		b0 = gen_ahostop(eaddr, Q_SRC);
-		b1 = gen_ahostop(eaddr, Q_DST);
+		b0 = gen_ahostop(cstate, eaddr, Q_SRC);
+		b1 = gen_ahostop(cstate, eaddr, Q_DST);
 		gen_or(b0, b1);
 		return b1;
 
 	case Q_ADDR1:
-		bpf_error("'addr1' is only supported on 802.11");
+		bpf_error(cstate, "'addr1' is only supported on 802.11");
 		break;
 
 	case Q_ADDR2:
-		bpf_error("'addr2' is only supported on 802.11");
+		bpf_error(cstate, "'addr2' is only supported on 802.11");
 		break;
 
 	case Q_ADDR3:
-		bpf_error("'addr3' is only supported on 802.11");
+		bpf_error(cstate, "'addr3' is only supported on 802.11");
 		break;
 
 	case Q_ADDR4:
-		bpf_error("'addr4' is only supported on 802.11");
+		bpf_error(cstate, "'addr4' is only supported on 802.11");
 		break;
 
 	case Q_RA:
-		bpf_error("'ra' is only supported on 802.11");
+		bpf_error(cstate, "'ra' is only supported on 802.11");
 		break;
 
 	case Q_TA:
-		bpf_error("'ta' is only supported on 802.11");
+		bpf_error(cstate, "'ta' is only supported on 802.11");
 		break;
 	}
 	abort();
@@ -7867,25 +7949,25 @@
 
 #if defined(SKF_AD_VLAN_TAG) && defined(SKF_AD_VLAN_TAG_PRESENT)
 static struct block *
-gen_vlan_bpf_extensions(int vlan_num)
+gen_vlan_bpf_extensions(compiler_state_t *cstate, int vlan_num)
 {
         struct block *b0, *b1;
         struct slist *s;
 
         /* generate new filter code based on extracting packet
          * metadata */
-        s = new_stmt(BPF_LD|BPF_B|BPF_ABS);
+        s = new_stmt(cstate, BPF_LD|BPF_B|BPF_ABS);
         s->s.k = SKF_AD_OFF + SKF_AD_VLAN_TAG_PRESENT;
 
-        b0 = new_block(JMP(BPF_JEQ));
+        b0 = new_block(cstate, JMP(BPF_JEQ));
         b0->stmts = s;
         b0->s.k = 1;
 
         if (vlan_num >= 0) {
-                s = new_stmt(BPF_LD|BPF_B|BPF_ABS);
+                s = new_stmt(cstate, BPF_LD|BPF_B|BPF_ABS);
                 s->s.k = SKF_AD_OFF + SKF_AD_VLAN_TAG;
 
-                b1 = new_block(JMP(BPF_JEQ));
+                b1 = new_block(cstate, JMP(BPF_JEQ));
                 b1->stmts = s;
                 b1->s.k = (bpf_int32) vlan_num;
 
@@ -7898,19 +7980,22 @@
 #endif
 
 static struct block *
-gen_vlan_no_bpf_extensions(int vlan_num)
+gen_vlan_no_bpf_extensions(compiler_state_t *cstate, int vlan_num)
 {
         struct block *b0, *b1;
 
         /* check for VLAN, including QinQ */
-        b0 = gen_linktype(ETHERTYPE_8021Q);
-        b1 = gen_linktype(ETHERTYPE_8021QINQ);
+        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(OR_LINKPL, 0, BPF_H,
+                b1 = gen_mcmp(cstate, OR_LINKPL, 0, BPF_H,
                               (bpf_int32)vlan_num, 0x0fff);
                 gen_and(b0, b1);
                 b0 = b1;
@@ -7920,13 +8005,13 @@
 	 * The payload follows the full header, including the
 	 * VLAN tags, so skip past this VLAN tag.
 	 */
-        off_linkpl.constant_part += 4;
+        cstate->off_linkpl.constant_part += 4;
 
 	/*
 	 * The link-layer type information follows the VLAN tags, so
 	 * skip past this VLAN tag.
 	 */
-        off_linktype.constant_part += 4;
+        cstate->off_linktype.constant_part += 4;
 
         return b0;
 }
@@ -7935,14 +8020,13 @@
  * support IEEE 802.1Q VLAN trunk over ethernet
  */
 struct block *
-gen_vlan(vlan_num)
-	int vlan_num;
+gen_vlan(compiler_state_t *cstate, int vlan_num)
 {
 	struct	block	*b0;
 
 	/* can't check for VLAN-encapsulated packets inside MPLS */
-	if (label_stack_depth > 0)
-		bpf_error("no VLAN match after MPLS");
+	if (cstate->label_stack_depth > 0)
+		bpf_error(cstate, "no VLAN match after MPLS");
 
 	/*
 	 * Check for a VLAN packet, and then change the offsets to point
@@ -7975,7 +8059,7 @@
 	 * be done assuming a VLAN, even though the "or" could be viewed
 	 * as meaning "or, if this isn't a VLAN packet...".
 	 */
-	switch (linktype) {
+	switch (cstate->linktype) {
 
 	case DLT_EN10MB:
 	case DLT_NETANALYZER:
@@ -7983,35 +8067,35 @@
 #if defined(SKF_AD_VLAN_TAG) && defined(SKF_AD_VLAN_TAG_PRESENT)
 		/* Verify that this is the outer part of the packet and
 		 * not encapsulated somehow. */
-		if (vlan_stack_depth == 0 && !off_linkhdr.is_variable &&
-		    off_linkhdr.constant_part ==
-		    off_outermostlinkhdr.constant_part) {
+		if (cstate->vlan_stack_depth == 0 && !cstate->off_linkhdr.is_variable &&
+		    cstate->off_linkhdr.constant_part ==
+		    cstate->off_outermostlinkhdr.constant_part) {
 			/*
 			 * Do we need special VLAN handling?
 			 */
-			if (bpf_pcap->bpf_codegen_flags & BPF_SPECIAL_VLAN_HANDLING)
-				b0 = gen_vlan_bpf_extensions(vlan_num);
+			if (cstate->bpf_pcap->bpf_codegen_flags & BPF_SPECIAL_VLAN_HANDLING)
+				b0 = gen_vlan_bpf_extensions(cstate, vlan_num);
 			else
-				b0 = gen_vlan_no_bpf_extensions(vlan_num);
+				b0 = gen_vlan_no_bpf_extensions(cstate, vlan_num);
 		} else
 #endif
-			b0 = gen_vlan_no_bpf_extensions(vlan_num);
+			b0 = gen_vlan_no_bpf_extensions(cstate, vlan_num);
                 break;
 
 	case DLT_IEEE802_11:
 	case DLT_PRISM_HEADER:
 	case DLT_IEEE802_11_RADIO_AVS:
 	case DLT_IEEE802_11_RADIO:
-		b0 = gen_vlan_no_bpf_extensions(vlan_num);
+		b0 = gen_vlan_no_bpf_extensions(cstate, vlan_num);
 		break;
 
 	default:
-		bpf_error("no VLAN support for data link type %d",
-		      linktype);
+		bpf_error(cstate, "no VLAN support for data link type %d",
+		      cstate->linktype);
 		/*NOTREACHED*/
 	}
 
-        vlan_stack_depth++;
+        cstate->vlan_stack_depth++;
 
 	return (b0);
 }
@@ -8020,30 +8104,29 @@
  * support for MPLS
  */
 struct block *
-gen_mpls(label_num)
-	int label_num;
+gen_mpls(compiler_state_t *cstate, int label_num)
 {
 	struct	block	*b0, *b1;
 
-        if (label_stack_depth > 0) {
+        if (cstate->label_stack_depth > 0) {
             /* just match the bottom-of-stack bit clear */
-            b0 = gen_mcmp(OR_PREVMPLSHDR, 2, BPF_B, 0, 0x01);
+            b0 = gen_mcmp(cstate, OR_PREVMPLSHDR, 2, BPF_B, 0, 0x01);
         } else {
             /*
              * We're not in an MPLS stack yet, so check the link-layer
              * type against MPLS.
              */
-            switch (linktype) {
+            switch (cstate->linktype) {
 
             case DLT_C_HDLC: /* fall through */
             case DLT_EN10MB:
             case DLT_NETANALYZER:
             case DLT_NETANALYZER_TRANSPARENT:
-                    b0 = gen_linktype(ETHERTYPE_MPLS);
+                    b0 = gen_linktype(cstate, ETHERTYPE_MPLS);
                     break;
 
             case DLT_PPP:
-                    b0 = gen_linktype(PPP_MPLS_UCAST);
+                    b0 = gen_linktype(cstate, PPP_MPLS_UCAST);
                     break;
 
                     /* FIXME add other DLT_s ...
@@ -8051,8 +8134,8 @@
                      * leave it for now */
 
             default:
-                    bpf_error("no MPLS support for data link type %d",
-                          linktype);
+                    bpf_error(cstate, "no MPLS support for data link type %d",
+                          cstate->linktype);
                     b0 = NULL;
                     /*NOTREACHED*/
                     break;
@@ -8062,7 +8145,7 @@
 	/* If a specific MPLS label is requested, check it */
 	if (label_num >= 0) {
 		label_num = label_num << 12; /* label is shifted 12 bits on the wire */
-		b1 = gen_mcmp(OR_LINKPL, 0, BPF_W, (bpf_int32)label_num,
+		b1 = gen_mcmp(cstate, OR_LINKPL, 0, BPF_W, (bpf_int32)label_num,
 		    0xfffff000); /* only compare the first 20 bits */
 		gen_and(b0, b1);
 		b0 = b1;
@@ -8082,9 +8165,9 @@
          *
          * XXX - this is a bit of a kludge.  See comments in gen_vlan().
          */
-        off_nl_nosnap += 4;
-        off_nl += 4;
-        label_stack_depth++;
+        cstate->off_nl_nosnap += 4;
+        cstate->off_nl += 4;
+        cstate->label_stack_depth++;
 	return (b0);
 }
 
@@ -8092,26 +8175,25 @@
  * Support PPPOE discovery and session.
  */
 struct block *
-gen_pppoed()
+gen_pppoed(compiler_state_t *cstate)
 {
 	/* check for PPPoE discovery */
-	return gen_linktype((bpf_int32)ETHERTYPE_PPPOED);
+	return gen_linktype(cstate, (bpf_int32)ETHERTYPE_PPPOED);
 }
 
 struct block *
-gen_pppoes(sess_num)
-	int sess_num;
+gen_pppoes(compiler_state_t *cstate, int sess_num)
 {
 	struct block *b0, *b1;
 
 	/*
 	 * Test against the PPPoE session link-layer type.
 	 */
-	b0 = gen_linktype((bpf_int32)ETHERTYPE_PPPOES);
+	b0 = gen_linktype(cstate, (bpf_int32)ETHERTYPE_PPPOES);
 
 	/* If a specific session is requested, check PPPoE session id */
 	if (sess_num >= 0) {
-		b1 = gen_mcmp(OR_LINKPL, 0, BPF_W,
+		b1 = gen_mcmp(cstate, OR_LINKPL, 0, BPF_W,
 		    (bpf_int32)sess_num, 0x0000ffff);
 		gen_and(b0, b1);
 		b0 = b1;
@@ -8154,17 +8236,17 @@
 	 * starts at the first byte of the PPP packet.  For PPPoE,
 	 * that offset is relative to the beginning of the total
 	 * link-layer payload, including any 802.2 LLC header, so
-	 * it's 6 bytes past off_nl.
+	 * it's 6 bytes past cstate->off_nl.
 	 */
-	PUSH_LINKHDR(DLT_PPP, off_linkpl.is_variable,
-	    off_linkpl.constant_part + off_nl + 6, /* 6 bytes past the PPPoE header */
-	    off_linkpl.reg);
+	PUSH_LINKHDR(cstate, DLT_PPP, cstate->off_linkpl.is_variable,
+	    cstate->off_linkpl.constant_part + cstate->off_nl + 6, /* 6 bytes past the PPPoE header */
+	    cstate->off_linkpl.reg);
 
-	off_linktype = off_linkhdr;
-	off_linkpl.constant_part = off_linkhdr.constant_part + 2;
+	cstate->off_linktype = cstate->off_linkhdr;
+	cstate->off_linkpl.constant_part = cstate->off_linkhdr.constant_part + 2;
 
-	off_nl = 0;
-	off_nl_nosnap = 0;	/* no 802.2 LLC */
+	cstate->off_nl = 0;
+	cstate->off_nl_nosnap = 0;	/* no 802.2 LLC */
 
 	return b0;
 }
@@ -8172,23 +8254,24 @@
 /* Check that this is Geneve and the VNI is correct if
  * specified. Parameterized to handle both IPv4 and IPv6. */
 static struct block *
-gen_geneve_check(struct block *(*gen_portfn)(int, int, int),
-		 enum e_offrel offrel, int vni)
+gen_geneve_check(compiler_state_t *cstate,
+    struct block *(*gen_portfn)(compiler_state_t *, int, int, int),
+    enum e_offrel offrel, int vni)
 {
 	struct block *b0, *b1;
 
-	b0 = gen_portfn(GENEVE_PORT, IPPROTO_UDP, Q_DST);
+	b0 = gen_portfn(cstate, GENEVE_PORT, IPPROTO_UDP, Q_DST);
 
 	/* Check that we are operating on version 0. Otherwise, we
 	 * can't decode the rest of the fields. The version is 2 bits
 	 * in the first byte of the Geneve header. */
-	b1 = gen_mcmp(offrel, 8, BPF_B, (bpf_int32)0, 0xc0);
+	b1 = gen_mcmp(cstate, offrel, 8, BPF_B, (bpf_int32)0, 0xc0);
 	gen_and(b0, b1);
 	b0 = b1;
 
 	if (vni >= 0) {
 		vni <<= 8; /* VNI is in the upper 3 bytes */
-		b1 = gen_mcmp(offrel, 12, BPF_W, (bpf_int32)vni,
+		b1 = gen_mcmp(cstate, offrel, 12, BPF_W, (bpf_int32)vni,
 			      0xffffff00);
 		gen_and(b0, b1);
 		b0 = b1;
@@ -8203,23 +8286,23 @@
  *   needed) into register A to be used later to compute
  *   the inner packet offsets. */
 static struct block *
-gen_geneve4(int vni)
+gen_geneve4(compiler_state_t *cstate, int vni)
 {
 	struct block *b0, *b1;
 	struct slist *s, *s1;
 
-	b0 = gen_geneve_check(gen_port, OR_TRAN_IPV4, vni);
+	b0 = gen_geneve_check(cstate, gen_port, OR_TRAN_IPV4, vni);
 
 	/* Load the IP header length into A. */
-	s = gen_loadx_iphdrlen();
+	s = gen_loadx_iphdrlen(cstate);
 
-	s1 = new_stmt(BPF_MISC|BPF_TXA);
+	s1 = new_stmt(cstate, BPF_MISC|BPF_TXA);
 	sappend(s, s1);
 
 	/* Forcibly append these statements to the true condition
 	 * of the protocol check by creating a new block that is
 	 * always true and ANDing them. */
-	b1 = new_block(BPF_JMP|BPF_JEQ|BPF_X);
+	b1 = new_block(cstate, BPF_JMP|BPF_JEQ|BPF_X);
 	b1->stmts = s;
 	b1->s.k = 0;
 
@@ -8229,36 +8312,36 @@
 }
 
 static struct block *
-gen_geneve6(int vni)
+gen_geneve6(compiler_state_t *cstate, int vni)
 {
 	struct block *b0, *b1;
 	struct slist *s, *s1;
 
-	b0 = gen_geneve_check(gen_port6, OR_TRAN_IPV6, vni);
+	b0 = gen_geneve_check(cstate, gen_port6, OR_TRAN_IPV6, vni);
 
 	/* Load the IP header length. We need to account for a
 	 * variable length link prefix if there is one. */
-	s = gen_abs_offset_varpart(&off_linkpl);
+	s = gen_abs_offset_varpart(cstate, &cstate->off_linkpl);
 	if (s) {
-		s1 = new_stmt(BPF_LD|BPF_IMM);
+		s1 = new_stmt(cstate, BPF_LD|BPF_IMM);
 		s1->s.k = 40;
 		sappend(s, s1);
 
-		s1 = new_stmt(BPF_ALU|BPF_ADD|BPF_X);
+		s1 = new_stmt(cstate, BPF_ALU|BPF_ADD|BPF_X);
 		s1->s.k = 0;
 		sappend(s, s1);
 	} else {
-		s = new_stmt(BPF_LD|BPF_IMM);
-		s->s.k = 40;;
+		s = new_stmt(cstate, BPF_LD|BPF_IMM);
+		s->s.k = 40;
 	}
 
 	/* Forcibly append these statements to the true condition
 	 * of the protocol check by creating a new block that is
 	 * always true and ANDing them. */
-	s1 = new_stmt(BPF_MISC|BPF_TAX);
+	s1 = new_stmt(cstate, BPF_MISC|BPF_TAX);
 	sappend(s, s1);
 
-	b1 = new_block(BPF_JMP|BPF_JEQ|BPF_X);
+	b1 = new_block(cstate, BPF_JMP|BPF_JEQ|BPF_X);
 	b1->stmts = s;
 	b1->s.k = 0;
 
@@ -8272,7 +8355,7 @@
  * - The offset of the end of the Geneve header.
  * - The offset of the end of the encapsulated MAC header. */
 static struct slist *
-gen_geneve_offsets(void)
+gen_geneve_offsets(compiler_state_t *cstate)
 {
 	struct slist *s, *s1, *s_proto;
 
@@ -8281,49 +8364,49 @@
 	 * (include any variable link prefix) and stored in A plus the
 	 * fixed sized headers (fixed link prefix, MAC length, and UDP
 	 * header). */
-	s = new_stmt(BPF_ALU|BPF_ADD|BPF_K);
-	s->s.k = off_linkpl.constant_part + off_nl + 8;
+	s = new_stmt(cstate, BPF_ALU|BPF_ADD|BPF_K);
+	s->s.k = cstate->off_linkpl.constant_part + cstate->off_nl + 8;
 
 	/* Stash this in X since we'll need it later. */
-	s1 = new_stmt(BPF_MISC|BPF_TAX);
+	s1 = new_stmt(cstate, BPF_MISC|BPF_TAX);
 	sappend(s, s1);
 
 	/* The EtherType in Geneve is 2 bytes in. Calculate this and
 	 * store it. */
-	s1 = new_stmt(BPF_ALU|BPF_ADD|BPF_K);
+	s1 = new_stmt(cstate, BPF_ALU|BPF_ADD|BPF_K);
 	s1->s.k = 2;
 	sappend(s, s1);
 
-	off_linktype.reg = alloc_reg();
-	off_linktype.is_variable = 1;
-	off_linktype.constant_part = 0;
+	cstate->off_linktype.reg = alloc_reg(cstate);
+	cstate->off_linktype.is_variable = 1;
+	cstate->off_linktype.constant_part = 0;
 
-	s1 = new_stmt(BPF_ST);
-	s1->s.k = off_linktype.reg;
+	s1 = new_stmt(cstate, BPF_ST);
+	s1->s.k = cstate->off_linktype.reg;
 	sappend(s, s1);
 
 	/* Load the Geneve option length and mask and shift to get the
 	 * number of bytes. It is stored in the first byte of the Geneve
 	 * header. */
-	s1 = new_stmt(BPF_LD|BPF_IND|BPF_B);
+	s1 = new_stmt(cstate, BPF_LD|BPF_IND|BPF_B);
 	s1->s.k = 0;
 	sappend(s, s1);
 
-	s1 = new_stmt(BPF_ALU|BPF_AND|BPF_K);
+	s1 = new_stmt(cstate, BPF_ALU|BPF_AND|BPF_K);
 	s1->s.k = 0x3f;
 	sappend(s, s1);
 
-	s1 = new_stmt(BPF_ALU|BPF_MUL|BPF_K);
+	s1 = new_stmt(cstate, BPF_ALU|BPF_MUL|BPF_K);
 	s1->s.k = 4;
 	sappend(s, s1);
 
 	/* Add in the rest of the Geneve base header. */
-	s1 = new_stmt(BPF_ALU|BPF_ADD|BPF_K);
+	s1 = new_stmt(cstate, BPF_ALU|BPF_ADD|BPF_K);
 	s1->s.k = 8;
 	sappend(s, s1);
 
 	/* Add the Geneve header length to its offset and store. */
-	s1 = new_stmt(BPF_ALU|BPF_ADD|BPF_X);
+	s1 = new_stmt(cstate, BPF_ALU|BPF_ADD|BPF_X);
 	s1->s.k = 0;
 	sappend(s, s1);
 
@@ -8335,10 +8418,10 @@
 	 * - The only link layer that we have specific support for is
 	 *   Ethernet. We will confirm that the packet actually is
 	 *   Ethernet at runtime before executing these checks. */
-	PUSH_LINKHDR(DLT_EN10MB, 1, 0, alloc_reg());
+	PUSH_LINKHDR(cstate, DLT_EN10MB, 1, 0, alloc_reg(cstate));
 
-	s1 = new_stmt(BPF_ST);
-	s1->s.k = off_linkhdr.reg;
+	s1 = new_stmt(cstate, BPF_ST);
+	s1->s.k = cstate->off_linkhdr.reg;
 	sappend(s, s1);
 
 	/* Calculate whether we have an Ethernet header or just raw IP/
@@ -8347,73 +8430,73 @@
 	 * seamlessly. Otherwise, keep what we've calculated already. */
 
 	/* We have a bare jmp so we can't use the optimizer. */
-	no_optimize = 1;
+	cstate->no_optimize = 1;
 
 	/* Load the EtherType in the Geneve header, 2 bytes in. */
-	s1 = new_stmt(BPF_LD|BPF_IND|BPF_H);
+	s1 = new_stmt(cstate, BPF_LD|BPF_IND|BPF_H);
 	s1->s.k = 2;
 	sappend(s, s1);
 
 	/* Load X with the end of the Geneve header. */
-	s1 = new_stmt(BPF_LDX|BPF_MEM);
-	s1->s.k = off_linkhdr.reg;
+	s1 = new_stmt(cstate, BPF_LDX|BPF_MEM);
+	s1->s.k = cstate->off_linkhdr.reg;
 	sappend(s, s1);
 
 	/* Check if the EtherType is Transparent Ethernet Bridging. At the
 	 * end of this check, we should have the total length in X. In
 	 * the non-Ethernet case, it's already there. */
-	s_proto = new_stmt(JMP(BPF_JEQ));
+	s_proto = new_stmt(cstate, JMP(BPF_JEQ));
 	s_proto->s.k = ETHERTYPE_TEB;
 	sappend(s, s_proto);
 
-	s1 = new_stmt(BPF_MISC|BPF_TXA);
+	s1 = new_stmt(cstate, BPF_MISC|BPF_TXA);
 	sappend(s, s1);
 	s_proto->s.jt = s1;
 
 	/* Since this is Ethernet, use the EtherType of the payload
 	 * directly as the linktype. Overwrite what we already have. */
-	s1 = new_stmt(BPF_ALU|BPF_ADD|BPF_K);
+	s1 = new_stmt(cstate, BPF_ALU|BPF_ADD|BPF_K);
 	s1->s.k = 12;
 	sappend(s, s1);
 
-	s1 = new_stmt(BPF_ST);
-	s1->s.k = off_linktype.reg;
+	s1 = new_stmt(cstate, BPF_ST);
+	s1->s.k = cstate->off_linktype.reg;
 	sappend(s, s1);
 
 	/* Advance two bytes further to get the end of the Ethernet
 	 * header. */
-	s1 = new_stmt(BPF_ALU|BPF_ADD|BPF_K);
+	s1 = new_stmt(cstate, BPF_ALU|BPF_ADD|BPF_K);
 	s1->s.k = 2;
 	sappend(s, s1);
 
 	/* Move the result to X. */
-	s1 = new_stmt(BPF_MISC|BPF_TAX);
+	s1 = new_stmt(cstate, BPF_MISC|BPF_TAX);
 	sappend(s, s1);
 
 	/* Store the final result of our linkpl calculation. */
-	off_linkpl.reg = alloc_reg();
-	off_linkpl.is_variable = 1;
-	off_linkpl.constant_part = 0;
+	cstate->off_linkpl.reg = alloc_reg(cstate);
+	cstate->off_linkpl.is_variable = 1;
+	cstate->off_linkpl.constant_part = 0;
 
-	s1 = new_stmt(BPF_STX);
-	s1->s.k = off_linkpl.reg;
+	s1 = new_stmt(cstate, BPF_STX);
+	s1->s.k = cstate->off_linkpl.reg;
 	sappend(s, s1);
 	s_proto->s.jf = s1;
 
-	off_nl = 0;
+	cstate->off_nl = 0;
 
 	return s;
 }
 
 /* Check to see if this is a Geneve packet. */
 struct block *
-gen_geneve(int vni)
+gen_geneve(compiler_state_t *cstate, int vni)
 {
 	struct block *b0, *b1;
 	struct slist *s;
 
-	b0 = gen_geneve4(vni);
-	b1 = gen_geneve6(vni);
+	b0 = gen_geneve4(cstate, vni);
+	b1 = gen_geneve6(cstate, vni);
 
 	gen_or(b0, b1);
 	b0 = b1;
@@ -8421,15 +8504,15 @@
 	/* Later filters should act on the payload of the Geneve frame,
 	 * update all of the header pointers. Attach this code so that
 	 * it gets executed in the event that the Geneve filter matches. */
-	s = gen_geneve_offsets();
+	s = gen_geneve_offsets(cstate);
 
-	b1 = gen_true();
+	b1 = gen_true(cstate);
 	sappend(s, b1->stmts);
 	b1->stmts = s;
 
 	gen_and(b0, b1);
 
-	is_geneve = 1;
+	cstate->is_geneve = 1;
 
 	return b1;
 }
@@ -8437,7 +8520,7 @@
 /* Check that the encapsulated frame has a link layer header
  * for Ethernet filters. */
 static struct block *
-gen_geneve_ll_check()
+gen_geneve_ll_check(compiler_state_t *cstate)
 {
 	struct block *b0;
 	struct slist *s, *s1;
@@ -8448,14 +8531,14 @@
 
 	/* Geneve always generates pure variable offsets so we can
 	 * compare only the registers. */
-	s = new_stmt(BPF_LD|BPF_MEM);
-	s->s.k = off_linkhdr.reg;
+	s = new_stmt(cstate, BPF_LD|BPF_MEM);
+	s->s.k = cstate->off_linkhdr.reg;
 
-	s1 = new_stmt(BPF_LDX|BPF_MEM);
-	s1->s.k = off_linkpl.reg;
+	s1 = new_stmt(cstate, BPF_LDX|BPF_MEM);
+	s1->s.k = cstate->off_linkpl.reg;
 	sappend(s, s1);
 
-	b0 = new_block(BPF_JMP|BPF_JEQ|BPF_X);
+	b0 = new_block(cstate, BPF_JMP|BPF_JEQ|BPF_X);
 	b0->stmts = s;
 	b0->s.k = 0;
 	gen_not(b0);
@@ -8464,54 +8547,51 @@
 }
 
 struct block *
-gen_atmfield_code(atmfield, jvalue, jtype, reverse)
-	int atmfield;
-	bpf_int32 jvalue;
-	bpf_u_int32 jtype;
-	int reverse;
+gen_atmfield_code(compiler_state_t *cstate, int atmfield, bpf_int32 jvalue,
+    bpf_u_int32 jtype, int reverse)
 {
 	struct block *b0;
 
 	switch (atmfield) {
 
 	case A_VPI:
-		if (!is_atm)
-			bpf_error("'vpi' supported only on raw ATM");
-		if (off_vpi == (u_int)-1)
+		if (!cstate->is_atm)
+			bpf_error(cstate, "'vpi' supported only on raw ATM");
+		if (cstate->off_vpi == (u_int)-1)
 			abort();
-		b0 = gen_ncmp(OR_LINKHDR, off_vpi, BPF_B, 0xffffffff, jtype,
+		b0 = gen_ncmp(cstate, OR_LINKHDR, cstate->off_vpi, BPF_B, 0xffffffff, jtype,
 		    reverse, jvalue);
 		break;
 
 	case A_VCI:
-		if (!is_atm)
-			bpf_error("'vci' supported only on raw ATM");
-		if (off_vci == (u_int)-1)
+		if (!cstate->is_atm)
+			bpf_error(cstate, "'vci' supported only on raw ATM");
+		if (cstate->off_vci == (u_int)-1)
 			abort();
-		b0 = gen_ncmp(OR_LINKHDR, off_vci, BPF_H, 0xffffffff, jtype,
+		b0 = gen_ncmp(cstate, OR_LINKHDR, cstate->off_vci, BPF_H, 0xffffffff, jtype,
 		    reverse, jvalue);
 		break;
 
 	case A_PROTOTYPE:
-		if (off_proto == (u_int)-1)
+		if (cstate->off_proto == (u_int)-1)
 			abort();	/* XXX - this isn't on FreeBSD */
-		b0 = gen_ncmp(OR_LINKHDR, off_proto, BPF_B, 0x0f, jtype,
+		b0 = gen_ncmp(cstate, OR_LINKHDR, cstate->off_proto, BPF_B, 0x0f, jtype,
 		    reverse, jvalue);
 		break;
 
 	case A_MSGTYPE:
-		if (off_payload == (u_int)-1)
+		if (cstate->off_payload == (u_int)-1)
 			abort();
-		b0 = gen_ncmp(OR_LINKHDR, off_payload + MSG_TYPE_POS, BPF_B,
+		b0 = gen_ncmp(cstate, OR_LINKHDR, cstate->off_payload + MSG_TYPE_POS, BPF_B,
 		    0xffffffff, jtype, reverse, jvalue);
 		break;
 
 	case A_CALLREFTYPE:
-		if (!is_atm)
-			bpf_error("'callref' supported only on raw ATM");
-		if (off_proto == (u_int)-1)
+		if (!cstate->is_atm)
+			bpf_error(cstate, "'callref' supported only on raw ATM");
+		if (cstate->off_proto == (u_int)-1)
 			abort();
-		b0 = gen_ncmp(OR_LINKHDR, off_proto, BPF_B, 0xffffffff,
+		b0 = gen_ncmp(cstate, OR_LINKHDR, cstate->off_proto, BPF_B, 0xffffffff,
 		    jtype, reverse, jvalue);
 		break;
 
@@ -8522,8 +8602,7 @@
 }
 
 struct block *
-gen_atmtype_abbrev(type)
-	int type;
+gen_atmtype_abbrev(compiler_state_t *cstate, int type)
 {
 	struct block *b0, *b1;
 
@@ -8531,63 +8610,63 @@
 
 	case A_METAC:
 		/* Get all packets in Meta signalling Circuit */
-		if (!is_atm)
-			bpf_error("'metac' supported only on raw ATM");
-		b0 = gen_atmfield_code(A_VPI, 0, BPF_JEQ, 0);
-		b1 = gen_atmfield_code(A_VCI, 1, BPF_JEQ, 0);
+		if (!cstate->is_atm)
+			bpf_error(cstate, "'metac' supported only on raw ATM");
+		b0 = gen_atmfield_code(cstate, A_VPI, 0, BPF_JEQ, 0);
+		b1 = gen_atmfield_code(cstate, A_VCI, 1, BPF_JEQ, 0);
 		gen_and(b0, b1);
 		break;
 
 	case A_BCC:
 		/* Get all packets in Broadcast Circuit*/
-		if (!is_atm)
-			bpf_error("'bcc' supported only on raw ATM");
-		b0 = gen_atmfield_code(A_VPI, 0, BPF_JEQ, 0);
-		b1 = gen_atmfield_code(A_VCI, 2, BPF_JEQ, 0);
+		if (!cstate->is_atm)
+			bpf_error(cstate, "'bcc' supported only on raw ATM");
+		b0 = gen_atmfield_code(cstate, A_VPI, 0, BPF_JEQ, 0);
+		b1 = gen_atmfield_code(cstate, A_VCI, 2, BPF_JEQ, 0);
 		gen_and(b0, b1);
 		break;
 
 	case A_OAMF4SC:
 		/* Get all cells in Segment OAM F4 circuit*/
-		if (!is_atm)
-			bpf_error("'oam4sc' supported only on raw ATM");
-		b0 = gen_atmfield_code(A_VPI, 0, BPF_JEQ, 0);
-		b1 = gen_atmfield_code(A_VCI, 3, BPF_JEQ, 0);
+		if (!cstate->is_atm)
+			bpf_error(cstate, "'oam4sc' supported only on raw ATM");
+		b0 = gen_atmfield_code(cstate, A_VPI, 0, BPF_JEQ, 0);
+		b1 = gen_atmfield_code(cstate, A_VCI, 3, BPF_JEQ, 0);
 		gen_and(b0, b1);
 		break;
 
 	case A_OAMF4EC:
 		/* Get all cells in End-to-End OAM F4 Circuit*/
-		if (!is_atm)
-			bpf_error("'oam4ec' supported only on raw ATM");
-		b0 = gen_atmfield_code(A_VPI, 0, BPF_JEQ, 0);
-		b1 = gen_atmfield_code(A_VCI, 4, BPF_JEQ, 0);
+		if (!cstate->is_atm)
+			bpf_error(cstate, "'oam4ec' supported only on raw ATM");
+		b0 = gen_atmfield_code(cstate, A_VPI, 0, BPF_JEQ, 0);
+		b1 = gen_atmfield_code(cstate, A_VCI, 4, BPF_JEQ, 0);
 		gen_and(b0, b1);
 		break;
 
 	case A_SC:
 		/*  Get all packets in connection Signalling Circuit */
-		if (!is_atm)
-			bpf_error("'sc' supported only on raw ATM");
-		b0 = gen_atmfield_code(A_VPI, 0, BPF_JEQ, 0);
-		b1 = gen_atmfield_code(A_VCI, 5, BPF_JEQ, 0);
+		if (!cstate->is_atm)
+			bpf_error(cstate, "'sc' supported only on raw ATM");
+		b0 = gen_atmfield_code(cstate, A_VPI, 0, BPF_JEQ, 0);
+		b1 = gen_atmfield_code(cstate, A_VCI, 5, BPF_JEQ, 0);
 		gen_and(b0, b1);
 		break;
 
 	case A_ILMIC:
 		/* Get all packets in ILMI Circuit */
-		if (!is_atm)
-			bpf_error("'ilmic' supported only on raw ATM");
-		b0 = gen_atmfield_code(A_VPI, 0, BPF_JEQ, 0);
-		b1 = gen_atmfield_code(A_VCI, 16, BPF_JEQ, 0);
+		if (!cstate->is_atm)
+			bpf_error(cstate, "'ilmic' supported only on raw ATM");
+		b0 = gen_atmfield_code(cstate, A_VPI, 0, BPF_JEQ, 0);
+		b1 = gen_atmfield_code(cstate, A_VCI, 16, BPF_JEQ, 0);
 		gen_and(b0, b1);
 		break;
 
 	case A_LANE:
 		/* Get all LANE packets */
-		if (!is_atm)
-			bpf_error("'lane' supported only on raw ATM");
-		b1 = gen_atmfield_code(A_PROTOTYPE, PT_LANE, BPF_JEQ, 0);
+		if (!cstate->is_atm)
+			bpf_error(cstate, "'lane' supported only on raw ATM");
+		b1 = gen_atmfield_code(cstate, A_PROTOTYPE, PT_LANE, BPF_JEQ, 0);
 
 		/*
 		 * Arrange that all subsequent tests assume LANE
@@ -8597,21 +8676,21 @@
 		 *
 		 * We assume LANE means Ethernet, not Token Ring.
 		 */
-		PUSH_LINKHDR(DLT_EN10MB, 0,
-		    off_payload + 2,	/* Ethernet header */
+		PUSH_LINKHDR(cstate, DLT_EN10MB, 0,
+		    cstate->off_payload + 2,	/* Ethernet header */
 		    -1);
-		off_linktype.constant_part = off_linkhdr.constant_part + 12;
-		off_linkpl.constant_part = off_linkhdr.constant_part + 14;	/* Ethernet */
-		off_nl = 0;			/* Ethernet II */
-		off_nl_nosnap = 3;		/* 802.3+802.2 */
+		cstate->off_linktype.constant_part = cstate->off_linkhdr.constant_part + 12;
+		cstate->off_linkpl.constant_part = cstate->off_linkhdr.constant_part + 14;	/* Ethernet */
+		cstate->off_nl = 0;			/* Ethernet II */
+		cstate->off_nl_nosnap = 3;		/* 802.3+802.2 */
 		break;
 
 	case A_LLC:
 		/* Get all LLC-encapsulated packets */
-		if (!is_atm)
-			bpf_error("'llc' supported only on raw ATM");
-		b1 = gen_atmfield_code(A_PROTOTYPE, PT_LLC, BPF_JEQ, 0);
-		linktype = prevlinktype;
+		if (!cstate->is_atm)
+			bpf_error(cstate, "'llc' supported only on raw ATM");
+		b1 = gen_atmfield_code(cstate, A_PROTOTYPE, PT_LLC, BPF_JEQ, 0);
+		cstate->linktype = cstate->prevlinktype;
 		break;
 
 	default:
@@ -8628,65 +8707,64 @@
  * For MTP2_HSL, sequences are on 2 bytes, and length on 9 bits
  */
 struct block *
-gen_mtp2type_abbrev(type)
-	int type;
+gen_mtp2type_abbrev(compiler_state_t *cstate, int type)
 {
 	struct block *b0, *b1;
 
 	switch (type) {
 
 	case M_FISU:
-		if ( (linktype != DLT_MTP2) &&
-		     (linktype != DLT_ERF) &&
-		     (linktype != DLT_MTP2_WITH_PHDR) )
-			bpf_error("'fisu' supported only on MTP2");
-		/* gen_ncmp(offrel, offset, size, mask, jtype, reverse, value) */
-		b0 = gen_ncmp(OR_PACKET, off_li, BPF_B, 0x3f, BPF_JEQ, 0, 0);
+		if ( (cstate->linktype != DLT_MTP2) &&
+		     (cstate->linktype != DLT_ERF) &&
+		     (cstate->linktype != DLT_MTP2_WITH_PHDR) )
+			bpf_error(cstate, "'fisu' supported only on MTP2");
+		/* gen_ncmp(cstate, offrel, offset, size, mask, jtype, reverse, value) */
+		b0 = gen_ncmp(cstate, OR_PACKET, cstate->off_li, BPF_B, 0x3f, BPF_JEQ, 0, 0);
 		break;
 
 	case M_LSSU:
-		if ( (linktype != DLT_MTP2) &&
-		     (linktype != DLT_ERF) &&
-		     (linktype != DLT_MTP2_WITH_PHDR) )
-			bpf_error("'lssu' supported only on MTP2");
-		b0 = gen_ncmp(OR_PACKET, off_li, BPF_B, 0x3f, BPF_JGT, 1, 2);
-		b1 = gen_ncmp(OR_PACKET, off_li, BPF_B, 0x3f, BPF_JGT, 0, 0);
+		if ( (cstate->linktype != DLT_MTP2) &&
+		     (cstate->linktype != DLT_ERF) &&
+		     (cstate->linktype != DLT_MTP2_WITH_PHDR) )
+			bpf_error(cstate, "'lssu' supported only on MTP2");
+		b0 = gen_ncmp(cstate, OR_PACKET, cstate->off_li, BPF_B, 0x3f, BPF_JGT, 1, 2);
+		b1 = gen_ncmp(cstate, OR_PACKET, cstate->off_li, BPF_B, 0x3f, BPF_JGT, 0, 0);
 		gen_and(b1, b0);
 		break;
 
 	case M_MSU:
-		if ( (linktype != DLT_MTP2) &&
-		     (linktype != DLT_ERF) &&
-		     (linktype != DLT_MTP2_WITH_PHDR) )
-			bpf_error("'msu' supported only on MTP2");
-		b0 = gen_ncmp(OR_PACKET, off_li, BPF_B, 0x3f, BPF_JGT, 0, 2);
+		if ( (cstate->linktype != DLT_MTP2) &&
+		     (cstate->linktype != DLT_ERF) &&
+		     (cstate->linktype != DLT_MTP2_WITH_PHDR) )
+			bpf_error(cstate, "'msu' supported only on MTP2");
+		b0 = gen_ncmp(cstate, OR_PACKET, cstate->off_li, BPF_B, 0x3f, BPF_JGT, 0, 2);
 		break;
 
 	case MH_FISU:
-		if ( (linktype != DLT_MTP2) &&
-		     (linktype != DLT_ERF) &&
-		     (linktype != DLT_MTP2_WITH_PHDR) )
-			bpf_error("'hfisu' supported only on MTP2_HSL");
-		/* gen_ncmp(offrel, offset, size, mask, jtype, reverse, value) */
-		b0 = gen_ncmp(OR_PACKET, off_li_hsl, BPF_H, 0xff80, BPF_JEQ, 0, 0);
+		if ( (cstate->linktype != DLT_MTP2) &&
+		     (cstate->linktype != DLT_ERF) &&
+		     (cstate->linktype != DLT_MTP2_WITH_PHDR) )
+			bpf_error(cstate, "'hfisu' supported only on MTP2_HSL");
+		/* gen_ncmp(cstate, offrel, offset, size, mask, jtype, reverse, value) */
+		b0 = gen_ncmp(cstate, OR_PACKET, cstate->off_li_hsl, BPF_H, 0xff80, BPF_JEQ, 0, 0);
 		break;
 
 	case MH_LSSU:
-		if ( (linktype != DLT_MTP2) &&
-		     (linktype != DLT_ERF) &&
-		     (linktype != DLT_MTP2_WITH_PHDR) )
-			bpf_error("'hlssu' supported only on MTP2_HSL");
-		b0 = gen_ncmp(OR_PACKET, off_li_hsl, BPF_H, 0xff80, BPF_JGT, 1, 0x0100);
-		b1 = gen_ncmp(OR_PACKET, off_li_hsl, BPF_H, 0xff80, BPF_JGT, 0, 0);
+		if ( (cstate->linktype != DLT_MTP2) &&
+		     (cstate->linktype != DLT_ERF) &&
+		     (cstate->linktype != DLT_MTP2_WITH_PHDR) )
+			bpf_error(cstate, "'hlssu' supported only on MTP2_HSL");
+		b0 = gen_ncmp(cstate, OR_PACKET, cstate->off_li_hsl, BPF_H, 0xff80, BPF_JGT, 1, 0x0100);
+		b1 = gen_ncmp(cstate, OR_PACKET, cstate->off_li_hsl, BPF_H, 0xff80, BPF_JGT, 0, 0);
 		gen_and(b1, b0);
 		break;
 
 	case MH_MSU:
-		if ( (linktype != DLT_MTP2) &&
-		     (linktype != DLT_ERF) &&
-		     (linktype != DLT_MTP2_WITH_PHDR) )
-			bpf_error("'hmsu' supported only on MTP2_HSL");
-		b0 = gen_ncmp(OR_PACKET, off_li_hsl, BPF_H, 0xff80, BPF_JGT, 0, 0x0100);
+		if ( (cstate->linktype != DLT_MTP2) &&
+		     (cstate->linktype != DLT_ERF) &&
+		     (cstate->linktype != DLT_MTP2_WITH_PHDR) )
+			bpf_error(cstate, "'hmsu' supported only on MTP2_HSL");
+		b0 = gen_ncmp(cstate, OR_PACKET, cstate->off_li_hsl, BPF_H, 0xff80, BPF_JGT, 0, 0x0100);
 		break;
 
 	default:
@@ -8696,18 +8774,15 @@
 }
 
 struct block *
-gen_mtp3field_code(mtp3field, jvalue, jtype, reverse)
-	int mtp3field;
-	bpf_u_int32 jvalue;
-	bpf_u_int32 jtype;
-	int reverse;
+gen_mtp3field_code(compiler_state_t *cstate, int mtp3field, bpf_u_int32 jvalue,
+    bpf_u_int32 jtype, int reverse)
 {
 	struct block *b0;
 	bpf_u_int32 val1 , val2 , val3;
-	u_int newoff_sio=off_sio;
-	u_int newoff_opc=off_opc;
-	u_int newoff_dpc=off_dpc;
-	u_int newoff_sls=off_sls;
+	u_int newoff_sio = cstate->off_sio;
+	u_int newoff_opc = cstate->off_opc;
+	u_int newoff_dpc = cstate->off_dpc;
+	u_int newoff_sls = cstate->off_sls;
 
 	switch (mtp3field) {
 
@@ -8716,24 +8791,24 @@
 		/* FALLTHROUGH */
 
 	case M_SIO:
-		if (off_sio == (u_int)-1)
-			bpf_error("'sio' supported only on SS7");
+		if (cstate->off_sio == (u_int)-1)
+			bpf_error(cstate, "'sio' supported only on SS7");
 		/* sio coded on 1 byte so max value 255 */
 		if(jvalue > 255)
-		        bpf_error("sio value %u too big; max value = 255",
+		        bpf_error(cstate, "sio value %u too big; max value = 255",
 		            jvalue);
-		b0 = gen_ncmp(OR_PACKET, newoff_sio, BPF_B, 0xffffffff,
+		b0 = gen_ncmp(cstate, OR_PACKET, newoff_sio, BPF_B, 0xffffffff,
 		    (u_int)jtype, reverse, (u_int)jvalue);
 		break;
 
 	case MH_OPC:
 		newoff_opc+=3;
         case M_OPC:
-	        if (off_opc == (u_int)-1)
-			bpf_error("'opc' supported only on SS7");
+	        if (cstate->off_opc == (u_int)-1)
+			bpf_error(cstate, "'opc' supported only on SS7");
 		/* opc coded on 14 bits so max value 16383 */
 		if (jvalue > 16383)
-		        bpf_error("opc value %u too big; max value = 16383",
+		        bpf_error(cstate, "opc value %u too big; max value = 16383",
 		            jvalue);
 		/* the following instructions are made to convert jvalue
 		 * to the form used to write opc in an ss7 message*/
@@ -8744,7 +8819,7 @@
 		val3 = jvalue & 0x00000003;
 		val3 = val3 <<22;
 		jvalue = val1 + val2 + val3;
-		b0 = gen_ncmp(OR_PACKET, newoff_opc, BPF_W, 0x00c0ff0f,
+		b0 = gen_ncmp(cstate, OR_PACKET, newoff_opc, BPF_W, 0x00c0ff0f,
 		    (u_int)jtype, reverse, (u_int)jvalue);
 		break;
 
@@ -8753,11 +8828,11 @@
 		/* FALLTHROUGH */
 
 	case M_DPC:
-	        if (off_dpc == (u_int)-1)
-			bpf_error("'dpc' supported only on SS7");
+	        if (cstate->off_dpc == (u_int)-1)
+			bpf_error(cstate, "'dpc' supported only on SS7");
 		/* dpc coded on 14 bits so max value 16383 */
 		if (jvalue > 16383)
-		        bpf_error("dpc value %u too big; max value = 16383",
+		        bpf_error(cstate, "dpc value %u too big; max value = 16383",
 		            jvalue);
 		/* the following instructions are made to convert jvalue
 		 * to the forme used to write dpc in an ss7 message*/
@@ -8766,23 +8841,23 @@
 		val2 = jvalue & 0x00003f00;
 		val2 = val2 << 8;
 		jvalue = val1 + val2;
-		b0 = gen_ncmp(OR_PACKET, newoff_dpc, BPF_W, 0xff3f0000,
+		b0 = gen_ncmp(cstate, OR_PACKET, newoff_dpc, BPF_W, 0xff3f0000,
 		    (u_int)jtype, reverse, (u_int)jvalue);
 		break;
 
 	case MH_SLS:
 	  newoff_sls+=3;
 	case M_SLS:
-	        if (off_sls == (u_int)-1)
-			bpf_error("'sls' supported only on SS7");
+	        if (cstate->off_sls == (u_int)-1)
+			bpf_error(cstate, "'sls' supported only on SS7");
 		/* sls coded on 4 bits so max value 15 */
 		if (jvalue > 15)
-		         bpf_error("sls value %u too big; max value = 15",
+		         bpf_error(cstate, "sls value %u too big; max value = 15",
 		             jvalue);
 		/* the following instruction is made to convert jvalue
 		 * to the forme used to write sls in an ss7 message*/
 		jvalue = jvalue << 4;
-		b0 = gen_ncmp(OR_PACKET, newoff_sls, BPF_B, 0xf0,
+		b0 = gen_ncmp(cstate, OR_PACKET, newoff_sls, BPF_B, 0xf0,
 		    (u_int)jtype,reverse, (u_int)jvalue);
 		break;
 
@@ -8793,8 +8868,7 @@
 }
 
 static struct block *
-gen_msg_abbrev(type)
-	int type;
+gen_msg_abbrev(compiler_state_t *cstate, int type)
 {
 	struct block *b1;
 
@@ -8805,27 +8879,27 @@
 	switch (type) {
 
 	case A_SETUP:
-		b1 = gen_atmfield_code(A_MSGTYPE, SETUP, BPF_JEQ, 0);
+		b1 = gen_atmfield_code(cstate, A_MSGTYPE, SETUP, BPF_JEQ, 0);
 		break;
 
 	case A_CALLPROCEED:
-		b1 = gen_atmfield_code(A_MSGTYPE, CALL_PROCEED, BPF_JEQ, 0);
+		b1 = gen_atmfield_code(cstate, A_MSGTYPE, CALL_PROCEED, BPF_JEQ, 0);
 		break;
 
 	case A_CONNECT:
-		b1 = gen_atmfield_code(A_MSGTYPE, CONNECT, BPF_JEQ, 0);
+		b1 = gen_atmfield_code(cstate, A_MSGTYPE, CONNECT, BPF_JEQ, 0);
 		break;
 
 	case A_CONNECTACK:
-		b1 = gen_atmfield_code(A_MSGTYPE, CONNECT_ACK, BPF_JEQ, 0);
+		b1 = gen_atmfield_code(cstate, A_MSGTYPE, CONNECT_ACK, BPF_JEQ, 0);
 		break;
 
 	case A_RELEASE:
-		b1 = gen_atmfield_code(A_MSGTYPE, RELEASE, BPF_JEQ, 0);
+		b1 = gen_atmfield_code(cstate, A_MSGTYPE, RELEASE, BPF_JEQ, 0);
 		break;
 
 	case A_RELEASE_DONE:
-		b1 = gen_atmfield_code(A_MSGTYPE, RELEASE_DONE, BPF_JEQ, 0);
+		b1 = gen_atmfield_code(cstate, A_MSGTYPE, RELEASE_DONE, BPF_JEQ, 0);
 		break;
 
 	default:
@@ -8835,27 +8909,26 @@
 }
 
 struct block *
-gen_atmmulti_abbrev(type)
-	int type;
+gen_atmmulti_abbrev(compiler_state_t *cstate, int type)
 {
 	struct block *b0, *b1;
 
 	switch (type) {
 
 	case A_OAM:
-		if (!is_atm)
-			bpf_error("'oam' supported only on raw ATM");
-		b1 = gen_atmmulti_abbrev(A_OAMF4);
+		if (!cstate->is_atm)
+			bpf_error(cstate, "'oam' supported only on raw ATM");
+		b1 = gen_atmmulti_abbrev(cstate, A_OAMF4);
 		break;
 
 	case A_OAMF4:
-		if (!is_atm)
-			bpf_error("'oamf4' supported only on raw ATM");
+		if (!cstate->is_atm)
+			bpf_error(cstate, "'oamf4' supported only on raw ATM");
 		/* OAM F4 type */
-		b0 = gen_atmfield_code(A_VCI, 3, BPF_JEQ, 0);
-		b1 = gen_atmfield_code(A_VCI, 4, BPF_JEQ, 0);
+		b0 = gen_atmfield_code(cstate, A_VCI, 3, BPF_JEQ, 0);
+		b1 = gen_atmfield_code(cstate, A_VCI, 4, BPF_JEQ, 0);
 		gen_or(b0, b1);
-		b0 = gen_atmfield_code(A_VPI, 0, BPF_JEQ, 0);
+		b0 = gen_atmfield_code(cstate, A_VPI, 0, BPF_JEQ, 0);
 		gen_and(b0, b1);
 		break;
 
@@ -8864,36 +8937,36 @@
 		 * Get Q.2931 signalling messages for switched
 		 * virtual connection
 		 */
-		if (!is_atm)
-			bpf_error("'connectmsg' supported only on raw ATM");
-		b0 = gen_msg_abbrev(A_SETUP);
-		b1 = gen_msg_abbrev(A_CALLPROCEED);
+		if (!cstate->is_atm)
+			bpf_error(cstate, "'connectmsg' supported only on raw ATM");
+		b0 = gen_msg_abbrev(cstate, A_SETUP);
+		b1 = gen_msg_abbrev(cstate, A_CALLPROCEED);
 		gen_or(b0, b1);
-		b0 = gen_msg_abbrev(A_CONNECT);
+		b0 = gen_msg_abbrev(cstate, A_CONNECT);
 		gen_or(b0, b1);
-		b0 = gen_msg_abbrev(A_CONNECTACK);
+		b0 = gen_msg_abbrev(cstate, A_CONNECTACK);
 		gen_or(b0, b1);
-		b0 = gen_msg_abbrev(A_RELEASE);
+		b0 = gen_msg_abbrev(cstate, A_RELEASE);
 		gen_or(b0, b1);
-		b0 = gen_msg_abbrev(A_RELEASE_DONE);
+		b0 = gen_msg_abbrev(cstate, A_RELEASE_DONE);
 		gen_or(b0, b1);
-		b0 = gen_atmtype_abbrev(A_SC);
+		b0 = gen_atmtype_abbrev(cstate, A_SC);
 		gen_and(b0, b1);
 		break;
 
 	case A_METACONNECT:
-		if (!is_atm)
-			bpf_error("'metaconnect' supported only on raw ATM");
-		b0 = gen_msg_abbrev(A_SETUP);
-		b1 = gen_msg_abbrev(A_CALLPROCEED);
+		if (!cstate->is_atm)
+			bpf_error(cstate, "'metaconnect' supported only on raw ATM");
+		b0 = gen_msg_abbrev(cstate, A_SETUP);
+		b1 = gen_msg_abbrev(cstate, A_CALLPROCEED);
 		gen_or(b0, b1);
-		b0 = gen_msg_abbrev(A_CONNECT);
+		b0 = gen_msg_abbrev(cstate, A_CONNECT);
 		gen_or(b0, b1);
-		b0 = gen_msg_abbrev(A_RELEASE);
+		b0 = gen_msg_abbrev(cstate, A_RELEASE);
 		gen_or(b0, b1);
-		b0 = gen_msg_abbrev(A_RELEASE_DONE);
+		b0 = gen_msg_abbrev(cstate, A_RELEASE_DONE);
 		gen_or(b0, b1);
-		b0 = gen_atmtype_abbrev(A_METAC);
+		b0 = gen_atmtype_abbrev(cstate, A_METAC);
 		gen_and(b0, b1);
 		break;
 
diff --git a/gencode.h b/gencode.h
index 67ed0dc..2b089d2 100644
--- a/gencode.h
+++ b/gencode.h
@@ -281,85 +281,115 @@
 	unsigned char pad;
 };
 
-struct arth *gen_loadi(int);
-struct arth *gen_load(int, struct arth *, int);
-struct arth *gen_loadlen(void);
-struct arth *gen_neg(struct arth *);
-struct arth *gen_arth(int, struct arth *, struct arth *);
+struct _compiler_state;
+
+typedef struct _compiler_state compiler_state_t;
+
+struct arth *gen_loadi(compiler_state_t *, int);
+struct arth *gen_load(compiler_state_t *, int, struct arth *, int);
+struct arth *gen_loadlen(compiler_state_t *);
+struct arth *gen_neg(compiler_state_t *, struct arth *);
+struct arth *gen_arth(compiler_state_t *, int, struct arth *, struct arth *);
 
 void gen_and(struct block *, struct block *);
 void gen_or(struct block *, struct block *);
 void gen_not(struct block *);
 
-struct block *gen_scode(const char *, struct qual);
-struct block *gen_ecode(const u_char *, struct qual);
-struct block *gen_acode(const u_char *, struct qual);
-struct block *gen_mcode(const char *, const char *, unsigned int, struct qual);
+struct block *gen_scode(compiler_state_t *, const char *, struct qual);
+struct block *gen_ecode(compiler_state_t *, const u_char *, struct qual);
+struct block *gen_acode(compiler_state_t *, const u_char *, struct qual);
+struct block *gen_mcode(compiler_state_t *, const char *, const char *,
+    unsigned int, struct qual);
 #ifdef INET6
-struct block *gen_mcode6(const char *, const char *, unsigned int, struct qual);
+struct block *gen_mcode6(compiler_state_t *, const char *, const char *,
+    unsigned int, struct qual);
 #endif
-struct block *gen_ncode(const char *, bpf_u_int32, struct qual);
-struct block *gen_proto_abbrev(int);
-struct block *gen_relation(int, struct arth *, struct arth *, int);
-struct block *gen_less(int);
-struct block *gen_greater(int);
-struct block *gen_byteop(int, int, int);
-struct block *gen_broadcast(int);
-struct block *gen_multicast(int);
-struct block *gen_inbound(int);
+struct block *gen_ncode(compiler_state_t *, const char *, bpf_u_int32,
+    struct qual);
+struct block *gen_proto_abbrev(compiler_state_t *, int);
+struct block *gen_relation(compiler_state_t *, int, struct arth *,
+    struct arth *, int);
+struct block *gen_less(compiler_state_t *, int);
+struct block *gen_greater(compiler_state_t *, int);
+struct block *gen_byteop(compiler_state_t *, int, int, int);
+struct block *gen_broadcast(compiler_state_t *, int);
+struct block *gen_multicast(compiler_state_t *, int);
+struct block *gen_inbound(compiler_state_t *, int);
 
-struct block *gen_llc(void);
-struct block *gen_llc_i(void);
-struct block *gen_llc_s(void);
-struct block *gen_llc_u(void);
-struct block *gen_llc_s_subtype(bpf_u_int32);
-struct block *gen_llc_u_subtype(bpf_u_int32);
+struct block *gen_llc(compiler_state_t *);
+struct block *gen_llc_i(compiler_state_t *);
+struct block *gen_llc_s(compiler_state_t *);
+struct block *gen_llc_u(compiler_state_t *);
+struct block *gen_llc_s_subtype(compiler_state_t *, bpf_u_int32);
+struct block *gen_llc_u_subtype(compiler_state_t *, bpf_u_int32);
 
-struct block *gen_vlan(int);
-struct block *gen_mpls(int);
+struct block *gen_vlan(compiler_state_t *, int);
+struct block *gen_mpls(compiler_state_t *, int);
 
-struct block *gen_pppoed(void);
-struct block *gen_pppoes(int);
+struct block *gen_pppoed(compiler_state_t *);
+struct block *gen_pppoes(compiler_state_t *, int);
 
-struct block *gen_geneve(int);
+struct block *gen_geneve(compiler_state_t *, int);
 
-struct block *gen_atmfield_code(int atmfield, bpf_int32 jvalue, bpf_u_int32 jtype, int reverse);
-struct block *gen_atmtype_abbrev(int type);
-struct block *gen_atmmulti_abbrev(int type);
+struct block *gen_atmfield_code(compiler_state_t *, int, bpf_int32,
+    bpf_u_int32, int);
+struct block *gen_atmtype_abbrev(compiler_state_t *, int type);
+struct block *gen_atmmulti_abbrev(compiler_state_t *, int type);
 
-struct block *gen_mtp2type_abbrev(int type);
-struct block *gen_mtp3field_code(int mtp3field, bpf_u_int32 jvalue, bpf_u_int32 jtype, int reverse);
+struct block *gen_mtp2type_abbrev(compiler_state_t *, int type);
+struct block *gen_mtp3field_code(compiler_state_t *, int, bpf_u_int32,
+    bpf_u_int32, int);
 
-struct block *gen_pf_ifname(const char *);
-struct block *gen_pf_rnr(int);
-struct block *gen_pf_srnr(int);
-struct block *gen_pf_ruleset(char *);
-struct block *gen_pf_reason(int);
-struct block *gen_pf_action(int);
-struct block *gen_pf_dir(int);
+struct block *gen_pf_ifname(compiler_state_t *, const char *);
+struct block *gen_pf_rnr(compiler_state_t *, int);
+struct block *gen_pf_srnr(compiler_state_t *, int);
+struct block *gen_pf_ruleset(compiler_state_t *, char *);
+struct block *gen_pf_reason(compiler_state_t *, int);
+struct block *gen_pf_action(compiler_state_t *, int);
 
-struct block *gen_p80211_type(int, int);
-struct block *gen_p80211_fcdir(int);
+struct block *gen_p80211_type(compiler_state_t *, int, int);
+struct block *gen_p80211_fcdir(compiler_state_t *, int);
 
-void bpf_optimize(struct block **);
-void bpf_error(const char *, ...)
+/*
+ * Representation of a program as a tree of blocks, plus current mark.
+ * A block is marked if only if its mark equals the current mark.
+ * Rather than traverse the code array, marking each item, 'cur_mark'
+ * is incremented.  This automatically makes each element unmarked.
+ */
+#define isMarked(icp, p) ((p)->mark == (icp)->cur_mark)
+#define unMarkAll(icp) (icp)->cur_mark += 1
+#define Mark(icp, p) ((p)->mark = (icp)->cur_mark)
+
+struct icode {
+	struct block *root;
+	int cur_mark;
+};
+
+void bpf_optimize(compiler_state_t *, struct icode *ic);
+void bpf_syntax_error(compiler_state_t *, const char *);
+void bpf_error(compiler_state_t *, const char *, ...)
     __attribute__((noreturn))
 #ifdef __ATTRIBUTE___FORMAT_OK
-    __attribute__((format (printf, 1, 2)))
+    __attribute__((format (printf, 2, 3)))
 #endif /* __ATTRIBUTE___FORMAT_OK */
     ;
 
-void finish_parse(struct block *);
-char *sdup(const char *);
+void finish_parse(compiler_state_t *, struct block *);
+char *sdup(compiler_state_t *, const char *);
 
-struct bpf_insn *icode_to_fcode(struct block *, u_int *);
-int pcap_parse(void);
-void lex_init(const char *);
-void lex_cleanup(void);
+struct _opt_state;
+typedef struct _opt_state opt_state_t;
+
+struct bpf_insn *icode_to_fcode(compiler_state_t *, struct icode *,
+    struct block *, u_int *);
 void sappend(struct slist *, struct slist *);
 
+/*
+ * Older versions of Bison don't put this declaration in
+ * grammar.h.
+ */
+int pcap_parse(void *, compiler_state_t *);
+
 /* XXX */
 #define JT(b)  ((b)->et.succ)
 #define JF(b)  ((b)->ef.succ)
-
-extern int no_optimize;
diff --git a/grammar.c b/grammar.c
index f5aa791..673449b 100644
--- a/grammar.c
+++ b/grammar.c
@@ -50,7 +50,7 @@
 #define YYSKELETON_NAME "yacc.c"
 
 /* Pure parsers.  */
-#define YYPURE 0
+#define YYPURE 1
 
 /* Push parsers.  */
 #define YYPUSH 0
@@ -66,11 +66,9 @@
 #define yydebug         pcap_debug
 #define yynerrs         pcap_nerrs
 
-#define yylval          pcap_lval
-#define yychar          pcap_char
 
 /* Copy the first part of user declarations.  */
-#line 1 "grammar.y" /* yacc.c:339  */
+#line 26 "grammar.y" /* yacc.c:339  */
 
 /*
  * Copyright (c) 1988, 1989, 1990, 1991, 1992, 1993, 1994, 1995, 1996
@@ -98,16 +96,16 @@
 #include "config.h"
 #endif
 
-#ifdef WIN32
+#ifdef _WIN32
 #include <pcap-stdinc.h>
-#else /* WIN32 */
+#else /* _WIN32 */
 #include <sys/types.h>
 #include <sys/socket.h>
-#endif /* WIN32 */
+#endif /* _WIN32 */
 
 #include <stdlib.h>
 
-#ifndef WIN32
+#ifndef _WIN32
 #if __STDC__
 struct mbuf;
 struct rtentry;
@@ -115,13 +113,16 @@
 
 #include <netinet/in.h>
 #include <arpa/inet.h>
-#endif /* WIN32 */
+#endif /* _WIN32 */
 
 #include <stdio.h>
 
 #include "pcap-int.h"
 
 #include "gencode.h"
+#include "grammar.h"
+#include "scanner.h"
+
 #ifdef HAVE_NET_PFVAR_H
 #include <net/if.h>
 #include <net/pfvar.h>
@@ -242,31 +243,18 @@
 	return (-1);
 }
 
-int n_errors = 0;
-
 static struct qual qerr = { Q_UNDEF, Q_UNDEF, Q_UNDEF, Q_UNDEF };
 
 static void
-yyerror(const char *msg)
+yyerror(void *yyscanner, compiler_state_t *cstate, const char *msg)
 {
-	++n_errors;
-	bpf_error("%s", msg);
+	bpf_syntax_error(cstate, msg);
 	/* NOTREACHED */
 }
 
-#ifdef NEED_YYPARSE_WRAPPER
-int yyparse(void);
-
-int
-pcap_parse()
-{
-	return (yyparse());
-}
-#endif
-
 #ifdef HAVE_NET_PFVAR_H
 static int
-pfreason_to_num(const char *reason)
+pfreason_to_num(compiler_state_t *cstate, const char *reason)
 {
 	const char *reasons[] = PFRES_NAMES;
 	int i;
@@ -275,12 +263,12 @@
 		if (pcap_strcasecmp(reason, reasons[i]) == 0)
 			return (i);
 	}
-	bpf_error("unknown PF reason");
+	bpf_error(cstate, "unknown PF reason");
 	/*NOTREACHED*/
 }
 
 static int
-pfaction_to_num(const char *action)
+pfaction_to_num(compiler_state_t *cstate, const char *action)
 {
 	if (pcap_strcasecmp(action, "pass") == 0 ||
 	    pcap_strcasecmp(action, "accept") == 0)
@@ -299,15 +287,15 @@
 		return (PF_NORDR);
 #endif
 	else {
-		bpf_error("unknown PF action");
+		bpf_error(cstate, "unknown PF action");
 		/*NOTREACHED*/
 	}
 }
 #else /* !HAVE_NET_PFVAR_H */
 static int
-pfreason_to_num(const char *reason)
+pfreason_to_num(compiler_state_t *cstate, const char *reason)
 {
-	bpf_error("libpcap was compiled on a machine without pf support");
+	bpf_error(cstate, "libpcap was compiled on a machine without pf support");
 	/*NOTREACHED*/
 
 	/* this is to make the VC compiler happy */
@@ -315,9 +303,9 @@
 }
 
 static int
-pfaction_to_num(const char *action)
+pfaction_to_num(compiler_state_t *cstate, const char *action)
 {
-	bpf_error("libpcap was compiled on a machine without pf support");
+	bpf_error(cstate, "libpcap was compiled on a machine without pf support");
 	/*NOTREACHED*/
 
 	/* this is to make the VC compiler happy */
@@ -325,7 +313,7 @@
 }
 #endif /* HAVE_NET_PFVAR_H */
 
-#line 329 "y.tab.c" /* yacc.c:339  */
+#line 317 "grammar.c" /* yacc.c:339  */
 
 # ifndef YY_NULLPTR
 #  if defined __cplusplus && 201103L <= __cplusplus
@@ -344,9 +332,9 @@
 #endif
 
 /* In a future release of Bison, this section will be replaced
-   by #include "y.tab.h".  */
-#ifndef YY_PCAP_Y_TAB_H_INCLUDED
-# define YY_PCAP_Y_TAB_H_INCLUDED
+   by #include "grammar.h".  */
+#ifndef YY_PCAP_GRAMMAR_H_INCLUDED
+# define YY_PCAP_GRAMMAR_H_INCLUDED
 /* Debug traces.  */
 #ifndef YYDEBUG
 # define YYDEBUG 0
@@ -607,7 +595,7 @@
 typedef union YYSTYPE YYSTYPE;
 union YYSTYPE
 {
-#line 256 "grammar.y" /* yacc.c:355  */
+#line 271 "grammar.y" /* yacc.c:355  */
 
 	int i;
 	bpf_u_int32 h;
@@ -623,22 +611,21 @@
 	} blk;
 	struct block *rblk;
 
-#line 627 "y.tab.c" /* yacc.c:355  */
+#line 615 "grammar.c" /* yacc.c:355  */
 };
 # define YYSTYPE_IS_TRIVIAL 1
 # define YYSTYPE_IS_DECLARED 1
 #endif
 
 
-extern YYSTYPE pcap_lval;
 
-int pcap_parse (void);
+int pcap_parse (void *yyscanner, compiler_state_t *cstate);
 
-#endif /* !YY_PCAP_Y_TAB_H_INCLUDED  */
+#endif /* !YY_PCAP_GRAMMAR_H_INCLUDED  */
 
 /* Copy the second part of user declarations.  */
 
-#line 642 "y.tab.c" /* yacc.c:358  */
+#line 629 "grammar.c" /* yacc.c:358  */
 
 #ifdef short
 # undef short
@@ -947,29 +934,29 @@
   /* YYRLINE[YYN] -- Source line where rule number YYN was defined.  */
 static const yytype_uint16 yyrline[] =
 {
-       0,   330,   330,   334,   336,   338,   339,   340,   341,   342,
-     344,   346,   348,   349,   351,   353,   354,   356,   358,   371,
-     380,   389,   398,   407,   409,   411,   413,   414,   415,   417,
-     419,   421,   422,   424,   425,   426,   427,   428,   429,   431,
-     432,   433,   434,   436,   438,   439,   440,   441,   442,   443,
-     446,   447,   450,   451,   452,   453,   454,   455,   456,   457,
-     458,   459,   460,   461,   464,   465,   466,   467,   470,   472,
-     473,   474,   475,   476,   477,   478,   479,   480,   481,   482,
-     483,   484,   485,   486,   487,   488,   489,   490,   491,   492,
-     493,   494,   495,   496,   497,   498,   499,   500,   501,   502,
-     503,   504,   505,   506,   507,   508,   509,   510,   512,   513,
-     514,   515,   516,   517,   518,   519,   520,   521,   522,   523,
-     524,   525,   526,   527,   528,   529,   530,   533,   534,   535,
-     536,   537,   538,   541,   546,   549,   553,   556,   557,   563,
-     564,   584,   600,   601,   622,   625,   626,   639,   640,   643,
-     646,   647,   648,   650,   651,   652,   654,   655,   657,   658,
-     659,   660,   661,   662,   663,   664,   665,   666,   667,   668,
-     669,   670,   671,   673,   674,   675,   676,   677,   679,   680,
-     682,   683,   684,   685,   686,   687,   688,   690,   691,   692,
-     693,   696,   697,   699,   700,   701,   702,   704,   711,   712,
-     715,   716,   717,   718,   719,   720,   723,   724,   725,   726,
-     727,   728,   729,   730,   732,   733,   734,   735,   737,   750,
-     751
+       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
 };
 #endif
 
@@ -1416,7 +1403,7 @@
     }                                                           \
   else                                                          \
     {                                                           \
-      yyerror (YY_("syntax error: cannot back up")); \
+      yyerror (yyscanner, cstate, YY_("syntax error: cannot back up")); \
       YYERROR;                                                  \
     }                                                           \
 while (0)
@@ -1453,7 +1440,7 @@
     {                                                                     \
       YYFPRINTF (stderr, "%s ", Title);                                   \
       yy_symbol_print (stderr,                                            \
-                  Type, Value); \
+                  Type, Value, yyscanner, cstate); \
       YYFPRINTF (stderr, "\n");                                           \
     }                                                                     \
 } while (0)
@@ -1464,10 +1451,12 @@
 `----------------------------------------*/
 
 static void
-yy_symbol_value_print (FILE *yyoutput, int yytype, YYSTYPE const * const yyvaluep)
+yy_symbol_value_print (FILE *yyoutput, int yytype, YYSTYPE const * const yyvaluep, void *yyscanner, compiler_state_t *cstate)
 {
   FILE *yyo = yyoutput;
   YYUSE (yyo);
+  YYUSE (yyscanner);
+  YYUSE (cstate);
   if (!yyvaluep)
     return;
 # ifdef YYPRINT
@@ -1483,12 +1472,12 @@
 `--------------------------------*/
 
 static void
-yy_symbol_print (FILE *yyoutput, int yytype, YYSTYPE const * const yyvaluep)
+yy_symbol_print (FILE *yyoutput, int yytype, YYSTYPE const * const yyvaluep, void *yyscanner, compiler_state_t *cstate)
 {
   YYFPRINTF (yyoutput, "%s %s (",
              yytype < YYNTOKENS ? "token" : "nterm", yytname[yytype]);
 
-  yy_symbol_value_print (yyoutput, yytype, yyvaluep);
+  yy_symbol_value_print (yyoutput, yytype, yyvaluep, yyscanner, cstate);
   YYFPRINTF (yyoutput, ")");
 }
 
@@ -1521,7 +1510,7 @@
 `------------------------------------------------*/
 
 static void
-yy_reduce_print (yytype_int16 *yyssp, YYSTYPE *yyvsp, int yyrule)
+yy_reduce_print (yytype_int16 *yyssp, YYSTYPE *yyvsp, int yyrule, void *yyscanner, compiler_state_t *cstate)
 {
   unsigned long int yylno = yyrline[yyrule];
   int yynrhs = yyr2[yyrule];
@@ -1535,7 +1524,7 @@
       yy_symbol_print (stderr,
                        yystos[yyssp[yyi + 1 - yynrhs]],
                        &(yyvsp[(yyi + 1) - (yynrhs)])
-                                              );
+                                              , yyscanner, cstate);
       YYFPRINTF (stderr, "\n");
     }
 }
@@ -1543,7 +1532,7 @@
 # define YY_REDUCE_PRINT(Rule)          \
 do {                                    \
   if (yydebug)                          \
-    yy_reduce_print (yyssp, yyvsp, Rule); \
+    yy_reduce_print (yyssp, yyvsp, Rule, yyscanner, cstate); \
 } while (0)
 
 /* Nonzero means print parse trace.  It is left uninitialized so that
@@ -1801,9 +1790,11 @@
 `-----------------------------------------------*/
 
 static void
-yydestruct (const char *yymsg, int yytype, YYSTYPE *yyvaluep)
+yydestruct (const char *yymsg, int yytype, YYSTYPE *yyvaluep, void *yyscanner, compiler_state_t *cstate)
 {
   YYUSE (yyvaluep);
+  YYUSE (yyscanner);
+  YYUSE (cstate);
   if (!yymsg)
     yymsg = "Deleting";
   YY_SYMBOL_PRINT (yymsg, yytype, yyvaluep, yylocationp);
@@ -1816,22 +1807,26 @@
 
 
 
-/* The lookahead symbol.  */
-int yychar;
-
-/* The semantic value of the lookahead symbol.  */
-YYSTYPE yylval;
-/* Number of syntax errors so far.  */
-int yynerrs;
-
-
 /*----------.
 | yyparse.  |
 `----------*/
 
 int
-yyparse (void)
+yyparse (void *yyscanner, compiler_state_t *cstate)
 {
+/* The lookahead symbol.  */
+int yychar;
+
+
+/* The semantic value of the lookahead symbol.  */
+/* Default value used for initialization, for pacifying older GCCs
+   or non-GCC compilers.  */
+YY_INITIAL_VALUE (static YYSTYPE yyval_default;)
+YYSTYPE yylval YY_INITIAL_VALUE (= yyval_default);
+
+    /* Number of syntax errors so far.  */
+    int yynerrs;
+
     int yystate;
     /* Number of tokens to shift before error messages enabled.  */
     int yyerrstatus;
@@ -1986,7 +1981,7 @@
   if (yychar == YYEMPTY)
     {
       YYDPRINTF ((stderr, "Reading a token: "));
-      yychar = yylex ();
+      yychar = yylex (&yylval, yyscanner);
     }
 
   if (yychar <= YYEOF)
@@ -2065,138 +2060,138 @@
   switch (yyn)
     {
         case 2:
-#line 331 "grammar.y" /* yacc.c:1646  */
+#line 346 "grammar.y" /* yacc.c:1646  */
     {
-	finish_parse((yyvsp[0].blk).b);
+	finish_parse(cstate, (yyvsp[0].blk).b);
 }
-#line 2073 "y.tab.c" /* yacc.c:1646  */
+#line 2068 "grammar.c" /* yacc.c:1646  */
     break;
 
   case 4:
-#line 336 "grammar.y" /* yacc.c:1646  */
+#line 351 "grammar.y" /* yacc.c:1646  */
     { (yyval.blk).q = qerr; }
-#line 2079 "y.tab.c" /* yacc.c:1646  */
+#line 2074 "grammar.c" /* yacc.c:1646  */
     break;
 
   case 6:
-#line 339 "grammar.y" /* yacc.c:1646  */
+#line 354 "grammar.y" /* yacc.c:1646  */
     { gen_and((yyvsp[-2].blk).b, (yyvsp[0].blk).b); (yyval.blk) = (yyvsp[0].blk); }
-#line 2085 "y.tab.c" /* yacc.c:1646  */
+#line 2080 "grammar.c" /* yacc.c:1646  */
     break;
 
   case 7:
-#line 340 "grammar.y" /* yacc.c:1646  */
+#line 355 "grammar.y" /* yacc.c:1646  */
     { gen_and((yyvsp[-2].blk).b, (yyvsp[0].blk).b); (yyval.blk) = (yyvsp[0].blk); }
-#line 2091 "y.tab.c" /* yacc.c:1646  */
+#line 2086 "grammar.c" /* yacc.c:1646  */
     break;
 
   case 8:
-#line 341 "grammar.y" /* yacc.c:1646  */
+#line 356 "grammar.y" /* yacc.c:1646  */
     { gen_or((yyvsp[-2].blk).b, (yyvsp[0].blk).b); (yyval.blk) = (yyvsp[0].blk); }
-#line 2097 "y.tab.c" /* yacc.c:1646  */
+#line 2092 "grammar.c" /* yacc.c:1646  */
     break;
 
   case 9:
-#line 342 "grammar.y" /* yacc.c:1646  */
+#line 357 "grammar.y" /* yacc.c:1646  */
     { gen_or((yyvsp[-2].blk).b, (yyvsp[0].blk).b); (yyval.blk) = (yyvsp[0].blk); }
-#line 2103 "y.tab.c" /* yacc.c:1646  */
+#line 2098 "grammar.c" /* yacc.c:1646  */
     break;
 
   case 10:
-#line 344 "grammar.y" /* yacc.c:1646  */
+#line 359 "grammar.y" /* yacc.c:1646  */
     { (yyval.blk) = (yyvsp[-1].blk); }
-#line 2109 "y.tab.c" /* yacc.c:1646  */
+#line 2104 "grammar.c" /* yacc.c:1646  */
     break;
 
   case 11:
-#line 346 "grammar.y" /* yacc.c:1646  */
+#line 361 "grammar.y" /* yacc.c:1646  */
     { (yyval.blk) = (yyvsp[-1].blk); }
-#line 2115 "y.tab.c" /* yacc.c:1646  */
+#line 2110 "grammar.c" /* yacc.c:1646  */
     break;
 
   case 13:
-#line 349 "grammar.y" /* yacc.c:1646  */
-    { (yyval.blk).b = gen_ncode(NULL, (bpf_u_int32)(yyvsp[0].i),
+#line 364 "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 2122 "y.tab.c" /* yacc.c:1646  */
+#line 2117 "grammar.c" /* yacc.c:1646  */
     break;
 
   case 14:
-#line 351 "grammar.y" /* yacc.c:1646  */
+#line 366 "grammar.y" /* yacc.c:1646  */
     { (yyval.blk) = (yyvsp[-1].blk); }
-#line 2128 "y.tab.c" /* yacc.c:1646  */
+#line 2123 "grammar.c" /* yacc.c:1646  */
     break;
 
   case 15:
-#line 353 "grammar.y" /* yacc.c:1646  */
-    { (yyval.blk).b = gen_scode((yyvsp[0].s), (yyval.blk).q = (yyvsp[-1].blk).q); }
-#line 2134 "y.tab.c" /* yacc.c:1646  */
+#line 368 "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  */
     break;
 
   case 16:
-#line 354 "grammar.y" /* yacc.c:1646  */
-    { (yyval.blk).b = gen_mcode((yyvsp[-2].s), NULL, (yyvsp[0].i),
+#line 369 "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 2141 "y.tab.c" /* yacc.c:1646  */
+#line 2136 "grammar.c" /* yacc.c:1646  */
     break;
 
   case 17:
-#line 356 "grammar.y" /* yacc.c:1646  */
-    { (yyval.blk).b = gen_mcode((yyvsp[-2].s), (yyvsp[0].s), 0,
+#line 371 "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 2148 "y.tab.c" /* yacc.c:1646  */
+#line 2143 "grammar.c" /* yacc.c:1646  */
     break;
 
   case 18:
-#line 358 "grammar.y" /* yacc.c:1646  */
+#line 373 "grammar.y" /* yacc.c:1646  */
     {
 				  /* Decide how to parse HID based on proto */
 				  (yyval.blk).q = (yyvsp[-1].blk).q;
 				  if ((yyval.blk).q.addr == Q_PORT)
-				  	bpf_error("'port' modifier applied to ip host");
+				  	bpf_error(cstate, "'port' modifier applied to ip host");
 				  else if ((yyval.blk).q.addr == Q_PORTRANGE)
-				  	bpf_error("'portrange' modifier applied to ip host");
+				  	bpf_error(cstate, "'portrange' modifier applied to ip host");
 				  else if ((yyval.blk).q.addr == Q_PROTO)
-				  	bpf_error("'proto' modifier applied to ip host");
+				  	bpf_error(cstate, "'proto' modifier applied to ip host");
 				  else if ((yyval.blk).q.addr == Q_PROTOCHAIN)
-				  	bpf_error("'protochain' modifier applied to ip host");
-				  (yyval.blk).b = gen_ncode((yyvsp[0].s), 0, (yyval.blk).q);
+				  	bpf_error(cstate, "'protochain' modifier applied to ip host");
+				  (yyval.blk).b = gen_ncode(cstate, (yyvsp[0].s), 0, (yyval.blk).q);
 				}
-#line 2166 "y.tab.c" /* yacc.c:1646  */
+#line 2161 "grammar.c" /* yacc.c:1646  */
     break;
 
   case 19:
-#line 371 "grammar.y" /* yacc.c:1646  */
+#line 386 "grammar.y" /* yacc.c:1646  */
     {
 #ifdef INET6
-				  (yyval.blk).b = gen_mcode6((yyvsp[-2].s), NULL, (yyvsp[0].i),
+				  (yyval.blk).b = gen_mcode6(cstate, (yyvsp[-2].s), NULL, (yyvsp[0].i),
 				    (yyval.blk).q = (yyvsp[-3].blk).q);
 #else
-				  bpf_error("'ip6addr/prefixlen' not supported "
+				  bpf_error(cstate, "'ip6addr/prefixlen' not supported "
 					"in this configuration");
 #endif /*INET6*/
 				}
-#line 2180 "y.tab.c" /* yacc.c:1646  */
+#line 2175 "grammar.c" /* yacc.c:1646  */
     break;
 
   case 20:
-#line 380 "grammar.y" /* yacc.c:1646  */
+#line 395 "grammar.y" /* yacc.c:1646  */
     {
 #ifdef INET6
-				  (yyval.blk).b = gen_mcode6((yyvsp[0].s), 0, 128,
+				  (yyval.blk).b = gen_mcode6(cstate, (yyvsp[0].s), 0, 128,
 				    (yyval.blk).q = (yyvsp[-1].blk).q);
 #else
-				  bpf_error("'ip6addr' not supported "
+				  bpf_error(cstate, "'ip6addr' not supported "
 					"in this configuration");
 #endif /*INET6*/
 				}
-#line 2194 "y.tab.c" /* yacc.c:1646  */
+#line 2189 "grammar.c" /* yacc.c:1646  */
     break;
 
   case 21:
-#line 389 "grammar.y" /* yacc.c:1646  */
+#line 404 "grammar.y" /* yacc.c:1646  */
     {
-				  (yyval.blk).b = gen_ecode((yyvsp[0].e), (yyval.blk).q = (yyvsp[-1].blk).q);
+				  (yyval.blk).b = gen_ecode(cstate, (yyvsp[0].e), (yyval.blk).q = (yyvsp[-1].blk).q);
 				  /*
 				   * $1 was allocated by "pcap_ether_aton()",
 				   * so we must free it now that we're done
@@ -2204,13 +2199,13 @@
 				   */
 				  free((yyvsp[0].e));
 				}
-#line 2208 "y.tab.c" /* yacc.c:1646  */
+#line 2203 "grammar.c" /* yacc.c:1646  */
     break;
 
   case 22:
-#line 398 "grammar.y" /* yacc.c:1646  */
+#line 413 "grammar.y" /* yacc.c:1646  */
     {
-				  (yyval.blk).b = gen_acode((yyvsp[0].e), (yyval.blk).q = (yyvsp[-1].blk).q);
+				  (yyval.blk).b = gen_acode(cstate, (yyvsp[0].e), (yyval.blk).q = (yyvsp[-1].blk).q);
 				  /*
 				   * $1 was allocated by "pcap_ether_aton()",
 				   * so we must free it now that we're done
@@ -2218,697 +2213,697 @@
 				   */
 				  free((yyvsp[0].e));
 				}
-#line 2222 "y.tab.c" /* yacc.c:1646  */
+#line 2217 "grammar.c" /* yacc.c:1646  */
     break;
 
   case 23:
-#line 407 "grammar.y" /* yacc.c:1646  */
+#line 422 "grammar.y" /* yacc.c:1646  */
     { gen_not((yyvsp[0].blk).b); (yyval.blk) = (yyvsp[0].blk); }
-#line 2228 "y.tab.c" /* yacc.c:1646  */
+#line 2223 "grammar.c" /* yacc.c:1646  */
     break;
 
   case 24:
-#line 409 "grammar.y" /* yacc.c:1646  */
+#line 424 "grammar.y" /* yacc.c:1646  */
     { (yyval.blk) = (yyvsp[-1].blk); }
-#line 2234 "y.tab.c" /* yacc.c:1646  */
+#line 2229 "grammar.c" /* yacc.c:1646  */
     break;
 
   case 25:
-#line 411 "grammar.y" /* yacc.c:1646  */
+#line 426 "grammar.y" /* yacc.c:1646  */
     { (yyval.blk) = (yyvsp[-1].blk); }
-#line 2240 "y.tab.c" /* yacc.c:1646  */
+#line 2235 "grammar.c" /* yacc.c:1646  */
     break;
 
   case 27:
-#line 414 "grammar.y" /* yacc.c:1646  */
+#line 429 "grammar.y" /* yacc.c:1646  */
     { gen_and((yyvsp[-2].blk).b, (yyvsp[0].blk).b); (yyval.blk) = (yyvsp[0].blk); }
-#line 2246 "y.tab.c" /* yacc.c:1646  */
+#line 2241 "grammar.c" /* yacc.c:1646  */
     break;
 
   case 28:
-#line 415 "grammar.y" /* yacc.c:1646  */
+#line 430 "grammar.y" /* yacc.c:1646  */
     { gen_or((yyvsp[-2].blk).b, (yyvsp[0].blk).b); (yyval.blk) = (yyvsp[0].blk); }
-#line 2252 "y.tab.c" /* yacc.c:1646  */
+#line 2247 "grammar.c" /* yacc.c:1646  */
     break;
 
   case 29:
-#line 417 "grammar.y" /* yacc.c:1646  */
-    { (yyval.blk).b = gen_ncode(NULL, (bpf_u_int32)(yyvsp[0].i),
+#line 432 "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 2259 "y.tab.c" /* yacc.c:1646  */
+#line 2254 "grammar.c" /* yacc.c:1646  */
     break;
 
   case 32:
-#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 2265 "y.tab.c" /* yacc.c:1646  */
+#line 2260 "grammar.c" /* yacc.c:1646  */
     break;
 
   case 33:
-#line 424 "grammar.y" /* yacc.c:1646  */
+#line 439 "grammar.y" /* yacc.c:1646  */
     { QSET((yyval.blk).q, (yyvsp[-2].i), (yyvsp[-1].i), (yyvsp[0].i)); }
-#line 2271 "y.tab.c" /* yacc.c:1646  */
+#line 2266 "grammar.c" /* yacc.c:1646  */
     break;
 
   case 34:
-#line 425 "grammar.y" /* yacc.c:1646  */
+#line 440 "grammar.y" /* yacc.c:1646  */
     { QSET((yyval.blk).q, (yyvsp[-1].i), (yyvsp[0].i), Q_DEFAULT); }
-#line 2277 "y.tab.c" /* yacc.c:1646  */
+#line 2272 "grammar.c" /* yacc.c:1646  */
     break;
 
   case 35:
-#line 426 "grammar.y" /* yacc.c:1646  */
+#line 441 "grammar.y" /* yacc.c:1646  */
     { QSET((yyval.blk).q, (yyvsp[-1].i), Q_DEFAULT, (yyvsp[0].i)); }
-#line 2283 "y.tab.c" /* yacc.c:1646  */
+#line 2278 "grammar.c" /* yacc.c:1646  */
     break;
 
   case 36:
-#line 427 "grammar.y" /* yacc.c:1646  */
+#line 442 "grammar.y" /* yacc.c:1646  */
     { QSET((yyval.blk).q, (yyvsp[-1].i), Q_DEFAULT, Q_PROTO); }
-#line 2289 "y.tab.c" /* yacc.c:1646  */
+#line 2284 "grammar.c" /* yacc.c:1646  */
     break;
 
   case 37:
-#line 428 "grammar.y" /* yacc.c:1646  */
+#line 443 "grammar.y" /* yacc.c:1646  */
     { QSET((yyval.blk).q, (yyvsp[-1].i), Q_DEFAULT, Q_PROTOCHAIN); }
-#line 2295 "y.tab.c" /* yacc.c:1646  */
+#line 2290 "grammar.c" /* yacc.c:1646  */
     break;
 
   case 38:
-#line 429 "grammar.y" /* yacc.c:1646  */
+#line 444 "grammar.y" /* yacc.c:1646  */
     { QSET((yyval.blk).q, (yyvsp[-1].i), Q_DEFAULT, (yyvsp[0].i)); }
-#line 2301 "y.tab.c" /* yacc.c:1646  */
+#line 2296 "grammar.c" /* yacc.c:1646  */
     break;
 
   case 39:
-#line 431 "grammar.y" /* yacc.c:1646  */
+#line 446 "grammar.y" /* yacc.c:1646  */
     { (yyval.blk) = (yyvsp[0].blk); }
-#line 2307 "y.tab.c" /* yacc.c:1646  */
+#line 2302 "grammar.c" /* yacc.c:1646  */
     break;
 
   case 40:
-#line 432 "grammar.y" /* yacc.c:1646  */
+#line 447 "grammar.y" /* yacc.c:1646  */
     { (yyval.blk).b = (yyvsp[-1].blk).b; (yyval.blk).q = (yyvsp[-2].blk).q; }
-#line 2313 "y.tab.c" /* yacc.c:1646  */
+#line 2308 "grammar.c" /* yacc.c:1646  */
     break;
 
   case 41:
-#line 433 "grammar.y" /* yacc.c:1646  */
-    { (yyval.blk).b = gen_proto_abbrev((yyvsp[0].i)); (yyval.blk).q = qerr; }
-#line 2319 "y.tab.c" /* yacc.c:1646  */
+#line 448 "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  */
     break;
 
   case 42:
-#line 434 "grammar.y" /* yacc.c:1646  */
-    { (yyval.blk).b = gen_relation((yyvsp[-1].i), (yyvsp[-2].a), (yyvsp[0].a), 0);
+#line 449 "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 2326 "y.tab.c" /* yacc.c:1646  */
+#line 2321 "grammar.c" /* yacc.c:1646  */
     break;
 
   case 43:
-#line 436 "grammar.y" /* yacc.c:1646  */
-    { (yyval.blk).b = gen_relation((yyvsp[-1].i), (yyvsp[-2].a), (yyvsp[0].a), 1);
+#line 451 "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 2333 "y.tab.c" /* yacc.c:1646  */
+#line 2328 "grammar.c" /* yacc.c:1646  */
     break;
 
   case 44:
-#line 438 "grammar.y" /* yacc.c:1646  */
+#line 453 "grammar.y" /* yacc.c:1646  */
     { (yyval.blk).b = (yyvsp[0].rblk); (yyval.blk).q = qerr; }
-#line 2339 "y.tab.c" /* yacc.c:1646  */
+#line 2334 "grammar.c" /* yacc.c:1646  */
     break;
 
   case 45:
-#line 439 "grammar.y" /* yacc.c:1646  */
-    { (yyval.blk).b = gen_atmtype_abbrev((yyvsp[0].i)); (yyval.blk).q = qerr; }
-#line 2345 "y.tab.c" /* yacc.c:1646  */
+#line 454 "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  */
     break;
 
   case 46:
-#line 440 "grammar.y" /* yacc.c:1646  */
-    { (yyval.blk).b = gen_atmmulti_abbrev((yyvsp[0].i)); (yyval.blk).q = qerr; }
-#line 2351 "y.tab.c" /* yacc.c:1646  */
+#line 455 "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  */
     break;
 
   case 47:
-#line 441 "grammar.y" /* yacc.c:1646  */
+#line 456 "grammar.y" /* yacc.c:1646  */
     { (yyval.blk).b = (yyvsp[0].blk).b; (yyval.blk).q = qerr; }
-#line 2357 "y.tab.c" /* yacc.c:1646  */
+#line 2352 "grammar.c" /* yacc.c:1646  */
     break;
 
   case 48:
-#line 442 "grammar.y" /* yacc.c:1646  */
-    { (yyval.blk).b = gen_mtp2type_abbrev((yyvsp[0].i)); (yyval.blk).q = qerr; }
-#line 2363 "y.tab.c" /* yacc.c:1646  */
+#line 457 "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  */
     break;
 
   case 49:
-#line 443 "grammar.y" /* yacc.c:1646  */
+#line 458 "grammar.y" /* yacc.c:1646  */
     { (yyval.blk).b = (yyvsp[0].blk).b; (yyval.blk).q = qerr; }
-#line 2369 "y.tab.c" /* yacc.c:1646  */
+#line 2364 "grammar.c" /* yacc.c:1646  */
     break;
 
   case 51:
-#line 447 "grammar.y" /* yacc.c:1646  */
+#line 462 "grammar.y" /* yacc.c:1646  */
     { (yyval.i) = Q_DEFAULT; }
-#line 2375 "y.tab.c" /* yacc.c:1646  */
+#line 2370 "grammar.c" /* yacc.c:1646  */
     break;
 
   case 52:
-#line 450 "grammar.y" /* yacc.c:1646  */
+#line 465 "grammar.y" /* yacc.c:1646  */
     { (yyval.i) = Q_SRC; }
-#line 2381 "y.tab.c" /* yacc.c:1646  */
+#line 2376 "grammar.c" /* yacc.c:1646  */
     break;
 
   case 53:
-#line 451 "grammar.y" /* yacc.c:1646  */
+#line 466 "grammar.y" /* yacc.c:1646  */
     { (yyval.i) = Q_DST; }
-#line 2387 "y.tab.c" /* yacc.c:1646  */
+#line 2382 "grammar.c" /* yacc.c:1646  */
     break;
 
   case 54:
-#line 452 "grammar.y" /* yacc.c:1646  */
+#line 467 "grammar.y" /* yacc.c:1646  */
     { (yyval.i) = Q_OR; }
-#line 2393 "y.tab.c" /* yacc.c:1646  */
+#line 2388 "grammar.c" /* yacc.c:1646  */
     break;
 
   case 55:
-#line 453 "grammar.y" /* yacc.c:1646  */
+#line 468 "grammar.y" /* yacc.c:1646  */
     { (yyval.i) = Q_OR; }
-#line 2399 "y.tab.c" /* yacc.c:1646  */
+#line 2394 "grammar.c" /* yacc.c:1646  */
     break;
 
   case 56:
-#line 454 "grammar.y" /* yacc.c:1646  */
+#line 469 "grammar.y" /* yacc.c:1646  */
     { (yyval.i) = Q_AND; }
-#line 2405 "y.tab.c" /* yacc.c:1646  */
+#line 2400 "grammar.c" /* yacc.c:1646  */
     break;
 
   case 57:
-#line 455 "grammar.y" /* yacc.c:1646  */
+#line 470 "grammar.y" /* yacc.c:1646  */
     { (yyval.i) = Q_AND; }
-#line 2411 "y.tab.c" /* yacc.c:1646  */
+#line 2406 "grammar.c" /* yacc.c:1646  */
     break;
 
   case 58:
-#line 456 "grammar.y" /* yacc.c:1646  */
+#line 471 "grammar.y" /* yacc.c:1646  */
     { (yyval.i) = Q_ADDR1; }
-#line 2417 "y.tab.c" /* yacc.c:1646  */
+#line 2412 "grammar.c" /* yacc.c:1646  */
     break;
 
   case 59:
-#line 457 "grammar.y" /* yacc.c:1646  */
+#line 472 "grammar.y" /* yacc.c:1646  */
     { (yyval.i) = Q_ADDR2; }
-#line 2423 "y.tab.c" /* yacc.c:1646  */
+#line 2418 "grammar.c" /* yacc.c:1646  */
     break;
 
   case 60:
-#line 458 "grammar.y" /* yacc.c:1646  */
+#line 473 "grammar.y" /* yacc.c:1646  */
     { (yyval.i) = Q_ADDR3; }
-#line 2429 "y.tab.c" /* yacc.c:1646  */
+#line 2424 "grammar.c" /* yacc.c:1646  */
     break;
 
   case 61:
-#line 459 "grammar.y" /* yacc.c:1646  */
+#line 474 "grammar.y" /* yacc.c:1646  */
     { (yyval.i) = Q_ADDR4; }
-#line 2435 "y.tab.c" /* yacc.c:1646  */
+#line 2430 "grammar.c" /* yacc.c:1646  */
     break;
 
   case 62:
-#line 460 "grammar.y" /* yacc.c:1646  */
+#line 475 "grammar.y" /* yacc.c:1646  */
     { (yyval.i) = Q_RA; }
-#line 2441 "y.tab.c" /* yacc.c:1646  */
+#line 2436 "grammar.c" /* yacc.c:1646  */
     break;
 
   case 63:
-#line 461 "grammar.y" /* yacc.c:1646  */
+#line 476 "grammar.y" /* yacc.c:1646  */
     { (yyval.i) = Q_TA; }
-#line 2447 "y.tab.c" /* yacc.c:1646  */
+#line 2442 "grammar.c" /* yacc.c:1646  */
     break;
 
   case 64:
-#line 464 "grammar.y" /* yacc.c:1646  */
+#line 479 "grammar.y" /* yacc.c:1646  */
     { (yyval.i) = Q_HOST; }
-#line 2453 "y.tab.c" /* yacc.c:1646  */
+#line 2448 "grammar.c" /* yacc.c:1646  */
     break;
 
   case 65:
-#line 465 "grammar.y" /* yacc.c:1646  */
+#line 480 "grammar.y" /* yacc.c:1646  */
     { (yyval.i) = Q_NET; }
-#line 2459 "y.tab.c" /* yacc.c:1646  */
+#line 2454 "grammar.c" /* yacc.c:1646  */
     break;
 
   case 66:
-#line 466 "grammar.y" /* yacc.c:1646  */
+#line 481 "grammar.y" /* yacc.c:1646  */
     { (yyval.i) = Q_PORT; }
-#line 2465 "y.tab.c" /* yacc.c:1646  */
+#line 2460 "grammar.c" /* yacc.c:1646  */
     break;
 
   case 67:
-#line 467 "grammar.y" /* yacc.c:1646  */
+#line 482 "grammar.y" /* yacc.c:1646  */
     { (yyval.i) = Q_PORTRANGE; }
-#line 2471 "y.tab.c" /* yacc.c:1646  */
+#line 2466 "grammar.c" /* yacc.c:1646  */
     break;
 
   case 68:
-#line 470 "grammar.y" /* yacc.c:1646  */
+#line 485 "grammar.y" /* yacc.c:1646  */
     { (yyval.i) = Q_GATEWAY; }
-#line 2477 "y.tab.c" /* yacc.c:1646  */
+#line 2472 "grammar.c" /* yacc.c:1646  */
     break;
 
   case 69:
-#line 472 "grammar.y" /* yacc.c:1646  */
+#line 487 "grammar.y" /* yacc.c:1646  */
     { (yyval.i) = Q_LINK; }
-#line 2483 "y.tab.c" /* yacc.c:1646  */
+#line 2478 "grammar.c" /* yacc.c:1646  */
     break;
 
   case 70:
-#line 473 "grammar.y" /* yacc.c:1646  */
+#line 488 "grammar.y" /* yacc.c:1646  */
     { (yyval.i) = Q_IP; }
-#line 2489 "y.tab.c" /* yacc.c:1646  */
+#line 2484 "grammar.c" /* yacc.c:1646  */
     break;
 
   case 71:
-#line 474 "grammar.y" /* yacc.c:1646  */
+#line 489 "grammar.y" /* yacc.c:1646  */
     { (yyval.i) = Q_ARP; }
-#line 2495 "y.tab.c" /* yacc.c:1646  */
+#line 2490 "grammar.c" /* yacc.c:1646  */
     break;
 
   case 72:
-#line 475 "grammar.y" /* yacc.c:1646  */
+#line 490 "grammar.y" /* yacc.c:1646  */
     { (yyval.i) = Q_RARP; }
-#line 2501 "y.tab.c" /* yacc.c:1646  */
+#line 2496 "grammar.c" /* yacc.c:1646  */
     break;
 
   case 73:
-#line 476 "grammar.y" /* yacc.c:1646  */
+#line 491 "grammar.y" /* yacc.c:1646  */
     { (yyval.i) = Q_SCTP; }
-#line 2507 "y.tab.c" /* yacc.c:1646  */
+#line 2502 "grammar.c" /* yacc.c:1646  */
     break;
 
   case 74:
-#line 477 "grammar.y" /* yacc.c:1646  */
+#line 492 "grammar.y" /* yacc.c:1646  */
     { (yyval.i) = Q_TCP; }
-#line 2513 "y.tab.c" /* yacc.c:1646  */
+#line 2508 "grammar.c" /* yacc.c:1646  */
     break;
 
   case 75:
-#line 478 "grammar.y" /* yacc.c:1646  */
+#line 493 "grammar.y" /* yacc.c:1646  */
     { (yyval.i) = Q_UDP; }
-#line 2519 "y.tab.c" /* yacc.c:1646  */
+#line 2514 "grammar.c" /* yacc.c:1646  */
     break;
 
   case 76:
-#line 479 "grammar.y" /* yacc.c:1646  */
+#line 494 "grammar.y" /* yacc.c:1646  */
     { (yyval.i) = Q_ICMP; }
-#line 2525 "y.tab.c" /* yacc.c:1646  */
+#line 2520 "grammar.c" /* yacc.c:1646  */
     break;
 
   case 77:
-#line 480 "grammar.y" /* yacc.c:1646  */
+#line 495 "grammar.y" /* yacc.c:1646  */
     { (yyval.i) = Q_IGMP; }
-#line 2531 "y.tab.c" /* yacc.c:1646  */
+#line 2526 "grammar.c" /* yacc.c:1646  */
     break;
 
   case 78:
-#line 481 "grammar.y" /* yacc.c:1646  */
+#line 496 "grammar.y" /* yacc.c:1646  */
     { (yyval.i) = Q_IGRP; }
-#line 2537 "y.tab.c" /* yacc.c:1646  */
+#line 2532 "grammar.c" /* yacc.c:1646  */
     break;
 
   case 79:
-#line 482 "grammar.y" /* yacc.c:1646  */
+#line 497 "grammar.y" /* yacc.c:1646  */
     { (yyval.i) = Q_PIM; }
-#line 2543 "y.tab.c" /* yacc.c:1646  */
+#line 2538 "grammar.c" /* yacc.c:1646  */
     break;
 
   case 80:
-#line 483 "grammar.y" /* yacc.c:1646  */
+#line 498 "grammar.y" /* yacc.c:1646  */
     { (yyval.i) = Q_VRRP; }
-#line 2549 "y.tab.c" /* yacc.c:1646  */
+#line 2544 "grammar.c" /* yacc.c:1646  */
     break;
 
   case 81:
-#line 484 "grammar.y" /* yacc.c:1646  */
+#line 499 "grammar.y" /* yacc.c:1646  */
     { (yyval.i) = Q_CARP; }
-#line 2555 "y.tab.c" /* yacc.c:1646  */
+#line 2550 "grammar.c" /* yacc.c:1646  */
     break;
 
   case 82:
-#line 485 "grammar.y" /* yacc.c:1646  */
+#line 500 "grammar.y" /* yacc.c:1646  */
     { (yyval.i) = Q_ATALK; }
-#line 2561 "y.tab.c" /* yacc.c:1646  */
+#line 2556 "grammar.c" /* yacc.c:1646  */
     break;
 
   case 83:
-#line 486 "grammar.y" /* yacc.c:1646  */
+#line 501 "grammar.y" /* yacc.c:1646  */
     { (yyval.i) = Q_AARP; }
-#line 2567 "y.tab.c" /* yacc.c:1646  */
+#line 2562 "grammar.c" /* yacc.c:1646  */
     break;
 
   case 84:
-#line 487 "grammar.y" /* yacc.c:1646  */
+#line 502 "grammar.y" /* yacc.c:1646  */
     { (yyval.i) = Q_DECNET; }
-#line 2573 "y.tab.c" /* yacc.c:1646  */
+#line 2568 "grammar.c" /* yacc.c:1646  */
     break;
 
   case 85:
-#line 488 "grammar.y" /* yacc.c:1646  */
+#line 503 "grammar.y" /* yacc.c:1646  */
     { (yyval.i) = Q_LAT; }
-#line 2579 "y.tab.c" /* yacc.c:1646  */
+#line 2574 "grammar.c" /* yacc.c:1646  */
     break;
 
   case 86:
-#line 489 "grammar.y" /* yacc.c:1646  */
+#line 504 "grammar.y" /* yacc.c:1646  */
     { (yyval.i) = Q_SCA; }
-#line 2585 "y.tab.c" /* yacc.c:1646  */
+#line 2580 "grammar.c" /* yacc.c:1646  */
     break;
 
   case 87:
-#line 490 "grammar.y" /* yacc.c:1646  */
+#line 505 "grammar.y" /* yacc.c:1646  */
     { (yyval.i) = Q_MOPDL; }
-#line 2591 "y.tab.c" /* yacc.c:1646  */
+#line 2586 "grammar.c" /* yacc.c:1646  */
     break;
 
   case 88:
-#line 491 "grammar.y" /* yacc.c:1646  */
+#line 506 "grammar.y" /* yacc.c:1646  */
     { (yyval.i) = Q_MOPRC; }
-#line 2597 "y.tab.c" /* yacc.c:1646  */
+#line 2592 "grammar.c" /* yacc.c:1646  */
     break;
 
   case 89:
-#line 492 "grammar.y" /* yacc.c:1646  */
+#line 507 "grammar.y" /* yacc.c:1646  */
     { (yyval.i) = Q_IPV6; }
-#line 2603 "y.tab.c" /* yacc.c:1646  */
+#line 2598 "grammar.c" /* yacc.c:1646  */
     break;
 
   case 90:
-#line 493 "grammar.y" /* yacc.c:1646  */
+#line 508 "grammar.y" /* yacc.c:1646  */
     { (yyval.i) = Q_ICMPV6; }
-#line 2609 "y.tab.c" /* yacc.c:1646  */
+#line 2604 "grammar.c" /* yacc.c:1646  */
     break;
 
   case 91:
-#line 494 "grammar.y" /* yacc.c:1646  */
+#line 509 "grammar.y" /* yacc.c:1646  */
     { (yyval.i) = Q_AH; }
-#line 2615 "y.tab.c" /* yacc.c:1646  */
+#line 2610 "grammar.c" /* yacc.c:1646  */
     break;
 
   case 92:
-#line 495 "grammar.y" /* yacc.c:1646  */
+#line 510 "grammar.y" /* yacc.c:1646  */
     { (yyval.i) = Q_ESP; }
-#line 2621 "y.tab.c" /* yacc.c:1646  */
+#line 2616 "grammar.c" /* yacc.c:1646  */
     break;
 
   case 93:
-#line 496 "grammar.y" /* yacc.c:1646  */
+#line 511 "grammar.y" /* yacc.c:1646  */
     { (yyval.i) = Q_ISO; }
-#line 2627 "y.tab.c" /* yacc.c:1646  */
+#line 2622 "grammar.c" /* yacc.c:1646  */
     break;
 
   case 94:
-#line 497 "grammar.y" /* yacc.c:1646  */
+#line 512 "grammar.y" /* yacc.c:1646  */
     { (yyval.i) = Q_ESIS; }
-#line 2633 "y.tab.c" /* yacc.c:1646  */
+#line 2628 "grammar.c" /* yacc.c:1646  */
     break;
 
   case 95:
-#line 498 "grammar.y" /* yacc.c:1646  */
+#line 513 "grammar.y" /* yacc.c:1646  */
     { (yyval.i) = Q_ISIS; }
-#line 2639 "y.tab.c" /* yacc.c:1646  */
+#line 2634 "grammar.c" /* yacc.c:1646  */
     break;
 
   case 96:
-#line 499 "grammar.y" /* yacc.c:1646  */
+#line 514 "grammar.y" /* yacc.c:1646  */
     { (yyval.i) = Q_ISIS_L1; }
-#line 2645 "y.tab.c" /* yacc.c:1646  */
+#line 2640 "grammar.c" /* yacc.c:1646  */
     break;
 
   case 97:
-#line 500 "grammar.y" /* yacc.c:1646  */
+#line 515 "grammar.y" /* yacc.c:1646  */
     { (yyval.i) = Q_ISIS_L2; }
-#line 2651 "y.tab.c" /* yacc.c:1646  */
+#line 2646 "grammar.c" /* yacc.c:1646  */
     break;
 
   case 98:
-#line 501 "grammar.y" /* yacc.c:1646  */
+#line 516 "grammar.y" /* yacc.c:1646  */
     { (yyval.i) = Q_ISIS_IIH; }
-#line 2657 "y.tab.c" /* yacc.c:1646  */
+#line 2652 "grammar.c" /* yacc.c:1646  */
     break;
 
   case 99:
-#line 502 "grammar.y" /* yacc.c:1646  */
+#line 517 "grammar.y" /* yacc.c:1646  */
     { (yyval.i) = Q_ISIS_LSP; }
-#line 2663 "y.tab.c" /* yacc.c:1646  */
+#line 2658 "grammar.c" /* yacc.c:1646  */
     break;
 
   case 100:
-#line 503 "grammar.y" /* yacc.c:1646  */
+#line 518 "grammar.y" /* yacc.c:1646  */
     { (yyval.i) = Q_ISIS_SNP; }
-#line 2669 "y.tab.c" /* yacc.c:1646  */
+#line 2664 "grammar.c" /* yacc.c:1646  */
     break;
 
   case 101:
-#line 504 "grammar.y" /* yacc.c:1646  */
+#line 519 "grammar.y" /* yacc.c:1646  */
     { (yyval.i) = Q_ISIS_PSNP; }
-#line 2675 "y.tab.c" /* yacc.c:1646  */
+#line 2670 "grammar.c" /* yacc.c:1646  */
     break;
 
   case 102:
-#line 505 "grammar.y" /* yacc.c:1646  */
+#line 520 "grammar.y" /* yacc.c:1646  */
     { (yyval.i) = Q_ISIS_CSNP; }
-#line 2681 "y.tab.c" /* yacc.c:1646  */
+#line 2676 "grammar.c" /* yacc.c:1646  */
     break;
 
   case 103:
-#line 506 "grammar.y" /* yacc.c:1646  */
+#line 521 "grammar.y" /* yacc.c:1646  */
     { (yyval.i) = Q_CLNP; }
-#line 2687 "y.tab.c" /* yacc.c:1646  */
+#line 2682 "grammar.c" /* yacc.c:1646  */
     break;
 
   case 104:
-#line 507 "grammar.y" /* yacc.c:1646  */
+#line 522 "grammar.y" /* yacc.c:1646  */
     { (yyval.i) = Q_STP; }
-#line 2693 "y.tab.c" /* yacc.c:1646  */
+#line 2688 "grammar.c" /* yacc.c:1646  */
     break;
 
   case 105:
-#line 508 "grammar.y" /* yacc.c:1646  */
+#line 523 "grammar.y" /* yacc.c:1646  */
     { (yyval.i) = Q_IPX; }
-#line 2699 "y.tab.c" /* yacc.c:1646  */
+#line 2694 "grammar.c" /* yacc.c:1646  */
     break;
 
   case 106:
-#line 509 "grammar.y" /* yacc.c:1646  */
+#line 524 "grammar.y" /* yacc.c:1646  */
     { (yyval.i) = Q_NETBEUI; }
-#line 2705 "y.tab.c" /* yacc.c:1646  */
+#line 2700 "grammar.c" /* yacc.c:1646  */
     break;
 
   case 107:
-#line 510 "grammar.y" /* yacc.c:1646  */
+#line 525 "grammar.y" /* yacc.c:1646  */
     { (yyval.i) = Q_RADIO; }
-#line 2711 "y.tab.c" /* yacc.c:1646  */
+#line 2706 "grammar.c" /* yacc.c:1646  */
     break;
 
   case 108:
-#line 512 "grammar.y" /* yacc.c:1646  */
-    { (yyval.rblk) = gen_broadcast((yyvsp[-1].i)); }
-#line 2717 "y.tab.c" /* yacc.c:1646  */
+#line 527 "grammar.y" /* yacc.c:1646  */
+    { (yyval.rblk) = gen_broadcast(cstate, (yyvsp[-1].i)); }
+#line 2712 "grammar.c" /* yacc.c:1646  */
     break;
 
   case 109:
-#line 513 "grammar.y" /* yacc.c:1646  */
-    { (yyval.rblk) = gen_multicast((yyvsp[-1].i)); }
-#line 2723 "y.tab.c" /* yacc.c:1646  */
+#line 528 "grammar.y" /* yacc.c:1646  */
+    { (yyval.rblk) = gen_multicast(cstate, (yyvsp[-1].i)); }
+#line 2718 "grammar.c" /* yacc.c:1646  */
     break;
 
   case 110:
-#line 514 "grammar.y" /* yacc.c:1646  */
-    { (yyval.rblk) = gen_less((yyvsp[0].i)); }
-#line 2729 "y.tab.c" /* yacc.c:1646  */
+#line 529 "grammar.y" /* yacc.c:1646  */
+    { (yyval.rblk) = gen_less(cstate, (yyvsp[0].i)); }
+#line 2724 "grammar.c" /* yacc.c:1646  */
     break;
 
   case 111:
-#line 515 "grammar.y" /* yacc.c:1646  */
-    { (yyval.rblk) = gen_greater((yyvsp[0].i)); }
-#line 2735 "y.tab.c" /* yacc.c:1646  */
+#line 530 "grammar.y" /* yacc.c:1646  */
+    { (yyval.rblk) = gen_greater(cstate, (yyvsp[0].i)); }
+#line 2730 "grammar.c" /* yacc.c:1646  */
     break;
 
   case 112:
-#line 516 "grammar.y" /* yacc.c:1646  */
-    { (yyval.rblk) = gen_byteop((yyvsp[-1].i), (yyvsp[-2].i), (yyvsp[0].i)); }
-#line 2741 "y.tab.c" /* yacc.c:1646  */
+#line 531 "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  */
     break;
 
   case 113:
-#line 517 "grammar.y" /* yacc.c:1646  */
-    { (yyval.rblk) = gen_inbound(0); }
-#line 2747 "y.tab.c" /* yacc.c:1646  */
+#line 532 "grammar.y" /* yacc.c:1646  */
+    { (yyval.rblk) = gen_inbound(cstate, 0); }
+#line 2742 "grammar.c" /* yacc.c:1646  */
     break;
 
   case 114:
-#line 518 "grammar.y" /* yacc.c:1646  */
-    { (yyval.rblk) = gen_inbound(1); }
-#line 2753 "y.tab.c" /* yacc.c:1646  */
+#line 533 "grammar.y" /* yacc.c:1646  */
+    { (yyval.rblk) = gen_inbound(cstate, 1); }
+#line 2748 "grammar.c" /* yacc.c:1646  */
     break;
 
   case 115:
-#line 519 "grammar.y" /* yacc.c:1646  */
-    { (yyval.rblk) = gen_vlan((yyvsp[0].i)); }
-#line 2759 "y.tab.c" /* yacc.c:1646  */
+#line 534 "grammar.y" /* yacc.c:1646  */
+    { (yyval.rblk) = gen_vlan(cstate, (yyvsp[0].i)); }
+#line 2754 "grammar.c" /* yacc.c:1646  */
     break;
 
   case 116:
-#line 520 "grammar.y" /* yacc.c:1646  */
-    { (yyval.rblk) = gen_vlan(-1); }
-#line 2765 "y.tab.c" /* yacc.c:1646  */
+#line 535 "grammar.y" /* yacc.c:1646  */
+    { (yyval.rblk) = gen_vlan(cstate, -1); }
+#line 2760 "grammar.c" /* yacc.c:1646  */
     break;
 
   case 117:
-#line 521 "grammar.y" /* yacc.c:1646  */
-    { (yyval.rblk) = gen_mpls((yyvsp[0].i)); }
-#line 2771 "y.tab.c" /* yacc.c:1646  */
+#line 536 "grammar.y" /* yacc.c:1646  */
+    { (yyval.rblk) = gen_mpls(cstate, (yyvsp[0].i)); }
+#line 2766 "grammar.c" /* yacc.c:1646  */
     break;
 
   case 118:
-#line 522 "grammar.y" /* yacc.c:1646  */
-    { (yyval.rblk) = gen_mpls(-1); }
-#line 2777 "y.tab.c" /* yacc.c:1646  */
+#line 537 "grammar.y" /* yacc.c:1646  */
+    { (yyval.rblk) = gen_mpls(cstate, -1); }
+#line 2772 "grammar.c" /* yacc.c:1646  */
     break;
 
   case 119:
-#line 523 "grammar.y" /* yacc.c:1646  */
-    { (yyval.rblk) = gen_pppoed(); }
-#line 2783 "y.tab.c" /* yacc.c:1646  */
+#line 538 "grammar.y" /* yacc.c:1646  */
+    { (yyval.rblk) = gen_pppoed(cstate); }
+#line 2778 "grammar.c" /* yacc.c:1646  */
     break;
 
   case 120:
-#line 524 "grammar.y" /* yacc.c:1646  */
-    { (yyval.rblk) = gen_pppoes((yyvsp[0].i)); }
-#line 2789 "y.tab.c" /* yacc.c:1646  */
+#line 539 "grammar.y" /* yacc.c:1646  */
+    { (yyval.rblk) = gen_pppoes(cstate, (yyvsp[0].i)); }
+#line 2784 "grammar.c" /* yacc.c:1646  */
     break;
 
   case 121:
-#line 525 "grammar.y" /* yacc.c:1646  */
-    { (yyval.rblk) = gen_pppoes(-1); }
-#line 2795 "y.tab.c" /* yacc.c:1646  */
+#line 540 "grammar.y" /* yacc.c:1646  */
+    { (yyval.rblk) = gen_pppoes(cstate, -1); }
+#line 2790 "grammar.c" /* yacc.c:1646  */
     break;
 
   case 122:
-#line 526 "grammar.y" /* yacc.c:1646  */
-    { (yyval.rblk) = gen_geneve((yyvsp[0].i)); }
-#line 2801 "y.tab.c" /* yacc.c:1646  */
+#line 541 "grammar.y" /* yacc.c:1646  */
+    { (yyval.rblk) = gen_geneve(cstate, (yyvsp[0].i)); }
+#line 2796 "grammar.c" /* yacc.c:1646  */
     break;
 
   case 123:
-#line 527 "grammar.y" /* yacc.c:1646  */
-    { (yyval.rblk) = gen_geneve(-1); }
-#line 2807 "y.tab.c" /* yacc.c:1646  */
+#line 542 "grammar.y" /* yacc.c:1646  */
+    { (yyval.rblk) = gen_geneve(cstate, -1); }
+#line 2802 "grammar.c" /* yacc.c:1646  */
     break;
 
   case 124:
-#line 528 "grammar.y" /* yacc.c:1646  */
+#line 543 "grammar.y" /* yacc.c:1646  */
     { (yyval.rblk) = (yyvsp[0].rblk); }
-#line 2813 "y.tab.c" /* yacc.c:1646  */
+#line 2808 "grammar.c" /* yacc.c:1646  */
     break;
 
   case 125:
-#line 529 "grammar.y" /* yacc.c:1646  */
+#line 544 "grammar.y" /* yacc.c:1646  */
     { (yyval.rblk) = (yyvsp[0].rblk); }
-#line 2819 "y.tab.c" /* yacc.c:1646  */
+#line 2814 "grammar.c" /* yacc.c:1646  */
     break;
 
   case 126:
-#line 530 "grammar.y" /* yacc.c:1646  */
+#line 545 "grammar.y" /* yacc.c:1646  */
     { (yyval.rblk) = (yyvsp[0].rblk); }
-#line 2825 "y.tab.c" /* yacc.c:1646  */
+#line 2820 "grammar.c" /* yacc.c:1646  */
     break;
 
   case 127:
-#line 533 "grammar.y" /* yacc.c:1646  */
-    { (yyval.rblk) = gen_pf_ifname((yyvsp[0].s)); }
-#line 2831 "y.tab.c" /* yacc.c:1646  */
+#line 548 "grammar.y" /* yacc.c:1646  */
+    { (yyval.rblk) = gen_pf_ifname(cstate, (yyvsp[0].s)); }
+#line 2826 "grammar.c" /* yacc.c:1646  */
     break;
 
   case 128:
-#line 534 "grammar.y" /* yacc.c:1646  */
-    { (yyval.rblk) = gen_pf_ruleset((yyvsp[0].s)); }
-#line 2837 "y.tab.c" /* yacc.c:1646  */
+#line 549 "grammar.y" /* yacc.c:1646  */
+    { (yyval.rblk) = gen_pf_ruleset(cstate, (yyvsp[0].s)); }
+#line 2832 "grammar.c" /* yacc.c:1646  */
     break;
 
   case 129:
-#line 535 "grammar.y" /* yacc.c:1646  */
-    { (yyval.rblk) = gen_pf_rnr((yyvsp[0].i)); }
-#line 2843 "y.tab.c" /* yacc.c:1646  */
+#line 550 "grammar.y" /* yacc.c:1646  */
+    { (yyval.rblk) = gen_pf_rnr(cstate, (yyvsp[0].i)); }
+#line 2838 "grammar.c" /* yacc.c:1646  */
     break;
 
   case 130:
-#line 536 "grammar.y" /* yacc.c:1646  */
-    { (yyval.rblk) = gen_pf_srnr((yyvsp[0].i)); }
-#line 2849 "y.tab.c" /* yacc.c:1646  */
+#line 551 "grammar.y" /* yacc.c:1646  */
+    { (yyval.rblk) = gen_pf_srnr(cstate, (yyvsp[0].i)); }
+#line 2844 "grammar.c" /* yacc.c:1646  */
     break;
 
   case 131:
-#line 537 "grammar.y" /* yacc.c:1646  */
-    { (yyval.rblk) = gen_pf_reason((yyvsp[0].i)); }
-#line 2855 "y.tab.c" /* yacc.c:1646  */
+#line 552 "grammar.y" /* yacc.c:1646  */
+    { (yyval.rblk) = gen_pf_reason(cstate, (yyvsp[0].i)); }
+#line 2850 "grammar.c" /* yacc.c:1646  */
     break;
 
   case 132:
-#line 538 "grammar.y" /* yacc.c:1646  */
-    { (yyval.rblk) = gen_pf_action((yyvsp[0].i)); }
-#line 2861 "y.tab.c" /* yacc.c:1646  */
+#line 553 "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 542 "grammar.y" /* yacc.c:1646  */
-    { (yyval.rblk) = gen_p80211_type((yyvsp[-2].i) | (yyvsp[0].i),
+#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 2870 "y.tab.c" /* yacc.c:1646  */
+#line 2865 "grammar.c" /* yacc.c:1646  */
     break;
 
   case 134:
-#line 546 "grammar.y" /* yacc.c:1646  */
-    { (yyval.rblk) = gen_p80211_type((yyvsp[0].i),
+#line 561 "grammar.y" /* yacc.c:1646  */
+    { (yyval.rblk) = gen_p80211_type(cstate, (yyvsp[0].i),
 					IEEE80211_FC0_TYPE_MASK);
 				}
-#line 2878 "y.tab.c" /* yacc.c:1646  */
+#line 2873 "grammar.c" /* yacc.c:1646  */
     break;
 
   case 135:
-#line 549 "grammar.y" /* yacc.c:1646  */
-    { (yyval.rblk) = gen_p80211_type((yyvsp[0].i),
+#line 564 "grammar.y" /* yacc.c:1646  */
+    { (yyval.rblk) = gen_p80211_type(cstate, (yyvsp[0].i),
 					IEEE80211_FC0_TYPE_MASK |
 					IEEE80211_FC0_SUBTYPE_MASK);
 				}
-#line 2887 "y.tab.c" /* yacc.c:1646  */
+#line 2882 "grammar.c" /* yacc.c:1646  */
     break;
 
   case 136:
-#line 553 "grammar.y" /* yacc.c:1646  */
-    { (yyval.rblk) = gen_p80211_fcdir((yyvsp[0].i)); }
-#line 2893 "y.tab.c" /* yacc.c:1646  */
+#line 568 "grammar.y" /* yacc.c:1646  */
+    { (yyval.rblk) = gen_p80211_fcdir(cstate, (yyvsp[0].i)); }
+#line 2888 "grammar.c" /* yacc.c:1646  */
     break;
 
   case 138:
-#line 557 "grammar.y" /* yacc.c:1646  */
+#line 572 "grammar.y" /* yacc.c:1646  */
     { (yyval.i) = str2tok((yyvsp[0].s), ieee80211_types);
 				  if ((yyval.i) == -1)
-				  	bpf_error("unknown 802.11 type name");
+				  	bpf_error(cstate, "unknown 802.11 type name");
 				}
-#line 2902 "y.tab.c" /* yacc.c:1646  */
+#line 2897 "grammar.c" /* yacc.c:1646  */
     break;
 
   case 140:
-#line 564 "grammar.y" /* yacc.c:1646  */
+#line 579 "grammar.y" /* yacc.c:1646  */
     { const struct tok *types = NULL;
 				  int i;
 				  for (i = 0;; i++) {
 				  	if (ieee80211_type_subtypes[i].tok == NULL) {
 				  		/* Ran out of types */
-						bpf_error("unknown 802.11 type");
+						bpf_error(cstate, "unknown 802.11 type");
 						break;
 					}
 					if ((yyvsp[(-1) - (1)].i) == ieee80211_type_subtypes[i].type) {
@@ -2919,18 +2914,18 @@
 
 				  (yyval.i) = str2tok((yyvsp[0].s), types);
 				  if ((yyval.i) == -1)
-					bpf_error("unknown 802.11 subtype name");
+					bpf_error(cstate, "unknown 802.11 subtype name");
 				}
-#line 2925 "y.tab.c" /* yacc.c:1646  */
+#line 2920 "grammar.c" /* yacc.c:1646  */
     break;
 
   case 141:
-#line 584 "grammar.y" /* yacc.c:1646  */
+#line 599 "grammar.y" /* yacc.c:1646  */
     { int i;
 				  for (i = 0;; i++) {
 				  	if (ieee80211_type_subtypes[i].tok == NULL) {
 				  		/* Ran out of types */
-						bpf_error("unknown 802.11 type name");
+						bpf_error(cstate, "unknown 802.11 type name");
 						break;
 					}
 					(yyval.i) = str2tok((yyvsp[0].s), ieee80211_type_subtypes[i].tok);
@@ -2940,48 +2935,48 @@
 					}
 				  }
 				}
-#line 2944 "y.tab.c" /* yacc.c:1646  */
+#line 2939 "grammar.c" /* yacc.c:1646  */
     break;
 
   case 142:
-#line 600 "grammar.y" /* yacc.c:1646  */
-    { (yyval.rblk) = gen_llc(); }
-#line 2950 "y.tab.c" /* yacc.c:1646  */
+#line 615 "grammar.y" /* yacc.c:1646  */
+    { (yyval.rblk) = gen_llc(cstate); }
+#line 2945 "grammar.c" /* yacc.c:1646  */
     break;
 
   case 143:
-#line 601 "grammar.y" /* yacc.c:1646  */
+#line 616 "grammar.y" /* yacc.c:1646  */
     { if (pcap_strcasecmp((yyvsp[0].s), "i") == 0)
-					(yyval.rblk) = gen_llc_i();
+					(yyval.rblk) = gen_llc_i(cstate);
 				  else if (pcap_strcasecmp((yyvsp[0].s), "s") == 0)
-					(yyval.rblk) = gen_llc_s();
+					(yyval.rblk) = gen_llc_s(cstate);
 				  else if (pcap_strcasecmp((yyvsp[0].s), "u") == 0)
-					(yyval.rblk) = gen_llc_u();
+					(yyval.rblk) = gen_llc_u(cstate);
 				  else {
-				  	u_int subtype;
+					int subtype;
 
 					subtype = str2tok((yyvsp[0].s), llc_s_subtypes);
 					if (subtype != -1)
-						(yyval.rblk) = gen_llc_s_subtype(subtype);
+						(yyval.rblk) = gen_llc_s_subtype(cstate, subtype);
 					else {
 						subtype = str2tok((yyvsp[0].s), llc_u_subtypes);
 						if (subtype == -1)
-					  		bpf_error("unknown LLC type name \"%s\"", (yyvsp[0].s));
-						(yyval.rblk) = gen_llc_u_subtype(subtype);
+					  		bpf_error(cstate, "unknown LLC type name \"%s\"", (yyvsp[0].s));
+						(yyval.rblk) = gen_llc_u_subtype(cstate, subtype);
 					}
 				  }
 				}
-#line 2975 "y.tab.c" /* yacc.c:1646  */
+#line 2970 "grammar.c" /* yacc.c:1646  */
     break;
 
   case 144:
-#line 622 "grammar.y" /* yacc.c:1646  */
-    { (yyval.rblk) = gen_llc_s_subtype(LLC_RNR); }
-#line 2981 "y.tab.c" /* yacc.c:1646  */
+#line 637 "grammar.y" /* yacc.c:1646  */
+    { (yyval.rblk) = gen_llc_s_subtype(cstate, LLC_RNR); }
+#line 2976 "grammar.c" /* yacc.c:1646  */
     break;
 
   case 146:
-#line 626 "grammar.y" /* yacc.c:1646  */
+#line 641 "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)
@@ -2991,414 +2986,414 @@
 				  else if (pcap_strcasecmp((yyvsp[0].s), "dstods") == 0)
 					(yyval.i) = IEEE80211_FC1_DIR_DSTODS;
 				  else
-					bpf_error("unknown 802.11 direction");
+					bpf_error(cstate, "unknown 802.11 direction");
 				}
-#line 2997 "y.tab.c" /* yacc.c:1646  */
+#line 2992 "grammar.c" /* yacc.c:1646  */
     break;
 
   case 147:
-#line 639 "grammar.y" /* yacc.c:1646  */
+#line 654 "grammar.y" /* yacc.c:1646  */
     { (yyval.i) = (yyvsp[0].i); }
-#line 3003 "y.tab.c" /* yacc.c:1646  */
+#line 2998 "grammar.c" /* yacc.c:1646  */
     break;
 
   case 148:
-#line 640 "grammar.y" /* yacc.c:1646  */
-    { (yyval.i) = pfreason_to_num((yyvsp[0].s)); }
-#line 3009 "y.tab.c" /* yacc.c:1646  */
+#line 655 "grammar.y" /* yacc.c:1646  */
+    { (yyval.i) = pfreason_to_num(cstate, (yyvsp[0].s)); }
+#line 3004 "grammar.c" /* yacc.c:1646  */
     break;
 
   case 149:
-#line 643 "grammar.y" /* yacc.c:1646  */
-    { (yyval.i) = pfaction_to_num((yyvsp[0].s)); }
-#line 3015 "y.tab.c" /* yacc.c:1646  */
+#line 658 "grammar.y" /* yacc.c:1646  */
+    { (yyval.i) = pfaction_to_num(cstate, (yyvsp[0].s)); }
+#line 3010 "grammar.c" /* yacc.c:1646  */
     break;
 
   case 150:
-#line 646 "grammar.y" /* yacc.c:1646  */
+#line 661 "grammar.y" /* yacc.c:1646  */
     { (yyval.i) = BPF_JGT; }
-#line 3021 "y.tab.c" /* yacc.c:1646  */
+#line 3016 "grammar.c" /* yacc.c:1646  */
     break;
 
   case 151:
-#line 647 "grammar.y" /* yacc.c:1646  */
+#line 662 "grammar.y" /* yacc.c:1646  */
     { (yyval.i) = BPF_JGE; }
-#line 3027 "y.tab.c" /* yacc.c:1646  */
+#line 3022 "grammar.c" /* yacc.c:1646  */
     break;
 
   case 152:
-#line 648 "grammar.y" /* yacc.c:1646  */
+#line 663 "grammar.y" /* yacc.c:1646  */
     { (yyval.i) = BPF_JEQ; }
-#line 3033 "y.tab.c" /* yacc.c:1646  */
+#line 3028 "grammar.c" /* yacc.c:1646  */
     break;
 
   case 153:
-#line 650 "grammar.y" /* yacc.c:1646  */
+#line 665 "grammar.y" /* yacc.c:1646  */
     { (yyval.i) = BPF_JGT; }
-#line 3039 "y.tab.c" /* yacc.c:1646  */
+#line 3034 "grammar.c" /* yacc.c:1646  */
     break;
 
   case 154:
-#line 651 "grammar.y" /* yacc.c:1646  */
+#line 666 "grammar.y" /* yacc.c:1646  */
     { (yyval.i) = BPF_JGE; }
-#line 3045 "y.tab.c" /* yacc.c:1646  */
+#line 3040 "grammar.c" /* yacc.c:1646  */
     break;
 
   case 155:
-#line 652 "grammar.y" /* yacc.c:1646  */
+#line 667 "grammar.y" /* yacc.c:1646  */
     { (yyval.i) = BPF_JEQ; }
-#line 3051 "y.tab.c" /* yacc.c:1646  */
+#line 3046 "grammar.c" /* yacc.c:1646  */
     break;
 
   case 156:
-#line 654 "grammar.y" /* yacc.c:1646  */
-    { (yyval.a) = gen_loadi((yyvsp[0].i)); }
-#line 3057 "y.tab.c" /* yacc.c:1646  */
+#line 669 "grammar.y" /* yacc.c:1646  */
+    { (yyval.a) = gen_loadi(cstate, (yyvsp[0].i)); }
+#line 3052 "grammar.c" /* yacc.c:1646  */
     break;
 
   case 158:
-#line 657 "grammar.y" /* yacc.c:1646  */
-    { (yyval.a) = gen_load((yyvsp[-3].i), (yyvsp[-1].a), 1); }
-#line 3063 "y.tab.c" /* yacc.c:1646  */
+#line 672 "grammar.y" /* yacc.c:1646  */
+    { (yyval.a) = gen_load(cstate, (yyvsp[-3].i), (yyvsp[-1].a), 1); }
+#line 3058 "grammar.c" /* yacc.c:1646  */
     break;
 
   case 159:
-#line 658 "grammar.y" /* yacc.c:1646  */
-    { (yyval.a) = gen_load((yyvsp[-5].i), (yyvsp[-3].a), (yyvsp[-1].i)); }
-#line 3069 "y.tab.c" /* yacc.c:1646  */
+#line 673 "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  */
     break;
 
   case 160:
-#line 659 "grammar.y" /* yacc.c:1646  */
-    { (yyval.a) = gen_arth(BPF_ADD, (yyvsp[-2].a), (yyvsp[0].a)); }
-#line 3075 "y.tab.c" /* yacc.c:1646  */
+#line 674 "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  */
     break;
 
   case 161:
-#line 660 "grammar.y" /* yacc.c:1646  */
-    { (yyval.a) = gen_arth(BPF_SUB, (yyvsp[-2].a), (yyvsp[0].a)); }
-#line 3081 "y.tab.c" /* yacc.c:1646  */
+#line 675 "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  */
     break;
 
   case 162:
-#line 661 "grammar.y" /* yacc.c:1646  */
-    { (yyval.a) = gen_arth(BPF_MUL, (yyvsp[-2].a), (yyvsp[0].a)); }
-#line 3087 "y.tab.c" /* yacc.c:1646  */
+#line 676 "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  */
     break;
 
   case 163:
-#line 662 "grammar.y" /* yacc.c:1646  */
-    { (yyval.a) = gen_arth(BPF_DIV, (yyvsp[-2].a), (yyvsp[0].a)); }
-#line 3093 "y.tab.c" /* yacc.c:1646  */
+#line 677 "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  */
     break;
 
   case 164:
-#line 663 "grammar.y" /* yacc.c:1646  */
-    { (yyval.a) = gen_arth(BPF_MOD, (yyvsp[-2].a), (yyvsp[0].a)); }
-#line 3099 "y.tab.c" /* yacc.c:1646  */
+#line 678 "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  */
     break;
 
   case 165:
-#line 664 "grammar.y" /* yacc.c:1646  */
-    { (yyval.a) = gen_arth(BPF_AND, (yyvsp[-2].a), (yyvsp[0].a)); }
-#line 3105 "y.tab.c" /* yacc.c:1646  */
+#line 679 "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  */
     break;
 
   case 166:
-#line 665 "grammar.y" /* yacc.c:1646  */
-    { (yyval.a) = gen_arth(BPF_OR, (yyvsp[-2].a), (yyvsp[0].a)); }
-#line 3111 "y.tab.c" /* yacc.c:1646  */
+#line 680 "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  */
     break;
 
   case 167:
-#line 666 "grammar.y" /* yacc.c:1646  */
-    { (yyval.a) = gen_arth(BPF_XOR, (yyvsp[-2].a), (yyvsp[0].a)); }
-#line 3117 "y.tab.c" /* yacc.c:1646  */
+#line 681 "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  */
     break;
 
   case 168:
-#line 667 "grammar.y" /* yacc.c:1646  */
-    { (yyval.a) = gen_arth(BPF_LSH, (yyvsp[-2].a), (yyvsp[0].a)); }
-#line 3123 "y.tab.c" /* yacc.c:1646  */
+#line 682 "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  */
     break;
 
   case 169:
-#line 668 "grammar.y" /* yacc.c:1646  */
-    { (yyval.a) = gen_arth(BPF_RSH, (yyvsp[-2].a), (yyvsp[0].a)); }
-#line 3129 "y.tab.c" /* yacc.c:1646  */
+#line 683 "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  */
     break;
 
   case 170:
-#line 669 "grammar.y" /* yacc.c:1646  */
-    { (yyval.a) = gen_neg((yyvsp[0].a)); }
-#line 3135 "y.tab.c" /* yacc.c:1646  */
+#line 684 "grammar.y" /* yacc.c:1646  */
+    { (yyval.a) = gen_neg(cstate, (yyvsp[0].a)); }
+#line 3130 "grammar.c" /* yacc.c:1646  */
     break;
 
   case 171:
-#line 670 "grammar.y" /* yacc.c:1646  */
+#line 685 "grammar.y" /* yacc.c:1646  */
     { (yyval.a) = (yyvsp[-1].a); }
-#line 3141 "y.tab.c" /* yacc.c:1646  */
+#line 3136 "grammar.c" /* yacc.c:1646  */
     break;
 
   case 172:
-#line 671 "grammar.y" /* yacc.c:1646  */
-    { (yyval.a) = gen_loadlen(); }
-#line 3147 "y.tab.c" /* yacc.c:1646  */
+#line 686 "grammar.y" /* yacc.c:1646  */
+    { (yyval.a) = gen_loadlen(cstate); }
+#line 3142 "grammar.c" /* yacc.c:1646  */
     break;
 
   case 173:
-#line 673 "grammar.y" /* yacc.c:1646  */
+#line 688 "grammar.y" /* yacc.c:1646  */
     { (yyval.i) = '&'; }
-#line 3153 "y.tab.c" /* yacc.c:1646  */
+#line 3148 "grammar.c" /* yacc.c:1646  */
     break;
 
   case 174:
-#line 674 "grammar.y" /* yacc.c:1646  */
+#line 689 "grammar.y" /* yacc.c:1646  */
     { (yyval.i) = '|'; }
-#line 3159 "y.tab.c" /* yacc.c:1646  */
+#line 3154 "grammar.c" /* yacc.c:1646  */
     break;
 
   case 175:
-#line 675 "grammar.y" /* yacc.c:1646  */
+#line 690 "grammar.y" /* yacc.c:1646  */
     { (yyval.i) = '<'; }
-#line 3165 "y.tab.c" /* yacc.c:1646  */
+#line 3160 "grammar.c" /* yacc.c:1646  */
     break;
 
   case 176:
-#line 676 "grammar.y" /* yacc.c:1646  */
+#line 691 "grammar.y" /* yacc.c:1646  */
     { (yyval.i) = '>'; }
-#line 3171 "y.tab.c" /* yacc.c:1646  */
+#line 3166 "grammar.c" /* yacc.c:1646  */
     break;
 
   case 177:
-#line 677 "grammar.y" /* yacc.c:1646  */
+#line 692 "grammar.y" /* yacc.c:1646  */
     { (yyval.i) = '='; }
-#line 3177 "y.tab.c" /* yacc.c:1646  */
+#line 3172 "grammar.c" /* yacc.c:1646  */
     break;
 
   case 179:
-#line 680 "grammar.y" /* yacc.c:1646  */
+#line 695 "grammar.y" /* yacc.c:1646  */
     { (yyval.i) = (yyvsp[-1].i); }
-#line 3183 "y.tab.c" /* yacc.c:1646  */
+#line 3178 "grammar.c" /* yacc.c:1646  */
     break;
 
   case 180:
-#line 682 "grammar.y" /* yacc.c:1646  */
+#line 697 "grammar.y" /* yacc.c:1646  */
     { (yyval.i) = A_LANE; }
-#line 3189 "y.tab.c" /* yacc.c:1646  */
+#line 3184 "grammar.c" /* yacc.c:1646  */
     break;
 
   case 181:
-#line 683 "grammar.y" /* yacc.c:1646  */
+#line 698 "grammar.y" /* yacc.c:1646  */
     { (yyval.i) = A_METAC;	}
-#line 3195 "y.tab.c" /* yacc.c:1646  */
+#line 3190 "grammar.c" /* yacc.c:1646  */
     break;
 
   case 182:
-#line 684 "grammar.y" /* yacc.c:1646  */
+#line 699 "grammar.y" /* yacc.c:1646  */
     { (yyval.i) = A_BCC; }
-#line 3201 "y.tab.c" /* yacc.c:1646  */
+#line 3196 "grammar.c" /* yacc.c:1646  */
     break;
 
   case 183:
-#line 685 "grammar.y" /* yacc.c:1646  */
+#line 700 "grammar.y" /* yacc.c:1646  */
     { (yyval.i) = A_OAMF4EC; }
-#line 3207 "y.tab.c" /* yacc.c:1646  */
+#line 3202 "grammar.c" /* yacc.c:1646  */
     break;
 
   case 184:
-#line 686 "grammar.y" /* yacc.c:1646  */
+#line 701 "grammar.y" /* yacc.c:1646  */
     { (yyval.i) = A_OAMF4SC; }
-#line 3213 "y.tab.c" /* yacc.c:1646  */
+#line 3208 "grammar.c" /* yacc.c:1646  */
     break;
 
   case 185:
-#line 687 "grammar.y" /* yacc.c:1646  */
+#line 702 "grammar.y" /* yacc.c:1646  */
     { (yyval.i) = A_SC; }
-#line 3219 "y.tab.c" /* yacc.c:1646  */
+#line 3214 "grammar.c" /* yacc.c:1646  */
     break;
 
   case 186:
-#line 688 "grammar.y" /* yacc.c:1646  */
+#line 703 "grammar.y" /* yacc.c:1646  */
     { (yyval.i) = A_ILMIC; }
-#line 3225 "y.tab.c" /* yacc.c:1646  */
+#line 3220 "grammar.c" /* yacc.c:1646  */
     break;
 
   case 187:
-#line 690 "grammar.y" /* yacc.c:1646  */
+#line 705 "grammar.y" /* yacc.c:1646  */
     { (yyval.i) = A_OAM; }
-#line 3231 "y.tab.c" /* yacc.c:1646  */
+#line 3226 "grammar.c" /* yacc.c:1646  */
     break;
 
   case 188:
-#line 691 "grammar.y" /* yacc.c:1646  */
+#line 706 "grammar.y" /* yacc.c:1646  */
     { (yyval.i) = A_OAMF4; }
-#line 3237 "y.tab.c" /* yacc.c:1646  */
+#line 3232 "grammar.c" /* yacc.c:1646  */
     break;
 
   case 189:
-#line 692 "grammar.y" /* yacc.c:1646  */
+#line 707 "grammar.y" /* yacc.c:1646  */
     { (yyval.i) = A_CONNECTMSG; }
-#line 3243 "y.tab.c" /* yacc.c:1646  */
+#line 3238 "grammar.c" /* yacc.c:1646  */
     break;
 
   case 190:
-#line 693 "grammar.y" /* yacc.c:1646  */
+#line 708 "grammar.y" /* yacc.c:1646  */
     { (yyval.i) = A_METACONNECT; }
-#line 3249 "y.tab.c" /* yacc.c:1646  */
+#line 3244 "grammar.c" /* yacc.c:1646  */
     break;
 
   case 191:
-#line 696 "grammar.y" /* yacc.c:1646  */
+#line 711 "grammar.y" /* yacc.c:1646  */
     { (yyval.blk).atmfieldtype = A_VPI; }
-#line 3255 "y.tab.c" /* yacc.c:1646  */
+#line 3250 "grammar.c" /* yacc.c:1646  */
     break;
 
   case 192:
-#line 697 "grammar.y" /* yacc.c:1646  */
+#line 712 "grammar.y" /* yacc.c:1646  */
     { (yyval.blk).atmfieldtype = A_VCI; }
-#line 3261 "y.tab.c" /* yacc.c:1646  */
+#line 3256 "grammar.c" /* yacc.c:1646  */
     break;
 
   case 194:
-#line 700 "grammar.y" /* yacc.c:1646  */
-    { (yyval.blk).b = gen_atmfield_code((yyvsp[-2].blk).atmfieldtype, (bpf_int32)(yyvsp[0].i), (bpf_u_int32)(yyvsp[-1].i), 0); }
-#line 3267 "y.tab.c" /* yacc.c:1646  */
+#line 715 "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  */
     break;
 
   case 195:
-#line 701 "grammar.y" /* yacc.c:1646  */
-    { (yyval.blk).b = gen_atmfield_code((yyvsp[-2].blk).atmfieldtype, (bpf_int32)(yyvsp[0].i), (bpf_u_int32)(yyvsp[-1].i), 1); }
-#line 3273 "y.tab.c" /* yacc.c:1646  */
+#line 716 "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  */
     break;
 
   case 196:
-#line 702 "grammar.y" /* yacc.c:1646  */
+#line 717 "grammar.y" /* yacc.c:1646  */
     { (yyval.blk).b = (yyvsp[-1].blk).b; (yyval.blk).q = qerr; }
-#line 3279 "y.tab.c" /* yacc.c:1646  */
+#line 3274 "grammar.c" /* yacc.c:1646  */
     break;
 
   case 197:
-#line 704 "grammar.y" /* yacc.c:1646  */
+#line 719 "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((yyval.blk).atmfieldtype, (bpf_int32) (yyvsp[0].i), BPF_JEQ, 0);
+		(yyval.blk).b = gen_atmfield_code(cstate, (yyval.blk).atmfieldtype, (bpf_int32) (yyvsp[0].i), BPF_JEQ, 0);
 	}
-#line 3290 "y.tab.c" /* yacc.c:1646  */
+#line 3285 "grammar.c" /* yacc.c:1646  */
     break;
 
   case 199:
-#line 712 "grammar.y" /* yacc.c:1646  */
+#line 727 "grammar.y" /* yacc.c:1646  */
     { gen_or((yyvsp[-2].blk).b, (yyvsp[0].blk).b); (yyval.blk) = (yyvsp[0].blk); }
-#line 3296 "y.tab.c" /* yacc.c:1646  */
+#line 3291 "grammar.c" /* yacc.c:1646  */
     break;
 
   case 200:
-#line 715 "grammar.y" /* yacc.c:1646  */
+#line 730 "grammar.y" /* yacc.c:1646  */
     { (yyval.i) = M_FISU; }
-#line 3302 "y.tab.c" /* yacc.c:1646  */
+#line 3297 "grammar.c" /* yacc.c:1646  */
     break;
 
   case 201:
-#line 716 "grammar.y" /* yacc.c:1646  */
+#line 731 "grammar.y" /* yacc.c:1646  */
     { (yyval.i) = M_LSSU; }
-#line 3308 "y.tab.c" /* yacc.c:1646  */
+#line 3303 "grammar.c" /* yacc.c:1646  */
     break;
 
   case 202:
-#line 717 "grammar.y" /* yacc.c:1646  */
+#line 732 "grammar.y" /* yacc.c:1646  */
     { (yyval.i) = M_MSU; }
-#line 3314 "y.tab.c" /* yacc.c:1646  */
+#line 3309 "grammar.c" /* yacc.c:1646  */
     break;
 
   case 203:
-#line 718 "grammar.y" /* yacc.c:1646  */
+#line 733 "grammar.y" /* yacc.c:1646  */
     { (yyval.i) = MH_FISU; }
-#line 3320 "y.tab.c" /* yacc.c:1646  */
+#line 3315 "grammar.c" /* yacc.c:1646  */
     break;
 
   case 204:
-#line 719 "grammar.y" /* yacc.c:1646  */
+#line 734 "grammar.y" /* yacc.c:1646  */
     { (yyval.i) = MH_LSSU; }
-#line 3326 "y.tab.c" /* yacc.c:1646  */
+#line 3321 "grammar.c" /* yacc.c:1646  */
     break;
 
   case 205:
-#line 720 "grammar.y" /* yacc.c:1646  */
+#line 735 "grammar.y" /* yacc.c:1646  */
     { (yyval.i) = MH_MSU; }
-#line 3332 "y.tab.c" /* yacc.c:1646  */
+#line 3327 "grammar.c" /* yacc.c:1646  */
     break;
 
   case 206:
-#line 723 "grammar.y" /* yacc.c:1646  */
+#line 738 "grammar.y" /* yacc.c:1646  */
     { (yyval.blk).mtp3fieldtype = M_SIO; }
-#line 3338 "y.tab.c" /* yacc.c:1646  */
+#line 3333 "grammar.c" /* yacc.c:1646  */
     break;
 
   case 207:
-#line 724 "grammar.y" /* yacc.c:1646  */
+#line 739 "grammar.y" /* yacc.c:1646  */
     { (yyval.blk).mtp3fieldtype = M_OPC; }
-#line 3344 "y.tab.c" /* yacc.c:1646  */
+#line 3339 "grammar.c" /* yacc.c:1646  */
     break;
 
   case 208:
-#line 725 "grammar.y" /* yacc.c:1646  */
+#line 740 "grammar.y" /* yacc.c:1646  */
     { (yyval.blk).mtp3fieldtype = M_DPC; }
-#line 3350 "y.tab.c" /* yacc.c:1646  */
+#line 3345 "grammar.c" /* yacc.c:1646  */
     break;
 
   case 209:
-#line 726 "grammar.y" /* yacc.c:1646  */
+#line 741 "grammar.y" /* yacc.c:1646  */
     { (yyval.blk).mtp3fieldtype = M_SLS; }
-#line 3356 "y.tab.c" /* yacc.c:1646  */
+#line 3351 "grammar.c" /* yacc.c:1646  */
     break;
 
   case 210:
-#line 727 "grammar.y" /* yacc.c:1646  */
+#line 742 "grammar.y" /* yacc.c:1646  */
     { (yyval.blk).mtp3fieldtype = MH_SIO; }
-#line 3362 "y.tab.c" /* yacc.c:1646  */
+#line 3357 "grammar.c" /* yacc.c:1646  */
     break;
 
   case 211:
-#line 728 "grammar.y" /* yacc.c:1646  */
+#line 743 "grammar.y" /* yacc.c:1646  */
     { (yyval.blk).mtp3fieldtype = MH_OPC; }
-#line 3368 "y.tab.c" /* yacc.c:1646  */
+#line 3363 "grammar.c" /* yacc.c:1646  */
     break;
 
   case 212:
-#line 729 "grammar.y" /* yacc.c:1646  */
+#line 744 "grammar.y" /* yacc.c:1646  */
     { (yyval.blk).mtp3fieldtype = MH_DPC; }
-#line 3374 "y.tab.c" /* yacc.c:1646  */
+#line 3369 "grammar.c" /* yacc.c:1646  */
     break;
 
   case 213:
-#line 730 "grammar.y" /* yacc.c:1646  */
+#line 745 "grammar.y" /* yacc.c:1646  */
     { (yyval.blk).mtp3fieldtype = MH_SLS; }
-#line 3380 "y.tab.c" /* yacc.c:1646  */
+#line 3375 "grammar.c" /* yacc.c:1646  */
     break;
 
   case 215:
-#line 733 "grammar.y" /* yacc.c:1646  */
-    { (yyval.blk).b = gen_mtp3field_code((yyvsp[-2].blk).mtp3fieldtype, (u_int)(yyvsp[0].i), (u_int)(yyvsp[-1].i), 0); }
-#line 3386 "y.tab.c" /* yacc.c:1646  */
+#line 748 "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  */
     break;
 
   case 216:
-#line 734 "grammar.y" /* yacc.c:1646  */
-    { (yyval.blk).b = gen_mtp3field_code((yyvsp[-2].blk).mtp3fieldtype, (u_int)(yyvsp[0].i), (u_int)(yyvsp[-1].i), 1); }
-#line 3392 "y.tab.c" /* yacc.c:1646  */
+#line 749 "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  */
     break;
 
   case 217:
-#line 735 "grammar.y" /* yacc.c:1646  */
+#line 750 "grammar.y" /* yacc.c:1646  */
     { (yyval.blk).b = (yyvsp[-1].blk).b; (yyval.blk).q = qerr; }
-#line 3398 "y.tab.c" /* yacc.c:1646  */
+#line 3393 "grammar.c" /* yacc.c:1646  */
     break;
 
   case 218:
-#line 737 "grammar.y" /* yacc.c:1646  */
+#line 752 "grammar.y" /* yacc.c:1646  */
     {
 	(yyval.blk).mtp3fieldtype = (yyvsp[-1].blk).mtp3fieldtype;
 	if ((yyval.blk).mtp3fieldtype == M_SIO ||
@@ -3409,19 +3404,19 @@
 	    (yyval.blk).mtp3fieldtype == MH_OPC ||
 	    (yyval.blk).mtp3fieldtype == MH_DPC ||
 	    (yyval.blk).mtp3fieldtype == MH_SLS)
-		(yyval.blk).b = gen_mtp3field_code((yyval.blk).mtp3fieldtype, (u_int) (yyvsp[0].i), BPF_JEQ, 0);
+		(yyval.blk).b = gen_mtp3field_code(cstate, (yyval.blk).mtp3fieldtype, (u_int) (yyvsp[0].i), BPF_JEQ, 0);
 	}
-#line 3415 "y.tab.c" /* yacc.c:1646  */
+#line 3410 "grammar.c" /* yacc.c:1646  */
     break;
 
   case 220:
-#line 751 "grammar.y" /* yacc.c:1646  */
+#line 766 "grammar.y" /* yacc.c:1646  */
     { gen_or((yyvsp[-2].blk).b, (yyvsp[0].blk).b); (yyval.blk) = (yyvsp[0].blk); }
-#line 3421 "y.tab.c" /* yacc.c:1646  */
+#line 3416 "grammar.c" /* yacc.c:1646  */
     break;
 
 
-#line 3425 "y.tab.c" /* yacc.c:1646  */
+#line 3420 "grammar.c" /* yacc.c:1646  */
       default: break;
     }
   /* User semantic actions sometimes alter yychar, and that requires
@@ -3471,7 +3466,7 @@
     {
       ++yynerrs;
 #if ! YYERROR_VERBOSE
-      yyerror (YY_("syntax error"));
+      yyerror (yyscanner, cstate, YY_("syntax error"));
 #else
 # define YYSYNTAX_ERROR yysyntax_error (&yymsg_alloc, &yymsg, \
                                         yyssp, yytoken)
@@ -3498,7 +3493,7 @@
                 yymsgp = yymsg;
               }
           }
-        yyerror (yymsgp);
+        yyerror (yyscanner, cstate, yymsgp);
         if (yysyntax_error_status == 2)
           goto yyexhaustedlab;
       }
@@ -3522,7 +3517,7 @@
       else
         {
           yydestruct ("Error: discarding",
-                      yytoken, &yylval);
+                      yytoken, &yylval, yyscanner, cstate);
           yychar = YYEMPTY;
         }
     }
@@ -3578,7 +3573,7 @@
 
 
       yydestruct ("Error: popping",
-                  yystos[yystate], yyvsp);
+                  yystos[yystate], yyvsp, yyscanner, cstate);
       YYPOPSTACK (1);
       yystate = *yyssp;
       YY_STACK_PRINT (yyss, yyssp);
@@ -3615,7 +3610,7 @@
 | yyexhaustedlab -- memory exhaustion comes here.  |
 `-------------------------------------------------*/
 yyexhaustedlab:
-  yyerror (YY_("memory exhausted"));
+  yyerror (yyscanner, cstate, YY_("memory exhausted"));
   yyresult = 2;
   /* Fall through.  */
 #endif
@@ -3627,7 +3622,7 @@
          user semantic actions for why this is necessary.  */
       yytoken = YYTRANSLATE (yychar);
       yydestruct ("Cleanup: discarding lookahead",
-                  yytoken, &yylval);
+                  yytoken, &yylval, yyscanner, cstate);
     }
   /* Do not reclaim the symbols of the rule whose action triggered
      this YYABORT or YYACCEPT.  */
@@ -3636,7 +3631,7 @@
   while (yyssp != yyss)
     {
       yydestruct ("Cleanup: popping",
-                  yystos[*yyssp], yyvsp);
+                  yystos[*yyssp], yyvsp, yyscanner, cstate);
       YYPOPSTACK (1);
     }
 #ifndef yyoverflow
@@ -3649,5 +3644,5 @@
 #endif
   return yyresult;
 }
-#line 753 "grammar.y" /* yacc.c:1906  */
+#line 768 "grammar.y" /* yacc.c:1906  */
 
diff --git a/tokdefs.h b/grammar.h
similarity index 95%
rename from tokdefs.h
rename to grammar.h
index da9fd91..2a495a0 100644
--- a/tokdefs.h
+++ b/grammar.h
@@ -30,8 +30,8 @@
    This special exception was added by the Free Software Foundation in
    version 2.2 of Bison.  */
 
-#ifndef YY_PCAP_Y_TAB_H_INCLUDED
-# define YY_PCAP_Y_TAB_H_INCLUDED
+#ifndef YY_PCAP_GRAMMAR_H_INCLUDED
+# define YY_PCAP_GRAMMAR_H_INCLUDED
 /* Debug traces.  */
 #ifndef YYDEBUG
 # define YYDEBUG 0
@@ -292,7 +292,7 @@
 typedef union YYSTYPE YYSTYPE;
 union YYSTYPE
 {
-#line 256 "grammar.y" /* yacc.c:1909  */
+#line 271 "grammar.y" /* yacc.c:1909  */
 
 	int i;
 	bpf_u_int32 h;
@@ -308,15 +308,14 @@
 	} blk;
 	struct block *rblk;
 
-#line 312 "y.tab.h" /* yacc.c:1909  */
+#line 312 "grammar.h" /* yacc.c:1909  */
 };
 # define YYSTYPE_IS_TRIVIAL 1
 # define YYSTYPE_IS_DECLARED 1
 #endif
 
 
-extern YYSTYPE pcap_lval;
 
-int pcap_parse (void);
+int pcap_parse (void *yyscanner, compiler_state_t *cstate);
 
-#endif /* !YY_PCAP_Y_TAB_H_INCLUDED  */
+#endif /* !YY_PCAP_GRAMMAR_H_INCLUDED  */
diff --git a/grammar.y b/grammar.y
index 995a514..8e1d40a 100644
--- a/grammar.y
+++ b/grammar.y
@@ -1,3 +1,28 @@
+/*
+ * We want a reentrant parser.
+ */
+%pure-parser
+
+/*
+ * We also want a reentrant scanner, so we have to pass the
+ * handle for the reentrant scanner to the parser, and the
+ * parser has to pass it to the lexical analyzer.
+ *
+ * We use void * rather than yyscan_t because, at least with some
+ * versions of Flex and Bison, if you use yyscan_t in %parse-param and
+ * %lex-param, you have to include scanner.h before grammar.h to get
+ * yyscan_t declared, and you have to include grammar.h before scanner.h
+ * to get YYSTYPE declared.  Using void * breaks the cycle; the Flex
+ * documentation says yyscan_t is just a void *.
+ */
+%parse-param   {void *yyscanner}
+%lex-param   {void *yyscanner}
+
+/*
+ * And we need to pass the compiler state to the scanner.
+ */
+%parse-param {compiler_state_t *cstate}
+
 %{
 /*
  * Copyright (c) 1988, 1989, 1990, 1991, 1992, 1993, 1994, 1995, 1996
@@ -25,16 +50,16 @@
 #include "config.h"
 #endif
 
-#ifdef WIN32
+#ifdef _WIN32
 #include <pcap-stdinc.h>
-#else /* WIN32 */
+#else /* _WIN32 */
 #include <sys/types.h>
 #include <sys/socket.h>
-#endif /* WIN32 */
+#endif /* _WIN32 */
 
 #include <stdlib.h>
 
-#ifndef WIN32
+#ifndef _WIN32
 #if __STDC__
 struct mbuf;
 struct rtentry;
@@ -42,13 +67,16 @@
 
 #include <netinet/in.h>
 #include <arpa/inet.h>
-#endif /* WIN32 */
+#endif /* _WIN32 */
 
 #include <stdio.h>
 
 #include "pcap-int.h"
 
 #include "gencode.h"
+#include "grammar.h"
+#include "scanner.h"
+
 #ifdef HAVE_NET_PFVAR_H
 #include <net/if.h>
 #include <net/pfvar.h>
@@ -169,31 +197,18 @@
 	return (-1);
 }
 
-int n_errors = 0;
-
 static struct qual qerr = { Q_UNDEF, Q_UNDEF, Q_UNDEF, Q_UNDEF };
 
 static void
-yyerror(const char *msg)
+yyerror(void *yyscanner, compiler_state_t *cstate, const char *msg)
 {
-	++n_errors;
-	bpf_error("%s", msg);
+	bpf_syntax_error(cstate, msg);
 	/* NOTREACHED */
 }
 
-#ifdef NEED_YYPARSE_WRAPPER
-int yyparse(void);
-
-int
-pcap_parse()
-{
-	return (yyparse());
-}
-#endif
-
 #ifdef HAVE_NET_PFVAR_H
 static int
-pfreason_to_num(const char *reason)
+pfreason_to_num(compiler_state_t *cstate, const char *reason)
 {
 	const char *reasons[] = PFRES_NAMES;
 	int i;
@@ -202,12 +217,12 @@
 		if (pcap_strcasecmp(reason, reasons[i]) == 0)
 			return (i);
 	}
-	bpf_error("unknown PF reason");
+	bpf_error(cstate, "unknown PF reason");
 	/*NOTREACHED*/
 }
 
 static int
-pfaction_to_num(const char *action)
+pfaction_to_num(compiler_state_t *cstate, const char *action)
 {
 	if (pcap_strcasecmp(action, "pass") == 0 ||
 	    pcap_strcasecmp(action, "accept") == 0)
@@ -226,15 +241,15 @@
 		return (PF_NORDR);
 #endif
 	else {
-		bpf_error("unknown PF action");
+		bpf_error(cstate, "unknown PF action");
 		/*NOTREACHED*/
 	}
 }
 #else /* !HAVE_NET_PFVAR_H */
 static int
-pfreason_to_num(const char *reason)
+pfreason_to_num(compiler_state_t *cstate, const char *reason)
 {
-	bpf_error("libpcap was compiled on a machine without pf support");
+	bpf_error(cstate, "libpcap was compiled on a machine without pf support");
 	/*NOTREACHED*/
 
 	/* this is to make the VC compiler happy */
@@ -242,9 +257,9 @@
 }
 
 static int
-pfaction_to_num(const char *action)
+pfaction_to_num(compiler_state_t *cstate, const char *action)
 {
-	bpf_error("libpcap was compiled on a machine without pf support");
+	bpf_error(cstate, "libpcap was compiled on a machine without pf support");
 	/*NOTREACHED*/
 
 	/* this is to make the VC compiler happy */
@@ -329,7 +344,7 @@
 %%
 prog:	  null expr
 {
-	finish_parse($2.b);
+	finish_parse(cstate, $2.b);
 }
 	| null
 	;
@@ -346,48 +361,48 @@
 or:	  OR			{ $$ = $<blk>0; }
 	;
 id:	  nid
-	| pnum			{ $$.b = gen_ncode(NULL, (bpf_u_int32)$1,
+	| pnum			{ $$.b = gen_ncode(cstate, NULL, (bpf_u_int32)$1,
 						   $$.q = $<blk>0.q); }
 	| paren pid ')'		{ $$ = $2; }
 	;
-nid:	  ID			{ $$.b = gen_scode($1, $$.q = $<blk>0.q); }
-	| HID '/' NUM		{ $$.b = gen_mcode($1, NULL, $3,
+nid:	  ID			{ $$.b = gen_scode(cstate, $1, $$.q = $<blk>0.q); }
+	| HID '/' NUM		{ $$.b = gen_mcode(cstate, $1, NULL, $3,
 				    $$.q = $<blk>0.q); }
-	| HID NETMASK HID	{ $$.b = gen_mcode($1, $3, 0,
+	| HID NETMASK HID	{ $$.b = gen_mcode(cstate, $1, $3, 0,
 				    $$.q = $<blk>0.q); }
 	| HID			{
 				  /* Decide how to parse HID based on proto */
 				  $$.q = $<blk>0.q;
 				  if ($$.q.addr == Q_PORT)
-				  	bpf_error("'port' modifier applied to ip host");
+				  	bpf_error(cstate, "'port' modifier applied to ip host");
 				  else if ($$.q.addr == Q_PORTRANGE)
-				  	bpf_error("'portrange' modifier applied to ip host");
+				  	bpf_error(cstate, "'portrange' modifier applied to ip host");
 				  else if ($$.q.addr == Q_PROTO)
-				  	bpf_error("'proto' modifier applied to ip host");
+				  	bpf_error(cstate, "'proto' modifier applied to ip host");
 				  else if ($$.q.addr == Q_PROTOCHAIN)
-				  	bpf_error("'protochain' modifier applied to ip host");
-				  $$.b = gen_ncode($1, 0, $$.q);
+				  	bpf_error(cstate, "'protochain' modifier applied to ip host");
+				  $$.b = gen_ncode(cstate, $1, 0, $$.q);
 				}
 	| HID6 '/' NUM		{
 #ifdef INET6
-				  $$.b = gen_mcode6($1, NULL, $3,
+				  $$.b = gen_mcode6(cstate, $1, NULL, $3,
 				    $$.q = $<blk>0.q);
 #else
-				  bpf_error("'ip6addr/prefixlen' not supported "
+				  bpf_error(cstate, "'ip6addr/prefixlen' not supported "
 					"in this configuration");
 #endif /*INET6*/
 				}
 	| HID6			{
 #ifdef INET6
-				  $$.b = gen_mcode6($1, 0, 128,
+				  $$.b = gen_mcode6(cstate, $1, 0, 128,
 				    $$.q = $<blk>0.q);
 #else
-				  bpf_error("'ip6addr' not supported "
+				  bpf_error(cstate, "'ip6addr' not supported "
 					"in this configuration");
 #endif /*INET6*/
 				}
 	| EID			{
-				  $$.b = gen_ecode($1, $$.q = $<blk>0.q);
+				  $$.b = gen_ecode(cstate, $1, $$.q = $<blk>0.q);
 				  /*
 				   * $1 was allocated by "pcap_ether_aton()",
 				   * so we must free it now that we're done
@@ -396,7 +411,7 @@
 				  free($1);
 				}
 	| AID			{
-				  $$.b = gen_acode($1, $$.q = $<blk>0.q);
+				  $$.b = gen_acode(cstate, $1, $$.q = $<blk>0.q);
 				  /*
 				   * $1 was allocated by "pcap_ether_aton()",
 				   * so we must free it now that we're done
@@ -414,7 +429,7 @@
 	| qid and id		{ gen_and($1.b, $3.b); $$ = $3; }
 	| qid or id		{ gen_or($1.b, $3.b); $$ = $3; }
 	;
-qid:	  pnum			{ $$.b = gen_ncode(NULL, (bpf_u_int32)$1,
+qid:	  pnum			{ $$.b = gen_ncode(cstate, NULL, (bpf_u_int32)$1,
 						   $$.q = $<blk>0.q); }
 	| pid
 	;
@@ -430,16 +445,16 @@
 	;
 rterm:	  head id		{ $$ = $2; }
 	| paren expr ')'	{ $$.b = $2.b; $$.q = $1.q; }
-	| pname			{ $$.b = gen_proto_abbrev($1); $$.q = qerr; }
-	| arth relop arth	{ $$.b = gen_relation($2, $1, $3, 0);
+	| pname			{ $$.b = gen_proto_abbrev(cstate, $1); $$.q = qerr; }
+	| arth relop arth	{ $$.b = gen_relation(cstate, $2, $1, $3, 0);
 				  $$.q = qerr; }
-	| arth irelop arth	{ $$.b = gen_relation($2, $1, $3, 1);
+	| arth irelop arth	{ $$.b = gen_relation(cstate, $2, $1, $3, 1);
 				  $$.q = qerr; }
 	| other			{ $$.b = $1; $$.q = qerr; }
-	| atmtype		{ $$.b = gen_atmtype_abbrev($1); $$.q = qerr; }
-	| atmmultitype		{ $$.b = gen_atmmulti_abbrev($1); $$.q = qerr; }
+	| atmtype		{ $$.b = gen_atmtype_abbrev(cstate, $1); $$.q = qerr; }
+	| atmmultitype		{ $$.b = gen_atmmulti_abbrev(cstate, $1); $$.q = qerr; }
 	| atmfield atmvalue	{ $$.b = $2.b; $$.q = qerr; }
-	| mtp2type		{ $$.b = gen_mtp2type_abbrev($1); $$.q = qerr; }
+	| mtp2type		{ $$.b = gen_mtp2type_abbrev(cstate, $1); $$.q = qerr; }
 	| mtp3field mtp3value	{ $$.b = $2.b; $$.q = qerr; }
 	;
 /* protocol level qualifiers */
@@ -509,54 +524,54 @@
 	| NETBEUI		{ $$ = Q_NETBEUI; }
 	| RADIO			{ $$ = Q_RADIO; }
 	;
-other:	  pqual TK_BROADCAST	{ $$ = gen_broadcast($1); }
-	| pqual TK_MULTICAST	{ $$ = gen_multicast($1); }
-	| LESS NUM		{ $$ = gen_less($2); }
-	| GREATER NUM		{ $$ = gen_greater($2); }
-	| CBYTE NUM byteop NUM	{ $$ = gen_byteop($3, $2, $4); }
-	| INBOUND		{ $$ = gen_inbound(0); }
-	| OUTBOUND		{ $$ = gen_inbound(1); }
-	| VLAN pnum		{ $$ = gen_vlan($2); }
-	| VLAN			{ $$ = gen_vlan(-1); }
-	| MPLS pnum		{ $$ = gen_mpls($2); }
-	| MPLS			{ $$ = gen_mpls(-1); }
-	| PPPOED		{ $$ = gen_pppoed(); }
-	| PPPOES pnum		{ $$ = gen_pppoes($2); }
-	| PPPOES		{ $$ = gen_pppoes(-1); }
-	| GENEVE pnum		{ $$ = gen_geneve($2); }
-	| GENEVE		{ $$ = gen_geneve(-1); }
+other:	  pqual TK_BROADCAST	{ $$ = gen_broadcast(cstate, $1); }
+	| pqual TK_MULTICAST	{ $$ = gen_multicast(cstate, $1); }
+	| LESS NUM		{ $$ = gen_less(cstate, $2); }
+	| GREATER NUM		{ $$ = gen_greater(cstate, $2); }
+	| CBYTE NUM byteop NUM	{ $$ = gen_byteop(cstate, $3, $2, $4); }
+	| INBOUND		{ $$ = gen_inbound(cstate, 0); }
+	| OUTBOUND		{ $$ = gen_inbound(cstate, 1); }
+	| VLAN pnum		{ $$ = gen_vlan(cstate, $2); }
+	| VLAN			{ $$ = gen_vlan(cstate, -1); }
+	| MPLS pnum		{ $$ = gen_mpls(cstate, $2); }
+	| MPLS			{ $$ = gen_mpls(cstate, -1); }
+	| PPPOED		{ $$ = gen_pppoed(cstate); }
+	| PPPOES pnum		{ $$ = gen_pppoes(cstate, $2); }
+	| PPPOES		{ $$ = gen_pppoes(cstate, -1); }
+	| GENEVE pnum		{ $$ = gen_geneve(cstate, $2); }
+	| GENEVE		{ $$ = gen_geneve(cstate, -1); }
 	| pfvar			{ $$ = $1; }
 	| pqual p80211		{ $$ = $2; }
 	| pllc			{ $$ = $1; }
 	;
 
-pfvar:	  PF_IFNAME ID		{ $$ = gen_pf_ifname($2); }
-	| PF_RSET ID		{ $$ = gen_pf_ruleset($2); }
-	| PF_RNR NUM		{ $$ = gen_pf_rnr($2); }
-	| PF_SRNR NUM		{ $$ = gen_pf_srnr($2); }
-	| PF_REASON reason	{ $$ = gen_pf_reason($2); }
-	| PF_ACTION action	{ $$ = gen_pf_action($2); }
+pfvar:	  PF_IFNAME ID		{ $$ = gen_pf_ifname(cstate, $2); }
+	| PF_RSET ID		{ $$ = gen_pf_ruleset(cstate, $2); }
+	| PF_RNR NUM		{ $$ = gen_pf_rnr(cstate, $2); }
+	| PF_SRNR NUM		{ $$ = gen_pf_srnr(cstate, $2); }
+	| PF_REASON reason	{ $$ = gen_pf_reason(cstate, $2); }
+	| PF_ACTION action	{ $$ = gen_pf_action(cstate, $2); }
 	;
 
 p80211:   TYPE type SUBTYPE subtype
-				{ $$ = gen_p80211_type($2 | $4,
+				{ $$ = gen_p80211_type(cstate, $2 | $4,
 					IEEE80211_FC0_TYPE_MASK |
 					IEEE80211_FC0_SUBTYPE_MASK);
 				}
-	| TYPE type		{ $$ = gen_p80211_type($2,
+	| TYPE type		{ $$ = gen_p80211_type(cstate, $2,
 					IEEE80211_FC0_TYPE_MASK);
 				}
-	| SUBTYPE type_subtype	{ $$ = gen_p80211_type($2,
+	| SUBTYPE type_subtype	{ $$ = gen_p80211_type(cstate, $2,
 					IEEE80211_FC0_TYPE_MASK |
 					IEEE80211_FC0_SUBTYPE_MASK);
 				}
-	| DIR dir		{ $$ = gen_p80211_fcdir($2); }
+	| DIR dir		{ $$ = gen_p80211_fcdir(cstate, $2); }
 	;
 
 type:	  NUM
 	| ID			{ $$ = str2tok($1, ieee80211_types);
 				  if ($$ == -1)
-				  	bpf_error("unknown 802.11 type name");
+				  	bpf_error(cstate, "unknown 802.11 type name");
 				}
 	;
 
@@ -566,7 +581,7 @@
 				  for (i = 0;; i++) {
 				  	if (ieee80211_type_subtypes[i].tok == NULL) {
 				  		/* Ran out of types */
-						bpf_error("unknown 802.11 type");
+						bpf_error(cstate, "unknown 802.11 type");
 						break;
 					}
 					if ($<i>-1 == ieee80211_type_subtypes[i].type) {
@@ -577,7 +592,7 @@
 
 				  $$ = str2tok($1, types);
 				  if ($$ == -1)
-					bpf_error("unknown 802.11 subtype name");
+					bpf_error(cstate, "unknown 802.11 subtype name");
 				}
 	;
 
@@ -585,7 +600,7 @@
 				  for (i = 0;; i++) {
 				  	if (ieee80211_type_subtypes[i].tok == NULL) {
 				  		/* Ran out of types */
-						bpf_error("unknown 802.11 type name");
+						bpf_error(cstate, "unknown 802.11 type name");
 						break;
 					}
 					$$ = str2tok($1, ieee80211_type_subtypes[i].tok);
@@ -597,29 +612,29 @@
 				}
 		;
 
-pllc:	LLC			{ $$ = gen_llc(); }
+pllc:	LLC			{ $$ = gen_llc(cstate); }
 	| LLC ID		{ if (pcap_strcasecmp($2, "i") == 0)
-					$$ = gen_llc_i();
+					$$ = gen_llc_i(cstate);
 				  else if (pcap_strcasecmp($2, "s") == 0)
-					$$ = gen_llc_s();
+					$$ = gen_llc_s(cstate);
 				  else if (pcap_strcasecmp($2, "u") == 0)
-					$$ = gen_llc_u();
+					$$ = gen_llc_u(cstate);
 				  else {
-				  	u_int subtype;
+					int subtype;
 
 					subtype = str2tok($2, llc_s_subtypes);
 					if (subtype != -1)
-						$$ = gen_llc_s_subtype(subtype);
+						$$ = gen_llc_s_subtype(cstate, subtype);
 					else {
 						subtype = str2tok($2, llc_u_subtypes);
 						if (subtype == -1)
-					  		bpf_error("unknown LLC type name \"%s\"", $2);
-						$$ = gen_llc_u_subtype(subtype);
+					  		bpf_error(cstate, "unknown LLC type name \"%s\"", $2);
+						$$ = gen_llc_u_subtype(cstate, subtype);
 					}
 				  }
 				}
 				/* sigh, "rnr" is already a keyword for PF */
-	| LLC PF_RNR		{ $$ = gen_llc_s_subtype(LLC_RNR); }
+	| LLC PF_RNR		{ $$ = gen_llc_s_subtype(cstate, LLC_RNR); }
 	;
 
 dir:	  NUM
@@ -632,15 +647,15 @@
 				  else if (pcap_strcasecmp($1, "dstods") == 0)
 					$$ = IEEE80211_FC1_DIR_DSTODS;
 				  else
-					bpf_error("unknown 802.11 direction");
+					bpf_error(cstate, "unknown 802.11 direction");
 				}
 	;
 
 reason:	  NUM			{ $$ = $1; }
-	| ID			{ $$ = pfreason_to_num($1); }
+	| ID			{ $$ = pfreason_to_num(cstate, $1); }
 	;
 
-action:	  ID			{ $$ = pfaction_to_num($1); }
+action:	  ID			{ $$ = pfaction_to_num(cstate, $1); }
 	;
 
 relop:	  '>'			{ $$ = BPF_JGT; }
@@ -651,24 +666,24 @@
 	| '<'			{ $$ = BPF_JGE; }
 	| NEQ			{ $$ = BPF_JEQ; }
 	;
-arth:	  pnum			{ $$ = gen_loadi($1); }
+arth:	  pnum			{ $$ = gen_loadi(cstate, $1); }
 	| narth
 	;
-narth:	  pname '[' arth ']'		{ $$ = gen_load($1, $3, 1); }
-	| pname '[' arth ':' NUM ']'	{ $$ = gen_load($1, $3, $5); }
-	| arth '+' arth			{ $$ = gen_arth(BPF_ADD, $1, $3); }
-	| arth '-' arth			{ $$ = gen_arth(BPF_SUB, $1, $3); }
-	| arth '*' arth			{ $$ = gen_arth(BPF_MUL, $1, $3); }
-	| arth '/' arth			{ $$ = gen_arth(BPF_DIV, $1, $3); }
-	| arth '%' arth			{ $$ = gen_arth(BPF_MOD, $1, $3); }
-	| arth '&' arth			{ $$ = gen_arth(BPF_AND, $1, $3); }
-	| arth '|' arth			{ $$ = gen_arth(BPF_OR, $1, $3); }
-	| arth '^' arth			{ $$ = gen_arth(BPF_XOR, $1, $3); }
-	| arth LSH arth			{ $$ = gen_arth(BPF_LSH, $1, $3); }
-	| arth RSH arth			{ $$ = gen_arth(BPF_RSH, $1, $3); }
-	| '-' arth %prec UMINUS		{ $$ = gen_neg($2); }
+narth:	  pname '[' arth ']'		{ $$ = gen_load(cstate, $1, $3, 1); }
+	| pname '[' arth ':' NUM ']'	{ $$ = gen_load(cstate, $1, $3, $5); }
+	| arth '+' arth			{ $$ = gen_arth(cstate, BPF_ADD, $1, $3); }
+	| arth '-' arth			{ $$ = gen_arth(cstate, BPF_SUB, $1, $3); }
+	| arth '*' arth			{ $$ = gen_arth(cstate, BPF_MUL, $1, $3); }
+	| arth '/' arth			{ $$ = gen_arth(cstate, BPF_DIV, $1, $3); }
+	| arth '%' arth			{ $$ = gen_arth(cstate, BPF_MOD, $1, $3); }
+	| arth '&' arth			{ $$ = gen_arth(cstate, BPF_AND, $1, $3); }
+	| arth '|' arth			{ $$ = gen_arth(cstate, BPF_OR, $1, $3); }
+	| arth '^' arth			{ $$ = gen_arth(cstate, BPF_XOR, $1, $3); }
+	| arth LSH arth			{ $$ = gen_arth(cstate, BPF_LSH, $1, $3); }
+	| arth RSH arth			{ $$ = gen_arth(cstate, BPF_RSH, $1, $3); }
+	| '-' arth %prec UMINUS		{ $$ = gen_neg(cstate, $2); }
 	| paren narth ')'		{ $$ = $2; }
-	| LEN				{ $$ = gen_loadlen(); }
+	| LEN				{ $$ = gen_loadlen(cstate); }
 	;
 byteop:	  '&'			{ $$ = '&'; }
 	| '|'			{ $$ = '|'; }
@@ -697,15 +712,15 @@
 	| VCI			{ $$.atmfieldtype = A_VCI; }
 	;
 atmvalue: atmfieldvalue
-	| relop NUM		{ $$.b = gen_atmfield_code($<blk>0.atmfieldtype, (bpf_int32)$2, (bpf_u_int32)$1, 0); }
-	| irelop NUM		{ $$.b = gen_atmfield_code($<blk>0.atmfieldtype, (bpf_int32)$2, (bpf_u_int32)$1, 1); }
+	| relop NUM		{ $$.b = gen_atmfield_code(cstate, $<blk>0.atmfieldtype, (bpf_int32)$2, (bpf_u_int32)$1, 0); }
+	| irelop NUM		{ $$.b = gen_atmfield_code(cstate, $<blk>0.atmfieldtype, (bpf_int32)$2, (bpf_u_int32)$1, 1); }
 	| paren atmlistvalue ')' { $$.b = $2.b; $$.q = qerr; }
 	;
 atmfieldvalue: NUM {
 	$$.atmfieldtype = $<blk>0.atmfieldtype;
 	if ($$.atmfieldtype == A_VPI ||
 	    $$.atmfieldtype == A_VCI)
-		$$.b = gen_atmfield_code($$.atmfieldtype, (bpf_int32) $1, BPF_JEQ, 0);
+		$$.b = gen_atmfield_code(cstate, $$.atmfieldtype, (bpf_int32) $1, BPF_JEQ, 0);
 	}
 	;
 atmlistvalue: atmfieldvalue
@@ -730,8 +745,8 @@
 	| HSLS                  { $$.mtp3fieldtype = MH_SLS; }
 	;
 mtp3value: mtp3fieldvalue
-	| relop NUM		{ $$.b = gen_mtp3field_code($<blk>0.mtp3fieldtype, (u_int)$2, (u_int)$1, 0); }
-	| irelop NUM		{ $$.b = gen_mtp3field_code($<blk>0.mtp3fieldtype, (u_int)$2, (u_int)$1, 1); }
+	| relop NUM		{ $$.b = gen_mtp3field_code(cstate, $<blk>0.mtp3fieldtype, (u_int)$2, (u_int)$1, 0); }
+	| irelop NUM		{ $$.b = gen_mtp3field_code(cstate, $<blk>0.mtp3fieldtype, (u_int)$2, (u_int)$1, 1); }
 	| paren mtp3listvalue ')' { $$.b = $2.b; $$.q = qerr; }
 	;
 mtp3fieldvalue: NUM {
@@ -744,7 +759,7 @@
 	    $$.mtp3fieldtype == MH_OPC ||
 	    $$.mtp3fieldtype == MH_DPC ||
 	    $$.mtp3fieldtype == MH_SLS)
-		$$.b = gen_mtp3field_code($$.mtp3fieldtype, (u_int) $1, BPF_JEQ, 0);
+		$$.b = gen_mtp3field_code(cstate, $$.mtp3fieldtype, (u_int) $1, BPF_JEQ, 0);
 	}
 	;
 mtp3listvalue: mtp3fieldvalue
diff --git a/inet.c b/inet.c
index e7d2104..16a483d 100644
--- a/inet.c
+++ b/inet.c
@@ -36,9 +36,9 @@
 #include "config.h"
 #endif
 
-#ifdef WIN32
+#ifdef _WIN32
 #include <pcap-stdinc.h>
-#else /* WIN32 */
+#else /* _WIN32 */
 
 #include <sys/param.h>
 #ifndef MSDOS
@@ -54,22 +54,16 @@
 struct rtentry;		/* declarations in <net/if.h> */
 #include <net/if.h>
 #include <netinet/in.h>
-#endif /* WIN32 */
+#endif /* _WIN32 */
 
-#include <ctype.h>
 #include <errno.h>
 #include <memory.h>
 #include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
-#if !defined(WIN32) && !defined(__BORLANDC__)
+#if !defined(_WIN32) && !defined(__BORLANDC__)
 #include <unistd.h>
-#endif /* !WIN32 && !__BORLANDC__ */
-#ifdef HAVE_LIMITS_H
-#include <limits.h>
-#else
-#define INT_MAX		2147483647
-#endif
+#endif /* !_WIN32 && !__BORLANDC__ */
 
 #include "pcap-int.h"
 
@@ -77,758 +71,7 @@
 #include "os-proto.h"
 #endif
 
-/* Not all systems have IFF_LOOPBACK */
-#ifdef IFF_LOOPBACK
-#define ISLOOPBACK(name, flags) ((flags) & IFF_LOOPBACK)
-#else
-#define ISLOOPBACK(name, flags) ((name)[0] == 'l' && (name)[1] == 'o' && \
-    (isdigit((unsigned char)((name)[2])) || (name)[2] == '\0'))
-#endif
-
-#ifdef IFF_UP
-#define ISUP(flags) ((flags) & IFF_UP)
-#else
-#define ISUP(flags) 0
-#endif
-
-#ifdef IFF_RUNNING
-#define ISRUNNING(flags) ((flags) & IFF_RUNNING)
-#else
-#define ISRUNNING(flags) 0
-#endif
-
-struct sockaddr *
-dup_sockaddr(struct sockaddr *sa, size_t sa_length)
-{
-	struct sockaddr *newsa;
-
-	if ((newsa = malloc(sa_length)) == NULL)
-		return (NULL);
-	return (memcpy(newsa, sa, sa_length));
-}
-
-/*
- * Construct a "figure of merit" for an interface, for use when sorting
- * the list of interfaces, in which interfaces that are up are superior
- * to interfaces that aren't up, interfaces that are up and running are
- * superior to interfaces that are up but not running, and non-loopback
- * interfaces that are up and running are superior to loopback interfaces,
- * and interfaces with the same flags have a figure of merit that's higher
- * the lower the instance number.
- *
- * The goal is to try to put the interfaces most likely to be useful for
- * capture at the beginning of the list.
- *
- * The figure of merit, which is lower the "better" the interface is,
- * has the uppermost bit set if the interface isn't running, the bit
- * below that set if the interface isn't up, the bit below that set
- * if the interface is a loopback interface, and the interface index
- * in the 29 bits below that.  (Yes, we assume u_int is 32 bits.)
- */
-static u_int
-get_figure_of_merit(pcap_if_t *dev)
-{
-	const char *cp;
-	u_int n;
-
-	if (strcmp(dev->name, "any") == 0) {
-		/*
-		 * Give the "any" device an artificially high instance
-		 * number, so it shows up after all other non-loopback
-		 * interfaces.
-		 */
-		n = 0x1FFFFFFF;	/* 29 all-1 bits */
-	} else {
-		/*
-		 * A number at the end of the device name string is
-		 * assumed to be a unit number.
-		 */
-		cp = dev->name + strlen(dev->name) - 1;
-		while (cp-1 >= dev->name && *(cp-1) >= '0' && *(cp-1) <= '9')
-			cp--;
-		if (*cp >= '0' && *cp <= '9')
-			n = atoi(cp);
-		else
-			n = 0;
-	}
-	if (!(dev->flags & PCAP_IF_RUNNING))
-		n |= 0x80000000;
-	if (!(dev->flags & PCAP_IF_UP))
-		n |= 0x40000000;
-	if (dev->flags & PCAP_IF_LOOPBACK)
-		n |= 0x20000000;
-	return (n);
-}
-
-/*
- * Look for a given device in the specified list of devices.
- *
- * If we find it, return 0 and set *curdev_ret to point to it.
- *
- * If we don't find it, check whether we can open it:
- *
- *     If that fails with PCAP_ERROR_NO_SUCH_DEVICE or
- *     PCAP_ERROR_IFACE_NOT_UP, don't attempt to add an entry for
- *     it, as that probably means it exists but doesn't support
- *     packet capture.
- *
- *     Otherwise, attempt to add an entry for it, with the specified
- *     ifnet flags and description, and, if that succeeds, return 0
- *     and set *curdev_ret to point to the new entry, otherwise
- *     return PCAP_ERROR and set errbuf to an error message.
- */
-int
-add_or_find_if(pcap_if_t **curdev_ret, pcap_if_t **alldevs, const char *name,
-    u_int flags, const char *description, char *errbuf)
-{
-	pcap_t *p;
-	pcap_if_t *curdev, *prevdev, *nextdev;
-	u_int this_figure_of_merit, nextdev_figure_of_merit;
-	char open_errbuf[PCAP_ERRBUF_SIZE];
-	int ret;
-
-	/*
-	 * Is there already an entry in the list for this interface?
-	 */
-	for (curdev = *alldevs; curdev != NULL; curdev = curdev->next) {
-		if (strcmp(name, curdev->name) == 0)
-			break;	/* yes, we found it */
-	}
-
-	if (curdev == NULL) {
-		/*
-		 * No, we didn't find it.
-		 *
-		 * Can we open this interface for live capture?
-		 *
-		 * We do this check so that interfaces that are
-		 * supplied by the interface enumeration mechanism
-		 * we're using but that don't support packet capture
-		 * aren't included in the list.  Loopback interfaces
-		 * on Solaris are an example of this; we don't just
-		 * omit loopback interfaces on all platforms because
-		 * you *can* capture on loopback interfaces on some
-		 * OSes.
-		 *
-		 * On OS X, we don't do this check if the device
-		 * name begins with "wlt"; at least some versions
-		 * of OS X offer monitor mode capturing by having
-		 * a separate "monitor mode" device for each wireless
-		 * adapter, rather than by implementing the ioctls
-		 * that {Free,Net,Open,DragonFly}BSD provide.
-		 * Opening that device puts the adapter into monitor
-		 * mode, which, at least for some adapters, causes
-		 * them to deassociate from the network with which
-		 * they're associated.
-		 *
-		 * Instead, we try to open the corresponding "en"
-		 * device (so that we don't end up with, for users
-		 * without sufficient privilege to open capture
-		 * devices, a list of adapters that only includes
-		 * the wlt devices).
-		 */
-#ifdef __APPLE__
-		if (strncmp(name, "wlt", 3) == 0) {
-			char *en_name;
-			size_t en_name_len;
-
-			/*
-			 * Try to allocate a buffer for the "en"
-			 * device's name.
-			 */
-			en_name_len = strlen(name) - 1;
-			en_name = malloc(en_name_len + 1);
-			if (en_name == NULL) {
-				(void)snprintf(errbuf, PCAP_ERRBUF_SIZE,
-				    "malloc: %s", pcap_strerror(errno));
-				return (-1);
-			}
-			strcpy(en_name, "en");
-			strcat(en_name, name + 3);
-			p = pcap_create(en_name, open_errbuf);
-			free(en_name);
-		} else
-#endif /* __APPLE */
-		p = pcap_create(name, open_errbuf);
-		if (p == NULL) {
-			/*
-			 * The attempt to create the pcap_t failed;
-			 * that's probably an indication that we're
-			 * out of memory.
-			 *
-			 * Don't bother including this interface,
-			 * but don't treat it as an error.
-			 */
-			*curdev_ret = NULL;
-			return (0);
-		}
-		/* Small snaplen, so we don't try to allocate much memory. */
-		pcap_set_snaplen(p, 68);
-		ret = pcap_activate(p);
-		pcap_close(p);
-		switch (ret) {
-
-		case PCAP_ERROR_NO_SUCH_DEVICE:
-		case PCAP_ERROR_IFACE_NOT_UP:
-			/*
-			 * We expect these two errors - they're the
-			 * reason we try to open the device.
-			 *
-			 * PCAP_ERROR_NO_SUCH_DEVICE typically means
-			 * "there's no such device *known to the
-			 * OS's capture mechanism*", so, even though
-			 * it might be a valid network interface, you
-			 * can't capture on it (e.g., the loopback
-			 * device in Solaris up to Solaris 10, or
-			 * the vmnet devices in OS X with VMware
-			 * Fusion).  We don't include those devices
-			 * in our list of devices, as there's no
-			 * point in doing so - they're not available
-			 * for capture.
-			 *
-			 * PCAP_ERROR_IFACE_NOT_UP means that the
-			 * OS's capture mechanism doesn't work on
-			 * interfaces not marked as up; some capture
-			 * mechanisms *do* support that, so we no
-			 * longer reject those interfaces out of hand,
-			 * but we *do* want to reject them if they
-			 * can't be opened for capture.
-			 */
-			*curdev_ret = NULL;
-			return (0);
-		}
-
-		/*
-		 * Yes, we can open it, or we can't, for some other
-		 * reason.
-		 *
-		 * If we can open it, we want to offer it for
-		 * capture, as you can capture on it.  If we can't,
-		 * we want to offer it for capture, so that, if
-		 * the user tries to capture on it, they'll get
-		 * an error and they'll know why they can't
-		 * capture on it (e.g., insufficient permissions)
-		 * or they'll report it as a problem (and then
-		 * have the error message to provide as information).
-		 *
-		 * Allocate a new entry.
-		 */
-		curdev = malloc(sizeof(pcap_if_t));
-		if (curdev == NULL) {
-			(void)snprintf(errbuf, PCAP_ERRBUF_SIZE,
-			    "malloc: %s", pcap_strerror(errno));
-			return (-1);
-		}
-
-		/*
-		 * Fill in the entry.
-		 */
-		curdev->next = NULL;
-		curdev->name = strdup(name);
-		if (curdev->name == NULL) {
-			(void)snprintf(errbuf, PCAP_ERRBUF_SIZE,
-			    "malloc: %s", pcap_strerror(errno));
-			free(curdev);
-			return (-1);
-		}
-		if (description != NULL) {
-			/*
-			 * We have a description for this interface.
-			 */
-			curdev->description = strdup(description);
-			if (curdev->description == NULL) {
-				(void)snprintf(errbuf, PCAP_ERRBUF_SIZE,
-				    "malloc: %s", pcap_strerror(errno));
-				free(curdev->name);
-				free(curdev);
-				return (-1);
-			}
-		} else {
-			/*
-			 * We don't.
-			 */
-			curdev->description = NULL;
-		}
-		curdev->addresses = NULL;	/* list starts out as empty */
-		curdev->flags = 0;
-		if (ISLOOPBACK(name, flags))
-			curdev->flags |= PCAP_IF_LOOPBACK;
-		if (ISUP(flags))
-			curdev->flags |= PCAP_IF_UP;
-		if (ISRUNNING(flags))
-			curdev->flags |= PCAP_IF_RUNNING;
-
-		/*
-		 * Add it to the list, in the appropriate location.
-		 * First, get the "figure of merit" for this
-		 * interface.
-		 */
-		this_figure_of_merit = get_figure_of_merit(curdev);
-
-		/*
-		 * Now look for the last interface with an figure of merit
-		 * less than or equal to the new interface's figure of
-		 * merit.
-		 *
-		 * We start with "prevdev" being NULL, meaning we're before
-		 * the first element in the list.
-		 */
-		prevdev = NULL;
-		for (;;) {
-			/*
-			 * Get the interface after this one.
-			 */
-			if (prevdev == NULL) {
-				/*
-				 * The next element is the first element.
-				 */
-				nextdev = *alldevs;
-			} else
-				nextdev = prevdev->next;
-
-			/*
-			 * Are we at the end of the list?
-			 */
-			if (nextdev == NULL) {
-				/*
-				 * Yes - we have to put the new entry
-				 * after "prevdev".
-				 */
-				break;
-			}
-
-			/*
-			 * Is the new interface's figure of merit less
-			 * than the next interface's figure of merit,
-			 * meaning that the new interface is better
-			 * than the next interface?
-			 */
-			nextdev_figure_of_merit = get_figure_of_merit(nextdev);
-			if (this_figure_of_merit < nextdev_figure_of_merit) {
-				/*
-				 * Yes - we should put the new entry
-				 * before "nextdev", i.e. after "prevdev".
-				 */
-				break;
-			}
-
-			prevdev = nextdev;
-		}
-
-		/*
-		 * Insert before "nextdev".
-		 */
-		curdev->next = nextdev;
-
-		/*
-		 * Insert after "prevdev" - unless "prevdev" is null,
-		 * in which case this is the first interface.
-		 */
-		if (prevdev == NULL) {
-			/*
-			 * This is the first interface.  Pass back a
-			 * pointer to it, and put "curdev" before
-			 * "nextdev".
-			 */
-			*alldevs = curdev;
-		} else
-			prevdev->next = curdev;
-	}
-
-	*curdev_ret = curdev;
-	return (0);
-}
-
-/*
- * Try to get a description for a given device.
- * Returns a mallocated description if it could and NULL if it couldn't.
- *
- * XXX - on FreeBSDs that support it, should it get the sysctl named
- * "dev.{adapter family name}.{adapter unit}.%desc" to get a description
- * of the adapter?  Note that "dev.an.0.%desc" is "Aironet PC4500/PC4800"
- * with my Cisco 350 card, so the name isn't entirely descriptive.  The
- * "dev.an.0.%pnpinfo" has a better description, although one might argue
- * that the problem is really a driver bug - if it can find out that it's
- * a Cisco 340 or 350, rather than an old Aironet card, it should use
- * that in the description.
- *
- * Do NetBSD, DragonflyBSD, or OpenBSD support this as well?  FreeBSD
- * and OpenBSD let you get a description, but it's not generated by the OS,
- * it's set with another ioctl that ifconfig supports; we use that to get
- * a description in FreeBSD and OpenBSD, but if there is no such
- * description available, it still might be nice to get some description
- * string based on the device type or something such as that.
- *
- * In OS X, the System Configuration framework can apparently return
- * names in 10.4 and later.
- *
- * It also appears that freedesktop.org's HAL offers an "info.product"
- * string, but the HAL specification says it "should not be used in any
- * UI" and "subsystem/capability specific properties" should be used
- * instead and, in any case, I think HAL is being deprecated in
- * favor of other stuff such as DeviceKit.  DeviceKit doesn't appear
- * to have any obvious product information for devices, but maybe
- * I haven't looked hard enough.
- *
- * Using the System Configuration framework, or HAL, or DeviceKit, or
- * whatever, would require that libpcap applications be linked with
- * the frameworks/libraries in question.  That shouldn't be a problem
- * for programs linking with the shared version of libpcap (unless
- * you're running on AIX - which I think is the only UN*X that doesn't
- * support linking a shared library with other libraries on which it
- * depends, and having an executable linked only with the first shared
- * library automatically pick up the other libraries when started -
- * and using HAL or whatever).  Programs linked with the static
- * version of libpcap would have to use pcap-config with the --static
- * flag in order to get the right linker flags in order to pick up
- * the additional libraries/frameworks; those programs need that anyway
- * for libpcap 1.1 and beyond on Linux, as, by default, it requires
- * -lnl.
- *
- * Do any other UN*Xes, or desktop environments support getting a
- * description?
- */
-static char *
-get_if_description(const char *name)
-{
-#ifdef SIOCGIFDESCR
-	char *description = NULL;
-	int s;
-	struct ifreq ifrdesc;
-#ifndef IFDESCRSIZE
-	size_t descrlen = 64;
-#else
-	size_t descrlen = IFDESCRSIZE;
-#endif /* IFDESCRSIZE */
-
-	/*
-	 * Get the description for the interface.
-	 */
-	memset(&ifrdesc, 0, sizeof ifrdesc);
-	strlcpy(ifrdesc.ifr_name, name, sizeof ifrdesc.ifr_name);
-	s = socket(AF_INET, SOCK_DGRAM, 0);
-	if (s >= 0) {
-#ifdef __FreeBSD__
-		/*
-		 * On FreeBSD, if the buffer isn't big enough for the
-		 * description, the ioctl succeeds, but the description
-		 * isn't copied, ifr_buffer.length is set to the description
-		 * length, and ifr_buffer.buffer is set to NULL.
-		 */
-		for (;;) {
-			free(description);
-			if ((description = malloc(descrlen)) != NULL) {
-				ifrdesc.ifr_buffer.buffer = description;
-				ifrdesc.ifr_buffer.length = descrlen;
-				if (ioctl(s, SIOCGIFDESCR, &ifrdesc) == 0) {
-					if (ifrdesc.ifr_buffer.buffer ==
-					    description)
-						break;
-					else
-						descrlen = ifrdesc.ifr_buffer.length;
-				} else {
-					/*
-					 * Failed to get interface description.
-					 */
-					free(description);
-					description = NULL;
-					break;
-				}
-			} else
-				break;
-		}
-#else /* __FreeBSD__ */
-		/*
-		 * The only other OS that currently supports
-		 * SIOCGIFDESCR is OpenBSD, and it has no way
-		 * to get the description length - it's clamped
-		 * to a maximum of IFDESCRSIZE.
-		 */
-		if ((description = malloc(descrlen)) != NULL) {
-			ifrdesc.ifr_data = (caddr_t)description;
-			if (ioctl(s, SIOCGIFDESCR, &ifrdesc) != 0) {
-				/*
-				 * Failed to get interface description.
-				 */
-				free(description);
-				description = NULL;
-			}
-		}
-#endif /* __FreeBSD__ */
-		close(s);
-		if (description != NULL && strlen(description) == 0) {
-			free(description);
-			description = NULL;
-		}
-	}
-
-	return (description);
-#else /* SIOCGIFDESCR */
-	return (NULL);
-#endif /* SIOCGIFDESCR */
-}
-
-/*
- * Try to get a description for a given device, and then look for that
- * device in the specified list of devices.
- *
- * If we find it, 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 description, 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, u_int flags,
-    struct sockaddr *addr, size_t addr_size,
-    struct sockaddr *netmask, size_t netmask_size,
-    struct sockaddr *broadaddr, size_t broadaddr_size,
-    struct sockaddr *dstaddr, size_t dstaddr_size,
-    char *errbuf)
-{
-	char *description;
-	pcap_if_t *curdev;
-
-	description = get_if_description(name);
-	if (add_or_find_if(&curdev, alldevs, name, flags, description,
-	    errbuf) == -1) {
-		free(description);
-		/*
-		 * Error - give up.
-		 */
-		return (-1);
-	}
-	free(description);
-	if (curdev == NULL) {
-		/*
-		 * Device wasn't added because it can't be opened.
-		 * Not a fatal error.
-		 */
-		return (0);
-	}
-
-	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)snprintf(errbuf, PCAP_ERRBUF_SIZE,
-		    "malloc: %s", pcap_strerror(errno));
-		return (-1);
-	}
-
-	curaddr->next = NULL;
-	if (addr != NULL) {
-		curaddr->addr = dup_sockaddr(addr, addr_size);
-		if (curaddr->addr == NULL) {
-			(void)snprintf(errbuf, PCAP_ERRBUF_SIZE,
-			    "malloc: %s", pcap_strerror(errno));
-			free(curaddr);
-			return (-1);
-		}
-	} else
-		curaddr->addr = NULL;
-
-	if (netmask != NULL) {
-		curaddr->netmask = dup_sockaddr(netmask, netmask_size);
-		if (curaddr->netmask == NULL) {
-			(void)snprintf(errbuf, PCAP_ERRBUF_SIZE,
-			    "malloc: %s", pcap_strerror(errno));
-			if (curaddr->addr != NULL)
-				free(curaddr->addr);
-			free(curaddr);
-			return (-1);
-		}
-	} else
-		curaddr->netmask = NULL;
-
-	if (broadaddr != NULL) {
-		curaddr->broadaddr = dup_sockaddr(broadaddr, broadaddr_size);
-		if (curaddr->broadaddr == NULL) {
-			(void)snprintf(errbuf, PCAP_ERRBUF_SIZE,
-			    "malloc: %s", pcap_strerror(errno));
-			if (curaddr->netmask != NULL)
-				free(curaddr->netmask);
-			if (curaddr->addr != NULL)
-				free(curaddr->addr);
-			free(curaddr);
-			return (-1);
-		}
-	} else
-		curaddr->broadaddr = NULL;
-
-	if (dstaddr != NULL) {
-		curaddr->dstaddr = dup_sockaddr(dstaddr, dstaddr_size);
-		if (curaddr->dstaddr == NULL) {
-			(void)snprintf(errbuf, PCAP_ERRBUF_SIZE,
-			    "malloc: %s", pcap_strerror(errno));
-			if (curaddr->broadaddr != NULL)
-				free(curaddr->broadaddr);
-			if (curaddr->netmask != NULL)
-				free(curaddr->netmask);
-			if (curaddr->addr != NULL)
-				free(curaddr->addr);
-			free(curaddr);
-			return (-1);
-		}
-	} else
-		curaddr->dstaddr = NULL;
-
-	/*
-	 * Find the end of the list of addresses.
-	 */
-	for (prevaddr = curdev->addresses; prevaddr != NULL; prevaddr = nextaddr) {
-		nextaddr = prevaddr->next;
-		if (nextaddr == NULL) {
-			/*
-			 * This is the end of the list.
-			 */
-			break;
-		}
-	}
-
-	if (prevaddr == NULL) {
-		/*
-		 * The list was empty; this is the first member.
-		 */
-		curdev->addresses = curaddr;
-	} else {
-		/*
-		 * "prevaddr" is the last member of the list; append
-		 * this member to it.
-		 */
-		prevaddr->next = curaddr;
-	}
-
-	return (0);
-}
-
-/*
- * Look for a given device in the specified list of devices.
- *
- * If we find it, return 0.
- *
- * If we don't find it, check whether we can open it:
- *
- *     If that fails with PCAP_ERROR_NO_SUCH_DEVICE or
- *     PCAP_ERROR_IFACE_NOT_UP, don't attempt to add an entry for
- *     it, as that probably means it exists but doesn't support
- *     packet capture.
- *
- *     Otherwise, attempt to add an entry for it, with the specified
- *     ifnet flags and description, and, if that succeeds, return 0
- *     and set *curdev_ret to point to the new entry, otherwise
- *     return PCAP_ERROR and set errbuf to an error message.
- */
-int
-pcap_add_if(pcap_if_t **devlist, const char *name, u_int flags,
-    const char *description, char *errbuf)
-{
-	pcap_if_t *curdev;
-
-	return (add_or_find_if(&curdev, devlist, name, flags, description,
-	    errbuf));
-}
-
-
-/*
- * Free a list of interfaces.
- */
-void
-pcap_freealldevs(pcap_if_t *alldevs)
-{
-	pcap_if_t *curdev, *nextdev;
-	pcap_addr_t *curaddr, *nextaddr;
-
-	for (curdev = alldevs; curdev != NULL; curdev = nextdev) {
-		nextdev = curdev->next;
-
-		/*
-		 * Free all addresses.
-		 */
-		for (curaddr = curdev->addresses; curaddr != NULL; curaddr = nextaddr) {
-			nextaddr = curaddr->next;
-			if (curaddr->addr)
-				free(curaddr->addr);
-			if (curaddr->netmask)
-				free(curaddr->netmask);
-			if (curaddr->broadaddr)
-				free(curaddr->broadaddr);
-			if (curaddr->dstaddr)
-				free(curaddr->dstaddr);
-			free(curaddr);
-		}
-
-		/*
-		 * Free the name string.
-		 */
-		free(curdev->name);
-
-		/*
-		 * Free the description string, if any.
-		 */
-		if (curdev->description != NULL)
-			free(curdev->description);
-
-		/*
-		 * Free the interface.
-		 */
-		free(curdev);
-	}
-}
-
-#if !defined(WIN32) && !defined(MSDOS)
+#if !defined(_WIN32) && !defined(MSDOS)
 
 /*
  * Return the name of a network interface attached to the system, or NULL
@@ -915,7 +158,7 @@
 
 	fd = socket(AF_INET, SOCK_DGRAM, 0);
 	if (fd < 0) {
-		(void)snprintf(errbuf, PCAP_ERRBUF_SIZE, "socket: %s",
+		(void)pcap_snprintf(errbuf, PCAP_ERRBUF_SIZE, "socket: %s",
 		    pcap_strerror(errno));
 		return (-1);
 	}
@@ -927,10 +170,10 @@
 	(void)strlcpy(ifr.ifr_name, device, sizeof(ifr.ifr_name));
 	if (ioctl(fd, SIOCGIFADDR, (char *)&ifr) < 0) {
 		if (errno == EADDRNOTAVAIL) {
-			(void)snprintf(errbuf, PCAP_ERRBUF_SIZE,
+			(void)pcap_snprintf(errbuf, PCAP_ERRBUF_SIZE,
 			    "%s: no IPv4 address assigned", device);
 		} else {
-			(void)snprintf(errbuf, PCAP_ERRBUF_SIZE,
+			(void)pcap_snprintf(errbuf, PCAP_ERRBUF_SIZE,
 			    "SIOCGIFADDR: %s: %s",
 			    device, pcap_strerror(errno));
 		}
@@ -946,7 +189,7 @@
 #endif
 	(void)strlcpy(ifr.ifr_name, device, sizeof(ifr.ifr_name));
 	if (ioctl(fd, SIOCGIFNETMASK, (char *)&ifr) < 0) {
-		(void)snprintf(errbuf, PCAP_ERRBUF_SIZE,
+		(void)pcap_snprintf(errbuf, PCAP_ERRBUF_SIZE,
 		    "SIOCGIFNETMASK: %s: %s", device, pcap_strerror(errno));
 		(void)close(fd);
 		return (-1);
@@ -961,7 +204,7 @@
 		else if (IN_CLASSC(*netp))
 			*maskp = IN_CLASSC_NET;
 		else {
-			(void)snprintf(errbuf, PCAP_ERRBUF_SIZE,
+			(void)pcap_snprintf(errbuf, PCAP_ERRBUF_SIZE,
 			    "inet class for 0x%x unknown", *netp);
 			return (-1);
 		}
@@ -970,28 +213,38 @@
 	return (0);
 }
 
-#elif defined(WIN32)
+#elif defined(_WIN32)
 
 /*
  * Return the name of a network interface attached to the system, or NULL
  * if none can be found.  The interface must be configured up; the
  * lowest unit number is preferred; loopback is ignored.
+ *
+ * In the best of all possible worlds, this would be the same as on
+ * UN*X, but there may be software that expects this to return a
+ * full list of devices after the first device.
  */
+#define ADAPTERSNAME_LEN	8192
 char *
 pcap_lookupdev(errbuf)
 	register char *errbuf;
 {
 	DWORD dwVersion;
 	DWORD dwWindowsMajorVersion;
+	char our_errbuf[PCAP_ERRBUF_SIZE+1];
+
+#pragma warning (push)
+#pragma warning (disable: 4996) /* disable MSVC's GetVersion() deprecated warning here */
 	dwVersion = GetVersion();	/* get the OS version */
+#pragma warning (pop)
 	dwWindowsMajorVersion = (DWORD)(LOBYTE(LOWORD(dwVersion)));
 
 	if (dwVersion >= 0x80000000 && dwWindowsMajorVersion >= 4) {
 		/*
 		 * Windows 95, 98, ME.
 		 */
-		ULONG NameLength = 8192;
-		static char AdaptersName[8192];
+		ULONG NameLength = ADAPTERSNAME_LEN;
+		static char AdaptersName[ADAPTERSNAME_LEN];
 
 		if (PacketGetAdapterNames(AdaptersName,&NameLength) )
 			return (AdaptersName);
@@ -999,60 +252,109 @@
 			return NULL;
 	} else {
 		/*
-		 * Windows NT (NT 4.0, W2K, WXP). Convert the names to UNICODE for backward compatibility
+		 * Windows NT (NT 4.0 and later).
+		 * Convert the names to Unicode for backward compatibility.
 		 */
-		ULONG NameLength = 8192;
-		static WCHAR AdaptersName[8192];
+		ULONG NameLength = ADAPTERSNAME_LEN;
+		static WCHAR AdaptersName[ADAPTERSNAME_LEN];
+		size_t BufferSpaceLeft;
 		char *tAstr;
-		WCHAR *tUstr;
-		WCHAR *TAdaptersName = (WCHAR*)malloc(8192 * sizeof(WCHAR));
+		WCHAR *Unameptr;
+		char *Adescptr;
+		size_t namelen, i;
+		WCHAR *TAdaptersName = (WCHAR*)malloc(ADAPTERSNAME_LEN * sizeof(WCHAR));
 		int NAdapts = 0;
 
 		if(TAdaptersName == NULL)
 		{
-			(void)snprintf(errbuf, PCAP_ERRBUF_SIZE, "memory allocation failure");
+			(void)pcap_snprintf(errbuf, PCAP_ERRBUF_SIZE, "memory allocation failure");
 			return NULL;
 		}
 
 		if ( !PacketGetAdapterNames((PTSTR)TAdaptersName,&NameLength) )
 		{
-			(void)snprintf(errbuf, PCAP_ERRBUF_SIZE,
-				"PacketGetAdapterNames: %s",
-				pcap_win32strerror());
+			pcap_win32_err_to_str(GetLastError(), our_errbuf);
+			(void)pcap_snprintf(errbuf, PCAP_ERRBUF_SIZE,
+				"PacketGetAdapterNames: %s", our_errbuf);
 			free(TAdaptersName);
 			return NULL;
 		}
 
 
+		BufferSpaceLeft = ADAPTERSNAME_LEN * sizeof(WCHAR);
 		tAstr = (char*)TAdaptersName;
-		tUstr = (WCHAR*)AdaptersName;
+		Unameptr = AdaptersName;
 
 		/*
-		 * Convert and copy the device names
+		 * Convert the device names to Unicode into AdapterName.
 		 */
-		while(sscanf(tAstr, "%S", tUstr) > 0)
-		{
-			tAstr += strlen(tAstr) + 1;
-			tUstr += wcslen(tUstr) + 1;
-			NAdapts ++;
-		}
+		do {
+			/*
+			 * Length of the name, including the terminating
+			 * NUL.
+			 */
+			namelen = strlen(tAstr) + 1;
 
-		tAstr++;
-		*tUstr = 0;
-		tUstr++;
+			/*
+			 * 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
+		 * Copy the descriptions, but don't convert them from
+		 * ASCII to Unicode.
 		 */
+		Adescptr = (char *)Unameptr;
 		while(NAdapts--)
 		{
-			char* tmp = (char*)tUstr;
-			strcpy(tmp, tAstr);
-			tmp += strlen(tAstr) + 1;
-			tUstr = (WCHAR*)tmp;
-			tAstr += strlen(tAstr) + 1;
+			size_t desclen;
+
+			desclen = strlen(tAstr) + 1;
+
+			/*
+			 * Do we have room for the name in the Unicode
+			 * buffer?
+			 */
+			if (BufferSpaceLeft < desclen) {
+				/*
+				 * No.
+				 */
+				goto quit;
+			}
+
+			/*
+			 * Just copy the ASCII string.
+			 * namelen includes the NUL, so we copy it as
+			 * well.
+			 */
+			memcpy(Adescptr, tAstr, desclen);
+			Adescptr += desclen;
+			tAstr += desclen;
+			BufferSpaceLeft -= desclen;
 		}
 
+	quit:
 		free(TAdaptersName);
 		return (char *)(AdaptersName);
 	}
@@ -1098,4 +400,4 @@
 	return (0);
 }
 
-#endif /* !WIN32 && !MSDOS */
+#endif /* !_WIN32 && !MSDOS */
diff --git a/lbl/os-aix7.h b/lbl/os-aix7.h
new file mode 100644
index 0000000..93b12f2
--- /dev/null
+++ b/lbl/os-aix7.h
@@ -0,0 +1,23 @@
+/*
+ * Copyright (c) 1993, 1994, 1995, 1996, 1997
+ *	The Regents of the University of California.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that: (1) source code distributions
+ * retain the above copyright notice and this paragraph in its entirety, (2)
+ * distributions including binary code include the above copyright notice and
+ * this paragraph in its entirety in the documentation or other materials
+ * provided with the distribution, and (3) all advertising materials mentioning
+ * features or use of this software display the following acknowledgement:
+ * ``This product includes software developed by the University of California,
+ * Lawrence Berkeley Laboratory and its contributors.'' Neither the name of
+ * the University nor the names of its contributors may be used to endorse
+ * or promote products derived from this software without specific prior
+ * written permission.
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+ */
+
+/* Prototypes missing in AIX 7.x */
+int	ffs(int i);
diff --git a/lbl/os-osf4.h b/lbl/os-osf4.h
index f461eea..055eb80 100644
--- a/lbl/os-osf4.h
+++ b/lbl/os-osf4.h
@@ -20,7 +20,7 @@
  */
 
 /* Prototypes missing in Digital UNIX 4.x */
-int	snprintf(char *, size_t, const char *, ...);
-int	vsnprintf(char *, size_t, const char *, va_list);
+int	pcap_snprintf(char *, size_t, const char *, ...);
+int	pcap_vsnprintf(char *, size_t, const char *, va_list);
 int	pfopen(char *, int);
 
diff --git a/lbl/os-osf5.h b/lbl/os-osf5.h
index 52ab175..5422f18 100644
--- a/lbl/os-osf5.h
+++ b/lbl/os-osf5.h
@@ -21,10 +21,10 @@
 
 /*
  * Prototypes missing in Tru64 UNIX 5.x
- * XXX - "snprintf()" and "vsnprintf()" aren't missing, but you have to
+ * XXX - "pcap_snprintf()" and "pcap_vsnprintf()" aren't missing, but you have to
  * #define the right value to get them defined by <stdio.h>.
  */
-int	snprintf(char *, size_t, const char *, ...);
-int	vsnprintf(char *, size_t, const char *, va_list);
+int	pcap_snprintf(char *, size_t, const char *, ...);
+int	pcap_vsnprintf(char *, size_t, const char *, va_list);
 int	pfopen(char *, int);
 
diff --git a/lbl/os-solaris2.h b/lbl/os-solaris2.h
index 22948b4..a555f5e 100644
--- a/lbl/os-solaris2.h
+++ b/lbl/os-solaris2.h
@@ -21,4 +21,4 @@
 
 /* Prototypes missing in SunOS 5 */
 char    *strerror(int);
-int	snprintf(char *, size_t, const char *, ...);
+int	pcap_snprintf(char *, size_t, const char *, ...);
diff --git a/lbl/os-sunos4.h b/lbl/os-sunos4.h
index b735857..6353fb0 100644
--- a/lbl/os-sunos4.h
+++ b/lbl/os-sunos4.h
@@ -65,7 +65,6 @@
 int	fchown(int, int, int);
 void	endgrent(void);
 void	endpwent(void);
-void	endservent(void);
 #ifdef __STDC__
 struct	ether_addr;
 #endif
@@ -146,7 +145,6 @@
 int	setpgrp(int, int);
 void	setpwent(void);
 int	setrlimit(int, struct rlimit *);
-void	setservent(int);
 int	setsockopt(int, int, int, char *, int);
 int	shutdown(int, int);
 int	sigblock(int);
@@ -157,7 +155,7 @@
 struct	sigvec;
 #endif
 int	sigvec(int, struct sigvec *, struct sigvec*);
-int	snprintf(char *, size_t, const char *, ...);
+int	pcap_snprintf(char *, size_t, const char *, ...);
 int	socket(int, int, int);
 int	socketpair(int, int, int, int *);
 int	symlink(const char *, const char *);
diff --git a/lbl/os-ultrix4.h b/lbl/os-ultrix4.h
index fa1f770..21e5702 100644
--- a/lbl/os-ultrix4.h
+++ b/lbl/os-ultrix4.h
@@ -23,7 +23,6 @@
 int	bcmp(const char *, const char *, u_int);
 void	bcopy(const void *, void *, u_int);
 void	bzero(void *, u_int);
-void	endservent(void);
 int	getopt(int, char * const *, const char *);
 #ifdef __STDC__
 struct timeval;
diff --git a/Win32/Src/getopt.c b/missing/getopt.c
similarity index 94%
rename from Win32/Src/getopt.c
rename to missing/getopt.c
index 03c2086..cc798e1 100644
--- a/Win32/Src/getopt.c
+++ b/missing/getopt.c
@@ -39,6 +39,8 @@
 #include <stdlib.h>
 #include <string.h>
 
+#include "getopt.h"
+
 int	opterr = 1,		/* if error message should be printed */
 	optind = 1,		/* index into parent argv vector */
 	optopt,			/* character checked for validity */
@@ -59,14 +61,17 @@
 	char * const *nargv;
 	const char *ostr;
 {
-#ifdef WIN32
-	char *__progname="windump";
-#else
-	extern char *__progname;
-#endif
+	char *cp;
+	static char *__progname;
 	static char *place = EMSG;		/* option letter processing */
 	char *oli;				/* option letter list index */
 
+	if (__progname == NULL) {
+		if ((cp = strrchr(nargv[0], '/')) != NULL)
+			__progname = cp + 1;
+		else
+			__progname = nargv[0];
+	}
 	if (optreset || !*place) {		/* update scanning pointer */
 		optreset = 0;
 		if (optind >= nargc || *(place = nargv[optind]) != '-') {
diff --git a/missing/getopt.h b/missing/getopt.h
new file mode 100644
index 0000000..d176345
--- /dev/null
+++ b/missing/getopt.h
@@ -0,0 +1,7 @@
+/*
+ * Header for the getopt() we supply if the platform doesn't supply it.
+ */
+extern char *optarg;			/* getopt(3) external variables */
+extern int optind, opterr, optopt;
+
+extern int getopt(int nargc, char * const *nargv, const char *ostr);
diff --git a/missing/snprintf.c b/missing/snprintf.c
index 9b63f8b..99f0bdf 100644
--- a/missing/snprintf.c
+++ b/missing/snprintf.c
@@ -456,13 +456,13 @@
 
 #ifndef HAVE_SNPRINTF
 int
-snprintf (char *str, size_t sz, const char *format, ...)
+pcap_snprintf (char *str, size_t sz, const char *format, ...)
 {
   va_list args;
   int ret;
 
   va_start(args, format);
-  ret = vsnprintf (str, sz, format, args);
+  ret = pcap_vsnprintf (str, sz, format, args);
 
 #ifdef PARANOIA
   {
@@ -473,7 +473,7 @@
     if (tmp == NULL)
       abort ();
 
-    ret2 = vsprintf (tmp, format, args);
+    ret2 = pcap_vsprintf (tmp, format, args);
     if (ret != ret2 || strcmp(str, tmp))
       abort ();
     free (tmp);
@@ -518,13 +518,13 @@
 
 #ifndef HAVE_ASNPRINTF
 int
-asnprintf (char **ret, size_t max_sz, const char *format, ...)
+pcap_asnprintf (char **ret, size_t max_sz, const char *format, ...)
 {
   va_list args;
   int val;
 
   va_start(args, format);
-  val = vasnprintf (ret, max_sz, format, args);
+  val = pcap_vasnprintf (ret, max_sz, format, args);
 
 #ifdef PARANOIA
   {
@@ -534,7 +534,7 @@
     if (tmp == NULL)
       abort ();
 
-    ret2 = vsprintf (tmp, format, args);
+    ret2 = pcap_vsprintf (tmp, format, args);
     if (val != ret2 || strcmp(*ret, tmp))
       abort ();
     free (tmp);
@@ -548,16 +548,16 @@
 
 #ifndef HAVE_VASPRINTF
 int
-vasprintf (char **ret, const char *format, va_list args)
+pcap_vasprintf (char **ret, const char *format, va_list args)
 {
-  return vasnprintf (ret, 0, format, args);
+  return pcap_vasnprintf (ret, 0, format, args);
 }
 #endif
 
 
 #ifndef HAVE_VASNPRINTF
 int
-vasnprintf (char **ret, size_t max_sz, const char *format, va_list args)
+pcap_vasnprintf (char **ret, size_t max_sz, const char *format, va_list args)
 {
   int st;
   size_t len;
@@ -600,7 +600,7 @@
 
 #ifndef HAVE_VSNPRINTF
 int
-vsnprintf (char *str, size_t sz, const char *format, va_list args)
+pcap_vsnprintf (char *str, size_t sz, const char *format, va_list args)
 {
   struct state state;
   int ret;
diff --git a/missing/strtok_r.c b/missing/strtok_r.c
new file mode 100644
index 0000000..c9c94b9
--- /dev/null
+++ b/missing/strtok_r.c
@@ -0,0 +1,87 @@
+/*-
+ * Copyright (c) 1998 Softweyr LLC.  All rights reserved.
+ *
+ * strtok_r, from Berkeley strtok
+ * Oct 13, 1998 by Wes Peters <wes@softweyr.com>
+ *
+ * Copyright (c) 1988, 1993
+ *	The Regents of the University of California.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notices, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notices, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY SOFTWEYR LLC, THE REGENTS AND CONTRIBUTORS
+ * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
+ * PARTICULAR PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL SOFTWEYR LLC, THE
+ * REGENTS, OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+ * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+ * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * From: @(#)strtok.c	8.1 (Berkeley) 6/4/93
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include "portability.h"
+
+char *
+pcap_strtok_r(char *s, const char *delim, char **last)
+{
+	char *spanp, *tok;
+	int c, sc;
+
+	if (s == NULL && (s = *last) == NULL)
+		return (NULL);
+
+	/*
+	 * Skip (span) leading delimiters (s += strspn(s, delim), sort of).
+	 */
+cont:
+	c = *s++;
+	for (spanp = (char *)delim; (sc = *spanp++) != 0;) {
+		if (c == sc)
+			goto cont;
+	}
+
+	if (c == 0) {		/* no non-delimiter characters */
+		*last = NULL;
+		return (NULL);
+	}
+	tok = s - 1;
+
+	/*
+	 * Scan token (scan for delimiters: s += strcspn(s, delim), sort of).
+	 * Note that delim must have one NUL; we stop if we see that, too.
+	 */
+	for (;;) {
+		c = *s++;
+		spanp = (char *)delim;
+		do {
+			if ((sc = *spanp++) == c) {
+				if (c == 0)
+					s = NULL;
+				else
+					s[-1] = '\0';
+				*last = s;
+				return (tok);
+			}
+		} while (sc != 0);
+	}
+	/* NOTREACHED */
+}
diff --git a/missing/win_snprintf.c b/missing/win_snprintf.c
new file mode 100644
index 0000000..65a8ea1
--- /dev/null
+++ b/missing/win_snprintf.c
@@ -0,0 +1,31 @@
+#include <stdio.h>
+#include <stdarg.h>
+
+int
+pcap_vsnprintf(char *str, size_t str_size, const char *format, va_list args)
+{
+	int ret;
+
+	ret = _vsnprintf_s(str, str_size, _TRUNCATE, format, args);
+
+	/*
+	 * XXX - _vsnprintf() and _snprintf() do *not* guarantee
+	 * that str is null-terminated, but C99's vsnprintf()
+	 * and snprintf() do, and we want to offer C99 behavior,
+	 * so forcibly null-terminate the string.
+	 */
+	str[str_size - 1] = '\0';
+	return (ret);
+}
+
+int
+pcap_snprintf(char *str, size_t str_size, const char *format, ...)
+{
+	va_list args;
+	int ret;
+
+	va_start(args, format);
+	ret = pcap_vsnprintf(str, str_size, format, args);
+	va_end(args);
+	return (ret);
+}
diff --git a/msdos/bin2c.c b/msdos/bin2c.c
index d82056e..26d9008 100644
--- a/msdos/bin2c.c
+++ b/msdos/bin2c.c
@@ -1,43 +1,43 @@
-#include <stdio.h>

-#include <stdlib.h>

-#include <stdarg.h>

-#include <time.h>

-

-static void Abort (char *fmt,...)

-{

-  va_list args;

-  va_start (args, fmt);

-  vfprintf (stderr, fmt, args);

-  va_end (args);

-  exit (1);

-}

-

-int main (int argc, char **argv)

-{

-  FILE  *inFile;

-  FILE  *outFile = stdout;

-  time_t now     = time (NULL);

-  int    ch, i;

-

-  if (argc != 2)

-     Abort ("Usage: %s bin-file [> result]", argv[0]);

-

-  if ((inFile = fopen(argv[1],"rb")) == NULL)

-     Abort ("Cannot open %s\n", argv[1]);

-

-  fprintf (outFile,

-           "/* data statements for file %s at %.24s */\n"

-           "/* Generated by BIN2C, G.Vanem 1995 */\n",

-           argv[1], ctime(&now));

-

-  i = 0;

-  while ((ch = fgetc(inFile)) != EOF)

-  {

-    if (i++ % 12 == 0)

-       fputs ("\n  ", outFile);

-    fprintf (outFile, "0x%02X,", ch);

-  }

-  fputc ('\n', outFile);

-  fclose (inFile);

-  return (0);

-}

+#include <stdio.h>
+#include <stdlib.h>
+#include <stdarg.h>
+#include <time.h>
+
+static void Abort (const char *fmt,...)
+{
+  va_list args;
+  va_start (args, fmt);
+  vfprintf (stderr, fmt, args);
+  va_end (args);
+  exit (1);
+}
+
+int main (int argc, char **argv)
+{
+  FILE  *inFile;
+  FILE  *outFile = stdout;
+  time_t now     = time (NULL);
+  int    ch, i;
+
+  if (argc != 2)
+     Abort ("Usage: %s bin-file [> result]", argv[0]);
+
+  if ((inFile = fopen(argv[1],"rb")) == NULL)
+     Abort ("Cannot open %s\n", argv[1]);
+
+  fprintf (outFile,
+           "/* data statements for file %s at %.24s */\n"
+           "/* Generated by BIN2C, G. Vanem 1995 */\n",
+           argv[1], ctime(&now));
+
+  i = 0;
+  while ((ch = fgetc(inFile)) != EOF)
+  {
+    if (i++ % 12 == 0)
+       fputs ("\n  ", outFile);
+    fprintf (outFile, "0x%02X,", ch);
+  }
+  fputc ('\n', outFile);
+  fclose (inFile);
+  return (0);
+}
diff --git a/msdos/common.dj b/msdos/common.dj
index ec0ce02..dacfd1f 100644
--- a/msdos/common.dj
+++ b/msdos/common.dj
@@ -7,7 +7,13 @@
 
 default: check_gcclib all
 
-GCCLIB   = /djgpp/lib/gcc-lib/djgpp/3.31
+#
+# 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
 
 #
@@ -19,10 +25,11 @@
 
 WATT32_ROOT = $(subst \,/,$(WATT_ROOT))
 
+OBJ_DIR = djgpp.obj
 
-ifeq ($(wildcard $(GCCLIB)/libgcc.a),)
+ifeq ($(wildcard $(GCC_LIB)),)
 check_gcclib:
-	@echo libgcc.a not found. Set \"$(GCCLIB)\" to \"/djgpp/lib/gcc-lib/djgpp/3.X\"
+	@echo libgcc.a not found. Set \"$(GCC_LIB)\" to \"/djgpp/lib/gcc/djgpp/4.X/libgcc.a\"
 endif
 
 
@@ -54,7 +61,7 @@
 YACC = bison.exe
 LEX  = flex.exe
 
-CFLAGS = -g -gcoff -O2 -Wall -I. -I$(WATT32_ROOT)/inc
+CFLAGS = -g -O2 -Wall -I. -I$(WATT32_ROOT)/inc
 
 ifeq ($(USE_EXCEPT),1)
   CFLAGS += -DUSE_EXCEPT
@@ -70,7 +77,7 @@
 endif
 
 %.o: %.c
-	$(CC) -c $(CFLAGS) $<
+	$(CC) -c $(CFLAGS) -o $@ $<
 	@echo
 
 %.o: %.s
diff --git a/msdos/makefile b/msdos/makefile
index cdb4e7c..234a276 100644
--- a/msdos/makefile
+++ b/msdos/makefile
@@ -1,184 +1,184 @@
-#

-#  Makefile for dos-libpcap. NB. This makefile requires a Borland

-#  compatible make tool.

-#

-#  Targets:

-#    Borland C 4.0+      (DOS large model)

-#    Metaware HighC 3.3+ (PharLap 386|DosX)

-#

-

-.AUTODEPEND

-.SWAP

-

-!if "$(WATT_ROOT)" == ""

-!error Environment variable "WATT_ROOT" not set.

-!endif

-

-WATT_INC = $(WATT_ROOT)\inc

-

-DEFS   = -DMSDOS -DDEBUG -DNDIS_DEBUG -D_U_= -Dinline= \

-         -DHAVE_STRERROR -DHAVE_LIMITS_H

-

-ASM    = tasm.exe -t -l -mx -m2 -DDEBUG

-

-SOURCE = grammar.c  scanner.c bpf_filt.c bpf_imag.c bpf_dump.c \

-         etherent.c gencode.c nametoad.c pcap-dos.c optimize.c \

-         savefile.c pcap.c inet.c msdos\ndis2.c msdos\pktdrvr.c \

-         missing\snprintf.c

-

-BORLAND_OBJ = $(SOURCE:.c=.obj) msdos\pkt_rx0.obj msdos\ndis_0.obj

-

-HIGHC_OBJ   = $(SOURCE:.c=.o32) msdos\pkt_rx0.o32

-

-all:

-            @echo Usage: make pcap_bc.lib or pcap_hc.lib

-

-

-pcap_bc.lib: bcc.arg $(BORLAND_OBJ) pcap_bc

-

-

-pcap_hc.lib: hc386.arg $(HIGHC_OBJ)

-            386lib $< @&&|

-               -nowarn -nobackup -twocase -replace $(HIGHC_OBJ)

-|

-

-pcap_bc:    $(BORLAND_OBJ)

-            @tlib pcap_bc.lib /C @&&|

-               -+$(**:.obj=-+)

-|

-

-.c.obj:

-            bcc.exe @bcc.arg -o$*.obj $*.c

-

-.c.o32:

-            hc386.exe @hc386.arg -o $*.o32 $*.c

-

-.asm.obj:

-            $(ASM) $*.asm, $*.obj

-

-.asm.o32:

-            $(ASM) -DDOSX=1 $*.asm, $*.o32

-

-scanner.c: scanner.l

-            flex -Ppcap_ -7 -oscanner.c scanner.l

-

-grammar.c tokdefs.h: grammar.y

-            bison --name-prefix=pcap_ --yacc --defines grammar.y

-            - @del grammar.c

-            - @del tokdefs.h

-            ren y_tab.c grammar.c

-            ren y_tab.h tokdefs.h

-

-bcc.arg:    msdos\Makefile

-            @copy &&|

-              $(DEFS) -ml -c -v -3 -O2 -po -RT- -w-

-              -I$(WATT_INC) -I. -I.\msdos\pm_drvr -H=$(TEMP)\bcc.sym

-| $<

-

-hc386.arg:  msdos\Makefile

-            @copy &&|

-            # -DUSE_32BIT_DRIVERS

-              $(DEFS) -DDOSX=1 -w3 -c -g -O5

-              -I$(WATT_INC) -I. -I.\msdos\pm_drvr

-              -Hsuffix=.o32

-              -Hnocopyr

-              -Hpragma=Offwarn(491,553,572)

-              -Hon=Recognize_library  # make memcpy/strlen etc. inline

-              -Hoff=Behaved           # turn off some optimiser warnings

-| $<

-

-clean:

-            @del *.obj

-            @del *.o32

-            @del *.lst

-            @del *.map

-            @del bcc.arg

-            @del hc386.arg

-            @del grammar.c

-            @del tokdefs.h

-            @del scanner.c

-            @echo Cleaned

-

-#

-# dependencies

-#             

-pkt_rx0.obj:  msdos\pkt_rx0.asm

-

-bpf_filt.obj: bpf_filt.c pcap-int.h pcap.h pcap-bpf.h gnuc.h

-

-bpf_imag.obj: bpf_imag.c pcap-int.h pcap.h pcap-bpf.h

-

-bpf_dump.obj: bpf_dump.c pcap.h pcap-bpf.h

-

-etherent.obj: etherent.c pcap-int.h pcap.h pcap-bpf.h pcap-namedb.h

-

-optimize.obj: optimize.c pcap-int.h pcap.h pcap-bpf.h gencode.h

-

-savefile.obj: savefile.c pcap-int.h pcap.h pcap-bpf.h

-

-pcap.obj: pcap.c pcap-dos.h pcap-int.h pcap.h pcap-bpf.h

-

-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

-

-scanner.obj: scanner.c pcap-int.h pcap.h pcap-bpf.h gencode.h \

-  pcap-namedb.h tokdefs.h

-

-gencode.obj: gencode.c pcap-dos.h pcap-int.h pcap.h pcap-bpf.h \

-  ethertype.h nlpid.h llc.h gencode.h atmuni31.h sunatmpos.h ppp.h sll.h \

-  arcnet.h pf.h pcap-namedb.h

-

-nametoad.obj: nametoad.c pcap-int.h pcap.h pcap-bpf.h gencode.h \

-  pcap-namedb.h ethertype.h

-

-pcap-dos.obj: pcap-dos.c pcap.h pcap-bpf.h pcap-dos.h pcap-int.h \

-  msdos\pktdrvr.h

-

-pktdrvr.obj: msdos\pktdrvr.c gnuc.h pcap-dos.h pcap-int.h \

-  pcap.h pcap-bpf.h msdos\pktdrvr.h msdos\pkt_stub.inc

-

-ndis2.obj: msdos\ndis2.c pcap-dos.h pcap-int.h pcap.h pcap-bpf.h \

-  msdos\ndis2.h

-

-pkt_rx0.o32:  msdos\pkt_rx0.asm

-

-bpf_filt.o32: bpf_filt.c pcap-int.h pcap.h pcap-bpf.h gnuc.h

-

-bpf_imag.o32: bpf_imag.c pcap-int.h pcap.h pcap-bpf.h

-

-bpf_dump.o32: bpf_dump.c pcap.h pcap-bpf.h

-

-etherent.o32: etherent.c pcap-int.h pcap.h pcap-bpf.h pcap-namedb.h

-

-optimize.o32: optimize.c pcap-int.h pcap.h pcap-bpf.h gencode.h

-

-savefile.o32: savefile.c pcap-int.h pcap.h pcap-bpf.h

-

-pcap.o32: pcap.c pcap-dos.h pcap-int.h pcap.h pcap-bpf.h

-

-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

-

-scanner.o32: scanner.c pcap-int.h pcap.h pcap-bpf.h gencode.h \

-  pcap-namedb.h tokdefs.h

-

-gencode.o32: gencode.c pcap-dos.h pcap-int.h pcap.h pcap-bpf.h \

-  ethertype.h nlpid.h llc.h gencode.h atmuni31.h sunatmpos.h ppp.h sll.h \

-  arcnet.h pf.h pcap-namedb.h

-

-nametoad.o32: nametoad.c pcap-int.h pcap.h pcap-bpf.h gencode.h \

-  pcap-namedb.h ethertype.h

-

-pcap-dos.o32: pcap-dos.c pcap.h pcap-bpf.h pcap-dos.h pcap-int.h \

-  msdos\pktdrvr.h

-

-pktdrvr.o32: msdos\pktdrvr.c gnuc.h pcap-dos.h pcap-int.h \

-  pcap.h pcap-bpf.h msdos\pktdrvr.h msdos\pkt_stub.inc

-

-ndis2.o32: msdos\ndis2.c pcap-dos.h pcap-int.h pcap.h pcap-bpf.h \

-  msdos\ndis2.h

-

+#
+#  Makefile for dos-libpcap. NB. This makefile requires a Borland
+#  compatible make tool.
+#
+#  Targets:
+#    Borland C 4.0+      (DOS large model)
+#    Metaware HighC 3.3+ (PharLap 386|DosX)
+#
+
+.AUTODEPEND
+.SWAP
+
+!if "$(WATT_ROOT)" == ""
+!error Environment variable "WATT_ROOT" not set.
+!endif
+
+WATT_INC = $(WATT_ROOT)\inc
+
+DEFS   = -DMSDOS -DDEBUG -DNDIS_DEBUG -D_U_= -Dinline= \
+         -DHAVE_STRERROR -DHAVE_LIMITS_H
+
+ASM    = tasm.exe -t -l -mx -m2 -DDEBUG
+
+SOURCE = grammar.c  scanner.c bpf_filt.c bpf_imag.c bpf_dump.c \
+         etherent.c gencode.c nametoad.c pcap-dos.c optimize.c \
+         savefile.c pcap.c inet.c msdos\ndis2.c msdos\pktdrvr.c \
+         missing\snprintf.c
+
+BORLAND_OBJ = $(SOURCE:.c=.obj) msdos\pkt_rx0.obj msdos\ndis_0.obj
+
+HIGHC_OBJ   = $(SOURCE:.c=.o32) msdos\pkt_rx0.o32
+
+all:
+            @echo Usage: make pcap_bc.lib or pcap_hc.lib
+
+
+pcap_bc.lib: bcc.arg $(BORLAND_OBJ) pcap_bc
+
+
+pcap_hc.lib: hc386.arg $(HIGHC_OBJ)
+            386lib $< @&&|
+               -nowarn -nobackup -twocase -replace $(HIGHC_OBJ)
+|
+
+pcap_bc:    $(BORLAND_OBJ)
+            @tlib pcap_bc.lib /C @&&|
+               -+$(**:.obj=-+)
+|
+
+.c.obj:
+            bcc.exe @bcc.arg -o$*.obj $*.c
+
+.c.o32:
+            hc386.exe @hc386.arg -o $*.o32 $*.c
+
+.asm.obj:
+            $(ASM) $*.asm, $*.obj
+
+.asm.o32:
+            $(ASM) -DDOSX=1 $*.asm, $*.o32
+
+scanner.c: scanner.l
+            flex -Ppcap_ -7 -oscanner.c scanner.l
+
+grammar.c tokdefs.h: grammar.y
+            bison --name-prefix=pcap_ --yacc --defines grammar.y
+            - @del grammar.c
+            - @del tokdefs.h
+            ren y_tab.c grammar.c
+            ren y_tab.h tokdefs.h
+
+bcc.arg:    msdos\Makefile
+            @copy &&|
+              $(DEFS) -ml -c -v -3 -O2 -po -RT- -w-
+              -I$(WATT_INC) -I. -I.\msdos\pm_drvr -H=$(TEMP)\bcc.sym
+| $<
+
+hc386.arg:  msdos\Makefile
+            @copy &&|
+            # -DUSE_32BIT_DRIVERS
+              $(DEFS) -DDOSX=1 -w3 -c -g -O5
+              -I$(WATT_INC) -I. -I.\msdos\pm_drvr
+              -Hsuffix=.o32
+              -Hnocopyr
+              -Hpragma=Offwarn(491,553,572)
+              -Hon=Recognize_library  # make memcpy/strlen etc. inline
+              -Hoff=Behaved           # turn off some optimiser warnings
+| $<
+
+clean:
+            @del *.obj
+            @del *.o32
+            @del *.lst
+            @del *.map
+            @del bcc.arg
+            @del hc386.arg
+            @del grammar.c
+            @del tokdefs.h
+            @del scanner.c
+            @echo Cleaned
+
+#
+# dependencies
+#
+pkt_rx0.obj:  msdos\pkt_rx0.asm
+
+bpf_filt.obj: bpf_filt.c pcap-int.h pcap.h pcap-bpf.h gnuc.h
+
+bpf_imag.obj: bpf_imag.c pcap-int.h pcap.h pcap-bpf.h
+
+bpf_dump.obj: bpf_dump.c pcap.h pcap-bpf.h
+
+etherent.obj: etherent.c pcap-int.h pcap.h pcap-bpf.h pcap-namedb.h
+
+optimize.obj: optimize.c pcap-int.h pcap.h pcap-bpf.h gencode.h
+
+savefile.obj: savefile.c pcap-int.h pcap.h pcap-bpf.h
+
+pcap.obj: pcap.c pcap-dos.h pcap-int.h pcap.h pcap-bpf.h
+
+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
+
+scanner.obj: scanner.c pcap-int.h pcap.h pcap-bpf.h gencode.h \
+  pcap-namedb.h tokdefs.h
+
+gencode.obj: gencode.c pcap-dos.h pcap-int.h pcap.h pcap-bpf.h \
+  ethertype.h nlpid.h llc.h gencode.h atmuni31.h sunatmpos.h ppp.h sll.h \
+  arcnet.h pf.h pcap-namedb.h
+
+nametoad.obj: nametoad.c pcap-int.h pcap.h pcap-bpf.h gencode.h \
+  pcap-namedb.h ethertype.h
+
+pcap-dos.obj: pcap-dos.c pcap.h pcap-bpf.h pcap-dos.h pcap-int.h \
+  msdos\pktdrvr.h
+
+pktdrvr.obj: msdos\pktdrvr.c gnuc.h pcap-dos.h pcap-int.h \
+  pcap.h pcap-bpf.h msdos\pktdrvr.h msdos\pkt_stub.inc
+
+ndis2.obj: msdos\ndis2.c pcap-dos.h pcap-int.h pcap.h pcap-bpf.h \
+  msdos\ndis2.h
+
+pkt_rx0.o32:  msdos\pkt_rx0.asm
+
+bpf_filt.o32: bpf_filt.c pcap-int.h pcap.h pcap-bpf.h gnuc.h
+
+bpf_imag.o32: bpf_imag.c pcap-int.h pcap.h pcap-bpf.h
+
+bpf_dump.o32: bpf_dump.c pcap.h pcap-bpf.h
+
+etherent.o32: etherent.c pcap-int.h pcap.h pcap-bpf.h pcap-namedb.h
+
+optimize.o32: optimize.c pcap-int.h pcap.h pcap-bpf.h gencode.h
+
+savefile.o32: savefile.c pcap-int.h pcap.h pcap-bpf.h
+
+pcap.o32: pcap.c pcap-dos.h pcap-int.h pcap.h pcap-bpf.h
+
+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
+
+scanner.o32: scanner.c pcap-int.h pcap.h pcap-bpf.h gencode.h \
+  pcap-namedb.h tokdefs.h
+
+gencode.o32: gencode.c pcap-dos.h pcap-int.h pcap.h pcap-bpf.h \
+  ethertype.h nlpid.h llc.h gencode.h atmuni31.h sunatmpos.h ppp.h sll.h \
+  arcnet.h pf.h pcap-namedb.h
+
+nametoad.o32: nametoad.c pcap-int.h pcap.h pcap-bpf.h gencode.h \
+  pcap-namedb.h ethertype.h
+
+pcap-dos.o32: pcap-dos.c pcap.h pcap-bpf.h pcap-dos.h pcap-int.h \
+  msdos\pktdrvr.h
+
+pktdrvr.o32: msdos\pktdrvr.c gnuc.h pcap-dos.h pcap-int.h \
+  pcap.h pcap-bpf.h msdos\pktdrvr.h msdos\pkt_stub.inc
+
+ndis2.o32: msdos\ndis2.c pcap-dos.h pcap-int.h pcap.h pcap-bpf.h \
+  msdos\ndis2.h
+
diff --git a/msdos/makefile.dj b/msdos/makefile.dj
index ae20ada..3f56da9 100644
--- a/msdos/makefile.dj
+++ b/msdos/makefile.dj
@@ -6,43 +6,49 @@
 #
 #  c:\net\pcap> make -f msdos/makefile.dj
 #
+# Note: you should do a "set LFN=y" before running this makefile.
+#
 
-VPATH = missing msdos
+VPATH = missing msdos bpf/net
 
 PREREQUISITES = scanner.c grammar.c tokdefs.h version.h msdos/pkt_stub.inc
 
-include msdos/common.dj
+include ./msdos/common.dj
 
 DRIVER_DIR = ./msdos/pm_drvr
 
-CFLAGS += -DDEBUG -DNDIS_DEBUG -DHAVE_LIMITS_H -DHAVE_STRERROR \
-          -D_U_='__attribute__((unused))' -DHAVE_VERSION_H
+CFLAGS += -DDEBUG -DNDIS_DEBUG -DHAVE_LIMITS_H -DHAVE_STRERROR -DHAVE_SNPRINTF -DHAVE_VSNPRINTF\
+          -D_U_='__attribute__((unused))'
 
-# CFLAGS += -Dyylval=pcap_lval -DBDEBUG -DNDEBUG
+CFLAGS += -Dyylval=pcap_lval # -DBDEBUG -DNDEBUG
 
-SOURCES = grammar.c scanner.c bpf_filt.c bpf_imag.c bpf_dump.c   \
-          etherent.c gencode.c nametoad.c pcap-dos.c optimize.c  \
-          savefile.c pcap.c inet.c msdos\pktdrvr.c msdos/ndis2.c \
-          missing/snprintf.c
+SOURCES = grammar.c scanner.c bpf/net/bpf_filter.c bpf_image.c bpf_dump.c \
+          etherent.c gencode.c nametoaddr.c pcap-common.c pcap-dos.c optimize.c \
+          savefile.c pcap.c sf-pcap.c sf-pcap-ng.c inet.c \
+          msdos/pktdrvr.c msdos/ndis2.c # missing/snprintf.c
 
-OBJECTS = $(notdir $(SOURCES:.c=.o))
+OBJECTS = $(addprefix $(OBJ_DIR)/, $(notdir $(SOURCES:.c=.o)))
 TEMPBIN = tmp.bin
 
 ifeq ($(USE_32BIT_DRIVERS),1)
-  PM_OBJECTS = $(addprefix $(DRIVER_DIR)/, \
+  PM_OBJECTS = $(addprefix $(OBJ_DIR)/, \
                  printk.o pci.o pci-scan.o bios32.o dma.o irq.o intwrap.o \
                  lock.o kmalloc.o quirks.o timer.o net_init.o)
   #
   # Static link of drivers
   #
   ifeq ($(USE_32BIT_MODULES),0)
-    PM_OBJECTS += $(addprefix $(DRIVER_DIR)/, \
+    PM_OBJECTS += $(addprefix $(OBJ_DIR)/, \
                     accton.o 8390.o 3c503.o 3c509.o 3c59x.o 3c515.o \
                     3c575_cb.o 3c90x.o ne.o wd.o cs89x0.o rtl8139.o)
   endif
 endif
 
-all: libpcap.a
+TARGETS = msdos/bin2c.exe libpcap.a filtertest.exe findalldevstest.exe \
+          nonblocktest.exe opentest.exe
+
+all: $(TARGETS)
+	@echo 'Welcome to libpcap/djgpp with samples.'
 
 ifeq ($(USE_32BIT_DRIVERS),1)
 $(PM_OBJECTS):
@@ -53,6 +59,22 @@
 	rm -f $@
 	ar rs $@ $^
 
+filtertest.exe: tests/filtertest.c libpcap.a
+	$(CC) $(CFLAGS) -Din_addr_t=u_long -o $@ $^ $(WATT32_ROOT)/lib/libwatt.a
+	@echo
+
+findalldevstest.exe: tests/findalldevstest.c libpcap.a
+	$(CC) $(CFLAGS) -o $@ $^ $(WATT32_ROOT)/lib/libwatt.a
+	@echo
+
+nonblocktest.exe: tests/nonblocktest.c libpcap.a
+	$(CC) $(CFLAGS) -o $@ $^ $(WATT32_ROOT)/lib/libwatt.a
+	@echo
+
+opentest.exe: tests/opentest.c libpcap.a
+	$(CC) $(CFLAGS) -o $@ $^ $(WATT32_ROOT)/lib/libwatt.a
+	@echo
+
 msdos/pkt_stub.inc: msdos/bin2c.exe msdos/pkt_rx1.S
 	$(ASM) -o $(TEMPBIN) -lmsdos/pkt_rx1.lst msdos/pkt_rx1.S
 	./msdos/bin2c $(TEMPBIN) > $@
@@ -61,8 +83,8 @@
 grammar.c tokdefs.h: grammar.y
 	rm -f grammar.c tokdefs.h
 	$(YACC) --name-prefix=pcap_ --yacc --defines grammar.y
-	mv -f y_tab.c grammar.c
-	mv -f y_tab.h tokdefs.h
+	mv -f y.tab.c grammar.c
+	mv -f y.tab.h tokdefs.h
 
 version.h: ./VERSION
 	@echo '/* Generated from VERSION. Do not edit */' > $@
@@ -76,31 +98,12 @@
 	$(CC) $*.c -o $*.exe
 
 clean:
-	$(MAKE) -f Makefile.dj -C $(DRIVER_DIR) clean
-	$(MAKE) -f Makefile.dj -C libcpcap clean
-	rm -f $(OBJECTS) msdos/pkt_rx1.lst Makefile.bak $(PREREQUISITES)
+	rm -f $(OBJECTS) msdos/pkt_rx1.lst Makefile.bak .depend.dj $(PREREQUISITES)
+#	$(MAKE) -f Makefile.dj -C $(DRIVER_DIR) clean
 
 vclean: clean
-	rm -f libpcap.a msdos/bin2c.exe
-
-#
-# Generated dependencies; Due to some hacks in gcc 2.95 and djgpp 2.03
-# we must prevent "$(DJDIR)/bin/../include/sys/version.h" from beeing
-# included in dependency output (or else this makefile cannot be used on
-# another machine). We therefore use a special 'specs' file during
-# pre-processing.
-#
-MM_SPECS = specs.tmp
-MAKEFILE = msdos/Makefile.dj
-
-depend: $(PREREQUISITES)
-	@echo Generating dependencies..
-	@cp $(MAKEFILE) Makefile.bak
-	@echo "*cpp: %(cpp_cpu) %{posix:-D_POSIX_SOURCE} -remap" > $(MM_SPECS)
-	sed -e "/^# DO NOT DELETE THIS LINE/,$$d" < Makefile.bak > $(MAKEFILE)
-	echo "# DO NOT DELETE THIS LINE"                        >> $(MAKEFILE)
-	$(CC) -MM -specs=$(MM_SPECS) $(CFLAGS) $(SOURCES)       >> $(MAKEFILE)
-	rm -f $(MM_SPECS)
+	rm -f $(TARGETS)
+	-rmdir $(OBJ_DIR)
 
 #
 # Manually generated dependencies
@@ -109,43 +112,16 @@
 scanner.c: scanner.l
 grammar.c tokdefs.h: grammar.y
 grammar.h: grammar.y
-scanner.l: pcap-int.h pcap-namedb.h gencode.h grammar.h gnuc.h
-grammar.y: pcap-int.h gencode.h pcap-namedb.h gnuc.h
+scanner.l: pcap-int.h pcap-namedb.h gencode.h grammar.h
+grammar.y: pcap-int.h gencode.h pcap-namedb.h
 
 #
-# Automatically generated dependencies
+# Generate dependencies.
 #
-# DO NOT DELETE THIS LINE
-grammar.o: grammar.c pcap-int.h pcap.h pcap-bpf.h gencode.h pf.h \
-  pcap-namedb.h
-scanner.o: scanner.c pcap-int.h pcap.h pcap-bpf.h gencode.h pcap-namedb.h \
-  tokdefs.h
-bpf_filt.o: bpf_filt.c pcap-int.h pcap.h pcap-bpf.h gnuc.h
-bpf_imag.o: bpf_imag.c pcap-int.h pcap.h pcap-bpf.h
-bpf_dump.o: bpf_dump.c pcap.h pcap-bpf.h
-etherent.o: etherent.c pcap-int.h pcap.h pcap-bpf.h pcap-namedb.h
-gencode.o: gencode.c pcap-dos.h msdos/pm_drvr/lock.h pcap-int.h pcap.h \
-  pcap-bpf.h ethertype.h nlpid.h llc.h gencode.h atmuni31.h sunatmpos.h \
-  ppp.h sll.h arcnet.h pf.h pcap-namedb.h
-nametoad.o: nametoad.c pcap-int.h pcap.h pcap-bpf.h gencode.h \
-  pcap-namedb.h ethertype.h
-pcap-dos.o: pcap-dos.c msdos/pm_drvr/pmdrvr.h msdos/pm_drvr/iface.h \
-  msdos/pm_drvr/lock.h msdos/pm_drvr/ioport.h pcap-dos.h pcap-int.h \
-  pcap.h pcap-bpf.h msdos/pm_drvr/kmalloc.h msdos/pm_drvr/bitops.h \
-  msdos/pm_drvr/timer.h msdos/pm_drvr/dma.h msdos/pm_drvr/irq.h \
-  msdos/pm_drvr/printk.h msdos/pm_drvr/pci.h msdos/pm_drvr/bios32.h \
-  msdos/pm_drvr/module.h msdos/pm_drvr/3c501.h msdos/pm_drvr/3c503.h \
-  msdos/pm_drvr/3c509.h msdos/pm_drvr/3c59x.h msdos/pm_drvr/3c515.h \
-  msdos/pm_drvr/3c90x.h msdos/pm_drvr/3c575_cb.h msdos/pm_drvr/ne.h \
-  msdos/pm_drvr/wd.h msdos/pm_drvr/accton.h msdos/pm_drvr/cs89x0.h \
-  msdos/pm_drvr/rtl8139.h msdos/pm_drvr/ne2k-pci.h msdos/pktdrvr.h
-optimize.o: optimize.c pcap-int.h pcap.h pcap-bpf.h gencode.h
-savefile.o: savefile.c pcap-int.h pcap.h pcap-bpf.h
-pcap.o: pcap.c pcap-dos.h msdos/pm_drvr/lock.h pcap-int.h pcap.h \
-  pcap-bpf.h
-inet.o: inet.c pcap-int.h pcap.h pcap-bpf.h
-pktdrvr.o: msdos/pktdrvr.c gnuc.h pcap-dos.h msdos/pm_drvr/lock.h \
-  pcap-int.h pcap.h pcap-bpf.h msdos/pktdrvr.h msdos/pkt_stub.inc
-ndis2.o: msdos/ndis2.c pcap-dos.h msdos/pm_drvr/lock.h pcap-int.h pcap.h \
-  pcap-bpf.h msdos/ndis2.h
-snprintf.o: missing/snprintf.c pcap-int.h pcap.h pcap-bpf.h
+REPLACE = sed -e 's/\(.*\)\.o: /\n$$(OBJ_DIR)\/\1.o: /'
+
+depend: $(PREREQUISITES)
+	$(CC) -MM $(CFLAGS) $(SOURCES) | $(REPLACE) > .depend.dj
+
+-include .depend.dj
+
diff --git a/msdos/makefile.wc b/msdos/makefile.wc
index e0d5672..61ba137 100644
--- a/msdos/makefile.wc
+++ b/msdos/makefile.wc
@@ -1,131 +1,134 @@
-#

-#  Watcom Makefile for dos-libpcap.

-#

-# Specify MODEL = `3r' or `3s'

-# Specify TARGET = `pharlap' or `dos4g'

-#

-# Use this makefile from the libpcap root directory.

-# E.g. like this:

-#

-#  c:\net\pcap> wmake -f msdos\makefile.wc

-#

-

-MODEL  = 3s

-TARGET = dos4g

-

-OBJDIR = msdos\$(TARGET).w$(MODEL)

-LIB    = $(OBJDIR)\pcap.lib

-

-.EXTENSIONS: .l .y

-

-DEFS = -dDEBUG -dNDIS_DEBUG -d_U_= -dHAVE_LIMITS_H -dHAVE_STRERROR &

-       -dHAVE_SNPRINTF -dHAVE_VSNPRINTF

-

-CC  = wcc386.exe

-ASM = wasm.exe -$(MODEL) $(DEFS) -dDOSX -dDOS4GW -zq -bt=dos -fr=nul -d3 -s

-

-OBJS = $(OBJDIR)\grammar.obj  $(OBJDIR)\scanner.obj  $(OBJDIR)\pcap.obj     &

-       $(OBJDIR)\bpf_filt.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

-

-CFLAGS = $(DEFS) $(YYDEFS) -I. -I$(%watt_root)\inc -I.\msdos\pm_drvr &

-         -$(MODEL) -mf -zff -zgf -zq -bt=dos -fr=nul -w6 -fpi        &

-         -oilrtf -zm

-

-TEMPBIN = tmp.bin

-

-all: $(OBJDIR) $(OBJDIR)\pcap.lib

-

-$(OBJDIR):

-          - mkdir $(OBJDIR)

-

-$(OBJDIR)\pcap.lib: $(OBJS) wlib.arg

-          wlib -q -b -c $(OBJDIR)\pcap.lib @wlib.arg

-

-wlib.arg: msdos\makefile.wc

-          %create $^@

-          for %f in ($(OBJS)) do %append $^@ +- %f

-

-$(OBJDIR)\pktdrvr.obj: msdos\pkt_stub.inc msdos\pktdrvr.c gnuc.h &

-  pcap-dos.h pcap-int.h pcap.h msdos\pktdrvr.h

-          *$(CC) $(CFLAGS) msdos\pktdrvr.c -fo=$@

-

-$(OBJDIR)\ndis2.obj: msdos\ndis2.c

-          *$(CC) $(CFLAGS) msdos\ndis2.c -fo=$@

-

-.ERASE

-.c{$(OBJDIR)}.obj:

-          *$(CC) $(CFLAGS) $[@ -fo=$@

-

-grammar.c tokdefs.h: grammar.y 

-          bison --name-prefix=pcap_ --yacc --defines $[@

-          - @del grammar.c

-          - @del tokdefs.h

-          ren y_tab.c grammar.c

-          ren y_tab.h tokdefs.h

-

-scanner.c: scanner.l

-          flex -Ppcap_ -7 -o$@ $[@

-

-msdos\pkt_stub.inc: bin2c.exe msdos\pkt_rx1.S

-          nasm -fbin -dDEBUG -o $(TEMPBIN) -lmsdos\pkt_rx1.lst msdos\pkt_rx1.S

-          bin2c.exe  $(TEMPBIN) > $@

-          @del $(TEMPBIN)

-

-bin2c.exe: msdos\bin2c.c

-          wcl $[@

-

-clean realclean vclean: .SYMBOLIC

-          for %f in (dos4g.w3r dos4g.w3s pharlap.w3r pharlap.w3s) do &

-            @del %f\*.obj

-          @del grammar.c

-          @del tokdefs.h

-          @del scanner.c

-          @del bin2c.exe

-          @del bin2c.obj

-          @del msdos\pkt_stub.inc

-          @echo Cleaned

-

-#

-# dependencies

-#                     

-$(OBJDIR)\bpf_filt.obj: bpf_filt.c pcap-int.h pcap.h pcap-bpf.h gnuc.h

-

-$(OBJDIR)\bpf_imag.obj: bpf_imag.c pcap-int.h pcap.h pcap-bpf.h

-

-$(OBJDIR)\bpf_dump.obj: bpf_dump.c pcap.h pcap-bpf.h

-

-$(OBJDIR)\etherent.obj: etherent.c pcap-int.h pcap.h pcap-bpf.h pcap-nam.h

-

-$(OBJDIR)\optimize.obj: optimize.c pcap-int.h pcap.h pcap-bpf.h gencode.h

-

-$(OBJDIR)\savefile.obj: savefile.c pcap-int.h pcap.h pcap-bpf.h

-

-$(OBJDIR)\pcap.obj: pcap.c pcap-dos.h pcap-int.h pcap.h pcap-bpf.h

-

-$(OBJDIR)\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 &

-  pf.h pcap-nam.h

-

-$(OBJDIR)\scanner.obj: scanner.c pcap-int.h pcap.h pcap-bpf.h gencode.h &

-  pcap-nam.h tokdefs.h

-

-$(OBJDIR)\gencode.obj: gencode.c pcap-dos.h pcap-int.h pcap.h pcap-bpf.h &

-  ethertyp.h nlpid.h llc.h gencode.h atmuni31.h sunatmpo.h ppp.h sll.h &

-  arcnet.h pf.h pcap-nam.h

-

-$(OBJDIR)\nametoad.obj: nametoad.c pcap-int.h pcap.h pcap-bpf.h gencode.h &

-  pcap-nam.h ethertyp.h

-

-$(OBJDIR)\pcap-dos.obj: pcap-dos.c pcap.h pcap-bpf.h pcap-dos.h pcap-int.h &

-  msdos\pktdrvr.h

-

-$(OBJDIR)\pktdrvr.obj: msdos\pktdrvr.c gnuc.h pcap-dos.h pcap-int.h &

-  pcap.h pcap-bpf.h msdos\pktdrvr.h msdos\pkt_stub.inc

-

-$(OBJDIR)\ndis2.obj: msdos\ndis2.c pcap-dos.h pcap-int.h pcap.h pcap-bpf.h &

-  msdos\ndis2.h

-

+#
+#  Watcom Makefile for dos-libpcap.
+#
+# Specify MODEL = `3r' or `3s'
+# Specify TARGET = `pharlap' or `dos4g'
+#
+# Use this makefile from the libpcap root directory.
+# E.g. like this:
+#
+#  c:\net\pcap> wmake -f msdos\makefile.wc
+#
+
+MODEL  = 3s
+TARGET = dos4g
+
+OBJDIR = msdos\$(TARGET).w$(MODEL)
+LIB    = $(OBJDIR)\pcap.lib
+
+.EXTENSIONS: .l .y
+
+DEFS = -dDEBUG -dNDIS_DEBUG -d_U_= -dHAVE_LIMITS_H -dHAVE_STRERROR &
+       -dHAVE_SNPRINTF -dHAVE_VSNPRINTF
+
+CC  = wcc386.exe
+ASM = wasm.exe -$(MODEL) $(DEFS) -dDOSX -dDOS4GW -zq -bt=dos -fr=nul -d3 -s
+
+OBJS = $(OBJDIR)\grammar.obj    $(OBJDIR)\scanner.obj  $(OBJDIR)\pcap.obj     &
+       $(OBJDIR)\bpf_filter.obj $(OBJDIR)\bpf_imag.obj $(OBJDIR)\bpf_dump.obj &
+       $(OBJDIR)\etherent.obj   $(OBJDIR)\gencode.obj  $(OBJDIR)\nametoad.obj &
+       $(OBJDIR)\pcap-dos.obj   $(OBJDIR)\pktdrvr.obj  $(OBJDIR)\optimize.obj &
+       $(OBJDIR)\savefile.obj   $(OBJDIR)\inet.obj     $(OBJDIR)\ndis2.obj
+
+CFLAGS = $(DEFS) $(YYDEFS) -I. -I$(%watt_root)\inc -I.\msdos\pm_drvr &
+         -$(MODEL) -mf -zff -zgf -zq -bt=dos -fr=nul -w6 -fpi        &
+         -oilrtf -zm
+
+TEMPBIN = tmp.bin
+
+all: $(OBJDIR) $(OBJDIR)\pcap.lib
+
+$(OBJDIR):
+          - mkdir $(OBJDIR)
+
+$(OBJDIR)\pcap.lib: $(OBJS) wlib.arg
+          wlib -q -b -c $(OBJDIR)\pcap.lib @wlib.arg
+
+wlib.arg: msdos\makefile.wc
+          %create $^@
+          for %f in ($(OBJS)) do %append $^@ +- %f
+
+$(OBJDIR)\pktdrvr.obj: msdos\pkt_stub.inc msdos\pktdrvr.c &
+  pcap-dos.h pcap-int.h pcap.h msdos\pktdrvr.h
+          *$(CC) $(CFLAGS) msdos\pktdrvr.c -fo=$@
+
+$(OBJDIR)\bpf_filter.obj: bpf\net\bpf_filter.c
+          *$(CC) $(CFLAGS) bpf\net\bpf_filter.c -fo=$@
+
+$(OBJDIR)\ndis2.obj: msdos\ndis2.c
+          *$(CC) $(CFLAGS) msdos\ndis2.c -fo=$@
+
+.ERASE
+.c{$(OBJDIR)}.obj:
+          *$(CC) $(CFLAGS) $[@ -fo=$@
+
+grammar.c tokdefs.h: grammar.y
+          bison --name-prefix=pcap_ --yacc --defines $[@
+          - @del grammar.c
+          - @del tokdefs.h
+          ren y_tab.c grammar.c
+          ren y_tab.h tokdefs.h
+
+scanner.c: scanner.l
+          flex -Ppcap_ -7 -o$@ $[@
+
+msdos\pkt_stub.inc: bin2c.exe msdos\pkt_rx1.S
+          nasm -fbin -dDEBUG -o $(TEMPBIN) -lmsdos\pkt_rx1.lst msdos\pkt_rx1.S
+          bin2c.exe  $(TEMPBIN) > $@
+          @del $(TEMPBIN)
+
+bin2c.exe: msdos\bin2c.c
+          wcl $[@
+
+clean realclean vclean: .SYMBOLIC
+          for %f in (dos4g.w3r dos4g.w3s pharlap.w3r pharlap.w3s) do &
+            @del %f\*.obj
+          @del grammar.c
+          @del tokdefs.h
+          @del scanner.c
+          @del bin2c.exe
+          @del bin2c.obj
+          @del msdos\pkt_stub.inc
+          @echo Cleaned
+
+#
+# dependencies
+#
+$(OBJDIR)\bpf_filter.obj: bpf\net\bpf_filter.c pcap-int.h pcap.h pcap-bpf.h
+
+$(OBJDIR)\bpf_imag.obj: bpf_imag.c pcap-int.h pcap.h pcap-bpf.h
+
+$(OBJDIR)\bpf_dump.obj: bpf_dump.c pcap.h pcap-bpf.h
+
+$(OBJDIR)\etherent.obj: etherent.c pcap-int.h pcap.h pcap-bpf.h pcap-namedb.h
+
+$(OBJDIR)\optimize.obj: optimize.c pcap-int.h pcap.h pcap-bpf.h gencode.h
+
+$(OBJDIR)\savefile.obj: savefile.c pcap-int.h pcap.h pcap-bpf.h
+
+$(OBJDIR)\pcap.obj: pcap.c pcap-dos.h pcap-int.h pcap.h pcap-bpf.h
+
+$(OBJDIR)\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
+
+$(OBJDIR)\scanner.obj: scanner.c pcap-int.h pcap.h pcap-bpf.h gencode.h &
+  pcap-namedb.h tokdefs.h
+
+$(OBJDIR)\gencode.obj: gencode.c pcap-dos.h pcap-int.h pcap.h pcap-bpf.h &
+  ethertyp.h nlpid.h llc.h gencode.h atmuni31.h sunatmpo.h ppp.h sll.h &
+  arcnet.h pcap-namedb.h
+
+$(OBJDIR)\nametoad.obj: nametoad.c pcap-int.h pcap.h pcap-bpf.h gencode.h &
+  pcap-namedb.h ethertyp.h
+
+$(OBJDIR)\pcap-dos.obj: pcap-dos.c pcap.h pcap-bpf.h pcap-dos.h pcap-int.h &
+  msdos\pktdrvr.h
+
+$(OBJDIR)\pktdrvr.obj: msdos\pktdrvr.c pcap-dos.h pcap-int.h &
+  pcap.h pcap-bpf.h msdos\pktdrvr.h msdos\pkt_stub.inc
+
+$(OBJDIR)\ndis2.obj: msdos\ndis2.c pcap-dos.h pcap-int.h pcap.h pcap-bpf.h &
+  msdos\ndis2.h
+
diff --git a/msdos/ndis2.c b/msdos/ndis2.c
index 0a5ea2a..526b221 100644
--- a/msdos/ndis2.c
+++ b/msdos/ndis2.c
@@ -1,860 +1,860 @@
-/* 

- * 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 */

-

+/*
+ * 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
index dc72f4c..f278b5d 100644
--- a/msdos/ndis2.h
+++ b/msdos/ndis2.h
@@ -1,559 +1,559 @@
-/* 

- * 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

+/*
+ * 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
index 2990985..ea65e0f 100644
--- a/msdos/ndis_0.asm
+++ b/msdos/ndis_0.asm
@@ -1,188 +1,188 @@
-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

+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/pkt_rx0.asm b/msdos/pkt_rx0.asm
index 94f3d09..d604fa1 100644
--- a/msdos/pkt_rx0.asm
+++ b/msdos/pkt_rx0.asm
@@ -1,197 +1,197 @@
-PAGE 60,132

-NAME PKT_RX

-

-ifdef ??version        ; using TASM

-  masm

-  jumps

-endif

-

-PUBLIC _pktDrop, _pktRxBuf, _pktTxBuf,    _pktTemp

-PUBLIC _rxOutOfs, _rxInOfs, _PktReceiver, _pktRxEnd

-

-;

-; these sizes MUST be equal to the sizes in PKTDRVR.H

-;

-

-RX_BUF_SIZE = 1500      ; max message size on Ethernet

-TX_BUF_SIZE = 1500

-

-ifdef DOSX

- .386

-  NUM_RX_BUF = 32       ; # of RX element buffers

-  _TEXT   SEGMENT PUBLIC DWORD USE16 'CODE'

-  _TEXT   ENDS

-  _DATA   SEGMENT PUBLIC DWORD USE16 'CODE'

-  _DATA   ENDS

-  D_SEG   EQU <_TEXT SEGMENT>

-  D_END   EQU <_TEXT ENDS>

-  ASSUME  CS:_TEXT,DS:_TEXT

-else

- .286

-  NUM_RX_BUF = 10

-  _TEXT   SEGMENT PUBLIC DWORD 'CODE'

-  _TEXT   ENDS

-  _DATA   SEGMENT PUBLIC DWORD 'DATA'

-  _DATA   ENDS

-  D_SEG   EQU <_DATA SEGMENT>

-  D_END   EQU <_DATA ENDS>

-  ASSUME  CS:_TEXT,DS:_DATA

-endif

-

-;-------------------------------------------

-

-D_SEG

-

-RX_ELEMENT     STRUC

-   firstCount  dw  0                          ; # of bytes on 1st call

-   secondCount dw  0                          ; # of bytes on 2nd call

-   handle      dw  0                          ; handle for upcall

-   destinAdr   db  6           dup (0)        ; packet destination address

-   sourceAdr   db  6           dup (0)        ; packet source address

-   protocol    dw  0                          ; packet protocol number

-   rxBuffer    db  RX_BUF_SIZE dup (0)        ; RX buffer

-ENDS

-               align 4

-_rxOutOfs      dw  offset _pktRxBuf           ; ring buffer offsets

-_rxInOfs       dw  offset _pktRxBuf           ; into _pktRxBuf

-_pktDrop       dw  0,0                        ; packet drop counter

-_pktTemp       db  20                dup (0)  ; temp work area

-_pktTxBuf      db  (TX_BUF_SIZE+14)  dup (0)  ; TX buffer

-_pktRxBuf      RX_ELEMENT NUM_RX_BUF dup (<>) ; RX structures

- LAST_OFS      = offset $

-

- screenSeg     dw  0B800h

- newInOffset   dw  0

-

- fanChars      db  '-\|/'

- fanIndex      dw  0

-

-D_END

-

-_TEXT SEGMENT

-

-

-SHOW_RX  MACRO

-         push es

-         push bx

-         mov bx, screenSeg

-         mov es, bx                    ;; r-mode segment of colour screen

-         mov di, 158                   ;; upper right corner - 1

-         mov bx, fanIndex

-         mov al, fanChars[bx]          ;; get write char

-         mov ah, 15                    ;;  and white colour

-         stosw                         ;; write to screen at ES:EDI

-         inc fanIndex                  ;; update next index

-         and fanIndex, 3

-         pop bx

-         pop es

-ENDM

-

-;------------------------------------------------------------------------

-;

-; This macro return ES:DI to tail of Rx queue

-

-ENQUEUE  MACRO

-         LOCAL @noWrap

-         mov ax, _rxInOfs              ;; DI = current in-offset

-         add ax, SIZE RX_ELEMENT       ;; point to next _pktRxBuf buffer

-         cmp ax, LAST_OFS              ;; pointing past last ?

-         jb  @noWrap                   ;; no - jump

-         lea ax, _pktRxBuf             ;; yes, point to 1st buffer

-         align 4

-@noWrap: cmp ax, _rxOutOfs             ;; in-ofs = out-ofs ?

-         je  @dump                     ;; yes, queue is full

-         mov di, _rxInOfs              ;; ES:DI -> buffer at queue input

-         mov newInOffset, ax           ;; remember new input offset

-

-   ;; NOTE. rxInOfs is updated after the packet has been copied

-   ;; to ES:DI (= DS:SI on 2nd call) by the packet driver

-

-ENDM

-

-;------------------------------------------------------------------------

-;

-; This routine gets called by the packet driver twice:

-;   1st time (AX=0) it requests an address where to put the packet

-;

-;   2nd time (AX=1) the packet has been copied to this location (DS:SI)

-;   BX has client handle (stored in RX_ELEMENT.handle).

-;   CX has # of bytes in packet on both call. They should be equal.

-;

-; A test for equality is done by putting CX in _pktRxBuf [n].firstCount

-; and _pktRxBuf[n].secondCount, and CL on first call in

-; _pktRxBuf[n].rxBuffer[CX]. These values are checked in "PktReceive"

-; (PKTDRVR.C)

-;

-;---------------------------------------------------------------------

-

-_PktReceiver:

-         pushf

-         cli                         ; no distraction wanted !

-         push ds

-         push bx

-ifdef DOSX

-         mov bx, cs

-else

-         mov bx, SEG _DATA

-endif

-         mov ds, bx

-         mov es, bx                  ; ES = DS = CS or seg _DATA

-         pop bx                      ; restore handle

-

-         cmp ax, 0                   ; first call? (AX=0)

-         jne @post                   ; AX=1: second call, do post process

-

-ifdef DEBUG

-         SHOW_RX                     ; show that a packet is received

-endif

-         cmp cx, RX_BUF_SIZE+14      ; size OK ?

-         ja  @skip                   ; no, packet to large for us

-

-         ENQUEUE                     ; ES:DI -> _pktRxBuf[n]

-

-         mov [di].firstCount, cx     ; remember the first count.

-         mov [di].handle, bx         ; remember the handle.

-         add di, 6                   ; ES:DI -> _pktRxBuf[n].destinAdr

-         pop ds

-         popf

-         retf                        ; far return to driver with ES:DI

-

-         align 4

-@dump:   inc _pktDrop[0]             ; discard the packet on 1st call

-         adc _pktDrop[2], 0          ; increment packets lost

-

-@skip:   xor di, di                  ; return ES:DI = NIL pointer

-         xor ax, ax

-         mov es, ax

-         pop ds

-         popf

-         retf

-

-         align 4

-@post:   or si, si                   ; DS:SI->_pktRxBuf[n][n].destinAdr

-         jz @discard                 ; make sure we don't use NULL-pointer

-

-         sub si, 6                   ; DS:SI -> _pktRxBuf[n].destinAdr

-       ;

-       ; push si

-       ; push [si].firstCount

-       ; call bpf_filter_match       ; run the filter here some day?

-       ; add sp, 4

-       ; cmp ax, 0

-       ; je  @discard

-

-         mov [si].secondCount, cx

-         mov ax, newInOffset

-         mov _rxInOfs, ax            ; update _pktRxBuf input offset

-

-         align 4

-@discard:pop ds

-         popf

-         retf

-

-_pktRxEnd  db 0                      ; marker for end of r-mode code/data

-

-_TEXT ENDS

-

-END

+PAGE 60,132
+NAME PKT_RX
+
+ifdef ??version        ; using TASM
+  masm
+  jumps
+endif
+
+PUBLIC _pktDrop, _pktRxBuf, _pktTxBuf,    _pktTemp
+PUBLIC _rxOutOfs, _rxInOfs, _PktReceiver, _pktRxEnd
+
+;
+; these sizes MUST be equal to the sizes in PKTDRVR.H
+;
+
+RX_BUF_SIZE = 1500      ; max message size on Ethernet
+TX_BUF_SIZE = 1500
+
+ifdef DOSX
+ .386
+  NUM_RX_BUF = 32       ; # of RX element buffers
+  _TEXT   SEGMENT PUBLIC DWORD USE16 'CODE'
+  _TEXT   ENDS
+  _DATA   SEGMENT PUBLIC DWORD USE16 'CODE'
+  _DATA   ENDS
+  D_SEG   EQU <_TEXT SEGMENT>
+  D_END   EQU <_TEXT ENDS>
+  ASSUME  CS:_TEXT,DS:_TEXT
+else
+ .286
+  NUM_RX_BUF = 10
+  _TEXT   SEGMENT PUBLIC DWORD 'CODE'
+  _TEXT   ENDS
+  _DATA   SEGMENT PUBLIC DWORD 'DATA'
+  _DATA   ENDS
+  D_SEG   EQU <_DATA SEGMENT>
+  D_END   EQU <_DATA ENDS>
+  ASSUME  CS:_TEXT,DS:_DATA
+endif
+
+;-------------------------------------------
+
+D_SEG
+
+RX_ELEMENT     STRUC
+   firstCount  dw  0                          ; # of bytes on 1st call
+   secondCount dw  0                          ; # of bytes on 2nd call
+   handle      dw  0                          ; handle for upcall
+   destinAdr   db  6           dup (0)        ; packet destination address
+   sourceAdr   db  6           dup (0)        ; packet source address
+   protocol    dw  0                          ; packet protocol number
+   rxBuffer    db  RX_BUF_SIZE dup (0)        ; RX buffer
+ENDS
+               align 4
+_rxOutOfs      dw  offset _pktRxBuf           ; ring buffer offsets
+_rxInOfs       dw  offset _pktRxBuf           ; into _pktRxBuf
+_pktDrop       dw  0,0                        ; packet drop counter
+_pktTemp       db  20                dup (0)  ; temp work area
+_pktTxBuf      db  (TX_BUF_SIZE+14)  dup (0)  ; TX buffer
+_pktRxBuf      RX_ELEMENT NUM_RX_BUF dup (<>) ; RX structures
+ LAST_OFS      = offset $
+
+ screenSeg     dw  0B800h
+ newInOffset   dw  0
+
+ fanChars      db  '-\|/'
+ fanIndex      dw  0
+
+D_END
+
+_TEXT SEGMENT
+
+
+SHOW_RX  MACRO
+         push es
+         push bx
+         mov bx, screenSeg
+         mov es, bx                    ;; r-mode segment of colour screen
+         mov di, 158                   ;; upper right corner - 1
+         mov bx, fanIndex
+         mov al, fanChars[bx]          ;; get write char
+         mov ah, 15                    ;;  and white colour
+         stosw                         ;; write to screen at ES:EDI
+         inc fanIndex                  ;; update next index
+         and fanIndex, 3
+         pop bx
+         pop es
+ENDM
+
+;------------------------------------------------------------------------
+;
+; This macro return ES:DI to tail of Rx queue
+
+ENQUEUE  MACRO
+         LOCAL @noWrap
+         mov ax, _rxInOfs              ;; DI = current in-offset
+         add ax, SIZE RX_ELEMENT       ;; point to next _pktRxBuf buffer
+         cmp ax, LAST_OFS              ;; pointing past last ?
+         jb  @noWrap                   ;; no - jump
+         lea ax, _pktRxBuf             ;; yes, point to 1st buffer
+         align 4
+@noWrap: cmp ax, _rxOutOfs             ;; in-ofs = out-ofs ?
+         je  @dump                     ;; yes, queue is full
+         mov di, _rxInOfs              ;; ES:DI -> buffer at queue input
+         mov newInOffset, ax           ;; remember new input offset
+
+   ;; NOTE. rxInOfs is updated after the packet has been copied
+   ;; to ES:DI (= DS:SI on 2nd call) by the packet driver
+
+ENDM
+
+;------------------------------------------------------------------------
+;
+; This routine gets called by the packet driver twice:
+;   1st time (AX=0) it requests an address where to put the packet
+;
+;   2nd time (AX=1) the packet has been copied to this location (DS:SI)
+;   BX has client handle (stored in RX_ELEMENT.handle).
+;   CX has # of bytes in packet on both call. They should be equal.
+;
+; A test for equality is done by putting CX in _pktRxBuf [n].firstCount
+; and _pktRxBuf[n].secondCount, and CL on first call in
+; _pktRxBuf[n].rxBuffer[CX]. These values are checked in "PktReceive"
+; (PKTDRVR.C)
+;
+;---------------------------------------------------------------------
+
+_PktReceiver:
+         pushf
+         cli                         ; no distraction wanted !
+         push ds
+         push bx
+ifdef DOSX
+         mov bx, cs
+else
+         mov bx, SEG _DATA
+endif
+         mov ds, bx
+         mov es, bx                  ; ES = DS = CS or seg _DATA
+         pop bx                      ; restore handle
+
+         cmp ax, 0                   ; first call? (AX=0)
+         jne @post                   ; AX=1: second call, do post process
+
+ifdef DEBUG
+         SHOW_RX                     ; show that a packet is received
+endif
+         cmp cx, RX_BUF_SIZE+14      ; size OK ?
+         ja  @skip                   ; no, packet to large for us
+
+         ENQUEUE                     ; ES:DI -> _pktRxBuf[n]
+
+         mov [di].firstCount, cx     ; remember the first count.
+         mov [di].handle, bx         ; remember the handle.
+         add di, 6                   ; ES:DI -> _pktRxBuf[n].destinAdr
+         pop ds
+         popf
+         retf                        ; far return to driver with ES:DI
+
+         align 4
+@dump:   inc _pktDrop[0]             ; discard the packet on 1st call
+         adc _pktDrop[2], 0          ; increment packets lost
+
+@skip:   xor di, di                  ; return ES:DI = NIL pointer
+         xor ax, ax
+         mov es, ax
+         pop ds
+         popf
+         retf
+
+         align 4
+@post:   or si, si                   ; DS:SI->_pktRxBuf[n][n].destinAdr
+         jz @discard                 ; make sure we don't use NULL-pointer
+
+         sub si, 6                   ; DS:SI -> _pktRxBuf[n].destinAdr
+       ;
+       ; push si
+       ; push [si].firstCount
+       ; call bpf_filter_match       ; run the filter here some day?
+       ; add sp, 4
+       ; cmp ax, 0
+       ; je  @discard
+
+         mov [si].secondCount, cx
+         mov ax, newInOffset
+         mov _rxInOfs, ax            ; update _pktRxBuf input offset
+
+         align 4
+@discard:pop ds
+         popf
+         retf
+
+_pktRxEnd  db 0                      ; marker for end of r-mode code/data
+
+_TEXT ENDS
+
+END
diff --git a/msdos/pkt_rx1.s b/msdos/pkt_rx1.s
index b294a36..654e657 100644
--- a/msdos/pkt_rx1.s
+++ b/msdos/pkt_rx1.s
@@ -1,155 +1,155 @@
-;

-; This file requires NASM 0.97+ to assemble

-;

-; Currently used only for djgpp + DOS4GW targets

-;

-; these sizes MUST be equal to the sizes in PKTDRVR.H

-;

-%define  ETH_MTU     1500                  ; max data size on Ethernet

-%define  ETH_MIN     60                    ; min/max total frame size

-%define  ETH_MAX     (ETH_MTU+2*6+2)

-%define  NUM_RX_BUF  32                    ; # of RX element buffers

-%define  RX_SIZE     (ETH_MAX+6)           ; sizeof(RX_ELEMENT) = 1514+6

-%idefine offset

-

-struc RX_ELEMENT

-      .firstCount  resw 1                  ; # of bytes on 1st call

-      .secondCount resw 1                  ; # of bytes on 2nd call

-      .handle      resw 1                  ; handle for upcall

-    ; .timeStamp   resw 4                  ; 64-bit RDTSC value

-      .destinAdr   resb 6                  ; packet destination address

-      .sourceAdr   resb 6                  ; packet source address

-      .protocol    resw 1                  ; packet protocol number

-      .rxBuffer    resb ETH_MTU            ; RX buffer

-endstruc

-

-;-------------------------------------------

-

-[org 0]  ; assemble to .bin file

-

-_rxOutOfs   dw   offset _pktRxBuf          ; ring buffer offsets

-_rxInOfs    dw   offset _pktRxBuf          ; into _pktRxBuf

-_pktDrop    dw   0,0                       ; packet drop counter

-_pktTemp    resb 20                        ; temp work area

-_pktTxBuf   resb (ETH_MAX)                 ; TX buffer

-_pktRxBuf   resb (RX_SIZE*NUM_RX_BUF)      ; RX structures

- LAST_OFS   equ  $

-

-screenSeg   dw  0B800h

-newInOffset dw  0

-

-fanChars    db  '-\|/'

-fanIndex    dw  0

-

-%macro SHOW_RX 0

-       push es

-       push bx

-       mov bx, [screenSeg]

-       mov es, bx                    ;; r-mode segment of colour screen

-       mov di, 158                   ;; upper right corner - 1

-       mov bx, [fanIndex]

-       mov al, [fanChars+bx]         ;; get write char

-       mov ah, 15                    ;;  and white colour

-       cld                           ;; Needed?

-       stosw                         ;; write to screen at ES:EDI

-       inc word [fanIndex]           ;; update next index

-       and word [fanIndex], 3

-       pop bx

-       pop es

-%endmacro

-

-;PutTimeStamp

-;       rdtsc

-;       mov [si].timeStamp, eax

-;       mov [si+4].timeStamp, edx

-;       ret

-

-

-;------------------------------------------------------------------------

-;

-; This routine gets called by the packet driver twice:

-;   1st time (AX=0) it requests an address where to put the packet

-;

-;   2nd time (AX=1) the packet has been copied to this location (DS:SI)

-;   BX has client handle (stored in RX_ELEMENT.handle).

-;   CX has # of bytes in packet on both call. They should be equal.

-; A test for equality is done by putting CX in _pktRxBuf [n].firstCount

-; and _pktRxBuf[n].secondCount, and CL on first call in

-; _pktRxBuf[n].rxBuffer[CX]. These values are checked in "PktReceive"

-; (PKTDRVR.C)

-;

-;---------------------------------------------------------------------

-

-_PktReceiver:

-         pushf

-         cli                         ; no distraction wanted !

-         push ds

-         push bx

-         mov bx, cs

-         mov ds, bx

-         mov es, bx                  ; ES = DS = CS or seg _DATA

-         pop bx                      ; restore handle

-

-         cmp ax, 0                   ; first call? (AX=0)

-         jne @post                   ; AX=1: second call, do post process

-

-%ifdef DEBUG

-         SHOW_RX                     ; show that a packet is received

-%endif

-

-         cmp cx, ETH_MAX             ; size OK ?

-         ja  @skip                   ; no, too big

-

-         mov ax, [_rxInOfs]

-         add ax, RX_SIZE

-         cmp ax, LAST_OFS

-         jb  @noWrap

-         mov ax, offset _pktRxBuf

-@noWrap:

-         cmp ax, [_rxOutOfs]

-         je  @dump

-         mov di, [_rxInOfs]          ; ES:DI -> _pktRxBuf[n]

-         mov [newInOffset], ax

-

-         mov [di], cx                ; remember firstCount.

-         mov [di+4], bx              ; remember handle.

-         add di, 6                   ; ES:DI -> _pktRxBuf[n].destinAdr

-         pop ds

-         popf

-         retf                        ; far return to driver with ES:DI

-

-@dump:   add word [_pktDrop+0], 1    ; discard the packet on 1st call

-         adc word [_pktDrop+2], 0    ; increment packets lost

-

-@skip:   xor di, di                  ; return ES:DI = NIL pointer

-         xor ax, ax

-         mov es, ax

-         pop ds

-         popf

-         retf

-

-@post:   or si, si                   ; DS:SI->_pktRxBuf[n][n].destinAdr

-         jz @discard                 ; make sure we don't use NULL-pointer

-

-       ;

-       ; push si

-       ; call bpf_filter_match       ; run the filter here some day

-       ; pop si

-       ; cmp ax, 0

-       ; je  @discard

-

-         mov [si-6+2], cx            ; store _pktRxBuf[n].secondCount

-         mov ax, [newInOffset]

-         mov [_rxInOfs], ax          ; update _pktRxBuf input offset

-

-       ; call PutTimeStamp

-

-@discard:

-         pop ds

-         popf

-         retf

-

-_pktRxEnd  db 0                      ; marker for end of r-mode code/data

-

-END

-

+;
+; This file requires NASM 0.97+ to assemble
+;
+; Currently used only for djgpp + DOS4GW targets
+;
+; these sizes MUST be equal to the sizes in PKTDRVR.H
+;
+%define  ETH_MTU     1500                  ; max data size on Ethernet
+%define  ETH_MIN     60                    ; min/max total frame size
+%define  ETH_MAX     (ETH_MTU+2*6+2)       ; =1514
+%define  NUM_RX_BUF  32                    ; # of RX element buffers
+%define  RX_SIZE     (ETH_MAX+6)           ; sizeof(RX_ELEMENT) = 1514+6
+%idefine offset
+
+struc RX_ELEMENT
+      .firstCount  resw 1                  ; # of bytes on 1st call
+      .secondCount resw 1                  ; # of bytes on 2nd call
+      .handle      resw 1                  ; handle for upcall
+    ; .timeStamp   resw 4                  ; 64-bit RDTSC value
+      .destinAdr   resb 6                  ; packet destination address
+      .sourceAdr   resb 6                  ; packet source address
+      .protocol    resw 1                  ; packet protocol number
+      .rxBuffer    resb ETH_MTU            ; RX buffer
+endstruc
+
+;-------------------------------------------
+
+[org 0]  ; assemble to .bin file
+
+_rxOutOfs   dw   offset _pktRxBuf          ; ring buffer offsets
+_rxInOfs    dw   offset _pktRxBuf          ; into _pktRxBuf
+_pktDrop    dw   0,0                       ; packet drop counter
+_pktTemp    resb 20                        ; temp work area
+_pktTxBuf   resb (ETH_MAX)                 ; TX buffer
+_pktRxBuf   resb (RX_SIZE*NUM_RX_BUF)      ; RX structures
+ LAST_OFS   equ  $
+
+screenSeg   dw  0B800h
+newInOffset dw  0
+
+fanChars    db  '-\|/'
+fanIndex    dw  0
+
+%macro SHOW_RX 0
+       push es
+       push bx
+       mov bx, [screenSeg]
+       mov es, bx                    ;; r-mode segment of colour screen
+       mov di, 158                   ;; upper right corner - 1
+       mov bx, [fanIndex]
+       mov al, [fanChars+bx]         ;; get write char
+       mov ah, 15                    ;;  and white colour
+       cld                           ;; Needed?
+       stosw                         ;; write to screen at ES:EDI
+       inc word [fanIndex]           ;; update next index
+       and word [fanIndex], 3
+       pop bx
+       pop es
+%endmacro
+
+;PutTimeStamp
+;       rdtsc
+;       mov [si].timeStamp, eax
+;       mov [si+4].timeStamp, edx
+;       ret
+
+
+;------------------------------------------------------------------------
+;
+; This routine gets called by the packet driver twice:
+;   1st time (AX=0) it requests an address where to put the packet
+;
+;   2nd time (AX=1) the packet has been copied to this location (DS:SI)
+;   BX has client handle (stored in RX_ELEMENT.handle).
+;   CX has # of bytes in packet on both call. They should be equal.
+; A test for equality is done by putting CX in _pktRxBuf [n].firstCount
+; and _pktRxBuf[n].secondCount, and CL on first call in
+; _pktRxBuf[n].rxBuffer[CX]. These values are checked in "PktReceive"
+; (PKTDRVR.C)
+;
+;---------------------------------------------------------------------
+
+_PktReceiver:
+         pushf
+         cli                         ; no distraction wanted !
+         push ds
+         push bx
+         mov bx, cs
+         mov ds, bx
+         mov es, bx                  ; ES = DS = CS or seg _DATA
+         pop bx                      ; restore handle
+
+         cmp ax, 0                   ; first call? (AX=0)
+         jne @post                   ; AX=1: second call, do post process
+
+%ifdef DEBUG
+         SHOW_RX                     ; show that a packet is received
+%endif
+
+         cmp cx, ETH_MAX             ; size OK ?
+         ja  @skip                   ; no, too big
+
+         mov ax, [_rxInOfs]
+         add ax, RX_SIZE
+         cmp ax, LAST_OFS
+         jb  @noWrap
+         mov ax, offset _pktRxBuf
+@noWrap:
+         cmp ax, [_rxOutOfs]
+         je  @dump
+         mov di, [_rxInOfs]          ; ES:DI -> _pktRxBuf[n]
+         mov [newInOffset], ax
+
+         mov [di], cx                ; remember firstCount.
+         mov [di+4], bx              ; remember handle.
+         add di, 6                   ; ES:DI -> _pktRxBuf[n].destinAdr
+         pop ds
+         popf
+         retf                        ; far return to driver with ES:DI
+
+@dump:   add word [_pktDrop+0], 1    ; discard the packet on 1st call
+         adc word [_pktDrop+2], 0    ; increment packets lost
+
+@skip:   xor di, di                  ; return ES:DI = NIL pointer
+         xor ax, ax
+         mov es, ax
+         pop ds
+         popf
+         retf
+
+@post:   or si, si                   ; DS:SI->_pktRxBuf[n][n].destinAdr
+         jz @discard                 ; make sure we don't use NULL-pointer
+
+       ;
+       ; push si
+       ; call bpf_filter_match       ; run the filter here some day
+       ; pop si
+       ; cmp ax, 0
+       ; je  @discard
+
+         mov [si-6+2], cx            ; store _pktRxBuf[n].secondCount
+         mov ax, [newInOffset]
+         mov [_rxInOfs], ax          ; update _pktRxBuf input offset
+
+       ; call PutTimeStamp
+
+@discard:
+         pop ds
+         popf
+         retf
+
+_pktRxEnd  db 0                      ; marker for end of r-mode code/data
+
+END
+
diff --git a/msdos/pktdrvr.c b/msdos/pktdrvr.c
index cd22ee6..37fc8a4 100644
--- a/msdos/pktdrvr.c
+++ b/msdos/pktdrvr.c
@@ -1,1436 +1,1436 @@
-/*

- *  File.........: pktdrvr.c

- *

- *  Responsible..: Gisle Vanem,  giva@bgnett.no

- *

- *  Created......: 26.Sept 1995

- *

- *  Description..: Packet-driver interface for 16/32-bit C :

- *                 Borland C/C++ 3.0+ small/large model

- *                 Watcom C/C++ 11+, DOS4GW flat model

- *                 Metaware HighC 3.1+ and PharLap 386|DosX

- *                 GNU C/C++ 2.7+ and djgpp 2.x extender

- *

- *  References...: PC/TCP Packet driver Specification. rev 1.09

- *                 FTP Software Inc.

- *

- */

-

-#include <stdio.h>

-#include <stdlib.h>

-#include <string.h>

-#include <dos.h>

-

-#include "pcap-dos.h"

-#include "pcap-int.h"

-#include "msdos/pktdrvr.h"

-

-#if (DOSX)

-#define NUM_RX_BUF  32      /* # of buffers in Rx FIFO queue */

-#else

-#define NUM_RX_BUF  10

-#endif

-

-#define DIM(x)   (sizeof((x)) / sizeof(x[0]))

-#define PUTS(s)  do {                                           \

-                   if (!pktInfo.quiet)                          \

-                      pktInfo.error ?                           \

-                        printf ("%s: %s\n", s, pktInfo.error) : \

-                        printf ("%s\n", pktInfo.error = s);     \

-                 } while (0)

-

-#if defined(__HIGHC__)

-  extern UINT _mwenv;

-

-#elif defined(__DJGPP__)

-  #include <stddef.h>

-  #include <dpmi.h>

-  #include <go32.h>

-  #include <pc.h>

-  #include <sys/farptr.h>

-

-#elif defined(__WATCOMC__)

-  #include <i86.h>

-  #include <stddef.h>

-  extern char _Extender;

-

-#else

-  extern void far PktReceiver (void);

-#endif

-

-

-#if (DOSX & (DJGPP|DOS4GW))

-  #include <sys/pack_on.h>

-

-  struct DPMI_regs {

-         DWORD  r_di;

-         DWORD  r_si;

-         DWORD  r_bp;

-         DWORD  reserved;

-         DWORD  r_bx;

-         DWORD  r_dx;

-         DWORD  r_cx;

-         DWORD  r_ax;

-         WORD   r_flags;

-         WORD   r_es, r_ds, r_fs, r_gs;

-         WORD   r_ip, r_cs, r_sp, r_ss;

-       };

-

-  /* Data located in a real-mode segment. This becomes far at runtime

-   */

-  typedef struct  {          /* must match data/code in pkt_rx1.s */

-          WORD       _rxOutOfs;

-          WORD       _rxInOfs;

-          DWORD      _pktDrop;

-          BYTE       _pktTemp [20];

-          TX_ELEMENT _pktTxBuf[1];

-          RX_ELEMENT _pktRxBuf[NUM_RX_BUF];

-          WORD       _dummy[2];        /* screenSeg,newInOffset */

-          BYTE       _fanChars[4];

-          WORD       _fanIndex;

-          BYTE       _PktReceiver[15]; /* starts on a paragraph (16byte) */

-        } PktRealStub;

-  #include <sys/pack_off.h>

-

-  static BYTE real_stub_array [] = {

-         #include "pkt_stub.inc"       /* generated opcode array */

-       };

-

-  #define rxOutOfs      offsetof (PktRealStub,_rxOutOfs)

-  #define rxInOfs       offsetof (PktRealStub,_rxInOfs)

-  #define PktReceiver   offsetof (PktRealStub,_PktReceiver [para_skip])

-  #define pktDrop       offsetof (PktRealStub,_pktDrop)

-  #define pktTemp       offsetof (PktRealStub,_pktTemp)

-  #define pktTxBuf      offsetof (PktRealStub,_pktTxBuf)

-  #define FIRST_RX_BUF  offsetof (PktRealStub,_pktRxBuf [0])

-  #define LAST_RX_BUF   offsetof (PktRealStub,_pktRxBuf [NUM_RX_BUF-1])

-

-#else

-  extern WORD       rxOutOfs;    /* offsets into pktRxBuf FIFO queue   */

-  extern WORD       rxInOfs;

-  extern DWORD      pktDrop;     /* # packets dropped in PktReceiver() */

-  extern BYTE       pktRxEnd;    /* marks the end of r-mode code/data  */

-

-  extern RX_ELEMENT pktRxBuf [NUM_RX_BUF];       /* PktDrvr Rx buffers */

-  extern TX_ELEMENT pktTxBuf;                    /* PktDrvr Tx buffer  */

-  extern char       pktTemp[20];                 /* PktDrvr temp area  */

-

-  #define FIRST_RX_BUF (WORD) &pktRxBuf [0]

-  #define LAST_RX_BUF  (WORD) &pktRxBuf [NUM_RX_BUF-1]

-#endif

-

-

-#ifdef __BORLANDC__           /* Use Borland's inline functions */

-  #define memcpy  __memcpy__

-  #define memcmp  __memcmp__

-  #define memset  __memset__

-#endif

-

-

-#if (DOSX & PHARLAP)

-  extern void PktReceiver (void);     /* in pkt_rx0.asm */

-  static int  RealCopy    (ULONG, ULONG, REALPTR*, FARPTR*, USHORT*);

-

-  #undef  FP_SEG

-  #undef  FP_OFF

-  #define FP_OFF(x)     ((WORD)(x))

-  #define FP_SEG(x)     ((WORD)(realBase >> 16))

-  #define DOS_ADDR(s,o) (((DWORD)(s) << 16) + (WORD)(o))

-  #define r_ax          eax

-  #define r_bx          ebx

-  #define r_dx          edx

-  #define r_cx          ecx

-  #define r_si          esi

-  #define r_di          edi

-  #define r_ds          ds

-  #define r_es          es

-  LOCAL FARPTR          protBase;

-  LOCAL REALPTR         realBase;

-  LOCAL WORD            realSeg;   /* DOS para-address of allocated area */

-  LOCAL SWI_REGS        reg;

-

-  static WORD _far *rxOutOfsFp, *rxInOfsFp;

-

-#elif (DOSX & DJGPP)

-  static _go32_dpmi_seginfo rm_mem;

-  static __dpmi_regs        reg;

-  static DWORD              realBase;

-  static int                para_skip = 0;

-

-  #define DOS_ADDR(s,o)     (((WORD)(s) << 4) + (o))

-  #define r_ax              x.ax

-  #define r_bx              x.bx

-  #define r_dx              x.dx

-  #define r_cx              x.cx

-  #define r_si              x.si

-  #define r_di              x.di

-  #define r_ds              x.ds

-  #define r_es              x.es

-

-#elif (DOSX & DOS4GW)

-  LOCAL struct DPMI_regs    reg;

-  LOCAL WORD                rm_base_seg, rm_base_sel;

-  LOCAL DWORD               realBase;

-  LOCAL int                 para_skip = 0;

-

-  LOCAL DWORD dpmi_get_real_vector (int intr);

-  LOCAL WORD  dpmi_real_malloc     (int size, WORD *selector);

-  LOCAL void  dpmi_real_free       (WORD selector);

-  #define DOS_ADDR(s,o) (((DWORD)(s) << 4) + (WORD)(o))

-

-#else              /* real-mode Borland etc. */

-  static struct  {

-         WORD r_ax, r_bx, r_cx, r_dx, r_bp;

-         WORD r_si, r_di, r_ds, r_es, r_flags;

-       } reg;

-#endif

-

-#ifdef __HIGHC__

-  #pragma Alias (pktDrop,    "_pktDrop")

-  #pragma Alias (pktRxBuf,   "_pktRxBuf")

-  #pragma Alias (pktTxBuf,   "_pktTxBuf")

-  #pragma Alias (pktTemp,    "_pktTemp")

-  #pragma Alias (rxOutOfs,   "_rxOutOfs")

-  #pragma Alias (rxInOfs,    "_rxInOfs")

-  #pragma Alias (pktRxEnd,   "_pktRxEnd")

-  #pragma Alias (PktReceiver,"_PktReceiver")

-#endif

-

-

-PUBLIC PKT_STAT    pktStat;    /* statistics for packets    */

-PUBLIC PKT_INFO    pktInfo;    /* packet-driver information */

-

-PUBLIC PKT_RX_MODE receiveMode  = PDRX_DIRECT;

-PUBLIC ETHER       myAddress    = {   0,  0,  0,  0,  0,  0 };

-PUBLIC ETHER       ethBroadcast = { 255,255,255,255,255,255 };

-

-LOCAL  struct {             /* internal statistics */

-       DWORD  tooSmall;     /* size < ETH_MIN */

-       DWORD  tooLarge;     /* size > ETH_MAX */

-       DWORD  badSync;      /* count_1 != count_2 */

-       DWORD  wrongHandle;  /* upcall to wrong handle */

-     } intStat;  

-

-/***************************************************************************/

-

-PUBLIC const char *PktGetErrorStr (int errNum)

-{

-  static const char *errStr[] = {

-                    "",

-                    "Invalid handle number",

-                    "No interfaces of specified class found",

-                    "No interfaces of specified type found",

-                    "No interfaces of specified number found",

-                    "Bad packet type specified",

-                    "Interface does not support multicast",

-                    "Packet driver cannot terminate",

-                    "Invalid receiver mode specified",

-                    "Insufficient memory space",

-                    "Type previously accessed, and not released",

-                    "Command out of range, or not implemented",

-                    "Cannot send packet (usually hardware error)",

-                    "Cannot change hardware address ( > 1 handle open)",

-                    "Hardware address has bad length or format",

-                    "Cannot reset interface (more than 1 handle open)",

-                    "Bad Check-sum",

-                    "Bad size",

-                    "Bad sync" ,

-                    "Source hit"

-                  };

-

-  if (errNum < 0 || errNum >= DIM(errStr))

-     return ("Unknown driver error.");

-  return (errStr [errNum]);

-}

-

-/**************************************************************************/

-

-PUBLIC const char *PktGetClassName (WORD class)

-{

-  switch (class)

-  { 

-    case PD_ETHER:

-         return ("DIX-Ether");

-    case PD_PRONET10:

-         return ("ProNET-10");

-    case PD_IEEE8025:

-         return ("IEEE 802.5");

-    case PD_OMNINET:

-         return ("OmniNet");

-    case PD_APPLETALK:

-         return ("AppleTalk");

-    case PD_SLIP:

-         return ("SLIP");

-    case PD_STARTLAN:

-         return ("StartLAN");

-    case PD_ARCNET:

-         return ("ArcNet");

-    case PD_AX25:

-         return ("AX.25");

-    case PD_KISS:

-         return ("KISS");

-    case PD_IEEE8023_2:

-         return ("IEEE 802.3 w/802.2 hdr");

-    case PD_FDDI8022:

-         return ("FDDI w/802.2 hdr");

-    case PD_X25:

-         return ("X.25");

-    case PD_LANstar:

-         return ("LANstar");

-    case PD_PPP:

-         return ("PPP");

-    default:

-         return ("unknown");

-  }

-}

-

-/**************************************************************************/

-

-PUBLIC char const *PktRXmodeStr (PKT_RX_MODE mode)

-{

-  static const char *modeStr [] = {

-                    "Receiver turned off",

-                    "Receive only directly addressed packets",

-                    "Receive direct & broadcast packets",

-                    "Receive direct,broadcast and limited multicast packets",

-                    "Receive direct,broadcast and all multicast packets",

-                    "Receive all packets (promiscuouos mode)"

-                  };

-

-  if (mode > DIM(modeStr))

-     return ("??");

-  return (modeStr [mode-1]);

-}

-

-/**************************************************************************/

-

-LOCAL __inline BOOL PktInterrupt (void)

-{

-  BOOL okay;

-

-#if (DOSX & PHARLAP)

-  _dx_real_int ((UINT)pktInfo.intr, &reg);

-  okay = ((reg.flags & 1) == 0);  /* OK if carry clear */

-

-#elif (DOSX & DJGPP)

-  __dpmi_int ((int)pktInfo.intr, &reg);

-  okay = ((reg.x.flags & 1) == 0);

-

-#elif (DOSX & DOS4GW)

-  union  REGS  r;

-  struct SREGS s;

-

-  memset (&r, 0, sizeof(r));

-  segread (&s);

-  r.w.ax  = 0x300;

-  r.x.ebx = pktInfo.intr;

-  r.w.cx  = 0;

-  s.es    = FP_SEG (&reg);

-  r.x.edi = FP_OFF (&reg);

-  reg.r_flags = 0;

-  reg.r_ss = reg.r_sp = 0;     /* DPMI host provides stack */

-

-  int386x (0x31, &r, &r, &s);

-  okay = (!r.w.cflag);

-

-#else

-  reg.r_flags = 0;

-  intr (pktInfo.intr, (struct REGPACK*)&reg);

-  okay = ((reg.r_flags & 1) == 0);

-#endif

-

-  if (okay)

-       pktInfo.error = NULL;

-  else pktInfo.error = PktGetErrorStr (reg.r_dx >> 8);

-  return (okay);

-}

-

-/**************************************************************************/

-

-/*

- * Search for packet driver at interrupt 60h through 80h. If ASCIIZ

- * string "PKT DRVR" found at offset 3 in the interrupt handler, return

- * interrupt number, else return zero in pktInfo.intr

- */

-PUBLIC BOOL PktSearchDriver (void)

-{

-  BYTE intr  = 0x20;

-  BOOL found = FALSE;

-

-  while (!found && intr < 0xFF)

-  {

-    static char str[12];                 /* 3 + strlen("PKT DRVR") */

-    static char pktStr[9] = "PKT DRVR";  /* ASCIIZ string at ofs 3 */

-    DWORD  rp;                           /* in interrupt  routine  */

-

-#if (DOSX & PHARLAP)

-    _dx_rmiv_get (intr, &rp);

-    ReadRealMem (&str, (REALPTR)rp, sizeof(str));

-

-#elif (DOSX & DJGPP)

-    __dpmi_raddr realAdr;

-    __dpmi_get_real_mode_interrupt_vector (intr, &realAdr);

-    rp = (realAdr.segment << 4) + realAdr.offset16;

-    dosmemget (rp, sizeof(str), &str);

-

-#elif (DOSX & DOS4GW)

-    rp = dpmi_get_real_vector (intr);

-    memcpy (&str, (void*)rp, sizeof(str));

-

-#else

-    _fmemcpy (&str, getvect(intr), sizeof(str));

-#endif

-

-    found = memcmp (&str[3],&pktStr,sizeof(pktStr)) == 0;

-    intr++;

-  }

-  pktInfo.intr = (found ? intr-1 : 0);

-  return (found);

-}

-

-

-/**************************************************************************/

-

-static BOOL PktSetAccess (void)

-{

-  reg.r_ax = 0x0200 + pktInfo.class;

-  reg.r_bx = 0xFFFF;

-  reg.r_dx = 0;

-  reg.r_cx = 0;

-

-#if (DOSX & PHARLAP)

-  reg.ds  = 0;

-  reg.esi = 0;

-  reg.es  = RP_SEG (realBase);

-  reg.edi = (WORD) &PktReceiver;

-

-#elif (DOSX & DJGPP)

-  reg.x.ds = 0;

-  reg.x.si = 0;

-  reg.x.es = rm_mem.rm_segment;

-  reg.x.di = PktReceiver;

-

-#elif (DOSX & DOS4GW)

-  reg.r_ds = 0;

-  reg.r_si = 0;

-  reg.r_es = rm_base_seg;

-  reg.r_di = PktReceiver;

-

-#else

-  reg.r_ds = 0;

-  reg.r_si = 0;

-  reg.r_es = FP_SEG (&PktReceiver);

-  reg.r_di = FP_OFF (&PktReceiver);

-#endif

-

-  if (!PktInterrupt())

-     return (FALSE);

-

-  pktInfo.handle = reg.r_ax;

-  return (TRUE);

-}

-

-/**************************************************************************/

-

-PUBLIC BOOL PktReleaseHandle (WORD handle)

-{

-  reg.r_ax = 0x0300;

-  reg.r_bx = handle;

-  return PktInterrupt();

-}

-

-/**************************************************************************/

-

-PUBLIC BOOL PktTransmit (const void *eth, int len)

-{

-  if (len > ETH_MTU)

-     return (FALSE);

-

-  reg.r_ax = 0x0400;             /* Function 4, send pkt */

-  reg.r_cx = len;                /* total size of frame  */

-

-#if (DOSX & DJGPP)

-  dosmemput (eth, len, realBase+pktTxBuf);

-  reg.x.ds = rm_mem.rm_segment;  /* DOS data segment and */

-  reg.x.si = pktTxBuf;           /* DOS offset to buffer */

-

-#elif (DOSX & DOS4GW)

-  memcpy ((void*)(realBase+pktTxBuf), eth, len);

-  reg.r_ds = rm_base_seg;

-  reg.r_si = pktTxBuf;

-

-#elif (DOSX & PHARLAP)

-  memcpy (&pktTxBuf, eth, len);

-  reg.r_ds = FP_SEG (&pktTxBuf);

-  reg.r_si = FP_OFF (&pktTxBuf);

-

-#else

-  reg.r_ds = FP_SEG (eth);

-  reg.r_si = FP_OFF (eth);

-#endif

-

-  return PktInterrupt();

-}

-

-/**************************************************************************/

-

-#if (DOSX & (DJGPP|DOS4GW))

-LOCAL __inline BOOL CheckElement (RX_ELEMENT *rx)

-#else

-LOCAL __inline BOOL CheckElement (RX_ELEMENT _far *rx)

-#endif

-{

-  WORD count_1, count_2;

-

-  /*

-   * We got an upcall to the same RMCB with wrong handle.

-   * This can happen if we failed to release handle at program exit

-   */

-  if (rx->handle != pktInfo.handle)

-  {

-    pktInfo.error = "Wrong handle";

-    intStat.wrongHandle++;

-    PktReleaseHandle (rx->handle);

-    return (FALSE);

-  }

-  count_1 = rx->firstCount;

-  count_2 = rx->secondCount;

-

-  if (count_1 != count_2)

-  {

-    pktInfo.error = "Bad sync";

-    intStat.badSync++;

-    return (FALSE);

-  }

-  if (count_1 > ETH_MAX)

-  {

-    pktInfo.error = "Large esize";

-    intStat.tooLarge++;

-    return (FALSE);

-  }

-#if 0

-  if (count_1 < ETH_MIN)

-  {

-    pktInfo.error = "Small esize";

-    intStat.tooSmall++;

-    return (FALSE);

-  }

-#endif

-  return (TRUE);

-}

-

-/**************************************************************************/

-

-PUBLIC BOOL PktTerminHandle (WORD handle)

-{

-  reg.r_ax = 0x0500;

-  reg.r_bx = handle;

-  return PktInterrupt();

-}

-

-/**************************************************************************/

-

-PUBLIC BOOL PktResetInterface (WORD handle)

-{

-  reg.r_ax = 0x0700;

-  reg.r_bx = handle;

-  return PktInterrupt();

-}

-

-/**************************************************************************/

-

-PUBLIC BOOL PktSetReceiverMode (PKT_RX_MODE mode)

-{

-  if (pktInfo.class == PD_SLIP || pktInfo.class == PD_PPP)

-     return (TRUE);

-

-  reg.r_ax = 0x1400;

-  reg.r_bx = pktInfo.handle;

-  reg.r_cx = (WORD)mode;

-

-  if (!PktInterrupt())

-     return (FALSE);

-

-  receiveMode = mode;

-  return (TRUE);

-}

-

-/**************************************************************************/

-

-PUBLIC BOOL PktGetReceiverMode (PKT_RX_MODE *mode)

-{

-  reg.r_ax = 0x1500;

-  reg.r_bx = pktInfo.handle;

-

-  if (!PktInterrupt())

-     return (FALSE);

-

-  *mode = reg.r_ax;

-  return (TRUE);

-}

-

-/**************************************************************************/

-

-static PKT_STAT initialStat;         /* statistics at startup */

-static BOOL     resetStat = FALSE;   /* statistics reset ? */

-

-PUBLIC BOOL PktGetStatistics (WORD handle)

-{

-  reg.r_ax = 0x1800;

-  reg.r_bx = handle;

-

-  if (!PktInterrupt())

-     return (FALSE);

-

-#if (DOSX & PHARLAP)

-  ReadRealMem (&pktStat, DOS_ADDR(reg.ds,reg.esi), sizeof(pktStat));

-

-#elif (DOSX & DJGPP)

-  dosmemget (DOS_ADDR(reg.x.ds,reg.x.si), sizeof(pktStat), &pktStat);

-

-#elif (DOSX & DOS4GW)

-  memcpy (&pktStat, (void*)DOS_ADDR(reg.r_ds,reg.r_si), sizeof(pktStat));

-

-#else

-  _fmemcpy (&pktStat, MK_FP(reg.r_ds,reg.r_si), sizeof(pktStat));

-#endif

-

-  return (TRUE);

-}

-

-/**************************************************************************/

-

-PUBLIC BOOL PktSessStatistics (WORD handle)

-{

-  if (!PktGetStatistics(pktInfo.handle))

-     return (FALSE);

-

-  if (resetStat)

-  {

-    pktStat.inPackets  -= initialStat.inPackets;

-    pktStat.outPackets -= initialStat.outPackets;

-    pktStat.inBytes    -= initialStat.inBytes;

-    pktStat.outBytes   -= initialStat.outBytes;

-    pktStat.inErrors   -= initialStat.inErrors;

-    pktStat.outErrors  -= initialStat.outErrors;

-    pktStat.outErrors  -= initialStat.outErrors;

-    pktStat.lost       -= initialStat.lost;

-  }

-  return (TRUE);

-}

-

-/**************************************************************************/

-

-PUBLIC BOOL PktResetStatistics (WORD handle)

-{

-  if (!PktGetStatistics(pktInfo.handle))

-     return (FALSE);

-

-  memcpy (&initialStat, &pktStat, sizeof(initialStat));

-  resetStat = TRUE;

-  return (TRUE);

-}

-

-/**************************************************************************/

-

-PUBLIC BOOL PktGetAddress (ETHER *addr)

-{

-  reg.r_ax = 0x0600;

-  reg.r_bx = pktInfo.handle;

-  reg.r_cx = sizeof (*addr);

-

-#if (DOSX & DJGPP)

-  reg.x.es = rm_mem.rm_segment;

-  reg.x.di = pktTemp;

-#elif (DOSX & DOS4GW)

-  reg.r_es = rm_base_seg;

-  reg.r_di = pktTemp;

-#else

-  reg.r_es = FP_SEG (&pktTemp);

-  reg.r_di = FP_OFF (&pktTemp);  /* ES:DI = address for result */

-#endif

-

-  if (!PktInterrupt())

-     return (FALSE);

-

-#if (DOSX & PHARLAP)

-  ReadRealMem (addr, realBase + (WORD)&pktTemp, sizeof(*addr));

-

-#elif (DOSX & DJGPP)

-  dosmemget (realBase+pktTemp, sizeof(*addr), addr);

-

-#elif (DOSX & DOS4GW)

-  memcpy (addr, (void*)(realBase+pktTemp), sizeof(*addr));

-

-#else

-  memcpy ((void*)addr, &pktTemp, sizeof(*addr));

-#endif

-

-  return (TRUE);

-}

-

-/**************************************************************************/

-

-PUBLIC BOOL PktSetAddress (const ETHER *addr)

-{

-  /* copy addr to real-mode scrath area */

-

-#if (DOSX & PHARLAP)

-  WriteRealMem (realBase + (WORD)&pktTemp, (void*)addr, sizeof(*addr));

-

-#elif (DOSX & DJGPP)

-  dosmemput (addr, sizeof(*addr), realBase+pktTemp);

-

-#elif (DOSX & DOS4GW)

-  memcpy ((void*)(realBase+pktTemp), addr, sizeof(*addr));

-

-#else

-  memcpy (&pktTemp, (void*)addr, sizeof(*addr));

-#endif

-

-  reg.r_ax = 0x1900;

-  reg.r_cx = sizeof (*addr);      /* address length       */

-

-#if (DOSX & DJGPP)

-  reg.x.es = rm_mem.rm_segment;   /* DOS offset to param  */

-  reg.x.di = pktTemp;             /* DOS segment to param */

-#elif (DOSX & DOS4GW)

-  reg.r_es = rm_base_seg;

-  reg.r_di = pktTemp;

-#else

-  reg.r_es = FP_SEG (&pktTemp);

-  reg.r_di = FP_OFF (&pktTemp);

-#endif

-

-  return PktInterrupt();

-}

-

-/**************************************************************************/

-

-PUBLIC BOOL PktGetDriverInfo (void)

-{

-  pktInfo.majVer = 0;

-  pktInfo.minVer = 0;

-  memset (&pktInfo.name, 0, sizeof(pktInfo.name));

-  reg.r_ax = 0x01FF;

-  reg.r_bx = 0;

-

-  if (!PktInterrupt())

-     return (FALSE);

-

-  pktInfo.number = reg.r_cx & 0xFF;

-  pktInfo.class  = reg.r_cx >> 8;

-#if 0

-  pktInfo.minVer = reg.r_bx % 10;

-  pktInfo.majVer = reg.r_bx / 10;

-#else

-  pktInfo.majVer = reg.r_bx;  // !!

-#endif

-  pktInfo.funcs  = reg.r_ax & 0xFF;

-  pktInfo.type   = reg.r_dx & 0xFF;

-

-#if (DOSX & PHARLAP)

-  ReadRealMem (&pktInfo.name, DOS_ADDR(reg.ds,reg.esi), sizeof(pktInfo.name));

-

-#elif (DOSX & DJGPP)

-  dosmemget (DOS_ADDR(reg.x.ds,reg.x.si), sizeof(pktInfo.name), &pktInfo.name);

-

-#elif (DOSX & DOS4GW)

-  memcpy (&pktInfo.name, (void*)DOS_ADDR(reg.r_ds,reg.r_si), sizeof(pktInfo.name));

-

-#else

-  _fmemcpy (&pktInfo.name, MK_FP(reg.r_ds,reg.r_si), sizeof(pktInfo.name));

-#endif

-  return (TRUE);

-}

-

-/**************************************************************************/

-

-PUBLIC BOOL PktGetDriverParam (void)

-{

-  reg.r_ax = 0x0A00;

-

-  if (!PktInterrupt())

-     return (FALSE);

-

-#if (DOSX & PHARLAP)

-  ReadRealMem (&pktInfo.majVer, DOS_ADDR(reg.es,reg.edi), PKT_PARAM_SIZE);

-

-#elif (DOSX & DJGPP)

-  dosmemget (DOS_ADDR(reg.x.es,reg.x.di), PKT_PARAM_SIZE, &pktInfo.majVer);

-

-#elif (DOSX & DOS4GW)

-  memcpy (&pktInfo.majVer, (void*)DOS_ADDR(reg.r_es,reg.r_di), PKT_PARAM_SIZE);

-

-#else

-  _fmemcpy (&pktInfo.majVer, MK_FP(reg.r_es,reg.r_di), PKT_PARAM_SIZE);

-#endif

-  return (TRUE);

-}

-

-/**************************************************************************/

-

-#if (DOSX & PHARLAP)

-  PUBLIC int PktReceive (BYTE *buf, int max)

-  {

-    WORD inOfs  = *rxInOfsFp;

-    WORD outOfs = *rxOutOfsFp;

-

-    if (outOfs != inOfs)

-    {

-      RX_ELEMENT _far *head = (RX_ELEMENT _far*)(protBase+outOfs);

-      int size, len = max;

-

-      if (CheckElement(head))

-      {

-        size = min (head->firstCount, sizeof(RX_ELEMENT));

-        len  = min (size, max);

-        _fmemcpy (buf, &head->destin, len);

-      }

-      else

-        size = -1;

-

-      outOfs += sizeof (RX_ELEMENT);

-      if (outOfs > LAST_RX_BUF)

-          outOfs = FIRST_RX_BUF;

-      *rxOutOfsFp = outOfs;

-      return (size);

-    }

-    return (0);

-  }

-

-  PUBLIC void PktQueueBusy (BOOL busy)

-  {

-    *rxOutOfsFp = busy ? (*rxInOfsFp + sizeof(RX_ELEMENT)) : *rxInOfsFp;

-    if (*rxOutOfsFp > LAST_RX_BUF)

-        *rxOutOfsFp = FIRST_RX_BUF;

-    *(DWORD _far*)(protBase + (WORD)&pktDrop) = 0;

-  }

-

-  PUBLIC WORD PktBuffersUsed (void)

-  {

-    WORD inOfs  = *rxInOfsFp;

-    WORD outOfs = *rxOutOfsFp;

-

-    if (inOfs >= outOfs)

-       return (inOfs - outOfs) / sizeof(RX_ELEMENT);

-    return (NUM_RX_BUF - (outOfs - inOfs) / sizeof(RX_ELEMENT));

-  }

-

-  PUBLIC DWORD PktRxDropped (void)

-  {

-    return (*(DWORD _far*)(protBase + (WORD)&pktDrop));

-  }

-

-#elif (DOSX & DJGPP)

-  PUBLIC int PktReceive (BYTE *buf, int max)

-  {

-    WORD ofs = _farpeekw (_dos_ds, realBase+rxOutOfs);

-

-    if (ofs != _farpeekw (_dos_ds, realBase+rxInOfs))

-    {

-      RX_ELEMENT head;

-      int  size, len = max;

-

-      head.firstCount  = _farpeekw (_dos_ds, realBase+ofs);

-      head.secondCount = _farpeekw (_dos_ds, realBase+ofs+2);

-      head.handle      = _farpeekw (_dos_ds, realBase+ofs+4);

-

-      if (CheckElement(&head))

-      {

-        size = min (head.firstCount, sizeof(RX_ELEMENT));

-        len  = min (size, max);

-        dosmemget (realBase+ofs+6, len, buf);

-      }

-      else

-        size = -1;

-

-      ofs += sizeof (RX_ELEMENT);

-      if (ofs > LAST_RX_BUF)

-           _farpokew (_dos_ds, realBase+rxOutOfs, FIRST_RX_BUF);

-      else _farpokew (_dos_ds, realBase+rxOutOfs, ofs);

-      return (size);

-    }

-    return (0);

-  }

-

-  PUBLIC void PktQueueBusy (BOOL busy)

-  {

-    WORD ofs;

-

-    disable();

-    ofs = _farpeekw (_dos_ds, realBase+rxInOfs);

-    if (busy)

-       ofs += sizeof (RX_ELEMENT);

-

-    if (ofs > LAST_RX_BUF)

-         _farpokew (_dos_ds, realBase+rxOutOfs, FIRST_RX_BUF);

-    else _farpokew (_dos_ds, realBase+rxOutOfs, ofs);

-    _farpokel (_dos_ds, realBase+pktDrop, 0UL);

-    enable();

-  }

-

-  PUBLIC WORD PktBuffersUsed (void)

-  {

-    WORD inOfs, outOfs;

-

-    disable();

-    inOfs  = _farpeekw (_dos_ds, realBase+rxInOfs);

-    outOfs = _farpeekw (_dos_ds, realBase+rxOutOfs);

-    enable();

-    if (inOfs >= outOfs)

-       return (inOfs - outOfs) / sizeof(RX_ELEMENT);

-    return (NUM_RX_BUF - (outOfs - inOfs) / sizeof(RX_ELEMENT));

-  }

-

-  PUBLIC DWORD PktRxDropped (void)

-  {

-    return _farpeekl (_dos_ds, realBase+pktDrop);

-  }

-

-#elif (DOSX & DOS4GW)

-  PUBLIC int PktReceive (BYTE *buf, int max)

-  {

-    WORD ofs = *(WORD*) (realBase+rxOutOfs);

-

-    if (ofs != *(WORD*) (realBase+rxInOfs))

-    {

-      RX_ELEMENT head;

-      int  size, len = max;

-

-      head.firstCount  = *(WORD*) (realBase+ofs);

-      head.secondCount = *(WORD*) (realBase+ofs+2);

-      head.handle      = *(WORD*) (realBase+ofs+4);

-

-      if (CheckElement(&head))

-      {

-        size = min (head.firstCount, sizeof(RX_ELEMENT));

-        len  = min (size, max);

-        memcpy (buf, (const void*)(realBase+ofs+6), len);

-      }

-      else

-        size = -1;

-

-      ofs += sizeof (RX_ELEMENT);

-      if (ofs > LAST_RX_BUF)

-           *(WORD*) (realBase+rxOutOfs) = FIRST_RX_BUF;

-      else *(WORD*) (realBase+rxOutOfs) = ofs;

-      return (size);

-    }

-    return (0);

-  }

-

-  PUBLIC void PktQueueBusy (BOOL busy)

-  {

-    WORD ofs;

-

-    _disable();

-    ofs = *(WORD*) (realBase+rxInOfs);

-    if (busy)

-       ofs += sizeof (RX_ELEMENT);

-

-    if (ofs > LAST_RX_BUF)

-         *(WORD*) (realBase+rxOutOfs) = FIRST_RX_BUF;

-    else *(WORD*) (realBase+rxOutOfs) = ofs;

-    *(DWORD*) (realBase+pktDrop) = 0UL;

-    _enable();

-  }

-

-  PUBLIC WORD PktBuffersUsed (void)

-  {

-    WORD inOfs, outOfs;

-

-    _disable();

-    inOfs  = *(WORD*) (realBase+rxInOfs);

-    outOfs = *(WORD*) (realBase+rxOutOfs);

-    _enable();

-    if (inOfs >= outOfs)

-       return (inOfs - outOfs) / sizeof(RX_ELEMENT);

-    return (NUM_RX_BUF - (outOfs - inOfs) / sizeof(RX_ELEMENT));

-  }

-

-  PUBLIC DWORD PktRxDropped (void)

-  {

-    return *(DWORD*) (realBase+pktDrop);

-  }

-

-#else     /* real-mode small/large model */

-

-  PUBLIC int PktReceive (BYTE *buf, int max)

-  {

-    if (rxOutOfs != rxInOfs)

-    {

-      RX_ELEMENT far *head = (RX_ELEMENT far*) MK_FP (_DS,rxOutOfs);

-      int  size, len = max;

-

-      if (CheckElement(head))

-      {

-        size = min (head->firstCount, sizeof(RX_ELEMENT));

-        len  = min (size, max);

-        _fmemcpy (buf, &head->destin, len);

-      }

-      else

-        size = -1;

-

-      rxOutOfs += sizeof (RX_ELEMENT);

-      if (rxOutOfs > LAST_RX_BUF)

-          rxOutOfs = FIRST_RX_BUF;

-      return (size);

-    }

-    return (0);

-  }

-

-  PUBLIC void PktQueueBusy (BOOL busy)

-  {

-    rxOutOfs = busy ? (rxInOfs + sizeof(RX_ELEMENT)) : rxInOfs;

-    if (rxOutOfs > LAST_RX_BUF)

-        rxOutOfs = FIRST_RX_BUF;

-    pktDrop = 0L;

-  }

-

-  PUBLIC WORD PktBuffersUsed (void)

-  {

-    WORD inOfs  = rxInOfs;

-    WORD outOfs = rxOutOfs;

-

-    if (inOfs >= outOfs)

-       return ((inOfs - outOfs) / sizeof(RX_ELEMENT));

-    return (NUM_RX_BUF - (outOfs - inOfs) / sizeof(RX_ELEMENT));

-  }

-

-  PUBLIC DWORD PktRxDropped (void)

-  {

-    return (pktDrop);

-  }

-#endif

-

-/**************************************************************************/

-

-LOCAL __inline void PktFreeMem (void)

-{

-#if (DOSX & PHARLAP)

-  if (realSeg)

-  {

-    _dx_real_free (realSeg);

-    realSeg = 0;

-  }

-#elif (DOSX & DJGPP)

-  if (rm_mem.rm_segment)

-  {

-    unsigned ofs;  /* clear the DOS-mem to prevent further upcalls */

-

-    for (ofs = 0; ofs < 16 * rm_mem.size / 4; ofs += 4)

-       _farpokel (_dos_ds, realBase + ofs, 0);

-    _go32_dpmi_free_dos_memory (&rm_mem);

-    rm_mem.rm_segment = 0;

-  }

-#elif (DOSX & DOS4GW)

-  if (rm_base_sel)

-  {

-    dpmi_real_free (rm_base_sel);

-    rm_base_sel = 0;

-  }

-#endif

-}

-

-/**************************************************************************/

-

-PUBLIC BOOL PktExitDriver (void)

-{           

-  if (pktInfo.handle)

-  {

-    if (!PktSetReceiverMode(PDRX_BROADCAST))

-       PUTS ("Error restoring receiver mode.");

-

-    if (!PktReleaseHandle(pktInfo.handle))

-       PUTS ("Error releasing PKT-DRVR handle.");

-

-    PktFreeMem();

-    pktInfo.handle = 0;

-  }

-

-  if (pcap_pkt_debug >= 1)

-     printf ("Internal stats: too-small %lu, too-large %lu, bad-sync %lu, "

-             "wrong-handle %lu\n",

-             intStat.tooSmall, intStat.tooLarge,

-             intStat.badSync, intStat.wrongHandle);

-  return (TRUE);

-}

-

-#if (DOSX & (DJGPP|DOS4GW))

-static void dump_pkt_stub (void)

-{

-  int i;

-

-  fprintf (stderr, "PktReceiver %lu, pkt_stub[PktReceiver] =\n",

-           PktReceiver);

-  for (i = 0; i < 15; i++)

-      fprintf (stderr, "%02X, ", real_stub_array[i+PktReceiver]);

-  fputs ("\n", stderr);

-}

-#endif

-

-/*

- * Front end initialization routine

- */

-PUBLIC BOOL PktInitDriver (PKT_RX_MODE mode)

-{

-  PKT_RX_MODE rxMode;

-  BOOL   writeInfo = (pcap_pkt_debug >= 3);

-

-  pktInfo.quiet = (pcap_pkt_debug < 3);

-

-#if (DOSX & PHARLAP) && defined(__HIGHC__)

-  if (_mwenv != 2)

-  {

-    fprintf (stderr, "Only Pharlap DOS extender supported.\n");

-    return (FALSE);

-  }

-#endif

-

-#if (DOSX & PHARLAP) && defined(__WATCOMC__)

-  if (_Extender != 1)

-  {

-    fprintf (stderr, "Only DOS4GW style extenders supported.\n");

-    return (FALSE);

-  }

-#endif

-

-  if (!PktSearchDriver())

-  {

-    PUTS ("Packet driver not found.");

-    PktFreeMem();

-    return (FALSE);

-  }

-

-  if (!PktGetDriverInfo())

-  {

-    PUTS ("Error getting pkt-drvr information.");

-    PktFreeMem();

-    return (FALSE);

-  }

-

-#if (DOSX & PHARLAP)

-  if (RealCopy((ULONG)&rxOutOfs, (ULONG)&pktRxEnd,

-               &realBase, &protBase, (USHORT*)&realSeg))

-  {

-    rxOutOfsFp  = (WORD _far *) (protBase + (WORD) &rxOutOfs);

-    rxInOfsFp   = (WORD _far *) (protBase + (WORD) &rxInOfs);

-    *rxOutOfsFp = FIRST_RX_BUF;

-    *rxInOfsFp  = FIRST_RX_BUF;

-  }

-  else

-  {

-    PUTS ("Cannot allocate real-mode stub.");

-    return (FALSE);

-  }

-

-#elif (DOSX & (DJGPP|DOS4GW))

-  if (sizeof(real_stub_array) > 0xFFFF)

-  {

-    fprintf (stderr, "`real_stub_array[]' too big.\n");

-    return (FALSE);

-  }

-#if (DOSX & DJGPP)

-  rm_mem.size = (sizeof(real_stub_array) + 15) / 16;

-

-  if (_go32_dpmi_allocate_dos_memory(&rm_mem) || rm_mem.rm_offset != 0)

-  {

-    PUTS ("real-mode init failed.");

-    return (FALSE);

-  }

-  realBase = (rm_mem.rm_segment << 4);

-  dosmemput (&real_stub_array, sizeof(real_stub_array), realBase);

-  _farpokel (_dos_ds, realBase+rxOutOfs, FIRST_RX_BUF);

-  _farpokel (_dos_ds, realBase+rxInOfs,  FIRST_RX_BUF);

-

-#elif (DOSX & DOS4GW)

-  rm_base_seg = dpmi_real_malloc (sizeof(real_stub_array), &rm_base_sel);

-  if (!rm_base_seg)

-  {

-    PUTS ("real-mode init failed.");

-    return (FALSE);

-  }

-  realBase = (rm_base_seg << 4);

-  memcpy ((void*)realBase, &real_stub_array, sizeof(real_stub_array));

-  *(WORD*) (realBase+rxOutOfs) = FIRST_RX_BUF;

-  *(WORD*) (realBase+rxInOfs)  = FIRST_RX_BUF;

-

-#endif

-  {

-    int pushf = PktReceiver;

-

-    while (real_stub_array[pushf++] != 0x9C &&    /* pushf */

-           real_stub_array[pushf]   != 0xFA)      /* cli   */

-    {

-      if (++para_skip > 16)

-      {

-        fprintf (stderr, "Something wrong with `pkt_stub.inc'.\n");

-        para_skip = 0;

-        dump_pkt_stub();

-        return (FALSE);

-      }

-    }

-    if (*(WORD*)(real_stub_array + offsetof(PktRealStub,_dummy)) != 0xB800)

-    {

-      fprintf (stderr, "`real_stub_array[]' is misaligned.\n");

-      return (FALSE);

-    }

-  }

-

-  if (pcap_pkt_debug > 2)

-      dump_pkt_stub();

-

-#else

-  rxOutOfs = FIRST_RX_BUF;

-  rxInOfs  = FIRST_RX_BUF;

-#endif

-

-  if (!PktSetAccess())

-  {

-    PUTS ("Error setting pkt-drvr access.");

-    PktFreeMem();

-    return (FALSE);

-  }

-

-  if (!PktGetAddress(&myAddress))

-  {

-    PUTS ("Error fetching adapter address.");

-    PktFreeMem();

-    return (FALSE);

-  }

-

-  if (!PktSetReceiverMode(mode))

-  {

-    PUTS ("Error setting receiver mode.");

-    PktFreeMem();

-    return (FALSE);

-  }

-

-  if (!PktGetReceiverMode(&rxMode))

-  {

-    PUTS ("Error getting receiver mode.");

-    PktFreeMem();

-    return (FALSE);

-  }

-

-  if (writeInfo)

-     printf ("Pkt-driver information:\n"

-             "  Version  : %d.%d\n"

-             "  Name     : %.15s\n"

-             "  Class    : %u (%s)\n"

-             "  Type     : %u\n"

-             "  Number   : %u\n"

-             "  Funcs    : %u\n"

-             "  Intr     : %Xh\n"

-             "  Handle   : %u\n"

-             "  Extended : %s\n"

-             "  Hi-perf  : %s\n"

-             "  RX mode  : %s\n"

-             "  Eth-addr : %02X:%02X:%02X:%02X:%02X:%02X\n",

-

-             pktInfo.majVer, pktInfo.minVer, pktInfo.name,

-             pktInfo.class,  PktGetClassName(pktInfo.class),

-             pktInfo.type,   pktInfo.number,

-             pktInfo.funcs,  pktInfo.intr,   pktInfo.handle,

-             pktInfo.funcs == 2 || pktInfo.funcs == 6 ? "Yes" : "No",

-             pktInfo.funcs == 5 || pktInfo.funcs == 6 ? "Yes" : "No",

-             PktRXmodeStr(rxMode),

-             myAddress[0], myAddress[1], myAddress[2],

-             myAddress[3], myAddress[4], myAddress[5]);

-

-#if defined(DEBUG) && (DOSX & PHARLAP)

-  if (writeInfo)

-  {

-    DWORD    rAdr = realBase + (WORD)&PktReceiver;

-    unsigned sel, ofs;

-

-    printf ("\nReceiver at   %04X:%04X\n", RP_SEG(rAdr),    RP_OFF(rAdr));

-    printf ("Realbase    = %04X:%04X\n",   RP_SEG(realBase),RP_OFF(realBase));

-

-    sel = _FP_SEG (protBase);

-    ofs = _FP_OFF (protBase);

-    printf ("Protbase    = %04X:%08X\n", sel,ofs);

-    printf ("RealSeg     = %04X\n", realSeg);

-

-    sel = _FP_SEG (rxOutOfsFp);

-    ofs = _FP_OFF (rxOutOfsFp);

-    printf ("rxOutOfsFp  = %04X:%08X\n", sel,ofs);

-

-    sel = _FP_SEG (rxInOfsFp);

-    ofs = _FP_OFF (rxInOfsFp);

-    printf ("rxInOfsFp   = %04X:%08X\n", sel,ofs);

-

-    printf ("Ready: *rxOutOfsFp = %04X *rxInOfsFp = %04X\n",

-            *rxOutOfsFp, *rxInOfsFp);

-

-    PktQueueBusy (TRUE);

-    printf ("Busy:  *rxOutOfsFp = %04X *rxInOfsFp = %04X\n",

-            *rxOutOfsFp, *rxInOfsFp);

-  }

-#endif

-

-  memset (&pktStat, 0, sizeof(pktStat));  /* clear statistics */

-  PktQueueBusy (TRUE);

-  return (TRUE);

-}

-

-

-/*

- * DPMI functions only for Watcom + DOS4GW extenders

- */

-#if (DOSX & DOS4GW)

-LOCAL DWORD dpmi_get_real_vector (int intr)

-{

-  union REGS r;

-

-  r.x.eax = 0x200;

-  r.x.ebx = (DWORD) intr;

-  int386 (0x31, &r, &r);

-  return ((r.w.cx << 4) + r.w.dx);

-}

-

-LOCAL WORD dpmi_real_malloc (int size, WORD *selector)

-{

-  union REGS r;

-

-  r.x.eax = 0x0100;             /* DPMI allocate DOS memory */

-  r.x.ebx = (size + 15) / 16;   /* Number of paragraphs requested */

-  int386 (0x31, &r, &r);

-  if (r.w.cflag & 1)

-     return (0);

-

-  *selector = r.w.dx;

-  return (r.w.ax);              /* Return segment address */

-}

-

-LOCAL void dpmi_real_free (WORD selector)

-{

-  union REGS r;

-

-  r.x.eax = 0x101;              /* DPMI free DOS memory */

-  r.x.ebx = selector;           /* Selector to free */

-  int386 (0x31, &r, &r);

-}

-#endif

-

-

-#if defined(DOSX) && (DOSX & PHARLAP)

-/*

- * Description:

- *     This routine allocates conventional memory for the specified block

- *     of code (which must be within the first 64K of the protected mode

- *     program segment) and copies the code to it.

- *

- *     The caller should free up the conventional memory block when it

- *     is done with the conventional memory.

- *

- *     NOTE THIS ROUTINE REQUIRES 386|DOS-EXTENDER 3.0 OR LATER.

- *

- * Calling arguments:

- *     start_offs      start of real mode code in program segment

- *     end_offs        1 byte past end of real mode code in program segment

- *     real_basep      returned;  real mode ptr to use as a base for the

- *                        real mode code (eg, to get the real mode FAR

- *                        addr of a function foo(), take

- *                        real_basep + (ULONG) foo).

- *                        This pointer is constructed such that

- *                        offsets within the real mode segment are

- *                        the same as the link-time offsets in the

- *                        protected mode program segment

- *     prot_basep      returned;  prot mode ptr to use as a base for getting

- *                        to the conventional memory, also constructed

- *                        so that adding the prot mode offset of a

- *                        function or variable to the base gets you a

- *                        ptr to the function or variable in the

- *                        conventional memory block.

- *     rmem_adrp       returned;  real mode para addr of allocated

- *                        conventional memory block, to be used to free

- *                        up the conventional memory when done.  DO NOT

- *                        USE THIS TO CONSTRUCT A REAL MODE PTR, USE

- *                        REAL_BASEP INSTEAD SO THAT OFFSETS WORK OUT

- *                        CORRECTLY.

- *

- * Returned values:

- *     0      if error

- *     1      if success

- */

-int RealCopy (ULONG    start_offs,

-              ULONG    end_offs,

-              REALPTR *real_basep,

-              FARPTR  *prot_basep,

-              USHORT  *rmem_adrp)

-{

-  ULONG   rm_base;    /* base real mode para addr for accessing */

-                      /* allocated conventional memory          */

-  UCHAR  *source;     /* source pointer for copy                */

-  FARPTR  destin;     /* destination pointer for copy           */

-  ULONG   len;        /* number of bytes to copy                */

-  ULONG   temp;

-  USHORT  stemp;

-

-  /* First check for valid inputs

-   */

-  if (start_offs >= end_offs || end_offs > 0x10000)

-     return (FALSE);

-

-  /* Round start_offs down to a paragraph (16-byte) boundary so we can set up

-   * the real mode pointer easily. Round up end_offs to make sure we allocate

-   * enough paragraphs

-   */

-  start_offs &= ~15;

-  end_offs = (15 + (end_offs << 4)) >> 4;

-

-  /* Allocate the conventional memory for our real mode code.  Remember to

-   * round byte count UP to 16-byte paragraph size.  We alloc it

-   * above the DOS data buffer so both the DOS data buffer and the appl

-   * conventional mem block can still be resized.

-   *

-   * First just try to alloc it;  if we can't get it, shrink the appl mem

-   * block down to the minimum, try to alloc the memory again, then grow the

-   * appl mem block back to the maximum.  (Don't try to shrink the DOS data

-   * buffer to free conventional memory;  it wouldn't be good for this routine

-   * to have the possible side effect of making file I/O run slower.)

-   */

-  len = ((end_offs - start_offs) + 15) >> 4;

-  if (_dx_real_above(len, rmem_adrp, &stemp) != _DOSE_NONE)

-  {

-    if (_dx_cmem_usage(0, 0, &temp, &temp) != _DOSE_NONE)

-       return (FALSE);

-

-    if (_dx_real_above(len, rmem_adrp, &stemp) != _DOSE_NONE)

-       *rmem_adrp = 0;

-

-    if (_dx_cmem_usage(0, 1, &temp, &temp) != _DOSE_NONE)

-    {

-      if (*rmem_adrp != 0)

-         _dx_real_free (*rmem_adrp);

-      return (FALSE);

-    }

-

-    if (*rmem_adrp == 0)

-       return (FALSE);

-  }

-

-  /* Construct real mode & protected mode pointers to access the allocated

-   * memory.  Note we know start_offs is aligned on a paragraph (16-byte)

-   * boundary, because we rounded it down.

-   *

-   * We make the offsets come out rights by backing off the real mode selector

-   * by start_offs.

-   */

-  rm_base = ((ULONG) *rmem_adrp) - (start_offs >> 4);

-  RP_SET (*real_basep, 0, rm_base);

-  FP_SET (*prot_basep, rm_base << 4, SS_DOSMEM);

-

-  /* Copy the real mode code/data to the allocated memory

-   */

-  source = (UCHAR *) start_offs;

-  destin = *prot_basep;

-  FP_SET (destin, FP_OFF(*prot_basep) + start_offs, FP_SEL(*prot_basep));

-  len = end_offs - start_offs;

-  WriteFarMem (destin, source, len);

-

-  return (TRUE);

-}

-#endif /* DOSX && (DOSX & PHARLAP) */

+/*
+ *  File.........: pktdrvr.c
+ *
+ *  Responsible..: Gisle Vanem,  giva@bgnett.no
+ *
+ *  Created......: 26.Sept 1995
+ *
+ *  Description..: Packet-driver interface for 16/32-bit C :
+ *                 Borland C/C++ 3.0+ small/large model
+ *                 Watcom C/C++ 11+, DOS4GW flat model
+ *                 Metaware HighC 3.1+ and PharLap 386|DosX
+ *                 GNU C/C++ 2.7+ and djgpp 2.x extender
+ *
+ *  References...: PC/TCP Packet driver Specification. rev 1.09
+ *                 FTP Software Inc.
+ *
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <dos.h>
+
+#include "pcap-dos.h"
+#include "pcap-int.h"
+#include "msdos/pktdrvr.h"
+
+#if (DOSX)
+#define NUM_RX_BUF  32      /* # of buffers in Rx FIFO queue */
+#else
+#define NUM_RX_BUF  10
+#endif
+
+#define DIM(x)   (sizeof((x)) / sizeof(x[0]))
+#define PUTS(s)  do {                                           \
+                   if (!pktInfo.quiet)                          \
+                      pktInfo.error ?                           \
+                        printf ("%s: %s\n", s, pktInfo.error) : \
+                        printf ("%s\n", pktInfo.error = s);     \
+                 } while (0)
+
+#if defined(__HIGHC__)
+  extern UINT _mwenv;
+
+#elif defined(__DJGPP__)
+  #include <stddef.h>
+  #include <dpmi.h>
+  #include <go32.h>
+  #include <pc.h>
+  #include <sys/farptr.h>
+
+#elif defined(__WATCOMC__)
+  #include <i86.h>
+  #include <stddef.h>
+  extern char _Extender;
+
+#else
+  extern void far PktReceiver (void);
+#endif
+
+
+#if (DOSX & (DJGPP|DOS4GW))
+  #include <sys/pack_on.h>
+
+  struct DPMI_regs {
+         DWORD  r_di;
+         DWORD  r_si;
+         DWORD  r_bp;
+         DWORD  reserved;
+         DWORD  r_bx;
+         DWORD  r_dx;
+         DWORD  r_cx;
+         DWORD  r_ax;
+         WORD   r_flags;
+         WORD   r_es, r_ds, r_fs, r_gs;
+         WORD   r_ip, r_cs, r_sp, r_ss;
+       };
+
+  /* Data located in a real-mode segment. This becomes far at runtime
+   */
+  typedef struct  {          /* must match data/code in pkt_rx1.s */
+          WORD       _rxOutOfs;
+          WORD       _rxInOfs;
+          DWORD      _pktDrop;
+          BYTE       _pktTemp [20];
+          TX_ELEMENT _pktTxBuf[1];
+          RX_ELEMENT _pktRxBuf[NUM_RX_BUF];
+          WORD       _dummy[2];        /* screenSeg,newInOffset */
+          BYTE       _fanChars[4];
+          WORD       _fanIndex;
+          BYTE       _PktReceiver[15]; /* starts on a paragraph (16byte) */
+        } PktRealStub;
+  #include <sys/pack_off.h>
+
+  static BYTE real_stub_array [] = {
+         #include "pkt_stub.inc"       /* generated opcode array */
+       };
+
+  #define rxOutOfs      offsetof (PktRealStub,_rxOutOfs)
+  #define rxInOfs       offsetof (PktRealStub,_rxInOfs)
+  #define PktReceiver   offsetof (PktRealStub,_PktReceiver [para_skip])
+  #define pktDrop       offsetof (PktRealStub,_pktDrop)
+  #define pktTemp       offsetof (PktRealStub,_pktTemp)
+  #define pktTxBuf      offsetof (PktRealStub,_pktTxBuf)
+  #define FIRST_RX_BUF  offsetof (PktRealStub,_pktRxBuf [0])
+  #define LAST_RX_BUF   offsetof (PktRealStub,_pktRxBuf [NUM_RX_BUF-1])
+
+#else
+  extern WORD       rxOutOfs;    /* offsets into pktRxBuf FIFO queue   */
+  extern WORD       rxInOfs;
+  extern DWORD      pktDrop;     /* # packets dropped in PktReceiver() */
+  extern BYTE       pktRxEnd;    /* marks the end of r-mode code/data  */
+
+  extern RX_ELEMENT pktRxBuf [NUM_RX_BUF];       /* PktDrvr Rx buffers */
+  extern TX_ELEMENT pktTxBuf;                    /* PktDrvr Tx buffer  */
+  extern char       pktTemp[20];                 /* PktDrvr temp area  */
+
+  #define FIRST_RX_BUF (WORD) &pktRxBuf [0]
+  #define LAST_RX_BUF  (WORD) &pktRxBuf [NUM_RX_BUF-1]
+#endif
+
+
+#ifdef __BORLANDC__           /* Use Borland's inline functions */
+  #define memcpy  __memcpy__
+  #define memcmp  __memcmp__
+  #define memset  __memset__
+#endif
+
+
+#if (DOSX & PHARLAP)
+  extern void PktReceiver (void);     /* in pkt_rx0.asm */
+  static int  RealCopy    (ULONG, ULONG, REALPTR*, FARPTR*, USHORT*);
+
+  #undef  FP_SEG
+  #undef  FP_OFF
+  #define FP_OFF(x)     ((WORD)(x))
+  #define FP_SEG(x)     ((WORD)(realBase >> 16))
+  #define DOS_ADDR(s,o) (((DWORD)(s) << 16) + (WORD)(o))
+  #define r_ax          eax
+  #define r_bx          ebx
+  #define r_dx          edx
+  #define r_cx          ecx
+  #define r_si          esi
+  #define r_di          edi
+  #define r_ds          ds
+  #define r_es          es
+  LOCAL FARPTR          protBase;
+  LOCAL REALPTR         realBase;
+  LOCAL WORD            realSeg;   /* DOS para-address of allocated area */
+  LOCAL SWI_REGS        reg;
+
+  static WORD _far *rxOutOfsFp, *rxInOfsFp;
+
+#elif (DOSX & DJGPP)
+  static _go32_dpmi_seginfo rm_mem;
+  static __dpmi_regs        reg;
+  static DWORD              realBase;
+  static int                para_skip = 0;
+
+  #define DOS_ADDR(s,o)     (((WORD)(s) << 4) + (o))
+  #define r_ax              x.ax
+  #define r_bx              x.bx
+  #define r_dx              x.dx
+  #define r_cx              x.cx
+  #define r_si              x.si
+  #define r_di              x.di
+  #define r_ds              x.ds
+  #define r_es              x.es
+
+#elif (DOSX & DOS4GW)
+  LOCAL struct DPMI_regs    reg;
+  LOCAL WORD                rm_base_seg, rm_base_sel;
+  LOCAL DWORD               realBase;
+  LOCAL int                 para_skip = 0;
+
+  LOCAL DWORD dpmi_get_real_vector (int intr);
+  LOCAL WORD  dpmi_real_malloc     (int size, WORD *selector);
+  LOCAL void  dpmi_real_free       (WORD selector);
+  #define DOS_ADDR(s,o) (((DWORD)(s) << 4) + (WORD)(o))
+
+#else              /* real-mode Borland etc. */
+  static struct  {
+         WORD r_ax, r_bx, r_cx, r_dx, r_bp;
+         WORD r_si, r_di, r_ds, r_es, r_flags;
+       } reg;
+#endif
+
+#ifdef __HIGHC__
+  #pragma Alias (pktDrop,    "_pktDrop")
+  #pragma Alias (pktRxBuf,   "_pktRxBuf")
+  #pragma Alias (pktTxBuf,   "_pktTxBuf")
+  #pragma Alias (pktTemp,    "_pktTemp")
+  #pragma Alias (rxOutOfs,   "_rxOutOfs")
+  #pragma Alias (rxInOfs,    "_rxInOfs")
+  #pragma Alias (pktRxEnd,   "_pktRxEnd")
+  #pragma Alias (PktReceiver,"_PktReceiver")
+#endif
+
+
+PUBLIC PKT_STAT    pktStat;    /* statistics for packets    */
+PUBLIC PKT_INFO    pktInfo;    /* packet-driver information */
+
+PUBLIC PKT_RX_MODE receiveMode  = PDRX_DIRECT;
+PUBLIC ETHER       myAddress    = {   0,  0,  0,  0,  0,  0 };
+PUBLIC ETHER       ethBroadcast = { 255,255,255,255,255,255 };
+
+LOCAL  struct {             /* internal statistics */
+       DWORD  tooSmall;     /* size < ETH_MIN */
+       DWORD  tooLarge;     /* size > ETH_MAX */
+       DWORD  badSync;      /* count_1 != count_2 */
+       DWORD  wrongHandle;  /* upcall to wrong handle */
+     } intStat;
+
+/***************************************************************************/
+
+PUBLIC const char *PktGetErrorStr (int errNum)
+{
+  static const char *errStr[] = {
+                    "",
+                    "Invalid handle number",
+                    "No interfaces of specified class found",
+                    "No interfaces of specified type found",
+                    "No interfaces of specified number found",
+                    "Bad packet type specified",
+                    "Interface does not support multicast",
+                    "Packet driver cannot terminate",
+                    "Invalid receiver mode specified",
+                    "Insufficient memory space",
+                    "Type previously accessed, and not released",
+                    "Command out of range, or not implemented",
+                    "Cannot send packet (usually hardware error)",
+                    "Cannot change hardware address ( > 1 handle open)",
+                    "Hardware address has bad length or format",
+                    "Cannot reset interface (more than 1 handle open)",
+                    "Bad Check-sum",
+                    "Bad size",
+                    "Bad sync" ,
+                    "Source hit"
+                  };
+
+  if (errNum < 0 || errNum >= DIM(errStr))
+     return ("Unknown driver error.");
+  return (errStr [errNum]);
+}
+
+/**************************************************************************/
+
+PUBLIC const char *PktGetClassName (WORD class)
+{
+  switch (class)
+  {
+    case PD_ETHER:
+         return ("DIX-Ether");
+    case PD_PRONET10:
+         return ("ProNET-10");
+    case PD_IEEE8025:
+         return ("IEEE 802.5");
+    case PD_OMNINET:
+         return ("OmniNet");
+    case PD_APPLETALK:
+         return ("AppleTalk");
+    case PD_SLIP:
+         return ("SLIP");
+    case PD_STARTLAN:
+         return ("StartLAN");
+    case PD_ARCNET:
+         return ("ArcNet");
+    case PD_AX25:
+         return ("AX.25");
+    case PD_KISS:
+         return ("KISS");
+    case PD_IEEE8023_2:
+         return ("IEEE 802.3 w/802.2 hdr");
+    case PD_FDDI8022:
+         return ("FDDI w/802.2 hdr");
+    case PD_X25:
+         return ("X.25");
+    case PD_LANstar:
+         return ("LANstar");
+    case PD_PPP:
+         return ("PPP");
+    default:
+         return ("unknown");
+  }
+}
+
+/**************************************************************************/
+
+PUBLIC char const *PktRXmodeStr (PKT_RX_MODE mode)
+{
+  static const char *modeStr [] = {
+                    "Receiver turned off",
+                    "Receive only directly addressed packets",
+                    "Receive direct & broadcast packets",
+                    "Receive direct,broadcast and limited multicast packets",
+                    "Receive direct,broadcast and all multicast packets",
+                    "Receive all packets (promiscuouos mode)"
+                  };
+
+  if (mode > DIM(modeStr))
+     return ("??");
+  return (modeStr [mode-1]);
+}
+
+/**************************************************************************/
+
+LOCAL __inline BOOL PktInterrupt (void)
+{
+  BOOL okay;
+
+#if (DOSX & PHARLAP)
+  _dx_real_int ((UINT)pktInfo.intr, &reg);
+  okay = ((reg.flags & 1) == 0);  /* OK if carry clear */
+
+#elif (DOSX & DJGPP)
+  __dpmi_int ((int)pktInfo.intr, &reg);
+  okay = ((reg.x.flags & 1) == 0);
+
+#elif (DOSX & DOS4GW)
+  union  REGS  r;
+  struct SREGS s;
+
+  memset (&r, 0, sizeof(r));
+  segread (&s);
+  r.w.ax  = 0x300;
+  r.x.ebx = pktInfo.intr;
+  r.w.cx  = 0;
+  s.es    = FP_SEG (&reg);
+  r.x.edi = FP_OFF (&reg);
+  reg.r_flags = 0;
+  reg.r_ss = reg.r_sp = 0;     /* DPMI host provides stack */
+
+  int386x (0x31, &r, &r, &s);
+  okay = (!r.w.cflag);
+
+#else
+  reg.r_flags = 0;
+  intr (pktInfo.intr, (struct REGPACK*)&reg);
+  okay = ((reg.r_flags & 1) == 0);
+#endif
+
+  if (okay)
+       pktInfo.error = NULL;
+  else pktInfo.error = PktGetErrorStr (reg.r_dx >> 8);
+  return (okay);
+}
+
+/**************************************************************************/
+
+/*
+ * Search for packet driver at interrupt 60h through 80h. If ASCIIZ
+ * string "PKT DRVR" found at offset 3 in the interrupt handler, return
+ * interrupt number, else return zero in pktInfo.intr
+ */
+PUBLIC BOOL PktSearchDriver (void)
+{
+  BYTE intr  = 0x20;
+  BOOL found = FALSE;
+
+  while (!found && intr < 0xFF)
+  {
+    static char str[12];                 /* 3 + strlen("PKT DRVR") */
+    static char pktStr[9] = "PKT DRVR";  /* ASCIIZ string at ofs 3 */
+    DWORD  rp;                           /* in interrupt  routine  */
+
+#if (DOSX & PHARLAP)
+    _dx_rmiv_get (intr, &rp);
+    ReadRealMem (&str, (REALPTR)rp, sizeof(str));
+
+#elif (DOSX & DJGPP)
+    __dpmi_raddr realAdr;
+    __dpmi_get_real_mode_interrupt_vector (intr, &realAdr);
+    rp = (realAdr.segment << 4) + realAdr.offset16;
+    dosmemget (rp, sizeof(str), &str);
+
+#elif (DOSX & DOS4GW)
+    rp = dpmi_get_real_vector (intr);
+    memcpy (&str, (void*)rp, sizeof(str));
+
+#else
+    _fmemcpy (&str, getvect(intr), sizeof(str));
+#endif
+
+    found = memcmp (&str[3],&pktStr,sizeof(pktStr)) == 0;
+    intr++;
+  }
+  pktInfo.intr = (found ? intr-1 : 0);
+  return (found);
+}
+
+
+/**************************************************************************/
+
+static BOOL PktSetAccess (void)
+{
+  reg.r_ax = 0x0200 + pktInfo.class;
+  reg.r_bx = 0xFFFF;
+  reg.r_dx = 0;
+  reg.r_cx = 0;
+
+#if (DOSX & PHARLAP)
+  reg.ds  = 0;
+  reg.esi = 0;
+  reg.es  = RP_SEG (realBase);
+  reg.edi = (WORD) &PktReceiver;
+
+#elif (DOSX & DJGPP)
+  reg.x.ds = 0;
+  reg.x.si = 0;
+  reg.x.es = rm_mem.rm_segment;
+  reg.x.di = PktReceiver;
+
+#elif (DOSX & DOS4GW)
+  reg.r_ds = 0;
+  reg.r_si = 0;
+  reg.r_es = rm_base_seg;
+  reg.r_di = PktReceiver;
+
+#else
+  reg.r_ds = 0;
+  reg.r_si = 0;
+  reg.r_es = FP_SEG (&PktReceiver);
+  reg.r_di = FP_OFF (&PktReceiver);
+#endif
+
+  if (!PktInterrupt())
+     return (FALSE);
+
+  pktInfo.handle = reg.r_ax;
+  return (TRUE);
+}
+
+/**************************************************************************/
+
+PUBLIC BOOL PktReleaseHandle (WORD handle)
+{
+  reg.r_ax = 0x0300;
+  reg.r_bx = handle;
+  return PktInterrupt();
+}
+
+/**************************************************************************/
+
+PUBLIC BOOL PktTransmit (const void *eth, int len)
+{
+  if (len > ETH_MTU)
+     return (FALSE);
+
+  reg.r_ax = 0x0400;             /* Function 4, send pkt */
+  reg.r_cx = len;                /* total size of frame  */
+
+#if (DOSX & DJGPP)
+  dosmemput (eth, len, realBase+pktTxBuf);
+  reg.x.ds = rm_mem.rm_segment;  /* DOS data segment and */
+  reg.x.si = pktTxBuf;           /* DOS offset to buffer */
+
+#elif (DOSX & DOS4GW)
+  memcpy ((void*)(realBase+pktTxBuf), eth, len);
+  reg.r_ds = rm_base_seg;
+  reg.r_si = pktTxBuf;
+
+#elif (DOSX & PHARLAP)
+  memcpy (&pktTxBuf, eth, len);
+  reg.r_ds = FP_SEG (&pktTxBuf);
+  reg.r_si = FP_OFF (&pktTxBuf);
+
+#else
+  reg.r_ds = FP_SEG (eth);
+  reg.r_si = FP_OFF (eth);
+#endif
+
+  return PktInterrupt();
+}
+
+/**************************************************************************/
+
+#if (DOSX & (DJGPP|DOS4GW))
+LOCAL __inline BOOL CheckElement (RX_ELEMENT *rx)
+#else
+LOCAL __inline BOOL CheckElement (RX_ELEMENT _far *rx)
+#endif
+{
+  WORD count_1, count_2;
+
+  /*
+   * We got an upcall to the same RMCB with wrong handle.
+   * This can happen if we failed to release handle at program exit
+   */
+  if (rx->handle != pktInfo.handle)
+  {
+    pktInfo.error = "Wrong handle";
+    intStat.wrongHandle++;
+    PktReleaseHandle (rx->handle);
+    return (FALSE);
+  }
+  count_1 = rx->firstCount;
+  count_2 = rx->secondCount;
+
+  if (count_1 != count_2)
+  {
+    pktInfo.error = "Bad sync";
+    intStat.badSync++;
+    return (FALSE);
+  }
+  if (count_1 > ETH_MAX)
+  {
+    pktInfo.error = "Large esize";
+    intStat.tooLarge++;
+    return (FALSE);
+  }
+#if 0
+  if (count_1 < ETH_MIN)
+  {
+    pktInfo.error = "Small esize";
+    intStat.tooSmall++;
+    return (FALSE);
+  }
+#endif
+  return (TRUE);
+}
+
+/**************************************************************************/
+
+PUBLIC BOOL PktTerminHandle (WORD handle)
+{
+  reg.r_ax = 0x0500;
+  reg.r_bx = handle;
+  return PktInterrupt();
+}
+
+/**************************************************************************/
+
+PUBLIC BOOL PktResetInterface (WORD handle)
+{
+  reg.r_ax = 0x0700;
+  reg.r_bx = handle;
+  return PktInterrupt();
+}
+
+/**************************************************************************/
+
+PUBLIC BOOL PktSetReceiverMode (PKT_RX_MODE mode)
+{
+  if (pktInfo.class == PD_SLIP || pktInfo.class == PD_PPP)
+     return (TRUE);
+
+  reg.r_ax = 0x1400;
+  reg.r_bx = pktInfo.handle;
+  reg.r_cx = (WORD)mode;
+
+  if (!PktInterrupt())
+     return (FALSE);
+
+  receiveMode = mode;
+  return (TRUE);
+}
+
+/**************************************************************************/
+
+PUBLIC BOOL PktGetReceiverMode (PKT_RX_MODE *mode)
+{
+  reg.r_ax = 0x1500;
+  reg.r_bx = pktInfo.handle;
+
+  if (!PktInterrupt())
+     return (FALSE);
+
+  *mode = reg.r_ax;
+  return (TRUE);
+}
+
+/**************************************************************************/
+
+static PKT_STAT initialStat;         /* statistics at startup */
+static BOOL     resetStat = FALSE;   /* statistics reset ? */
+
+PUBLIC BOOL PktGetStatistics (WORD handle)
+{
+  reg.r_ax = 0x1800;
+  reg.r_bx = handle;
+
+  if (!PktInterrupt())
+     return (FALSE);
+
+#if (DOSX & PHARLAP)
+  ReadRealMem (&pktStat, DOS_ADDR(reg.ds,reg.esi), sizeof(pktStat));
+
+#elif (DOSX & DJGPP)
+  dosmemget (DOS_ADDR(reg.x.ds,reg.x.si), sizeof(pktStat), &pktStat);
+
+#elif (DOSX & DOS4GW)
+  memcpy (&pktStat, (void*)DOS_ADDR(reg.r_ds,reg.r_si), sizeof(pktStat));
+
+#else
+  _fmemcpy (&pktStat, MK_FP(reg.r_ds,reg.r_si), sizeof(pktStat));
+#endif
+
+  return (TRUE);
+}
+
+/**************************************************************************/
+
+PUBLIC BOOL PktSessStatistics (WORD handle)
+{
+  if (!PktGetStatistics(pktInfo.handle))
+     return (FALSE);
+
+  if (resetStat)
+  {
+    pktStat.inPackets  -= initialStat.inPackets;
+    pktStat.outPackets -= initialStat.outPackets;
+    pktStat.inBytes    -= initialStat.inBytes;
+    pktStat.outBytes   -= initialStat.outBytes;
+    pktStat.inErrors   -= initialStat.inErrors;
+    pktStat.outErrors  -= initialStat.outErrors;
+    pktStat.outErrors  -= initialStat.outErrors;
+    pktStat.lost       -= initialStat.lost;
+  }
+  return (TRUE);
+}
+
+/**************************************************************************/
+
+PUBLIC BOOL PktResetStatistics (WORD handle)
+{
+  if (!PktGetStatistics(pktInfo.handle))
+     return (FALSE);
+
+  memcpy (&initialStat, &pktStat, sizeof(initialStat));
+  resetStat = TRUE;
+  return (TRUE);
+}
+
+/**************************************************************************/
+
+PUBLIC BOOL PktGetAddress (ETHER *addr)
+{
+  reg.r_ax = 0x0600;
+  reg.r_bx = pktInfo.handle;
+  reg.r_cx = sizeof (*addr);
+
+#if (DOSX & DJGPP)
+  reg.x.es = rm_mem.rm_segment;
+  reg.x.di = pktTemp;
+#elif (DOSX & DOS4GW)
+  reg.r_es = rm_base_seg;
+  reg.r_di = pktTemp;
+#else
+  reg.r_es = FP_SEG (&pktTemp);
+  reg.r_di = FP_OFF (&pktTemp);  /* ES:DI = address for result */
+#endif
+
+  if (!PktInterrupt())
+     return (FALSE);
+
+#if (DOSX & PHARLAP)
+  ReadRealMem (addr, realBase + (WORD)&pktTemp, sizeof(*addr));
+
+#elif (DOSX & DJGPP)
+  dosmemget (realBase+pktTemp, sizeof(*addr), addr);
+
+#elif (DOSX & DOS4GW)
+  memcpy (addr, (void*)(realBase+pktTemp), sizeof(*addr));
+
+#else
+  memcpy ((void*)addr, &pktTemp, sizeof(*addr));
+#endif
+
+  return (TRUE);
+}
+
+/**************************************************************************/
+
+PUBLIC BOOL PktSetAddress (const ETHER *addr)
+{
+  /* copy addr to real-mode scrath area */
+
+#if (DOSX & PHARLAP)
+  WriteRealMem (realBase + (WORD)&pktTemp, (void*)addr, sizeof(*addr));
+
+#elif (DOSX & DJGPP)
+  dosmemput (addr, sizeof(*addr), realBase+pktTemp);
+
+#elif (DOSX & DOS4GW)
+  memcpy ((void*)(realBase+pktTemp), addr, sizeof(*addr));
+
+#else
+  memcpy (&pktTemp, (void*)addr, sizeof(*addr));
+#endif
+
+  reg.r_ax = 0x1900;
+  reg.r_cx = sizeof (*addr);      /* address length       */
+
+#if (DOSX & DJGPP)
+  reg.x.es = rm_mem.rm_segment;   /* DOS offset to param  */
+  reg.x.di = pktTemp;             /* DOS segment to param */
+#elif (DOSX & DOS4GW)
+  reg.r_es = rm_base_seg;
+  reg.r_di = pktTemp;
+#else
+  reg.r_es = FP_SEG (&pktTemp);
+  reg.r_di = FP_OFF (&pktTemp);
+#endif
+
+  return PktInterrupt();
+}
+
+/**************************************************************************/
+
+PUBLIC BOOL PktGetDriverInfo (void)
+{
+  pktInfo.majVer = 0;
+  pktInfo.minVer = 0;
+  memset (&pktInfo.name, 0, sizeof(pktInfo.name));
+  reg.r_ax = 0x01FF;
+  reg.r_bx = 0;
+
+  if (!PktInterrupt())
+     return (FALSE);
+
+  pktInfo.number = reg.r_cx & 0xFF;
+  pktInfo.class  = reg.r_cx >> 8;
+#if 0
+  pktInfo.minVer = reg.r_bx % 10;
+  pktInfo.majVer = reg.r_bx / 10;
+#else
+  pktInfo.majVer = reg.r_bx;  // !!
+#endif
+  pktInfo.funcs  = reg.r_ax & 0xFF;
+  pktInfo.type   = reg.r_dx & 0xFF;
+
+#if (DOSX & PHARLAP)
+  ReadRealMem (&pktInfo.name, DOS_ADDR(reg.ds,reg.esi), sizeof(pktInfo.name));
+
+#elif (DOSX & DJGPP)
+  dosmemget (DOS_ADDR(reg.x.ds,reg.x.si), sizeof(pktInfo.name), &pktInfo.name);
+
+#elif (DOSX & DOS4GW)
+  memcpy (&pktInfo.name, (void*)DOS_ADDR(reg.r_ds,reg.r_si), sizeof(pktInfo.name));
+
+#else
+  _fmemcpy (&pktInfo.name, MK_FP(reg.r_ds,reg.r_si), sizeof(pktInfo.name));
+#endif
+  return (TRUE);
+}
+
+/**************************************************************************/
+
+PUBLIC BOOL PktGetDriverParam (void)
+{
+  reg.r_ax = 0x0A00;
+
+  if (!PktInterrupt())
+     return (FALSE);
+
+#if (DOSX & PHARLAP)
+  ReadRealMem (&pktInfo.majVer, DOS_ADDR(reg.es,reg.edi), PKT_PARAM_SIZE);
+
+#elif (DOSX & DJGPP)
+  dosmemget (DOS_ADDR(reg.x.es,reg.x.di), PKT_PARAM_SIZE, &pktInfo.majVer);
+
+#elif (DOSX & DOS4GW)
+  memcpy (&pktInfo.majVer, (void*)DOS_ADDR(reg.r_es,reg.r_di), PKT_PARAM_SIZE);
+
+#else
+  _fmemcpy (&pktInfo.majVer, MK_FP(reg.r_es,reg.r_di), PKT_PARAM_SIZE);
+#endif
+  return (TRUE);
+}
+
+/**************************************************************************/
+
+#if (DOSX & PHARLAP)
+  PUBLIC int PktReceive (BYTE *buf, int max)
+  {
+    WORD inOfs  = *rxInOfsFp;
+    WORD outOfs = *rxOutOfsFp;
+
+    if (outOfs != inOfs)
+    {
+      RX_ELEMENT _far *head = (RX_ELEMENT _far*)(protBase+outOfs);
+      int size, len = max;
+
+      if (CheckElement(head))
+      {
+        size = min (head->firstCount, sizeof(RX_ELEMENT));
+        len  = min (size, max);
+        _fmemcpy (buf, &head->destin, len);
+      }
+      else
+        size = -1;
+
+      outOfs += sizeof (RX_ELEMENT);
+      if (outOfs > LAST_RX_BUF)
+          outOfs = FIRST_RX_BUF;
+      *rxOutOfsFp = outOfs;
+      return (size);
+    }
+    return (0);
+  }
+
+  PUBLIC void PktQueueBusy (BOOL busy)
+  {
+    *rxOutOfsFp = busy ? (*rxInOfsFp + sizeof(RX_ELEMENT)) : *rxInOfsFp;
+    if (*rxOutOfsFp > LAST_RX_BUF)
+        *rxOutOfsFp = FIRST_RX_BUF;
+    *(DWORD _far*)(protBase + (WORD)&pktDrop) = 0;
+  }
+
+  PUBLIC WORD PktBuffersUsed (void)
+  {
+    WORD inOfs  = *rxInOfsFp;
+    WORD outOfs = *rxOutOfsFp;
+
+    if (inOfs >= outOfs)
+       return (inOfs - outOfs) / sizeof(RX_ELEMENT);
+    return (NUM_RX_BUF - (outOfs - inOfs) / sizeof(RX_ELEMENT));
+  }
+
+  PUBLIC DWORD PktRxDropped (void)
+  {
+    return (*(DWORD _far*)(protBase + (WORD)&pktDrop));
+  }
+
+#elif (DOSX & DJGPP)
+  PUBLIC int PktReceive (BYTE *buf, int max)
+  {
+    WORD ofs = _farpeekw (_dos_ds, realBase+rxOutOfs);
+
+    if (ofs != _farpeekw (_dos_ds, realBase+rxInOfs))
+    {
+      RX_ELEMENT head;
+      int  size, len = max;
+
+      head.firstCount  = _farpeekw (_dos_ds, realBase+ofs);
+      head.secondCount = _farpeekw (_dos_ds, realBase+ofs+2);
+      head.handle      = _farpeekw (_dos_ds, realBase+ofs+4);
+
+      if (CheckElement(&head))
+      {
+        size = min (head.firstCount, sizeof(RX_ELEMENT));
+        len  = min (size, max);
+        dosmemget (realBase+ofs+6, len, buf);
+      }
+      else
+        size = -1;
+
+      ofs += sizeof (RX_ELEMENT);
+      if (ofs > LAST_RX_BUF)
+           _farpokew (_dos_ds, realBase+rxOutOfs, FIRST_RX_BUF);
+      else _farpokew (_dos_ds, realBase+rxOutOfs, ofs);
+      return (size);
+    }
+    return (0);
+  }
+
+  PUBLIC void PktQueueBusy (BOOL busy)
+  {
+    WORD ofs;
+
+    disable();
+    ofs = _farpeekw (_dos_ds, realBase+rxInOfs);
+    if (busy)
+       ofs += sizeof (RX_ELEMENT);
+
+    if (ofs > LAST_RX_BUF)
+         _farpokew (_dos_ds, realBase+rxOutOfs, FIRST_RX_BUF);
+    else _farpokew (_dos_ds, realBase+rxOutOfs, ofs);
+    _farpokel (_dos_ds, realBase+pktDrop, 0UL);
+    enable();
+  }
+
+  PUBLIC WORD PktBuffersUsed (void)
+  {
+    WORD inOfs, outOfs;
+
+    disable();
+    inOfs  = _farpeekw (_dos_ds, realBase+rxInOfs);
+    outOfs = _farpeekw (_dos_ds, realBase+rxOutOfs);
+    enable();
+    if (inOfs >= outOfs)
+       return (inOfs - outOfs) / sizeof(RX_ELEMENT);
+    return (NUM_RX_BUF - (outOfs - inOfs) / sizeof(RX_ELEMENT));
+  }
+
+  PUBLIC DWORD PktRxDropped (void)
+  {
+    return _farpeekl (_dos_ds, realBase+pktDrop);
+  }
+
+#elif (DOSX & DOS4GW)
+  PUBLIC int PktReceive (BYTE *buf, int max)
+  {
+    WORD ofs = *(WORD*) (realBase+rxOutOfs);
+
+    if (ofs != *(WORD*) (realBase+rxInOfs))
+    {
+      RX_ELEMENT head;
+      int  size, len = max;
+
+      head.firstCount  = *(WORD*) (realBase+ofs);
+      head.secondCount = *(WORD*) (realBase+ofs+2);
+      head.handle      = *(WORD*) (realBase+ofs+4);
+
+      if (CheckElement(&head))
+      {
+        size = min (head.firstCount, sizeof(RX_ELEMENT));
+        len  = min (size, max);
+        memcpy (buf, (const void*)(realBase+ofs+6), len);
+      }
+      else
+        size = -1;
+
+      ofs += sizeof (RX_ELEMENT);
+      if (ofs > LAST_RX_BUF)
+           *(WORD*) (realBase+rxOutOfs) = FIRST_RX_BUF;
+      else *(WORD*) (realBase+rxOutOfs) = ofs;
+      return (size);
+    }
+    return (0);
+  }
+
+  PUBLIC void PktQueueBusy (BOOL busy)
+  {
+    WORD ofs;
+
+    _disable();
+    ofs = *(WORD*) (realBase+rxInOfs);
+    if (busy)
+       ofs += sizeof (RX_ELEMENT);
+
+    if (ofs > LAST_RX_BUF)
+         *(WORD*) (realBase+rxOutOfs) = FIRST_RX_BUF;
+    else *(WORD*) (realBase+rxOutOfs) = ofs;
+    *(DWORD*) (realBase+pktDrop) = 0UL;
+    _enable();
+  }
+
+  PUBLIC WORD PktBuffersUsed (void)
+  {
+    WORD inOfs, outOfs;
+
+    _disable();
+    inOfs  = *(WORD*) (realBase+rxInOfs);
+    outOfs = *(WORD*) (realBase+rxOutOfs);
+    _enable();
+    if (inOfs >= outOfs)
+       return (inOfs - outOfs) / sizeof(RX_ELEMENT);
+    return (NUM_RX_BUF - (outOfs - inOfs) / sizeof(RX_ELEMENT));
+  }
+
+  PUBLIC DWORD PktRxDropped (void)
+  {
+    return *(DWORD*) (realBase+pktDrop);
+  }
+
+#else     /* real-mode small/large model */
+
+  PUBLIC int PktReceive (BYTE *buf, int max)
+  {
+    if (rxOutOfs != rxInOfs)
+    {
+      RX_ELEMENT far *head = (RX_ELEMENT far*) MK_FP (_DS,rxOutOfs);
+      int  size, len = max;
+
+      if (CheckElement(head))
+      {
+        size = min (head->firstCount, sizeof(RX_ELEMENT));
+        len  = min (size, max);
+        _fmemcpy (buf, &head->destin, len);
+      }
+      else
+        size = -1;
+
+      rxOutOfs += sizeof (RX_ELEMENT);
+      if (rxOutOfs > LAST_RX_BUF)
+          rxOutOfs = FIRST_RX_BUF;
+      return (size);
+    }
+    return (0);
+  }
+
+  PUBLIC void PktQueueBusy (BOOL busy)
+  {
+    rxOutOfs = busy ? (rxInOfs + sizeof(RX_ELEMENT)) : rxInOfs;
+    if (rxOutOfs > LAST_RX_BUF)
+        rxOutOfs = FIRST_RX_BUF;
+    pktDrop = 0L;
+  }
+
+  PUBLIC WORD PktBuffersUsed (void)
+  {
+    WORD inOfs  = rxInOfs;
+    WORD outOfs = rxOutOfs;
+
+    if (inOfs >= outOfs)
+       return ((inOfs - outOfs) / sizeof(RX_ELEMENT));
+    return (NUM_RX_BUF - (outOfs - inOfs) / sizeof(RX_ELEMENT));
+  }
+
+  PUBLIC DWORD PktRxDropped (void)
+  {
+    return (pktDrop);
+  }
+#endif
+
+/**************************************************************************/
+
+LOCAL __inline void PktFreeMem (void)
+{
+#if (DOSX & PHARLAP)
+  if (realSeg)
+  {
+    _dx_real_free (realSeg);
+    realSeg = 0;
+  }
+#elif (DOSX & DJGPP)
+  if (rm_mem.rm_segment)
+  {
+    unsigned ofs;  /* clear the DOS-mem to prevent further upcalls */
+
+    for (ofs = 0; ofs < 16 * rm_mem.size / 4; ofs += 4)
+       _farpokel (_dos_ds, realBase + ofs, 0);
+    _go32_dpmi_free_dos_memory (&rm_mem);
+    rm_mem.rm_segment = 0;
+  }
+#elif (DOSX & DOS4GW)
+  if (rm_base_sel)
+  {
+    dpmi_real_free (rm_base_sel);
+    rm_base_sel = 0;
+  }
+#endif
+}
+
+/**************************************************************************/
+
+PUBLIC BOOL PktExitDriver (void)
+{
+  if (pktInfo.handle)
+  {
+    if (!PktSetReceiverMode(PDRX_BROADCAST))
+       PUTS ("Error restoring receiver mode.");
+
+    if (!PktReleaseHandle(pktInfo.handle))
+       PUTS ("Error releasing PKT-DRVR handle.");
+
+    PktFreeMem();
+    pktInfo.handle = 0;
+  }
+
+  if (pcap_pkt_debug >= 1)
+     printf ("Internal stats: too-small %lu, too-large %lu, bad-sync %lu, "
+             "wrong-handle %lu\n",
+             intStat.tooSmall, intStat.tooLarge,
+             intStat.badSync, intStat.wrongHandle);
+  return (TRUE);
+}
+
+#if (DOSX & (DJGPP|DOS4GW))
+static void dump_pkt_stub (void)
+{
+  int i;
+
+  fprintf (stderr, "PktReceiver %lu, pkt_stub[PktReceiver] =\n",
+           PktReceiver);
+  for (i = 0; i < 15; i++)
+      fprintf (stderr, "%02X, ", real_stub_array[i+PktReceiver]);
+  fputs ("\n", stderr);
+}
+#endif
+
+/*
+ * Front end initialization routine
+ */
+PUBLIC BOOL PktInitDriver (PKT_RX_MODE mode)
+{
+  PKT_RX_MODE rxMode;
+  BOOL   writeInfo = (pcap_pkt_debug >= 3);
+
+  pktInfo.quiet = (pcap_pkt_debug < 3);
+
+#if (DOSX & PHARLAP) && defined(__HIGHC__)
+  if (_mwenv != 2)
+  {
+    fprintf (stderr, "Only Pharlap DOS extender supported.\n");
+    return (FALSE);
+  }
+#endif
+
+#if (DOSX & PHARLAP) && defined(__WATCOMC__)
+  if (_Extender != 1)
+  {
+    fprintf (stderr, "Only DOS4GW style extenders supported.\n");
+    return (FALSE);
+  }
+#endif
+
+  if (!PktSearchDriver())
+  {
+    PUTS ("Packet driver not found.");
+    PktFreeMem();
+    return (FALSE);
+  }
+
+  if (!PktGetDriverInfo())
+  {
+    PUTS ("Error getting pkt-drvr information.");
+    PktFreeMem();
+    return (FALSE);
+  }
+
+#if (DOSX & PHARLAP)
+  if (RealCopy((ULONG)&rxOutOfs, (ULONG)&pktRxEnd,
+               &realBase, &protBase, (USHORT*)&realSeg))
+  {
+    rxOutOfsFp  = (WORD _far *) (protBase + (WORD) &rxOutOfs);
+    rxInOfsFp   = (WORD _far *) (protBase + (WORD) &rxInOfs);
+    *rxOutOfsFp = FIRST_RX_BUF;
+    *rxInOfsFp  = FIRST_RX_BUF;
+  }
+  else
+  {
+    PUTS ("Cannot allocate real-mode stub.");
+    return (FALSE);
+  }
+
+#elif (DOSX & (DJGPP|DOS4GW))
+  if (sizeof(real_stub_array) > 0xFFFF)
+  {
+    fprintf (stderr, "`real_stub_array[]' too big.\n");
+    return (FALSE);
+  }
+#if (DOSX & DJGPP)
+  rm_mem.size = (sizeof(real_stub_array) + 15) / 16;
+
+  if (_go32_dpmi_allocate_dos_memory(&rm_mem) || rm_mem.rm_offset != 0)
+  {
+    PUTS ("real-mode init failed.");
+    return (FALSE);
+  }
+  realBase = (rm_mem.rm_segment << 4);
+  dosmemput (&real_stub_array, sizeof(real_stub_array), realBase);
+  _farpokel (_dos_ds, realBase+rxOutOfs, FIRST_RX_BUF);
+  _farpokel (_dos_ds, realBase+rxInOfs,  FIRST_RX_BUF);
+
+#elif (DOSX & DOS4GW)
+  rm_base_seg = dpmi_real_malloc (sizeof(real_stub_array), &rm_base_sel);
+  if (!rm_base_seg)
+  {
+    PUTS ("real-mode init failed.");
+    return (FALSE);
+  }
+  realBase = (rm_base_seg << 4);
+  memcpy ((void*)realBase, &real_stub_array, sizeof(real_stub_array));
+  *(WORD*) (realBase+rxOutOfs) = FIRST_RX_BUF;
+  *(WORD*) (realBase+rxInOfs)  = FIRST_RX_BUF;
+
+#endif
+  {
+    int pushf = PktReceiver;
+
+    while (real_stub_array[pushf++] != 0x9C &&    /* pushf */
+           real_stub_array[pushf]   != 0xFA)      /* cli   */
+    {
+      if (++para_skip > 16)
+      {
+        fprintf (stderr, "Something wrong with `pkt_stub.inc'.\n");
+        para_skip = 0;
+        dump_pkt_stub();
+        return (FALSE);
+      }
+    }
+    if (*(WORD*)(real_stub_array + offsetof(PktRealStub,_dummy)) != 0xB800)
+    {
+      fprintf (stderr, "`real_stub_array[]' is misaligned.\n");
+      return (FALSE);
+    }
+  }
+
+  if (pcap_pkt_debug > 2)
+      dump_pkt_stub();
+
+#else
+  rxOutOfs = FIRST_RX_BUF;
+  rxInOfs  = FIRST_RX_BUF;
+#endif
+
+  if (!PktSetAccess())
+  {
+    PUTS ("Error setting pkt-drvr access.");
+    PktFreeMem();
+    return (FALSE);
+  }
+
+  if (!PktGetAddress(&myAddress))
+  {
+    PUTS ("Error fetching adapter address.");
+    PktFreeMem();
+    return (FALSE);
+  }
+
+  if (!PktSetReceiverMode(mode))
+  {
+    PUTS ("Error setting receiver mode.");
+    PktFreeMem();
+    return (FALSE);
+  }
+
+  if (!PktGetReceiverMode(&rxMode))
+  {
+    PUTS ("Error getting receiver mode.");
+    PktFreeMem();
+    return (FALSE);
+  }
+
+  if (writeInfo)
+     printf ("Pkt-driver information:\n"
+             "  Version  : %d.%d\n"
+             "  Name     : %.15s\n"
+             "  Class    : %u (%s)\n"
+             "  Type     : %u\n"
+             "  Number   : %u\n"
+             "  Funcs    : %u\n"
+             "  Intr     : %Xh\n"
+             "  Handle   : %u\n"
+             "  Extended : %s\n"
+             "  Hi-perf  : %s\n"
+             "  RX mode  : %s\n"
+             "  Eth-addr : %02X:%02X:%02X:%02X:%02X:%02X\n",
+
+             pktInfo.majVer, pktInfo.minVer, pktInfo.name,
+             pktInfo.class,  PktGetClassName(pktInfo.class),
+             pktInfo.type,   pktInfo.number,
+             pktInfo.funcs,  pktInfo.intr,   pktInfo.handle,
+             pktInfo.funcs == 2 || pktInfo.funcs == 6 ? "Yes" : "No",
+             pktInfo.funcs == 5 || pktInfo.funcs == 6 ? "Yes" : "No",
+             PktRXmodeStr(rxMode),
+             myAddress[0], myAddress[1], myAddress[2],
+             myAddress[3], myAddress[4], myAddress[5]);
+
+#if defined(DEBUG) && (DOSX & PHARLAP)
+  if (writeInfo)
+  {
+    DWORD    rAdr = realBase + (WORD)&PktReceiver;
+    unsigned sel, ofs;
+
+    printf ("\nReceiver at   %04X:%04X\n", RP_SEG(rAdr),    RP_OFF(rAdr));
+    printf ("Realbase    = %04X:%04X\n",   RP_SEG(realBase),RP_OFF(realBase));
+
+    sel = _FP_SEG (protBase);
+    ofs = _FP_OFF (protBase);
+    printf ("Protbase    = %04X:%08X\n", sel,ofs);
+    printf ("RealSeg     = %04X\n", realSeg);
+
+    sel = _FP_SEG (rxOutOfsFp);
+    ofs = _FP_OFF (rxOutOfsFp);
+    printf ("rxOutOfsFp  = %04X:%08X\n", sel,ofs);
+
+    sel = _FP_SEG (rxInOfsFp);
+    ofs = _FP_OFF (rxInOfsFp);
+    printf ("rxInOfsFp   = %04X:%08X\n", sel,ofs);
+
+    printf ("Ready: *rxOutOfsFp = %04X *rxInOfsFp = %04X\n",
+            *rxOutOfsFp, *rxInOfsFp);
+
+    PktQueueBusy (TRUE);
+    printf ("Busy:  *rxOutOfsFp = %04X *rxInOfsFp = %04X\n",
+            *rxOutOfsFp, *rxInOfsFp);
+  }
+#endif
+
+  memset (&pktStat, 0, sizeof(pktStat));  /* clear statistics */
+  PktQueueBusy (TRUE);
+  return (TRUE);
+}
+
+
+/*
+ * DPMI functions only for Watcom + DOS4GW extenders
+ */
+#if (DOSX & DOS4GW)
+LOCAL DWORD dpmi_get_real_vector (int intr)
+{
+  union REGS r;
+
+  r.x.eax = 0x200;
+  r.x.ebx = (DWORD) intr;
+  int386 (0x31, &r, &r);
+  return ((r.w.cx << 4) + r.w.dx);
+}
+
+LOCAL WORD dpmi_real_malloc (int size, WORD *selector)
+{
+  union REGS r;
+
+  r.x.eax = 0x0100;             /* DPMI allocate DOS memory */
+  r.x.ebx = (size + 15) / 16;   /* Number of paragraphs requested */
+  int386 (0x31, &r, &r);
+  if (r.w.cflag & 1)
+     return (0);
+
+  *selector = r.w.dx;
+  return (r.w.ax);              /* Return segment address */
+}
+
+LOCAL void dpmi_real_free (WORD selector)
+{
+  union REGS r;
+
+  r.x.eax = 0x101;              /* DPMI free DOS memory */
+  r.x.ebx = selector;           /* Selector to free */
+  int386 (0x31, &r, &r);
+}
+#endif
+
+
+#if defined(DOSX) && (DOSX & PHARLAP)
+/*
+ * Description:
+ *     This routine allocates conventional memory for the specified block
+ *     of code (which must be within the first 64K of the protected mode
+ *     program segment) and copies the code to it.
+ *
+ *     The caller should free up the conventional memory block when it
+ *     is done with the conventional memory.
+ *
+ *     NOTE THIS ROUTINE REQUIRES 386|DOS-EXTENDER 3.0 OR LATER.
+ *
+ * Calling arguments:
+ *     start_offs      start of real mode code in program segment
+ *     end_offs        1 byte past end of real mode code in program segment
+ *     real_basep      returned;  real mode ptr to use as a base for the
+ *                        real mode code (eg, to get the real mode FAR
+ *                        addr of a function foo(), take
+ *                        real_basep + (ULONG) foo).
+ *                        This pointer is constructed such that
+ *                        offsets within the real mode segment are
+ *                        the same as the link-time offsets in the
+ *                        protected mode program segment
+ *     prot_basep      returned;  prot mode ptr to use as a base for getting
+ *                        to the conventional memory, also constructed
+ *                        so that adding the prot mode offset of a
+ *                        function or variable to the base gets you a
+ *                        ptr to the function or variable in the
+ *                        conventional memory block.
+ *     rmem_adrp       returned;  real mode para addr of allocated
+ *                        conventional memory block, to be used to free
+ *                        up the conventional memory when done.  DO NOT
+ *                        USE THIS TO CONSTRUCT A REAL MODE PTR, USE
+ *                        REAL_BASEP INSTEAD SO THAT OFFSETS WORK OUT
+ *                        CORRECTLY.
+ *
+ * Returned values:
+ *     0      if error
+ *     1      if success
+ */
+int RealCopy (ULONG    start_offs,
+              ULONG    end_offs,
+              REALPTR *real_basep,
+              FARPTR  *prot_basep,
+              USHORT  *rmem_adrp)
+{
+  ULONG   rm_base;    /* base real mode para addr for accessing */
+                      /* allocated conventional memory          */
+  UCHAR  *source;     /* source pointer for copy                */
+  FARPTR  destin;     /* destination pointer for copy           */
+  ULONG   len;        /* number of bytes to copy                */
+  ULONG   temp;
+  USHORT  stemp;
+
+  /* First check for valid inputs
+   */
+  if (start_offs >= end_offs || end_offs > 0x10000)
+     return (FALSE);
+
+  /* Round start_offs down to a paragraph (16-byte) boundary so we can set up
+   * the real mode pointer easily. Round up end_offs to make sure we allocate
+   * enough paragraphs
+   */
+  start_offs &= ~15;
+  end_offs = (15 + (end_offs << 4)) >> 4;
+
+  /* Allocate the conventional memory for our real mode code.  Remember to
+   * round byte count UP to 16-byte paragraph size.  We alloc it
+   * above the DOS data buffer so both the DOS data buffer and the appl
+   * conventional mem block can still be resized.
+   *
+   * First just try to alloc it;  if we can't get it, shrink the appl mem
+   * block down to the minimum, try to alloc the memory again, then grow the
+   * appl mem block back to the maximum.  (Don't try to shrink the DOS data
+   * buffer to free conventional memory;  it wouldn't be good for this routine
+   * to have the possible side effect of making file I/O run slower.)
+   */
+  len = ((end_offs - start_offs) + 15) >> 4;
+  if (_dx_real_above(len, rmem_adrp, &stemp) != _DOSE_NONE)
+  {
+    if (_dx_cmem_usage(0, 0, &temp, &temp) != _DOSE_NONE)
+       return (FALSE);
+
+    if (_dx_real_above(len, rmem_adrp, &stemp) != _DOSE_NONE)
+       *rmem_adrp = 0;
+
+    if (_dx_cmem_usage(0, 1, &temp, &temp) != _DOSE_NONE)
+    {
+      if (*rmem_adrp != 0)
+         _dx_real_free (*rmem_adrp);
+      return (FALSE);
+    }
+
+    if (*rmem_adrp == 0)
+       return (FALSE);
+  }
+
+  /* Construct real mode & protected mode pointers to access the allocated
+   * memory.  Note we know start_offs is aligned on a paragraph (16-byte)
+   * boundary, because we rounded it down.
+   *
+   * We make the offsets come out rights by backing off the real mode selector
+   * by start_offs.
+   */
+  rm_base = ((ULONG) *rmem_adrp) - (start_offs >> 4);
+  RP_SET (*real_basep, 0, rm_base);
+  FP_SET (*prot_basep, rm_base << 4, SS_DOSMEM);
+
+  /* Copy the real mode code/data to the allocated memory
+   */
+  source = (UCHAR *) start_offs;
+  destin = *prot_basep;
+  FP_SET (destin, FP_OFF(*prot_basep) + start_offs, FP_SEL(*prot_basep));
+  len = end_offs - start_offs;
+  WriteFarMem (destin, source, len);
+
+  return (TRUE);
+}
+#endif /* DOSX && (DOSX & PHARLAP) */
diff --git a/msdos/pktdrvr.h b/msdos/pktdrvr.h
index 08898ae..3e0cfe0 100644
--- a/msdos/pktdrvr.h
+++ b/msdos/pktdrvr.h
@@ -1,153 +1,153 @@
-#ifndef __PKTDRVR_H

-#define __PKTDRVR_H

-

-#define PUBLIC

-#define LOCAL        static

-

-#define RX_BUF_SIZE  ETH_MTU   /* buffer size variables. NB !! */

-#define TX_BUF_SIZE  ETH_MTU   /* must be same as in pkt_rx*.* */

-

-#ifdef __HIGHC__

-#pragma Off(Align_members)

-#else

-#pragma pack(1)

-#endif

-

-typedef enum  {                /* Packet-driver classes */

-        PD_ETHER      = 1,

-        PD_PRONET10   = 2,

-        PD_IEEE8025   = 3,

-        PD_OMNINET    = 4,

-        PD_APPLETALK  = 5,

-        PD_SLIP       = 6,

-        PD_STARTLAN   = 7,

-        PD_ARCNET     = 8,

-        PD_AX25       = 9,

-        PD_KISS       = 10,

-        PD_IEEE8023_2 = 11,

-        PD_FDDI8022   = 12,

-        PD_X25        = 13,

-        PD_LANstar    = 14,

-        PD_PPP        = 18

-      } PKT_CLASS;

-

-typedef enum  {             /* Packet-driver receive modes    */

-        PDRX_OFF    = 1,    /* turn off receiver              */

-        PDRX_DIRECT,        /* receive only to this interface */

-        PDRX_BROADCAST,     /* DIRECT + broadcast packets     */

-        PDRX_MULTICAST1,    /* BROADCAST + limited multicast  */

-        PDRX_MULTICAST2,    /* BROADCAST + all multicast      */

-        PDRX_ALL_PACKETS,   /* receive all packets on network */

-      } PKT_RX_MODE;

-

-typedef struct {

-        char type[8];

-        char len;

-      } PKT_FRAME;

-

-

-typedef struct {

-        BYTE  class;        /* = 1 for DEC/Interl/Xerox Ethernet */

-        BYTE  number;       /* = 0 for single LAN adapter        */

-        WORD  type;         /* = 13 for 3C523                    */

-        BYTE  funcs;        /* Basic/Extended/HiPerf functions   */

-        WORD  intr;         /* user interrupt vector number      */

-        WORD  handle;       /* Handle associated with session    */

-        BYTE  name [15];    /* Name of adapter interface,ie.3C523*/

-        BOOL  quiet;        /* (don't) print errors to stdout    */

-        const char *error;  /* address of error string           */

-        BYTE  majVer;       /* Major driver implementation ver.  */

-        BYTE  minVer;       /* Minor driver implementation ver.  */

-        BYTE  dummyLen;     /* length of following data          */

-        WORD  MAClength;    /* HiPerformance data, N/A           */

-        WORD  MTU;          /* HiPerformance data, N/A           */

-        WORD  multicast;    /* HiPerformance data, N/A           */

-        WORD  rcvrBuffers;  /* valid for                         */

-        WORD  UMTbufs;      /*   High Performance drivers only   */

-        WORD  postEOIintr;  /*                  Usage ??         */

-      } PKT_INFO;

-

-#define PKT_PARAM_SIZE  14    /* members majVer - postEOIintr */

-

-

-typedef struct {

-        DWORD inPackets;          /* # of packets received    */

-        DWORD outPackets;         /* # of packets transmitted */

-        DWORD inBytes;            /* # of bytes received      */

-        DWORD outBytes;           /* # of bytes transmitted   */

-        DWORD inErrors;           /* # of reception errors    */

-        DWORD outErrors;          /* # of transmission errors */

-        DWORD lost;               /* # of packets lost (RX)   */

-      } PKT_STAT;

-                   

-

-typedef struct {

-        ETHER destin;

-        ETHER source;

-        WORD  proto;

-        BYTE  data [TX_BUF_SIZE];

-      } TX_ELEMENT;

-

-typedef struct {

-        WORD  firstCount;         /* # of bytes on 1st         */

-        WORD  secondCount;        /* and 2nd upcall            */

-        WORD  handle;             /* instance that upcalled    */

-        ETHER destin;             /* E-net destination address */

-        ETHER source;             /* E-net source address      */

-        WORD  proto;              /* protocol number           */

-        BYTE  data [RX_BUF_SIZE];

-      } RX_ELEMENT;

-

-

-#ifdef __HIGHC__

-#pragma pop(Align_members)

-#else

-#pragma pack()

-#endif

-

-

-/*

- * Prototypes for publics

- */

-

-#ifdef __cplusplus

-extern "C" {

-#endif

-

-extern PKT_STAT    pktStat;     /* statistics for packets */

-extern PKT_INFO    pktInfo;     /* packet-driver information */

-

-extern PKT_RX_MODE receiveMode;

-extern ETHER       myAddress, ethBroadcast;

-

-extern BOOL  PktInitDriver (PKT_RX_MODE mode);

-extern BOOL  PktExitDriver (void);

-

-extern const char *PktGetErrorStr    (int errNum);

-extern const char *PktGetClassName   (WORD class);

-extern const char *PktRXmodeStr      (PKT_RX_MODE mode);

-extern BOOL        PktSearchDriver   (void);

-extern int         PktReceive        (BYTE *buf, int max);

-extern BOOL        PktTransmit       (const void *eth, int len);

-extern DWORD       PktRxDropped      (void);

-extern BOOL        PktReleaseHandle  (WORD handle);

-extern BOOL        PktTerminHandle   (WORD handle);

-extern BOOL        PktResetInterface (WORD handle);

-extern BOOL        PktSetReceiverMode(PKT_RX_MODE  mode);

-extern BOOL        PktGetReceiverMode(PKT_RX_MODE *mode);

-extern BOOL        PktGetStatistics  (WORD handle);

-extern BOOL        PktSessStatistics (WORD handle);

-extern BOOL        PktResetStatistics(WORD handle);

-extern BOOL        PktGetAddress     (ETHER *addr);

-extern BOOL        PktSetAddress     (const ETHER *addr);

-extern BOOL        PktGetDriverInfo  (void);

-extern BOOL        PktGetDriverParam (void);

-extern void        PktQueueBusy      (BOOL busy);

-extern WORD        PktBuffersUsed    (void);

-

-#ifdef __cplusplus

-}

-#endif

-

-#endif /* __PKTDRVR_H */

-

+#ifndef __PKTDRVR_H
+#define __PKTDRVR_H
+
+#define PUBLIC
+#define LOCAL        static
+
+#define RX_BUF_SIZE  ETH_MTU   /* buffer size variables. NB !! */
+#define TX_BUF_SIZE  ETH_MTU   /* must be same as in pkt_rx*.* */
+
+#ifdef __HIGHC__
+#pragma Off(Align_members)
+#else
+#pragma pack(1)
+#endif
+
+typedef enum  {                /* Packet-driver classes */
+        PD_ETHER      = 1,
+        PD_PRONET10   = 2,
+        PD_IEEE8025   = 3,
+        PD_OMNINET    = 4,
+        PD_APPLETALK  = 5,
+        PD_SLIP       = 6,
+        PD_STARTLAN   = 7,
+        PD_ARCNET     = 8,
+        PD_AX25       = 9,
+        PD_KISS       = 10,
+        PD_IEEE8023_2 = 11,
+        PD_FDDI8022   = 12,
+        PD_X25        = 13,
+        PD_LANstar    = 14,
+        PD_PPP        = 18
+      } PKT_CLASS;
+
+typedef enum  {             /* Packet-driver receive modes    */
+        PDRX_OFF    = 1,    /* turn off receiver              */
+        PDRX_DIRECT,        /* receive only to this interface */
+        PDRX_BROADCAST,     /* DIRECT + broadcast packets     */
+        PDRX_MULTICAST1,    /* BROADCAST + limited multicast  */
+        PDRX_MULTICAST2,    /* BROADCAST + all multicast      */
+        PDRX_ALL_PACKETS,   /* receive all packets on network */
+      } PKT_RX_MODE;
+
+typedef struct {
+        char type[8];
+        char len;
+      } PKT_FRAME;
+
+
+typedef struct {
+        BYTE  class;        /* = 1 for DEC/Interl/Xerox Ethernet */
+        BYTE  number;       /* = 0 for single LAN adapter        */
+        WORD  type;         /* = 13 for 3C523                    */
+        BYTE  funcs;        /* Basic/Extended/HiPerf functions   */
+        WORD  intr;         /* user interrupt vector number      */
+        WORD  handle;       /* Handle associated with session    */
+        BYTE  name [15];    /* Name of adapter interface,ie.3C523*/
+        BOOL  quiet;        /* (don't) print errors to stdout    */
+        const char *error;  /* address of error string           */
+        BYTE  majVer;       /* Major driver implementation ver.  */
+        BYTE  minVer;       /* Minor driver implementation ver.  */
+        BYTE  dummyLen;     /* length of following data          */
+        WORD  MAClength;    /* HiPerformance data, N/A           */
+        WORD  MTU;          /* HiPerformance data, N/A           */
+        WORD  multicast;    /* HiPerformance data, N/A           */
+        WORD  rcvrBuffers;  /* valid for                         */
+        WORD  UMTbufs;      /*   High Performance drivers only   */
+        WORD  postEOIintr;  /*                  Usage ??         */
+      } PKT_INFO;
+
+#define PKT_PARAM_SIZE  14    /* members majVer - postEOIintr */
+
+
+typedef struct {
+        DWORD inPackets;          /* # of packets received    */
+        DWORD outPackets;         /* # of packets transmitted */
+        DWORD inBytes;            /* # of bytes received      */
+        DWORD outBytes;           /* # of bytes transmitted   */
+        DWORD inErrors;           /* # of reception errors    */
+        DWORD outErrors;          /* # of transmission errors */
+        DWORD lost;               /* # of packets lost (RX)   */
+      } PKT_STAT;
+
+
+typedef struct {
+        ETHER destin;
+        ETHER source;
+        WORD  proto;
+        BYTE  data [TX_BUF_SIZE];
+      } TX_ELEMENT;
+
+typedef struct {
+        WORD  firstCount;         /* # of bytes on 1st         */
+        WORD  secondCount;        /* and 2nd upcall            */
+        WORD  handle;             /* instance that upcalled    */
+        ETHER destin;             /* E-net destination address */
+        ETHER source;             /* E-net source address      */
+        WORD  proto;              /* protocol number           */
+        BYTE  data [RX_BUF_SIZE];
+      } RX_ELEMENT;
+
+
+#ifdef __HIGHC__
+#pragma pop(Align_members)
+#else
+#pragma pack()
+#endif
+
+
+/*
+ * Prototypes for publics
+ */
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+extern PKT_STAT    pktStat;     /* statistics for packets */
+extern PKT_INFO    pktInfo;     /* packet-driver information */
+
+extern PKT_RX_MODE receiveMode;
+extern ETHER       myAddress, ethBroadcast;
+
+extern BOOL  PktInitDriver (PKT_RX_MODE mode);
+extern BOOL  PktExitDriver (void);
+
+extern const char *PktGetErrorStr    (int errNum);
+extern const char *PktGetClassName   (WORD class);
+extern const char *PktRXmodeStr      (PKT_RX_MODE mode);
+extern BOOL        PktSearchDriver   (void);
+extern int         PktReceive        (BYTE *buf, int max);
+extern BOOL        PktTransmit       (const void *eth, int len);
+extern DWORD       PktRxDropped      (void);
+extern BOOL        PktReleaseHandle  (WORD handle);
+extern BOOL        PktTerminHandle   (WORD handle);
+extern BOOL        PktResetInterface (WORD handle);
+extern BOOL        PktSetReceiverMode(PKT_RX_MODE  mode);
+extern BOOL        PktGetReceiverMode(PKT_RX_MODE *mode);
+extern BOOL        PktGetStatistics  (WORD handle);
+extern BOOL        PktSessStatistics (WORD handle);
+extern BOOL        PktResetStatistics(WORD handle);
+extern BOOL        PktGetAddress     (ETHER *addr);
+extern BOOL        PktSetAddress     (const ETHER *addr);
+extern BOOL        PktGetDriverInfo  (void);
+extern BOOL        PktGetDriverParam (void);
+extern void        PktQueueBusy      (BOOL busy);
+extern WORD        PktBuffersUsed    (void);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __PKTDRVR_H */
+
diff --git a/msdos/readme.dos b/msdos/readme.dos
index 353d0cc..990a2e8 100644
--- a/msdos/readme.dos
+++ b/msdos/readme.dos
@@ -10,19 +10,21 @@
  - GNU C 2.7+ with djgpp 2.01+ DOS extender
  - Watcom C 11.x with DOS4GW extender
 
-Note: the files in the libpcap.zip contains short trucated filenames.
+Note: the files in the libpcap.zip contains short truncated filenames.
   So for djgpp to work with these, disable the use of long file names by
-  setting "LFN=n" in the environment.
+  setting "LFN=n" in the environment. On the other hand, if you get libpcap
+  from Github or the official libpcap.tar.gz, some filenames are beyond 8+3.
+  In this case set "LFN=y".
 
 Files specific to DOS are pcap-dos.[ch] and the assembly and C files in
-the MSDOS sub-directory. Remember to built lipcap libraries from the top
+the MSDOS sub-directory. Remember to built the libpcap library from the top
 install directory. And not from the MSDOS sub-directory.
 
 Note for djgpp users:
   If you got the libpcap from the official site www.tcpdump, then that
   distribution does NOT contain any sources for building 32-bit drivers.
   Instead get the full version at
-     http://www.bgnett.no/~giva/pcap/libpcap.zip
+     http://www.watt-32.net/pcap/libpcap.zip
 
   and set "USE_32BIT_DRIVERS = 1" in msdos\common.dj.
 
@@ -49,30 +51,28 @@
    receive network data. It's mostly used to access the 'hosts'
    file and other <netdb.h> features. Get 'watt32s*.zip' at:
 
-     http://www.bgnett.no/~giva/
+     http://www.watt-32.net
 
 2. Exception handler and disassember library (libexc.a) is needed if
    "USE_EXCEPT = 1" in common.dj. Available at:
 
-     http://www.bgnett.no/~giva/misc/exc_dx07.zip
+     http://www.watt-32.net/misc/exc_dx07.zip
 
 3. Flex & Bison is used to generate parser for the filter handler
    pcap_compile:
-
-     ftp://ftp.simtel.net/pub/simtelnet/gnu/djgpp/v2gnu/flx254b.zip
-     ftp://ftp.simtel.net/pub/simtelnet/gnu/djgpp/v2gnu/bsn128b.zip
+     ftp://ftp.delorie.com/pub/djgpp/current/v2gnu/flx254b.zip
+     ftp://ftp.delorie.com/pub/djgpp/current/v2gnu/bsn241b.zip
 
 4. NASM assembler v 0.98 or later is required when building djgpp and
    Watcom targets:
-
-     ftp://ftp.simtel.net/pub/simtelnet/gnu/djgpp/v2tk/nasm098p.zip
+     http://www.nasm.us/
 
 5. sed (Stream Editor) is required for doing `make depend'.
-   It's available at
-     ftp://ftp.simtel.net/pub/simtelnet/gnu/djgpp/v2gnu/sed*.zip
+   It's available at:
+     ftp://ftp.delorie.com/pub/djgpp/current/v2gnu/sed422b.zip
 
-   A touch tool to update the time-stamp of a file. E.g.
-     ftp://ftp.simtel.net/pub/simtelnet/gnu/djgpp/v2gnu/grep*.zip
+   A touch tool to update the time-stamp of a file. E.g.:
+     ftp://ftp.delorie.com/pub/djgpp/current/v2gnu/grep29b.zip
 
 6. For djgpp rm.exe and cp.exe are required. These should already be
    part of your djgpp installation. Also required (experimental at the
@@ -121,10 +121,17 @@
 
    Note: Code in `USE_NDIS2' does not work at the moment.
 
-4. The resulting libraries are put in current directory. There's no
-   test-program for `libpcap'. Linking the library with `tcpdump' is
-   the ultimate test anyway.
+4. The resulting library is put in current directory. There's some
+   test-program for `libpcap': `filtertest.exe', `findalldevstest.exe',
+     `nonblocktest.exe' and `opentest.exe'.
 
+   But linking the library with `tcpdump' is the ultimate test. DOS/djgpp
+   should now hopefully be a supported target. Get the sources at:
+     http://www.tcpdump.org/
+   or
+     https://github.com/the-tcpdump-group/tcpdump/
+
+   (click on the 'Download ZIP' on the right side of that page.)
 
 
 Extensions to libpcap
@@ -132,14 +139,14 @@
 
 I've included some extra functions to DOS-libpcap:
 
-  `pcap_config_hook (const char *name, const char *value)'
+  `pcap_config_hook (const char *keyword, const char *value)' :
 
     Allows an application to set values of internal libpcap variables.
-    `name' is typically a left-side keyword with an associated `value'
-    that is called from application's configure process (see tcpdump's
-    config.c file). libpcap keeps a set of tables that are searched for
-    a name/value match. Currently only used to set debug-levels and
-    parameters for the 32-bit network drivers.
+    `keyword' and an associated `value' should be present in the `debug_tab[]'
+    array in pcap-dos.c (currently only used to set debug-levels and parameters
+    for the 32-bit network drivers.) Thus an application using DOS-libpcap can
+    override the default value during it's configure process (see tcpdump's
+    msdos/config.c file for an extended example).
 
   `pcap_set_wait (pcap_t *, void (*)(void), int)' :
 
@@ -153,8 +160,7 @@
 Happy sniffing !
 
 
-Gisle Vanem <giva@bgnett.no>
-            <gvanem@broadpark.no>
+Gisle Vanem <gvanem@yahoo.no>
 
-October 1999, 2004
+October 1999, 2004, 2006, 2013
 
diff --git a/nametoaddr.c b/nametoaddr.c
index e6483a3..71280b3 100644
--- a/nametoaddr.c
+++ b/nametoaddr.c
@@ -31,10 +31,36 @@
 #include <netdnet/dnetdb.h>
 #endif
 
-#ifdef WIN32
+#ifdef _WIN32
 #include <pcap-stdinc.h>
 
-#else /* WIN32 */
+#ifdef INET6
+/*
+ * To quote the MSDN page for getaddrinfo() at
+ *
+ *    https://msdn.microsoft.com/en-us/library/windows/desktop/ms738520(v=vs.85).aspx
+ *
+ * "Support for getaddrinfo on Windows 2000 and older versions
+ * The getaddrinfo function was added to the Ws2_32.dll on Windows XP and
+ * later. To execute an application that uses this function on earlier
+ * versions of Windows, then you need to include the Ws2tcpip.h and
+ * Wspiapi.h files. When the Wspiapi.h include file is added, the
+ * getaddrinfo function is defined to the WspiapiGetAddrInfo inline
+ * function in the Wspiapi.h file. At runtime, the WspiapiGetAddrInfo
+ * function is implemented in such a way that if the Ws2_32.dll or the
+ * Wship6.dll (the file containing getaddrinfo in the IPv6 Technology
+ * Preview for Windows 2000) does not include getaddrinfo, then a
+ * version of getaddrinfo is implemented inline based on code in the
+ * Wspiapi.h header file. This inline code will be used on older Windows
+ * platforms that do not natively support the getaddrinfo function."
+ *
+ * We use getaddrinfo(), so we include Wspiapi.h here.  pcap-stdinc.h
+ * includes Ws2tcpip.h, so we don't need to include it ourselves.
+ */
+#include <Wspiapi.h>
+#endif
+
+#else /* _WIN32 */
 
 #include <sys/param.h>
 #include <sys/types.h>				/* concession to AIX */
@@ -42,9 +68,9 @@
 #include <sys/time.h>
 
 #include <netinet/in.h>
-#endif /* WIN32 */
+#endif /* _WIN32 */
 
-#ifndef WIN32
+#ifndef _WIN32
 #ifdef HAVE_ETHER_HOSTTON
 /*
  * XXX - do we need any of this if <netinet/if_ether.h> doesn't declare
@@ -62,7 +88,7 @@
 #endif /* HAVE_ETHER_HOSTTON */
 #include <arpa/inet.h>
 #include <netdb.h>
-#endif /* WIN32 */
+#endif /* _WIN32 */
 
 #include <ctype.h>
 #include <errno.h>
@@ -74,6 +100,7 @@
 
 #include "gencode.h"
 #include <pcap/namedb.h>
+#include "nametoaddr.h"
 
 #ifdef HAVE_OS_PROTO_H
 #include "os-proto.h"
@@ -140,7 +167,7 @@
 bpf_u_int32
 pcap_nametonetaddr(const char *name)
 {
-#ifndef WIN32
+#ifndef _WIN32
 	struct netent *np;
 
 	if ((np = getnetbyname(name)) != NULL)
@@ -150,6 +177,15 @@
 #else
 	/*
 	 * There's no "getnetbyname()" on Windows.
+	 *
+	 * XXX - I guess we could use the BSD code to read
+	 * C:\Windows\System32\drivers\etc/networks, assuming
+	 * that's its home on all the versions of Windows
+	 * we use, but that file probably just has the loopback
+	 * network on 127/24 on 99 44/100% of Windows machines.
+	 *
+	 * (Heck, these days it probably just has that on 99 44/100%
+	 * of *UN*X* machines.)
 	 */
 	return 0;
 #endif
@@ -274,8 +310,14 @@
 	u_short p;
 };
 
-/* Static data base of ether protocol types. */
-struct eproto eproto_db[] = {
+/*
+ * Static data base of ether protocol types.
+ * tcpdump used to import this, and it's declared as an export on
+ * Debian, at least, so make it a public symbol, even though we
+ * don't officially export it by declaring it in a header file.
+ * (Programs *should* do this themselves, as tcpdump now does.)
+ */
+PCAP_API_DEF struct eproto eproto_db[] = {
 	{ "pup", ETHERTYPE_PUP },
 	{ "xns", ETHERTYPE_NS },
 	{ "ip", ETHERTYPE_IP },
@@ -383,7 +425,7 @@
 	u_int node, area;
 
 	if (sscanf(s, "%d.%d", &area, &node) != 2)
-		bpf_error("malformed decnet address '%s'", s);
+		return(0);
 
 	*addr = (area << AREASHIFT) & AREAMASK;
 	*addr |= (node & NODEMASK);
@@ -487,23 +529,20 @@
 }
 #endif
 
-u_short
-__pcap_nametodnaddr(const char *name)
+int
+__pcap_nametodnaddr(const char *name, u_short *res)
 {
 #ifdef	DECNETLIB
 	struct nodeent *getnodebyname();
 	struct nodeent *nep;
-	unsigned short res;
 
 	nep = getnodebyname(name);
 	if (nep == ((struct nodeent *)0))
-		bpf_error("unknown decnet host name '%s'\n", name);
+		return(0);
 
-	memcpy((char *)&res, (char *)nep->n_addr, sizeof(unsigned short));
-	return(res);
+	memcpy((char *)res, (char *)nep->n_addr, sizeof(unsigned short));
+	return(1);
 #else
-	bpf_error("decnet name support not included, '%s' cannot be translated\n",
-		name);
 	return(0);
 #endif
 }
diff --git a/fad-null.c b/nametoaddr.h
similarity index 70%
rename from fad-null.c
rename to nametoaddr.h
index cecfbcb..fd6b7e1 100644
--- a/fad-null.c
+++ b/nametoaddr.h
@@ -1,6 +1,5 @@
-/* -*- Mode: c; tab-width: 8; indent-tabs-mode: 1; c-basic-offset: 8; -*- */
 /*
- * Copyright (c) 1994, 1995, 1996, 1997, 1998
+ * Copyright (c) 1994, 1996
  *	The Regents of the University of California.  All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
@@ -32,29 +31,18 @@
  * SUCH DAMAGE.
  */
 
-#ifdef HAVE_CONFIG_H
-#include "config.h"
+#ifdef __cplusplus
+extern "C" {
 #endif
 
-#include <pcap.h>
-
 /*
- * Get a list of all interfaces that are up and that we can open.
- * Returns -1 on error, 0 otherwise.
- * The list, as returned through "alldevsp", may be null if no interfaces
- * were up and could be opened.
- *
- * This is the implementation used on platforms that have no support for
- * packet capture.
+ * Routines used for name-or-address-string-to-address resolution
+ * that are *not* exported to code using libpcap.
  */
-int
-pcap_findalldevs_interfaces(pcap_if_t **alldevsp, char *errbuf)
-{
-	/*
-	 * Succeed, but don't return any interfaces; we return only those
-	 * we can open, and we can't open any if there's no support
-	 * for packet capture.
-	 */
-	*alldevsp = NULL;
-	return (0);
+int __pcap_atodn(const char *, bpf_u_int32 *);
+int __pcap_atoin(const char *, bpf_u_int32 *);
+int __pcap_nametodnaddr(const char *, u_short *);
+
+#ifdef __cplusplus
 }
+#endif
diff --git a/net b/net
new file mode 120000
index 0000000..b3eaca9
--- /dev/null
+++ b/net
@@ -0,0 +1 @@
+./bpf/net
\ No newline at end of file
diff --git a/optimize.c b/optimize.c
index ada2019..19980dc 100644
--- a/optimize.c
+++ b/optimize.c
@@ -25,9 +25,9 @@
 #include "config.h"
 #endif
 
-#ifdef WIN32
+#ifdef _WIN32
 #include <pcap-stdinc.h>
-#else /* WIN32 */
+#else /* _WIN32 */
 #if HAVE_INTTYPES_H
 #include <inttypes.h>
 #elif HAVE_STDINT_H
@@ -37,7 +37,7 @@
 #include <sys/bitypes.h>
 #endif
 #include <sys/types.h>
-#endif /* WIN32 */
+#endif /* _WIN32 */
 
 #include <stdio.h>
 #include <stdlib.h>
@@ -55,7 +55,7 @@
 #endif
 
 #ifdef BDEBUG
-extern int dflag;
+int pcap_optimizer_debug;
 #endif
 
 #if defined(MSDOS) && !defined(__DJGPP__)
@@ -63,8 +63,26 @@
 #define ffs _w32_ffs
 #endif
 
-#if defined(WIN32) && defined (_MSC_VER)
-int ffs(int mask);
+/*
+ * So is the check for _MSC_VER done because MinGW has this?
+ */
+#if defined(_WIN32) && defined (_MSC_VER)
+/*
+ * ffs -- vax ffs instruction
+ *
+ * XXX - with versions of VS that have it, use _BitScanForward()?
+ */
+static int
+ffs(int mask)
+{
+	int bit;
+
+	if (mask == 0)
+		return(0);
+	for (bit = 1; !(mask & 1); bit++)
+		mask >>= 1;
+	return(bit);
+}
 #endif
 
 /*
@@ -89,45 +107,48 @@
 #define AX_ATOM N_ATOMS
 
 /*
- * A flag to indicate that further optimization is needed.
- * Iterative passes are continued until a given pass yields no
- * branch movement.
+ * These data structures are used in a Cocke and Shwarz style
+ * value numbering scheme.  Since the flowgraph is acyclic,
+ * exit values can be propagated from a node's predecessors
+ * provided it is uniquely defined.
  */
-static int done;
+struct valnode {
+	int code;
+	int v0, v1;
+	int val;
+	struct valnode *next;
+};
 
-/*
- * A block is marked if only if its mark equals the current mark.
- * Rather than traverse the code array, marking each item, 'cur_mark' is
- * incremented.  This automatically makes each element unmarked.
- */
-static int cur_mark;
-#define isMarked(p) ((p)->mark == cur_mark)
-#define unMarkAll() cur_mark += 1
-#define Mark(p) ((p)->mark = cur_mark)
+/* Integer constants mapped with the load immediate opcode. */
+#define K(i) F(opt_state, BPF_LD|BPF_IMM|BPF_W, i, 0L)
 
-static void opt_init(struct block *);
-static void opt_cleanup(void);
+struct vmapinfo {
+	int is_const;
+	bpf_int32 const_val;
+};
 
-static void intern_blocks(struct block *);
+struct _opt_state {
+	/*
+	 * A flag to indicate that further optimization is needed.
+	 * Iterative passes are continued until a given pass yields no
+	 * branch movement.
+	 */
+	int done;
 
-static void find_inedges(struct block *);
-#ifdef BDEBUG
-static void opt_dump(struct block *);
-#endif
+	int n_blocks;
+	struct block **blocks;
+	int n_edges;
+	struct edge **edges;
 
-static int n_blocks;
-struct block **blocks;
-static int n_edges;
-struct edge **edges;
+	/*
+	 * A bit vector set representation of the dominators.
+	 * We round up the set size to the next power of two.
+	 */
+	int nodewords;
+	int edgewords;
+	struct block **levels;
+	bpf_u_int32 *space;
 
-/*
- * A bit vector set representation of the dominators.
- * We round up the set size to the next power of two.
- */
-static int nodewords;
-static int edgewords;
-struct block **levels;
-bpf_u_int32 *space;
 #define BITS_PER_WORD (8*sizeof(bpf_u_int32))
 /*
  * True if a is in uset {p}
@@ -177,48 +198,79 @@
 	while (--_n >= 0) *_x++ |= *_y++;\
 }
 
-static uset all_dom_sets;
-static uset all_closure_sets;
-static uset all_edge_sets;
+	uset all_dom_sets;
+	uset all_closure_sets;
+	uset all_edge_sets;
+
+#define MODULUS 213
+	struct valnode *hashtbl[MODULUS];
+	int curval;
+	int maxval;
+
+	struct vmapinfo *vmap;
+	struct valnode *vnode_base;
+	struct valnode *next_vnode;
+};
+
+typedef struct {
+	/*
+	 * Some pointers used to convert the basic block form of the code,
+	 * into the array form that BPF requires.  'fstart' will point to
+	 * the malloc'd array while 'ftail' is used during the recursive
+	 * traversal.
+	 */
+	struct bpf_insn *fstart;
+	struct bpf_insn *ftail;
+} conv_state_t;
+
+static void opt_init(compiler_state_t *, opt_state_t *, struct icode *);
+static void opt_cleanup(opt_state_t *);
+
+static void intern_blocks(opt_state_t *, struct icode *);
+
+static void find_inedges(opt_state_t *, struct block *);
+#ifdef BDEBUG
+static void opt_dump(compiler_state_t *, struct icode *);
+#endif
 
 #ifndef MAX
 #define MAX(a,b) ((a)>(b)?(a):(b))
 #endif
 
 static void
-find_levels_r(struct block *b)
+find_levels_r(opt_state_t *opt_state, struct icode *ic, struct block *b)
 {
 	int level;
 
-	if (isMarked(b))
+	if (isMarked(ic, b))
 		return;
 
-	Mark(b);
+	Mark(ic, b);
 	b->link = 0;
 
 	if (JT(b)) {
-		find_levels_r(JT(b));
-		find_levels_r(JF(b));
+		find_levels_r(opt_state, ic, JT(b));
+		find_levels_r(opt_state, ic, JF(b));
 		level = MAX(JT(b)->level, JF(b)->level) + 1;
 	} else
 		level = 0;
 	b->level = level;
-	b->link = levels[level];
-	levels[level] = b;
+	b->link = opt_state->levels[level];
+	opt_state->levels[level] = b;
 }
 
 /*
  * Level graph.  The levels go from 0 at the leaves to
- * N_LEVELS at the root.  The levels[] array points to the
+ * N_LEVELS at the root.  The opt_state->levels[] array points to the
  * first node of the level list, whose elements are linked
  * with the 'link' field of the struct block.
  */
 static void
-find_levels(struct block *root)
+find_levels(opt_state_t *opt_state, struct icode *ic)
 {
-	memset((char *)levels, 0, n_blocks * sizeof(*levels));
-	unMarkAll();
-	find_levels_r(root);
+	memset((char *)opt_state->levels, 0, opt_state->n_blocks * sizeof(*opt_state->levels));
+	unMarkAll(ic);
+	find_levels_r(opt_state, ic, ic->root);
 }
 
 /*
@@ -226,7 +278,7 @@
  * Assumes graph has been leveled.
  */
 static void
-find_dom(struct block *root)
+find_dom(opt_state_t *opt_state, struct block *root)
 {
 	int i;
 	struct block *b;
@@ -235,33 +287,33 @@
 	/*
 	 * Initialize sets to contain all nodes.
 	 */
-	x = all_dom_sets;
-	i = n_blocks * nodewords;
+	x = opt_state->all_dom_sets;
+	i = opt_state->n_blocks * opt_state->nodewords;
 	while (--i >= 0)
 		*x++ = ~0;
 	/* Root starts off empty. */
-	for (i = nodewords; --i >= 0;)
+	for (i = opt_state->nodewords; --i >= 0;)
 		root->dom[i] = 0;
 
 	/* root->level is the highest level no found. */
 	for (i = root->level; i >= 0; --i) {
-		for (b = levels[i]; b; b = b->link) {
+		for (b = opt_state->levels[i]; b; b = b->link) {
 			SET_INSERT(b->dom, b->id);
 			if (JT(b) == 0)
 				continue;
-			SET_INTERSECT(JT(b)->dom, b->dom, nodewords);
-			SET_INTERSECT(JF(b)->dom, b->dom, nodewords);
+			SET_INTERSECT(JT(b)->dom, b->dom, opt_state->nodewords);
+			SET_INTERSECT(JF(b)->dom, b->dom, opt_state->nodewords);
 		}
 	}
 }
 
 static void
-propedom(struct edge *ep)
+propedom(opt_state_t *opt_state, struct edge *ep)
 {
 	SET_INSERT(ep->edom, ep->id);
 	if (ep->succ) {
-		SET_INTERSECT(ep->succ->et.edom, ep->edom, edgewords);
-		SET_INTERSECT(ep->succ->ef.edom, ep->edom, edgewords);
+		SET_INTERSECT(ep->succ->et.edom, ep->edom, opt_state->edgewords);
+		SET_INTERSECT(ep->succ->ef.edom, ep->edom, opt_state->edgewords);
 	}
 }
 
@@ -270,23 +322,23 @@
  * Assumes graph has been leveled and predecessors established.
  */
 static void
-find_edom(struct block *root)
+find_edom(opt_state_t *opt_state, struct block *root)
 {
 	int i;
 	uset x;
 	struct block *b;
 
-	x = all_edge_sets;
-	for (i = n_edges * edgewords; --i >= 0; )
+	x = opt_state->all_edge_sets;
+	for (i = opt_state->n_edges * opt_state->edgewords; --i >= 0; )
 		x[i] = ~0;
 
 	/* root->level is the highest level no found. */
-	memset(root->et.edom, 0, edgewords * sizeof(*(uset)0));
-	memset(root->ef.edom, 0, edgewords * sizeof(*(uset)0));
+	memset(root->et.edom, 0, opt_state->edgewords * sizeof(*(uset)0));
+	memset(root->ef.edom, 0, opt_state->edgewords * sizeof(*(uset)0));
 	for (i = root->level; i >= 0; --i) {
-		for (b = levels[i]; b != 0; b = b->link) {
-			propedom(&b->et);
-			propedom(&b->ef);
+		for (b = opt_state->levels[i]; b != 0; b = b->link) {
+			propedom(opt_state, &b->et);
+			propedom(opt_state, &b->ef);
 		}
 	}
 }
@@ -299,7 +351,7 @@
  * Assumes graph has been leveled.
  */
 static void
-find_closure(struct block *root)
+find_closure(opt_state_t *opt_state, struct block *root)
 {
 	int i;
 	struct block *b;
@@ -307,17 +359,17 @@
 	/*
 	 * Initialize sets to contain no nodes.
 	 */
-	memset((char *)all_closure_sets, 0,
-	      n_blocks * nodewords * sizeof(*all_closure_sets));
+	memset((char *)opt_state->all_closure_sets, 0,
+	      opt_state->n_blocks * opt_state->nodewords * sizeof(*opt_state->all_closure_sets));
 
 	/* root->level is the highest level no found. */
 	for (i = root->level; i >= 0; --i) {
-		for (b = levels[i]; b; b = b->link) {
+		for (b = opt_state->levels[i]; b; b = b->link) {
 			SET_INSERT(b->closure, b->id);
 			if (JT(b) == 0)
 				continue;
-			SET_UNION(JT(b)->closure, b->closure, nodewords);
-			SET_UNION(JF(b)->closure, b->closure, nodewords);
+			SET_UNION(JT(b)->closure, b->closure, opt_state->nodewords);
+			SET_UNION(JF(b)->closure, b->closure, opt_state->nodewords);
 		}
 	}
 }
@@ -413,7 +465,7 @@
 compute_local_ud(struct block *b)
 {
 	struct slist *s;
-	atomset def = 0, use = 0, kill = 0;
+	atomset def = 0, use = 0, killed = 0;
 	int atom;
 
 	for (s = b->stmts; s; s = s->next) {
@@ -437,7 +489,7 @@
 		atom = atomdef(&s->s);
 		if (atom >= 0) {
 			if (!ATOMELEM(use, atom))
-				kill |= ATOMMASK(atom);
+				killed |= ATOMMASK(atom);
 			def |= ATOMMASK(atom);
 		}
 	}
@@ -463,7 +515,7 @@
 	}
 
 	b->def = def;
-	b->kill = kill;
+	b->kill = killed;
 	b->in_use = use;
 }
 
@@ -471,7 +523,7 @@
  * Assume graph is already leveled.
  */
 static void
-find_ud(struct block *root)
+find_ud(opt_state_t *opt_state, struct block *root)
 {
 	int i, maxlevel;
 	struct block *p;
@@ -482,61 +534,30 @@
 	 */
 	maxlevel = root->level;
 	for (i = maxlevel; i >= 0; --i)
-		for (p = levels[i]; p; p = p->link) {
+		for (p = opt_state->levels[i]; p; p = p->link) {
 			compute_local_ud(p);
 			p->out_use = 0;
 		}
 
 	for (i = 1; i <= maxlevel; ++i) {
-		for (p = levels[i]; p; p = p->link) {
+		for (p = opt_state->levels[i]; p; p = p->link) {
 			p->out_use |= JT(p)->in_use | JF(p)->in_use;
 			p->in_use |= p->out_use &~ p->kill;
 		}
 	}
 }
-
-/*
- * These data structures are used in a Cocke and Shwarz style
- * value numbering scheme.  Since the flowgraph is acyclic,
- * exit values can be propagated from a node's predecessors
- * provided it is uniquely defined.
- */
-struct valnode {
-	int code;
-	int v0, v1;
-	int val;
-	struct valnode *next;
-};
-
-#define MODULUS 213
-static struct valnode *hashtbl[MODULUS];
-static int curval;
-static int maxval;
-
-/* Integer constants mapped with the load immediate opcode. */
-#define K(i) F(BPF_LD|BPF_IMM|BPF_W, i, 0L)
-
-struct vmapinfo {
-	int is_const;
-	bpf_int32 const_val;
-};
-
-struct vmapinfo *vmap;
-struct valnode *vnode_base;
-struct valnode *next_vnode;
-
 static void
-init_val(void)
+init_val(opt_state_t *opt_state)
 {
-	curval = 0;
-	next_vnode = vnode_base;
-	memset((char *)vmap, 0, maxval * sizeof(*vmap));
-	memset((char *)hashtbl, 0, sizeof hashtbl);
+	opt_state->curval = 0;
+	opt_state->next_vnode = opt_state->vnode_base;
+	memset((char *)opt_state->vmap, 0, opt_state->maxval * sizeof(*opt_state->vmap));
+	memset((char *)opt_state->hashtbl, 0, sizeof opt_state->hashtbl);
 }
 
 /* Because we really don't have an IR, this stuff is a little messy. */
 static int
-F(int code, int v0, int v1)
+F(opt_state_t *opt_state, int code, int v0, int v1)
 {
 	u_int hash;
 	int val;
@@ -545,23 +566,23 @@
 	hash = (u_int)code ^ (v0 << 4) ^ (v1 << 8);
 	hash %= MODULUS;
 
-	for (p = hashtbl[hash]; p; p = p->next)
+	for (p = opt_state->hashtbl[hash]; p; p = p->next)
 		if (p->code == code && p->v0 == v0 && p->v1 == v1)
 			return p->val;
 
-	val = ++curval;
+	val = ++opt_state->curval;
 	if (BPF_MODE(code) == BPF_IMM &&
 	    (BPF_CLASS(code) == BPF_LD || BPF_CLASS(code) == BPF_LDX)) {
-		vmap[val].const_val = v0;
-		vmap[val].is_const = 1;
+		opt_state->vmap[val].const_val = v0;
+		opt_state->vmap[val].is_const = 1;
 	}
-	p = next_vnode++;
+	p = opt_state->next_vnode++;
 	p->val = val;
 	p->code = code;
 	p->v0 = v0;
 	p->v1 = v1;
-	p->next = hashtbl[hash];
-	hashtbl[hash] = p;
+	p->next = opt_state->hashtbl[hash];
+	opt_state->hashtbl[hash] = p;
 
 	return val;
 }
@@ -580,12 +601,13 @@
  * (Unary operators are handled elsewhere.)
  */
 static void
-fold_op(struct stmt *s, int v0, int v1)
+fold_op(compiler_state_t *cstate, struct icode *ic, opt_state_t *opt_state,
+    struct stmt *s, int v0, int v1)
 {
 	bpf_u_int32 a, b;
 
-	a = vmap[v0].const_val;
-	b = vmap[v1].const_val;
+	a = opt_state->vmap[v0].const_val;
+	b = opt_state->vmap[v1].const_val;
 
 	switch (BPF_OP(s->code)) {
 	case BPF_ADD:
@@ -602,13 +624,13 @@
 
 	case BPF_DIV:
 		if (b == 0)
-			bpf_error("division by zero");
+			bpf_error(cstate, "division by zero");
 		a /= b;
 		break;
 
 	case BPF_MOD:
 		if (b == 0)
-			bpf_error("modulus by zero");
+			bpf_error(cstate, "modulus by zero");
 		a %= b;
 		break;
 
@@ -637,7 +659,7 @@
 	}
 	s->k = a;
 	s->code = BPF_LD|BPF_IMM;
-	done = 0;
+	opt_state->done = 0;
 }
 
 static inline struct slist *
@@ -658,7 +680,7 @@
 }
 
 static void
-opt_peep(struct block *b)
+opt_peep(opt_state_t *opt_state, struct block *b)
 {
 	struct slist *s;
 	struct slist *next, *last;
@@ -693,7 +715,7 @@
 		if (s->s.code == BPF_ST &&
 		    next->s.code == (BPF_LDX|BPF_MEM) &&
 		    s->s.k == next->s.k) {
-			done = 0;
+			opt_state->done = 0;
 			next->s.code = BPF_MISC|BPF_TAX;
 		}
 		/*
@@ -704,7 +726,7 @@
 		    next->s.code == (BPF_MISC|BPF_TAX)) {
 			s->s.code = BPF_LDX|BPF_IMM;
 			next->s.code = BPF_MISC|BPF_TXA;
-			done = 0;
+			opt_state->done = 0;
 		}
 		/*
 		 * This is an ugly special case, but it happens
@@ -783,7 +805,7 @@
 			s->s.code = NOP;
 			add->s.code = NOP;
 			tax->s.code = NOP;
-			done = 0;
+			opt_state->done = 0;
 		}
 	}
 	/*
@@ -801,7 +823,7 @@
 	    	 */
 		if (last->s.code == (BPF_ALU|BPF_SUB|BPF_X)) {
 			val = b->val[X_ATOM];
-			if (vmap[val].is_const) {
+			if (opt_state->vmap[val].is_const) {
 				/*
 				 * If we have a subtract to do a comparison,
 				 * and the X register is a known constant,
@@ -811,9 +833,9 @@
 				 * sub x  ->	nop
 				 * jeq #y	jeq #(x+y)
 				 */
-				b->s.k += vmap[val].const_val;
+				b->s.k += opt_state->vmap[val].const_val;
 				last->s.code = NOP;
-				done = 0;
+				opt_state->done = 0;
 			} else if (b->s.k == 0) {
 				/*
 				 * If the X register isn't a constant,
@@ -826,7 +848,7 @@
 				 */
 				last->s.code = NOP;
 				b->s.code = BPF_JMP|BPF_JEQ|BPF_X;
-				done = 0;
+				opt_state->done = 0;
 			}
 		}
 		/*
@@ -838,7 +860,7 @@
 		else if (last->s.code == (BPF_ALU|BPF_SUB|BPF_K)) {
 			last->s.code = NOP;
 			b->s.k += last->s.k;
-			done = 0;
+			opt_state->done = 0;
 		}
 		/*
 		 * And, similarly, a constant AND can be simplified
@@ -852,7 +874,7 @@
 			b->s.k = last->s.k;
 			b->s.code = BPF_JMP|BPF_K|BPF_JSET;
 			last->s.code = NOP;
-			done = 0;
+			opt_state->done = 0;
 			opt_not(b);
 		}
 	}
@@ -863,7 +885,7 @@
 	if (b->s.code == (BPF_JMP|BPF_K|BPF_JSET)) {
 		if (b->s.k == 0)
 			JT(b) = JF(b);
-		if (b->s.k == 0xffffffff)
+		if ((u_int)b->s.k == 0xffffffffU)
 			JF(b) = JT(b);
 	}
 	/*
@@ -872,8 +894,8 @@
 	 * constant.
 	 */
 	val = b->val[X_ATOM];
-	if (vmap[val].is_const && BPF_SRC(b->s.code) == BPF_X) {
-		bpf_int32 v = vmap[val].const_val;
+	if (opt_state->vmap[val].is_const && BPF_SRC(b->s.code) == BPF_X) {
+		bpf_int32 v = opt_state->vmap[val].const_val;
 		b->s.code &= ~BPF_X;
 		b->s.k = v;
 	}
@@ -882,8 +904,8 @@
 	 * comparison result.
 	 */
 	val = b->val[A_ATOM];
-	if (vmap[val].is_const && BPF_SRC(b->s.code) == BPF_K) {
-		bpf_int32 v = vmap[val].const_val;
+	if (opt_state->vmap[val].is_const && BPF_SRC(b->s.code) == BPF_K) {
+		bpf_int32 v = opt_state->vmap[val].const_val;
 		switch (BPF_OP(b->s.code)) {
 
 		case BPF_JEQ:
@@ -891,11 +913,11 @@
 			break;
 
 		case BPF_JGT:
-			v = (unsigned)v > b->s.k;
+			v = (unsigned)v > (unsigned)b->s.k;
 			break;
 
 		case BPF_JGE:
-			v = (unsigned)v >= b->s.k;
+			v = (unsigned)v >= (unsigned)b->s.k;
 			break;
 
 		case BPF_JSET:
@@ -906,7 +928,7 @@
 			abort();
 		}
 		if (JF(b) != JT(b))
-			done = 0;
+			opt_state->done = 0;
 		if (v)
 			JF(b) = JT(b);
 		else
@@ -921,7 +943,8 @@
  * evaluation and code transformations weren't folded together.
  */
 static void
-opt_stmt(struct stmt *s, int val[], int alter)
+opt_stmt(compiler_state_t *cstate, struct icode *ic, opt_state_t *opt_state,
+    struct stmt *s, int val[], int alter)
 {
 	int op;
 	int v;
@@ -931,7 +954,7 @@
 	case BPF_LD|BPF_ABS|BPF_W:
 	case BPF_LD|BPF_ABS|BPF_H:
 	case BPF_LD|BPF_ABS|BPF_B:
-		v = F(s->code, s->k, 0L);
+		v = F(opt_state, s->code, s->k, 0L);
 		vstore(s, &val[A_ATOM], v, alter);
 		break;
 
@@ -939,19 +962,19 @@
 	case BPF_LD|BPF_IND|BPF_H:
 	case BPF_LD|BPF_IND|BPF_B:
 		v = val[X_ATOM];
-		if (alter && vmap[v].is_const) {
+		if (alter && opt_state->vmap[v].is_const) {
 			s->code = BPF_LD|BPF_ABS|BPF_SIZE(s->code);
-			s->k += vmap[v].const_val;
-			v = F(s->code, s->k, 0L);
-			done = 0;
+			s->k += opt_state->vmap[v].const_val;
+			v = F(opt_state, s->code, s->k, 0L);
+			opt_state->done = 0;
 		}
 		else
-			v = F(s->code, s->k, v);
+			v = F(opt_state, s->code, s->k, v);
 		vstore(s, &val[A_ATOM], v, alter);
 		break;
 
 	case BPF_LD|BPF_LEN:
-		v = F(s->code, 0L, 0L);
+		v = F(opt_state, s->code, 0L, 0L);
 		vstore(s, &val[A_ATOM], v, alter);
 		break;
 
@@ -966,18 +989,18 @@
 		break;
 
 	case BPF_LDX|BPF_MSH|BPF_B:
-		v = F(s->code, s->k, 0L);
+		v = F(opt_state, s->code, s->k, 0L);
 		vstore(s, &val[X_ATOM], v, alter);
 		break;
 
 	case BPF_ALU|BPF_NEG:
-		if (alter && vmap[val[A_ATOM]].is_const) {
+		if (alter && opt_state->vmap[val[A_ATOM]].is_const) {
 			s->code = BPF_LD|BPF_IMM;
-			s->k = -vmap[val[A_ATOM]].const_val;
+			s->k = -opt_state->vmap[val[A_ATOM]].const_val;
 			val[A_ATOM] = K(s->k);
 		}
 		else
-			val[A_ATOM] = F(s->code, val[A_ATOM], 0L);
+			val[A_ATOM] = F(opt_state, s->code, val[A_ATOM], 0L);
 		break;
 
 	case BPF_ALU|BPF_ADD|BPF_K:
@@ -1008,13 +1031,13 @@
 					break;
 				}
 			}
-			if (vmap[val[A_ATOM]].is_const) {
-				fold_op(s, val[A_ATOM], K(s->k));
+			if (opt_state->vmap[val[A_ATOM]].is_const) {
+				fold_op(cstate, ic, opt_state, s, val[A_ATOM], K(s->k));
 				val[A_ATOM] = K(s->k);
 				break;
 			}
 		}
-		val[A_ATOM] = F(s->code, val[A_ATOM], K(s->k));
+		val[A_ATOM] = F(opt_state, s->code, val[A_ATOM], K(s->k));
 		break;
 
 	case BPF_ALU|BPF_ADD|BPF_X:
@@ -1028,17 +1051,17 @@
 	case BPF_ALU|BPF_LSH|BPF_X:
 	case BPF_ALU|BPF_RSH|BPF_X:
 		op = BPF_OP(s->code);
-		if (alter && vmap[val[X_ATOM]].is_const) {
-			if (vmap[val[A_ATOM]].is_const) {
-				fold_op(s, val[A_ATOM], val[X_ATOM]);
+		if (alter && opt_state->vmap[val[X_ATOM]].is_const) {
+			if (opt_state->vmap[val[A_ATOM]].is_const) {
+				fold_op(cstate, ic, opt_state, s, val[A_ATOM], val[X_ATOM]);
 				val[A_ATOM] = K(s->k);
 			}
 			else {
 				s->code = BPF_ALU|BPF_K|op;
-				s->k = vmap[val[X_ATOM]].const_val;
-				done = 0;
+				s->k = opt_state->vmap[val[X_ATOM]].const_val;
+				opt_state->done = 0;
 				val[A_ATOM] =
-					F(s->code, val[A_ATOM], K(s->k));
+					F(opt_state, s->code, val[A_ATOM], K(s->k));
 			}
 			break;
 		}
@@ -1049,8 +1072,8 @@
 		 * optimizations.
 		 * XXX We could also check for mul by 1, etc.
 		 */
-		if (alter && vmap[val[A_ATOM]].is_const
-		    && vmap[val[A_ATOM]].const_val == 0) {
+		if (alter && opt_state->vmap[val[A_ATOM]].is_const
+		    && opt_state->vmap[val[A_ATOM]].const_val == 0) {
 			if (op == BPF_ADD || op == BPF_OR || op == BPF_XOR) {
 				s->code = BPF_MISC|BPF_TXA;
 				vstore(s, &val[A_ATOM], val[X_ATOM], alter);
@@ -1068,7 +1091,7 @@
 				break;
 			}
 		}
-		val[A_ATOM] = F(s->code, val[A_ATOM], val[X_ATOM]);
+		val[A_ATOM] = F(opt_state, s->code, val[A_ATOM], val[X_ATOM]);
 		break;
 
 	case BPF_MISC|BPF_TXA:
@@ -1077,10 +1100,10 @@
 
 	case BPF_LD|BPF_MEM:
 		v = val[s->k];
-		if (alter && vmap[v].is_const) {
+		if (alter && opt_state->vmap[v].is_const) {
 			s->code = BPF_LD|BPF_IMM;
-			s->k = vmap[v].const_val;
-			done = 0;
+			s->k = opt_state->vmap[v].const_val;
+			opt_state->done = 0;
 		}
 		vstore(s, &val[A_ATOM], v, alter);
 		break;
@@ -1091,10 +1114,10 @@
 
 	case BPF_LDX|BPF_MEM:
 		v = val[s->k];
-		if (alter && vmap[v].is_const) {
+		if (alter && opt_state->vmap[v].is_const) {
 			s->code = BPF_LDX|BPF_IMM;
-			s->k = vmap[v].const_val;
-			done = 0;
+			s->k = opt_state->vmap[v].const_val;
+			opt_state->done = 0;
 		}
 		vstore(s, &val[X_ATOM], v, alter);
 		break;
@@ -1110,7 +1133,7 @@
 }
 
 static void
-deadstmt(register struct stmt *s, register struct stmt *last[])
+deadstmt(opt_state_t *opt_state, register struct stmt *s, register struct stmt *last[])
 {
 	register int atom;
 
@@ -1126,7 +1149,7 @@
 	atom = atomdef(s);
 	if (atom >= 0) {
 		if (last[atom]) {
-			done = 0;
+			opt_state->done = 0;
 			last[atom]->code = NOP;
 		}
 		last[atom] = s;
@@ -1134,7 +1157,7 @@
 }
 
 static void
-opt_deadstores(register struct block *b)
+opt_deadstores(opt_state_t *opt_state, register struct block *b)
 {
 	register struct slist *s;
 	register int atom;
@@ -1143,18 +1166,19 @@
 	memset((char *)last, 0, sizeof last);
 
 	for (s = b->stmts; s != 0; s = s->next)
-		deadstmt(&s->s, last);
-	deadstmt(&b->s, last);
+		deadstmt(opt_state, &s->s, last);
+	deadstmt(opt_state, &b->s, last);
 
 	for (atom = 0; atom < N_ATOMS; ++atom)
 		if (last[atom] && !ATOMELEM(b->out_use, atom)) {
 			last[atom]->code = NOP;
-			done = 0;
+			opt_state->done = 0;
 		}
 }
 
 static void
-opt_blk(struct block *b, int do_stmts)
+opt_blk(compiler_state_t *cstate, struct icode *ic, opt_state_t *opt_state,
+    struct block *b, int do_stmts)
 {
 	struct slist *s;
 	struct edge *p;
@@ -1204,7 +1228,7 @@
 	aval = b->val[A_ATOM];
 	xval = b->val[X_ATOM];
 	for (s = b->stmts; s; s = s->next)
-		opt_stmt(&s->s, b->val, do_stmts);
+		opt_stmt(cstate, ic, opt_state, &s->s, b->val, do_stmts);
 
 	/*
 	 * This is a special case: if we don't use anything from this
@@ -1235,11 +1259,11 @@
 	     BPF_CLASS(b->s.code) == BPF_RET)) {
 		if (b->stmts != 0) {
 			b->stmts = 0;
-			done = 0;
+			opt_state->done = 0;
 		}
 	} else {
-		opt_peep(b);
-		opt_deadstores(b);
+		opt_peep(opt_state, b);
+		opt_deadstores(opt_state, b);
 	}
 	/*
 	 * Set up values for branch optimizer.
@@ -1326,7 +1350,7 @@
 }
 
 static void
-opt_j(struct edge *ep)
+opt_j(opt_state_t *opt_state, struct edge *ep)
 {
 	register int i, k;
 	register struct block *target;
@@ -1340,7 +1364,7 @@
 		 * there is no data dependency.
 		 */
 		if (!use_conflict(ep->pred, ep->succ->et.succ)) {
-			done = 0;
+			opt_state->done = 0;
 			ep->succ = JT(ep->succ);
 		}
 	}
@@ -1352,7 +1376,7 @@
 	 * efficient loop.
 	 */
  top:
-	for (i = 0; i < edgewords; ++i) {
+	for (i = 0; i < opt_state->edgewords; ++i) {
 		register bpf_u_int32 x = ep->edom[i];
 
 		while (x != 0) {
@@ -1360,13 +1384,13 @@
 			x &=~ (1 << k);
 			k += i * BITS_PER_WORD;
 
-			target = fold_edge(ep->succ, edges[k]);
+			target = fold_edge(ep->succ, opt_state->edges[k]);
 			/*
 			 * Check that there is no data dependency between
 			 * nodes that will be violated if we move the edge.
 			 */
 			if (target != 0 && !use_conflict(ep->pred, target)) {
-				done = 0;
+				opt_state->done = 0;
 				ep->succ = target;
 				if (JT(target) != 0)
 					/*
@@ -1381,7 +1405,7 @@
 
 
 static void
-or_pullup(struct block *b)
+or_pullup(opt_state_t *opt_state, struct block *b)
 {
 	int val, at_top;
 	struct block *pull;
@@ -1469,11 +1493,11 @@
 	else
 		*diffp = pull;
 
-	done = 0;
+	opt_state->done = 0;
 }
 
 static void
-and_pullup(struct block *b)
+and_pullup(opt_state_t *opt_state, struct block *b)
 {
 	int val, at_top;
 	struct block *pull;
@@ -1560,22 +1584,23 @@
 	else
 		*diffp = pull;
 
-	done = 0;
+	opt_state->done = 0;
 }
 
 static void
-opt_blks(struct block *root, int do_stmts)
+opt_blks(compiler_state_t *cstate, opt_state_t *opt_state, struct icode *ic,
+    int do_stmts)
 {
 	int i, maxlevel;
 	struct block *p;
 
-	init_val();
-	maxlevel = root->level;
+	init_val(opt_state);
+	maxlevel = ic->root->level;
 
-	find_inedges(root);
+	find_inedges(opt_state, ic->root);
 	for (i = maxlevel; i >= 0; --i)
-		for (p = levels[i]; p; p = p->link)
-			opt_blk(p, do_stmts);
+		for (p = opt_state->levels[i]; p; p = p->link)
+			opt_blk(cstate, ic, opt_state, p, do_stmts);
 
 	if (do_stmts)
 		/*
@@ -1585,17 +1610,17 @@
 		return;
 
 	for (i = 1; i <= maxlevel; ++i) {
-		for (p = levels[i]; p; p = p->link) {
-			opt_j(&p->et);
-			opt_j(&p->ef);
+		for (p = opt_state->levels[i]; p; p = p->link) {
+			opt_j(opt_state, &p->et);
+			opt_j(opt_state, &p->ef);
 		}
 	}
 
-	find_inedges(root);
+	find_inedges(opt_state, ic->root);
 	for (i = 1; i <= maxlevel; ++i) {
-		for (p = levels[i]; p; p = p->link) {
-			or_pullup(p);
-			and_pullup(p);
+		for (p = opt_state->levels[i]; p; p = p->link) {
+			or_pullup(opt_state, p);
+			and_pullup(opt_state, p);
 		}
 	}
 }
@@ -1608,20 +1633,20 @@
 }
 
 static void
-find_inedges(struct block *root)
+find_inedges(opt_state_t *opt_state, struct block *root)
 {
 	int i;
 	struct block *b;
 
-	for (i = 0; i < n_blocks; ++i)
-		blocks[i]->in_edges = 0;
+	for (i = 0; i < opt_state->n_blocks; ++i)
+		opt_state->blocks[i]->in_edges = 0;
 
 	/*
 	 * Traverse the graph, adding each edge to the predecessor
 	 * list of its successors.  Skip the leaves (i.e. level 0).
 	 */
 	for (i = root->level; i > 0; --i) {
-		for (b = levels[i]; b != 0; b = b->link) {
+		for (b = opt_state->levels[i]; b != 0; b = b->link) {
 			link_inedge(&b->et, JT(b));
 			link_inedge(&b->ef, JF(b));
 		}
@@ -1653,83 +1678,82 @@
 }
 
 static void
-opt_loop(struct block *root, int do_stmts)
+opt_loop(compiler_state_t *cstate, opt_state_t *opt_state, struct icode *ic,
+    int do_stmts)
 {
 
 #ifdef BDEBUG
-	if (dflag > 1) {
+	if (pcap_optimizer_debug > 1) {
 		printf("opt_loop(root, %d) begin\n", do_stmts);
-		opt_dump(root);
+		opt_dump(cstate, ic);
 	}
 #endif
 	do {
-		done = 1;
-		find_levels(root);
-		find_dom(root);
-		find_closure(root);
-		find_ud(root);
-		find_edom(root);
-		opt_blks(root, do_stmts);
+		opt_state->done = 1;
+		find_levels(opt_state, ic);
+		find_dom(opt_state, ic->root);
+		find_closure(opt_state, ic->root);
+		find_ud(opt_state, ic->root);
+		find_edom(opt_state, ic->root);
+		opt_blks(cstate, opt_state, ic, do_stmts);
 #ifdef BDEBUG
-		if (dflag > 1) {
-			printf("opt_loop(root, %d) bottom, done=%d\n", do_stmts, done);
-			opt_dump(root);
+		if (pcap_optimizer_debug > 1) {
+			printf("opt_loop(root, %d) bottom, done=%d\n", do_stmts, opt_state->done);
+			opt_dump(cstate, ic);
 		}
 #endif
-	} while (!done);
+	} while (!opt_state->done);
 }
 
 /*
  * Optimize the filter code in its dag representation.
  */
 void
-bpf_optimize(struct block **rootp)
+bpf_optimize(compiler_state_t *cstate, struct icode *ic)
 {
-	struct block *root;
+	opt_state_t opt_state;
 
-	root = *rootp;
-
-	opt_init(root);
-	opt_loop(root, 0);
-	opt_loop(root, 1);
-	intern_blocks(root);
+	opt_init(cstate, &opt_state, ic);
+	opt_loop(cstate, &opt_state, ic, 0);
+	opt_loop(cstate, &opt_state, ic, 1);
+	intern_blocks(&opt_state, ic);
 #ifdef BDEBUG
-	if (dflag > 1) {
+	if (pcap_optimizer_debug > 1) {
 		printf("after intern_blocks()\n");
-		opt_dump(root);
+		opt_dump(cstate, ic);
 	}
 #endif
-	opt_root(rootp);
+	opt_root(&ic->root);
 #ifdef BDEBUG
-	if (dflag > 1) {
+	if (pcap_optimizer_debug > 1) {
 		printf("after opt_root()\n");
-		opt_dump(root);
+		opt_dump(cstate, ic);
 	}
 #endif
-	opt_cleanup();
+	opt_cleanup(&opt_state);
 }
 
 static void
-make_marks(struct block *p)
+make_marks(struct icode *ic, struct block *p)
 {
-	if (!isMarked(p)) {
-		Mark(p);
+	if (!isMarked(ic, p)) {
+		Mark(ic, p);
 		if (BPF_CLASS(p->s.code) != BPF_RET) {
-			make_marks(JT(p));
-			make_marks(JF(p));
+			make_marks(ic, JT(p));
+			make_marks(ic, JF(p));
 		}
 	}
 }
 
 /*
- * Mark code array such that isMarked(i) is true
+ * Mark code array such that isMarked(ic->cur_mark, i) is true
  * only for nodes that are alive.
  */
 static void
-mark_code(struct block *p)
+mark_code(struct icode *ic)
 {
-	cur_mark += 1;
-	make_marks(p);
+	ic->cur_mark += 1;
+	make_marks(ic, ic->root);
 }
 
 /*
@@ -1767,33 +1791,33 @@
 }
 
 static void
-intern_blocks(struct block *root)
+intern_blocks(opt_state_t *opt_state, struct icode *ic)
 {
 	struct block *p;
 	int i, j;
 	int done1; /* don't shadow global */
  top:
 	done1 = 1;
-	for (i = 0; i < n_blocks; ++i)
-		blocks[i]->link = 0;
+	for (i = 0; i < opt_state->n_blocks; ++i)
+		opt_state->blocks[i]->link = 0;
 
-	mark_code(root);
+	mark_code(ic);
 
-	for (i = n_blocks - 1; --i >= 0; ) {
-		if (!isMarked(blocks[i]))
+	for (i = opt_state->n_blocks - 1; --i >= 0; ) {
+		if (!isMarked(ic, opt_state->blocks[i]))
 			continue;
-		for (j = i + 1; j < n_blocks; ++j) {
-			if (!isMarked(blocks[j]))
+		for (j = i + 1; j < opt_state->n_blocks; ++j) {
+			if (!isMarked(ic, opt_state->blocks[j]))
 				continue;
-			if (eq_blk(blocks[i], blocks[j])) {
-				blocks[i]->link = blocks[j]->link ?
-					blocks[j]->link : blocks[j];
+			if (eq_blk(opt_state->blocks[i], opt_state->blocks[j])) {
+				opt_state->blocks[i]->link = opt_state->blocks[j]->link ?
+					opt_state->blocks[j]->link : opt_state->blocks[j];
 				break;
 			}
 		}
 	}
-	for (i = 0; i < n_blocks; ++i) {
-		p = blocks[i];
+	for (i = 0; i < opt_state->n_blocks; ++i) {
+		p = opt_state->blocks[i];
 		if (JT(p) == 0)
 			continue;
 		if (JT(p)->link) {
@@ -1810,14 +1834,14 @@
 }
 
 static void
-opt_cleanup(void)
+opt_cleanup(opt_state_t *opt_state)
 {
-	free((void *)vnode_base);
-	free((void *)vmap);
-	free((void *)edges);
-	free((void *)space);
-	free((void *)levels);
-	free((void *)blocks);
+	free((void *)opt_state->vnode_base);
+	free((void *)opt_state->vmap);
+	free((void *)opt_state->edges);
+	free((void *)opt_state->space);
+	free((void *)opt_state->levels);
+	free((void *)opt_state->blocks);
 }
 
 /*
@@ -1839,12 +1863,12 @@
  * All nodes should be initially unmarked.
  */
 static int
-count_blocks(struct block *p)
+count_blocks(struct icode *ic, struct block *p)
 {
-	if (p == 0 || isMarked(p))
+	if (p == 0 || isMarked(ic, p))
 		return 0;
-	Mark(p);
-	return count_blocks(JT(p)) + count_blocks(JF(p)) + 1;
+	Mark(ic, p);
+	return count_blocks(ic, JT(p)) + count_blocks(ic, JF(p)) + 1;
 }
 
 /*
@@ -1852,20 +1876,20 @@
  * the basic blocks, and entering them into the 'blocks' array.`
  */
 static void
-number_blks_r(struct block *p)
+number_blks_r(opt_state_t *opt_state, struct icode *ic, struct block *p)
 {
 	int n;
 
-	if (p == 0 || isMarked(p))
+	if (p == 0 || isMarked(ic, p))
 		return;
 
-	Mark(p);
-	n = n_blocks++;
+	Mark(ic, p);
+	n = opt_state->n_blocks++;
 	p->id = n;
-	blocks[n] = p;
+	opt_state->blocks[n] = p;
 
-	number_blks_r(JT(p));
-	number_blks_r(JF(p));
+	number_blks_r(opt_state, ic, JT(p));
+	number_blks_r(opt_state, ic, JF(p));
 }
 
 /*
@@ -1887,14 +1911,14 @@
  *	an extra long jump if the false branch requires it (p->longjf).
  */
 static u_int
-count_stmts(struct block *p)
+count_stmts(struct icode *ic, struct block *p)
 {
 	u_int n;
 
-	if (p == 0 || isMarked(p))
+	if (p == 0 || isMarked(ic, p))
 		return 0;
-	Mark(p);
-	n = count_stmts(JT(p)) + count_stmts(JF(p));
+	Mark(ic, p);
+	n = count_stmts(ic, JT(p)) + count_stmts(ic, JF(p));
 	return slength(p->stmts) + n + 1 + p->longjt + p->longjf;
 }
 
@@ -1904,7 +1928,7 @@
  * from the total number of blocks and/or statements.
  */
 static void
-opt_init(struct block *root)
+opt_init(compiler_state_t *cstate, opt_state_t *opt_state, struct icode *ic)
 {
 	bpf_u_int32 *p;
 	int i, n, max_stmts;
@@ -1913,84 +1937,81 @@
 	 * First, count the blocks, so we can malloc an array to map
 	 * block number to block.  Then, put the blocks into the array.
 	 */
-	unMarkAll();
-	n = count_blocks(root);
-	blocks = (struct block **)calloc(n, sizeof(*blocks));
-	if (blocks == NULL)
-		bpf_error("malloc");
-	unMarkAll();
-	n_blocks = 0;
-	number_blks_r(root);
+	unMarkAll(ic);
+	n = count_blocks(ic, ic->root);
+	opt_state->blocks = (struct block **)calloc(n, sizeof(*opt_state->blocks));
+	if (opt_state->blocks == NULL)
+		bpf_error(cstate, "malloc");
+	unMarkAll(ic);
+	opt_state->n_blocks = 0;
+	number_blks_r(opt_state, ic, ic->root);
 
-	n_edges = 2 * n_blocks;
-	edges = (struct edge **)calloc(n_edges, sizeof(*edges));
-	if (edges == NULL)
-		bpf_error("malloc");
+	opt_state->n_edges = 2 * opt_state->n_blocks;
+	opt_state->edges = (struct edge **)calloc(opt_state->n_edges, sizeof(*opt_state->edges));
+	if (opt_state->edges == NULL)
+		bpf_error(cstate, "malloc");
 
 	/*
 	 * The number of levels is bounded by the number of nodes.
 	 */
-	levels = (struct block **)calloc(n_blocks, sizeof(*levels));
-	if (levels == NULL)
-		bpf_error("malloc");
+	opt_state->levels = (struct block **)calloc(opt_state->n_blocks, sizeof(*opt_state->levels));
+	if (opt_state->levels == NULL)
+		bpf_error(cstate, "malloc");
 
-	edgewords = n_edges / (8 * sizeof(bpf_u_int32)) + 1;
-	nodewords = n_blocks / (8 * sizeof(bpf_u_int32)) + 1;
+	opt_state->edgewords = opt_state->n_edges / (8 * sizeof(bpf_u_int32)) + 1;
+	opt_state->nodewords = opt_state->n_blocks / (8 * sizeof(bpf_u_int32)) + 1;
 
 	/* XXX */
-	space = (bpf_u_int32 *)malloc(2 * n_blocks * nodewords * sizeof(*space)
-				 + n_edges * edgewords * sizeof(*space));
-	if (space == NULL)
-		bpf_error("malloc");
-	p = space;
-	all_dom_sets = p;
+	opt_state->space = (bpf_u_int32 *)malloc(2 * opt_state->n_blocks * opt_state->nodewords * sizeof(*opt_state->space)
+				 + opt_state->n_edges * opt_state->edgewords * sizeof(*opt_state->space));
+	if (opt_state->space == NULL)
+		bpf_error(cstate, "malloc");
+	p = opt_state->space;
+	opt_state->all_dom_sets = p;
 	for (i = 0; i < n; ++i) {
-		blocks[i]->dom = p;
-		p += nodewords;
+		opt_state->blocks[i]->dom = p;
+		p += opt_state->nodewords;
 	}
-	all_closure_sets = p;
+	opt_state->all_closure_sets = p;
 	for (i = 0; i < n; ++i) {
-		blocks[i]->closure = p;
-		p += nodewords;
+		opt_state->blocks[i]->closure = p;
+		p += opt_state->nodewords;
 	}
-	all_edge_sets = p;
+	opt_state->all_edge_sets = p;
 	for (i = 0; i < n; ++i) {
-		register struct block *b = blocks[i];
+		register struct block *b = opt_state->blocks[i];
 
 		b->et.edom = p;
-		p += edgewords;
+		p += opt_state->edgewords;
 		b->ef.edom = p;
-		p += edgewords;
+		p += opt_state->edgewords;
 		b->et.id = i;
-		edges[i] = &b->et;
-		b->ef.id = n_blocks + i;
-		edges[n_blocks + i] = &b->ef;
+		opt_state->edges[i] = &b->et;
+		b->ef.id = opt_state->n_blocks + i;
+		opt_state->edges[opt_state->n_blocks + i] = &b->ef;
 		b->et.pred = b;
 		b->ef.pred = b;
 	}
 	max_stmts = 0;
 	for (i = 0; i < n; ++i)
-		max_stmts += slength(blocks[i]->stmts) + 1;
+		max_stmts += slength(opt_state->blocks[i]->stmts) + 1;
 	/*
 	 * We allocate at most 3 value numbers per statement,
 	 * so this is an upper bound on the number of valnodes
 	 * we'll need.
 	 */
-	maxval = 3 * max_stmts;
-	vmap = (struct vmapinfo *)calloc(maxval, sizeof(*vmap));
-	vnode_base = (struct valnode *)calloc(maxval, sizeof(*vnode_base));
-	if (vmap == NULL || vnode_base == NULL)
-		bpf_error("malloc");
+	opt_state->maxval = 3 * max_stmts;
+	opt_state->vmap = (struct vmapinfo *)calloc(opt_state->maxval, sizeof(*opt_state->vmap));
+	opt_state->vnode_base = (struct valnode *)calloc(opt_state->maxval, sizeof(*opt_state->vnode_base));
+	if (opt_state->vmap == NULL || opt_state->vnode_base == NULL)
+		bpf_error(cstate, "malloc");
 }
 
 /*
- * Some pointers used to convert the basic block form of the code,
- * into the array form that BPF requires.  'fstart' will point to
- * the malloc'd array while 'ftail' is used during the recursive traversal.
+ * This is only used when supporting optimizer debugging.  It is
+ * global state, so do *not* do more than one compile in parallel
+ * and expect it to provide meaningful information.
  */
-static struct bpf_insn *fstart;
-static struct bpf_insn *ftail;
-
 #ifdef BDEBUG
 int bids[1000];
 #endif
@@ -2002,35 +2023,36 @@
  * properly.
  */
 static int
-convert_code_r(struct block *p)
+convert_code_r(compiler_state_t *cstate, conv_state_t *conv_state,
+    struct icode *ic, struct block *p)
 {
 	struct bpf_insn *dst;
 	struct slist *src;
-	int slen;
+	u_int slen;
 	u_int off;
 	int extrajmps;		/* number of extra jumps inserted */
 	struct slist **offset = NULL;
 
-	if (p == 0 || isMarked(p))
+	if (p == 0 || isMarked(ic, p))
 		return (1);
-	Mark(p);
+	Mark(ic, p);
 
-	if (convert_code_r(JF(p)) == 0)
+	if (convert_code_r(cstate, conv_state, ic, JF(p)) == 0)
 		return (0);
-	if (convert_code_r(JT(p)) == 0)
+	if (convert_code_r(cstate, conv_state, ic, JT(p)) == 0)
 		return (0);
 
 	slen = slength(p->stmts);
-	dst = ftail -= (slen + 1 + p->longjt + p->longjf);
+	dst = conv_state->ftail -= (slen + 1 + p->longjt + p->longjf);
 		/* inflate length by any extra jumps */
 
-	p->offset = dst - fstart;
+	p->offset = (int)(dst - conv_state->fstart);
 
 	/* generate offset[] for convenience  */
 	if (slen) {
 		offset = (struct slist **)calloc(slen, sizeof(struct slist *));
 		if (!offset) {
-			bpf_error("not enough core");
+			bpf_error(cstate, "not enough core");
 			/*NOTREACHED*/
 		}
 	}
@@ -2054,7 +2076,7 @@
 		if (BPF_CLASS(src->s.code) != BPF_JMP || src->s.code == (BPF_JMP|BPF_JA)) {
 #if 0
 			if (src->s.jt || src->s.jf) {
-				bpf_error("illegal jmp destination");
+				bpf_error(cstate, "illegal jmp destination");
 				/*NOTREACHED*/
 			}
 #endif
@@ -2064,7 +2086,7 @@
 			goto filled;
 
 	    {
-		int i;
+		u_int i;
 		int jt, jf;
 		const char *ljerr = "%s for block-local relative jump: off=%d";
 
@@ -2074,7 +2096,7 @@
 #endif
 
 		if (!src->s.jt || !src->s.jf) {
-			bpf_error(ljerr, "no jmp destination", off);
+			bpf_error(cstate, ljerr, "no jmp destination", off);
 			/*NOTREACHED*/
 		}
 
@@ -2082,7 +2104,7 @@
 		for (i = 0; i < slen; i++) {
 			if (offset[i] == src->s.jt) {
 				if (jt) {
-					bpf_error(ljerr, "multiple matches", off);
+					bpf_error(cstate, ljerr, "multiple matches", off);
 					/*NOTREACHED*/
 				}
 
@@ -2091,7 +2113,7 @@
 			}
 			if (offset[i] == src->s.jf) {
 				if (jf) {
-					bpf_error(ljerr, "multiple matches", off);
+					bpf_error(cstate, ljerr, "multiple matches", off);
 					/*NOTREACHED*/
 				}
 				dst->jf = i - off - 1;
@@ -2099,7 +2121,7 @@
 			}
 		}
 		if (!jt || !jf) {
-			bpf_error(ljerr, "no destination found", off);
+			bpf_error(cstate, ljerr, "no destination found", off);
 			/*NOTREACHED*/
 		}
 	    }
@@ -2111,7 +2133,7 @@
 		free(offset);
 
 #ifdef BDEBUG
-	bids[dst - fstart] = p->id + 1;
+	bids[dst - conv_state->fstart] = p->id + 1;
 #endif
 	dst->code = (u_short)p->s.code;
 	dst->k = p->s.k;
@@ -2174,28 +2196,30 @@
  * done with the filter program.  See the pcap man page.
  */
 struct bpf_insn *
-icode_to_fcode(struct block *root, u_int *lenp)
+icode_to_fcode(compiler_state_t *cstate, struct icode *ic,
+    struct block *root, u_int *lenp)
 {
 	u_int n;
 	struct bpf_insn *fp;
+	conv_state_t conv_state;
 
 	/*
 	 * Loop doing convert_code_r() until no branches remain
 	 * with too-large offsets.
 	 */
 	while (1) {
-	    unMarkAll();
-	    n = *lenp = count_stmts(root);
+	    unMarkAll(ic);
+	    n = *lenp = count_stmts(ic, root);
 
 	    fp = (struct bpf_insn *)malloc(sizeof(*fp) * n);
 	    if (fp == NULL)
-		    bpf_error("malloc");
+		    bpf_error(cstate, "malloc");
 	    memset((char *)fp, 0, sizeof(*fp) * n);
-	    fstart = fp;
-	    ftail = fp + n;
+	    conv_state.fstart = fp;
+	    conv_state.ftail = fp + n;
 
-	    unMarkAll();
-	    if (convert_code_r(root))
+	    unMarkAll(ic);
+	    if (convert_code_r(cstate, &conv_state, ic, root))
 		break;
 	    free(fp);
 	}
@@ -2220,7 +2244,7 @@
 	 * Validate the program.
 	 */
 	if (!bpf_validate(fp->bf_insns, fp->bf_len)) {
-		snprintf(p->errbuf, sizeof(p->errbuf),
+		pcap_snprintf(p->errbuf, sizeof(p->errbuf),
 			"BPF program is not valid");
 		return (-1);
 	}
@@ -2234,7 +2258,7 @@
 	p->fcode.bf_len = fp->bf_len;
 	p->fcode.bf_insns = (struct bpf_insn *)malloc(prog_size);
 	if (p->fcode.bf_insns == NULL) {
-		snprintf(p->errbuf, sizeof(p->errbuf),
+		pcap_snprintf(p->errbuf, sizeof(p->errbuf),
 			 "malloc: %s", pcap_strerror(errno));
 		return (-1);
 	}
@@ -2244,14 +2268,15 @@
 
 #ifdef BDEBUG
 static void
-dot_dump_node(struct block *block, struct bpf_program *prog, FILE *out)
+dot_dump_node(struct icode *ic, struct block *block, struct bpf_program *prog,
+    FILE *out)
 {
 	int icount, noffset;
 	int i;
 
-	if (block == NULL || isMarked(block))
+	if (block == NULL || isMarked(ic, block))
 		return;
-	Mark(block);
+	Mark(ic, block);
 
 	icount = slength(block->stmts) + 1 + block->longjt + block->longjf;
 	noffset = min(block->offset + icount, (int)prog->bf_len);
@@ -2271,15 +2296,16 @@
 		fprintf(out, ", peripheries=2");
 	fprintf(out, "];\n");
 
-	dot_dump_node(JT(block), prog, out);
-	dot_dump_node(JF(block), prog, out);
+	dot_dump_node(ic, JT(block), prog, out);
+	dot_dump_node(ic, JF(block), prog, out);
 }
+
 static void
-dot_dump_edge(struct block *block, FILE *out)
+dot_dump_edge(struct icode *ic, struct block *block, FILE *out)
 {
-	if (block == NULL || isMarked(block))
+	if (block == NULL || isMarked(ic, block))
 		return;
-	Mark(block);
+	Mark(ic, block);
 
 	if (JT(block)) {
 		fprintf(out, "\t\"block%d\":se -> \"block%d\":n [label=\"T\"]; \n",
@@ -2287,9 +2313,10 @@
 		fprintf(out, "\t\"block%d\":sw -> \"block%d\":n [label=\"F\"]; \n",
 			   block->id, JF(block)->id);
 	}
-	dot_dump_edge(JT(block), out);
-	dot_dump_edge(JF(block), out);
+	dot_dump_edge(ic, JT(block), out);
+	dot_dump_edge(ic, JF(block), out);
 }
+
 /* Output the block CFG using graphviz/DOT language
  * In the CFG, block's code, value index for each registers at EXIT,
  * and the jump relationship is show.
@@ -2310,46 +2337,48 @@
  *  and run `dot -Tpng -O bpf.dot' to draw the graph.
  */
 static void
-dot_dump(struct block *root)
+dot_dump(compiler_state_t *cstate, struct icode *ic)
 {
 	struct bpf_program f;
 	FILE *out = stdout;
 
 	memset(bids, 0, sizeof bids);
-	f.bf_insns = icode_to_fcode(root, &f.bf_len);
+	f.bf_insns = icode_to_fcode(cstate, ic, ic->root, &f.bf_len);
 
 	fprintf(out, "digraph BPF {\n");
-	unMarkAll();
-	dot_dump_node(root, &f, out);
-	unMarkAll();
-	dot_dump_edge(root, out);
+	ic->cur_mark = 0;
+	unMarkAll(ic);
+	dot_dump_node(ic, ic->root, &f, out);
+	ic->cur_mark = 0;
+	unMarkAll(ic);
+	dot_dump_edge(ic, ic->root, out);
 	fprintf(out, "}\n");
 
 	free((char *)f.bf_insns);
 }
 
 static void
-plain_dump(struct block *root)
+plain_dump(compiler_state_t *cstate, struct icode *ic)
 {
 	struct bpf_program f;
 
 	memset(bids, 0, sizeof bids);
-	f.bf_insns = icode_to_fcode(root, &f.bf_len);
+	f.bf_insns = icode_to_fcode(cstate, ic, ic->root, &f.bf_len);
 	bpf_dump(&f, 1);
 	putchar('\n');
 	free((char *)f.bf_insns);
 }
+
 static void
-opt_dump(struct block *root)
+opt_dump(compiler_state_t *cstate, struct icode *ic)
 {
 	/* if optimizer debugging is enabled, output DOT graph
-	 * `dflag=4' is equivalent to -dddd to follow -d/-dd/-ddd
-     * convention in tcpdump command line
+	 * `pcap_optimizer_debug=4' is equivalent to -dddd to follow -d/-dd/-ddd
+	 * convention in tcpdump command line
 	 */
-	if (dflag > 3)
-		dot_dump(root);
+	if (pcap_optimizer_debug > 3)
+		dot_dump(cstate, ic);
 	else
-		plain_dump(root);
+		plain_dump(cstate, ic);
 }
-
 #endif
diff --git a/pcap-bpf.c b/pcap-bpf.c
index b1da1a0..b765904 100644
--- a/pcap-bpf.c
+++ b/pcap-bpf.c
@@ -48,6 +48,15 @@
 #endif
 #include <sys/utsname.h>
 
+#if defined(__FreeBSD__) && defined(SIOCIFCREATE2)
+/*
+ * Add support for capturing on FreeBSD usbusN interfaces.
+ */
+static const char usbus_prefix[] = "usbus";
+#define USBUS_PREFIX_LEN	(sizeof(usbus_prefix) - 1)
+#include <dirent.h>
+#endif
+
 #ifdef HAVE_ZEROCOPY_BPF
 #include <machine/atomic.h>
 #endif
@@ -134,10 +143,6 @@
  * Private data for capturing on BPF devices.
  */
 struct pcap_bpf {
-#ifdef PCAP_FDDIPAD
-	int fddipad;
-#endif
-
 #ifdef HAVE_ZEROCOPY_BPF
 	/*
 	 * Zero-copy read buffer -- for zero-copy BPF.  'buffer' above will
@@ -171,10 +176,23 @@
  * Stuff to do when we close.
  */
 #define MUST_CLEAR_RFMON	0x00000001	/* clear rfmon (monitor) mode */
+#define MUST_DESTROY_USBUS	0x00000002	/* destroy usbusN interface */
 
 #ifdef BIOCGDLTLIST
 # if (defined(HAVE_NET_IF_MEDIA_H) && defined(IFM_IEEE80211)) && !defined(__APPLE__)
 #define HAVE_BSD_IEEE80211
+
+/*
+ * The ifm_ulist member of a struct ifmediareq is an int * on most systems,
+ * but it's a uint64_t on newer versions of OpenBSD.
+ *
+ * We check this by checking whether IFM_GMASK is defined and > 2^32-1.
+ */
+#  if defined(IFM_GMASK) && IFM_GMASK > 0xFFFFFFFF
+#    define IFM_ULIST_TYPE	uint64_t
+#  else
+#    define IFM_ULIST_TYPE	int
+#  endif
 # endif
 
 # if defined(__APPLE__) || defined(HAVE_BSD_IEEE80211)
@@ -347,7 +365,7 @@
 			if (data)
 				return (data);
 			if (ioctl(p->fd, BIOCROTZBUF, &bz) < 0) {
-				(void) snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
+				(void) pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
 				    "BIOCROTZBUF: %s", strerror(errno));
 				return (PCAP_ERROR);
 			}
@@ -375,7 +393,7 @@
 			}
 			return (0);
 		} else if (r < 0) {
-			(void) snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
+			(void) pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
 			    "select: %s", strerror(errno));
 			return (PCAP_ERROR);
 		}
@@ -394,7 +412,7 @@
 	 * data.
 	 */
 	if (ioctl(p->fd, BIOCROTZBUF, &bz) < 0) {
-		(void) snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
+		(void) pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
 		    "BIOCROTZBUF: %s", strerror(errno));
 		return (PCAP_ERROR);
 	}
@@ -419,16 +437,32 @@
 #endif /* HAVE_ZEROCOPY_BPF */
 
 pcap_t *
-pcap_create_interface(const char *device, char *ebuf)
+pcap_create_interface(const char *device _U_, char *ebuf)
 {
 	pcap_t *p;
 
-	p = pcap_create_common(device, ebuf, sizeof (struct pcap_bpf));
+	p = pcap_create_common(ebuf, sizeof (struct pcap_bpf));
 	if (p == NULL)
 		return (NULL);
 
 	p->activate_op = pcap_activate_bpf;
 	p->can_set_rfmon_op = pcap_can_set_rfmon_bpf;
+#ifdef BIOCSTSTAMP
+	/*
+	 * We claim that we support microsecond and nanosecond time
+	 * stamps.
+	 */
+	p->tstamp_precision_count = 2;
+	p->tstamp_precision_list = malloc(2 * sizeof(u_int));
+	if (p->tstamp_precision_list == NULL) {
+		snprintf(ebuf, PCAP_ERRBUF_SIZE, "malloc: %s",
+		    pcap_strerror(errno));
+		free(p);
+		return (NULL);
+	}
+	p->tstamp_precision_list[0] = PCAP_TSTAMP_PRECISION_MICRO;
+	p->tstamp_precision_list[1] = PCAP_TSTAMP_PRECISION_NANO;
+#endif /* BIOCSTSTAMP */
 	return (p);
 }
 
@@ -437,7 +471,7 @@
  * On failure, returns a PCAP_ERROR_ value, and sets p->errbuf.
  */
 static int
-bpf_open(pcap_t *p)
+bpf_open(char *errbuf)
 {
 	int fd;
 #ifdef HAVE_CLONING_BPF
@@ -453,7 +487,7 @@
 	 * and create the BPF device entries, if they don't
 	 * already exist.
 	 */
-	if (bpf_load(p->errbuf) == PCAP_ERROR)
+	if (bpf_load(errbuf) == PCAP_ERROR)
 		return (PCAP_ERROR);
 #endif
 
@@ -464,7 +498,7 @@
 			fd = PCAP_ERROR_PERM_DENIED;
 		else
 			fd = PCAP_ERROR;
-		snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
+		pcap_snprintf(errbuf, PCAP_ERRBUF_SIZE,
 		  "(cannot open device) %s: %s", device, pcap_strerror(errno));
 	}
 #else
@@ -472,7 +506,7 @@
 	 * Go through all the minors and find one that isn't in use.
 	 */
 	do {
-		(void)snprintf(device, sizeof(device), "/dev/bpf%d", n++);
+		(void)pcap_snprintf(device, sizeof(device), "/dev/bpf%d", n++);
 		/*
 		 * Initially try a read/write open (to allow the inject
 		 * method to work).  If that fails due to permission
@@ -506,7 +540,7 @@
 				 * means we probably have no BPF
 				 * devices.
 				 */
-				snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
+				pcap_snprintf(errbuf, PCAP_ERRBUF_SIZE,
 				    "(there are no BPF devices)");
 			} else {
 				/*
@@ -515,7 +549,7 @@
 				 * devices, but all the ones
 				 * that exist are busy.
 				 */
-				snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
+				pcap_snprintf(errbuf, PCAP_ERRBUF_SIZE,
 				    "(all BPF devices are busy)");
 			}
 			break;
@@ -527,7 +561,7 @@
 			 * if any.
 			 */
 			fd = PCAP_ERROR_PERM_DENIED;
-			snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
+			pcap_snprintf(errbuf, PCAP_ERRBUF_SIZE,
 			    "(cannot open BPF device) %s: %s", device,
 			    pcap_strerror(errno));
 			break;
@@ -537,7 +571,7 @@
 			 * Some other problem.
 			 */
 			fd = PCAP_ERROR;
-			snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
+			pcap_snprintf(errbuf, PCAP_ERRBUF_SIZE,
 			    "(cannot open BPF device) %s: %s", device,
 			    pcap_strerror(errno));
 			break;
@@ -548,6 +582,66 @@
 	return (fd);
 }
 
+/*
+ * Open and bind to a device; used if we're not actually going to use
+ * the device, but are just testing whether it can be opened, or opening
+ * it to get information about it.
+ *
+ * Returns an error code on failure (always negative), and an FD for
+ * the now-bound BPF device on success (always non-negative).
+ */
+static int
+bpf_open_and_bind(const char *name, char *errbuf)
+{
+	int fd;
+	struct ifreq ifr;
+
+	/*
+	 * First, open a BPF device.
+	 */
+	fd = bpf_open(errbuf);
+	if (fd < 0)
+		return (fd);	/* fd is the appropriate error code */
+
+	/*
+	 * Now bind to the device.
+	 */
+	(void)strncpy(ifr.ifr_name, name, sizeof(ifr.ifr_name));
+	if (ioctl(fd, BIOCSETIF, (caddr_t)&ifr) < 0) {
+		switch (errno) {
+
+		case ENXIO:
+			/*
+			 * There's no such device.
+			 */
+			close(fd);
+			return (PCAP_ERROR_NO_SUCH_DEVICE);
+
+		case ENETDOWN:
+			/*
+			 * Return a "network down" indication, so that
+			 * the application can report that rather than
+			 * saying we had a mysterious failure and
+			 * suggest that they report a problem to the
+			 * libpcap developers.
+			 */
+			close(fd);
+			return (PCAP_ERROR_IFACE_NOT_UP);
+
+		default:
+			pcap_snprintf(errbuf, PCAP_ERRBUF_SIZE,
+			    "BIOCSETIF: %s: %s", name, pcap_strerror(errno));
+			close(fd);
+			return (PCAP_ERROR);
+		}
+	}
+
+	/*
+	 * Success.
+	 */
+	return (fd);
+}
+
 #ifdef BIOCGDLTLIST
 static int
 get_dlt_list(int fd, int v, struct bpf_dltlist *bdlp, char *ebuf)
@@ -559,13 +653,13 @@
 
 		bdlp->bfl_list = (u_int *) malloc(sizeof(u_int) * (bdlp->bfl_len + 1));
 		if (bdlp->bfl_list == NULL) {
-			(void)snprintf(ebuf, PCAP_ERRBUF_SIZE, "malloc: %s",
+			(void)pcap_snprintf(ebuf, PCAP_ERRBUF_SIZE, "malloc: %s",
 			    pcap_strerror(errno));
 			return (PCAP_ERROR);
 		}
 
 		if (ioctl(fd, BIOCGDLTLIST, (caddr_t)bdlp) < 0) {
-			(void)snprintf(ebuf, PCAP_ERRBUF_SIZE,
+			(void)pcap_snprintf(ebuf, PCAP_ERRBUF_SIZE,
 			    "BIOCGDLTLIST: %s", pcap_strerror(errno));
 			free(bdlp->bfl_list);
 			return (PCAP_ERROR);
@@ -620,7 +714,7 @@
 		 * this device"; don't treat it as an error.
 		 */
 		if (errno != EINVAL) {
-			(void)snprintf(ebuf, PCAP_ERRBUF_SIZE,
+			(void)pcap_snprintf(ebuf, PCAP_ERRBUF_SIZE,
 			    "BIOCGDLTLIST: %s", pcap_strerror(errno));
 			return (PCAP_ERROR);
 		}
@@ -679,7 +773,7 @@
 		 * 10.4 (Darwin 8.x).  s/en/wlt/, and check
 		 * whether the device exists.
 		 */
-		if (strncmp(p->opt.source, "en", 2) != 0) {
+		if (strncmp(p->opt.device, "en", 2) != 0) {
 			/*
 			 * Not an enN device; no monitor mode.
 			 */
@@ -687,12 +781,12 @@
 		}
 		fd = socket(AF_INET, SOCK_DGRAM, 0);
 		if (fd == -1) {
-			(void)snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
+			(void)pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
 			    "socket: %s", pcap_strerror(errno));
 			return (PCAP_ERROR);
 		}
 		strlcpy(ifr.ifr_name, "wlt", sizeof(ifr.ifr_name));
-		strlcat(ifr.ifr_name, p->opt.source + 2, sizeof(ifr.ifr_name));
+		strlcat(ifr.ifr_name, p->opt.device + 2, sizeof(ifr.ifr_name));
 		if (ioctl(fd, SIOCGIFFLAGS, (char *)&ifr) < 0) {
 			/*
 			 * No such device?
@@ -712,14 +806,14 @@
 	 *
 	 * First, open a BPF device.
 	 */
-	fd = bpf_open(p);
+	fd = bpf_open(p->errbuf);
 	if (fd < 0)
 		return (fd);	/* fd is the appropriate error code */
 
 	/*
 	 * Now bind to the device.
 	 */
-	(void)strncpy(ifr.ifr_name, p->opt.source, sizeof(ifr.ifr_name));
+	(void)strncpy(ifr.ifr_name, p->opt.device, sizeof(ifr.ifr_name));
 	if (ioctl(fd, BIOCSETIF, (caddr_t)&ifr) < 0) {
 		switch (errno) {
 
@@ -742,9 +836,9 @@
 			return (PCAP_ERROR_IFACE_NOT_UP);
 
 		default:
-			snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
+			pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
 			    "BIOCSETIF: %s: %s",
-			    p->opt.source, pcap_strerror(errno));
+			    p->opt.device, pcap_strerror(errno));
 			close(fd);
 			return (PCAP_ERROR);
 		}
@@ -770,6 +864,7 @@
 		return (1);
 	}
 	free(bdl.bfl_list);
+	close(fd);
 #endif /* BIOCGDLTLIST */
 	return (0);
 #elif defined(HAVE_BSD_IEEE80211)
@@ -805,7 +900,7 @@
 	 * by libpcap, and thus not yet seen by the application.
 	 */
 	if (ioctl(p->fd, BIOCGSTATS, (caddr_t)&s) < 0) {
-		snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "BIOCGSTATS: %s",
+		pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "BIOCGSTATS: %s",
 		    pcap_strerror(errno));
 		return (PCAP_ERROR);
 	}
@@ -825,7 +920,7 @@
 	register u_char *bp, *ep;
 	u_char *datap;
 #ifdef PCAP_FDDIPAD
-	register int pad;
+	register u_int pad;
 #endif
 #ifdef HAVE_ZEROCOPY_BPF
 	int i;
@@ -866,7 +961,7 @@
 		} else
 #endif
 		{
-			cc = read(p->fd, (char *)p->buffer, p->bufsize);
+			cc = read(p->fd, p->buffer, p->bufsize);
 		}
 		if (cc < 0) {
 			/* Don't choke when we get ptraced */
@@ -914,7 +1009,7 @@
 				 * pcap_dispatch() etc. aren't
 				 * defined to retur that.
 				 */
-				snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
+				pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
 				    "The interface went down");
 				return (PCAP_ERROR);
 
@@ -933,24 +1028,28 @@
 				/* fall through */
 #endif
 			}
-			snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "read: %s",
+			pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "read: %s",
 			    pcap_strerror(errno));
 			return (PCAP_ERROR);
 		}
-		bp = p->buffer;
+		bp = (u_char *)p->buffer;
 	} else
 		bp = p->bp;
 
 	/*
 	 * Loop through each packet.
 	 */
+#ifdef BIOCSTSTAMP
+#define bhp ((struct bpf_xhdr *)bp)
+#else
 #define bhp ((struct bpf_hdr *)bp)
+#endif
 	ep = bp + cc;
 #ifdef PCAP_FDDIPAD
 	pad = p->fddipad;
 #endif
 	while (bp < ep) {
-		register int caplen, hdrlen;
+		register u_int caplen, hdrlen;
 
 		/*
 		 * Has "pcap_breakloop()" been called?
@@ -1006,7 +1105,25 @@
 		if (pb->filtering_in_kernel ||
 		    bpf_filter(p->fcode.bf_insns, datap, bhp->bh_datalen, caplen)) {
 			struct pcap_pkthdr pkthdr;
+#ifdef BIOCSTSTAMP
+			struct bintime bt;
 
+			bt.sec = bhp->bh_tstamp.bt_sec;
+			bt.frac = bhp->bh_tstamp.bt_frac;
+			if (p->opt.tstamp_precision == PCAP_TSTAMP_PRECISION_NANO) {
+				struct timespec ts;
+
+				bintime2timespec(&bt, &ts);
+				pkthdr.ts.tv_sec = ts.tv_sec;
+				pkthdr.ts.tv_usec = ts.tv_nsec;
+			} else {
+				struct timeval tv;
+
+				bintime2timeval(&bt, &tv);
+				pkthdr.ts.tv_sec = tv.tv_sec;
+				pkthdr.ts.tv_usec = tv.tv_usec;
+			}
+#else
 			pkthdr.ts.tv_sec = bhp->bh_tstamp.tv_sec;
 #ifdef _AIX
 			/*
@@ -1017,6 +1134,7 @@
 #else
 			pkthdr.ts.tv_usec = bhp->bh_tstamp.tv_usec;
 #endif
+#endif /* BIOCSTSTAMP */
 #ifdef PCAP_FDDIPAD
 			if (caplen > pad)
 				pkthdr.caplen = caplen - pad;
@@ -1084,7 +1202,7 @@
 		u_int spoof_eth_src = 0;
 
 		if (ioctl(p->fd, BIOCSHDRCMPLT, &spoof_eth_src) == -1) {
-			(void)snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
+			(void)pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
 			    "send: can't turn off BIOCSHDRCMPLT: %s",
 			    pcap_strerror(errno));
 			return (PCAP_ERROR);
@@ -1097,7 +1215,7 @@
 	}
 #endif /* __APPLE__ */
 	if (ret == -1) {
-		snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "send: %s",
+		pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "send: %s",
 		    pcap_strerror(errno));
 		return (PCAP_ERROR);
 	}
@@ -1113,7 +1231,7 @@
 	if (odm_initialize() == -1) {
 		if (odm_err_msg(odmerrno, &errstr) == -1)
 			errstr = "Unknown error";
-		snprintf(errbuf, PCAP_ERRBUF_SIZE,
+		pcap_snprintf(errbuf, PCAP_ERRBUF_SIZE,
 		    "bpf_load: odm_initialize failed: %s",
 		    errstr);
 		return (PCAP_ERROR);
@@ -1122,7 +1240,7 @@
 	if ((odmlockid = odm_lock("/etc/objrepos/config_lock", ODM_WAIT)) == -1) {
 		if (odm_err_msg(odmerrno, &errstr) == -1)
 			errstr = "Unknown error";
-		snprintf(errbuf, PCAP_ERRBUF_SIZE,
+		pcap_snprintf(errbuf, PCAP_ERRBUF_SIZE,
 		    "bpf_load: odm_lock of /etc/objrepos/config_lock failed: %s",
 		    errstr);
 		(void)odm_terminate();
@@ -1141,7 +1259,7 @@
 		if (errbuf != NULL) {
 			if (odm_err_msg(odmerrno, &errstr) == -1)
 				errstr = "Unknown error";
-			snprintf(errbuf, PCAP_ERRBUF_SIZE,
+			pcap_snprintf(errbuf, PCAP_ERRBUF_SIZE,
 			    "bpf_load: odm_unlock failed: %s",
 			    errstr);
 		}
@@ -1152,7 +1270,7 @@
 		if (errbuf != NULL) {
 			if (odm_err_msg(odmerrno, &errstr) == -1)
 				errstr = "Unknown error";
-			snprintf(errbuf, PCAP_ERRBUF_SIZE,
+			pcap_snprintf(errbuf, PCAP_ERRBUF_SIZE,
 			    "bpf_load: odm_terminate failed: %s",
 			    errstr);
 		}
@@ -1186,7 +1304,7 @@
 
 	major = genmajor(BPF_NAME);
 	if (major == -1) {
-		snprintf(errbuf, PCAP_ERRBUF_SIZE,
+		pcap_snprintf(errbuf, PCAP_ERRBUF_SIZE,
 		    "bpf_load: genmajor failed: %s", pcap_strerror(errno));
 		(void)bpf_odmcleanup(NULL);
 		return (PCAP_ERROR);
@@ -1196,7 +1314,7 @@
 	if (!minors) {
 		minors = genminor("bpf", major, 0, BPF_MINORS, 1, 1);
 		if (!minors) {
-			snprintf(errbuf, PCAP_ERRBUF_SIZE,
+			pcap_snprintf(errbuf, PCAP_ERRBUF_SIZE,
 			    "bpf_load: genminor failed: %s",
 			    pcap_strerror(errno));
 			(void)bpf_odmcleanup(NULL);
@@ -1209,7 +1327,7 @@
 
 	rc = stat(BPF_NODE "0", &sbuf);
 	if (rc == -1 && errno != ENOENT) {
-		snprintf(errbuf, PCAP_ERRBUF_SIZE,
+		pcap_snprintf(errbuf, PCAP_ERRBUF_SIZE,
 		    "bpf_load: can't stat %s: %s",
 		    BPF_NODE "0", pcap_strerror(errno));
 		return (PCAP_ERROR);
@@ -1220,7 +1338,7 @@
 			sprintf(buf, "%s%d", BPF_NODE, i);
 			unlink(buf);
 			if (mknod(buf, S_IRUSR | S_IFCHR, domakedev(major, i)) == -1) {
-				snprintf(errbuf, PCAP_ERRBUF_SIZE,
+				pcap_snprintf(errbuf, PCAP_ERRBUF_SIZE,
 				    "bpf_load: can't mknod %s: %s",
 				    buf, pcap_strerror(errno));
 				return (PCAP_ERROR);
@@ -1236,7 +1354,7 @@
 	    (cfg_ld.kmid == 0)) {
 		/* Driver isn't loaded, load it now */
 		if (sysconfig(SYS_SINGLELOAD, (void *)&cfg_ld, sizeof(cfg_ld)) == -1) {
-			snprintf(errbuf, PCAP_ERRBUF_SIZE,
+			pcap_snprintf(errbuf, PCAP_ERRBUF_SIZE,
 			    "bpf_load: could not load driver: %s",
 			    strerror(errno));
 			return (PCAP_ERROR);
@@ -1251,7 +1369,7 @@
 	for (i = 0; i < BPF_MINORS; i++) {
 		cfg_bpf.devno = domakedev(major, i);
 		if (sysconfig(SYS_CFGKMOD, (void *)&cfg_km, sizeof(cfg_km)) == -1) {
-			snprintf(errbuf, PCAP_ERRBUF_SIZE,
+			pcap_snprintf(errbuf, PCAP_ERRBUF_SIZE,
 			    "bpf_load: could not configure driver: %s",
 			    strerror(errno));
 			return (PCAP_ERROR);
@@ -1265,7 +1383,7 @@
 #endif
 
 /*
- * Turn off rfmon mode if necessary.
+ * Undo any operations done when opening the device when necessary.
  */
 static void
 pcap_cleanup_bpf(pcap_t *p)
@@ -1333,6 +1451,24 @@
 		}
 #endif /* HAVE_BSD_IEEE80211 */
 
+#if defined(__FreeBSD__) && defined(SIOCIFCREATE2)
+		/*
+		 * Attempt to destroy the usbusN interface that we created.
+		 */
+		if (pb->must_do_on_close & MUST_DESTROY_USBUS) {
+			if (if_nametoindex(pb->device) > 0) {
+				int s;
+
+				s = socket(AF_LOCAL, SOCK_DGRAM, 0);
+				if (s >= 0) {
+					strlcpy(ifr.ifr_name, pb->device,
+					    sizeof(ifr.ifr_name));
+					ioctl(s, SIOCIFDESTROY, &ifr);
+					close(s);
+				}
+			}
+		}
+#endif /* defined(__FreeBSD__) && defined(SIOCIFCREATE2) */
 		/*
 		 * Take this pcap out of the list of pcaps for which we
 		 * have to take the interface out of some mode.
@@ -1378,7 +1514,7 @@
 		 * No such device exists.
 		 */
 #ifdef __APPLE__
-		if (p->opt.rfmon && strncmp(p->opt.source, "wlt", 3) == 0) {
+		if (p->opt.rfmon && strncmp(p->opt.device, "wlt", 3) == 0) {
 			/*
 			 * Monitor mode was requested, and we're trying
 			 * to open a "wltN" device.  Assume that this
@@ -1390,7 +1526,7 @@
 			if (fd != -1) {
 				strlcpy(ifr.ifr_name, "en",
 				    sizeof(ifr.ifr_name));
-				strlcat(ifr.ifr_name, p->opt.source + 3,
+				strlcat(ifr.ifr_name, p->opt.device + 3,
 				    sizeof(ifr.ifr_name));
 				if (ioctl(fd, SIOCGIFFLAGS, (char *)&ifr) < 0) {
 					/*
@@ -1399,7 +1535,7 @@
 					 * exist.
 					 */
 					err = PCAP_ERROR_NO_SUCH_DEVICE;
-					snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
+					pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
 					    "SIOCGIFFLAGS on %s failed: %s",
 					    ifr.ifr_name, pcap_strerror(errno));
 				} else {
@@ -1423,7 +1559,7 @@
 				 * just report "no such device".
 				 */
 				err = PCAP_ERROR_NO_SUCH_DEVICE;
-				snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
+				pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
 				    "socket() failed: %s",
 				    pcap_strerror(errno));
 			}
@@ -1433,7 +1569,7 @@
 		/*
 		 * No such device.
 		 */
-		snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "BIOCSETIF failed: %s",
+		pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "BIOCSETIF failed: %s",
 		    pcap_strerror(errno));
 		return (PCAP_ERROR_NO_SUCH_DEVICE);
 	} else if (errno == ENETDOWN) {
@@ -1450,8 +1586,8 @@
 		 * Some other error; fill in the error string, and
 		 * return PCAP_ERROR.
 		 */
-		snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "BIOCSETIF: %s: %s",
-		    p->opt.source, pcap_strerror(errno));
+		pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "BIOCSETIF: %s: %s",
+		    p->opt.device, pcap_strerror(errno));
 		return (PCAP_ERROR);
 	}
 }
@@ -1514,7 +1650,7 @@
 	u_int bufmode, zbufmax;
 #endif
 
-	fd = bpf_open(p);
+	fd = bpf_open(p->errbuf);
 	if (fd < 0) {
 		status = fd;
 		goto bad;
@@ -1523,14 +1659,14 @@
 	p->fd = fd;
 
 	if (ioctl(fd, BIOCVERSION, (caddr_t)&bv) < 0) {
-		snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "BIOCVERSION: %s",
+		pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "BIOCVERSION: %s",
 		    pcap_strerror(errno));
 		status = PCAP_ERROR;
 		goto bad;
 	}
 	if (bv.bv_major != BPF_MAJOR_VERSION ||
 	    bv.bv_minor < BPF_MINOR_VERSION) {
-		snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
+		pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
 		    "kernel bpf filter out of date");
 		status = PCAP_ERROR;
 		goto bad;
@@ -1541,7 +1677,7 @@
 	 * Retrieve the zoneid of the zone we are currently executing in.
 	 */
 	if ((ifr.lifr_zoneid = getzoneid()) == -1) {
-		snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "getzoneid(): %s",
+		pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "getzoneid(): %s",
 		    pcap_strerror(errno));
 		status = PCAP_ERROR;
 		goto bad;
@@ -1553,36 +1689,42 @@
 	 * traffic on datalinks in non-global zones.  Non-global zones
 	 * do not have access to datalinks outside of their own namespace.
 	 */
-	if ((zonesep = strchr(p->opt.source, '/')) != NULL) {
+	if ((zonesep = strchr(p->opt.device, '/')) != NULL) {
 		char path_zname[ZONENAME_MAX];
 		int  znamelen;
 		char *lnamep;
 
 		if (ifr.lifr_zoneid != GLOBAL_ZONEID) {
-			snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
+			pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
 			    "zonename/linkname only valid in global zone.");
 			status = PCAP_ERROR;
 			goto bad;
 		}
-		znamelen = zonesep - p->opt.source;
-		(void) strlcpy(path_zname, p->opt.source, znamelen + 1);
+		znamelen = zonesep - p->opt.device;
+		(void) strlcpy(path_zname, p->opt.device, znamelen + 1);
 		ifr.lifr_zoneid = getzoneidbyname(path_zname);
 		if (ifr.lifr_zoneid == -1) {
-			snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
+			pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
 			    "getzoneidbyname(%s): %s", path_zname,
 			pcap_strerror(errno));
 			status = PCAP_ERROR;
 			goto bad;
 		}
 		lnamep = strdup(zonesep + 1);
-		free(p->opt.source);
-		p->opt.source = lnamep;
+		if (lnamep == NULL) {
+			pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "strdup: %s",
+			    pcap_strerror(errno));
+			status = PCAP_ERROR;
+			goto bad;
+		}
+		free(p->opt.device);
+		p->opt.device = lnamep;
 	}
 #endif
 
-	pb->device = strdup(p->opt.source);
+	pb->device = strdup(p->opt.device);
 	if (pb->device == NULL) {
-		snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "strdup: %s",
+		pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "strdup: %s",
 		     pcap_strerror(errno));
 		status = PCAP_ERROR;
 		goto bad;
@@ -1618,7 +1760,7 @@
 				/*
 				 * 10.4 (Darwin 8.x).  s/en/wlt/
 				 */
-				if (strncmp(p->opt.source, "en", 2) != 0) {
+				if (strncmp(p->opt.device, "en", 2) != 0) {
 					/*
 					 * Not an enN device; check
 					 * whether the device even exists.
@@ -1626,7 +1768,7 @@
 					sockfd = socket(AF_INET, SOCK_DGRAM, 0);
 					if (sockfd != -1) {
 						strlcpy(ifrname,
-						    p->opt.source, ifnamsiz);
+						    p->opt.device, ifnamsiz);
 						if (ioctl(sockfd, SIOCGIFFLAGS,
 						    (char *)&ifr) < 0) {
 							/*
@@ -1637,7 +1779,7 @@
 							 * exist.
 							 */
 							status = PCAP_ERROR_NO_SUCH_DEVICE;
-							snprintf(p->errbuf,
+							pcap_snprintf(p->errbuf,
 							    PCAP_ERRBUF_SIZE,
 							    "SIOCGIFFLAGS failed: %s",
 							    pcap_strerror(errno));
@@ -1651,25 +1793,25 @@
 						 * report "no such device".
 						 */
 						status = PCAP_ERROR_NO_SUCH_DEVICE;
-						snprintf(p->errbuf,
+						pcap_snprintf(p->errbuf,
 						    PCAP_ERRBUF_SIZE,
 						    "socket() failed: %s",
 						    pcap_strerror(errno));
 					}
 					goto bad;
 				}
-				wltdev = malloc(strlen(p->opt.source) + 2);
+				wltdev = malloc(strlen(p->opt.device) + 2);
 				if (wltdev == NULL) {
-					(void)snprintf(p->errbuf,
+					(void)pcap_snprintf(p->errbuf,
 					    PCAP_ERRBUF_SIZE, "malloc: %s",
 					    pcap_strerror(errno));
 					status = PCAP_ERROR;
 					goto bad;
 				}
 				strcpy(wltdev, "wlt");
-				strcat(wltdev, p->opt.source + 2);
-				free(p->opt.source);
-				p->opt.source = wltdev;
+				strcat(wltdev, p->opt.device + 2);
+				free(p->opt.device);
+				p->opt.device = wltdev;
 			}
 			/*
 			 * Everything else is 10.5 or later; for those,
@@ -1678,6 +1820,85 @@
 		}
 	}
 #endif /* __APPLE__ */
+
+	/*
+	 * If this is FreeBSD, and the device name begins with "usbus",
+	 * try to create the interface if it's not available.
+	 */
+#if defined(__FreeBSD__) && defined(SIOCIFCREATE2)
+	if (strncmp(p->opt.device, usbus_prefix, USBUS_PREFIX_LEN) == 0) {
+		/*
+		 * Do we already have an interface with that name?
+		 */
+		if (if_nametoindex(p->opt.device) == 0) {
+			/*
+			 * No.  We need to create it, and, if we
+			 * succeed, remember that we should destroy
+			 * it when the pcap_t is closed.
+			 */
+			int s;
+
+			/*
+			 * Open a socket to use for ioctls to
+			 * create the interface.
+			 */
+			s = socket(AF_LOCAL, SOCK_DGRAM, 0);
+			if (s < 0) {
+				pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
+				    "Can't open socket: %s",
+				    pcap_strerror(errno));
+				status = PCAP_ERROR;
+				goto bad;
+			}
+
+			/*
+			 * If we haven't already done so, arrange to have
+			 * "pcap_close_all()" called when we exit.
+			 */
+			if (!pcap_do_addexit(p)) {
+				/*
+				 * "atexit()" failed; don't create the
+				 * interface, just give up.
+				 */
+				pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
+				     "atexit failed");
+				close(s);
+				status = PCAP_ERROR;
+				goto bad;
+			}
+
+			/*
+			 * Create the interface.
+			 */
+			strlcpy(ifr.ifr_name, p->opt.device, sizeof(ifr.ifr_name));
+			if (ioctl(s, SIOCIFCREATE2, &ifr) < 0) {
+				if (errno == EINVAL) {
+					pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
+					    "Invalid USB bus interface %s",
+					    p->opt.device);
+				} else {
+					pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
+					    "Can't create interface for %s: %s",
+					    p->opt.device, pcap_strerror(errno));
+				}
+				close(s);
+				status = PCAP_ERROR;
+				goto bad;
+			}
+
+			/*
+			 * Make sure we clean this up when we close.
+			 */
+			pb->must_do_on_close |= MUST_DESTROY_USBUS;
+
+			/*
+			 * Add this to the list of pcaps to close when we exit.
+			 */
+			pcap_add_to_pcaps_to_close(p);
+		}
+	}
+#endif /* defined(__FreeBSD__) && defined(SIOCIFCREATE2) */
+
 #ifdef HAVE_ZEROCOPY_BPF
 	/*
 	 * If the BPF extension to set buffer mode is present, try setting
@@ -1701,7 +1922,7 @@
 		 * size.
 		 */
 		if (ioctl(fd, BIOCGETZMAX, (caddr_t)&zbufmax) < 0) {
-			snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "BIOCGETZMAX: %s",
+			pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "BIOCGETZMAX: %s",
 			    pcap_strerror(errno));
 			status = PCAP_ERROR;
 			goto bad;
@@ -1728,7 +1949,7 @@
 		pb->zbuf2 = mmap(NULL, pb->zbufsize, PROT_READ | PROT_WRITE,
 		    MAP_ANON, -1, 0);
 		if (pb->zbuf1 == MAP_FAILED || pb->zbuf2 == MAP_FAILED) {
-			snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "mmap: %s",
+			pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "mmap: %s",
 			    pcap_strerror(errno));
 			status = PCAP_ERROR;
 			goto bad;
@@ -1738,15 +1959,15 @@
 		bz.bz_bufb = pb->zbuf2;
 		bz.bz_buflen = pb->zbufsize;
 		if (ioctl(fd, BIOCSETZBUF, (caddr_t)&bz) < 0) {
-			snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "BIOCSETZBUF: %s",
+			pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "BIOCSETZBUF: %s",
 			    pcap_strerror(errno));
 			status = PCAP_ERROR;
 			goto bad;
 		}
-		(void)strncpy(ifrname, p->opt.source, ifnamsiz);
+		(void)strncpy(ifrname, p->opt.device, ifnamsiz);
 		if (ioctl(fd, BIOCSETIF, (caddr_t)&ifr) < 0) {
-			snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "BIOCSETIF: %s: %s",
-			    p->opt.source, pcap_strerror(errno));
+			pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "BIOCSETIF: %s: %s",
+			    p->opt.device, pcap_strerror(errno));
 			status = PCAP_ERROR;
 			goto bad;
 		}
@@ -1764,8 +1985,8 @@
 			 */
 			if (ioctl(fd, BIOCSBLEN,
 			    (caddr_t)&p->opt.buffer_size) < 0) {
-				snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
-				    "BIOCSBLEN: %s: %s", p->opt.source,
+				pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
+				    "BIOCSBLEN: %s: %s", p->opt.device,
 				    pcap_strerror(errno));
 				status = PCAP_ERROR;
 				goto bad;
@@ -1774,7 +1995,7 @@
 			/*
 			 * Now bind to the device.
 			 */
-			(void)strncpy(ifrname, p->opt.source, ifnamsiz);
+			(void)strncpy(ifrname, p->opt.device, ifnamsiz);
 #ifdef BIOCSETLIF
 			if (ioctl(fd, BIOCSETLIF, (caddr_t)&ifr) < 0)
 #else
@@ -1807,7 +2028,7 @@
 				 */
 				(void) ioctl(fd, BIOCSBLEN, (caddr_t)&v);
 
-				(void)strncpy(ifrname, p->opt.source, ifnamsiz);
+				(void)strncpy(ifrname, p->opt.device, ifnamsiz);
 #ifdef BIOCSETLIF
 				if (ioctl(fd, BIOCSETLIF, (caddr_t)&ifr) >= 0)
 #else
@@ -1822,9 +2043,9 @@
 			}
 
 			if (v == 0) {
-				snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
+				pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
 				    "BIOCSBLEN: %s: No buffer size worked",
-				    p->opt.source);
+				    p->opt.device);
 				status = PCAP_ERROR;
 				goto bad;
 			}
@@ -1833,7 +2054,7 @@
 
 	/* Get the data link layer type. */
 	if (ioctl(fd, BIOCGDLT, (caddr_t)&v) < 0) {
-		snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "BIOCGDLT: %s",
+		pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "BIOCGDLT: %s",
 		    pcap_strerror(errno));
 		status = PCAP_ERROR;
 		goto bad;
@@ -1866,7 +2087,7 @@
 		/*
 		 * We don't know what to map this to yet.
 		 */
-		snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "unknown interface type %u",
+		pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "unknown interface type %u",
 		    v);
 		status = PCAP_ERROR;
 		goto bad;
@@ -1954,7 +2175,7 @@
 					 * the default mode, attempt to
 					 * select the new mode.
 					 */
-					if (new_dlt != v) {
+					if ((u_int)new_dlt != v) {
 						if (ioctl(p->fd, BIOCSDLT,
 						    &new_dlt) != -1) {
 							/*
@@ -2026,7 +2247,7 @@
 			 * If the new mode we want isn't the default mode,
 			 * attempt to select the new mode.
 			 */
-			if (new_dlt != v) {
+			if ((u_int)new_dlt != v) {
 				if (ioctl(p->fd, BIOCSDLT, &new_dlt) != -1) {
 					/*
 					 * We succeeded; make this the
@@ -2078,7 +2299,7 @@
 	 * BSDs - check CVS log for "bpf.c"?
 	 */
 	if (ioctl(fd, BIOCSHDRCMPLT, &spoof_eth_src) == -1) {
-		(void)snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
+		(void)pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
 		    "BIOCSHDRCMPLT: %s", pcap_strerror(errno));
 		status = PCAP_ERROR;
 		goto bad;
@@ -2120,7 +2341,7 @@
 			bpf_to.tv_sec = p->opt.timeout / 1000;
 			bpf_to.tv_usec = (p->opt.timeout * 1000) % 1000000;
 			if (ioctl(p->fd, BIOCSRTIMEOUT, (caddr_t)&bpf_to) < 0) {
-				snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
+				pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
 				    "BIOCSRTIMEOUT: %s", pcap_strerror(errno));
 				status = PCAP_ERROR;
 				goto bad;
@@ -2130,7 +2351,7 @@
 			to.tv_sec = p->opt.timeout / 1000;
 			to.tv_usec = (p->opt.timeout * 1000) % 1000000;
 			if (ioctl(p->fd, BIOCSRTIMEOUT, (caddr_t)&to) < 0) {
-				snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
+				pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
 				    "BIOCSRTIMEOUT: %s", pcap_strerror(errno));
 				status = PCAP_ERROR;
 				goto bad;
@@ -2165,7 +2386,7 @@
 #endif /* _AIX */
 		v = 1;
 		if (ioctl(p->fd, BIOCIMMEDIATE, &v) < 0) {
-			snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
+			pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
 			    "BIOCIMMEDIATE: %s", pcap_strerror(errno));
 			status = PCAP_ERROR;
 			goto bad;
@@ -2178,7 +2399,7 @@
 		/*
 		 * We don't support immediate mode.  Fail.
 		 */
-		snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "Immediate mode not supported");
+		pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "Immediate mode not supported");
 		status = PCAP_ERROR;
 		goto bad;
 	}
@@ -2187,14 +2408,24 @@
 	if (p->opt.promisc) {
 		/* set promiscuous mode, just warn if it fails */
 		if (ioctl(p->fd, BIOCPROMISC, NULL) < 0) {
-			snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "BIOCPROMISC: %s",
+			pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "BIOCPROMISC: %s",
 			    pcap_strerror(errno));
 			status = PCAP_WARNING_PROMISC_NOTSUP;
 		}
 	}
 
+#ifdef BIOCSTSTAMP
+	v = BPF_T_BINTIME;
+	if (ioctl(p->fd, BIOCSTSTAMP, &v) < 0) {
+		snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "BIOCSTSTAMP: %s",
+		    pcap_strerror(errno));
+		status = PCAP_ERROR;
+		goto bad;
+	}
+#endif /* BIOCSTSTAMP */
+
 	if (ioctl(fd, BIOCGBLEN, (caddr_t)&v) < 0) {
-		snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "BIOCGBLEN: %s",
+		pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "BIOCGBLEN: %s",
 		    pcap_strerror(errno));
 		status = PCAP_ERROR;
 		goto bad;
@@ -2203,9 +2434,9 @@
 #ifdef HAVE_ZEROCOPY_BPF
 	if (!pb->zerocopy) {
 #endif
-	p->buffer = (u_char *)malloc(p->bufsize);
+	p->buffer = malloc(p->bufsize);
 	if (p->buffer == NULL) {
-		snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "malloc: %s",
+		pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "malloc: %s",
 		    pcap_strerror(errno));
 		status = PCAP_ERROR;
 		goto bad;
@@ -2236,7 +2467,7 @@
 	total_prog.bf_len = 1;
 	total_prog.bf_insns = &total_insn;
 	if (ioctl(p->fd, BIOCSETF, (caddr_t)&total_prog) < 0) {
-		snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "BIOCSETF: %s",
+		pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "BIOCSETF: %s",
 		    pcap_strerror(errno));
 		status = PCAP_ERROR;
 		goto bad;
@@ -2306,9 +2537,136 @@
 	return (status);
 }
 
+/*
+ * Not all interfaces can be bound to by BPF, so try to bind to
+ * the specified interface; return 0 if we fail with
+ * PCAP_ERROR_NO_SUCH_DEVICE (which means we got an ENXIO when we tried
+ * to bind, which means this interface isn't in the list of interfaces
+ * attached to BPF) and 1 otherwise.
+ */
+static int
+check_bpf_bindable(const char *name)
+{
+	int fd;
+	char errbuf[PCAP_ERRBUF_SIZE];
+
+	fd = bpf_open_and_bind(name, errbuf);
+	if (fd < 0) {
+		/*
+		 * Error - was it PCAP_ERROR_NO_SUCH_DEVICE?
+		 */
+		if (fd == PCAP_ERROR_NO_SUCH_DEVICE) {
+			/*
+			 * Yes, so we can't bind to this because it's
+			 * not something supported by BPF.
+			 */
+			return (0);
+		}
+		/*
+		 * No, so we don't know whether it's supported or not;
+		 * say it is, so that the user can at least try to
+		 * open it and report the error (which is probably
+		 * "you don't have permission to open BPF devices";
+		 * reporting those interfaces means users will ask
+		 * "why am I getting a permissions error when I try
+		 * to capture" rather than "why am I not seeing any
+		 * interfaces", making the underlying problem clearer).
+		 */
+		return (1);
+	}
+
+	/*
+	 * Success.
+	 */
+	close(fd);
+	return (1);
+}
+
+#if defined(__FreeBSD__) && defined(SIOCIFCREATE2)
+static int
+finddevs_usb(pcap_if_t **alldevsp, char *errbuf)
+{
+	DIR *usbdir;
+	struct dirent *usbitem;
+	size_t name_max;
+	char *name;
+
+	/*
+	 * We might have USB sniffing support, so try looking for USB
+	 * interfaces.
+	 *
+	 * We want to report a usbusN device for each USB bus, but
+	 * usbusN interfaces might, or might not, exist for them -
+	 * we create one if there isn't already one.
+	 *
+	 * So, instead, we look in /dev/usb for all buses and create
+	 * a "usbusN" device for each one.
+	 */
+	usbdir = opendir("/dev/usb");
+	if (usbdir == NULL) {
+		/*
+		 * Just punt.
+		 */
+		return (0);
+	}
+
+	/*
+	 * Leave enough room for a 32-bit (10-digit) bus number.
+	 * Yes, that's overkill, but we won't be using
+	 * the buffer very long.
+	 */
+	name_max = USBUS_PREFIX_LEN + 10 + 1;
+	name = malloc(name_max);
+	if (name == NULL) {
+		closedir(usbdir);
+		return (0);
+	}
+	while ((usbitem = readdir(usbdir)) != NULL) {
+		char *p;
+		size_t busnumlen;
+		int err;
+
+		if (strcmp(usbitem->d_name, ".") == 0 ||
+		    strcmp(usbitem->d_name, "..") == 0) {
+			/*
+			 * Ignore these.
+			 */
+			continue;
+		}
+		p = strchr(usbitem->d_name, '.');
+		if (p == NULL)
+			continue;
+		busnumlen = p - usbitem->d_name;
+		memcpy(name, usbus_prefix, USBUS_PREFIX_LEN);
+		memcpy(name + USBUS_PREFIX_LEN, usbitem->d_name, busnumlen);
+		*(name + USBUS_PREFIX_LEN + busnumlen) = '\0';
+		err = pcap_add_if(alldevsp, name, PCAP_IF_UP, NULL, errbuf);
+		if (err != 0) {
+			free(name);
+			closedir(usbdir);
+			return (err);
+		}
+	}
+	free(name);
+	closedir(usbdir);
+	return (0);
+}
+#endif
+
 int
 pcap_platform_finddevs(pcap_if_t **alldevsp, char *errbuf)
 {
+	/*
+	 * Get the list of regular interfaces first.
+	 */
+	if (pcap_findalldevs_interfaces(alldevsp, errbuf, check_bpf_bindable) == -1)
+		return (-1);	/* failure */
+
+#if defined(__FreeBSD__) && defined(SIOCIFCREATE2)
+	if (finddevs_usb(alldevsp, errbuf) == -1)
+		return (-1);
+#endif
+
 	return (0);
 }
 
@@ -2319,20 +2677,20 @@
 	struct pcap_bpf *pb = p->priv;
 	int sock;
 	struct ifmediareq req;
-	int *media_list;
+	IFM_ULIST_TYPE *media_list;
 	int i;
 	int can_do;
 	struct ifreq ifr;
 
 	sock = socket(AF_INET, SOCK_DGRAM, 0);
 	if (sock == -1) {
-		snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "can't open socket: %s",
+		pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "can't open socket: %s",
 		    pcap_strerror(errno));
 		return (PCAP_ERROR);
 	}
 
 	memset(&req, 0, sizeof req);
-	strncpy(req.ifm_name, p->opt.source, sizeof req.ifm_name);
+	strncpy(req.ifm_name, p->opt.device, sizeof req.ifm_name);
 
 	/*
 	 * Find out how many media types we have.
@@ -2358,7 +2716,7 @@
 			return (PCAP_ERROR_RFMON_NOTSUP);
 
 		default:
-			snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
+			pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
 			    "SIOCGIFMEDIA 1: %s", pcap_strerror(errno));
 			close(sock);
 			return (PCAP_ERROR);
@@ -2376,16 +2734,16 @@
 	 * Allocate a buffer to hold all the media types, and
 	 * get the media types.
 	 */
-	media_list = malloc(req.ifm_count * sizeof(int));
+	media_list = malloc(req.ifm_count * sizeof(*media_list));
 	if (media_list == NULL) {
-		snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "malloc: %s",
+		pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "malloc: %s",
 		    pcap_strerror(errno));
 		close(sock);
 		return (PCAP_ERROR);
 	}
 	req.ifm_ulist = media_list;
 	if (ioctl(sock, SIOCGIFMEDIA, &req) < 0) {
-		snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "SIOCGIFMEDIA: %s",
+		pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "SIOCGIFMEDIA: %s",
 		    pcap_strerror(errno));
 		free(media_list);
 		close(sock);
@@ -2438,17 +2796,15 @@
 				 * "atexit()" failed; don't put the interface
 				 * in monitor mode, just give up.
 				 */
-				snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
-				     "atexit failed");
 				close(sock);
 				return (PCAP_ERROR);
 			}
 			memset(&ifr, 0, sizeof(ifr));
-			(void)strncpy(ifr.ifr_name, p->opt.source,
+			(void)strncpy(ifr.ifr_name, p->opt.device,
 			    sizeof(ifr.ifr_name));
 			ifr.ifr_media = req.ifm_current | IFM_IEEE80211_MONITOR;
 			if (ioctl(sock, SIOCSIFMEDIA, &ifr) == -1) {
-				snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
+				pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
 				     "SIOCSIFMEDIA: %s", pcap_strerror(errno));
 				close(sock);
 				return (PCAP_ERROR);
@@ -2481,7 +2837,7 @@
 find_802_11(struct bpf_dltlist *bdlp)
 {
 	int new_dlt;
-	int i;
+	u_int i;
 
 	/*
 	 * Scan the list of DLT_ values, looking for 802.11 values,
@@ -2673,7 +3029,7 @@
 	 * some kernels.
 	 */
 	if (errno != EINVAL) {
-		snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "BIOCSETF: %s",
+		pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "BIOCSETF: %s",
 		    pcap_strerror(errno));
 		return (-1);
 	}
@@ -2702,7 +3058,7 @@
 	direction = (d == PCAP_D_IN) ? BPF_D_IN :
 	    ((d == PCAP_D_OUT) ? BPF_D_OUT : BPF_D_INOUT);
 	if (ioctl(p->fd, BIOCSDIRECTION, &direction) == -1) {
-		(void) snprintf(p->errbuf, sizeof(p->errbuf),
+		(void) pcap_snprintf(p->errbuf, sizeof(p->errbuf),
 		    "Cannot set direction to %s: %s",
 		        (d == PCAP_D_IN) ? "PCAP_D_IN" :
 			((d == PCAP_D_OUT) ? "PCAP_D_OUT" : "PCAP_D_INOUT"),
@@ -2717,14 +3073,14 @@
 	 * We don't support PCAP_D_OUT.
 	 */
 	if (d == PCAP_D_OUT) {
-		snprintf(p->errbuf, sizeof(p->errbuf),
+		pcap_snprintf(p->errbuf, sizeof(p->errbuf),
 		    "Setting direction to PCAP_D_OUT is not supported on BPF");
 		return -1;
 	}
 
 	seesent = (d == PCAP_D_INOUT);
 	if (ioctl(p->fd, BIOCSSEESENT, &seesent) == -1) {
-		(void) snprintf(p->errbuf, sizeof(p->errbuf),
+		(void) pcap_snprintf(p->errbuf, sizeof(p->errbuf),
 		    "Cannot set direction to %s: %s",
 		        (d == PCAP_D_INOUT) ? "PCAP_D_INOUT" : "PCAP_D_IN",
 			strerror(errno));
@@ -2732,7 +3088,7 @@
 	}
 	return (0);
 #else
-	(void) snprintf(p->errbuf, sizeof(p->errbuf),
+	(void) pcap_snprintf(p->errbuf, sizeof(p->errbuf),
 	    "This system doesn't support BIOCSSEESENT, so the direction can't be set");
 	return (-1);
 #endif
@@ -2743,7 +3099,7 @@
 {
 #ifdef BIOCSDLT
 	if (ioctl(p->fd, BIOCSDLT, &dlt) == -1) {
-		(void) snprintf(p->errbuf, sizeof(p->errbuf),
+		(void) pcap_snprintf(p->errbuf, sizeof(p->errbuf),
 		    "Cannot set DLT %d: %s", dlt, strerror(errno));
 		return (-1);
 	}
diff --git a/pcap-bt-linux.c b/pcap-bt-linux.c
index 56df687..4452fe4 100644
--- a/pcap-bt-linux.c
+++ b/pcap-bt-linux.c
@@ -87,7 +87,7 @@
 		/* if bluetooth is not supported this this is not fatal*/
 		if (errno == EAFNOSUPPORT)
 			return 0;
-		snprintf(err_str, PCAP_ERRBUF_SIZE,
+		pcap_snprintf(err_str, PCAP_ERRBUF_SIZE,
 		    "Can't open raw Bluetooth socket: %s", strerror(errno));
 		return -1;
 	}
@@ -95,7 +95,7 @@
 	dev_list = malloc(HCI_MAX_DEV * sizeof(*dev_req) + sizeof(*dev_list));
 	if (!dev_list)
 	{
-		snprintf(err_str, PCAP_ERRBUF_SIZE, "Can't allocate %zu bytes for Bluetooth device list",
+		pcap_snprintf(err_str, PCAP_ERRBUF_SIZE, "Can't allocate %zu bytes for Bluetooth device list",
 			HCI_MAX_DEV * sizeof(*dev_req) + sizeof(*dev_list));
 		ret = -1;
 		goto done;
@@ -105,7 +105,7 @@
 
 	if (ioctl(sock, HCIGETDEVLIST, (void *) dev_list) < 0)
 	{
-		snprintf(err_str, PCAP_ERRBUF_SIZE,
+		pcap_snprintf(err_str, PCAP_ERRBUF_SIZE,
 		    "Can't get Bluetooth device list via ioctl: %s",
 		    strerror(errno));
 		ret = -1;
@@ -116,8 +116,8 @@
 	for (i = 0; i < dev_list->dev_num; i++, dev_req++) {
 		char dev_name[20], dev_descr[30];
 
-		snprintf(dev_name, 20, BT_IFACE"%d", dev_req->dev_id);
-		snprintf(dev_descr, 30, "Bluetooth adapter number %d", i);
+		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)
@@ -171,7 +171,7 @@
 	/* OK, it's probably ours. */
 	*is_ours = 1;
 
-	p = pcap_create_common(device, ebuf, sizeof (struct pcap_bt));
+	p = pcap_create_common(ebuf, sizeof (struct pcap_bt));
 	if (p == NULL)
 		return (NULL);
 
@@ -190,17 +190,16 @@
 	int err = PCAP_ERROR;
 
 	/* get bt interface id */
-	if (sscanf(handle->opt.source, BT_IFACE"%d", &dev_id) != 1)
+	if (sscanf(handle->opt.device, BT_IFACE"%d", &dev_id) != 1)
 	{
-		snprintf(handle->errbuf, PCAP_ERRBUF_SIZE,
+		pcap_snprintf(handle->errbuf, PCAP_ERRBUF_SIZE,
 			"Can't get Bluetooth device index from %s",
-			 handle->opt.source);
+			 handle->opt.device);
 		return PCAP_ERROR;
 	}
 
 	/* Initialize some components of the pcap structure. */
-	handle->bufsize = handle->snapshot+BT_CTRL_SIZE+sizeof(pcap_bluetooth_h4_header);
-	handle->offset = BT_CTRL_SIZE;
+	handle->bufsize = BT_CTRL_SIZE+sizeof(pcap_bluetooth_h4_header)+handle->snapshot;
 	handle->linktype = DLT_BLUETOOTH_HCI_H4_WITH_PHDR;
 
 	handle->read_op = bt_read_linux;
@@ -216,28 +215,28 @@
 	/* Create HCI socket */
 	handle->fd = socket(AF_BLUETOOTH, SOCK_RAW, BTPROTO_HCI);
 	if (handle->fd < 0) {
-		snprintf(handle->errbuf, PCAP_ERRBUF_SIZE,
+		pcap_snprintf(handle->errbuf, PCAP_ERRBUF_SIZE,
 		    "Can't create raw socket: %s", strerror(errno));
 		return PCAP_ERROR;
 	}
 
 	handle->buffer = malloc(handle->bufsize);
 	if (!handle->buffer) {
-		snprintf(handle->errbuf, PCAP_ERRBUF_SIZE, "Can't allocate dump buffer: %s",
+		pcap_snprintf(handle->errbuf, PCAP_ERRBUF_SIZE, "Can't allocate dump buffer: %s",
 			pcap_strerror(errno));
 		goto close_fail;
 	}
 
 	opt = 1;
 	if (setsockopt(handle->fd, SOL_HCI, HCI_DATA_DIR, &opt, sizeof(opt)) < 0) {
-		snprintf(handle->errbuf, PCAP_ERRBUF_SIZE,
+		pcap_snprintf(handle->errbuf, PCAP_ERRBUF_SIZE,
 		    "Can't enable data direction info: %s", strerror(errno));
 		goto close_fail;
 	}
 
 	opt = 1;
 	if (setsockopt(handle->fd, SOL_HCI, HCI_TIME_STAMP, &opt, sizeof(opt)) < 0) {
-		snprintf(handle->errbuf, PCAP_ERRBUF_SIZE,
+		pcap_snprintf(handle->errbuf, PCAP_ERRBUF_SIZE,
 		    "Can't enable time stamp: %s", strerror(errno));
 		goto close_fail;
 	}
@@ -248,7 +247,7 @@
 	memset((void *) &flt.type_mask, 0xff, sizeof(flt.type_mask));
 	memset((void *) &flt.event_mask, 0xff, sizeof(flt.event_mask));
 	if (setsockopt(handle->fd, SOL_HCI, HCI_FILTER, &flt, sizeof(flt)) < 0) {
-		snprintf(handle->errbuf, PCAP_ERRBUF_SIZE,
+		pcap_snprintf(handle->errbuf, PCAP_ERRBUF_SIZE,
 		    "Can't set filter: %s", strerror(errno));
 		goto close_fail;
 	}
@@ -261,7 +260,7 @@
 	addr.hci_channel = HCI_CHANNEL_RAW;
 #endif
 	if (bind(handle->fd, (struct sockaddr *) &addr, sizeof(addr)) < 0) {
-		snprintf(handle->errbuf, PCAP_ERRBUF_SIZE,
+		pcap_snprintf(handle->errbuf, PCAP_ERRBUF_SIZE,
 		    "Can't attach to device %d: %s", handlep->dev_id,
 		    strerror(errno));
 		goto close_fail;
@@ -282,7 +281,7 @@
 		if (setsockopt(handle->fd, SOL_SOCKET, SO_RCVBUF,
 		    &handle->opt.buffer_size,
 		    sizeof(handle->opt.buffer_size)) == -1) {
-			snprintf(handle->errbuf, PCAP_ERRBUF_SIZE,
+			pcap_snprintf(handle->errbuf, PCAP_ERRBUF_SIZE,
 				 "SO_RCVBUF: %s", pcap_strerror(errno));
 			goto close_fail;
 		}
@@ -305,16 +304,19 @@
 	ssize_t ret;
 	struct pcap_pkthdr pkth;
 	pcap_bluetooth_h4_header* bthdr;
+	u_char *pktd;
+	int in = 0;
 
-	bthdr = (pcap_bluetooth_h4_header*) &handle->buffer[handle->offset];
-	iv.iov_base = &handle->buffer[handle->offset+sizeof(pcap_bluetooth_h4_header)];
+	pktd = (u_char *)handle->buffer + BT_CTRL_SIZE;
+	bthdr = (pcap_bluetooth_h4_header*)(void *)pktd;
+	iv.iov_base = pktd + sizeof(pcap_bluetooth_h4_header);
 	iv.iov_len  = handle->snapshot;
 
 	memset(&msg, 0, sizeof(msg));
 	msg.msg_iov = &iv;
 	msg.msg_iovlen = 1;
 	msg.msg_control = handle->buffer;
-	msg.msg_controllen = handle->offset;
+	msg.msg_controllen = BT_CTRL_SIZE;
 
 	/* ignore interrupt system call error */
 	do {
@@ -327,7 +329,7 @@
 	} while ((ret == -1) && (errno == EINTR));
 
 	if (ret < 0) {
-		snprintf(handle->errbuf, PCAP_ERRBUF_SIZE,
+		pcap_snprintf(handle->errbuf, PCAP_ERRBUF_SIZE,
 		    "Can't receive packet: %s", strerror(errno));
 		return -1;
 	}
@@ -336,7 +338,6 @@
 
 	/* get direction and timestamp*/
 	cmsg = CMSG_FIRSTHDR(&msg);
-	int in=0;
 	while (cmsg) {
 		switch (cmsg->cmsg_type) {
 			case HCI_CMSG_DIR:
@@ -357,9 +358,8 @@
 	pkth.caplen+=sizeof(pcap_bluetooth_h4_header);
 	pkth.len = pkth.caplen;
 	if (handle->fcode.bf_insns == NULL ||
-	    bpf_filter(handle->fcode.bf_insns, &handle->buffer[handle->offset],
-	      pkth.len, pkth.caplen)) {
-		callback(user, &pkth, &handle->buffer[handle->offset]);
+	    bpf_filter(handle->fcode.bf_insns, pktd, pkth.len, pkth.caplen)) {
+		callback(user, &pkth, pktd);
 		return 1;
 	}
 	return 0;	/* didn't pass filter */
@@ -368,7 +368,7 @@
 static int
 bt_inject_linux(pcap_t *handle, const void *buf, size_t size)
 {
-	snprintf(handle->errbuf, PCAP_ERRBUF_SIZE, "inject not supported on "
+	pcap_snprintf(handle->errbuf, PCAP_ERRBUF_SIZE, "inject not supported on "
     		"bluetooth devices");
 	return (-1);
 }
@@ -389,7 +389,7 @@
 	} while ((ret == -1) && (errno == EINTR));
 
 	if (ret < 0) {
-		snprintf(handle->errbuf, PCAP_ERRBUF_SIZE,
+		pcap_snprintf(handle->errbuf, PCAP_ERRBUF_SIZE,
 		    "Can't get stats via ioctl: %s", strerror(errno));
 		return (-1);
 
diff --git a/pcap-bt-monitor-linux.c b/pcap-bt-monitor-linux.c
index f193e26..521d6d5 100644
--- a/pcap-bt-monitor-linux.c
+++ b/pcap-bt-monitor-linux.c
@@ -34,12 +34,12 @@
 #endif
 
 #include <errno.h>
+#include <stdint.h>
 #include <stdlib.h>
 #include <string.h>
 
 #include <bluetooth/bluetooth.h>
 #include <bluetooth/hci.h>
-#include <bluetooth/mgmt.h>
 
 #include "pcap/bluetooth.h"
 #include "pcap-int.h"
@@ -49,6 +49,16 @@
 #define BT_CONTROL_SIZE 32
 #define INTERFACE_NAME "bluetooth-monitor"
 
+/*
+ * Fields and alignment must match the declaration in the Linux kernel 3.4+.
+ * See struct hci_mon_hdr in include/net/bluetooth/hci_mon.h.
+ */
+struct hci_mon_hdr {
+    uint16_t opcode;
+    uint16_t index;
+    uint16_t len;
+} __attribute__((packed));
+
 int
 bt_monitor_findalldevs(pcap_if_t **alldevsp, char *err_str)
 {
@@ -72,13 +82,15 @@
     ssize_t ret;
     struct pcap_pkthdr pkth;
     pcap_bluetooth_linux_monitor_header *bthdr;
-    struct mgmt_hdr hdr;
+    u_char *pktd;
+    struct hci_mon_hdr hdr;
 
-    bthdr = (pcap_bluetooth_linux_monitor_header*) &handle->buffer[handle->offset];
+    pktd = (u_char *)handle->buffer + BT_CONTROL_SIZE;
+    bthdr = (pcap_bluetooth_linux_monitor_header*)(void *)pktd;
 
     iv[0].iov_base = &hdr;
-    iv[0].iov_len = MGMT_HDR_SIZE;
-    iv[1].iov_base = &handle->buffer[handle->offset + sizeof(pcap_bluetooth_linux_monitor_header)];
+    iv[0].iov_len = sizeof(hdr);
+    iv[1].iov_base = pktd + sizeof(pcap_bluetooth_linux_monitor_header);
     iv[1].iov_len = handle->snapshot;
 
     memset(&pkth.ts, 0, sizeof(pkth.ts));
@@ -86,7 +98,7 @@
     msg.msg_iov = iv;
     msg.msg_iovlen = 2;
     msg.msg_control = handle->buffer;
-    msg.msg_controllen = handle->offset;
+    msg.msg_controllen = BT_CONTROL_SIZE;
 
     do {
         ret = recvmsg(handle->fd, &msg, 0);
@@ -98,12 +110,12 @@
     } while ((ret == -1) && (errno == EINTR));
 
     if (ret < 0) {
-        snprintf(handle->errbuf, PCAP_ERRBUF_SIZE,
+        pcap_snprintf(handle->errbuf, PCAP_ERRBUF_SIZE,
             "Can't receive packet: %s", strerror(errno));
         return -1;
     }
 
-    pkth.caplen = ret - MGMT_HDR_SIZE + sizeof(pcap_bluetooth_linux_monitor_header);
+    pkth.caplen = ret - sizeof(hdr) + sizeof(pcap_bluetooth_linux_monitor_header);
     pkth.len = pkth.caplen;
 
     for (cmsg = CMSG_FIRSTHDR(&msg); cmsg != NULL; cmsg = CMSG_NXTHDR(&msg, cmsg)) {
@@ -118,9 +130,8 @@
     bthdr->opcode = htons(hdr.opcode);
 
     if (handle->fcode.bf_insns == NULL ||
-        bpf_filter(handle->fcode.bf_insns, &handle->buffer[handle->offset],
-          pkth.len, pkth.caplen)) {
-        callback(user, &pkth, &handle->buffer[handle->offset]);
+        bpf_filter(handle->fcode.bf_insns, pktd, pkth.len, pkth.caplen)) {
+        callback(user, &pkth, pktd);
         return 1;
     }
     return 0;   /* didn't pass filter */
@@ -129,7 +140,7 @@
 static int
 bt_monitor_inject(pcap_t *handle, const void *buf _U_, size_t size _U_)
 {
-    snprintf(handle->errbuf, PCAP_ERRBUF_SIZE, "inject not supported yet");
+    pcap_snprintf(handle->errbuf, PCAP_ERRBUF_SIZE, "inject not supported yet");
     return -1;
 }
 
@@ -162,8 +173,7 @@
         return PCAP_ERROR_RFMON_NOTSUP;
     }
 
-    handle->bufsize = handle->snapshot + BT_CONTROL_SIZE + sizeof(pcap_bluetooth_linux_monitor_header);
-    handle->offset = BT_CONTROL_SIZE;
+    handle->bufsize = BT_CONTROL_SIZE + sizeof(pcap_bluetooth_linux_monitor_header) + handle->snapshot;
     handle->linktype = DLT_BLUETOOTH_LINUX_MONITOR;
 
     handle->read_op = bt_monitor_read;
@@ -177,14 +187,14 @@
 
     handle->fd = socket(AF_BLUETOOTH, SOCK_RAW, BTPROTO_HCI);
     if (handle->fd < 0) {
-        snprintf(handle->errbuf, PCAP_ERRBUF_SIZE,
+        pcap_snprintf(handle->errbuf, PCAP_ERRBUF_SIZE,
             "Can't create raw socket: %s", strerror(errno));
         return PCAP_ERROR;
     }
 
     handle->buffer = malloc(handle->bufsize);
     if (!handle->buffer) {
-        snprintf(handle->errbuf, PCAP_ERRBUF_SIZE, "Can't allocate dump buffer: %s",
+        pcap_snprintf(handle->errbuf, PCAP_ERRBUF_SIZE, "Can't allocate dump buffer: %s",
             pcap_strerror(errno));
         goto close_fail;
     }
@@ -195,14 +205,14 @@
     addr.hci_channel = HCI_CHANNEL_MONITOR;
 
     if (bind(handle->fd, (struct sockaddr *) &addr, sizeof(addr)) < 0) {
-        snprintf(handle->errbuf, PCAP_ERRBUF_SIZE,
+        pcap_snprintf(handle->errbuf, PCAP_ERRBUF_SIZE,
             "Can't attach to interface: %s", strerror(errno));
         goto close_fail;
     }
 
     opt = 1;
     if (setsockopt(handle->fd, SOL_SOCKET, SO_TIMESTAMP, &opt, sizeof(opt)) < 0) {
-        snprintf(handle->errbuf, PCAP_ERRBUF_SIZE,
+        pcap_snprintf(handle->errbuf, PCAP_ERRBUF_SIZE,
             "Can't enable time stamp: %s", strerror(errno));
         goto close_fail;
     }
@@ -232,7 +242,7 @@
     }
 
     *is_ours = 1;
-    p = pcap_create_common(device, ebuf, 0);
+    p = pcap_create_common(ebuf, 0);
     if (p == NULL)
         return NULL;
 
diff --git a/pcap-can-linux.c b/pcap-can-linux.c
deleted file mode 100644
index a8e1e35..0000000
--- a/pcap-can-linux.c
+++ /dev/null
@@ -1,319 +0,0 @@
-/*
- * Copyright (c) 2009 Felix Obenhuber
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- * 3. The name of the author may not be used to endorse or promote
- * products derived from this software without specific prior written
- * permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
- * SocketCan sniffing API implementation for Linux platform
- * By Felix Obenhuber <felix@obenhuber.de>
- *
- */
-
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-
-#include "pcap-int.h"
-#include "pcap-can-linux.h"
-
-#ifdef NEED_STRERROR_H
-#include "strerror.h"
-#endif
-
-#include <errno.h>
-#include <stdlib.h>
-#include <unistd.h>
-#include <fcntl.h>
-#include <string.h>
-#include <sys/ioctl.h>
-#include <sys/socket.h>
-#include <net/if.h>
-#include <arpa/inet.h>
-
-#include <linux/can.h>
-#include <linux/can/raw.h>
-
-/* not yet defined anywhere */
-#ifndef PF_CAN
-#define PF_CAN 29
-#endif
-#ifndef AF_CAN
-#define AF_CAN PF_CAN
-#endif
-
-/* forward declaration */
-static int can_activate(pcap_t *);
-static int can_read_linux(pcap_t *, int , pcap_handler , u_char *);
-static int can_inject_linux(pcap_t *, const void *, size_t);
-static int can_setfilter_linux(pcap_t *, struct bpf_program *);
-static int can_setdirection_linux(pcap_t *, pcap_direction_t);
-static int can_stats_linux(pcap_t *, struct pcap_stat *);
-
-/*
- * Private data for capturing on Linux CANbus devices.
- */
-struct pcap_can {
-	int ifindex;		/* interface index of device we're bound to */
-};
-
-int
-can_findalldevs(pcap_if_t **devlistp, char *errbuf)
-{
-	/*
-	 * There are no platform-specific devices since each device
-	 * exists as a regular network interface.
-	 *
-	 * XXX - true?
-	 */
-	return 0;
-}
-
-pcap_t *
-can_create(const char *device, char *ebuf, int *is_ours)
-{
-	const char *cp;
-	char *cpend;
-	long devnum;
-	pcap_t* p;
-
-	/* Does this look like a CANbus device? */
-	cp = strrchr(device, '/');
-	if (cp == NULL)
-		cp = device;
-	/* Does it begin with "can" or "vcan"? */
-	if (strncmp(cp, "can", 3) == 0) {
-		/* Begins with "can" */
-		cp += 3;	/* skip past "can" */
-	} else if (strncmp(cp, "vcan", 4) == 0) {
-		/* Begins with "vcan" */
-		cp += 4;
-	} else {
-		/* Nope, doesn't begin with "can" or "vcan" */
-		*is_ours = 0;
-		return NULL;
-	}
-	/* Yes - is "can" or "vcan" followed by a number from 0? */
-	devnum = strtol(cp, &cpend, 10);
-	if (cpend == cp || *cpend != '\0') {
-		/* Not followed by a number. */
-		*is_ours = 0;
-		return NULL;
-	}
-	if (devnum < 0) {
-		/* Followed by a non-valid number. */
-		*is_ours = 0;
-		return NULL;
-	}
-
-	/* OK, it's probably ours. */
-	*is_ours = 1;
-
-	p = pcap_create_common(device, ebuf, sizeof (struct pcap_can));
-	if (p == NULL)
-		return (NULL);
-
-	p->activate_op = can_activate;
-	return (p);
-}
-
-
-static int
-can_activate(pcap_t* handle)
-{
-	struct pcap_can *handlep = handle->priv;
-	struct sockaddr_can addr;
-	struct ifreq ifr;
-
-	/* Initialize some components of the pcap structure. */
-	handle->bufsize = 24;
-	handle->offset = 8;
-	handle->linktype = DLT_CAN_SOCKETCAN;
-	handle->read_op = can_read_linux;
-	handle->inject_op = can_inject_linux;
-	handle->setfilter_op = can_setfilter_linux;
-	handle->setdirection_op = can_setdirection_linux;
-	handle->set_datalink_op = NULL;
-	handle->getnonblock_op = pcap_getnonblock_fd;
-	handle->setnonblock_op = pcap_setnonblock_fd;
-	handle->stats_op = can_stats_linux;
-
-	/* Create socket */
-	handle->fd = socket(PF_CAN, SOCK_RAW, CAN_RAW);
-	if (handle->fd < 0)
-	{
-		snprintf(handle->errbuf, PCAP_ERRBUF_SIZE, "Can't create raw socket %d:%s",
-			errno, strerror(errno));
-		return PCAP_ERROR;
-	}
-
-	/* get interface index */
-	memset(&ifr, 0, sizeof(ifr));
-	strlcpy(ifr.ifr_name, handle->opt.source, sizeof(ifr.ifr_name));
-	if (ioctl(handle->fd, SIOCGIFINDEX, &ifr) < 0)
-	{
-		snprintf(handle->errbuf, PCAP_ERRBUF_SIZE,
-				"Unable to get interface index: %s",
-			pcap_strerror(errno));
-		pcap_cleanup_live_common(handle);
-		return PCAP_ERROR;
-	}
-	handlep->ifindex = ifr.ifr_ifindex;
-
-	/* allocate butter */
-	handle->buffer = malloc(handle->bufsize);
-	if (!handle->buffer)
-	{
-		snprintf(handle->errbuf, PCAP_ERRBUF_SIZE, "Can't allocate dump buffer: %s",
-			pcap_strerror(errno));
-		pcap_cleanup_live_common(handle);
-		return PCAP_ERROR;
-	}
-
-	/* Bind to the socket */
-	addr.can_family = AF_CAN;
-	addr.can_ifindex = handlep->ifindex;
-	if( bind( handle->fd, (struct sockaddr*)&addr, sizeof(addr) ) < 0  )
-	{
-		snprintf(handle->errbuf, PCAP_ERRBUF_SIZE, "Can't attach to device %d %d:%s",
-			handlep->ifindex, errno, strerror(errno));
-		pcap_cleanup_live_common(handle);
-		return PCAP_ERROR;
-	}
-
-	if (handle->opt.rfmon)
-	{
-		/* Monitor mode doesn't apply to CAN devices. */
-		pcap_cleanup_live_common(handle);
-		return PCAP_ERROR_RFMON_NOTSUP;
-	}
-
-	handle->selectable_fd = handle->fd;
-	return 0;
-
-}
-
-
-static int
-can_read_linux(pcap_t *handle, int max_packets, pcap_handler callback, u_char *user)
-{
-	struct msghdr msg;
-	struct pcap_pkthdr pkth;
-	struct iovec iv;
-	struct can_frame* cf;
-
-	iv.iov_base = &handle->buffer[handle->offset];
-	iv.iov_len = handle->snapshot;
-
-	memset(&msg, 0, sizeof(msg));
-	msg.msg_iov = &iv;
-	msg.msg_iovlen = 1;
-	msg.msg_control = handle->buffer;
-	msg.msg_controllen = handle->offset;
-
-	do
-	{
-		pkth.caplen = recvmsg(handle->fd, &msg, 0);
-		if (handle->break_loop)
-		{
-			handle->break_loop = 0;
-			return -2;
-		}
-	} while ((pkth.caplen == -1) && (errno == EINTR));
-
-	if (pkth.caplen == -1)
-	{
-		snprintf(handle->errbuf, PCAP_ERRBUF_SIZE, "Can't receive packet %d:%s",
-			errno, strerror(errno));
-		return -1;
-	}
-
-	/* adjust capture len according to frame len */
-	cf = (struct can_frame*)&handle->buffer[8];
-	pkth.caplen -= 8 - cf->can_dlc;
-	pkth.len = pkth.caplen;
-
-	cf->can_id = htonl( cf->can_id );
-
-	if( -1 == gettimeofday(&pkth.ts, NULL) )
-	{
-		snprintf(handle->errbuf, PCAP_ERRBUF_SIZE, "Can't get time of day %d:%s",
-			errno, strerror(errno));
-		return -1;
-	}
-
-	callback(user, &pkth, &handle->buffer[8]);
-
-	return 1;
-}
-
-
-static int
-can_inject_linux(pcap_t *handle, const void *buf, size_t size)
-{
-	/* not yet implemented */
-	snprintf(handle->errbuf, PCAP_ERRBUF_SIZE, "inject not supported on "
-		"can devices");
-	return (-1);
-}
-
-
-static int
-can_stats_linux(pcap_t *handle, struct pcap_stat *stats)
-{
-	/* not yet implemented */
-	stats->ps_recv = 0;			 /* number of packets received */
-	stats->ps_drop = 0;			 /* number of packets dropped */
-	stats->ps_ifdrop = 0;		 /* drops by interface -- only supported on some platforms */
-	return 0;
-}
-
-
-static int
-can_setfilter_linux(pcap_t *p, struct bpf_program *fp)
-{
-	/* not yet implemented */
-	return 0;
-}
-
-
-static int
-can_setdirection_linux(pcap_t *p, pcap_direction_t d)
-{
-	/* no support for PCAP_D_OUT */
-	if (d == PCAP_D_OUT)
-	{
-		snprintf(p->errbuf, sizeof(p->errbuf),
-			"Setting direction to PCAP_D_OUT is not supported on can");
-		return -1;
-	}
-
-	p->direction = d;
-
-	return 0;
-}
-
-
-/* eof */
diff --git a/pcap-can-linux.h b/pcap-can-linux.h
deleted file mode 100644
index fe806ff..0000000
--- a/pcap-can-linux.h
+++ /dev/null
@@ -1,36 +0,0 @@
-/*
- * Copyright (c) 2009 Felix Obenhuber
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- * 3. The name of the author may not be used to endorse or promote
- * products derived from this software without specific prior written
- * permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
- */
-
-/*
- * Prototypes for SocketCAN related functions
- */
-pcap_t* can_create(const char *device, char *ebuf, int *is_ours);
-int can_findalldevs(pcap_if_t **devlistp, char *errbuf);
diff --git a/pcap-canusb-linux.c b/pcap-canusb-linux.c
deleted file mode 100644
index f44c45e..0000000
--- a/pcap-canusb-linux.c
+++ /dev/null
@@ -1,474 +0,0 @@
-/*
- * Copyright (c) 2009 Felix Obenhuber
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- * 3. The name of the author may not be used to endorse or promote
- * products derived from this software without specific prior written
- * permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
- * Sockettrace sniffing API implementation for Linux platform
- * By Felix Obenhuber <felix@obenhuber.de>
- *
- */
-
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-
-#include <libusb-1.0/libusb.h>
-
-#include <stdlib.h>
-#include <unistd.h>
-#include <fcntl.h>
-#include <errno.h>
-#include <string.h>
-#include <pthread.h>
-
-#include "pcap-int.h"
-#include "pcap-canusb-linux.h"
-
-#define CANUSB_IFACE "canusb"
-
-#define CANUSB_VID 0x0403
-#define CANUSB_PID 0x8990
-
-#define USE_THREAD 1
-
-#if USE_THREAD == 0
-#include <signal.h>
-#endif
-
-
-/* forward declaration */
-static int canusb_activate(pcap_t *);
-static int canusb_read_linux(pcap_t *, int , pcap_handler , u_char *);
-static int canusb_inject_linux(pcap_t *, const void *, size_t);
-static int canusb_setfilter_linux(pcap_t *, struct bpf_program *);
-static int canusb_setdirection_linux(pcap_t *, pcap_direction_t);
-static int canusb_stats_linux(pcap_t *, struct pcap_stat *);
-
-struct CAN_Msg
-{
-    uint32_t timestamp;
-    uint32_t id;
-    uint32_t length;
-    uint8_t data[8];
-};
-
-/*
- * Private data for capturing on Linux CANbus USB devices.
- */
-struct pcap_canusb {
-    libusb_context *ctx;
-    libusb_device_handle *dev;
-    pthread_t worker;
-    int rdpipe, wrpipe;
-    volatile int loop;
-};
-
-int canusb_findalldevs(pcap_if_t **alldevsp, char *err_str)
-{
-    libusb_context *fdctx;
-    libusb_device** devs;
-    unsigned char sernum[65];
-    int cnt, i;
-
-    if (libusb_init(&fdctx) != 0) {
-        /*
-         * XXX - if this doesn't just mean "no USB file system mounted",
-         * perhaps we should report a real error rather than just
-         * saying "no CANUSB devices".
-         */
-        return 0;
-    }
-
-    cnt = libusb_get_device_list(fdctx,&devs);
-
-    for(i=0;i<cnt;i++)
-    {
-        int ret;
-        // Check if this device is interesting.
-        struct libusb_device_descriptor desc;
-        libusb_get_device_descriptor(devs[i],&desc);
-
-        if ((desc.idVendor != CANUSB_VID) || (desc.idProduct != CANUSB_PID))
-            continue; //It is not, check next device
-
-        //It is!
-        libusb_device_handle *dh = NULL;
-
-        if ((ret = libusb_open(devs[i],&dh)) == 0)
-        {
-            char dev_name[30];
-            char dev_descr[50];
-            int n = libusb_get_string_descriptor_ascii(dh,desc.iSerialNumber,sernum,64);
-            sernum[n] = 0;
-
-            snprintf(dev_name, 30, CANUSB_IFACE"%s", sernum);
-            snprintf(dev_descr, 50, "CanUSB [%s]", sernum);
-
-            libusb_close(dh);
-
-            if (pcap_add_if(alldevsp, dev_name, 0, dev_descr, err_str) < 0)
-            {
-                libusb_free_device_list(devs,1);
-                libusb_exit(fdctx);
-                return -1;
-            }
-        }
-    }
-
-    libusb_free_device_list(devs,1);
-    libusb_exit(fdctx);
-    return 0;
-}
-
-static libusb_device_handle* canusb_opendevice(struct libusb_context *ctx, char* devserial)
-{
-    libusb_device** devs;
-    unsigned char serial[65];
-    int cnt,i,n;
-
-    cnt = libusb_get_device_list(ctx,&devs);
-
-    for(i=0;i<cnt;i++)
-    {
-        // Check if this device is interesting.
-        struct libusb_device_descriptor desc;
-        libusb_get_device_descriptor(devs[i],&desc);
-
-        if ((desc.idVendor != CANUSB_VID) || (desc.idProduct != CANUSB_PID))
-          continue;
-
-        //Found one!
-        libusb_device_handle *dh = NULL;
-
-        if (libusb_open(devs[i],&dh) != 0) continue;
-
-        n = libusb_get_string_descriptor_ascii(dh,desc.iSerialNumber,serial,64);
-        serial[n] = 0;
-
-        if ((devserial) && (strcmp((char *)serial,devserial) != 0))
-        {
-            libusb_close(dh);
-            continue;
-        }
-
-        if ((libusb_kernel_driver_active(dh,0)) && (libusb_detach_kernel_driver(dh,0) != 0))
-        {
-            libusb_close(dh);
-            continue;
-        }
-
-        if (libusb_set_configuration(dh,1) != 0)
-        {
-            libusb_close(dh);
-            continue;
-        }
-
-        if (libusb_claim_interface(dh,0) != 0)
-        {
-            libusb_close(dh);
-            continue;
-        }
-
-        //Fount it!
-        libusb_free_device_list(devs,1);
-        return dh;
-    }
-
-    libusb_free_device_list(devs,1);
-    return NULL;
-}
-
-
-pcap_t *
-canusb_create(const char *device, char *ebuf, int *is_ours)
-{
-    const char *cp;
-    char *cpend;
-    long devnum;
-    pcap_t* p;
-    struct pcap_canusb *canusb;
-
-    /* Does this look like a DAG device? */
-    cp = strrchr(device, '/');
-    if (cp == NULL)
-        cp = device;
-    /* Does it begin with "canusb"? */
-    if (strncmp(cp, "canusb", 6) != 0) {
-        /* Nope, doesn't begin with "canusb" */
-        *is_ours = 0;
-        return NULL;
-    }
-    /* Yes - is "canusb" followed by a number? */
-    cp += 6;
-    devnum = strtol(cp, &cpend, 10);
-    if (cpend == cp || *cpend != '\0') {
-        /* Not followed by a number. */
-        *is_ours = 0;
-        return NULL;
-    }
-    if (devnum < 0) {
-        /* Followed by a non-valid number. */
-        *is_ours = 0;
-        return NULL;
-    }
-
-    /* OK, it's probably ours. */
-    *is_ours = 1;
-
-    p = pcap_create_common(device, ebuf, sizeof (struct pcap_canusb));
-    if (p == NULL)
-        return (NULL);
-
-    canusb = p->priv;
-    canusb->ctx = NULL;
-    canusb->dev = NULL;
-    canusb->rdpipe = -1;
-    canusb->wrpipe = -1;
-
-    p->activate_op = canusb_activate;
-
-    return (p);
-}
-
-
-static void* canusb_capture_thread(void *arg)
-{
-    struct pcap_canusb *canusb = arg;
-    int i;
-    struct
-    {
-      uint8_t rxsz, txsz;
-    } status;
-
-    fcntl(canusb->wrpipe, F_SETFL, O_NONBLOCK);
-
-    while(canusb->loop)
-    {
-        int sz;
-        struct CAN_Msg msg;
-
-        libusb_interrupt_transfer(canusb->dev, 0x81, (unsigned char*)&status, sizeof(status), &sz, 100);
-        //HACK!!!!! -> drop buffered data, read new one by reading twice.
-        libusb_interrupt_transfer(canusb->dev, 0x81, (unsigned char*)&status, sizeof(status), &sz, 100);
-
-        for(i = 0; i<status.rxsz; i++)
-        {
-            libusb_bulk_transfer(canusb->dev, 0x85, (unsigned char*)&msg, sizeof(msg), &sz, 100);
-            if(write(canusb->wrpipe, &msg, sizeof(msg)) < 0)
-                fprintf(stderr,"write() error: %s\n", strerror(errno));
-        }
-
-    }
-
-    return NULL;
-}
-
-static int canusb_startcapture(struct pcap_canusb* this)
-{
-    int pipefd[2];
-
-    if (pipe(pipefd) == -1)
-        return -1;
-
-    this->rdpipe = pipefd[0];
-    this->wrpipe = pipefd[1];
-
-    this->loop = 1;
-    pthread_create(&this->worker, NULL, canusb_capture_thread, this);
-
-    return this->rdpipe;
-}
-
-static void canusb_clearbufs(struct pcap_canusb* this)
-{
-    unsigned char cmd[16];
-    int al;
-
-    cmd[0] = 1;  //Empty incoming buffer
-    cmd[1] = 1;  //Empty outgoing buffer
-    cmd[3] = 0;  //Not a write to serial number
-    memset(&cmd[4],0,16-4);
-
-    libusb_interrupt_transfer(this->dev, 0x1,cmd,16,&al,100);
-}
-
-
-static void canusb_close(pcap_t* handle)
-{
-    struct pcap_canusb *canusb = handle->priv;
-
-    canusb->loop = 0;
-    pthread_join(canusb->worker, NULL);
-
-    if (canusb->dev)
-    {
-        libusb_close(canusb->dev);
-        canusb->dev = NULL;
-    }
-    if (canusb->ctx)
-    {
-        libusb_exit(canusb->ctx);
-        canusb->ctx = NULL;
-    }
-}
-
-
-
-static int canusb_activate(pcap_t* handle)
-{
-    struct pcap_canusb *canusb = handle->priv;
-    char *serial;
-
-    if (libusb_init(&canusb->ctx) != 0) {
-        /*
-         * XXX - what causes this to fail?
-         */
-        snprintf(handle->errbuf, PCAP_ERRBUF_SIZE, "libusb_init() failed");
-        return PCAP_ERROR;
-    }
-
-    handle->read_op = canusb_read_linux;
-
-    handle->inject_op = canusb_inject_linux;
-    handle->setfilter_op = canusb_setfilter_linux;
-    handle->setdirection_op = canusb_setdirection_linux;
-    handle->getnonblock_op = pcap_getnonblock_fd;
-    handle->setnonblock_op = pcap_setnonblock_fd;
-    handle->stats_op = canusb_stats_linux;
-    handle->cleanup_op = canusb_close;
-
-    /* Initialize some components of the pcap structure. */
-    handle->bufsize = 32;
-    handle->offset = 8;
-    handle->linktype = DLT_CAN_SOCKETCAN;
-    handle->set_datalink_op = NULL;
-
-    serial = handle->opt.source + strlen(CANUSB_IFACE);
-
-    canusb->dev = canusb_opendevice(canusb->ctx, serial);
-    if (!canusb->dev)
-    {
-        libusb_exit(canusb->ctx);
-        snprintf(handle->errbuf, PCAP_ERRBUF_SIZE, "Can't open USB Device");
-        return PCAP_ERROR;
-    }
-
-    canusb_clearbufs(canusb);
-
-    handle->fd = canusb_startcapture(canusb);
-    handle->selectable_fd = handle->fd;
-
-    return 0;
-}
-
-
-
-
-static int
-canusb_read_linux(pcap_t *handle, int max_packets, pcap_handler callback, u_char *user)
-{
-    static struct timeval firstpacket = { -1, -1};
-    int i = 0;
-    struct CAN_Msg msg;
-    struct pcap_pkthdr pkth;
-
-    while(i < max_packets)
-    {
-        int n;
-        usleep(10 * 1000);
-        n = read(handle->fd, &msg, sizeof(msg));
-        if (n <= 0)
-            break;
-        pkth.caplen = pkth.len = n;
-        pkth.caplen -= 4;
-        pkth.caplen -= 8 - msg.length;
-
-        if ((firstpacket.tv_sec == -1) && (firstpacket.tv_usec == -1))
-            gettimeofday(&firstpacket, NULL);
-
-        pkth.ts.tv_usec = firstpacket.tv_usec + (msg.timestamp % 100) * 10000;
-        pkth.ts.tv_sec = firstpacket.tv_usec + (msg.timestamp / 100);
-        if (pkth.ts.tv_usec > 1000000)
-        {
-            pkth.ts.tv_usec -= 1000000;
-            pkth.ts.tv_sec++;
-        }
-
-        callback(user, &pkth, (void*)&msg.id);
-        i++;
-    }
-
-    return i;
-}
-
-
-static int
-canusb_inject_linux(pcap_t *handle, const void *buf, size_t size)
-{
-    /* not yet implemented */
-    snprintf(handle->errbuf, PCAP_ERRBUF_SIZE, "inject not supported on canusb devices");
-    return (-1);
-}
-
-
-static int
-canusb_stats_linux(pcap_t *handle, struct pcap_stat *stats)
-{
-    /* not yet implemented */
-    stats->ps_recv = 0;     /* number of packets received */
-    stats->ps_drop = 0;     /* number of packets dropped */
-    stats->ps_ifdrop = 0;   /* drops by interface -- only supported on some platforms */
-    return 0;
-}
-
-
-static int
-canusb_setfilter_linux(pcap_t *p, struct bpf_program *fp)
-{
-    /* not yet implemented */
-    return 0;
-}
-
-
-static int
-canusb_setdirection_linux(pcap_t *p, pcap_direction_t d)
-{
-    /* no support for PCAP_D_OUT */
-    if (d == PCAP_D_OUT)
-    {
-        snprintf(p->errbuf, sizeof(p->errbuf),
-            "Setting direction to PCAP_D_OUT is not supported on this interface");
-        return -1;
-    }
-
-    p->direction = d;
-
-    return 0;
-}
-
-
-/* eof */
diff --git a/pcap-common.c b/pcap-common.c
index b6f0c97..84368f6 100644
--- a/pcap-common.c
+++ b/pcap-common.c
@@ -25,9 +25,9 @@
 #include "config.h"
 #endif
 
-#ifdef WIN32
+#ifdef _WIN32
 #include <pcap-stdinc.h>
-#else /* WIN32 */
+#else /* _WIN32 */
 #if HAVE_INTTYPES_H
 #include <inttypes.h>
 #elif HAVE_STDINT_H
@@ -37,11 +37,14 @@
 #include <sys/bitypes.h>
 #endif
 #include <sys/types.h>
-#endif /* WIN32 */
+#endif /* _WIN32 */
 
 #include "pcap-int.h"
+#include "extract.h"
+#include "pcap/sll.h"
 #include "pcap/usb.h"
 #include "pcap/nflog.h"
+#include "pcap/can_socketcan.h"
 
 #include "pcap-common.h"
 
@@ -351,7 +354,7 @@
 
 #define LINKTYPE_GPRS_LLC	169		/* GPRS LLC */
 #define LINKTYPE_GPF_T		170		/* GPF-T (ITU-T G.7041/Y.1303) */
-#define LINKTYPE_GPF_F		171		/* GPF-T (ITU-T G.7041/Y.1303) */
+#define LINKTYPE_GPF_F		171		/* GPF-F (ITU-T G.7041/Y.1303) */
 
 /*
  * Requested by Oolan Zimmer <oz@gcom.com> for use in Gcom's T1/E1 line
@@ -426,10 +429,17 @@
 #define LINKTYPE_A653_ICM       185
 
 /*
- * USB packets, beginning with a USB setup header; requested by
- * Paolo Abeni <paolo.abeni@email.it>.
+ * This used to be "USB packets, beginning with a USB setup header;
+ * requested by Paolo Abeni <paolo.abeni@email.it>."
+ *
+ * However, that header didn't work all that well - it left out some
+ * useful information - and was abandoned in favor of the DLT_USB_LINUX
+ * header.
+ *
+ * This is now used by FreeBSD for its BPF taps for USB; that has its
+ * own headers.  So it is written, so it is done.
  */
-#define LINKTYPE_USB		186
+#define LINKTYPE_USB_FREEBSD	186
 
 /*
  * Bluetooth HCI UART transport layer (part H:4); requested by
@@ -736,8 +746,10 @@
 
 /*
  * CAN (Controller Area Network) frames, with a pseudo-header as supplied
- * by Linux SocketCAN.  See Documentation/networking/can.txt in the Linux
- * source.
+ * by Linux SocketCAN, and with multi-byte numerical fields in that header
+ * in big-endian byte order.
+ *
+ * See Documentation/networking/can.txt in the Linux source.
  *
  * Requested by Felix Obenhuber <felix@obenhuber.de>.
  */
@@ -959,7 +971,6 @@
  */
 #define LINKTYPE_PROFIBUS_DL		257
 
-
 /*
  * Apple's DLT_PKTAP headers.
  *
@@ -1000,7 +1011,24 @@
 #define LINKTYPE_ZWAVE_R1_R2	261
 #define LINKTYPE_ZWAVE_R3	262
 
-#define LINKTYPE_MATCHING_MAX	262		/* highest value in the "matching" range */
+/*
+ * per Steve Karg <skarg@users.sourceforge.net>, formats for Wattstopper
+ * Digital Lighting Management room bus serial protocol captures.
+ */
+#define LINKTYPE_WATTSTOPPER_DLM 263
+
+/*
+ * ISO 14443 contactless smart card messages.
+ */
+#define LINKTYPE_ISO_14443      264
+
+/*
+ * Radio data system (RDS) groups.  IEC 62106.
+ * Per Jonathan Brucker <jonathan.brucke@gmail.com>.
+ */
+#define LINKTYPE_RDS		265
+
+#define LINKTYPE_MATCHING_MAX	265		/* highest value in the "matching" range */
 
 static struct linktype_map {
 	int	dlt;
@@ -1147,6 +1175,48 @@
 	return linktype;
 }
 
+#define EXTRACT_
+
+/*
+ * DLT_LINUX_SLL packets with a protocol type of LINUX_SLL_P_CAN or
+ * LINUX_SLL_P_CANFD have SocketCAN headers in front of the payload,
+ * with the CAN ID being in host byte order.
+ *
+ * When reading a DLT_LINUX_SLL capture file, we need to check for those
+ * packets and convert the CAN ID from the byte order of the host that
+ * wrote the file to this host's byte order.
+ */
+static void
+swap_linux_sll_header(const struct pcap_pkthdr *hdr, u_char *buf)
+{
+	u_int caplen = hdr->caplen;
+	u_int length = hdr->len;
+	struct sll_header *shdr = (struct sll_header *)buf;
+	u_int16_t protocol;
+	pcap_can_socketcan_hdr *chdr;
+
+	if (caplen < (u_int) sizeof(struct sll_header) ||
+	    length < (u_int) sizeof(struct sll_header)) {
+		/* Not enough data to have the protocol field */
+		return;
+	}
+
+	protocol = EXTRACT_16BITS(&shdr->sll_protocol);
+	if (protocol != LINUX_SLL_P_CAN && protocol != LINUX_SLL_P_CANFD)
+		return;
+
+	/*
+	 * SocketCAN packet; fix up the packet's header.
+	 */
+	chdr = (pcap_can_socketcan_hdr *)(buf + sizeof(struct sll_header));
+	if (caplen < (u_int) sizeof(struct sll_header) + sizeof(chdr->can_id) ||
+	    length < (u_int) sizeof(struct sll_header) + sizeof(chdr->can_id)) {
+		/* Not enough data to have the CAN ID */
+		return;
+	}
+	chdr->can_id = SWAPLONG(chdr->can_id);
+}
+
 /*
  * The DLT_USB_LINUX and DLT_USB_LINUX_MMAPPED headers are in host
  * byte order when capturing (it's supplied directly from a
@@ -1316,7 +1386,8 @@
 	u_int length = hdr->len;
 	u_int16_t size;
 
-	if (caplen < (int) sizeof(nflog_hdr_t) || length < (int) sizeof(nflog_hdr_t)) {
+	if (caplen < (u_int) sizeof(nflog_hdr_t) ||
+	    length < (u_int) sizeof(nflog_hdr_t)) {
 		/* Not enough data to have any TLVs. */
 		return;
 	}
@@ -1371,6 +1442,10 @@
 	 */
 	switch (linktype) {
 
+	case DLT_LINUX_SLL:
+		swap_linux_sll_header(hdr, data);
+		break;
+
 	case DLT_USB_LINUX:
 		swap_linux_usb_header(hdr, data, 0);
 		break;
diff --git a/pcap-config b/pcap-config
new file mode 100755
index 0000000..ec97bd7
--- /dev/null
+++ b/pcap-config
@@ -0,0 +1,89 @@
+#! /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.1 b/pcap-config.1
index 2a2272b..0388d0f 100644
--- a/pcap-config.1
+++ b/pcap-config.1
@@ -18,7 +18,7 @@
 .\" WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
 .\" MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
 .\"
-.TH PCAP-CONFIG 1 "22 May 2009"
+.TH PCAP-CONFIG 1 "15 February 2015"
 .SH NAME
 pcap-config \- write libpcap compiler and linker flags to standard output
 .SH SYNOPSIS
diff --git a/pcap-dag.c b/pcap-dag.c
index 4915248..201696c 100644
--- a/pcap-dag.c
+++ b/pcap-dag.c
@@ -53,6 +53,99 @@
 #define DAG_MAX_BOARDS 32
 #endif
 
+
+#ifndef TYPE_AAL5
+#define TYPE_AAL5               4
+#endif
+
+#ifndef TYPE_MC_HDLC
+#define TYPE_MC_HDLC            5
+#endif
+
+#ifndef TYPE_MC_RAW
+#define TYPE_MC_RAW             6
+#endif
+
+#ifndef TYPE_MC_ATM
+#define TYPE_MC_ATM             7
+#endif
+
+#ifndef TYPE_MC_RAW_CHANNEL
+#define TYPE_MC_RAW_CHANNEL     8
+#endif
+
+#ifndef TYPE_MC_AAL5
+#define TYPE_MC_AAL5            9
+#endif
+
+#ifndef TYPE_COLOR_HDLC_POS
+#define TYPE_COLOR_HDLC_POS     10
+#endif
+
+#ifndef TYPE_COLOR_ETH
+#define TYPE_COLOR_ETH          11
+#endif
+
+#ifndef TYPE_MC_AAL2
+#define TYPE_MC_AAL2            12
+#endif
+
+#ifndef TYPE_IP_COUNTER
+#define TYPE_IP_COUNTER         13
+#endif
+
+#ifndef TYPE_TCP_FLOW_COUNTER
+#define TYPE_TCP_FLOW_COUNTER   14
+#endif
+
+#ifndef TYPE_DSM_COLOR_HDLC_POS
+#define TYPE_DSM_COLOR_HDLC_POS 15
+#endif
+
+#ifndef TYPE_DSM_COLOR_ETH
+#define TYPE_DSM_COLOR_ETH      16
+#endif
+
+#ifndef TYPE_COLOR_MC_HDLC_POS
+#define TYPE_COLOR_MC_HDLC_POS  17
+#endif
+
+#ifndef TYPE_AAL2
+#define TYPE_AAL2               18
+#endif
+
+#ifndef TYPE_COLOR_HASH_POS
+#define TYPE_COLOR_HASH_POS     19
+#endif
+
+#ifndef TYPE_COLOR_HASH_ETH
+#define TYPE_COLOR_HASH_ETH     20
+#endif
+
+#ifndef TYPE_INFINIBAND
+#define TYPE_INFINIBAND         21
+#endif
+
+#ifndef TYPE_IPV4
+#define TYPE_IPV4               22
+#endif
+
+#ifndef TYPE_IPV6
+#define TYPE_IPV6               23
+#endif
+
+#ifndef TYPE_RAW_LINK
+#define TYPE_RAW_LINK           24
+#endif
+
+#ifndef TYPE_INFINIBAND_LINK
+#define TYPE_INFINIBAND_LINK    25
+#endif
+
+#ifndef TYPE_PAD
+#define TYPE_PAD                48
+#endif
+
 #define ATM_CELL_SIZE		52
 #define ATM_HDR_SIZE		4
 
@@ -144,28 +237,25 @@
 static void
 dag_platform_cleanup(pcap_t *p)
 {
-	struct pcap_dag *pd;
+	struct pcap_dag *pd = p->pr;
 
-	if (p != NULL) {
-		pd = p->priv;
 #ifdef HAVE_DAG_STREAMS_API
-		if(dag_stop_stream(p->fd, pd->dag_stream) < 0)
-			fprintf(stderr,"dag_stop_stream: %s\n", strerror(errno));
+	if(dag_stop_stream(p->fd, pd->dag_stream) < 0)
+		fprintf(stderr,"dag_stop_stream: %s\n", strerror(errno));
 
-		if(dag_detach_stream(p->fd, pd->dag_stream) < 0)
-			fprintf(stderr,"dag_detach_stream: %s\n", strerror(errno));
+	if(dag_detach_stream(p->fd, pd->dag_stream) < 0)
+		fprintf(stderr,"dag_detach_stream: %s\n", strerror(errno));
 #else
-		if(dag_stop(p->fd) < 0)
-			fprintf(stderr,"dag_stop: %s\n", strerror(errno));
+	if(dag_stop(p->fd) < 0)
+		fprintf(stderr,"dag_stop: %s\n", strerror(errno));
 #endif /* HAVE_DAG_STREAMS_API */
-		if(p->fd != -1) {
-			if(dag_close(p->fd) < 0)
-				fprintf(stderr,"dag_close: %s\n", strerror(errno));
-			p->fd = -1;
-		}
-		delete_pcap_dag(p);
-		pcap_cleanup_live_common(p);
+	if(p->fd != -1) {
+		if(dag_close(p->fd) < 0)
+			fprintf(stderr,"dag_close: %s\n", strerror(errno));
+		p->fd = -1;
 	}
+	delete_pcap_dag(p);
+	pcap_cleanup_live_common(p);
 	/* Note: don't need to call close(p->fd) here as dag_close(p->fd) does this. */
 }
 
@@ -174,7 +264,8 @@
 {
 	while (pcap_dags != NULL) {
 		if (pcap_dags->pid == getpid()) {
-			dag_platform_cleanup(pcap_dags->p);
+			if (pcap_dags->p != NULL)
+				dag_platform_cleanup(pcap_dags->p);
 		} else {
 			delete_pcap_dag(pcap_dags->p);
 		}
@@ -634,7 +725,7 @@
 	int n;
 	daginf_t* daginf;
 	char * newDev = NULL;
-	char * device = handle->opt.source;
+	char * device = handle->opt.device;
 #ifdef HAVE_DAG_STREAMS_API
 	uint32_t mindata;
 	struct timeval maxwait;
@@ -642,7 +733,7 @@
 #endif
 
 	if (device == NULL) {
-		snprintf(handle->errbuf, PCAP_ERRBUF_SIZE, "device is NULL: %s", pcap_strerror(errno));
+		pcap_snprintf(handle->errbuf, PCAP_ERRBUF_SIZE, "device is NULL: %s", pcap_strerror(errno));
 		return -1;
 	}
 
@@ -651,26 +742,26 @@
 #ifdef HAVE_DAG_STREAMS_API
 	newDev = (char *)malloc(strlen(device) + 16);
 	if (newDev == NULL) {
-		snprintf(handle->errbuf, PCAP_ERRBUF_SIZE, "Can't allocate string for device name: %s\n", pcap_strerror(errno));
+		pcap_snprintf(handle->errbuf, PCAP_ERRBUF_SIZE, "Can't allocate string for device name: %s", pcap_strerror(errno));
 		goto fail;
 	}
 
 	/* Parse input name to get dag device and stream number if provided */
 	if (dag_parse_name(device, newDev, strlen(device) + 16, &handlep->dag_stream) < 0) {
-		snprintf(handle->errbuf, PCAP_ERRBUF_SIZE, "dag_parse_name: %s\n", pcap_strerror(errno));
+		pcap_snprintf(handle->errbuf, PCAP_ERRBUF_SIZE, "dag_parse_name: %s", pcap_strerror(errno));
 		goto fail;
 	}
 	device = newDev;
 
 	if (handlep->dag_stream%2) {
-		snprintf(handle->errbuf, PCAP_ERRBUF_SIZE, "dag_parse_name: tx (even numbered) streams not supported for capture\n");
+		pcap_snprintf(handle->errbuf, PCAP_ERRBUF_SIZE, "dag_parse_name: tx (even numbered) streams not supported for capture");
 		goto fail;
 	}
 #else
 	if (strncmp(device, "/dev/", 5) != 0) {
 		newDev = (char *)malloc(strlen(device) + 5);
 		if (newDev == NULL) {
-			snprintf(handle->errbuf, PCAP_ERRBUF_SIZE, "Can't allocate string for device name: %s\n", pcap_strerror(errno));
+			pcap_snprintf(handle->errbuf, PCAP_ERRBUF_SIZE, "Can't allocate string for device name: %s", pcap_strerror(errno));
 			goto fail;
 		}
 		strcpy(newDev, "/dev/");
@@ -681,14 +772,14 @@
 
 	/* setup device parameters */
 	if((handle->fd = dag_open((char *)device)) < 0) {
-		snprintf(handle->errbuf, PCAP_ERRBUF_SIZE, "dag_open %s: %s", device, pcap_strerror(errno));
+		pcap_snprintf(handle->errbuf, PCAP_ERRBUF_SIZE, "dag_open %s: %s", device, pcap_strerror(errno));
 		goto fail;
 	}
 
 #ifdef HAVE_DAG_STREAMS_API
 	/* Open requested stream. Can fail if already locked or on error */
 	if (dag_attach_stream(handle->fd, handlep->dag_stream, 0, 0) < 0) {
-		snprintf(handle->errbuf, PCAP_ERRBUF_SIZE, "dag_attach_stream: %s\n", pcap_strerror(errno));
+		pcap_snprintf(handle->errbuf, PCAP_ERRBUF_SIZE, "dag_attach_stream: %s", pcap_strerror(errno));
 		goto failclose;
 	}
 
@@ -697,7 +788,7 @@
 	 */
 	if (dag_get_stream_poll(handle->fd, handlep->dag_stream,
 				&mindata, &maxwait, &poll) < 0) {
-		snprintf(handle->errbuf, PCAP_ERRBUF_SIZE, "dag_get_stream_poll: %s\n", pcap_strerror(errno));
+		pcap_snprintf(handle->errbuf, PCAP_ERRBUF_SIZE, "dag_get_stream_poll: %s", pcap_strerror(errno));
 		goto faildetach;
 	}
 
@@ -722,13 +813,13 @@
 
 	if (dag_set_stream_poll(handle->fd, handlep->dag_stream,
 				mindata, &maxwait, &poll) < 0) {
-		snprintf(handle->errbuf, PCAP_ERRBUF_SIZE, "dag_set_stream_poll: %s\n", pcap_strerror(errno));
+		pcap_snprintf(handle->errbuf, PCAP_ERRBUF_SIZE, "dag_set_stream_poll: %s", pcap_strerror(errno));
 		goto faildetach;
 	}
 
 #else
 	if((handlep->dag_mem_base = dag_mmap(handle->fd)) == MAP_FAILED) {
-		snprintf(handle->errbuf, PCAP_ERRBUF_SIZE,"dag_mmap %s: %s\n", device, pcap_strerror(errno));
+		pcap_snprintf(handle->errbuf, PCAP_ERRBUF_SIZE,"dag_mmap %s: %s", device, pcap_strerror(errno));
 		goto failclose;
 	}
 
@@ -748,22 +839,22 @@
 		handle->snapshot = MIN_DAG_SNAPLEN;
 	}
 	/* snap len has to be a multiple of 4 */
-	snprintf(conf, 30, "varlen slen=%d", (snaplen + 3) & ~3);
+	pcap_snprintf(conf, 30, "varlen slen=%d", (snaplen + 3) & ~3);
 
 	if(dag_configure(handle->fd, conf) < 0) {
-		snprintf(handle->errbuf, PCAP_ERRBUF_SIZE,"dag_configure %s: %s\n", device, pcap_strerror(errno));
+		pcap_snprintf(handle->errbuf, PCAP_ERRBUF_SIZE,"dag_configure %s: %s", device, pcap_strerror(errno));
 		goto faildetach;
 	}
 #endif
 
 #ifdef HAVE_DAG_STREAMS_API
 	if(dag_start_stream(handle->fd, handlep->dag_stream) < 0) {
-		snprintf(handle->errbuf, PCAP_ERRBUF_SIZE, "dag_start_stream %s: %s\n", device, pcap_strerror(errno));
+		pcap_snprintf(handle->errbuf, PCAP_ERRBUF_SIZE, "dag_start_stream %s: %s", device, pcap_strerror(errno));
 		goto faildetach;
 	}
 #else
 	if(dag_start(handle->fd) < 0) {
-		snprintf(handle->errbuf, PCAP_ERRBUF_SIZE, "dag_start %s: %s\n", device, pcap_strerror(errno));
+		pcap_snprintf(handle->errbuf, PCAP_ERRBUF_SIZE, "dag_start %s: %s", device, pcap_strerror(errno));
 		goto failclose;
 	}
 #endif /* HAVE_DAG_STREAMS_API */
@@ -798,8 +889,8 @@
 			if ((n = atoi(s)) == 0 || n == 16 || n == 32) {
 				handlep->dag_fcs_bits = n;
 			} else {
-				snprintf(handle->errbuf, PCAP_ERRBUF_SIZE,
-					"pcap_activate %s: bad ERF_FCS_BITS value (%d) in environment\n", device, n);
+				pcap_snprintf(handle->errbuf, PCAP_ERRBUF_SIZE,
+					"pcap_activate %s: bad ERF_FCS_BITS value (%d) in environment", device, n);
 				goto failstop;
 			}
 		}
@@ -826,7 +917,7 @@
 	handle->bufsize = 0;
 
 	if (new_pcap_dag(handle) < 0) {
-		snprintf(handle->errbuf, PCAP_ERRBUF_SIZE, "new_pcap_dag %s: %s\n", device, pcap_strerror(errno));
+		pcap_snprintf(handle->errbuf, PCAP_ERRBUF_SIZE, "new_pcap_dag %s: %s", device, pcap_strerror(errno));
 		goto failstop;
 	}
 
@@ -932,7 +1023,7 @@
 	/* OK, it's probably ours. */
 	*is_ours = 1;
 
-	p = pcap_create_common(device, ebuf, sizeof (struct pcap_dag));
+	p = pcap_create_common(ebuf, sizeof (struct pcap_dag));
 	if (p == NULL)
 		return NULL;
 
@@ -948,11 +1039,9 @@
 	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_snprintf(ebuf, PCAP_ERRBUF_SIZE, "malloc: %s",
 		    pcap_strerror(errno));
-		if (p->tstamp_type_list != NULL)
-			free(p->tstamp_type_list);
-		free(p);
+		pcap_close(p);
 		return NULL;
 	}
 	p->tstamp_precision_list[0] = PCAP_TSTAMP_PRECISION_MICRO;
@@ -998,7 +1087,7 @@
 
 	/* Try all the DAGs 0-DAG_MAX_BOARDS */
 	for (c = 0; c < DAG_MAX_BOARDS; c++) {
-		snprintf(name, 12, "dag%d", c);
+		pcap_snprintf(name, 12, "dag%d", c);
 		if (-1 == dag_parse_name(name, dagname, DAGNAME_BUFSIZE, &dagstream))
 		{
 			return -1;
@@ -1021,7 +1110,7 @@
 					if (0 == dag_attach_stream(dagfd, stream, 0, 0)) {
 						dag_detach_stream(dagfd, stream);
 
-						snprintf(name,  10, "dag%d:%d", c, stream);
+						pcap_snprintf(name,  10, "dag%d:%d", c, stream);
 						if (pcap_add_if(devlistp, name, 0, description, errbuf) == -1) {
 							/*
 							 * Failure.
@@ -1097,7 +1186,7 @@
 
 		if (dag_get_stream_poll(p->fd, pd->dag_stream,
 					&mindata, &maxwait, &poll) < 0) {
-			snprintf(errbuf, PCAP_ERRBUF_SIZE, "dag_get_stream_poll: %s\n", pcap_strerror(errno));
+			pcap_snprintf(errbuf, PCAP_ERRBUF_SIZE, "dag_get_stream_poll: %s", pcap_strerror(errno));
 			return -1;
 		}
 
@@ -1112,7 +1201,7 @@
 
 		if (dag_set_stream_poll(p->fd, pd->dag_stream,
 					mindata, &maxwait, &poll) < 0) {
-			snprintf(errbuf, PCAP_ERRBUF_SIZE, "dag_set_stream_poll: %s\n", pcap_strerror(errno));
+			pcap_snprintf(errbuf, PCAP_ERRBUF_SIZE, "dag_set_stream_poll: %s", pcap_strerror(errno));
 			return -1;
 		}
 	}
@@ -1135,7 +1224,7 @@
 	memset(types, 0, 255);
 
 	if (p->dlt_list == NULL && (p->dlt_list = malloc(255*sizeof(*(p->dlt_list)))) == NULL) {
-		(void)snprintf(p->errbuf, sizeof(p->errbuf), "malloc: %s", pcap_strerror(errno));
+		(void)pcap_snprintf(p->errbuf, sizeof(p->errbuf), "malloc: %s", pcap_strerror(errno));
 		return (-1);
 	}
 
@@ -1144,7 +1233,7 @@
 #ifdef HAVE_DAG_GET_STREAM_ERF_TYPES
 	/* Get list of possible ERF types for this card */
 	if (dag_get_stream_erf_types(p->fd, pd->dag_stream, types, 255) < 0) {
-		snprintf(p->errbuf, sizeof(p->errbuf), "dag_get_stream_erf_types: %s", pcap_strerror(errno));
+		pcap_snprintf(p->errbuf, sizeof(p->errbuf), "dag_get_stream_erf_types: %s", pcap_strerror(errno));
 		return (-1);
 	}
 
@@ -1153,7 +1242,7 @@
 #elif defined HAVE_DAG_GET_ERF_TYPES
 	/* Get list of possible ERF types for this card */
 	if (dag_get_erf_types(p->fd, types, 255) < 0) {
-		snprintf(p->errbuf, sizeof(p->errbuf), "dag_get_erf_types: %s", pcap_strerror(errno));
+		pcap_snprintf(p->errbuf, sizeof(p->errbuf), "dag_get_erf_types: %s", pcap_strerror(errno));
 		return (-1);
 	}
 
@@ -1260,3 +1349,31 @@
 
 	return p->linktype;
 }
+
+#ifdef DAG_ONLY
+/*
+ * This libpcap build supports only DAG cards, not regular network
+ * interfaces.
+ */
+
+/*
+ * There are no regular interfaces, just DAG interfaces.
+ */
+int
+pcap_platform_finddevs(pcap_if_t **alldevsp, char *errbuf)
+{
+	*alldevsp = NULL;
+	return (0);
+}
+
+/*
+ * Attempts to open a regular interface fail.
+ */
+pcap_t *
+pcap_create_interface(const char *device, char *errbuf)
+{
+	pcap_snprintf(errbuf, PCAP_ERRBUF_SIZE,
+	    "This version of libpcap only supports DAG cards");
+	return NULL;
+}
+#endif
diff --git a/pcap-dag.h b/pcap-dag.h
index 68520dc..dfeccd8 100644
--- a/pcap-dag.h
+++ b/pcap-dag.h
@@ -10,97 +10,3 @@
 
 pcap_t *dag_create(const char *, char *, int *);
 int dag_findalldevs(pcap_if_t **devlistp, char *errbuf);
-
-#ifndef TYPE_AAL5
-#define TYPE_AAL5               4
-#endif
-
-#ifndef TYPE_MC_HDLC
-#define TYPE_MC_HDLC            5
-#endif
-
-#ifndef TYPE_MC_RAW
-#define TYPE_MC_RAW             6
-#endif
-
-#ifndef TYPE_MC_ATM
-#define TYPE_MC_ATM             7
-#endif
-
-#ifndef TYPE_MC_RAW_CHANNEL
-#define TYPE_MC_RAW_CHANNEL     8
-#endif
-
-#ifndef TYPE_MC_AAL5
-#define TYPE_MC_AAL5            9
-#endif
-
-#ifndef TYPE_COLOR_HDLC_POS
-#define TYPE_COLOR_HDLC_POS     10
-#endif
-
-#ifndef TYPE_COLOR_ETH
-#define TYPE_COLOR_ETH          11
-#endif
-
-#ifndef TYPE_MC_AAL2
-#define TYPE_MC_AAL2            12
-#endif
-
-#ifndef TYPE_IP_COUNTER
-#define TYPE_IP_COUNTER         13
-#endif
-
-#ifndef TYPE_TCP_FLOW_COUNTER
-#define TYPE_TCP_FLOW_COUNTER   14
-#endif
-
-#ifndef TYPE_DSM_COLOR_HDLC_POS
-#define TYPE_DSM_COLOR_HDLC_POS 15
-#endif
-
-#ifndef TYPE_DSM_COLOR_ETH
-#define TYPE_DSM_COLOR_ETH      16
-#endif
-
-#ifndef TYPE_COLOR_MC_HDLC_POS
-#define TYPE_COLOR_MC_HDLC_POS  17
-#endif
-
-#ifndef TYPE_AAL2
-#define TYPE_AAL2               18
-#endif
-
-#ifndef TYPE_COLOR_HASH_POS
-#define TYPE_COLOR_HASH_POS     19
-#endif
-
-#ifndef TYPE_COLOR_HASH_ETH
-#define TYPE_COLOR_HASH_ETH     20
-#endif
-
-#ifndef TYPE_INFINIBAND
-#define TYPE_INFINIBAND         21
-#endif
-
-#ifndef TYPE_IPV4
-#define TYPE_IPV4               22
-#endif
-
-#ifndef TYPE_IPV6
-#define TYPE_IPV6               23
-#endif
-
-#ifndef TYPE_RAW_LINK
-#define TYPE_RAW_LINK           24
-#endif
-
-#ifndef TYPE_INFINIBAND_LINK
-#define TYPE_INFINIBAND_LINK    25
-#endif
-
-
-
-#ifndef TYPE_PAD
-#define TYPE_PAD                48
-#endif
diff --git a/pcap-dbus.c b/pcap-dbus.c
index ab3f125..8e92093 100644
--- a/pcap-dbus.c
+++ b/pcap-dbus.c
@@ -66,9 +66,9 @@
 	message = dbus_connection_pop_message(handlep->conn);
 
 	while (!message) {
-		// XXX handle->opt.timeout = timeout_ms;
+		/* XXX handle->opt.timeout = timeout_ms; */
 		if (!dbus_connection_read_write(handlep->conn, 100)) {
-			snprintf(handle->errbuf, PCAP_ERRBUF_SIZE, "Connection closed");
+			pcap_snprintf(handle->errbuf, PCAP_ERRBUF_SIZE, "Connection closed");
 			return -1;
 		}
 
@@ -81,7 +81,7 @@
 	}
 
 	if (dbus_message_is_signal(message, DBUS_INTERFACE_LOCAL, "Disconnected")) {
-		snprintf(handle->errbuf, PCAP_ERRBUF_SIZE, "Disconnected");
+		pcap_snprintf(handle->errbuf, PCAP_ERRBUF_SIZE, "Disconnected");
 		return -1;
 	}
 
@@ -112,7 +112,7 @@
 	DBusMessage *msg;
 
 	if (!(msg = dbus_message_demarshal(buf, size, &error))) {
-		snprintf(handle->errbuf, PCAP_ERRBUF_SIZE, "dbus_message_demarshal() failed: %s", error.message);
+		pcap_snprintf(handle->errbuf, PCAP_ERRBUF_SIZE, "dbus_message_demarshal() failed: %s", error.message);
 		dbus_error_free(&error);
 		return -1;
 	}
@@ -160,21 +160,21 @@
 	#define N_RULES sizeof(rules)/sizeof(rules[0])
 
 	struct pcap_dbus *handlep = handle->priv;
-	const char *dev = handle->opt.source;
+	const char *dev = handle->opt.device;
 
 	DBusError error = DBUS_ERROR_INIT;
-	int i;
+	u_int i;
 
 	if (strcmp(dev, "dbus-system") == 0) {
 		if (!(handlep->conn = dbus_bus_get(DBUS_BUS_SYSTEM, &error))) {
-			snprintf(handle->errbuf, PCAP_ERRBUF_SIZE, "Failed to get system bus: %s", error.message);
+			pcap_snprintf(handle->errbuf, PCAP_ERRBUF_SIZE, "Failed to get system bus: %s", error.message);
 			dbus_error_free(&error);
 			return PCAP_ERROR;
 		}
 
 	} else if (strcmp(dev, "dbus-session") == 0) {
 		if (!(handlep->conn = dbus_bus_get(DBUS_BUS_SESSION, &error))) {
-			snprintf(handle->errbuf, PCAP_ERRBUF_SIZE, "Failed to get session bus: %s", error.message);
+			pcap_snprintf(handle->errbuf, PCAP_ERRBUF_SIZE, "Failed to get session bus: %s", error.message);
 			dbus_error_free(&error);
 			return PCAP_ERROR;
 		}
@@ -183,19 +183,19 @@
 		const char *addr = dev + 7;
 
 		if (!(handlep->conn = dbus_connection_open(addr, &error))) {
-			snprintf(handle->errbuf, PCAP_ERRBUF_SIZE, "Failed to open connection to: %s: %s", addr, error.message);
+			pcap_snprintf(handle->errbuf, PCAP_ERRBUF_SIZE, "Failed to open connection to: %s: %s", addr, error.message);
 			dbus_error_free(&error);
 			return PCAP_ERROR;
 		}
 
 		if (!dbus_bus_register(handlep->conn, &error)) {
-			snprintf(handle->errbuf, PCAP_ERRBUF_SIZE, "Failed to register bus %s: %s\n", addr, error.message);
+			pcap_snprintf(handle->errbuf, PCAP_ERRBUF_SIZE, "Failed to register bus %s: %s\n", addr, error.message);
 			dbus_error_free(&error);
 			return PCAP_ERROR;
 		}
 
 	} else {
-		snprintf(handle->errbuf, PCAP_ERRBUF_SIZE, "Can't get bus address from %s", handle->opt.source);
+		pcap_snprintf(handle->errbuf, PCAP_ERRBUF_SIZE, "Can't get bus address from %s", handle->opt.device);
 		return PCAP_ERROR;
 	}
 
@@ -234,7 +234,7 @@
 			/* try without eavesdrop */
 			dbus_bus_add_match(handlep->conn, rules[i] + strlen(EAVESDROPPING_RULE), &error);
 			if (dbus_error_is_set(&error)) {
-				snprintf(handle->errbuf, PCAP_ERRBUF_SIZE, "Failed to add bus match: %s\n", error.message);
+				pcap_snprintf(handle->errbuf, PCAP_ERRBUF_SIZE, "Failed to add bus match: %s\n", error.message);
 				dbus_error_free(&error);
 				dbus_cleanup(handle);
 				return PCAP_ERROR;
@@ -259,7 +259,7 @@
 	}
 
 	*is_ours = 1;
-	p = pcap_create_common(device, ebuf, sizeof (struct pcap_dbus));
+	p = pcap_create_common(ebuf, sizeof (struct pcap_dbus));
 	if (p == NULL)
 		return (NULL);
 
diff --git a/pcap-dlpi.c b/pcap-dlpi.c
index c007135..a431e7c 100644
--- a/pcap-dlpi.c
+++ b/pcap-dlpi.c
@@ -153,10 +153,12 @@
 static int dlrawdatareq(int, const u_char *, int);
 #endif
 static int recv_ack(int, int, const char *, char *, char *, int *);
-static char *dlstrerror(bpf_u_int32);
-static char *dlprim(bpf_u_int32);
+static char *dlstrerror(char *, size_t, bpf_u_int32);
+static char *dlprim(char *, size_t, bpf_u_int32);
 #if defined(HAVE_SOLARIS) && defined(HAVE_SYS_BUFMOD_H)
-static char *get_release(bpf_u_int32 *, bpf_u_int32 *, bpf_u_int32 *);
+#define GET_RELEASE_BUFSIZE	32
+static void get_release(char *, size_t, bpf_u_int32 *, bpf_u_int32 *,
+    bpf_u_int32 *);
 #endif
 static int send_request(int, char *, int, char *, char *);
 #ifdef HAVE_HPUX9
@@ -166,14 +168,6 @@
 static int get_dlpi_ppa(int, const char *, int, char *);
 #endif
 
-/* XXX Needed by HP-UX (at least) */
-static bpf_u_int32 ctlbuf[MAXDLBUF];
-static struct strbuf ctl = {
-	MAXDLBUF,
-	0,
-	(char *)ctlbuf
-};
-
 /*
  * Cast a buffer to "union DL_primitives" without provoking warnings
  * from the compiler.
@@ -186,6 +180,12 @@
 	int cc;
 	u_char *bp;
 	int flags;
+	bpf_u_int32 ctlbuf[MAXDLBUF];
+	struct strbuf ctl = {
+		MAXDLBUF,
+		0,
+		(char *)ctlbuf
+	};
 	struct strbuf data;
 
 	flags = 0;
@@ -213,6 +213,9 @@
 			 * would be DL_HP_RAWDATA_IND on HP-UX
 			 * if we're in raw mode?
 			 */
+			ctl.buf = (char *)ctlbuf;
+			ctl.maxlen = MAXDLBUF;
+			ctl.len = 0;
 			if (getmsg(p->fd, &ctl, &data, &flags) < 0) {
 				/* Don't choke when we get ptraced */
 				switch (errno) {
@@ -230,7 +233,7 @@
 			}
 			cc = data.len;
 		} while (cc == 0);
-		bp = p->buffer + p->offset;
+		bp = (u_char *)p->buffer + p->offset;
 	} else
 		bp = p->bp;
 
@@ -248,19 +251,19 @@
 #if defined(DLIOCRAW)
 	ret = write(p->fd, buf, size);
 	if (ret == -1) {
-		snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "send: %s",
+		pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "send: %s",
 		    pcap_strerror(errno));
 		return (-1);
 	}
 #elif defined(DL_HP_RAWDLS)
 	if (pd->send_fd < 0) {
-		snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
+		pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
 		    "send: Output FD couldn't be opened");
 		return (-1);
 	}
 	ret = dlrawdatareq(pd->send_fd, buf, size);
 	if (ret == -1) {
-		snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "send: %s",
+		pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "send: %s",
 		    pcap_strerror(errno));
 		return (-1);
 	}
@@ -331,28 +334,12 @@
 }
 
 static int
-pcap_activate_dlpi(pcap_t *p)
+open_dlpi_device(const char *name, int *ppa, char *errbuf)
 {
-#ifdef DL_HP_RAWDLS
-	struct pcap_dlpi *pd = p->priv;
-#endif
-	int status = 0;
-	int retv;
-	register char *cp;
-	int ppa;
-#ifdef HAVE_SOLARIS
-	int isatm = 0;
-#endif
-	register dl_info_ack_t *infop;
-#ifdef HAVE_SYS_BUFMOD_H
-	bpf_u_int32 ss;
-#ifdef HAVE_SOLARIS
-	register char *release;
-	bpf_u_int32 osmajor, osminor, osmicro;
-#endif
-#endif
-	bpf_u_int32 buf[MAXDLBUF];
+	int status;
 	char dname[100];
+	char *cp;
+	int fd;
 #ifndef HAVE_DEV_DLPI
 	char dname2[100];
 #endif
@@ -361,9 +348,9 @@
 	/*
 	** Remove any "/dev/" on the front of the device.
 	*/
-	cp = strrchr(p->opt.source, '/');
+	cp = strrchr(name, '/');
 	if (cp == NULL)
-		strlcpy(dname, p->opt.source, sizeof(dname));
+		strlcpy(dname, name, sizeof(dname));
 	else
 		strlcpy(dname, cp + 1, sizeof(dname));
 
@@ -371,11 +358,9 @@
 	 * Split the device name into a device type name and a unit number;
 	 * chop off the unit number, so "dname" is just a device type name.
 	 */
-	cp = split_dname(dname, &ppa, p->errbuf);
-	if (cp == NULL) {
-		status = PCAP_ERROR_NO_SUCH_DEVICE;
-		goto bad;
-	}
+	cp = split_dname(dname, ppa, errbuf);
+	if (cp == NULL)
+		return (PCAP_ERROR_NO_SUCH_DEVICE);
 	*cp = '\0';
 
 	/*
@@ -390,13 +375,137 @@
 	 * device number, rather than hardwiring "/dev/dlpi".
 	 */
 	cp = "/dev/dlpi";
-	if ((p->fd = open(cp, O_RDWR)) < 0) {
+	if ((fd = open(cp, O_RDWR)) < 0) {
 		if (errno == EPERM || errno == EACCES)
 			status = PCAP_ERROR_PERM_DENIED;
 		else
 			status = PCAP_ERROR;
-		snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
+		pcap_snprintf(errbuf, PCAP_ERRBUF_SIZE,
 		    "%s: %s", cp, pcap_strerror(errno));
+		return (status);
+	}
+
+	/*
+	 * 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) {
+		close(fd);
+		return (*ppa);
+	}
+#else
+	/*
+	 * If the device name begins with "/", assume it begins with
+	 * the pathname of the directory containing the device to open;
+	 * otherwise, concatenate the device directory name and the
+	 * device name.
+	 */
+	if (*name == '/')
+		strlcpy(dname, name, sizeof(dname));
+	else
+		pcap_snprintf(dname, sizeof(dname), "%s/%s", PCAP_DEV_PREFIX,
+		    name);
+
+	/*
+	 * Get the unit number, and a pointer to the end of the device
+	 * type name.
+	 */
+	cp = split_dname(dname, ppa, errbuf);
+	if (cp == NULL)
+		return (PCAP_ERROR_NO_SUCH_DEVICE);
+
+	/*
+	 * Make a copy of the device pathname, and then remove the unit
+	 * number from the device pathname.
+	 */
+	strlcpy(dname2, dname, sizeof(dname));
+	*cp = '\0';
+
+	/* Try device without unit number */
+	if ((fd = open(dname, O_RDWR)) < 0) {
+		if (errno != ENOENT) {
+			if (errno == EPERM || errno == EACCES)
+				status = PCAP_ERROR_PERM_DENIED;
+			else
+				status = PCAP_ERROR;
+			pcap_snprintf(errbuf, PCAP_ERRBUF_SIZE, "%s: %s", dname,
+			    pcap_strerror(errno));
+			return (status);
+		}
+
+		/* Try again with unit number */
+		if ((fd = open(dname2, O_RDWR)) < 0) {
+			if (errno == ENOENT) {
+				status = PCAP_ERROR_NO_SUCH_DEVICE;
+
+				/*
+				 * We provide an error message even
+				 * for this error, for diagnostic
+				 * purposes (so that, for example,
+				 * the app can show the message if the
+				 * user requests it).
+				 *
+				 * In it, we just report "No DLPI device
+				 * found" with the device name, so people
+				 * don't get confused and think, for example,
+				 * that if they can't capture on "lo0"
+				 * on Solaris prior to Solaris 11 the fix
+				 * is to change libpcap (or the application
+				 * that uses it) to look for something other
+				 * than "/dev/lo0", as the fix is to use
+				 * Solaris 11 or some operating system
+				 * other than Solaris - you just *can't*
+				 * capture on a loopback interface
+				 * on Solaris prior to Solaris 11, the lack
+				 * of a DLPI device for the loopback
+				 * interface is just a symptom of that
+				 * inability.
+				 */
+				pcap_snprintf(errbuf, PCAP_ERRBUF_SIZE,
+				    "%s: No DLPI device found", name);
+			} else {
+				if (errno == EPERM || errno == EACCES)
+					status = PCAP_ERROR_PERM_DENIED;
+				else
+					status = PCAP_ERROR;
+				pcap_snprintf(errbuf, PCAP_ERRBUF_SIZE, "%s: %s",
+				    dname2, pcap_strerror(errno));
+			}
+			return (status);
+		}
+		/* XXX Assume unit zero */
+		*ppa = 0;
+	}
+#endif
+	return (fd);
+}
+
+static int
+pcap_activate_dlpi(pcap_t *p)
+{
+#ifdef DL_HP_RAWDLS
+	struct pcap_dlpi *pd = p->priv;
+#endif
+	int status = 0;
+	int retv;
+	int ppa;
+#ifdef HAVE_SOLARIS
+	int isatm = 0;
+#endif
+	register dl_info_ack_t *infop;
+#ifdef HAVE_SYS_BUFMOD_H
+	bpf_u_int32 ss;
+#ifdef HAVE_SOLARIS
+	char release[GET_RELEASE_BUFSIZE];
+	bpf_u_int32 osmajor, osminor, osmicro;
+#endif
+#endif
+	bpf_u_int32 buf[MAXDLBUF];
+
+	p->fd = open_dlpi_device(p->opt.device, &ppa, p->errbuf);
+	if (p->fd < 0) {
+		status = p->fd;
 		goto bad;
 	}
 
@@ -412,101 +521,7 @@
 	 * to open it for reading only and, if that succeeds, just let
 	 * the send attempts fail.
 	 */
-	pd->send_fd = open(cp, O_RDWR);
-#endif
-
-	/*
-	 * Get a table of all PPAs for that device, and search that
-	 * table for the specified device type name and unit number.
-	 */
-	ppa = get_dlpi_ppa(p->fd, dname, ppa, p->errbuf);
-	if (ppa < 0) {
-		status = ppa;
-		goto bad;
-	}
-#else
-	/*
-	 * If the device name begins with "/", assume it begins with
-	 * the pathname of the directory containing the device to open;
-	 * otherwise, concatenate the device directory name and the
-	 * device name.
-	 */
-	if (*p->opt.source == '/')
-		strlcpy(dname, p->opt.source, sizeof(dname));
-	else
-		snprintf(dname, sizeof(dname), "%s/%s", PCAP_DEV_PREFIX,
-		    p->opt.source);
-
-	/*
-	 * Get the unit number, and a pointer to the end of the device
-	 * type name.
-	 */
-	cp = split_dname(dname, &ppa, p->errbuf);
-	if (cp == NULL) {
-		status = PCAP_ERROR_NO_SUCH_DEVICE;
-		goto bad;
-	}
-
-	/*
-	 * Make a copy of the device pathname, and then remove the unit
-	 * number from the device pathname.
-	 */
-	strlcpy(dname2, dname, sizeof(dname));
-	*cp = '\0';
-
-	/* Try device without unit number */
-	if ((p->fd = open(dname, O_RDWR)) < 0) {
-		if (errno != ENOENT) {
-			if (errno == EPERM || errno == EACCES)
-				status = PCAP_ERROR_PERM_DENIED;
-			else
-				status = PCAP_ERROR;
-			snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "%s: %s", dname,
-			    pcap_strerror(errno));
-			goto bad;
-		}
-
-		/* Try again with unit number */
-		if ((p->fd = open(dname2, O_RDWR)) < 0) {
-			if (errno == ENOENT) {
-				status = PCAP_ERROR_NO_SUCH_DEVICE;
-
-				/*
-				 * We provide an error message even
-				 * for this error, for diagnostic
-				 * purposes (so that, for example,
-				 * the app can show the message if the
-				 * user requests it).
-				 *
-				 * In it, we just report "No DLPI device
-				 * found" with the device name, so people
-				 * don't get confused and think, for example,
-				 * that if they can't capture on "lo0"
-				 * on Solaris the fix is to change libpcap
-				 * (or the application that uses it) to
-				 * look for something other than "/dev/lo0",
-				 * as the fix is to look for an operating
-				 * system other than Solaris - you just
-				 * *can't* capture on a loopback interface
-				 * on Solaris, the lack of a DLPI device
-				 * for the loopback interface is just a
-				 * symptom of that inability.
-				 */
-				snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
-				    "%s: No DLPI device found", p->opt.source);
-			} else {
-				if (errno == EPERM || errno == EACCES)
-					status = PCAP_ERROR_PERM_DENIED;
-				else
-					status = PCAP_ERROR;
-				snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "%s: %s",
-				    dname2, pcap_strerror(errno));
-			}
-			goto bad;
-		}
-		/* XXX Assume unit zero */
-		ppa = 0;
-	}
+	pd->send_fd = open("/dev/dlpi", O_RDWR);
 #endif
 
 	/*
@@ -627,7 +642,7 @@
 		*/
 		if (strioctl(p->fd, A_PROMISCON_REQ, 0, NULL) < 0) {
 			status = PCAP_ERROR;
-			snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
+			pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
 			    "A_PROMISCON_REQ: %s", pcap_strerror(errno));
 			goto bad;
 		}
@@ -745,7 +760,7 @@
 	*/
 	if (strioctl(p->fd, DLIOCRAW, 0, NULL) < 0) {
 		status = PCAP_ERROR;
-		snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "DLIOCRAW: %s",
+		pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "DLIOCRAW: %s",
 		    pcap_strerror(errno));
 		goto bad;
 	}
@@ -763,10 +778,10 @@
 	** Ask for bugid 1149065.
 	*/
 #ifdef HAVE_SOLARIS
-	release = get_release(&osmajor, &osminor, &osmicro);
+	get_release(release, sizeof (release), &osmajor, &osminor, &osmicro);
 	if (osmajor == 5 && (osminor <= 2 || (osminor == 3 && osmicro < 2)) &&
 	    getenv("BUFMOD_FIXED") == NULL) {
-		snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
+		pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
 		"WARNING: bufmod is broken in SunOS %s; ignoring snaplen.",
 		    release);
 		ss = 0;
@@ -786,7 +801,7 @@
 	*/
 	if (ioctl(p->fd, I_FLUSH, FLUSHR) != 0) {
 		status = PCAP_ERROR;
-		snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "FLUSHR: %s",
+		pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "FLUSHR: %s",
 		    pcap_strerror(errno));
 		goto bad;
 	}
@@ -841,7 +856,7 @@
 	 */
 	cp = device + strlen(device) - 1;
 	if (*cp < '0' || *cp > '9') {
-		snprintf(ebuf, PCAP_ERRBUF_SIZE, "%s missing unit number",
+		pcap_snprintf(ebuf, PCAP_ERRBUF_SIZE, "%s missing unit number",
 		    device);
 		return (NULL);
 	}
@@ -853,16 +868,16 @@
 	errno = 0;
 	unit = strtol(cp, &eos, 10);
 	if (*eos != '\0') {
-		snprintf(ebuf, PCAP_ERRBUF_SIZE, "%s bad unit number", device);
+		pcap_snprintf(ebuf, PCAP_ERRBUF_SIZE, "%s bad unit number", device);
 		return (NULL);
 	}
 	if (errno == ERANGE || unit > INT_MAX) {
-		snprintf(ebuf, PCAP_ERRBUF_SIZE, "%s unit number too large",
+		pcap_snprintf(ebuf, PCAP_ERRBUF_SIZE, "%s unit number too large",
 		    device);
 		return (NULL);
 	}
 	if (unit < 0) {
-		snprintf(ebuf, PCAP_ERRBUF_SIZE, "%s unit number is negative",
+		pcap_snprintf(ebuf, PCAP_ERRBUF_SIZE, "%s unit number is negative",
 		    device);
 		return (NULL);
 	}
@@ -960,6 +975,56 @@
 	return (0);
 }
 
+/*
+ * Not all interfaces are DLPI interfaces, and thus not all interfaces
+ * can be opened with DLPI (for example, the loopback interface is not
+ * a DLPI interface on Solaris prior to Solaris 11), so try to open
+ * the specified interface; return 0 if we fail with PCAP_ERROR_NO_SUCH_DEVICE
+ * and 1 otherwise.
+ */
+static int
+is_dlpi_interface(const char *name)
+{
+	int fd;
+	int ppa;
+	char errbuf[PCAP_ERRBUF_SIZE];
+
+	fd = open_dlpi_device(name, &ppa, errbuf);
+	if (fd < 0) {
+		/*
+		 * Error - was it PCAP_ERROR_NO_SUCH_DEVICE?
+		 */
+		if (fd == PCAP_ERROR_NO_SUCH_DEVICE) {
+			/*
+			 * Yes, so we can't open this because it's
+			 * not a DLPI interface.
+			 */
+			return (0);
+		}
+		/*
+		 * No, so, in the case where there's a single DLPI
+		 * device for all interfaces of this type ("style
+		 * 2" providers?), we don't know whether it's a DLPI
+		 * interface or not, as we didn't try an attach.
+		 * Say it is a DLPI device, so that the user can at
+		 * least try to open it and report the error (which
+		 * is probably "you don't have permission to open that
+		 * DLPI device"; reporting those interfaces means
+		 * users will ask "why am I getting a permissions error
+		 * when I try to capture" rather than "why am I not
+		 * seeing any interfaces", making the underlying problem
+		 * clearer).
+		 */
+		return (1);
+	}
+
+	/*
+	 * Success.
+	 */
+	close(fd);
+	return (1);
+}
+
 int
 pcap_platform_finddevs(pcap_if_t **alldevsp, char *errbuf)
 {
@@ -972,8 +1037,16 @@
 	} buf;
 	char baname[2+1+1];
 	u_int i;
+#endif
 
 	/*
+	 * Get the list of regular interfaces first.
+	 */
+	if (pcap_findalldevs_interfaces(alldevsp, errbuf, is_dlpi_interface) == -1)
+		return (-1);	/* failure */
+
+#ifdef HAVE_SOLARIS
+	/*
 	 * We may have to do special magic to get ATM devices.
 	 */
 	if ((fd = open("/dev/ba", O_RDWR)) < 0) {
@@ -989,12 +1062,12 @@
 	}
 
 	if (strioctl(fd, A_GET_UNITS, sizeof(buf), (char *)&buf) < 0) {
-		snprintf(errbuf, PCAP_ERRBUF_SIZE, "A_GET_UNITS: %s",
+		pcap_snprintf(errbuf, PCAP_ERRBUF_SIZE, "A_GET_UNITS: %s",
 		    pcap_strerror(errno));
 		return (-1);
 	}
 	for (i = 0; i < buf.nunits; i++) {
-		snprintf(baname, sizeof baname, "ba%u", i);
+		pcap_snprintf(baname, sizeof baname, "ba%u", i);
 		if (pcap_add_if(alldevsp, baname, 0, NULL, errbuf) < 0)
 			return (-1);
 	}
@@ -1015,7 +1088,7 @@
 
 	flags = 0;
 	if (putmsg(fd, &ctl, (struct strbuf *) NULL, flags) < 0) {
-		snprintf(ebuf, PCAP_ERRBUF_SIZE,
+		pcap_snprintf(ebuf, PCAP_ERRBUF_SIZE,
 		    "send_request: putmsg \"%s\": %s",
 		    what, pcap_strerror(errno));
 		return (-1);
@@ -1029,6 +1102,8 @@
 	union	DL_primitives	*dlp;
 	struct	strbuf	ctl;
 	int	flags;
+	char	errmsgbuf[PCAP_ERRBUF_SIZE];
+	char	dlprimbuf[64];
 
 	/*
 	 * Clear out "*uerror", so it's only set for DL_ERROR_ACK/DL_SYSERR,
@@ -1043,7 +1118,7 @@
 
 	flags = 0;
 	if (getmsg(fd, &ctl, (struct strbuf*)NULL, &flags) < 0) {
-		snprintf(ebuf, PCAP_ERRBUF_SIZE, "recv_ack: %s getmsg: %s",
+		pcap_snprintf(ebuf, PCAP_ERRBUF_SIZE, "recv_ack: %s getmsg: %s",
 		    what, pcap_strerror(errno));
 		return (PCAP_ERROR);
 	}
@@ -1066,7 +1141,7 @@
 		case DL_SYSERR:
 			if (uerror != NULL)
 				*uerror = dlp->error_ack.dl_unix_errno;
-			snprintf(ebuf, PCAP_ERRBUF_SIZE,
+			pcap_snprintf(ebuf, PCAP_ERRBUF_SIZE,
 			    "recv_ack: %s: UNIX error - %s",
 			    what, pcap_strerror(dlp->error_ack.dl_unix_errno));
 			if (dlp->error_ack.dl_unix_errno == EPERM ||
@@ -1075,8 +1150,9 @@
 			break;
 
 		default:
-			snprintf(ebuf, PCAP_ERRBUF_SIZE, "recv_ack: %s: %s",
-			    what, dlstrerror(dlp->error_ack.dl_errno));
+			pcap_snprintf(ebuf, PCAP_ERRBUF_SIZE,
+			    "recv_ack: %s: %s", what,
+			    dlstrerror(errmsgbuf, sizeof (errmsgbuf), dlp->error_ack.dl_errno));
 			if (dlp->error_ack.dl_errno == DL_BADPPA)
 				return (PCAP_ERROR_NO_SUCH_DEVICE);
 			else if (dlp->error_ack.dl_errno == DL_ACCESS)
@@ -1086,14 +1162,14 @@
 		return (PCAP_ERROR);
 
 	default:
-		snprintf(ebuf, PCAP_ERRBUF_SIZE,
+		pcap_snprintf(ebuf, PCAP_ERRBUF_SIZE,
 		    "recv_ack: %s: Unexpected primitive ack %s",
-		    what, dlprim(dlp->dl_primitive));
+		    what, dlprim(dlprimbuf, sizeof (dlprimbuf), dlp->dl_primitive));
 		return (PCAP_ERROR);
 	}
 
 	if (ctl.len < size) {
-		snprintf(ebuf, PCAP_ERRBUF_SIZE,
+		pcap_snprintf(ebuf, PCAP_ERRBUF_SIZE,
 		    "recv_ack: %s: Ack too small (%d < %d)",
 		    what, ctl.len, size);
 		return (PCAP_ERROR);
@@ -1102,10 +1178,8 @@
 }
 
 static char *
-dlstrerror(bpf_u_int32 dl_errno)
+dlstrerror(char *errbuf, size_t errbufsize, bpf_u_int32 dl_errno)
 {
-	static char errstring[6+2+8+1];
-
 	switch (dl_errno) {
 
 	case DL_ACCESS:
@@ -1206,16 +1280,14 @@
 		return ("Pending outstanding connect indications");
 
 	default:
-		sprintf(errstring, "Error %02x", dl_errno);
-		return (errstring);
+		pcap_snprintf(errbuf, errbufsize, "Error %02x", dl_errno);
+		return (errbuf);
 	}
 }
 
 static char *
-dlprim(bpf_u_int32 prim)
+dlprim(char *primbuf, size_t primbufsize, bpf_u_int32 prim)
 {
-	static char primbuf[80];
-
 	switch (prim) {
 
 	case DL_INFO_REQ:
@@ -1300,7 +1372,8 @@
 		return ("DL_RESET_CON");
 
 	default:
-		(void) sprintf(primbuf, "unknown primitive 0x%x", prim);
+		pcap_snprintf(primbuf, primbufsize, "unknown primitive 0x%x",
+		    prim);
 		return (primbuf);
 	}
 }
@@ -1412,28 +1485,29 @@
 #endif /* DL_HP_RAWDLS */
 
 #if defined(HAVE_SOLARIS) && defined(HAVE_SYS_BUFMOD_H)
-static char *
-get_release(bpf_u_int32 *majorp, bpf_u_int32 *minorp, bpf_u_int32 *microp)
+static void
+get_release(char *buf, size_t bufsize, bpf_u_int32 *majorp,
+    bpf_u_int32 *minorp, bpf_u_int32 *microp)
 {
 	char *cp;
-	static char buf[32];
 
 	*majorp = 0;
 	*minorp = 0;
 	*microp = 0;
-	if (sysinfo(SI_RELEASE, buf, sizeof(buf)) < 0)
-		return ("?");
+	if (sysinfo(SI_RELEASE, buf, bufsize) < 0) {
+		strlcpy(buf, "?", bufsize);
+		return;
+	}
 	cp = buf;
 	if (!isdigit((unsigned char)*cp))
-		return (buf);
+		return;
 	*majorp = strtol(cp, &cp, 10);
 	if (*cp++ != '.')
-		return (buf);
+		return;
 	*minorp =  strtol(cp, &cp, 10);
 	if (*cp++ != '.')
-		return (buf);
+		return;
 	*microp =  strtol(cp, &cp, 10);
-	return (buf);
 }
 #endif
 
@@ -1521,21 +1595,21 @@
 	 */
 	/* get the head first */
 	if (getmsg(fd, &ctl, (struct strbuf *)NULL, &flags) < 0) {
-		snprintf(ebuf, PCAP_ERRBUF_SIZE,
+		pcap_snprintf(ebuf, PCAP_ERRBUF_SIZE,
 		    "get_dlpi_ppa: hpppa getmsg: %s", pcap_strerror(errno));
 		return (PCAP_ERROR);
 	}
 
 	dlp = (dl_hp_ppa_ack_t *)ctl.buf;
 	if (dlp->dl_primitive != DL_HP_PPA_ACK) {
-		snprintf(ebuf, PCAP_ERRBUF_SIZE,
+		pcap_snprintf(ebuf, PCAP_ERRBUF_SIZE,
 		    "get_dlpi_ppa: hpppa unexpected primitive ack 0x%x",
 		    (bpf_u_int32)dlp->dl_primitive);
 		return (PCAP_ERROR);
 	}
 
 	if (ctl.len < DL_HP_PPA_ACK_SIZE) {
-		snprintf(ebuf, PCAP_ERRBUF_SIZE,
+		pcap_snprintf(ebuf, PCAP_ERRBUF_SIZE,
 		    "get_dlpi_ppa: hpppa ack too small (%d < %lu)",
 		     ctl.len, (unsigned long)DL_HP_PPA_ACK_SIZE);
 		return (PCAP_ERROR);
@@ -1543,7 +1617,7 @@
 
 	/* allocate buffer */
 	if ((ppa_data_buf = (char *)malloc(dlp->dl_length)) == NULL) {
-		snprintf(ebuf, PCAP_ERRBUF_SIZE,
+		pcap_snprintf(ebuf, PCAP_ERRBUF_SIZE,
 		    "get_dlpi_ppa: hpppa malloc: %s", pcap_strerror(errno));
 		return (PCAP_ERROR);
 	}
@@ -1552,13 +1626,13 @@
 	ctl.buf = (char *)ppa_data_buf;
 	/* get the data */
 	if (getmsg(fd, &ctl, (struct strbuf *)NULL, &flags) < 0) {
-		snprintf(ebuf, PCAP_ERRBUF_SIZE,
+		pcap_snprintf(ebuf, PCAP_ERRBUF_SIZE,
 		    "get_dlpi_ppa: hpppa getmsg: %s", pcap_strerror(errno));
 		free(ppa_data_buf);
 		return (PCAP_ERROR);
 	}
 	if (ctl.len < dlp->dl_length) {
-		snprintf(ebuf, PCAP_ERRBUF_SIZE,
+		pcap_snprintf(ebuf, PCAP_ERRBUF_SIZE,
 		    "get_dlpi_ppa: hpppa ack too small (%d < %lu)",
 		    ctl.len, (unsigned long)dlp->dl_length);
 		free(ppa_data_buf);
@@ -1615,9 +1689,9 @@
 		 * device number of a device with the name "/dev/<dev><unit>",
 		 * if such a device exists, as the old code did.
 		 */
-		snprintf(dname, sizeof(dname), "/dev/%s%d", device, unit);
+		pcap_snprintf(dname, sizeof(dname), "/dev/%s%d", device, unit);
 		if (stat(dname, &statbuf) < 0) {
-			snprintf(ebuf, PCAP_ERRBUF_SIZE, "stat: %s: %s",
+			pcap_snprintf(ebuf, PCAP_ERRBUF_SIZE, "stat: %s: %s",
 			    dname, pcap_strerror(errno));
 			return (PCAP_ERROR);
 		}
@@ -1634,12 +1708,12 @@
 		}
 	}
 	if (i == ap->dl_count) {
-		snprintf(ebuf, PCAP_ERRBUF_SIZE,
+		pcap_snprintf(ebuf, PCAP_ERRBUF_SIZE,
 		    "can't find /dev/dlpi PPA for %s%d", device, unit);
 		return (PCAP_ERROR_NO_SUCH_DEVICE);
 	}
 	if (ip->dl_hdw_state == HDW_DEAD) {
-		snprintf(ebuf, PCAP_ERRBUF_SIZE,
+		pcap_snprintf(ebuf, PCAP_ERRBUF_SIZE,
 		    "%s%d: hardware state: DOWN\n", device, unit);
 		free(ppa_data_buf);
 		return (PCAP_ERROR);
@@ -1678,19 +1752,19 @@
 	if (cp != NULL)
 		ifname = cp + 1;
 	if (nlist(path_vmunix, &nl) < 0) {
-		snprintf(ebuf, PCAP_ERRBUF_SIZE, "nlist %s failed",
+		pcap_snprintf(ebuf, PCAP_ERRBUF_SIZE, "nlist %s failed",
 		    path_vmunix);
 		return (-1);
 	}
 	if (nl[NL_IFNET].n_value == 0) {
-		snprintf(ebuf, PCAP_ERRBUF_SIZE,
+		pcap_snprintf(ebuf, PCAP_ERRBUF_SIZE,
 		    "could't find %s kernel symbol",
 		    nl[NL_IFNET].n_name);
 		return (-1);
 	}
 	kd = open("/dev/kmem", O_RDONLY);
 	if (kd < 0) {
-		snprintf(ebuf, PCAP_ERRBUF_SIZE, "kmem open: %s",
+		pcap_snprintf(ebuf, PCAP_ERRBUF_SIZE, "kmem open: %s",
 		    pcap_strerror(errno));
 		return (-1);
 	}
@@ -1712,7 +1786,7 @@
 			return (ifnet.if_index);
 	}
 
-	snprintf(ebuf, PCAP_ERRBUF_SIZE, "Can't find %s", ifname);
+	pcap_snprintf(ebuf, PCAP_ERRBUF_SIZE, "Can't find %s", ifname);
 	return (-1);
 }
 
@@ -1723,17 +1797,17 @@
 	register int cc;
 
 	if (lseek(fd, addr, SEEK_SET) < 0) {
-		snprintf(ebuf, PCAP_ERRBUF_SIZE, "lseek: %s",
+		pcap_snprintf(ebuf, PCAP_ERRBUF_SIZE, "lseek: %s",
 		    pcap_strerror(errno));
 		return (-1);
 	}
 	cc = read(fd, buf, len);
 	if (cc < 0) {
-		snprintf(ebuf, PCAP_ERRBUF_SIZE, "read: %s",
+		pcap_snprintf(ebuf, PCAP_ERRBUF_SIZE, "read: %s",
 		    pcap_strerror(errno));
 		return (-1);
 	} else if (cc != len) {
-		snprintf(ebuf, PCAP_ERRBUF_SIZE, "short read (%d != %d)", cc,
+		pcap_snprintf(ebuf, PCAP_ERRBUF_SIZE, "short read (%d != %d)", cc,
 		    len);
 		return (-1);
 	}
@@ -1742,14 +1816,14 @@
 #endif
 
 pcap_t *
-pcap_create_interface(const char *device, char *ebuf)
+pcap_create_interface(const char *device _U_, char *ebuf)
 {
 	pcap_t *p;
 #ifdef DL_HP_RAWDLS
 	struct pcap_dlpi *pd;
 #endif
 
-	p = pcap_create_common(device, ebuf, sizeof (struct pcap_dlpi));
+	p = pcap_create_common(ebuf, sizeof (struct pcap_dlpi));
 	if (p == NULL)
 		return (NULL);
 
diff --git a/pcap-dos.c b/pcap-dos.c
index 8632cee..ea6b225 100644
--- a/pcap-dos.c
+++ b/pcap-dos.c
@@ -1,6 +1,6 @@
 /*
  *  This file is part of DOS-libpcap
- *  Ported to DOS/DOSX by G. Vanem <gvanem@broadpark.no>
+ *  Ported to DOS/DOSX by G. Vanem <gvanem@yahoo.no>
  *
  *  pcap-dos.c: Interface to PKTDRVR, NDIS2 and 32-bit pmode
  *              network drivers.
@@ -145,15 +145,15 @@
  * Private data for capturing on MS-DOS.
  */
 struct pcap_dos {
-	void (*wait_proc)(void); /*          call proc while waiting */
+	void (*wait_proc)(void); /* call proc while waiting */
 	struct pcap_stat stat;
 };
 
-pcap_t *pcap_create_interface (const char *device, char *ebuf)
+pcap_t *pcap_create_interface (const char *device _U_, char *ebuf)
 {
 	pcap_t *p;
 
-	p = pcap_create_common(device, ebuf, sizeof (struct pcap_dos));
+	p = pcap_create_common(ebuf, sizeof (struct pcap_dos));
 	if (p == NULL)
 		return (NULL);
 
@@ -167,8 +167,6 @@
  */
 static int pcap_activate_dos (pcap_t *pcap)
 {
-  struct pcap_dos *pcapd = pcap->priv;
-
   if (pcap->opt.rfmon) {
     /*
      * No monitor mode on DOS.
@@ -188,23 +186,26 @@
   pcap->stats_op          = pcap_stats_dos;
   pcap->inject_op         = pcap_sendpacket_dos;
   pcap->setfilter_op      = pcap_setfilter_dos;
-  pcap->setdirection_op   = NULL; /* Not implemented.*/
+  pcap->setdirection_op   = NULL;  /* Not implemented.*/
   pcap->fd                = ++ref_count;
 
+  pcap->bufsize = ETH_MAX+100;     /* add some margin */
+  pcap->buffer = calloc (pcap->bufsize, 1);
+
   if (pcap->fd == 1)  /* first time we're called */
   {
-    if (!init_watt32(pcap, pcap->opt.source, pcap->errbuf) ||
-        !first_init(pcap->opt.source, pcap->errbuf, pcap->opt.promisc))
+    if (!init_watt32(pcap, pcap->opt.device, pcap->errbuf) ||
+        !first_init(pcap->opt.device, pcap->errbuf, pcap->opt.promisc))
     {
       return (PCAP_ERROR);
     }
     atexit (close_driver);
   }
-  else if (stricmp(active_dev->name,pcap->opt.source))
+  else if (stricmp(active_dev->name,pcap->opt.device))
   {
-    snprintf (pcap->errbuf, PCAP_ERRBUF_SIZE,
-              "Cannot use different devices simultaneously "
-              "(`%s' vs. `%s')", active_dev->name, pcap->opt.source);
+    pcap_snprintf (pcap->errbuf, PCAP_ERRBUF_SIZE,
+                   "Cannot use different devices simultaneously "
+                   "(`%s' vs. `%s')", active_dev->name, pcap->opt.device);
     return (PCAP_ERROR);
   }
   handle_to_device [pcap->fd-1] = active_dev;
@@ -221,7 +222,6 @@
   struct pcap_dos *pd = p->priv;
   struct pcap_pkthdr pcap;
   struct timeval     now, expiry = { 0,0 };
-  BYTE  *rx_buf;
   int    rx_len = 0;
 
   if (p->opt.timeout > 0)
@@ -253,13 +253,11 @@
     if (dev->peek_rx_buf)
     {
       PCAP_ASSERT (dev->release_rx_buf);
-      rx_len = (*dev->peek_rx_buf) (&rx_buf);
+      rx_len = (*dev->peek_rx_buf) (&p->buffer);
     }
     else
     {
-      BYTE buf [ETH_MAX+100]; /* add some margin */
-      rx_len = (*dev->copy_rx_buf) (buf, p->snapshot);
-      rx_buf = buf;
+      rx_len = (*dev->copy_rx_buf) (p->buffer, p->snapshot);
     }
 
     if (rx_len > 0)  /* got a packet */
@@ -272,7 +270,7 @@
       pcap.len    = rx_len;
 
       if (callback &&
-          (!p->fcode.bf_insns || bpf_filter(p->fcode.bf_insns, rx_buf, pcap.len, pcap.caplen)))
+          (!p->fcode.bf_insns || bpf_filter(p->fcode.bf_insns, p->buffer, pcap.len, pcap.caplen)))
       {
         filter_count++;
 
@@ -280,11 +278,11 @@
          * capture.
          */
         gettimeofday2 (&pcap.ts, NULL);
-        (*callback) (data, &pcap, rx_buf);
+        (*callback) (data, &pcap, p->buffer);
       }
 
       if (dev->release_rx_buf)
-        (*dev->release_rx_buf) (rx_buf);
+        (*dev->release_rx_buf) (p->buffer);
 
       if (pcap_pkt_debug > 0)
       {
@@ -296,6 +294,18 @@
       return (1);
     }
 
+    /* Has "pcap_breakloop()" been called?
+     */
+    if (p->break_loop) {
+      /*
+       * Yes - clear the flag that indicates that it
+       * has, and return -2 to indicate that we were
+       * told to break out of the loop.
+       */
+      p->break_loop = 0;
+      return (-2);
+    }
+
     /* If not to wait for a packet or pcap_cleanup_dos() called from
      * e.g. SIGINT handler, exit loop now.
      */
@@ -311,8 +321,8 @@
     kbhit();    /* a real CPU hog */
 #endif
 
-    if (p->wait_proc)
-      (*p->wait_proc)();     /* call yield func */
+    if (pd->wait_proc)
+      (*pd->wait_proc)();     /* call yield func */
   }
 
   if (rx_len < 0)            /* receive error */
@@ -330,7 +340,6 @@
 static int
 pcap_read_dos (pcap_t *p, int cnt, pcap_handler callback, u_char *data)
 {
-  struct pcap_dos *pd = p->priv;
   int rc, num = 0;
 
   while (num <= cnt || PACKET_COUNT_IS_UNLIMITED(cnt))
@@ -442,7 +451,7 @@
 {
   struct pcap_dos *pd;
 
-  if (p && !exc_occured)
+  if (!exc_occured)
   {
     pd = p->priv;
     if (pcap_stats(p,NULL) < 0)
@@ -495,6 +504,8 @@
 int pcap_lookupnet (const char *device, bpf_u_int32 *localnet,
                     bpf_u_int32 *netmask, char *errbuf)
 {
+  DWORD mask, net;
+
   if (!_watt_is_init)
   {
     strcpy (errbuf, "pcap_open_offline() or pcap_activate() must be "
@@ -502,22 +513,25 @@
     return (-1);
   }
 
-  *netmask  = _w32_sin_mask;
-  *localnet = my_ip_addr & *netmask;
-  if (*localnet == 0)
+  mask  = _w32_sin_mask;
+  net = my_ip_addr & mask;
+  if (net == 0)
   {
     if (IN_CLASSA(*netmask))
-       *localnet = IN_CLASSA_NET;
+       net = IN_CLASSA_NET;
     else if (IN_CLASSB(*netmask))
-       *localnet = IN_CLASSB_NET;
+       net = IN_CLASSB_NET;
     else if (IN_CLASSC(*netmask))
-       *localnet = IN_CLASSC_NET;
+       net = IN_CLASSC_NET;
     else
     {
-      sprintf (errbuf, "inet class for 0x%lx unknown", *netmask);
+      pcap_snprintf (errbuf, PCAP_ERRBUF_SIZE, "inet class for 0x%lx unknown", mask);
       return (-1);
     }
   }
+  *localnet = htonl (net);
+  *netmask = htonl (mask);
+
   ARGSUSED (device);
   return (0);
 }
@@ -525,17 +539,17 @@
 /*
  * Get a list of all interfaces that are present and that we probe okay.
  * Returns -1 on error, 0 otherwise.
- * The list, as returned through "alldevsp", may be null if no interfaces
+ * The list, as returned through "alldevsp", may be NULL if no interfaces
  * were up and could be opened.
  */
-int pcap_findalldevs (pcap_if_t **alldevsp, char *errbuf)
+int pcap_platform_finddevs  (pcap_if_t **alldevsp, char *errbuf)
 {
   struct device     *dev;
-  struct sockaddr_ll sa_ll_1, sa_ll_2;
+  struct sockaddr_in sa_ll_1, sa_ll_2;
   struct sockaddr   *addr, *netmask, *broadaddr, *dstaddr;
   pcap_if_t *devlist = NULL;
   int       ret = 0;
-  size_t    addr_size = sizeof(struct sockaddr_ll);
+  size_t    addr_size = sizeof(*addr);
 
   for (dev = (struct device*)dev_base; dev; dev = dev->next)
   {
@@ -550,14 +564,14 @@
 
     memset (&sa_ll_1, 0, sizeof(sa_ll_1));
     memset (&sa_ll_2, 0, sizeof(sa_ll_2));
-    sa_ll_1.sll_family = AF_PACKET;
-    sa_ll_2.sll_family = AF_PACKET;
+    sa_ll_1.sin_family = AF_INET;
+    sa_ll_2.sin_family = AF_INET;
 
     addr      = (struct sockaddr*) &sa_ll_1;
     netmask   = (struct sockaddr*) &sa_ll_1;
     dstaddr   = (struct sockaddr*) &sa_ll_1;
     broadaddr = (struct sockaddr*) &sa_ll_2;
-    memset (&sa_ll_2.sll_addr, 0xFF, sizeof(sa_ll_2.sll_addr));
+    memset (&sa_ll_2.sin_addr, 0xFF, sizeof(sa_ll_2.sin_addr));
 
     if (pcap_add_if(&devlist, dev->name, dev->flags,
                     dev->long_name, errbuf) < 0)
@@ -565,13 +579,15 @@
       ret = -1;
       break;
     }
-    if (add_addr_to_iflist(&devlist,dev->name, dev->flags, addr, addr_size,
+#if 0   /* Pkt drivers should have no addresses */
+    if (add_addr_to_iflist(&devlist, dev->name, dev->flags, addr, addr_size,
                            netmask, addr_size, broadaddr, addr_size,
                            dstaddr, addr_size, errbuf) < 0)
     {
       ret = -1;
       break;
     }
+#endif
   }
 
   if (devlist && ret < 0)
@@ -605,12 +621,12 @@
  */
 void pcap_set_wait (pcap_t *p, void (*yield)(void), int wait)
 {
-  struct pcap_dos *pd;
   if (p)
   {
-    pd                   = p->priv;
-    pd->wait_proc        = yield;
-    p->opt.timeout        = wait;
+    struct pcap_dos *pd = p->priv;
+
+    pd->wait_proc  = yield;
+    p->opt.timeout = wait;
   }
 }
 
@@ -635,7 +651,7 @@
 
       if (!(*dev->probe)(dev))    /* call the xx_probe() function */
       {
-        sprintf (ebuf, "failed to detect device `%s'", dev_name);
+        pcap_snprintf (ebuf, PCAP_ERRBUF_SIZE, "failed to detect device `%s'", dev_name);
         return (NULL);
       }
       probed_dev = dev;  /* device is probed okay and may be used */
@@ -657,7 +673,7 @@
 
     if (!(*dev->open)(dev))
     {
-      sprintf (ebuf, "failed to activate device `%s'", dev_name);
+      pcap_snprintf (ebuf, PCAP_ERRBUF_SIZE, "failed to activate device `%s'", dev_name);
       if (pktInfo.error && !strncmp(dev->name,"pkt",3))
       {
         strcat (ebuf, ": ");
@@ -679,14 +695,14 @@
    */
   if (!dev)
   {
-    sprintf (ebuf, "device `%s' not supported", dev_name);
+    pcap_snprintf (ebuf, PCAP_ERRBUF_SIZE, "device `%s' not supported", dev_name);
     return (NULL);
   }
 
 not_probed:
   if (!probed_dev)
   {
-    sprintf (ebuf, "device `%s' not probed", dev_name);
+    pcap_snprintf (ebuf, PCAP_ERRBUF_SIZE, "device `%s' not probed", dev_name);
     return (NULL);
   }
   return (dev);
@@ -756,7 +772,7 @@
          fprintf (stderr, "Catching signal %d.\n", sig);
   }
   exc_occured = 1;
-  pcap_cleanup_dos (NULL);
+  close_driver();
 }
 #endif  /* __DJGPP__ */
 
@@ -933,7 +949,7 @@
   if (_watt_is_init)
      sock_exit();
 
-  env = getenv ("PCAP_DEBUG");
+  env = getenv ("PCAP_TRACE");
   if (env && atoi(env) > 0 &&
       pcap_pkt_debug < 0)   /* if not already set */
   {
@@ -973,7 +989,7 @@
   }
   else if (rc && using_pktdrv)
   {
-    sprintf (err_buf, "sock_init() failed, code %d", rc);
+    pcap_snprintf (err_buf, PCAP_ERRBUF_SIZE, "sock_init() failed, code %d", rc);
     return (0);
   }
 
@@ -1053,9 +1069,9 @@
  * pcap_config_hook() is an extension to application's config
  * handling. Uses Watt-32's config-table function.
  */
-int pcap_config_hook (const char *name, const char *value)
+int pcap_config_hook (const char *keyword, const char *value)
 {
-  return parse_config_table (debug_tab, NULL, name, value);
+  return parse_config_table (debug_tab, NULL, keyword, value);
 }
 
 /*
diff --git a/pcap-filter.manmisc b/pcap-filter.manmisc
new file mode 100644
index 0000000..b9bf387
--- /dev/null
+++ b/pcap-filter.manmisc
@@ -0,0 +1,1032 @@
+.\" Copyright (c) 1987, 1988, 1989, 1990, 1991, 1992, 1994, 1995, 1996, 1997
+.\"	The Regents of the University of California.  All rights reserved.
+.\" All rights reserved.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that: (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-FILTER 7 "3 August 2015"
+.SH NAME
+pcap-filter \- packet filter syntax
+.br
+.ad
+.SH DESCRIPTION
+.LP
+.B pcap_compile()
+is used to compile a string into a filter program.
+The resulting filter program can then be applied to
+some stream of packets to determine which packets will be supplied to
+.BR pcap_loop() ,
+.BR pcap_dispatch() ,
+.BR pcap_next() ,
+or
+.BR pcap_next_ex() .
+.LP
+The \fIfilter expression\fP consists of one or more
+.IR primitives .
+Primitives usually consist of an
+.I id
+(name or number) preceded by one or more qualifiers.
+There are three
+different kinds of qualifier:
+.IP \fItype\fP
+.I type
+qualifiers say what kind of thing the id name or number refers to.
+Possible types are
+.BR host ,
+.B net ,
+.B port
+and
+.BR portrange .
+E.g., `host foo', `net 128.3', `port 20', `portrange 6000-6008'.
+If there is no type
+qualifier,
+.B host
+is assumed.
+.IP \fIdir\fP
+.I dir
+qualifiers specify a particular transfer direction to and/or from
+.IR id .
+Possible directions are
+.BR src ,
+.BR dst ,
+.BR "src or dst" ,
+.BR "src and dst" ,
+.BR ra ,
+.BR ta ,
+.BR addr1 ,
+.BR addr2 ,
+.BR addr3 ,
+and
+.BR addr4 .
+E.g., `src foo', `dst net 128.3', `src or dst port ftp-data'.
+If
+there is no dir qualifier,
+.B "src or dst"
+is assumed.
+The
+.BR ra ,
+.BR ta ,
+.BR addr1 ,
+.BR addr2 ,
+.BR addr3 ,
+and
+.B addr4
+qualifiers are only valid for IEEE 802.11 Wireless LAN link layers.
+For some link layers, such as SLIP and the ``cooked'' Linux capture mode
+used for the ``any'' device and for some other device types, the
+.B inbound
+and
+.B outbound
+qualifiers can be used to specify a desired direction.
+.IP \fIproto\fP
+.I proto
+qualifiers restrict the match to a particular protocol.
+Possible
+protos are:
+.BR ether ,
+.BR fddi ,
+.BR tr ,
+.BR wlan ,
+.BR ip ,
+.BR ip6 ,
+.BR arp ,
+.BR rarp ,
+.BR decnet ,
+.B tcp
+and
+.BR udp .
+E.g., `ether src foo', `arp net 128.3', `tcp port 21', `udp portrange
+7000-7009', `wlan addr2 0:2:3:4:5:6'.
+If there is
+no proto qualifier, all protocols consistent with the type are
+assumed.
+E.g., `src foo' means `(ip or arp or rarp) src foo'
+(except the latter is not legal syntax), `net bar' means `(ip or
+arp or rarp) net bar' and `port 53' means `(tcp or udp) port 53'.
+.LP
+[`fddi' is actually an alias for `ether'; the parser treats them
+identically as meaning ``the data link level used on the specified
+network interface.''  FDDI headers contain Ethernet-like source
+and destination addresses, and often contain Ethernet-like packet
+types, so you can filter on these FDDI fields just as with the
+analogous Ethernet fields.
+FDDI headers also contain other fields,
+but you cannot name them explicitly in a filter expression.
+.LP
+Similarly, `tr' and `wlan' are aliases for `ether'; the previous
+paragraph's statements about FDDI headers also apply to Token Ring
+and 802.11 wireless LAN headers.  For 802.11 headers, the destination
+address is the DA field and the source address is the SA field; the
+BSSID, RA, and TA fields aren't tested.]
+.LP
+In addition to the above, there are some special `primitive' keywords
+that don't follow the pattern:
+.BR gateway ,
+.BR broadcast ,
+.BR less ,
+.B greater
+and arithmetic expressions.
+All of these are described below.
+.LP
+More complex filter expressions are built up by using the words
+.BR and ,
+.B or
+and
+.B not
+to combine primitives.
+E.g., `host foo and not port ftp and not port ftp-data'.
+To save typing, identical qualifier lists can be omitted.
+E.g.,
+`tcp dst port ftp or ftp-data or domain' is exactly the same as
+`tcp dst port ftp or tcp dst port ftp-data or tcp dst port domain'.
+.LP
+Allowable primitives are:
+.IP "\fBdst host \fIhost\fR"
+True if the IPv4/v6 destination field of the packet is \fIhost\fP,
+which may be either an address or a name.
+.IP "\fBsrc host \fIhost\fR"
+True if the IPv4/v6 source field of the packet is \fIhost\fP.
+.IP "\fBhost \fIhost\fP"
+True if either the IPv4/v6 source or destination of the packet is \fIhost\fP.
+.IP
+Any of the above host expressions can be prepended with the keywords,
+\fBip\fP, \fBarp\fP, \fBrarp\fP, or \fBip6\fP as in:
+.in +.5i
+.nf
+\fBip host \fIhost\fR
+.fi
+.in -.5i
+which is equivalent to:
+.in +.5i
+.nf
+\fBether proto \fI\\ip\fB and host \fIhost\fR
+.fi
+.in -.5i
+If \fIhost\fR is a name with multiple IP addresses, each address will
+be checked for a match.
+.IP "\fBether dst \fIehost\fP"
+True if the Ethernet destination address is \fIehost\fP.
+\fIEhost\fP
+may be either a name from /etc/ethers or a number (see
+.IR ethers (3N)
+for numeric format).
+.IP "\fBether src \fIehost\fP"
+True if the Ethernet source address is \fIehost\fP.
+.IP "\fBether host \fIehost\fP"
+True if either the Ethernet source or destination address is \fIehost\fP.
+.IP "\fBgateway\fP \fIhost\fP"
+True if the packet used \fIhost\fP as a gateway.
+I.e., the Ethernet
+source or destination address was \fIhost\fP but neither the IP source
+nor the IP destination was \fIhost\fP.
+\fIHost\fP must be a name and
+must be found both by the machine's host-name-to-IP-address resolution
+mechanisms (host name file, DNS, NIS, etc.) and by the machine's
+host-name-to-Ethernet-address resolution mechanism (/etc/ethers, etc.).
+(An equivalent expression is
+.in +.5i
+.nf
+\fBether host \fIehost \fBand not host \fIhost\fR
+.fi
+.in -.5i
+which can be used with either names or numbers for \fIhost / ehost\fP.)
+This syntax does not work in IPv6-enabled configuration at this moment.
+.IP "\fBdst net \fInet\fR"
+True if the IPv4/v6 destination address of the packet has a network
+number of \fInet\fP.
+\fINet\fP may be either a name from the networks database
+(/etc/networks, etc.) or a network number.
+An IPv4 network number can be written as a dotted quad (e.g., 192.168.1.0),
+dotted triple (e.g., 192.168.1), dotted pair (e.g, 172.16), or single
+number (e.g., 10); the netmask is 255.255.255.255 for a dotted quad
+(which means that it's really a host match), 255.255.255.0 for a dotted
+triple, 255.255.0.0 for a dotted pair, or 255.0.0.0 for a single number.
+An IPv6 network number must be written out fully; the netmask is
+ff:ff:ff:ff:ff:ff:ff:ff, so IPv6 "network" matches are really always
+host matches, and a network match requires a netmask length.
+.IP "\fBsrc net \fInet\fR"
+True if the IPv4/v6 source address of the packet has a network
+number of \fInet\fP.
+.IP "\fBnet \fInet\fR"
+True if either the IPv4/v6 source or destination address of the packet has a network
+number of \fInet\fP.
+.IP "\fBnet \fInet\fR \fBmask \fInetmask\fR"
+True if the IPv4 address matches \fInet\fR with the specific \fInetmask\fR.
+May be qualified with \fBsrc\fR or \fBdst\fR.
+Note that this syntax is not valid for IPv6 \fInet\fR.
+.IP "\fBnet \fInet\fR/\fIlen\fR"
+True if the IPv4/v6 address matches \fInet\fR with a netmask \fIlen\fR
+bits wide.
+May be qualified with \fBsrc\fR or \fBdst\fR.
+.IP "\fBdst port \fIport\fR"
+True if the packet is ip/tcp, ip/udp, ip6/tcp or ip6/udp and has a
+destination port value of \fIport\fP.
+The \fIport\fP can be a number or a name used in /etc/services (see
+.IR tcp (4P)
+and
+.IR udp (4P)).
+If a name is used, both the port
+number and protocol are checked.
+If a number or ambiguous name is used,
+only the port number is checked (e.g., \fBdst port 513\fR will print both
+tcp/login traffic and udp/who traffic, and \fBport domain\fR will print
+both tcp/domain and udp/domain traffic).
+.IP "\fBsrc port \fIport\fR"
+True if the packet has a source port value of \fIport\fP.
+.IP "\fBport \fIport\fR"
+True if either the source or destination port of the packet is \fIport\fP.
+.IP "\fBdst portrange \fIport1\fB-\fIport2\fR"
+True if the packet is ip/tcp, ip/udp, ip6/tcp or ip6/udp and has a
+destination port value between \fIport1\fP and \fIport2\fP.
+.I port1
+and
+.I port2
+are interpreted in the same fashion as the
+.I port
+parameter for
+.BR port .
+.IP "\fBsrc portrange \fIport1\fB-\fIport2\fR"
+True if the packet has a source port value between \fIport1\fP and
+\fIport2\fP.
+.IP "\fBportrange \fIport1\fB-\fIport2\fR"
+True if either the source or destination port of the packet is between
+\fIport1\fP and \fIport2\fP.
+.IP
+Any of the above port or port range expressions can be prepended with
+the keywords, \fBtcp\fP or \fBudp\fP, as in:
+.in +.5i
+.nf
+\fBtcp src port \fIport\fR
+.fi
+.in -.5i
+which matches only tcp packets whose source port is \fIport\fP.
+.IP "\fBless \fIlength\fR"
+True if the packet has a length less than or equal to \fIlength\fP.
+This is equivalent to:
+.in +.5i
+.nf
+\fBlen <= \fIlength\fP.
+.fi
+.in -.5i
+.IP "\fBgreater \fIlength\fR"
+True if the packet has a length greater than or equal to \fIlength\fP.
+This is equivalent to:
+.in +.5i
+.nf
+\fBlen >= \fIlength\fP.
+.fi
+.in -.5i
+.IP "\fBip proto \fIprotocol\fR"
+True if the packet is an IPv4 packet (see
+.IR ip (4P))
+of protocol type \fIprotocol\fP.
+\fIProtocol\fP can be a number or one of the names
+\fBicmp\fP, \fBicmp6\fP, \fBigmp\fP, \fBigrp\fP, \fBpim\fP, \fBah\fP,
+\fBesp\fP, \fBvrrp\fP, \fBudp\fP, or \fBtcp\fP.
+Note that the identifiers \fBtcp\fP, \fBudp\fP, and \fBicmp\fP are also
+keywords and must be escaped via backslash (\\).
+Note that this primitive does not chase the protocol header chain.
+.IP "\fBip6 proto \fIprotocol\fR"
+True if the packet is an IPv6 packet of protocol type \fIprotocol\fP.
+Note that this primitive does not chase the protocol header chain.
+.IP "\fBproto \fIprotocol\fR"
+True if the packet is an IPv4 or IPv6 packet of protocol type
+\fIprotocol\fP.  Note that this primitive does not chase the protocol
+header chain.
+.IP  "\fBtcp\fR, \fBudp\fR, \fBicmp\fR"
+Abbreviations for:
+.in +.5i
+.nf
+\fBproto \fIp\fR\fB
+.fi
+.in -.5i
+where \fIp\fR is one of the above protocols.
+.IP "\fBip6 protochain \fIprotocol\fR"
+True if the packet is IPv6 packet,
+and contains protocol header with type \fIprotocol\fR
+in its protocol header chain.
+For example,
+.in +.5i
+.nf
+\fBip6 protochain 6\fR
+.fi
+.in -.5i
+matches any IPv6 packet with TCP protocol header in the protocol header chain.
+The packet may contain, for example,
+authentication header, routing header, or hop-by-hop option header,
+between IPv6 header and TCP header.
+The BPF code emitted by this primitive is complex and
+cannot be optimized by the BPF optimizer code, and is not supported by
+filter engines in the kernel, so this can be somewhat slow, and may
+cause more packets to be dropped.
+.IP "\fBip protochain \fIprotocol\fR"
+Equivalent to \fBip6 protochain \fIprotocol\fR, but this is for IPv4.
+.IP "\fBprotochain \fIprotocol\fR"
+True if the packet is an IPv4 or IPv6 packet of protocol type
+\fIprotocol\fP.  Note that this primitive chases the protocol
+header chain.
+.IP "\fBether broadcast\fR"
+True if the packet is an Ethernet broadcast packet.
+The \fIether\fP
+keyword is optional.
+.IP "\fBip broadcast\fR"
+True if the packet is an IPv4 broadcast packet.
+It checks for both the all-zeroes and all-ones broadcast conventions,
+and looks up the subnet mask on the interface on which the capture is
+being done.
+.IP
+If the subnet mask of the interface on which the capture is being done
+is not available, either because the interface on which capture is being
+done has no netmask or because the capture is being done on the Linux
+"any" interface, which can capture on more than one interface, this
+check will not work correctly.
+.IP "\fBether multicast\fR"
+True if the packet is an Ethernet multicast packet.
+The \fBether\fP
+keyword is optional.
+This is shorthand for `\fBether[0] & 1 != 0\fP'.
+.IP "\fBip multicast\fR"
+True if the packet is an IPv4 multicast packet.
+.IP "\fBip6 multicast\fR"
+True if the packet is an IPv6 multicast packet.
+.IP  "\fBether proto \fIprotocol\fR"
+True if the packet is of ether type \fIprotocol\fR.
+\fIProtocol\fP can be a number or one of the names
+\fBip\fP, \fBip6\fP, \fBarp\fP, \fBrarp\fP, \fBatalk\fP, \fBaarp\fP,
+\fBdecnet\fP, \fBsca\fP, \fBlat\fP, \fBmopdl\fP, \fBmoprc\fP,
+\fBiso\fP, \fBstp\fP, \fBipx\fP, or \fBnetbeui\fP.
+Note these identifiers are also keywords
+and must be escaped via backslash (\\).
+.IP
+[In the case of FDDI (e.g., `\fBfddi proto arp\fR'), Token Ring
+(e.g., `\fBtr proto arp\fR'), and IEEE 802.11 wireless LANS (e.g.,
+`\fBwlan proto arp\fR'), for most of those protocols, the
+protocol identification comes from the 802.2 Logical Link Control (LLC)
+header, which is usually layered on top of the FDDI, Token Ring, or
+802.11 header.
+.IP
+When filtering for most protocol identifiers on FDDI, Token Ring, or
+802.11, the filter checks only the protocol ID field of an LLC header
+in so-called SNAP format with an Organizational Unit Identifier (OUI) of
+0x000000, for encapsulated Ethernet; it doesn't check whether the packet
+is in SNAP format with an OUI of 0x000000.
+The exceptions are:
+.RS
+.TP
+\fBiso\fP
+the filter checks the DSAP (Destination Service Access Point) and
+SSAP (Source Service Access Point) fields of the LLC header;
+.TP
+\fBstp\fP and \fBnetbeui\fP
+the filter checks the DSAP of the LLC header;
+.TP
+\fBatalk\fP
+the filter checks for a SNAP-format packet with an OUI of 0x080007
+and the AppleTalk etype.
+.RE
+.IP
+In the case of Ethernet, the filter checks the Ethernet type field
+for most of those protocols.  The exceptions are:
+.RS
+.TP
+\fBiso\fP, \fBstp\fP, and \fBnetbeui\fP
+the filter checks for an 802.3 frame and then checks the LLC header as
+it does for FDDI, Token Ring, and 802.11;
+.TP
+\fBatalk\fP
+the filter checks both for the AppleTalk etype in an Ethernet frame and
+for a SNAP-format packet as it does for FDDI, Token Ring, and 802.11;
+.TP
+\fBaarp\fP
+the filter checks for the AppleTalk ARP etype in either an Ethernet
+frame or an 802.2 SNAP frame with an OUI of 0x000000;
+.TP
+\fBipx\fP
+the filter checks for the IPX etype in an Ethernet frame, the IPX
+DSAP in the LLC header, the 802.3-with-no-LLC-header encapsulation of
+IPX, and the IPX etype in a SNAP frame.
+.RE
+.IP "\fBip\fR, \fBip6\fR, \fBarp\fR, \fBrarp\fR, \fBatalk\fR, \fBaarp\fR, \fBdecnet\fR, \fBiso\fR, \fBstp\fR, \fBipx\fR, \fBnetbeui\fP"
+Abbreviations for:
+.in +.5i
+.nf
+\fBether proto \fIp\fR
+.fi
+.in -.5i
+where \fIp\fR is one of the above protocols.
+.IP "\fBlat\fR, \fBmoprc\fR, \fBmopdl\fR"
+Abbreviations for:
+.in +.5i
+.nf
+\fBether proto \fIp\fR
+.fi
+.in -.5i
+where \fIp\fR is one of the above protocols.
+Note that not all applications using
+.BR pcap (3PCAP)
+currently know how to parse these protocols.
+.IP "\fBdecnet src \fIhost\fR"
+True if the DECNET source address is
+.IR host ,
+which may be an address of the form ``10.123'', or a DECNET host
+name.
+[DECNET host name support is only available on ULTRIX systems
+that are configured to run DECNET.]
+.IP "\fBdecnet dst \fIhost\fR"
+True if the DECNET destination address is
+.IR host .
+.IP "\fBdecnet host \fIhost\fR"
+True if either the DECNET source or destination address is
+.IR host .
+.IP \fBllc\fP
+True if the packet has an 802.2 LLC header.  This includes:
+.IP
+Ethernet packets with a length field rather than a type field that
+aren't raw NetWare-over-802.3 packets;
+.IP
+IEEE 802.11 data packets;
+.IP
+Token Ring packets (no check is done for LLC frames);
+.IP
+FDDI packets (no check is done for LLC frames);
+.IP
+LLC-encapsulated ATM packets, for SunATM on Solaris.
+.IP
+
+.IP "\fBllc\fP \Fitype\fR"
+True if the packet has an 802.2 LLC header and has the specified
+.IR type .
+.I type
+can be one of:
+.RS
+.TP
+\fBi\fR
+Information (I) PDUs
+.TP
+\fBs\fR
+Supervisory (S) PDUs
+.TP
+\fBu\fR
+Unnumbered (U) PDUs
+.TP
+\fBrr\fR
+Receiver Ready (RR) S PDUs
+.TP
+\fBrnr\fR
+Receiver Not Ready (RNR) S PDUs
+.TP
+\fBrej\fR
+Reject (REJ) S PDUs
+.TP
+\fBui\fR
+Unnumbered Information (UI) U PDUs
+.TP
+\fBua\fR
+Unnumbered Acknowledgment (UA) U PDUs
+.TP
+\fBdisc\fR
+Disconnect (DISC) U PDUs
+.TP
+\fBsabme\fR
+Set Asynchronous Balanced Mode Extended (SABME) U PDUs
+.TP
+\fBtest\fR
+Test (TEST) U PDUs
+.TP
+\fBxid\fR
+Exchange Identification (XID) U PDUs
+.TP
+\fBfrmr\fR
+Frame Reject (FRMR) U PDUs
+.RE
+.IP "\fBifname \fIinterface\fR"
+True if the packet was logged as coming from the specified interface (applies
+only to packets logged by OpenBSD's or FreeBSD's
+.BR pf (4)).
+.IP "\fBon \fIinterface\fR"
+Synonymous with the
+.B ifname
+modifier.
+.IP "\fBrnr \fInum\fR"
+True if the packet was logged as matching the specified PF rule number
+(applies only to packets logged by OpenBSD's or FreeBSD's
+.BR pf (4)).
+.IP "\fBrulenum \fInum\fR"
+Synonymous with the
+.B rnr
+modifier.
+.IP "\fBreason \fIcode\fR"
+True if the packet was logged with the specified PF reason code.  The known
+codes are:
+.BR match ,
+.BR bad-offset ,
+.BR fragment ,
+.BR short ,
+.BR normalize ,
+and
+.B memory
+(applies only to packets logged by OpenBSD's or FreeBSD's
+.BR pf (4)).
+.IP "\fBrset \fIname\fR"
+True if the packet was logged as matching the specified PF ruleset
+name of an anchored ruleset (applies only to packets logged by OpenBSD's
+or FreeBSD's
+.BR pf (4)).
+.IP "\fBruleset \fIname\fR"
+Synonymous with the
+.B rset
+modifier.
+.IP "\fBsrnr \fInum\fR"
+True if the packet was logged as matching the specified PF rule number
+of an anchored ruleset (applies only to packets logged by OpenBSD's or
+FreeBSD's
+.BR pf (4)).
+.IP "\fBsubrulenum \fInum\fR"
+Synonymous with the
+.B srnr
+modifier.
+.IP "\fBaction \fIact\fR"
+True if PF took the specified action when the packet was logged.  Known actions
+are:
+.B pass
+and
+.B block
+and, with later versions of
+.BR pf (4)),
+.BR nat ,
+.BR rdr ,
+.B binat
+and
+.B scrub
+(applies only to packets logged by OpenBSD's or FreeBSD's
+.BR pf (4)).
+.IP "\fBwlan ra \fIehost\fR"
+True if the IEEE 802.11 RA is
+.IR ehost .
+The RA field is used in all frames except for management frames.
+.IP "\fBwlan ta \fIehost\fR"
+True if the IEEE 802.11 TA is
+.IR ehost .
+The TA field is used in all frames except for management frames and
+CTS (Clear To Send) and ACK (Acknowledgment) control frames.
+.IP "\fBwlan addr1 \fIehost\fR"
+True if the first IEEE 802.11 address is
+.IR ehost .
+.IP "\fBwlan addr2 \fIehost\fR"
+True if the second IEEE 802.11 address, if present, is
+.IR ehost .
+The second address field is used in all frames except for CTS (Clear To
+Send) and ACK (Acknowledgment) control frames.
+.IP "\fBwlan addr3 \fIehost\fR"
+True if the third IEEE 802.11 address, if present, is
+.IR ehost .
+The third address field is used in management and data frames, but not
+in control frames.
+.IP "\fBwlan addr4 \fIehost\fR"
+True if the fourth IEEE 802.11 address, if present, is
+.IR ehost .
+The fourth address field is only used for
+WDS (Wireless Distribution System) frames.
+.IP "\fBtype \fIwlan_type\fR"
+True if the IEEE 802.11 frame type matches the specified \fIwlan_type\fR.
+Valid \fIwlan_type\fRs are:
+\fBmgt\fP,
+\fBctl\fP
+and \fBdata\fP.
+.IP "\fBtype \fIwlan_type \fBsubtype \fIwlan_subtype\fR"
+True if the IEEE 802.11 frame type matches the specified \fIwlan_type\fR
+and frame subtype matches the specified \fIwlan_subtype\fR.
+.IP
+If the specified \fIwlan_type\fR is \fBmgt\fP,
+then valid \fIwlan_subtype\fRs are:
+\fBassoc-req\fP,
+\fBassoc-resp\fP,
+\fBreassoc-req\fP,
+\fBreassoc-resp\fP,
+\fBprobe-req\fP,
+\fBprobe-resp\fP,
+\fBbeacon\fP,
+\fBatim\fP,
+\fBdisassoc\fP,
+\fBauth\fP and
+\fBdeauth\fP.
+.IP
+If the specified \fIwlan_type\fR is \fBctl\fP,
+then valid \fIwlan_subtype\fRs are:
+\fBps-poll\fP,
+\fBrts\fP,
+\fBcts\fP,
+\fBack\fP,
+\fBcf-end\fP and
+\fBcf-end-ack\fP.
+.IP
+If the specified \fIwlan_type\fR is \fBdata\fP,
+then valid \fIwlan_subtype\fRs are:
+\fBdata\fP,
+\fBdata-cf-ack\fP,
+\fBdata-cf-poll\fP,
+\fBdata-cf-ack-poll\fP,
+\fBnull\fP,
+\fBcf-ack\fP,
+\fBcf-poll\fP,
+\fBcf-ack-poll\fP,
+\fBqos-data\fP,
+\fBqos-data-cf-ack\fP,
+\fBqos-data-cf-poll\fP,
+\fBqos-data-cf-ack-poll\fP,
+\fBqos\fP,
+\fBqos-cf-poll\fP and
+\fBqos-cf-ack-poll\fP.
+.IP "\fBsubtype \fIwlan_subtype\fR"
+True if the IEEE 802.11 frame subtype matches the specified \fIwlan_subtype\fR
+and frame has the type to which the specified \fIwlan_subtype\fR belongs.
+.IP "\fBdir \fIdir\fR"
+True if the IEEE 802.11 frame direction matches the specified
+.IR dir .
+Valid directions are:
+.BR nods ,
+.BR tods ,
+.BR fromds ,
+.BR dstods ,
+or a numeric value.
+.IP "\fBvlan \fI[vlan_id]\fR"
+True if the packet is an IEEE 802.1Q VLAN packet.
+If \fI[vlan_id]\fR is specified, only true if the packet has the specified
+\fIvlan_id\fR.
+Note that the first \fBvlan\fR keyword encountered in \fIexpression\fR
+changes the decoding offsets for the remainder of \fIexpression\fR on
+the assumption that the packet is a VLAN packet.  The \fBvlan
+\fI[vlan_id]\fR expression may be used more than once, to filter on VLAN
+hierarchies.  Each use of that expression increments the filter offsets
+by 4.
+.IP
+For example:
+.in +.5i
+.nf
+\fBvlan 100 && vlan 200\fR
+.fi
+.in -.5i
+filters on VLAN 200 encapsulated within VLAN 100, and
+.in +.5i
+.nf
+\fBvlan && vlan 300 && ip\fR
+.fi
+.in -.5i
+filters IPv4 protocols encapsulated in VLAN 300 encapsulated within any
+higher order VLAN.
+.IP "\fBmpls \fI[label_num]\fR"
+True if the packet is an MPLS packet.
+If \fI[label_num]\fR is specified, only true is the packet has the specified
+\fIlabel_num\fR.
+Note that the first \fBmpls\fR keyword encountered in \fIexpression\fR
+changes the decoding offsets for the remainder of \fIexpression\fR on
+the assumption that the packet is a MPLS-encapsulated IP packet.  The
+\fBmpls \fI[label_num]\fR expression may be used more than once, to
+filter on MPLS hierarchies.  Each use of that expression increments the
+filter offsets by 4.
+.IP
+For example:
+.in +.5i
+.nf
+\fBmpls 100000 && mpls 1024\fR
+.fi
+.in -.5i
+filters packets with an outer label of 100000 and an inner label of
+1024, and
+.in +.5i
+.nf
+\fBmpls && mpls 1024 && host 192.9.200.1\fR
+.fi
+.in -.5i
+filters packets to or from 192.9.200.1 with an inner label of 1024 and
+any outer label.
+.IP \fBpppoed\fP
+True if the packet is a PPP-over-Ethernet Discovery packet (Ethernet
+type 0x8863).
+.IP "\fBpppoes \fI[session_id]\fR"
+True if the packet is a PPP-over-Ethernet Session packet (Ethernet
+type 0x8864).
+If \fI[session_id]\fR is specified, only true if the packet has the specified
+\fIsession_id\fR.
+Note that the first \fBpppoes\fR keyword encountered in \fIexpression\fR
+changes the decoding offsets for the remainder of \fIexpression\fR on
+the assumption that the packet is a PPPoE session packet.
+.IP
+For example:
+.in +.5i
+.nf
+\fBpppoes 0x27 && ip\fR
+.fi
+.in -.5i
+filters IPv4 protocols encapsulated in PPPoE session id 0x27.
+.IP "\fBgeneve \fI[vni]\fR"
+True if the packet is a Geneve packet (UDP port 6081). If \fI[vni]\fR
+is specified, only true if the packet has the specified \fIvni\fR.
+Note that when the \fBgeneve\fR keyword is encountered in
+\fIexpression\fR, it changes the decoding offsets for the remainder of
+\fIexpression\fR on the assumption that the packet is a Geneve packet.
+.IP
+For example:
+.in +.5i
+.nf
+\fBgeneve 0xb && ip\fR
+.fi
+.in -.5i
+filters IPv4 protocols encapsulated in Geneve with VNI 0xb. This will
+match both IP directly encapsulated in Geneve as well as IP contained
+inside an Ethernet frame.
+.IP "\fBiso proto \fIprotocol\fR"
+True if the packet is an OSI packet of protocol type \fIprotocol\fP.
+\fIProtocol\fP can be a number or one of the names
+\fBclnp\fP, \fBesis\fP, or \fBisis\fP.
+.IP "\fBclnp\fR, \fBesis\fR, \fBisis\fR"
+Abbreviations for:
+.in +.5i
+.nf
+\fBiso proto \fIp\fR
+.fi
+.in -.5i
+where \fIp\fR is one of the above protocols.
+.IP "\fBl1\fR, \fBl2\fR, \fBiih\fR, \fBlsp\fR, \fBsnp\fR, \fBcsnp\fR, \fBpsnp\fR"
+Abbreviations for IS-IS PDU types.
+.IP "\fBvpi\fP \fIn\fR"
+True if the packet is an ATM packet, for SunATM on Solaris, with a
+virtual path identifier of
+.IR n .
+.IP "\fBvci\fP \fIn\fR"
+True if the packet is an ATM packet, for SunATM on Solaris, with a
+virtual channel identifier of
+.IR n .
+.IP \fBlane\fP
+True if the packet is an ATM packet, for SunATM on Solaris, and is
+an ATM LANE packet.
+Note that the first \fBlane\fR keyword encountered in \fIexpression\fR
+changes the tests done in the remainder of \fIexpression\fR
+on the assumption that the packet is either a LANE emulated Ethernet
+packet or a LANE LE Control packet.  If \fBlane\fR isn't specified, the
+tests are done under the assumption that the packet is an
+LLC-encapsulated packet.
+.IP \fBoamf4s\fP
+True if the packet is an ATM packet, for SunATM on Solaris, and is
+a segment OAM F4 flow cell (VPI=0 & VCI=3).
+.IP \fBoamf4e\fP
+True if the packet is an ATM packet, for SunATM on Solaris, and is
+an end-to-end OAM F4 flow cell (VPI=0 & VCI=4).
+.IP \fBoamf4\fP
+True if the packet is an ATM packet, for SunATM on Solaris, and is
+a segment or end-to-end OAM F4 flow cell (VPI=0 & (VCI=3 | VCI=4)).
+.IP \fBoam\fP
+True if the packet is an ATM packet, for SunATM on Solaris, and is
+a segment or end-to-end OAM F4 flow cell (VPI=0 & (VCI=3 | VCI=4)).
+.IP \fBmetac\fP
+True if the packet is an ATM packet, for SunATM on Solaris, and is
+on a meta signaling circuit (VPI=0 & VCI=1).
+.IP \fBbcc\fP
+True if the packet is an ATM packet, for SunATM on Solaris, and is
+on a broadcast signaling circuit (VPI=0 & VCI=2).
+.IP \fBsc\fP
+True if the packet is an ATM packet, for SunATM on Solaris, and is
+on a signaling circuit (VPI=0 & VCI=5).
+.IP \fBilmic\fP
+True if the packet is an ATM packet, for SunATM on Solaris, and is
+on an ILMI circuit (VPI=0 & VCI=16).
+.IP \fBconnectmsg\fP
+True if the packet is an ATM packet, for SunATM on Solaris, and is
+on a signaling circuit and is a Q.2931 Setup, Call Proceeding, Connect,
+Connect Ack, Release, or Release Done message.
+.IP \fBmetaconnect\fP
+True if the packet is an ATM packet, for SunATM on Solaris, and is
+on a meta signaling circuit and is a Q.2931 Setup, Call Proceeding, Connect,
+Release, or Release Done message.
+.IP  "\fIexpr relop expr\fR"
+True if the relation holds, where \fIrelop\fR is one of >, <, >=, <=, =,
+!=, and \fIexpr\fR is an arithmetic expression composed of integer
+constants (expressed in standard C syntax), the normal binary operators
+[+, -, *, /, %, &, |, ^, <<, >>], a length operator, and special packet data
+accessors.  Note that all comparisons are unsigned, so that, for example,
+0x80000000 and 0xffffffff are > 0.
+.IP
+The % and ^ operators are currently only supported for filtering in the
+kernel on Linux with 3.7 and later kernels; on all other systems, if
+those operators are used, filtering will be done in user mode, which
+will increase the overhead of capturing packets and may cause more
+packets to be dropped.
+.IP
+To access data inside the packet, use the following syntax:
+.in +.5i
+.nf
+\fIproto\fB [ \fIexpr\fB : \fIsize\fB ]\fR
+.fi
+.in -.5i
+\fIProto\fR is one of \fBether, fddi, tr, wlan, ppp, slip, link,
+ip, arp, rarp, tcp, udp, icmp, ip6\fR or \fBradio\fR, and
+indicates the protocol layer for the index operation.
+(\fBether, fddi, wlan, tr, ppp, slip\fR and \fBlink\fR all refer to the
+link layer. \fBradio\fR refers to the "radio header" added to some
+802.11 captures.)
+Note that \fItcp, udp\fR and other upper-layer protocol types only
+apply to IPv4, not IPv6 (this will be fixed in the future).
+The byte offset, relative to the indicated protocol layer, is
+given by \fIexpr\fR.
+\fISize\fR is optional and indicates the number of bytes in the
+field of interest; it can be either one, two, or four, and defaults to one.
+The length operator, indicated by the keyword \fBlen\fP, gives the
+length of the packet.
+
+For example, `\fBether[0] & 1 != 0\fP' catches all multicast traffic.
+The expression `\fBip[0] & 0xf != 5\fP'
+catches all IPv4 packets with options.
+The expression
+`\fBip[6:2] & 0x1fff = 0\fP'
+catches only unfragmented IPv4 datagrams and frag zero of fragmented
+IPv4 datagrams.
+This check is implicitly applied to the \fBtcp\fP and \fBudp\fP
+index operations.
+For instance, \fBtcp[0]\fP always means the first
+byte of the TCP \fIheader\fP, and never means the first byte of an
+intervening fragment.
+
+Some offsets and field values may be expressed as names rather than
+as numeric values.
+The following protocol header field offsets are
+available: \fBicmptype\fP (ICMP type field), \fBicmpcode\fP (ICMP
+code field), and \fBtcpflags\fP (TCP flags field).
+
+The following ICMP type field values are available: \fBicmp-echoreply\fP,
+\fBicmp-unreach\fP, \fBicmp-sourcequench\fP, \fBicmp-redirect\fP,
+\fBicmp-echo\fP, \fBicmp-routeradvert\fP, \fBicmp-routersolicit\fP,
+\fBicmp-timxceed\fP, \fBicmp-paramprob\fP, \fBicmp-tstamp\fP,
+\fBicmp-tstampreply\fP, \fBicmp-ireq\fP, \fBicmp-ireqreply\fP,
+\fBicmp-maskreq\fP, \fBicmp-maskreply\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.
+.LP
+Primitives may be combined using:
+.IP
+A parenthesized group of primitives and operators.
+.IP
+Negation (`\fB!\fP' or `\fBnot\fP').
+.IP
+Concatenation (`\fB&&\fP' or `\fBand\fP').
+.IP
+Alternation (`\fB||\fP' or `\fBor\fP').
+.LP
+Negation has highest precedence.
+Alternation and concatenation have equal precedence and associate
+left to right.
+Note that explicit \fBand\fR tokens, not juxtaposition,
+are now required for concatenation.
+.LP
+If an identifier is given without a keyword, the most recent keyword
+is assumed.
+For example,
+.in +.5i
+.nf
+\fBnot host vs and ace\fR
+.fi
+.in -.5i
+is short for
+.in +.5i
+.nf
+\fBnot host vs and host ace\fR
+.fi
+.in -.5i
+which should not be confused with
+.in +.5i
+.nf
+\fBnot ( host vs or ace )\fR
+.fi
+.in -.5i
+.SH EXAMPLES
+.LP
+To select all packets arriving at or departing from \fIsundown\fP:
+.RS
+.nf
+\fBhost sundown\fP
+.fi
+.RE
+.LP
+To select traffic between \fIhelios\fR and either \fIhot\fR or \fIace\fR:
+.RS
+.nf
+\fBhost helios and \\( hot or ace \\)\fP
+.fi
+.RE
+.LP
+To select all IP packets between \fIace\fR and any host except \fIhelios\fR:
+.RS
+.nf
+\fBip host ace and not helios\fP
+.fi
+.RE
+.LP
+To select all traffic between local hosts and hosts at Berkeley:
+.RS
+.nf
+.B
+net ucb-ether
+.fi
+.RE
+.LP
+To select all ftp traffic through internet gateway \fIsnup\fP:
+.RS
+.nf
+.B
+gateway snup and (port ftp or ftp-data)
+.fi
+.RE
+.LP
+To select traffic neither sourced from nor destined for local hosts
+(if you gateway to one other net, this stuff should never make it
+onto your local net).
+.RS
+.nf
+.B
+ip and not net \fIlocalnet\fP
+.fi
+.RE
+.LP
+To select the start and end packets (the SYN and FIN packets) of each
+TCP conversation that involves a non-local host.
+.RS
+.nf
+.B
+tcp[tcpflags] & (tcp-syn|tcp-fin) != 0 and not src and dst net \fIlocalnet\fP
+.fi
+.RE
+.LP
+To select all IPv4 HTTP packets to and from port 80, i.e. print only
+packets that contain data, not, for example, SYN and FIN packets and
+ACK-only packets.  (IPv6 is left as an exercise for the reader.)
+.RS
+.nf
+.B
+tcp port 80 and (((ip[2:2] - ((ip[0]&0xf)<<2)) - ((tcp[12]&0xf0)>>2)) != 0)
+.fi
+.RE
+.LP
+To select IP packets longer than 576 bytes sent through gateway \fIsnup\fP:
+.RS
+.nf
+.B
+gateway snup and ip[2:2] > 576
+.fi
+.RE
+.LP
+To select IP broadcast or multicast packets that were
+.I not
+sent via Ethernet broadcast or multicast:
+.RS
+.nf
+.B
+ether[0] & 1 = 0 and ip[16] >= 224
+.fi
+.RE
+.LP
+To select all ICMP packets that are not echo requests/replies (i.e., not
+ping packets):
+.RS
+.nf
+.B
+icmp[icmptype] != icmp-echo and icmp[icmptype] != icmp-echoreply
+.fi
+.RE
+.SH "SEE ALSO"
+pcap(3PCAP)
+.SH BUGS
+Please send problems, bugs, questions, desirable enhancements, etc. to:
+.LP
+.RS
+tcpdump-workers@lists.tcpdump.org
+.RE
+.LP
+Filter expressions on fields other than those in Token Ring headers will
+not correctly handle source-routed Token Ring packets.
+.LP
+Filter expressions on fields other than those in 802.11 headers will not
+correctly handle 802.11 data packets with both To DS and From DS set.
+.LP
+.BR "ip6 proto"
+should chase header chain, but at this moment it does not.
+.BR "ip6 protochain"
+is supplied for this behavior.
+.LP
+Arithmetic expression against transport layer headers, like \fBtcp[0]\fP,
+does not work against IPv6 packets.
+It only looks at IPv4 packets.
diff --git a/pcap-filter.manmisc.in b/pcap-filter.manmisc.in
index d740194..9d3f34b 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@ "17 May 2013"
+.TH PCAP-FILTER @MAN_MISC_INFO@ "3 August 2015"
 .SH NAME
 pcap-filter \- packet filter syntax
 .br
@@ -298,7 +298,7 @@
 \fBicmp\fP, \fBicmp6\fP, \fBigmp\fP, \fBigrp\fP, \fBpim\fP, \fBah\fP,
 \fBesp\fP, \fBvrrp\fP, \fBudp\fP, or \fBtcp\fP.
 Note that the identifiers \fBtcp\fP, \fBudp\fP, and \fBicmp\fP are also
-keywords and must be escaped via backslash (\\), which is \\\\ in the C-shell.
+keywords and must be escaped via backslash (\\).
 Note that this primitive does not chase the protocol header chain.
 .IP "\fBip6 proto \fIprotocol\fR"
 True if the packet is an IPv6 packet of protocol type \fIprotocol\fP.
@@ -372,9 +372,9 @@
 Note these identifiers are also keywords
 and must be escaped via backslash (\\).
 .IP
-[In the case of FDDI (e.g., `\fBfddi protocol arp\fR'), Token Ring
-(e.g., `\fBtr protocol arp\fR'), and IEEE 802.11 wireless LANS (e.g.,
-`\fBwlan protocol arp\fR'), for most of those protocols, the
+[In the case of FDDI (e.g., `\fBfddi proto arp\fR'), Token Ring
+(e.g., `\fBtr proto arp\fR'), and IEEE 802.11 wireless LANS (e.g.,
+`\fBwlan proto arp\fR'), for most of those protocols, the
 protocol identification comes from the 802.2 Logical Link Control (LLC)
 header, which is usually layered on top of the FDDI, Token Ring, or
 802.11 header.
@@ -879,8 +879,7 @@
 .LP
 Primitives may be combined using:
 .IP
-A parenthesized group of primitives and operators
-(parentheses are special to the Shell and must be escaped).
+A parenthesized group of primitives and operators.
 .IP
 Negation (`\fB!\fP' or `\fBnot\fP').
 .IP
diff --git a/pcap-int.h b/pcap-int.h
index 2f71e11..7db7ff5 100644
--- a/pcap-int.h
+++ b/pcap-int.h
@@ -40,14 +40,16 @@
 extern "C" {
 #endif
 
-#ifdef WIN32
-#include <Packet32.h>
-extern CRITICAL_SECTION g_PcapCompileCriticalSection;
-#endif /* WIN32 */
-
-#ifdef MSDOS
-#include <fcntl.h>
-#include <io.h>
+#if defined(_WIN32)
+  /*
+   * Make sure Packet32.h doesn't define BPF structures that we've
+   * probably already defined as a result of including <pcap/pcap.h>.
+   */
+  #define BPF_MAJOR_VERSION
+  #include <Packet32.h>
+#elif defined(MSDOS)
+  #include <fcntl.h>
+  #include <io.h>
 #endif
 
 #if (defined(_MSC_VER) && (_MSC_VER <= 1200)) /* we are compiling with Visual Studio 6, that doesn't support the LL suffix*/
@@ -106,9 +108,9 @@
 #define MAXIMUM_SNAPLEN		262144
 
 struct pcap_opt {
-	char	*source;
+	char	*device;
 	int	timeout;	/* timeout for buffering */
-	int	buffer_size;
+	u_int	buffer_size;
 	int	promisc;
 	int	rfmon;		/* monitor mode */
 	int	immediate;	/* immediate mode - deliver packets as soon as they arrive */
@@ -126,11 +128,19 @@
 typedef int	(*getnonblock_op_t)(pcap_t *, char *);
 typedef int	(*setnonblock_op_t)(pcap_t *, int, char *);
 typedef int	(*stats_op_t)(pcap_t *, struct pcap_stat *);
-#ifdef WIN32
+#ifdef _WIN32
+typedef struct pcap_stat *(*stats_ex_op_t)(pcap_t *, int *);
 typedef int	(*setbuff_op_t)(pcap_t *, int);
 typedef int	(*setmode_op_t)(pcap_t *, int);
 typedef int	(*setmintocopy_op_t)(pcap_t *, int);
-typedef Adapter *(*getadapter_op_t)(pcap_t *);
+typedef HANDLE	(*getevent_op_t)(pcap_t *);
+typedef int	(*oid_get_request_op_t)(pcap_t *, bpf_u_int32, void *, size_t *);
+typedef int	(*oid_set_request_op_t)(pcap_t *, bpf_u_int32, const void *, size_t *);
+typedef u_int	(*sendqueue_transmit_op_t)(pcap_t *, pcap_send_queue *, int);
+typedef int	(*setuserbuffer_op_t)(pcap_t *, int);
+typedef int	(*live_dump_op_t)(pcap_t *, char *, int, int);
+typedef int	(*live_dump_ended_op_t)(pcap_t *, int);
+typedef PAirpcapHandle	(*get_airpcap_handle_op_t)(pcap_t *);
 #endif
 typedef void	(*cleanup_op_t)(pcap_t *);
 
@@ -145,24 +155,22 @@
 	read_op_t read_op;
 
 	/*
-	 * Method to call to read to read packets from a savefile.
+	 * Method to call to read packets from a savefile.
 	 */
 	int (*next_packet_op)(pcap_t *, struct pcap_pkthdr *, u_char **);
 
-#ifdef WIN32
+#ifdef _WIN32
 	ADAPTER *adapter;
-	LPPACKET Packet;
-	int nonblock;
 #else
 	int fd;
 	int selectable_fd;
-#endif /* WIN32 */
+#endif /* _WIN32 */
 
 	/*
 	 * Read buffer.
 	 */
-	int bufsize;
-	u_char *buffer;
+	u_int bufsize;
+	void *buffer;
 	u_char *bp;
 	int cc;
 
@@ -172,7 +180,7 @@
 
 	int swapped;
 	FILE *rfile;		/* null if live capture, non-null if savefile */
-	int fddipad;
+	u_int fddipad;
 	struct pcap *next;	/* list of open pcaps that need stuff cleared on close */
 
 	/*
@@ -199,6 +207,10 @@
 	 */
 	u_char *pkt;
 
+#ifdef _WIN32
+	struct pcap_stat stat;		/* used for pcap_stats_ex() */
+#endif
+
 	/* We're accepting only packets in this direction/these directions. */
 	pcap_direction_t direction;
 
@@ -240,15 +252,23 @@
 	 */
 	pcap_handler oneshot_callback;
 
-#ifdef WIN32
+#ifdef _WIN32
 	/*
 	 * These are, at least currently, specific to the Win32 NPF
 	 * driver.
 	 */
+	stats_ex_op_t stats_ex_op;
 	setbuff_op_t setbuff_op;
 	setmode_op_t setmode_op;
 	setmintocopy_op_t setmintocopy_op;
-	getadapter_op_t getadapter_op;
+	getevent_op_t getevent_op;
+	oid_get_request_op_t oid_get_request_op;
+	oid_set_request_op_t oid_set_request_op;
+	sendqueue_transmit_op_t sendqueue_transmit_op;
+	setuserbuffer_op_t setuserbuffer_op;
+	live_dump_op_t live_dump_op;
+	live_dump_ended_op_t live_dump_ended_op;
+	get_airpcap_handle_op_t get_airpcap_handle_op;
 #endif
 	cleanup_op_t cleanup_op;
 };
@@ -338,34 +358,15 @@
 	pcap_t *pd;
 };
 
-int	yylex(void);
-
 #ifndef min
 #define min(a, b) ((a) > (b) ? (b) : (a))
 #endif
 
-/* XXX should these be in pcap.h? */
 int	pcap_offline_read(pcap_t *, int, pcap_handler, u_char *);
-int	pcap_read(pcap_t *, int cnt, pcap_handler, u_char *);
-
-#ifndef HAVE_STRLCPY
-#define strlcpy(x, y, z) \
-	(strncpy((x), (y), (z)), \
-	 ((z) <= 0 ? 0 : ((x)[(z) - 1] = '\0')), \
-	 strlen((y)))
-#endif
 
 #include <stdarg.h>
 
-#if !defined(HAVE_SNPRINTF)
-#define snprintf pcap_snprintf
-extern int snprintf (char *, size_t, const char *, ...);
-#endif
-
-#if !defined(HAVE_VSNPRINTF)
-#define vsnprintf pcap_vsnprintf
-extern int vsnprintf (char *, size_t, const char *, va_list ap);
-#endif
+#include "portability.h"
 
 /*
  * Does the packet count argument to a module's read routine say
@@ -376,7 +377,7 @@
 /*
  * Routines that most pcap implementations can use for non-blocking mode.
  */
-#if !defined(WIN32) && !defined(MSDOS)
+#if !defined(_WIN32) && !defined(MSDOS)
 int	pcap_getnonblock_fd(pcap_t *, char *);
 int	pcap_setnonblock_fd(pcap_t *p, int, char *);
 #endif
@@ -393,38 +394,43 @@
  * by pcap_create routines.
  */
 pcap_t	*pcap_create_interface(const char *, char *);
-pcap_t	*pcap_create_common(const char *, char *, size_t);
+pcap_t	*pcap_create_common(char *, size_t);
 int	pcap_do_addexit(pcap_t *);
 void	pcap_add_to_pcaps_to_close(pcap_t *);
 void	pcap_remove_from_pcaps_to_close(pcap_t *);
 void	pcap_cleanup_live_common(pcap_t *);
-int	pcap_not_initialized(pcap_t *);
 int	pcap_check_activated(pcap_t *);
 
 /*
  * Internal interfaces for "pcap_findalldevs()".
  *
- * "pcap_findalldevs_interfaces()" finds interfaces using the
- * "standard" mechanisms (SIOCGIFCONF, "getifaddrs()", etc.).
- *
  * "pcap_platform_finddevs()" is a platform-dependent routine to
- * add devices not found by the "standard" mechanisms.
+ * find local network interfaces.
+ *
+ * "pcap_findalldevs_interfaces()" is a helper to find those interfaces
+ * using the "standard" mechanisms (SIOCGIFCONF, "getifaddrs()", etc.).
  *
  * "pcap_add_if()" adds an interface to the list of interfaces, for
  * use by various "find interfaces" routines.
  */
-int	pcap_findalldevs_interfaces(pcap_if_t **, char *);
 int	pcap_platform_finddevs(pcap_if_t **, char *);
-int	add_addr_to_iflist(pcap_if_t **, const char *, u_int, struct sockaddr *,
-	    size_t, struct sockaddr *, size_t, struct sockaddr *, size_t,
-	    struct sockaddr *, size_t, char *);
+#if !defined(_WIN32) && !defined(MSDOS)
+int	pcap_findalldevs_interfaces(pcap_if_t **, char *,
+	    int (*)(const char *));
+#endif
+int	add_addr_to_iflist(pcap_if_t **, const char *, bpf_u_int32,
+	    struct sockaddr *, size_t, struct sockaddr *, size_t,
+	    struct sockaddr *, size_t, struct sockaddr *, size_t, char *);
 int	add_addr_to_dev(pcap_if_t *, struct sockaddr *, size_t,
 	    struct sockaddr *, size_t, struct sockaddr *, size_t,
 	    struct sockaddr *dstaddr, size_t, char *errbuf);
-int	pcap_add_if(pcap_if_t **, const char *, u_int, const char *, char *);
-struct sockaddr *dup_sockaddr(struct sockaddr *, size_t);
-int	add_or_find_if(pcap_if_t **, pcap_if_t **, const char *, u_int,
+int	pcap_add_if(pcap_if_t **, const char *, bpf_u_int32, const char *,
+	    char *);
+int	add_or_find_if(pcap_if_t **, pcap_if_t **, const char *, bpf_u_int32,
 	    const char *, char *);
+#ifndef _WIN32
+bpf_u_int32 if_flags_to_pcap_flags(const char *, u_int);
+#endif
 
 /*
  * Internal interfaces for "pcap_open_offline()".
@@ -448,8 +454,8 @@
  */
 void	pcap_oneshot(u_char *, const struct pcap_pkthdr *, const u_char *);
 
-#ifdef WIN32
-char	*pcap_win32strerror(void);
+#ifdef _WIN32
+void	pcap_win32_err_to_str(DWORD, char *);
 #endif
 
 int	install_bpf_program(pcap_t *, struct bpf_program *);
diff --git a/pcap-libdlpi.c b/pcap-libdlpi.c
index 333e532..625f1e0 100644
--- a/pcap-libdlpi.c
+++ b/pcap-libdlpi.c
@@ -106,7 +106,7 @@
 	 * dlpi_open() will not fail if the underlying link does not support
 	 * passive mode. See dlpi(7P) for details.
 	 */
-	retv = dlpi_open(p->opt.source, &dh, DLPI_RAW|DLPI_PASSIVE);
+	retv = dlpi_open(p->opt.device, &dh, DLPI_RAW|DLPI_PASSIVE);
 	if (retv != DLPI_SUCCESS) {
 		if (retv == DLPI_ELINKNAMEINVAL || retv == DLPI_ENOLINK)
 			status = PCAP_ERROR_NO_SUCH_DEVICE;
@@ -115,7 +115,7 @@
 			status = PCAP_ERROR_PERM_DENIED;
 		else
 			status = PCAP_ERROR;
-		pcap_libdlpi_err(p->opt.source, "dlpi_open", retv,
+		pcap_libdlpi_err(p->opt.device, "dlpi_open", retv,
 		    p->errbuf);
 		return (status);
 	}
@@ -133,7 +133,7 @@
 	/* Bind with DLPI_ANY_SAP. */
 	if ((retv = dlpi_bind(pd->dlpi_hd, DLPI_ANY_SAP, 0)) != DLPI_SUCCESS) {
 		status = PCAP_ERROR;
-		pcap_libdlpi_err(p->opt.source, "dlpi_bind", retv, p->errbuf);
+		pcap_libdlpi_err(p->opt.device, "dlpi_bind", retv, p->errbuf);
 		goto bad;
 	}
 
@@ -187,7 +187,7 @@
 	/* Determine link type.  */
 	if ((retv = dlpi_info(pd->dlpi_hd, &dlinfo, 0)) != DLPI_SUCCESS) {
 		status = PCAP_ERROR;
-		pcap_libdlpi_err(p->opt.source, "dlpi_info", retv, p->errbuf);
+		pcap_libdlpi_err(p->opt.device, "dlpi_info", retv, p->errbuf);
 		goto bad;
 	}
 
@@ -209,7 +209,7 @@
 	 */
 	if (ioctl(p->fd, I_FLUSH, FLUSHR) != 0) {
 		status = PCAP_ERROR;
-		snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "FLUSHR: %s",
+		pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "FLUSHR: %s",
 		    pcap_strerror(errno));
 		goto bad;
 	}
@@ -258,7 +258,7 @@
 			err = PCAP_ERROR_PERM_DENIED;
 		else
 			err = PCAP_ERROR;
-		pcap_libdlpi_err(p->opt.source, "dlpi_promiscon" STRINGIFY(level),
+		pcap_libdlpi_err(p->opt.device, "dlpi_promiscon" STRINGIFY(level),
 		    retv, p->errbuf);
 		return (err);
 	}
@@ -266,6 +266,17 @@
 }
 
 /*
+ * Presumably everything returned by dlpi_walk() is a DLPI device,
+ * so there's no work to be done here to check whether name refers
+ * to a DLPI device.
+ */
+static int
+is_dlpi_interface(const char *name _U_)
+{
+	return (1);
+}
+
+/*
  * In Solaris, the "standard" mechanism" i.e SIOCGLIFCONF will only find
  * network links that are plumbed and are up. dlpi_walk(3DLPI) will find
  * additional network links present in the system.
@@ -279,12 +290,18 @@
 	linkwalk_t	lw = {NULL, 0};
 	int 		save_errno;
 
+	/*
+	 * Get the list of regular interfaces first.
+	 */
+	if (pcap_findalldevs_interfaces(alldevsp, errbuf, is_dlpi_interface) == -1)
+		return (-1);	/* failure */
+
 	/* dlpi_walk() for loopback will be added here. */
 
 	dlpi_walk(list_interfaces, &lw, 0);
 
 	if (lw.lw_err != 0) {
-		snprintf(errbuf, PCAP_ERRBUF_SIZE,
+		pcap_snprintf(errbuf, PCAP_ERRBUF_SIZE,
 		    "dlpi_walk: %s", pcap_strerror(lw.lw_err));
 		retv = -1;
 		goto done;
@@ -337,7 +354,7 @@
 		}
 
 		msglen = p->bufsize;
-		bufp = p->buffer + p->offset;
+		bufp = (u_char *)p->buffer + p->offset;
 
 		retv = dlpi_recv(pd->dlpi_hd, NULL, NULL, bufp,
 		    &msglen, -1, NULL);
@@ -404,16 +421,16 @@
 static void
 pcap_libdlpi_err(const char *linkname, const char *func, int err, char *errbuf)
 {
-	snprintf(errbuf, PCAP_ERRBUF_SIZE, "libpcap: %s failed on %s: %s",
+	pcap_snprintf(errbuf, PCAP_ERRBUF_SIZE, "libpcap: %s failed on %s: %s",
 	    func, linkname, dlpi_strerror(err));
 }
 
 pcap_t *
-pcap_create_interface(const char *device, char *ebuf)
+pcap_create_interface(const char *device _U_, char *ebuf)
 {
 	pcap_t *p;
 
-	p = pcap_create_common(device, ebuf, sizeof (struct pcap_dlpi));
+	p = pcap_create_common(ebuf, sizeof (struct pcap_dlpi));
 	if (p == NULL)
 		return (NULL);
 
diff --git a/pcap-linktype.manmisc b/pcap-linktype.manmisc
new file mode 100644
index 0000000..e680567
--- /dev/null
+++ b/pcap-linktype.manmisc
@@ -0,0 +1,48 @@
+.\" Copyright (c) 1987, 1988, 1989, 1990, 1991, 1992, 1994, 1995, 1996, 1997
+.\"	The Regents of the University of California.  All rights reserved.
+.\" All rights reserved.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that: (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-LINKTYPE 7 "7 April 2014"
+.SH NAME
+pcap-linktype \- link-layer header types supported by libpcap
+.SH DESCRIPTION
+For a live capture or ``savefile'', libpcap supplies, as the return
+value of the
+.BR pcap_datalink (3PCAP)
+routine, a value that indicates the type of link-layer header at the
+beginning of the packets it provides.  This is not necessarily the type
+of link-layer header that the packets being captured have on the network
+from which they're being captured; for example, packets from an IEEE
+802.11 network might be provided by libpcap with Ethernet headers that
+the network adapter or the network adapter driver generates from the
+802.11 headers.  The names for those values begin with
+.BR DLT_ ,
+so they are sometimes called "DLT_ values".
+.PP
+The values stored in the link-layer header type field in the savefile
+header are, in most but not all cases, the same as the values returned
+by
+.BR pcap_datalink() .
+The names for those values begin with
+.BR LINKTYPE_ .
+.PP
+The link-layer header types supported by libpcap are described at
+http://www.tcpdump.org/linktypes.html.
+.SH SEE ALSO
+pcap_datalink(3PCAP)
diff --git a/pcap-linktype.manmisc.in b/pcap-linktype.manmisc.in
index e42c5b3..7634a96 100644
--- a/pcap-linktype.manmisc.in
+++ b/pcap-linktype.manmisc.in
@@ -18,7 +18,7 @@
 .\" WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
 .\" MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
 .\"
-.TH PCAP-LINKTYPE @MAN_MISC_INFO@ "12 March 2011"
+.TH PCAP-LINKTYPE @MAN_MISC_INFO@ "7 April 2014"
 .SH NAME
 pcap-linktype \- link-layer header types supported by libpcap
 .SH DESCRIPTION
diff --git a/pcap-linux.c b/pcap-linux.c
index a226da1..924df42 100644
--- a/pcap-linux.c
+++ b/pcap-linux.c
@@ -221,7 +221,16 @@
 
 #ifdef HAVE_LINUX_IF_BONDING_H
 #include <linux/if_bonding.h>
+
+/*
+ * The ioctl code to use to check whether a device is a bonding device.
+ */
+#if defined(SIOCBONDINFOQUERY)
+	#define BOND_INFO_QUERY_IOCTL SIOCBONDINFOQUERY
+#elif defined(BOND_INFO_QUERY_OLD)
+	#define BOND_INFO_QUERY_IOCTL BOND_INFO_QUERY_OLD
 #endif
+#endif /* HAVE_LINUX_IF_BONDING_H */
 
 /*
  * Got Wireless Extensions?
@@ -310,6 +319,7 @@
 	u_int	tp_version;	/* version of tpacket_hdr for mmaped ring */
 	u_int	tp_hdrlen;	/* hdrlen of tpacket_hdr for mmaped ring */
 	u_char	*oneshot_buffer; /* buffer for copy of packet */
+	int	poll_timeout;	/* timeout to use in poll() */
 #ifdef HAVE_TPACKET3
 	unsigned char *current_packet; /* Current packet within the TPACKET_V3 block. Move to next block if NULL. */
 	int packets_left; /* Unhandled packets left within the block from previous call to pcap_read_linux_mmap_v3 in case of TPACKET_V3. */
@@ -378,7 +388,8 @@
 };
 
 #ifdef HAVE_PACKET_RING
-#define RING_GET_FRAME(h) (((union thdr **)h->buffer)[h->offset])
+#define RING_GET_FRAME_AT(h, offset) (((union thdr **)h->buffer)[(offset)])
+#define RING_GET_CURRENT_FRAME(h) RING_GET_FRAME_AT(h, h->offset)
 
 static void destroy_ring(pcap_t *handle);
 static int create_ring(pcap_t *handle, int *status);
@@ -422,7 +433,8 @@
     const char *device);
 #endif /* HAVE_PF_PACKET_SOCKETS */
 #if defined(HAVE_LINUX_NET_TSTAMP_H) && defined(PACKET_TIMESTAMP)
-static int	iface_ethtool_get_ts_info(pcap_t *handle, char *ebuf);
+static int	iface_ethtool_get_ts_info(const char *device, pcap_t *handle,
+    char *ebuf);
 #endif
 #ifdef HAVE_PACKET_RING
 static int	iface_get_offload(pcap_t *handle);
@@ -447,7 +459,7 @@
 {
 	pcap_t *handle;
 
-	handle = pcap_create_common(device, ebuf, sizeof (struct pcap_linux));
+	handle = pcap_create_common(ebuf, sizeof (struct pcap_linux));
 	if (handle == NULL)
 		return NULL;
 
@@ -458,8 +470,8 @@
 	/*
 	 * See what time stamp types we support.
 	 */
-	if (iface_ethtool_get_ts_info(handle, ebuf) == -1) {
-		free(handle);
+	if (iface_ethtool_get_ts_info(device, handle, ebuf) == -1) {
+		pcap_close(handle);
 		return NULL;
 	}
 #endif
@@ -476,11 +488,9 @@
 	handle->tstamp_precision_count = 2;
 	handle->tstamp_precision_list = malloc(2 * sizeof(u_int));
 	if (handle->tstamp_precision_list == NULL) {
-		snprintf(ebuf, PCAP_ERRBUF_SIZE, "malloc: %s",
+		pcap_snprintf(ebuf, PCAP_ERRBUF_SIZE, "malloc: %s",
 		    pcap_strerror(errno));
-		if (handle->tstamp_type_list != NULL)
-			free(handle->tstamp_type_list);
-		free(handle);
+		pcap_close(handle);
 		return NULL;
 	}
 	handle->tstamp_precision_list[0] = PCAP_TSTAMP_PRECISION_MICRO;
@@ -532,7 +542,7 @@
  *
  * Yes, you can have multiple monitor devices for a given
  * physical device.
-*/
+ */
 
 /*
  * Is this a mac80211 device?  If so, fill in the physical device path and
@@ -550,7 +560,7 @@
 	 * Generate the path string for the symlink to the physical device.
 	 */
 	if (asprintf(&pathstr, "/sys/class/net/%s/phy80211", device) == -1) {
-		snprintf(handle->errbuf, PCAP_ERRBUF_SIZE,
+		pcap_snprintf(handle->errbuf, PCAP_ERRBUF_SIZE,
 		    "%s: Can't generate path name string for /sys/class/net device",
 		    device);
 		return PCAP_ERROR;
@@ -565,7 +575,7 @@
 			free(pathstr);
 			return 0;
 		}
-		snprintf(handle->errbuf, PCAP_ERRBUF_SIZE,
+		pcap_snprintf(handle->errbuf, PCAP_ERRBUF_SIZE,
 		    "%s: Can't readlink %s: %s", device, pathstr,
 		    strerror(errno));
 		free(pathstr);
@@ -622,20 +632,20 @@
 
 	state->nl_sock = nl_socket_alloc();
 	if (!state->nl_sock) {
-		snprintf(handle->errbuf, PCAP_ERRBUF_SIZE,
+		pcap_snprintf(handle->errbuf, PCAP_ERRBUF_SIZE,
 		    "%s: failed to allocate netlink handle", device);
 		return PCAP_ERROR;
 	}
 
 	if (genl_connect(state->nl_sock)) {
-		snprintf(handle->errbuf, PCAP_ERRBUF_SIZE,
+		pcap_snprintf(handle->errbuf, PCAP_ERRBUF_SIZE,
 		    "%s: failed to connect to generic netlink", device);
 		goto out_handle_destroy;
 	}
 
 	err = genl_ctrl_alloc_cache(state->nl_sock, &state->nl_cache);
 	if (err < 0) {
-		snprintf(handle->errbuf, PCAP_ERRBUF_SIZE,
+		pcap_snprintf(handle->errbuf, PCAP_ERRBUF_SIZE,
 		    "%s: failed to allocate generic netlink cache: %s",
 		    device, get_nl_errmsg(-err));
 		goto out_handle_destroy;
@@ -643,7 +653,7 @@
 
 	state->nl80211 = genl_ctrl_search_by_name(state->nl_cache, "nl80211");
 	if (!state->nl80211) {
-		snprintf(handle->errbuf, PCAP_ERRBUF_SIZE,
+		pcap_snprintf(handle->errbuf, PCAP_ERRBUF_SIZE,
 		    "%s: nl80211 not found", device);
 		goto out_cache_free;
 	}
@@ -666,9 +676,14 @@
 }
 
 static int
+del_mon_if(pcap_t *handle, int sock_fd, struct nl80211_state *state,
+    const char *device, const char *mondevice);
+
+static int
 add_mon_if(pcap_t *handle, int sock_fd, struct nl80211_state *state,
     const char *device, const char *mondevice)
 {
+	struct pcap_linux *handlep = handle->priv;
 	int ifindex;
 	struct nl_msg *msg;
 	int err;
@@ -679,7 +694,7 @@
 
 	msg = nlmsg_alloc();
 	if (!msg) {
-		snprintf(handle->errbuf, PCAP_ERRBUF_SIZE,
+		pcap_snprintf(handle->errbuf, PCAP_ERRBUF_SIZE,
 		    "%s: failed to allocate netlink msg", device);
 		return PCAP_ERROR;
 	}
@@ -711,7 +726,7 @@
 			 * Real failure, not just "that device is not
 			 * available.
 			 */
-			snprintf(handle->errbuf, PCAP_ERRBUF_SIZE,
+			pcap_snprintf(handle->errbuf, PCAP_ERRBUF_SIZE,
 			    "%s: nl_send_auto_complete failed adding %s interface: %s",
 			    device, mondevice, get_nl_errmsg(-err));
 			nlmsg_free(msg);
@@ -739,7 +754,7 @@
 			 * Real failure, not just "that device is not
 			 * available.
 			 */
-			snprintf(handle->errbuf, PCAP_ERRBUF_SIZE,
+			pcap_snprintf(handle->errbuf, PCAP_ERRBUF_SIZE,
 			    "%s: nl_wait_for_ack failed adding %s interface: %s",
 			    device, mondevice, get_nl_errmsg(-err));
 			nlmsg_free(msg);
@@ -751,10 +766,24 @@
 	 * Success.
 	 */
 	nlmsg_free(msg);
+
+	/*
+	 * Try to remember the monitor device.
+	 */
+	handlep->mondevice = strdup(mondevice);
+	if (handlep->mondevice == NULL) {
+		pcap_snprintf(handle->errbuf, PCAP_ERRBUF_SIZE, "strdup: %s",
+			 pcap_strerror(errno));
+		/*
+		 * Get rid of the monitor device.
+		 */
+		del_mon_if(handle, sock_fd, state, device, mondevice);
+		return PCAP_ERROR;
+	}
 	return 1;
 
 nla_put_failure:
-	snprintf(handle->errbuf, PCAP_ERRBUF_SIZE,
+	pcap_snprintf(handle->errbuf, PCAP_ERRBUF_SIZE,
 	    "%s: nl_put failed adding %s interface",
 	    device, mondevice);
 	nlmsg_free(msg);
@@ -775,7 +804,7 @@
 
 	msg = nlmsg_alloc();
 	if (!msg) {
-		snprintf(handle->errbuf, PCAP_ERRBUF_SIZE,
+		pcap_snprintf(handle->errbuf, PCAP_ERRBUF_SIZE,
 		    "%s: failed to allocate netlink msg", device);
 		return PCAP_ERROR;
 	}
@@ -786,7 +815,7 @@
 
 	err = nl_send_auto_complete(state->nl_sock, msg);
 	if (err < 0) {
-		snprintf(handle->errbuf, PCAP_ERRBUF_SIZE,
+		pcap_snprintf(handle->errbuf, PCAP_ERRBUF_SIZE,
 		    "%s: nl_send_auto_complete failed deleting %s interface: %s",
 		    device, mondevice, get_nl_errmsg(-err));
 		nlmsg_free(msg);
@@ -794,7 +823,7 @@
 	}
 	err = nl_wait_for_ack(state->nl_sock);
 	if (err < 0) {
-		snprintf(handle->errbuf, PCAP_ERRBUF_SIZE,
+		pcap_snprintf(handle->errbuf, PCAP_ERRBUF_SIZE,
 		    "%s: nl_wait_for_ack failed adding %s interface: %s",
 		    device, mondevice, get_nl_errmsg(-err));
 		nlmsg_free(msg);
@@ -808,7 +837,7 @@
 	return 1;
 
 nla_put_failure:
-	snprintf(handle->errbuf, PCAP_ERRBUF_SIZE,
+	pcap_snprintf(handle->errbuf, PCAP_ERRBUF_SIZE,
 	    "%s: nl_put failed deleting %s interface",
 	    device, mondevice);
 	nlmsg_free(msg);
@@ -853,10 +882,13 @@
 		 */
 		char mondevice[3+10+1];	/* mon{UINT_MAX}\0 */
 
-		snprintf(mondevice, sizeof mondevice, "mon%u", n);
+		pcap_snprintf(mondevice, sizeof mondevice, "mon%u", n);
 		ret = add_mon_if(handle, sock_fd, &nlstate, device, mondevice);
 		if (ret == 1) {
-			handlep->mondevice = strdup(mondevice);
+			/*
+			 * Success.  We don't clean up the libnl state
+			 * yet, as we'll be using it later.
+			 */
 			goto added;
 		}
 		if (ret < 0) {
@@ -869,7 +901,7 @@
 		}
 	}
 
-	snprintf(handle->errbuf, PCAP_ERRBUF_SIZE,
+	pcap_snprintf(handle->errbuf, PCAP_ERRBUF_SIZE,
 	    "%s: No free monN interfaces", device);
 	nl80211_cleanup(&nlstate);
 	return PCAP_ERROR;
@@ -894,7 +926,10 @@
 		 * "atexit()" failed; don't put the interface
 		 * in rfmon mode, just give up.
 		 */
-		return PCAP_ERROR_RFMON_NOTSUP;
+		del_mon_if(handle, sock_fd, &nlstate, device,
+		    handlep->mondevice);
+		nl80211_cleanup(&nlstate);
+		return PCAP_ERROR;
 	}
 
 	/*
@@ -903,7 +938,7 @@
 	memset(&ifr, 0, sizeof(ifr));
 	strlcpy(ifr.ifr_name, handlep->mondevice, sizeof(ifr.ifr_name));
 	if (ioctl(sock_fd, SIOCGIFFLAGS, &ifr) == -1) {
-		snprintf(handle->errbuf, PCAP_ERRBUF_SIZE,
+		pcap_snprintf(handle->errbuf, PCAP_ERRBUF_SIZE,
 		    "%s: Can't get flags for %s: %s", device,
 		    handlep->mondevice, strerror(errno));
 		del_mon_if(handle, sock_fd, &nlstate, device,
@@ -913,7 +948,7 @@
 	}
 	ifr.ifr_flags |= IFF_UP|IFF_RUNNING;
 	if (ioctl(sock_fd, SIOCSIFFLAGS, &ifr) == -1) {
-		snprintf(handle->errbuf, PCAP_ERRBUF_SIZE,
+		pcap_snprintf(handle->errbuf, PCAP_ERRBUF_SIZE,
 		    "%s: Can't set flags for %s: %s", device,
 		    handlep->mondevice, strerror(errno));
 		del_mon_if(handle, sock_fd, &nlstate, device,
@@ -957,7 +992,7 @@
 static int
 is_bonding_device(int fd, const char *device)
 {
-#if defined(BOND_INFO_QUERY_OLD) || defined(SIOCBONDINFOQUERY)
+#ifdef BOND_INFO_QUERY_IOCTL
 	struct ifreq ifr;
 	ifbond ifb;
 
@@ -965,13 +1000,9 @@
 	strlcpy(ifr.ifr_name, device, sizeof ifr.ifr_name);
 	memset(&ifb, 0, sizeof ifb);
 	ifr.ifr_data = (caddr_t)&ifb;
-#ifdef SIOCBONDINFOQUERY
-	if (ioctl(fd, SIOCBONDINFOQUERY, &ifr) == 0)
-#else /* SIOCBONDINFOQUERY */
-	if (ioctl(fd, BOND_INFO_QUERY_OLD, &ifr) == 0)
-#endif /* SIOCBONDINFOQUERY */
+	if (ioctl(fd, BOND_INFO_QUERY_IOCTL, &ifr) == 0)
 		return 1;	/* success, so it's a bonding device */
-#endif /* defined(BOND_INFO_QUERY_OLD) || defined(SIOCBONDINFOQUERY) */
+#endif /* BOND_INFO_QUERY_IOCTL */
 
 	return 0;	/* no, it's not a bonding device */
 }
@@ -989,7 +1020,7 @@
 	struct iwreq ireq;
 #endif
 
-	if (strcmp(handle->opt.source, "any") == 0) {
+	if (strcmp(handle->opt.device, "any") == 0) {
 		/*
 		 * Monitor mode makes no sense on the "any" device.
 		 */
@@ -1009,7 +1040,7 @@
 	 * wmaster device, so we don't bother checking whether
 	 * a mac80211 device supports the Wireless Extensions.
 	 */
-	ret = get_mac80211_phydev(handle, handle->opt.source, phydev_path,
+	ret = get_mac80211_phydev(handle, handle->opt.device, phydev_path,
 	    PATH_MAX);
 	if (ret < 0)
 		return ret;	/* error */
@@ -1030,12 +1061,12 @@
 	 */
 	sock_fd = socket(PF_PACKET, SOCK_RAW, htons(ETH_P_ALL));
 	if (sock_fd == -1) {
-		(void)snprintf(handle->errbuf, PCAP_ERRBUF_SIZE,
+		(void)pcap_snprintf(handle->errbuf, PCAP_ERRBUF_SIZE,
 		    "socket: %s", pcap_strerror(errno));
 		return PCAP_ERROR;
 	}
 
-	if (is_bonding_device(sock_fd, handle->opt.source)) {
+	if (is_bonding_device(sock_fd, handle->opt.device)) {
 		/* It's a bonding device, so don't even try. */
 		close(sock_fd);
 		return 0;
@@ -1044,7 +1075,7 @@
 	/*
 	 * Attempt to get the current mode.
 	 */
-	strlcpy(ireq.ifr_ifrn.ifrn_name, handle->opt.source,
+	strlcpy(ireq.ifr_ifrn.ifrn_name, handle->opt.device,
 	    sizeof ireq.ifr_ifrn.ifrn_name);
 	if (ioctl(sock_fd, SIOCGIWMODE, &ireq) != -1) {
 		/*
@@ -1055,7 +1086,7 @@
 	}
 	if (errno == ENODEV) {
 		/* The device doesn't even exist. */
-		(void)snprintf(handle->errbuf, PCAP_ERRBUF_SIZE,
+		(void)pcap_snprintf(handle->errbuf, PCAP_ERRBUF_SIZE,
 		    "SIOCGIWMODE failed: %s", pcap_strerror(errno));
 		close(sock_fd);
 		return PCAP_ERROR_NO_SUCH_DEVICE;
@@ -1293,6 +1324,94 @@
 }
 
 /*
+ * Set the timeout to be used in poll() with memory-mapped packet capture.
+ */
+static void
+set_poll_timeout(struct pcap_linux *handlep)
+{
+#ifdef HAVE_TPACKET3
+	struct utsname utsname;
+	char *version_component, *endp;
+	int major, minor;
+	int broken_tpacket_v3 = 1;
+
+	/*
+	 * Some versions of TPACKET_V3 have annoying bugs/misfeatures
+	 * around which we have to work.  Determine if we have those
+	 * problems or not.
+	 */
+	if (uname(&utsname) == 0) {
+		/*
+		 * 3.19 is the first release with a fixed version of
+		 * TPACKET_V3.  We treat anything before that as
+		 * not haveing a fixed version; that may really mean
+		 * it has *no* version.
+		 */
+		version_component = utsname.release;
+		major = strtol(version_component, &endp, 10);
+		if (endp != version_component && *endp == '.') {
+			/*
+			 * OK, that was a valid major version.
+			 * Get the minor version.
+			 */
+			version_component = endp + 1;
+			minor = strtol(version_component, &endp, 10);
+			if (endp != version_component &&
+			    (*endp == '.' || *endp == '\0')) {
+				/*
+				 * OK, that was a valid minor version.
+				 * Is this 3.19 or newer?
+				 */
+				if (major >= 4 || (major == 3 && minor >= 19)) {
+					/* Yes. TPACKET_V3 works correctly. */
+					broken_tpacket_v3 = 0;
+				}
+			}
+		}
+	}
+#endif
+	if (handlep->timeout == 0) {
+#ifdef HAVE_TPACKET3
+		/*
+		 * XXX - due to a set of (mis)features in the TPACKET_V3
+		 * kernel code prior to the 3.19 kernel, blocking forever
+		 * with a TPACKET_V3 socket can, if few packets are
+		 * arriving and passing the socket filter, cause most
+		 * packets to be dropped.  See libpcap issue #335 for the
+		 * full painful story.
+		 *
+		 * The workaround is to have poll() time out very quickly,
+		 * so we grab the frames handed to us, and return them to
+		 * the kernel, ASAP.
+		 */
+		if (handlep->tp_version == TPACKET_V3 && broken_tpacket_v3)
+			handlep->poll_timeout = 1;	/* don't block for very long */
+		else
+#endif
+			handlep->poll_timeout = -1;	/* block forever */
+	} else if (handlep->timeout > 0) {
+#ifdef HAVE_TPACKET3
+		/*
+		 * For TPACKET_V3, the timeout is handled by the kernel,
+		 * so block forever; that way, we don't get extra timeouts.
+		 * Don't do that if we have a broken TPACKET_V3, though.
+		 */
+		if (handlep->tp_version == TPACKET_V3 && !broken_tpacket_v3)
+			handlep->poll_timeout = -1;	/* block forever, let TPACKET_V3 wake us up */
+		else
+#endif
+			handlep->poll_timeout = handlep->timeout;	/* block for that amount of time */
+	} else {
+		/*
+		 * Non-blocking mode; we call poll() to pick up error
+		 * indications, but we don't want it to wait for
+		 * anything.
+		 */
+		handlep->poll_timeout = 0;
+	}
+}
+
+/*
  *  Get a handle for a live capture from the given device. You can
  *  pass NULL as device to get all packages (without link level
  *  information of course). If you pass 1 as promisc the interface
@@ -1309,7 +1428,7 @@
 	int		status = 0;
 	int		ret;
 
-	device = handle->opt.source;
+	device = handle->opt.device;
 
 	/*
 	 * Make sure the name we were handed will fit into the ioctls we
@@ -1346,7 +1465,7 @@
 		if (handle->opt.promisc) {
 			handle->opt.promisc = 0;
 			/* Just a warning. */
-			snprintf(handle->errbuf, PCAP_ERRBUF_SIZE,
+			pcap_snprintf(handle->errbuf, PCAP_ERRBUF_SIZE,
 			    "Promiscuous mode not supported on the \"any\" device");
 			status = PCAP_WARNING_PROMISC_NOTSUP;
 		}
@@ -1354,7 +1473,7 @@
 
 	handlep->device	= strdup(device);
 	if (handlep->device == NULL) {
-		snprintf(handle->errbuf, PCAP_ERRBUF_SIZE, "strdup: %s",
+		pcap_snprintf(handle->errbuf, PCAP_ERRBUF_SIZE, "strdup: %s",
 			 pcap_strerror(errno) );
 		return PCAP_ERROR;
 	}
@@ -1402,7 +1521,11 @@
 			 * set to the status to return,
 			 * which might be 0, or might be
 			 * a PCAP_WARNING_ value.
+			 *
+			 * Set the timeout to use in poll() before
+			 * returning.
 			 */
+			set_poll_timeout(handlep);
 			return status;
 
 		case 0:
@@ -1447,7 +1570,7 @@
 		if (setsockopt(handle->fd, SOL_SOCKET, SO_RCVBUF,
 		    &handle->opt.buffer_size,
 		    sizeof(handle->opt.buffer_size)) == -1) {
-			snprintf(handle->errbuf, PCAP_ERRBUF_SIZE,
+			pcap_snprintf(handle->errbuf, PCAP_ERRBUF_SIZE,
 				 "SO_RCVBUF: %s", pcap_strerror(errno));
 			status = PCAP_ERROR;
 			goto fail;
@@ -1458,7 +1581,7 @@
 
 	handle->buffer	 = malloc(handle->bufsize + handle->offset);
 	if (!handle->buffer) {
-		snprintf(handle->errbuf, PCAP_ERRBUF_SIZE,
+		pcap_snprintf(handle->errbuf, PCAP_ERRBUF_SIZE,
 			 "malloc: %s", pcap_strerror(errno));
 		status = PCAP_ERROR;
 		goto fail;
@@ -1520,6 +1643,22 @@
 			return 0;
 
 		/*
+		 * If this is an outgoing CAN or CAN FD frame, and
+		 * the user doesn't only want outgoing packets,
+		 * reject it; CAN devices and drivers, and the CAN
+		 * stack, always arrange to loop back transmitted
+		 * packets, so they also appear as incoming packets.
+		 * We don't want duplicate packets, and we can't
+		 * easily distinguish packets looped back by the CAN
+		 * layer than those received by the CAN layer, so we
+		 * eliminate this packet instead.
+		 */
+		if ((sll->sll_protocol == LINUX_SLL_P_CAN ||
+		     sll->sll_protocol == LINUX_SLL_P_CANFD) &&
+		     handle->direction != PCAP_D_OUT)
+			return 0;
+
+		/*
 		 * If the user only wants incoming packets, reject it.
 		 */
 		if (handle->direction == PCAP_D_IN)
@@ -1599,7 +1738,7 @@
 	 * if we're using a memory-mapped buffer, we won't even
 	 * get notified of "network down" events.
 	 */
-	bp = handle->buffer + handle->offset;
+	bp = (u_char *)handle->buffer + handle->offset;
 
 #if defined(HAVE_PACKET_AUXDATA) && defined(HAVE_LINUX_TPACKET_AUXDATA_TP_VLAN_TCI)
 	msg.msg_name		= &from;
@@ -1655,12 +1794,12 @@
 			 * PCAP_ERROR_IFACE_NOT_UP, but pcap_dispatch()
 			 * etc. aren't defined to return that.
 			 */
-			snprintf(handle->errbuf, PCAP_ERRBUF_SIZE,
+			pcap_snprintf(handle->errbuf, PCAP_ERRBUF_SIZE,
 				"The interface went down");
 			return PCAP_ERROR;
 
 		default:
-			snprintf(handle->errbuf, PCAP_ERRBUF_SIZE,
+			pcap_snprintf(handle->errbuf, PCAP_ERRBUF_SIZE,
 				 "recvfrom: %s", pcap_strerror(errno));
 			return PCAP_ERROR;
 		}
@@ -1739,13 +1878,22 @@
 #endif
 				continue;
 
-			len = packet_len > iov.iov_len ? iov.iov_len : packet_len;
-			if (len < (unsigned int) handlep->vlan_offset)
+			len = (u_int)packet_len > iov.iov_len ? iov.iov_len : (u_int)packet_len;
+			if (len < (u_int)handlep->vlan_offset)
 				break;
 
+			/*
+			 * Move everything in the header, except the
+			 * type field, down VLAN_TAG_LEN bytes, to
+			 * allow us to insert the VLAN tag between
+			 * that stuff and the type field.
+			 */
 			bp -= VLAN_TAG_LEN;
 			memmove(bp, bp + VLAN_TAG_LEN, handlep->vlan_offset);
 
+			/*
+			 * Now insert the tag.
+			 */
 			tag = (struct vlan_tag *)(bp + handlep->vlan_offset);
 			tag->vlan_tpid = htons(VLAN_TPID(aux, aux));
 			tag->vlan_tci = htons(aux->tp_vlan_tci);
@@ -1755,6 +1903,10 @@
                         aux_data.vlan_tag = htons(aux->tp_vlan_tci) & 0x0fff;
                         aux_data.vlan_tag_present = (aux->tp_status & TP_STATUS_VLAN_VALID);
 #endif
+
+			/*
+			 * Add the tag to the packet lengths.
+			 */
 			packet_len += VLAN_TAG_LEN;
 		}
 	}
@@ -1812,7 +1964,7 @@
 #if defined(SIOCGSTAMPNS) && defined(SO_TIMESTAMPNS)
 	if (handle->opt.tstamp_precision == PCAP_TSTAMP_PRECISION_NANO) {
 		if (ioctl(handle->fd, SIOCGSTAMPNS, &pcap_header.ts) == -1) {
-			snprintf(handle->errbuf, PCAP_ERRBUF_SIZE,
+			pcap_snprintf(handle->errbuf, PCAP_ERRBUF_SIZE,
 					"SIOCGSTAMPNS: %s", pcap_strerror(errno));
 			return PCAP_ERROR;
 		}
@@ -1820,7 +1972,7 @@
 #endif
 	{
 		if (ioctl(handle->fd, SIOCGSTAMP, &pcap_header.ts) == -1) {
-			snprintf(handle->errbuf, PCAP_ERRBUF_SIZE,
+			pcap_snprintf(handle->errbuf, PCAP_ERRBUF_SIZE,
 					"SIOCGSTAMP: %s", pcap_strerror(errno));
 			return PCAP_ERROR;
 		}
@@ -1918,7 +2070,7 @@
 
 	ret = send(handle->fd, buf, size, 0);
 	if (ret == -1) {
-		snprintf(handle->errbuf, PCAP_ERRBUF_SIZE, "send: %s",
+		pcap_snprintf(handle->errbuf, PCAP_ERRBUF_SIZE, "send: %s",
 		    pcap_strerror(errno));
 		return (-1);
 	}
@@ -2040,7 +2192,7 @@
 		 * is built on a system without "struct tpacket_stats".
 		 */
 		if (errno != EOPNOTSUPP) {
-			snprintf(handle->errbuf, PCAP_ERRBUF_SIZE,
+			pcap_snprintf(handle->errbuf, PCAP_ERRBUF_SIZE,
 			    "pcap_stats: %s", pcap_strerror(errno));
 			return -1;
 		}
@@ -2126,7 +2278,7 @@
 	if (ioctl(fd, SIOCGIFFLAGS, (char *)&ifrflags) < 0) {
 		if (errno == ENXIO || errno == ENODEV)
 			return (0);	/* device doesn't actually exist - ignore it */
-		(void)snprintf(errbuf, PCAP_ERRBUF_SIZE,
+		(void)pcap_snprintf(errbuf, PCAP_ERRBUF_SIZE,
 		    "SIOCGIFFLAGS: %.*s: %s",
 		    (int)sizeof(ifrflags.ifr_name),
 		    ifrflags.ifr_name,
@@ -2137,7 +2289,8 @@
 	/*
 	 * Add an entry for this interface, with no addresses.
 	 */
-	if (pcap_add_if(devlistp, name, ifrflags.ifr_flags, NULL,
+	if (pcap_add_if(devlistp, name,
+	    if_flags_to_pcap_flags(name, ifrflags.ifr_flags), NULL,
 	    errbuf) == -1) {
 		/*
 		 * Failure.
@@ -2185,7 +2338,7 @@
 		/*
 		 * Fail if we got some other error.
 		 */
-		(void)snprintf(errbuf, PCAP_ERRBUF_SIZE,
+		(void)pcap_snprintf(errbuf, PCAP_ERRBUF_SIZE,
 		    "Can't open /sys/class/net: %s", pcap_strerror(errno));
 		return (-1);
 	}
@@ -2193,9 +2346,9 @@
 	/*
 	 * Create a socket from which to fetch interface information.
 	 */
-	fd = socket(AF_INET, SOCK_DGRAM, 0);
+	fd = socket(PF_UNIX, SOCK_RAW, 0);
 	if (fd < 0) {
-		(void)snprintf(errbuf, PCAP_ERRBUF_SIZE,
+		(void)pcap_snprintf(errbuf, PCAP_ERRBUF_SIZE,
 		    "socket: %s", pcap_strerror(errno));
 		(void)closedir(sys_class_net_d);
 		return (-1);
@@ -2232,7 +2385,7 @@
 		 * for devices, newer kernels have symlinks to
 		 * directories.)
 		 */
-		snprintf(subsystem_path, sizeof subsystem_path,
+		pcap_snprintf(subsystem_path, sizeof subsystem_path,
 		    "/sys/class/net/%s/ifindex", ent->d_name);
 		if (lstat(subsystem_path, &statb) != 0) {
 			/*
@@ -2263,7 +2416,7 @@
 		 * fail due to an error reading the directory?
 		 */
 		if (errno != 0) {
-			(void)snprintf(errbuf, PCAP_ERRBUF_SIZE,
+			(void)pcap_snprintf(errbuf, PCAP_ERRBUF_SIZE,
 			    "Error reading /sys/class/net: %s",
 			    pcap_strerror(errno));
 			ret = -1;
@@ -2303,7 +2456,7 @@
 		/*
 		 * Fail if we got some other error.
 		 */
-		(void)snprintf(errbuf, PCAP_ERRBUF_SIZE,
+		(void)pcap_snprintf(errbuf, PCAP_ERRBUF_SIZE,
 		    "Can't open /proc/net/dev: %s", pcap_strerror(errno));
 		return (-1);
 	}
@@ -2311,9 +2464,9 @@
 	/*
 	 * Create a socket from which to fetch interface information.
 	 */
-	fd = socket(AF_INET, SOCK_DGRAM, 0);
+	fd = socket(PF_UNIX, SOCK_RAW, 0);
 	if (fd < 0) {
-		(void)snprintf(errbuf, PCAP_ERRBUF_SIZE,
+		(void)pcap_snprintf(errbuf, PCAP_ERRBUF_SIZE,
 		    "socket: %s", pcap_strerror(errno));
 		(void)fclose(proc_net_f);
 		return (-1);
@@ -2352,7 +2505,7 @@
 		 * fail due to an error reading the file?
 		 */
 		if (ferror(proc_net_f)) {
-			(void)snprintf(errbuf, PCAP_ERRBUF_SIZE,
+			(void)pcap_snprintf(errbuf, PCAP_ERRBUF_SIZE,
 			    "Error reading /proc/net/dev: %s",
 			    pcap_strerror(errno));
 			ret = -1;
@@ -2369,12 +2522,27 @@
  */
 static const char any_descr[] = "Pseudo-device that captures on all interfaces";
 
+/*
+ * A SOCK_PACKET or PF_PACKET socket can be bound to any network interface.
+ */
+static int
+can_be_bound(const char *name _U_)
+{
+	return (1);
+}
+
 int
 pcap_platform_finddevs(pcap_if_t **alldevsp, char *errbuf)
 {
 	int ret;
 
 	/*
+	 * Get the list of regular interfaces first.
+	 */
+	if (pcap_findalldevs_interfaces(alldevsp, errbuf, can_be_bound) == -1)
+		return (-1);	/* failure */
+
+	/*
 	 * Read "/sys/class/net", and add to the list of interfaces all
 	 * interfaces listed there that we don't already have, because,
 	 * on Linux, SIOCGIFCONF reports only interfaces with IPv4 addresses,
@@ -2396,7 +2564,7 @@
 	/*
 	 * Add the "any" device.
 	 */
-	if (pcap_add_if(alldevsp, "any", IFF_UP|IFF_RUNNING,
+	if (pcap_add_if(alldevsp, "any", PCAP_IF_UP|PCAP_IF_RUNNING,
 	    any_descr, errbuf) < 0)
 		return (-1);
 
@@ -2557,7 +2725,7 @@
 	 */
 	if (handlep->filter_in_userland) {
 		if (reset_kernel_filter(handle) == -1) {
-			snprintf(handle->errbuf, PCAP_ERRBUF_SIZE,
+			pcap_snprintf(handle->errbuf, PCAP_ERRBUF_SIZE,
 			    "can't remove kernel filter: %s",
 			    pcap_strerror(errno));
 			err = -2;	/* fatal error */
@@ -2604,7 +2772,7 @@
 	 * We're not using PF_PACKET sockets, so we can't determine
 	 * the direction of the packet.
 	 */
-	snprintf(handle->errbuf, PCAP_ERRBUF_SIZE,
+	pcap_snprintf(handle->errbuf, PCAP_ERRBUF_SIZE,
 	    "Setting direction is not supported on SOCK_PACKET sockets");
 	return -1;
 }
@@ -2791,7 +2959,14 @@
 #define ARPHRD_CAN 280
 #endif
 	case ARPHRD_CAN:
-		handle->linktype = DLT_CAN_SOCKETCAN;
+		/*
+		 * Map this to DLT_LINUX_SLL; that way, CAN frames will
+		 * have ETH_P_CAN/LINUX_SLL_P_CAN as the protocol and
+		 * CAN FD frames will have ETH_P_CANFD/LINUX_SLL_P_CANFD
+		 * as the protocol, so they can be distinguished by the
+		 * protocol in the SLL header.
+		 */
+		handle->linktype = DLT_LINUX_SLL;
 		break;
 
 #ifndef ARPHRD_IEEE802_TR
@@ -3074,7 +3249,7 @@
 		 * so let's use "Linux-cooked" mode. Jean II
 		 *
 		 * XXX - this is handled in activate_new(). */
-		//handlep->cooked = 1;
+		/* handlep->cooked = 1; */
 		break;
 
 	/* ARPHRD_LAPD is unofficial and randomly allocated, if reallocation
@@ -3117,7 +3292,7 @@
 		 *
 		 * XXX - this is handled in activate_new().
 		 */
-		//handlep->cooked = 1;
+		/* handlep->cooked = 1; */
 		break;
 
 	default:
@@ -3140,7 +3315,7 @@
 {
 #ifdef HAVE_PF_PACKET_SOCKETS
 	struct pcap_linux *handlep = handle->priv;
-	const char		*device = handle->opt.source;
+	const char		*device = handle->opt.device;
 	int			is_any_device = (strcmp(device, "any") == 0);
 	int			sock_fd = -1, arptype;
 #ifdef HAVE_PACKET_AUXDATA
@@ -3148,7 +3323,7 @@
 #endif
 	int			err = 0;
 	struct packet_mreq	mr;
-#ifdef SO_BPF_EXTENSIONS
+#if defined(SO_BPF_EXTENSIONS) && defined(SKF_AD_VLAN_TAG_PRESENT)
 	int			bpf_extensions;
 	socklen_t		len = sizeof(bpf_extensions);
 #endif
@@ -3172,7 +3347,7 @@
 			return 0;
 		}
 
-		snprintf(handle->errbuf, PCAP_ERRBUF_SIZE, "socket: %s",
+		pcap_snprintf(handle->errbuf, PCAP_ERRBUF_SIZE, "socket: %s",
 			 pcap_strerror(errno) );
 		if (errno == EPERM || errno == EACCES) {
 			/*
@@ -3274,14 +3449,14 @@
 			 * kernels) - reopen in cooked mode.
 			 */
 			if (close(sock_fd) == -1) {
-				snprintf(handle->errbuf, PCAP_ERRBUF_SIZE,
+				pcap_snprintf(handle->errbuf, PCAP_ERRBUF_SIZE,
 					 "close: %s", pcap_strerror(errno));
 				return PCAP_ERROR;
 			}
 			sock_fd = socket(PF_PACKET, SOCK_DGRAM,
 			    htons(ETH_P_ALL));
 			if (sock_fd == -1) {
-				snprintf(handle->errbuf, PCAP_ERRBUF_SIZE,
+				pcap_snprintf(handle->errbuf, PCAP_ERRBUF_SIZE,
 				    "socket: %s", pcap_strerror(errno));
 				if (errno == EPERM || errno == EACCES) {
 					/*
@@ -3316,7 +3491,7 @@
 				 * update "map_arphrd_to_dlt()"
 				 * to handle the new type.
 				 */
-				snprintf(handle->errbuf, PCAP_ERRBUF_SIZE,
+				pcap_snprintf(handle->errbuf, PCAP_ERRBUF_SIZE,
 					"arptype %d not "
 					"supported by libpcap - "
 					"falling back to cooked "
@@ -3406,7 +3581,7 @@
 		mr.mr_type    = PACKET_MR_PROMISC;
 		if (setsockopt(sock_fd, SOL_PACKET, PACKET_ADD_MEMBERSHIP,
 		    &mr, sizeof(mr)) == -1) {
-			snprintf(handle->errbuf, PCAP_ERRBUF_SIZE,
+			pcap_snprintf(handle->errbuf, PCAP_ERRBUF_SIZE,
 				"setsockopt: %s", pcap_strerror(errno));
 			close(sock_fd);
 			return PCAP_ERROR;
@@ -3419,7 +3594,7 @@
 	val = 1;
 	if (setsockopt(sock_fd, SOL_PACKET, PACKET_AUXDATA, &val,
 		       sizeof(val)) == -1 && errno != ENOPROTOOPT) {
-		snprintf(handle->errbuf, PCAP_ERRBUF_SIZE,
+		pcap_snprintf(handle->errbuf, PCAP_ERRBUF_SIZE,
 			 "setsockopt: %s", pcap_strerror(errno));
 		close(sock_fd);
 		return PCAP_ERROR;
@@ -3449,15 +3624,24 @@
 
 	/*
 	 * Set the offset at which to insert VLAN tags.
+	 * That should be the offset of the type field.
 	 */
 	switch (handle->linktype) {
 
 	case DLT_EN10MB:
+		/*
+		 * The type field is after the destination and source
+		 * MAC address.
+		 */
 		handlep->vlan_offset = 2 * ETH_ALEN;
 		break;
 
 	case DLT_LINUX_SLL:
-		handlep->vlan_offset = 14;
+		/*
+		 * The type field is in the last 2 bytes of the
+		 * DLT_LINUX_SLL header.
+		 */
+		handlep->vlan_offset = SLL_HDR_LEN - 2;
 		break;
 
 	default:
@@ -3470,7 +3654,7 @@
 		int nsec_tstamps = 1;
 
 		if (setsockopt(sock_fd, SOL_SOCKET, SO_TIMESTAMPNS, &nsec_tstamps, sizeof(nsec_tstamps)) < 0) {
-			snprintf(handle->errbuf, PCAP_ERRBUF_SIZE, "setsockopt: unable to set SO_TIMESTAMPNS");
+			pcap_snprintf(handle->errbuf, PCAP_ERRBUF_SIZE, "setsockopt: unable to set SO_TIMESTAMPNS");
 			close(sock_fd);
 			return PCAP_ERROR;
 		}
@@ -3482,7 +3666,7 @@
 	 */
 	handle->fd = sock_fd;
 
-#ifdef SO_BPF_EXTENSIONS
+#if defined(SO_BPF_EXTENSIONS) && defined(SKF_AD_VLAN_TAG_PRESENT)
 	/*
 	 * Can we generate special code for VLAN checks?
 	 * (XXX - what if we need the special code but it's not supported
@@ -3497,7 +3681,7 @@
 			handle->bpf_codegen_flags |= BPF_SPECIAL_VLAN_HANDLING;
 		}
 	}
-#endif /* SO_BPF_EXTENSIONS */
+#endif /* defined(SO_BPF_EXTENSIONS) && defined(SKF_AD_VLAN_TAG_PRESENT) */
 
 	return 1;
 #else /* HAVE_PF_PACKET_SOCKETS */
@@ -3533,7 +3717,7 @@
 	 */
 	handlep->oneshot_buffer = malloc(handle->snapshot);
 	if (handlep->oneshot_buffer == NULL) {
-		snprintf(handle->errbuf, PCAP_ERRBUF_SIZE,
+		pcap_snprintf(handle->errbuf, PCAP_ERRBUF_SIZE,
 			 "can't allocate oneshot buffer: %s",
 			 pcap_strerror(errno));
 		*status = PCAP_ERROR;
@@ -3638,7 +3822,7 @@
 			return 1;	/* no */
 
 		/* Failed to even find out; this is a fatal error. */
-		snprintf(handle->errbuf, PCAP_ERRBUF_SIZE,
+		pcap_snprintf(handle->errbuf, PCAP_ERRBUF_SIZE,
 			"can't get %s header len on packet socket: %s",
 			version_str,
 			pcap_strerror(errno));
@@ -3649,7 +3833,7 @@
 	val = version;
 	if (setsockopt(handle->fd, SOL_PACKET, PACKET_VERSION, &val,
 			   sizeof(val)) < 0) {
-		snprintf(handle->errbuf, PCAP_ERRBUF_SIZE,
+		pcap_snprintf(handle->errbuf, PCAP_ERRBUF_SIZE,
 			"can't activate %s on packet socket: %s",
 			version_str,
 			pcap_strerror(errno));
@@ -3661,7 +3845,7 @@
 	val = VLAN_TAG_LEN;
 	if (setsockopt(handle->fd, SOL_PACKET, PACKET_RESERVE, &val,
 			   sizeof(val)) < 0) {
-		snprintf(handle->errbuf, PCAP_ERRBUF_SIZE,
+		pcap_snprintf(handle->errbuf, PCAP_ERRBUF_SIZE,
 			"can't set up reserve on packet socket: %s",
 			pcap_strerror(errno));
 		return -1;
@@ -3793,7 +3977,7 @@
 			/*
 			 * Failed.
 			 */
-			snprintf(handle->errbuf, PCAP_ERRBUF_SIZE,
+			pcap_snprintf(handle->errbuf, PCAP_ERRBUF_SIZE,
 			    "uname failed: %s", pcap_strerror(errno));
 			return -1;
 		}
@@ -3899,14 +4083,14 @@
 				return -1;
 			}
 			if (!offload) {
-				mtu = iface_get_mtu(handle->fd, handle->opt.source,
+				mtu = iface_get_mtu(handle->fd, handle->opt.device,
 				    handle->errbuf);
 				if (mtu == -1) {
 					*status = PCAP_ERROR;
 					return -1;
 				}
-				if (frame_size > mtu + 18)
-					frame_size = mtu + 18;
+				if (frame_size > (unsigned int)mtu + 18)
+					frame_size = (unsigned int)mtu + 18;
 			}
 		}
 
@@ -3916,7 +4100,7 @@
 		len = sizeof(sk_type);
 		if (getsockopt(handle->fd, SOL_SOCKET, SO_TYPE, &sk_type,
 		    &len) < 0) {
-			snprintf(handle->errbuf, PCAP_ERRBUF_SIZE,
+			pcap_snprintf(handle->errbuf, PCAP_ERRBUF_SIZE,
 			    "getsockopt: %s", pcap_strerror(errno));
 			*status = PCAP_ERROR;
 			return -1;
@@ -3931,7 +4115,7 @@
 				 * PACKET_RESERVE", in which case we fall back
 				 * as best we can.
 				 */
-				snprintf(handle->errbuf, PCAP_ERRBUF_SIZE,
+				pcap_snprintf(handle->errbuf, PCAP_ERRBUF_SIZE,
 				    "getsockopt: %s", pcap_strerror(errno));
 				*status = PCAP_ERROR;
 				return -1;
@@ -3987,7 +4171,7 @@
 		break;
 #endif
 	default:
-		snprintf(handle->errbuf, PCAP_ERRBUF_SIZE,
+		pcap_snprintf(handle->errbuf, PCAP_ERRBUF_SIZE,
 		    "Internal error: unknown TPACKET_ value %u",
 		    handlep->tp_version);
 		*status = PCAP_ERROR;
@@ -4040,7 +4224,7 @@
 		hwconfig.rx_filter = HWTSTAMP_FILTER_ALL;
 
 		memset(&ifr, 0, sizeof(ifr));
-		strlcpy(ifr.ifr_name, handle->opt.source, sizeof(ifr.ifr_name));
+		strlcpy(ifr.ifr_name, handle->opt.device, sizeof(ifr.ifr_name));
 		ifr.ifr_data = (void *)&hwconfig;
 
 		if (ioctl(handle->fd, SIOCSHWTSTAMP, &ifr) < 0) {
@@ -4058,18 +4242,26 @@
 				return -1;
 
 			case EOPNOTSUPP:
+			case ERANGE:
 				/*
 				 * Treat this as a warning, as the
 				 * only way to fix the warning is to
 				 * get an adapter that supports hardware
-				 * time stamps.  We'll just fall back
-				 * on the standard host time stamps.
+				 * time stamps for *all* packets.
+				 * (ERANGE means "we support hardware
+				 * time stamps, but for packets matching
+				 * that particular filter", so it means
+				 * "we don't support hardware time stamps
+				 * for all incoming packets" here.)
+				 *
+				 * We'll just fall back on the standard
+				 * host time stamps.
 				 */
 				*status = PCAP_WARNING_TSTAMP_TYPE_NOTSUP;
 				break;
 
 			default:
-				snprintf(handle->errbuf, PCAP_ERRBUF_SIZE,
+				pcap_snprintf(handle->errbuf, PCAP_ERRBUF_SIZE,
 					"SIOCSHWTSTAMP failed: %s",
 					pcap_strerror(errno));
 				*status = PCAP_ERROR;
@@ -4097,7 +4289,7 @@
 			}
 			if (setsockopt(handle->fd, SOL_PACKET, PACKET_TIMESTAMP,
 				(void *)&timesource, sizeof(timesource))) {
-				snprintf(handle->errbuf, PCAP_ERRBUF_SIZE,
+				pcap_snprintf(handle->errbuf, PCAP_ERRBUF_SIZE,
 					"can't set PACKET_TIMESTAMP: %s",
 					pcap_strerror(errno));
 				*status = PCAP_ERROR;
@@ -4147,7 +4339,7 @@
 			 */
 			return 0;
 		}
-		snprintf(handle->errbuf, PCAP_ERRBUF_SIZE,
+		pcap_snprintf(handle->errbuf, PCAP_ERRBUF_SIZE,
 		    "can't create rx ring on packet socket: %s",
 		    pcap_strerror(errno));
 		*status = PCAP_ERROR;
@@ -4159,7 +4351,7 @@
 	handlep->mmapbuf = mmap(0, handlep->mmapbuflen,
 	    PROT_READ|PROT_WRITE, MAP_SHARED, handle->fd, 0);
 	if (handlep->mmapbuf == MAP_FAILED) {
-		snprintf(handle->errbuf, PCAP_ERRBUF_SIZE,
+		pcap_snprintf(handle->errbuf, PCAP_ERRBUF_SIZE,
 		    "can't mmap rx ring: %s", pcap_strerror(errno));
 
 		/* clear the allocated ring on error*/
@@ -4172,7 +4364,7 @@
 	handle->cc = req.tp_frame_nr;
 	handle->buffer = malloc(handle->cc * sizeof(union thdr *));
 	if (!handle->buffer) {
-		snprintf(handle->errbuf, PCAP_ERRBUF_SIZE,
+		pcap_snprintf(handle->errbuf, PCAP_ERRBUF_SIZE,
 		    "can't allocate ring of frame headers: %s",
 		    pcap_strerror(errno));
 
@@ -4186,7 +4378,7 @@
 	for (i=0; i<req.tp_block_nr; ++i) {
 		void *base = &handlep->mmapbuf[i*req.tp_block_size];
 		for (j=0; j<frames_per_block; ++j, ++handle->offset) {
-			RING_GET_FRAME(handle) = base;
+			RING_GET_CURRENT_FRAME(handle) = base;
 			base += req.tp_frame_size;
 		}
 	}
@@ -4299,156 +4491,131 @@
 			handlep->timeout = ~handlep->timeout;
 		}
 	}
+	/* Update the timeout to use in poll(). */
+	set_poll_timeout(handlep);
 	return 0;
 }
 
-static inline union thdr *
-pcap_get_ring_frame(pcap_t *handle, int status)
+/*
+ * Get the status field of the ring buffer frame at a specified offset.
+ */
+static inline int
+pcap_get_ring_frame_status(pcap_t *handle, int offset)
 {
 	struct pcap_linux *handlep = handle->priv;
 	union thdr h;
 
-	h.raw = RING_GET_FRAME(handle);
+	h.raw = RING_GET_FRAME_AT(handle, offset);
 	switch (handlep->tp_version) {
 	case TPACKET_V1:
-		if (status != (h.h1->tp_status ? TP_STATUS_USER :
-						TP_STATUS_KERNEL))
-			return NULL;
+		return (h.h1->tp_status);
 		break;
 	case TPACKET_V1_64:
-		if (status != (h.h1_64->tp_status ? TP_STATUS_USER :
-						TP_STATUS_KERNEL))
-			return NULL;
+		return (h.h1_64->tp_status);
 		break;
 #ifdef HAVE_TPACKET2
 	case TPACKET_V2:
-		if (status != (h.h2->tp_status ? TP_STATUS_USER :
-						TP_STATUS_KERNEL))
-			return NULL;
+		return (h.h2->tp_status);
 		break;
 #endif
 #ifdef HAVE_TPACKET3
 	case TPACKET_V3:
-		if (status != (h.h3->hdr.bh1.block_status ? TP_STATUS_USER :
-						TP_STATUS_KERNEL))
-			return NULL;
+		return (h.h3->hdr.bh1.block_status);
 		break;
 #endif
 	}
-	return h.raw;
+	/* This should not happen. */
+	return 0;
 }
 
 #ifndef POLLRDHUP
 #define POLLRDHUP 0
 #endif
 
-/* wait for frames availability.*/
+/*
+ * Block waiting for frames to be available.
+ */
 static int pcap_wait_for_frames_mmap(pcap_t *handle)
 {
-	if (!pcap_get_ring_frame(handle, TP_STATUS_USER)) {
-		struct pcap_linux *handlep = handle->priv;
-		int timeout;
-		char c;
-		struct pollfd pollinfo;
-		int ret;
+	struct pcap_linux *handlep = handle->priv;
+	char c;
+	struct pollfd pollinfo;
+	int ret;
 
-		pollinfo.fd = handle->fd;
-		pollinfo.events = POLLIN;
+	pollinfo.fd = handle->fd;
+	pollinfo.events = POLLIN;
 
-		if (handlep->timeout == 0) {
-#ifdef HAVE_TPACKET3
+	do {
+		/*
+		 * Yes, we do this even in non-blocking mode, as it's
+		 * the only way to get error indications from a
+		 * tpacket socket.
+		 *
+		 * The timeout is 0 in non-blocking mode, so poll()
+		 * returns immediately.
+		 */
+		ret = poll(&pollinfo, 1, handlep->poll_timeout);
+		if (ret < 0 && errno != EINTR) {
+			pcap_snprintf(handle->errbuf, PCAP_ERRBUF_SIZE,
+				"can't poll on packet socket: %s",
+				pcap_strerror(errno));
+			return PCAP_ERROR;
+		} else if (ret > 0 &&
+			(pollinfo.revents & (POLLHUP|POLLRDHUP|POLLERR|POLLNVAL))) {
 			/*
-			 * XXX - due to a set of (mis)features in the
-			 * TPACKET_V3 kernel code, blocking forever with
-			 * a TPACKET_V3 socket can, if few packets
-			 * are arriving and passing the socket filter,
-			 * cause most packets to be dropped.  See
-			 * libpcap issue #335 for the full painful
-			 * story.  The workaround is to have poll()
-			 * time out very quickly, so we grab the
-			 * frames handed to us, and return them to
-			 * the kernel, ASAP.
-			 *
-			 * If those issues are ever fixed, we might
-			 * want to check the kernel version and block
-			 * forever with TPACKET_V3 if we're running
-			 * with a kernel that has the fix.
+			 * There's some indication other than
+			 * "you can read on this descriptor" on
+			 * the descriptor.
 			 */
-			if (handlep->tp_version == TPACKET_V3)
-				timeout = 1;	/* don't block for very long */
-			else
-#endif
-				timeout = -1;	/* block forever */
-		} else if (handlep->timeout > 0)
-			timeout = handlep->timeout;	/* block for that amount of time */
-		else
-			timeout = 0;	/* non-blocking mode - poll to pick up errors */
-		do {
-			ret = poll(&pollinfo, 1, timeout);
-			if (ret < 0 && errno != EINTR) {
-				snprintf(handle->errbuf, PCAP_ERRBUF_SIZE,
-					"can't poll on packet socket: %s",
-					pcap_strerror(errno));
+			if (pollinfo.revents & (POLLHUP | POLLRDHUP)) {
+				pcap_snprintf(handle->errbuf,
+					PCAP_ERRBUF_SIZE,
+					"Hangup on packet socket");
 				return PCAP_ERROR;
-			} else if (ret > 0 &&
-				(pollinfo.revents & (POLLHUP|POLLRDHUP|POLLERR|POLLNVAL))) {
+			}
+			if (pollinfo.revents & POLLERR) {
 				/*
-				 * There's some indication other than
-				 * "you can read on this descriptor" on
-				 * the descriptor.
+				 * A recv() will give us the actual error code.
+				 *
+				 * XXX - make the socket non-blocking?
 				 */
-				if (pollinfo.revents & (POLLHUP | POLLRDHUP)) {
-					snprintf(handle->errbuf,
-						PCAP_ERRBUF_SIZE,
-						"Hangup on packet socket");
-					return PCAP_ERROR;
-				}
-				if (pollinfo.revents & POLLERR) {
+				if (recv(handle->fd, &c, sizeof c,
+					MSG_PEEK) != -1)
+					continue;	/* what, no error? */
+				if (errno == ENETDOWN) {
 					/*
-					 * A recv() will give us the
-					 * actual error code.
+					 * The device on which we're
+					 * capturing went away.
 					 *
-					 * XXX - make the socket non-blocking?
+					 * XXX - we should really return
+					 * PCAP_ERROR_IFACE_NOT_UP, but
+					 * pcap_dispatch() etc. aren't
+					 * defined to return that.
 					 */
-					if (recv(handle->fd, &c, sizeof c,
-						MSG_PEEK) != -1)
-						continue;	/* what, no error? */
-					if (errno == ENETDOWN) {
-						/*
-						 * The device on which we're
-						 * capturing went away.
-						 *
-						 * XXX - we should really return
-						 * PCAP_ERROR_IFACE_NOT_UP,
-						 * but pcap_dispatch() etc.
-						 * aren't defined to return
-						 * that.
-						 */
-						snprintf(handle->errbuf,
-							PCAP_ERRBUF_SIZE,
-							"The interface went down");
-					} else {
-						snprintf(handle->errbuf,
-							PCAP_ERRBUF_SIZE,
-							"Error condition on packet socket: %s",
-							strerror(errno));
-					}
-					return PCAP_ERROR;
-				}
-				if (pollinfo.revents & POLLNVAL) {
-					snprintf(handle->errbuf,
+					pcap_snprintf(handle->errbuf,
 						PCAP_ERRBUF_SIZE,
-						"Invalid polling request on packet socket");
-					return PCAP_ERROR;
+						"The interface went down");
+				} else {
+					pcap_snprintf(handle->errbuf,
+						PCAP_ERRBUF_SIZE,
+						"Error condition on packet socket: %s",
+						strerror(errno));
 				}
+				return PCAP_ERROR;
 			}
-			/* check for break loop condition on interrupted syscall*/
-			if (handle->break_loop) {
-				handle->break_loop = 0;
-				return PCAP_ERROR_BREAK;
+			if (pollinfo.revents & POLLNVAL) {
+				pcap_snprintf(handle->errbuf,
+					PCAP_ERRBUF_SIZE,
+					"Invalid polling request on packet socket");
+				return PCAP_ERROR;
 			}
-		} while (ret < 0);
-	}
+		}
+		/* check for break loop condition on interrupted syscall*/
+		if (handle->break_loop) {
+			handle->break_loop = 0;
+			return PCAP_ERROR_BREAK;
+		}
+	} while (ret < 0);
 	return 0;
 }
 
@@ -4474,7 +4641,7 @@
 
 	/* perform sanity check on internal offset. */
 	if (tp_mac + tp_snaplen > handle->bufsize) {
-		snprintf(handle->errbuf, PCAP_ERRBUF_SIZE,
+		pcap_snprintf(handle->errbuf, PCAP_ERRBUF_SIZE,
 			"corrupted frame on kernel ring mac "
 			"offset %u + caplen %u > frame len %d",
 			tp_mac, tp_snaplen, handle->bufsize);
@@ -4516,7 +4683,7 @@
 		if (bp < (u_char *)frame +
 				   TPACKET_ALIGN(handlep->tp_hdrlen) +
 				   sizeof(struct sockaddr_ll)) {
-			snprintf(handle->errbuf, PCAP_ERRBUF_SIZE,
+			pcap_snprintf(handle->errbuf, PCAP_ERRBUF_SIZE,
 				"cooked-mode frame doesn't have room for sll header");
 			return -1;
 		}
@@ -4567,13 +4734,24 @@
 	{
 		struct vlan_tag *tag;
 
+		/*
+		 * Move everything in the header, except the type field,
+		 * down VLAN_TAG_LEN bytes, to allow us to insert the
+		 * VLAN tag between that stuff and the type field.
+		 */
 		bp -= VLAN_TAG_LEN;
 		memmove(bp, bp + VLAN_TAG_LEN, handlep->vlan_offset);
 
+		/*
+		 * Now insert the tag.
+		 */
 		tag = (struct vlan_tag *)(bp + handlep->vlan_offset);
 		tag->vlan_tpid = htons(tp_vlan_tpid);
 		tag->vlan_tci = htons(tp_vlan_tci);
 
+		/*
+		 * Add the tag to the packet lengths.
+		 */
 		pcaphdr.caplen += VLAN_TAG_LEN;
 		pcaphdr.len += VLAN_TAG_LEN;
 	}
@@ -4588,7 +4766,7 @@
 	 * Trim the snapshot length to be no longer than the
 	 * specified snapshot length.
 	 */
-	if (pcaphdr.caplen > handle->snapshot)
+	if (pcaphdr.caplen > (bpf_u_int32)handle->snapshot)
 		pcaphdr.caplen = handle->snapshot;
 
 	/* pass the packet to the user */
@@ -4602,22 +4780,32 @@
 		u_char *user)
 {
 	struct pcap_linux *handlep = handle->priv;
+	union thdr h;
 	int pkts = 0;
 	int ret;
 
 	/* wait for frames availability.*/
-	ret = pcap_wait_for_frames_mmap(handle);
-	if (ret) {
-		return ret;
+	h.raw = RING_GET_CURRENT_FRAME(handle);
+	if (h.h1->tp_status == TP_STATUS_KERNEL) {
+		/*
+		 * The current frame is owned by the kernel; wait for
+		 * a frame to be handed to us.
+		 */
+		ret = pcap_wait_for_frames_mmap(handle);
+		if (ret) {
+			return ret;
+		}
 	}
 
 	/* non-positive values of max_packets are used to require all
 	 * packets currently available in the ring */
 	while ((pkts < max_packets) || PACKET_COUNT_IS_UNLIMITED(max_packets)) {
-		union thdr h;
-
-		h.raw = pcap_get_ring_frame(handle, TP_STATUS_USER);
-		if (!h.raw)
+		/*
+		 * Get the current ring buffer frame, and break if
+		 * it's still owned by the kernel.
+		 */
+		h.raw = RING_GET_CURRENT_FRAME(handle);
+		if (h.h1->tp_status == TP_STATUS_KERNEL)
 			break;
 
 		ret = pcap_handle_packet_mmap(
@@ -4676,22 +4864,32 @@
 		u_char *user)
 {
 	struct pcap_linux *handlep = handle->priv;
+	union thdr h;
 	int pkts = 0;
 	int ret;
 
 	/* wait for frames availability.*/
-	ret = pcap_wait_for_frames_mmap(handle);
-	if (ret) {
-		return ret;
+	h.raw = RING_GET_CURRENT_FRAME(handle);
+	if (h.h1_64->tp_status == TP_STATUS_KERNEL) {
+		/*
+		 * The current frame is owned by the kernel; wait for
+		 * a frame to be handed to us.
+		 */
+		ret = pcap_wait_for_frames_mmap(handle);
+		if (ret) {
+			return ret;
+		}
 	}
 
 	/* non-positive values of max_packets are used to require all
 	 * packets currently available in the ring */
 	while ((pkts < max_packets) || PACKET_COUNT_IS_UNLIMITED(max_packets)) {
-		union thdr h;
-
-		h.raw = pcap_get_ring_frame(handle, TP_STATUS_USER);
-		if (!h.raw)
+		/*
+		 * Get the current ring buffer frame, and break if
+		 * it's still owned by the kernel.
+		 */
+		h.raw = RING_GET_CURRENT_FRAME(handle);
+		if (h.h1_64->tp_status == TP_STATUS_KERNEL)
 			break;
 
 		ret = pcap_handle_packet_mmap(
@@ -4751,22 +4949,32 @@
 		u_char *user)
 {
 	struct pcap_linux *handlep = handle->priv;
+	union thdr h;
 	int pkts = 0;
 	int ret;
 
 	/* wait for frames availability.*/
-	ret = pcap_wait_for_frames_mmap(handle);
-	if (ret) {
-		return ret;
+	h.raw = RING_GET_CURRENT_FRAME(handle);
+	if (h.h2->tp_status == TP_STATUS_KERNEL) {
+		/*
+		 * The current frame is owned by the kernel; wait for
+		 * a frame to be handed to us.
+		 */
+		ret = pcap_wait_for_frames_mmap(handle);
+		if (ret) {
+			return ret;
+		}
 	}
 
 	/* non-positive values of max_packets are used to require all
 	 * packets currently available in the ring */
 	while ((pkts < max_packets) || PACKET_COUNT_IS_UNLIMITED(max_packets)) {
-		union thdr h;
-
-		h.raw = pcap_get_ring_frame(handle, TP_STATUS_USER);
-		if (!h.raw)
+		/*
+		 * Get the current ring buffer frame, and break if
+		 * it's still owned by the kernel.
+		 */
+		h.raw = RING_GET_CURRENT_FRAME(handle);
+		if (h.h2->tp_status == TP_STATUS_KERNEL)
 			break;
 
 		ret = pcap_handle_packet_mmap(
@@ -4838,13 +5046,20 @@
 again:
 	if (handlep->current_packet == NULL) {
 		/* wait for frames availability.*/
-		ret = pcap_wait_for_frames_mmap(handle);
-		if (ret) {
-			return ret;
+		h.raw = RING_GET_CURRENT_FRAME(handle);
+		if (h.h3->hdr.bh1.block_status == TP_STATUS_KERNEL) {
+			/*
+			 * The current frame is owned by the kernel; wait
+			 * for a frame to be handed to us.
+			 */
+			ret = pcap_wait_for_frames_mmap(handle);
+			if (ret) {
+				return ret;
+			}
 		}
 	}
-	h.raw = pcap_get_ring_frame(handle, TP_STATUS_USER);
-	if (!h.raw) {
+	h.raw = RING_GET_CURRENT_FRAME(handle);
+	if (h.h3->hdr.bh1.block_status == TP_STATUS_KERNEL) {
 		if (pkts == 0 && handlep->timeout == 0) {
 			/* Block until we see a packet. */
 			goto again;
@@ -4855,21 +5070,30 @@
 	/* non-positive values of max_packets are used to require all
 	 * packets currently available in the ring */
 	while ((pkts < max_packets) || PACKET_COUNT_IS_UNLIMITED(max_packets)) {
+		int packets_to_read;
+
 		if (handlep->current_packet == NULL) {
-			h.raw = pcap_get_ring_frame(handle, TP_STATUS_USER);
-			if (!h.raw)
+			h.raw = RING_GET_CURRENT_FRAME(handle);
+			if (h.h3->hdr.bh1.block_status == TP_STATUS_KERNEL)
 				break;
 
 			handlep->current_packet = h.raw + h.h3->hdr.bh1.offset_to_first_pkt;
 			handlep->packets_left = h.h3->hdr.bh1.num_pkts;
 		}
-		int packets_to_read = handlep->packets_left;
+		packets_to_read = handlep->packets_left;
 
-		if (!PACKET_COUNT_IS_UNLIMITED(max_packets) && packets_to_read > max_packets) {
-			packets_to_read = max_packets;
+		if (!PACKET_COUNT_IS_UNLIMITED(max_packets) &&
+		    packets_to_read > (max_packets - pkts)) {
+			/*
+			 * We've been given a maximum number of packets
+			 * to process, and there are more packets in
+			 * this buffer than that.  Only process enough
+			 * of them to get us up to that maximum.
+			 */
+			packets_to_read = max_packets - pkts;
 		}
 
-		while(packets_to_read--) {
+		while (packets_to_read-- && !handle->break_loop) {
 			struct tpacket3_hdr* tp3_hdr = (struct tpacket3_hdr*) handlep->current_packet;
 			ret = pcap_handle_packet_mmap(
 					handle,
@@ -4974,12 +5198,12 @@
 	 * walk the ring backward and count the free blocks.
 	 */
 	offset = handle->offset;
-	if (--handle->offset < 0)
-		handle->offset = handle->cc - 1;
+	if (--offset < 0)
+		offset = handle->cc - 1;
 	for (n=0; n < handle->cc; ++n) {
-		if (--handle->offset < 0)
-			handle->offset = handle->cc - 1;
-		if (!pcap_get_ring_frame(handle, TP_STATUS_KERNEL))
+		if (--offset < 0)
+			offset = handle->cc - 1;
+		if (pcap_get_ring_frame_status(handle, offset) != TP_STATUS_KERNEL)
 			break;
 	}
 
@@ -5000,9 +5224,6 @@
 	if (n != 0)
 		n--;
 
-	/* be careful to not change current ring position */
-	handle->offset = offset;
-
 	/*
 	 * Set the count of blocks worth of packets to filter
 	 * in userland to the total number of blocks in the
@@ -5036,7 +5257,7 @@
 	strlcpy(ifr.ifr_name, device, sizeof(ifr.ifr_name));
 
 	if (ioctl(fd, SIOCGIFINDEX, &ifr) == -1) {
-		snprintf(ebuf, PCAP_ERRBUF_SIZE,
+		pcap_snprintf(ebuf, PCAP_ERRBUF_SIZE,
 			 "SIOCGIFINDEX: %s", pcap_strerror(errno));
 		return -1;
 	}
@@ -5072,7 +5293,7 @@
 			 */
 			return PCAP_ERROR_IFACE_NOT_UP;
 		} else {
-			snprintf(ebuf, PCAP_ERRBUF_SIZE,
+			pcap_snprintf(ebuf, PCAP_ERRBUF_SIZE,
 				 "bind: %s", pcap_strerror(errno));
 			return PCAP_ERROR;
 		}
@@ -5081,7 +5302,7 @@
 	/* Any pending errors, e.g., network is down? */
 
 	if (getsockopt(fd, SOL_SOCKET, SO_ERROR, &err, &errlen) == -1) {
-		snprintf(ebuf, PCAP_ERRBUF_SIZE,
+		pcap_snprintf(ebuf, PCAP_ERRBUF_SIZE,
 			"getsockopt: %s", pcap_strerror(errno));
 		return 0;
 	}
@@ -5096,7 +5317,7 @@
 		 */
 		return PCAP_ERROR_IFACE_NOT_UP;
 	} else if (err > 0) {
-		snprintf(ebuf, PCAP_ERRBUF_SIZE,
+		pcap_snprintf(ebuf, PCAP_ERRBUF_SIZE,
 			"bind: %s", pcap_strerror(err));
 		return 0;
 	}
@@ -5122,7 +5343,7 @@
 	    sizeof ireq.ifr_ifrn.ifrn_name);
 	if (ioctl(sock_fd, SIOCGIWNAME, &ireq) >= 0)
 		return 1;	/* yes */
-	snprintf(ebuf, PCAP_ERRBUF_SIZE,
+	pcap_snprintf(ebuf, PCAP_ERRBUF_SIZE,
 	    "%s: SIOCGIWNAME: %s", device, pcap_strerror(errno));
 	if (errno == ENODEV)
 		return PCAP_ERROR_NO_SUCH_DEVICE;
@@ -5261,7 +5482,7 @@
 	ireq.u.data.length = 0;
 	ireq.u.data.flags = 0;
 	if (ioctl(sock_fd, SIOCGIWPRIV, &ireq) != -1) {
-		snprintf(handle->errbuf, PCAP_ERRBUF_SIZE,
+		pcap_snprintf(handle->errbuf, PCAP_ERRBUF_SIZE,
 		    "%s: SIOCGIWPRIV with a zero-length buffer didn't fail!",
 		    device);
 		return PCAP_ERROR;
@@ -5274,7 +5495,7 @@
 			/*
 			 * Failed.
 			 */
-			snprintf(handle->errbuf, PCAP_ERRBUF_SIZE,
+			pcap_snprintf(handle->errbuf, PCAP_ERRBUF_SIZE,
 			    "%s: SIOCGIWPRIV: %s", device,
 			    pcap_strerror(errno));
 			return PCAP_ERROR;
@@ -5285,13 +5506,13 @@
 		 */
 		priv = malloc(ireq.u.data.length * sizeof (struct iw_priv_args));
 		if (priv == NULL) {
-			snprintf(handle->errbuf, PCAP_ERRBUF_SIZE,
+			pcap_snprintf(handle->errbuf, PCAP_ERRBUF_SIZE,
 			    "malloc: %s", pcap_strerror(errno));
 			return PCAP_ERROR;
 		}
 		ireq.u.data.pointer = (void *)priv;
 		if (ioctl(sock_fd, SIOCGIWPRIV, &ireq) == -1) {
-			snprintf(handle->errbuf, PCAP_ERRBUF_SIZE,
+			pcap_snprintf(handle->errbuf, PCAP_ERRBUF_SIZE,
 			    "%s: SIOCGIWPRIV: %s", device,
 			    pcap_strerror(errno));
 			free(priv);
@@ -5547,7 +5768,7 @@
 	memset(&ifr, 0, sizeof(ifr));
 	strlcpy(ifr.ifr_name, device, sizeof(ifr.ifr_name));
 	if (ioctl(sock_fd, SIOCGIFFLAGS, &ifr) == -1) {
-		snprintf(handle->errbuf, PCAP_ERRBUF_SIZE,
+		pcap_snprintf(handle->errbuf, PCAP_ERRBUF_SIZE,
 		    "%s: Can't get flags: %s", device, strerror(errno));
 		return PCAP_ERROR;
 	}
@@ -5556,7 +5777,7 @@
 		oldflags = ifr.ifr_flags;
 		ifr.ifr_flags &= ~IFF_UP;
 		if (ioctl(sock_fd, SIOCSIFFLAGS, &ifr) == -1) {
-			snprintf(handle->errbuf, PCAP_ERRBUF_SIZE,
+			pcap_snprintf(handle->errbuf, PCAP_ERRBUF_SIZE,
 			    "%s: Can't set flags: %s", device, strerror(errno));
 			return PCAP_ERROR;
 		}
@@ -5575,7 +5796,7 @@
 		 */
 		ifr.ifr_flags = oldflags;
 		if (ioctl(sock_fd, SIOCSIFFLAGS, &ifr) == -1) {
-			snprintf(handle->errbuf, PCAP_ERRBUF_SIZE,
+			pcap_snprintf(handle->errbuf, PCAP_ERRBUF_SIZE,
 			    "%s: Can't set flags: %s", device, strerror(errno));
 			return PCAP_ERROR;
 		}
@@ -5659,7 +5880,7 @@
 		strlcpy(ireq.ifr_ifrn.ifrn_name, device,
 		    sizeof ireq.ifr_ifrn.ifrn_name);
 		if (ioctl(sock_fd, SIOCGIWFREQ, &ireq) == -1) {
-			snprintf(handle->errbuf, PCAP_ERRBUF_SIZE,
+			pcap_snprintf(handle->errbuf, PCAP_ERRBUF_SIZE,
 			    "%s: SIOCGIWFREQ: %s", device,
 			    pcap_strerror(errno));
 			return PCAP_ERROR;
@@ -5736,7 +5957,7 @@
 	if (oldflags != 0) {
 		ifr.ifr_flags = oldflags;
 		if (ioctl(sock_fd, SIOCSIFFLAGS, &ifr) == -1) {
-			snprintf(handle->errbuf, PCAP_ERRBUF_SIZE,
+			pcap_snprintf(handle->errbuf, PCAP_ERRBUF_SIZE,
 			    "%s: Can't set flags: %s", device, strerror(errno));
 
 			/*
@@ -5819,10 +6040,13 @@
 };
 #define NUM_SOF_TIMESTAMPING_TYPES	(sizeof sof_ts_type_map / sizeof sof_ts_type_map[0])
 
+/*
+ * Set the list of time stamping types to include all types.
+ */
 static void
-iface_set_default_ts_types(pcap_t *handle)
+iface_set_all_ts_types(pcap_t *handle)
 {
-	int i;
+	u_int i;
 
 	handle->tstamp_type_count = NUM_SOF_TIMESTAMPING_TYPES;
 	handle->tstamp_type_list = malloc(NUM_SOF_TIMESTAMPING_TYPES * sizeof(u_int));
@@ -5835,56 +6059,96 @@
  * Get a list of time stamping capabilities.
  */
 static int
-iface_ethtool_get_ts_info(pcap_t *handle, char *ebuf)
+iface_ethtool_get_ts_info(const char *device, pcap_t *handle, char *ebuf)
 {
 	int fd;
 	struct ifreq ifr;
 	struct ethtool_ts_info info;
 	int num_ts_types;
-	int i, j;
+	u_int i, j;
 
 	/*
-	 * This doesn't apply to the "any" device; you have to ask
-	 * specific devices for their capabilities, so just default
-	 * to saying we support all of them.
+	 * This doesn't apply to the "any" device; you can't say "turn on
+	 * hardware time stamping for all devices that exist now and arrange
+	 * that it be turned on for any device that appears in the future",
+	 * and not all devices even necessarily *support* hardware time
+	 * stamping, so don't report any time stamp types.
 	 */
-	if (strcmp(handle->opt.source, "any") == 0) {
-		iface_set_default_ts_types(handle);
+	if (strcmp(device, "any") == 0) {
+		handle->tstamp_type_list = NULL;
 		return 0;
 	}
 
 	/*
 	 * Create a socket from which to fetch time stamping capabilities.
 	 */
-	fd = socket(AF_INET, SOCK_DGRAM, 0);
+	fd = socket(PF_UNIX, SOCK_RAW, 0);
 	if (fd < 0) {
-		(void)snprintf(ebuf, PCAP_ERRBUF_SIZE,
+		(void)pcap_snprintf(ebuf, PCAP_ERRBUF_SIZE,
 		    "socket for SIOCETHTOOL(ETHTOOL_GET_TS_INFO): %s", pcap_strerror(errno));
 		return -1;
 	}
 
 	memset(&ifr, 0, sizeof(ifr));
-	strlcpy(ifr.ifr_name, handle->opt.source, sizeof(ifr.ifr_name));
+	strlcpy(ifr.ifr_name, device, sizeof(ifr.ifr_name));
 	memset(&info, 0, sizeof(info));
 	info.cmd = ETHTOOL_GET_TS_INFO;
 	ifr.ifr_data = (caddr_t)&info;
 	if (ioctl(fd, SIOCETHTOOL, &ifr) == -1) {
+		int save_errno = errno;
+
 		close(fd);
-		if (errno == EOPNOTSUPP || errno == EINVAL) {
+		switch (save_errno) {
+
+		case EOPNOTSUPP:
+		case EINVAL:
 			/*
-			 * OK, let's just return all the possible time
-			 * stamping types.
+			 * OK, this OS version or driver doesn't support
+			 * asking for the time stamping types, so let's
+			 * just return all the possible types.
 			 */
-			iface_set_default_ts_types(handle);
+			iface_set_all_ts_types(handle);
 			return 0;
+
+		case ENODEV:
+			/*
+			 * OK, no such device.
+			 * The user will find that out when they try to
+			 * activate the device; just return an empty
+			 * list of time stamp types.
+			 */
+			handle->tstamp_type_list = NULL;
+			return 0;
+
+		default:
+			/*
+			 * Other error.
+			 */
+			pcap_snprintf(ebuf, PCAP_ERRBUF_SIZE,
+			    "%s: SIOCETHTOOL(ETHTOOL_GET_TS_INFO) ioctl failed: %s", device,
+			    strerror(save_errno));
+			return -1;
 		}
-		snprintf(ebuf, PCAP_ERRBUF_SIZE,
-		    "%s: SIOCETHTOOL(ETHTOOL_GET_TS_INFO) ioctl failed: %s", handle->opt.source,
-		    strerror(errno));
-		return -1;
 	}
 	close(fd);
 
+	/*
+	 * Do we support hardware time stamping of *all* packets?
+	 */
+	if (!(info.rx_filters & (1 << HWTSTAMP_FILTER_ALL))) {
+		/*
+		 * No, so don't report any time stamp types.
+		 *
+		 * XXX - some devices either don't report
+		 * HWTSTAMP_FILTER_ALL when they do support it, or
+		 * report HWTSTAMP_FILTER_ALL but map it to only
+		 * time stamping a few PTP packets.  See
+		 * http://marc.info/?l=linux-netdev&m=146318183529571&w=2
+		 */
+		handle->tstamp_type_list = NULL;
+		return 0;
+	}
+
 	num_ts_types = 0;
 	for (i = 0; i < NUM_SOF_TIMESTAMPING_TYPES; i++) {
 		if (info.so_timestamping & sof_ts_type_map[i].soft_timestamping_val)
@@ -5906,13 +6170,25 @@
 }
 #else /* ETHTOOL_GET_TS_INFO */
 static int
-iface_ethtool_get_ts_info(pcap_t *handle, char *ebuf _U_)
+iface_ethtool_get_ts_info(const char *device, pcap_t *handle, char *ebuf _U_)
 {
 	/*
+	 * This doesn't apply to the "any" device; you can't say "turn on
+	 * hardware time stamping for all devices that exist now and arrange
+	 * that it be turned on for any device that appears in the future",
+	 * and not all devices even necessarily *support* hardware time
+	 * stamping, so don't report any time stamp types.
+	 */
+	if (strcmp(device, "any") == 0) {
+		handle->tstamp_type_list = NULL;
+		return 0;
+	}
+
+	/*
 	 * We don't have an ioctl to use to ask what's supported,
 	 * so say we support everything.
 	 */
-	iface_set_default_ts_types(handle);
+	iface_set_all_ts_types(handle);
 	return 0;
 }
 #endif /* ETHTOOL_GET_TS_INFO */
@@ -5936,7 +6212,7 @@
 	struct ethtool_value eval;
 
 	memset(&ifr, 0, sizeof(ifr));
-	strlcpy(ifr.ifr_name, handle->opt.source, sizeof(ifr.ifr_name));
+	strlcpy(ifr.ifr_name, handle->opt.device, sizeof(ifr.ifr_name));
 	eval.cmd = cmd;
 	eval.data = 0;
 	ifr.ifr_data = (caddr_t)&eval;
@@ -5950,8 +6226,8 @@
 			 */
 			return 0;
 		}
-		snprintf(handle->errbuf, PCAP_ERRBUF_SIZE,
-		    "%s: SIOCETHTOOL(%s) ioctl failed: %s", handle->opt.source,
+		pcap_snprintf(handle->errbuf, PCAP_ERRBUF_SIZE,
+		    "%s: SIOCETHTOOL(%s) ioctl failed: %s", handle->opt.device,
 		    cmdname, strerror(errno));
 		return -1;
 	}
@@ -6043,7 +6319,7 @@
 	struct pcap_linux *handlep = handle->priv;
 	int		arptype;
 	struct ifreq	ifr;
-	const char	*device = handle->opt.source;
+	const char	*device = handle->opt.device;
 	struct utsname	utsname;
 	int		mtu;
 
@@ -6051,7 +6327,7 @@
 
 	handle->fd = socket(PF_INET, SOCK_PACKET, htons(ETH_P_ALL));
 	if (handle->fd == -1) {
-		snprintf(handle->errbuf, PCAP_ERRBUF_SIZE,
+		pcap_snprintf(handle->errbuf, PCAP_ERRBUF_SIZE,
 			 "socket: %s", pcap_strerror(errno));
 		if (errno == EPERM || errno == EACCES) {
 			/*
@@ -6096,7 +6372,7 @@
 	 */
 	map_arphrd_to_dlt(handle, handle->fd, arptype, device, 0);
 	if (handle->linktype == -1) {
-		snprintf(handle->errbuf, PCAP_ERRBUF_SIZE,
+		pcap_snprintf(handle->errbuf, PCAP_ERRBUF_SIZE,
 			 "unknown arptype %d", arptype);
 		return PCAP_ERROR;
 	}
@@ -6107,7 +6383,7 @@
 		memset(&ifr, 0, sizeof(ifr));
 		strlcpy(ifr.ifr_name, device, sizeof(ifr.ifr_name));
 		if (ioctl(handle->fd, SIOCGIFFLAGS, &ifr) == -1) {
-			snprintf(handle->errbuf, PCAP_ERRBUF_SIZE,
+			pcap_snprintf(handle->errbuf, PCAP_ERRBUF_SIZE,
 				 "SIOCGIFFLAGS: %s", pcap_strerror(errno));
 			return PCAP_ERROR;
 		}
@@ -6135,7 +6411,7 @@
 
 			ifr.ifr_flags |= IFF_PROMISC;
 			if (ioctl(handle->fd, SIOCSIFFLAGS, &ifr) == -1) {
-			        snprintf(handle->errbuf, PCAP_ERRBUF_SIZE,
+			        pcap_snprintf(handle->errbuf, PCAP_ERRBUF_SIZE,
 					 "SIOCSIFFLAGS: %s",
 					 pcap_strerror(errno));
 				return PCAP_ERROR;
@@ -6204,8 +6480,8 @@
 		if (mtu == -1)
 			return PCAP_ERROR;
 		handle->bufsize = MAX_LINKHEADER_SIZE + mtu;
-		if (handle->bufsize < handle->snapshot)
-			handle->bufsize = handle->snapshot;
+		if (handle->bufsize < (u_int)handle->snapshot)
+			handle->bufsize = (u_int)handle->snapshot;
 	} else {
 		/*
 		 * This is a 2.2[.x] or later kernel.
@@ -6213,7 +6489,7 @@
 		 * We can safely pass "recvfrom()" a byte count
 		 * based on the snapshot length.
 		 */
-		handle->bufsize = handle->snapshot;
+		handle->bufsize = (u_int)handle->snapshot;
 	}
 
 	/*
@@ -6245,7 +6521,7 @@
 	memset(&saddr, 0, sizeof(saddr));
 	strlcpy(saddr.sa_data, device, sizeof(saddr.sa_data));
 	if (bind(fd, &saddr, sizeof(saddr)) == -1) {
-		snprintf(ebuf, PCAP_ERRBUF_SIZE,
+		pcap_snprintf(ebuf, PCAP_ERRBUF_SIZE,
 			 "bind: %s", pcap_strerror(errno));
 		return -1;
 	}
@@ -6253,13 +6529,13 @@
 	/* Any pending errors, e.g., network is down? */
 
 	if (getsockopt(fd, SOL_SOCKET, SO_ERROR, &err, &errlen) == -1) {
-		snprintf(ebuf, PCAP_ERRBUF_SIZE,
+		pcap_snprintf(ebuf, PCAP_ERRBUF_SIZE,
 			"getsockopt: %s", pcap_strerror(errno));
 		return -1;
 	}
 
 	if (err > 0) {
-		snprintf(ebuf, PCAP_ERRBUF_SIZE,
+		pcap_snprintf(ebuf, PCAP_ERRBUF_SIZE,
 			"bind: %s", pcap_strerror(err));
 		return -1;
 	}
@@ -6285,7 +6561,7 @@
 	strlcpy(ifr.ifr_name, device, sizeof(ifr.ifr_name));
 
 	if (ioctl(fd, SIOCGIFMTU, &ifr) == -1) {
-		snprintf(ebuf, PCAP_ERRBUF_SIZE,
+		pcap_snprintf(ebuf, PCAP_ERRBUF_SIZE,
 			 "SIOCGIFMTU: %s", pcap_strerror(errno));
 		return -1;
 	}
@@ -6305,7 +6581,7 @@
 	strlcpy(ifr.ifr_name, device, sizeof(ifr.ifr_name));
 
 	if (ioctl(fd, SIOCGIFHWADDR, &ifr) == -1) {
-		snprintf(ebuf, PCAP_ERRBUF_SIZE,
+		pcap_snprintf(ebuf, PCAP_ERRBUF_SIZE,
 			 "SIOCGIFHWADDR: %s", pcap_strerror(errno));
 		if (errno == ENODEV) {
 			/*
@@ -6338,7 +6614,7 @@
 	len = handle->fcode.bf_len;
 	f = (struct bpf_insn *)malloc(prog_size);
 	if (f == NULL) {
-		snprintf(handle->errbuf, PCAP_ERRBUF_SIZE,
+		pcap_snprintf(handle->errbuf, PCAP_ERRBUF_SIZE,
 			 "malloc: %s", pcap_strerror(errno));
 		return -1;
 	}
@@ -6515,13 +6791,13 @@
 		 */
 		save_mode = fcntl(handle->fd, F_GETFL, 0);
 		if (save_mode == -1) {
-			snprintf(handle->errbuf, PCAP_ERRBUF_SIZE,
+			pcap_snprintf(handle->errbuf, PCAP_ERRBUF_SIZE,
 			    "can't get FD flags when changing filter: %s",
 			    pcap_strerror(errno));
 			return -2;
 		}
 		if (fcntl(handle->fd, F_SETFL, save_mode | O_NONBLOCK) < 0) {
-			snprintf(handle->errbuf, PCAP_ERRBUF_SIZE,
+			pcap_snprintf(handle->errbuf, PCAP_ERRBUF_SIZE,
 			    "can't set nonblocking mode when changing filter: %s",
 			    pcap_strerror(errno));
 			return -2;
@@ -6538,13 +6814,13 @@
 			 */
 			(void)fcntl(handle->fd, F_SETFL, save_mode);
 			(void)reset_kernel_filter(handle);
-			snprintf(handle->errbuf, PCAP_ERRBUF_SIZE,
+			pcap_snprintf(handle->errbuf, PCAP_ERRBUF_SIZE,
 			    "recv failed when changing filter: %s",
 			    pcap_strerror(save_errno));
 			return -2;
 		}
 		if (fcntl(handle->fd, F_SETFL, save_mode) == -1) {
-			snprintf(handle->errbuf, PCAP_ERRBUF_SIZE,
+			pcap_snprintf(handle->errbuf, PCAP_ERRBUF_SIZE,
 			    "can't restore FD flags when changing filter: %s",
 			    pcap_strerror(save_errno));
 			return -2;
@@ -6575,7 +6851,7 @@
 		 * Report it as a fatal error.
 		 */
 		if (reset_kernel_filter(handle) == -1) {
-			snprintf(handle->errbuf, PCAP_ERRBUF_SIZE,
+			pcap_snprintf(handle->errbuf, PCAP_ERRBUF_SIZE,
 			    "can't remove kernel total filter: %s",
 			    pcap_strerror(errno));
 			return -2;	/* fatal error */
diff --git a/pcap-netfilter-linux.c b/pcap-netfilter-linux.c
index 3ee6faa..bde648f 100644
--- a/pcap-netfilter-linux.c
+++ b/pcap-netfilter-linux.c
@@ -79,10 +79,12 @@
  */
 struct pcap_netfilter {
 	u_int	packets_read;	/* count of packets read with recvfrom() */
+	u_int   packets_nobufs; /* ENOBUFS counter */
 };
 
 static int nfqueue_send_verdict(const pcap_t *handle, u_int16_t group_id, u_int32_t id, u_int32_t verdict);
 
+
 static int
 netfilter_read_linux(pcap_t *handle, int max_packets, pcap_handler callback, u_char *user)
 {
@@ -98,21 +100,22 @@
 			handle->break_loop = 0;
 			return -2;
 		}
-	} while ((len == -1) && (errno == EINTR));
+		if(errno == ENOBUFS) handlep->packets_nobufs++;
+	} while ((len == -1) && (errno == EINTR || errno == ENOBUFS));
 
 	if (len < 0) {
-		snprintf(handle->errbuf, PCAP_ERRBUF_SIZE, "Can't receive packet %d:%s", errno, pcap_strerror(errno));
+		pcap_snprintf(handle->errbuf, PCAP_ERRBUF_SIZE, "Can't receive packet %d:%s", errno, pcap_strerror(errno));
 		return -1;
 	}
 
-	buf = handle->buffer;
-	while (len >= NLMSG_SPACE(0)) {
+	buf = (unsigned char *)handle->buffer;
+	while ((u_int)len >= NLMSG_SPACE(0)) {
 		const struct nlmsghdr *nlh = (const struct nlmsghdr *) buf;
 		u_int32_t msg_len;
 		nftype_t type = OTHER;
 
-		if (nlh->nlmsg_len < sizeof(struct nlmsghdr) || len < nlh->nlmsg_len) {
-			snprintf(handle->errbuf, PCAP_ERRBUF_SIZE, "Message truncated: (got: %d) (nlmsg_len: %u)", len, nlh->nlmsg_len);
+		if (nlh->nlmsg_len < sizeof(struct nlmsghdr) || (u_int)len < nlh->nlmsg_len) {
+			pcap_snprintf(handle->errbuf, PCAP_ERRBUF_SIZE, "Message truncated: (got: %d) (nlmsg_len: %u)", len, nlh->nlmsg_len);
 			return -1;
 		}
 
@@ -134,7 +137,7 @@
 				const struct nfattr *payload_attr = NULL;
 
 				if (nlh->nlmsg_len < HDR_LENGTH) {
-					snprintf(handle->errbuf, PCAP_ERRBUF_SIZE, "Malformed message: (nlmsg_len: %u)", nlh->nlmsg_len);
+					pcap_snprintf(handle->errbuf, PCAP_ERRBUF_SIZE, "Malformed message: (nlmsg_len: %u)", nlh->nlmsg_len);
 					return -1;
 				}
 
@@ -202,8 +205,8 @@
 		}
 
 		msg_len = NLMSG_ALIGN(nlh->nlmsg_len);
-		if (msg_len > len)
-			msg_len = len;
+		if (msg_len > (u_int)len)
+			msg_len = (u_int)len;
 
 		len -= msg_len;
 		buf += msg_len;
@@ -224,7 +227,7 @@
 	struct pcap_netfilter *handlep = handle->priv;
 
 	stats->ps_recv = handlep->packets_read;
-	stats->ps_drop = 0;
+	stats->ps_drop = handlep->packets_nobufs;
 	stats->ps_ifdrop = 0;
 	return 0;
 }
@@ -232,7 +235,7 @@
 static int
 netfilter_inject_linux(pcap_t *handle, const void *buf, size_t size)
 {
-	snprintf(handle->errbuf, PCAP_ERRBUF_SIZE, "inject not supported on netfilter devices");
+	pcap_snprintf(handle->errbuf, PCAP_ERRBUF_SIZE, "inject not supported on netfilter devices");
 	return (-1);
 }
 
@@ -307,7 +310,7 @@
 		if (snl.nl_pid != 0 || seq_id != nlh->nlmsg_seq)	/* if not from kernel or wrong sequence skip */
 			continue;
 
-		while (len >= NLMSG_SPACE(0) && NLMSG_OK(nlh, len)) {
+		while ((u_int)len >= NLMSG_SPACE(0) && NLMSG_OK(nlh, len)) {
 			if (nlh->nlmsg_type == NLMSG_ERROR || (nlh->nlmsg_type == NLMSG_DONE && nlh->nlmsg_flags & NLM_F_MULTI)) {
 				if (nlh->nlmsg_len < NLMSG_ALIGN(sizeof(struct nlmsgerr))) {
 					errno = EBADMSG;
@@ -417,7 +420,7 @@
 static int
 netfilter_activate(pcap_t* handle)
 {
-	const char *dev = handle->opt.source;
+	const char *dev = handle->opt.device;
 	unsigned short groups[32];
 	int group_count = 0;
 	nftype_t type = OTHER;
@@ -439,16 +442,16 @@
 			char *end_dev;
 
 			if (group_count == 32) {
-				snprintf(handle->errbuf, PCAP_ERRBUF_SIZE,
+				pcap_snprintf(handle->errbuf, PCAP_ERRBUF_SIZE,
 						"Maximum 32 netfilter groups! dev: %s",
-						handle->opt.source);
+						handle->opt.device);
 				return PCAP_ERROR;
 			}
 
 			group_id = strtol(dev, &end_dev, 0);
 			if (end_dev != dev) {
 				if (group_id < 0 || group_id > 65535) {
-					snprintf(handle->errbuf, PCAP_ERRBUF_SIZE,
+					pcap_snprintf(handle->errbuf, PCAP_ERRBUF_SIZE,
 							"Netfilter group range from 0 to 65535 (got %ld)",
 							group_id);
 					return PCAP_ERROR;
@@ -464,9 +467,9 @@
 	}
 
 	if (type == OTHER || *dev) {
-		snprintf(handle->errbuf, PCAP_ERRBUF_SIZE,
+		pcap_snprintf(handle->errbuf, PCAP_ERRBUF_SIZE,
 				"Can't get netfilter group(s) index from %s",
-				handle->opt.source);
+				handle->opt.device);
 		return PCAP_ERROR;
 	}
 
@@ -491,7 +494,7 @@
 	/* Create netlink socket */
 	handle->fd = socket(AF_NETLINK, SOCK_RAW, NETLINK_NETFILTER);
 	if (handle->fd < 0) {
-		snprintf(handle->errbuf, PCAP_ERRBUF_SIZE, "Can't create raw socket %d:%s", errno, pcap_strerror(errno));
+		pcap_snprintf(handle->errbuf, PCAP_ERRBUF_SIZE, "Can't create raw socket %d:%s", errno, pcap_strerror(errno));
 		return PCAP_ERROR;
 	}
 
@@ -509,54 +512,54 @@
 
 	handle->buffer = malloc(handle->bufsize);
 	if (!handle->buffer) {
-		snprintf(handle->errbuf, PCAP_ERRBUF_SIZE, "Can't allocate dump buffer: %s", pcap_strerror(errno));
+		pcap_snprintf(handle->errbuf, PCAP_ERRBUF_SIZE, "Can't allocate dump buffer: %s", pcap_strerror(errno));
 		goto close_fail;
 	}
 
 	if (type == NFLOG) {
 		if (nflog_send_config_cmd(handle, 0, NFULNL_CFG_CMD_PF_UNBIND, AF_INET) < 0) {
-			snprintf(handle->errbuf, PCAP_ERRBUF_SIZE, "NFULNL_CFG_CMD_PF_UNBIND: %s", pcap_strerror(errno));
+			pcap_snprintf(handle->errbuf, PCAP_ERRBUF_SIZE, "NFULNL_CFG_CMD_PF_UNBIND: %s", pcap_strerror(errno));
 			goto close_fail;
 		}
 
 		if (nflog_send_config_cmd(handle, 0, NFULNL_CFG_CMD_PF_BIND, AF_INET) < 0) {
-			snprintf(handle->errbuf, PCAP_ERRBUF_SIZE, "NFULNL_CFG_CMD_PF_BIND: %s", pcap_strerror(errno));
+			pcap_snprintf(handle->errbuf, PCAP_ERRBUF_SIZE, "NFULNL_CFG_CMD_PF_BIND: %s", pcap_strerror(errno));
 			goto close_fail;
 		}
 
 		/* Bind socket to the nflog groups */
 		for (i = 0; i < group_count; i++) {
 			if (nflog_send_config_cmd(handle, groups[i], NFULNL_CFG_CMD_BIND, AF_UNSPEC) < 0) {
-				snprintf(handle->errbuf, PCAP_ERRBUF_SIZE, "Can't listen on group group index: %s", pcap_strerror(errno));
+				pcap_snprintf(handle->errbuf, PCAP_ERRBUF_SIZE, "Can't listen on group group index: %s", pcap_strerror(errno));
 				goto close_fail;
 			}
 
 			if (nflog_send_config_mode(handle, groups[i], NFULNL_COPY_PACKET, handle->snapshot) < 0) {
-				snprintf(handle->errbuf, PCAP_ERRBUF_SIZE, "NFULNL_COPY_PACKET: %s", pcap_strerror(errno));
+				pcap_snprintf(handle->errbuf, PCAP_ERRBUF_SIZE, "NFULNL_COPY_PACKET: %s", pcap_strerror(errno));
 				goto close_fail;
 			}
 		}
 
 	} else {
 		if (nfqueue_send_config_cmd(handle, 0, NFQNL_CFG_CMD_PF_UNBIND, AF_INET) < 0) {
-			snprintf(handle->errbuf, PCAP_ERRBUF_SIZE, "NFQNL_CFG_CMD_PF_UNBIND: %s", pcap_strerror(errno));
+			pcap_snprintf(handle->errbuf, PCAP_ERRBUF_SIZE, "NFQNL_CFG_CMD_PF_UNBIND: %s", pcap_strerror(errno));
 			goto close_fail;
 		}
 
 		if (nfqueue_send_config_cmd(handle, 0, NFQNL_CFG_CMD_PF_BIND, AF_INET) < 0) {
-			snprintf(handle->errbuf, PCAP_ERRBUF_SIZE, "NFQNL_CFG_CMD_PF_BIND: %s", pcap_strerror(errno));
+			pcap_snprintf(handle->errbuf, PCAP_ERRBUF_SIZE, "NFQNL_CFG_CMD_PF_BIND: %s", pcap_strerror(errno));
 			goto close_fail;
 		}
 
 		/* Bind socket to the nfqueue groups */
 		for (i = 0; i < group_count; i++) {
 			if (nfqueue_send_config_cmd(handle, groups[i], NFQNL_CFG_CMD_BIND, AF_UNSPEC) < 0) {
-				snprintf(handle->errbuf, PCAP_ERRBUF_SIZE, "Can't listen on group group index: %s", pcap_strerror(errno));
+				pcap_snprintf(handle->errbuf, PCAP_ERRBUF_SIZE, "Can't listen on group group index: %s", pcap_strerror(errno));
 				goto close_fail;
 			}
 
 			if (nfqueue_send_config_mode(handle, groups[i], NFQNL_COPY_PACKET, handle->snapshot) < 0) {
-				snprintf(handle->errbuf, PCAP_ERRBUF_SIZE, "NFQNL_COPY_PACKET: %s", pcap_strerror(errno));
+				pcap_snprintf(handle->errbuf, PCAP_ERRBUF_SIZE, "NFQNL_COPY_PACKET: %s", pcap_strerror(errno));
 				goto close_fail;
 			}
 		}
@@ -575,7 +578,7 @@
 		 * Set the socket buffer size to the specified value.
 		 */
 		if (setsockopt(handle->fd, SOL_SOCKET, SO_RCVBUF, &handle->opt.buffer_size, sizeof(handle->opt.buffer_size)) == -1) {
-			snprintf(handle->errbuf, PCAP_ERRBUF_SIZE, "SO_RCVBUF: %s", pcap_strerror(errno));
+			pcap_snprintf(handle->errbuf, PCAP_ERRBUF_SIZE, "SO_RCVBUF: %s", pcap_strerror(errno));
 			goto close_fail;
 		}
 	}
@@ -623,7 +626,7 @@
 	/* OK, it's probably ours. */
 	*is_ours = 1;
 
-	p = pcap_create_common(device, ebuf, sizeof (struct pcap_netfilter));
+	p = pcap_create_common(ebuf, sizeof (struct pcap_netfilter));
 	if (p == NULL)
 		return (NULL);
 
@@ -641,7 +644,7 @@
 		/* if netlink is not supported this is not fatal */
 		if (errno == EAFNOSUPPORT || errno == EPROTONOSUPPORT)
 			return 0;
-		snprintf(err_str, PCAP_ERRBUF_SIZE, "Can't open netlink socket %d:%s",
+		pcap_snprintf(err_str, PCAP_ERRBUF_SIZE, "Can't open netlink socket %d:%s",
 			errno, pcap_strerror(errno));
 		return -1;
 	}
diff --git a/pcap-new.c b/pcap-new.c
new file mode 100644
index 0000000..494e425
--- /dev/null
+++ b/pcap-new.c
@@ -0,0 +1,1265 @@
+/*
+ * Copyright (c) 2002 - 2005 NetGroup, Politecnico di Torino (Italy)
+ * Copyright (c) 2005 - 2008 CACE Technologies, Davis (California)
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the Politecnico di Torino, CACE Technologies
+ * nor the names of its contributors may be used to endorse or promote
+ * products derived from this software without specific prior written
+ * permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include "pcap-int.h"	// for the details of the pcap_t structure
+#include "pcap-rpcap.h"
+#include "sockutils.h"
+#include <errno.h>		// for the errno variable
+#include <stdlib.h>		// for malloc(), free(), ...
+#include <string.h>		// for strstr, etc
+
+#ifndef WIN32
+#include <dirent.h>		// for readdir
+#endif
+
+/* Keeps a list of all the opened connections in the active mode. */
+extern struct activehosts *activeHosts;
+
+/*
+ * \brief Keeps the main socket identifier when we want to accept a new remote connection (active mode only).
+ * See the documentation of pcap_remoteact_accept() and pcap_remoteact_cleanup() for more details.
+ */
+SOCKET sockmain;
+
+/* String identifier to be used in the pcap_findalldevs_ex() */
+#define PCAP_TEXT_SOURCE_FILE "File"
+/* String identifier to be used in the pcap_findalldevs_ex() */
+#define PCAP_TEXT_SOURCE_ADAPTER "Network adapter"
+
+/* String identifier to be used in the pcap_findalldevs_ex() */
+#define PCAP_TEXT_SOURCE_ON_LOCAL_HOST "on local host"
+/* String identifier to be used in the pcap_findalldevs_ex() */
+#define PCAP_TEXT_SOURCE_ON_REMOTE_HOST "on remote node"
+
+/*
+* Private data for capturing on WinPcap devices.
+*/
+struct pcap_win {
+	int nonblock;
+	int rfmon_selfstart;		/* a flag tells whether the monitor mode is set by itself */
+	int filtering_in_kernel;	/* using kernel filter */
+
+#ifdef HAVE_DAG_API
+	int	dag_fcs_bits;		/* Number of checksum bits from link layer */
+#endif
+};
+
+/****************************************************
+ *                                                  *
+ * Function bodies                                  *
+ *                                                  *
+ ****************************************************/
+
+int pcap_findalldevs_ex(char *source, struct pcap_rmtauth *auth, pcap_if_t **alldevs, char *errbuf)
+{
+	SOCKET sockctrl;		/* socket descriptor of the control connection */
+	uint32 totread = 0;		/* number of bytes of the payload read from the socket */
+	int nread;
+	struct addrinfo hints;		/* temp variable needed to resolve hostnames into to socket representation */
+	struct addrinfo *addrinfo;	/* temp variable needed to resolve hostnames into to socket representation */
+	struct rpcap_header header;	/* structure that keeps the general header of the rpcap protocol */
+	int i, j;		/* temp variables */
+	int naddr;		/* temp var needed to avoid problems with IPv6 addresses */
+	struct pcap_addr *addr;	/* another such temp */
+	int retval;		/* store the return value of the functions */
+	int nif;		/* Number of interfaces listed */
+	int active = 0;	/* 'true' if we the other end-party is in active mode */
+	char host[PCAP_BUF_SIZE], port[PCAP_BUF_SIZE], name[PCAP_BUF_SIZE], path[PCAP_BUF_SIZE], filename[PCAP_BUF_SIZE];
+	int type;
+	pcap_t *fp;
+	char tmpstring[PCAP_BUF_SIZE + 1];		/* Needed to convert names and descriptions from 'old' syntax to the 'new' one */
+	pcap_if_t *dev;		/* Previous device into the pcap_if_t chain */
+
+
+	if (strlen(source) > PCAP_BUF_SIZE)
+	{
+		pcap_snprintf(errbuf, PCAP_ERRBUF_SIZE, "The source string is too long. Cannot handle it correctly.");
+		return -1;
+	}
+
+	/*
+	 * Determine the type of the source (file, local, remote)
+	 * There are some differences if pcap_findalldevs_ex() is called to list files and remote adapters.
+	 * In the first case, the name of the directory we have to look into must be present (therefore
+	 * the 'name' parameter of the pcap_parsesrcstr() is present).
+	 * In the second case, the name of the adapter is not required (we need just the host). So, we have
+	 * to use a first time this function to get the source type, and a second time to get the appropriate
+	 * info, which depends on the source type.
+	 */
+	if (pcap_parsesrcstr(source, &type, NULL, NULL, NULL, errbuf) == -1)
+		return -1;
+
+	if (type == PCAP_SRC_IFLOCAL)
+	{
+		if (pcap_parsesrcstr(source, &type, host, NULL, NULL, errbuf) == -1)
+			return -1;
+
+		/* Initialize temporary string */
+		tmpstring[PCAP_BUF_SIZE] = 0;
+
+		/* The user wants to retrieve adapters from a local host */
+		if (pcap_findalldevs(alldevs, errbuf) == -1)
+			return -1;
+
+		if ((alldevs == NULL) || (*alldevs == NULL))
+		{
+			pcap_snprintf(errbuf, PCAP_ERRBUF_SIZE,
+				"No interfaces found! Make sure libpcap/WinPcap is properly installed"
+				" on the local machine.");
+			return -1;
+		}
+
+		/* Scan all the interfaces and modify name and description */
+		/* This is a trick in order to avoid the re-implementation of the pcap_findalldevs here */
+		dev = *alldevs;
+		while (dev)
+		{
+			/* Create the new device identifier */
+			if (pcap_createsrcstr(tmpstring, PCAP_SRC_IFLOCAL, NULL, NULL, dev->name, errbuf) == -1)
+				return -1;
+
+			/* Delete the old pointer */
+			free(dev->name);
+
+			/* Make a copy of the new device identifier */
+			dev->name = strdup(tmpstring);
+			if (dev->name == NULL)
+			{
+				pcap_snprintf(errbuf, PCAP_ERRBUF_SIZE, "malloc() failed: %s", pcap_strerror(errno));
+				return -1;
+			}
+
+			/* Create the new device description */
+			if ((dev->description == NULL) || (dev->description[0] == 0))
+				pcap_snprintf(tmpstring, sizeof(tmpstring) - 1, "%s '%s' %s", PCAP_TEXT_SOURCE_ADAPTER,
+				dev->name, PCAP_TEXT_SOURCE_ON_LOCAL_HOST);
+			else
+				pcap_snprintf(tmpstring, sizeof(tmpstring) - 1, "%s '%s' %s", PCAP_TEXT_SOURCE_ADAPTER,
+				dev->description, PCAP_TEXT_SOURCE_ON_LOCAL_HOST);
+
+			/* Delete the old pointer */
+			free(dev->description);
+
+			/* Make a copy of the description */
+			dev->description = strdup(tmpstring);
+			if (dev->description == NULL)
+			{
+				pcap_snprintf(errbuf, PCAP_ERRBUF_SIZE, "malloc() failed: %s", pcap_strerror(errno));
+				return -1;
+			}
+
+			dev = dev->next;
+		}
+
+		return 0;
+	}
+
+	(*alldevs) = NULL;
+
+	if (type == PCAP_SRC_FILE)
+	{
+		size_t stringlen;
+#ifdef WIN32
+		WIN32_FIND_DATA filedata;
+		HANDLE filehandle;
+#else
+		struct dirent *filedata;
+		DIR *unixdir;
+#endif
+
+		if (pcap_parsesrcstr(source, &type, host, port, name, errbuf) == -1)
+			return -1;
+
+		/* Check that the filename is correct */
+		stringlen = strlen(name);
+
+		/* The directory must end with '\' in Win32 and '/' in UNIX */
+#ifdef WIN32
+#define ENDING_CHAR '\\'
+#else
+#define ENDING_CHAR '/'
+#endif
+
+		if (name[stringlen - 1] != ENDING_CHAR)
+		{
+			name[stringlen] = ENDING_CHAR;
+			name[stringlen + 1] = 0;
+
+			stringlen++;
+		}
+
+		/* Save the path for future reference */
+		pcap_snprintf(path, sizeof(path), "%s", name);
+
+#ifdef WIN32
+		/* To perform directory listing, Win32 must have an 'asterisk' as ending char */
+		if (name[stringlen - 1] != '*')
+		{
+			name[stringlen] = '*';
+			name[stringlen + 1] = 0;
+		}
+
+		filehandle = FindFirstFile(name, &filedata);
+
+		if (filehandle == INVALID_HANDLE_VALUE)
+		{
+			pcap_snprintf(errbuf, PCAP_ERRBUF_SIZE, "Error when listing files: does folder '%s' exist?", path);
+			return -1;
+		}
+
+#else
+		/* opening the folder */
+		unixdir= opendir(path);
+
+		/* get the first file into it */
+		filedata= readdir(unixdir);
+
+		if (filedata == NULL)
+		{
+			pcap_snprintf(errbuf, PCAP_ERRBUF_SIZE, "Error when listing files: does folder '%s' exist?", path);
+			return -1;
+		}
+#endif
+
+		do
+		{
+
+#ifdef WIN32
+			pcap_snprintf(filename, sizeof(filename), "%s%s", path, filedata.cFileName);
+#else
+			pcap_snprintf(filename, sizeof(filename), "%s%s", path, filedata->d_name);
+#endif
+
+			fp = pcap_open_offline(filename, errbuf);
+
+			if (fp)
+			{
+				/* allocate the main structure */
+				if (*alldevs == NULL)	/* This is in case it is the first file */
+				{
+					(*alldevs) = (pcap_if_t *)malloc(sizeof(pcap_if_t));
+					dev = (*alldevs);
+				}
+				else
+				{
+					dev->next = (pcap_if_t *)malloc(sizeof(pcap_if_t));
+					dev = dev->next;
+				}
+
+				/* check that the malloc() didn't fail */
+				if (dev == NULL)
+				{
+					pcap_snprintf(errbuf, PCAP_ERRBUF_SIZE, "malloc() failed: %s", pcap_strerror(errno));
+					return -1;
+				}
+
+				/* Initialize the structure to 'zero' */
+				memset(dev, 0, sizeof(pcap_if_t));
+
+				/* Create the new source identifier */
+				if (pcap_createsrcstr(tmpstring, PCAP_SRC_FILE, NULL, NULL, filename, errbuf) == -1)
+					return -1;
+
+				stringlen = strlen(tmpstring);
+
+				dev->name = (char *)malloc(stringlen + 1);
+				if (dev->name == NULL)
+				{
+					pcap_snprintf(errbuf, PCAP_ERRBUF_SIZE, "malloc() failed: %s", pcap_strerror(errno));
+					return -1;
+				}
+
+				strlcpy(dev->name, tmpstring, stringlen);
+
+				dev->name[stringlen] = 0;
+
+				/* Create the description */
+				pcap_snprintf(tmpstring, sizeof(tmpstring) - 1, "%s '%s' %s", PCAP_TEXT_SOURCE_FILE,
+					filename, PCAP_TEXT_SOURCE_ON_LOCAL_HOST);
+
+				stringlen = strlen(tmpstring);
+
+				dev->description = (char *)malloc(stringlen + 1);
+
+				if (dev->description == NULL)
+				{
+					pcap_snprintf(errbuf, PCAP_ERRBUF_SIZE, "malloc() failed: %s", pcap_strerror(errno));
+					return -1;
+				}
+
+				/* Copy the new device description into the correct memory location */
+				strlcpy(dev->description, tmpstring, stringlen + 1);
+
+				pcap_close(fp);
+			}
+		}
+#ifdef WIN32
+		while (FindNextFile(filehandle, &filedata) != 0);
+#else
+		while ( (filedata= readdir(unixdir)) != NULL);
+#endif
+
+
+#ifdef WIN32
+		/* Close the search handle. */
+		FindClose(filehandle);
+#endif
+
+		return 0;
+	}
+
+	/* If we come here, it is a remote host */
+
+	/* Retrieve the needed data for getting adapter list */
+	if (pcap_parsesrcstr(source, &type, host, port, NULL, errbuf) == -1)
+		return -1;
+
+	/* Warning: this call can be the first one called by the user. */
+	/* For this reason, we have to initialize the WinSock support. */
+	if (sock_init(errbuf, PCAP_ERRBUF_SIZE) == -1)
+		return -1;
+
+	/* Check for active mode */
+	sockctrl = rpcap_remoteact_getsock(host, &active, errbuf);
+	if (sockctrl == INVALID_SOCKET)
+		return -1;
+
+	if (!active) {
+		/*
+		 * We're not in active mode; let's try to open a new
+		 * control connection.
+		 */
+		addrinfo = NULL;
+
+		memset(&hints, 0, sizeof(struct addrinfo));
+		hints.ai_family = PF_UNSPEC;
+		hints.ai_socktype = SOCK_STREAM;
+
+		if (port[0] == 0)
+		{
+			/* the user chose not to specify the port */
+			if (sock_initaddress(host, RPCAP_DEFAULT_NETPORT, &hints, &addrinfo, errbuf, PCAP_ERRBUF_SIZE) == -1)
+				return -1;
+		}
+		else
+		{
+			if (sock_initaddress(host, port, &hints, &addrinfo, errbuf, PCAP_ERRBUF_SIZE) == -1)
+				return -1;
+		}
+
+		if ((sockctrl = sock_open(addrinfo, SOCKOPEN_CLIENT, 0, errbuf, PCAP_ERRBUF_SIZE)) == -1)
+			goto error;
+
+		/* addrinfo is no longer used */
+		freeaddrinfo(addrinfo);
+		addrinfo = NULL;
+
+		if (rpcap_sendauth(sockctrl, auth, errbuf) == -1)
+		{
+			sock_close(sockctrl, NULL, 0);
+			return -1;
+		}
+	}
+
+	/* RPCAP findalldevs command */
+	rpcap_createhdr(&header, RPCAP_MSG_FINDALLIF_REQ, 0, 0);
+
+	if (sock_send(sockctrl, (char *)&header, sizeof(struct rpcap_header), errbuf, PCAP_ERRBUF_SIZE) == -1)
+		goto error;
+
+	if (sock_recv(sockctrl, (char *)&header, sizeof(struct rpcap_header), SOCK_RECEIVEALL_YES, errbuf, PCAP_ERRBUF_SIZE) == -1)
+		goto error;
+
+	/* Checks if the message is correct */
+	retval = rpcap_checkmsg(errbuf, sockctrl, &header, RPCAP_MSG_FINDALLIF_REPLY, RPCAP_MSG_ERROR, 0);
+
+	if (retval != RPCAP_MSG_FINDALLIF_REPLY)		/* the message is not the one expected */
+	{
+		switch (retval)
+		{
+		case -3:	/* Unrecoverable network error */
+		case -2:	/* The other endpoint send a message that is not allowed here */
+		case -1:	/* The other endpoint has a version number that is not compatible with our */
+			break;
+
+		case RPCAP_MSG_ERROR:		/* The other endpoint reported an error */
+			break;
+
+		default:
+		{
+			pcap_snprintf(errbuf, PCAP_ERRBUF_SIZE, "Internal error");
+			break;
+		};
+		}
+
+		if (!active)
+			sock_close(sockctrl, NULL, 0);
+
+		return -1;
+	}
+
+	/* read the number of interfaces */
+	nif = ntohs(header.value);
+
+	/* loop until all interfaces have been received */
+	for (i = 0; i < nif; i++)
+	{
+		struct rpcap_findalldevs_if findalldevs_if;
+		char tmpstring2[PCAP_BUF_SIZE + 1];		/* Needed to convert names and descriptions from 'old' syntax to the 'new' one */
+		size_t stringlen;
+
+		tmpstring2[PCAP_BUF_SIZE] = 0;
+
+		/* receive the findalldevs structure from remote host */
+		nread = sock_recv(sockctrl, (char *)&findalldevs_if,
+		    sizeof(struct rpcap_findalldevs_if), SOCK_RECEIVEALL_YES,
+		    errbuf, PCAP_ERRBUF_SIZE);
+		if (nread == -1)
+			goto error;
+		totread += nread;
+
+		findalldevs_if.namelen = ntohs(findalldevs_if.namelen);
+		findalldevs_if.desclen = ntohs(findalldevs_if.desclen);
+		findalldevs_if.naddr = ntohs(findalldevs_if.naddr);
+
+		/* allocate the main structure */
+		if (i == 0)
+		{
+			(*alldevs) = (pcap_if_t *)malloc(sizeof(pcap_if_t));
+			dev = (*alldevs);
+		}
+		else
+		{
+			dev->next = (pcap_if_t *)malloc(sizeof(pcap_if_t));
+			dev = dev->next;
+		}
+
+		/* check that the malloc() didn't fail */
+		if (dev == NULL)
+		{
+			pcap_snprintf(errbuf, PCAP_ERRBUF_SIZE, "malloc() failed: %s", pcap_strerror(errno));
+			goto error;
+		}
+
+		/* Initialize the structure to 'zero' */
+		memset(dev, 0, sizeof(pcap_if_t));
+
+		/* allocate mem for name and description */
+		if (findalldevs_if.namelen)
+		{
+
+			if (findalldevs_if.namelen >= sizeof(tmpstring))
+			{
+				pcap_snprintf(errbuf, PCAP_ERRBUF_SIZE, "Interface name too long");
+				goto error;
+			}
+
+			/* Retrieve adapter name */
+			nread = sock_recv(sockctrl, tmpstring,
+			    findalldevs_if.namelen, SOCK_RECEIVEALL_YES,
+			    errbuf, PCAP_ERRBUF_SIZE);
+			if (nread == -1)
+				goto error;
+			totread += nread;
+
+			tmpstring[findalldevs_if.namelen] = 0;
+
+			/* Create the new device identifier */
+			if (pcap_createsrcstr(tmpstring2, PCAP_SRC_IFREMOTE, host, port, tmpstring, errbuf) == -1)
+				return -1;
+
+			stringlen = strlen(tmpstring2);
+
+			dev->name = (char *)malloc(stringlen + 1);
+			if (dev->name == NULL)
+			{
+				pcap_snprintf(errbuf, PCAP_ERRBUF_SIZE, "malloc() failed: %s", pcap_strerror(errno));
+				goto error;
+			}
+
+			/* Copy the new device name into the correct memory location */
+			strlcpy(dev->name, tmpstring2, stringlen + 1);
+		}
+
+		if (findalldevs_if.desclen)
+		{
+			if (findalldevs_if.desclen >= sizeof(tmpstring))
+			{
+				pcap_snprintf(errbuf, PCAP_ERRBUF_SIZE, "Interface description too long");
+				goto error;
+			}
+
+			/* Retrieve adapter description */
+			nread = sock_recv(sockctrl, tmpstring,
+			    findalldevs_if.desclen, SOCK_RECEIVEALL_YES,
+			    errbuf, PCAP_ERRBUF_SIZE);
+			if (nread == -1)
+				goto error;
+			totread += nread;
+
+			tmpstring[findalldevs_if.desclen] = 0;
+
+			pcap_snprintf(tmpstring2, sizeof(tmpstring2) - 1, "%s '%s' %s %s", PCAP_TEXT_SOURCE_ADAPTER,
+				tmpstring, PCAP_TEXT_SOURCE_ON_REMOTE_HOST, host);
+
+			stringlen = strlen(tmpstring2);
+
+			dev->description = (char *)malloc(stringlen + 1);
+
+			if (dev->description == NULL)
+			{
+				pcap_snprintf(errbuf, PCAP_ERRBUF_SIZE, "malloc() failed: %s", pcap_strerror(errno));
+				goto error;
+			}
+
+			/* Copy the new device description into the correct memory location */
+			strlcpy(dev->description, tmpstring2, stringlen + 1);
+		}
+
+		dev->flags = ntohl(findalldevs_if.flags);
+
+		naddr = 0;
+		addr = NULL;
+		/* loop until all addresses have been received */
+		for (j = 0; j < findalldevs_if.naddr; j++)
+		{
+			struct rpcap_findalldevs_ifaddr ifaddr;
+
+			/* Retrieve the interface addresses */
+			nread = sock_recv(sockctrl, (char *)&ifaddr,
+			    sizeof(struct rpcap_findalldevs_ifaddr),
+			    SOCK_RECEIVEALL_YES, errbuf, PCAP_ERRBUF_SIZE);
+			if (nread == -1)
+				goto error;
+			totread += nread;
+
+			/*
+			 * WARNING libpcap bug: the address listing is
+			 * available only for AF_INET.
+			 *
+			 * XXX - IPv6?
+			 */
+			if (ntohs(ifaddr.addr.ss_family) == AF_INET)
+			{
+				if (addr == NULL)
+				{
+					dev->addresses = (struct pcap_addr *) malloc(sizeof(struct pcap_addr));
+					addr = dev->addresses;
+				}
+				else
+				{
+					addr->next = (struct pcap_addr *) malloc(sizeof(struct pcap_addr));
+					addr = addr->next;
+				}
+				naddr++;
+
+				if (addr == NULL)
+				{
+					pcap_snprintf(errbuf, PCAP_ERRBUF_SIZE, "malloc() failed: %s", pcap_strerror(errno));
+					goto error;
+				}
+				addr->next = NULL;
+
+				if (rpcap_deseraddr((struct sockaddr_storage *) &ifaddr.addr,
+					(struct sockaddr_storage **) &addr->addr, errbuf) == -1)
+					goto error;
+				if (rpcap_deseraddr((struct sockaddr_storage *) &ifaddr.netmask,
+					(struct sockaddr_storage **) &addr->netmask, errbuf) == -1)
+					goto error;
+				if (rpcap_deseraddr((struct sockaddr_storage *) &ifaddr.broadaddr,
+					(struct sockaddr_storage **) &addr->broadaddr, errbuf) == -1)
+					goto error;
+				if (rpcap_deseraddr((struct sockaddr_storage *) &ifaddr.dstaddr,
+					(struct sockaddr_storage **) &addr->dstaddr, errbuf) == -1)
+					goto error;
+
+				if ((addr->addr == NULL) && (addr->netmask == NULL) &&
+					(addr->broadaddr == NULL) && (addr->dstaddr == NULL))
+				{
+					free(addr);
+					addr = NULL;
+					if (naddr == 1)
+						naddr = 0;	/* the first item of the list had NULL addresses */
+				}
+			}
+		}
+	}
+
+	/* Checks if all the data has been read; if not, discard the data in excess */
+	if (totread != ntohl(header.plen))
+	{
+		if (sock_discard(sockctrl, ntohl(header.plen) - totread, errbuf, PCAP_ERRBUF_SIZE) == 1)
+			return -1;
+	}
+
+	/* Control connection has to be closed only in case the remote machine is in passive mode */
+	if (!active)
+	{
+		/* DO not send RPCAP_CLOSE, since we did not open a pcap_t; no need to free resources */
+		if (sock_close(sockctrl, errbuf, PCAP_ERRBUF_SIZE))
+			return -1;
+	}
+
+	/* To avoid inconsistencies in the number of sock_init() */
+	sock_cleanup();
+
+	return 0;
+
+error:
+	/*
+	 * In case there has been an error, I don't want to overwrite it with a new one
+	 * if the following call fails. I want to return always the original error.
+	 *
+	 * Take care: this connection can already be closed when we try to close it.
+	 * This happens because a previous error in the rpcapd, which requested to
+	 * closed the connection. In that case, we already recognized that into the
+	 * rpspck_isheaderok() and we already acknowledged the closing.
+	 * In that sense, this call is useless here (however it is needed in case
+	 * the client generates the error).
+	 *
+	 * Checks if all the data has been read; if not, discard the data in excess
+	 */
+	if (totread != ntohl(header.plen))
+	{
+		if (sock_discard(sockctrl, ntohl(header.plen) - totread, NULL, 0) == 1)
+			return -1;
+	}
+
+	/* Control connection has to be closed only in case the remote machine is in passive mode */
+	if (!active)
+		sock_close(sockctrl, NULL, 0);
+
+	/* To avoid inconsistencies in the number of sock_init() */
+	sock_cleanup();
+
+	return -1;
+}
+
+int pcap_createsrcstr(char *source, int type, const char *host, const char *port, const char *name, char *errbuf)
+{
+	switch (type)
+	{
+	case PCAP_SRC_FILE:
+	{
+		strlcpy(source, PCAP_SRC_FILE_STRING, PCAP_BUF_SIZE);
+		if ((name) && (*name))
+		{
+			strlcat(source, name, PCAP_BUF_SIZE);
+			return 0;
+		}
+		else
+		{
+			pcap_snprintf(errbuf, PCAP_ERRBUF_SIZE, "The file name cannot be NULL.");
+			return -1;
+		}
+	}
+
+	case PCAP_SRC_IFREMOTE:
+	{
+		strlcpy(source, PCAP_SRC_IF_STRING, PCAP_BUF_SIZE);
+		if ((host) && (*host))
+		{
+			if ((strcspn(host, "aAbBcCdDeEfFgGhHjJkKlLmMnNoOpPqQrRsStTuUvVwWxXyYzZ")) == strlen(host))
+			{
+				/* the host name does not contains alphabetic chars. So, it is a numeric address */
+				/* In this case we have to include it between square brackets */
+				strlcat(source, "[", PCAP_BUF_SIZE);
+				strlcat(source, host, PCAP_BUF_SIZE);
+				strlcat(source, "]", PCAP_BUF_SIZE);
+			}
+			else
+				strlcat(source, host, PCAP_BUF_SIZE);
+
+			if ((port) && (*port))
+			{
+				strlcat(source, ":", PCAP_BUF_SIZE);
+				strlcat(source, port, PCAP_BUF_SIZE);
+			}
+
+			strlcat(source, "/", PCAP_BUF_SIZE);
+		}
+		else
+		{
+			pcap_snprintf(errbuf, PCAP_ERRBUF_SIZE, "The host name cannot be NULL.");
+			return -1;
+		}
+
+		if ((name) && (*name))
+			strlcat(source, name, PCAP_BUF_SIZE);
+
+		return 0;
+	}
+
+	case PCAP_SRC_IFLOCAL:
+	{
+		strlcpy(source, PCAP_SRC_IF_STRING, PCAP_BUF_SIZE);
+
+		if ((name) && (*name))
+			strlcat(source, name, PCAP_BUF_SIZE);
+
+		return 0;
+	}
+
+	default:
+	{
+		pcap_snprintf(errbuf, PCAP_ERRBUF_SIZE, "The interface type is not valid.");
+		return -1;
+	}
+	}
+}
+
+int pcap_parsesrcstr(const char *source, int *type, char *host, char *port, char *name, char *errbuf)
+{
+	char *ptr;
+	int ntoken;
+	char tmpname[PCAP_BUF_SIZE];
+	char tmphost[PCAP_BUF_SIZE];
+	char tmpport[PCAP_BUF_SIZE];
+	int tmptype;
+
+	/* Initialization stuff */
+	tmpname[0] = 0;
+	tmphost[0] = 0;
+	tmpport[0] = 0;
+
+	if (host)
+		*host = 0;
+	if (port)
+		*port = 0;
+	if (name)
+		*name = 0;
+
+	/* Look for a 'rpcap://' identifier */
+	if ((ptr = strstr(source, PCAP_SRC_IF_STRING)) != NULL)
+	{
+		if (strlen(PCAP_SRC_IF_STRING) == strlen(source))
+		{
+			/* The source identifier contains only the 'rpcap://' string. */
+			/* So, this is a local capture. */
+			*type = PCAP_SRC_IFLOCAL;
+			return 0;
+		}
+
+		ptr += strlen(PCAP_SRC_IF_STRING);
+
+		if (strchr(ptr, '[')) /* This is probably a numeric address */
+		{
+			ntoken = sscanf(ptr, "[%[1234567890:.]]:%[^/]/%s", tmphost, tmpport, tmpname);
+
+			if (ntoken == 1)	/* probably the port is missing */
+				ntoken = sscanf(ptr, "[%[1234567890:.]]/%s", tmphost, tmpname);
+
+			tmptype = PCAP_SRC_IFREMOTE;
+		}
+		else
+		{
+			ntoken = sscanf(ptr, "%[^/:]:%[^/]/%s", tmphost, tmpport, tmpname);
+
+			if (ntoken == 1)
+			{
+				/*
+				 * This can be due to two reasons:
+				 * - we want a remote capture, but the network port is missing
+				 * - we want to do a local capture
+				 * To distinguish between the two, we look for the '/' char
+				 */
+				if (strchr(ptr, '/'))
+				{
+					/* We're on a remote capture */
+					sscanf(ptr, "%[^/]/%s", tmphost, tmpname);
+					tmptype = PCAP_SRC_IFREMOTE;
+				}
+				else
+				{
+					/* We're on a local capture */
+					if (*ptr)
+						strlcpy(tmpname, ptr, PCAP_BUF_SIZE);
+
+					/* Clean the host name, since it is a remote capture */
+					/* NOTE: the host name has been assigned in the previous "ntoken= sscanf(...)" line */
+					tmphost[0] = 0;
+
+					tmptype = PCAP_SRC_IFLOCAL;
+				}
+			}
+			else
+				tmptype = PCAP_SRC_IFREMOTE;
+		}
+
+		if (host)
+			strlcpy(host, tmphost, PCAP_BUF_SIZE);
+		if (port)
+			strlcpy(port, tmpport, PCAP_BUF_SIZE);
+		if (type)
+			*type = tmptype;
+
+		if (name)
+		{
+			/*
+			 * If the user wants the host name, but it cannot be located into the source string, return error
+			 * However, if the user is not interested in the interface name (e.g. if we're called by
+			 * pcap_findalldevs_ex(), which does not have interface name, do not return error
+			 */
+			if (tmpname[0])
+			{
+				strlcpy(name, tmpname, PCAP_BUF_SIZE);
+			}
+			else
+			{
+				if (errbuf)
+					pcap_snprintf(errbuf, PCAP_ERRBUF_SIZE, "The interface name has not been specified in the source string.");
+
+				return -1;
+			}
+		}
+
+		return 0;
+	}
+
+	/* Look for a 'file://' identifier */
+	if ((ptr = strstr(source, PCAP_SRC_FILE_STRING)) != NULL)
+	{
+		ptr += strlen(PCAP_SRC_FILE_STRING);
+		if (*ptr)
+		{
+			if (name)
+				strlcpy(name, ptr, PCAP_BUF_SIZE);
+
+			if (type)
+				*type = PCAP_SRC_FILE;
+
+			return 0;
+		}
+		else
+		{
+			if (errbuf)
+				pcap_snprintf(errbuf, PCAP_ERRBUF_SIZE, "The file name has not been specified in the source string.");
+
+			return -1;
+		}
+
+	}
+
+	/* Backward compatibility; the user didn't use the 'rpcap://, file://'  specifiers */
+	if ((source) && (*source))
+	{
+		if (name)
+			strlcpy(name, source, PCAP_BUF_SIZE);
+
+		if (type)
+			*type = PCAP_SRC_IFLOCAL;
+
+		return 0;
+	}
+	else
+	{
+		if (errbuf)
+			pcap_snprintf(errbuf, PCAP_ERRBUF_SIZE, "The interface name has not been specified in the source string.");
+
+		return -1;
+	}
+};
+
+pcap_t *pcap_open(const char *source, int snaplen, int flags, int read_timeout, struct pcap_rmtauth *auth, char *errbuf)
+{
+	char host[PCAP_BUF_SIZE], port[PCAP_BUF_SIZE], name[PCAP_BUF_SIZE];
+	int type;
+	pcap_t *fp;
+	int result;
+
+	if (strlen(source) > PCAP_BUF_SIZE)
+	{
+		pcap_snprintf(errbuf, PCAP_ERRBUF_SIZE, "The source string is too long. Cannot handle it correctly.");
+		return NULL;
+	}
+
+	/* determine the type of the source (file, local, remote) */
+	if (pcap_parsesrcstr(source, &type, host, port, name, errbuf) == -1)
+		return NULL;
+
+
+	switch (type)
+	{
+	case PCAP_SRC_FILE:
+		fp = pcap_open_offline(name, errbuf);
+		break;
+
+	case PCAP_SRC_IFREMOTE:
+		fp = pcap_create(source, errbuf);
+		if (fp == NULL)
+		{
+			return NULL;
+		}
+
+		/*
+		 * Although we already have host, port and iface, we prefer TO PASS only 'pars' to the
+		 * pcap_open_remote() so that it has to call the pcap_parsesrcstr() again.
+		 * This is less optimized, but much clearer.
+		 */
+
+		result = pcap_opensource_remote(fp, auth);
+
+		if (result != 0)
+		{
+			pcap_close(fp);
+			return NULL;
+		}
+
+		struct pcap_md *md;				/* structure used when doing a remote live capture */
+		md = (struct pcap_md *) ((u_char*)fp->priv + sizeof(struct pcap_win));
+
+		fp->snapshot = snaplen;
+		fp->opt.timeout = read_timeout;
+		md->rmt_flags = flags;
+		break;
+
+	case PCAP_SRC_IFLOCAL:
+
+		fp = pcap_open_live(name, snaplen, (flags & PCAP_OPENFLAG_PROMISCUOUS), read_timeout, errbuf);
+
+#ifdef WIN32
+		/*
+		 * these flags are supported on Windows only
+		 */
+		if (fp != NULL && fp->adapter != NULL)
+		{
+			/* disable loopback capture if requested */
+			if (flags & PCAP_OPENFLAG_NOCAPTURE_LOCAL)
+			{
+				if (!PacketSetLoopbackBehavior(fp->adapter, NPF_DISABLE_LOOPBACK))
+				{
+					pcap_snprintf(errbuf, PCAP_ERRBUF_SIZE, "Unable to disable the capture of loopback packets.");
+					pcap_close(fp);
+					return NULL;
+				}
+			}
+
+			/* set mintocopy to zero if requested */
+			if (flags & PCAP_OPENFLAG_MAX_RESPONSIVENESS)
+			{
+				if (!PacketSetMinToCopy(fp->adapter, 0))
+				{
+					pcap_snprintf(errbuf, PCAP_ERRBUF_SIZE, "Unable to set max responsiveness.");
+					pcap_close(fp);
+					return NULL;
+				}
+			}
+		}
+#endif /* WIN32 */
+
+		break;
+
+	default:
+		strlcpy(errbuf, "Source type not supported", PCAP_ERRBUF_SIZE);
+		return NULL;
+	}
+	return fp;
+}
+
+struct pcap_samp *pcap_setsampling(pcap_t *p)
+{
+	struct pcap_md *md;				/* structure used when doing a remote live capture */
+
+	md = (struct pcap_md *) ((u_char*)p->priv + sizeof(struct pcap_win));
+	return &(md->rmt_samp);
+}
+
+SOCKET pcap_remoteact_accept(const char *address, const char *port, const char *hostlist, char *connectinghost, struct pcap_rmtauth *auth, char *errbuf)
+{
+	/* socket-related variables */
+	struct addrinfo hints;			/* temporary struct to keep settings needed to open the new socket */
+	struct addrinfo *addrinfo;		/* keeps the addrinfo chain; required to open a new socket */
+	struct sockaddr_storage from;	/* generic sockaddr_storage variable */
+	socklen_t fromlen;				/* keeps the length of the sockaddr_storage variable */
+	SOCKET sockctrl;				/* keeps the main socket identifier */
+	struct activehosts *temp, *prev;	/* temp var needed to scan he host list chain */
+
+	*connectinghost = 0;		/* just in case */
+
+	/* Prepare to open a new server socket */
+	memset(&hints, 0, sizeof(struct addrinfo));
+	/* WARNING Currently it supports only ONE socket family among ipv4 and IPv6  */
+	hints.ai_family = AF_INET;		/* PF_UNSPEC to have both IPv4 and IPv6 server */
+	hints.ai_flags = AI_PASSIVE;	/* Ready to a bind() socket */
+	hints.ai_socktype = SOCK_STREAM;
+
+	/* Warning: this call can be the first one called by the user. */
+	/* For this reason, we have to initialize the WinSock support. */
+	if (sock_init(errbuf, PCAP_ERRBUF_SIZE) == -1)
+		return -1;
+
+	/* Do the work */
+	if ((port == NULL) || (port[0] == 0))
+	{
+		if (sock_initaddress(address, RPCAP_DEFAULT_NETPORT_ACTIVE, &hints, &addrinfo, errbuf, PCAP_ERRBUF_SIZE) == -1)
+		{
+			SOCK_ASSERT(errbuf, 1);
+			return -2;
+		}
+	}
+	else
+	{
+		if (sock_initaddress(address, port, &hints, &addrinfo, errbuf, PCAP_ERRBUF_SIZE) == -1)
+		{
+			SOCK_ASSERT(errbuf, 1);
+			return -2;
+		}
+	}
+
+
+	if ((sockmain = sock_open(addrinfo, SOCKOPEN_SERVER, 1, errbuf, PCAP_ERRBUF_SIZE)) == -1)
+	{
+		SOCK_ASSERT(errbuf, 1);
+		return -2;
+	}
+
+	/* Connection creation */
+	fromlen = sizeof(struct sockaddr_storage);
+
+	sockctrl = accept(sockmain, (struct sockaddr *) &from, &fromlen);
+
+	/* We're not using sock_close, since we do not want to send a shutdown */
+	/* (which is not allowed on a non-connected socket) */
+	closesocket(sockmain);
+	sockmain = 0;
+
+	if (sockctrl == -1)
+	{
+		sock_geterror("accept(): ", errbuf, PCAP_ERRBUF_SIZE);
+		return -2;
+	}
+
+	/* Get the numeric for of the name of the connecting host */
+	if (getnameinfo((struct sockaddr *) &from, fromlen, connectinghost, RPCAP_HOSTLIST_SIZE, NULL, 0, NI_NUMERICHOST))
+	{
+		sock_geterror("getnameinfo(): ", errbuf, PCAP_ERRBUF_SIZE);
+		rpcap_senderror(sockctrl, errbuf, PCAP_ERR_REMOTEACCEPT, NULL);
+		sock_close(sockctrl, NULL, 0);
+		return -1;
+	}
+
+	/* checks if the connecting host is among the ones allowed */
+	if (sock_check_hostlist((char *)hostlist, RPCAP_HOSTLIST_SEP, &from, errbuf, PCAP_ERRBUF_SIZE) < 0)
+	{
+		rpcap_senderror(sockctrl, errbuf, PCAP_ERR_REMOTEACCEPT, NULL);
+		sock_close(sockctrl, NULL, 0);
+		return -1;
+	}
+
+	/* Send authentication to the remote machine */
+	if (rpcap_sendauth(sockctrl, auth, errbuf) == -1)
+	{
+		rpcap_senderror(sockctrl, errbuf, PCAP_ERR_REMOTEACCEPT, NULL);
+		sock_close(sockctrl, NULL, 0);
+		return -3;
+	}
+
+	/* Checks that this host does not already have a cntrl connection in place */
+
+	/* Initialize pointers */
+	temp = activeHosts;
+	prev = NULL;
+
+	while (temp)
+	{
+		/* This host already has an active connection in place, so I don't have to update the host list */
+		if (sock_cmpaddr(&temp->host, &from) == 0)
+			return sockctrl;
+
+		prev = temp;
+		temp = temp->next;
+	}
+
+	/* The host does not exist in the list; so I have to update the list */
+	if (prev)
+	{
+		prev->next = (struct activehosts *) malloc(sizeof(struct activehosts));
+		temp = prev->next;
+	}
+	else
+	{
+		activeHosts = (struct activehosts *) malloc(sizeof(struct activehosts));
+		temp = activeHosts;
+	}
+
+	if (temp == NULL)
+	{
+		pcap_snprintf(errbuf, PCAP_ERRBUF_SIZE, "malloc() failed: %s", pcap_strerror(errno));
+		rpcap_senderror(sockctrl, errbuf, PCAP_ERR_REMOTEACCEPT, NULL);
+		sock_close(sockctrl, NULL, 0);
+		return -1;
+	}
+
+	memcpy(&temp->host, &from, fromlen);
+	temp->sockctrl = sockctrl;
+	temp->next = NULL;
+
+	return sockctrl;
+}
+
+int pcap_remoteact_close(const char *host, char *errbuf)
+{
+	struct activehosts *temp, *prev;	/* temp var needed to scan the host list chain */
+	struct addrinfo hints, *addrinfo, *ai_next;	/* temp var needed to translate between hostname to its address */
+	int retval;
+
+	temp = activeHosts;
+	prev = NULL;
+
+	/* retrieve the network address corresponding to 'host' */
+	addrinfo = NULL;
+	memset(&hints, 0, sizeof(struct addrinfo));
+	hints.ai_family = PF_UNSPEC;
+	hints.ai_socktype = SOCK_STREAM;
+
+	retval = getaddrinfo(host, "0", &hints, &addrinfo);
+	if (retval != 0)
+	{
+		pcap_snprintf(errbuf, PCAP_ERRBUF_SIZE, "getaddrinfo() %s", gai_strerror(retval));
+		return -1;
+	}
+
+	while (temp)
+	{
+		ai_next = addrinfo;
+		while (ai_next)
+		{
+			if (sock_cmpaddr(&temp->host, (struct sockaddr_storage *) ai_next->ai_addr) == 0)
+			{
+				struct rpcap_header header;
+
+				/* Close this connection */
+				rpcap_createhdr(&header, RPCAP_MSG_CLOSE, 0, 0);
+
+				/* I don't check for errors, since I'm going to close everything */
+				sock_send(temp->sockctrl, (char *)&header, sizeof(struct rpcap_header), errbuf, PCAP_ERRBUF_SIZE);
+
+				if (sock_close(temp->sockctrl, errbuf, PCAP_ERRBUF_SIZE))
+				{
+					/* To avoid inconsistencies in the number of sock_init() */
+					sock_cleanup();
+
+					return -1;
+				}
+
+				if (prev)
+					prev->next = temp->next;
+				else
+					activeHosts = temp->next;
+
+				freeaddrinfo(addrinfo);
+
+				free(temp);
+
+				/* To avoid inconsistencies in the number of sock_init() */
+				sock_cleanup();
+
+				return 0;
+			}
+
+			ai_next = ai_next->ai_next;
+		}
+		prev = temp;
+		temp = temp->next;
+	}
+
+	if (addrinfo)
+		freeaddrinfo(addrinfo);
+
+	/* To avoid inconsistencies in the number of sock_init() */
+	sock_cleanup();
+
+	pcap_snprintf(errbuf, PCAP_ERRBUF_SIZE, "The host you want to close the active connection is not known");
+	return -1;
+}
+
+void pcap_remoteact_cleanup(void)
+{
+	/* Very dirty, but it works */
+	if (sockmain)
+	{
+		closesocket(sockmain);
+
+		/* To avoid inconsistencies in the number of sock_init() */
+		sock_cleanup();
+	}
+
+}
+
+int pcap_remoteact_list(char *hostlist, char sep, int size, char *errbuf)
+{
+	struct activehosts *temp;	/* temp var needed to scan the host list chain */
+	size_t len;
+	char hoststr[RPCAP_HOSTLIST_SIZE + 1];
+
+	temp = activeHosts;
+
+	len = 0;
+	*hostlist = 0;
+
+	while (temp)
+	{
+		/*int sock_getascii_addrport(const struct sockaddr_storage *sockaddr, char *address, int addrlen, char *port, int portlen, int flags, char *errbuf, int errbuflen) */
+
+		/* Get the numeric form of the name of the connecting host */
+		if (sock_getascii_addrport((struct sockaddr_storage *) &temp->host, hoststr,
+			RPCAP_HOSTLIST_SIZE, NULL, 0, NI_NUMERICHOST, errbuf, PCAP_ERRBUF_SIZE) != -1)
+			/*	if (getnameinfo( (struct sockaddr *) &temp->host, sizeof (struct sockaddr_storage), hoststr, */
+			/*		RPCAP_HOSTLIST_SIZE, NULL, 0, NI_NUMERICHOST) ) */
+		{
+			/*	sock_geterror("getnameinfo(): ", errbuf, PCAP_ERRBUF_SIZE); */
+			return -1;
+		}
+
+		len = len + strlen(hoststr) + 1 /* the separator */;
+
+		if ((size < 0) || (len >= (size_t)size))
+		{
+			pcap_snprintf(errbuf, PCAP_ERRBUF_SIZE, "The string you provided is not able to keep "
+				"the hostnames for all the active connections");
+			return -1;
+		}
+
+		strlcat(hostlist, hoststr, PCAP_ERRBUF_SIZE);
+		hostlist[len - 1] = sep;
+		hostlist[len] = 0;
+
+		temp = temp->next;
+	}
+
+	return 0;
+}
diff --git a/pcap-nit.c b/pcap-nit.c
index a8355f9..1b626e2 100644
--- a/pcap-nit.c
+++ b/pcap-nit.c
@@ -114,11 +114,11 @@
 		if (cc < 0) {
 			if (errno == EWOULDBLOCK)
 				return (0);
-			snprintf(p->errbuf, sizeof(p->errbuf), "pcap_read: %s",
+			pcap_snprintf(p->errbuf, sizeof(p->errbuf), "pcap_read: %s",
 				pcap_strerror(errno));
 			return (-1);
 		}
-		bp = p->buffer;
+		bp = (u_char *)p->buffer;
 	} else
 		bp = p->bp;
 
@@ -168,7 +168,7 @@
 			continue;
 
 		default:
-			snprintf(p->errbuf, sizeof(p->errbuf),
+			pcap_snprintf(p->errbuf, sizeof(p->errbuf),
 			    "bad nit state %d", nh->nh_state);
 			return (-1);
 		}
@@ -206,7 +206,7 @@
 	strncpy(sa.sa_data, device, sizeof(sa.sa_data));
 	ret = sendto(p->fd, buf, size, 0, &sa, sizeof(sa));
 	if (ret == -1) {
-		snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "send: %s",
+		pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "send: %s",
 		    pcap_strerror(errno));
 		return (-1);
 	}
@@ -249,7 +249,7 @@
 		nioc.nioc_flags |= NF_PROMISC;
 
 	if (ioctl(p->fd, SIOCSNIT, &nioc) < 0) {
-		snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "SIOCSNIT: %s",
+		pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "SIOCSNIT: %s",
 		    pcap_strerror(errno));
 		return (-1);
 	}
@@ -280,15 +280,22 @@
 	memset(p, 0, sizeof(*p));
 	p->fd = fd = socket(AF_NIT, SOCK_RAW, NITPROTO_RAW);
 	if (fd < 0) {
-		snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
+		pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
 		    "socket: %s", pcap_strerror(errno));
 		goto bad;
 	}
 	snit.snit_family = AF_NIT;
-	(void)strncpy(snit.snit_ifname, p->opt.source, NITIFSIZ);
+	(void)strncpy(snit.snit_ifname, p->opt.device, NITIFSIZ);
 
 	if (bind(fd, (struct sockaddr *)&snit, sizeof(snit))) {
-		snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
+		/*
+		 * XXX - there's probably a particular bind error that
+		 * means "there's no such device" and a particular bind
+		 * error that means "that device doesn't support NIT";
+		 * they might be the same error, if they both end up
+		 * meaning "NIT doesn't know about that device".
+		 */
+		pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
 		    "bind: %s: %s", snit.snit_ifname, pcap_strerror(errno));
 		goto bad;
 	}
@@ -301,7 +308,7 @@
 	p->linktype = DLT_EN10MB;
 
 	p->bufsize = BUFSPACE;
-	p->buffer = (u_char *)malloc(p->bufsize);
+	p->buffer = malloc(p->bufsize);
 	if (p->buffer == NULL) {
 		strlcpy(p->errbuf, pcap_strerror(errno), PCAP_ERRBUF_SIZE);
 		goto bad;
@@ -348,11 +355,11 @@
 }
 
 pcap_t *
-pcap_create_interface(const char *device, char *ebuf)
+pcap_create_interface(const char *device _U_, char *ebuf)
 {
 	pcap_t *p;
 
-	p = pcap_create_common(device, ebuf, sizeof (struct pcap_nit));
+	p = pcap_create_common(ebuf, sizeof (struct pcap_nit));
 	if (p == NULL)
 		return (NULL);
 
@@ -360,8 +367,18 @@
 	return (p);
 }
 
+/*
+ * XXX - there's probably a particular bind error that means "that device
+ * doesn't support NIT"; if so, we should try a bind and use that.
+ */
+static int
+can_be_bound(const char *name _U_)
+{
+	return (1);
+}
+
 int
 pcap_platform_finddevs(pcap_if_t **alldevsp, char *errbuf)
 {
-	return (0);
+	return (pcap_findalldevs_interfaces(alldevsp, errbuf, can_be_bound));
 }
diff --git a/pcap-null.c b/pcap-null.c
index 934fb2c..b5fa3ab 100644
--- a/pcap-null.c
+++ b/pcap-null.c
@@ -36,7 +36,7 @@
 static char nosup[] = "live packet capture not supported on this system";
 
 pcap_t *
-pcap_create_interface(const char *device, char *ebuf)
+pcap_create_interface(const char *device _U_, char *ebuf)
 {
 	(void)strlcpy(ebuf, nosup, PCAP_ERRBUF_SIZE);
 	return (NULL);
@@ -45,5 +45,9 @@
 int
 pcap_platform_finddevs(pcap_if_t **alldevsp, char *errbuf)
 {
+	/*
+	 * There are no interfaces on which we can capture.
+	 */
+	*alldevsp = NULL;
 	return (0);
 }
diff --git a/pcap-pf.c b/pcap-pf.c
index e03b2ed..7346908 100644
--- a/pcap-pf.c
+++ b/pcap-pf.c
@@ -107,7 +107,7 @@
 #ifdef LBL_ALIGN
 	struct enstamp stamp;
 #endif
-	register int pad;
+	register u_int pad;
 
  again:
 	cc = pc->cc;
@@ -127,11 +127,11 @@
 				(void)lseek(pc->fd, 0L, SEEK_SET);
 				goto again;
 			}
-			snprintf(pc->errbuf, sizeof(pc->errbuf), "pf read: %s",
+			pcap_snprintf(pc->errbuf, sizeof(pc->errbuf), "pf read: %s",
 				pcap_strerror(errno));
 			return (-1);
 		}
-		bp = pc->buffer + pc->offset;
+		bp = (u_char *)pc->buffer + pc->offset;
 	} else
 		bp = pc->bp;
 	/*
@@ -160,7 +160,7 @@
 			}
 		}
 		if (cc < sizeof(*sp)) {
-			snprintf(pc->errbuf, sizeof(pc->errbuf),
+			pcap_snprintf(pc->errbuf, sizeof(pc->errbuf),
 			    "pf short read (%d)", cc);
 			return (-1);
 		}
@@ -172,7 +172,7 @@
 #endif
 			sp = (struct enstamp *)bp;
 		if (sp->ens_stamplen != sizeof(*sp)) {
-			snprintf(pc->errbuf, sizeof(pc->errbuf),
+			pcap_snprintf(pc->errbuf, sizeof(pc->errbuf),
 			    "pf short stamplen (%d)",
 			    sp->ens_stamplen);
 			return (-1);
@@ -232,7 +232,7 @@
 
 	ret = write(p->fd, buf, size);
 	if (ret == -1) {
-		snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "send: %s",
+		pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "send: %s",
 		    pcap_strerror(errno));
 		return (-1);
 	}
@@ -321,14 +321,17 @@
 	 * its argument, even though it takes a "char *" rather than a
 	 * "const char *" as its first argument.  That appears to be
 	 * the case, at least on Digital UNIX 4.0.
+	 *
+	 * XXX - is there an error that means "no such device"?  Is
+	 * there one that means "that device doesn't support pf"?
 	 */
-	p->fd = pfopen(p->opt.source, O_RDWR);
+	p->fd = pfopen(p->opt.device, O_RDWR);
 	if (p->fd == -1 && errno == EACCES)
-		p->fd = pfopen(p->opt.source, O_RDONLY);
+		p->fd = pfopen(p->opt.device, O_RDONLY);
 	if (p->fd < 0) {
-		snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "pf open: %s: %s\n\
+		pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "pf open: %s: %s\n\
 your system may not be properly configured; see the packetfilter(4) man page\n",
-			p->opt.source, pcap_strerror(errno));
+			p->opt.device, pcap_strerror(errno));
 		goto bad;
 	}
 	pf->OrigMissed = -1;
@@ -338,7 +341,7 @@
 	if (p->opt.promisc)
 		enmode |= ENPROMISC;
 	if (ioctl(p->fd, EIOCMBIS, (caddr_t)&enmode) < 0) {
-		snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "EIOCMBIS: %s",
+		pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "EIOCMBIS: %s",
 		    pcap_strerror(errno));
 		goto bad;
 	}
@@ -349,13 +352,13 @@
 #endif
 	/* set the backlog */
 	if (ioctl(p->fd, EIOCSETW, (caddr_t)&backlog) < 0) {
-		snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "EIOCSETW: %s",
+		pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "EIOCSETW: %s",
 		    pcap_strerror(errno));
 		goto bad;
 	}
 	/* discover interface type */
 	if (ioctl(p->fd, EIOCDEVP, (caddr_t)&devparams) < 0) {
-		snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "EIOCDEVP: %s",
+		pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "EIOCDEVP: %s",
 		    pcap_strerror(errno));
 		goto bad;
 	}
@@ -437,7 +440,7 @@
 		 * framing", there's not much we can do, as that
 		 * doesn't specify a particular type of header.
 		 */
-		snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
+		pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
 		    "unknown data-link type %u", devparams.end_dev_type);
 		goto bad;
 	}
@@ -450,7 +453,7 @@
 	} else
 		p->fddipad = 0;
 	if (ioctl(p->fd, EIOCTRUNCATE, (caddr_t)&p->snapshot) < 0) {
-		snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "EIOCTRUNCATE: %s",
+		pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "EIOCTRUNCATE: %s",
 		    pcap_strerror(errno));
 		goto bad;
 	}
@@ -459,7 +462,7 @@
 	Filter.enf_Priority = 37;	/* anything > 2 */
 	Filter.enf_FilterLen = 0;	/* means "always true" */
 	if (ioctl(p->fd, EIOCSETF, (caddr_t)&Filter) < 0) {
-		snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "EIOCSETF: %s",
+		pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "EIOCSETF: %s",
 		    pcap_strerror(errno));
 		goto bad;
 	}
@@ -469,14 +472,14 @@
 		timeout.tv_sec = p->opt.timeout / 1000;
 		timeout.tv_usec = (p->opt.timeout * 1000) % 1000000;
 		if (ioctl(p->fd, EIOCSRTIMEOUT, (caddr_t)&timeout) < 0) {
-			snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "EIOCSRTIMEOUT: %s",
+			pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "EIOCSRTIMEOUT: %s",
 				pcap_strerror(errno));
 			goto bad;
 		}
 	}
 
 	p->bufsize = BUFSPACE;
-	p->buffer = (u_char*)malloc(p->bufsize + p->offset);
+	p->buffer = malloc(p->bufsize + p->offset);
 	if (p->buffer == NULL) {
 		strlcpy(p->errbuf, pcap_strerror(errno), PCAP_ERRBUF_SIZE);
 		goto bad;
@@ -503,11 +506,11 @@
 }
 
 pcap_t *
-pcap_create_interface(const char *device, char *ebuf)
+pcap_create_interface(const char *device _U_, char *ebuf)
 {
 	pcap_t *p;
 
-	p = pcap_create_common(device, ebuf, sizeof (struct pcap_pf));
+	p = pcap_create_common(ebuf, sizeof (struct pcap_pf));
 	if (p == NULL)
 		return (NULL);
 
@@ -515,10 +518,20 @@
 	return (p);
 }
 
+/*
+ * XXX - is there an error from pfopen() that means "no such device"?
+ * Is there one that means "that device doesn't support pf"?
+ */
+static int
+can_be_bound(const char *name _U_)
+{
+	return (1);
+}
+
 int
 pcap_platform_finddevs(pcap_if_t **alldevsp, char *errbuf)
 {
-	return (0);
+	return (pcap_findalldevs_interfaces(alldevsp, errbuf, can_be_bound));
 }
 
 static int
@@ -547,7 +560,7 @@
 			 * Yes.  Try to install the filter.
 			 */
 			if (ioctl(p->fd, BIOCSETF, (caddr_t)fp) < 0) {
-				snprintf(p->errbuf, sizeof(p->errbuf),
+				pcap_snprintf(p->errbuf, sizeof(p->errbuf),
 				    "BIOCSETF: %s", pcap_strerror(errno));
 				return (-1);
 			}
diff --git a/pcap-rpcap.c b/pcap-rpcap.c
new file mode 100644
index 0000000..b954058
--- /dev/null
+++ b/pcap-rpcap.c
@@ -0,0 +1,2127 @@
+/*
+ * Copyright (c) 2002 - 2005 NetGroup, Politecnico di Torino (Italy)
+ * Copyright (c) 2005 - 2008 CACE Technologies, Davis (California)
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the Politecnico di Torino, CACE Technologies
+ * nor the names of its contributors may be used to endorse or promote
+ * products derived from this software without specific prior written
+ * permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <string.h>		/* for strlen(), ... */
+#include <stdlib.h>		/* for malloc(), free(), ... */
+#include <stdarg.h>		/* for functions with variable number of arguments */
+#include <errno.h>		/* for the errno variable */
+#include "pcap-int.h"
+#include "pcap-rpcap.h"
+#include "sockutils.h"
+
+/*
+ * \file pcap-rpcap.c
+ *
+ * This file keeps all the new funtions that are needed for the RPCAP protocol.
+ * Almost all the pcap functions need to be modified in order to become compatible
+ * with the RPCAP protocol. However, you can find here only the ones that are completely new.
+ *
+ * This file keeps also the functions that are 'private', i.e. are needed by the RPCAP
+ * protocol but are not exported to the user.
+ *
+ * \warning All the RPCAP functions that are allowed to return a buffer containing
+ * the error description can return max PCAP_ERRBUF_SIZE characters.
+ * However there is no guarantees that the string will be zero-terminated.
+ * Best practice is to define the errbuf variable as a char of size 'PCAP_ERRBUF_SIZE+1'
+ * and to insert manually a NULL character at the end of the buffer. This will
+ * guarantee that no buffer overflows occur even if we use the printf() to show
+ * the error on the screen.
+ */
+
+#define PCAP_STATS_STANDARD	0	/* Used by pcap_stats_remote to see if we want standard or extended statistics */
+#define PCAP_STATS_EX		1	/* Used by pcap_stats_remote to see if we want standard or extended statistics */
+
+/* Keeps a list of all the opened connections in the active mode. */
+struct activehosts *activeHosts;
+
+/*
+ * Private data for capturing on WinPcap devices.
+ */
+struct pcap_win {
+	int nonblock;
+	int rfmon_selfstart;		/* a flag tells whether the monitor mode is set by itself */
+	int filtering_in_kernel;	/* using kernel filter */
+
+#ifdef HAVE_DAG_API
+	int	dag_fcs_bits;		/* Number of checksum bits from link layer */
+#endif
+};
+
+/****************************************************
+ *                                                  *
+ * Locally defined functions                        *
+ *                                                  *
+ ****************************************************/
+static int rpcap_checkver(SOCKET sock, struct rpcap_header *header, char *errbuf);
+static struct pcap_stat *rpcap_stats_remote(pcap_t *p, struct pcap_stat *ps, int mode);
+static int pcap_pack_bpffilter(pcap_t *fp, char *sendbuf, int *sendbufidx, struct bpf_program *prog);
+static int pcap_createfilter_norpcappkt(pcap_t *fp, struct bpf_program *prog);
+static int pcap_updatefilter_remote(pcap_t *fp, struct bpf_program *prog);
+static int pcap_setfilter_remote(pcap_t *fp, struct bpf_program *prog);
+static int pcap_setsampling_remote(pcap_t *p);
+
+
+/****************************************************
+ *                                                  *
+ * Function bodies                                  *
+ *                                                  *
+ ****************************************************/
+
+/*
+ * \ingroup remote_pri_func
+ *
+ * \brief 	It traslates (i.e. de-serializes) a 'sockaddr_storage' structure from
+ * the network byte order to the host byte order.
+ *
+ * It accepts a 'sockaddr_storage' structure as it is received from the network and it
+ * converts it into the host byte order (by means of a set of ntoh() ).
+ * The function will allocate the 'sockaddrout' variable according to the address family
+ * in use. In case the address does not belong to the AF_INET nor AF_INET6 families,
+ * 'sockaddrout' is not allocated and a NULL pointer is returned.
+ * This usually happens because that address does not exist on the other host, so the
+ * RPCAP daemon sent a 'sockaddr_storage' structure containing all 'zero' values.
+ *
+ * \param sockaddrin: a 'sockaddr_storage' pointer to the variable that has to be
+ * de-serialized.
+ *
+ * \param sockaddrout: a 'sockaddr_storage' pointer to the variable that will contain
+ * the de-serialized data. The structure returned can be either a 'sockaddr_in' or 'sockaddr_in6'.
+ * This variable will be allocated automatically inside this function.
+ *
+ * \param errbuf: a pointer to a user-allocated buffer (of size PCAP_ERRBUF_SIZE)
+ * that will contain the error message (in case there is one).
+ *
+ * \return '0' if everything is fine, '-1' if some errors occurred. Basically, the error
+ * can be only the fact that the malloc() failed to allocate memory.
+ * The error message is returned in the 'errbuf' variable, while the deserialized address
+ * is returned into the 'sockaddrout' variable.
+ *
+ * \warning This function supports only AF_INET and AF_INET6 address families.
+ *
+ * \warning The sockaddrout (if not NULL) must be deallocated by the user.
+ */
+int rpcap_deseraddr(struct sockaddr_storage *sockaddrin, struct sockaddr_storage **sockaddrout, char *errbuf)
+{
+	/* Warning: we support only AF_INET and AF_INET6 */
+	if (ntohs(sockaddrin->ss_family) == AF_INET)
+	{
+		struct sockaddr_in *sockaddr;
+
+		sockaddr = (struct sockaddr_in *) sockaddrin;
+		sockaddr->sin_family = ntohs(sockaddr->sin_family);
+		sockaddr->sin_port = ntohs(sockaddr->sin_port);
+
+		(*sockaddrout) = (struct sockaddr_storage *) malloc(sizeof(struct sockaddr_in));
+		if ((*sockaddrout) == NULL)
+		{
+			pcap_snprintf(errbuf, PCAP_ERRBUF_SIZE, "malloc() failed: %s", pcap_strerror(errno));
+			return -1;
+		}
+		memcpy(*sockaddrout, sockaddr, sizeof(struct sockaddr_in));
+		return 0;
+	}
+	if (ntohs(sockaddrin->ss_family) == AF_INET6)
+	{
+		struct sockaddr_in6 *sockaddr;
+
+		sockaddr = (struct sockaddr_in6 *) sockaddrin;
+		sockaddr->sin6_family = ntohs(sockaddr->sin6_family);
+		sockaddr->sin6_port = ntohs(sockaddr->sin6_port);
+		sockaddr->sin6_flowinfo = ntohl(sockaddr->sin6_flowinfo);
+		sockaddr->sin6_scope_id = ntohl(sockaddr->sin6_scope_id);
+
+		(*sockaddrout) = (struct sockaddr_storage *) malloc(sizeof(struct sockaddr_in6));
+		if ((*sockaddrout) == NULL)
+		{
+			pcap_snprintf(errbuf, PCAP_ERRBUF_SIZE, "malloc() failed: %s", pcap_strerror(errno));
+			return -1;
+		}
+		memcpy(*sockaddrout, sockaddr, sizeof(struct sockaddr_in6));
+		return 0;
+	}
+
+	/* It is neither AF_INET nor AF_INET6 */
+	*sockaddrout = NULL;
+	return 0;
+}
+
+/* \ingroup remote_pri_func
+ *
+ * \brief It reads a packet from the network socket. This does not make use of
+ * callback (hence the "nocb" string into its name).
+ *
+ * This function is called by the several pcap_next_ex() when they detect that
+ * we have a remote capture and they are the client side. In that case, they need
+ * to read packets from the socket.
+ *
+ * Parameters and return values are exactly the same of the pcap_next_ex().
+ *
+ * \warning By choice, this function does not make use of semaphores. A smarter
+ * implementation should put a semaphore into the data thread, and a signal will
+ * be raised as soon as there is data into the socket buffer.
+ * However this is complicated and it does not bring any advantages when reading
+ * from the network, in which network delays can be much more important than
+ * these optimizations. Therefore, we chose the following approach:
+ * - the 'timeout' chosen by the user is split in two (half on the server side,
+ * with the usual meaning, and half on the client side)
+ * - this function checks for packets; if there are no packets, it waits for
+ * timeout/2 and then it checks again. If packets are still missing, it returns,
+ * otherwise it reads packets.
+ */
+static int pcap_read_nocb_remote(pcap_t *p, struct pcap_pkthdr **pkt_header, u_char **pkt_data)
+{
+	struct rpcap_header *header;		/* general header according to the RPCAP format */
+	struct rpcap_pkthdr *net_pkt_header;	/* header of the packet */
+	char netbuf[RPCAP_NETBUF_SIZE];		/* size of the network buffer in which the packet is copied, just for UDP */
+	uint32 totread;				/* number of bytes (of payload) currently read from the network (referred to the current pkt) */
+	int nread;
+	int retval;				/* generic return value */
+
+	/* Structures needed for the select() call */
+	fd_set rfds;				/* set of socket descriptors we have to check */
+	struct timeval tv;			/* maximum time the select() can block waiting for data */
+	struct pcap_md *md;			/* structure used when doing a remote live capture */
+
+	md = (struct pcap_md *) ((u_char*)p->priv + sizeof(struct pcap_win));
+
+	/*
+	 * Define the read timeout, to be used in the select()
+	 * 'timeout', in pcap_t, is in milliseconds; we have to convert it into sec and microsec
+	 */
+	tv.tv_sec = p->opt.timeout / 1000;
+	tv.tv_usec = (p->opt.timeout - tv.tv_sec * 1000) * 1000;
+
+	/* Watch out sockdata to see if it has input */
+	FD_ZERO(&rfds);
+
+	/*
+	 * 'fp->rmt_sockdata' has always to be set before calling the select(),
+	 * since it is cleared by the select()
+	 */
+	FD_SET(md->rmt_sockdata, &rfds);
+
+	retval = select((int) md->rmt_sockdata + 1, &rfds, NULL, NULL, &tv);
+	if (retval == -1)
+	{
+		sock_geterror("select(): ", p->errbuf, PCAP_ERRBUF_SIZE);
+		return -1;
+	}
+
+	/* There is no data waiting, so return '0' */
+	if (retval == 0)
+		return 0;
+
+	/*
+	 * data is here; so, let's copy it into the user buffer.
+	 * I'm going to read a new packet; so I reset the number of bytes (payload only) read
+	 */
+	totread = 0;
+
+	/*
+	 * We have to define 'header' as a pointer to a larger buffer,
+	 * because in case of UDP we have to read all the message within a single call
+	 */
+	header = (struct rpcap_header *) netbuf;
+	net_pkt_header = (struct rpcap_pkthdr *) (netbuf + sizeof(struct rpcap_header));
+
+	if (md->rmt_flags & PCAP_OPENFLAG_DATATX_UDP)
+	{
+		/* Read the entire message from the network */
+		if (sock_recv(md->rmt_sockdata, netbuf, RPCAP_NETBUF_SIZE, SOCK_RECEIVEALL_NO, p->errbuf, PCAP_ERRBUF_SIZE) == -1)
+			return -1;
+	}
+	else
+	{
+		if (sock_recv(md->rmt_sockdata, netbuf, sizeof(struct rpcap_header), SOCK_RECEIVEALL_YES, p->errbuf, PCAP_ERRBUF_SIZE) == -1)
+			return -1;
+	}
+
+	/* Checks if the message is correct */
+	retval = rpcap_checkmsg(p->errbuf, md->rmt_sockdata, header, RPCAP_MSG_PACKET, 0);
+
+	if (retval != RPCAP_MSG_PACKET)		/* the message is not the one expected */
+	{
+		switch (retval)
+		{
+		case -3:		/* Unrecoverable network error */
+			return -1;	/* Do nothing; just exit from here; the error code is already into the errbuf */
+
+		case -2:		/* The other endpoint sent a message that is not allowed here */
+		case -1:		/* The other endpoint has a version number that is not compatible with our */
+			return 0;	/* Return 'no packets received' */
+
+		default:
+			SOCK_ASSERT("Internal error", 1);
+			return 0;	/* Return 'no packets received' */
+		}
+	}
+
+	/* In case of TCP, read the remaining of the packet from the socket */
+	if (!(md->rmt_flags & PCAP_OPENFLAG_DATATX_UDP))
+	{
+		/* Read the RPCAP packet header from the network */
+		nread = sock_recv(md->rmt_sockdata, (char *)net_pkt_header,
+		    sizeof(struct rpcap_pkthdr), SOCK_RECEIVEALL_YES,
+		    p->errbuf, PCAP_ERRBUF_SIZE);
+		if (nread == -1)
+			return -1;
+		totread += nread;
+	}
+
+	if ((ntohl(net_pkt_header->caplen) + sizeof(struct pcap_pkthdr)) <= p->bufsize)
+	{
+		/* Initialize returned structures */
+		*pkt_header = (struct pcap_pkthdr *) p->buffer;
+		*pkt_data = (u_char*)p->buffer + sizeof(struct pcap_pkthdr);
+
+		(*pkt_header)->caplen = ntohl(net_pkt_header->caplen);
+		(*pkt_header)->len = ntohl(net_pkt_header->len);
+		(*pkt_header)->ts.tv_sec = ntohl(net_pkt_header->timestamp_sec);
+		(*pkt_header)->ts.tv_usec = ntohl(net_pkt_header->timestamp_usec);
+
+		/*
+		 * I don't update the counter of the packets dropped by the network since we're using TCP,
+		 * therefore no packets are dropped. Just update the number of packets received correctly
+		 */
+		md->TotCapt++;
+
+		/* Copies the packet into the data buffer */
+		if (md->rmt_flags & PCAP_OPENFLAG_DATATX_UDP)
+		{
+			unsigned int npkt;
+
+			/*
+			 * In case of UDP the packet has already been read, we have to copy it into 'buffer'.
+			 * Another option should be to declare 'netbuf' as 'static'. However this prevents
+			 * using several pcap instances within the same process (because the static buffer is shared among
+			 * all processes)
+			 */
+			memcpy(*pkt_data, netbuf + sizeof(struct rpcap_header) + sizeof(struct rpcap_pkthdr), (*pkt_header)->caplen);
+
+			/* We're using UDP, so we need to update the counter of the packets dropped by the network */
+			npkt = ntohl(net_pkt_header->npkt);
+
+			if (md->TotCapt != npkt)
+			{
+				md->TotNetDrops += (npkt - md->TotCapt);
+				md->TotCapt = npkt;
+			}
+
+		}
+		else
+		{
+			/* In case of TCP, read the remaining of the packet from the socket */
+			nread = sock_recv(md->rmt_sockdata, *pkt_data,
+			    (*pkt_header)->caplen, SOCK_RECEIVEALL_YES,
+			    p->errbuf, PCAP_ERRBUF_SIZE);
+			if (nread == -1)
+				return -1;
+			totread += nread;
+
+			/* Checks if all the data has been read; if not, discard the data in excess */
+			/* This check has to be done only on TCP connections */
+			if (totread != ntohl(header->plen))
+				sock_discard(md->rmt_sockdata, ntohl(header->plen) - totread, NULL, 0);
+		}
+
+
+		/* Packet read successfully */
+		return 1;
+	}
+	else
+	{
+		pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "Received a packet that is larger than the internal buffer size.");
+		return -1;
+	}
+
+}
+
+/* \ingroup remote_pri_func
+ *
+ * \brief It reads a packet from the network socket.
+ *
+ * This function is called by the several pcap_read() when they detect that
+ * we have a remote capture and they are the client side. In that case, they need
+ * to read packets from the socket.
+ *
+ * This function relies on the pcap_read_nocb_remote to deliver packets. The
+ * difference, here, is that as soon as a packet is read, it is delivered
+ * to the application by means of a callback function.
+ *
+ * Parameters and return values are exactly the same of the pcap_read().
+ */
+static int pcap_read_remote(pcap_t *p, int cnt, pcap_handler callback, u_char *user)
+{
+	struct pcap_pkthdr *pkt_header;
+	u_char *pkt_data;
+	int n = 0;
+
+	while ((n < cnt) || (cnt < 0))
+	{
+		if (pcap_read_nocb_remote(p, &pkt_header, &pkt_data) == 1)
+		{
+			(*callback)(user, pkt_header, pkt_data);
+			n++;
+		}
+		else
+			return n;
+	}
+	return n;
+}
+
+/* \ingroup remote_pri_func
+ *
+ * \brief It sends a CLOSE command to the capture server.
+ *
+ * This function is called when the user wants to close a pcap_t adapter.
+ * In case we're capturing from the network, it sends a command to the other
+ * peer that says 'ok, let's stop capturing'.
+ * This function is called automatically when the user calls the pcap_close().
+ *
+ * Parameters and return values are exactly the same of the pcap_close().
+ *
+ * \warning Since we're closing the connection, we do not check for errors.
+ */
+static void pcap_cleanup_remote(pcap_t *fp)
+{
+	struct rpcap_header header;		/* header of the RPCAP packet */
+	struct activehosts *temp;		/* temp var needed to scan the host list chain, to detect if we're in active mode */
+	int active = 0;					/* active mode or not? */
+	struct pcap_md *md;				/* structure used when doing a remote live capture */
+
+	md = (struct pcap_md *) ((u_char*)fp->priv + sizeof(struct pcap_win));
+
+	/* detect if we're in active mode */
+	temp = activeHosts;
+	while (temp)
+	{
+		if (temp->sockctrl == md->rmt_sockctrl)
+		{
+			active = 1;
+			break;
+		}
+		temp = temp->next;
+	}
+
+	if (!active)
+	{
+		rpcap_createhdr(&header, RPCAP_MSG_CLOSE, 0, 0);
+
+		/* I don't check for errors, since I'm going to close everything */
+		sock_send(md->rmt_sockctrl, (char *)&header, sizeof(struct rpcap_header), NULL, 0);
+	}
+	else
+	{
+		rpcap_createhdr(&header, RPCAP_MSG_ENDCAP_REQ, 0, 0);
+
+		/* I don't check for errors, since I'm going to close everything */
+		sock_send(md->rmt_sockctrl, (char *)&header, sizeof(struct rpcap_header), NULL, 0);
+
+		/* wait for the answer */
+		/* Don't check what we got, since the present libpcap does not uses this pcap_t anymore */
+		sock_recv(md->rmt_sockctrl, (char *)&header, sizeof(struct rpcap_header), SOCK_RECEIVEALL_YES, NULL, 0);
+
+		if (ntohl(header.plen) != 0)
+			sock_discard(md->rmt_sockctrl, ntohl(header.plen), NULL, 0);
+	}
+
+	if (md->rmt_sockdata)
+	{
+		sock_close(md->rmt_sockdata, NULL, 0);
+		md->rmt_sockdata = 0;
+	}
+
+	if ((!active) && (md->rmt_sockctrl))
+		sock_close(md->rmt_sockctrl, NULL, 0);
+
+	md->rmt_sockctrl = 0;
+
+	if (md->currentfilter)
+	{
+		free(md->currentfilter);
+		md->currentfilter = NULL;
+	}
+
+	/* To avoid inconsistencies in the number of sock_init() */
+	sock_cleanup();
+}
+
+/* \ingroup remote_pri_func
+ *
+ * \brief It retrieves network statistics from the other peer.
+ *
+ * This function is just a void cointainer, since the work is done by the rpcap_stats_remote().
+ * See that funcion for more details.
+ *
+ * Parameters and return values are exactly the same of the pcap_stats().
+ */
+static int pcap_stats_remote(pcap_t *p, struct pcap_stat *ps)
+{
+	struct pcap_stat *retval;
+
+	retval = rpcap_stats_remote(p, ps, PCAP_STATS_STANDARD);
+
+	if (retval)
+		return 0;
+	else
+		return -1;
+}
+
+#ifdef _WIN32
+/* \ingroup remote_pri_func
+ *
+ * \brief It retrieves network statistics from the other peer.
+ *
+ * This function is just a void cointainer, since the work is done by the rpcap_stats_remote().
+ * See that funcion for more details.
+ *
+ * Parameters and return values are exactly the same of the pcap_stats_ex().
+ */
+static struct pcap_stat *pcap_stats_ex_remote(pcap_t *p, int *pcap_stat_size)
+{
+	*pcap_stat_size = sizeof (p->stat);
+
+	/* PCAP_STATS_EX (third param) means 'extended pcap_stats()' */
+	return (rpcap_stats_remote(p, &(p->stat), PCAP_STATS_EX));
+}
+#endif
+
+/* \ingroup remote_pri_func
+ *
+ * \brief It retrieves network statistics from the other peer.
+ *
+ * This function can be called in two modes:
+ * - PCAP_STATS_STANDARD: if we want just standard statistics (i.e. the pcap_stats() )
+ * - PCAP_STATS_EX: if we want extended statistics (i.e. the pcap_stats_ex() )
+ *
+ * This 'mode' parameter is needed because in the standard pcap_stats() the variable that keeps the
+ * statistics is allocated by the user. Unfortunately, this structure has been extended in order
+ * to keep new stats. However, if the user has a smaller structure and it passes it to the pcap_stats,
+ * thid function will try to fill in more data than the size of the structure, so that the application
+ * goes in memory overflow.
+ * So, we need to know it we have to copy just the standard fields, or the extended fields as well.
+ *
+ * In case we want to copy the extended fields as well, the problem of memory overflow does no
+ * longer exist because the structure pcap_stat is no longer allocated by the program;
+ * it is allocated by the library instead.
+ *
+ * \param p: the pcap_t structure related to the current instance.
+ *
+ * \param ps: a 'pcap_stat' structure, needed for compatibility with pcap_stat(), in which
+ * the structure is allocated by the user. In case of pcap_stats_ex, this structure and the
+ * function return value point to the same variable.
+ *
+ * \param mode: one of PCAP_STATS_STANDARD or PCAP_STATS_EX.
+ *
+ * \return The structure that keeps the statistics, or NULL in case of error.
+ * The error string is placed in the pcap_t structure.
+ */
+static struct pcap_stat *rpcap_stats_remote(pcap_t *p, struct pcap_stat *ps, int mode)
+{
+	struct rpcap_header header;		/* header of the RPCAP packet */
+	struct rpcap_stats netstats;		/* statistics sent on the network */
+	uint32 totread = 0;			/* number of bytes of the payload read from the socket */
+	int nread;
+	int retval;				/* temp variable which stores functions return value */
+	struct pcap_md *md;			/* structure used when doing a remote live capture */
+
+	md = (struct pcap_md *) ((u_char*)p->priv + sizeof(struct pcap_win));
+
+	/*
+	 * If the capture has still to start, we cannot ask statistics to the other peer,
+	 * so we return a fake number
+	 */
+	if (!md->rmt_capstarted)
+	{
+		if (mode == PCAP_STATS_STANDARD)
+		{
+			ps->ps_drop = 0;
+			ps->ps_ifdrop = 0;
+			ps->ps_recv = 0;
+		}
+		else
+		{
+			ps->ps_capt = 0;
+			ps->ps_drop = 0;
+			ps->ps_ifdrop = 0;
+			ps->ps_netdrop = 0;
+			ps->ps_recv = 0;
+			ps->ps_sent = 0;
+		}
+
+		return ps;
+	}
+
+	rpcap_createhdr(&header, RPCAP_MSG_STATS_REQ, 0, 0);
+
+	/* Send the PCAP_STATS command */
+	if (sock_send(md->rmt_sockctrl, (char *)&header, sizeof(struct rpcap_header), p->errbuf, PCAP_ERRBUF_SIZE))
+		goto error;
+
+	/* Receive the RPCAP stats reply message */
+	if (sock_recv(md->rmt_sockctrl, (char *)&header, sizeof(struct rpcap_header), SOCK_RECEIVEALL_YES, p->errbuf, PCAP_ERRBUF_SIZE) == -1)
+		goto error;
+
+	/* Checks if the message is correct */
+	retval = rpcap_checkmsg(p->errbuf, md->rmt_sockctrl, &header, RPCAP_MSG_STATS_REPLY, RPCAP_MSG_ERROR, 0);
+
+	if (retval != RPCAP_MSG_STATS_REPLY)		/* the message is not the one expected */
+	{
+		switch (retval)
+		{
+		case -3:		/* Unrecoverable network error */
+		case -2:		/* The other endpoint send a message that is not allowed here */
+		case -1:		/* The other endpoint has a version number that is not compatible with our */
+			goto error;
+
+		case RPCAP_MSG_ERROR:		/* The other endpoint reported an error */
+			/* Update totread, since the rpcap_checkmsg() already purged the buffer */
+			totread = ntohl(header.plen);
+
+			/* Do nothing; just exit; the error code is already into the errbuf */
+			goto error;
+
+		default:
+			pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "Internal error");
+			goto error;
+		}
+	}
+
+	nread = sock_recv(md->rmt_sockctrl, (char *)&netstats,
+	    sizeof(struct rpcap_stats), SOCK_RECEIVEALL_YES,
+	    p->errbuf, PCAP_ERRBUF_SIZE);
+	if (nread == -1)
+		goto error;
+	totread += nread;
+
+	if (mode == PCAP_STATS_STANDARD)
+	{
+		ps->ps_drop = ntohl(netstats.krnldrop);
+		ps->ps_ifdrop = ntohl(netstats.ifdrop);
+		ps->ps_recv = ntohl(netstats.ifrecv);
+	}
+	else
+	{
+		ps->ps_capt = md->TotCapt;
+		ps->ps_drop = ntohl(netstats.krnldrop);
+		ps->ps_ifdrop = ntohl(netstats.ifdrop);
+		ps->ps_netdrop = md->TotNetDrops;
+		ps->ps_recv = ntohl(netstats.ifrecv);
+		ps->ps_sent = ntohl(netstats.svrcapt);
+	}
+
+	/* Checks if all the data has been read; if not, discard the data in excess */
+	if (totread != ntohl(header.plen))
+	{
+		if (sock_discard(md->rmt_sockctrl, ntohl(header.plen) - totread, NULL, 0) == 1)
+			goto error;
+	}
+
+	return ps;
+
+error:
+	if (totread != ntohl(header.plen))
+		sock_discard(md->rmt_sockctrl, ntohl(header.plen) - totread, NULL, 0);
+
+	return NULL;
+}
+
+/* \ingroup remote_pri_func
+ *
+ * \brief It opens a remote adapter by opening an RPCAP connection and so on.
+ *
+ * This function does basically the job of pcap_open_live() for a remote interface.
+ * In other words, we have a pcap_read for win32, which reads packets from NPF,
+ * another for LINUX, and so on. Now, we have a pcap_opensource_remote() as well.
+ * The difference, here, is the capture thread does not start until the
+ * pcap_startcapture_remote() is called.
+ *
+ * This is because, in remote capture, we cannot start capturing data as soon ad the
+ * 'open adapter' command is sent. Suppose the remote adapter is already overloaded;
+ * if we start a capture (which, by default, has a NULL filter) the new traffic can
+ * saturate the network.
+ *
+ * Instead, we want to "open" the adapter, then send a "start capture" command only
+ * when we're ready to start the capture.
+ * This funtion does this job: it sends a "open adapter" command (according to the
+ * RPCAP protocol), but it does not start the capture.
+ *
+ * Since the other libpcap functions do not share this way of life, we have to make
+ * some dirty things in order to make everyting working.
+ *
+ * \param fp: A pointer to a pcap_t structure that has been previously created with
+ * \ref pcap_create().
+ * \param source: see pcap_open().
+ * \param auth: see pcap_open().
+ *
+ * \return 0 in case of success, -1 otherwise. In case of success, the pcap_t pointer in fp can be
+ * used as a parameter to the following calls (pcap_compile() and so on). In case of
+ * problems, fp->errbuf contains a text explanation of error.
+ *
+ * \warning In case we call the pcap_compile() and the capture is not started, the filter
+ * will be saved into the pcap_t structure, and it will be sent to the other host later
+ * (when the pcap_startcapture_remote() is called).
+ */
+int pcap_opensource_remote(pcap_t *fp, struct pcap_rmtauth *auth)
+{
+	char host[PCAP_BUF_SIZE], ctrlport[PCAP_BUF_SIZE], iface[PCAP_BUF_SIZE];
+
+	char sendbuf[RPCAP_NETBUF_SIZE];	/* temporary buffer in which data to be sent is buffered */
+	int sendbufidx = 0;			/* index which keeps the number of bytes currently buffered */
+	uint32 totread = 0;			/* number of bytes of the payload read from the socket */
+	int nread;
+	int retval;				/* store the return value of the functions */
+	int active = 0;				/* '1' if we're in active mode */
+
+	/* socket-related variables */
+	struct addrinfo hints;			/* temp, needed to open a socket connection */
+	struct addrinfo *addrinfo;		/* temp, needed to open a socket connection */
+	SOCKET sockctrl = 0;			/* socket descriptor of the control connection */
+
+	/* RPCAP-related variables */
+	struct rpcap_header header;		/* header of the RPCAP packet */
+	struct rpcap_openreply openreply;	/* open reply message */
+
+	struct pcap_md *md;			/* structure used when doing a remote live capture */
+
+	md = (struct pcap_md *) ((u_char*)fp->priv + sizeof(struct pcap_win));
+
+
+	/*
+	 * determine the type of the source (NULL, file, local, remote)
+	 * You must have a valid source string even if we're in active mode, because otherwise
+	 * the call to the following function will fail.
+	 */
+	if (pcap_parsesrcstr(fp->opt.device, &retval, host, ctrlport, iface, fp->errbuf) == -1)
+		return -1;
+
+	if (retval != PCAP_SRC_IFREMOTE)
+	{
+		pcap_snprintf(fp->errbuf, PCAP_ERRBUF_SIZE, "This function is able to open only remote interfaces");
+		return -1;
+	}
+
+	addrinfo = NULL;
+
+	/*
+	 * Warning: this call can be the first one called by the user.
+	 * For this reason, we have to initialize the WinSock support.
+	 */
+	if (sock_init(fp->errbuf, PCAP_ERRBUF_SIZE) == -1)
+		return -1;
+
+	sockctrl = rpcap_remoteact_getsock(host, &active, fp->errbuf);
+	if (sockctrl == INVALID_SOCKET)
+		return -1;
+
+	if (!active)
+	{
+		/*
+		 * We're not in active mode; let's try to open a new
+		 * control connection.
+		 */
+		memset(&hints, 0, sizeof(struct addrinfo));
+		hints.ai_family = PF_UNSPEC;
+		hints.ai_socktype = SOCK_STREAM;
+
+		if ((ctrlport == NULL) || (ctrlport[0] == 0))
+		{
+			/* the user chose not to specify the port */
+			if (sock_initaddress(host, RPCAP_DEFAULT_NETPORT, &hints, &addrinfo, fp->errbuf, PCAP_ERRBUF_SIZE) == -1)
+				return -1;
+		}
+		else
+		{
+			/* the user chose not to specify the port */
+			if (sock_initaddress(host, ctrlport, &hints, &addrinfo, fp->errbuf, PCAP_ERRBUF_SIZE) == -1)
+				return -1;
+		}
+
+		if ((sockctrl = sock_open(addrinfo, SOCKOPEN_CLIENT, 0, fp->errbuf, PCAP_ERRBUF_SIZE)) == INVALID_SOCKET)
+			goto error;
+
+		freeaddrinfo(addrinfo);
+		addrinfo = NULL;
+
+		if (rpcap_sendauth(sockctrl, auth, fp->errbuf) == -1)
+			goto error;
+	}
+
+	/*
+	 * Now it's time to start playing with the RPCAP protocol
+	 * RPCAP open command: create the request message
+	 */
+	if (sock_bufferize(NULL, sizeof(struct rpcap_header), NULL,
+		&sendbufidx, RPCAP_NETBUF_SIZE, SOCKBUF_CHECKONLY, fp->errbuf, PCAP_ERRBUF_SIZE))
+		goto error;
+
+	rpcap_createhdr((struct rpcap_header *) sendbuf, RPCAP_MSG_OPEN_REQ, 0, (uint32) strlen(iface));
+
+	if (sock_bufferize(iface, (int) strlen(iface), sendbuf, &sendbufidx,
+		RPCAP_NETBUF_SIZE, SOCKBUF_BUFFERIZE, fp->errbuf, PCAP_ERRBUF_SIZE))
+		goto error;
+
+	if (sock_send(sockctrl, sendbuf, sendbufidx, fp->errbuf, PCAP_ERRBUF_SIZE))
+		goto error;
+
+	/* Receive the RPCAP open reply message */
+	if (sock_recv(sockctrl, (char *)&header, sizeof(struct rpcap_header), SOCK_RECEIVEALL_YES, fp->errbuf, PCAP_ERRBUF_SIZE) == -1)
+		goto error;
+
+	/* Checks if the message is correct */
+	retval = rpcap_checkmsg(fp->errbuf, sockctrl, &header, RPCAP_MSG_OPEN_REPLY, RPCAP_MSG_ERROR, 0);
+
+	if (retval != RPCAP_MSG_OPEN_REPLY)		/* the message is not the one expected */
+	{
+		switch (retval)
+		{
+		case -3:		/* Unrecoverable network error */
+		case -2:		/* The other endpoint send a message that is not allowed here */
+		case -1:		/* The other endpoint has a version number that is not compatible with our */
+			goto error;
+
+		case RPCAP_MSG_ERROR:		/* The other endpoint reported an error */
+			/* Update totread, since the rpcap_checkmsg() already purged the buffer */
+			totread = ntohl(header.plen);
+			/* Do nothing; just exit; the error code is already into the errbuf */
+			goto error;
+
+		default:
+			pcap_snprintf(fp->errbuf, PCAP_ERRBUF_SIZE, "Internal error");
+			goto error;
+		}
+	}
+
+	nread = sock_recv(sockctrl, (char *)&openreply,
+	    sizeof(struct rpcap_openreply), SOCK_RECEIVEALL_YES,
+	    fp->errbuf, PCAP_ERRBUF_SIZE);
+	if (nread == -1)
+		goto error;
+	totread += nread;
+
+	/* Set proper fields into the pcap_t struct */
+	fp->linktype = ntohl(openreply.linktype);
+	fp->tzoff = ntohl(openreply.tzoff);
+	md->rmt_sockctrl = sockctrl;
+	md->rmt_clientside = 1;
+
+
+	/* This code is duplicated from the end of this function */
+	fp->read_op = pcap_read_remote;
+	fp->setfilter_op = pcap_setfilter_remote;
+	fp->getnonblock_op = NULL;	/* This is not implemented in remote capture */
+	fp->setnonblock_op = NULL;	/* This is not implemented in remote capture */
+	fp->stats_op = pcap_stats_remote;
+#ifdef _WIN32
+	fp->stats_ex_op = pcap_stats_ex_remote;
+#endif
+	fp->cleanup_op = pcap_cleanup_remote;
+
+	/* Checks if all the data has been read; if not, discard the data in excess */
+	if (totread != ntohl(header.plen))
+	{
+		if (sock_discard(sockctrl, ntohl(header.plen) - totread, NULL, 0) == 1)
+			goto error;
+	}
+	return 0;
+
+error:
+	/*
+	 * When the connection has been established, we have to close it. So, at the
+	 * beginning of this function, if an error occur we return immediately with
+	 * a return NULL; when the connection is established, we have to come here
+	 * ('goto error;') in order to close everything properly.
+	 *
+	 * Checks if all the data has been read; if not, discard the data in excess
+	 */
+	if (totread != ntohl(header.plen))
+		sock_discard(sockctrl, ntohl(header.plen) - totread, NULL, 0);
+
+	if (addrinfo)
+		freeaddrinfo(addrinfo);
+
+	if (!active)
+		sock_close(sockctrl, NULL, 0);
+
+	return -1;
+}
+
+/* \ingroup remote_pri_func
+ *
+ * \brief It starts a remote capture.
+ *
+ * This function is requires since the RPCAP protocol decouples the 'open' from the
+ * 'start capture' functions.
+ * This function takes all the parameters needed (which have been stored into the pcap_t structure)
+ * and sends them to the server.
+ * If everything is fine, it creates a new child thread that reads data from the network
+ * and puts data it into the user buffer.
+ * The pcap_read() will read data from the user buffer, as usual.
+ *
+ * The remote capture acts like a new "kernel", which puts packets directly into
+ * the buffer pointed by pcap_t.
+ * In fact, this function does not rely on a kernel that reads packets and put them
+ * into the user buffer; it has to do that on its own.
+ *
+ * \param fp: the pcap_t descriptor of the device currently open.
+ *
+ * \return '0' if everything is fine, '-1' otherwise. The error message (if one)
+ * is returned into the 'errbuf' field of the pcap_t structure.
+ */
+int pcap_startcapture_remote(pcap_t *fp)
+{
+	char sendbuf[RPCAP_NETBUF_SIZE];	/* temporary buffer in which data to be sent is buffered */
+	int sendbufidx = 0;			/* index which keeps the number of bytes currently buffered */
+	char portdata[PCAP_BUF_SIZE];		/* temp variable needed to keep the network port for the the data connection */
+	uint32 totread = 0;			/* number of bytes of the payload read from the socket */
+	int nread;
+	int retval;				/* store the return value of the functions */
+	int active = 0;				/* '1' if we're in active mode */
+	struct activehosts *temp;		/* temp var needed to scan the host list chain, to detect if we're in active mode */
+	char host[INET6_ADDRSTRLEN + 1];	/* numeric name of the other host */
+
+	/* socket-related variables*/
+	struct addrinfo hints;			/* temp, needed to open a socket connection */
+	struct addrinfo *addrinfo;		/* temp, needed to open a socket connection */
+	SOCKET sockdata = 0;			/* socket descriptor of the data connection */
+	struct sockaddr_storage saddr;		/* temp, needed to retrieve the network data port chosen on the local machine */
+	socklen_t saddrlen;			/* temp, needed to retrieve the network data port chosen on the local machine */
+	int ai_family;				/* temp, keeps the address family used by the control connection */
+
+	/* RPCAP-related variables*/
+	struct rpcap_header header;			/* header of the RPCAP packet */
+	struct rpcap_startcapreq *startcapreq;		/* start capture request message */
+	struct rpcap_startcapreply startcapreply;	/* start capture reply message */
+
+	/* Variables related to the buffer setting */
+	int res, itemp;
+	int sockbufsize = 0;
+
+	struct pcap_md *md;			/* structure used when doing a remote live capture */
+
+	md = (struct pcap_md *) ((u_char*)fp->priv + sizeof(struct pcap_win));
+
+	/*
+	 * Let's check if sampling has been required.
+	 * If so, let's set it first
+	 */
+	if (pcap_setsampling_remote(fp) != 0)
+		return -1;
+
+
+	/* detect if we're in active mode */
+	temp = activeHosts;
+	while (temp)
+	{
+		if (temp->sockctrl == md->rmt_sockctrl)
+		{
+			active = 1;
+			break;
+		}
+		temp = temp->next;
+	}
+
+	addrinfo = NULL;
+
+	/*
+	 * Gets the complete sockaddr structure used in the ctrl connection
+	 * This is needed to get the address family of the control socket
+	 * Tip: I cannot save the ai_family of the ctrl sock in the pcap_t struct,
+	 * since the ctrl socket can already be open in case of active mode;
+	 * so I would have to call getpeername() anyway
+	 */
+	saddrlen = sizeof(struct sockaddr_storage);
+	if (getpeername(md->rmt_sockctrl, (struct sockaddr *) &saddr, &saddrlen) == -1)
+	{
+		sock_geterror("getsockname(): ", fp->errbuf, PCAP_ERRBUF_SIZE);
+		goto error;
+	}
+	ai_family = ((struct sockaddr_storage *) &saddr)->ss_family;
+
+	/* Get the numeric address of the remote host we are connected to */
+	if (getnameinfo((struct sockaddr *) &saddr, saddrlen, host,
+		sizeof(host), NULL, 0, NI_NUMERICHOST))
+	{
+		sock_geterror("getnameinfo(): ", fp->errbuf, PCAP_ERRBUF_SIZE);
+		goto error;
+	}
+
+	/*
+	 * Data connection is opened by the server toward the client if:
+	 * - we're using TCP, and the user wants us to be in active mode
+	 * - we're using UDP
+	 */
+	if ((active) || (md->rmt_flags & PCAP_OPENFLAG_DATATX_UDP))
+	{
+		/*
+		 * We have to create a new socket to receive packets
+		 * We have to do that immediately, since we have to tell the other
+		 * end which network port we picked up
+		 */
+		memset(&hints, 0, sizeof(struct addrinfo));
+		/* TEMP addrinfo is NULL in case of active */
+		hints.ai_family = ai_family;	/* Use the same address family of the control socket */
+		hints.ai_socktype = (md->rmt_flags & PCAP_OPENFLAG_DATATX_UDP) ? SOCK_DGRAM : SOCK_STREAM;
+		hints.ai_flags = AI_PASSIVE;	/* Data connection is opened by the server toward the client */
+
+		/* Let's the server pick up a free network port for us */
+		if (sock_initaddress(NULL, "0", &hints, &addrinfo, fp->errbuf, PCAP_ERRBUF_SIZE) == -1)
+			goto error;
+
+		if ((sockdata = sock_open(addrinfo, SOCKOPEN_SERVER,
+			1 /* max 1 connection in queue */, fp->errbuf, PCAP_ERRBUF_SIZE)) == INVALID_SOCKET)
+			goto error;
+
+		/* addrinfo is no longer used */
+		freeaddrinfo(addrinfo);
+		addrinfo = NULL;
+
+		/* get the complete sockaddr structure used in the data connection */
+		saddrlen = sizeof(struct sockaddr_storage);
+		if (getsockname(sockdata, (struct sockaddr *) &saddr, &saddrlen) == -1)
+		{
+			sock_geterror("getsockname(): ", fp->errbuf, PCAP_ERRBUF_SIZE);
+			goto error;
+		}
+
+		/* Get the local port the system picked up */
+		if (getnameinfo((struct sockaddr *) &saddr, saddrlen, NULL,
+			0, portdata, sizeof(portdata), NI_NUMERICSERV))
+		{
+			sock_geterror("getnameinfo(): ", fp->errbuf, PCAP_ERRBUF_SIZE);
+			goto error;
+		}
+	}
+
+	/*
+	 * Now it's time to start playing with the RPCAP protocol
+	 * RPCAP start capture command: create the request message
+	 */
+	if (sock_bufferize(NULL, sizeof(struct rpcap_header), NULL,
+		&sendbufidx, RPCAP_NETBUF_SIZE, SOCKBUF_CHECKONLY, fp->errbuf, PCAP_ERRBUF_SIZE))
+		goto error;
+
+	rpcap_createhdr((struct rpcap_header *) sendbuf, RPCAP_MSG_STARTCAP_REQ, 0,
+		sizeof(struct rpcap_startcapreq) + sizeof(struct rpcap_filter) + fp->fcode.bf_len * sizeof(struct rpcap_filterbpf_insn));
+
+	/* Fill the structure needed to open an adapter remotely */
+	startcapreq = (struct rpcap_startcapreq *) &sendbuf[sendbufidx];
+
+	if (sock_bufferize(NULL, sizeof(struct rpcap_startcapreq), NULL,
+		&sendbufidx, RPCAP_NETBUF_SIZE, SOCKBUF_CHECKONLY, fp->errbuf, PCAP_ERRBUF_SIZE))
+		goto error;
+
+	memset(startcapreq, 0, sizeof(struct rpcap_startcapreq));
+
+	/* By default, apply half the timeout on one side, half of the other */
+	fp->opt.timeout = fp->opt.timeout / 2;
+	startcapreq->read_timeout = htonl(fp->opt.timeout);
+
+	/* portdata on the openreq is meaningful only if we're in active mode */
+	if ((active) || (md->rmt_flags & PCAP_OPENFLAG_DATATX_UDP))
+	{
+		sscanf(portdata, "%d", (int *)&(startcapreq->portdata));	/* cast to avoid a compiler warning */
+		startcapreq->portdata = htons(startcapreq->portdata);
+	}
+
+	startcapreq->snaplen = htonl(fp->snapshot);
+	startcapreq->flags = 0;
+
+	if (md->rmt_flags & PCAP_OPENFLAG_PROMISCUOUS)
+		startcapreq->flags |= RPCAP_STARTCAPREQ_FLAG_PROMISC;
+	if (md->rmt_flags & PCAP_OPENFLAG_DATATX_UDP)
+		startcapreq->flags |= RPCAP_STARTCAPREQ_FLAG_DGRAM;
+	if (active)
+		startcapreq->flags |= RPCAP_STARTCAPREQ_FLAG_SERVEROPEN;
+
+	startcapreq->flags = htons(startcapreq->flags);
+
+	/* Pack the capture filter */
+	if (pcap_pack_bpffilter(fp, &sendbuf[sendbufidx], &sendbufidx, &fp->fcode))
+		goto error;
+
+	if (sock_send(md->rmt_sockctrl, sendbuf, sendbufidx, fp->errbuf, PCAP_ERRBUF_SIZE))
+		goto error;
+
+
+	/* Receive the RPCAP start capture reply message */
+	if (sock_recv(md->rmt_sockctrl, (char *)&header, sizeof(struct rpcap_header), SOCK_RECEIVEALL_YES, fp->errbuf, PCAP_ERRBUF_SIZE) == -1)
+		goto error;
+
+	/* Checks if the message is correct */
+	retval = rpcap_checkmsg(fp->errbuf, md->rmt_sockctrl, &header, RPCAP_MSG_STARTCAP_REPLY, RPCAP_MSG_ERROR, 0);
+
+	if (retval != RPCAP_MSG_STARTCAP_REPLY)		/* the message is not the one expected */
+	{
+		switch (retval)
+		{
+		case -3:		/* Unrecoverable network error */
+		case -2:		/* The other endpoint send a message that is not allowed here */
+		case -1:		/* The other endpoint has a version number that is not compatible with our */
+			goto error;
+
+		case RPCAP_MSG_ERROR:		/* The other endpoint reported an error */
+			/* Update totread, since the rpcap_checkmsg() already purged the buffer */
+			totread = ntohl(header.plen);
+			/* Do nothing; just exit; the error code is already into the errbuf */
+			goto error;
+
+		default:
+			pcap_snprintf(fp->errbuf, PCAP_ERRBUF_SIZE, "Internal error");
+			goto error;
+		}
+	}
+
+	nread = sock_recv(md->rmt_sockctrl, (char *)&startcapreply,
+	    sizeof(struct rpcap_startcapreply), SOCK_RECEIVEALL_YES,
+	    fp->errbuf, PCAP_ERRBUF_SIZE);
+	if (nread == -1)
+		goto error;
+	totread += nread;
+
+	/*
+	 * In case of UDP data stream, the connection is always opened by the daemon
+	 * So, this case is already covered by the code above.
+	 * Now, we have still to handle TCP connections, because:
+	 * - if we're in active mode, we have to wait for a remote connection
+	 * - if we're in passive more, we have to start a connection
+	 *
+	 * We have to do he job in two steps because in case we're opening a TCP connection, we have
+	 * to tell the port we're using to the remote side; in case we're accepting a TCP
+	 * connection, we have to wait this info from the remote side.
+	 */
+
+	if (!(md->rmt_flags & PCAP_OPENFLAG_DATATX_UDP))
+	{
+		if (!active)
+		{
+			memset(&hints, 0, sizeof(struct addrinfo));
+			hints.ai_family = ai_family;		/* Use the same address family of the control socket */
+			hints.ai_socktype = (md->rmt_flags & PCAP_OPENFLAG_DATATX_UDP) ? SOCK_DGRAM : SOCK_STREAM;
+			pcap_snprintf(portdata, PCAP_BUF_SIZE, "%d", ntohs(startcapreply.portdata));
+
+			/* Let's the server pick up a free network port for us */
+			if (sock_initaddress(host, portdata, &hints, &addrinfo, fp->errbuf, PCAP_ERRBUF_SIZE) == -1)
+				goto error;
+
+			if ((sockdata = sock_open(addrinfo, SOCKOPEN_CLIENT, 0, fp->errbuf, PCAP_ERRBUF_SIZE)) == INVALID_SOCKET)
+				goto error;
+
+			/* addrinfo is no longer used */
+			freeaddrinfo(addrinfo);
+			addrinfo = NULL;
+		}
+		else
+		{
+			SOCKET socktemp;	/* We need another socket, since we're going to accept() a connection */
+
+			/* Connection creation */
+			saddrlen = sizeof(struct sockaddr_storage);
+
+			socktemp = accept(sockdata, (struct sockaddr *) &saddr, &saddrlen);
+
+			if (socktemp == -1)
+			{
+				sock_geterror("accept(): ", fp->errbuf, PCAP_ERRBUF_SIZE);
+				goto error;
+			}
+
+			/* Now that I accepted the connection, the server socket is no longer needed */
+			sock_close(sockdata, fp->errbuf, PCAP_ERRBUF_SIZE);
+			sockdata = socktemp;
+		}
+	}
+
+	/* Let's save the socket of the data connection */
+	md->rmt_sockdata = sockdata;
+
+	/* Allocates WinPcap/libpcap user buffer, which is a socket buffer in case of a remote capture */
+	/* It has the same size of the one used on the other side of the connection */
+	fp->bufsize = ntohl(startcapreply.bufsize);
+
+	/* Let's get the actual size of the socket buffer */
+	itemp = sizeof(sockbufsize);
+
+	res = getsockopt(sockdata, SOL_SOCKET, SO_RCVBUF, (char *)&sockbufsize, &itemp);
+	if (res == -1)
+	{
+		sock_geterror("pcap_startcapture_remote()", fp->errbuf, PCAP_ERRBUF_SIZE);
+		SOCK_ASSERT(fp->errbuf, 1);
+	}
+
+	/*
+	 * Warning: on some kernels (e.g. Linux), the size of the user buffer does not take
+	 * into account the pcap_header and such, and it is set equal to the snaplen.
+	 * In my view, this is wrong (the meaning of the bufsize became a bit strange).
+	 * So, here bufsize is the whole size of the user buffer.
+	 * In case the bufsize returned is too small, let's adjust it accordingly.
+	 */
+	if (fp->bufsize <= (u_int) fp->snapshot)
+		fp->bufsize += sizeof(struct pcap_pkthdr);
+
+	/* if the current socket buffer is smaller than the desired one */
+	if ((u_int) sockbufsize < fp->bufsize)
+	{
+		/* Loop until the buffer size is OK or the original socket buffer size is larger than this one */
+		while (1)
+		{
+			res = setsockopt(sockdata, SOL_SOCKET, SO_RCVBUF, (char *)&(fp->bufsize), sizeof(fp->bufsize));
+
+			if (res == 0)
+				break;
+
+			/*
+			 * If something goes wrong, half the buffer size (checking that it does not become smaller than
+			 * the current one)
+			 */
+			fp->bufsize /= 2;
+
+			if ((u_int) sockbufsize >= fp->bufsize)
+			{
+				fp->bufsize = sockbufsize;
+				break;
+			}
+		}
+	}
+
+	/*
+	 * Let's allocate the packet; this is required in order to put the packet somewhere when
+	 * extracting data from the socket
+	 * Since buffering has already been done in the socket buffer, here we need just a buffer,
+	 * whose size is equal to the pcap header plus the snapshot length
+	 */
+	fp->bufsize = fp->snapshot + sizeof(struct pcap_pkthdr);
+
+	fp->buffer = (u_char *)malloc(fp->bufsize);
+	if (fp->buffer == NULL)
+	{
+		pcap_snprintf(fp->errbuf, PCAP_ERRBUF_SIZE, "malloc: %s", pcap_strerror(errno));
+		goto error;
+	}
+
+
+	/* Checks if all the data has been read; if not, discard the data in excess */
+	if (totread != ntohl(header.plen))
+	{
+		if (sock_discard(md->rmt_sockctrl, ntohl(header.plen) - totread, NULL, 0) == 1)
+			goto error;
+	}
+
+	/*
+	 * In case the user does not want to capture RPCAP packets, let's update the filter
+	 * We have to update it here (instead of sending it into the 'StartCapture' message
+	 * because when we generate the 'start capture' we do not know (yet) all the ports
+	 * we're currently using.
+	 */
+	if (md->rmt_flags & PCAP_OPENFLAG_NOCAPTURE_RPCAP)
+	{
+		struct bpf_program fcode;
+
+		if (pcap_createfilter_norpcappkt(fp, &fcode) == -1)
+			goto error;
+
+		/* We cannot use 'pcap_setfilter_remote' because formally the capture has not been started yet */
+		/* (the 'fp->rmt_capstarted' variable will be updated some lines below) */
+		if (pcap_updatefilter_remote(fp, &fcode) == -1)
+			goto error;
+
+		pcap_freecode(&fcode);
+	}
+
+	md->rmt_capstarted = 1;
+	return 0;
+
+error:
+	/*
+	 * When the connection has been established, we have to close it. So, at the
+	 * beginning of this function, if an error occur we return immediately with
+	 * a return NULL; when the connection is established, we have to come here
+	 * ('goto error;') in order to close everything properly.
+	 *
+	 * Checks if all the data has been read; if not, discard the data in excess
+	 */
+	if (totread != ntohl(header.plen))
+		sock_discard(md->rmt_sockctrl, ntohl(header.plen) - totread, NULL, 0);
+
+	if ((sockdata) && (sockdata != -1))		/* we can be here because sockdata said 'error' */
+		sock_close(sockdata, NULL, 0);
+
+	if (!active)
+		sock_close(md->rmt_sockctrl, NULL, 0);
+
+	/*
+	 * We do not have to call pcap_close() here, because this function is always called
+	 * by the user in case something bad happens
+	 */
+	// 	if (fp)
+	// 	{
+	// 		pcap_close(fp);
+	// 		fp= NULL;
+	// 	}
+
+	return -1;
+}
+
+/*
+ * \brief Takes a bpf program and sends it to the other host.
+ *
+ * This function can be called in two cases:
+ * - the pcap_startcapture() is called (we have to send the filter along with
+ * the 'start capture' command)
+ * - we want to udpate the filter during a capture (i.e. the pcap_setfilter()
+ * is called when the capture is still on)
+ *
+ * This function serializes the filter into the sending buffer ('sendbuf', passed
+ * as a parameter) and return back. It does not send anything on the network.
+ *
+ * \param fp: the pcap_t descriptor of the device currently opened.
+ *
+ * \param sendbuf: the buffer on which the serialized data has to copied.
+ *
+ * \param sendbufidx: it is used to return the abounf of bytes copied into the buffer.
+ *
+ * \param prog: the bpf program we have to copy.
+ *
+ * \return '0' if everything is fine, '-1' otherwise. The error message (if one)
+ * is returned into the 'errbuf' field of the pcap_t structure.
+ */
+static int pcap_pack_bpffilter(pcap_t *fp, char *sendbuf, int *sendbufidx, struct bpf_program *prog)
+{
+	struct rpcap_filter *filter;
+	struct rpcap_filterbpf_insn *insn;
+	struct bpf_insn *bf_insn;
+	struct bpf_program fake_prog;		/* To be used just in case the user forgot to set a filter */
+	unsigned int i;
+
+
+	if (prog->bf_len == 0)	/* No filters have been specified; so, let's apply a "fake" filter */
+	{
+		if (pcap_compile(fp, &fake_prog, NULL /* buffer */, 1, 0) == -1)
+			return -1;
+
+		prog = &fake_prog;
+	}
+
+	filter = (struct rpcap_filter *) sendbuf;
+
+	if (sock_bufferize(NULL, sizeof(struct rpcap_filter), NULL, sendbufidx,
+		RPCAP_NETBUF_SIZE, SOCKBUF_CHECKONLY, fp->errbuf, PCAP_ERRBUF_SIZE))
+		return -1;
+
+	filter->filtertype = htons(RPCAP_UPDATEFILTER_BPF);
+	filter->nitems = htonl((int32)prog->bf_len);
+
+	if (sock_bufferize(NULL, prog->bf_len * sizeof(struct rpcap_filterbpf_insn),
+		NULL, sendbufidx, RPCAP_NETBUF_SIZE, SOCKBUF_CHECKONLY, fp->errbuf, PCAP_ERRBUF_SIZE))
+		return -1;
+
+	insn = (struct rpcap_filterbpf_insn *) (filter + 1);
+	bf_insn = prog->bf_insns;
+
+	for (i = 0; i < prog->bf_len; i++)
+	{
+		insn->code = htons(bf_insn->code);
+		insn->jf = bf_insn->jf;
+		insn->jt = bf_insn->jt;
+		insn->k = htonl(bf_insn->k);
+
+		insn++;
+		bf_insn++;
+	}
+
+	return 0;
+}
+
+/* \ingroup remote_pri_func
+ *
+ * \brief Update a filter on a remote host.
+ *
+ * This function is called when the user wants to update a filter.
+ * In case we're capturing from the network, it sends the filter to the other peer.
+ * This function is *not* called automatically when the user calls the pcap_setfilter().
+ * There will be two cases:
+ * - the capture is already on: in this case, pcap_setfilter() calls pcap_updatefilter_remote()
+ * - the capture has not started yet: in this case, pcap_setfilter() stores the filter into
+ * the pcap_t structure, and then the filter is sent with the pcap_startcap().
+ *
+ * Parameters and return values are exactly the same of the pcap_setfilter().
+ *
+ * \warning This function *does not* clear the packet currently into the buffers. Therefore,
+ * the user has to expect to receive some packets that are related to the previous filter.
+ * If you want to discard all the packets before applying a new filter, you have to close
+ * the current capture session and start a new one.
+ */
+static int pcap_updatefilter_remote(pcap_t *fp, struct bpf_program *prog)
+{
+	int retval;						/* general variable used to keep the return value of other functions */
+	char sendbuf[RPCAP_NETBUF_SIZE];/* temporary buffer in which data to be sent is buffered */
+	int sendbufidx = 0;				/* index which keeps the number of bytes currently buffered */
+	struct rpcap_header header;		/* To keep the reply message */
+	struct pcap_md *md;				/* structure used when doing a remote live capture */
+
+	md = (struct pcap_md *) ((u_char*)fp->priv + sizeof(struct pcap_win));
+
+
+	if (sock_bufferize(NULL, sizeof(struct rpcap_header), NULL, &sendbufidx,
+		RPCAP_NETBUF_SIZE, SOCKBUF_CHECKONLY, fp->errbuf, PCAP_ERRBUF_SIZE))
+		return -1;
+
+	rpcap_createhdr((struct rpcap_header *) sendbuf, RPCAP_MSG_UPDATEFILTER_REQ, 0,
+		sizeof(struct rpcap_filter) + prog->bf_len * sizeof(struct rpcap_filterbpf_insn));
+
+	if (pcap_pack_bpffilter(fp, &sendbuf[sendbufidx], &sendbufidx, prog))
+		return -1;
+
+	if (sock_send(md->rmt_sockctrl, sendbuf, sendbufidx, fp->errbuf, PCAP_ERRBUF_SIZE))
+		return -1;
+
+	/* Waits for the answer */
+	if (sock_recv(md->rmt_sockctrl, (char *)&header, sizeof(struct rpcap_header), SOCK_RECEIVEALL_YES, fp->errbuf, PCAP_ERRBUF_SIZE) == -1)
+		return -1;
+
+	/* Checks if the message is correct */
+	retval = rpcap_checkmsg(fp->errbuf, md->rmt_sockctrl, &header, RPCAP_MSG_UPDATEFILTER_REPLY, 0);
+
+	if (retval != RPCAP_MSG_UPDATEFILTER_REPLY)		/* the message is not the one expected */
+	{
+		switch (retval)
+		{
+		case -3:		/* Unrecoverable network error */
+		case -2:		/* The other endpoint sent a message that is not allowed here */
+		case -1:		/* The other endpoint has a version number that is not compatible with our */
+			/* Do nothing; just exit from here; the error code is already into the errbuf */
+			return -1;
+
+		default:
+			SOCK_ASSERT("Internal error", 0);
+			return -1;
+		}
+	}
+
+	if (ntohl(header.plen) != 0)	/* the message has an unexpected size */
+	{
+		if (sock_discard(md->rmt_sockctrl, ntohl(header.plen), fp->errbuf, PCAP_ERRBUF_SIZE) == -1)
+			return -1;
+	}
+
+	return 0;
+}
+
+/*
+ * \ingroup remote_pri_func
+ *
+ * \brief Send a filter to a remote host.
+ *
+ * This function is called when the user wants to set a filter.
+ * In case we're capturing from the network, it sends the filter to the other peer.
+ * This function is called automatically when the user calls the pcap_setfilter().
+ *
+ * Parameters and return values are exactly the same of the pcap_setfilter().
+ */
+static int pcap_setfilter_remote(pcap_t *fp, struct bpf_program *prog)
+{
+	struct pcap_md *md;				/* structure used when doing a remote live capture */
+
+	md = (struct pcap_md *) ((u_char*)fp->priv + sizeof(struct pcap_win));
+
+	if (!md->rmt_capstarted)
+	{
+		/* copy filter into the pcap_t structure */
+		if (install_bpf_program(fp, prog) == -1)
+			return -1;
+		return 0;
+	}
+
+	/* we have to update a filter during run-time */
+	if (pcap_updatefilter_remote(fp, prog))
+		return -1;
+
+	return 0;
+}
+
+/*
+ * \ingroup remote_pri_func
+ *
+ * \brief Update the current filter in order not to capture rpcap packets.
+ *
+ * This function is called *only* when the user wants exclude RPCAP packets
+ * related to the current session from the captured packets.
+ *
+ * \return '0' if everything is fine, '-1' otherwise. The error message (if one)
+ * is returned into the 'errbuf' field of the pcap_t structure.
+ */
+static int pcap_createfilter_norpcappkt(pcap_t *fp, struct bpf_program *prog)
+{
+	int RetVal = 0;
+	struct pcap_md *md;				/* structure used when doing a remote live capture */
+
+	md = (struct pcap_md *) ((u_char*)fp->priv + sizeof(struct pcap_win));
+
+	/* We do not want to capture our RPCAP traffic. So, let's update the filter */
+	if (md->rmt_flags & PCAP_OPENFLAG_NOCAPTURE_RPCAP)
+	{
+		struct sockaddr_storage saddr;		/* temp, needed to retrieve the network data port chosen on the local machine */
+		socklen_t saddrlen;					/* temp, needed to retrieve the network data port chosen on the local machine */
+		char myaddress[128];
+		char myctrlport[128];
+		char mydataport[128];
+		char peeraddress[128];
+		char peerctrlport[128];
+		char *newfilter;
+		const int newstringsize = 1024;
+		size_t currentfiltersize;
+
+		/* Get the name/port of the other peer */
+		saddrlen = sizeof(struct sockaddr_storage);
+		if (getpeername(md->rmt_sockctrl, (struct sockaddr *) &saddr, &saddrlen) == -1)
+		{
+			sock_geterror("getpeername(): ", fp->errbuf, PCAP_ERRBUF_SIZE);
+			return -1;
+		}
+
+		if (getnameinfo((struct sockaddr *) &saddr, saddrlen, peeraddress,
+			sizeof(peeraddress), peerctrlport, sizeof(peerctrlport), NI_NUMERICHOST | NI_NUMERICSERV))
+		{
+			sock_geterror("getnameinfo(): ", fp->errbuf, PCAP_ERRBUF_SIZE);
+			return -1;
+		}
+
+		/* We cannot check the data port, because this is available only in case of TCP sockets */
+		/* Get the name/port of the current host */
+		if (getsockname(md->rmt_sockctrl, (struct sockaddr *) &saddr, &saddrlen) == -1)
+		{
+			sock_geterror("getsockname(): ", fp->errbuf, PCAP_ERRBUF_SIZE);
+			return -1;
+		}
+
+		/* Get the local port the system picked up */
+		if (getnameinfo((struct sockaddr *) &saddr, saddrlen, myaddress,
+			sizeof(myaddress), myctrlport, sizeof(myctrlport), NI_NUMERICHOST | NI_NUMERICSERV))
+		{
+			sock_geterror("getnameinfo(): ", fp->errbuf, PCAP_ERRBUF_SIZE);
+			return -1;
+		}
+
+		/* Let's now check the data port */
+		if (getsockname(md->rmt_sockdata, (struct sockaddr *) &saddr, &saddrlen) == -1)
+		{
+			sock_geterror("getsockname(): ", fp->errbuf, PCAP_ERRBUF_SIZE);
+			return -1;
+		}
+
+		/* Get the local port the system picked up */
+		if (getnameinfo((struct sockaddr *) &saddr, saddrlen, NULL, 0, mydataport, sizeof(mydataport), NI_NUMERICSERV))
+		{
+			sock_geterror("getnameinfo(): ", fp->errbuf, PCAP_ERRBUF_SIZE);
+			return -1;
+		}
+
+		currentfiltersize = strlen(md->currentfilter);
+
+		newfilter = (char *)malloc(currentfiltersize + newstringsize + 1);
+
+		if (currentfiltersize)
+		{
+			pcap_snprintf(newfilter, currentfiltersize + newstringsize,
+				"(%s) and not (host %s and host %s and port %s and port %s) and not (host %s and host %s and port %s)",
+				md->currentfilter, myaddress, peeraddress, myctrlport, peerctrlport, myaddress, peeraddress, mydataport);
+		}
+		else
+		{
+			pcap_snprintf(newfilter, currentfiltersize + newstringsize,
+				"not (host %s and host %s and port %s and port %s) and not (host %s and host %s and port %s)",
+				myaddress, peeraddress, myctrlport, peerctrlport, myaddress, peeraddress, mydataport);
+		}
+
+		newfilter[currentfiltersize + newstringsize] = 0;
+
+		/* This is only an hack to make the pcap_compile() working properly */
+		md->rmt_clientside = 0;
+
+		if (pcap_compile(fp, prog, newfilter, 1, 0) == -1)
+			RetVal = -1;
+
+		/* This is only an hack to make the pcap_compile() working properly */
+		md->rmt_clientside = 1;
+
+		free(newfilter);
+	}
+
+	return RetVal;
+}
+
+/*
+ * \ingroup remote_pri_func
+ *
+ * \brief Set sampling parameters in the remote host.
+ *
+ * This function is called when the user wants to set activate sampling on the remote host.
+ *
+ * Sampling parameters are defined into the 'pcap_t' structure.
+ *
+ * \param p: the pcap_t descriptor of the device currently opened.
+ *
+ * \return '0' if everything is OK, '-1' is something goes wrong. The error message is returned
+ * in the 'errbuf' member of the pcap_t structure.
+ */
+static int pcap_setsampling_remote(pcap_t *p)
+{
+	int retval;						/* general variable used to keep the return value of other functions */
+	char sendbuf[RPCAP_NETBUF_SIZE];/* temporary buffer in which data to be sent is buffered */
+	int sendbufidx = 0;				/* index which keeps the number of bytes currently buffered */
+	struct rpcap_header header;		/* To keep the reply message */
+	struct rpcap_sampling *sampling_pars;	/* Structure that is needed to send sampling parameters to the remote host */
+	struct pcap_md *md;				/* structure used when doing a remote live capture */
+
+	md = (struct pcap_md *) ((u_char*)p->priv + sizeof(struct pcap_win));
+
+	/* If no samping is requested, return 'ok' */
+	if (md->rmt_samp.method == PCAP_SAMP_NOSAMP)
+		return 0;
+
+	if (sock_bufferize(NULL, sizeof(struct rpcap_header), NULL,
+		&sendbufidx, RPCAP_NETBUF_SIZE, SOCKBUF_CHECKONLY, p->errbuf, PCAP_ERRBUF_SIZE))
+		return -1;
+
+	rpcap_createhdr((struct rpcap_header *) sendbuf, RPCAP_MSG_SETSAMPLING_REQ, 0, sizeof(struct rpcap_sampling));
+
+	/* Fill the structure needed to open an adapter remotely */
+	sampling_pars = (struct rpcap_sampling *) &sendbuf[sendbufidx];
+
+	if (sock_bufferize(NULL, sizeof(struct rpcap_sampling), NULL,
+		&sendbufidx, RPCAP_NETBUF_SIZE, SOCKBUF_CHECKONLY, p->errbuf, PCAP_ERRBUF_SIZE))
+		return -1;
+
+	memset(sampling_pars, 0, sizeof(struct rpcap_sampling));
+
+	sampling_pars->method = md->rmt_samp.method;
+	sampling_pars->value = htonl(md->rmt_samp.value);
+
+	if (sock_send(md->rmt_sockctrl, sendbuf, sendbufidx, p->errbuf, PCAP_ERRBUF_SIZE))
+		return -1;
+
+	/* Waits for the answer */
+	if (sock_recv(md->rmt_sockctrl, (char *)&header, sizeof(struct rpcap_header), SOCK_RECEIVEALL_YES, p->errbuf, PCAP_ERRBUF_SIZE) == -1)
+		return -1;
+
+	/* Checks if the message is correct */
+	retval = rpcap_checkmsg(p->errbuf, md->rmt_sockctrl, &header, RPCAP_MSG_SETSAMPLING_REPLY, 0);
+
+	if (retval != RPCAP_MSG_SETSAMPLING_REPLY)		/* the message is not the one expected */
+	{
+		switch (retval)
+		{
+		case -3:		/* Unrecoverable network error */
+		case -2:		/* The other endpoint sent a message that is not allowed here */
+		case -1:		/* The other endpoint has a version number that is not compatible with our */
+		case RPCAP_MSG_ERROR:
+			/* Do nothing; just exit from here; the error code is already into the errbuf */
+			return -1;
+
+		default:
+			SOCK_ASSERT("Internal error", 0);
+			return -1;
+		}
+	}
+
+	if (ntohl(header.plen) != 0)	/* the message has an unexpected size */
+	{
+		if (sock_discard(md->rmt_sockctrl, ntohl(header.plen), p->errbuf, PCAP_ERRBUF_SIZE) == -1)
+			return -1;
+	}
+
+	return 0;
+
+}
+
+/*********************************************************
+ *                                                       *
+ * Miscellaneous functions                               *
+ *                                                       *
+ *********************************************************/
+
+
+/* \ingroup remote_pri_func
+ * \brief It sends a RPCAP error to the other peer.
+ *
+ * This function has to be called when the main program detects an error. This function
+ * will send on the other peer the 'buffer' specified by the user.
+ * This function *does not* request a RPCAP CLOSE connection. A CLOSE command must be sent
+ * explicitly by the program, since we do not know it the error can be recovered in some
+ * way or it is a non-recoverable one.
+ *
+ * \param sock: the socket we are currently using.
+ *
+ * \param error: an user-allocated (and '0' terminated) buffer that contains the error
+ * description that has to be transmitted on the other peer. The error message cannot
+ * be longer than PCAP_ERRBUF_SIZE.
+ *
+ * \param errcode: a integer which tells the other party the type of error we had;
+ * currently is is not too much used.
+ *
+ * \param errbuf: a pointer to a user-allocated buffer (of size PCAP_ERRBUF_SIZE)
+ * that will contain the error message (in case there is one). It could be network problem.
+ *
+ * \return '0' if everything is fine, '-1' if some errors occurred. The error message is returned
+ * in the 'errbuf' variable.
+ */
+int rpcap_senderror(SOCKET sock, char *error, unsigned short errcode, char *errbuf)
+{
+	char sendbuf[RPCAP_NETBUF_SIZE];			/* temporary buffer in which data to be sent is buffered */
+	int sendbufidx = 0;							/* index which keeps the number of bytes currently buffered */
+	uint16 length;
+
+	length = (uint16)strlen(error);
+
+	if (length > PCAP_ERRBUF_SIZE)
+		length = PCAP_ERRBUF_SIZE;
+
+	rpcap_createhdr((struct rpcap_header *) sendbuf, RPCAP_MSG_ERROR, errcode, length);
+
+	if (sock_bufferize(NULL, sizeof(struct rpcap_header), NULL, &sendbufidx,
+		RPCAP_NETBUF_SIZE, SOCKBUF_CHECKONLY, errbuf, PCAP_ERRBUF_SIZE))
+		return -1;
+
+	if (sock_bufferize(error, length, sendbuf, &sendbufidx,
+		RPCAP_NETBUF_SIZE, SOCKBUF_BUFFERIZE, errbuf, PCAP_ERRBUF_SIZE))
+		return -1;
+
+	if (sock_send(sock, sendbuf, sendbufidx, errbuf, PCAP_ERRBUF_SIZE))
+		return -1;
+
+	return 0;
+}
+
+/* \ingroup remote_pri_func
+ * \brief Sends the authentication message.
+ *
+ * It sends the authentication parameters on the control socket.
+ * This function is required in order to open the connection with the other end party.
+ *
+ * \param sock: the socket we are currently using.
+ *
+ * \param auth: authentication parameters that have to be sent.
+ *
+ * \param errbuf: a pointer to a user-allocated buffer (of size PCAP_ERRBUF_SIZE)
+ * that will contain the error message (in case there is one). It could be network problem
+ * of the fact that the authorization failed.
+ *
+ * \return '0' if everything is fine, '-1' if some errors occurred. The error message is returned
+ * in the 'errbuf' variable.
+ * The error message could be also 'the authentication failed'.
+ */
+int rpcap_sendauth(SOCKET sock, struct pcap_rmtauth *auth, char *errbuf)
+{
+	char sendbuf[RPCAP_NETBUF_SIZE];	/* temporary buffer in which data that has to be sent is buffered */
+	int sendbufidx = 0;					/* index which keeps the number of bytes currently buffered */
+	uint16 length;						/* length of the payload of this message */
+	struct rpcap_auth *rpauth;
+	uint16 auth_type;
+	struct rpcap_header header;
+	int retval;							/* temp variable which stores functions return value */
+
+	if (auth)
+	{
+		auth_type = auth->type;
+
+		switch (auth->type)
+		{
+		case RPCAP_RMTAUTH_NULL:
+			length = sizeof(struct rpcap_auth);
+			break;
+
+		case RPCAP_RMTAUTH_PWD:
+			length = sizeof(struct rpcap_auth);
+			if (auth->username) length += (uint16) strlen(auth->username);
+			if (auth->password) length += (uint16) strlen(auth->password);
+			break;
+
+		default:
+			pcap_snprintf(errbuf, PCAP_ERRBUF_SIZE, "Authentication type not recognized.");
+			return -1;
+		}
+	}
+	else
+	{
+		auth_type = RPCAP_RMTAUTH_NULL;
+		length = sizeof(struct rpcap_auth);
+	}
+
+
+	if (sock_bufferize(NULL, sizeof(struct rpcap_header), NULL,
+		&sendbufidx, RPCAP_NETBUF_SIZE, SOCKBUF_CHECKONLY, errbuf, PCAP_ERRBUF_SIZE))
+		return -1;
+
+	rpcap_createhdr((struct rpcap_header *) sendbuf, RPCAP_MSG_AUTH_REQ, 0, length);
+
+	rpauth = (struct rpcap_auth *) &sendbuf[sendbufidx];
+
+	if (sock_bufferize(NULL, sizeof(struct rpcap_auth), NULL,
+		&sendbufidx, RPCAP_NETBUF_SIZE, SOCKBUF_CHECKONLY, errbuf, PCAP_ERRBUF_SIZE))
+		return -1;
+
+	memset(rpauth, 0, sizeof(struct rpcap_auth));
+
+	rpauth->type = htons(auth_type);
+
+	if (auth_type == RPCAP_RMTAUTH_PWD)
+	{
+
+		if (auth->username)
+			rpauth->slen1 = (uint16) strlen(auth->username);
+		else
+			rpauth->slen1 = 0;
+
+		if (sock_bufferize(auth->username, rpauth->slen1, sendbuf,
+			&sendbufidx, RPCAP_NETBUF_SIZE, SOCKBUF_BUFFERIZE, errbuf, PCAP_ERRBUF_SIZE))
+			return -1;
+
+		if (auth->password)
+			rpauth->slen2 = (uint16) strlen(auth->password);
+		else
+			rpauth->slen2 = 0;
+
+		if (sock_bufferize(auth->password, rpauth->slen2, sendbuf,
+			&sendbufidx, RPCAP_NETBUF_SIZE, SOCKBUF_BUFFERIZE, errbuf, PCAP_ERRBUF_SIZE))
+			return -1;
+
+		rpauth->slen1 = htons(rpauth->slen1);
+		rpauth->slen2 = htons(rpauth->slen2);
+	}
+
+	if (sock_send(sock, sendbuf, sendbufidx, errbuf, PCAP_ERRBUF_SIZE))
+		return -1;
+
+	if (sock_recv(sock, (char *)&header, sizeof(struct rpcap_header), SOCK_RECEIVEALL_YES, errbuf, PCAP_ERRBUF_SIZE) == -1)
+		return -1;
+
+	retval = rpcap_checkmsg(errbuf, sock, &header, RPCAP_MSG_AUTH_REPLY, RPCAP_MSG_ERROR, 0);
+
+	if (retval != RPCAP_MSG_AUTH_REPLY)		/* the message is not the one expected */
+	{
+		switch (retval)
+		{
+		case -3:		/* Unrecoverable network error */
+		case -2:		/* The other endpoint sent a message that is not allowed here */
+		case -1:		/* The other endpoint has a version number that is not compatible with our */
+			/* Do nothing; just exit from here; the error code is already into the errbuf */
+			return -1;
+
+		case RPCAP_MSG_ERROR:
+			return -1;
+
+		default:
+			SOCK_ASSERT("Internal error", 0);
+			return -1;
+		}
+	}
+
+	if (ntohl(header.plen))
+	{
+		if (sock_discard(sock, ntohl(header.plen), errbuf, PCAP_ERRBUF_SIZE))
+			return -1;
+	}
+
+	return 0;
+}
+
+/* \ingroup remote_pri_func
+ * \brief Creates a structure of type rpcap_header.
+ *
+ * This function is provided just because the creation of an rpcap header is quite a common
+ * task. It accepts all the values that appears into an rpcap_header, and it puts them in
+ * place using the proper hton() calls.
+ *
+ * \param header: a pointer to a user-allocated buffer which will contain the serialized
+ * header, ready to be sent on the network.
+ *
+ * \param type: a value (in the host by order) which will be placed into the header.type
+ * field and that represents the type of the current message.
+ *
+ * \param value: a value (in the host by order) which will be placed into the header.value
+ * field and that has a message-dependent meaning.
+ *
+ * \param length: a value (in the host by order) which will be placed into the header.length
+ * field and that represents the payload length of the message.
+ *
+ * \return Nothing. The serialized header is returned into the 'header' variable.
+ */
+void rpcap_createhdr(struct rpcap_header *header, uint8 type, uint16 value, uint32 length)
+{
+	memset(header, 0, sizeof(struct rpcap_header));
+
+	header->ver = RPCAP_VERSION;
+	header->type = type;
+	header->value = htons(value);
+	header->plen = htonl(length);
+}
+
+/* ingroup remote_pri_func
+ * \brief Checks if the header of the received message is correct.
+ *
+ * This function is a way to easily check if the message received, in a certain
+ * state of the RPCAP protocol Finite State Machine, is valid. This function accepts,
+ * as a parameter, the list of message types that are allowed in a certain situation,
+ * and it returns the one which occurs.
+ *
+ * \param errbuf: a pointer to a user-allocated buffer (of size PCAP_ERRBUF_SIZE)
+ * that will contain the error message (in case there is one). It could be either problem
+ * occurred inside this function (e.g. a network problem in case it tries to send an
+ * error on the other peer and the send() call fails), an error message which has been
+ * sent to us from the other party, or a version error (the message receive has a version
+ * number that is incompatible with our).
+ *
+ * \param sock: the socket that has to be used to receive data. This function can
+ * read data from socket in case the version contained into the message is not compatible
+ * with our. In that case, all the message is purged from the socket, so that the following
+ * recv() calls will return a new message.
+ *
+ * \param header: a pointer to and 'rpcap_header' structure that keeps the data received from
+ * the network (still in network byte order) and that has to be checked.
+ *
+ * \param first: this function has a variable number of parameters. From this point on,
+ * all the messages that are valid in this context must be passed as parameters.
+ * The message type list must be terminated with a '0' value, the null message type,
+ * which means 'no more types to check'. The RPCAP protocol does not define anything with
+ * message type equal to zero, so there is no ambiguity in using this value as a list terminator.
+ *
+ * \return The message type of the message that has been detected. In case of errors (e.g. the
+ * header contains a type that is not listed among the allowed types), this function will
+ * return the following codes:
+ * - (-1) if the version is incompatible.
+ * - (-2) if the code is not among the one listed into the parameters list
+ * - (-3) if a network error (connection reset, ...)
+ * - RPCAP_MSG_ERROR if the message is an error message (it follow that the RPCAP_MSG_ERROR
+ * could not be present in the allowed message-types list, because this function checks
+ * for errors anyway)
+ *
+ * In case either the version is incompatible or nothing matches (i.e. it returns '-1' or '-2'),
+ * it discards the message body (i.e. it reads the remaining part of the message from the
+ * network and it discards it) so that the application is ready to receive a new message.
+ */
+int rpcap_checkmsg(char *errbuf, SOCKET sock, struct rpcap_header *header, uint8 first, ...)
+{
+	va_list ap;
+	uint8 type;
+	int32 len;
+
+	va_start(ap, first);
+
+	/* Check if the present version of the protocol can handle this message */
+	if (rpcap_checkver(sock, header, errbuf))
+	{
+		SOCK_ASSERT(errbuf, 1);
+
+		va_end(ap);
+		return -1;
+	}
+
+	type = first;
+
+	while (type != 0)
+	{
+		/*
+		 * The message matches with one of the types listed
+		 * There is no need of conversions since both values are uint8
+		 *
+		 * Check if the other side reported an error.
+		 * If yes, it retrieves it and it returns it back to the caller
+		 */
+		if (header->type == RPCAP_MSG_ERROR)
+		{
+			len = ntohl(header->plen);
+
+			if (len >= PCAP_ERRBUF_SIZE)
+			{
+				if (sock_recv(sock, errbuf, PCAP_ERRBUF_SIZE - 1, SOCK_RECEIVEALL_YES, errbuf, PCAP_ERRBUF_SIZE))
+					return -3;
+
+				sock_discard(sock, len - (PCAP_ERRBUF_SIZE - 1), NULL, 0);
+
+				/* Put '\0' at the end of the string */
+				errbuf[PCAP_ERRBUF_SIZE - 1] = 0;
+			}
+			else
+			{
+				if (sock_recv(sock, errbuf, len, SOCK_RECEIVEALL_YES, errbuf, PCAP_ERRBUF_SIZE) == -1)
+					return -3;
+
+				/* Put '\0' at the end of the string */
+				errbuf[len] = 0;
+			}
+
+
+			va_end(ap);
+			return header->type;
+		}
+
+		if (header->type == type)
+		{
+			va_end(ap);
+			return header->type;
+		}
+
+		/* get next argument */
+		type = va_arg(ap, int);
+	}
+
+	/* we already have an error, so please discard this one */
+	sock_discard(sock, ntohl(header->plen), NULL, 0);
+
+	pcap_snprintf(errbuf, PCAP_ERRBUF_SIZE, "The other endpoint sent a message that is not allowed here.");
+	SOCK_ASSERT(errbuf, 1);
+
+	va_end(ap);
+	return -2;
+}
+
+/* \ingroup remote_pri_func
+ * \brief Checks if the version contained into the message is compatible with
+ * the one handled by this implementation.
+ *
+ * Right now, this function does not have any sophisticated task: if the versions
+ * are different, it returns -1 and it discards the message.
+ * It is expected that in the future this message will become more complex.
+ *
+ * \param sock: the socket that has to be used to receive data. This function can
+ * read data from socket in case the version contained into the message is not compatible
+ * with our. In that case, all the message is purged from the socket, so that the following
+ * recv() calls will return a new (clean) message.
+ *
+ * \param header: a pointer to and 'rpcap_header' structure that keeps the data received from
+ * the network (still in network byte order) and that has to be checked.
+ *
+ * \param errbuf: a pointer to a user-allocated buffer (of size PCAP_ERRBUF_SIZE)
+ * that will contain the error message (in case there is one). The error message is
+ * "incompatible version".
+ *
+ * \return '0' if everything is fine, '-1' if some errors occurred. The error message is returned
+ * in the 'errbuf' variable.
+ */
+static int rpcap_checkver(SOCKET sock, struct rpcap_header *header, char *errbuf)
+{
+	/*
+	 * This is a sample function.
+	 *
+	 * In the real world, you have to check at the type code,
+	 * and decide accordingly.
+	 */
+
+	if (header->ver != RPCAP_VERSION)
+	{
+		pcap_snprintf(errbuf, PCAP_ERRBUF_SIZE, "Incompatible version number: message discarded.");
+
+		/* we already have an error, so please discard this one */
+		sock_discard(sock, ntohl(header->plen), NULL, 0);
+		return -1;
+	}
+
+	return 0;
+}
+
+/* \ingroup remote_pri_func
+ *
+ * \brief It returns the socket currently used for this active connection
+ * (active mode only) and provides an indication of whether this connection
+ * is in active mode or not.
+ *
+ * This function is just for internal use; it returns the socket ID of the
+ * active connection currently opened.
+ *
+ * \param host: a string that keeps the host name of the host for which we
+ * want to get the socket ID for that active connection.
+ *
+ * \param isactive: a pointer to an int that is set to 1 if there's an
+ * active connection to that host and 0 otherwise.
+ *
+ * \param errbuf: a pointer to a user-allocated buffer (of size
+ * PCAP_ERRBUF_SIZE) that will contain the error message (in case
+ * there is one).
+ *
+ * \return the socket identifier if everything is fine, '0' if this host
+ * is not in the active host list. An indication of whether this host
+ * is in the active host list is returned into the isactive variable.
+ * It returns 'INVALID_SOCKET' in case of error. The error message is
+ * returned into the errbuf variable.
+ */
+SOCKET rpcap_remoteact_getsock(const char *host, int *isactive, char *errbuf)
+{
+	struct activehosts *temp;					/* temp var needed to scan the host list chain */
+	struct addrinfo hints, *addrinfo, *ai_next;	/* temp var needed to translate between hostname to its address */
+	int retval;
+
+	/* retrieve the network address corresponding to 'host' */
+	addrinfo = NULL;
+	memset(&hints, 0, sizeof(struct addrinfo));
+	hints.ai_family = PF_UNSPEC;
+	hints.ai_socktype = SOCK_STREAM;
+
+	retval = getaddrinfo(host, "0", &hints, &addrinfo);
+	if (retval != 0)
+	{
+		pcap_snprintf(errbuf, PCAP_ERRBUF_SIZE, "getaddrinfo() %s", gai_strerror(retval));
+		*isactive = 0;
+		return INVALID_SOCKET;
+	}
+
+	temp = activeHosts;
+
+	while (temp)
+	{
+		ai_next = addrinfo;
+		while (ai_next)
+		{
+			if (sock_cmpaddr(&temp->host, (struct sockaddr_storage *) ai_next->ai_addr) == 0) {
+				*isactive = 1;
+				return (temp->sockctrl);
+			}
+
+			ai_next = ai_next->ai_next;
+		}
+		temp = temp->next;
+	}
+
+	if (addrinfo)
+		freeaddrinfo(addrinfo);
+
+	/*
+	 * The host for which you want to get the socket ID does not have an
+	 * active connection.
+	 */
+	*isactive = 0;
+	return 0;
+}
diff --git a/pcap-rpcap.h b/pcap-rpcap.h
new file mode 100644
index 0000000..f84e8ba
--- /dev/null
+++ b/pcap-rpcap.h
@@ -0,0 +1,465 @@
+/*
+ * Copyright (c) 2002 - 2005 NetGroup, Politecnico di Torino (Italy)
+ * Copyright (c) 2005 - 2008 CACE Technologies, Davis (California)
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the Politecnico di Torino, CACE Technologies
+ * nor the names of its contributors may be used to endorse or promote
+ * products derived from this software without specific prior written
+ * permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+#ifndef __PCAP_RPCAP_H__
+#define __PCAP_RPCAP_H__
+
+
+#include "pcap.h"
+#include "sockutils.h"	/* Needed for some structures (like SOCKET, sockaddr_in) which are used here */
+
+
+/*
+ * \file pcap-pcap.h
+ *
+ * This file keeps all the new definitions and typedefs that are exported to the user and
+ * that are needed for the RPCAP protocol.
+ *
+ * \warning All the RPCAP functions that are allowed to return a buffer containing
+ * the error description can return max PCAP_ERRBUF_SIZE characters.
+ * However there is no guarantees that the string will be zero-terminated.
+ * Best practice is to define the errbuf variable as a char of size 'PCAP_ERRBUF_SIZE+1'
+ * and to insert manually the termination char at the end of the buffer. This will
+ * guarantee that no buffer overflows occur even if we use the printf() to show
+ * the error on the screen.
+ *
+ * \warning This file declares some typedefs that MUST be of a specific size.
+ * These definitions (i.e. typedefs) could need to be changed on other platforms than
+ * Intel IA32.
+ *
+ * \warning This file defines some structures that are used to transfer data on the network.
+ * Be careful that you compiler MUST not insert padding into these structures
+ * for better alignment.
+ * These structures have been created in order to be correctly aligned to a 32 bits
+ * boundary, but be careful in any case.
+ */
+
+
+
+
+
+
+
+
+/*********************************************************
+ *                                                       *
+ * General definitions / typedefs for the RPCAP protocol *
+ *                                                       *
+ *********************************************************/
+
+/* All the following structures and typedef belongs to the Private Documentation */
+/*
+ * \addtogroup remote_pri_struct
+ * \{
+ */
+
+#define RPCAP_DEFAULT_NETPORT "2002" /* Default port on which the RPCAP daemon is waiting for connections. */
+/* Default port on which the client workstation is waiting for connections in case of active mode. */
+#define RPCAP_DEFAULT_NETPORT_ACTIVE "2003"
+#define RPCAP_DEFAULT_NETADDR ""	/* Default network address on which the RPCAP daemon binds to. */
+#define RPCAP_VERSION 0				/* Present version of the RPCAP protocol (0 = Experimental). */
+#define RPCAP_TIMEOUT_INIT 90		/* Initial timeout for RPCAP connections (default: 90 sec) */
+#define RPCAP_TIMEOUT_RUNTIME 180	/* Run-time timeout for RPCAP connections (default: 3 min) */
+#define RPCAP_ACTIVE_WAIT 30		/* Waiting time between two attempts to open a connection, in active mode (default: 30 sec) */
+#define RPCAP_SUSPEND_WRONGAUTH 1	/* If the authentication is wrong, stops 1 sec before accepting a new auth message */
+
+/*
+ * \brief Buffer used by socket functions to send-receive packets.
+ * In case you plan to have messages larger than this value, you have to increase it.
+ */
+#define RPCAP_NETBUF_SIZE 64000
+
+
+/*
+ * \brief Separators used for the host list.
+ *
+ * It is used:
+ * - by the rpcapd daemon, when you types a list of allowed connecting hosts
+ * - by the rpcap in active mode, when the client waits for incoming connections from other hosts
+ */
+#define RPCAP_HOSTLIST_SEP " ,;\n\r"
+
+
+
+
+/* WARNING: These could need to be changed on other platforms */
+typedef unsigned char uint8;		/* Provides an 8-bits unsigned integer */
+typedef unsigned short uint16;		/* Provides a 16-bits unsigned integer */
+typedef unsigned int uint32;		/* Provides a 32-bits unsigned integer */
+typedef int int32;					/* Provides a 32-bits integer */
+
+
+
+
+/*
+ * \brief Keeps a list of all the opened connections in the active mode.
+ *
+ * This structure defines a linked list of items that are needed to keep the info required to
+ * manage the active mode.
+ * In other words, when a new connection in active mode starts, this structure is updated so that
+ * it reflects the list of active mode connections currently opened.
+ * This structure is required by findalldevs() and open_remote() to see if they have to open a new
+ * control connection toward the host, or they already have a control connection in place.
+ */
+struct activehosts
+{
+	struct sockaddr_storage host;
+	SOCKET sockctrl;
+	struct activehosts *next;
+};
+
+
+/*********************************************************
+ *                                                       *
+ * Protocol messages formats                             *
+ *                                                       *
+ *********************************************************/
+/* WARNING Take care you compiler does not insert padding for better alignments into these structs */
+
+
+/* Common header for all the RPCAP messages */
+struct rpcap_header
+{
+	uint8 ver;							/* RPCAP version number */
+	uint8 type;							/* RPCAP message type (error, findalldevs, ...) */
+	uint16 value;						/* Message-dependent value (not always used) */
+	uint32 plen;						/* Length of the payload of this RPCAP message */
+};
+
+
+/* Format of the message for the interface description (findalldevs command) */
+struct rpcap_findalldevs_if
+{
+	uint16 namelen;						/* Length of the interface name */
+	uint16 desclen;						/* Length of the interface description */
+	uint32 flags;						/* Interface flags */
+	uint16 naddr;						/* Number of addresses */
+	uint16 dummy;						/* Must be zero */
+};
+
+
+/* Format of the message for the address listing (findalldevs command) */
+struct rpcap_findalldevs_ifaddr
+{
+	struct sockaddr_storage addr;		/* Network address */
+	struct sockaddr_storage netmask;	/* Netmask for that address */
+	struct sockaddr_storage broadaddr;	/* Broadcast address for that address */
+	struct sockaddr_storage dstaddr;	/* P2P destination address for that address */
+};
+
+
+
+/*
+ * \brief Format of the message of the connection opening reply (open command).
+ *
+ * This structure transfers over the network some of the values useful on the client side.
+ */
+struct rpcap_openreply
+{
+	int32 linktype;						/* Link type */
+	int32 tzoff;						/* Timezone offset */
+};
+
+
+
+/* Format of the message that starts a remote capture (startcap command) */
+struct rpcap_startcapreq
+{
+	uint32 snaplen;						/* Length of the snapshot (number of bytes to capture for each packet) */
+	uint32 read_timeout;				/* Read timeout in milliseconds */
+	uint16 flags;						/* Flags (see RPCAP_STARTCAPREQ_FLAG_xxx) */
+	uint16 portdata;					/* Network port on which the client is waiting at (if 'serveropen') */
+};
+
+
+/* Format of the reply message that devoted to start a remote capture (startcap reply command) */
+struct rpcap_startcapreply
+{
+	int32 bufsize;						/* Size of the user buffer allocated by WinPcap; it can be different from the one we chose */
+	uint16 portdata;					/* Network port on which the server is waiting at (passive mode only) */
+	uint16 dummy;						/* Must be zero */
+};
+
+
+/*
+ * \brief Format of the header which encapsulates captured packets when transmitted on the network.
+ *
+ * This message requires the general header as well, since we want to be able to exchange
+ * more information across the network in the future (for example statistics, and kind like that).
+ */
+struct rpcap_pkthdr
+{
+	uint32 timestamp_sec;	/* 'struct timeval' compatible, it represents the 'tv_sec' field */
+	uint32 timestamp_usec;	/* 'struct timeval' compatible, it represents the 'tv_usec' field */
+	uint32 caplen;			/* Length of portion present in the capture */
+	uint32 len;				/* Real length this packet (off wire) */
+	uint32 npkt;			/* Ordinal number of the packet (i.e. the first one captured has '1', the second one '2', etc) */
+};
+
+
+/* General header used for the pcap_setfilter() command; keeps just the number of BPF instructions */
+struct rpcap_filter
+{
+	uint16 filtertype;		/* type of the filter transferred (BPF instructions, ...) */
+	uint16 dummy;			/* Must be zero */
+	uint32 nitems;			/* Number of items contained into the filter (e.g. BPF instructions for BPF filters) */
+};
+
+
+/* Structure that keeps a single BPF instuction; it is repeated 'ninsn' times according to the 'rpcap_filterbpf' header */
+struct rpcap_filterbpf_insn
+{
+	uint16 code;			/* opcode of the instruction */
+	uint8 jt;				/* relative offset to jump to in case of 'true' */
+	uint8 jf;				/* relative offset to jump to in case of 'false' */
+	int32 k;				/* instruction-dependent value */
+};
+
+
+/* Structure that keeps the data required for the authentication on the remote host */
+struct rpcap_auth
+{
+	uint16 type;			/* Authentication type */
+	uint16 dummy;			/* Must be zero */
+	uint16 slen1;			/* Length of the first authentication item (e.g. username) */
+	uint16 slen2;			/* Length of the second authentication item (e.g. password) */
+};
+
+
+/* Structure that keeps the statistics about the number of packets captured, dropped, etc. */
+struct rpcap_stats
+{
+	uint32 ifrecv;		/* Packets received by the kernel filter (i.e. pcap_stats.ps_recv) */
+	uint32 ifdrop;		/* Packets dropped by the network interface (e.g. not enough buffers) (i.e. pcap_stats.ps_ifdrop) */
+	uint32 krnldrop;	/* Packets dropped by the kernel filter (i.e. pcap_stats.ps_drop) */
+	uint32 svrcapt;		/* Packets captured by the RPCAP daemon and sent on the network */
+};
+
+
+/* Structure that is needed to set sampling parameters */
+struct rpcap_sampling
+{
+	uint8 method;		/* Sampling method */
+	uint8 dummy1;		/* Must be zero */
+	uint16 dummy2;		/* Must be zero */
+	uint32 value;		/* Parameter related to the sampling method */
+};
+
+
+/*
+ * Private data for doing a live capture.
+ */
+struct pcap_md {
+	struct pcap_stat stat;
+	/* XXX */
+	int		use_bpf;		/* using kernel filter */
+	u_long	TotPkts;		/* can't overflow for 79 hrs on ether */
+	u_long	TotAccepted;	/* count accepted by filter */
+	u_long	TotDrops;		/* count of dropped packets */
+	long	TotMissed;		/* missed by i/f during this run */
+	long	OrigMissed;		/* missed by i/f before this run */
+	char	*device;		/* device name */
+	int		timeout;		/* timeout for buffering */
+	int		must_clear;		/* stuff we must clear when we close */
+	struct pcap *next;		/* list of open pcaps that need stuff cleared on close */
+#ifdef linux
+	int		sock_packet;	/* using Linux 2.0 compatible interface */
+	int		cooked;			/* using SOCK_DGRAM rather than SOCK_RAW */
+	int		ifindex;		/* interface index of device we're bound to */
+	int		lo_ifindex;		/* interface index of the loopback device */
+	u_int	packets_read;	/* count of packets read with recvfrom() */
+	bpf_u_int32 oldmode;	/* mode to restore when turning monitor mode off */
+	u_int	tp_version;		/* version of tpacket_hdr for mmaped ring */
+	u_int	tp_hdrlen;		/* hdrlen of tpacket_hdr for mmaped ring */
+#endif /* linux */
+
+#ifdef HAVE_DAG_API
+#ifdef HAVE_DAG_STREAMS_API
+	u_char	*dag_mem_bottom;/* DAG card current memory bottom pointer */
+	u_char	*dag_mem_top;	/* DAG card current memory top pointer */
+#else /* HAVE_DAG_STREAMS_API */
+	void	*dag_mem_base;	/* DAG card memory base address */
+	u_int	dag_mem_bottom;	/* DAG card current memory bottom offset */
+	u_int	dag_mem_top;	/* DAG card current memory top offset */
+#endif /* HAVE_DAG_STREAMS_API */
+	int	dag_fcs_bits;		/* Number of checksum bits from link layer */
+	int	dag_offset_flags;	/* Flags to pass to dag_offset(). */
+	int	dag_stream;			/* DAG stream number */
+	int	dag_timeout;		/* timeout specified to pcap_open_live.
+							 * Same as in linux above, introduce
+							 * generally?
+							 */
+#endif /* HAVE_DAG_API */
+#ifdef HAVE_ZEROCOPY_BPF
+	/*
+	 * Zero-copy read buffer -- for zero-copy BPF.  'buffer' above will
+	 * alternative between these two actual mmap'd buffers as required.
+	 * As there is a header on the front size of the mmap'd buffer, only
+	 * some of the buffer is exposed to libpcap as a whole via bufsize;
+	 * zbufsize is the true size.  zbuffer tracks the current zbuf
+	 * associated with buffer so that it can be used to decide which the
+	 * next buffer to read will be.
+	 */
+	u_char *zbuf1, *zbuf2, *zbuffer;
+	u_int zbufsize;
+	u_int zerocopy;
+	u_int interrupted;
+	struct timespec firstsel;
+	/*
+	 * If there's currently a buffer being actively processed, then it is
+	 * referenced here; 'buffer' is also pointed at it, but offset by the
+	 * size of the header.
+	 */
+	struct bpf_zbuf_header *bzh;
+#endif /* HAVE_ZEROCOPY_BPF */
+
+
+
+#ifdef HAVE_REMOTE
+	/*
+	 * There is really a mess with previous variables, and it seems to me that they are not used
+	 * (they are used in pcap_pf.c only). I think we have to start using them.
+	 * The meaning is the following:
+	 *
+	 * - TotPkts: the amount of packets received by the bpf filter, *before* applying the filter
+	 * - TotAccepted: the amount of packets that satisfies the filter
+	 * - TotDrops: the amount of packet that were dropped into the kernel buffer because of lack of space
+	 * - TotMissed: the amount of packets that were dropped by the physical interface; it is basically
+	 * the value of the hardware counter into the card. This number is never put to zero, so this number
+	 * takes into account the *total* number of interface drops starting from the interface power-on.
+	 * - OrigMissed: the amount of packets that were dropped by the interface *when the capture begins*.
+	 * This value is used to detect the number of packets dropped by the interface *during the present
+	 * capture*, so that (ps_ifdrops= TotMissed - OrigMissed).
+	 */
+	unsigned int TotNetDrops;		/* keeps the number of packets that have been dropped by the network */
+	/*
+	 * \brief It keeps the number of packets that have been received by the application.
+	 *
+	 * Packets dropped by the kernel buffer are not counted in this variable. The variable is always
+	 * equal to (TotAccepted - TotDrops), except for the case of remote capture, in which we have also
+	 * packets in flight, i.e. that have been transmitted by the remote host, but that have not been
+	 * received (yet) from the client. In this case, (TotAccepted - TotDrops - TotNetDrops) gives a
+	 * wrong result, since this number does not corresponds always to the number of packet received by
+	 * the application. For this reason, in the remote capture we need another variable that takes
+	 * into account of the number of packets actually received by the application.
+	 */
+	unsigned int TotCapt;
+
+	/*! \brief '1' if we're the network client; needed by several functions (like pcap_setfilter() ) to know if
+	they have to use the socket or they have to open the local adapter. */
+	int rmt_clientside;
+
+	SOCKET rmt_sockctrl;		//!< socket ID of the socket used for the control connection
+	SOCKET rmt_sockdata;		//!< socket ID of the socket used for the data connection
+	int rmt_flags;				//!< we have to save flags, since they are passed by the pcap_open_live(), but they are used by the pcap_startcapture()
+	int rmt_capstarted;			//!< 'true' if the capture is already started (needed to knoe if we have to call the pcap_startcapture()
+	struct pcap_samp rmt_samp;	//!< Keeps the parameters related to the sampling process.
+	char *currentfilter;		//!< Pointer to a buffer (allocated at run-time) that stores the current filter. Needed when flag PCAP_OPENFLAG_NOCAPTURE_RPCAP is turned on.
+#endif /* HAVE_REMOTE */
+
+};
+
+
+/* Messages field coding */
+#define RPCAP_MSG_ERROR 1				/* Message that keeps an error notification */
+#define RPCAP_MSG_FINDALLIF_REQ 2		/* Request to list all the remote interfaces */
+#define RPCAP_MSG_OPEN_REQ 3			/* Request to open a remote device */
+#define RPCAP_MSG_STARTCAP_REQ 4		/* Request to start a capture on a remote device */
+#define RPCAP_MSG_UPDATEFILTER_REQ 5	/* Send a compiled filter into the remote device */
+#define RPCAP_MSG_CLOSE 6				/* Close the connection with the remote peer */
+#define RPCAP_MSG_PACKET 7				/* This is a 'data' message, which carries a network packet */
+#define RPCAP_MSG_AUTH_REQ 8			/* Message that keeps the authentication parameters */
+#define RPCAP_MSG_STATS_REQ 9			/* It requires to have network statistics */
+#define RPCAP_MSG_ENDCAP_REQ 10			/* Stops the current capture, keeping the device open */
+#define RPCAP_MSG_SETSAMPLING_REQ 11	/* Set sampling parameters */
+
+#define RPCAP_MSG_FINDALLIF_REPLY	(128+RPCAP_MSG_FINDALLIF_REQ)		/* Keeps the list of all the remote interfaces */
+#define RPCAP_MSG_OPEN_REPLY		(128+RPCAP_MSG_OPEN_REQ)			/* The remote device has been opened correctly */
+#define RPCAP_MSG_STARTCAP_REPLY	(128+RPCAP_MSG_STARTCAP_REQ)		/* The capture is starting correctly */
+#define RPCAP_MSG_UPDATEFILTER_REPLY (128+RPCAP_MSG_UPDATEFILTER_REQ)	/* The filter has been applied correctly on the remote device */
+#define RPCAP_MSG_AUTH_REPLY		(128+RPCAP_MSG_AUTH_REQ)			/* Sends a message that says 'ok, authorization successful' */
+#define RPCAP_MSG_STATS_REPLY		(128+RPCAP_MSG_STATS_REQ)			/* Message that keeps the network statistics */
+#define RPCAP_MSG_ENDCAP_REPLY		(128+RPCAP_MSG_ENDCAP_REQ)			/* Confirms that the capture stopped successfully */
+#define RPCAP_MSG_SETSAMPLING_REPLY	(128+RPCAP_MSG_SETSAMPLING_REQ)		/* Confirms that the capture stopped successfully */
+
+#define RPCAP_STARTCAPREQ_FLAG_PROMISC 1	/* Enables promiscuous mode (default: disabled) */
+#define RPCAP_STARTCAPREQ_FLAG_DGRAM 2		/* Use a datagram (i.e. UDP) connection for the data stream (default: use TCP)*/
+#define RPCAP_STARTCAPREQ_FLAG_SERVEROPEN 4	/* The server has to open the data connection toward the client */
+#define RPCAP_STARTCAPREQ_FLAG_INBOUND 8	/* Capture only inbound packets (take care: the flag has no effects with promiscuous enabled) */
+#define RPCAP_STARTCAPREQ_FLAG_OUTBOUND 16	/* Capture only outbound packets (take care: the flag has no effects with promiscuous enabled) */
+
+#define RPCAP_UPDATEFILTER_BPF 1			/* This code tells us that the filter is encoded with the BPF/NPF syntax */
+
+
+/* Network error codes */
+#define PCAP_ERR_NETW 1					/* Network error */
+#define PCAP_ERR_INITTIMEOUT 2			/* The RPCAP initial timeout has expired */
+#define PCAP_ERR_AUTH 3					/* Generic authentication error */
+#define PCAP_ERR_FINDALLIF 4			/* Generic findalldevs error */
+#define PCAP_ERR_NOREMOTEIF 5			/* The findalldevs was ok, but the remote end had no interfaces to list */
+#define PCAP_ERR_OPEN 6					/* Generic pcap_open error */
+#define PCAP_ERR_UPDATEFILTER 7			/* Generic updatefilter error */
+#define PCAP_ERR_GETSTATS 8				/* Generic pcap_stats error */
+#define PCAP_ERR_READEX 9				/* Generic pcap_next_ex error */
+#define PCAP_ERR_HOSTNOAUTH 10			/* The host is not authorized to connect to this server */
+#define PCAP_ERR_REMOTEACCEPT 11		/* Generic pcap_remoteaccept error */
+#define PCAP_ERR_STARTCAPTURE 12		/* Generic pcap_startcapture error */
+#define PCAP_ERR_ENDCAPTURE 13			/* Generic pcap_endcapture error */
+#define PCAP_ERR_RUNTIMETIMEOUT	14		/* The RPCAP run-time timeout has expired */
+#define PCAP_ERR_SETSAMPLING 15			/* Error during the settings of sampling parameters */
+#define PCAP_ERR_WRONGMSG 16			/* The other end endpoint sent a message which has not been recognized */
+#define PCAP_ERR_WRONGVER 17			/* The other end endpoint has a version number that is not compatible with our */
+/*
+ * \}
+ * // end of private documentation
+ */
+
+
+/*********************************************************
+ *                                                       *
+ * Exported function prototypes                          *
+ *                                                       *
+ *********************************************************/
+int pcap_opensource_remote(pcap_t *p, struct pcap_rmtauth *auth);
+int pcap_startcapture_remote(pcap_t *fp);
+
+void rpcap_createhdr(struct rpcap_header *header, uint8 type, uint16 value, uint32 length);
+int rpcap_deseraddr(struct sockaddr_storage *sockaddrin, struct sockaddr_storage **sockaddrout, char *errbuf);
+int rpcap_checkmsg(char *errbuf, SOCKET sock, struct rpcap_header *header, uint8 first, ...);
+int rpcap_senderror(SOCKET sock, char *error, unsigned short errcode, char *errbuf);
+int rpcap_sendauth(SOCKET sock, struct pcap_rmtauth *auth, char *errbuf);
+
+SOCKET rpcap_remoteact_getsock(const char *host, int *isactive, char *errbuf);
+
+#endif
+
diff --git a/pcap-savefile.manfile b/pcap-savefile.manfile
new file mode 100644
index 0000000..f07d849
--- /dev/null
+++ b/pcap-savefile.manfile
@@ -0,0 +1,133 @@
+.\" 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-SAVEFILE 5 "8 March 2015"
+.SH NAME
+pcap-savefile \- libpcap savefile format
+.SH DESCRIPTION
+NOTE: applications and libraries should, if possible, use libpcap to
+read savefiles, rather than having their own code to read savefiles.
+If, in the future, a new file format is supported by libpcap,
+applications and libraries using libpcap to read savefiles will be able
+to read the new format of savefiles, but applications and libraries
+using their own code to read savefiles will have to be changed to
+support the new file format.
+.PP
+``Savefiles'' read and written by libpcap and applications using libpcap
+start with a per-file header.  The format of the per-file header is:
+.RS
+.TS
+box;
+c s
+c | c
+c s.
+Magic number
+_
+Major version	Minor version
+_
+Time zone offset
+_
+Time stamp accuracy
+_
+Snapshot length
+_
+Link-layer header type
+.TE
+.RE
+.PP
+All fields in the per-file header are in the byte order of the host
+writing the file.  Normally, the first field in the per-file header is a
+4-byte magic number, with the value 0xa1b2c3d4.  The magic number, when
+read by a host with the same byte order as the host that wrote the file,
+will have the value 0xa1b2c3d4, and, when read by a host with the
+opposite byte order as the host that wrote the file, will have the value
+0xd4c3b2a1.  That allows software reading the file to determine whether
+the byte order of the host that wrote the file is the same as the byte
+order of the host on which the file is being read, and thus whether the
+values in the per-file and per-packet headers need to be byte-swapped.
+.PP
+If the magic number has the value 0xa1b23c4d (with the two nibbles of
+the two lower-order bytes of the magic number swapped), which would be
+read as 0xa1b23c4d by a host with the same byte order as the host that
+wrote the file and as 0x4d3cb2a1 by a host with the opposite byte order
+as the host that wrote the file, the file format is the same as for
+regular files, except that the time stamps for packets are given in
+seconds and nanoseconds rather than seconds and microseconds.
+.PP
+Following this are:
+.IP
+A 2-byte file format major version number; the current version number is
+2.
+.IP
+A 2-byte file format minor version number; the current version number is
+4.
+.IP
+A 4-byte time zone offset; this is always 0.
+.IP
+A 4-byte number giving the accuracy of time stamps in the file; this is
+always 0.
+.IP
+A 4-byte number giving the "snapshot length" of the capture; packets
+longer than the snapshot length are truncated to the snapshot length, so
+that, if the snapshot length is
+.IR N ,
+only the first
+.I N
+bytes of a packet longer than
+.I N
+bytes will be saved in the capture.
+.IP
+a 4-byte number giving the link-layer header type for packets in the
+capture; see
+.BR pcap-linktype (7)
+for the
+.B LINKTYPE_
+values that can appear in this field.
+.PP
+Following the per-file header are zero or more packets; each packet
+begins with a per-packet header, which is immediately followed by the
+raw packet data.  The format of the per-packet header is:
+.RS
+.TS
+box;
+c.
+Time stamp, seconds value
+_
+Time stamp, microseconds or nanoseconds value
+_
+Length of captured packet data
+_
+Un-truncated length of the packet data
+.TE
+.RE
+.PP
+All fields in the per-packet header are in the byte order of the host
+writing the file.  The per-packet header begins with a time stamp giving
+the approximate time the packet was captured; the time stamp consists of
+a 4-byte value, giving the time in seconds since January 1, 1970,
+00:00:00 UTC, followed by a 4-byte value, giving the time in
+microseconds or nanoseconds since that second, depending on the magic
+number in the file header.  Following that are a 4-byte value giving the
+number of bytes of captured data that follow the per-packet header and a
+4-byte value giving the number of bytes that would have been present had
+the packet not been truncated by the snapshot length.  The two lengths
+will be equal if the number of bytes of packet data are less than or
+equal to the snapshot length.
+.SH SEE ALSO
+pcap(3PCAP), pcap-linktype(7)
diff --git a/pcap-savefile.manfile.in b/pcap-savefile.manfile.in
index 622f6c6..451dd90 100644
--- a/pcap-savefile.manfile.in
+++ b/pcap-savefile.manfile.in
@@ -17,7 +17,7 @@
 .\" WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
 .\" MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
 .\"
-.TH PCAP-SAVEFILE @MAN_FILE_FORMATS@ "29 July 2013"
+.TH PCAP-SAVEFILE @MAN_FILE_FORMATS@ "8 March 2015"
 .SH NAME
 pcap-savefile \- libpcap savefile format
 .SH DESCRIPTION
diff --git a/pcap-septel.c b/pcap-septel.c
index 61cd2f5..88dc89d 100644
--- a/pcap-septel.c
+++ b/pcap-septel.c
@@ -232,7 +232,7 @@
 	/* OK, it's probably ours. */
 	*is_ours = 1;
 
-	p = pcap_create_common(device, ebuf, sizeof (struct pcap_septel));
+	p = pcap_create_common(ebuf, sizeof (struct pcap_septel));
 	if (p == NULL)
 		return NULL;
 
@@ -276,7 +276,7 @@
   /* Make our private copy of the filter */
 
   if (install_bpf_program(p, fp) < 0) {
-    snprintf(p->errbuf, sizeof(p->errbuf),
+    pcap_snprintf(p->errbuf, sizeof(p->errbuf),
 	     "malloc: %s", pcap_strerror(errno));
     return -1;
   }
@@ -291,3 +291,31 @@
   fprintf(errbuf, PCAP_ERRBUF_SIZE, "Non-blocking mode not supported on Septel devices");
   return (-1);
 }
+
+#ifdef SEPTEL_ONLY
+/*
+ * This libpcap build supports only Septel cards, not regular network
+ * interfaces.
+ */
+
+/*
+ * There are no regular interfaces, just Septel interfaces.
+ */
+int
+pcap_platform_finddevs(pcap_if_t **alldevsp, char *errbuf)
+{
+  *alldevsp = NULL;
+  return (0);
+}
+
+/*
+ * Attempts to open a regular interface fail.
+ */
+pcap_t *
+pcap_create_interface(const char *device, char *errbuf)
+{
+  pcap_snprintf(errbuf, PCAP_ERRBUF_SIZE,
+                "This version of libpcap only supports Septel cards");
+  return (NULL);
+}
+#endif
diff --git a/pcap-sita.c b/pcap-sita.c
index b35b106..1cd5f75 100644
--- a/pcap-sita.c
+++ b/pcap-sita.c
@@ -208,10 +208,14 @@
 
 	empty_unit_iface(u);
 	if (u->imsg) {											/* then if an inbound message buffer exists */
-		u->imsg = (char *)realloc(u->imsg, 1);				/* and re-allocate the old large buffer into a new small one */
-		if (u->imsg == NULL) {	/* oops, realloc call failed */
-			fprintf(stderr, "Warning...call to realloc() failed, value of errno is %d\n", errno);
+		void *bigger_buffer;
 
+		bigger_buffer = (char *)realloc(u->imsg, 1);				/* and re-allocate the old large buffer into a new small one */
+		if (bigger_buffer == NULL) {	/* oops, realloc call failed */
+			fprintf(stderr, "Warning...call to realloc() failed, value of errno is %d\n", errno);
+			return;
+		}
+		u->imsg = bigger_buffer;
 	}
 }
 
@@ -262,7 +266,7 @@
 
 	empty_unit_table();
 	if ((fp = fopen("/etc/hosts", "r")) == NULL) {										/* try to open the hosts file and if it fails */
-		snprintf(errbuf, PCAP_ERRBUF_SIZE, "Cannot open '/etc/hosts' for reading.");	/* return the nohostsfile error response */
+		pcap_snprintf(errbuf, PCAP_ERRBUF_SIZE, "Cannot open '/etc/hosts' for reading.");	/* return the nohostsfile error response */
 		return -1;
 	}
 	while (fgets(buf, MAX_LINE_SIZE-1, fp)) {			/* while looping over the file */
@@ -285,11 +289,11 @@
 		geoslot = *(ptr2 + 5) - '0';					/* and geo-slot number */
 		if (chassis < 1 || chassis > MAX_CHASSIS ||
 			geoslot < 1 || geoslot > MAX_GEOSLOT) {		/* if the chassis and/or slot numbers appear to be bad... */
-			snprintf(errbuf, PCAP_ERRBUF_SIZE, "Invalid ACN name in '/etc/hosts'.");	/* warn the user */
+			pcap_snprintf(errbuf, PCAP_ERRBUF_SIZE, "Invalid ACN name in '/etc/hosts'.");	/* warn the user */
 			continue;																	/* and ignore the entry */
 		}
 		if ((ptr2 = (char *)malloc(strlen(ptr) + 1)) == NULL) {
-			snprintf(errbuf, PCAP_ERRBUF_SIZE, "malloc: %s", pcap_strerror(errno));
+			pcap_snprintf(errbuf, PCAP_ERRBUF_SIZE, "malloc: %s", pcap_strerror(errno));
 			continue;
 		}
 		strcpy(ptr2, ptr);								/* copy the IP address into our malloc'ed memory */
@@ -402,14 +406,14 @@
 
 static void nonUnified_IOP_port_name(char *buf, size_t bufsize, const char *proto, unit_t *u) {
 
-	snprintf(buf, bufsize, "%s_%d_%d", proto, u->chassis, u->geoslot);
+	pcap_snprintf(buf, bufsize, "%s_%d_%d", proto, u->chassis, u->geoslot);
 }
 
 static void unified_IOP_port_name(char *buf, size_t bufsize, const char *proto, unit_t *u, int IOPportnum) {
 	int			portnum;
 
 	portnum = ((u->chassis - 1) * 64) + ((u->geoslot - 1) * 8) + IOPportnum + 1;
-	snprintf(buf, bufsize, "%s_%d", proto, portnum);
+	pcap_snprintf(buf, bufsize, "%s_%d", proto, portnum);
 }
 
 static char *translate_IOP_to_pcap_name(unit_t *u, char *IOPname, bpf_u_int32 iftype) {
@@ -568,6 +572,7 @@
 	char				*newname;
 	bpf_u_int32				interfaceType;
 	unsigned char		flags;
+	void *bigger_buffer;
 
 	prev_iff = 0;
 	for (chassis = 0; chassis <= MAX_CHASSIS; chassis++) {
@@ -577,7 +582,7 @@
 			ptr = u->imsg;													/* point to the start of the msg for this IOP */
 			while (ptr < (u->imsg + u->len)) {
 				if ((iff = malloc(sizeof(pcap_if_t))) == NULL) {
-					snprintf(errbuf, PCAP_ERRBUF_SIZE, "malloc: %s", pcap_strerror(errno));
+					pcap_snprintf(errbuf, PCAP_ERRBUF_SIZE, "malloc: %s", pcap_strerror(errno));
 					return -1;
 				}
 				memset((char *)iff, 0, sizeof(pcap_if_t)); /* bzero() is deprecated, replaced with memset() */
@@ -586,7 +591,7 @@
 
 				if (*ptr) {													/* if there is a count for the name */
 					if ((iff->name = malloc(*ptr + 1)) == NULL) {			/* get that amount of space */
-						snprintf(errbuf, PCAP_ERRBUF_SIZE, "malloc: %s", pcap_strerror(errno));
+						pcap_snprintf(errbuf, PCAP_ERRBUF_SIZE, "malloc: %s", pcap_strerror(errno));
 						return -1;
 					}
 					memcpy(iff->name, (ptr + 1), *ptr);						/* copy the name into the malloc'ed space */
@@ -597,7 +602,7 @@
 
 				if (*ptr) {													/* if there is a count for the description */
 					if ((iff->description = malloc(*ptr + 1)) == NULL) {	/* get that amount of space */
-						snprintf(errbuf, PCAP_ERRBUF_SIZE, "malloc: %s", pcap_strerror(errno));
+						pcap_snprintf(errbuf, PCAP_ERRBUF_SIZE, "malloc: %s", pcap_strerror(errno));
 						return -1;
 					}
 					memcpy(iff->description, (ptr + 1), *ptr);				/* copy the name into the malloc'ed space */
@@ -617,15 +622,15 @@
 				prev_addr = 0;
 				while (address_count--) {
 					if ((addr = malloc(sizeof(pcap_addr_t))) == NULL) {
-						snprintf(errbuf, PCAP_ERRBUF_SIZE, "malloc: %s", pcap_strerror(errno));
+						pcap_snprintf(errbuf, PCAP_ERRBUF_SIZE, "malloc: %s", pcap_strerror(errno));
 						return -1;
 					}
-+					memset((char *)addr, 0, sizeof(pcap_addr_t)); /* bzero() is deprecated, replaced with memset() */
+ 					memset((char *)addr, 0, sizeof(pcap_addr_t)); /* bzero() is deprecated, replaced with memset() */
 					if (iff->addresses == 0) iff->addresses = addr;
 					if (prev_addr) prev_addr->next = addr;							/* insert a forward link */
 					if (*ptr) {														/* if there is a count for the address */
 						if ((s = malloc(sizeof(struct sockaddr_in))) == NULL) {		/* get that amount of space */
-							snprintf(errbuf, PCAP_ERRBUF_SIZE, "malloc: %s", pcap_strerror(errno));
+							pcap_snprintf(errbuf, PCAP_ERRBUF_SIZE, "malloc: %s", pcap_strerror(errno));
 							return -1;
 						}
 						memset((char *)s, 0, sizeof(struct sockaddr_in)); /* bzero() is deprecated, replaced with memset() */
@@ -637,7 +642,7 @@
 					ptr++;													/* then forwards one more for the 'length of the address' field */
 					if (*ptr) {												/* process any netmask */
 						if ((s = malloc(sizeof(struct sockaddr_in))) == NULL) {
-							snprintf(errbuf, PCAP_ERRBUF_SIZE, "malloc: %s", pcap_strerror(errno));
+							pcap_snprintf(errbuf, PCAP_ERRBUF_SIZE, "malloc: %s", pcap_strerror(errno));
 							return -1;
 						}
 						/* bzero() is deprecated, replaced with memset() */
@@ -651,7 +656,7 @@
 					ptr++;
 					if (*ptr) {												/* process any broadcast address */
 						if ((s = malloc(sizeof(struct sockaddr_in))) == NULL) {
-							snprintf(errbuf, PCAP_ERRBUF_SIZE, "malloc: %s", pcap_strerror(errno));
+							pcap_snprintf(errbuf, PCAP_ERRBUF_SIZE, "malloc: %s", pcap_strerror(errno));
 							return -1;
 						}
 						/* bzero() is deprecated, replaced with memset() */
@@ -665,7 +670,7 @@
 					ptr++;
 					if (*ptr) {												/* process any destination address */
 						if ((s = malloc(sizeof(struct sockaddr_in))) == NULL) {
-							snprintf(errbuf, PCAP_ERRBUF_SIZE, "malloc: %s", pcap_strerror(errno));
+							pcap_snprintf(errbuf, PCAP_ERRBUF_SIZE, "malloc: %s", pcap_strerror(errno));
 							return -1;
 						}
 						/* bzero() is deprecated, replaced with memset() */
@@ -682,10 +687,12 @@
 				prev_iff = iff;
 
 				newname = translate_IOP_to_pcap_name(u, iff->name, interfaceType);		/* add a translation entry and get a point to the mangled name */
-				if ((iff->name = realloc(iff->name, strlen(newname) + 1)) == NULL) {	/* we now re-write the name stored in the interface list */
-					snprintf(errbuf, PCAP_ERRBUF_SIZE, "realloc: %s", pcap_strerror(errno));
+				bigger_buffer = realloc(iff->name, strlen(newname) + 1));
+				if (bigger_buffer == NULL) {	/* we now re-write the name stored in the interface list */
+					pcap_snprintf(errbuf, PCAP_ERRBUF_SIZE, "realloc: %s", pcap_strerror(errno));
 					return -1;
 				}
+				iff->name = bigger_buffer;
 				strcpy(iff->name, newname);												/* to this new name */
 			}
 		}
@@ -816,7 +823,7 @@
 	iface_t		*p;
 	pcap_if_t	*alldevsp;
 
-	pcap_findalldevs_interfaces(&alldevsp, errbuf);
+	pcap_platform_finddevs(&alldevsp, errbuf);
 	for (chassis = 0; chassis <= MAX_CHASSIS; chassis++) {										/* scan the table... */
 		for (geoslot = 0; geoslot <= MAX_GEOSLOT; geoslot++) {
 			u = &units[chassis][geoslot];
@@ -892,7 +899,7 @@
 }
 
 static int pcap_setdirection_acn(pcap_t *handle, pcap_direction_t d) {
-	snprintf(handle->errbuf, sizeof(handle->errbuf),
+	pcap_snprintf(handle->errbuf, sizeof(handle->errbuf),
 	    "Setting direction is not supported on ACN adapters");
 	return -1;
 }
@@ -951,7 +958,7 @@
 	pcap_header.caplen		= ntohl(*(uint32_t *)&packet_header[8]);				/* caplen */
 	pcap_header.len			= ntohl(*(uint32_t *)&packet_header[12]);				/* len */
 
-	handle->bp = handle->buffer + handle->offset;									/* start off the receive pointer at the right spot */
+	handle->bp = (u_char *)handle->buffer + handle->offset;									/* start off the receive pointer at the right spot */
 	if (acn_read_n_bytes_with_timeout(handle, pcap_header.caplen) == -1) return 0;	/* then try to read in the rest of the data */
 
 	callback(user, &pcap_header, handle->bp);										/* call the user supplied callback function */
@@ -981,7 +988,7 @@
 	handle->read_op = pcap_read_acn;
 	handle->stats_op = pcap_stats_acn;
 
-	fd = acn_open_live(handle->opt.source, handle->errbuf,
+	fd = acn_open_live(handle->opt.device, handle->errbuf,
 	    &handle->linktype);
 	if (fd == -1)
 		return PCAP_ERROR;
@@ -992,7 +999,7 @@
 
 	handle->buffer	 = malloc(handle->bufsize + handle->offset);
 	if (!handle->buffer) {
-	        snprintf(handle->errbuf, PCAP_ERRBUF_SIZE,
+	        pcap_snprintf(handle->errbuf, PCAP_ERRBUF_SIZE,
 			 "malloc: %s", pcap_strerror(errno));
 		pcap_cleanup_acn(handle);
 		return PCAP_ERROR;
@@ -1007,13 +1014,36 @@
 	return 0;
 }
 
-pcap_t *pcap_create_interface(const char *device, char *ebuf) {
+pcap_t *pcap_create_interface(const char *device _U_, char *ebuf) {
 	pcap_t *p;
 
-	p = pcap_create_common(device, ebuf, 0);
+	p = pcap_create_common(ebuf, 0);
 	if (p == NULL)
 		return (NULL);
 
 	p->activate_op = pcap_activate_sita;
 	return (p);
 }
+
+int pcap_platform_finddevs(pcap_if_t **alldevsp, char *errbuf) {
+
+	//printf("pcap_findalldevs()\n");				// fulko
+
+	*alldevsp = 0;												/* initialize the returned variables before we do anything */
+	strcpy(errbuf, "");
+	if (acn_parse_hosts_file(errbuf))							/* scan the hosts file for potential IOPs */
+		{
+		//printf("pcap_findalldevs() returning BAD after parsehosts\n");				// fulko
+		return -1;
+		}
+	//printf("pcap_findalldevs() got hostlist now finding devs\n");				// fulko
+	if (acn_findalldevs(errbuf))								/* then ask the IOPs for their monitorable devices */
+		{
+		//printf("pcap_findalldevs() returning BAD after findalldevs\n");				// fulko
+		return -1;
+		}
+	*alldevsp = acn_if_list;
+	acn_if_list = 0;											/* then forget our list head, because someone will call pcap_freealldevs() to empty the malloc'ed stuff */
+	//printf("pcap_findalldevs() returning ZERO OK\n");				// fulko
+	return 0;
+}
diff --git a/pcap-snf.c b/pcap-snf.c
index 03dc08d..207c495 100644
--- a/pcap-snf.c
+++ b/pcap-snf.c
@@ -51,7 +51,7 @@
 	int rc;
 
 	if ((rc = snf_ring_getstats(snfps->snf_ring, &stats))) {
-		snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "snf_get_stats: %s",
+		pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "snf_get_stats: %s",
 			 pcap_strerror(rc));
 		return -1;
 	}
@@ -66,9 +66,6 @@
 {
 	struct pcap_snf *ps = p->priv;
 
-	if (p == NULL)
-		return;
-
 #ifdef SNF_HAVE_INJECT_API
         if (ps->snf_inj)
                 snf_inject_close(ps->snf_inj);
@@ -164,7 +161,7 @@
 				continue;
 			}
 			else {
-				snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "snf_read: %s",
+				pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "snf_read: %s",
 				 	 pcap_strerror(err));
 				return -1;
 			}
@@ -219,7 +216,7 @@
         if (ps->snf_inj == NULL) {
                 rc = snf_inject_open(ps->snf_boardnum, 0, &ps->snf_inj);
                 if (rc) {
-                        snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
+                        pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
                                 "snf_inject_open: %s", pcap_strerror(rc));
                         return (-1);
                 }
@@ -230,7 +227,7 @@
                 return (size);
         }
         else {
-                snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "snf_inject_send: %s",
+                pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "snf_inject_send: %s",
                          pcap_strerror(rc));
                 return (-1);
         }
@@ -245,13 +242,13 @@
 snf_activate(pcap_t* p)
 {
 	struct pcap_snf *ps = p->priv;
-	char *device = p->opt.source;
+	char *device = p->opt.device;
 	const char *nr = NULL;
 	int err;
 	int flags = -1, ring_id = -1;
 
 	if (device == NULL) {
-		snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
+		pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
 			 "device is NULL: %s", pcap_strerror(errno));
 		return -1;
 	}
@@ -272,7 +269,7 @@
 			flags, /* may want pshared */
 			&ps->snf_handle);
 	if (err != 0) {
-		snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
+		pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
 			 "snf_open failed: %s", pcap_strerror(err));
 		return -1;
 	}
@@ -282,7 +279,7 @@
 	}
 	err = snf_ring_open_id(ps->snf_handle, ring_id, &ps->snf_ring);
 	if (err != 0) {
-		snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
+		pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
 			 "snf_ring_open_id(ring=%d) failed: %s",
 			 ring_id, pcap_strerror(err));
 		return -1;
@@ -295,7 +292,7 @@
 
 	err = snf_start(ps->snf_handle);
 	if (err != 0) {
-		snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
+		pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
 			 "snf_start failed: %s", pcap_strerror(err));
 		return -1;
 	}
@@ -335,7 +332,7 @@
 
 	if (snf_getifaddrs(&ifaddrs) || ifaddrs == NULL)
 	{
-		(void)snprintf(errbuf, PCAP_ERRBUF_SIZE,
+		(void)pcap_snprintf(errbuf, PCAP_ERRBUF_SIZE,
 			"snf_getifaddrs: %s", pcap_strerror(errno));
 		return (-1);
 	}
@@ -347,7 +344,7 @@
 		 */
 		curdev = (pcap_if_t *)malloc(sizeof(pcap_if_t));
 		if (curdev == NULL) {
-		(void)snprintf(errbuf, PCAP_ERRBUF_SIZE,
+		(void)pcap_snprintf(errbuf, PCAP_ERRBUF_SIZE,
 			"snf_findalldevs malloc: %s", pcap_strerror(errno));
 			return (-1);
 		}
@@ -361,16 +358,16 @@
 		curdev->next = NULL;
 		curdev->name = strdup(ifa->snf_ifa_name);
 		if (curdev->name == NULL) {
-			(void)snprintf(errbuf, PCAP_ERRBUF_SIZE,
+			(void)pcap_snprintf(errbuf, PCAP_ERRBUF_SIZE,
 			    "snf_findalldevs strdup: %s", pcap_strerror(errno));
 			free(curdev);
 			return (-1);
 		}
-		(void)snprintf(desc,MAX_DESC_LENGTH,"Myricom snf%d",
+		(void)pcap_snprintf(desc,MAX_DESC_LENGTH,"Myricom snf%d",
 				ifa->snf_ifa_portnum);
 		curdev->description = strdup(desc);
 		if (curdev->description == NULL) {
-			(void)snprintf(errbuf, PCAP_ERRBUF_SIZE,
+			(void)pcap_snprintf(errbuf, PCAP_ERRBUF_SIZE,
 			"snf_findalldevs strdup1: %s", pcap_strerror(errno));
 			free(curdev->name);
 			free(curdev);
@@ -381,7 +378,7 @@
 
 		curaddr = (pcap_addr_t *)malloc(sizeof(pcap_addr_t));
 		if (curaddr == NULL) {
-			(void)snprintf(errbuf, PCAP_ERRBUF_SIZE,
+			(void)pcap_snprintf(errbuf, PCAP_ERRBUF_SIZE,
 			     "snf_findalldevs malloc1: %s", pcap_strerror(errno));
 			free(curdev->description);
 			free(curdev->name);
@@ -392,7 +389,7 @@
 		curaddr->next = NULL;
 		curaddr->addr = (struct sockaddr*)malloc(sizeof(struct sockaddr_storage));
 		if (curaddr->addr == NULL) {
-			(void)snprintf(errbuf, PCAP_ERRBUF_SIZE,
+			(void)pcap_snprintf(errbuf, PCAP_ERRBUF_SIZE,
 			    "malloc2: %s", pcap_strerror(errno));
 			free(curdev->description);
 			free(curdev->name);
@@ -470,7 +467,7 @@
 	/* OK, it's probably ours. */
 	*is_ours = 1;
 
-	p = pcap_create_common(device, ebuf, sizeof (struct pcap_snf));
+	p = pcap_create_common(ebuf, sizeof (struct pcap_snf));
 	if (p == NULL)
 		return NULL;
 	ps = p->priv;
@@ -481,11 +478,9 @@
 	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_snprintf(ebuf, PCAP_ERRBUF_SIZE, "malloc: %s",
 		    pcap_strerror(errno));
-		if (p->tstamp_type_list != NULL)
-			free(p->tstamp_type_list);
-		free(p);
+		pcap_close(p);
 		return NULL;
 	}
 	p->tstamp_precision_list[0] = PCAP_TSTAMP_PRECISION_MICRO;
@@ -495,3 +490,31 @@
 	ps->snf_boardnum = boardnum;
 	return p;
 }
+
+#ifdef SNF_ONLY
+/*
+ * This libpcap build supports only SNF cards, not regular network
+ * interfaces..
+ */
+
+/*
+ * There are no regular interfaces, just DAG interfaces.
+ */
+int
+pcap_platform_finddevs(pcap_if_t **alldevsp, char *errbuf)
+{
+	*alldevsp = NULL;
+	return (0);
+}
+
+/*
+ * Attempts to open a regular interface fail.
+ */
+pcap_t *
+pcap_create_interface(const char *device, char *errbuf)
+{
+	pcap_snprintf(errbuf, PCAP_ERRBUF_SIZE,
+	    "This version of libpcap only supports SNF cards");
+	return NULL;
+}
+#endif
diff --git a/pcap-snit.c b/pcap-snit.c
index 0ce7860..7934945 100644
--- a/pcap-snit.c
+++ b/pcap-snit.c
@@ -130,11 +130,11 @@
 		if (cc < 0) {
 			if (errno == EWOULDBLOCK)
 				return (0);
-			snprintf(p->errbuf, sizeof(p->errbuf), "pcap_read: %s",
+			pcap_snprintf(p->errbuf, sizeof(p->errbuf), "pcap_read: %s",
 				pcap_strerror(errno));
 			return (-1);
 		}
-		bp = p->buffer;
+		bp = (u_char *)p->buffer;
 	} else
 		bp = p->bp;
 
@@ -223,7 +223,7 @@
 	data.len = size;
 	ret = putmsg(p->fd, &ctl, &data);
 	if (ret == -1) {
-		snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "send: %s",
+		pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "send: %s",
 		    pcap_strerror(errno));
 		return (-1);
 	}
@@ -247,7 +247,7 @@
 		si.ic_len = sizeof(zero);
 		si.ic_dp = (char *)&zero;
 		if (ioctl(p->fd, I_STR, (char *)&si) < 0) {
-			snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "NIOCSCHUNK: %s",
+			pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "NIOCSCHUNK: %s",
 			    pcap_strerror(errno));
 			return (-1);
 		}
@@ -260,7 +260,7 @@
 		si.ic_len = sizeof(timeout);
 		si.ic_dp = (char *)&timeout;
 		if (ioctl(p->fd, I_STR, (char *)&si) < 0) {
-			snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "NIOCSTIME: %s",
+			pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "NIOCSTIME: %s",
 			    pcap_strerror(errno));
 			return (-1);
 		}
@@ -272,7 +272,7 @@
 	si.ic_len = sizeof(flags);
 	si.ic_dp = (char *)&flags;
 	if (ioctl(p->fd, I_STR, (char *)&si) < 0) {
-		snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "NIOCSFLAGS: %s",
+		pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "NIOCSFLAGS: %s",
 		    pcap_strerror(errno));
 		return (-1);
 	}
@@ -286,7 +286,7 @@
 	struct ifreq ifr;		/* interface request struct */
 	int chunksize = CHUNKSIZE;
 	int fd;
-	static char dev[] = "/dev/nit";
+	static const char dev[] = "/dev/nit";
 
 	if (p->opt.rfmon) {
 		/*
@@ -320,19 +320,19 @@
 	if (fd < 0 && errno == EACCES)
 		p->fd = fd = open(dev, O_RDONLY);
 	if (fd < 0) {
-		snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "%s: %s", dev,
+		pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "%s: %s", dev,
 		    pcap_strerror(errno));
 		goto bad;
 	}
 
 	/* arrange to get discrete messages from the STREAM and use NIT_BUF */
 	if (ioctl(fd, I_SRDOPT, (char *)RMSGD) < 0) {
-		snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "I_SRDOPT: %s",
+		pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "I_SRDOPT: %s",
 		    pcap_strerror(errno));
 		goto bad;
 	}
 	if (ioctl(fd, I_PUSH, "nbuf") < 0) {
-		snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "push nbuf: %s",
+		pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "push nbuf: %s",
 		    pcap_strerror(errno));
 		goto bad;
 	}
@@ -342,19 +342,24 @@
 	si.ic_len = sizeof(chunksize);
 	si.ic_dp = (char *)&chunksize;
 	if (ioctl(fd, I_STR, (char *)&si) < 0) {
-		snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "NIOCSCHUNK: %s",
+		pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "NIOCSCHUNK: %s",
 		    pcap_strerror(errno));
 		goto bad;
 	}
 
 	/* request the interface */
-	strncpy(ifr.ifr_name, p->opt.source, sizeof(ifr.ifr_name));
+	strncpy(ifr.ifr_name, p->opt.device, sizeof(ifr.ifr_name));
 	ifr.ifr_name[sizeof(ifr.ifr_name) - 1] = '\0';
 	si.ic_cmd = NIOCBIND;
 	si.ic_len = sizeof(ifr);
 	si.ic_dp = (char *)&ifr;
 	if (ioctl(fd, I_STR, (char *)&si) < 0) {
-		snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "NIOCBIND: %s: %s",
+		/*
+		 * XXX - is there an error that means "no such device"?
+		 * Is there one that means "that device doesn't support
+		 * STREAMS NIT"?
+		 */
+		pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "NIOCBIND: %s: %s",
 			ifr.ifr_name, pcap_strerror(errno));
 		goto bad;
 	}
@@ -364,7 +369,7 @@
 	si.ic_len = sizeof(p->snapshot);
 	si.ic_dp = (char *)&p->snapshot;
 	if (ioctl(fd, I_STR, (char *)&si) < 0) {
-		snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "NIOCSSNAP: %s",
+		pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "NIOCSSNAP: %s",
 		    pcap_strerror(errno));
 		goto bad;
 	}
@@ -378,7 +383,7 @@
 	p->linktype = DLT_EN10MB;
 
 	p->bufsize = BUFSPACE;
-	p->buffer = (u_char *)malloc(p->bufsize);
+	p->buffer = malloc(p->bufsize);
 	if (p->buffer == NULL) {
 		strlcpy(p->errbuf, pcap_strerror(errno), PCAP_ERRBUF_SIZE);
 		goto bad;
@@ -426,11 +431,11 @@
 }
 
 pcap_t *
-pcap_create_interface(const char *device, char *ebuf)
+pcap_create_interface(const char *device _U_, char *ebuf)
 {
 	pcap_t *p;
 
-	p = pcap_create_common(device, ebuf, sizeof (struct pcap_snit));
+	p = pcap_create_common(ebuf, sizeof (struct pcap_snit));
 	if (p == NULL)
 		return (NULL);
 
@@ -438,8 +443,18 @@
 	return (p);
 }
 
+/*
+ * XXX - there's probably a NIOCBIND error that means "that device
+ * doesn't support NIT"; if so, we should try an NIOCBIND and use that.
+ */
+static int
+can_be_bound(const char *name _U_)
+{
+	return (1);
+}
+
 int
 pcap_platform_finddevs(pcap_if_t **alldevsp, char *errbuf)
 {
-	return (0);
+	return (pcap_findalldevs_interfaces(alldevsp, errbuf, can_be_bound));
 }
diff --git a/pcap-snoop.c b/pcap-snoop.c
index f622f31..687b1d9 100644
--- a/pcap-snoop.c
+++ b/pcap-snoop.c
@@ -95,7 +95,7 @@
 		case EWOULDBLOCK:
 			return (0);			/* XXX */
 		}
-		snprintf(p->errbuf, sizeof(p->errbuf),
+		pcap_snprintf(p->errbuf, sizeof(p->errbuf),
 		    "read: %s", pcap_strerror(errno));
 		return (-1);
 	}
@@ -150,7 +150,7 @@
 	 */
 	ret = write(p->fd, buf, size);
 	if (ret == -1) {
-		snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "send: %s",
+		pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "send: %s",
 		    pcap_strerror(errno));
 		return (-1);
 	}
@@ -167,7 +167,7 @@
 	rs = &rawstats;
 	memset(rs, 0, sizeof(*rs));
 	if (ioctl(p->fd, SIOCRAWSTATS, (char *)rs) < 0) {
-		snprintf(p->errbuf, sizeof(p->errbuf),
+		pcap_snprintf(p->errbuf, sizeof(p->errbuf),
 		    "SIOCRAWSTATS: %s", pcap_strerror(errno));
 		return (-1);
 	}
@@ -212,22 +212,29 @@
 
 	fd = socket(PF_RAW, SOCK_RAW, RAWPROTO_SNOOP);
 	if (fd < 0) {
-		snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "snoop socket: %s",
+		pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "snoop socket: %s",
 		    pcap_strerror(errno));
 		goto bad;
 	}
 	p->fd = fd;
 	memset(&sr, 0, sizeof(sr));
 	sr.sr_family = AF_RAW;
-	(void)strncpy(sr.sr_ifname, p->opt.source, sizeof(sr.sr_ifname));
+	(void)strncpy(sr.sr_ifname, p->opt.device, sizeof(sr.sr_ifname));
 	if (bind(fd, (struct sockaddr *)&sr, sizeof(sr))) {
-		snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "snoop bind: %s",
+		/*
+		 * XXX - there's probably a particular bind error that
+		 * means "there's no such device" and a particular bind
+		 * error that means "that device doesn't support snoop";
+		 * they might be the same error, if they both end up
+		 * meaning "snoop doesn't know about that device".
+		 */
+		pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "snoop bind: %s",
 		    pcap_strerror(errno));
 		goto bad;
 	}
 	memset(&sf, 0, sizeof(sf));
 	if (ioctl(fd, SIOCADDSNOOP, &sf) < 0) {
-		snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "SIOCADDSNOOP: %s",
+		pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "SIOCADDSNOOP: %s",
 		    pcap_strerror(errno));
 		goto bad;
 	}
@@ -239,19 +246,19 @@
 	/*
 	 * XXX hack - map device name to link layer type
 	 */
-	if (strncmp("et", p->opt.source, 2) == 0 ||	/* Challenge 10 Mbit */
-	    strncmp("ec", p->opt.source, 2) == 0 ||	/* Indigo/Indy 10 Mbit,
+	if (strncmp("et", p->opt.device, 2) == 0 ||	/* Challenge 10 Mbit */
+	    strncmp("ec", p->opt.device, 2) == 0 ||	/* Indigo/Indy 10 Mbit,
 							   O2 10/100 */
-	    strncmp("ef", p->opt.source, 2) == 0 ||	/* O200/2000 10/100 Mbit */
-	    strncmp("eg", p->opt.source, 2) == 0 ||	/* Octane/O2xxx/O3xxx Gigabit */
-	    strncmp("gfe", p->opt.source, 3) == 0 ||	/* GIO 100 Mbit */
-	    strncmp("fxp", p->opt.source, 3) == 0 ||	/* Challenge VME Enet */
-	    strncmp("ep", p->opt.source, 2) == 0 ||	/* Challenge 8x10 Mbit EPLEX */
-	    strncmp("vfe", p->opt.source, 3) == 0 ||	/* Challenge VME 100Mbit */
-	    strncmp("fa", p->opt.source, 2) == 0 ||
-	    strncmp("qaa", p->opt.source, 3) == 0 ||
-	    strncmp("cip", p->opt.source, 3) == 0 ||
-	    strncmp("el", p->opt.source, 2) == 0) {
+	    strncmp("ef", p->opt.device, 2) == 0 ||	/* O200/2000 10/100 Mbit */
+	    strncmp("eg", p->opt.device, 2) == 0 ||	/* Octane/O2xxx/O3xxx Gigabit */
+	    strncmp("gfe", p->opt.device, 3) == 0 ||	/* GIO 100 Mbit */
+	    strncmp("fxp", p->opt.device, 3) == 0 ||	/* Challenge VME Enet */
+	    strncmp("ep", p->opt.device, 2) == 0 ||	/* Challenge 8x10 Mbit EPLEX */
+	    strncmp("vfe", p->opt.device, 3) == 0 ||	/* Challenge VME 100Mbit */
+	    strncmp("fa", p->opt.device, 2) == 0 ||
+	    strncmp("qaa", p->opt.device, 3) == 0 ||
+	    strncmp("cip", p->opt.device, 3) == 0 ||
+	    strncmp("el", p->opt.device, 2) == 0) {
 		p->linktype = DLT_EN10MB;
 		p->offset = RAW_HDRPAD(sizeof(struct ether_header));
 		ll_hdrlen = sizeof(struct ether_header);
@@ -284,26 +291,26 @@
 			p->dlt_list[1] = DLT_DOCSIS;
 			p->dlt_count = 2;
 		}
-	} else if (strncmp("ipg", p->opt.source, 3) == 0 ||
-		   strncmp("rns", p->opt.source, 3) == 0 ||	/* O2/200/2000 FDDI */
-		   strncmp("xpi", p->opt.source, 3) == 0) {
+	} else if (strncmp("ipg", p->opt.device, 3) == 0 ||
+		   strncmp("rns", p->opt.device, 3) == 0 ||	/* O2/200/2000 FDDI */
+		   strncmp("xpi", p->opt.device, 3) == 0) {
 		p->linktype = DLT_FDDI;
 		p->offset = 3;				/* XXX yeah? */
 		ll_hdrlen = 13;
-	} else if (strncmp("ppp", p->opt.source, 3) == 0) {
+	} else if (strncmp("ppp", p->opt.device, 3) == 0) {
 		p->linktype = DLT_RAW;
 		ll_hdrlen = 0;	/* DLT_RAW meaning "no PPP header, just the IP packet"? */
-	} else if (strncmp("qfa", p->opt.source, 3) == 0) {
+	} else if (strncmp("qfa", p->opt.device, 3) == 0) {
 		p->linktype = DLT_IP_OVER_FC;
 		ll_hdrlen = 24;
-	} else if (strncmp("pl", p->opt.source, 2) == 0) {
+	} else if (strncmp("pl", p->opt.device, 2) == 0) {
 		p->linktype = DLT_RAW;
 		ll_hdrlen = 0;	/* Cray UNICOS/mp pseudo link */
-	} else if (strncmp("lo", p->opt.source, 2) == 0) {
+	} else if (strncmp("lo", p->opt.device, 2) == 0) {
 		p->linktype = DLT_NULL;
 		ll_hdrlen = 4;
 	} else {
-		snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
+		pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
 		    "snoop: unknown physical layer type");
 		goto bad;
 	}
@@ -323,9 +330,9 @@
 	 * the MTU first and, if that succeeds, trim the snap length
 	 * to be no greater than the MTU.
 	 */
-	(void)strncpy(ifr.ifr_name, p->opt.source, sizeof(ifr.ifr_name));
+	(void)strncpy(ifr.ifr_name, p->opt.device, sizeof(ifr.ifr_name));
 	if (ioctl(fd, SIOCGIFMTU, (char *)&ifr) < 0) {
-		snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "SIOCGIFMTU: %s",
+		pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "SIOCGIFMTU: %s",
 		    pcap_strerror(errno));
 		goto bad;
 	}
@@ -359,21 +366,21 @@
 	if (snooplen < 0)
 		snooplen = 0;
 	if (ioctl(fd, SIOCSNOOPLEN, &snooplen) < 0) {
-		snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "SIOCSNOOPLEN: %s",
+		pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "SIOCSNOOPLEN: %s",
 		    pcap_strerror(errno));
 		goto bad;
 	}
 	v = 1;
 	if (ioctl(fd, SIOCSNOOPING, &v) < 0) {
-		snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "SIOCSNOOPING: %s",
+		pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "SIOCSNOOPING: %s",
 		    pcap_strerror(errno));
 		goto bad;
 	}
 
 	p->bufsize = 4096;				/* XXX */
-	p->buffer = (u_char *)malloc(p->bufsize);
+	p->buffer = malloc(p->bufsize);
 	if (p->buffer == NULL) {
-		snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "malloc: %s",
+		pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "malloc: %s",
 		    pcap_strerror(errno));
 		goto bad;
 	}
@@ -399,11 +406,11 @@
 }
 
 pcap_t *
-pcap_create_interface(const char *device, char *ebuf)
+pcap_create_interface(const char *device _U_, char *ebuf)
 {
 	pcap_t *p;
 
-	p = pcap_create_common(device, ebuf, sizeof (struct pcap_snoop));
+	p = pcap_create_common(ebuf, sizeof (struct pcap_snoop));
 	if (p == NULL)
 		return (NULL);
 
@@ -411,8 +418,18 @@
 	return (p);
 }
 
+/*
+ * XXX - there's probably a particular bind error that means "that device
+ * doesn't support snoop"; if so, we should try a bind and use that.
+ */
+static int
+can_be_bound(const char *name _U_)
+{
+	return (1);
+}
+
 int
 pcap_platform_finddevs(pcap_if_t **alldevsp, char *errbuf)
 {
-	return (0);
+	return (pcap_findalldevs_interfaces(alldevsp, errbuf, can_be_bound));
 }
diff --git a/pcap-stdinc.h b/pcap-stdinc.h
index f70dcce..a1be680 100644
--- a/pcap-stdinc.h
+++ b/pcap-stdinc.h
@@ -28,6 +28,35 @@
  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  */
+
+/*
+ * Copyright (C) 1999 WIDE Project.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the project nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
 #ifndef pcap_stdinc_h
 #define pcap_stdinc_h
 
@@ -45,39 +74,53 @@
 #include <time.h>
 #include <io.h>
 
-#include "bittypes.h"
-#include "IP6_misc.h"
-
-#define caddr_t char*
+#include <ws2tcpip.h>
 
 #if defined(_MSC_VER)
-  #define snprintf  _snprintf
-  #define vsnprintf _vsnprintf
-  #define strdup    _strdup
-#endif
+  /*
+   * MSVC.
+   */
+  #if _MSC_VER >= 1800
+    /*
+     * VS 2013 or newer; we have <inttypes.h>.
+     */
+    #include <inttypes.h>
 
-#define inline __inline
+    #define u_int8_t uint8_t
+    #define u_int16_t uint16_t
+    #define u_int32_t uint32_t
+    #define u_int64_t uint64_t
+  #else
+    /*
+     * Earlier VS; we have to define this stuff ourselves.
+     */
+    #ifndef HAVE_U_INT8_T
+      typedef unsigned char u_int8_t;
+      typedef signed char int8_t;
+    #endif
 
-#ifdef __MINGW32__
+    #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>
-#else
-  #ifndef _UINTPTR_T_DEFINED
-    #ifdef  _WIN64
-      typedef unsigned __int64    uintptr_t;
-    #else
-      typedef _W64 unsigned int   uintptr_t;
-    #endif
-    #define _UINTPTR_T_DEFINED
-  #endif
-
-  #ifndef _INTPTR_T_DEFINED
-    #ifdef  _WIN64
-      typedef __int64    intptr_t;
-    #else
-      typedef _W64 int   intptr_t;
-    #endif
-    #define _INTPTR_T_DEFINED
-  #endif
-#endif /*__MINGW32__*/
+#endif
 
 #endif /* pcap_stdinc_h */
diff --git a/pcap-tc.c b/pcap-tc.c
new file mode 100644
index 0000000..768dbd7
--- /dev/null
+++ b/pcap-tc.c
@@ -0,0 +1,1284 @@
+/*
+ * Copyright (c) 2008 CACE Technologies, Davis (California)
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of CACE Technologies nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <pcap.h>
+#include <pcap-int.h>
+
+#include "pcap-tc.h"
+
+#include <malloc.h>
+#include <memory.h>
+#include <string.h>
+#include <errno.h>
+
+#ifdef _WIN32
+#include <tchar.h>
+#endif
+
+typedef TC_STATUS	(TC_CALLCONV *TcFcnQueryPortList)			(PTC_PORT *ppPorts, PULONG pLength);
+typedef TC_STATUS	(TC_CALLCONV *TcFcnFreePortList)			(TC_PORT *pPorts);
+
+typedef PCHAR		(TC_CALLCONV *TcFcnStatusGetString)			(TC_STATUS status);
+
+typedef PCHAR		(TC_CALLCONV *TcFcnPortGetName)				(TC_PORT port);
+typedef PCHAR		(TC_CALLCONV *TcFcnPortGetDescription)		(TC_PORT port);
+
+typedef TC_STATUS	(TC_CALLCONV *TcFcnInstanceOpenByName)		(PCHAR name, PTC_INSTANCE pInstance);
+typedef TC_STATUS	(TC_CALLCONV *TcFcnInstanceClose)			(TC_INSTANCE instance);
+typedef TC_STATUS	(TC_CALLCONV *TcFcnInstanceSetFeature)		(TC_INSTANCE instance, ULONG feature, ULONG value);
+typedef TC_STATUS	(TC_CALLCONV *TcFcnInstanceQueryFeature)	(TC_INSTANCE instance, ULONG feature, PULONG pValue);
+typedef TC_STATUS	(TC_CALLCONV *TcFcnInstanceReceivePackets)	(TC_INSTANCE instance, PTC_PACKETS_BUFFER pBuffer);
+typedef HANDLE		(TC_CALLCONV *TcFcnInstanceGetReceiveWaitHandle) (TC_INSTANCE instance);
+typedef TC_STATUS	(TC_CALLCONV *TcFcnInstanceTransmitPackets)	(TC_INSTANCE instance, TC_PACKETS_BUFFER pBuffer);
+typedef TC_STATUS	(TC_CALLCONV *TcFcnInstanceQueryStatistics)	(TC_INSTANCE instance, PTC_STATISTICS pStatistics);
+
+typedef TC_STATUS	(TC_CALLCONV *TcFcnPacketsBufferCreate)		(ULONG size, PTC_PACKETS_BUFFER pBuffer);
+typedef VOID		(TC_CALLCONV *TcFcnPacketsBufferDestroy)	(TC_PACKETS_BUFFER buffer);
+typedef TC_STATUS	(TC_CALLCONV *TcFcnPacketsBufferQueryNextPacket)(TC_PACKETS_BUFFER buffer, PTC_PACKET_HEADER pHeader, PVOID *ppData);
+typedef TC_STATUS	(TC_CALLCONV *TcFcnPacketsBufferCommitNextPacket)(TC_PACKETS_BUFFER buffer, PTC_PACKET_HEADER pHeader, PVOID pData);
+
+typedef VOID		(TC_CALLCONV *TcFcnStatisticsDestroy)		(TC_STATISTICS statistics);
+typedef TC_STATUS	(TC_CALLCONV *TcFcnStatisticsUpdate)		(TC_STATISTICS statistics);
+typedef TC_STATUS	(TC_CALLCONV *TcFcnStatisticsQueryValue)	(TC_STATISTICS statistics, ULONG counterId, PULONGLONG pValue);
+
+typedef enum LONG
+{
+	TC_API_UNLOADED = 0,
+	TC_API_LOADED,
+	TC_API_CANNOT_LOAD,
+	TC_API_LOADING
+}
+	TC_API_LOAD_STATUS;
+
+
+typedef struct _TC_FUNCTIONS
+{
+	TC_API_LOAD_STATUS			LoadStatus;
+#ifdef _WIN32
+	HMODULE						hTcApiDllHandle;
+#endif
+	TcFcnQueryPortList			QueryPortList;
+	TcFcnFreePortList			FreePortList;
+	TcFcnStatusGetString		StatusGetString;
+
+	TcFcnPortGetName			PortGetName;
+	TcFcnPortGetDescription		PortGetDescription;
+
+	TcFcnInstanceOpenByName		InstanceOpenByName;
+	TcFcnInstanceClose			InstanceClose;
+	TcFcnInstanceSetFeature		InstanceSetFeature;
+	TcFcnInstanceQueryFeature	InstanceQueryFeature;
+	TcFcnInstanceReceivePackets	InstanceReceivePackets;
+#ifdef _WIN32
+	TcFcnInstanceGetReceiveWaitHandle InstanceGetReceiveWaitHandle;
+#endif
+	TcFcnInstanceTransmitPackets InstanceTransmitPackets;
+	TcFcnInstanceQueryStatistics InstanceQueryStatistics;
+
+	TcFcnPacketsBufferCreate	PacketsBufferCreate;
+	TcFcnPacketsBufferDestroy	PacketsBufferDestroy;
+	TcFcnPacketsBufferQueryNextPacket	PacketsBufferQueryNextPacket;
+	TcFcnPacketsBufferCommitNextPacket  PacketsBufferCommitNextPacket;
+
+	TcFcnStatisticsDestroy		StatisticsDestroy;
+	TcFcnStatisticsUpdate		StatisticsUpdate;
+	TcFcnStatisticsQueryValue	StatisticsQueryValue;
+}
+	TC_FUNCTIONS;
+
+static pcap_if_t* TcCreatePcapIfFromPort(TC_PORT port);
+static int TcSetDatalink(pcap_t *p, int dlt);
+static int TcGetNonBlock(pcap_t *p, char *errbuf);
+static int TcSetNonBlock(pcap_t *p, int nonblock, char *errbuf);
+static void TcCleanup(pcap_t *p);
+static int TcInject(pcap_t *p, const void *buf, size_t size);
+static int TcRead(pcap_t *p, int cnt, pcap_handler callback, u_char *user);
+static int TcStats(pcap_t *p, struct pcap_stat *ps);
+static int TcSetFilter(pcap_t *p, struct bpf_program *fp);
+#ifdef _WIN32
+static struct pcap_stat *TcStatsEx(pcap_t *p, int *pcap_stat_size);
+static int TcSetBuff(pcap_t *p, int dim);
+static int TcSetMode(pcap_t *p, int mode);
+static int TcSetMinToCopy(pcap_t *p, int size);
+static HANDLE TcGetReceiveWaitHandle(pcap_t *p);
+static int TcOidGetRequest(pcap_t *p, bpf_u_int32 oid, void *data, size_t *lenp);
+static int TcOidSetRequest(pcap_t *p, bpf_u_int32 oid, const void *data, size_t *lenp);
+static u_int TcSendqueueTransmit(pcap_t *p, pcap_send_queue *queue, int sync);
+static int TcSetUserBuffer(pcap_t *p, int size);
+static int TcLiveDump(pcap_t *p, char *filename, int maxsize, int maxpacks);
+static int TcLiveDumpEnded(pcap_t *p, int sync);
+static PAirpcapHandle TcGetAirPcapHandle(pcap_t *p);
+#endif
+
+#ifdef _WIN32
+TC_FUNCTIONS g_TcFunctions =
+{
+	TC_API_UNLOADED, /* LoadStatus */
+	NULL,  /* hTcApiDllHandle */
+	NULL,  /* QueryPortList */
+	NULL,  /* FreePortList */
+	NULL,  /* StatusGetString */
+	NULL,  /* PortGetName */
+	NULL,  /* PortGetDescription */
+	NULL,  /* InstanceOpenByName */
+	NULL,  /* InstanceClose */
+	NULL,  /* InstanceSetFeature */
+	NULL,  /* InstanceQueryFeature */
+	NULL,  /* InstanceReceivePackets */
+	NULL,  /* InstanceGetReceiveWaitHandle */
+	NULL,  /* InstanceTransmitPackets */
+	NULL,  /* InstanceQueryStatistics */
+	NULL,  /* PacketsBufferCreate */
+	NULL,  /* PacketsBufferDestroy */
+	NULL,  /* PacketsBufferQueryNextPacket */
+	NULL,  /* PacketsBufferCommitNextPacket */
+	NULL,  /* StatisticsDestroy */
+	NULL,  /* StatisticsUpdate */
+	NULL  /* StatisticsQueryValue */
+};
+#else
+TC_FUNCTIONS g_TcFunctions =
+{
+	TC_API_LOADED, /* LoadStatus */
+	TcQueryPortList,
+	TcFreePortList,
+	TcStatusGetString,
+	TcPortGetName,
+	TcPortGetDescription,
+	TcInstanceOpenByName,
+	TcInstanceClose,
+	TcInstanceSetFeature,
+	TcInstanceQueryFeature,
+	TcInstanceReceivePackets,
+#ifdef _WIN32
+	TcInstanceGetReceiveWaitHandle,
+#endif
+	TcInstanceTransmitPackets,
+	TcInstanceQueryStatistics,
+	TcPacketsBufferCreate,
+	TcPacketsBufferDestroy,
+	TcPacketsBufferQueryNextPacket,
+	TcPacketsBufferCommitNextPacket,
+	TcStatisticsDestroy,
+	TcStatisticsUpdate,
+	TcStatisticsQueryValue,
+};
+#endif
+
+#define MAX_TC_PACKET_SIZE	9500
+
+#pragma pack(push, 1)
+
+#define PPH_PH_FLAG_PADDING	((UCHAR)0x01)
+#define PPH_PH_VERSION		((UCHAR)0x00)
+
+typedef struct _PPI_PACKET_HEADER
+{
+	UCHAR	PphVersion;
+	UCHAR	PphFlags;
+	USHORT	PphLength;
+	ULONG	PphDlt;
+}
+	PPI_PACKET_HEADER, *PPPI_PACKET_HEADER;
+
+typedef struct _PPI_FIELD_HEADER
+{
+	USHORT PfhType;
+	USHORT PfhLength;
+}
+	PPI_FIELD_HEADER, *PPPI_FIELD_HEADER;
+
+
+#define		PPI_FIELD_TYPE_AGGREGATION_EXTENSION	((UCHAR)0x08)
+
+typedef struct _PPI_FIELD_AGGREGATION_EXTENSION
+{
+	ULONG		InterfaceId;
+}
+	PPI_FIELD_AGGREGATION_EXTENSION, *PPPI_FIELD_AGGREGATION_EXTENSION;
+
+
+#define		PPI_FIELD_TYPE_802_3_EXTENSION			((UCHAR)0x09)
+
+#define PPI_FLD_802_3_EXT_FLAG_FCS_PRESENT			((ULONG)0x00000001)
+
+typedef struct _PPI_FIELD_802_3_EXTENSION
+{
+	ULONG		Flags;
+	ULONG		Errors;
+}
+	PPI_FIELD_802_3_EXTENSION, *PPPI_FIELD_802_3_EXTENSION;
+
+typedef struct _PPI_HEADER
+{
+	PPI_PACKET_HEADER PacketHeader;
+	PPI_FIELD_HEADER  AggregationFieldHeader;
+	PPI_FIELD_AGGREGATION_EXTENSION AggregationField;
+	PPI_FIELD_HEADER  Dot3FieldHeader;
+	PPI_FIELD_802_3_EXTENSION Dot3Field;
+}
+	PPI_HEADER, *PPPI_HEADER;
+#pragma pack(pop)
+
+#ifdef _WIN32
+//
+// This wrapper around loadlibrary appends the system folder (usually c:\windows\system32)
+// to the relative path of the DLL, so that the DLL is always loaded from an absolute path
+// (It's no longer possible to load airpcap.dll from the application folder).
+// This solves the DLL Hijacking issue discovered in August 2010
+// http://blog.metasploit.com/2010/08/exploiting-dll-hijacking-flaws.html
+//
+HMODULE LoadLibrarySafe(LPCTSTR lpFileName)
+{
+  TCHAR path[MAX_PATH];
+  TCHAR fullFileName[MAX_PATH];
+  UINT res;
+  HMODULE hModule = NULL;
+  do
+  {
+	res = GetSystemDirectory(path, MAX_PATH);
+
+	if (res == 0)
+	{
+		//
+		// some bad failure occurred;
+		//
+		break;
+	}
+
+	if (res > MAX_PATH)
+	{
+		//
+		// the buffer was not big enough
+		//
+		SetLastError(ERROR_INSUFFICIENT_BUFFER);
+		break;
+	}
+
+	if (res + 1 + _tcslen(lpFileName) + 1 < MAX_PATH)
+	{
+		memcpy(fullFileName, path, res * sizeof(TCHAR));
+		fullFileName[res] = _T('\\');
+		memcpy(&fullFileName[res + 1], lpFileName, (_tcslen(lpFileName) + 1) * sizeof(TCHAR));
+
+		hModule = LoadLibrary(fullFileName);
+	}
+	else
+	{
+		SetLastError(ERROR_INSUFFICIENT_BUFFER);
+	}
+
+  }while(FALSE);
+
+  return hModule;
+}
+
+/*
+ * NOTE: this function should be called by the pcap functions that can theoretically
+ *       deal with the Tc library for the first time, namely listing the adapters and
+ *       opening one. All the other ones (close, read, write, set parameters) work
+ *       on an open instance of TC, so we do not care to call this function
+ */
+TC_API_LOAD_STATUS LoadTcFunctions(void)
+{
+	TC_API_LOAD_STATUS currentStatus;
+
+	do
+	{
+		currentStatus = InterlockedCompareExchange((LONG*)&g_TcFunctions.LoadStatus, TC_API_LOADING, TC_API_UNLOADED);
+
+		while(currentStatus == TC_API_LOADING)
+		{
+			currentStatus = InterlockedCompareExchange((LONG*)&g_TcFunctions.LoadStatus, TC_API_LOADING, TC_API_LOADING);
+			Sleep(10);
+		}
+
+		/*
+		 * at this point we are either in the LOADED state, unloaded state (i.e. we are the ones loading everything)
+		 * or in cannot load
+		 */
+		if(currentStatus  == TC_API_LOADED)
+		{
+			return TC_API_LOADED;
+		}
+
+		if (currentStatus == TC_API_CANNOT_LOAD)
+		{
+			return TC_API_CANNOT_LOAD;
+		}
+
+		currentStatus = TC_API_CANNOT_LOAD;
+
+		g_TcFunctions.hTcApiDllHandle = LoadLibrarySafe("TcApi.dll");
+		if (g_TcFunctions.hTcApiDllHandle == NULL)	break;
+
+		g_TcFunctions.QueryPortList					= (TcFcnQueryPortList)			GetProcAddress(g_TcFunctions.hTcApiDllHandle, "TcQueryPortList");
+		g_TcFunctions.FreePortList					= (TcFcnFreePortList)			GetProcAddress(g_TcFunctions.hTcApiDllHandle, "TcFreePortList");
+
+		g_TcFunctions.StatusGetString				= (TcFcnStatusGetString)		GetProcAddress(g_TcFunctions.hTcApiDllHandle, "TcStatusGetString");
+
+		g_TcFunctions.PortGetName					= (TcFcnPortGetName)			GetProcAddress(g_TcFunctions.hTcApiDllHandle, "TcPortGetName");
+		g_TcFunctions.PortGetDescription			= (TcFcnPortGetDescription)		GetProcAddress(g_TcFunctions.hTcApiDllHandle, "TcPortGetDescription");
+
+		g_TcFunctions.InstanceOpenByName			= (TcFcnInstanceOpenByName)		GetProcAddress(g_TcFunctions.hTcApiDllHandle, "TcInstanceOpenByName");
+		g_TcFunctions.InstanceClose					= (TcFcnInstanceClose)			GetProcAddress(g_TcFunctions.hTcApiDllHandle, "TcInstanceClose");
+		g_TcFunctions.InstanceSetFeature			= (TcFcnInstanceSetFeature)		GetProcAddress(g_TcFunctions.hTcApiDllHandle, "TcInstanceSetFeature");
+		g_TcFunctions.InstanceQueryFeature			= (TcFcnInstanceQueryFeature)	GetProcAddress(g_TcFunctions.hTcApiDllHandle, "TcInstanceQueryFeature");
+		g_TcFunctions.InstanceReceivePackets		= (TcFcnInstanceReceivePackets)	GetProcAddress(g_TcFunctions.hTcApiDllHandle, "TcInstanceReceivePackets");
+		g_TcFunctions.InstanceGetReceiveWaitHandle	= (TcFcnInstanceGetReceiveWaitHandle)GetProcAddress(g_TcFunctions.hTcApiDllHandle, "TcInstanceGetReceiveWaitHandle");
+		g_TcFunctions.InstanceTransmitPackets		= (TcFcnInstanceTransmitPackets)GetProcAddress(g_TcFunctions.hTcApiDllHandle, "TcInstanceTransmitPackets");
+		g_TcFunctions.InstanceQueryStatistics		= (TcFcnInstanceQueryStatistics)GetProcAddress(g_TcFunctions.hTcApiDllHandle, "TcInstanceQueryStatistics");
+
+		g_TcFunctions.PacketsBufferCreate			= (TcFcnPacketsBufferCreate)	GetProcAddress(g_TcFunctions.hTcApiDllHandle, "TcPacketsBufferCreate");
+		g_TcFunctions.PacketsBufferDestroy			= (TcFcnPacketsBufferDestroy)	GetProcAddress(g_TcFunctions.hTcApiDllHandle, "TcPacketsBufferDestroy");
+		g_TcFunctions.PacketsBufferQueryNextPacket	= (TcFcnPacketsBufferQueryNextPacket)GetProcAddress(g_TcFunctions.hTcApiDllHandle, "TcPacketsBufferQueryNextPacket");
+		g_TcFunctions.PacketsBufferCommitNextPacket	= (TcFcnPacketsBufferCommitNextPacket)GetProcAddress(g_TcFunctions.hTcApiDllHandle, "TcPacketsBufferCommitNextPacket");
+
+		g_TcFunctions.StatisticsDestroy				= (TcFcnStatisticsDestroy)		GetProcAddress(g_TcFunctions.hTcApiDllHandle, "TcStatisticsDestroy");
+		g_TcFunctions.StatisticsUpdate				= (TcFcnStatisticsUpdate)		GetProcAddress(g_TcFunctions.hTcApiDllHandle, "TcStatisticsUpdate");
+		g_TcFunctions.StatisticsQueryValue			= (TcFcnStatisticsQueryValue)	GetProcAddress(g_TcFunctions.hTcApiDllHandle, "TcStatisticsQueryValue");
+
+		if (   g_TcFunctions.QueryPortList == NULL
+			|| g_TcFunctions.FreePortList == NULL
+			|| g_TcFunctions.StatusGetString == NULL
+			|| g_TcFunctions.PortGetName == NULL
+			|| g_TcFunctions.PortGetDescription == NULL
+			|| g_TcFunctions.InstanceOpenByName == NULL
+			|| g_TcFunctions.InstanceClose == NULL
+			|| g_TcFunctions.InstanceSetFeature	 == NULL
+			|| g_TcFunctions.InstanceQueryFeature == NULL
+			|| g_TcFunctions.InstanceReceivePackets == NULL
+			|| g_TcFunctions.InstanceGetReceiveWaitHandle == NULL
+			|| g_TcFunctions.InstanceTransmitPackets == NULL
+			|| g_TcFunctions.InstanceQueryStatistics == NULL
+			|| g_TcFunctions.PacketsBufferCreate == NULL
+			|| g_TcFunctions.PacketsBufferDestroy == NULL
+			|| g_TcFunctions.PacketsBufferQueryNextPacket == NULL
+			|| g_TcFunctions.PacketsBufferCommitNextPacket == NULL
+			|| g_TcFunctions.StatisticsDestroy == NULL
+			|| g_TcFunctions.StatisticsUpdate == NULL
+			|| g_TcFunctions.StatisticsQueryValue == NULL
+		)
+		{
+			break;
+		}
+
+		/*
+		 * everything got loaded, yay!!
+		 */
+		currentStatus = TC_API_LOADED;
+	}while(FALSE);
+
+	if (currentStatus != TC_API_LOADED)
+	{
+		if (g_TcFunctions.hTcApiDllHandle != NULL)
+		{
+			FreeLibrary(g_TcFunctions.hTcApiDllHandle);
+			g_TcFunctions.hTcApiDllHandle = NULL;
+		}
+	}
+
+	InterlockedExchange((LONG*)&g_TcFunctions.LoadStatus, currentStatus);
+
+	return currentStatus;
+}
+#else
+// static linking
+TC_API_LOAD_STATUS LoadTcFunctions(void)
+{
+	return TC_API_LOADED;
+}
+#endif
+
+/*
+ * Private data for capturing on TurboCap devices.
+ */
+struct pcap_tc {
+	TC_INSTANCE TcInstance;
+	TC_PACKETS_BUFFER TcPacketsBuffer;
+	ULONG TcAcceptedCount;
+	u_char *PpiPacket;
+};
+
+int
+TcFindAllDevs(pcap_if_t **alldevsp, char *errbuf)
+{
+	TC_API_LOAD_STATUS loadStatus;
+	ULONG numPorts;
+	PTC_PORT pPorts = NULL;
+	TC_STATUS status;
+	int result = 0;
+	pcap_if_t *dev, *cursor;
+	ULONG i;
+
+	do
+	{
+		loadStatus = LoadTcFunctions();
+
+		if (loadStatus != TC_API_LOADED)
+		{
+			result = 0;
+			break;
+		}
+
+		/*
+		 * enumerate the ports, and add them to the list
+		 */
+		status = g_TcFunctions.QueryPortList(&pPorts, &numPorts);
+
+		if (status != TC_SUCCESS)
+		{
+			result = 0;
+			break;
+		}
+
+		for (i = 0; i < numPorts; i++)
+		{
+			/*
+			 * transform the port into an entry in the list
+			 */
+			dev = TcCreatePcapIfFromPort(pPorts[i]);
+
+			if (dev != NULL)
+			{
+				/*
+				 * append it at the end
+				 */
+				if (*alldevsp == NULL)
+				{
+					*alldevsp = dev;
+				}
+				else
+				{
+					for(cursor = *alldevsp; cursor->next != NULL; cursor = cursor->next);
+					cursor->next = dev;
+				}
+			}
+		}
+
+		if (numPorts > 0)
+		{
+			/*
+			 * ignore the result here
+			 */
+			status = g_TcFunctions.FreePortList(pPorts);
+		}
+
+	}while(FALSE);
+
+	return result;
+}
+
+static pcap_if_t* TcCreatePcapIfFromPort(TC_PORT port)
+{
+	CHAR *name;
+	CHAR *description;
+	pcap_if_t *newIf = NULL;
+
+	newIf = (pcap_if_t*)malloc(sizeof(*newIf));
+	if (newIf == NULL)
+	{
+		return NULL;
+	}
+
+	memset(newIf, 0, sizeof(*newIf));
+
+	name = g_TcFunctions.PortGetName(port);
+	description = g_TcFunctions.PortGetDescription(port);
+
+	newIf->name = (char*)malloc(strlen(name) + 1);
+	if (newIf->name == NULL)
+	{
+		free(newIf);
+		return NULL;
+	}
+
+	newIf->description = (char*)malloc(strlen(description) + 1);
+	if (newIf->description == NULL)
+	{
+		free(newIf->name);
+		free(newIf);
+		return NULL;
+	}
+
+	strcpy(newIf->name, name);
+	strcpy(newIf->description, description);
+
+	newIf->addresses = NULL;
+	newIf->next = NULL;
+	newIf->flags = 0;
+
+	return newIf;
+
+}
+
+static int
+TcActivate(pcap_t *p)
+{
+	struct pcap_tc *pt = p->priv;
+	TC_STATUS status;
+	ULONG timeout;
+	PPPI_HEADER pPpiHeader;
+
+	if (p->opt.rfmon)
+	{
+		/*
+		 * No monitor mode on Tc cards; they're Ethernet
+		 * capture adapters.
+		 */
+		return PCAP_ERROR_RFMON_NOTSUP;
+	}
+
+	pt->PpiPacket = malloc(sizeof(PPI_HEADER) + MAX_TC_PACKET_SIZE);
+
+	if (pt->PpiPacket == NULL)
+	{
+		pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "Error allocating memory");
+		return PCAP_ERROR;
+	}
+
+	/*
+	 * Initialize the PPI fixed fields
+	 */
+	pPpiHeader = (PPPI_HEADER)pt->PpiPacket;
+	pPpiHeader->PacketHeader.PphDlt = DLT_EN10MB;
+	pPpiHeader->PacketHeader.PphLength = sizeof(PPI_HEADER);
+	pPpiHeader->PacketHeader.PphFlags = 0;
+	pPpiHeader->PacketHeader.PphVersion = 0;
+
+	pPpiHeader->AggregationFieldHeader.PfhLength = sizeof(PPI_FIELD_AGGREGATION_EXTENSION);
+	pPpiHeader->AggregationFieldHeader.PfhType = PPI_FIELD_TYPE_AGGREGATION_EXTENSION;
+
+	pPpiHeader->Dot3FieldHeader.PfhLength = sizeof(PPI_FIELD_802_3_EXTENSION);
+	pPpiHeader->Dot3FieldHeader.PfhType = PPI_FIELD_TYPE_802_3_EXTENSION;
+
+	status = g_TcFunctions.InstanceOpenByName(p->opt.device, &pt->TcInstance);
+
+	if (status != TC_SUCCESS)
+	{
+		/* Adapter detected but we are not able to open it. Return failure. */
+		pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "Error opening TurboCap adapter: %s", g_TcFunctions.StatusGetString(status));
+		return PCAP_ERROR;
+	}
+
+	p->linktype = DLT_EN10MB;
+	p->dlt_list = (u_int *) malloc(sizeof(u_int) * 2);
+	/*
+	 * If that fails, just leave the list empty.
+	 */
+	if (p->dlt_list != NULL) {
+		p->dlt_list[0] = DLT_EN10MB;
+		p->dlt_list[1] = DLT_PPI;
+		p->dlt_count = 2;
+	}
+
+	/*
+	 * ignore promiscuous mode
+	 * p->opt.promisc
+	 */
+
+
+	/*
+	 * ignore all the buffer sizes
+	 */
+
+	/*
+	 * enable reception
+	 */
+	status = g_TcFunctions.InstanceSetFeature(pt->TcInstance, TC_INST_FT_RX_STATUS, 1);
+
+	if (status != TC_SUCCESS)
+	{
+		pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE,"Error enabling reception on a TurboCap instance: %s", g_TcFunctions.StatusGetString(status));
+		goto bad;
+	}
+
+	/*
+	 * enable transmission
+	 */
+	status = g_TcFunctions.InstanceSetFeature(pt->TcInstance, TC_INST_FT_TX_STATUS, 1);
+	/*
+	 * Ignore the error here.
+	 */
+
+	p->inject_op = TcInject;
+	/*
+	 * if the timeout is -1, it means immediate return, no timeout
+	 * if the timeout is 0, it means INFINITE
+	 */
+
+	if (p->opt.timeout == 0)
+	{
+		timeout = 0xFFFFFFFF;
+	}
+	else
+	if (p->opt.timeout < 0)
+	{
+		/*
+		 *  we insert a minimal timeout here
+		 */
+		timeout = 10;
+	}
+	else
+	{
+		timeout = p->opt.timeout;
+	}
+
+	status = g_TcFunctions.InstanceSetFeature(pt->TcInstance, TC_INST_FT_READ_TIMEOUT, timeout);
+
+	if (status != TC_SUCCESS)
+	{
+		pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE,"Error setting the read timeout a TurboCap instance: %s", g_TcFunctions.StatusGetString(status));
+		goto bad;
+	}
+
+	p->read_op = TcRead;
+	p->setfilter_op = TcSetFilter;
+	p->setdirection_op = NULL;	/* Not implemented. */
+	p->set_datalink_op = TcSetDatalink;
+	p->getnonblock_op = TcGetNonBlock;
+	p->setnonblock_op = TcSetNonBlock;
+	p->stats_op = TcStats;
+#ifdef _WIN32
+	p->stats_ex_op = TcStatsEx;
+	p->setbuff_op = TcSetBuff;
+	p->setmode_op = TcSetMode;
+	p->setmintocopy_op = TcSetMinToCopy;
+	p->getevent_op = TcGetReceiveWaitHandle;
+	p->oid_get_request_op = TcOidGetRequest;
+	p->oid_set_request_op = TcOidSetRequest;
+	p->sendqueue_transmit_op = TcSendqueueTransmit;
+	p->setuserbuffer_op = TcSetUserBuffer;
+	p->live_dump_op = TcLiveDump;
+	p->live_dump_ended_op = TcLiveDumpEnded;
+	p->get_airpcap_handle_op = TcGetAirPcapHandle;
+#else
+	p->selectable_fd = -1;
+#endif
+
+	p->cleanup_op = TcCleanup;
+
+	return 0;
+bad:
+	TcCleanup(p);
+	return PCAP_ERROR;
+}
+
+pcap_t *
+TcCreate(const char *device, char *ebuf, int *is_ours)
+{
+	ULONG numPorts;
+	PTC_PORT pPorts = NULL;
+	TC_STATUS status;
+	int is_tc;
+	ULONG i;
+	pcap_t *p;
+
+	if (LoadTcFunctions() != TC_API_LOADED)
+	{
+		/*
+		 * XXX - report this as an error rather than as
+		 * "not a TurboCap device"?
+		 */
+		*is_ours = 0;
+		return NULL;
+	}
+
+	/*
+	 * enumerate the ports, and add them to the list
+	 */
+	status = g_TcFunctions.QueryPortList(&pPorts, &numPorts);
+
+	if (status != TC_SUCCESS)
+	{
+		/*
+		 * XXX - report this as an error rather than as
+		 * "not a TurboCap device"?
+		 */
+		*is_ours = 0;
+		return NULL;
+	}
+
+	is_tc = FALSE;
+	for (i = 0; i < numPorts; i++)
+	{
+		if (strcmp(g_TcFunctions.PortGetName(pPorts[i]), device) == 0)
+		{
+			is_tc = TRUE;
+			break;
+		}
+	}
+
+	if (numPorts > 0)
+	{
+		/*
+		 * ignore the result here
+		 */
+		(void)g_TcFunctions.FreePortList(pPorts);
+	}
+
+	if (!is_tc)
+	{
+		*is_ours = 0;
+		return NULL;
+	}
+
+	/* OK, it's probably ours. */
+	*is_ours = 1;
+
+	p = pcap_create_common(ebuf, sizeof (struct pcap_tc));
+	if (p == NULL)
+		return NULL;
+
+	p->activate_op = TcActivate;
+	return p;
+}
+
+static int TcSetDatalink(pcap_t *p, int dlt)
+{
+	/*
+	 * always return 0, as the check is done by pcap_set_datalink
+	 */
+	return 0;
+}
+
+static int TcGetNonBlock(pcap_t *p, char *errbuf)
+{
+	pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
+		    "Getting the non blocking status is not available for TurboCap ports");
+	pcap_snprintf(errbuf, PCAP_ERRBUF_SIZE,
+		    "Getting the non blocking status is not available for TurboCap ports");
+		return -1;
+
+}
+static int TcSetNonBlock(pcap_t *p, int nonblock, char *errbuf)
+{
+	pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
+		    "Setting the non blocking status is not available for TurboCap ports");
+	pcap_snprintf(errbuf, PCAP_ERRBUF_SIZE,
+		    "Setting the non blocking status is not available for TurboCap ports");
+		return -1;
+}
+
+
+static void TcCleanup(pcap_t *p)
+{
+	struct pcap_tc *pt = p->priv;
+
+	if (pt->TcPacketsBuffer != NULL)
+	{
+		g_TcFunctions.PacketsBufferDestroy(pt->TcPacketsBuffer);
+		pt->TcPacketsBuffer = NULL;
+	}
+	if (pt->TcInstance != NULL)
+	{
+		/*
+		 * here we do not check for the error values
+		 */
+		g_TcFunctions.InstanceClose(pt->TcInstance);
+		pt->TcInstance = NULL;
+	}
+
+	if (pt->PpiPacket != NULL)
+	{
+		free(pt->PpiPacket);
+		pt->PpiPacket = NULL;
+	}
+
+	pcap_cleanup_live_common(p);
+}
+
+/* Send a packet to the network */
+static int TcInject(pcap_t *p, const void *buf, size_t size)
+{
+	struct pcap_tc *pt = p->priv;
+	TC_STATUS status;
+	TC_PACKETS_BUFFER buffer;
+	TC_PACKET_HEADER header;
+
+	if (size >= 0xFFFF)
+	{
+		pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "send error: the TurboCap API does not support packets larger than 64k");
+		return -1;
+	}
+
+	status = g_TcFunctions.PacketsBufferCreate(sizeof(TC_PACKET_HEADER) + TC_ALIGN_USHORT_TO_64BIT((USHORT)size), &buffer);
+
+	if (status != TC_SUCCESS)
+	{
+		pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "send error: TcPacketsBufferCreate failure: %s (%08x)", g_TcFunctions.StatusGetString(status), status);
+		return -1;
+	}
+
+	/*
+	 * we assume that the packet is without the checksum, as common with WinPcap
+	 */
+	memset(&header, 0, sizeof(header));
+
+	header.Length = (USHORT)size;
+	header.CapturedLength = header.Length;
+
+	status = g_TcFunctions.PacketsBufferCommitNextPacket(buffer, &header, (PVOID)buf);
+
+	if (status == TC_SUCCESS)
+	{
+		status = g_TcFunctions.InstanceTransmitPackets(pt->TcInstance, buffer);
+
+		if (status != TC_SUCCESS)
+		{
+			pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "send error: TcInstanceTransmitPackets failure: %s (%08x)", g_TcFunctions.StatusGetString(status), status);
+		}
+	}
+	else
+	{
+		pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "send error: TcPacketsBufferCommitNextPacket failure: %s (%08x)", g_TcFunctions.StatusGetString(status), status);
+	}
+
+	g_TcFunctions.PacketsBufferDestroy(buffer);
+
+	if (status != TC_SUCCESS)
+	{
+		return -1;
+	}
+	else
+	{
+		return 0;
+	}
+}
+
+static int TcRead(pcap_t *p, int cnt, pcap_handler callback, u_char *user)
+{
+	struct pcap_tc *pt = p->priv;
+	TC_STATUS status;
+	int n = 0;
+
+	/*
+	 * Has "pcap_breakloop()" been called?
+	 */
+	if (p->break_loop)
+	{
+		/*
+		 * Yes - clear the flag that indicates that it
+		 * has, and return -2 to indicate that we were
+		 * told to break out of the loop.
+		 */
+		p->break_loop = 0;
+		return -2;
+	}
+
+	if (pt->TcPacketsBuffer == NULL)
+	{
+		status = g_TcFunctions.InstanceReceivePackets(pt->TcInstance, &pt->TcPacketsBuffer);
+		if (status != TC_SUCCESS)
+		{
+			pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "read error, TcInstanceReceivePackets failure: %s (%08x)", g_TcFunctions.StatusGetString(status), status);
+			return -1;
+		}
+	}
+
+	while (TRUE)
+	{
+		struct pcap_pkthdr hdr;
+		TC_PACKET_HEADER tcHeader;
+		PVOID data;
+		ULONG filterResult;
+
+		/*
+		 * Has "pcap_breakloop()" been called?
+		 * If so, return immediately - if we haven't read any
+		 * packets, clear the flag and return -2 to indicate
+		 * that we were told to break out of the loop, otherwise
+		 * leave the flag set, so that the *next* call will break
+		 * out of the loop without having read any packets, and
+		 * return the number of packets we've processed so far.
+		 */
+		if (p->break_loop)
+		{
+			if (n == 0)
+			{
+				p->break_loop = 0;
+				return -2;
+			}
+			else
+			{
+				return n;
+			}
+		}
+
+		if (pt->TcPacketsBuffer == NULL)
+		{
+			break;
+		}
+
+		status = g_TcFunctions.PacketsBufferQueryNextPacket(pt->TcPacketsBuffer, &tcHeader, &data);
+
+		if (status == TC_ERROR_END_OF_BUFFER)
+		{
+			g_TcFunctions.PacketsBufferDestroy(pt->TcPacketsBuffer);
+			pt->TcPacketsBuffer = NULL;
+			break;
+		}
+
+		if (status != TC_SUCCESS)
+		{
+			pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "read error, TcPacketsBufferQueryNextPacket failure: %s (%08x)", g_TcFunctions.StatusGetString(status), status);
+			return -1;
+		}
+
+		/* No underlaying filtering system. We need to filter on our own */
+		if (p->fcode.bf_insns)
+		{
+			filterResult = bpf_filter(p->fcode.bf_insns, data, tcHeader.Length, tcHeader.CapturedLength);
+
+			if (filterResult == 0)
+			{
+				continue;
+			}
+
+			if (filterResult > tcHeader.CapturedLength)
+			{
+				filterResult = tcHeader.CapturedLength;
+			}
+		}
+		else
+		{
+			filterResult = tcHeader.CapturedLength;
+		}
+
+		pt->TcAcceptedCount ++;
+
+		hdr.ts.tv_sec = (bpf_u_int32)(tcHeader.Timestamp / (ULONGLONG)(1000  * 1000 * 1000));
+		hdr.ts.tv_usec = (bpf_u_int32)((tcHeader.Timestamp % (ULONGLONG)(1000  * 1000 * 1000)) / 1000);
+
+		if (p->linktype == DLT_EN10MB)
+		{
+			hdr.caplen = filterResult;
+			hdr.len = tcHeader.Length;
+			(*callback)(user, &hdr, data);
+		}
+		else
+		{
+			PPPI_HEADER pPpiHeader = (PPPI_HEADER)pt->PpiPacket;
+			PVOID data2 = pPpiHeader + 1;
+
+			pPpiHeader->AggregationField.InterfaceId = TC_PH_FLAGS_RX_PORT_ID(tcHeader.Flags);
+			pPpiHeader->Dot3Field.Errors = tcHeader.Errors;
+			if (tcHeader.Flags & TC_PH_FLAGS_CHECKSUM)
+			{
+				pPpiHeader->Dot3Field.Flags = PPI_FLD_802_3_EXT_FLAG_FCS_PRESENT;
+			}
+			else
+			{
+				pPpiHeader->Dot3Field.Flags = 0;
+			}
+
+			if (filterResult <= MAX_TC_PACKET_SIZE)
+			{
+				memcpy(data2, data, filterResult);
+				hdr.caplen = sizeof(PPI_HEADER) + filterResult;
+				hdr.len = sizeof(PPI_HEADER) + tcHeader.Length;
+			}
+			else
+			{
+				memcpy(data2, data, MAX_TC_PACKET_SIZE);
+				hdr.caplen = sizeof(PPI_HEADER) + MAX_TC_PACKET_SIZE;
+				hdr.len = sizeof(PPI_HEADER) + tcHeader.Length;
+			}
+
+			(*callback)(user, &hdr, pt->PpiPacket);
+
+		}
+
+		if (++n >= cnt && cnt > 0)
+		{
+			return n;
+		}
+	}
+
+	return n;
+}
+
+static int
+TcStats(pcap_t *p, struct pcap_stat *ps)
+{
+	struct pcap_tc *pt = p->priv;
+	TC_STATISTICS statistics;
+	TC_STATUS status;
+	ULONGLONG counter;
+	struct pcap_stat s;
+
+	status = g_TcFunctions.InstanceQueryStatistics(pt->TcInstance, &statistics);
+
+	if (status != TC_SUCCESS)
+	{
+		pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "TurboCap error in TcInstanceQueryStatistics: %s (%08x)", g_TcFunctions.StatusGetString(status), status);
+		return -1;
+	}
+
+	memset(&s, 0, sizeof(s));
+
+	status = g_TcFunctions.StatisticsQueryValue(statistics, TC_COUNTER_INSTANCE_TOTAL_RX_PACKETS, &counter);
+	if (status != TC_SUCCESS)
+	{
+		pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "TurboCap error in TcStatisticsQueryValue: %s (%08x)", g_TcFunctions.StatusGetString(status), status);
+		return -1;
+	}
+	if (counter <= (ULONGLONG)0xFFFFFFFF)
+	{
+		s.ps_recv = (ULONG)counter;
+	}
+	else
+	{
+		s.ps_recv = 0xFFFFFFFF;
+	}
+
+	status = g_TcFunctions.StatisticsQueryValue(statistics, TC_COUNTER_INSTANCE_RX_DROPPED_PACKETS, &counter);
+	if (status != TC_SUCCESS)
+	{
+		pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "TurboCap error in TcStatisticsQueryValue: %s (%08x)", g_TcFunctions.StatusGetString(status), status);
+		return -1;
+	}
+	if (counter <= (ULONGLONG)0xFFFFFFFF)
+	{
+		s.ps_ifdrop = (ULONG)counter;
+		s.ps_drop = (ULONG)counter;
+	}
+	else
+	{
+		s.ps_ifdrop = 0xFFFFFFFF;
+		s.ps_drop = 0xFFFFFFFF;
+	}
+
+#if defined(_WIN32) && defined(HAVE_REMOTE)
+	s.ps_capt = pt->TcAcceptedCount;
+#endif
+	*ps = s;
+
+	return 0;
+}
+
+
+/*
+ * We filter at user level, since the kernel driver does't process the packets
+ */
+static int
+TcSetFilter(pcap_t *p, struct bpf_program *fp)
+{
+	if(!fp)
+	{
+		strncpy(p->errbuf, "setfilter: No filter specified", sizeof(p->errbuf));
+		return -1;
+	}
+
+	/* Install a user level filter */
+	if (install_bpf_program(p, fp) < 0)
+	{
+		pcap_snprintf(p->errbuf, sizeof(p->errbuf),
+			"setfilter, unable to install the filter: %s", pcap_strerror(errno));
+		return -1;
+	}
+
+	return 0;
+}
+
+#ifdef _WIN32
+static struct pcap_stat *
+TcStatsEx(pcap_t *p, int *pcap_stat_size)
+{
+	struct pcap_tc *pt = p->priv;
+	TC_STATISTICS statistics;
+	TC_STATUS status;
+	ULONGLONG counter;
+
+	*pcap_stat_size = sizeof (p->stat);
+
+	status = g_TcFunctions.InstanceQueryStatistics(pt->TcInstance, &statistics);
+
+	if (status != TC_SUCCESS)
+	{
+		pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "TurboCap error in TcInstanceQueryStatistics: %s (%08x)", g_TcFunctions.StatusGetString(status), status);
+		return NULL;
+	}
+
+	memset(&p->stat, 0, sizeof(p->stat));
+
+	status = g_TcFunctions.StatisticsQueryValue(statistics, TC_COUNTER_INSTANCE_TOTAL_RX_PACKETS, &counter);
+	if (status != TC_SUCCESS)
+	{
+		pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "TurboCap error in TcStatisticsQueryValue: %s (%08x)", g_TcFunctions.StatusGetString(status), status);
+		return NULL;
+	}
+	if (counter <= (ULONGLONG)0xFFFFFFFF)
+	{
+		p->stat.ps_recv = (ULONG)counter;
+	}
+	else
+	{
+		p->stat.ps_recv = 0xFFFFFFFF;
+	}
+
+	status = g_TcFunctions.StatisticsQueryValue(statistics, TC_COUNTER_INSTANCE_RX_DROPPED_PACKETS, &counter);
+	if (status != TC_SUCCESS)
+	{
+		pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "TurboCap error in TcStatisticsQueryValue: %s (%08x)", g_TcFunctions.StatusGetString(status), status);
+		return NULL;
+	}
+	if (counter <= (ULONGLONG)0xFFFFFFFF)
+	{
+		p->stat.ps_ifdrop = (ULONG)counter;
+		p->stat.ps_drop = (ULONG)counter;
+	}
+	else
+	{
+		p->stat.ps_ifdrop = 0xFFFFFFFF;
+		p->stat.ps_drop = 0xFFFFFFFF;
+	}
+
+#ifdef HAVE_REMOTE
+	p->stat.ps_capt = pt->TcAcceptedCount;
+#endif
+
+	return &p->stat;
+}
+
+/* Set the dimension of the kernel-level capture buffer */
+static int
+TcSetBuff(pcap_t *p, int dim)
+{
+	/*
+	 * XXX turbocap has an internal way of managing buffers.
+	 * And at the moment it's not configurable, so we just
+	 * silently ignore the request to set the buffer.
+	 */
+	return 0;
+}
+
+static int
+TcSetMode(pcap_t *p, int mode)
+{
+	if (mode != MODE_CAPT)
+	{
+		pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "Mode %u not supported by TurboCap devices. TurboCap only supports capture.", mode);
+		return -1;
+	}
+
+	return 0;
+}
+
+static int
+TcSetMinToCopy(pcap_t *p, int size)
+{
+	struct pcap_tc *pt = p->priv;
+	TC_STATUS status;
+
+	if (size < 0)
+	{
+		pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "Mintocopy cannot be less than 0.");
+		return -1;
+	}
+
+	status = g_TcFunctions.InstanceSetFeature(pt->TcInstance, TC_INST_FT_MINTOCOPY, (ULONG)size);
+
+	if (status != TC_SUCCESS)
+	{
+		pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "TurboCap error setting the mintocopy: %s (%08x)", g_TcFunctions.StatusGetString(status), status);
+	}
+
+	return 0;
+}
+
+static HANDLE
+TcGetReceiveWaitHandle(pcap_t *p)
+{
+	struct pcap_tc *pt = p->priv;
+
+	return g_TcFunctions.InstanceGetReceiveWaitHandle(pt->TcInstance);
+}
+
+static int
+TcOidGetRequest(pcap_t *p, bpf_u_int32 oid _U_, void *data _U_, size_t *lenp _U_)
+{
+	pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
+	    "An OID get request cannot be performed on a TurboCap device");
+	return PCAP_ERROR;
+}
+
+static int
+TcOidSetRequest(pcap_t *p, bpf_u_int32 oid _U_, const void *data _U_,
+    size_t *lenp _U_)
+{
+	pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
+	    "An OID set request cannot be performed on a TurboCap device");
+	return PCAP_ERROR;
+}
+
+static u_int
+TcSendqueueTransmit(pcap_t *p, pcap_send_queue *queue _U_, int sync _U_)
+{
+	pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
+	    "Packets cannot be bulk transmitted on a TurboCap device");
+	return 0;
+}
+
+static int
+TcSetUserBuffer(pcap_t *p, int size _U_)
+{
+	pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
+	    "The user buffer cannot be set on a TurboCap device");
+	return -1;
+}
+
+static int
+TcLiveDump(pcap_t *p, char *filename _U_, int maxsize _U_, int maxpacks _U_)
+{
+	pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
+	    "Live packet dumping cannot be performed on a TurboCap device");
+	return -1;
+}
+
+static int
+TcLiveDumpEnded(pcap_t *p, int sync _U_)
+{
+	pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
+	    "Live packet dumping cannot be performed on a TurboCap device");
+	return -1;
+}
+
+static PAirpcapHandle
+TcGetAirPcapHandle(pcap_t *p _U_)
+{
+	return NULL;
+}
+#endif
diff --git a/pcap-canusb-linux.h b/pcap-tc.h
similarity index 68%
rename from pcap-canusb-linux.h
rename to pcap-tc.h
index c8f3be1..59ddec2 100644
--- a/pcap-canusb-linux.h
+++ b/pcap-tc.h
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2009 Felix Obenhuber
+ * Copyright (c) 2008 CACE Technologies, Davis (California)
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
@@ -11,9 +11,9 @@
  * 2. Redistributions in binary form must reproduce the above copyright
  * notice, this list of conditions and the following disclaimer in the
  * documentation and/or other materials provided with the distribution.
- * 3. The name of the author may not be used to endorse or promote
- * products derived from this software without specific prior written
- * permission.
+ * 3. Neither the name of CACE Technologies nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
  *
  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
@@ -29,9 +29,26 @@
  *
  */
 
-/*
- * Prototypes for SocketCAN related functions
- */
-pcap_t* canusb_create(const char *device, char *ebuf, int *is_ours);
-int canusb_findalldevs(pcap_if_t **pdevlist, char* errbuf);
+#ifndef __PCAP_TC_H__
+#define __PCAP_TC_H__
 
+/*
+ * needed because gcc headers do not have C_ASSERT
+ */
+#ifndef C_ASSERT
+#define C_ASSERT(a)
+#endif
+
+#include <TcApi.h>
+
+/*
+ * functions used effectively by the pcap library
+ */
+
+pcap_t *
+TcCreate(const char *device, char *ebuf, int *is_ours);
+
+int
+TcFindAllDevs(pcap_if_t **alldevsp, char *errbuf);
+
+#endif
diff --git a/pcap-tstamp.manmisc b/pcap-tstamp.manmisc
new file mode 100644
index 0000000..7d078fb
--- /dev/null
+++ b/pcap-tstamp.manmisc
@@ -0,0 +1,175 @@
+.\"
+.\" Copyright (c) 1987, 1988, 1989, 1990, 1991, 1992, 1994, 1995, 1996, 1997
+.\"	The Regents of the University of California.  All rights reserved.
+.\" All rights reserved.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that: (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-TSTAMP 7 "8 March 2015"
+.SH NAME
+pcap-tstamp \- packet time stamps in libpcap
+.SH DESCRIPTION
+When capturing traffic, each packet is given a time stamp representing,
+for incoming packets, the arrival time of the packet and, for outgoing
+packets, the transmission time of the packet.  This time is an
+approximation of the arrival or transmission time.  If it is supplied by
+the operating system running on the host on which the capture is being
+done, there are several reasons why it might not precisely represent the
+arrival or transmission time:
+.IP
+if the time stamp is applied to the packet when the networking stack
+receives the packet, the networking stack might not see the packet until
+an interrupt is delivered for the packet or a timer event causes the
+networking device driver to poll for packets, and the time stamp might
+not be applied until the packet has had some processing done by other
+code in the networking stack, so there might be a significant delay
+between the time when the last bit of the packet is received by the
+capture device and when the networking stack time-stamps the packet;
+.IP
+the timer used to generate the time stamps might have low resolution,
+for example, it might be a timer updated once per host operating system
+timer tick, with the host operating system timer ticking once every few
+milliseconds;
+.IP
+a high-resolution timer might use a counter that runs at a rate
+dependent on the processor clock speed, and that clock speed might be
+adjusted upwards or downwards over time and the timer might not be able
+to compensate for all those adjustments;
+.IP
+the host operating system's clock might be adjusted over time to match a
+time standard to which the host is being synchronized, which might be
+done by temporarily slowing down or speeding up the clock or by making a
+single adjustment;
+.IP
+different CPU cores on a multi-core or multi-processor system might be
+running at different speeds, or might not have time counters all
+synchronized, so packets time-stamped by different cores might not have
+consistent time stamps.
+.LP
+In addition, packets time-stamped by different cores might be
+time-stamped in one order and added to the queue of packets for libpcap
+to read in another order, so time stamps might not be monotonically
+increasing.
+.LP
+Some capture devices on some platforms can provide time stamps for
+packets; those time stamps are usually high-resolution time stamps, and
+are usually applied to the packet when the first or last bit of the
+packet arrives, and are thus more accurate than time stamps provided by
+the host operating system.  Those time stamps might not, however, be
+synchronized with the host operating system's clock, so that, for
+example, the time stamp of a packet might not correspond to the time
+stamp of an event on the host triggered by the arrival of that packet.
+.LP
+Depending on the capture device and the software on the host, libpcap
+might allow different types of time stamp to be used.  The
+.BR pcap_list_tstamp_types (3PCAP)
+routine provides, for a packet capture handle created by
+.BR pcap_create (3PCAP)
+but not yet activated by
+.BR pcap_activate (3PCAP),
+a list of time stamp types supported by the capture device for that
+handle.
+The list might be empty, in which case no choice of time stamp type is
+offered for that capture device.  If the list is not empty, the
+.BR pcap_set_tstamp_type (3PCAP)
+routine can be used after a
+.B pcap_create()
+call and before a
+.B pcap_activate()
+call to specify the type of time stamp to be used on the device.
+The time stamp types are listed here; the first value is the #define to
+use in code, the second value is the value returned by
+.B pcap_tstamp_type_val_to_name()
+and accepted by
+.BR pcap_tstamp_type_name_to_val() .
+.RS 5
+.TP 5
+.BR PCAP_TSTAMP_HOST " - " host
+Time stamp provided by the host on which the capture is being done.  The
+precision of this time stamp is unspecified; it might or might not be
+synchronized with the host operating system's clock.
+.TP 5
+.BR PCAP_TSTAMP_HOST_LOWPREC " - " host_lowprec
+Time stamp provided by the host on which the capture is being done.
+This is a low-precision time stamp, synchronized with the host operating
+system's clock.
+.TP 5
+.BR PCAP_TSTAMP_HOST_HIPREC " - " host_hiprec
+Time stamp provided by the host on which the capture is being done.
+This is a high-precision time stamp; it might or might not be
+synchronized with the host operating system's clock.  It might be more
+expensive to fetch than
+.BR PCAP_TSTAMP_HOST_LOWPREC .
+.TP 5
+.BR PCAP_TSTAMP_ADAPTER " - " adapter
+Time stamp provided by the network adapter on which the capture is being
+done.  This is a high-precision time stamp, synchronized with the host
+operating system's clock.
+.TP 5
+.BR PCAP_TSTAMP_ADAPTER_UNSYNCED " - " adapter_unsynced
+Time stamp provided by the network adapter on which the capture is being
+done.  This is a high-precision time stamp; it is not synchronized with
+the host operating system's clock.
+.RE
+.LP
+By default, when performing a live capture or reading from a savefile,
+time stamps are supplied as seconds since January 1, 1970, 00:00:00 UTC,
+and microseconds since that seconds value, even if higher-resolution
+time stamps are available from the capture device or in the savefile.
+If, when reading a savefile, the time stamps in the file have a higher
+resolution than one microsecond, the additional digits of resolution are
+discarded.
+.LP
+The
+.BR pcap_set_tstamp_precision (3PCAP)
+routine can be used after a
+.B pcap_create()
+call and after a
+.B pcap_activate()
+call to specify the resolution of the time stamps to get for the device.
+If the hardware or software cannot supply a higher-resolution time
+stamp, the
+.B pcap_set_tstamp_precision()
+call will fail, and the time stamps supplied after the
+.B pcap_activate()
+call will have microsecond resolution.
+.LP
+When opening a savefile, the
+.BR pcap_open_offline_with_tstamp_precision (3PCAP)
+and
+.BR pcap_fopen_offline_with_tstamp_precision (3PCAP)
+routines can be used to specify the resolution of time stamps to be read
+from the file; if the time stamps in the file have a lower resolution,
+the fraction-of-a-second portion of the time stamps will be scaled to
+the specified resolution.
+.LP
+The
+.BR pcap_get_tstamp_precision (3PCAP)
+routine returns the resolution of time stamps that will be supplied;
+when capturing packets, this does not reflect the actual precision of
+the time stamp supplied by the hardware or operating system and, when
+reading a savefile, this does not indicate the actual precision of time
+stamps in the file.
+.SH SEE ALSO
+pcap_set_tstamp_type(3PCAP),
+pcap_list_tstamp_types(3PCAP),
+pcap_tstamp_type_val_to_name(3PCAP),
+pcap_tstamp_type_name_to_val(3PCAP),
+pcap_set_tstamp_precision(3PCAP),
+pcap_open_offline_with_tstamp_precision(3PCAP),
+pcap_fopen_offline_with_tstamp_precision(3PCAP),
+pcap_get_tstamp_precision(3PCAP)
diff --git a/pcap-tstamp.manmisc.in b/pcap-tstamp.manmisc.in
index 74a9a35..2e1ef61 100644
--- a/pcap-tstamp.manmisc.in
+++ b/pcap-tstamp.manmisc.in
@@ -19,7 +19,7 @@
 .\" WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
 .\" MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
 .\"
-.TH PCAP-TSTAMP @MAN_MISC_INFO@ "21 December 2013"
+.TH PCAP-TSTAMP @MAN_MISC_INFO@ "8 March 2015"
 .SH NAME
 pcap-tstamp \- packet time stamps in libpcap
 .SH DESCRIPTION
diff --git a/pcap-usb-linux.c b/pcap-usb-linux.c
index 957273a..fb1188a 100644
--- a/pcap-usb-linux.c
+++ b/pcap-usb-linux.c
@@ -144,8 +144,8 @@
 {
 	char dev_name[10];
 	char dev_descr[30];
-	snprintf(dev_name, 10, USB_IFACE"%d", n);
-	snprintf(dev_descr, 30, "USB bus number %d", n);
+	pcap_snprintf(dev_name, 10, USB_IFACE"%d", n);
+	pcap_snprintf(dev_descr, 30, "USB bus number %d", n);
 
 	if (pcap_add_if(alldevsp, dev_name, 0,
 	    dev_descr, err_str) < 0)
@@ -156,6 +156,7 @@
 int
 usb_findalldevs(pcap_if_t **alldevsp, char *err_str)
 {
+	int fd;
 	struct dirent* data;
 	int ret = 0;
 	DIR* dir;
@@ -163,7 +164,46 @@
 	char* name;
 	size_t len;
 
-	/* try scanning sysfs usb bus directory */
+	/*
+	 * Do we have a "scan all buses" device?
+	 * First, try the binary device.
+	 */
+	fd = open(LINUX_USB_MON_DEV"0", O_RDONLY, 0);
+	if (fd >= 0) {
+		/*
+		 * Yes.
+		 */
+		close(fd);
+		if (pcap_add_if(alldevsp, "usbmon0", 0, "All USB buses",
+		    err_str) < 0)
+			return -1;
+	} else {
+		/*
+		 * No binary device; do we have the text device?
+		 */
+		fd = open(USB_TEXT_DIR"/0t", O_RDONLY, 0);
+		if (fd < 0) {
+			/*
+			 * Not at the new location; try the old location.
+			 */
+			fd = open(USB_TEXT_DIR_OLD"/0t", O_RDONLY, 0);
+		}
+		if (fd >= 0) {
+			/*
+			 * We found it.
+			 */
+			close(fd);
+			if (pcap_add_if(alldevsp, "usbmon0", 0, "All USB buses",
+			    err_str) < 0)
+				return -1;
+		}
+	}
+
+	/*
+	 * Now look for individual USB buses.
+	 *
+	 * First, try scanning sysfs USB bus directory.
+	 */
 	dir = opendir(SYS_USB_BUS_DIR);
 	if (dir != NULL) {
 		while ((ret == 0) && ((data = readdir(dir)) != 0)) {
@@ -182,7 +222,7 @@
 		return ret;
 	}
 
-	/* that didn't work; try scanning procfs usb bus directory */
+	/* That didn't work; try scanning procfs USB bus directory. */
 	dir = opendir(PROC_USB_BUS_DIR);
 	if (dir != NULL) {
 		while ((ret == 0) && ((data = readdir(dir)) != 0)) {
@@ -247,7 +287,7 @@
 	DIR* dir;
 
 	/* scan usb bus directories for device nodes */
-	snprintf(buf, sizeof(buf), "/dev/bus/usb/%03d", bus);
+	pcap_snprintf(buf, sizeof(buf), "/dev/bus/usb/%03d", bus);
 	dir = opendir(buf);
 	if (!dir)
 		return;
@@ -259,7 +299,7 @@
 		if (name[0] == '.')
 			continue;
 
-		snprintf(buf, sizeof(buf), "/dev/bus/usb/%03d/%s", bus, data->d_name);
+		pcap_snprintf(buf, sizeof(buf), "/dev/bus/usb/%03d/%s", bus, data->d_name);
 
 		fd = open(buf, O_RDWR);
 		if (fd == -1)
@@ -328,7 +368,7 @@
 	/* OK, it's probably ours. */
 	*is_ours = 1;
 
-	p = pcap_create_common(device, ebuf, sizeof (struct pcap_usb_linux));
+	p = pcap_create_common(ebuf, sizeof (struct pcap_usb_linux));
 	if (p == NULL)
 		return (NULL);
 
@@ -355,15 +395,15 @@
 	handle->setnonblock_op = pcap_setnonblock_fd;
 
 	/*get usb bus index from device name */
-	if (sscanf(handle->opt.source, USB_IFACE"%d", &handlep->bus_index) != 1)
+	if (sscanf(handle->opt.device, USB_IFACE"%d", &handlep->bus_index) != 1)
 	{
-		snprintf(handle->errbuf, PCAP_ERRBUF_SIZE,
-			"Can't get USB bus index from %s", handle->opt.source);
+		pcap_snprintf(handle->errbuf, PCAP_ERRBUF_SIZE,
+			"Can't get USB bus index from %s", handle->opt.device);
 		return PCAP_ERROR;
 	}
 
 	/*now select the read method: try to open binary interface */
-	snprintf(full_path, USB_LINE_LEN, LINUX_USB_MON_DEV"%d", handlep->bus_index);
+	pcap_snprintf(full_path, USB_LINE_LEN, LINUX_USB_MON_DEV"%d", handlep->bus_index);
 	handle->fd = open(full_path, O_RDONLY, 0);
 	if (handle->fd >= 0)
 	{
@@ -402,7 +442,7 @@
 	}
 	else {
 		/*Binary interface not available, try open text interface */
-		snprintf(full_path, USB_LINE_LEN, USB_TEXT_DIR"/%dt", handlep->bus_index);
+		pcap_snprintf(full_path, USB_LINE_LEN, USB_TEXT_DIR"/%dt", handlep->bus_index);
 		handle->fd = open(full_path, O_RDONLY, 0);
 		if (handle->fd < 0)
 		{
@@ -412,12 +452,12 @@
 				 * Not found at the new location; try
 				 * the old location.
 				 */
-				snprintf(full_path, USB_LINE_LEN, USB_TEXT_DIR_OLD"/%dt", handlep->bus_index);
+				pcap_snprintf(full_path, USB_LINE_LEN, USB_TEXT_DIR_OLD"/%dt", handlep->bus_index);
 				handle->fd = open(full_path, O_RDONLY, 0);
 			}
 			if (handle->fd < 0) {
 				/* no more fallback, give it up*/
-				snprintf(handle->errbuf, PCAP_ERRBUF_SIZE,
+				pcap_snprintf(handle->errbuf, PCAP_ERRBUF_SIZE,
 					"Can't open USB bus file %s: %s", full_path, strerror(errno));
 				return PCAP_ERROR;
 			}
@@ -445,7 +485,7 @@
 	 * buffer */
 	handle->buffer = malloc(handle->bufsize);
 	if (!handle->buffer) {
-		snprintf(handle->errbuf, PCAP_ERRBUF_SIZE,
+		pcap_snprintf(handle->errbuf, PCAP_ERRBUF_SIZE,
 			 "malloc: %s", pcap_strerror(errno));
 		close(handle->fd);
 		return PCAP_ERROR;
@@ -496,7 +536,7 @@
 		if (errno == EAGAIN)
 			return 0;	/* no data there */
 
-		snprintf(handle->errbuf, PCAP_ERRBUF_SIZE,
+		pcap_snprintf(handle->errbuf, PCAP_ERRBUF_SIZE,
 		    "Can't read from fd %d: %s", handle->fd, strerror(errno));
 		return -1;
 	}
@@ -509,7 +549,7 @@
 		&cnt);
 	if (ret < 8)
 	{
-		snprintf(handle->errbuf, PCAP_ERRBUF_SIZE,
+		pcap_snprintf(handle->errbuf, PCAP_ERRBUF_SIZE,
 		    "Can't parse USB bus message '%s', too few tokens (expected 8 got %d)",
 		    string, ret);
 		return -1;
@@ -523,7 +563,7 @@
 	/* don't use usbmon provided timestamp, since it have low precision*/
 	if (gettimeofday(&pkth.ts, NULL) < 0)
 	{
-		snprintf(handle->errbuf, PCAP_ERRBUF_SIZE,
+		pcap_snprintf(handle->errbuf, PCAP_ERRBUF_SIZE,
 			"Can't get timestamp for message '%s' %d:%s",
 			string, errno, strerror(errno));
 		return -1;
@@ -575,7 +615,7 @@
 		str5, &cnt);
 		if (ret < 5)
 		{
-			snprintf(handle->errbuf, PCAP_ERRBUF_SIZE,
+			pcap_snprintf(handle->errbuf, PCAP_ERRBUF_SIZE,
 				"Can't parse USB bus message '%s', too few tokens (expected 5 got %d)",
 				string, ret);
 			return -1;
@@ -599,7 +639,7 @@
 	ret = sscanf(string, " %d%n", &urb_len, &cnt);
 	if (ret < 1)
 	{
-		snprintf(handle->errbuf, PCAP_ERRBUF_SIZE,
+		pcap_snprintf(handle->errbuf, PCAP_ERRBUF_SIZE,
 		  "Can't parse urb length from '%s'", string);
 		return -1;
 	}
@@ -617,7 +657,7 @@
 	/* check for data presence; data is present if and only if urb tag is '=' */
 	if (sscanf(string, " %c", &urb_tag) != 1)
 	{
-		snprintf(handle->errbuf, PCAP_ERRBUF_SIZE,
+		pcap_snprintf(handle->errbuf, PCAP_ERRBUF_SIZE,
 			"Can't parse urb tag from '%s'", string);
 		return -1;
 	}
@@ -636,7 +676,7 @@
 	 * a partial information.
 	 * At least until linux 2.6.17 there is no way to set usbmon intenal buffer
 	 * length and default value is 130. */
-	while ((string[0] != 0) && (string[1] != 0) && (pkth.caplen < handle->snapshot))
+	while ((string[0] != 0) && (string[1] != 0) && (pkth.caplen < (bpf_u_int32)handle->snapshot))
 	{
 		rawdata[0] = ascii_to_int(string[0]) * 16 + ascii_to_int(string[1]);
 		rawdata++;
@@ -649,8 +689,8 @@
 
 got:
 	uhdr->data_len = data_len;
-	if (pkth.caplen > handle->snapshot)
-		pkth.caplen = handle->snapshot;
+	if (pkth.caplen > (bpf_u_int32)handle->snapshot)
+		pkth.caplen = (bpf_u_int32)handle->snapshot;
 
 	if (handle->fcode.bf_insns == NULL ||
 	    bpf_filter(handle->fcode.bf_insns, handle->buffer,
@@ -665,7 +705,7 @@
 static int
 usb_inject_linux(pcap_t *handle, const void *buf, size_t size)
 {
-	snprintf(handle->errbuf, PCAP_ERRBUF_SIZE, "inject not supported on "
+	pcap_snprintf(handle->errbuf, PCAP_ERRBUF_SIZE, "inject not supported on "
 		"USB devices");
 	return (-1);
 }
@@ -680,7 +720,7 @@
 	char * ptr = string;
 	int fd;
 
-	snprintf(string, USB_LINE_LEN, USB_TEXT_DIR"/%ds", handlep->bus_index);
+	pcap_snprintf(string, USB_LINE_LEN, USB_TEXT_DIR"/%ds", handlep->bus_index);
 	fd = open(string, O_RDONLY, 0);
 	if (fd < 0)
 	{
@@ -690,11 +730,11 @@
 			 * Not found at the new location; try the old
 			 * location.
 			 */
-			snprintf(string, USB_LINE_LEN, USB_TEXT_DIR_OLD"/%ds", handlep->bus_index);
+			pcap_snprintf(string, USB_LINE_LEN, USB_TEXT_DIR_OLD"/%ds", handlep->bus_index);
 			fd = open(string, O_RDONLY, 0);
 		}
 		if (fd < 0) {
-			snprintf(handle->errbuf, PCAP_ERRBUF_SIZE,
+			pcap_snprintf(handle->errbuf, PCAP_ERRBUF_SIZE,
 				"Can't open USB stats file %s: %s",
 				string, strerror(errno));
 			return -1;
@@ -709,7 +749,7 @@
 
 	if (ret < 0)
 	{
-		snprintf(handle->errbuf, PCAP_ERRBUF_SIZE,
+		pcap_snprintf(handle->errbuf, PCAP_ERRBUF_SIZE,
 			"Can't read stats from fd %d ", fd);
 		return -1;
 	}
@@ -763,7 +803,7 @@
 	ret = ioctl(handle->fd, MON_IOCG_STATS, &st);
 	if (ret < 0)
 	{
-		snprintf(handle->errbuf, PCAP_ERRBUF_SIZE,
+		pcap_snprintf(handle->errbuf, PCAP_ERRBUF_SIZE,
 			"Can't read stats from fd %d:%s ", handle->fd, strerror(errno));
 		return -1;
 	}
@@ -785,11 +825,11 @@
 	struct mon_bin_get info;
 	int ret;
 	struct pcap_pkthdr pkth;
-	int clen = handle->snapshot - sizeof(pcap_usb_header);
+	u_int clen = handle->snapshot - sizeof(pcap_usb_header);
 
 	/* the usb header is going to be part of 'packet' data*/
 	info.hdr = (pcap_usb_header*) handle->buffer;
-	info.data = handle->buffer + sizeof(pcap_usb_header);
+	info.data = (u_char *)handle->buffer + sizeof(pcap_usb_header);
 	info.data_len = clen;
 
 	/* ignore interrupt system call errors */
@@ -806,7 +846,7 @@
 		if (errno == EAGAIN)
 			return 0;	/* no data there */
 
-		snprintf(handle->errbuf, PCAP_ERRBUF_SIZE,
+		pcap_snprintf(handle->errbuf, PCAP_ERRBUF_SIZE,
 		    "Can't read from fd %d: %s", handle->fd, strerror(errno));
 		return -1;
 	}
@@ -847,7 +887,7 @@
 	pcap_usb_header* hdr;
 	int nflush = 0;
 	int packets = 0;
-	int clen, max_clen;
+	u_int clen, max_clen;
 
 	max_clen = handle->snapshot - sizeof(pcap_usb_header);
 
@@ -877,7 +917,7 @@
 			if (errno == EAGAIN)
 				return 0;	/* no data there */
 
-			snprintf(handle->errbuf, PCAP_ERRBUF_SIZE,
+			pcap_snprintf(handle->errbuf, PCAP_ERRBUF_SIZE,
 			    "Can't mfetch fd %d: %s", handle->fd, strerror(errno));
 			return -1;
 		}
@@ -918,7 +958,7 @@
 
 	/* flush pending events*/
 	if (ioctl(handle->fd, MON_IOCH_MFLUSH, nflush) == -1) {
-		snprintf(handle->errbuf, PCAP_ERRBUF_SIZE,
+		pcap_snprintf(handle->errbuf, PCAP_ERRBUF_SIZE,
 		    "Can't mflush fd %d: %s", handle->fd, strerror(errno));
 		return -1;
 	}
diff --git a/pcap-win32.c b/pcap-win32.c
index f449f79..d998637 100644
--- a/pcap-win32.c
+++ b/pcap-win32.c
@@ -1,6 +1,6 @@
 /*
  * Copyright (c) 1999 - 2005 NetGroup, Politecnico di Torino (Italy)
- * Copyright (c) 2005 - 2008 CACE Technologies, Davis (California)
+ * Copyright (c) 2005 - 2010 CACE Technologies, Davis (California)
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
@@ -31,8 +31,10 @@
  *
  */
 
-#include <pcap-int.h>
+#define PCAP_DONT_INCLUDE_PCAP_BPF_H
 #include <Packet32.h>
+#include <pcap-int.h>
+#include <pcap/dlt.h>
 #ifdef __MINGW32__
 #ifdef __MINGW64__
 #include <ntddndis.h>
@@ -51,6 +53,9 @@
 int* _errno();
 #define errno (*_errno())
 #endif /* __MINGW32__ */
+#ifdef HAVE_REMOTE
+#include "pcap-rpcap.h"
+#endif /* HAVE_REMOTE */
 
 static int pcap_setfilter_win32_npf(pcap_t *, struct bpf_program *);
 static int pcap_setfilter_win32_dag(pcap_t *, struct bpf_program *);
@@ -71,45 +76,64 @@
  */
 struct pcap_win {
 	int nonblock;
-
-	int filtering_in_kernel; /* using kernel filter */
+	int rfmon_selfstart;		/* a flag tells whether the monitor mode is set by itself */
+	int filtering_in_kernel;	/* using kernel filter */
 
 #ifdef HAVE_DAG_API
-	int	dag_fcs_bits;	/* Number of checksum bits from link layer */
+	int	dag_fcs_bits;		/* Number of checksum bits from link layer */
 #endif
 };
 
-/*
- * Header that the WinPcap driver associates to the packets.
- * Once was in bpf.h
- */
-struct bpf_hdr {
-	struct timeval	bh_tstamp;	/* time stamp */
-	bpf_u_int32	bh_caplen;	/* length of captured portion */
-	bpf_u_int32	bh_datalen;	/* original length of packet */
-	u_short		bh_hdrlen;	/* length of bpf header (this struct
-					   plus alignment padding) */
-};
-
-CRITICAL_SECTION g_PcapCompileCriticalSection;
-
 BOOL WINAPI DllMain(
   HANDLE hinstDLL,
   DWORD dwReason,
   LPVOID lpvReserved
 )
 {
-	if (dwReason == DLL_PROCESS_ATTACH)
-	{
-		InitializeCriticalSection(&g_PcapCompileCriticalSection);
-	}
-
-	return TRUE;
+	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()
+wsockinit(void)
 {
 	WORD wVersionRequested;
 	WSADATA wsaData;
@@ -117,34 +141,114 @@
 	static int done = 0;
 
 	if (done)
-		return err;
+		return (err);
 
 	wVersionRequested = MAKEWORD( 1, 1);
 	err = WSAStartup( wVersionRequested, &wsaData );
 	atexit ((void(*)(void))WSACleanup);
-	InitializeCriticalSection(&g_PcapCompileCriticalSection);
 	done = 1;
 
 	if ( err != 0 )
 		err = -1;
-	return err;
+	return (err);
 }
 
-int pcap_wsockinit()
+int
+pcap_wsockinit(void)
 {
-       return wsockinit();
+       return (wsockinit());
 }
 
 static int
 pcap_stats_win32(pcap_t *p, struct pcap_stat *ps)
 {
+	struct bpf_stat bstats;
+	char errbuf[PCAP_ERRBUF_SIZE+1];
 
-	if(PacketGetStats(p->adapter, (struct bpf_stat*)ps) != TRUE){
-		snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "PacketGetStats error: %s", pcap_win32strerror());
-		return -1;
+	/*
+	 * Try to get statistics.
+	 *
+	 * (Please note - "struct pcap_stat" is *not* the same as
+	 * WinPcap's "struct bpf_stat". It might currently have the
+	 * same layout, but let's not cheat.
+	 *
+	 * Note also that we don't fill in ps_capt, as we might have
+	 * been called by code compiled against an earlier version of
+	 * WinPcap that didn't have ps_capt, in which case filling it
+	 * in would stomp on whatever comes after the structure passed
+	 * to us.
+	 */
+	if (!PacketGetStats(p->adapter, &bstats)) {
+		pcap_win32_err_to_str(GetLastError(), errbuf);
+		pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
+		    "PacketGetStats error: %s", errbuf);
+		return (-1);
 	}
+	ps->ps_recv = bstats.bs_recv;
+	ps->ps_drop = bstats.bs_drop;
 
-	return 0;
+	/*
+	 * 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 */
@@ -153,10 +257,10 @@
 {
 	if(PacketSetBuff(p->adapter,dim)==FALSE)
 	{
-		snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "driver error: not enough memory to allocate the kernel buffer");
-		return -1;
+		pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "driver error: not enough memory to allocate the kernel buffer");
+		return (-1);
 	}
-	return 0;
+	return (0);
 }
 
 /* Set the driver working mode */
@@ -165,11 +269,11 @@
 {
 	if(PacketSetMode(p->adapter,mode)==FALSE)
 	{
-		snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "driver error: working mode not recognized");
-		return -1;
+		pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "driver error: working mode not recognized");
+		return (-1);
 	}
 
-	return 0;
+	return (0);
 }
 
 /*set the minimum amount of data that will release a read call*/
@@ -178,22 +282,210 @@
 {
 	if(PacketSetMinToCopy(p->adapter, size)==FALSE)
 	{
-		snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "driver error: unable to set the requested mintocopy size");
-		return -1;
+		pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "driver error: unable to set the requested mintocopy size");
+		return (-1);
 	}
-	return 0;
+	return (0);
 }
 
-/*return the Adapter for a pcap_t*/
-static Adapter *
-pcap_getadapter_win32(pcap_t *p)
+static HANDLE
+pcap_getevent_win32(pcap_t *p)
 {
-	return p->adapter;
+	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;
@@ -215,15 +507,27 @@
 			return (PCAP_ERROR_BREAK);
 		}
 
-	    /* capture the packets */
-		if(PacketReceivePacket(p->adapter,p->Packet,TRUE)==FALSE){
-			snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "read error: PacketReceivePacket failed");
+		/*
+		 * Capture the packets.
+		 *
+		 * The PACKET structure had a bunch of extra stuff for
+		 * Windows 9x/Me, but the only interesting data in it
+		 * in the versions of Windows that we support is just
+		 * a copy of p->buffer, a copy of p->buflen, and the
+		 * actual number of bytes read returned from
+		 * PacketReceivePacket(), none of which has to be
+		 * retained from call to call, so we just keep one on
+		 * the stack.
+		 */
+		PacketInitPacket(&Packet, (BYTE *)p->buffer, p->bufsize);
+		if (!PacketReceivePacket(p->adapter, &Packet, TRUE)) {
+			pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "read error: PacketReceivePacket failed");
 			return (PCAP_ERROR);
 		}
 
-		cc = p->Packet->ulBytesReceived;
+		cc = Packet.ulBytesReceived;
 
-		bp = p->Packet->Buffer;
+		bp = p->buffer;
 	}
 	else
 		bp = p->bp;
@@ -252,7 +556,7 @@
 				return (PCAP_ERROR_BREAK);
 			} else {
 				p->bp = bp;
-				p->cc = ep - bp;
+				p->cc = (int) (ep - bp);
 				return (n);
 			}
 		}
@@ -282,7 +586,7 @@
 			bp += Packet_WORDALIGN(caplen + hdrlen);
 			if (++n >= cnt && !PACKET_COUNT_IS_UNLIMITED(cnt)) {
 				p->bp = bp;
-				p->cc = ep - bp;
+				p->cc = (int) (ep - bp);
 				return (n);
 			}
 		} else {
@@ -302,6 +606,7 @@
 pcap_read_win32_dag(pcap_t *p, int cnt, pcap_handler callback, u_char *user)
 {
 	struct pcap_win *pw = p->priv;
+	PACKET Packet;
 	u_char *dp = NULL;
 	int	packet_len = 0, caplen = 0;
 	struct pcap_pkthdr	pcap_header;
@@ -317,16 +622,28 @@
 	cc = p->cc;
 	if (cc == 0) /* Get new packets only if we have processed all the ones of the previous read */
 	{
-	    /* Get new packets from the network */
-		if(PacketReceivePacket(p->adapter, p->Packet, TRUE)==FALSE){
-			snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "read error: PacketReceivePacket failed");
+		/*
+		 * Get new packets from the network.
+		 *
+		 * The PACKET structure had a bunch of extra stuff for
+		 * Windows 9x/Me, but the only interesting data in it
+		 * in the versions of Windows that we support is just
+		 * a copy of p->buffer, a copy of p->buflen, and the
+		 * actual number of bytes read returned from
+		 * PacketReceivePacket(), none of which has to be
+		 * retained from call to call, so we just keep one on
+		 * the stack.
+		 */
+		PacketInitPacket(&Packet, (BYTE *)p->buffer, p->bufsize);
+		if (!PacketReceivePacket(p->adapter, &Packet, TRUE)) {
+			pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "read error: PacketReceivePacket failed");
 			return (-1);
 		}
 
-		cc = p->Packet->ulBytesReceived;
+		cc = Packet.ulBytesReceived;
 		if(cc == 0)
 			/* The timeout has expired but we no packets arrived */
-			return 0;
+			return (0);
 		header = (dag_record_t*)p->adapter->DagBuffer;
 	}
 	else
@@ -344,7 +661,7 @@
 			break;
 
 		/* Increase the number of captured packets */
-		pw->stat.ps_recv++;
+		p->stat.ps_recv++;
 
 		/* Find the beginning of the packet */
 		dp = ((u_char *)header) + dag_record_size;
@@ -455,7 +772,7 @@
 	}
 	while((u_char*)header < endofbuf);
 
-  return 1;
+	return (1);
 }
 #endif /* HAVE_DAG_API */
 
@@ -468,15 +785,15 @@
 
 	if (PacketToSend == NULL)
 	{
-		snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "send error: PacketAllocatePacket failed");
-		return -1;
+		pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "send error: PacketAllocatePacket failed");
+		return (-1);
 	}
 
-	PacketInitPacket(PacketToSend,(PVOID)buf,size);
+	PacketInitPacket(PacketToSend, (PVOID)buf, (UINT)size);
 	if(PacketSendPacket(p->adapter,PacketToSend,TRUE) == FALSE){
-		snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "send error: PacketSendPacket failed");
+		pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "send error: PacketSendPacket failed");
 		PacketFreePacket(PacketToSend);
-		return -1;
+		return (-1);
 	}
 
 	PacketFreePacket(PacketToSend);
@@ -486,19 +803,20 @@
 	 * "pcap_inject()" is expected to return the number of bytes
 	 * sent.
 	 */
-	return size;
+	return ((int)size);
 }
 
 static void
 pcap_cleanup_win32(pcap_t *p)
 {
+	struct pcap_win *pw = p->priv;
 	if (p->adapter != NULL) {
 		PacketCloseAdapter(p->adapter);
 		p->adapter = NULL;
 	}
-	if (p->Packet) {
-		PacketFreePacket(p->Packet);
-		p->Packet = NULL;
+	if (pw->rfmon_selfstart)
+	{
+		PacketSetMonitorMode(p->opt.device, 0);
 	}
 	pcap_cleanup_live_common(p);
 }
@@ -508,32 +826,123 @@
 {
 	struct pcap_win *pw = p->priv;
 	NetType type;
+	int res;
+	char errbuf[PCAP_ERRBUF_SIZE+1];
+
+#ifdef HAVE_REMOTE
+	char host[PCAP_BUF_SIZE + 1];
+	char port[PCAP_BUF_SIZE + 1];
+	char name[PCAP_BUF_SIZE + 1];
+	int srctype;
+	int opensource_remote_result;
+
+	struct pcap_md *md;				/* structure used when doing a remote live capture */
+	md = (struct pcap_md *) ((u_char*)p->priv + sizeof(struct pcap_win));
+
+	/*
+	Retrofit; we have to make older applications compatible with the remote capture
+	So, we're calling the pcap_open_remote() from here, that is a very dirty thing.
+	Obviously, we cannot exploit all the new features; for instance, we cannot
+	send authentication, we cannot use a UDP data connection, and so on.
+	*/
+	if (pcap_parsesrcstr(p->opt.device, &srctype, host, port, name, p->errbuf))
+		return PCAP_ERROR;
+
+	if (srctype == PCAP_SRC_IFREMOTE)
+	{
+		opensource_remote_result = pcap_opensource_remote(p, NULL);
+
+		if (opensource_remote_result != 0)
+			return opensource_remote_result;
+
+		md->rmt_flags = (p->opt.promisc) ? PCAP_OPENFLAG_PROMISCUOUS : 0;
+
+		return 0;
+	}
+
+	if (srctype == PCAP_SRC_IFLOCAL)
+	{
+		/*
+		* If it starts with rpcap://, cut down the string
+		*/
+		if (strncmp(p->opt.device, PCAP_SRC_IF_STRING, strlen(PCAP_SRC_IF_STRING)) == 0)
+		{
+			size_t len = strlen(p->opt.device) - strlen(PCAP_SRC_IF_STRING) + 1;
+			char *new_string;
+			/*
+			* allocate a new string and free the old one
+			*/
+			if (len > 0)
+			{
+				new_string = (char*)malloc(len);
+				if (new_string != NULL)
+				{
+					char *tmp;
+					strcpy_s(new_string, len, p->opt.device + strlen(PCAP_SRC_IF_STRING));
+					tmp = p->opt.device;
+					p->opt.device = new_string;
+					free(tmp);
+				}
+			}
+		}
+	}
+
+#endif	/* HAVE_REMOTE */
 
 	if (p->opt.rfmon) {
 		/*
-		 * No monitor mode on Windows.  It could be done on
-		 * Vista with drivers that support the native 802.11
-		 * mechanism and monitor mode.
+		 * Monitor mode is supported on Windows Vista and later.
 		 */
-		return (PCAP_ERROR_RFMON_NOTSUP);
+		if (PacketGetMonitorMode(p->opt.device) == 1)
+		{
+			pw->rfmon_selfstart = 0;
+		}
+		else
+		{
+			if ((res = PacketSetMonitorMode(p->opt.device, 1)) != 1)
+			{
+				pw->rfmon_selfstart = 0;
+				// Monitor mode is not supported.
+				if (res == 0)
+				{
+					return PCAP_ERROR_RFMON_NOTSUP;
+				}
+				else
+				{
+					return PCAP_ERROR;
+				}
+			}
+			else
+			{
+				pw->rfmon_selfstart = 1;
+			}
+		}
 	}
 
 	/* Init WinSock */
 	wsockinit();
 
-	p->adapter = PacketOpenAdapter(p->opt.source);
+	p->adapter = PacketOpenAdapter(p->opt.device);
 
 	if (p->adapter == NULL)
 	{
 		/* Adapter detected but we are not able to open it. Return failure. */
-		snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "Error opening adapter: %s", pcap_win32strerror());
-		return PCAP_ERROR;
+		pcap_win32_err_to_str(GetLastError(), errbuf);
+		if (pw->rfmon_selfstart)
+		{
+			PacketSetMonitorMode(p->opt.device, 0);
+		}
+		pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
+		    "Error opening adapter: %s", errbuf);
+		return (PCAP_ERROR);
 	}
 
 	/*get network type*/
 	if(PacketGetNetType (p->adapter,&type) == FALSE)
 	{
-		snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "Cannot determine the network type: %s", pcap_win32strerror());
+		pcap_win32_err_to_str(GetLastError(), errbuf);
+		pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
+		    "Cannot determine the network type: %s", errbuf);
 		goto bad;
 	}
 
@@ -622,7 +1031,7 @@
 
 		if (PacketSetHwFilter(p->adapter,NDIS_PACKET_TYPE_PROMISCUOUS) == FALSE)
 		{
-			snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "failed to set hardware filter to promiscuous mode");
+			pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "failed to set hardware filter to promiscuous mode");
 			goto bad;
 		}
 	}
@@ -630,7 +1039,7 @@
 	{
 		if (PacketSetHwFilter(p->adapter,NDIS_PACKET_TYPE_ALL_LOCAL) == FALSE)
 		{
-			snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "failed to set hardware filter to non-promiscuous mode");
+			pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "failed to set hardware filter to non-promiscuous mode");
 			goto bad;
 		}
 	}
@@ -638,13 +1047,6 @@
 	/* Set the buffer size */
 	p->bufsize = WIN32_DEFAULT_USER_BUFFER_SIZE;
 
-	/* allocate Packet structure used during the capture */
-	if((p->Packet = PacketAllocatePacket())==NULL)
-	{
-		snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "failed to allocate the PACKET structure");
-		goto bad;
-	}
-
 	if(!(p->adapter->Flags & INFO_FLAG_DAG_CARD))
 	{
 	/*
@@ -652,32 +1054,33 @@
 	 */
 		/*
 		 * If the buffer size wasn't explicitly set, default to
-		 * WIN32_DEFAULT_USER_BUFFER_SIZE.
+		 * WIN32_DEFAULT_KERNEL_BUFFER_SIZE.
 		 */
 	 	if (p->opt.buffer_size == 0)
 	 		p->opt.buffer_size = WIN32_DEFAULT_KERNEL_BUFFER_SIZE;
 
 		if(PacketSetBuff(p->adapter,p->opt.buffer_size)==FALSE)
 		{
-			snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "driver error: not enough memory to allocate the kernel buffer");
+			pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "driver error: not enough memory to allocate the kernel buffer");
 			goto bad;
 		}
 
-		p->buffer = (u_char *)malloc(p->bufsize);
+		p->buffer = malloc(p->bufsize);
 		if (p->buffer == NULL)
 		{
-			snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "malloc: %s", pcap_strerror(errno));
+			pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "malloc: %s", pcap_strerror(errno));
 			goto bad;
 		}
 
-		PacketInitPacket(p->Packet,(BYTE*)p->buffer,p->bufsize);
-
 		if (p->opt.immediate)
 		{
 			/* tell the driver to copy the buffer as soon as data arrives */
 			if(PacketSetMinToCopy(p->adapter,0)==FALSE)
 			{
-				snprintf(p->errbuf, PCAP_ERRBUF_SIZE,"Error calling PacketSetMinToCopy: %s", pcap_win32strerror());
+				pcap_win32_err_to_str(GetLastError(), errbuf);
+				pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
+				    "Error calling PacketSetMinToCopy: %s",
+				    errbuf);
 				goto bad;
 			}
 		}
@@ -686,7 +1089,10 @@
 			/* tell the driver to copy the buffer only if it contains at least 16K */
 			if(PacketSetMinToCopy(p->adapter,16000)==FALSE)
 			{
-				snprintf(p->errbuf, PCAP_ERRBUF_SIZE,"Error calling PacketSetMinToCopy: %s", pcap_win32strerror());
+				pcap_win32_err_to_str(GetLastError(), errbuf);
+				pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
+				    "Error calling PacketSetMinToCopy: %s",
+				    errbuf);
 				goto bad;
 			}
 		}
@@ -704,9 +1110,9 @@
 		int		postype = 0;
 		char	keyname[512];
 
-		snprintf(keyname, sizeof(keyname), "%s\\CardParams\\%s",
+		pcap_snprintf(keyname, sizeof(keyname), "%s\\CardParams\\%s",
 			"SYSTEM\\CurrentControlSet\\Services\\DAG",
-			strstr(_strlwr(p->opt.source), "dag"));
+			strstr(_strlwr(p->opt.device), "dag"));
 		do
 		{
 			status = RegOpenKeyEx(HKEY_LOCAL_MACHINE, keyname, 0, KEY_READ, &dagkey);
@@ -765,10 +1171,18 @@
 	p->getnonblock_op = pcap_getnonblock_win32;
 	p->setnonblock_op = pcap_setnonblock_win32;
 	p->stats_op = pcap_stats_win32;
+	p->stats_ex_op = pcap_stats_ex_win32;
 	p->setbuff_op = pcap_setbuff_win32;
 	p->setmode_op = pcap_setmode_win32;
 	p->setmintocopy_op = pcap_setmintocopy_win32;
-	p->getadapter_op = pcap_getadapter_win32;
+	p->getevent_op = pcap_getevent_win32;
+	p->oid_get_request_op = pcap_oid_get_request_win32;
+	p->oid_set_request_op = pcap_oid_set_request_win32;
+	p->sendqueue_transmit_op = pcap_sendqueue_transmit_win32;
+	p->setuserbuffer_op = pcap_setuserbuffer_win32;
+	p->live_dump_op = pcap_live_dump_win32;
+	p->live_dump_ended_op = pcap_live_dump_ended_win32;
+	p->get_airpcap_handle_op = pcap_get_airpcap_handle_win32;
 	p->cleanup_op = pcap_cleanup_win32;
 
 	return (0);
@@ -777,47 +1191,30 @@
 	return (PCAP_ERROR);
 }
 
+/*
+* Check if rfmon mode is supported on the pcap_t for Windows systems.
+*/
+static int
+pcap_can_set_rfmon_win32(pcap_t *p)
+{
+	return (PacketIsMonitorModeSupported(p->opt.device) == 1);
+}
+
 pcap_t *
-pcap_create_interface(const char *device, char *ebuf)
+pcap_create_interface(const char *device _U_, char *ebuf)
 {
 	pcap_t *p;
 
-	if (strlen(device) == 1)
-	{
-		/*
-		 * It's probably a unicode string
-		 * Convert to ascii and pass it to pcap_create_common
-		 *
-		 * This wonderful hack is needed because pcap_lookupdev still returns
-		 * unicode strings, and it's used by windump when no device is specified
-		 * in the command line
-		 */
-		size_t length;
-		char* deviceAscii;
-
-		length = wcslen((wchar_t*)device);
-
-		deviceAscii = (char*)malloc(length + 1);
-
-		if (deviceAscii == NULL)
-		{
-			snprintf(ebuf, PCAP_ERRBUF_SIZE, "Malloc failed");
-			return NULL;
-		}
-
-		snprintf(deviceAscii, length + 1, "%ws", (wchar_t*)device);
-		p = pcap_create_common(deviceAscii, ebuf, sizeof (struct pcap_win));
-		free(deviceAscii);
-	}
-	else
-	{
-		p = pcap_create_common(device, ebuf, sizeof (struct pcap_win));
-	}
-
+#ifdef HAVE_REMOTE
+	p = pcap_create_common(ebuf, sizeof(struct pcap_win) + sizeof(struct pcap_md));
+#else
+	p = pcap_create_common(ebuf, sizeof(struct pcap_win));
+#endif /* HAVE_REMOTE */
 	if (p == NULL)
 		return (NULL);
 
 	p->activate_op = pcap_activate_win32;
+	p->can_set_rfmon_op = pcap_can_set_rfmon_win32;
 	return (p);
 }
 
@@ -887,16 +1284,16 @@
 
 	if(!fp)
 	{
-		strncpy(p->errbuf, "setfilter: No filter specified", sizeof(p->errbuf));
-		return -1;
+		strlcpy(p->errbuf, "setfilter: No filter specified", sizeof(p->errbuf));
+		return (-1);
 	}
 
 	/* Install a user level filter */
 	if (install_bpf_program(p, fp) < 0)
 	{
-		snprintf(p->errbuf, sizeof(p->errbuf),
+		pcap_snprintf(p->errbuf, sizeof(p->errbuf),
 			"setfilter, unable to install the filter: %s", pcap_strerror(errno));
-		return -1;
+		return (-1);
 	}
 
 	return (0);
@@ -920,6 +1317,7 @@
 {
 	struct pcap_win *pw = p->priv;
 	int newtimeout;
+	char win_errbuf[PCAP_ERRBUF_SIZE+1];
 
 	if (nonblock) {
 		/*
@@ -930,22 +1328,221 @@
 		/*
 		 * Restore the timeout set when the device was opened.
 		 * (Note that this may be -1, in which case we're not
-		 * really leaving non-blocking mode.)
+		 * really leaving non-blocking mode.  However, although
+		 * the timeout argument to pcap_set_timeout() and
+		 * pcap_open_live() is an int, you're not supposed to
+		 * supply a negative value, so that "shouldn't happen".)
 		 */
 		newtimeout = p->opt.timeout;
 	}
 	if (!PacketSetReadTimeout(p->adapter, newtimeout)) {
-		snprintf(errbuf, PCAP_ERRBUF_SIZE,
-		    "PacketSetReadTimeout: %s", pcap_win32strerror());
+		pcap_win32_err_to_str(GetLastError(), win_errbuf);
+		pcap_snprintf(errbuf, PCAP_ERRBUF_SIZE,
+		    "PacketSetReadTimeout: %s", win_errbuf);
 		return (-1);
 	}
 	pw->nonblock = (newtimeout == -1);
 	return (0);
 }
 
-/*platform-dependent routine to add devices other than NDIS interfaces*/
+static int
+pcap_add_if_win32(pcap_if_t **devlist, char *name, bpf_u_int32 flags,
+    const char *description, char *errbuf)
+{
+	pcap_if_t *curdev;
+	npf_if_addr if_addrs[MAX_NETWORK_ADDRESSES];
+	LONG if_addr_size;
+	int res = 0;
+
+	if_addr_size = MAX_NETWORK_ADDRESSES;
+
+	/*
+	 * Add an entry for this interface, with no addresses.
+	 */
+	if (add_or_find_if(&curdev, devlist, name, flags, description,
+	    errbuf) == -1) {
+		/*
+		 * Failure.
+		 */
+		return (-1);
+	}
+
+	/*
+	 * Get the list of addresses for the interface.
+	 */
+	if (!PacketGetNetInfoEx((void *)name, if_addrs, &if_addr_size)) {
+		/*
+		 * Failure.
+		 *
+		 * We don't return an error, because this can happen with
+		 * NdisWan interfaces, and we want to supply them even
+		 * if we can't supply their addresses.
+		 *
+		 * We return an entry with an empty address list.
+		 */
+		return (0);
+	}
+
+	/*
+	 * Now add the addresses.
+	 */
+	while (if_addr_size-- > 0) {
+		/*
+		 * "curdev" is an entry for this interface; add an entry for
+		 * this address to its list of addresses.
+		 */
+		if(curdev == NULL)
+			break;
+		res = add_addr_to_dev(curdev,
+		    (struct sockaddr *)&if_addrs[if_addr_size].IPAddress,
+		    sizeof (struct sockaddr_storage),
+		    (struct sockaddr *)&if_addrs[if_addr_size].SubnetMask,
+		    sizeof (struct sockaddr_storage),
+		    (struct sockaddr *)&if_addrs[if_addr_size].Broadcast,
+		    sizeof (struct sockaddr_storage),
+		    NULL,
+		    0,
+		    errbuf);
+		if (res == -1) {
+			/*
+			 * Failure.
+			 */
+			break;
+		}
+	}
+
+	return (res);
+}
+
 int
 pcap_platform_finddevs(pcap_if_t **alldevsp, char *errbuf)
 {
-	return (0);
+	pcap_if_t *devlist = NULL;
+	int ret = 0;
+	const char *desc;
+	char *AdaptersName;
+	ULONG NameLength;
+	char *name;
+	char our_errbuf[PCAP_ERRBUF_SIZE+1];
+
+	/*
+	 * Find out how big a buffer we need.
+	 *
+	 * This call should always return FALSE; if the error is
+	 * ERROR_INSUFFICIENT_BUFFER, NameLength will be set to
+	 * the size of the buffer we need, otherwise there's a
+	 * problem, and NameLength should be set to 0.
+	 *
+	 * It shouldn't require NameLength to be set, but,
+	 * at least as of WinPcap 4.1.3, it checks whether
+	 * NameLength is big enough before it checks for a
+	 * NULL buffer argument, so, while it'll still do
+	 * the right thing if NameLength is uninitialized and
+	 * whatever junk happens to be there is big enough
+	 * (because the pointer argument will be null), it's
+	 * still reading an uninitialized variable.
+	 */
+	NameLength = 0;
+	if (!PacketGetAdapterNames(NULL, &NameLength))
+	{
+		DWORD last_error = GetLastError();
+
+		if (last_error != ERROR_INSUFFICIENT_BUFFER)
+		{
+			pcap_win32_err_to_str(last_error, our_errbuf);
+			pcap_snprintf(errbuf, PCAP_ERRBUF_SIZE,
+			    "PacketGetAdapterNames: %s", our_errbuf);
+			return (-1);
+		}
+	}
+
+	if (NameLength > 0)
+		AdaptersName = (char*) malloc(NameLength);
+	else
+	{
+		*alldevsp = NULL;
+		return 0;
+	}
+	if (AdaptersName == NULL)
+	{
+		pcap_snprintf(errbuf, PCAP_ERRBUF_SIZE, "Cannot allocate enough memory to list the adapters.");
+		return (-1);
+	}
+
+	if (!PacketGetAdapterNames(AdaptersName, &NameLength)) {
+		pcap_win32_err_to_str(GetLastError(), our_errbuf);
+		pcap_snprintf(errbuf, PCAP_ERRBUF_SIZE, "PacketGetAdapterNames: %s",
+		    our_errbuf);
+		free(AdaptersName);
+		return (-1);
+	}
+
+	/*
+	 * "PacketGetAdapterNames()" returned a list of
+	 * null-terminated ASCII interface name strings,
+	 * terminated by a null string, followed by a list
+	 * of null-terminated ASCII interface description
+	 * strings, terminated by a null string.
+	 * This means there are two ASCII nulls at the end
+	 * of the first list.
+	 *
+	 * Find the end of the first list; that's the
+	 * beginning of the second list.
+	 */
+	desc = &AdaptersName[0];
+	while (*desc != '\0' || *(desc + 1) != '\0')
+		desc++;
+
+	/*
+ 	 * Found it - "desc" points to the first of the two
+	 * nulls at the end of the list of names, so the
+	 * first byte of the list of descriptions is two bytes
+	 * after it.
+	 */
+	desc += 2;
+
+	/*
+	 * Loop over the elements in the first list.
+	 */
+	name = &AdaptersName[0];
+	while (*name != '\0') {
+		bpf_u_int32 flags = 0;
+#ifdef HAVE_PACKET_IS_LOOPBACK_ADAPTER
+		/*
+		 * Is this a loopback interface?
+		 */
+		if (PacketIsLoopbackAdapter(name)) {
+			/* Yes */
+			flags |= PCAP_IF_LOOPBACK;
+		}
+#endif
+
+		/*
+		 * Add an entry for this interface.
+		 */
+		if (pcap_add_if_win32(&devlist, name, flags, desc,
+		    errbuf) == -1) {
+			/*
+			 * Failure.
+			 */
+			ret = -1;
+			break;
+		}
+		name += strlen(name) + 1;
+		desc += strlen(desc) + 1;
+	}
+
+	if (ret == -1) {
+		/*
+		 * We had an error; free the list we've been constructing.
+		 */
+		if (devlist != NULL) {
+			pcap_freealldevs(devlist);
+			devlist = NULL;
+		}
+	}
+
+	*alldevsp = devlist;
+	free(AdaptersName);
+	return (ret);
 }
diff --git a/pcap.3pcap b/pcap.3pcap
new file mode 100644
index 0000000..9f408a0
--- /dev/null
+++ b/pcap.3pcap
@@ -0,0 +1,937 @@
+.\" 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 3PCAP "8 March 2015"
+.SH NAME
+pcap \- Packet Capture library
+.SH SYNOPSIS
+.nf
+.ft B
+#include <pcap/pcap.h>
+.LP
+.ft B
+.ft
+.fi
+.SH DESCRIPTION
+The Packet Capture library
+provides a high level interface to packet capture systems. All packets
+on the network, even those destined for other hosts, are accessible
+through this mechanism.
+It also supports saving captured packets to a ``savefile'', and reading
+packets from a ``savefile''.
+.SS Opening a capture handle for reading
+To open a handle for a live capture, given the name of the network or
+other interface on which the capture should be done, call
+.BR pcap_create (),
+set the appropriate options on the handle, and then activate it with
+.BR pcap_activate ().
+.PP
+To obtain a list of devices that can be opened for a live capture, call
+.BR pcap_findalldevs ();
+to free the list returned by
+.BR pcap_findalldevs (),
+call
+.BR pcap_freealldevs ().
+.BR pcap_lookupdev ()
+will return the first device on that list that is not a ``loopback``
+network interface.
+.PP
+To open a handle for a ``savefile'' from which to read packets, given the
+pathname of the ``savefile'', call
+.BR pcap_open_offline ();
+to set up a handle for a ``savefile'', given a
+.B "FILE\ *"
+referring to a file already opened for reading, call
+.BR pcap_fopen_offline ().
+.PP
+In order to get a ``fake''
+.B pcap_t
+for use in routines that require a
+.B pcap_t
+as an argument, such as routines to open a ``savefile'' for writing and
+to compile a filter expression, call
+.BR pcap_open_dead ().
+.PP
+.BR pcap_create (),
+.BR pcap_open_offline (),
+.BR pcap_fopen_offline (),
+and
+.BR pcap_open_dead ()
+return a pointer to a
+.BR pcap_t ,
+which is the handle used for reading packets from the capture stream or
+the ``savefile'', and for finding out information about the capture
+stream or ``savefile''.
+To close a handle, use
+.BR pcap_close ().
+.PP
+The options that can be set on a capture handle include
+.IP "snapshot length"
+If, when capturing, you capture the entire contents of the packet, that
+requires more CPU time to copy the packet to your application, more disk
+and possibly network bandwidth to write the packet data to a file, and
+more disk space to save the packet.  If you don't need the entire
+contents of the packet - for example, if you are only interested in the
+TCP headers of packets - you can set the "snapshot length" for the
+capture to an appropriate value.  If the snapshot length is set to
+.IR snaplen ,
+and
+.I snaplen
+is less
+than the size of a packet that is captured, only the first
+.I snaplen
+bytes of that packet will be captured and provided as packet data.
+.IP
+A snapshot length of 65535 should be sufficient, on most if not all
+networks, to capture all the data available from the packet.
+.IP
+The snapshot length is set with
+.BR pcap_set_snaplen ().
+.IP "promiscuous mode"
+On broadcast LANs such as Ethernet, if the network isn't switched, or if
+the adapter is connected to a "mirror port" on a switch to which all
+packets passing through the switch are sent, a network adapter receives
+all packets on the LAN, including unicast or multicast packets not sent
+to a network address that the network adapter isn't configured to
+recognize.
+.IP
+Normally, the adapter will discard those packets; however, many network
+adapters support "promiscuous mode", which is a mode in which all
+packets, even if they are not sent to an address that the adapter
+recognizes, are provided to the host.  This is useful for passively
+capturing traffic between two or more other hosts for analysis.
+.IP
+Note that even if an application does not set promiscuous mode, the
+adapter could well be in promiscuous mode for some other reason.
+.IP
+For now, this doesn't work on the "any" device; if an argument of "any"
+or NULL is supplied, the setting of promiscuous mode is ignored.
+.IP
+Promiscuous mode is set with
+.BR pcap_set_promisc ().
+.IP "monitor mode"
+On IEEE 802.11 wireless LANs, even if an adapter is in promiscuous mode,
+it will supply to the host only frames for the network with which it's
+associated.  It might also supply only data frames, not management or
+control frames, and might not provide the 802.11 header or radio
+information pseudo-header for those frames.
+.IP
+In "monitor mode", sometimes also called "rfmon mode" (for "Radio
+Frequency MONitor"), the adapter will supply all frames that it
+receives, with 802.11 headers, and might supply a pseudo-header with
+radio information about the frame as well.
+.IP
+Note that in monitor mode the adapter might disassociate from the
+network with which it's associated, so that you will not be able to use
+any wireless networks with that adapter.  This could prevent accessing
+files on a network server, or resolving host names or network addresses,
+if you are capturing in monitor mode and are not connected to another
+network with another adapter.
+.IP
+Monitor mode is set with
+.BR pcap_set_rfmon (),
+and
+.BR pcap_can_set_rfmon ()
+can be used to determine whether an adapter can be put into monitor
+mode.
+.IP "read 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.
+.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
+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.
+.IP
+.BR NOTE :
+the read 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
+.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
+.BR pcap_set_timeout ().
+.IP "buffer size"
+Packets that arrive for a capture are stored in a buffer, so that they
+do not have to be read by the application as soon as they arrive.  On
+some platforms, the buffer's size can be set; a size that's too small
+could mean that, if too many packets are being captured and the snapshot
+length doesn't limit the amount of data that's buffered, packets could
+be dropped if the buffer fills up before the application can read
+packets from it, while a size that's too large could use more
+non-pageable operating system memory than is necessary to prevent
+packets from being dropped.
+.IP
+The buffer size is set with
+.BR pcap_set_buffer_size ().
+.IP "timestamp type"
+On some platforms, the time stamp given to packets on live captures can
+come from different sources that can have different resolutions or that
+can have different relationships to the time values for the current time
+supplied by routines on the native operating system.  See
+.BR pcap-tstamp (7)
+for a list of time stamp types.
+.IP
+The time stamp type is set with
+.BR pcap_set_tstamp_type ().
+.PP
+Reading packets from a network interface may require that you have
+special privileges:
+.TP
+.B Under SunOS 3.x or 4.x with NIT or BPF:
+You must have read access to
+.I /dev/nit
+or
+.IR /dev/bpf* .
+.TP
+.B Under Solaris with DLPI:
+You must have read/write access to the network pseudo device, e.g.
+.IR /dev/le .
+On at least some versions of Solaris, however, this is not sufficient to
+allow
+.I tcpdump
+to capture in promiscuous mode; on those versions of Solaris, you must
+be root, or the application capturing packets
+must be installed setuid to root, in order to capture in promiscuous
+mode.  Note that, on many (perhaps all) interfaces, if you don't capture
+in promiscuous mode, you will not see any outgoing packets, so a capture
+not done in promiscuous mode may not be very useful.
+.IP
+In newer versions of Solaris, you must have been given the
+.B net_rawaccess
+privilege; this is both necessary and sufficient to give you access to the
+network pseudo-device - there is no need to change the privileges on
+that device.  A user can be given that privilege by, for example, adding
+that privilege to the user's
+.B defaultpriv
+key with the
+.B usermod (1M)
+command.
+.TP
+.B Under HP-UX with DLPI:
+You must be root or the application capturing packets must be installed
+setuid to root.
+.TP
+.B Under IRIX with snoop:
+You must be root or the application capturing packets must be installed
+setuid to root.
+.TP
+.B Under Linux:
+You must be root or the application capturing packets must be installed
+setuid to root (unless your distribution has a kernel
+that supports capability bits such as CAP_NET_RAW and code to allow
+those capability bits to be given to particular accounts and to cause
+those bits to be set on a user's initial processes when they log in, in
+which case you  must have CAP_NET_RAW in order to capture and
+CAP_NET_ADMIN to enumerate network devices with, for example, the
+.B \-D
+flag).
+.TP
+.B Under ULTRIX and Digital UNIX/Tru64 UNIX:
+Any user may capture network traffic.
+However, no user (not even the super-user) can capture in promiscuous
+mode on an interface unless the super-user has enabled promiscuous-mode
+operation on that interface using
+.IR pfconfig (8),
+and no user (not even the super-user) can capture unicast traffic
+received by or sent by the machine on an interface unless the super-user
+has enabled copy-all-mode operation on that interface using
+.IR pfconfig ,
+so
+.I useful
+packet capture on an interface probably requires that either
+promiscuous-mode or copy-all-mode operation, or both modes of
+operation, be enabled on that interface.
+.TP
+.B Under BSD (this includes Mac OS X):
+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
+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,
+if the system even supports that; if it doesn't support that, you might
+have to find some other way to make that happen at boot time.
+.PP
+Reading a saved packet file doesn't require special privileges.
+.PP
+The packets read from the handle may include a ``pseudo-header''
+containing various forms of packet meta-data, and probably includes a
+link-layer header whose contents can differ for different network
+interfaces.  To determine the format of the packets supplied by the
+handle, call
+.BR pcap_datalink ();
+.I http://www.tcpdump.org/linktypes.html
+lists the values it returns and describes the packet formats that
+correspond to those values.
+.PP
+Do
+.B NOT
+assume that the packets for a given capture or ``savefile`` will have
+any given link-layer header type, such as
+.B DLT_EN10MB
+for Ethernet.  For example, the "any" device on Linux will have a
+link-layer header type of
+.B DLT_LINUX_SLL
+even if all devices on the system at the time the "any" device is opened
+have some other data link type, such as
+.B DLT_EN10MB
+for Ethernet.
+.PP
+To obtain the
+.B "FILE\ *"
+corresponding to a
+.B pcap_t
+opened for a ``savefile'', call
+.BR pcap_file ().
+.TP
+.B Routines
+.RS
+.TP
+.BR pcap_create (3PCAP)
+get a
+.B pcap_t
+for live capture
+.TP
+.BR pcap_activate (3PCAP)
+activate a
+.B pcap_t
+for live capture
+.TP
+.BR pcap_findalldevs (3PCAP)
+get a list of devices that can be opened for a live capture
+.TP
+.BR pcap_freealldevs (3PCAP)
+free list of devices
+.TP
+.BR pcap_lookupdev (3PCAP)
+get first non-loopback device on that list
+.TP
+.BR pcap_open_offline (3PCAP)
+open a
+.B pcap_t
+for a ``savefile'', given a pathname
+.TP
+.BR pcap_open_offline_with_tstamp_precision (3PCAP)
+open a
+.B pcap_t
+for a ``savefile'', given a pathname, and specify the precision to
+provide for packet time stamps
+.TP
+.BR pcap_fopen_offline (3PCAP)
+open a
+.B pcap_t
+for a ``savefile'', given a
+.B "FILE\ *"
+.TP
+.BR pcap_fopen_offline_with_tstamp_precision (3PCAP)
+open a
+.B pcap_t
+for a ``savefile'', given a
+.BR "FILE\ *" ,
+and specify the precision to provide for packet time stamps
+.TP
+.BR pcap_open_dead (3PCAP)
+create a ``fake''
+.B pcap_t
+.TP
+.BR pcap_close (3PCAP)
+close a
+.B pcap_t
+.TP
+.BR pcap_set_snaplen (3PCAP)
+set the snapshot length for a not-yet-activated
+.B pcap_t
+for live capture
+.TP
+.BR pcap_snapshot (3PCAP)
+get the snapshot length for a
+.B pcap_t
+.TP
+.BR pcap_set_promisc (3PCAP)
+set promiscuous mode for a not-yet-activated
+.B pcap_t
+for live capture
+.TP
+.BR pcap_set_rfmon (3PCAP)
+set monitor mode for a not-yet-activated
+.B pcap_t
+for live capture
+.TP
+.BR pcap_can_set_rfmon (3PCAP)
+determine whether monitor mode can be set for a
+.B pcap_t
+for live capture
+.TP
+.BR pcap_set_timeout (3PCAP)
+set read timeout for a not-yet-activated
+.B pcap_t
+for live capture
+.TP
+.BR pcap_set_buffer_size (3PCAP)
+set buffer size for a not-yet-activated
+.B pcap_t
+for live capture
+.TP
+.BR pcap_set_tstamp_type (3PCAP)
+set time stamp type for a not-yet-activated
+.B pcap_t
+for live capture
+.TP
+.BR pcap_list_tstamp_types (3PCAP)
+get list of available time stamp types for a not-yet-activated
+.B pcap_t
+for live capture
+.TP
+.BR pcap_free_tstamp_types (3PCAP)
+free list of available time stamp types
+.TP
+.BR pcap_tstamp_type_val_to_name (3PCAP)
+get name for a time stamp type
+.TP
+.BR pcap_tstamp_type_val_to_description (3PCAP)
+get description for a time stamp type
+.TP
+.BR pcap_tstamp_type_name_to_val (3PCAP)
+get time stamp type corresponding to a name
+.TP
+.BR pcap_set_tstamp_precision (3PCAP)
+set time stamp precision for a not-yet-activated
+.B pcap_t
+for live capture
+.TP
+.BR pcap_get_tstamp_precision (3PCAP)
+get the time stamp precision of a
+.B pcap_t
+for live capture
+.TP
+.BR pcap_datalink (3PCAP)
+get link-layer header type for a
+.B pcap_t
+.TP
+.BR pcap_file (3PCAP)
+get the
+.B "FILE\ *"
+for a
+.B pcap_t
+opened for a ``savefile''
+.TP
+.BR pcap_is_swapped (3PCAP)
+determine whether a ``savefile'' being read came from a machine with the
+opposite byte order
+.TP
+.BR pcap_major_version (3PCAP)
+.PD 0
+.TP
+.BR pcap_minor_version (3PCAP)
+get the major and minor version of the file format version for a
+``savefile''
+.PD
+.RE
+.SS Selecting a link-layer header type for a live capture
+Some devices may provide more than one link-layer header type.  To
+obtain a list of all link-layer header types provided by a device, call
+.BR pcap_list_datalinks ()
+on an activated
+.B pcap_t
+for the device.
+To free a list of link-layer header types, call
+.BR pcap_free_datalinks ().
+To set the link-layer header type for a device, call
+.BR pcap_set_datalink ().
+This should be done after the device has been activated but before any
+packets are read and before any filters are compiled or installed.
+.TP
+.B Routines
+.RS
+.TP
+.BR pcap_list_datalinks (3PCAP)
+get a list of link-layer header types for a device
+.TP
+.BR pcap_free_datalinks (3PCAP)
+free list of link-layer header types
+.TP
+.BR pcap_set_datalink (3PCAP)
+set link-layer header type for a device
+.TP
+.BR pcap_datalink_val_to_name (3PCAP)
+get name for a link-layer header type
+.TP
+.BR pcap_datalink_val_to_description (3PCAP)
+get description for a link-layer header type
+.TP
+.BR pcap_datalink_name_to_val (3PCAP)
+get link-layer header type corresponding to a name
+.RE
+.SS Reading packets
+Packets are read with
+.BR pcap_dispatch ()
+or
+.BR pcap_loop (),
+which process one or more packets, calling a callback routine for each
+packet, or with
+.BR pcap_next ()
+or
+.BR pcap_next_ex (),
+which return the next packet.
+The callback for
+.BR pcap_dispatch ()
+and
+.BR pcap_loop ()
+is supplied a pointer to a
+.IR "struct pcap_pkthdr" ,
+which includes the following members:
+.RS
+.TP
+.B ts
+a
+.I struct timeval
+containing the time when the packet was captured
+.TP
+.B caplen
+a
+.I bpf_u_int32
+giving the number of bytes of the packet that are available from the
+capture
+.TP
+.B len
+a
+.I bpf_u_int32
+giving the length of the packet, in bytes (which might be more than the
+number of bytes available from the capture, if the length of the packet
+is larger than the maximum number of bytes to capture).
+.RE
+.PP
+The callback is also supplied a
+.I const u_char
+pointer to the first
+.B caplen
+(as given in the
+.I struct pcap_pkthdr
+mentioned above)
+bytes of data from the packet.  This won't necessarily be the entire
+packet; to capture the entire packet, you will have to provide a value
+for
+.I snaplen
+in your call to
+.BR pcap_set_snaplen ()
+that is sufficiently large to get all of the packet's data - a value of
+65535 should be sufficient on most if not all networks).  When reading
+from a ``savefile'', the snapshot length specified when the capture was
+performed will limit the amount of packet data available.
+.PP
+.BR pcap_next ()
+is passed an argument that points to a
+.I struct pcap_pkthdr
+structure, and fills it in with the time stamp and length values for the
+packet.  It returns a
+.I const u_char
+to the first
+.B caplen
+bytes of the packet on success, and NULL on error.
+.PP
+.BR pcap_next_ex ()
+is passed two pointer arguments, one of which points to a
+.IR struct pcap_pkthdr *
+and one of which points to a
+.IR "const u_char" *.
+It sets the first pointer to point to a
+.I struct pcap_pkthdr
+structure with the time stamp and length values for the packet, and sets
+the second pointer to point to the first
+.B caplen
+bytes of the packet.
+.PP
+To force the loop in
+.BR pcap_dispatch ()
+or
+.BR pcap_loop ()
+to terminate, call
+.BR pcap_breakloop ().
+.PP
+By default, when reading packets from an interface opened for a live
+capture,
+.BR pcap_dispatch (),
+.BR pcap_next (),
+and
+.BR pcap_next_ex ()
+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.
+.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
+available to read.  Call
+.BR pcap_setnonblock ()
+to put a handle into non-blocking mode or to take it out of non-blocking
+mode; call
+.BR pcap_getnonblock ()
+to determine whether a handle is in non-blocking mode.  Note that
+non-blocking mode does not work correctly in Mac OS X 10.6.
+.PP
+Non-blocking mode is often combined with routines such as
+.BR select (2)
+or
+.BR poll (2)
+or other routines a platform offers to wait for any of a set of
+descriptors to be ready to read.  To obtain, for a handle, a descriptor
+that can be used in those routines, call
+.BR pcap_get_selectable_fd ().
+Not all handles have such a descriptor available;
+.BR pcap_get_selectable_fd ()
+will return \-1 if no such descriptor exists.  In addition, for various
+reasons, one or more of those routines will not work properly with the
+descriptor; the documentation for
+.BR pcap_get_selectable_fd ()
+gives details.  Note that, just as an attempt to read packets from a
+.B pcap_t
+may not return any packets if the read timeout expires, a
+.BR select (),
+.BR poll (),
+or other such call may, if the read timeout expires, indicate that a
+descriptor is ready to read even if there are no packets available to
+read.
+.TP
+.B Routines
+.RS
+.TP
+.BR pcap_dispatch (3PCAP)
+read a bufferful of packets from a
+.B pcap_t
+open for a live capture or the full set of packets from a
+.B pcap_t
+open for a ``savefile''
+.TP
+.BR pcap_loop (3PCAP)
+read packets from a
+.B pcap_t
+until an interrupt or error occurs
+.TP
+.BR pcap_next (3PCAP)
+read the next packet from a
+.B pcap_t
+without an indication whether an error occurred
+.TP
+.BR pcap_next_ex (3PCAP)
+read the next packet from a
+.B pcap_t
+with an error indication on an error
+.TP
+.BR pcap_breakloop (3PCAP)
+prematurely terminate the loop in
+.BR pcap_dispatch ()
+or
+.BR pcap_loop ()
+.TP
+.BR pcap_setnonblock (3PCAP)
+set or clear non-blocking mode on a
+.B pcap_t
+.TP
+.BR pcap_getnonblock (3PCAP)
+get the state of non-blocking mode for a
+.B pcap_t
+.TP
+.BR pcap_get_selectable_fd (3PCAP)
+attempt to get a descriptor for a
+.B pcap_t
+that can be used in calls such as
+.BR select (2)
+and
+.BR poll (2)
+.RE
+.SS Filters
+In order to cause only certain packets to be returned when reading
+packets, a filter can be set on a handle.  For a live capture, the
+filtering will be performed in kernel mode, if possible, to avoid
+copying ``uninteresting'' packets from the kernel to user mode.
+.PP
+A filter can be specified as a text string; the syntax and semantics of
+the string are as described by
+.BR pcap-filter (7).
+A filter string is compiled into a program in a pseudo-machine-language
+by
+.BR pcap_compile ()
+and the resulting program can be made a filter for a handle with
+.BR pcap_setfilter ().
+The result of
+.BR pcap_compile ()
+can be freed with a call to
+.BR pcap_freecode ().
+.BR pcap_compile ()
+may require a network mask for certain expressions in the filter string;
+.BR pcap_lookupnet ()
+can be used to find the network address and network mask for a given
+capture device.
+.PP
+A compiled filter can also be applied directly to a packet that has been
+read using
+.BR pcap_offline_filter ().
+.TP
+.B Routines
+.RS
+.TP
+.BR pcap_compile (3PCAP)
+compile filter expression to a pseudo-machine-language code program
+.TP
+.BR pcap_freecode (3PCAP)
+free a filter program
+.TP
+.BR pcap_setfilter (3PCAP)
+set filter for a
+.B pcap_t
+.TP
+.BR pcap_lookupnet (3PCAP)
+get network address and network mask for a capture device
+.TP
+.BR pcap_offline_filter (3PCAP)
+apply a filter program to a packet
+.RE
+.SS Incoming and outgoing packets
+By default, libpcap will attempt to capture both packets sent by the
+machine and packets received by the machine.  To limit it to capturing
+only packets received by the machine or, if possible, only packets sent
+by the machine, call
+.BR pcap_setdirection ().
+.TP
+.BR Routines
+.RS
+.TP
+.BR pcap_setdirection (3PCAP)
+specify whether to capture incoming packets, outgoing packets, or both
+.RE
+.SS Capture statistics
+To get statistics about packets received and dropped in a live capture,
+call
+.BR pcap_stats ().
+.TP
+.B Routines
+.RS
+.TP
+.BR pcap_stats (3PCAP)
+get capture statistics
+.RE
+.SS Opening a handle for writing captured packets
+To open a ``savefile`` to which to write packets, given the pathname the
+``savefile'' should have, call
+.BR pcap_dump_open ().
+To open a ``savefile`` to which to write packets, given the pathname the
+``savefile'' should have, call
+.BR pcap_dump_open ();
+to set up a handle for a ``savefile'', given a
+.B "FILE\ *"
+referring to a file already opened for writing, call
+.BR pcap_dump_fopen ().
+They each return pointers to a
+.BR pcap_dumper_t ,
+which is the handle used for writing packets to the ``savefile''.  If it
+succeeds, it will have created the file if it doesn't exist and
+truncated the file if it does exist.
+To close a
+.BR pcap_dumper_t ,
+call
+.BR pcap_dump_close ().
+.TP
+.B Routines
+.RS
+.TP
+.BR pcap_dump_open (3PCAP)
+open a
+.B pcap_dumper_t
+for a ``savefile``, given a pathname
+.TP
+.BR pcap_dump_fopen (3PCAP)
+open a
+.B pcap_dumper_t
+for a ``savefile``, given a
+.B "FILE\ *"
+.TP
+.BR pcap_dump_close (3PCAP)
+close a
+.B pcap_dumper_t
+.TP
+.BR pcap_dump_file (3PCAP)
+get the
+.B "FILE\ *"
+for a
+.B pcap_dumper_t
+opened for a ``savefile''
+.RE
+.SS Writing packets
+To write a packet to a
+.BR pcap_dumper_t ,
+call
+.BR pcap_dump ().
+Packets written with
+.BR pcap_dump ()
+may be buffered, rather than being immediately written to the
+``savefile''.  Closing the
+.B pcap_dumper_t
+will cause all buffered-but-not-yet-written packets to be written to the
+``savefile''.
+To force all packets written to the
+.BR pcap_dumper_t ,
+and not yet written to the ``savefile'' because they're buffered by the
+.BR pcap_dumper_t ,
+to be written to the ``savefile'', without closing the
+.BR pcap_dumper_t ,
+call
+.BR pcap_dump_flush ().
+.TP
+.B Routines
+.RS
+.TP
+.BR pcap_dump (3PCAP)
+write packet to a
+.B pcap_dumper_t
+.TP
+.BR pcap_dump_flush (3PCAP)
+flush buffered packets written to a
+.B pcap_dumper_t
+to the ``savefile''
+.TP
+.BR pcap_dump_ftell (3PCAP)
+get current file position for a
+.B pcap_dumper_t
+.RE
+.SS Injecting packets
+If you have the required privileges, you can inject packets onto a
+network with a
+.B pcap_t
+for a live capture, using
+.BR pcap_inject ()
+or
+.BR pcap_sendpacket ().
+(The two routines exist for compatibility with both OpenBSD and WinPcap;
+they perform the same function, but have different return values.)
+.TP
+.B Routines
+.RS
+.TP
+.BR pcap_inject (3PCAP)
+.PD 0
+.TP
+.BR pcap_sendpacket (3PCAP)
+transmit a packet
+.PD
+.RE
+.SS Reporting errors
+Some routines return error or warning status codes; to convert them to a
+string, use
+.BR pcap_statustostr ().
+.TP
+.B Routines
+.RS
+.TP
+.BR pcap_statustostr (3PCAP)
+get a string for an error or warning status code
+.RE
+.SS Getting library version information
+To get a string giving version information about libpcap, call
+.BR pcap_lib_version ().
+.TP
+.B Routines
+.RS
+.TP
+.BR pcap_lib_version (3PCAP)
+get library version string
+.RE
+.SH BACKWARDS COMPATIBILITY
+.PP
+In versions of libpcap prior to 1.0, the
+.B pcap.h
+header file was not in a
+.B pcap
+directory on most platforms; if you are writing an application that must
+work on versions of libpcap prior to 1.0, include
+.BR <pcap.h> ,
+which will include
+.B <pcap/pcap.h>
+for you, rather than including
+.BR <pcap/pcap.h> .
+.PP
+.BR pcap_create ()
+and
+.BR pcap_activate ()
+were not available in versions of libpcap prior to 1.0; if you are
+writing an application that must work on versions of libpcap prior to
+1.0, either use
+.BR pcap_open_live ()
+to get a handle for a live capture or, if you want to be able to use the
+additional capabilities offered by using
+.BR pcap_create ()
+and
+.BR pcap_activate (),
+use an
+.BR autoconf (1)
+script or some other configuration script to check whether the libpcap
+1.0 APIs are available and use them only if they are.
+.SH SEE ALSO
+autoconf(1), tcpdump(1), tcpslice(1), pcap-filter(7), pfconfig(8),
+usermod(1M)
+.SH AUTHORS
+The original authors of libpcap are:
+.LP
+Van Jacobson,
+Craig Leres and
+Steven McCanne, all of the
+Lawrence Berkeley National Laboratory, University of California, Berkeley, CA.
+.LP
+The current version is available from "The Tcpdump Group"'s Web site at
+.LP
+.RS
+.I http://www.tcpdump.org/
+.RE
+.SH BUGS
+Please send problems, bugs, questions, desirable enhancements, etc. to:
+.LP
+.RS
+tcpdump-workers@lists.tcpdump.org
+.RE
diff --git a/pcap.3pcap.in b/pcap.3pcap.in
index c02ac43..93478f1 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 "16 April 2014"
+.TH PCAP 3PCAP "8 March 2015"
 .SH NAME
 pcap \- Packet Capture library
 .SH SYNOPSIS
diff --git a/pcap.c b/pcap.c
index 4e9c94a..77a709f 100644
--- a/pcap.c
+++ b/pcap.c
@@ -35,9 +35,9 @@
 #include "config.h"
 #endif
 
-#ifdef WIN32
+#ifdef _WIN32
 #include <pcap-stdinc.h>
-#else /* WIN32 */
+#else /* _WIN32 */
 #if HAVE_INTTYPES_H
 #include <inttypes.h>
 #elif HAVE_STDINT_H
@@ -47,7 +47,7 @@
 #include <sys/bitypes.h>
 #endif
 #include <sys/types.h>
-#endif /* WIN32 */
+#endif /* _WIN32 */
 
 #include <stdio.h>
 #include <stdlib.h>
@@ -80,6 +80,10 @@
 #include "pcap-snf.h"
 #endif /* HAVE_SNF_API */
 
+#ifdef HAVE_TC_API
+#include "pcap-tc.h"
+#endif /* HAVE_TC_API */
+
 #ifdef PCAP_SUPPORT_USB
 #include "pcap-usb-linux.h"
 #endif
@@ -92,14 +96,6 @@
 #include "pcap-bt-monitor-linux.h"
 #endif
 
-#ifdef PCAP_SUPPORT_CAN
-#include "pcap-can-linux.h"
-#endif
-
-#ifdef PCAP_SUPPORT_CANUSB
-#include "pcap-canusb-linux.h"
-#endif
-
 #ifdef PCAP_SUPPORT_NETFILTER
 #include "pcap-netfilter-linux.h"
 #endif
@@ -108,17 +104,46 @@
 #include "pcap-dbus.h"
 #endif
 
-int
-pcap_not_initialized(pcap_t *pcap _U_)
+static int
+pcap_not_initialized(pcap_t *pcap)
 {
+	/* in case the caller doesn't check for PCAP_ERROR_NOT_ACTIVATED */
+	(void)pcap_snprintf(pcap->errbuf, sizeof(pcap->errbuf),
+	    "This handle hasn't been activated yet");
 	/* this means 'not initialized' */
 	return (PCAP_ERROR_NOT_ACTIVATED);
 }
 
-#ifdef WIN32
-Adapter *
-pcap_no_adapter(pcap_t *pcap _U_)
+#ifdef _WIN32
+static void *
+pcap_not_initialized_ptr(pcap_t *pcap)
 {
+	(void)pcap_snprintf(pcap->errbuf, sizeof(pcap->errbuf),
+	    "This handle hasn't been activated yet");
+	return (NULL);
+}
+
+static HANDLE
+pcap_getevent_not_initialized(pcap_t *pcap)
+{
+	(void)pcap_snprintf(pcap->errbuf, sizeof(pcap->errbuf),
+	    "This handle hasn't been activated yet");
+	return (INVALID_HANDLE_VALUE);
+}
+
+static u_int
+pcap_sendqueue_transmit_not_initialized(pcap_t *pcap, pcap_send_queue* queue, int sync)
+{
+	(void)pcap_snprintf(pcap->errbuf, sizeof(pcap->errbuf),
+	    "This handle hasn't been activated yet");
+	return (0);
+}
+
+static PAirpcapHandle
+pcap_get_airpcap_handle_not_initialized(pcap_t *pcap)
+{
+	(void)pcap_snprintf(pcap->errbuf, sizeof(pcap->errbuf),
+	    "This handle hasn't been activated yet");
 	return (NULL);
 }
 #endif
@@ -165,7 +190,7 @@
 		*tstamp_typesp = (int*)calloc(sizeof(**tstamp_typesp),
 		    p->tstamp_type_count);
 		if (*tstamp_typesp == NULL) {
-			(void)snprintf(p->errbuf, sizeof(p->errbuf),
+			(void)pcap_snprintf(p->errbuf, sizeof(p->errbuf),
 			    "malloc: %s", pcap_strerror(errno));
 			return (PCAP_ERROR);
 		}
@@ -270,47 +295,7 @@
 	return (p->read_op(p, 1, p->oneshot_callback, (u_char *)&s));
 }
 
-#if defined(DAG_ONLY)
-int
-pcap_findalldevs(pcap_if_t **alldevsp, char *errbuf)
-{
-	return (dag_findalldevs(alldevsp, errbuf));
-}
-
-pcap_t *
-pcap_create(const char *source, char *errbuf)
-{
-	int is_ours;
-	return (dag_create(source, errbuf, &is_ours));
-}
-#elif defined(SEPTEL_ONLY)
-int
-pcap_findalldevs(pcap_if_t **alldevsp, char *errbuf)
-{
-	return (septel_findalldevs(alldevsp, errbuf));
-}
-
-pcap_t *
-pcap_create(const char *source, char *errbuf)
-{
-	int is_ours;
-	return (septel_create(source, errbuf, &is_ours));
-}
-#elif defined(SNF_ONLY)
-int
-pcap_findalldevs(pcap_if_t **alldevsp, char *errbuf)
-{
-	return (snf_findalldevs(alldevsp, errbuf));
-}
-
-pcap_t *
-pcap_create(const char *source, char *errbuf)
-{
-	int is_ours;
-	return (snf_create(source, errbuf, &is_ours));
-}
-#else /* regular pcap */
-struct capture_source_type {
+static struct capture_source_type {
 	int (*findalldevs_op)(pcap_if_t **, char *);
 	pcap_t *(*create_op)(const char *, char *, int *);
 } capture_source_types[] = {
@@ -323,18 +308,15 @@
 #ifdef HAVE_SNF_API
 	{ snf_findalldevs, snf_create },
 #endif
+#ifdef HAVE_TC_API
+	{ TcFindAllDevs, TcCreate },
+#endif
 #ifdef PCAP_SUPPORT_BT
 	{ bt_findalldevs, bt_create },
 #endif
 #ifdef PCAP_SUPPORT_BT_MONITOR
 	{ bt_monitor_findalldevs, bt_monitor_create },
 #endif
-#if PCAP_SUPPORT_CANUSB
-	{ canusb_findalldevs, canusb_create },
-#endif
-#ifdef PCAP_SUPPORT_CAN
-	{ can_findalldevs, can_create },
-#endif
 #ifdef PCAP_SUPPORT_USB
 	{ usb_findalldevs, usb_create },
 #endif
@@ -359,26 +341,11 @@
 	size_t i;
 
 	/*
-	 * Get the list of regular interfaces first.
+	 * Find all the local network interfaces on which we
+	 * can capture.
 	 */
-	if (pcap_findalldevs_interfaces(alldevsp, errbuf) == -1)
-		return (-1);	/* failure */
-
-	/*
-	 * Add any interfaces that need a platform-specific mechanism
-	 * to find.
-	 */
-	if (pcap_platform_finddevs(alldevsp, errbuf) == -1) {
-		/*
-		 * We had an error; free the list we've been
-		 * constructing.
-		 */
-		if (*alldevsp != NULL) {
-			pcap_freealldevs(*alldevsp);
-			*alldevsp = NULL;
-		}
+	if (pcap_platform_finddevs(alldevsp, errbuf) == -1)
 		return (-1);
-	}
 
 	/*
 	 * Ask each of the non-local-network-interface capture
@@ -402,21 +369,53 @@
 }
 
 pcap_t *
-pcap_create(const char *source, char *errbuf)
+pcap_create(const char *device, char *errbuf)
 {
 	size_t i;
 	int is_theirs;
 	pcap_t *p;
+	char *device_str;
 
 	/*
-	 * A null source name is equivalent to the "any" device -
+	 * A null device name is equivalent to the "any" device -
 	 * which might not be supported on this platform, but
 	 * this means that you'll get a "not supported" error
 	 * rather than, say, a crash when we try to dereference
 	 * the null pointer.
 	 */
-	if (source == NULL)
-		source = "any";
+	if (device == NULL)
+		device_str = strdup("any");
+	else {
+#ifdef _WIN32
+		/*
+		 * If the string appears to be little-endian UCS-2/UTF-16,
+		 * convert it to ASCII.
+		 *
+		 * XXX - to UTF-8 instead?  Or report an error if any
+		 * character isn't ASCII?
+		 */
+		if (device[0] != '\0' && device[1] == '\0') {
+			size_t length;
+
+			length = wcslen((wchar_t *)device);
+			device_str = (char *)malloc(length + 1);
+			if (device_str == NULL) {
+				pcap_snprintf(errbuf, PCAP_ERRBUF_SIZE,
+				    "malloc: %s", pcap_strerror(errno));
+				return (NULL);
+			}
+
+			pcap_snprintf(device_str, length + 1, "%ws",
+			    (const wchar_t *)device);
+		} else
+#endif
+			device_str = strdup(device);
+	}
+	if (device_str == NULL) {
+		pcap_snprintf(errbuf, PCAP_ERRBUF_SIZE,
+		    "malloc: %s", pcap_strerror(errno));
+		return (NULL);
+	}
 
 	/*
 	 * Try each of the non-local-network-interface capture
@@ -425,7 +424,8 @@
 	 */
 	for (i = 0; capture_source_types[i].create_op != NULL; i++) {
 		is_theirs = 0;
-		p = capture_source_types[i].create_op(source, errbuf, &is_theirs);
+		p = capture_source_types[i].create_op(device_str, errbuf,
+		    &is_theirs);
 		if (is_theirs) {
 			/*
 			 * The device name refers to a device of the
@@ -436,6 +436,14 @@
 			 * should return that to report the failure
 			 * to create.
 			 */
+			if (p == NULL) {
+				/*
+				 * We assume the caller filled in errbuf.
+				 */
+				free(device_str);
+				return (NULL);
+			}
+			p->opt.device = device_str;
 			return (p);
 		}
 	}
@@ -443,9 +451,17 @@
 	/*
 	 * OK, try it as a regular network interface.
 	 */
-	return (pcap_create_interface(source, errbuf));
+	p = pcap_create_interface(device_str, errbuf);
+	if (p == NULL) {
+		/*
+		 * We assume the caller filled in errbuf.
+		 */
+		free(device_str);
+		return (NULL);
+	}
+	p->opt.device = device_str;
+	return (p);
 }
-#endif
 
 static void
 initialize_ops(pcap_t *p)
@@ -463,11 +479,19 @@
 	p->getnonblock_op = (getnonblock_op_t)pcap_not_initialized;
 	p->setnonblock_op = (setnonblock_op_t)pcap_not_initialized;
 	p->stats_op = (stats_op_t)pcap_not_initialized;
-#ifdef WIN32
+#ifdef _WIN32
+	p->stats_ex_op = (stats_ex_op_t)pcap_not_initialized_ptr;
 	p->setbuff_op = (setbuff_op_t)pcap_not_initialized;
 	p->setmode_op = (setmode_op_t)pcap_not_initialized;
 	p->setmintocopy_op = (setmintocopy_op_t)pcap_not_initialized;
-	p->getadapter_op = pcap_no_adapter;
+	p->getevent_op = pcap_getevent_not_initialized;
+	p->oid_get_request_op = (oid_get_request_op_t)pcap_not_initialized;
+	p->oid_set_request_op = (oid_set_request_op_t)pcap_not_initialized;
+	p->sendqueue_transmit_op = pcap_sendqueue_transmit_not_initialized;
+	p->setuserbuffer_op = (setuserbuffer_op_t)pcap_not_initialized;
+	p->live_dump_op = (live_dump_op_t)pcap_not_initialized;
+	p->live_dump_ended_op = (live_dump_ended_op_t)pcap_not_initialized;
+	p->get_airpcap_handle_op = pcap_get_airpcap_handle_not_initialized;
 #endif
 
 	/*
@@ -498,7 +522,7 @@
 	 */
 	chunk = malloc(sizeof (pcap_t) + size);
 	if (chunk == NULL) {
-		snprintf(ebuf, PCAP_ERRBUF_SIZE, "malloc: %s",
+		pcap_snprintf(ebuf, PCAP_ERRBUF_SIZE, "malloc: %s",
 		    pcap_strerror(errno));
 		return (NULL);
 	}
@@ -509,7 +533,7 @@
 	 */
 	p = (pcap_t *)chunk;
 
-#ifndef WIN32
+#ifndef _WIN32
 	p->fd = -1;	/* not opened yet */
 	p->selectable_fd = -1;
 #endif
@@ -529,7 +553,7 @@
 }
 
 pcap_t *
-pcap_create_common(const char *source, char *ebuf, size_t size)
+pcap_create_common(char *ebuf, size_t size)
 {
 	pcap_t *p;
 
@@ -537,14 +561,6 @@
 	if (p == NULL)
 		return (NULL);
 
-	p->opt.source = strdup(source);
-	if (p->opt.source == NULL) {
-		snprintf(ebuf, PCAP_ERRBUF_SIZE, "malloc: %s",
-		    pcap_strerror(errno));
-		free(p);
-		return (NULL);
-	}
-
 	/*
 	 * Default to "can't set rfmon mode"; if it's supported by
 	 * a platform, the create routine that called us can set
@@ -556,9 +572,9 @@
 	initialize_ops(p);
 
 	/* put in some defaults*/
- 	pcap_set_snaplen(p, MAXIMUM_SNAPLEN);	/* max packet size */
-	p->opt.timeout = 0;			/* no timeout specified */
-	p->opt.buffer_size = 0;			/* use the platform's default */
+ 	p->snapshot = MAXIMUM_SNAPLEN;	/* max packet size */
+	p->opt.timeout = 0;		/* no timeout specified */
+	p->opt.buffer_size = 0;		/* use the platform's default */
 	p->opt.promisc = 0;
 	p->opt.rfmon = 0;
 	p->opt.immediate = 0;
@@ -577,7 +593,7 @@
 pcap_check_activated(pcap_t *p)
 {
 	if (p->activated) {
-		snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "can't perform "
+		pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "can't perform "
 			" operation on activated capture");
 		return (-1);
 	}
@@ -589,6 +605,16 @@
 {
 	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);
 }
@@ -629,6 +655,13 @@
 		return (PCAP_ERROR_ACTIVATED);
 
 	/*
+	 * The argument should have been u_int, but that's too late
+	 * to change now - it's an API.
+	 */
+	if (tstamp_type < 0)
+		return (PCAP_WARNING_TSTAMP_TYPE_NOTSUP);
+
+	/*
 	 * If p->tstamp_type_count is 0, we only support PCAP_TSTAMP_HOST;
 	 * the default time stamp type is PCAP_TSTAMP_HOST.
 	 */
@@ -642,7 +675,7 @@
 		 * Check whether we claim to support this type of time stamp.
 		 */
 		for (i = 0; i < p->tstamp_type_count; i++) {
-			if (p->tstamp_type_list[i] == tstamp_type) {
+			if (p->tstamp_type_list[i] == (u_int)tstamp_type) {
 				/*
 				 * Yes.
 				 */
@@ -672,6 +705,12 @@
 {
 	if (pcap_check_activated(p))
 		return (PCAP_ERROR_ACTIVATED);
+	if (buffer_size <= 0) {
+		/*
+		 * Silently ignore invalid values.
+		 */
+		return (0);
+	}
 	p->opt.buffer_size = buffer_size;
 	return (0);
 }
@@ -685,6 +724,13 @@
 		return (PCAP_ERROR_ACTIVATED);
 
 	/*
+	 * The argument should have been u_int, but that's too late
+	 * to change now - it's an API.
+	 */
+	if (tstamp_precision < 0)
+		return (PCAP_ERROR_TSTAMP_PRECISION_NOTSUP);
+
+	/*
 	 * If p->tstamp_precision_count is 0, we only support setting
 	 * the time stamp precision to microsecond precision; every
 	 * pcap module *MUST* support microsecond precision, even if
@@ -702,7 +748,7 @@
 		 * time stamp.
 		 */
 		for (i = 0; i < p->tstamp_precision_count; i++) {
-			if (p->tstamp_precision_list[i] == tstamp_precision) {
+			if (p->tstamp_precision_list[i] == (u_int)tstamp_precision) {
 				/*
 				 * Yes.
 				 */
@@ -749,7 +795,7 @@
 			 * handle errors other than PCAP_ERROR, return the
 			 * error message corresponding to the status.
 			 */
-			snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "%s",
+			pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "%s",
 			    pcap_statustostr(status));
 		}
 
@@ -763,12 +809,12 @@
 }
 
 pcap_t *
-pcap_open_live(const char *source, int snaplen, int promisc, int to_ms, char *errbuf)
+pcap_open_live(const char *device, int snaplen, int promisc, int to_ms, char *errbuf)
 {
 	pcap_t *p;
 	int status;
 
-	p = pcap_create(source, errbuf);
+	p = pcap_create(device, errbuf);
 	if (p == NULL)
 		return (NULL);
 	status = pcap_set_snaplen(p, snaplen);
@@ -797,15 +843,15 @@
 	return (p);
 fail:
 	if (status == PCAP_ERROR)
-		snprintf(errbuf, PCAP_ERRBUF_SIZE, "%s: %s", source,
+		pcap_snprintf(errbuf, PCAP_ERRBUF_SIZE, "%s: %s", device,
 		    p->errbuf);
 	else if (status == PCAP_ERROR_NO_SUCH_DEVICE ||
 	    status == PCAP_ERROR_PERM_DENIED ||
 	    status == PCAP_ERROR_PROMISC_PERM_DENIED)
-		snprintf(errbuf, PCAP_ERRBUF_SIZE, "%s: %s (%s)", source,
+		pcap_snprintf(errbuf, PCAP_ERRBUF_SIZE, "%s: %s (%s)", device,
 		    pcap_statustostr(status), p->errbuf);
 	else
-		snprintf(errbuf, PCAP_ERRBUF_SIZE, "%s: %s", source,
+		pcap_snprintf(errbuf, PCAP_ERRBUF_SIZE, "%s: %s", device,
 		    pcap_statustostr(status));
 	pcap_close(p);
 	return (NULL);
@@ -821,13 +867,6 @@
 		return (NULL);
 
 	p->opt.tstamp_precision = PCAP_TSTAMP_PRECISION_MICRO;
-	p->opt.source = strdup("(savefile)");
-	if (p->opt.source == NULL) {
-		snprintf(ebuf, PCAP_ERRBUF_SIZE, "malloc: %s",
-		    pcap_strerror(errno));
-		free(p);
-		return (NULL);
-	}
 
 	return (p);
 }
@@ -838,16 +877,6 @@
 	return (p->read_op(p, cnt, callback, user));
 }
 
-/*
- * XXX - is this necessary?
- */
-int
-pcap_read(pcap_t *p, int cnt, pcap_handler callback, u_char *user)
-{
-
-	return (p->read_op(p, cnt, callback, user));
-}
-
 int
 pcap_loop(pcap_t *p, int cnt, pcap_handler callback, u_char *user)
 {
@@ -917,7 +946,7 @@
 		 */
 		*dlt_buffer = (int*)malloc(sizeof(**dlt_buffer));
 		if (*dlt_buffer == NULL) {
-			(void)snprintf(p->errbuf, sizeof(p->errbuf),
+			(void)pcap_snprintf(p->errbuf, sizeof(p->errbuf),
 			    "malloc: %s", pcap_strerror(errno));
 			return (PCAP_ERROR);
 		}
@@ -926,7 +955,7 @@
 	} else {
 		*dlt_buffer = (int*)calloc(sizeof(**dlt_buffer), p->dlt_count);
 		if (*dlt_buffer == NULL) {
-			(void)snprintf(p->errbuf, sizeof(p->errbuf),
+			(void)pcap_snprintf(p->errbuf, sizeof(p->errbuf),
 			    "malloc: %s", pcap_strerror(errno));
 			return (PCAP_ERROR);
 		}
@@ -959,6 +988,9 @@
 	int i;
 	const char *dlt_name;
 
+	if (dlt < 0)
+		goto unsupported;
+
 	if (p->dlt_count == 0 || p->set_datalink_op == NULL) {
 		/*
 		 * We couldn't fetch the list of DLTs, or we don't
@@ -976,7 +1008,7 @@
 		return (0);
 	}
 	for (i = 0; i < p->dlt_count; i++)
-		if (p->dlt_list[i] == dlt)
+		if (p->dlt_list[i] == (u_int)dlt)
 			break;
 	if (i >= p->dlt_count)
 		goto unsupported;
@@ -1004,11 +1036,11 @@
 unsupported:
 	dlt_name = pcap_datalink_val_to_name(dlt);
 	if (dlt_name != NULL) {
-		(void) snprintf(p->errbuf, sizeof(p->errbuf),
+		(void) pcap_snprintf(p->errbuf, sizeof(p->errbuf),
 		    "%s is not one of the DLTs supported by this device",
 		    dlt_name);
 	} else {
-		(void) snprintf(p->errbuf, sizeof(p->errbuf),
+		(void) pcap_snprintf(p->errbuf, sizeof(p->errbuf),
 		    "DLT %d is not one of the DLTs supported by this device",
 		    dlt);
 	}
@@ -1106,133 +1138,139 @@
 	int	dlt;
 };
 
-#define DLT_CHOICE(code, description) { #code, description, code }
+#define DLT_CHOICE(code, description) { #code, description, DLT_ ## code }
 #define DLT_CHOICE_SENTINEL { NULL, NULL, 0 }
 
 static struct dlt_choice dlt_choices[] = {
-	DLT_CHOICE(DLT_NULL, "BSD loopback"),
-	DLT_CHOICE(DLT_EN10MB, "Ethernet"),
-	DLT_CHOICE(DLT_IEEE802, "Token ring"),
-	DLT_CHOICE(DLT_ARCNET, "BSD ARCNET"),
-	DLT_CHOICE(DLT_SLIP, "SLIP"),
-	DLT_CHOICE(DLT_PPP, "PPP"),
-	DLT_CHOICE(DLT_FDDI, "FDDI"),
-	DLT_CHOICE(DLT_ATM_RFC1483, "RFC 1483 LLC-encapsulated ATM"),
-	DLT_CHOICE(DLT_RAW, "Raw IP"),
-	DLT_CHOICE(DLT_SLIP_BSDOS, "BSD/OS SLIP"),
-	DLT_CHOICE(DLT_PPP_BSDOS, "BSD/OS PPP"),
-	DLT_CHOICE(DLT_ATM_CLIP, "Linux Classical IP-over-ATM"),
-	DLT_CHOICE(DLT_PPP_SERIAL, "PPP over serial"),
-	DLT_CHOICE(DLT_PPP_ETHER, "PPPoE"),
-        DLT_CHOICE(DLT_SYMANTEC_FIREWALL, "Symantec Firewall"),
-	DLT_CHOICE(DLT_C_HDLC, "Cisco HDLC"),
-	DLT_CHOICE(DLT_IEEE802_11, "802.11"),
-	DLT_CHOICE(DLT_FRELAY, "Frame Relay"),
-	DLT_CHOICE(DLT_LOOP, "OpenBSD loopback"),
-	DLT_CHOICE(DLT_ENC, "OpenBSD encapsulated IP"),
-	DLT_CHOICE(DLT_LINUX_SLL, "Linux cooked"),
-	DLT_CHOICE(DLT_LTALK, "Localtalk"),
-	DLT_CHOICE(DLT_PFLOG, "OpenBSD pflog file"),
-	DLT_CHOICE(DLT_PFSYNC, "Packet filter state syncing"),
-	DLT_CHOICE(DLT_PRISM_HEADER, "802.11 plus Prism header"),
-	DLT_CHOICE(DLT_IP_OVER_FC, "RFC 2625 IP-over-Fibre Channel"),
-	DLT_CHOICE(DLT_SUNATM, "Sun raw ATM"),
-	DLT_CHOICE(DLT_IEEE802_11_RADIO, "802.11 plus radiotap header"),
-	DLT_CHOICE(DLT_ARCNET_LINUX, "Linux ARCNET"),
-        DLT_CHOICE(DLT_JUNIPER_MLPPP, "Juniper Multi-Link PPP"),
-	DLT_CHOICE(DLT_JUNIPER_MLFR, "Juniper Multi-Link Frame Relay"),
-        DLT_CHOICE(DLT_JUNIPER_ES, "Juniper Encryption Services PIC"),
-        DLT_CHOICE(DLT_JUNIPER_GGSN, "Juniper GGSN PIC"),
-	DLT_CHOICE(DLT_JUNIPER_MFR, "Juniper FRF.16 Frame Relay"),
-        DLT_CHOICE(DLT_JUNIPER_ATM2, "Juniper ATM2 PIC"),
-        DLT_CHOICE(DLT_JUNIPER_SERVICES, "Juniper Advanced Services PIC"),
-        DLT_CHOICE(DLT_JUNIPER_ATM1, "Juniper ATM1 PIC"),
-	DLT_CHOICE(DLT_APPLE_IP_OVER_IEEE1394, "Apple IP-over-IEEE 1394"),
-	DLT_CHOICE(DLT_MTP2_WITH_PHDR, "SS7 MTP2 with Pseudo-header"),
-	DLT_CHOICE(DLT_MTP2, "SS7 MTP2"),
-	DLT_CHOICE(DLT_MTP3, "SS7 MTP3"),
-	DLT_CHOICE(DLT_SCCP, "SS7 SCCP"),
-	DLT_CHOICE(DLT_DOCSIS, "DOCSIS"),
-	DLT_CHOICE(DLT_LINUX_IRDA, "Linux IrDA"),
-	DLT_CHOICE(DLT_IEEE802_11_RADIO_AVS, "802.11 plus AVS radio information header"),
-        DLT_CHOICE(DLT_JUNIPER_MONITOR, "Juniper Passive Monitor PIC"),
-	DLT_CHOICE(DLT_BACNET_MS_TP, "BACnet MS/TP"),
-	DLT_CHOICE(DLT_PPP_PPPD, "PPP for pppd, with direction flag"),
-	DLT_CHOICE(DLT_JUNIPER_PPPOE, "Juniper PPPoE"),
-	DLT_CHOICE(DLT_JUNIPER_PPPOE_ATM, "Juniper PPPoE/ATM"),
-	DLT_CHOICE(DLT_GPRS_LLC, "GPRS LLC"),
-	DLT_CHOICE(DLT_GPF_T, "GPF-T"),
-	DLT_CHOICE(DLT_GPF_F, "GPF-F"),
-	DLT_CHOICE(DLT_JUNIPER_PIC_PEER, "Juniper PIC Peer"),
-	DLT_CHOICE(DLT_ERF_ETH,	"Ethernet with Endace ERF header"),
-	DLT_CHOICE(DLT_ERF_POS, "Packet-over-SONET with Endace ERF header"),
-	DLT_CHOICE(DLT_LINUX_LAPD, "Linux vISDN LAPD"),
-	DLT_CHOICE(DLT_JUNIPER_ETHER, "Juniper Ethernet"),
-	DLT_CHOICE(DLT_JUNIPER_PPP, "Juniper PPP"),
-	DLT_CHOICE(DLT_JUNIPER_FRELAY, "Juniper Frame Relay"),
-	DLT_CHOICE(DLT_JUNIPER_CHDLC, "Juniper C-HDLC"),
-	DLT_CHOICE(DLT_MFR, "FRF.16 Frame Relay"),
-	DLT_CHOICE(DLT_JUNIPER_VP, "Juniper Voice PIC"),
-	DLT_CHOICE(DLT_A429, "Arinc 429"),
-	DLT_CHOICE(DLT_A653_ICM, "Arinc 653 Interpartition Communication"),
-	DLT_CHOICE(DLT_USB, "USB"),
-	DLT_CHOICE(DLT_BLUETOOTH_HCI_H4, "Bluetooth HCI UART transport layer"),
-	DLT_CHOICE(DLT_IEEE802_16_MAC_CPS, "IEEE 802.16 MAC Common Part Sublayer"),
-	DLT_CHOICE(DLT_USB_LINUX, "USB with Linux header"),
-	DLT_CHOICE(DLT_CAN20B, "Controller Area Network (CAN) v. 2.0B"),
-	DLT_CHOICE(DLT_IEEE802_15_4_LINUX, "IEEE 802.15.4 with Linux padding"),
-	DLT_CHOICE(DLT_PPI, "Per-Packet Information"),
-	DLT_CHOICE(DLT_IEEE802_16_MAC_CPS_RADIO, "IEEE 802.16 MAC Common Part Sublayer plus radiotap header"),
-	DLT_CHOICE(DLT_JUNIPER_ISM, "Juniper Integrated Service Module"),
-	DLT_CHOICE(DLT_IEEE802_15_4, "IEEE 802.15.4 with FCS"),
-	DLT_CHOICE(DLT_SITA, "SITA pseudo-header"),
-	DLT_CHOICE(DLT_ERF, "Endace ERF header"),
-	DLT_CHOICE(DLT_RAIF1, "Ethernet with u10 Networks pseudo-header"),
-	DLT_CHOICE(DLT_IPMB, "IPMB"),
-	DLT_CHOICE(DLT_JUNIPER_ST, "Juniper Secure Tunnel"),
-	DLT_CHOICE(DLT_BLUETOOTH_HCI_H4_WITH_PHDR, "Bluetooth HCI UART transport layer plus pseudo-header"),
-	DLT_CHOICE(DLT_AX25_KISS, "AX.25 with KISS header"),
-	DLT_CHOICE(DLT_IEEE802_15_4_NONASK_PHY, "IEEE 802.15.4 with non-ASK PHY data"),
-	DLT_CHOICE(DLT_MPLS, "MPLS with label as link-layer header"),
-	DLT_CHOICE(DLT_LINUX_EVDEV, "Linux evdev events"),
-	DLT_CHOICE(DLT_USB_LINUX_MMAPPED, "USB with padded Linux header"),
-	DLT_CHOICE(DLT_DECT, "DECT"),
-	DLT_CHOICE(DLT_AOS, "AOS Space Data Link protocol"),
-	DLT_CHOICE(DLT_WIHART, "Wireless HART"),
-	DLT_CHOICE(DLT_FC_2, "Fibre Channel FC-2"),
-	DLT_CHOICE(DLT_FC_2_WITH_FRAME_DELIMS, "Fibre Channel FC-2 with frame delimiters"),
-	DLT_CHOICE(DLT_IPNET, "Solaris ipnet"),
-	DLT_CHOICE(DLT_CAN_SOCKETCAN, "CAN-bus with SocketCAN headers"),
-	DLT_CHOICE(DLT_IPV4, "Raw IPv4"),
-	DLT_CHOICE(DLT_IPV6, "Raw IPv6"),
-	DLT_CHOICE(DLT_IEEE802_15_4_NOFCS, "IEEE 802.15.4 without FCS"),
-	DLT_CHOICE(DLT_DBUS, "D-Bus"),
-	DLT_CHOICE(DLT_JUNIPER_VS, "Juniper Virtual Server"),
-	DLT_CHOICE(DLT_JUNIPER_SRX_E2E, "Juniper SRX E2E"),
-	DLT_CHOICE(DLT_JUNIPER_FIBRECHANNEL, "Juniper Fibre Channel"),
-	DLT_CHOICE(DLT_DVB_CI, "DVB-CI"),
-	DLT_CHOICE(DLT_MUX27010, "MUX27010"),
-	DLT_CHOICE(DLT_STANAG_5066_D_PDU, "STANAG 5066 D_PDUs"),
-	DLT_CHOICE(DLT_JUNIPER_ATM_CEMIC, "Juniper ATM CEMIC"),
-	DLT_CHOICE(DLT_NFLOG, "Linux netfilter log messages"),
-	DLT_CHOICE(DLT_NETANALYZER, "Ethernet with Hilscher netANALYZER pseudo-header"),
-	DLT_CHOICE(DLT_NETANALYZER_TRANSPARENT, "Ethernet with Hilscher netANALYZER pseudo-header and with preamble and SFD"),
-	DLT_CHOICE(DLT_IPOIB, "RFC 4391 IP-over-Infiniband"),
-	DLT_CHOICE(DLT_MPEG_2_TS, "MPEG-2 transport stream"),
-	DLT_CHOICE(DLT_NG40, "ng40 protocol tester Iub/Iur"),
-	DLT_CHOICE(DLT_NFC_LLCP, "NFC LLCP PDUs with pseudo-header"),
-	DLT_CHOICE(DLT_INFINIBAND, "InfiniBand"),
-	DLT_CHOICE(DLT_SCTP, "SCTP"),
-	DLT_CHOICE(DLT_USBPCAP, "USB with USBPcap header"),
-	DLT_CHOICE(DLT_RTAC_SERIAL, "Schweitzer Engineering Laboratories RTAC packets"),
-	DLT_CHOICE(DLT_BLUETOOTH_LE_LL, "Bluetooth Low Energy air interface"),
-	DLT_CHOICE(DLT_NETLINK, "Linux netlink"),
-	DLT_CHOICE(DLT_BLUETOOTH_LINUX_MONITOR, "Bluetooth Linux Monitor"),
-	DLT_CHOICE(DLT_BLUETOOTH_BREDR_BB, "Bluetooth Basic Rate/Enhanced Data Rate baseband packets"),
-	DLT_CHOICE(DLT_BLUETOOTH_LE_LL_WITH_PHDR, "Bluetooth Low Energy air interface with pseudo-header"),
-	DLT_CHOICE(DLT_PROFIBUS_DL, "PROFIBUS data link layer"),
-	DLT_CHOICE(DLT_PKTAP, "Apple DLT_PKTAP"),
-	DLT_CHOICE(DLT_EPON, "Ethernet with 802.3 Clause 65 EPON preamble"),
+	DLT_CHOICE(NULL, "BSD loopback"),
+	DLT_CHOICE(EN10MB, "Ethernet"),
+	DLT_CHOICE(IEEE802, "Token ring"),
+	DLT_CHOICE(ARCNET, "BSD ARCNET"),
+	DLT_CHOICE(SLIP, "SLIP"),
+	DLT_CHOICE(PPP, "PPP"),
+	DLT_CHOICE(FDDI, "FDDI"),
+	DLT_CHOICE(ATM_RFC1483, "RFC 1483 LLC-encapsulated ATM"),
+	DLT_CHOICE(RAW, "Raw IP"),
+	DLT_CHOICE(SLIP_BSDOS, "BSD/OS SLIP"),
+	DLT_CHOICE(PPP_BSDOS, "BSD/OS PPP"),
+	DLT_CHOICE(ATM_CLIP, "Linux Classical IP-over-ATM"),
+	DLT_CHOICE(PPP_SERIAL, "PPP over serial"),
+	DLT_CHOICE(PPP_ETHER, "PPPoE"),
+	DLT_CHOICE(SYMANTEC_FIREWALL, "Symantec Firewall"),
+	DLT_CHOICE(C_HDLC, "Cisco HDLC"),
+	DLT_CHOICE(IEEE802_11, "802.11"),
+	DLT_CHOICE(FRELAY, "Frame Relay"),
+	DLT_CHOICE(LOOP, "OpenBSD loopback"),
+	DLT_CHOICE(ENC, "OpenBSD encapsulated IP"),
+	DLT_CHOICE(LINUX_SLL, "Linux cooked"),
+	DLT_CHOICE(LTALK, "Localtalk"),
+	DLT_CHOICE(PFLOG, "OpenBSD pflog file"),
+	DLT_CHOICE(PFSYNC, "Packet filter state syncing"),
+	DLT_CHOICE(PRISM_HEADER, "802.11 plus Prism header"),
+	DLT_CHOICE(IP_OVER_FC, "RFC 2625 IP-over-Fibre Channel"),
+	DLT_CHOICE(SUNATM, "Sun raw ATM"),
+	DLT_CHOICE(IEEE802_11_RADIO, "802.11 plus radiotap header"),
+	DLT_CHOICE(ARCNET_LINUX, "Linux ARCNET"),
+	DLT_CHOICE(JUNIPER_MLPPP, "Juniper Multi-Link PPP"),
+	DLT_CHOICE(JUNIPER_MLFR, "Juniper Multi-Link Frame Relay"),
+	DLT_CHOICE(JUNIPER_ES, "Juniper Encryption Services PIC"),
+	DLT_CHOICE(JUNIPER_GGSN, "Juniper GGSN PIC"),
+	DLT_CHOICE(JUNIPER_MFR, "Juniper FRF.16 Frame Relay"),
+	DLT_CHOICE(JUNIPER_ATM2, "Juniper ATM2 PIC"),
+	DLT_CHOICE(JUNIPER_SERVICES, "Juniper Advanced Services PIC"),
+	DLT_CHOICE(JUNIPER_ATM1, "Juniper ATM1 PIC"),
+	DLT_CHOICE(APPLE_IP_OVER_IEEE1394, "Apple IP-over-IEEE 1394"),
+	DLT_CHOICE(MTP2_WITH_PHDR, "SS7 MTP2 with Pseudo-header"),
+	DLT_CHOICE(MTP2, "SS7 MTP2"),
+	DLT_CHOICE(MTP3, "SS7 MTP3"),
+	DLT_CHOICE(SCCP, "SS7 SCCP"),
+	DLT_CHOICE(DOCSIS, "DOCSIS"),
+	DLT_CHOICE(LINUX_IRDA, "Linux IrDA"),
+	DLT_CHOICE(IEEE802_11_RADIO_AVS, "802.11 plus AVS radio information header"),
+	DLT_CHOICE(JUNIPER_MONITOR, "Juniper Passive Monitor PIC"),
+	DLT_CHOICE(BACNET_MS_TP, "BACnet MS/TP"),
+	DLT_CHOICE(PPP_PPPD, "PPP for pppd, with direction flag"),
+	DLT_CHOICE(JUNIPER_PPPOE, "Juniper PPPoE"),
+	DLT_CHOICE(JUNIPER_PPPOE_ATM, "Juniper PPPoE/ATM"),
+	DLT_CHOICE(GPRS_LLC, "GPRS LLC"),
+	DLT_CHOICE(GPF_T, "GPF-T"),
+	DLT_CHOICE(GPF_F, "GPF-F"),
+	DLT_CHOICE(JUNIPER_PIC_PEER, "Juniper PIC Peer"),
+	DLT_CHOICE(ERF_ETH,	"Ethernet with Endace ERF header"),
+	DLT_CHOICE(ERF_POS, "Packet-over-SONET with Endace ERF header"),
+	DLT_CHOICE(LINUX_LAPD, "Linux vISDN LAPD"),
+	DLT_CHOICE(JUNIPER_ETHER, "Juniper Ethernet"),
+	DLT_CHOICE(JUNIPER_PPP, "Juniper PPP"),
+	DLT_CHOICE(JUNIPER_FRELAY, "Juniper Frame Relay"),
+	DLT_CHOICE(JUNIPER_CHDLC, "Juniper C-HDLC"),
+	DLT_CHOICE(MFR, "FRF.16 Frame Relay"),
+	DLT_CHOICE(JUNIPER_VP, "Juniper Voice PIC"),
+	DLT_CHOICE(A429, "Arinc 429"),
+	DLT_CHOICE(A653_ICM, "Arinc 653 Interpartition Communication"),
+	DLT_CHOICE(USB_FREEBSD, "USB with FreeBSD header"),
+	DLT_CHOICE(BLUETOOTH_HCI_H4, "Bluetooth HCI UART transport layer"),
+	DLT_CHOICE(IEEE802_16_MAC_CPS, "IEEE 802.16 MAC Common Part Sublayer"),
+	DLT_CHOICE(USB_LINUX, "USB with Linux header"),
+	DLT_CHOICE(CAN20B, "Controller Area Network (CAN) v. 2.0B"),
+	DLT_CHOICE(IEEE802_15_4_LINUX, "IEEE 802.15.4 with Linux padding"),
+	DLT_CHOICE(PPI, "Per-Packet Information"),
+	DLT_CHOICE(IEEE802_16_MAC_CPS_RADIO, "IEEE 802.16 MAC Common Part Sublayer plus radiotap header"),
+	DLT_CHOICE(JUNIPER_ISM, "Juniper Integrated Service Module"),
+	DLT_CHOICE(IEEE802_15_4, "IEEE 802.15.4 with FCS"),
+	DLT_CHOICE(SITA, "SITA pseudo-header"),
+	DLT_CHOICE(ERF, "Endace ERF header"),
+	DLT_CHOICE(RAIF1, "Ethernet with u10 Networks pseudo-header"),
+	DLT_CHOICE(IPMB, "IPMB"),
+	DLT_CHOICE(JUNIPER_ST, "Juniper Secure Tunnel"),
+	DLT_CHOICE(BLUETOOTH_HCI_H4_WITH_PHDR, "Bluetooth HCI UART transport layer plus pseudo-header"),
+	DLT_CHOICE(AX25_KISS, "AX.25 with KISS header"),
+	DLT_CHOICE(IEEE802_15_4_NONASK_PHY, "IEEE 802.15.4 with non-ASK PHY data"),
+	DLT_CHOICE(MPLS, "MPLS with label as link-layer header"),
+	DLT_CHOICE(LINUX_EVDEV, "Linux evdev events"),
+	DLT_CHOICE(USB_LINUX_MMAPPED, "USB with padded Linux header"),
+	DLT_CHOICE(DECT, "DECT"),
+	DLT_CHOICE(AOS, "AOS Space Data Link protocol"),
+	DLT_CHOICE(WIHART, "Wireless HART"),
+	DLT_CHOICE(FC_2, "Fibre Channel FC-2"),
+	DLT_CHOICE(FC_2_WITH_FRAME_DELIMS, "Fibre Channel FC-2 with frame delimiters"),
+	DLT_CHOICE(IPNET, "Solaris ipnet"),
+	DLT_CHOICE(CAN_SOCKETCAN, "CAN-bus with SocketCAN headers"),
+	DLT_CHOICE(IPV4, "Raw IPv4"),
+	DLT_CHOICE(IPV6, "Raw IPv6"),
+	DLT_CHOICE(IEEE802_15_4_NOFCS, "IEEE 802.15.4 without FCS"),
+	DLT_CHOICE(DBUS, "D-Bus"),
+	DLT_CHOICE(JUNIPER_VS, "Juniper Virtual Server"),
+	DLT_CHOICE(JUNIPER_SRX_E2E, "Juniper SRX E2E"),
+	DLT_CHOICE(JUNIPER_FIBRECHANNEL, "Juniper Fibre Channel"),
+	DLT_CHOICE(DVB_CI, "DVB-CI"),
+	DLT_CHOICE(MUX27010, "MUX27010"),
+	DLT_CHOICE(STANAG_5066_D_PDU, "STANAG 5066 D_PDUs"),
+	DLT_CHOICE(JUNIPER_ATM_CEMIC, "Juniper ATM CEMIC"),
+	DLT_CHOICE(NFLOG, "Linux netfilter log messages"),
+	DLT_CHOICE(NETANALYZER, "Ethernet with Hilscher netANALYZER pseudo-header"),
+	DLT_CHOICE(NETANALYZER_TRANSPARENT, "Ethernet with Hilscher netANALYZER pseudo-header and with preamble and SFD"),
+	DLT_CHOICE(IPOIB, "RFC 4391 IP-over-Infiniband"),
+	DLT_CHOICE(MPEG_2_TS, "MPEG-2 transport stream"),
+	DLT_CHOICE(NG40, "ng40 protocol tester Iub/Iur"),
+	DLT_CHOICE(NFC_LLCP, "NFC LLCP PDUs with pseudo-header"),
+	DLT_CHOICE(INFINIBAND, "InfiniBand"),
+	DLT_CHOICE(SCTP, "SCTP"),
+	DLT_CHOICE(USBPCAP, "USB with USBPcap header"),
+	DLT_CHOICE(RTAC_SERIAL, "Schweitzer Engineering Laboratories RTAC packets"),
+	DLT_CHOICE(BLUETOOTH_LE_LL, "Bluetooth Low Energy air interface"),
+	DLT_CHOICE(NETLINK, "Linux netlink"),
+	DLT_CHOICE(BLUETOOTH_LINUX_MONITOR, "Bluetooth Linux Monitor"),
+	DLT_CHOICE(BLUETOOTH_BREDR_BB, "Bluetooth Basic Rate/Enhanced Data Rate baseband packets"),
+	DLT_CHOICE(BLUETOOTH_LE_LL_WITH_PHDR, "Bluetooth Low Energy air interface with pseudo-header"),
+	DLT_CHOICE(PROFIBUS_DL, "PROFIBUS data link layer"),
+	DLT_CHOICE(PKTAP, "Apple DLT_PKTAP"),
+	DLT_CHOICE(EPON, "Ethernet with 802.3 Clause 65 EPON preamble"),
+	DLT_CHOICE(IPMI_HPM_2, "IPMI trace packets"),
+	DLT_CHOICE(ZWAVE_R1_R2, "Z-Wave RF profile R1 and R2 packets"),
+	DLT_CHOICE(ZWAVE_R3, "Z-Wave RF profile R3 packets"),
+	DLT_CHOICE(WATTSTOPPER_DLM, "WattStopper Digital Lighting Management (DLM) and Legrand Nitoo Open protocol"),
+	DLT_CHOICE(ISO_14443, "ISO 14443 messages"),
+	DLT_CHOICE(RDS, "IEC 62106 Radio Data System groups"),
 	DLT_CHOICE_SENTINEL
 };
 
@@ -1242,8 +1280,7 @@
 	int i;
 
 	for (i = 0; dlt_choices[i].name != NULL; i++) {
-		if (pcap_strcasecmp(dlt_choices[i].name + sizeof("DLT_") - 1,
-		    name) == 0)
+		if (pcap_strcasecmp(dlt_choices[i].name, name) == 0)
 			return (dlt_choices[i].dlt);
 	}
 	return (-1);
@@ -1256,7 +1293,7 @@
 
 	for (i = 0; dlt_choices[i].name != NULL; i++) {
 		if (dlt_choices[i].dlt == dlt)
-			return (dlt_choices[i].name + sizeof("DLT_") - 1);
+			return (dlt_choices[i].name);
 	}
 	return (NULL);
 }
@@ -1365,7 +1402,7 @@
 int
 pcap_fileno(pcap_t *p)
 {
-#ifndef WIN32
+#ifndef _WIN32
 	return (p->fd);
 #else
 	if (p->adapter != NULL)
@@ -1375,7 +1412,7 @@
 #endif
 }
 
-#if !defined(WIN32) && !defined(MSDOS)
+#if !defined(_WIN32) && !defined(MSDOS)
 int
 pcap_get_selectable_fd(pcap_t *p)
 {
@@ -1384,7 +1421,7 @@
 #endif
 
 void
-pcap_perror(pcap_t *p, char *prefix)
+pcap_perror(pcap_t *p, const char *prefix)
 {
 	fprintf(stderr, "%s: %s\n", prefix, p->errbuf);
 }
@@ -1415,11 +1452,8 @@
 /*
  * Get the current non-blocking mode setting, under the assumption that
  * it's just the standard POSIX non-blocking flag.
- *
- * We don't look at "p->nonblock", in case somebody tweaked the FD
- * directly.
  */
-#if !defined(WIN32) && !defined(MSDOS)
+#if !defined(_WIN32) && !defined(MSDOS)
 int
 pcap_getnonblock_fd(pcap_t *p, char *errbuf)
 {
@@ -1427,7 +1461,7 @@
 
 	fdflags = fcntl(p->fd, F_GETFL, 0);
 	if (fdflags == -1) {
-		snprintf(errbuf, PCAP_ERRBUF_SIZE, "F_GETFL: %s",
+		pcap_snprintf(errbuf, PCAP_ERRBUF_SIZE, "F_GETFL: %s",
 		    pcap_strerror(errno));
 		return (-1);
 	}
@@ -1455,7 +1489,7 @@
 	return (ret);
 }
 
-#if !defined(WIN32) && !defined(MSDOS)
+#if !defined(_WIN32) && !defined(MSDOS)
 /*
  * Set non-blocking mode, under the assumption that it's just the
  * standard POSIX non-blocking flag.  (This can be called by the
@@ -1469,7 +1503,7 @@
 
 	fdflags = fcntl(p->fd, F_GETFL, 0);
 	if (fdflags == -1) {
-		snprintf(errbuf, PCAP_ERRBUF_SIZE, "F_GETFL: %s",
+		pcap_snprintf(errbuf, PCAP_ERRBUF_SIZE, "F_GETFL: %s",
 		    pcap_strerror(errno));
 		return (-1);
 	}
@@ -1478,7 +1512,7 @@
 	else
 		fdflags &= ~O_NONBLOCK;
 	if (fcntl(p->fd, F_SETFL, fdflags) == -1) {
-		snprintf(errbuf, PCAP_ERRBUF_SIZE, "F_SETFL: %s",
+		pcap_snprintf(errbuf, PCAP_ERRBUF_SIZE, "F_SETFL: %s",
 		    pcap_strerror(errno));
 		return (-1);
 	}
@@ -1486,21 +1520,18 @@
 }
 #endif
 
-#ifdef WIN32
+#ifdef _WIN32
 /*
- * Generate a string for the last Win32-specific error (i.e. an error generated when
+ * Generate a string for a Win32-specific error (i.e. an error generated when
  * calling a Win32 API).
  * For errors occurred during standard C calls, we still use pcap_strerror()
  */
-char *
-pcap_win32strerror(void)
+void
+pcap_win32_err_to_str(DWORD error, char *errbuf)
 {
-	DWORD error;
-	static char errbuf[PCAP_ERRBUF_SIZE+1];
-	int errlen;
+	size_t errlen;
 	char *p;
 
-	error = GetLastError();
 	FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM, NULL, error, 0, errbuf,
 	    PCAP_ERRBUF_SIZE, NULL);
 
@@ -1514,8 +1545,7 @@
 		errbuf[errlen - 2] = '\0';
 	}
 	p = strchr(errbuf, '\0');
-	snprintf (p, sizeof(errbuf)-(p-errbuf), " (%lu)", error);
-	return (errbuf);
+	pcap_snprintf (p, PCAP_ERRBUF_SIZE+1-(p-errbuf), " (%lu)", error);
 }
 #endif
 
@@ -1574,7 +1604,7 @@
 	case PCAP_ERROR_TSTAMP_PRECISION_NOTSUP:
 		return ("That device doesn't support that time stamp precision");
 	}
-	(void)snprintf(ebuf, sizeof ebuf, "Unknown error: %d", errnum);
+	(void)pcap_snprintf(ebuf, sizeof ebuf, "Unknown error: %d", errnum);
 	return(ebuf);
 }
 
@@ -1585,16 +1615,25 @@
 pcap_strerror(int errnum)
 {
 #ifdef HAVE_STRERROR
+#ifdef _WIN32
+	static char errbuf[PCAP_ERRBUF_SIZE];
+	errno_t errno;
+	errno = strerror_s(errbuf, PCAP_ERRBUF_SIZE, errnum);
+	if (errno != 0) /* errno = 0 if successful */
+		strlcpy(errbuf, "strerror_s() error", PCAP_ERRBUF_SIZE);
+	return (errbuf);
+#else
 	return (strerror(errnum));
+#endif /* _WIN32 */
 #else
 	extern int sys_nerr;
 	extern const char *const sys_errlist[];
-	static char ebuf[15+10+1];
+	static char errbuf[PCAP_ERRBUF_SIZE];
 
 	if ((unsigned int)errnum < sys_nerr)
 		return ((char *)sys_errlist[errnum]);
-	(void)snprintf(ebuf, sizeof ebuf, "Unknown error: %d", errnum);
-	return(ebuf);
+	(void)pcap_snprintf(errbuf, sizeof errbuf, "Unknown error: %d", errnum);
+	return (errbuf);
 #endif
 }
 
@@ -1614,7 +1653,7 @@
 pcap_setdirection(pcap_t *p, pcap_direction_t d)
 {
 	if (p->setdirection_op == NULL) {
-		snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
+		pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
 		    "Setting direction is not implemented on this platform");
 		return (-1);
 	} else
@@ -1630,12 +1669,18 @@
 static int
 pcap_stats_dead(pcap_t *p, struct pcap_stat *ps _U_)
 {
-	snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
+	pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
 	    "Statistics aren't available from a pcap_open_dead pcap_t");
 	return (-1);
 }
 
-#ifdef WIN32
+#ifdef _WIN32
+struct pcap_stat *
+pcap_stats_ex(pcap_t *p, int *pcap_stat_size)
+{
+	return (p->stats_ex_op(p, pcap_stat_size));
+}
+
 int
 pcap_setbuff(pcap_t *p, int dim)
 {
@@ -1645,7 +1690,7 @@
 static int
 pcap_setbuff_dead(pcap_t *p, int dim)
 {
-	snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
+	pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
 	    "The kernel buffer size cannot be set on a pcap_open_dead pcap_t");
 	return (-1);
 }
@@ -1659,7 +1704,7 @@
 static int
 pcap_setmode_dead(pcap_t *p, int mode)
 {
-	snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
+	pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
 	    "impossible to set mode on a pcap_open_dead pcap_t");
 	return (-1);
 }
@@ -1670,19 +1715,181 @@
 	return (p->setmintocopy_op(p, size));
 }
 
-Adapter *
-pcap_get_adapter(pcap_t *p)
-{
-	return (p->getadapter_op(p));
-}
-
 static int
 pcap_setmintocopy_dead(pcap_t *p, int size)
 {
-	snprintf(p->errbuf, PCAP_ERRBUF_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)
+{
+	pcap_send_queue *tqueue;
+
+	/* Allocate the queue */
+	tqueue = (pcap_send_queue *)malloc(sizeof(pcap_send_queue));
+	if (tqueue == NULL){
+		return (NULL);
+	}
+
+	/* Allocate the buffer */
+	tqueue->buffer = (char *)malloc(memsize);
+	if (tqueue->buffer == NULL) {
+		free(tqueue);
+		return (NULL);
+	}
+
+	tqueue->maxlen = memsize;
+	tqueue->len = 0;
+
+	return (tqueue);
+}
+
+void
+pcap_sendqueue_destroy(pcap_send_queue *queue)
+{
+	free(queue->buffer);
+	free(queue);
+}
+
+int
+pcap_sendqueue_queue(pcap_send_queue *queue, const struct pcap_pkthdr *pkt_header, const u_char *pkt_data)
+{
+	if (queue->len + sizeof(struct pcap_pkthdr) + pkt_header->caplen > queue->maxlen){
+		return (-1);
+	}
+
+	/* Copy the pcap_pkthdr header*/
+	memcpy(queue->buffer + queue->len, pkt_header, sizeof(struct pcap_pkthdr));
+	queue->len += sizeof(struct pcap_pkthdr);
+
+	/* copy the packet */
+	memcpy(queue->buffer + queue->len, pkt_data, pkt_header->caplen);
+	queue->len += pkt_header->caplen;
+
+	return (0);
+}
+
+u_int
+pcap_sendqueue_transmit(pcap_t *p, pcap_send_queue *queue, int sync)
+{
+	return (p->sendqueue_transmit_op(p, queue, sync));
+}
+
+static u_int
+pcap_sendqueue_transmit_dead(pcap_t *p, pcap_send_queue *queue, int sync)
+{
+	pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
+	    "Packets cannot be transmitted on a pcap_open_dead pcap_t");
+	return (0);
+}
+
+int
+pcap_setuserbuffer(pcap_t *p, int size)
+{
+	return (p->setuserbuffer_op(p, size));
+}
+
+static int
+pcap_setuserbuffer_dead(pcap_t *p, int size)
+{
+	pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
+	    "The user buffer cannot be set on a pcap_open_dead pcap_t");
+	return (-1);
+}
+
+int
+pcap_live_dump(pcap_t *p, char *filename, int maxsize, int maxpacks)
+{
+	return (p->live_dump_op(p, filename, maxsize, maxpacks));
+}
+
+static int
+pcap_live_dump_dead(pcap_t *p, char *filename, int maxsize, int maxpacks)
+{
+	pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
+	    "Live packet dumping cannot be performed on a pcap_open_dead pcap_t");
+	return (-1);
+}
+
+int
+pcap_live_dump_ended(pcap_t *p, int sync)
+{
+	return (p->live_dump_ended_op(p, sync));
+}
+
+static int
+pcap_live_dump_ended_dead(pcap_t *p, int sync)
+{
+	pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
+	    "Live packet dumping cannot be performed on a pcap_open_dead pcap_t");
+	return (-1);
+}
+
+PAirpcapHandle
+pcap_get_airpcap_handle(pcap_t *p)
+{
+	PAirpcapHandle handle;
+
+	handle = p->get_airpcap_handle_op(p);
+	if (handle == NULL) {
+		(void)pcap_snprintf(p->errbuf, sizeof(p->errbuf),
+		    "This isn't an AirPcap device");
+	}
+	return (handle);
+}
+
+static PAirpcapHandle
+pcap_get_airpcap_handle_dead(pcap_t *p)
+{
+	return (NULL);
+}
 #endif
 
 /*
@@ -1727,12 +1934,11 @@
 	 * "pcap_close_all()" called when we exit.
 	 */
 	if (!did_atexit) {
-		if (atexit(pcap_close_all) == -1) {
+		if (atexit(pcap_close_all) != 0) {
 			/*
 			 * "atexit()" failed; let our caller know.
 			 */
-			strncpy(p->errbuf, "atexit failed",
-			    PCAP_ERRBUF_SIZE);
+			strlcpy(p->errbuf, "atexit failed", PCAP_ERRBUF_SIZE);
 			return (0);
 		}
 		did_atexit = 1;
@@ -1797,7 +2003,7 @@
 		p->tstamp_precision_count = 0;
 	}
 	pcap_freecode(&p->fcode);
-#if !defined(WIN32) && !defined(MSDOS)
+#if !defined(_WIN32) && !defined(MSDOS)
 	if (p->fd >= 0) {
 		close(p->fd);
 		p->fd = -1;
@@ -1834,10 +2040,19 @@
 	p->linktype = linktype;
 	p->opt.tstamp_precision = precision;
 	p->stats_op = pcap_stats_dead;
-#ifdef WIN32
+#ifdef _WIN32
+	p->stats_ex_op = (stats_ex_op_t)pcap_not_initialized_ptr;
 	p->setbuff_op = pcap_setbuff_dead;
 	p->setmode_op = pcap_setmode_dead;
 	p->setmintocopy_op = pcap_setmintocopy_dead;
+	p->getevent_op = pcap_getevent_dead;
+	p->oid_get_request_op = pcap_oid_get_request_dead;
+	p->oid_set_request_op = pcap_oid_set_request_dead;
+	p->sendqueue_transmit_op = pcap_sendqueue_transmit_dead;
+	p->setuserbuffer_op = pcap_setuserbuffer_dead;
+	p->live_dump_op = pcap_live_dump_dead;
+	p->live_dump_ended_op = pcap_live_dump_ended_dead;
+	p->get_airpcap_handle_op = pcap_get_airpcap_handle_dead;
 #endif
 	p->cleanup_op = pcap_cleanup_dead;
 
@@ -1884,8 +2099,8 @@
 void
 pcap_close(pcap_t *p)
 {
-	if (p->opt.source != NULL)
-		free(p->opt.source);
+	if (p->opt.device != NULL)
+		free(p->opt.device);
 	p->cleanup_op(p);
 	free(p);
 }
@@ -1908,37 +2123,30 @@
 		return (0);
 }
 
-/*
- * We make the version string static, and return a pointer to it, rather
- * than exporting the version string directly.  On at least some UNIXes,
- * if you import data from a shared library into an program, the data is
- * bound into the program binary, so if the string in the version of the
- * library with which the program was linked isn't the same as the
- * string in the version of the library with which the program is being
- * run, various undesirable things may happen (warnings, the string
- * being the one from the version of the library with which the program
- * was linked, or even weirder things, such as the string being the one
- * from the library but being truncated).
- */
-#ifdef HAVE_VERSION_H
-#include "version.h"
-#else
-static const char pcap_version_string[] = "libpcap version 1.x.y";
-#endif
+#include "pcap_version.h"
 
-#ifdef WIN32
-/*
- * XXX - it'd be nice if we could somehow generate the WinPcap and libpcap
- * version numbers when building WinPcap.  (It'd be nice to do so for
- * the packet.dll version number as well.)
- */
-static const char wpcap_version_string[] = "4.0";
-static const char pcap_version_string_fmt[] =
-    "WinPcap version %s, based on %s";
-static const char pcap_version_string_packet_dll_fmt[] =
-    "WinPcap version %s (packet.dll version %s), based on %s";
+#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)
 {
@@ -1964,8 +2172,10 @@
 			    malloc(full_pcap_version_string_len);
 			if (full_pcap_version_string == NULL)
 				return (NULL);
-			sprintf(full_pcap_version_string,
-			    pcap_version_string_fmt, wpcap_version_string,
+			pcap_snprintf(full_pcap_version_string,
+			    full_pcap_version_string_len,
+			    pcap_version_string_fmt,
+			    wpcap_version_string,
 			    pcap_version_string);
 		} else {
 			/*
@@ -1983,15 +2193,55 @@
 			full_pcap_version_string = malloc(full_pcap_version_string_len);
 			if (full_pcap_version_string == NULL)
 				return (NULL);
-			sprintf(full_pcap_version_string,
+			pcap_snprintf(full_pcap_version_string,
+			    full_pcap_version_string_len,
 			    pcap_version_string_packet_dll_fmt,
-			    wpcap_version_string, packet_version_string,
+			    wpcap_version_string,
+			    packet_version_string,
 			    pcap_version_string);
 		}
 	}
 	return (full_pcap_version_string);
 }
 
+#else /* HAVE_VERSION_H */
+
+/*
+ * libpcap being built for Windows, not as part of a WinPcap/Npcap source
+ * tree.
+ */
+static const char pcap_version_string_packet_dll_fmt[] =
+	"%s (packet.dll version %s)";
+const char *
+pcap_lib_version(void)
+{
+	char *packet_version_string;
+	size_t full_pcap_version_string_len;
+
+	if (full_pcap_version_string == NULL) {
+		/*
+		 * Generate the version string.  Report the packet.dll
+		 * version.
+		 */
+		packet_version_string = PacketGetVersion();
+		full_pcap_version_string_len =
+		    (sizeof pcap_version_string_packet_dll_fmt - 4) +
+		    strlen(pcap_version_string) +
+		    strlen(packet_version_string);
+		full_pcap_version_string = malloc(full_pcap_version_string_len);
+		if (full_pcap_version_string == NULL)
+			return (NULL);
+		pcap_snprintf(full_pcap_version_string,
+		    full_pcap_version_string_len,
+		    pcap_version_string_packet_dll_fmt,
+		    pcap_version_string,
+		    packet_version_string);
+	}
+	return (full_pcap_version_string);
+}
+
+#endif /* HAVE_VERSION_H */
+
 #elif defined(MSDOS)
 
 static char *full_pcap_version_string;
@@ -2027,3 +2277,51 @@
 	return (pcap_version_string);
 }
 #endif
+
+#ifdef YYDEBUG
+/*
+ * Set the internal "debug printout" flag for the filter expression parser.
+ * The code to print that stuff is present only if YYDEBUG is defined, so
+ * the flag, and the routine to set it, are defined only if YYDEBUG is
+ * defined.
+ *
+ * This is intended for libpcap developers, not for general use.
+ * If you want to set these in a program, you'll have to declare this
+ * routine yourself, with the appropriate DLL import attribute on Windows;
+ * it's not declared in any header file, and won't be declared in any
+ * header file provided by libpcap.
+ */
+PCAP_API void pcap_set_parser_debug(int value);
+
+PCAP_API_DEF void
+pcap_set_parser_debug(int value)
+{
+	extern int pcap_debug;
+
+	pcap_debug = value;
+}
+#endif
+
+#ifdef BDEBUG
+/*
+ * Set the internal "debug printout" flag for the filter expression optimizer.
+ * The code to print that stuff is present only if BDEBUG is defined, so
+ * the flag, and the routine to set it, are defined only if BDEBUG is
+ * defined.
+ *
+ * This is intended for libpcap developers, not for general use.
+ * If you want to set these in a program, you'll have to declare this
+ * routine yourself, with the appropriate DLL import attribute on Windows;
+ * it's not declared in any header file, and won't be declared in any
+ * header file provided by libpcap.
+ */
+PCAP_API void pcap_set_optimizer_debug(int value);
+
+PCAP_API_DEF void
+pcap_set_optimizer_debug(int value)
+{
+	extern int pcap_optimizer_debug;
+
+	pcap_optimizer_debug = value;
+}
+#endif
diff --git a/pcap/bluetooth.h b/pcap/bluetooth.h
index 01bd5a2..c5f378a 100644
--- a/pcap/bluetooth.h
+++ b/pcap/bluetooth.h
@@ -31,8 +31,8 @@
  * By Paolo Abeni <paolo.abeni@email.it>
  */
 
-#ifndef _PCAP_BLUETOOTH_STRUCTS_H__
-#define _PCAP_BLUETOOTH_STRUCTS_H__
+#ifndef lib_pcap_bluetooth_h
+#define lib_pcap_bluetooth_h
 
 /*
  * Header prepended libpcap to each bluetooth h4 frame,
diff --git a/pcap/bpf.h b/pcap/bpf.h
index 66b7a27..78ad890 100644
--- a/pcap/bpf.h
+++ b/pcap/bpf.h
@@ -72,6 +72,8 @@
 #if !defined(_NET_BPF_H_) && !defined(_NET_BPF_H_INCLUDED) && !defined(_BPF_H_) && !defined(_H_BPF) && !defined(lib_pcap_bpf_h)
 #define lib_pcap_bpf_h
 
+#include <pcap/export-defs.h>
+
 #ifdef __cplusplus
 extern "C" {
 #endif
@@ -108,1243 +110,7 @@
 	struct bpf_insn *bf_insns;
 };
 
-/*
- * Link-layer header type codes.
- *
- * Do *NOT* add new values to this list without asking
- * "tcpdump-workers@lists.tcpdump.org" for a value.  Otherwise, you run
- * the risk of using a value that's already being used for some other
- * purpose, and of having tools that read libpcap-format captures not
- * being able to handle captures with your new DLT_ value, with no hope
- * that they will ever be changed to do so (as that would destroy their
- * ability to read captures using that value for that other purpose).
- *
- * See
- *
- *	http://www.tcpdump.org/linktypes.html
- *
- * for detailed descriptions of some of these link-layer header types.
- */
-
-/*
- * These are the types that are the same on all platforms, and that
- * have been defined by <net/bpf.h> for ages.
- */
-#define DLT_NULL	0	/* BSD loopback encapsulation */
-#define DLT_EN10MB	1	/* Ethernet (10Mb) */
-#define DLT_EN3MB	2	/* Experimental Ethernet (3Mb) */
-#define DLT_AX25	3	/* Amateur Radio AX.25 */
-#define DLT_PRONET	4	/* Proteon ProNET Token Ring */
-#define DLT_CHAOS	5	/* Chaos */
-#define DLT_IEEE802	6	/* 802.5 Token Ring */
-#define DLT_ARCNET	7	/* ARCNET, with BSD-style header */
-#define DLT_SLIP	8	/* Serial Line IP */
-#define DLT_PPP		9	/* Point-to-point Protocol */
-#define DLT_FDDI	10	/* FDDI */
-
-/*
- * These are types that are different on some platforms, and that
- * have been defined by <net/bpf.h> for ages.  We use #ifdefs to
- * detect the BSDs that define them differently from the traditional
- * libpcap <net/bpf.h>
- *
- * XXX - DLT_ATM_RFC1483 is 13 in BSD/OS, and DLT_RAW is 14 in BSD/OS,
- * but I don't know what the right #define is for BSD/OS.
- */
-#define DLT_ATM_RFC1483	11	/* LLC-encapsulated ATM */
-
-#ifdef __OpenBSD__
-#define DLT_RAW		14	/* raw IP */
-#else
-#define DLT_RAW		12	/* raw IP */
-#endif
-
-/*
- * Given that the only OS that currently generates BSD/OS SLIP or PPP
- * is, well, BSD/OS, arguably everybody should have chosen its values
- * for DLT_SLIP_BSDOS and DLT_PPP_BSDOS, which are 15 and 16, but they
- * didn't.  So it goes.
- */
-#if defined(__NetBSD__) || defined(__FreeBSD__)
-#ifndef DLT_SLIP_BSDOS
-#define DLT_SLIP_BSDOS	13	/* BSD/OS Serial Line IP */
-#define DLT_PPP_BSDOS	14	/* BSD/OS Point-to-point Protocol */
-#endif
-#else
-#define DLT_SLIP_BSDOS	15	/* BSD/OS Serial Line IP */
-#define DLT_PPP_BSDOS	16	/* BSD/OS Point-to-point Protocol */
-#endif
-
-/*
- * 17 was used for DLT_PFLOG in OpenBSD; it no longer is.
- *
- * It was DLT_LANE8023 in SuSE 6.3, so we defined LINKTYPE_PFLOG
- * as 117 so that pflog captures would use a link-layer header type
- * value that didn't collide with any other values.  On all
- * platforms other than OpenBSD, we defined DLT_PFLOG as 117,
- * and we mapped between LINKTYPE_PFLOG and DLT_PFLOG.
- *
- * OpenBSD eventually switched to using 117 for DLT_PFLOG as well.
- *
- * Don't use 17 for anything else.
- */
-
-/*
- * 18 is used for DLT_PFSYNC in OpenBSD, NetBSD, DragonFly BSD and
- * Mac OS X; don't use it for anything else.  (FreeBSD uses 121,
- * which collides with DLT_HHDLC, even though it doesn't use 18
- * for anything and doesn't appear to have ever used it for anything.)
- *
- * We define it as 18 on those platforms; it is, unfortunately, used
- * for DLT_CIP in Suse 6.3, so we don't define it as DLT_PFSYNC
- * in general.  As the packet format for it, like that for
- * DLT_PFLOG, is not only OS-dependent but OS-version-dependent,
- * we don't support printing it in tcpdump except on OSes that
- * have the relevant header files, so it's not that useful on
- * other platforms.
- */
-#if defined(__OpenBSD__) || defined(__NetBSD__) || defined(__DragonFly__) || defined(__APPLE__)
-#define DLT_PFSYNC	18
-#endif
-
-#define DLT_ATM_CLIP	19	/* Linux Classical-IP over ATM */
-
-/*
- * Apparently Redback uses this for its SmartEdge 400/800.  I hope
- * nobody else decided to use it, too.
- */
-#define DLT_REDBACK_SMARTEDGE	32
-
-/*
- * These values are defined by NetBSD; other platforms should refrain from
- * using them for other purposes, so that NetBSD savefiles with link
- * types of 50 or 51 can be read as this type on all platforms.
- */
-#define DLT_PPP_SERIAL	50	/* PPP over serial with HDLC encapsulation */
-#define DLT_PPP_ETHER	51	/* PPP over Ethernet */
-
-/*
- * The Axent Raptor firewall - now the Symantec Enterprise Firewall - uses
- * a link-layer type of 99 for the tcpdump it supplies.  The link-layer
- * header has 6 bytes of unknown data, something that appears to be an
- * Ethernet type, and 36 bytes that appear to be 0 in at least one capture
- * I've seen.
- */
-#define DLT_SYMANTEC_FIREWALL	99
-
-/*
- * Values between 100 and 103 are used in capture file headers as
- * link-layer header type LINKTYPE_ values corresponding to DLT_ types
- * that differ between platforms; don't use those values for new DLT_
- * new types.
- */
-
-/*
- * Values starting with 104 are used for newly-assigned link-layer
- * header type values; for those link-layer header types, the DLT_
- * value returned by pcap_datalink() and passed to pcap_open_dead(),
- * and the LINKTYPE_ value that appears in capture files, are the
- * same.
- *
- * DLT_MATCHING_MIN is the lowest such value; DLT_MATCHING_MAX is
- * the highest such value.
- */
-#define DLT_MATCHING_MIN	104
-
-/*
- * This value was defined by libpcap 0.5; platforms that have defined
- * it with a different value should define it here with that value -
- * a link type of 104 in a save file will be mapped to DLT_C_HDLC,
- * whatever value that happens to be, so programs will correctly
- * handle files with that link type regardless of the value of
- * DLT_C_HDLC.
- *
- * The name DLT_C_HDLC was used by BSD/OS; we use that name for source
- * compatibility with programs written for BSD/OS.
- *
- * libpcap 0.5 defined it as DLT_CHDLC; we define DLT_CHDLC as well,
- * for source compatibility with programs written for libpcap 0.5.
- */
-#define DLT_C_HDLC	104	/* Cisco HDLC */
-#define DLT_CHDLC	DLT_C_HDLC
-
-#define DLT_IEEE802_11	105	/* IEEE 802.11 wireless */
-
-/*
- * 106 is reserved for Linux Classical IP over ATM; it's like DLT_RAW,
- * except when it isn't.  (I.e., sometimes it's just raw IP, and
- * sometimes it isn't.)  We currently handle it as DLT_LINUX_SLL,
- * so that we don't have to worry about the link-layer header.)
- */
-
-/*
- * Frame Relay; BSD/OS has a DLT_FR with a value of 11, but that collides
- * with other values.
- * DLT_FR and DLT_FRELAY packets start with the Q.922 Frame Relay header
- * (DLCI, etc.).
- */
-#define DLT_FRELAY	107
-
-/*
- * OpenBSD DLT_LOOP, for loopback devices; it's like DLT_NULL, except
- * that the AF_ type in the link-layer header is in network byte order.
- *
- * DLT_LOOP is 12 in OpenBSD, but that's DLT_RAW in other OSes, so
- * we don't use 12 for it in OSes other than OpenBSD.
- */
-#ifdef __OpenBSD__
-#define DLT_LOOP	12
-#else
-#define DLT_LOOP	108
-#endif
-
-/*
- * Encapsulated packets for IPsec; DLT_ENC is 13 in OpenBSD, but that's
- * DLT_SLIP_BSDOS in NetBSD, so we don't use 13 for it in OSes other
- * than OpenBSD.
- */
-#ifdef __OpenBSD__
-#define DLT_ENC		13
-#else
-#define DLT_ENC		109
-#endif
-
-/*
- * Values between 110 and 112 are reserved for use in capture file headers
- * as link-layer types corresponding to DLT_ types that might differ
- * between platforms; don't use those values for new DLT_ types
- * other than the corresponding DLT_ types.
- */
-
-/*
- * This is for Linux cooked sockets.
- */
-#define DLT_LINUX_SLL	113
-
-/*
- * Apple LocalTalk hardware.
- */
-#define DLT_LTALK	114
-
-/*
- * Acorn Econet.
- */
-#define DLT_ECONET	115
-
-/*
- * Reserved for use with OpenBSD ipfilter.
- */
-#define DLT_IPFILTER	116
-
-/*
- * OpenBSD DLT_PFLOG.
- */
-#define DLT_PFLOG	117
-
-/*
- * Registered for Cisco-internal use.
- */
-#define DLT_CISCO_IOS	118
-
-/*
- * For 802.11 cards using the Prism II chips, with a link-layer
- * header including Prism monitor mode information plus an 802.11
- * header.
- */
-#define DLT_PRISM_HEADER	119
-
-/*
- * Reserved for Aironet 802.11 cards, with an Aironet link-layer header
- * (see Doug Ambrisko's FreeBSD patches).
- */
-#define DLT_AIRONET_HEADER	120
-
-/*
- * Sigh.
- *
- * This was reserved for Siemens HiPath HDLC on 2002-01-25, as
- * requested by Tomas Kukosa.
- *
- * On 2004-02-25, a FreeBSD checkin to sys/net/bpf.h was made that
- * assigned 121 as DLT_PFSYNC.  Its libpcap does DLT_ <-> LINKTYPE_
- * mapping, so it probably supports capturing on the pfsync device
- * but not saving the captured data to a pcap file.
- *
- * OpenBSD, from which pf came, however, uses 18 for DLT_PFSYNC;
- * their libpcap does no DLT_ <-> LINKTYPE_ mapping, so it would
- * use 18 in pcap files as well.
- *
- * NetBSD and DragonFly BSD also use 18 for DLT_PFSYNC; their
- * libpcaps do DLT_ <-> LINKTYPE_ mapping, and neither has an entry
- * for DLT_PFSYNC, so it might not be able to write out dump files
- * with 18 as the link-layer header type.  (Earlier versions might
- * not have done mapping, in which case they'd work the same way
- * OpenBSD does.)
- *
- * Mac OS X defines it as 18, but doesn't appear to use it as of
- * Mac OS X 10.7.3.  Its libpcap does DLT_ <-> LINKTYPE_ mapping.
- *
- * We'll define DLT_PFSYNC as 121 on FreeBSD and define it as 18 on
- * all other platforms.  We'll define DLT_HHDLC as 121 on everything
- * except for FreeBSD; anybody who wants to compile, on FreeBSD, code
- * that uses DLT_HHDLC is out of luck.
- *
- * We'll define LINKTYPE_PFSYNC as 18, *even on FreeBSD*, and map
- * it, so that savefiles won't use 121 for PFSYNC - they'll all
- * use 18.  Code that uses pcap_datalink() to determine the link-layer
- * header type of a savefile won't, when built and run on FreeBSD,
- * be able to distinguish between LINKTYPE_PFSYNC and LINKTYPE_HHDLC
- * capture files; code that doesn't, such as the code in Wireshark,
- * will be able to distinguish between them.
- */
-#ifdef __FreeBSD__
-#define DLT_PFSYNC		121
-#else
-#define DLT_HHDLC		121
-#endif
-
-/*
- * This is for RFC 2625 IP-over-Fibre Channel.
- *
- * This is not for use with raw Fibre Channel, where the link-layer
- * header starts with a Fibre Channel frame header; it's for IP-over-FC,
- * where the link-layer header starts with an RFC 2625 Network_Header
- * field.
- */
-#define DLT_IP_OVER_FC		122
-
-/*
- * This is for Full Frontal ATM on Solaris with SunATM, with a
- * pseudo-header followed by an AALn PDU.
- *
- * There may be other forms of Full Frontal ATM on other OSes,
- * with different pseudo-headers.
- *
- * If ATM software returns a pseudo-header with VPI/VCI information
- * (and, ideally, packet type information, e.g. signalling, ILMI,
- * LANE, LLC-multiplexed traffic, etc.), it should not use
- * DLT_ATM_RFC1483, but should get a new DLT_ value, so tcpdump
- * and the like don't have to infer the presence or absence of a
- * pseudo-header and the form of the pseudo-header.
- */
-#define DLT_SUNATM		123	/* Solaris+SunATM */
-
-/*
- * Reserved as per request from Kent Dahlgren <kent@praesum.com>
- * for private use.
- */
-#define DLT_RIO                 124     /* RapidIO */
-#define DLT_PCI_EXP             125     /* PCI Express */
-#define DLT_AURORA              126     /* Xilinx Aurora link layer */
-
-/*
- * Header for 802.11 plus a number of bits of link-layer information
- * including radio information, used by some recent BSD drivers as
- * well as the madwifi Atheros driver for Linux.
- */
-#define DLT_IEEE802_11_RADIO	127	/* 802.11 plus radiotap radio header */
-
-/*
- * Reserved for the TZSP encapsulation, as per request from
- * Chris Waters <chris.waters@networkchemistry.com>
- * TZSP is a generic encapsulation for any other link type,
- * which includes a means to include meta-information
- * with the packet, e.g. signal strength and channel
- * for 802.11 packets.
- */
-#define DLT_TZSP                128     /* Tazmen Sniffer Protocol */
-
-/*
- * BSD's ARCNET headers have the source host, destination host,
- * and type at the beginning of the packet; that's what's handed
- * up to userland via BPF.
- *
- * Linux's ARCNET headers, however, have a 2-byte offset field
- * between the host IDs and the type; that's what's handed up
- * to userland via PF_PACKET sockets.
- *
- * We therefore have to have separate DLT_ values for them.
- */
-#define DLT_ARCNET_LINUX	129	/* ARCNET */
-
-/*
- * Juniper-private data link types, as per request from
- * Hannes Gredler <hannes@juniper.net>.  The DLT_s are used
- * for passing on chassis-internal metainformation such as
- * QOS profiles, etc..
- */
-#define DLT_JUNIPER_MLPPP       130
-#define DLT_JUNIPER_MLFR        131
-#define DLT_JUNIPER_ES          132
-#define DLT_JUNIPER_GGSN        133
-#define DLT_JUNIPER_MFR         134
-#define DLT_JUNIPER_ATM2        135
-#define DLT_JUNIPER_SERVICES    136
-#define DLT_JUNIPER_ATM1        137
-
-/*
- * Apple IP-over-IEEE 1394, as per a request from Dieter Siegmund
- * <dieter@apple.com>.  The header that's presented is an Ethernet-like
- * header:
- *
- *	#define FIREWIRE_EUI64_LEN	8
- *	struct firewire_header {
- *		u_char  firewire_dhost[FIREWIRE_EUI64_LEN];
- *		u_char  firewire_shost[FIREWIRE_EUI64_LEN];
- *		u_short firewire_type;
- *	};
- *
- * with "firewire_type" being an Ethernet type value, rather than,
- * for example, raw GASP frames being handed up.
- */
-#define DLT_APPLE_IP_OVER_IEEE1394	138
-
-/*
- * Various SS7 encapsulations, as per a request from Jeff Morriss
- * <jeff.morriss[AT]ulticom.com> and subsequent discussions.
- */
-#define DLT_MTP2_WITH_PHDR	139	/* pseudo-header with various info, followed by MTP2 */
-#define DLT_MTP2		140	/* MTP2, without pseudo-header */
-#define DLT_MTP3		141	/* MTP3, without pseudo-header or MTP2 */
-#define DLT_SCCP		142	/* SCCP, without pseudo-header or MTP2 or MTP3 */
-
-/*
- * DOCSIS MAC frames.
- */
-#define DLT_DOCSIS		143
-
-/*
- * Linux-IrDA packets. Protocol defined at http://www.irda.org.
- * Those packets include IrLAP headers and above (IrLMP...), but
- * don't include Phy framing (SOF/EOF/CRC & byte stuffing), because Phy
- * framing can be handled by the hardware and depend on the bitrate.
- * This is exactly the format you would get capturing on a Linux-IrDA
- * interface (irdaX), but not on a raw serial port.
- * Note the capture is done in "Linux-cooked" mode, so each packet include
- * a fake packet header (struct sll_header). This is because IrDA packet
- * decoding is dependant on the direction of the packet (incomming or
- * outgoing).
- * When/if other platform implement IrDA capture, we may revisit the
- * issue and define a real DLT_IRDA...
- * Jean II
- */
-#define DLT_LINUX_IRDA		144
-
-/*
- * Reserved for IBM SP switch and IBM Next Federation switch.
- */
-#define DLT_IBM_SP		145
-#define DLT_IBM_SN		146
-
-/*
- * Reserved for private use.  If you have some link-layer header type
- * that you want to use within your organization, with the capture files
- * using that link-layer header type not ever be sent outside your
- * organization, you can use these values.
- *
- * No libpcap release will use these for any purpose, nor will any
- * tcpdump release use them, either.
- *
- * Do *NOT* use these in capture files that you expect anybody not using
- * your private versions of capture-file-reading tools to read; in
- * particular, do *NOT* use them in products, otherwise you may find that
- * people won't be able to use tcpdump, or snort, or Ethereal, or... to
- * read capture files from your firewall/intrusion detection/traffic
- * monitoring/etc. appliance, or whatever product uses that DLT_ value,
- * and you may also find that the developers of those applications will
- * not accept patches to let them read those files.
- *
- * Also, do not use them if somebody might send you a capture using them
- * for *their* private type and tools using them for *your* private type
- * would have to read them.
- *
- * Instead, ask "tcpdump-workers@lists.tcpdump.org" for a new DLT_ value,
- * as per the comment above, and use the type you're given.
- */
-#define DLT_USER0		147
-#define DLT_USER1		148
-#define DLT_USER2		149
-#define DLT_USER3		150
-#define DLT_USER4		151
-#define DLT_USER5		152
-#define DLT_USER6		153
-#define DLT_USER7		154
-#define DLT_USER8		155
-#define DLT_USER9		156
-#define DLT_USER10		157
-#define DLT_USER11		158
-#define DLT_USER12		159
-#define DLT_USER13		160
-#define DLT_USER14		161
-#define DLT_USER15		162
-
-/*
- * For future use with 802.11 captures - defined by AbsoluteValue
- * Systems to store a number of bits of link-layer information
- * including radio information:
- *
- *	http://www.shaftnet.org/~pizza/software/capturefrm.txt
- *
- * but it might be used by some non-AVS drivers now or in the
- * future.
- */
-#define DLT_IEEE802_11_RADIO_AVS 163	/* 802.11 plus AVS radio header */
-
-/*
- * Juniper-private data link type, as per request from
- * Hannes Gredler <hannes@juniper.net>.  The DLT_s are used
- * for passing on chassis-internal metainformation such as
- * QOS profiles, etc..
- */
-#define DLT_JUNIPER_MONITOR     164
-
-/*
- * BACnet MS/TP frames.
- */
-#define DLT_BACNET_MS_TP	165
-
-/*
- * Another PPP variant as per request from Karsten Keil <kkeil@suse.de>.
- *
- * This is used in some OSes to allow a kernel socket filter to distinguish
- * between incoming and outgoing packets, on a socket intended to
- * supply pppd with outgoing packets so it can do dial-on-demand and
- * hangup-on-lack-of-demand; incoming packets are filtered out so they
- * don't cause pppd to hold the connection up (you don't want random
- * input packets such as port scans, packets from old lost connections,
- * etc. to force the connection to stay up).
- *
- * The first byte of the PPP header (0xff03) is modified to accomodate
- * the direction - 0x00 = IN, 0x01 = OUT.
- */
-#define DLT_PPP_PPPD		166
-
-/*
- * Names for backwards compatibility with older versions of some PPP
- * software; new software should use DLT_PPP_PPPD.
- */
-#define DLT_PPP_WITH_DIRECTION	DLT_PPP_PPPD
-#define DLT_LINUX_PPP_WITHDIRECTION	DLT_PPP_PPPD
-
-/*
- * Juniper-private data link type, as per request from
- * Hannes Gredler <hannes@juniper.net>.  The DLT_s are used
- * for passing on chassis-internal metainformation such as
- * QOS profiles, cookies, etc..
- */
-#define DLT_JUNIPER_PPPOE       167
-#define DLT_JUNIPER_PPPOE_ATM   168
-
-#define DLT_GPRS_LLC		169	/* GPRS LLC */
-#define DLT_GPF_T		170	/* GPF-T (ITU-T G.7041/Y.1303) */
-#define DLT_GPF_F		171	/* GPF-F (ITU-T G.7041/Y.1303) */
-
-/*
- * Requested by Oolan Zimmer <oz@gcom.com> for use in Gcom's T1/E1 line
- * monitoring equipment.
- */
-#define DLT_GCOM_T1E1		172
-#define DLT_GCOM_SERIAL		173
-
-/*
- * Juniper-private data link type, as per request from
- * Hannes Gredler <hannes@juniper.net>.  The DLT_ is used
- * for internal communication to Physical Interface Cards (PIC)
- */
-#define DLT_JUNIPER_PIC_PEER    174
-
-/*
- * Link types requested by Gregor Maier <gregor@endace.com> of Endace
- * Measurement Systems.  They add an ERF header (see
- * http://www.endace.com/support/EndaceRecordFormat.pdf) in front of
- * the link-layer header.
- */
-#define DLT_ERF_ETH		175	/* Ethernet */
-#define DLT_ERF_POS		176	/* Packet-over-SONET */
-
-/*
- * Requested by Daniele Orlandi <daniele@orlandi.com> for raw LAPD
- * for vISDN (http://www.orlandi.com/visdn/).  Its link-layer header
- * includes additional information before the LAPD header, so it's
- * not necessarily a generic LAPD header.
- */
-#define DLT_LINUX_LAPD		177
-
-/*
- * Juniper-private data link type, as per request from
- * Hannes Gredler <hannes@juniper.net>.
- * The DLT_ are used for prepending meta-information
- * like interface index, interface name
- * before standard Ethernet, PPP, Frelay & C-HDLC Frames
- */
-#define DLT_JUNIPER_ETHER       178
-#define DLT_JUNIPER_PPP         179
-#define DLT_JUNIPER_FRELAY      180
-#define DLT_JUNIPER_CHDLC       181
-
-/*
- * Multi Link Frame Relay (FRF.16)
- */
-#define DLT_MFR                 182
-
-/*
- * Juniper-private data link type, as per request from
- * Hannes Gredler <hannes@juniper.net>.
- * The DLT_ is used for internal communication with a
- * voice Adapter Card (PIC)
- */
-#define DLT_JUNIPER_VP          183
-
-/*
- * Arinc 429 frames.
- * DLT_ requested by Gianluca Varenni <gianluca.varenni@cacetech.com>.
- * Every frame contains a 32bit A429 label.
- * More documentation on Arinc 429 can be found at
- * http://www.condoreng.com/support/downloads/tutorials/ARINCTutorial.pdf
- */
-#define DLT_A429                184
-
-/*
- * Arinc 653 Interpartition Communication messages.
- * DLT_ requested by Gianluca Varenni <gianluca.varenni@cacetech.com>.
- * Please refer to the A653-1 standard for more information.
- */
-#define DLT_A653_ICM            185
-
-/*
- * USB packets, beginning with a USB setup header; requested by
- * Paolo Abeni <paolo.abeni@email.it>.
- */
-#define DLT_USB			186
-
-/*
- * Bluetooth HCI UART transport layer (part H:4); requested by
- * Paolo Abeni.
- */
-#define DLT_BLUETOOTH_HCI_H4	187
-
-/*
- * IEEE 802.16 MAC Common Part Sublayer; requested by Maria Cruz
- * <cruz_petagay@bah.com>.
- */
-#define DLT_IEEE802_16_MAC_CPS	188
-
-/*
- * USB packets, beginning with a Linux USB header; requested by
- * Paolo Abeni <paolo.abeni@email.it>.
- */
-#define DLT_USB_LINUX		189
-
-/*
- * Controller Area Network (CAN) v. 2.0B packets.
- * DLT_ requested by Gianluca Varenni <gianluca.varenni@cacetech.com>.
- * Used to dump CAN packets coming from a CAN Vector board.
- * More documentation on the CAN v2.0B frames can be found at
- * http://www.can-cia.org/downloads/?269
- */
-#define DLT_CAN20B              190
-
-/*
- * IEEE 802.15.4, with address fields padded, as is done by Linux
- * drivers; requested by Juergen Schimmer.
- */
-#define DLT_IEEE802_15_4_LINUX	191
-
-/*
- * Per Packet Information encapsulated packets.
- * DLT_ requested by Gianluca Varenni <gianluca.varenni@cacetech.com>.
- */
-#define DLT_PPI			192
-
-/*
- * Header for 802.16 MAC Common Part Sublayer plus a radiotap radio header;
- * requested by Charles Clancy.
- */
-#define DLT_IEEE802_16_MAC_CPS_RADIO	193
-
-/*
- * Juniper-private data link type, as per request from
- * Hannes Gredler <hannes@juniper.net>.
- * The DLT_ is used for internal communication with a
- * integrated service module (ISM).
- */
-#define DLT_JUNIPER_ISM         194
-
-/*
- * IEEE 802.15.4, exactly as it appears in the spec (no padding, no
- * nothing); requested by Mikko Saarnivala <mikko.saarnivala@sensinode.com>.
- * For this one, we expect the FCS to be present at the end of the frame;
- * if the frame has no FCS, DLT_IEEE802_15_4_NOFCS should be used.
- */
-#define DLT_IEEE802_15_4	195
-
-/*
- * Various link-layer types, with a pseudo-header, for SITA
- * (http://www.sita.aero/); requested by Fulko Hew (fulko.hew@gmail.com).
- */
-#define DLT_SITA		196
-
-/*
- * Various link-layer types, with a pseudo-header, for Endace DAG cards;
- * encapsulates Endace ERF records.  Requested by Stephen Donnelly
- * <stephen@endace.com>.
- */
-#define DLT_ERF			197
-
-/*
- * Special header prepended to Ethernet packets when capturing from a
- * u10 Networks board.  Requested by Phil Mulholland
- * <phil@u10networks.com>.
- */
-#define DLT_RAIF1		198
-
-/*
- * IPMB packet for IPMI, beginning with the I2C slave address, followed
- * by the netFn and LUN, etc..  Requested by Chanthy Toeung
- * <chanthy.toeung@ca.kontron.com>.
- */
-#define DLT_IPMB		199
-
-/*
- * Juniper-private data link type, as per request from
- * Hannes Gredler <hannes@juniper.net>.
- * The DLT_ is used for capturing data on a secure tunnel interface.
- */
-#define DLT_JUNIPER_ST          200
-
-/*
- * Bluetooth HCI UART transport layer (part H:4), with pseudo-header
- * that includes direction information; requested by Paolo Abeni.
- */
-#define DLT_BLUETOOTH_HCI_H4_WITH_PHDR	201
-
-/*
- * AX.25 packet with a 1-byte KISS header; see
- *
- *	http://www.ax25.net/kiss.htm
- *
- * as per Richard Stearn <richard@rns-stearn.demon.co.uk>.
- */
-#define DLT_AX25_KISS		202
-
-/*
- * LAPD packets from an ISDN channel, starting with the address field,
- * with no pseudo-header.
- * Requested by Varuna De Silva <varunax@gmail.com>.
- */
-#define DLT_LAPD		203
-
-/*
- * Variants of various link-layer headers, with a one-byte direction
- * pseudo-header prepended - zero means "received by this host",
- * non-zero (any non-zero value) means "sent by this host" - as per
- * Will Barker <w.barker@zen.co.uk>.
- */
-#define DLT_PPP_WITH_DIR	204	/* PPP - don't confuse with DLT_PPP_WITH_DIRECTION */
-#define DLT_C_HDLC_WITH_DIR	205	/* Cisco HDLC */
-#define DLT_FRELAY_WITH_DIR	206	/* Frame Relay */
-#define DLT_LAPB_WITH_DIR	207	/* LAPB */
-
-/*
- * 208 is reserved for an as-yet-unspecified proprietary link-layer
- * type, as requested by Will Barker.
- */
-
-/*
- * IPMB with a Linux-specific pseudo-header; as requested by Alexey Neyman
- * <avn@pigeonpoint.com>.
- */
-#define DLT_IPMB_LINUX		209
-
-/*
- * FlexRay automotive bus - http://www.flexray.com/ - as requested
- * by Hannes Kaelber <hannes.kaelber@x2e.de>.
- */
-#define DLT_FLEXRAY		210
-
-/*
- * Media Oriented Systems Transport (MOST) bus for multimedia
- * transport - http://www.mostcooperation.com/ - as requested
- * by Hannes Kaelber <hannes.kaelber@x2e.de>.
- */
-#define DLT_MOST		211
-
-/*
- * Local Interconnect Network (LIN) bus for vehicle networks -
- * http://www.lin-subbus.org/ - as requested by Hannes Kaelber
- * <hannes.kaelber@x2e.de>.
- */
-#define DLT_LIN			212
-
-/*
- * X2E-private data link type used for serial line capture,
- * as requested by Hannes Kaelber <hannes.kaelber@x2e.de>.
- */
-#define DLT_X2E_SERIAL		213
-
-/*
- * X2E-private data link type used for the Xoraya data logger
- * family, as requested by Hannes Kaelber <hannes.kaelber@x2e.de>.
- */
-#define DLT_X2E_XORAYA		214
-
-/*
- * IEEE 802.15.4, exactly as it appears in the spec (no padding, no
- * nothing), but with the PHY-level data for non-ASK PHYs (4 octets
- * of 0 as preamble, one octet of SFD, one octet of frame length+
- * reserved bit, and then the MAC-layer data, starting with the
- * frame control field).
- *
- * Requested by Max Filippov <jcmvbkbc@gmail.com>.
- */
-#define DLT_IEEE802_15_4_NONASK_PHY	215
-
-/*
- * David Gibson <david@gibson.dropbear.id.au> requested this for
- * captures from the Linux kernel /dev/input/eventN devices. This
- * is used to communicate keystrokes and mouse movements from the
- * Linux kernel to display systems, such as Xorg.
- */
-#define DLT_LINUX_EVDEV		216
-
-/*
- * GSM Um and Abis interfaces, preceded by a "gsmtap" header.
- *
- * Requested by Harald Welte <laforge@gnumonks.org>.
- */
-#define DLT_GSMTAP_UM		217
-#define DLT_GSMTAP_ABIS		218
-
-/*
- * MPLS, with an MPLS label as the link-layer header.
- * Requested by Michele Marchetto <michele@openbsd.org> on behalf
- * of OpenBSD.
- */
-#define DLT_MPLS		219
-
-/*
- * USB packets, beginning with a Linux USB header, with the USB header
- * padded to 64 bytes; required for memory-mapped access.
- */
-#define DLT_USB_LINUX_MMAPPED	220
-
-/*
- * DECT packets, with a pseudo-header; requested by
- * Matthias Wenzel <tcpdump@mazzoo.de>.
- */
-#define DLT_DECT		221
-
-/*
- * From: "Lidwa, Eric (GSFC-582.0)[SGT INC]" <eric.lidwa-1@nasa.gov>
- * Date: Mon, 11 May 2009 11:18:30 -0500
- *
- * DLT_AOS. We need it for AOS Space Data Link Protocol.
- *   I have already written dissectors for but need an OK from
- *   legal before I can submit a patch.
- *
- */
-#define DLT_AOS                 222
-
-/*
- * Wireless HART (Highway Addressable Remote Transducer)
- * From the HART Communication Foundation
- * IES/PAS 62591
- *
- * Requested by Sam Roberts <vieuxtech@gmail.com>.
- */
-#define DLT_WIHART		223
-
-/*
- * Fibre Channel FC-2 frames, beginning with a Frame_Header.
- * Requested by Kahou Lei <kahou82@gmail.com>.
- */
-#define DLT_FC_2		224
-
-/*
- * Fibre Channel FC-2 frames, beginning with an encoding of the
- * SOF, and ending with an encoding of the EOF.
- *
- * The encodings represent the frame delimiters as 4-byte sequences
- * representing the corresponding ordered sets, with K28.5
- * represented as 0xBC, and the D symbols as the corresponding
- * byte values; for example, SOFi2, which is K28.5 - D21.5 - D1.2 - D21.2,
- * is represented as 0xBC 0xB5 0x55 0x55.
- *
- * Requested by Kahou Lei <kahou82@gmail.com>.
- */
-#define DLT_FC_2_WITH_FRAME_DELIMS	225
-
-/*
- * Solaris ipnet pseudo-header; requested by Darren Reed <Darren.Reed@Sun.COM>.
- *
- * The pseudo-header starts with a one-byte version number; for version 2,
- * the pseudo-header is:
- *
- * struct dl_ipnetinfo {
- *     u_int8_t   dli_version;
- *     u_int8_t   dli_family;
- *     u_int16_t  dli_htype;
- *     u_int32_t  dli_pktlen;
- *     u_int32_t  dli_ifindex;
- *     u_int32_t  dli_grifindex;
- *     u_int32_t  dli_zsrc;
- *     u_int32_t  dli_zdst;
- * };
- *
- * dli_version is 2 for the current version of the pseudo-header.
- *
- * dli_family is a Solaris address family value, so it's 2 for IPv4
- * and 26 for IPv6.
- *
- * dli_htype is a "hook type" - 0 for incoming packets, 1 for outgoing
- * packets, and 2 for packets arriving from another zone on the same
- * machine.
- *
- * dli_pktlen is the length of the packet data following the pseudo-header
- * (so the captured length minus dli_pktlen is the length of the
- * pseudo-header, assuming the entire pseudo-header was captured).
- *
- * dli_ifindex is the interface index of the interface on which the
- * packet arrived.
- *
- * dli_grifindex is the group interface index number (for IPMP interfaces).
- *
- * dli_zsrc is the zone identifier for the source of the packet.
- *
- * dli_zdst is the zone identifier for the destination of the packet.
- *
- * A zone number of 0 is the global zone; a zone number of 0xffffffff
- * means that the packet arrived from another host on the network, not
- * from another zone on the same machine.
- *
- * An IPv4 or IPv6 datagram follows the pseudo-header; dli_family indicates
- * which of those it is.
- */
-#define DLT_IPNET		226
-
-/*
- * CAN (Controller Area Network) frames, with a pseudo-header as supplied
- * by Linux SocketCAN.  See Documentation/networking/can.txt in the Linux
- * source.
- *
- * Requested by Felix Obenhuber <felix@obenhuber.de>.
- */
-#define DLT_CAN_SOCKETCAN	227
-
-/*
- * Raw IPv4/IPv6; different from DLT_RAW in that the DLT_ value specifies
- * whether it's v4 or v6.  Requested by Darren Reed <Darren.Reed@Sun.COM>.
- */
-#define DLT_IPV4		228
-#define DLT_IPV6		229
-
-/*
- * IEEE 802.15.4, exactly as it appears in the spec (no padding, no
- * nothing), and with no FCS at the end of the frame; requested by
- * Jon Smirl <jonsmirl@gmail.com>.
- */
-#define DLT_IEEE802_15_4_NOFCS	230
-
-/*
- * Raw D-Bus:
- *
- *	http://www.freedesktop.org/wiki/Software/dbus
- *
- * messages:
- *
- *	http://dbus.freedesktop.org/doc/dbus-specification.html#message-protocol-messages
- *
- * starting with the endianness flag, followed by the message type, etc.,
- * but without the authentication handshake before the message sequence:
- *
- *	http://dbus.freedesktop.org/doc/dbus-specification.html#auth-protocol
- *
- * Requested by Martin Vidner <martin@vidner.net>.
- */
-#define DLT_DBUS		231
-
-/*
- * Juniper-private data link type, as per request from
- * Hannes Gredler <hannes@juniper.net>.
- */
-#define DLT_JUNIPER_VS			232
-#define DLT_JUNIPER_SRX_E2E		233
-#define DLT_JUNIPER_FIBRECHANNEL	234
-
-/*
- * DVB-CI (DVB Common Interface for communication between a PC Card
- * module and a DVB receiver).  See
- *
- *	http://www.kaiser.cx/pcap-dvbci.html
- *
- * for the specification.
- *
- * Requested by Martin Kaiser <martin@kaiser.cx>.
- */
-#define DLT_DVB_CI		235
-
-/*
- * Variant of 3GPP TS 27.010 multiplexing protocol (similar to, but
- * *not* the same as, 27.010).  Requested by Hans-Christoph Schemmel
- * <hans-christoph.schemmel@cinterion.com>.
- */
-#define DLT_MUX27010		236
-
-/*
- * STANAG 5066 D_PDUs.  Requested by M. Baris Demiray
- * <barisdemiray@gmail.com>.
- */
-#define DLT_STANAG_5066_D_PDU	237
-
-/*
- * Juniper-private data link type, as per request from
- * Hannes Gredler <hannes@juniper.net>.
- */
-#define DLT_JUNIPER_ATM_CEMIC	238
-
-/*
- * NetFilter LOG messages
- * (payload of netlink NFNL_SUBSYS_ULOG/NFULNL_MSG_PACKET packets)
- *
- * Requested by Jakub Zawadzki <darkjames-ws@darkjames.pl>
- */
-#define DLT_NFLOG		239
-
-/*
- * Hilscher Gesellschaft fuer Systemautomation mbH link-layer type
- * for Ethernet packets with a 4-byte pseudo-header and always
- * with the payload including the FCS, as supplied by their
- * netANALYZER hardware and software.
- *
- * Requested by Holger P. Frommer <HPfrommer@hilscher.com>
- */
-#define DLT_NETANALYZER		240
-
-/*
- * Hilscher Gesellschaft fuer Systemautomation mbH link-layer type
- * for Ethernet packets with a 4-byte pseudo-header and FCS and
- * with the Ethernet header preceded by 7 bytes of preamble and
- * 1 byte of SFD, as supplied by their netANALYZER hardware and
- * software.
- *
- * Requested by Holger P. Frommer <HPfrommer@hilscher.com>
- */
-#define DLT_NETANALYZER_TRANSPARENT	241
-
-/*
- * IP-over-InfiniBand, as specified by RFC 4391.
- *
- * Requested by Petr Sumbera <petr.sumbera@oracle.com>.
- */
-#define DLT_IPOIB		242
-
-/*
- * MPEG-2 transport stream (ISO 13818-1/ITU-T H.222.0).
- *
- * Requested by Guy Martin <gmsoft@tuxicoman.be>.
- */
-#define DLT_MPEG_2_TS		243
-
-/*
- * ng4T GmbH's UMTS Iub/Iur-over-ATM and Iub/Iur-over-IP format as
- * used by their ng40 protocol tester.
- *
- * Requested by Jens Grimmer <jens.grimmer@ng4t.com>.
- */
-#define DLT_NG40		244
-
-/*
- * Pseudo-header giving adapter number and flags, followed by an NFC
- * (Near-Field Communications) Logical Link Control Protocol (LLCP) PDU,
- * as specified by NFC Forum Logical Link Control Protocol Technical
- * Specification LLCP 1.1.
- *
- * Requested by Mike Wakerly <mikey@google.com>.
- */
-#define DLT_NFC_LLCP		245
-
-/*
- * 245 is used as LINKTYPE_PFSYNC; do not use it for any other purpose.
- *
- * DLT_PFSYNC has different values on different platforms, and all of
- * them collide with something used elsewhere.  On platforms that
- * don't already define it, define it as 245.
- */
-#if !defined(__FreeBSD__) && !defined(__OpenBSD__) && !defined(__NetBSD__) && !defined(__DragonFly__) && !defined(__APPLE__)
-#define DLT_PFSYNC		246
-#endif
-
-/*
- * Raw InfiniBand packets, starting with the Local Routing Header.
- *
- * Requested by Oren Kladnitsky <orenk@mellanox.com>.
- */
-#define DLT_INFINIBAND		247
-
-/*
- * SCTP, with no lower-level protocols (i.e., no IPv4 or IPv6).
- *
- * Requested by Michael Tuexen <Michael.Tuexen@lurchi.franken.de>.
- */
-#define DLT_SCTP		248
-
-/*
- * USB packets, beginning with a USBPcap header.
- *
- * Requested by Tomasz Mon <desowin@gmail.com>
- */
-#define DLT_USBPCAP		249
-
-/*
- * Schweitzer Engineering Laboratories "RTAC" product serial-line
- * packets.
- *
- * Requested by Chris Bontje <chris_bontje@selinc.com>.
- */
-#define DLT_RTAC_SERIAL		250
-
-/*
- * Bluetooth Low Energy air interface link-layer packets.
- *
- * Requested by Mike Kershaw <dragorn@kismetwireless.net>.
- */
-#define DLT_BLUETOOTH_LE_LL	251
-
-/*
- * DLT type for upper-protocol layer PDU saves from wireshark.
- *
- * the actual contents are determined by two TAGs stored with each
- * packet:
- *   EXP_PDU_TAG_LINKTYPE          the link type (LINKTYPE_ value) of the
- *				   original packet.
- *
- *   EXP_PDU_TAG_PROTO_NAME        the name of the wireshark dissector
- * 				   that can make sense of the data stored.
- */
-#define DLT_WIRESHARK_UPPER_PDU	252
-
-/*
- * DLT type for the netlink protocol (nlmon devices).
- */
-#define DLT_NETLINK		253
-
-/*
- * Bluetooth Linux Monitor headers for the BlueZ stack.
- */
-#define DLT_BLUETOOTH_LINUX_MONITOR	254
-
-/*
- * Bluetooth Basic Rate/Enhanced Data Rate baseband packets, as
- * captured by Ubertooth.
- */
-#define DLT_BLUETOOTH_BREDR_BB	255
-
-/*
- * Bluetooth Low Energy link layer packets, as captured by Ubertooth.
- */
-#define DLT_BLUETOOTH_LE_LL_WITH_PHDR	256
-
-/*
- * PROFIBUS data link layer.
- */
-#define DLT_PROFIBUS_DL		257
-
-/*
- * Apple's DLT_PKTAP headers.
- *
- * Sadly, the folks at Apple either had no clue that the DLT_USERn values
- * are for internal use within an organization and partners only, and
- * didn't know that the right way to get a link-layer header type is to
- * ask tcpdump.org for one, or knew and didn't care, so they just
- * used DLT_USER2, which causes problems for everything except for
- * their version of tcpdump.
- *
- * So I'll just give them one; hopefully this will show up in a
- * libpcap release in time for them to get this into 10.10 Big Sur
- * or whatever Mavericks' successor is called.  LINKTYPE_PKTAP
- * will be 258 *even on OS X*; that is *intentional*, so that
- * PKTAP files look the same on *all* OSes (different OSes can have
- * different numerical values for a given DLT_, but *MUST NOT* have
- * different values for what goes in a file, as files can be moved
- * between OSes!).
- *
- * When capturing, on a system with a Darwin-based OS, on a device
- * that returns 149 (DLT_USER2 and Apple's DLT_PKTAP) with this
- * version of libpcap, the DLT_ value for the pcap_t  will be DLT_PKTAP,
- * and that will continue to be DLT_USER2 on Darwin-based OSes. That way,
- * binary compatibility with Mavericks is preserved for programs using
- * this version of libpcap.  This does mean that if you were using
- * DLT_USER2 for some capture device on OS X, you can't do so with
- * this version of libpcap, just as you can't with Apple's libpcap -
- * on OS X, they define DLT_PKTAP to be DLT_USER2, so programs won't
- * be able to distinguish between PKTAP and whatever you were using
- * DLT_USER2 for.
- *
- * If the program saves the capture to a file using this version of
- * libpcap's pcap_dump code, the LINKTYPE_ value in the file will be
- * LINKTYPE_PKTAP, which will be 258, even on Darwin-based OSes.
- * That way, the file will *not* be a DLT_USER2 file.  That means
- * that the latest version of tcpdump, when built with this version
- * of libpcap, and sufficiently recent versions of Wireshark will
- * be able to read those files and interpret them correctly; however,
- * Apple's version of tcpdump in OS X 10.9 won't be able to handle
- * them.  (Hopefully, Apple will pick up this version of libpcap,
- * and the corresponding version of tcpdump, so that tcpdump will
- * be able to handle the old LINKTYPE_USER2 captures *and* the new
- * LINKTYPE_PKTAP captures.)
- */
-#ifdef __APPLE__
-#define DLT_PKTAP	DLT_USER2
-#else
-#define DLT_PKTAP	258
-#endif
-
-/*
- * Ethernet packets preceded by a header giving the last 6 octets
- * of the preamble specified by 802.3-2012 Clause 65, section
- * 65.1.3.2 "Transmit".
- */
-#define DLT_EPON	259
-
-/*
- * IPMI trace packets, as specified by Table 3-20 "Trace Data Block Format"
- * in the PICMG HPM.2 specification.
- */
-#define DLT_IPMI_HPM_2	260
-
-/*
- * per  Joshua Wright <jwright@hasborg.com>, formats for Zwave captures.
- */
-#define DLT_ZWAVE_R1_R2  261
-#define DLT_ZWAVE_R3     262
-
-/*
- * per Steve Karg <skarg@users.sourceforge.net>, formats for Wattstopper
- * Digital Lighting Management room bus serial protocol captures.
- */
-#define DLT_WATTSTOPPER_DLM     263
-
-#define DLT_MATCHING_MAX	263	/* highest value in the "matching" range */
-
-/*
- * DLT and savefile link type values are split into a class and
- * a member of that class.  A class value of 0 indicates a regular
- * DLT_/LINKTYPE_ value.
- */
-#define DLT_CLASS(x)		((x) & 0x03ff0000)
-
-/*
- * NetBSD-specific generic "raw" link type.  The class value indicates
- * that this is the generic raw type, and the lower 16 bits are the
- * address family we're dealing with.  Those values are NetBSD-specific;
- * do not assume that they correspond to AF_ values for your operating
- * system.
- */
-#define	DLT_CLASS_NETBSD_RAWAF	0x02240000
-#define	DLT_NETBSD_RAWAF(af)	(DLT_CLASS_NETBSD_RAWAF | (af))
-#define	DLT_NETBSD_RAWAF_AF(x)	((x) & 0x0000ffff)
-#define	DLT_IS_NETBSD_RAWAF(x)	(DLT_CLASS(x) == DLT_CLASS_NETBSD_RAWAF)
-
+#include <pcap/dlt.h>
 
 /*
  * The instruction encodings.
@@ -1489,21 +255,17 @@
 /*
  * Macros for insn array initializers.
  */
-#ifndef BPF_STMT
 #define BPF_STMT(code, k) { (u_short)(code), 0, 0, k }
-#endif
-#ifndef BPF_JUMP
 #define BPF_JUMP(code, k, jt, jf) { (u_short)(code), jt, jf, k }
-#endif
 
 #if __STDC__ || defined(__cplusplus)
-extern int bpf_validate(const struct bpf_insn *, int);
-extern u_int bpf_filter(const struct bpf_insn *, const u_char *, u_int, u_int);
+PCAP_API int bpf_validate(const struct bpf_insn *, int);
+PCAP_API u_int bpf_filter(const struct bpf_insn *, const u_char *, u_int, u_int);
 extern u_int bpf_filter_with_aux_data(const struct bpf_insn *, const u_char *, u_int, u_int, const struct bpf_aux_data *);
 #else
-extern int bpf_validate();
-extern u_int bpf_filter();
-extern u_int bpf_filter();
+PCAP_API int bpf_validate();
+PCAP_API u_int bpf_filter();
+extern u_int bpf_filter_with_aux_data();
 #endif
 
 /*
diff --git a/Win32/Src/ffs.c b/pcap/can_socketcan.h
similarity index 69%
rename from Win32/Src/ffs.c
rename to pcap/can_socketcan.h
index 099ff8e..68d2a13 100644
--- a/Win32/Src/ffs.c
+++ b/pcap/can_socketcan.h
@@ -1,7 +1,12 @@
 /*-
- * Copyright (c) 1990, 1993
+ * Copyright (c) 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1997
  *	The Regents of the University of California.  All rights reserved.
  *
+ * This code is derived from the Stanford/CMU enet packet filter,
+ * (net/enet.c) distributed as part of 4.3BSD, and code contributed
+ * to Berkeley by Steven McCanne and Van Jacobson both of Lawrence
+ * Berkeley Laboratory.
+ *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
  * are met:
@@ -12,8 +17,8 @@
  *    documentation and/or other materials provided with the distribution.
  * 3. All advertising materials mentioning features or use of this software
  *    must display the following acknowledgement:
- *	This product includes software developed by the University of
- *	California, Berkeley and its contributors.
+ *      This product includes software developed by the University of
+ *      California, Berkeley and its contributors.
  * 4. Neither the name of the University nor the names of its contributors
  *    may be used to endorse or promote products derived from this software
  *    without specific prior written permission.
@@ -31,24 +36,19 @@
  * SUCH DAMAGE.
  */
 
-#if defined(LIBC_SCCS) && !defined(lint)
-static char sccsid[] = "@(#)ffs.c	8.1 (Berkeley) 6/4/93";
-#endif /* LIBC_SCCS and not lint */
-
-#include <string.h>
+#ifndef lib_pcap_can_socketcan_h
+#define lib_pcap_can_socketcan_h
 
 /*
- * ffs -- vax ffs instruction
+ * SocketCAN header, as per Documentation/networking/can.txt in the
+ * Linux source.
  */
-int
-ffs(mask)
-	register int mask;
-{
-	register int bit;
+typedef struct {
+	u_int32_t can_id;
+	u_int8_t payload_length;
+	u_int8_t pad;
+	u_int8_t reserved1;
+	u_int8_t reserved2;
+} pcap_can_socketcan_hdr;
 
-	if (mask == 0)
-		return(0);
-	for (bit = 1; !(mask & 1); bit++)
-		mask >>= 1;
-	return(bit);
-}
+#endif
diff --git a/pcap/dlt.h b/pcap/dlt.h
new file mode 100644
index 0000000..2d74713
--- /dev/null
+++ b/pcap/dlt.h
@@ -0,0 +1,1340 @@
+/*-
+ * Copyright (c) 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1997
+ *	The Regents of the University of California.  All rights reserved.
+ *
+ * This code is derived from the Stanford/CMU enet packet filter,
+ * (net/enet.c) distributed as part of 4.3BSD, and code contributed
+ * to Berkeley by Steven McCanne and Van Jacobson both of Lawrence
+ * Berkeley Laboratory.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *      This product includes software developed by the University of
+ *      California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ *      @(#)bpf.h       7.1 (Berkeley) 5/7/91
+ */
+
+#ifndef lib_pcap_dlt_h
+#define lib_pcap_dlt_h
+
+/*
+ * Link-layer header type codes.
+ *
+ * Do *NOT* add new values to this list without asking
+ * "tcpdump-workers@lists.tcpdump.org" for a value.  Otherwise, you run
+ * the risk of using a value that's already being used for some other
+ * purpose, and of having tools that read libpcap-format captures not
+ * being able to handle captures with your new DLT_ value, with no hope
+ * that they will ever be changed to do so (as that would destroy their
+ * ability to read captures using that value for that other purpose).
+ *
+ * See
+ *
+ *	http://www.tcpdump.org/linktypes.html
+ *
+ * for detailed descriptions of some of these link-layer header types.
+ */
+
+/*
+ * These are the types that are the same on all platforms, and that
+ * have been defined by <net/bpf.h> for ages.
+ */
+#define DLT_NULL	0	/* BSD loopback encapsulation */
+#define DLT_EN10MB	1	/* Ethernet (10Mb) */
+#define DLT_EN3MB	2	/* Experimental Ethernet (3Mb) */
+#define DLT_AX25	3	/* Amateur Radio AX.25 */
+#define DLT_PRONET	4	/* Proteon ProNET Token Ring */
+#define DLT_CHAOS	5	/* Chaos */
+#define DLT_IEEE802	6	/* 802.5 Token Ring */
+#define DLT_ARCNET	7	/* ARCNET, with BSD-style header */
+#define DLT_SLIP	8	/* Serial Line IP */
+#define DLT_PPP		9	/* Point-to-point Protocol */
+#define DLT_FDDI	10	/* FDDI */
+
+/*
+ * These are types that are different on some platforms, and that
+ * have been defined by <net/bpf.h> for ages.  We use #ifdefs to
+ * detect the BSDs that define them differently from the traditional
+ * libpcap <net/bpf.h>
+ *
+ * XXX - DLT_ATM_RFC1483 is 13 in BSD/OS, and DLT_RAW is 14 in BSD/OS,
+ * but I don't know what the right #define is for BSD/OS.
+ */
+#define DLT_ATM_RFC1483	11	/* LLC-encapsulated ATM */
+
+#ifdef __OpenBSD__
+#define DLT_RAW		14	/* raw IP */
+#else
+#define DLT_RAW		12	/* raw IP */
+#endif
+
+/*
+ * Given that the only OS that currently generates BSD/OS SLIP or PPP
+ * is, well, BSD/OS, arguably everybody should have chosen its values
+ * for DLT_SLIP_BSDOS and DLT_PPP_BSDOS, which are 15 and 16, but they
+ * didn't.  So it goes.
+ */
+#if defined(__NetBSD__) || defined(__FreeBSD__)
+#ifndef DLT_SLIP_BSDOS
+#define DLT_SLIP_BSDOS	13	/* BSD/OS Serial Line IP */
+#define DLT_PPP_BSDOS	14	/* BSD/OS Point-to-point Protocol */
+#endif
+#else
+#define DLT_SLIP_BSDOS	15	/* BSD/OS Serial Line IP */
+#define DLT_PPP_BSDOS	16	/* BSD/OS Point-to-point Protocol */
+#endif
+
+/*
+ * 17 was used for DLT_PFLOG in OpenBSD; it no longer is.
+ *
+ * It was DLT_LANE8023 in SuSE 6.3, so we defined LINKTYPE_PFLOG
+ * as 117 so that pflog captures would use a link-layer header type
+ * value that didn't collide with any other values.  On all
+ * platforms other than OpenBSD, we defined DLT_PFLOG as 117,
+ * and we mapped between LINKTYPE_PFLOG and DLT_PFLOG.
+ *
+ * OpenBSD eventually switched to using 117 for DLT_PFLOG as well.
+ *
+ * Don't use 17 for anything else.
+ */
+
+/*
+ * 18 is used for DLT_PFSYNC in OpenBSD, NetBSD, DragonFly BSD and
+ * Mac OS X; don't use it for anything else.  (FreeBSD uses 121,
+ * which collides with DLT_HHDLC, even though it doesn't use 18
+ * for anything and doesn't appear to have ever used it for anything.)
+ *
+ * We define it as 18 on those platforms; it is, unfortunately, used
+ * for DLT_CIP in Suse 6.3, so we don't define it as DLT_PFSYNC
+ * in general.  As the packet format for it, like that for
+ * DLT_PFLOG, is not only OS-dependent but OS-version-dependent,
+ * we don't support printing it in tcpdump except on OSes that
+ * have the relevant header files, so it's not that useful on
+ * other platforms.
+ */
+#if defined(__OpenBSD__) || defined(__NetBSD__) || defined(__DragonFly__) || defined(__APPLE__)
+#define DLT_PFSYNC	18
+#endif
+
+#define DLT_ATM_CLIP	19	/* Linux Classical-IP over ATM */
+
+/*
+ * Apparently Redback uses this for its SmartEdge 400/800.  I hope
+ * nobody else decided to use it, too.
+ */
+#define DLT_REDBACK_SMARTEDGE	32
+
+/*
+ * These values are defined by NetBSD; other platforms should refrain from
+ * using them for other purposes, so that NetBSD savefiles with link
+ * types of 50 or 51 can be read as this type on all platforms.
+ */
+#define DLT_PPP_SERIAL	50	/* PPP over serial with HDLC encapsulation */
+#define DLT_PPP_ETHER	51	/* PPP over Ethernet */
+
+/*
+ * The Axent Raptor firewall - now the Symantec Enterprise Firewall - uses
+ * a link-layer type of 99 for the tcpdump it supplies.  The link-layer
+ * header has 6 bytes of unknown data, something that appears to be an
+ * Ethernet type, and 36 bytes that appear to be 0 in at least one capture
+ * I've seen.
+ */
+#define DLT_SYMANTEC_FIREWALL	99
+
+/*
+ * Values between 100 and 103 are used in capture file headers as
+ * link-layer header type LINKTYPE_ values corresponding to DLT_ types
+ * that differ between platforms; don't use those values for new DLT_
+ * new types.
+ */
+
+/*
+ * Values starting with 104 are used for newly-assigned link-layer
+ * header type values; for those link-layer header types, the DLT_
+ * value returned by pcap_datalink() and passed to pcap_open_dead(),
+ * and the LINKTYPE_ value that appears in capture files, are the
+ * same.
+ *
+ * DLT_MATCHING_MIN is the lowest such value; DLT_MATCHING_MAX is
+ * the highest such value.
+ */
+#define DLT_MATCHING_MIN	104
+
+/*
+ * This value was defined by libpcap 0.5; platforms that have defined
+ * it with a different value should define it here with that value -
+ * a link type of 104 in a save file will be mapped to DLT_C_HDLC,
+ * whatever value that happens to be, so programs will correctly
+ * handle files with that link type regardless of the value of
+ * DLT_C_HDLC.
+ *
+ * The name DLT_C_HDLC was used by BSD/OS; we use that name for source
+ * compatibility with programs written for BSD/OS.
+ *
+ * libpcap 0.5 defined it as DLT_CHDLC; we define DLT_CHDLC as well,
+ * for source compatibility with programs written for libpcap 0.5.
+ */
+#define DLT_C_HDLC	104	/* Cisco HDLC */
+#define DLT_CHDLC	DLT_C_HDLC
+
+#define DLT_IEEE802_11	105	/* IEEE 802.11 wireless */
+
+/*
+ * 106 is reserved for Linux Classical IP over ATM; it's like DLT_RAW,
+ * except when it isn't.  (I.e., sometimes it's just raw IP, and
+ * sometimes it isn't.)  We currently handle it as DLT_LINUX_SLL,
+ * so that we don't have to worry about the link-layer header.)
+ */
+
+/*
+ * Frame Relay; BSD/OS has a DLT_FR with a value of 11, but that collides
+ * with other values.
+ * DLT_FR and DLT_FRELAY packets start with the Q.922 Frame Relay header
+ * (DLCI, etc.).
+ */
+#define DLT_FRELAY	107
+
+/*
+ * OpenBSD DLT_LOOP, for loopback devices; it's like DLT_NULL, except
+ * that the AF_ type in the link-layer header is in network byte order.
+ *
+ * DLT_LOOP is 12 in OpenBSD, but that's DLT_RAW in other OSes, so
+ * we don't use 12 for it in OSes other than OpenBSD.
+ */
+#ifdef __OpenBSD__
+#define DLT_LOOP	12
+#else
+#define DLT_LOOP	108
+#endif
+
+/*
+ * Encapsulated packets for IPsec; DLT_ENC is 13 in OpenBSD, but that's
+ * DLT_SLIP_BSDOS in NetBSD, so we don't use 13 for it in OSes other
+ * than OpenBSD.
+ */
+#ifdef __OpenBSD__
+#define DLT_ENC		13
+#else
+#define DLT_ENC		109
+#endif
+
+/*
+ * Values between 110 and 112 are reserved for use in capture file headers
+ * as link-layer types corresponding to DLT_ types that might differ
+ * between platforms; don't use those values for new DLT_ types
+ * other than the corresponding DLT_ types.
+ */
+
+/*
+ * This is for Linux cooked sockets.
+ */
+#define DLT_LINUX_SLL	113
+
+/*
+ * Apple LocalTalk hardware.
+ */
+#define DLT_LTALK	114
+
+/*
+ * Acorn Econet.
+ */
+#define DLT_ECONET	115
+
+/*
+ * Reserved for use with OpenBSD ipfilter.
+ */
+#define DLT_IPFILTER	116
+
+/*
+ * OpenBSD DLT_PFLOG.
+ */
+#define DLT_PFLOG	117
+
+/*
+ * Registered for Cisco-internal use.
+ */
+#define DLT_CISCO_IOS	118
+
+/*
+ * For 802.11 cards using the Prism II chips, with a link-layer
+ * header including Prism monitor mode information plus an 802.11
+ * header.
+ */
+#define DLT_PRISM_HEADER	119
+
+/*
+ * Reserved for Aironet 802.11 cards, with an Aironet link-layer header
+ * (see Doug Ambrisko's FreeBSD patches).
+ */
+#define DLT_AIRONET_HEADER	120
+
+/*
+ * Sigh.
+ *
+ * 121 was reserved for Siemens HiPath HDLC on 2002-01-25, as
+ * requested by Tomas Kukosa.
+ *
+ * On 2004-02-25, a FreeBSD checkin to sys/net/bpf.h was made that
+ * assigned 121 as DLT_PFSYNC.  In current versions, its libpcap
+ * does DLT_ <-> LINKTYPE_ mapping, mapping DLT_PFSYNC to a
+ * LINKTYPE_PFSYNC value of 246, so it should write out DLT_PFSYNC
+ * dump files with 246 as the link-layer header type.  (Earlier
+ * versions might not have done mapping, in which case they would
+ * have written them out with a link-layer header type of 121.)
+ *
+ * OpenBSD, from which pf came, however, uses 18 for DLT_PFSYNC;
+ * its libpcap does no DLT_ <-> LINKTYPE_ mapping, so it would
+ * write out DLT_PFSYNC dump files with use 18 as the link-layer
+ * header type.
+ *
+ * NetBSD, DragonFly BSD, and Darwin also use 18 for DLT_PFSYNC; in
+ * current versions, their libpcaps do DLT_ <-> LINKTYPE_ mapping,
+ * mapping DLT_PFSYNC to a LINKTYPE_PFSYNC value of 246, so they
+ * should write out DLT_PFSYNC dump files with 246 as the link-layer
+ * header type.  (Earlier versions might not have done mapping,
+ * in which case they'd work the same way OpenBSD does, writing
+ * them out with a link-layer header type of 18.)
+ *
+ * We'll define DLT_PFSYNC as:
+ *
+ *    18 on NetBSD, OpenBSD, DragonFly BSD, and Darwin;
+ *
+ *    121 on FreeBSD;
+ *
+ *    246 everywhere else.
+ *
+ * We'll define DLT_HHDLC as 121 on everything except for FreeBSD;
+ * anybody who wants to compile, on FreeBSD, code that uses DLT_HHDLC
+ * is out of luck.
+ *
+ * We'll define LINKTYPE_PFSYNC as 246 on *all* platforms, so that
+ * savefiles written using *this* code won't use 18 or 121 for PFSYNC,
+ * they'll all use 246.
+ *
+ * Code that uses pcap_datalink() to determine the link-layer header
+ * type of a savefile won't, when built and run on FreeBSD, be able
+ * to distinguish between LINKTYPE_PFSYNC and LINKTYPE_HHDLC capture
+ * files, as pcap_datalink() will give 121 for both of them.  Code
+ * that doesn't, such as the code in Wireshark, will be able to
+ * distinguish between them.
+ *
+ * FreeBSD's libpcap won't map a link-layer header type of 18 - i.e.,
+ * DLT_PFSYNC files from OpenBSD and possibly older versions of NetBSD,
+ * DragonFly BSD, and OS X - to DLT_PFSYNC, so code built with FreeBSD's
+ * libpcap won't treat those files as DLT_PFSYNC files.
+ *
+ * Other libpcaps won't map a link-layer header type of 121 to DLT_PFSYNC;
+ * this means they can read DLT_HHDLC files, if any exist, but won't
+ * treat pcap files written by any older versions of FreeBSD libpcap that
+ * didn't map to 246 as DLT_PFSYNC files.
+ */
+#ifdef __FreeBSD__
+#define DLT_PFSYNC		121
+#else
+#define DLT_HHDLC		121
+#endif
+
+/*
+ * This is for RFC 2625 IP-over-Fibre Channel.
+ *
+ * This is not for use with raw Fibre Channel, where the link-layer
+ * header starts with a Fibre Channel frame header; it's for IP-over-FC,
+ * where the link-layer header starts with an RFC 2625 Network_Header
+ * field.
+ */
+#define DLT_IP_OVER_FC		122
+
+/*
+ * This is for Full Frontal ATM on Solaris with SunATM, with a
+ * pseudo-header followed by an AALn PDU.
+ *
+ * There may be other forms of Full Frontal ATM on other OSes,
+ * with different pseudo-headers.
+ *
+ * If ATM software returns a pseudo-header with VPI/VCI information
+ * (and, ideally, packet type information, e.g. signalling, ILMI,
+ * LANE, LLC-multiplexed traffic, etc.), it should not use
+ * DLT_ATM_RFC1483, but should get a new DLT_ value, so tcpdump
+ * and the like don't have to infer the presence or absence of a
+ * pseudo-header and the form of the pseudo-header.
+ */
+#define DLT_SUNATM		123	/* Solaris+SunATM */
+
+/*
+ * Reserved as per request from Kent Dahlgren <kent@praesum.com>
+ * for private use.
+ */
+#define DLT_RIO                 124     /* RapidIO */
+#define DLT_PCI_EXP             125     /* PCI Express */
+#define DLT_AURORA              126     /* Xilinx Aurora link layer */
+
+/*
+ * Header for 802.11 plus a number of bits of link-layer information
+ * including radio information, used by some recent BSD drivers as
+ * well as the madwifi Atheros driver for Linux.
+ */
+#define DLT_IEEE802_11_RADIO	127	/* 802.11 plus radiotap radio header */
+
+/*
+ * Reserved for the TZSP encapsulation, as per request from
+ * Chris Waters <chris.waters@networkchemistry.com>
+ * TZSP is a generic encapsulation for any other link type,
+ * which includes a means to include meta-information
+ * with the packet, e.g. signal strength and channel
+ * for 802.11 packets.
+ */
+#define DLT_TZSP                128     /* Tazmen Sniffer Protocol */
+
+/*
+ * BSD's ARCNET headers have the source host, destination host,
+ * and type at the beginning of the packet; that's what's handed
+ * up to userland via BPF.
+ *
+ * Linux's ARCNET headers, however, have a 2-byte offset field
+ * between the host IDs and the type; that's what's handed up
+ * to userland via PF_PACKET sockets.
+ *
+ * We therefore have to have separate DLT_ values for them.
+ */
+#define DLT_ARCNET_LINUX	129	/* ARCNET */
+
+/*
+ * Juniper-private data link types, as per request from
+ * Hannes Gredler <hannes@juniper.net>.  The DLT_s are used
+ * for passing on chassis-internal metainformation such as
+ * QOS profiles, etc..
+ */
+#define DLT_JUNIPER_MLPPP       130
+#define DLT_JUNIPER_MLFR        131
+#define DLT_JUNIPER_ES          132
+#define DLT_JUNIPER_GGSN        133
+#define DLT_JUNIPER_MFR         134
+#define DLT_JUNIPER_ATM2        135
+#define DLT_JUNIPER_SERVICES    136
+#define DLT_JUNIPER_ATM1        137
+
+/*
+ * Apple IP-over-IEEE 1394, as per a request from Dieter Siegmund
+ * <dieter@apple.com>.  The header that's presented is an Ethernet-like
+ * header:
+ *
+ *	#define FIREWIRE_EUI64_LEN	8
+ *	struct firewire_header {
+ *		u_char  firewire_dhost[FIREWIRE_EUI64_LEN];
+ *		u_char  firewire_shost[FIREWIRE_EUI64_LEN];
+ *		u_short firewire_type;
+ *	};
+ *
+ * with "firewire_type" being an Ethernet type value, rather than,
+ * for example, raw GASP frames being handed up.
+ */
+#define DLT_APPLE_IP_OVER_IEEE1394	138
+
+/*
+ * Various SS7 encapsulations, as per a request from Jeff Morriss
+ * <jeff.morriss[AT]ulticom.com> and subsequent discussions.
+ */
+#define DLT_MTP2_WITH_PHDR	139	/* pseudo-header with various info, followed by MTP2 */
+#define DLT_MTP2		140	/* MTP2, without pseudo-header */
+#define DLT_MTP3		141	/* MTP3, without pseudo-header or MTP2 */
+#define DLT_SCCP		142	/* SCCP, without pseudo-header or MTP2 or MTP3 */
+
+/*
+ * DOCSIS MAC frames.
+ */
+#define DLT_DOCSIS		143
+
+/*
+ * Linux-IrDA packets. Protocol defined at http://www.irda.org.
+ * Those packets include IrLAP headers and above (IrLMP...), but
+ * don't include Phy framing (SOF/EOF/CRC & byte stuffing), because Phy
+ * framing can be handled by the hardware and depend on the bitrate.
+ * This is exactly the format you would get capturing on a Linux-IrDA
+ * interface (irdaX), but not on a raw serial port.
+ * Note the capture is done in "Linux-cooked" mode, so each packet include
+ * a fake packet header (struct sll_header). This is because IrDA packet
+ * decoding is dependant on the direction of the packet (incomming or
+ * outgoing).
+ * When/if other platform implement IrDA capture, we may revisit the
+ * issue and define a real DLT_IRDA...
+ * Jean II
+ */
+#define DLT_LINUX_IRDA		144
+
+/*
+ * Reserved for IBM SP switch and IBM Next Federation switch.
+ */
+#define DLT_IBM_SP		145
+#define DLT_IBM_SN		146
+
+/*
+ * Reserved for private use.  If you have some link-layer header type
+ * that you want to use within your organization, with the capture files
+ * using that link-layer header type not ever be sent outside your
+ * organization, you can use these values.
+ *
+ * No libpcap release will use these for any purpose, nor will any
+ * tcpdump release use them, either.
+ *
+ * Do *NOT* use these in capture files that you expect anybody not using
+ * your private versions of capture-file-reading tools to read; in
+ * particular, do *NOT* use them in products, otherwise you may find that
+ * people won't be able to use tcpdump, or snort, or Ethereal, or... to
+ * read capture files from your firewall/intrusion detection/traffic
+ * monitoring/etc. appliance, or whatever product uses that DLT_ value,
+ * and you may also find that the developers of those applications will
+ * not accept patches to let them read those files.
+ *
+ * Also, do not use them if somebody might send you a capture using them
+ * for *their* private type and tools using them for *your* private type
+ * would have to read them.
+ *
+ * Instead, ask "tcpdump-workers@lists.tcpdump.org" for a new DLT_ value,
+ * as per the comment above, and use the type you're given.
+ */
+#define DLT_USER0		147
+#define DLT_USER1		148
+#define DLT_USER2		149
+#define DLT_USER3		150
+#define DLT_USER4		151
+#define DLT_USER5		152
+#define DLT_USER6		153
+#define DLT_USER7		154
+#define DLT_USER8		155
+#define DLT_USER9		156
+#define DLT_USER10		157
+#define DLT_USER11		158
+#define DLT_USER12		159
+#define DLT_USER13		160
+#define DLT_USER14		161
+#define DLT_USER15		162
+
+/*
+ * For future use with 802.11 captures - defined by AbsoluteValue
+ * Systems to store a number of bits of link-layer information
+ * including radio information:
+ *
+ *	http://www.shaftnet.org/~pizza/software/capturefrm.txt
+ *
+ * but it might be used by some non-AVS drivers now or in the
+ * future.
+ */
+#define DLT_IEEE802_11_RADIO_AVS 163	/* 802.11 plus AVS radio header */
+
+/*
+ * Juniper-private data link type, as per request from
+ * Hannes Gredler <hannes@juniper.net>.  The DLT_s are used
+ * for passing on chassis-internal metainformation such as
+ * QOS profiles, etc..
+ */
+#define DLT_JUNIPER_MONITOR     164
+
+/*
+ * BACnet MS/TP frames.
+ */
+#define DLT_BACNET_MS_TP	165
+
+/*
+ * Another PPP variant as per request from Karsten Keil <kkeil@suse.de>.
+ *
+ * This is used in some OSes to allow a kernel socket filter to distinguish
+ * between incoming and outgoing packets, on a socket intended to
+ * supply pppd with outgoing packets so it can do dial-on-demand and
+ * hangup-on-lack-of-demand; incoming packets are filtered out so they
+ * don't cause pppd to hold the connection up (you don't want random
+ * input packets such as port scans, packets from old lost connections,
+ * etc. to force the connection to stay up).
+ *
+ * The first byte of the PPP header (0xff03) is modified to accomodate
+ * the direction - 0x00 = IN, 0x01 = OUT.
+ */
+#define DLT_PPP_PPPD		166
+
+/*
+ * Names for backwards compatibility with older versions of some PPP
+ * software; new software should use DLT_PPP_PPPD.
+ */
+#define DLT_PPP_WITH_DIRECTION	DLT_PPP_PPPD
+#define DLT_LINUX_PPP_WITHDIRECTION	DLT_PPP_PPPD
+
+/*
+ * Juniper-private data link type, as per request from
+ * Hannes Gredler <hannes@juniper.net>.  The DLT_s are used
+ * for passing on chassis-internal metainformation such as
+ * QOS profiles, cookies, etc..
+ */
+#define DLT_JUNIPER_PPPOE       167
+#define DLT_JUNIPER_PPPOE_ATM   168
+
+#define DLT_GPRS_LLC		169	/* GPRS LLC */
+#define DLT_GPF_T		170	/* GPF-T (ITU-T G.7041/Y.1303) */
+#define DLT_GPF_F		171	/* GPF-F (ITU-T G.7041/Y.1303) */
+
+/*
+ * Requested by Oolan Zimmer <oz@gcom.com> for use in Gcom's T1/E1 line
+ * monitoring equipment.
+ */
+#define DLT_GCOM_T1E1		172
+#define DLT_GCOM_SERIAL		173
+
+/*
+ * Juniper-private data link type, as per request from
+ * Hannes Gredler <hannes@juniper.net>.  The DLT_ is used
+ * for internal communication to Physical Interface Cards (PIC)
+ */
+#define DLT_JUNIPER_PIC_PEER    174
+
+/*
+ * Link types requested by Gregor Maier <gregor@endace.com> of Endace
+ * Measurement Systems.  They add an ERF header (see
+ * http://www.endace.com/support/EndaceRecordFormat.pdf) in front of
+ * the link-layer header.
+ */
+#define DLT_ERF_ETH		175	/* Ethernet */
+#define DLT_ERF_POS		176	/* Packet-over-SONET */
+
+/*
+ * Requested by Daniele Orlandi <daniele@orlandi.com> for raw LAPD
+ * for vISDN (http://www.orlandi.com/visdn/).  Its link-layer header
+ * includes additional information before the LAPD header, so it's
+ * not necessarily a generic LAPD header.
+ */
+#define DLT_LINUX_LAPD		177
+
+/*
+ * Juniper-private data link type, as per request from
+ * Hannes Gredler <hannes@juniper.net>.
+ * The DLT_ are used for prepending meta-information
+ * like interface index, interface name
+ * before standard Ethernet, PPP, Frelay & C-HDLC Frames
+ */
+#define DLT_JUNIPER_ETHER       178
+#define DLT_JUNIPER_PPP         179
+#define DLT_JUNIPER_FRELAY      180
+#define DLT_JUNIPER_CHDLC       181
+
+/*
+ * Multi Link Frame Relay (FRF.16)
+ */
+#define DLT_MFR                 182
+
+/*
+ * Juniper-private data link type, as per request from
+ * Hannes Gredler <hannes@juniper.net>.
+ * The DLT_ is used for internal communication with a
+ * voice Adapter Card (PIC)
+ */
+#define DLT_JUNIPER_VP          183
+
+/*
+ * Arinc 429 frames.
+ * DLT_ requested by Gianluca Varenni <gianluca.varenni@cacetech.com>.
+ * Every frame contains a 32bit A429 label.
+ * More documentation on Arinc 429 can be found at
+ * http://www.condoreng.com/support/downloads/tutorials/ARINCTutorial.pdf
+ */
+#define DLT_A429                184
+
+/*
+ * Arinc 653 Interpartition Communication messages.
+ * DLT_ requested by Gianluca Varenni <gianluca.varenni@cacetech.com>.
+ * Please refer to the A653-1 standard for more information.
+ */
+#define DLT_A653_ICM            185
+
+/*
+ * This used to be "USB packets, beginning with a USB setup header;
+ * requested by Paolo Abeni <paolo.abeni@email.it>."
+ *
+ * However, that header didn't work all that well - it left out some
+ * useful information - and was abandoned in favor of the DLT_USB_LINUX
+ * header.
+ *
+ * This is now used by FreeBSD for its BPF taps for USB; that has its
+ * own headers.  So it is written, so it is done.
+ *
+ * For source-code compatibility, we also define DLT_USB to have this
+ * value.  We do it numerically so that, if code that includes this
+ * file (directly or indirectly) also includes an OS header that also
+ * defines DLT_USB as 186, we don't get a redefinition warning.
+ * (NetBSD 7 does that.)
+ */
+#define DLT_USB_FREEBSD		186
+#define DLT_USB			186
+
+/*
+ * Bluetooth HCI UART transport layer (part H:4); requested by
+ * Paolo Abeni.
+ */
+#define DLT_BLUETOOTH_HCI_H4	187
+
+/*
+ * IEEE 802.16 MAC Common Part Sublayer; requested by Maria Cruz
+ * <cruz_petagay@bah.com>.
+ */
+#define DLT_IEEE802_16_MAC_CPS	188
+
+/*
+ * USB packets, beginning with a Linux USB header; requested by
+ * Paolo Abeni <paolo.abeni@email.it>.
+ */
+#define DLT_USB_LINUX		189
+
+/*
+ * Controller Area Network (CAN) v. 2.0B packets.
+ * DLT_ requested by Gianluca Varenni <gianluca.varenni@cacetech.com>.
+ * Used to dump CAN packets coming from a CAN Vector board.
+ * More documentation on the CAN v2.0B frames can be found at
+ * http://www.can-cia.org/downloads/?269
+ */
+#define DLT_CAN20B              190
+
+/*
+ * IEEE 802.15.4, with address fields padded, as is done by Linux
+ * drivers; requested by Juergen Schimmer.
+ */
+#define DLT_IEEE802_15_4_LINUX	191
+
+/*
+ * Per Packet Information encapsulated packets.
+ * DLT_ requested by Gianluca Varenni <gianluca.varenni@cacetech.com>.
+ */
+#define DLT_PPI			192
+
+/*
+ * Header for 802.16 MAC Common Part Sublayer plus a radiotap radio header;
+ * requested by Charles Clancy.
+ */
+#define DLT_IEEE802_16_MAC_CPS_RADIO	193
+
+/*
+ * Juniper-private data link type, as per request from
+ * Hannes Gredler <hannes@juniper.net>.
+ * The DLT_ is used for internal communication with a
+ * integrated service module (ISM).
+ */
+#define DLT_JUNIPER_ISM         194
+
+/*
+ * IEEE 802.15.4, exactly as it appears in the spec (no padding, no
+ * nothing); requested by Mikko Saarnivala <mikko.saarnivala@sensinode.com>.
+ * For this one, we expect the FCS to be present at the end of the frame;
+ * if the frame has no FCS, DLT_IEEE802_15_4_NOFCS should be used.
+ */
+#define DLT_IEEE802_15_4	195
+
+/*
+ * Various link-layer types, with a pseudo-header, for SITA
+ * (http://www.sita.aero/); requested by Fulko Hew (fulko.hew@gmail.com).
+ */
+#define DLT_SITA		196
+
+/*
+ * Various link-layer types, with a pseudo-header, for Endace DAG cards;
+ * encapsulates Endace ERF records.  Requested by Stephen Donnelly
+ * <stephen@endace.com>.
+ */
+#define DLT_ERF			197
+
+/*
+ * Special header prepended to Ethernet packets when capturing from a
+ * u10 Networks board.  Requested by Phil Mulholland
+ * <phil@u10networks.com>.
+ */
+#define DLT_RAIF1		198
+
+/*
+ * IPMB packet for IPMI, beginning with the I2C slave address, followed
+ * by the netFn and LUN, etc..  Requested by Chanthy Toeung
+ * <chanthy.toeung@ca.kontron.com>.
+ */
+#define DLT_IPMB		199
+
+/*
+ * Juniper-private data link type, as per request from
+ * Hannes Gredler <hannes@juniper.net>.
+ * The DLT_ is used for capturing data on a secure tunnel interface.
+ */
+#define DLT_JUNIPER_ST          200
+
+/*
+ * Bluetooth HCI UART transport layer (part H:4), with pseudo-header
+ * that includes direction information; requested by Paolo Abeni.
+ */
+#define DLT_BLUETOOTH_HCI_H4_WITH_PHDR	201
+
+/*
+ * AX.25 packet with a 1-byte KISS header; see
+ *
+ *	http://www.ax25.net/kiss.htm
+ *
+ * as per Richard Stearn <richard@rns-stearn.demon.co.uk>.
+ */
+#define DLT_AX25_KISS		202
+
+/*
+ * LAPD packets from an ISDN channel, starting with the address field,
+ * with no pseudo-header.
+ * Requested by Varuna De Silva <varunax@gmail.com>.
+ */
+#define DLT_LAPD		203
+
+/*
+ * Variants of various link-layer headers, with a one-byte direction
+ * pseudo-header prepended - zero means "received by this host",
+ * non-zero (any non-zero value) means "sent by this host" - as per
+ * Will Barker <w.barker@zen.co.uk>.
+ */
+#define DLT_PPP_WITH_DIR	204	/* PPP - don't confuse with DLT_PPP_WITH_DIRECTION */
+#define DLT_C_HDLC_WITH_DIR	205	/* Cisco HDLC */
+#define DLT_FRELAY_WITH_DIR	206	/* Frame Relay */
+#define DLT_LAPB_WITH_DIR	207	/* LAPB */
+
+/*
+ * 208 is reserved for an as-yet-unspecified proprietary link-layer
+ * type, as requested by Will Barker.
+ */
+
+/*
+ * IPMB with a Linux-specific pseudo-header; as requested by Alexey Neyman
+ * <avn@pigeonpoint.com>.
+ */
+#define DLT_IPMB_LINUX		209
+
+/*
+ * FlexRay automotive bus - http://www.flexray.com/ - as requested
+ * by Hannes Kaelber <hannes.kaelber@x2e.de>.
+ */
+#define DLT_FLEXRAY		210
+
+/*
+ * Media Oriented Systems Transport (MOST) bus for multimedia
+ * transport - http://www.mostcooperation.com/ - as requested
+ * by Hannes Kaelber <hannes.kaelber@x2e.de>.
+ */
+#define DLT_MOST		211
+
+/*
+ * Local Interconnect Network (LIN) bus for vehicle networks -
+ * http://www.lin-subbus.org/ - as requested by Hannes Kaelber
+ * <hannes.kaelber@x2e.de>.
+ */
+#define DLT_LIN			212
+
+/*
+ * X2E-private data link type used for serial line capture,
+ * as requested by Hannes Kaelber <hannes.kaelber@x2e.de>.
+ */
+#define DLT_X2E_SERIAL		213
+
+/*
+ * X2E-private data link type used for the Xoraya data logger
+ * family, as requested by Hannes Kaelber <hannes.kaelber@x2e.de>.
+ */
+#define DLT_X2E_XORAYA		214
+
+/*
+ * IEEE 802.15.4, exactly as it appears in the spec (no padding, no
+ * nothing), but with the PHY-level data for non-ASK PHYs (4 octets
+ * of 0 as preamble, one octet of SFD, one octet of frame length+
+ * reserved bit, and then the MAC-layer data, starting with the
+ * frame control field).
+ *
+ * Requested by Max Filippov <jcmvbkbc@gmail.com>.
+ */
+#define DLT_IEEE802_15_4_NONASK_PHY	215
+
+/*
+ * David Gibson <david@gibson.dropbear.id.au> requested this for
+ * captures from the Linux kernel /dev/input/eventN devices. This
+ * is used to communicate keystrokes and mouse movements from the
+ * Linux kernel to display systems, such as Xorg.
+ */
+#define DLT_LINUX_EVDEV		216
+
+/*
+ * GSM Um and Abis interfaces, preceded by a "gsmtap" header.
+ *
+ * Requested by Harald Welte <laforge@gnumonks.org>.
+ */
+#define DLT_GSMTAP_UM		217
+#define DLT_GSMTAP_ABIS		218
+
+/*
+ * MPLS, with an MPLS label as the link-layer header.
+ * Requested by Michele Marchetto <michele@openbsd.org> on behalf
+ * of OpenBSD.
+ */
+#define DLT_MPLS		219
+
+/*
+ * USB packets, beginning with a Linux USB header, with the USB header
+ * padded to 64 bytes; required for memory-mapped access.
+ */
+#define DLT_USB_LINUX_MMAPPED	220
+
+/*
+ * DECT packets, with a pseudo-header; requested by
+ * Matthias Wenzel <tcpdump@mazzoo.de>.
+ */
+#define DLT_DECT		221
+
+/*
+ * From: "Lidwa, Eric (GSFC-582.0)[SGT INC]" <eric.lidwa-1@nasa.gov>
+ * Date: Mon, 11 May 2009 11:18:30 -0500
+ *
+ * DLT_AOS. We need it for AOS Space Data Link Protocol.
+ *   I have already written dissectors for but need an OK from
+ *   legal before I can submit a patch.
+ *
+ */
+#define DLT_AOS                 222
+
+/*
+ * Wireless HART (Highway Addressable Remote Transducer)
+ * From the HART Communication Foundation
+ * IES/PAS 62591
+ *
+ * Requested by Sam Roberts <vieuxtech@gmail.com>.
+ */
+#define DLT_WIHART		223
+
+/*
+ * Fibre Channel FC-2 frames, beginning with a Frame_Header.
+ * Requested by Kahou Lei <kahou82@gmail.com>.
+ */
+#define DLT_FC_2		224
+
+/*
+ * Fibre Channel FC-2 frames, beginning with an encoding of the
+ * SOF, and ending with an encoding of the EOF.
+ *
+ * The encodings represent the frame delimiters as 4-byte sequences
+ * representing the corresponding ordered sets, with K28.5
+ * represented as 0xBC, and the D symbols as the corresponding
+ * byte values; for example, SOFi2, which is K28.5 - D21.5 - D1.2 - D21.2,
+ * is represented as 0xBC 0xB5 0x55 0x55.
+ *
+ * Requested by Kahou Lei <kahou82@gmail.com>.
+ */
+#define DLT_FC_2_WITH_FRAME_DELIMS	225
+
+/*
+ * Solaris ipnet pseudo-header; requested by Darren Reed <Darren.Reed@Sun.COM>.
+ *
+ * The pseudo-header starts with a one-byte version number; for version 2,
+ * the pseudo-header is:
+ *
+ * struct dl_ipnetinfo {
+ *     u_int8_t   dli_version;
+ *     u_int8_t   dli_family;
+ *     u_int16_t  dli_htype;
+ *     u_int32_t  dli_pktlen;
+ *     u_int32_t  dli_ifindex;
+ *     u_int32_t  dli_grifindex;
+ *     u_int32_t  dli_zsrc;
+ *     u_int32_t  dli_zdst;
+ * };
+ *
+ * dli_version is 2 for the current version of the pseudo-header.
+ *
+ * dli_family is a Solaris address family value, so it's 2 for IPv4
+ * and 26 for IPv6.
+ *
+ * dli_htype is a "hook type" - 0 for incoming packets, 1 for outgoing
+ * packets, and 2 for packets arriving from another zone on the same
+ * machine.
+ *
+ * dli_pktlen is the length of the packet data following the pseudo-header
+ * (so the captured length minus dli_pktlen is the length of the
+ * pseudo-header, assuming the entire pseudo-header was captured).
+ *
+ * dli_ifindex is the interface index of the interface on which the
+ * packet arrived.
+ *
+ * dli_grifindex is the group interface index number (for IPMP interfaces).
+ *
+ * dli_zsrc is the zone identifier for the source of the packet.
+ *
+ * dli_zdst is the zone identifier for the destination of the packet.
+ *
+ * A zone number of 0 is the global zone; a zone number of 0xffffffff
+ * means that the packet arrived from another host on the network, not
+ * from another zone on the same machine.
+ *
+ * An IPv4 or IPv6 datagram follows the pseudo-header; dli_family indicates
+ * which of those it is.
+ */
+#define DLT_IPNET		226
+
+/*
+ * CAN (Controller Area Network) frames, with a pseudo-header as supplied
+ * by Linux SocketCAN, and with multi-byte numerical fields in that header
+ * in big-endian byte order.
+ *
+ * See Documentation/networking/can.txt in the Linux source.
+ *
+ * Requested by Felix Obenhuber <felix@obenhuber.de>.
+ */
+#define DLT_CAN_SOCKETCAN	227
+
+/*
+ * Raw IPv4/IPv6; different from DLT_RAW in that the DLT_ value specifies
+ * whether it's v4 or v6.  Requested by Darren Reed <Darren.Reed@Sun.COM>.
+ */
+#define DLT_IPV4		228
+#define DLT_IPV6		229
+
+/*
+ * IEEE 802.15.4, exactly as it appears in the spec (no padding, no
+ * nothing), and with no FCS at the end of the frame; requested by
+ * Jon Smirl <jonsmirl@gmail.com>.
+ */
+#define DLT_IEEE802_15_4_NOFCS	230
+
+/*
+ * Raw D-Bus:
+ *
+ *	http://www.freedesktop.org/wiki/Software/dbus
+ *
+ * messages:
+ *
+ *	http://dbus.freedesktop.org/doc/dbus-specification.html#message-protocol-messages
+ *
+ * starting with the endianness flag, followed by the message type, etc.,
+ * but without the authentication handshake before the message sequence:
+ *
+ *	http://dbus.freedesktop.org/doc/dbus-specification.html#auth-protocol
+ *
+ * Requested by Martin Vidner <martin@vidner.net>.
+ */
+#define DLT_DBUS		231
+
+/*
+ * Juniper-private data link type, as per request from
+ * Hannes Gredler <hannes@juniper.net>.
+ */
+#define DLT_JUNIPER_VS			232
+#define DLT_JUNIPER_SRX_E2E		233
+#define DLT_JUNIPER_FIBRECHANNEL	234
+
+/*
+ * DVB-CI (DVB Common Interface for communication between a PC Card
+ * module and a DVB receiver).  See
+ *
+ *	http://www.kaiser.cx/pcap-dvbci.html
+ *
+ * for the specification.
+ *
+ * Requested by Martin Kaiser <martin@kaiser.cx>.
+ */
+#define DLT_DVB_CI		235
+
+/*
+ * Variant of 3GPP TS 27.010 multiplexing protocol (similar to, but
+ * *not* the same as, 27.010).  Requested by Hans-Christoph Schemmel
+ * <hans-christoph.schemmel@cinterion.com>.
+ */
+#define DLT_MUX27010		236
+
+/*
+ * STANAG 5066 D_PDUs.  Requested by M. Baris Demiray
+ * <barisdemiray@gmail.com>.
+ */
+#define DLT_STANAG_5066_D_PDU	237
+
+/*
+ * Juniper-private data link type, as per request from
+ * Hannes Gredler <hannes@juniper.net>.
+ */
+#define DLT_JUNIPER_ATM_CEMIC	238
+
+/*
+ * NetFilter LOG messages
+ * (payload of netlink NFNL_SUBSYS_ULOG/NFULNL_MSG_PACKET packets)
+ *
+ * Requested by Jakub Zawadzki <darkjames-ws@darkjames.pl>
+ */
+#define DLT_NFLOG		239
+
+/*
+ * Hilscher Gesellschaft fuer Systemautomation mbH link-layer type
+ * for Ethernet packets with a 4-byte pseudo-header and always
+ * with the payload including the FCS, as supplied by their
+ * netANALYZER hardware and software.
+ *
+ * Requested by Holger P. Frommer <HPfrommer@hilscher.com>
+ */
+#define DLT_NETANALYZER		240
+
+/*
+ * Hilscher Gesellschaft fuer Systemautomation mbH link-layer type
+ * for Ethernet packets with a 4-byte pseudo-header and FCS and
+ * with the Ethernet header preceded by 7 bytes of preamble and
+ * 1 byte of SFD, as supplied by their netANALYZER hardware and
+ * software.
+ *
+ * Requested by Holger P. Frommer <HPfrommer@hilscher.com>
+ */
+#define DLT_NETANALYZER_TRANSPARENT	241
+
+/*
+ * IP-over-InfiniBand, as specified by RFC 4391.
+ *
+ * Requested by Petr Sumbera <petr.sumbera@oracle.com>.
+ */
+#define DLT_IPOIB		242
+
+/*
+ * MPEG-2 transport stream (ISO 13818-1/ITU-T H.222.0).
+ *
+ * Requested by Guy Martin <gmsoft@tuxicoman.be>.
+ */
+#define DLT_MPEG_2_TS		243
+
+/*
+ * ng4T GmbH's UMTS Iub/Iur-over-ATM and Iub/Iur-over-IP format as
+ * used by their ng40 protocol tester.
+ *
+ * Requested by Jens Grimmer <jens.grimmer@ng4t.com>.
+ */
+#define DLT_NG40		244
+
+/*
+ * Pseudo-header giving adapter number and flags, followed by an NFC
+ * (Near-Field Communications) Logical Link Control Protocol (LLCP) PDU,
+ * as specified by NFC Forum Logical Link Control Protocol Technical
+ * Specification LLCP 1.1.
+ *
+ * Requested by Mike Wakerly <mikey@google.com>.
+ */
+#define DLT_NFC_LLCP		245
+
+/*
+ * 246 is used as LINKTYPE_PFSYNC; do not use it for any other purpose.
+ *
+ * DLT_PFSYNC has different values on different platforms, and all of
+ * them collide with something used elsewhere.  On platforms that
+ * don't already define it, define it as 246.
+ */
+#if !defined(__FreeBSD__) && !defined(__OpenBSD__) && !defined(__NetBSD__) && !defined(__DragonFly__) && !defined(__APPLE__)
+#define DLT_PFSYNC		246
+#endif
+
+/*
+ * Raw InfiniBand packets, starting with the Local Routing Header.
+ *
+ * Requested by Oren Kladnitsky <orenk@mellanox.com>.
+ */
+#define DLT_INFINIBAND		247
+
+/*
+ * SCTP, with no lower-level protocols (i.e., no IPv4 or IPv6).
+ *
+ * Requested by Michael Tuexen <Michael.Tuexen@lurchi.franken.de>.
+ */
+#define DLT_SCTP		248
+
+/*
+ * USB packets, beginning with a USBPcap header.
+ *
+ * Requested by Tomasz Mon <desowin@gmail.com>
+ */
+#define DLT_USBPCAP		249
+
+/*
+ * Schweitzer Engineering Laboratories "RTAC" product serial-line
+ * packets.
+ *
+ * Requested by Chris Bontje <chris_bontje@selinc.com>.
+ */
+#define DLT_RTAC_SERIAL		250
+
+/*
+ * Bluetooth Low Energy air interface link-layer packets.
+ *
+ * Requested by Mike Kershaw <dragorn@kismetwireless.net>.
+ */
+#define DLT_BLUETOOTH_LE_LL	251
+
+/*
+ * DLT type for upper-protocol layer PDU saves from wireshark.
+ *
+ * the actual contents are determined by two TAGs stored with each
+ * packet:
+ *   EXP_PDU_TAG_LINKTYPE          the link type (LINKTYPE_ value) of the
+ *				   original packet.
+ *
+ *   EXP_PDU_TAG_PROTO_NAME        the name of the wireshark dissector
+ * 				   that can make sense of the data stored.
+ */
+#define DLT_WIRESHARK_UPPER_PDU	252
+
+/*
+ * DLT type for the netlink protocol (nlmon devices).
+ */
+#define DLT_NETLINK		253
+
+/*
+ * Bluetooth Linux Monitor headers for the BlueZ stack.
+ */
+#define DLT_BLUETOOTH_LINUX_MONITOR	254
+
+/*
+ * Bluetooth Basic Rate/Enhanced Data Rate baseband packets, as
+ * captured by Ubertooth.
+ */
+#define DLT_BLUETOOTH_BREDR_BB	255
+
+/*
+ * Bluetooth Low Energy link layer packets, as captured by Ubertooth.
+ */
+#define DLT_BLUETOOTH_LE_LL_WITH_PHDR	256
+
+/*
+ * PROFIBUS data link layer.
+ */
+#define DLT_PROFIBUS_DL		257
+
+/*
+ * Apple's DLT_PKTAP headers.
+ *
+ * Sadly, the folks at Apple either had no clue that the DLT_USERn values
+ * are for internal use within an organization and partners only, and
+ * didn't know that the right way to get a link-layer header type is to
+ * ask tcpdump.org for one, or knew and didn't care, so they just
+ * used DLT_USER2, which causes problems for everything except for
+ * their version of tcpdump.
+ *
+ * So I'll just give them one; hopefully this will show up in a
+ * libpcap release in time for them to get this into 10.10 Big Sur
+ * or whatever Mavericks' successor is called.  LINKTYPE_PKTAP
+ * will be 258 *even on OS X*; that is *intentional*, so that
+ * PKTAP files look the same on *all* OSes (different OSes can have
+ * different numerical values for a given DLT_, but *MUST NOT* have
+ * different values for what goes in a file, as files can be moved
+ * between OSes!).
+ *
+ * When capturing, on a system with a Darwin-based OS, on a device
+ * that returns 149 (DLT_USER2 and Apple's DLT_PKTAP) with this
+ * version of libpcap, the DLT_ value for the pcap_t  will be DLT_PKTAP,
+ * and that will continue to be DLT_USER2 on Darwin-based OSes. That way,
+ * binary compatibility with Mavericks is preserved for programs using
+ * this version of libpcap.  This does mean that if you were using
+ * DLT_USER2 for some capture device on OS X, you can't do so with
+ * this version of libpcap, just as you can't with Apple's libpcap -
+ * on OS X, they define DLT_PKTAP to be DLT_USER2, so programs won't
+ * be able to distinguish between PKTAP and whatever you were using
+ * DLT_USER2 for.
+ *
+ * If the program saves the capture to a file using this version of
+ * libpcap's pcap_dump code, the LINKTYPE_ value in the file will be
+ * LINKTYPE_PKTAP, which will be 258, even on Darwin-based OSes.
+ * That way, the file will *not* be a DLT_USER2 file.  That means
+ * that the latest version of tcpdump, when built with this version
+ * of libpcap, and sufficiently recent versions of Wireshark will
+ * be able to read those files and interpret them correctly; however,
+ * Apple's version of tcpdump in OS X 10.9 won't be able to handle
+ * them.  (Hopefully, Apple will pick up this version of libpcap,
+ * and the corresponding version of tcpdump, so that tcpdump will
+ * be able to handle the old LINKTYPE_USER2 captures *and* the new
+ * LINKTYPE_PKTAP captures.)
+ */
+#ifdef __APPLE__
+#define DLT_PKTAP	DLT_USER2
+#else
+#define DLT_PKTAP	258
+#endif
+
+/*
+ * Ethernet packets preceded by a header giving the last 6 octets
+ * of the preamble specified by 802.3-2012 Clause 65, section
+ * 65.1.3.2 "Transmit".
+ */
+#define DLT_EPON	259
+
+/*
+ * IPMI trace packets, as specified by Table 3-20 "Trace Data Block Format"
+ * in the PICMG HPM.2 specification.
+ */
+#define DLT_IPMI_HPM_2	260
+
+/*
+ * per  Joshua Wright <jwright@hasborg.com>, formats for Zwave captures.
+ */
+#define DLT_ZWAVE_R1_R2  261
+#define DLT_ZWAVE_R3     262
+
+/*
+ * per Steve Karg <skarg@users.sourceforge.net>, formats for Wattstopper
+ * Digital Lighting Management room bus serial protocol captures.
+ */
+#define DLT_WATTSTOPPER_DLM     263
+
+/*
+ * ISO 14443 contactless smart card messages.
+ */
+#define DLT_ISO_14443	264
+
+/*
+ * Radio data system (RDS) groups.  IEC 62106.
+ * Per Jonathan Brucker <jonathan.brucke@gmail.com>.
+ */
+#define DLT_RDS		265
+
+/*
+ * In case the code that includes this file (directly or indirectly)
+ * has also included OS files that happen to define DLT_MATCHING_MAX,
+ * with a different value (perhaps because that OS hasn't picked up
+ * the latest version of our DLT definitions), we undefine the
+ * previous value of DLT_MATCHING_MAX.
+ */
+#ifdef DLT_MATCHING_MAX
+#undef DLT_MATCHING_MAX
+#endif
+#define DLT_MATCHING_MAX	265	/* highest value in the "matching" range */
+
+/*
+ * DLT and savefile link type values are split into a class and
+ * a member of that class.  A class value of 0 indicates a regular
+ * DLT_/LINKTYPE_ value.
+ */
+#define DLT_CLASS(x)		((x) & 0x03ff0000)
+
+/*
+ * NetBSD-specific generic "raw" link type.  The class value indicates
+ * that this is the generic raw type, and the lower 16 bits are the
+ * address family we're dealing with.  Those values are NetBSD-specific;
+ * do not assume that they correspond to AF_ values for your operating
+ * system.
+ */
+#define	DLT_CLASS_NETBSD_RAWAF	0x02240000
+#define	DLT_NETBSD_RAWAF(af)	(DLT_CLASS_NETBSD_RAWAF | (af))
+#define	DLT_NETBSD_RAWAF_AF(x)	((x) & 0x0000ffff)
+#define	DLT_IS_NETBSD_RAWAF(x)	(DLT_CLASS(x) == DLT_CLASS_NETBSD_RAWAF)
+
+#endif /* !defined(lib_pcap_dlt_h) */
diff --git a/pcap/export-defs.h b/pcap/export-defs.h
new file mode 100644
index 0000000..a235057
--- /dev/null
+++ b/pcap/export-defs.h
@@ -0,0 +1,108 @@
+/* -*- Mode: c; tab-width: 8; indent-tabs-mode: 1; c-basic-offset: 8; -*- */
+/*
+ * Copyright (c) 1993, 1994, 1995, 1996, 1997
+ *	The Regents of the University of California.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *	This product includes software developed by the Computer Systems
+ *	Engineering Group at Lawrence Berkeley Laboratory.
+ * 4. Neither the name of the University nor of the Laboratory may be used
+ *    to endorse or promote products derived from this software without
+ *    specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#ifndef lib_pcap_export_defs_h
+#define lib_pcap_export_defs_h
+
+/*
+ * PCAP_API_DEF must be used when defining *data* exported from
+ * libpcap.  It can be used when defining *functions* exported
+ * from libpcap, but it doesn't have to be used there.  It
+ * should not be used in declarations in headers.
+ *
+ * PCAP_API must be used when *declaring* data or functions
+ * exported from libpcap; PCAP_API_DEF won't work on all platforms.
+ */
+
+/*
+ * Check whether this is GCC major.minor or a later release, or some
+ * compiler that claims to be "just like GCC" of that version or a
+ * later release.
+ */
+#define IS_AT_LEAST_GNUC_VERSION(major, minor) \
+	(defined(__GNUC__) && \
+	    (__GNUC__ > (major) || \
+	     (__GNUC__ == (major) && __GNUC_MINOR__ >= (minor))))
+
+#if defined(_WIN32)
+  #ifdef BUILDING_PCAP
+    /*
+     * We're compiling libpcap, so we should export functions in our
+     * API.
+     */
+    #define PCAP_API_DEF	__declspec(dllexport)
+  #else
+    #define PCAP_API_DEF	__declspec(dllimport)
+  #endif
+#elif defined(MSDOS)
+  /* XXX - does this need special treatment? */
+  #define PCAP_API_DEF
+#else /* UN*X */
+  #ifdef BUILDING_PCAP
+    /*
+     * We're compiling libpcap, so we should export functions in our API.
+     * The compiler might be configured not to export functions from a
+     * shared library by default, so we might have to explicitly mark
+     * functions as exported.
+     */
+    #if IS_AT_LEAST_GNUC_VERSION(3, 4)
+      /*
+       * GCC 3.4 or later, or some compiler asserting compatibility with
+       * GCC 3.4 or later, so we have __attribute__((visibility()).
+       */
+      #define PCAP_API_DEF	__attribute__((visibility("default")))
+    #elif defined(__SUNPRO_C) && (__SUNPRO_C >= 0x550)
+      /*
+       * Sun C 5.5 or later, so we have __global.
+       * (Sun C 5.9 and later also have __attribute__((visibility()),
+       * but there's no reason to prefer it with Sun C.)
+       */
+      #define PCAP_API_DEF	__global
+    #else
+      /*
+       * We don't have anything to say.
+       */
+      #define PCAP_API_DEF
+    #endif
+  #else
+    /*
+     * We're not building libpcap.
+     */
+    #define PCAP_API_DEF
+  #endif
+#endif /* _WIN32/MSDOS/UN*X */
+
+#define PCAP_API	PCAP_API_DEF extern
+
+#endif /* lib_pcap_export_defs_h */
diff --git a/pcap/namedb.h b/pcap/namedb.h
index d3a3432..73fb40a 100644
--- a/pcap/namedb.h
+++ b/pcap/namedb.h
@@ -43,7 +43,10 @@
  * XXX this stuff doesn't belong in this interface, but this
  * library already must do name to address translation, so
  * on systems that don't have support for /etc/ethers, we
- * export these hooks since they'll
+ * export these hooks since they're already being used by
+ * some applications (such as tcpdump) and already being
+ * marked as exported in some OSes offering libpcap (such
+ * as Debian).
  */
 struct pcap_etherent {
 	u_char addr[6];
@@ -52,21 +55,21 @@
 #ifndef PCAP_ETHERS_FILE
 #define PCAP_ETHERS_FILE "/etc/ethers"
 #endif
-struct	pcap_etherent *pcap_next_etherent(FILE *);
-u_char *pcap_ether_hostton(const char*);
-u_char *pcap_ether_aton(const char *);
+PCAP_API struct	pcap_etherent *pcap_next_etherent(FILE *);
+PCAP_API u_char *pcap_ether_hostton(const char*);
+PCAP_API u_char *pcap_ether_aton(const char *);
 
-bpf_u_int32 **pcap_nametoaddr(const char *);
+PCAP_API bpf_u_int32 **pcap_nametoaddr(const char *);
 #ifdef INET6
-struct addrinfo *pcap_nametoaddrinfo(const char *);
+PCAP_API struct addrinfo *pcap_nametoaddrinfo(const char *);
 #endif
-bpf_u_int32 pcap_nametonetaddr(const char *);
+PCAP_API bpf_u_int32 pcap_nametonetaddr(const char *);
 
-int	pcap_nametoport(const char *, int *, int *);
-int	pcap_nametoportrange(const char *, int *, int *, int *);
-int	pcap_nametoproto(const char *);
-int	pcap_nametoeproto(const char *);
-int	pcap_nametollc(const char *);
+PCAP_API int	pcap_nametoport(const char *, int *, int *);
+PCAP_API int	pcap_nametoportrange(const char *, int *, int *, int *);
+PCAP_API int	pcap_nametoproto(const char *);
+PCAP_API int	pcap_nametoeproto(const char *);
+PCAP_API int	pcap_nametollc(const char *);
 /*
  * If a protocol is unknown, PROTO_UNDEF is returned.
  * Also, pcap_nametoport() returns the protocol along with the port number.
@@ -75,11 +78,6 @@
  */
 #define PROTO_UNDEF		-1
 
-/* XXX move these to pcap-int.h? */
-int __pcap_atodn(const char *, bpf_u_int32 *);
-int __pcap_atoin(const char *, bpf_u_int32 *);
-u_short	__pcap_nametodnaddr(const char *);
-
 #ifdef __cplusplus
 }
 #endif
diff --git a/pcap/nflog.h b/pcap/nflog.h
index 388dd0c..a3867cd 100644
--- a/pcap/nflog.h
+++ b/pcap/nflog.h
@@ -25,8 +25,8 @@
  * DAMAGE.
  */
 
-#ifndef _PCAP_NFLOG_H__
-#define _PCAP_NFLOG_H__
+#ifndef lib_pcap_nflog_h
+#define lib_pcap_nflog_h
 
 /*
  * Structure of an NFLOG header and TLV parts, as described at
diff --git a/pcap/pcap.h b/pcap/pcap.h
index c9fab4c..7f92a37 100644
--- a/pcap/pcap.h
+++ b/pcap/pcap.h
@@ -35,7 +35,9 @@
 #ifndef lib_pcap_pcap_h
 #define lib_pcap_pcap_h
 
-#if defined(WIN32)
+#include <pcap/export-defs.h>
+
+#if defined(_WIN32)
   #include <pcap-stdinc.h>
 #elif defined(MSDOS)
   #include <sys/types.h>
@@ -43,7 +45,7 @@
 #else /* UN*X */
   #include <sys/types.h>
   #include <sys/time.h>
-#endif /* WIN32/MSDOS/UN*X */
+#endif /* _WIN32/MSDOS/UN*X */
 
 #ifndef PCAP_DONT_INCLUDE_PCAP_BPF_H
 #include <pcap/bpf.h>
@@ -170,9 +172,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 */
-#ifdef WIN32
-	u_int bs_capt;		/* number of packets that reach the application */
-#endif /* WIN32 */
+#if defined(_WIN32) && defined(HAVE_REMOTE)
+	u_int ps_capt;		/* number of packets that reach the application */
+	u_int ps_sent;		/* number of packets sent by the server on the network */
+	u_int ps_netdrop;	/* number of packets lost on the network */
+#endif /* _WIN32 && HAVE_REMOTE */
 };
 
 #ifdef MSDOS
@@ -271,27 +275,27 @@
  */
 #define PCAP_NETMASK_UNKNOWN	0xffffffff
 
-char	*pcap_lookupdev(char *);
-int	pcap_lookupnet(const char *, bpf_u_int32 *, bpf_u_int32 *, char *);
+PCAP_API char	*pcap_lookupdev(char *);
+PCAP_API int	pcap_lookupnet(const char *, bpf_u_int32 *, bpf_u_int32 *, char *);
 
-pcap_t	*pcap_create(const char *, char *);
-int	pcap_set_snaplen(pcap_t *, int);
-int	pcap_set_promisc(pcap_t *, int);
-int	pcap_can_set_rfmon(pcap_t *);
-int	pcap_set_rfmon(pcap_t *, int);
-int	pcap_set_timeout(pcap_t *, int);
-int	pcap_set_tstamp_type(pcap_t *, int);
-int	pcap_set_immediate_mode(pcap_t *, int);
-int	pcap_set_buffer_size(pcap_t *, int);
-int	pcap_set_tstamp_precision(pcap_t *, int);
-int	pcap_get_tstamp_precision(pcap_t *);
-int	pcap_activate(pcap_t *);
+PCAP_API pcap_t	*pcap_create(const char *, char *);
+PCAP_API int	pcap_set_snaplen(pcap_t *, int);
+PCAP_API int	pcap_set_promisc(pcap_t *, int);
+PCAP_API int	pcap_can_set_rfmon(pcap_t *);
+PCAP_API int	pcap_set_rfmon(pcap_t *, int);
+PCAP_API int	pcap_set_timeout(pcap_t *, int);
+PCAP_API int	pcap_set_tstamp_type(pcap_t *, int);
+PCAP_API int	pcap_set_immediate_mode(pcap_t *, int);
+PCAP_API int	pcap_set_buffer_size(pcap_t *, int);
+PCAP_API int	pcap_set_tstamp_precision(pcap_t *, int);
+PCAP_API int	pcap_get_tstamp_precision(pcap_t *);
+PCAP_API int	pcap_activate(pcap_t *);
 
-int	pcap_list_tstamp_types(pcap_t *, int **);
-void	pcap_free_tstamp_types(int *);
-int	pcap_tstamp_type_name_to_val(const char *);
-const char *pcap_tstamp_type_val_to_name(int);
-const char *pcap_tstamp_type_val_to_description(int);
+PCAP_API int	pcap_list_tstamp_types(pcap_t *, int **);
+PCAP_API void	pcap_free_tstamp_types(int *);
+PCAP_API int	pcap_tstamp_type_name_to_val(const char *);
+PCAP_API const char *pcap_tstamp_type_val_to_name(int);
+PCAP_API const char *pcap_tstamp_type_val_to_description(int);
 
 /*
  * Time stamp types.
@@ -346,83 +350,87 @@
 #define PCAP_TSTAMP_PRECISION_MICRO	0	/* use timestamps with microsecond precision, default */
 #define PCAP_TSTAMP_PRECISION_NANO	1	/* use timestamps with nanosecond precision */
 
-pcap_t	*pcap_open_live(const char *, int, int, int, char *);
-pcap_t	*pcap_open_dead(int, int);
-pcap_t	*pcap_open_dead_with_tstamp_precision(int, int, u_int);
-pcap_t	*pcap_open_offline_with_tstamp_precision(const char *, u_int, char *);
-pcap_t	*pcap_open_offline(const char *, char *);
-#if defined(WIN32)
-pcap_t  *pcap_hopen_offline_with_tstamp_precision(intptr_t, u_int, char *);
-pcap_t  *pcap_hopen_offline(intptr_t, char *);
-#if !defined(LIBPCAP_EXPORTS)
-#define pcap_fopen_offline_with_tstamp_precision(f,p,b) \
+PCAP_API pcap_t	*pcap_open_live(const char *, int, int, int, char *);
+PCAP_API pcap_t	*pcap_open_dead(int, int);
+PCAP_API pcap_t	*pcap_open_dead_with_tstamp_precision(int, int, u_int);
+PCAP_API pcap_t	*pcap_open_offline_with_tstamp_precision(const char *, u_int, char *);
+PCAP_API pcap_t	*pcap_open_offline(const char *, char *);
+#ifdef _WIN32
+  PCAP_API pcap_t  *pcap_hopen_offline_with_tstamp_precision(intptr_t, u_int, char *);
+  PCAP_API pcap_t  *pcap_hopen_offline(intptr_t, char *);
+  /*
+   * If we're building libpcap, these are internal routines in savefile.c,
+   * so we mustn't define them as macros.
+   */
+  #ifndef BUILDING_PCAP
+    #define pcap_fopen_offline_with_tstamp_precision(f,p,b) \
 	pcap_hopen_offline_with_tstamp_precision(_get_osfhandle(_fileno(f)), p, b)
-#define pcap_fopen_offline(f,b) \
+    #define pcap_fopen_offline(f,b) \
 	pcap_hopen_offline(_get_osfhandle(_fileno(f)), b)
-#else /*LIBPCAP_EXPORTS*/
-static pcap_t *pcap_fopen_offline_with_tstamp_precision(FILE *, u_int, char *);
-static pcap_t *pcap_fopen_offline(FILE *, char *);
-#endif
-#else /*WIN32*/
-pcap_t	*pcap_fopen_offline_with_tstamp_precision(FILE *, u_int, char *);
-pcap_t	*pcap_fopen_offline(FILE *, char *);
-#endif /*WIN32*/
+  #endif
+#else /*_WIN32*/
+  PCAP_API pcap_t	*pcap_fopen_offline_with_tstamp_precision(FILE *, u_int, char *);
+  PCAP_API pcap_t	*pcap_fopen_offline(FILE *, char *);
+#endif /*_WIN32*/
 
-void	pcap_close(pcap_t *);
-int	pcap_loop(pcap_t *, int, pcap_handler, u_char *);
-int	pcap_dispatch(pcap_t *, int, pcap_handler, u_char *);
-const u_char*
-	pcap_next(pcap_t *, struct pcap_pkthdr *);
-int 	pcap_next_ex(pcap_t *, struct pcap_pkthdr **, const u_char **);
-void	pcap_breakloop(pcap_t *);
-int	pcap_stats(pcap_t *, struct pcap_stat *);
-int	pcap_setfilter(pcap_t *, struct bpf_program *);
-int 	pcap_setdirection(pcap_t *, pcap_direction_t);
-int	pcap_getnonblock(pcap_t *, char *);
-int	pcap_setnonblock(pcap_t *, int, char *);
-int	pcap_inject(pcap_t *, const void *, size_t);
-int	pcap_sendpacket(pcap_t *, const u_char *, int);
-const char *pcap_statustostr(int);
-const char *pcap_strerror(int);
-char	*pcap_geterr(pcap_t *);
-void	pcap_perror(pcap_t *, char *);
-int	pcap_compile(pcap_t *, struct bpf_program *, const char *, int,
+PCAP_API void	pcap_close(pcap_t *);
+PCAP_API int	pcap_loop(pcap_t *, int, pcap_handler, u_char *);
+PCAP_API int	pcap_dispatch(pcap_t *, int, pcap_handler, u_char *);
+PCAP_API const u_char *pcap_next(pcap_t *, struct pcap_pkthdr *);
+PCAP_API int 	pcap_next_ex(pcap_t *, struct pcap_pkthdr **, const u_char **);
+PCAP_API void	pcap_breakloop(pcap_t *);
+PCAP_API int	pcap_stats(pcap_t *, struct pcap_stat *);
+PCAP_API int	pcap_setfilter(pcap_t *, struct bpf_program *);
+PCAP_API int 	pcap_setdirection(pcap_t *, pcap_direction_t);
+PCAP_API int	pcap_getnonblock(pcap_t *, char *);
+PCAP_API int	pcap_setnonblock(pcap_t *, int, char *);
+PCAP_API int	pcap_inject(pcap_t *, const void *, size_t);
+PCAP_API int	pcap_sendpacket(pcap_t *, const u_char *, int);
+PCAP_API const char *pcap_statustostr(int);
+PCAP_API const char *pcap_strerror(int);
+PCAP_API char	*pcap_geterr(pcap_t *);
+PCAP_API void	pcap_perror(pcap_t *, const char *);
+PCAP_API int	pcap_compile(pcap_t *, struct bpf_program *, const char *, int,
 	    bpf_u_int32);
-int	pcap_compile_nopcap(int, int, struct bpf_program *,
+PCAP_API int	pcap_compile_nopcap(int, int, struct bpf_program *,
 	    const char *, int, bpf_u_int32);
-void	pcap_freecode(struct bpf_program *);
-int	pcap_offline_filter(const struct bpf_program *,
+PCAP_API void	pcap_freecode(struct bpf_program *);
+PCAP_API int	pcap_offline_filter(const struct bpf_program *,
 	    const struct pcap_pkthdr *, const u_char *);
-int	pcap_datalink(pcap_t *);
-int	pcap_datalink_ext(pcap_t *);
-int	pcap_list_datalinks(pcap_t *, int **);
-int	pcap_set_datalink(pcap_t *, int);
-void	pcap_free_datalinks(int *);
-int	pcap_datalink_name_to_val(const char *);
-const char *pcap_datalink_val_to_name(int);
-const char *pcap_datalink_val_to_description(int);
-int	pcap_snapshot(pcap_t *);
-int	pcap_is_swapped(pcap_t *);
-int	pcap_major_version(pcap_t *);
-int	pcap_minor_version(pcap_t *);
+PCAP_API int	pcap_datalink(pcap_t *);
+PCAP_API int	pcap_datalink_ext(pcap_t *);
+PCAP_API int	pcap_list_datalinks(pcap_t *, int **);
+PCAP_API int	pcap_set_datalink(pcap_t *, int);
+PCAP_API void	pcap_free_datalinks(int *);
+PCAP_API int	pcap_datalink_name_to_val(const char *);
+PCAP_API const char *pcap_datalink_val_to_name(int);
+PCAP_API const char *pcap_datalink_val_to_description(int);
+PCAP_API int	pcap_snapshot(pcap_t *);
+PCAP_API int	pcap_is_swapped(pcap_t *);
+PCAP_API int	pcap_major_version(pcap_t *);
+PCAP_API int	pcap_minor_version(pcap_t *);
 
 /* XXX */
-FILE	*pcap_file(pcap_t *);
-int	pcap_fileno(pcap_t *);
+PCAP_API FILE	*pcap_file(pcap_t *);
+PCAP_API int	pcap_fileno(pcap_t *);
 
-pcap_dumper_t *pcap_dump_open(pcap_t *, const char *);
-pcap_dumper_t *pcap_dump_fopen(pcap_t *, FILE *fp);
-pcap_dumper_t *pcap_dump_open_append(pcap_t *, const char *);
-FILE	*pcap_dump_file(pcap_dumper_t *);
-long	pcap_dump_ftell(pcap_dumper_t *);
-int	pcap_dump_flush(pcap_dumper_t *);
-void	pcap_dump_close(pcap_dumper_t *);
-void	pcap_dump(u_char *, const struct pcap_pkthdr *, const u_char *);
+#ifdef _WIN32
+  PCAP_API int	pcap_wsockinit(void);
+#endif
 
-int	pcap_findalldevs(pcap_if_t **, char *);
-void	pcap_freealldevs(pcap_if_t *);
+PCAP_API pcap_dumper_t *pcap_dump_open(pcap_t *, const char *);
+PCAP_API pcap_dumper_t *pcap_dump_fopen(pcap_t *, FILE *fp);
+PCAP_API pcap_dumper_t *pcap_dump_open_append(pcap_t *, const char *);
+PCAP_API FILE	*pcap_dump_file(pcap_dumper_t *);
+PCAP_API long	pcap_dump_ftell(pcap_dumper_t *);
+PCAP_API int	pcap_dump_flush(pcap_dumper_t *);
+PCAP_API void	pcap_dump_close(pcap_dumper_t *);
+PCAP_API void	pcap_dump(u_char *, const struct pcap_pkthdr *, const u_char *);
 
-const char *pcap_lib_version(void);
+PCAP_API int	pcap_findalldevs(pcap_if_t **, char *);
+PCAP_API void	pcap_freealldevs(pcap_if_t *);
+
+PCAP_API const char *pcap_lib_version(void);
 
 /*
  * On at least some versions of NetBSD and QNX, we don't want to declare
@@ -432,51 +440,96 @@
  * declared when we build pcap-bpf.c.
  */
 #if !defined(__NetBSD__) && !defined(__QNX__)
-u_int	bpf_filter(const struct bpf_insn *, const u_char *, u_int, u_int);
+  PCAP_API u_int	bpf_filter(const struct bpf_insn *, const u_char *, u_int, u_int);
 #endif
-int	bpf_validate(const struct bpf_insn *f, int len);
-char	*bpf_image(const struct bpf_insn *, int);
-void	bpf_dump(const struct bpf_program *, int);
+PCAP_API int	bpf_validate(const struct bpf_insn *f, int len);
+PCAP_API char	*bpf_image(const struct bpf_insn *, int);
+PCAP_API void	bpf_dump(const struct bpf_program *, int);
 
-#if defined(WIN32)
+#if defined(_WIN32)
 
-/*
- * Win32 definitions
- */
+  /*
+   * Win32 definitions
+   */
 
-int pcap_setbuff(pcap_t *p, int dim);
-int pcap_setmode(pcap_t *p, int mode);
-int pcap_setmintocopy(pcap_t *p, int size);
-Adapter *pcap_get_adapter(pcap_t *p);
+  /*!
+    \brief A queue of raw packets that will be sent to the network with pcap_sendqueue_transmit().
+  */
+  struct pcap_send_queue
+  {
+	u_int maxlen;	/* Maximum size of the the queue, in bytes. This
+			   variable contains the size of the buffer field. */
+	u_int len;	/* Current size of the queue, in bytes. */
+	char *buffer;	/* Buffer containing the packets to be sent. */
+  };
 
-#ifdef WPCAP
-/* Include file with the wpcap-specific extensions */
-#include <Win32-Extensions.h>
-#endif /* WPCAP */
+  typedef struct pcap_send_queue pcap_send_queue;
 
-#define MODE_CAPT 0
-#define MODE_STAT 1
-#define MODE_MON 2
+  /*!
+    \brief This typedef is a support for the pcap_get_airpcap_handle() function
+  */
+  #if !defined(AIRPCAP_HANDLE__EAE405F5_0171_9592_B3C2_C19EC426AD34__DEFINED_)
+    #define AIRPCAP_HANDLE__EAE405F5_0171_9592_B3C2_C19EC426AD34__DEFINED_
+    typedef struct _AirpcapHandle *PAirpcapHandle;
+  #endif
+
+  PCAP_API int pcap_setbuff(pcap_t *p, int dim);
+  PCAP_API int pcap_setmode(pcap_t *p, int mode);
+  PCAP_API int pcap_setmintocopy(pcap_t *p, int size);
+
+  PCAP_API HANDLE pcap_getevent(pcap_t *p);
+
+  PCAP_API int pcap_oid_get_request(pcap_t *, bpf_u_int32, void *, size_t *);
+  PCAP_API int pcap_oid_set_request(pcap_t *, bpf_u_int32, const void *, size_t *);
+
+  PCAP_API pcap_send_queue* pcap_sendqueue_alloc(u_int memsize);
+
+  PCAP_API void pcap_sendqueue_destroy(pcap_send_queue* queue);
+
+  PCAP_API int pcap_sendqueue_queue(pcap_send_queue* queue, const struct pcap_pkthdr *pkt_header, const u_char *pkt_data);
+
+  PCAP_API u_int pcap_sendqueue_transmit(pcap_t *p, pcap_send_queue* queue, int sync);
+
+  PCAP_API struct pcap_stat *pcap_stats_ex(pcap_t *p, int *pcap_stat_size);
+
+  PCAP_API int pcap_setuserbuffer(pcap_t *p, int size);
+
+  PCAP_API int pcap_live_dump(pcap_t *p, char *filename, int maxsize, int maxpacks);
+
+  PCAP_API int pcap_live_dump_ended(pcap_t *p, int sync);
+
+  PCAP_API int pcap_start_oem(char* err_str, int flags);
+
+  PCAP_API PAirpcapHandle pcap_get_airpcap_handle(pcap_t *p);
+
+  #define MODE_CAPT 0
+  #define MODE_STAT 1
+  #define MODE_MON 2
 
 #elif defined(MSDOS)
 
-/*
- * MS-DOS definitions
- */
+  /*
+   * MS-DOS definitions
+   */
 
-int  pcap_stats_ex (pcap_t *, struct pcap_stat_ex *);
-void pcap_set_wait (pcap_t *p, void (*yield)(void), int wait);
-u_long pcap_mac_packets (void);
+  PCAP_API int  pcap_stats_ex (pcap_t *, struct pcap_stat_ex *);
+  PCAP_API void pcap_set_wait (pcap_t *p, void (*yield)(void), int wait);
+  PCAP_API u_long pcap_mac_packets (void);
 
 #else /* UN*X */
 
-/*
- * UN*X definitions
- */
+  /*
+   * UN*X definitions
+   */
 
-int	pcap_get_selectable_fd(pcap_t *);
+  PCAP_API int	pcap_get_selectable_fd(pcap_t *);
 
-#endif /* WIN32/MSDOS/UN*X */
+#endif /* _WIN32/MSDOS/UN*X */
+
+#ifdef HAVE_REMOTE
+  /* Includes most of the public stuff that is needed for the remote capture */
+  #include <remote-ext.h>
+#endif	 /* HAVE_REMOTE */
 
 #ifdef __cplusplus
 }
diff --git a/pcap/sll.h b/pcap/sll.h
index 38da29f..b46d15f 100644
--- a/pcap/sll.h
+++ b/pcap/sll.h
@@ -123,5 +123,7 @@
  */
 #define LINUX_SLL_P_802_3	0x0001	/* Novell 802.3 frames without 802.2 LLC header */
 #define LINUX_SLL_P_802_2	0x0004	/* 802.2 frames (not D/I/X Ethernet) */
+#define LINUX_SLL_P_CAN		0x000C	/* CAN frames, with SocketCAN pseudo-headers */
+#define LINUX_SLL_P_CANFD	0x000D	/* CAN FD frames, with SocketCAN pseudo-headers */
 
 #endif
diff --git a/pcap/usb.h b/pcap/usb.h
index 8395527..26a9046 100644
--- a/pcap/usb.h
+++ b/pcap/usb.h
@@ -31,8 +31,8 @@
  * By Paolo Abeni <paolo.abeni@email.it>
  */
 
-#ifndef _PCAP_USB_STRUCTS_H__
-#define _PCAP_USB_STRUCTS_H__
+#ifndef lib_pcap_usb_h
+#define lib_pcap_usb_h
 
 /*
  * possible transfer mode
diff --git a/pcap_activate.3pcap b/pcap_activate.3pcap
index 61887a7..8c89939 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 "21 September 2010"
+.TH PCAP_ACTIVATE 3PCAP "7 April 2014"
 .SH NAME
 pcap_activate \- activate a capture handle
 .SH SYNOPSIS
@@ -37,46 +37,65 @@
 being in effect.
 .SH RETURN VALUE
 .B pcap_activate()
-returns 0 on success without warnings,
+returns 0 on success without warnings, a non-zero positive value on
+success with warnings, and a negative value on error.
+A non-zero return value indicates what warning or error condition
+occurred.
+.LP
+The possible warning values are:
+.TP
 .B PCAP_WARNING_PROMISC_NOTSUP
-on success on a device that doesn't support promiscuous mode if
-promiscuous mode was requested,
+Promiscuous mode was requested, but the capture source doesn't support
+promiscuous mode.
+.TP
 .B PCAP_WARNING_TSTAMP_TYPE_NOTSUP
-on success if the time stamp type specified in a previous
+The time stamp type specified in a previous
 .B pcap_set_tstamp_type()
 call isn't supported by the capture source (the time stamp type is
 left as the default),
+.TP
 .B PCAP_WARNING
-on success with any other warning,
-.B PCAP_ERROR_ACTIVATED
-if the handle has already been activated,
-.B PCAP_ERROR_NO_SUCH_DEVICE
-if the capture source specified when the handle was created doesn't
-exist,
-.B PCAP_ERROR_PERM_DENIED
-if the process doesn't have permission to open the capture source,
-.B PCAP_ERROR_PROMISC_PERM_DENIED
-if the process has permission to open the capture source but doesn't
-have permission to put it into promiscuous mode,
-.B PCAP_ERROR_RFMON_NOTSUP
-if monitor mode was specified but the capture source doesn't support
-monitor mode,
-.B PCAP_ERROR_IFACE_NOT_UP
-if the capture source is not up, and
-.B PCAP_ERROR
-if another error occurred.
-If
-.B PCAP_WARNING
-or
-.B PCAP_ERROR
-is returned,
+Another warning condition occurred;
 .B pcap_geterr()
 or
 .B pcap_perror()
 may be called with
 .I p
-as an argument to fetch or display a message describing the warning or
-error.
+as an argument to fetch or display a message describing the warning
+condition.
+.LP
+The possible error values are:
+.TP
+.B PCAP_ERROR_ACTIVATED
+The handle has already been activated.
+.TP
+.B PCAP_ERROR_NO_SUCH_DEVICE
+The capture source specified when the handle was created doesn't
+exist.
+.TP
+.B PCAP_ERROR_PERM_DENIED
+The process doesn't have permission to open the capture source.
+.TP
+.B PCAP_ERROR_PROMISC_PERM_DENIED
+The process has permission to open the capture source but doesn't
+have permission to put it into promiscuous mode.
+.TP
+.B PCAP_ERROR_RFMON_NOTSUP
+Monitor mode was specified but the capture source doesn't support
+monitor mode.
+.TP
+.B PCAP_ERROR_IFACE_NOT_UP
+The capture source device is not up.
+.TP
+.B PCAP_ERROR
+Another error occurred.
+.B pcap_geterr()
+or
+.B pcap_perror()
+may be called with
+.I p
+as an argument to fetch or display a message describing the error.
+.LP
 If
 .BR PCAP_WARNING_PROMISC_NOTSUP ,
 .BR PCAP_ERROR_NO_SUCH_DEVICE ,
@@ -91,5 +110,13 @@
 as an argument to fetch or display an message giving additional details
 about the problem that might be useful for debugging the problem if it's
 unexpected.
+.LP
+Additional warning and error codes may be added in the future; a program
+should check for positive, negative, and zero return codes, and treat
+all positive return codes as warnings and all negative return
+codes as errors.
+.B pcap_statustostr()
+can be called, with a warning or error code as an argument, to fetch a
+message describing the warning or error code.
 .SH SEE ALSO
 pcap(3PCAP)
diff --git a/pcap_breakloop.3pcap b/pcap_breakloop.3pcap
index 6744924..3f9327b 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 "5 April 2008"
+.TH PCAP_BREAKLOOP 3PCAP "8 March 2015"
 .SH NAME
 pcap_breakloop \- force a pcap_dispatch() or pcap_loop() call to return
 .SH SYNOPSIS
diff --git a/pcap_can_set_rfmon.3pcap b/pcap_can_set_rfmon.3pcap
index b579804..389e50d 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 "18 May 2010"
+.TH PCAP_CAN_SET_RFMON 3PCAP "3 January 2014"
 .SH NAME
 pcap_can_set_rfmon \- check whether monitor mode can be set for a
 not-yet-activated capture handle
@@ -37,26 +37,36 @@
 .SH RETURN VALUE
 .B pcap_can_set_rfmon()
 returns 0 if monitor mode could not be set,
-1 if monitor mode could be set,
+1 if monitor mode could be set, and a negative value on error.
+A negative return value indicates what error condition occurred.
+The possible error values are:
+.TP
 .B PCAP_ERROR_NO_SUCH_DEVICE
-if the capture source specified when the handle was created doesn't
-exist,
+The capture source specified when the handle was created doesn't
+exist.
+.TP
 .B PCAP_ERROR_PERM_DENIED
-if the process doesn't have permission to check whether monitor mode
-could be supported,
+The process doesn't have permission to check whether monitor mode
+could be supported.
+.TP
 .B PCAP_ERROR_ACTIVATED
-if called on a capture handle that has been activated, or
+The capture handle has already been activated.
+.TP
 .B PCAP_ERROR
-if an error occurred.
-If
-.B PCAP_ERROR
-is returned,
+Another error occurred.
 .B pcap_geterr()
 or
 .B pcap_perror()
 may be called with
 .I p
-as an argument to fetch or display the error text.
+as an argument to fetch or display a message describing the error.
+.LP
+Additional error codes may be added in the future; a program should
+check for 0, 1, and negative, return codes, and treat all negative
+return codes as errors.
+.B pcap_statustostr()
+can be called, with a warning or error code as an argument, to fetch a
+message describing the warning or error code.
 .SH SEE ALSO
 pcap(3PCAP), pcap_create(3PCAP), pcap_activate(3PCAP),
 pcap_set_rfmon(3PCAP)
diff --git a/pcap_close.3pcap b/pcap_close.3pcap
index 91eb677..e2316a4 100644
--- a/pcap_close.3pcap
+++ b/pcap_close.3pcap
@@ -17,7 +17,7 @@
 .\" WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
 .\" MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
 .\"
-.TH PCAP_CLOSE 3PCAP "5 April 2008"
+.TH PCAP_CLOSE 3PCAP "3 January 2014"
 .SH NAME
 pcap_close \- close a capture device or savefile
 .SH SYNOPSIS
diff --git a/pcap_compile.3pcap b/pcap_compile.3pcap
new file mode 100644
index 0000000..6eb20be
--- /dev/null
+++ b/pcap_compile.3pcap
@@ -0,0 +1,70 @@
+.\" 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_COMPILE 3PCAP "7 April 2014"
+.SH NAME
+pcap_compile \- compile a filter expression
+.SH SYNOPSIS
+.nf
+.ft B
+#include <pcap/pcap.h>
+.ft
+.LP
+.ft B
+int pcap_compile(pcap_t *p, struct bpf_program *fp,
+.ti +8
+const char *str, int optimize, bpf_u_int32 netmask);
+.ft
+.fi
+.SH DESCRIPTION
+.B pcap_compile()
+is used to compile the string
+.I str
+into a filter program.  See
+.BR pcap-filter (7)
+for the syntax of that string.
+.I program
+is a pointer to a
+.I bpf_program
+struct and is filled in by
+.BR pcap_compile() .
+.I optimize
+controls whether optimization on the resulting code is performed.
+.I netmask
+specifies the IPv4 netmask of the network on which packets are being
+captured; it is used only when checking for IPv4 broadcast addresses in
+the filter program.  If the netmask of the network on which packets are
+being captured isn't known to the program, or if packets are being
+captured on the Linux "any" pseudo-interface that can capture on more
+than one network, a value of PCAP_NETMASK_UNKNOWN can be supplied; tests
+for IPv4 broadcast addresses will fail to compile, but all other tests in
+the filter program will be OK.
+.SH RETURN VALUE
+.B pcap_compile()
+returns 0 on success and \-1 on failure.
+If \-1 is returned,
+.B pcap_geterr()
+or
+.B pcap_perror()
+may be called with
+.I p
+as an argument to fetch or display the error text.
+.SH SEE ALSO
+pcap(3PCAP), pcap_setfilter(3PCAP), pcap_freecode(3PCAP),
+pcap_geterr(3PCAP), pcap-filter(7)
diff --git a/pcap_compile.3pcap.in b/pcap_compile.3pcap.in
index 0e5276a..2bd0eb4 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 "1 December 2009"
+.TH PCAP_COMPILE 3PCAP "7 April 2014"
 .SH NAME
 pcap_compile \- compile a filter expression
 .SH SYNOPSIS
diff --git a/pcap_create.3pcap b/pcap_create.3pcap
index 5c537fc..3040b3b 100644
--- a/pcap_create.3pcap
+++ b/pcap_create.3pcap
@@ -17,7 +17,7 @@
 .\" WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
 .\" MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
 .\"
-.TH PCAP_CREATE 3PCAP "5 April 2008"
+.TH PCAP_CREATE 3PCAP "3 January 2014"
 .SH NAME
 pcap_create \- create a live capture handle
 .SH SYNOPSIS
diff --git a/pcap_datalink.3pcap b/pcap_datalink.3pcap
new file mode 100644
index 0000000..4cb1007
--- /dev/null
+++ b/pcap_datalink.3pcap
@@ -0,0 +1,68 @@
+.\" Copyright (c) 1994, 1996, 1997
+.\"	The Regents of the University of California.  All rights reserved.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that: (1) source code distributions
+.\" retain the above copyright notice and this paragraph in its entirety, (2)
+.\" distributions including binary code include the above copyright notice and
+.\" this paragraph in its entirety in the documentation or other materials
+.\" provided with the distribution, and (3) all advertising materials mentioning
+.\" features or use of this software display the following acknowledgement:
+.\" ``This product includes software developed by the University of California,
+.\" Lawrence Berkeley Laboratory and its contributors.'' Neither the name of
+.\" the University nor the names of its contributors may be used to endorse
+.\" or promote products derived from this software without specific prior
+.\" written permission.
+.\" THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
+.\" WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
+.\" MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+.\"
+.TH PCAP_DATALINK 3PCAP "7 April 2014"
+.SH NAME
+pcap_datalink \- get the link-layer header type
+.SH SYNOPSIS
+.nf
+.ft B
+#include <pcap/pcap.h>
+.ft
+.LP
+.ft B
+int pcap_datalink(pcap_t *p);
+.ft
+.fi
+.SH DESCRIPTION
+.B pcap_datalink()
+returns the link-layer header type for the live capture or ``savefile''
+specified by
+.IR p .
+.PP
+It must not be called on a pcap descriptor created by
+.B pcap_create()
+that has not yet been activated by
+.BR pcap_activate() .
+.PP
+.I http://www.tcpdump.org/linktypes.html
+lists the values
+.B pcap_datalink()
+can return and describes the packet formats that
+correspond to those values.
+.PP
+Do
+.B NOT
+assume that the packets for a given capture or ``savefile`` will have
+any given link-layer header type, such as
+.B DLT_EN10MB
+for Ethernet.  For example, the "any" device on Linux will have a
+link-layer header type of
+.B DLT_LINUX_SLL
+even if all devices on the system at the time the "any" device is opened
+have some other data link type, such as
+.B DLT_EN10MB
+for Ethernet.
+.SH RETURN VALUE
+.B pcap_datalink()
+returns the link-layer header type on success and
+.B PCAP_ERROR_NOT_ACTIVATED
+if called on a capture handle that has been created but not activated.
+.SH SEE ALSO
+pcap(3PCAP), pcap-linktype(7)
diff --git a/pcap_datalink.3pcap.in b/pcap_datalink.3pcap.in
index b07fc28..be50a64 100644
--- a/pcap_datalink.3pcap.in
+++ b/pcap_datalink.3pcap.in
@@ -17,7 +17,7 @@
 .\" WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
 .\" MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
 .\"
-.TH PCAP_DATALINK 3PCAP "13 October 2013"
+.TH PCAP_DATALINK 3PCAP "7 April 2014"
 .SH NAME
 pcap_datalink \- get the link-layer header type
 .SH SYNOPSIS
diff --git a/pcap_datalink_name_to_val.3pcap b/pcap_datalink_name_to_val.3pcap
index 4bc1728..8a6905a 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 "22 August 2010"
+.TH PCAP_DATALINK_NAME_TO_VAL 3PCAP "5 December 2014"
 .SH NAME
 pcap_datalink_name_to_val \- get the link-layer header type value
 corresponding to a header type name
@@ -41,6 +41,7 @@
 translation is case-insensitive.
 .SH RETURN VALUE
 .B pcap_datalink_name_to_val()
-returns type value on success and \-1 on failure.
+returns the type value on success and \-1 if the name is not a known
+type name..
 .SH SEE ALSO
 pcap(3PCAP)
diff --git a/pcap_datalink_val_to_name.3pcap b/pcap_datalink_val_to_name.3pcap
index 0b17825..aa3e89a 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 "22 August 2010"
+.TH PCAP_DATALINK_VAL_TO_NAME 3PCAP "3 January 2014"
 .SH NAME
 pcap_datalink_val_to_name, pcap_datalink_val_to_description \- get a
 name or description for a link-layer header type value
@@ -35,12 +35,20 @@
 .SH DESCRIPTION
 .B pcap_datalink_val_to_name()
 translates a link-layer header type value to the corresponding
-link-layer header type name.
+link-layer header type name, which is the
+.B DLT_
+name for the link-layer header type value with the
+.B DLT_
+removed.
 .B NULL
-is returned on failure.
+is returned if the type value does not correspond to a known
+.B DLT_
+value.
 .PP
 .B pcap_datalink_val_to_description()
 translates a link-layer header type value to a short description of that
 link-layer header type.
 .B NULL
-is returned on failure.
+is returned if the type value does not correspond to a known
+.B DLT_
+value.
diff --git a/pcap_dump.3pcap b/pcap_dump.3pcap
index 95f3040..6402b4b 100644
--- a/pcap_dump.3pcap
+++ b/pcap_dump.3pcap
@@ -17,7 +17,7 @@
 .\" WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
 .\" MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
 .\"
-.TH PCAP_DUMP 3PCAP "5 April 2008"
+.TH PCAP_DUMP 3PCAP "8 March 2015"
 .SH NAME
 pcap_dump \- write a packet to a capture file
 .SH SYNOPSIS
diff --git a/pcap_dump_close.3pcap b/pcap_dump_close.3pcap
index afd00cb..bd95a52 100644
--- a/pcap_dump_close.3pcap
+++ b/pcap_dump_close.3pcap
@@ -17,7 +17,7 @@
 .\" WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
 .\" MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
 .\"
-.TH PCAP_DUMP_CLOSE 3PCAP "5 April 2008"
+.TH PCAP_DUMP_CLOSE 3PCAP "3 January 2014"
 .SH NAME
 pcap_dump_close \- close a savefile being written to
 .SH SYNOPSIS
diff --git a/pcap_dump_file.3pcap b/pcap_dump_file.3pcap
index 982b0dc..8fea610 100644
--- a/pcap_dump_file.3pcap
+++ b/pcap_dump_file.3pcap
@@ -17,7 +17,7 @@
 .\" WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
 .\" MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
 .\"
-.TH PCAP_DUMP_FILE 3PCAP "5 April 2008"
+.TH PCAP_DUMP_FILE 3PCAP "3 January 2014"
 .SH NAME
 pcap_dump_file \- get the standard I/O stream for a savefile being written
 .SH SYNOPSIS
diff --git a/pcap_dump_flush.3pcap b/pcap_dump_flush.3pcap
index ba98dee..c8f110b 100644
--- a/pcap_dump_flush.3pcap
+++ b/pcap_dump_flush.3pcap
@@ -17,7 +17,7 @@
 .\" WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
 .\" MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
 .\"
-.TH PCAP_DUMP_FLUSH 3PCAP "5 April 2008"
+.TH PCAP_DUMP_FLUSH 3PCAP "3 January 2014"
 .SH NAME
 pcap_dump_flush \- flush to a savefile packets dumped
 .SH SYNOPSIS
diff --git a/pcap_dump_ftell.3pcap b/pcap_dump_ftell.3pcap
index 6d5c828..757e948 100644
--- a/pcap_dump_ftell.3pcap
+++ b/pcap_dump_ftell.3pcap
@@ -17,7 +17,7 @@
 .\" WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
 .\" MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
 .\"
-.TH PCAP_DUMP_FTELL 3PCAP "5 April 2008"
+.TH PCAP_DUMP_FTELL 3PCAP "3 January 2014"
 .SH NAME
 pcap_dump_ftell \- get the current file offset for a savefile being written
 .SH SYNOPSIS
diff --git a/pcap_dump_open.3pcap b/pcap_dump_open.3pcap
new file mode 100644
index 0000000..fd96aab
--- /dev/null
+++ b/pcap_dump_open.3pcap
@@ -0,0 +1,96 @@
+.\" 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_DUMP_OPEN 3PCAP "16 February 2015"
+.SH NAME
+pcap_dump_open, pcap_dump_fopen \- open a file to which to write packets
+.SH SYNOPSIS
+.nf
+.ft B
+#include <pcap/pcap.h>
+.ft
+.nf
+.LP
+.ft B
+pcap_dumper_t *pcap_dump_open(pcap_t *p, const char *fname);
+pcap_dumper_t *pcap_dump_open_append(pcap_t *p, const char *fname);
+pcap_dumper_t *pcap_dump_fopen(pcap_t *p, FILE *fp);
+.ft
+.fi
+.SH DESCRIPTION
+.B pcap_dump_open()
+is called to open a ``savefile'' for writing.
+.I fname
+specifies the name of the file to open. The file will have
+the same format as those used by
+.BR tcpdump (1)
+and
+.BR tcpslice (1).
+The name "-" is a synonym
+for
+.BR stdout .
+.PP
+.B pcap_dump_fopen()
+is called to write data to an existing open stream
+.IR fp .
+Note that on Windows, that stream should be opened in binary mode.
+.PP
+.I p
+is a capture or ``savefile'' handle returned by an earlier call to
+.B pcap_create()
+and activated by an earlier call to
+.BR pcap_activate() ,
+or returned by an earlier call to
+.BR pcap_open_offline() ,
+.BR pcap_open_live() ,
+or
+.BR pcap_open_dead() .
+The time stamp precision, link-layer type, and snapshot length from
+.I p
+are used as the link-layer type and snapshot length of the output file.
+.PP
+.B pcap_dump_open_append()
+is like
+.B pcap_dump_open
+but does not create the file if it does not exist and, if it does
+already exist, and is a pcap file with the same byte order as the host
+opening the file, and has the same time stamp precision, link-layer
+header type, and snapshot length as
+.IR p ,
+it will write new packets at the end of the file.
+.SH RETURN VALUES
+A pointer to a
+.B pcap_dumper_t
+structure to use in subsequent
+.B pcap_dump()
+and
+.B pcap_dump_close()
+calls is returned on success.
+.B NULL
+is returned on failure.
+If
+.B NULL
+is returned,
+.B pcap_geterr(\fIp\fB)
+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_dump(3PCAP), pcap_dump_close(3PCAP), pcap_geterr(3PCAP),
+pcap-savefile(5)
diff --git a/pcap_dump_open.3pcap.in b/pcap_dump_open.3pcap.in
index 0b2e3c6..3f91d13 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 "5 April 2008"
+.TH PCAP_DUMP_OPEN 3PCAP "16 February 2015"
 .SH NAME
 pcap_dump_open, pcap_dump_fopen \- open a file to which to write packets
 .SH SYNOPSIS
diff --git a/pcap_file.3pcap b/pcap_file.3pcap
index 7b18c81..cd6b06b 100644
--- a/pcap_file.3pcap
+++ b/pcap_file.3pcap
@@ -17,7 +17,7 @@
 .\" WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
 .\" MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
 .\"
-.TH PCAP_FILE 3PCAP "5 April 2008"
+.TH PCAP_FILE 3PCAP "3 January 2014"
 .SH NAME
 pcap_file \- get the standard I/O stream for a savefile being read
 .SH SYNOPSIS
diff --git a/pcap_fileno.3pcap b/pcap_fileno.3pcap
index 39d068b..7aeb069 100644
--- a/pcap_fileno.3pcap
+++ b/pcap_fileno.3pcap
@@ -17,7 +17,7 @@
 .\" WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
 .\" MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
 .\"
-.TH PCAP_FILENO 3PCAP "3 November 2009"
+.TH PCAP_FILENO 3PCAP "7 April 2014"
 .SH NAME
 pcap_fileno \- get the file descriptor for a live capture
 .SH SYNOPSIS
diff --git a/pcap_findalldevs.3pcap b/pcap_findalldevs.3pcap
index 00bb911..2dd3e59 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 "10 January 2014"
+.TH PCAP_FINDALLDEVS 3PCAP "7 April 2014"
 .SH NAME
 pcap_findalldevs, pcap_freealldevs \- get a list of capture devices, and
 free that list
diff --git a/pcap_freecode.3pcap b/pcap_freecode.3pcap
index c3c3ea6..fac4b3d 100644
--- a/pcap_freecode.3pcap
+++ b/pcap_freecode.3pcap
@@ -17,7 +17,7 @@
 .\" WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
 .\" MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
 .\"
-.TH PCAP_FREECODE 3PCAP "5 April 2008"
+.TH PCAP_FREECODE 3PCAP "3 January 2014"
 .SH NAME
 pcap_freecode \- free a BPF program
 .SH SYNOPSIS
diff --git a/pcap_get_selectable_fd.3pcap b/pcap_get_selectable_fd.3pcap
index 6640577..86b0c26 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 "22 July 2011"
+.TH PCAP_GET_SELECTABLE_FD 3PCAP "18 October 2014"
 .SH NAME
 pcap_get_selectable_fd \- get a file descriptor on which a select() can
 be done for a live capture
diff --git a/pcap_get_tstamp_precision.3pcap b/pcap_get_tstamp_precision.3pcap
new file mode 100644
index 0000000..709147a
--- /dev/null
+++ b/pcap_get_tstamp_precision.3pcap
@@ -0,0 +1,52 @@
+.\"Copyright (c) 2013, Michal Sekletar
+.\"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 names of the authors may not be used to endorse or promote
+.\"     products derived from this software without specific prior
+.\"     written permission.
+.\"
+.\"THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
+.\"IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
+.\"WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+
+.TH PCAP_GET_TSTAMP_PRECISION 3PCAP "18 December 2013"
+.SH NAME
+pcap_get_tstamp_precision \- get the time stamp precision returned in
+captures
+.SH SYNOPSIS
+.nf
+.ft B
+#include <pcap/pcap.h>
+.ft
+.LP
+.ft B
+int pcap_get_tstamp_precision(pcap_t *p);
+.ft
+.fi
+.SH DESCRIPTION
+.B pcap_get_tstamp_precision()
+returns the precision of the time stamp returned in packet captures on the pcap
+descriptor.
+.SH RETURN VALUE
+.B pcap_get_tstamp_precision()
+returns
+.B PCAP_TSTAMP_PRECISION_MICRO
+or
+.BR PCAP_TSTAMP_PRECISION_NANO ,
+which indicates
+that pcap captures contains time stamps in microseconds or nanoseconds
+respectively.
+.SH SEE ALSO
+pcap(3PCAP),
+pcap_set_tstamp_precision(3PCAP),
+pcap-tstamp(7)
diff --git a/pcap_get_tstamp_precision.3pcap.in b/pcap_get_tstamp_precision.3pcap.in
index 656c142..285e770 100644
--- a/pcap_get_tstamp_precision.3pcap.in
+++ b/pcap_get_tstamp_precision.3pcap.in
@@ -19,7 +19,7 @@
 .\"IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
 .\"WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
 
-.TH PCAP_GET_TSTAMP_PRECISION 3PCAP "27 August 2013"
+.TH PCAP_GET_TSTAMP_PRECISION 3PCAP "18 December 2013"
 .SH NAME
 pcap_get_tstamp_precision \- get the time stamp precision returned in
 captures
diff --git a/pcap_geterr.3pcap b/pcap_geterr.3pcap
index fcabec3..2e99c37 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 "5 April 2008"
+.TH PCAP_GETERR 3PCAP "3 January 2014"
 .SH NAME
 pcap_geterr, pcap_perror \- get or print libpcap error message text
 .SH SYNOPSIS
@@ -28,7 +28,7 @@
 .LP
 .ft B
 char *pcap_geterr(pcap_t *p);
-void pcap_perror(pcap_t *p, char *prefix);
+void pcap_perror(pcap_t *p, const char *prefix);
 .ft
 .fi
 .SH DESCRIPTION
diff --git a/pcap_inject.3pcap b/pcap_inject.3pcap
index 7ccdf2c..ff9792d 100644
--- a/pcap_inject.3pcap
+++ b/pcap_inject.3pcap
@@ -17,7 +17,7 @@
 .\" WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
 .\" MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
 .\"
-.TH PCAP_INJECT 3PCAP "5 April 2008"
+.TH PCAP_INJECT 3PCAP "3 January 2014"
 .SH NAME
 pcap_inject, pcap_sendpacket \- transmit a packet
 .SH SYNOPSIS
diff --git a/pcap_is_swapped.3pcap b/pcap_is_swapped.3pcap
index a120616..c4e62ae 100644
--- a/pcap_is_swapped.3pcap
+++ b/pcap_is_swapped.3pcap
@@ -17,7 +17,7 @@
 .\" WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
 .\" MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
 .\"
-.TH PCAP_IS_SWAPPED 3PCAP "17 September 2013"
+.TH PCAP_IS_SWAPPED 3PCAP "7 April 2014"
 .SH NAME
 pcap_is_swapped \- find out whether a savefile has the native byte order
 .SH SYNOPSIS
diff --git a/pcap_lib_version.3pcap b/pcap_lib_version.3pcap
index 3ec2e32..4b86b2d 100644
--- a/pcap_lib_version.3pcap
+++ b/pcap_lib_version.3pcap
@@ -17,7 +17,7 @@
 .\" WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
 .\" MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
 .\"
-.TH PCAP_LIB_VERSION 3PCAP "5 April 2008"
+.TH PCAP_LIB_VERSION 3PCAP "3 January 2014"
 .SH NAME
 pcap_lib_version \- get the version information for libpcap
 .SH SYNOPSIS
diff --git a/pcap_list_datalinks.3pcap b/pcap_list_datalinks.3pcap
new file mode 100644
index 0000000..1fde73d
--- /dev/null
+++ b/pcap_list_datalinks.3pcap
@@ -0,0 +1,73 @@
+.\" 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_LIST_DATALINKS 3PCAP "8 March 2015"
+.SH NAME
+pcap_list_datalinks, pcap_free_datalinks \- get a list of link-layer header
+types supported by a capture device, and free that list
+.SH SYNOPSIS
+.nf
+.ft B
+#include <pcap/pcap.h>
+.ft
+.LP
+.ft B
+int pcap_list_datalinks(pcap_t *p, int **dlt_buf);
+void pcap_free_datalinks(int *dlt_list);
+.ft
+.fi
+.SH DESCRIPTION
+.B pcap_list_datalinks()
+is used to get a list of the supported link-layer header types of the
+interface associated with the pcap descriptor.
+.B pcap_list_datalinks()
+allocates an array to hold the list and sets
+.IR *dlt_buf
+to point to that array.
+.LP
+The caller is responsible for freeing the array with
+.BR pcap_free_datalinks() ,
+which frees the list of link-layer header types pointed to by
+.IR dlt_list .
+.LP
+It must not be called on a pcap descriptor created by
+.B pcap_create()
+that has not yet been activated by
+.BR pcap_activate() .
+.SH RETURN VALUE
+.B pcap_list_datalinks()
+returns the number of link-layer header types in the array on success,
+.B PCAP_ERROR_NOT_ACTIVATED
+if called on a capture handle that has been created but not activated,
+and
+.B PCAP_ERROR
+(\-1) on other errors.
+If
+.B PCAP_ERROR
+is returned,
+.B pcap_geterr()
+or
+.B pcap_perror()
+may be called with
+.I p
+as an argument to fetch or display the error text.
+.SH SEE ALSO
+pcap(3PCAP), pcap_geterr(3PCAP),
+pcap_datalink_val_to_name(3PCAP),
+pcap-linktype(7)
diff --git a/pcap_list_datalinks.3pcap.in b/pcap_list_datalinks.3pcap.in
index f849346..9f52b63 100644
--- a/pcap_list_datalinks.3pcap.in
+++ b/pcap_list_datalinks.3pcap.in
@@ -17,7 +17,7 @@
 .\" WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
 .\" MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
 .\"
-.TH PCAP_LIST_DATALINKS 3PCAP "17 September 2013"
+.TH PCAP_LIST_DATALINKS 3PCAP "8 March 2015"
 .SH NAME
 pcap_list_datalinks, pcap_free_datalinks \- get a list of link-layer header
 types supported by a capture device, and free that list
diff --git a/pcap_list_tstamp_types.3pcap b/pcap_list_tstamp_types.3pcap
new file mode 100644
index 0000000..4afa36f
--- /dev/null
+++ b/pcap_list_tstamp_types.3pcap
@@ -0,0 +1,70 @@
+.\"
+.\" 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_LIST_TSTAMP_TYPES 3PCAP "22 August 2010"
+.SH NAME
+pcap_list_tstamp_types, pcap_free_tstamp_types \- get a list of time
+stamp types supported by a capture device, and free that list
+.SH SYNOPSIS
+.nf
+.ft B
+#include <pcap/pcap.h>
+.ft
+.LP
+.ft B
+int pcap_list_tstamp_types(pcap_t *p, int **tstamp_typesp);
+void pcap_free_tstamp_types(int *tstamp_types);
+.ft
+.fi
+.SH DESCRIPTION
+.B pcap_list_tstamp_types()
+is used to get a list of the supported time stamp types of the interface
+associated with the pcap descriptor.
+.B pcap_list_tstamp_types()
+allocates an array to hold the list and sets
+.I *tstamp_typesp
+to point to the array.
+See
+.BR pcap-tstamp (7)
+for a list of all the time stamp types.
+.PP
+The caller is responsible for freeing the array with
+.BR pcap_free_tstamp_types() ,
+which frees the list pointed to by
+.IR tstamp_types .
+.SH RETURN VALUE
+.B pcap_list_tstamp_types()
+returns the number of time stamp types in the array on success and
+.B PCAP_ERROR
+on failure.
+A return value of zero means that you cannot specify a time stamp type;
+you are limited to the capture device's default time stamp type.
+If
+.B PCAP_ERROR
+is returned,
+.B pcap_geterr()
+or
+.B pcap_perror()
+may be called with
+.I p
+as an argument to fetch or display the error text.
+.SH SEE ALSO
+pcap(3PCAP), pcap_geterr(3PCAP), pcap_tstamp_type_val_to_name(3PCAP),
+pcap-tstamp(7)
diff --git a/pcap_list_tstamp_types.3pcap.in b/pcap_list_tstamp_types.3pcap.in
index 66d3d66..a139324 100644
--- a/pcap_list_tstamp_types.3pcap.in
+++ b/pcap_list_tstamp_types.3pcap.in
@@ -18,7 +18,7 @@
 .\" WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
 .\" MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
 .\"
-.TH PCAP_LIST_TSTAMP_TYPES 3PCAP "21 August 2010"
+.TH PCAP_LIST_TSTAMP_TYPES 3PCAP "22 August 2010"
 .SH NAME
 pcap_list_tstamp_types, pcap_free_tstamp_types \- get a list of time
 stamp types supported by a capture device, and free that list
diff --git a/pcap_lookupdev.3pcap b/pcap_lookupdev.3pcap
index 79dda42..aaa3a20 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 "5 April 2008"
+.TH PCAP_LOOKUPDEV 3PCAP "3 January 2014"
 .SH NAME
 pcap_lookupdev \- find the default device on which to capture
 .SH SYNOPSIS
diff --git a/pcap_lookupnet.3pcap b/pcap_lookupnet.3pcap
index a3d14ae..c38ff3a 100644
--- a/pcap_lookupnet.3pcap
+++ b/pcap_lookupnet.3pcap
@@ -17,7 +17,7 @@
 .\" WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
 .\" MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
 .\"
-.TH PCAP_LOOKUPNET 3PCAP "5 April 2008"
+.TH PCAP_LOOKUPNET 3PCAP "3 January 2014"
 .SH NAME
 pcap_lookupnet \- find the IPv4 network number and netmask for a device
 .SH SYNOPSIS
diff --git a/pcap_loop.3pcap b/pcap_loop.3pcap
index 011d85c..0eaf6e5 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 "13 October 2013"
+.TH PCAP_LOOP 3PCAP "18 October 2014"
 .SH NAME
 pcap_loop, pcap_dispatch \- process packets from a live capture or savefile
 .SH SYNOPSIS
diff --git a/pcap_major_version.3pcap b/pcap_major_version.3pcap
index a085838..8334e16 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 "21 December 2011"
+.TH PCAP_MAJOR_VERSION 3PCAP "7 April 2014"
 .SH NAME
 pcap_major_version, pcap_minor_version \- get the version number of a savefile
 .SH SYNOPSIS
diff --git a/pcap_next_ex.3pcap b/pcap_next_ex.3pcap
index c310c2f..d69e728 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 "13 October 2013"
+.TH PCAP_NEXT_EX 3PCAP "7 April 2014"
 .SH NAME
 pcap_next_ex, pcap_next \- read the next packet from a pcap_t
 .SH SYNOPSIS
diff --git a/pcap_offline_filter.3pcap b/pcap_offline_filter.3pcap
index b471c6a..08c0b66 100644
--- a/pcap_offline_filter.3pcap
+++ b/pcap_offline_filter.3pcap
@@ -17,7 +17,7 @@
 .\" WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
 .\" MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
 .\"
-.TH PCAP_OFFLINE_FILTER 3PCAP "25 November 2012"
+.TH PCAP_OFFLINE_FILTER 3PCAP "7 April 2014"
 .SH NAME
 pcap_offline_filter \- check whether a filter matches a packet
 .SH SYNOPSIS
diff --git a/pcap_open_dead.3pcap b/pcap_open_dead.3pcap
new file mode 100644
index 0000000..4a75c32
--- /dev/null
+++ b/pcap_open_dead.3pcap
@@ -0,0 +1,79 @@
+.\" 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_OPEN_DEAD 3PCAP "3 January 2014"
+.SH NAME
+pcap_open_dead, pcap_open_dead_with_tstamp_precision \- open a fake
+pcap_t for compiling filters or opening a capture for output
+.SH SYNOPSIS
+.nf
+.ft B
+#include <pcap/pcap.h>
+.ft
+.LP
+.ft B
+pcap_t *pcap_open_dead(int linktype, int snaplen);
+pcap_t *pcap_open_dead_with_tstamp_precision(int linktype, int snaplen,
+    u_int precision);
+.ft
+.fi
+.SH DESCRIPTION
+.PP
+.B pcap_open_dead()
+and
+.B pcap_open_dead_with_tstamp_precision()
+are used for creating a
+.B pcap_t
+structure to use when calling the other functions in libpcap.  It is
+typically used when just using libpcap for compiling BPF code; it can
+also be used if using
+.BR pcap_dump_open() ,
+.BR pcap_dump() ,
+and
+.B pcap_dump_close()
+to write a savefile if there is no
+.B pcap_t
+that supplies the packets to be written.
+.PP
+.I linktype
+specifies the link-layer type for the
+.BR pcap_t .
+.PP
+.I snaplen
+specifies the snapshot length for the
+.BR pcap_t .
+.PP
+When
+.BR pcap_open_dead_with_tstamp_precision() ,
+is used to create a
+.B pcap_t
+for use with
+.BR pcap_dump_open() ,
+.I precision
+specifies the time stamp precision for packets;
+.B PCAP_TSTAMP_PRECISION_MICRO
+should be specified if the packets to be written have time stamps in
+seconds and microseconds, and
+.B PCAP_TSTAMP_PRECISION_NANO
+should be specified if the packets to be written have time stamps in
+seconds and nanoseconds.  Its value does not affect
+.BR pcap_compile() .
+.SH SEE ALSO
+pcap(3PCAP), pcap_compile(3PCAP), pcap_dump_open(3PCAP),
+pcap-linktype(7)
diff --git a/pcap_open_dead.3pcap.in b/pcap_open_dead.3pcap.in
index 2d1b48c..a3dc592 100644
--- a/pcap_open_dead.3pcap.in
+++ b/pcap_open_dead.3pcap.in
@@ -17,7 +17,7 @@
 .\" WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
 .\" MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
 .\"
-.TH PCAP_OPEN_DEAD 3PCAP "1 July 2013"
+.TH PCAP_OPEN_DEAD 3PCAP "3 January 2014"
 .SH NAME
 pcap_open_dead, pcap_open_dead_with_tstamp_precision \- open a fake
 pcap_t for compiling filters or opening a capture for output
diff --git a/pcap_open_live.3pcap b/pcap_open_live.3pcap
index 715994b..8c5d474 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 "5 April 2008"
+.TH PCAP_OPEN_LIVE 3PCAP "3 January 2014"
 .SH NAME
 pcap_open_live \- open a device for capturing
 .SH SYNOPSIS
diff --git a/pcap_open_offline.3pcap b/pcap_open_offline.3pcap
new file mode 100644
index 0000000..996572a
--- /dev/null
+++ b/pcap_open_offline.3pcap
@@ -0,0 +1,109 @@
+.\" 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_OPEN_OFFLINE 3PCAP "3 January 2014"
+.SH NAME
+pcap_open_offline, pcap_open_offline_with_tstamp_precision,
+pcap_fopen_offline, pcap_fopen_offline_with_tstamp_precision \- open a saved capture file for reading
+.SH SYNOPSIS
+.nf
+.ft B
+#include <pcap/pcap.h>
+.ft
+.LP
+.nf
+.ft B
+char errbuf[PCAP_ERRBUF_SIZE];
+.ft
+.LP
+.ft B
+pcap_t *pcap_open_offline(const char *fname, char *errbuf);
+pcap_t *pcap_open_offline_with_tstamp_precision(const char *fname,
+    u_int precision, char *errbuf);
+pcap_t *pcap_fopen_offline(FILE *fp, char *errbuf);
+pcap_t *pcap_fopen_offline_with_tstamp_precision(FILE *fp,
+    u_int precision, char *errbuf);
+.ft
+.fi
+.SH DESCRIPTION
+.B pcap_open_offline()
+and
+.B pcap_open_offline_with_tstamp_precision()
+are called to open a ``savefile'' for reading.
+.PP
+.I fname
+specifies the name of the file to open. The file can have the pcap file
+format as described in
+.BR pcap-savefile (5),
+which is the file format used by, among other programs,
+.BR tcpdump (1)
+and
+.BR tcpslice (1),
+or can have the pcap-ng file format, although not all pcap-ng files can
+be read.
+The name "-" is a synonym for
+.BR stdin .
+.PP
+.B pcap_open_offline_with_tstamp_precision()
+takes an additional
+.I precision
+argument specifying the time stamp precision desired;
+if
+.B PCAP_TSTAMP_PRECISION_MICRO
+is specified, packet time stamps will be supplied in seconds and
+microseconds,
+and if
+.B PCAP_TSTAMP_PRECISION_NANO
+is specified, packet time stamps will be supplied in seconds and
+nanoseconds.  If the time stamps in the file do not have the same
+precision as the requested precision, they will be scaled up or down as
+necessary before being supplied.
+.PP
+Alternatively, you may call
+.B pcap_fopen_offline()
+or
+.B pcap_fopen_offline_with_tstamp_precision()
+to read dumped data from an existing open stream
+.IR fp .
+.B pcap_fopen_offline_with_tstamp_precision() takes an additional
+.I precision
+argument as described above.
+Note that on Windows, that stream should be opened in binary mode.
+.SH RETURN VALUE
+.BR pcap_open_offline() ,
+.BR pcap_open_offline_with_tstamp_precision() ,
+.BR pcap_fopen_offline() ,
+and
+.B pcap_fopen_offline_with_tstamp_precision()
+return a
+.I pcap_t *
+on success and
+.B NULL
+on failure.
+If
+.B NULL
+is returned,
+.I errbuf
+is filled in with an appropriate error message.
+.I errbuf
+is assumed to be able to hold at least
+.B PCAP_ERRBUF_SIZE
+chars.
+.SH SEE ALSO
+pcap(3PCAP), pcap-savefile(5)
diff --git a/pcap_open_offline.3pcap.in b/pcap_open_offline.3pcap.in
index 7239729..7fe551e 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 "1 July 2013"
+.TH PCAP_OPEN_OFFLINE 3PCAP "3 January 2014"
 .SH NAME
 pcap_open_offline, pcap_open_offline_with_tstamp_precision,
 pcap_fopen_offline, pcap_fopen_offline_with_tstamp_precision \- open a saved capture file for reading
diff --git a/pcap_set_buffer_size.3pcap b/pcap_set_buffer_size.3pcap
index fea1df7..684f739 100644
--- a/pcap_set_buffer_size.3pcap
+++ b/pcap_set_buffer_size.3pcap
@@ -17,7 +17,7 @@
 .\" WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
 .\" MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
 .\"
-.TH PCAP_SET_BUFFER_SIZE 3PCAP "5 April 2008"
+.TH PCAP_SET_BUFFER_SIZE 3PCAP "3 January 2014"
 .SH NAME
 pcap_set_buffer_size \- set the buffer size for a not-yet-activated
 capture handle
diff --git a/pcap_set_datalink.3pcap b/pcap_set_datalink.3pcap
index 60a7bfc..24d57a5 100644
--- a/pcap_set_datalink.3pcap
+++ b/pcap_set_datalink.3pcap
@@ -17,7 +17,7 @@
 .\" WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
 .\" MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
 .\"
-.TH PCAP_SET_DATALINK 3PCAP "22 August 2010"
+.TH PCAP_SET_DATALINK 3PCAP "3 January 2014"
 .SH NAME
 pcap_set_datalink \- set the link-layer header type to be used by a
 capture device
diff --git a/pcap_set_immediate_mode.3pcap b/pcap_set_immediate_mode.3pcap
index 87ec98b..b3ad243 100644
--- a/pcap_set_immediate_mode.3pcap
+++ b/pcap_set_immediate_mode.3pcap
@@ -18,7 +18,7 @@
 .\" WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
 .\" MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
 .\"
-.TH PCAP_SET_IMMEDIATE_MODE 3PCAP "8 May 2013"
+.TH PCAP_SET_IMMEDIATE_MODE 3PCAP "5 December 2013"
 .SH NAME
 pcap_set_immediate_mode \- set immediate mode for a not-yet-activated capture
 handle
diff --git a/pcap_set_promisc.3pcap b/pcap_set_promisc.3pcap
index 5d17572..fcd797a 100644
--- a/pcap_set_promisc.3pcap
+++ b/pcap_set_promisc.3pcap
@@ -17,7 +17,7 @@
 .\" WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
 .\" MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
 .\"
-.TH PCAP_SET_PROMISC 3PCAP "5 April 2008"
+.TH PCAP_SET_PROMISC 3PCAP "3 January 2014"
 .SH NAME
 pcap_set_promisc \- set promiscuous mode for a not-yet-activated
 capture handle
diff --git a/pcap_set_rfmon.3pcap b/pcap_set_rfmon.3pcap
index a386e8b..691518a 100644
--- a/pcap_set_rfmon.3pcap
+++ b/pcap_set_rfmon.3pcap
@@ -17,7 +17,7 @@
 .\" WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
 .\" MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
 .\"
-.TH PCAP_SET_RFMON 3PCAP "5 April 2008"
+.TH PCAP_SET_RFMON 3PCAP "3 January 2014"
 .SH NAME
 pcap_set_rfmon \- set monitor mode for a not-yet-activated capture
 handle
diff --git a/pcap_set_snaplen.3pcap b/pcap_set_snaplen.3pcap
index 8080ea1..44eb154 100644
--- a/pcap_set_snaplen.3pcap
+++ b/pcap_set_snaplen.3pcap
@@ -17,7 +17,7 @@
 .\" WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
 .\" MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
 .\"
-.TH PCAP_SET_SNAPLEN 3PCAP "5 April 2008"
+.TH PCAP_SET_SNAPLEN 3PCAP "3 January 2014"
 .SH NAME
 pcap_set_snaplen \- set the snapshot length for a not-yet-activated
 capture handle
diff --git a/pcap_set_timeout.3pcap b/pcap_set_timeout.3pcap
index b728203..a89327f 100644
--- a/pcap_set_timeout.3pcap
+++ b/pcap_set_timeout.3pcap
@@ -17,7 +17,7 @@
 .\" WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
 .\" MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
 .\"
-.TH PCAP_SET_TIMEOUT 3PCAP "16 April 2014"
+.TH PCAP_SET_TIMEOUT 3PCAP "1 December 2015"
 .SH NAME
 pcap_set_timeout \- set the read timeout for a not-yet-activated
 capture handle
@@ -36,10 +36,15 @@
 the handle is activated to
 .IR to_ms ,
 which is in units of milliseconds.
+.LP
+The behavior, if the timeout isn't specified, is undefined.  We
+recommend always setting the timeout to a non-zero value unless
+immediate mode is set, in which case the timeout has no effect.
 .SH RETURN VALUE
 .B pcap_set_timeout()
 returns 0 on success or
 .B PCAP_ERROR_ACTIVATED
 if called on a capture handle that has been activated.
 .SH SEE ALSO
-pcap(3PCAP), pcap_create(3PCAP), pcap_activate(3PCAP)
+pcap(3PCAP), pcap_create(3PCAP), pcap_activate(3PCAP),
+pcap_set_immediate_mode(3PCAP)
diff --git a/pcap_set_tstamp_precision.3pcap b/pcap_set_tstamp_precision.3pcap
new file mode 100644
index 0000000..773aa32
--- /dev/null
+++ b/pcap_set_tstamp_precision.3pcap
@@ -0,0 +1,61 @@
+.\"Copyright (c) 2013, Michal Sekletar
+.\"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 names of the authors may not be used to endorse or promote
+.\"     products derived from this software without specific prior
+.\"     written permission.
+.\"
+.\"THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
+.\"IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
+.\"WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+
+.TH PCAP_SET_TSTAMP_PRECISION 3PCAP "5 February 2015"
+.SH NAME
+pcap_set_tstamp_precision \- set the time stamp precision returned in
+captures
+.SH SYNOPSIS
+.nf
+.ft B
+#include <pcap/pcap.h>
+.ft
+.LP
+.ft B
+int pcap_set_tstamp_precision(pcap_t *p, int tstamp_precision);
+.ft
+.fi
+.SH DESCRIPTION
+.B pcap_set_tstamp_precision()
+sets the precision of the time stamp desired for packets captured on the pcap
+descriptor to the type specified by
+.IR tstamp_precision .
+It must be called on a pcap descriptor created by
+.B pcap_create()
+that has not yet been activated by
+.BR pcap_activate() .
+Two time stamp precisions are supported, microseconds and nanoseconds. One can
+use options
+.B PCAP_TSTAMP_PRECISION_MICRO and
+.B PCAP_TSTAMP_PRECISION_NANO
+to request desired precision. By default, time stamps are in microseconds.
+.SH RETURN VALUE
+.B pcap_set_tstamp_precision()
+returns 0 on success if the specified time stamp precision is expected to be
+supported by the operating system,
+.B PCAP_ERROR_TSTAMP_PRECISION_NOTSUP
+if operating system does not support requested time stamp precision,
+.B PCAP_ERROR_ACTIVATED
+if called on a capture handle that has been activated.
+.SH SEE ALSO
+pcap(3PCAP),
+pcap_get_tstamp_precision(3PCAP),
+pcap-tstamp(7)
diff --git a/pcap_set_tstamp_precision.3pcap.in b/pcap_set_tstamp_precision.3pcap.in
index 85fa84d..57c4ea3 100644
--- a/pcap_set_tstamp_precision.3pcap.in
+++ b/pcap_set_tstamp_precision.3pcap.in
@@ -19,7 +19,7 @@
 .\"IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
 .\"WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
 
-.TH PCAP_SET_TSTAMP_PRECISION 3PCAP "27 August 2013"
+.TH PCAP_SET_TSTAMP_PRECISION 3PCAP "5 February 2015"
 .SH NAME
 pcap_set_tstamp_precision \- set the time stamp precision returned in
 captures
diff --git a/pcap_set_tstamp_type.3pcap b/pcap_set_tstamp_type.3pcap
new file mode 100644
index 0000000..8a3bda0
--- /dev/null
+++ b/pcap_set_tstamp_type.3pcap
@@ -0,0 +1,65 @@
+.\"
+.\" 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_TSTAMP_TYPE 3PCAP "5 December 2014"
+.SH NAME
+pcap_set_tstamp_type \- set the time stamp type to be used by a
+capture device
+.SH SYNOPSIS
+.nf
+.ft B
+#include <pcap/pcap.h>
+.ft
+.LP
+.ft B
+int pcap_set_tstamp_type(pcap_t *p, int tstamp_type);
+.ft
+.fi
+.SH DESCRIPTION
+.B pcap_set_tstamp_type()
+sets the the type of time stamp desired for packets captured on the pcap
+descriptor to the type specified by
+.IR tstamp_type .
+It must be called on a pcap descriptor created by
+.B pcap_create()
+that has not yet been activated by
+.BR pcap_activate() .
+.B pcap_list_tstamp_types()
+will give a list of the time stamp types supported by a given capture
+device.
+See
+.BR pcap-tstamp (7)
+for a list of all the time stamp types.
+.SH RETURN VALUE
+.B pcap_set_tstamp_type()
+returns 0 on success if the specified time stamp type is expected to be
+supported by the capture device,
+.B PCAP_WARNING_TSTAMP_TYPE_NOTSUP
+if the specified time stamp type is not supported by the
+capture device,
+.B PCAP_ERROR_ACTIVATED
+if called on a capture handle that has been activated, and
+.B PCAP_ERROR_CANTSET_TSTAMP_TYPE
+if the capture device doesn't support setting the time stamp type.
+.SH SEE ALSO
+pcap(3PCAP),
+pcap_list_tstamp_types(3PCAP),
+pcap_tstamp_type_name_to_val(3PCAP),
+pcap-tstamp(7)
diff --git a/pcap_set_tstamp_type.3pcap.in b/pcap_set_tstamp_type.3pcap.in
index fd673bd..e58cdd4 100644
--- a/pcap_set_tstamp_type.3pcap.in
+++ b/pcap_set_tstamp_type.3pcap.in
@@ -18,7 +18,7 @@
 .\" WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
 .\" MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
 .\"
-.TH PCAP_SET_TSTAMP_TYPE 3PCAP "21 August 2010"
+.TH PCAP_SET_TSTAMP_TYPE 3PCAP "5 December 2014"
 .SH NAME
 pcap_set_tstamp_type \- set the time stamp type to be used by a
 capture device
diff --git a/pcap_setdirection.3pcap b/pcap_setdirection.3pcap
index 871a5b0..11945f5 100644
--- a/pcap_setdirection.3pcap
+++ b/pcap_setdirection.3pcap
@@ -17,7 +17,7 @@
 .\" WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
 .\" MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
 .\"
-.TH PCAP_SETDIRECTION 3PCAP "5 April 2008"
+.TH PCAP_SETDIRECTION 3PCAP "8 March 2015"
 .SH NAME
 pcap_setdirection \- set the direction for which packets will be captured
 .SH SYNOPSIS
diff --git a/pcap_setfilter.3pcap b/pcap_setfilter.3pcap
index c737797..6efd253 100644
--- a/pcap_setfilter.3pcap
+++ b/pcap_setfilter.3pcap
@@ -17,7 +17,7 @@
 .\" WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
 .\" MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
 .\"
-.TH PCAP_SETFILTER 3PCAP "13 May 2008"
+.TH PCAP_SETFILTER 3PCAP "7 April 2014"
 .SH NAME
 pcap_setfilter \- set the filter
 .SH SYNOPSIS
diff --git a/pcap_setnonblock.3pcap b/pcap_setnonblock.3pcap
index a99ea07..6959127 100644
--- a/pcap_setnonblock.3pcap
+++ b/pcap_setnonblock.3pcap
@@ -17,7 +17,7 @@
 .\" WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
 .\" MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
 .\"
-.TH PCAP_SETNONBLOCK 3PCAP "5 April 2008"
+.TH PCAP_SETNONBLOCK 3PCAP "18 October 2014"
 .SH NAME
 pcap_setnonblock, pcap_getnonblock \- set or get the state of
 non-blocking mode on a capture device
diff --git a/pcap_snapshot.3pcap b/pcap_snapshot.3pcap
index 47eb42a..7af8c33 100644
--- a/pcap_snapshot.3pcap
+++ b/pcap_snapshot.3pcap
@@ -17,7 +17,7 @@
 .\" WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
 .\" MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
 .\"
-.TH PCAP_SNAPSHOT 3PCAP "17 September 2013"
+.TH PCAP_SNAPSHOT 3PCAP "7 April 2014"
 .SH NAME
 pcap_snapshot \- get the snapshot length
 .SH SYNOPSIS
diff --git a/pcap_stats.3pcap b/pcap_stats.3pcap
index 159054e..2dce4b5 100644
--- a/pcap_stats.3pcap
+++ b/pcap_stats.3pcap
@@ -17,7 +17,7 @@
 .\" WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
 .\" MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
 .\"
-.TH PCAP_STATS 3PCAP "7 September 2009"
+.TH PCAP_STATS 3PCAP "3 January 2014"
 .SH NAME
 pcap_stats \- get capture statistics
 .SH SYNOPSIS
diff --git a/pcap_statustostr.3pcap b/pcap_statustostr.3pcap
index 77b8c5f..9c2057a 100644
--- a/pcap_statustostr.3pcap
+++ b/pcap_statustostr.3pcap
@@ -17,7 +17,7 @@
 .\" WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
 .\" MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
 .\"
-.TH PCAP_STATUSTOSTR 3PCAP "9 April 2008"
+.TH PCAP_STATUSTOSTR 3PCAP "3 January 2014"
 .SH NAME
 pcap_statustostr \- convert a PCAP_ERROR_ or PCAP_WARNING_ value to a string
 .SH SYNOPSIS
diff --git a/pcap_strerror.3pcap b/pcap_strerror.3pcap
index 7185162..7c7d53f 100644
--- a/pcap_strerror.3pcap
+++ b/pcap_strerror.3pcap
@@ -17,7 +17,7 @@
 .\" WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
 .\" MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
 .\"
-.TH PCAP_STRERROR 3PCAP "4 April 2008"
+.TH PCAP_STRERROR 3PCAP "3 January 2014"
 .SH NAME
 pcap_strerror \- convert an errno value to a string
 .SH SYNOPSIS
diff --git a/pcap_tstamp_type_name_to_val.3pcap b/pcap_tstamp_type_name_to_val.3pcap
index 22dd15f..ac2e35d 100644
--- a/pcap_tstamp_type_name_to_val.3pcap
+++ b/pcap_tstamp_type_name_to_val.3pcap
@@ -18,7 +18,7 @@
 .\" WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
 .\" MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
 .\"
-.TH PCAP_TSTAMP_TYPE_NAME_TO_VAL 3PCAP "21 August 2010"
+.TH PCAP_TSTAMP_TYPE_NAME_TO_VAL 3PCAP "5 December 2014"
 .SH NAME
 pcap_tstamp_type_name_to_val \- get the time stamp type value
 corresponding to a time stamp type name
diff --git a/pcap_tstamp_type_val_to_name.3pcap b/pcap_tstamp_type_val_to_name.3pcap
index 903cea7..261554e 100644
--- a/pcap_tstamp_type_val_to_name.3pcap
+++ b/pcap_tstamp_type_val_to_name.3pcap
@@ -18,7 +18,7 @@
 .\" WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
 .\" MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
 .\"
-.TH PCAP_TSTAMP_TYPE_VAL_TO_NAME 3PCAP "21 August 2010"
+.TH PCAP_TSTAMP_TYPE_VAL_TO_NAME 3PCAP "12 December 2013"
 .SH NAME
 pcap_tstamp_type_val_to_name, pcap_tstamp_type_val_to_description \- get
 a name or description for a time stamp type value
diff --git a/pcap_version.h b/pcap_version.h
new file mode 100644
index 0000000..619c6d8
--- /dev/null
+++ b/pcap_version.h
@@ -0,0 +1,13 @@
+/*
+ * We make the version string static, and return a pointer to it, rather
+ * than exporting the version string directly.  On at least some UNIXes,
+ * if you import data from a shared library into an program, the data is
+ * bound into the program binary, so if the string in the version of the
+ * library with which the program was linked isn't the same as the
+ * string in the version of the library with which the program is being
+ * run, various undesirable things may happen (warnings, the string
+ * being the one from the version of the library with which the program
+ * was linked, or even weirder things, such as the string being the one
+ * from the library but being truncated).
+ */
+static const char pcap_version_string[] = "libpcap version 1.8.1";
diff --git a/pcap_version.h.in b/pcap_version.h.in
new file mode 100644
index 0000000..3104c8e
--- /dev/null
+++ b/pcap_version.h.in
@@ -0,0 +1,13 @@
+/*
+ * We make the version string static, and return a pointer to it, rather
+ * than exporting the version string directly.  On at least some UNIXes,
+ * if you import data from a shared library into an program, the data is
+ * bound into the program binary, so if the string in the version of the
+ * library with which the program was linked isn't the same as the
+ * string in the version of the library with which the program is being
+ * run, various undesirable things may happen (warnings, the string
+ * being the one from the version of the library with which the program
+ * was linked, or even weirder things, such as the string being the one
+ * from the library but being truncated).
+ */
+static const char pcap_version_string[] = "libpcap version %%LIBPCAP_VERSION%%";
diff --git a/portability.h b/portability.h
new file mode 100644
index 0000000..8a6bf40
--- /dev/null
+++ b/portability.h
@@ -0,0 +1,216 @@
+/*
+ * Copyright (c) 1994, 1995, 1996
+ *	The Regents of the University of California.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *	This product includes software developed by the Computer Systems
+ *	Engineering Group at Lawrence Berkeley Laboratory.
+ * 4. Neither the name of the University nor of the Laboratory may be used
+ *    to endorse or promote products derived from this software without
+ *    specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#ifndef portability_h
+#define	portability_h
+
+/*
+ * Helpers for portability between Windows and UN*X and between different
+ * flavors of UN*X.
+ */
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#ifndef HAVE_STRLCPY
+ /*
+  * Macro that does the same thing as strlcpy().
+  */
+ #ifdef _MSC_VER
+  /*
+   * strncpy_s() is supported at least back to Visual
+   * Studio 2005.
+   */
+  #define strlcpy(x, y, z) \
+	strncpy_s((x), (z), (y), _TRUNCATE)
+
+ #else
+  #define strlcpy(x, y, z) \
+	(strncpy((x), (y), (z)), \
+	 ((z) <= 0 ? 0 : ((x)[(z) - 1] = '\0')), \
+	 (void) strlen((y)))
+ #endif
+#endif
+
+/*
+ * For flagging arguments as format strings in MSVC.
+ */
+#if _MSC_VER >= 1400
+ #include <sal.h>
+ #if _MSC_VER > 1400
+  #define FORMAT_STRING(p) _Printf_format_string_ p
+ #else
+  #define FORMAT_STRING(p) __format_string p
+ #endif
+#else
+ #define FORMAT_STRING(p) p
+#endif
+
+#ifdef _MSC_VER
+  #define strdup	_strdup
+  #define sscanf	sscanf_s
+  #define setbuf(x, y) \
+	setvbuf((x), (y), _IONBF, 0)
+  #define fopen(x, y) \
+	fopen_safe((x), (y))
+  FILE *fopen_safe(const char *filename, const char* mode);
+#endif
+
+#if defined(_MSC_VER) || defined(__MINGW32__)
+  #define strlcat(x, y, z) \
+	strncat_s((x), (z), (y), _TRUNCATE)
+#endif
+
+#ifdef _MSC_VER
+  /*
+   * MSVC.
+   */
+  #if _MSC_VER >= 1900
+    /*
+     * VS 2015 or newer; we have snprintf() function.
+     */
+    #define HAVE_SNPRINTF
+  #endif
+#endif
+
+/*
+ * On Windows, snprintf(), with that name and with C99 behavior - i.e.,
+ * guaranteeing that the formatted string is null-terminated - didn't
+ * appear until Visual Studio 2015.  Prior to that, the C runtime had
+ * only _snprintf(), which *doesn't* guarantee that the string is
+ * null-terminated if it is truncated due to the buffer being too
+ * small.  We therefore can't just define snprintf to be _snprintf
+ * and define vsnprintf to be _vsnprintf, as we're relying on null-
+ * termination of strings in all cases.
+ *
+ * We also want to allow this to be built with versions of Visual Studio
+ * prior to VS 2015, so we can't rely on snprintf() being present.
+ *
+ * And we want to make sure that, if we support plugins in the future,
+ * a routine with C99 snprintf() behavior will be available to them.
+ * We also don't want it to collide with the C library snprintf() if
+ * there is one.
+ *
+ * So we make pcap_snprintf() and pcap_vsnprintf() available, either by
+ * #defining them to be snprintf or vsnprintf, respectively, or by
+ * defining our own versions and exporting them.
+ */
+#ifdef HAVE_SNPRINTF
+#define pcap_snprintf snprintf
+#else
+extern int pcap_snprintf(char *, size_t, FORMAT_STRING(const char *), ...)
+#ifdef __ATTRIBUTE___FORMAT_OK
+    __attribute__((format (printf, 3, 4)))
+#endif /* __ATTRIBUTE___FORMAT_OK */
+    ;
+#endif
+
+#ifdef HAVE_VSNPRINTF
+#define pcap_vsnprintf vsnprintf
+#else
+extern int pcap_vsnprintf(char *, size_t, const char *, va_list ap);
+#endif
+
+#ifdef HAVE_STRTOK_R
+  #define pcap_strtok_r	strtok_r
+#else
+  #ifdef _MSC_VER
+    /*
+     * Microsoft gives it a different name.
+     */
+    #define pcap_strtok_r	strtok_s
+  #else
+    /*
+     * Define it ourselves.
+     */
+    #define NEED_STRTOK_R
+    extern int pcap_strtok_r(char *, const char *, char **);
+  #endif
+#endif /* HAVE_STRTOK_R */
+
+#ifdef _WIN32
+  /*
+   * These may be defined by <inttypes.h>.
+   *
+   * XXX - for MSVC, we always want the _MSC_EXTENSIONS versions.
+   * What about other compilers?  If, as the MinGW Web site says MinGW
+   * does, the other compilers just use Microsoft's run-time library,
+   * then they should probably use the _MSC_EXTENSIONS even if the
+   * compiler doesn't define _MSC_EXTENSIONS.
+   *
+   * XXX - we currently aren't using any of these, but this allows
+   * their use in the future.
+   */
+  #ifndef PRId64
+    #ifdef _MSC_EXTENSIONS
+      #define PRId64	"I64d"
+    #else
+      #define PRId64	"lld"
+    #endif
+  #endif /* PRId64 */
+
+  #ifndef PRIo64
+    #ifdef _MSC_EXTENSIONS
+      #define PRIo64	"I64o"
+    #else
+      #define PRIo64	"llo"
+    #endif
+  #endif /* PRIo64 */
+
+  #ifndef PRIx64
+    #ifdef _MSC_EXTENSIONS
+      #define PRIx64	"I64x"
+    #else
+      #define PRIx64	"llx"
+    #endif
+  #endif
+
+  #ifndef PRIu64
+    #ifdef _MSC_EXTENSIONS
+      #define PRIu64	"I64u"
+    #else
+      #define PRIu64	"llu"
+    #endif
+  #endif
+
+  #if !defined(__cplusplus)
+    #define inline __inline
+  #endif
+#endif /* _WIN32 */
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/remote-ext.h b/remote-ext.h
new file mode 100644
index 0000000..ed2f9bb
--- /dev/null
+++ b/remote-ext.h
@@ -0,0 +1,467 @@
+/*
+ * Copyright (c) 2002 - 2003
+ * NetGroup, Politecnico di Torino (Italy)
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the Politecnico di Torino nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+
+#ifndef __REMOTE_EXT_H__
+#define __REMOTE_EXT_H__
+
+
+#ifndef HAVE_REMOTE
+#error Please do not include this file directly. Just define HAVE_REMOTE and then include pcap.h
+#endif
+
+/*// Definition for Microsoft Visual Studio */
+#if _MSC_VER > 1000
+#pragma once
+#endif
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/*
+ * \file remote-ext.h
+ *
+ * The goal of this file it to include most of the new definitions that should be
+ * placed into the pcap.h file.
+ *
+ * It includes all new definitions (structures and functions like pcap_open().
+ * Some of the functions are not really a remote feature, but, right now,
+ * they are placed here.
+ */
+
+
+
+/*// All this stuff is public */
+/*
+ * \addtogroup remote_struct
+ * \{
+ */
+
+
+
+
+/*
+ * \brief Defines the maximum buffer size in which address, port, interface names are kept.
+ *
+ * In case the adapter name or such is larger than this value, it is truncated.
+ * This is not used by the user; however it must be aware that an hostname / interface
+ * name longer than this value will be truncated.
+ */
+#define PCAP_BUF_SIZE 1024
+
+
+/*
+ * \addtogroup remote_source_ID
+ * \{
+ */
+
+
+/*
+ * \brief Internal representation of the type of source in use (file,
+ * remote/local interface).
+ *
+ * This indicates a file, i.e. the user want to open a capture from a local file.
+ */
+#define PCAP_SRC_FILE 2
+/*
+ * \brief Internal representation of the type of source in use (file,
+ * remote/local interface).
+ *
+ * This indicates a local interface, i.e. the user want to open a capture from
+ * a local interface. This does not involve the RPCAP protocol.
+ */
+#define PCAP_SRC_IFLOCAL 3
+/*
+ * \brief Internal representation of the type of source in use (file,
+ * remote/local interface).
+ *
+ * This indicates a remote interface, i.e. the user want to open a capture from
+ * an interface on a remote host. This does involve the RPCAP protocol.
+ */
+#define PCAP_SRC_IFREMOTE 4
+
+/*
+ * \}
+ */
+
+
+
+/* \addtogroup remote_source_string
+ *
+ * The formats allowed by the pcap_open() are the following:
+ * - file://path_and_filename [opens a local file]
+ * - rpcap://devicename [opens the selected device devices available on the local host, without using the RPCAP protocol]
+ * - rpcap://host/devicename [opens the selected device available on a remote host]
+ * - rpcap://host:port/devicename [opens the selected device available on a remote host, using a non-standard port for RPCAP]
+ * - adaptername [to open a local adapter; kept for compability, but it is strongly discouraged]
+ * - (NULL) [to open the first local adapter; kept for compability, but it is strongly discouraged]
+ *
+ * The formats allowed by the pcap_findalldevs_ex() are the following:
+ * - file://folder/ [lists all the files in the given folder]
+ * - rpcap:// [lists all local adapters]
+ * - rpcap://host:port/ [lists the devices available on a remote host]
+ *
+ * Referring to the 'host' and 'port' parameters, they can be either numeric or literal. Since
+ * IPv6 is fully supported, these are the allowed formats:
+ *
+ * - host (literal): e.g. host.foo.bar
+ * - host (numeric IPv4): e.g. 10.11.12.13
+ * - host (numeric IPv4, IPv6 style): e.g. [10.11.12.13]
+ * - host (numeric IPv6): e.g. [1:2:3::4]
+ * - port: can be either numeric (e.g. '80') or literal (e.g. 'http')
+ *
+ * Here you find some allowed examples:
+ * - rpcap://host.foo.bar/devicename [everything literal, no port number]
+ * - rpcap://host.foo.bar:1234/devicename [everything literal, with port number]
+ * - rpcap://10.11.12.13/devicename [IPv4 numeric, no port number]
+ * - rpcap://10.11.12.13:1234/devicename [IPv4 numeric, with port number]
+ * - rpcap://[10.11.12.13]:1234/devicename [IPv4 numeric with IPv6 format, with port number]
+ * - rpcap://[1:2:3::4]/devicename [IPv6 numeric, no port number]
+ * - rpcap://[1:2:3::4]:1234/devicename [IPv6 numeric, with port number]
+ * - rpcap://[1:2:3::4]:http/devicename [IPv6 numeric, with literal port number]
+ *
+ * \{
+ */
+
+
+/*
+ * \brief String that will be used to determine the type of source in use (file,
+ * remote/local interface).
+ *
+ * This string will be prepended to the interface name in order to create a string
+ * that contains all the information required to open the source.
+ *
+ * This string indicates that the user wants to open a capture from a local file.
+ */
+#define PCAP_SRC_FILE_STRING "file://"
+/*
+ * \brief String that will be used to determine the type of source in use (file,
+ * remote/local interface).
+ *
+ * This string will be prepended to the interface name in order to create a string
+ * that contains all the information required to open the source.
+ *
+ * This string indicates that the user wants to open a capture from a network interface.
+ * This string does not necessarily involve the use of the RPCAP protocol. If the
+ * interface required resides on the local host, the RPCAP protocol is not involved
+ * and the local functions are used.
+ */
+#define PCAP_SRC_IF_STRING "rpcap://"
+
+/*
+ * \}
+ */
+
+
+
+
+
+/*
+ * \addtogroup remote_open_flags
+ * \{
+ */
+
+/*
+ * \brief Defines if the adapter has to go in promiscuous mode.
+ *
+ * It is '1' if you have to open the adapter in promiscuous mode, '0' otherwise.
+ * Note that even if this parameter is false, the interface could well be in promiscuous
+ * mode for some other reason (for example because another capture process with
+ * promiscuous mode enabled is currently using that interface).
+ * On on Linux systems with 2.2 or later kernels (that have the "any" device), this
+ * flag does not work on the "any" device; if an argument of "any" is supplied,
+ * the 'promisc' flag is ignored.
+ */
+#define PCAP_OPENFLAG_PROMISCUOUS		1
+
+/*
+ * \brief Defines if the data transfer (in case of a remote
+ * capture) has to be done with UDP protocol.
+ *
+ * If it is '1' if you want a UDP data connection, '0' if you want
+ * a TCP data connection; control connection is always TCP-based.
+ * A UDP connection is much lighter, but it does not guarantee that all
+ * the captured packets arrive to the client workstation. Moreover,
+ * it could be harmful in case of network congestion.
+ * This flag is meaningless if the source is not a remote interface.
+ * In that case, it is simply ignored.
+ */
+#define PCAP_OPENFLAG_DATATX_UDP			2
+
+
+/*
+ * \brief Defines if the remote probe will capture its own generated traffic.
+ *
+ * In case the remote probe uses the same interface to capture traffic and to send
+ * data back to the caller, the captured traffic includes the RPCAP traffic as well.
+ * If this flag is turned on, the RPCAP traffic is excluded from the capture, so that
+ * the trace returned back to the collector is does not include this traffic.
+ */
+#define PCAP_OPENFLAG_NOCAPTURE_RPCAP	4
+
+/*
+ * \brief Defines if the local adapter will capture its own generated traffic.
+ *
+ * This flag tells the underlying capture driver to drop the packets that were sent by itself.
+ * This is useful when building applications like bridges, that should ignore the traffic
+ * they just sent.
+ */
+#define PCAP_OPENFLAG_NOCAPTURE_LOCAL	8
+
+/*
+ * \brief This flag configures the adapter for maximum responsiveness.
+ *
+ * In presence of a large value for nbytes, WinPcap waits for the arrival of several packets before
+ * copying the data to the user. This guarantees a low number of system calls, i.e. lower processor usage,
+ * i.e. better performance, which is good for applications like sniffers. If the user sets the
+ * PCAP_OPENFLAG_MAX_RESPONSIVENESS flag, the capture driver will copy the packets as soon as the application
+ * is ready to receive them. This is suggested for real time applications (like, for example, a bridge)
+ * that need the best responsiveness.
+ */
+#define PCAP_OPENFLAG_MAX_RESPONSIVENESS	16
+
+/*
+ * \}
+ */
+
+
+/*
+ * \addtogroup remote_samp_methods
+ * \{
+ */
+
+/*
+ *\brief No sampling has to be done on the current capture.
+ *
+ * In this case, no sampling algorithms are applied to the current capture.
+ */
+#define PCAP_SAMP_NOSAMP	0
+
+/*
+ * \brief It defines that only 1 out of N packets must be returned to the user.
+ *
+ * In this case, the 'value' field of the 'pcap_samp' structure indicates the
+ * number of packets (minus 1) that must be discarded before one packet got accepted.
+ * In other words, if 'value = 10', the first packet is returned to the caller, while
+ * the following 9 are discarded.
+ */
+#define PCAP_SAMP_1_EVERY_N	1
+
+/*
+ * \brief It defines that we have to return 1 packet every N milliseconds.
+ *
+ * In this case, the 'value' field of the 'pcap_samp' structure indicates the 'waiting
+ * time' in milliseconds before one packet got accepted.
+ * In other words, if 'value = 10', the first packet is returned to the caller; the next
+ * returned one will be the first packet that arrives when 10ms have elapsed.
+ */
+#define PCAP_SAMP_FIRST_AFTER_N_MS 2
+
+/*
+ * \}
+ */
+
+
+/*
+ * \addtogroup remote_auth_methods
+ * \{
+ */
+
+/*
+ * \brief It defines the NULL authentication.
+ *
+ * This value has to be used within the 'type' member of the pcap_rmtauth structure.
+ * The 'NULL' authentication has to be equal to 'zero', so that old applications
+ * can just put every field of struct pcap_rmtauth to zero, and it does work.
+ */
+#define RPCAP_RMTAUTH_NULL 0
+/*
+ * \brief It defines the username/password authentication.
+ *
+ * With this type of authentication, the RPCAP protocol will use the username/
+ * password provided to authenticate the user on the remote machine. If the
+ * authentication is successful (and the user has the right to open network devices)
+ * the RPCAP connection will continue; otherwise it will be dropped.
+ *
+ * This value has to be used within the 'type' member of the pcap_rmtauth structure.
+ */
+#define RPCAP_RMTAUTH_PWD 1
+
+/*
+ * \}
+ */
+
+
+
+
+/*
+ * \brief This structure keeps the information needed to autheticate
+ * the user on a remote machine.
+ *
+ * The remote machine can either grant or refuse the access according
+ * to the information provided.
+ * In case the NULL authentication is required, both 'username' and
+ * 'password' can be NULL pointers.
+ *
+ * This structure is meaningless if the source is not a remote interface;
+ * in that case, the functions which requires such a structure can accept
+ * a NULL pointer as well.
+ */
+struct pcap_rmtauth
+{
+	/*
+	 * \brief Type of the authentication required.
+	 *
+	 * In order to provide maximum flexibility, we can support different types
+	 * of authentication based on the value of this 'type' variable. The currently
+	 * supported authentication methods are defined into the
+	 * \link remote_auth_methods Remote Authentication Methods Section\endlink.
+	 */
+	int type;
+	/*
+	 * \brief Zero-terminated string containing the username that has to be
+	 * used on the remote machine for authentication.
+	 *
+	 * This field is meaningless in case of the RPCAP_RMTAUTH_NULL authentication
+	 * and it can be NULL.
+	 */
+	char *username;
+	/*
+	 * \brief Zero-terminated string containing the password that has to be
+	 * used on the remote machine for authentication.
+	 *
+	 * This field is meaningless in case of the RPCAP_RMTAUTH_NULL authentication
+	 * and it can be NULL.
+	 */
+	char *password;
+};
+
+
+/*
+ * \brief This structure defines the information related to sampling.
+ *
+ * In case the sampling is requested, the capturing device should read
+ * only a subset of the packets coming from the source. The returned packets depend
+ * on the sampling parameters.
+ *
+ * \warning The sampling process is applied <strong>after</strong> the filtering process.
+ * In other words, packets are filtered first, then the sampling process selects a
+ * subset of the 'filtered' packets and it returns them to the caller.
+ */
+struct pcap_samp
+{
+	/*
+	 * Method used for sampling. Currently, the supported methods are listed in the
+	 * \link remote_samp_methods Sampling Methods Section\endlink.
+	 */
+	int method;
+
+	/*
+	 * This value depends on the sampling method defined. For its meaning, please check
+	 * at the \link remote_samp_methods Sampling Methods Section\endlink.
+	 */
+	int value;
+};
+
+
+
+
+// Maximum length of an host name (needed for the RPCAP active mode)
+#define RPCAP_HOSTLIST_SIZE 1024
+
+
+/*
+ * \}
+ */ // end of public documentation
+
+
+// Exported functions
+
+
+
+/*
+ * \name New WinPcap functions
+ *
+ * This section lists the new functions that are able to help considerably in writing
+ * WinPcap programs because of their easiness of use.
+ */
+// \{
+PCAP_API pcap_t *pcap_open(const char *source, int snaplen, int flags, int read_timeout, struct pcap_rmtauth *auth, char *errbuf);
+PCAP_API int pcap_createsrcstr(char *source, int type, const char *host, const char *port, const char *name, char *errbuf);
+PCAP_API int pcap_parsesrcstr(const char *source, int *type, char *host, char *port, char *name, char *errbuf);
+PCAP_API int pcap_findalldevs_ex(char *source, struct pcap_rmtauth *auth, pcap_if_t **alldevs, char *errbuf);
+PCAP_API struct pcap_samp *pcap_setsampling(pcap_t *p);
+
+// \}
+// End of new WinPcap functions
+
+/*
+ * \name Remote Capture functions
+ */
+
+/*
+ * Some minor differences between UN*X sockets and and Winsock sockets.
+ */
+#ifndef _WIN32
+  /*!
+   * \brief In Winsock, a socket handle is of type SOCKET; in UN*X, it's
+   * a file descriptor, and therefore a signed integer.
+   * We define SOCKET to be a signed integer on UN*X, so that it can
+   * be used on both platforms.
+   */
+  #define SOCKET int
+
+  /*!
+   * \brief In Winsock, the error return if socket() fails is INVALID_SOCKET;
+   * in UN*X, it's -1.
+   * We define INVALID_SOCKET to be -1 on UN*X, so that it can be used on
+   * both platforms.
+   */
+  #define INVALID_SOCKET -1
+#endif
+
+// \{
+PCAP_API SOCKET pcap_remoteact_accept(const char *address, const char *port, const char *hostlist, char *connectinghost, struct pcap_rmtauth *auth, char *errbuf);
+PCAP_API int pcap_remoteact_list(char *hostlist, char sep, int size, char *errbuf);
+PCAP_API int pcap_remoteact_close(const char *host, char *errbuf);
+PCAP_API void pcap_remoteact_cleanup();
+// \}
+// End of remote capture functions
+
+#ifdef __cplusplus
+}
+#endif
+
+
+#endif
+
diff --git a/runlex.sh b/runlex.sh
deleted file mode 100755
index 06b8bd4..0000000
--- a/runlex.sh
+++ /dev/null
@@ -1,233 +0,0 @@
-#! /bin/sh
-
-#
-# runlex.sh
-# Script to run Lex/Flex.
-# First argument is the (quoted) name of the command; if it's null, that
-# means that neither Flex nor Lex was found, so we report an error and
-# quit.
-#
-
-#
-# Get the name of the command to run, and then shift to get the arguments.
-#
-if [ $# -eq 0 ]
-then
-	echo "Usage: runlex <lex/flex command to run> [ arguments ]" 1>&2
-	exit 1
-fi
-LEX="$1"
-shift
-
-#
-# Check whether we have Lex or Flex.
-#
-if [ -z "${LEX}" ]
-then
-	echo "Neither lex nor flex was found" 1>&2
-	exit 1
-fi
-
-#
-# Process the flags.  We don't use getopt because we don't want to
-# embed complete knowledge of what options are supported by Lex/Flex.
-#
-flags=""
-outfile=lex.yy.c
-while [ $# -ne 0 ]
-do
-	case "$1" in
-
-	-o*)
-		#
-		# Set the output file name.
-		#
-		outfile=`echo "$1" | sed 's/-o\(.*\)/\1/'`
-		;;
-
-	-*)
-		#
-		# Add this to the list of flags.
-		#
-		flags="$flags $1"
-		;;
-
-	--|*)
-		#
-		# End of flags.
-		#
-		break
-		;;
-	esac
-	shift
-done
-
-#
-# Is it Lex, or is it Flex?
-#
-if [ "${LEX}" = flex ]
-then
-	#
-	# It's Flex.
-	#
-	have_flex=yes
-
-	#
-	# Does it support the --noFUNCTION options?  If so, we pass
-	# --nounput, as at least some versions that support those
-	# options don't support disabling yyunput by defining
-	# YY_NO_UNPUT.
-	#
-	if flex --help | egrep noFUNCTION >/dev/null
-	then
-		flags="$flags --nounput"
-
-		#
-		# Does it support -R, for generating reentrant scanners?
-		# If so, we're not currently using that feature, but
-		# it'll generate some unused functions anyway - and there
-		# won't be any header file declaring them, so there'll be
-		# defined-but-not-declared warnings.  Therefore, we use
-		# --noFUNCTION options to suppress generating those
-		# functions.
-		#
-		if flex --help | egrep reentrant >/dev/null
-		then
-			flags="$flags --noyyget_lineno --noyyget_in --noyyget_out --noyyget_leng --noyyget_text --noyyset_lineno --noyyset_in --noyyset_out"
-		fi
-	fi
-else
-	#
-	# It's Lex.
-	#
-	have_flex=no
-fi
-
-#
-# OK, run it.
-# If it's lex, it doesn't support -o, so we just write to
-# lex.yy.c and, if it succeeds, rename it to the right name,
-# otherwise we remove lex.yy.c.
-# If it's flex, it supports -o, so we use that - flex with -P doesn't
-# write to lex.yy.c, it writes to a lex.{prefix from -P}.c.
-#
-if [ $have_flex = yes ]
-then
-	${LEX} $flags -o"$outfile" "$@"
-
-	#
-	# Did it succeed?
-	#
-	status=$?
-	if [ $status -ne 0 ]
-	then
-		#
-		# No.  Exit with the failing exit status.
-		#
-		exit $status
-	fi
-
-	#
-	# Flex has the annoying habit of stripping all but the last
-	# component of the "-o" flag argument and using that as the
-	# place to put the output.  This gets in the way of building
-	# in a directory different from the source directory.  Try
-	# to work around this.
-	#
-	# Is the outfile where we think it is?
-	#
-	outfile_base=`basename "$outfile"`
-	if [ "$outfile_base" != "$outfile" -a \( ! -r "$outfile" \) -a -r "$outfile_base" ]
-	then
-		#
-		# No, it's not, but it is in the current directory.  Put it
-		# where it's supposed to be.
-		#
-		mv "$outfile_base" "$outfile"
-
-		#
-		# Did that succeed?
-		#
-		status=$?
-		if [ $status -ne 0 ]
-		then
-			#
-			# No.  Exit with the failing exit status.
-			#
-			exit $status
-		fi
-	fi
-else
-	${LEX} $flags "$@"
-
-	#
-	# Did it succeed?
-	#
-	status=$?
-	if [ $status -ne 0 ]
-	then
-		#
-		# No.  Get rid of any lex.yy.c file we generated, and
-		# exit with the failing exit status.
-		#
-		rm -f lex.yy.c
-		exit $status
-	fi
-
-	#
-	# OK, rename lex.yy.c to the right output file.
-	#
-	mv lex.yy.c "$outfile"
-
-	#
-	# Did that succeed?
-	#
-	status=$?
-	if [ $status -ne 0 ]
-	then
-		#
-		# No.  Get rid of any lex.yy.c file we generated, and
-		# exit with the failing exit status.
-		#
-		rm -f lex.yy.c
-		exit $status
-	fi
-fi
-
-#
-# OK, now let's generate a header file declaring the relevant functions
-# defined by the .c file; if the .c file is .../foo.c, the header file
-# will be .../foo.h.
-#
-# This works around some other Flex suckage, wherein it doesn't declare
-# the lex routine before defining it, causing compiler warnings.
-# XXX - newer versions of Flex support --header-file=, to generate the
-# appropriate header file.  With those versions, we should use that option.
-#
-
-#
-# Get the name of the prefix; scan the source files for a %option prefix
-# line.  We use the last one.
-#
-prefix=`sed -n 's/%option[ 	][ 	]*prefix="\(.*\)".*/\1/p' "$@" | tail -1`
-if [ ! -z "$prefix" ]
-then
-	prefixline="#define yylex ${prefix}lex"
-fi
-
-#
-# Construct the name of the header file.
-#
-header_file=`dirname "$outfile"`/`basename "$outfile" .c`.h
-
-#
-# Spew out the declaration.
-#
-cat <<EOF >$header_file
-/* This is generated by runlex.sh.  Do not edit it. */
-$prefixline
-#ifndef YY_DECL
-#define YY_DECL int yylex(void)
-#endif
-YY_DECL;
-EOF
diff --git a/savefile.c b/savefile.c
index 783ec45..247338c 100644
--- a/savefile.c
+++ b/savefile.c
@@ -32,9 +32,9 @@
 #include "config.h"
 #endif
 
-#ifdef WIN32
+#ifdef _WIN32
 #include <pcap-stdinc.h>
-#else /* WIN32 */
+#else /* _WIN32 */
 #if HAVE_INTTYPES_H
 #include <inttypes.h>
 #elif HAVE_STDINT_H
@@ -44,7 +44,7 @@
 #include <sys/bitypes.h>
 #endif
 #include <sys/types.h>
-#endif /* WIN32 */
+#endif /* _WIN32 */
 
 #include <errno.h>
 #include <memory.h>
@@ -53,7 +53,6 @@
 #include <string.h>
 
 #include "pcap-int.h"
-#include "pcap/usb.h"
 
 #ifdef HAVE_OS_PROTO_H
 #include "os-proto.h"
@@ -62,10 +61,27 @@
 #include "sf-pcap.h"
 #include "sf-pcap-ng.h"
 
+#ifdef _WIN32
+/*
+ * These aren't exported on Windows, because they would only work if both
+ * WinPcap and the code using it were to use the Universal CRT; otherwise,
+ * a FILE structure in WinPcap and a FILE structure in the code using it
+ * could be different if they're using different versions of the C runtime.
+ *
+ * Instead, pcap/pcap.h defines them as macros that wrap the hopen versions,
+ * with the wrappers calling _fileno() and _get_osfhandle() themselves,
+ * so that they convert the appropriate CRT version's FILE structure to
+ * a HANDLE (which is OS-defined, not CRT-defined, and is part of the Win32
+ * and Win64 ABIs).
+ */
+static pcap_t *pcap_fopen_offline_with_tstamp_precision(FILE *, u_int, char *);
+static pcap_t *pcap_fopen_offline(FILE *, char *);
+#endif
+
 /*
  * Setting O_BINARY on DOS/Windows is a bit tricky
  */
-#if defined(WIN32)
+#if defined(_WIN32)
   #define SET_BINMODE(f)  _setmode(_fileno(f), _O_BINARY)
 #elif defined(MSDOS)
   #if defined(__HIGHC__)
@@ -96,7 +112,7 @@
 	 * as it would have to handle reading partial packets and
 	 * keeping the state of the read.)
 	 */
-	snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
+	pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
 	    "Savefiles cannot be put into non-blocking mode");
 	return (-1);
 }
@@ -104,16 +120,24 @@
 static int
 sf_stats(pcap_t *p, struct pcap_stat *ps)
 {
-	snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
+	pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
 	    "Statistics aren't available from savefiles");
 	return (-1);
 }
 
-#ifdef WIN32
+#ifdef _WIN32
+static struct pcap_stat *
+sf_stats_ex(pcap_t *p, int *size)
+{
+	pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
+	    "Statistics aren't available from savefiles");
+	return (NULL);
+}
+
 static int
 sf_setbuff(pcap_t *p, int dim)
 {
-	snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
+	pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
 	    "The kernel buffer size cannot be set while reading from a file");
 	return (-1);
 }
@@ -121,7 +145,7 @@
 static int
 sf_setmode(pcap_t *p, int mode)
 {
-	snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
+	pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
 	    "impossible to set mode while reading from a file");
 	return (-1);
 }
@@ -129,10 +153,74 @@
 static int
 sf_setmintocopy(pcap_t *p, int size)
 {
-	snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
+	pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
 	    "The mintocopy parameter cannot be set while reading from a file");
 	return (-1);
 }
+
+static HANDLE
+sf_getevent(pcap_t *pcap)
+{
+	(void)pcap_snprintf(pcap->errbuf, sizeof(pcap->errbuf),
+	    "The read event cannot be retrieved while reading from a file");
+	return (INVALID_HANDLE_VALUE);
+}
+
+static int
+sf_oid_get_request(pcap_t *p, bpf_u_int32 oid _U_, void *data _U_,
+    size_t *lenp _U_)
+{
+	pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
+	    "An OID get request cannot be performed on a file");
+	return (PCAP_ERROR);
+}
+
+static int
+sf_oid_set_request(pcap_t *p, bpf_u_int32 oid _U_, const void *data _U_,
+    size_t *lenp _U_)
+{
+	pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
+	    "An OID set request cannot be performed on a file");
+	return (PCAP_ERROR);
+}
+
+static u_int
+sf_sendqueue_transmit(pcap_t *p, pcap_send_queue *queue, int sync)
+{
+	strlcpy(p->errbuf, "Sending packets isn't supported on savefiles",
+	    PCAP_ERRBUF_SIZE);
+	return (0);
+}
+
+static int
+sf_setuserbuffer(pcap_t *p, int size)
+{
+	pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
+	    "The user buffer cannot be set when reading from a file");
+	return (-1);
+}
+
+static int
+sf_live_dump(pcap_t *p, char *filename, int maxsize, int maxpacks)
+{
+	pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
+	    "Live packet dumping cannot be performed when reading from a file");
+	return (-1);
+}
+
+static int
+sf_live_dump_ended(pcap_t *p, int sync)
+{
+	pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
+	    "Live packet dumping cannot be performed on a pcap_open_dead pcap_t");
+	return (-1);
+}
+
+static PAirpcapHandle
+sf_get_airpcap_handle(pcap_t *pcap)
+{
+	return (NULL);
+}
 #endif
 
 static int
@@ -150,7 +238,7 @@
 static int
 sf_setdirection(pcap_t *p, pcap_direction_t d)
 {
-	snprintf(p->errbuf, sizeof(p->errbuf),
+	pcap_snprintf(p->errbuf, sizeof(p->errbuf),
 	    "Setting direction is not supported on savefiles");
 	return (-1);
 }
@@ -165,17 +253,38 @@
 	pcap_freecode(&p->fcode);
 }
 
+/*
+* fopen's safe version on Windows.
+*/
+#ifdef _MSC_VER
+FILE *fopen_safe(const char *filename, const char* mode)
+{
+	FILE *fp = NULL;
+	errno_t errno;
+	errno = fopen_s(&fp, filename, mode);
+	if (errno == 0)
+		return fp;
+	else
+		return NULL;
+}
+#endif
+
 pcap_t *
 pcap_open_offline_with_tstamp_precision(const char *fname, u_int precision,
-    char *errbuf)
+					char *errbuf)
 {
 	FILE *fp;
 	pcap_t *p;
 
+	if (fname == NULL) {
+		pcap_snprintf(errbuf, PCAP_ERRBUF_SIZE,
+		    "A null pointer was supplied as the file name");
+		return (NULL);
+	}
 	if (fname[0] == '-' && fname[1] == '\0')
 	{
 		fp = stdin;
-#if defined(WIN32) || defined(MSDOS)
+#if defined(_WIN32) || defined(MSDOS)
 		/*
 		 * We're reading from the standard input, so put it in binary
 		 * mode, as savefiles are binary files.
@@ -184,13 +293,13 @@
 #endif
 	}
 	else {
-#if !defined(WIN32) && !defined(MSDOS)
+#if !defined(_WIN32) && !defined(MSDOS)
 		fp = fopen(fname, "r");
 #else
 		fp = fopen(fname, "rb");
 #endif
 		if (fp == NULL) {
-			snprintf(errbuf, PCAP_ERRBUF_SIZE, "%s: %s", fname,
+			pcap_snprintf(errbuf, PCAP_ERRBUF_SIZE, "%s: %s", fname,
 			    pcap_strerror(errno));
 			return (NULL);
 		}
@@ -210,7 +319,7 @@
 	    PCAP_TSTAMP_PRECISION_MICRO, errbuf));
 }
 
-#ifdef WIN32
+#ifdef _WIN32
 pcap_t* pcap_hopen_offline_with_tstamp_precision(intptr_t osfd, u_int precision,
     char *errbuf)
 {
@@ -220,14 +329,14 @@
 	fd = _open_osfhandle(osfd, _O_RDONLY);
 	if ( fd < 0 )
 	{
-		snprintf(errbuf, PCAP_ERRBUF_SIZE, pcap_strerror(errno));
+		pcap_snprintf(errbuf, PCAP_ERRBUF_SIZE, pcap_strerror(errno));
 		return NULL;
 	}
 
 	file = _fdopen(fd, "rb");
 	if ( file == NULL )
 	{
-		snprintf(errbuf, PCAP_ERRBUF_SIZE, pcap_strerror(errno));
+		pcap_snprintf(errbuf, PCAP_ERRBUF_SIZE, pcap_strerror(errno));
 		return NULL;
 	}
 
@@ -249,7 +358,7 @@
 
 #define	N_FILE_TYPES	(sizeof check_headers / sizeof check_headers[0])
 
-#ifdef WIN32
+#ifdef _WIN32
 static
 #endif
 pcap_t *
@@ -272,11 +381,11 @@
 	amt_read = fread((char *)&magic, 1, sizeof(magic), fp);
 	if (amt_read != sizeof(magic)) {
 		if (ferror(fp)) {
-			snprintf(errbuf, PCAP_ERRBUF_SIZE,
+			pcap_snprintf(errbuf, PCAP_ERRBUF_SIZE,
 			    "error reading dump file: %s",
 			    pcap_strerror(errno));
 		} else {
-			snprintf(errbuf, PCAP_ERRBUF_SIZE,
+			pcap_snprintf(errbuf, PCAP_ERRBUF_SIZE,
 			    "truncated dump file; tried to read %lu file header bytes, only got %lu",
 			    (unsigned long)sizeof(magic),
 			    (unsigned long)amt_read);
@@ -304,7 +413,7 @@
 	/*
 	 * Well, who knows what this mess is....
 	 */
-	snprintf(errbuf, PCAP_ERRBUF_SIZE, "unknown file format");
+	pcap_snprintf(errbuf, PCAP_ERRBUF_SIZE, "unknown file format");
 	return (NULL);
 
 found:
@@ -313,7 +422,7 @@
 	/* Padding only needed for live capture fcode */
 	p->fddipad = 0;
 
-#if !defined(WIN32) && !defined(MSDOS)
+#if !defined(_WIN32) && !defined(MSDOS)
 	/*
 	 * You can do "select()" and "poll()" on plain files on most
 	 * platforms, and should be able to do so on pipes.
@@ -332,10 +441,19 @@
 	p->getnonblock_op = sf_getnonblock;
 	p->setnonblock_op = sf_setnonblock;
 	p->stats_op = sf_stats;
-#ifdef WIN32
+#ifdef _WIN32
+	p->stats_ex_op = sf_stats_ex;
 	p->setbuff_op = sf_setbuff;
 	p->setmode_op = sf_setmode;
 	p->setmintocopy_op = sf_setmintocopy;
+	p->getevent_op = sf_getevent;
+	p->oid_get_request_op = sf_oid_get_request;
+	p->oid_set_request_op = sf_oid_set_request;
+	p->sendqueue_transmit_op = sf_sendqueue_transmit;
+	p->setuserbuffer_op = sf_setuserbuffer;
+	p->live_dump_op = sf_live_dump;
+	p->live_dump_ended_op = sf_live_dump_ended;
+	p->get_airpcap_handle_op = sf_get_airpcap_handle;
 #endif
 
 	/*
@@ -354,7 +472,7 @@
 	return (p);
 }
 
-#ifdef WIN32
+#ifdef _WIN32
 static
 #endif
 pcap_t *
diff --git a/scanner.c b/scanner.c
index df78682..b36239a 100644
--- a/scanner.c
+++ b/scanner.c
@@ -1,33 +1,18 @@
+#line 2 "scanner.c"
+#line 2 "scanner.l"
+/* Must come first for _LARGE_FILE_API on AIX. */
 #ifdef HAVE_CONFIG_H
 #include "config.h"
 #endif
-#line 2 "scanner.c"
 
-#line 4 "scanner.c"
+
+
+#line 11 "scanner.c"
 
 #define  YY_INT_ALIGNED short int
 
 /* A lexical scanner generated by flex */
 
-#define yy_create_buffer pcap__create_buffer
-#define yy_delete_buffer pcap__delete_buffer
-#define yy_flex_debug pcap__flex_debug
-#define yy_init_buffer pcap__init_buffer
-#define yy_flush_buffer pcap__flush_buffer
-#define yy_load_buffer_state pcap__load_buffer_state
-#define yy_switch_to_buffer pcap__switch_to_buffer
-#define yyin pcap_in
-#define yyleng pcap_leng
-#define yylex pcap_lex
-#define yylineno pcap_lineno
-#define yyout pcap_out
-#define yyrestart pcap_restart
-#define yytext pcap_text
-#define yywrap pcap_wrap
-#define yyalloc pcap_alloc
-#define yyrealloc pcap_realloc
-#define yyfree pcap_free
-
 #define FLEX_SCANNER
 #define YY_FLEX_MAJOR_VERSION 2
 #define YY_FLEX_MINOR_VERSION 5
@@ -141,24 +126,41 @@
  */
 #define YY_SC_TO_UI(c) ((unsigned int) (unsigned char) c)
 
+/* An opaque pointer. */
+#ifndef YY_TYPEDEF_YY_SCANNER_T
+#define YY_TYPEDEF_YY_SCANNER_T
+typedef void* yyscan_t;
+#endif
+
+/* For convenience, these vars (plus the bison vars far below)
+   are macros in the reentrant scanner. */
+#define yyin yyg->yyin_r
+#define yyout yyg->yyout_r
+#define yyextra yyg->yyextra_r
+#define yyleng yyg->yyleng_r
+#define yytext yyg->yytext_r
+#define yylineno (YY_CURRENT_BUFFER_LVALUE->yy_bs_lineno)
+#define yycolumn (YY_CURRENT_BUFFER_LVALUE->yy_bs_column)
+#define yy_flex_debug yyg->yy_flex_debug_r
+
 /* Enter a start condition.  This macro really ought to take a parameter,
  * but we do it the disgusting crufty way forced on us by the ()-less
  * definition of BEGIN.
  */
-#define BEGIN (yy_start) = 1 + 2 *
+#define BEGIN yyg->yy_start = 1 + 2 *
 
 /* Translate the current start state into a value that can be later handed
  * to BEGIN to return to the state.  The YYSTATE alias is for lex
  * compatibility.
  */
-#define YY_START (((yy_start) - 1) / 2)
+#define YY_START ((yyg->yy_start - 1) / 2)
 #define YYSTATE YY_START
 
 /* Action number for EOF rule of a given start state. */
 #define YY_STATE_EOF(state) (YY_END_OF_BUFFER + state + 1)
 
 /* Special action meaning "start processing a new file". */
-#define YY_NEW_FILE pcap_restart(pcap_in  )
+#define YY_NEW_FILE pcap_restart(yyin ,yyscanner )
 
 #define YY_END_OF_BUFFER_CHAR 0
 
@@ -189,10 +191,6 @@
 typedef size_t yy_size_t;
 #endif
 
-extern yy_size_t pcap_leng;
-
-extern FILE *pcap_in, *pcap_out;
-
 #define EOB_ACT_CONTINUE_SCAN 0
 #define EOB_ACT_END_OF_FILE 1
 #define EOB_ACT_LAST_MATCH 2
@@ -204,17 +202,17 @@
 #define yyless(n) \
 	do \
 		{ \
-		/* Undo effects of setting up pcap_text. */ \
+		/* Undo effects of setting up yytext. */ \
         int yyless_macro_arg = (n); \
         YY_LESS_LINENO(yyless_macro_arg);\
-		*yy_cp = (yy_hold_char); \
+		*yy_cp = yyg->yy_hold_char; \
 		YY_RESTORE_YY_MORE_OFFSET \
-		(yy_c_buf_p) = yy_cp = yy_bp + yyless_macro_arg - YY_MORE_ADJ; \
-		YY_DO_BEFORE_ACTION; /* set up pcap_text again */ \
+		yyg->yy_c_buf_p = yy_cp = yy_bp + yyless_macro_arg - YY_MORE_ADJ; \
+		YY_DO_BEFORE_ACTION; /* set up yytext again */ \
 		} \
 	while ( 0 )
 
-#define unput(c) yyunput( c, (yytext_ptr)  )
+#define unput(c) yyunput( c, yyg->yytext_ptr , yyscanner )
 
 #ifndef YY_STRUCT_YY_BUFFER_STATE
 #define YY_STRUCT_YY_BUFFER_STATE
@@ -274,78 +272,58 @@
 	 *
 	 * When we actually see the EOF, we change the status to "new"
 	 * (via pcap_restart()), so that the user can continue scanning by
-	 * just pointing pcap_in at a new input file.
+	 * just pointing yyin at a new input file.
 	 */
 #define YY_BUFFER_EOF_PENDING 2
 
 	};
 #endif /* !YY_STRUCT_YY_BUFFER_STATE */
 
-/* Stack of input buffers. */
-static size_t yy_buffer_stack_top = 0; /**< index of top of stack. */
-static size_t yy_buffer_stack_max = 0; /**< capacity of stack. */
-static YY_BUFFER_STATE * yy_buffer_stack = 0; /**< Stack as an array. */
-
 /* We provide macros for accessing buffer states in case in the
  * future we want to put the buffer states in a more general
  * "scanner state".
  *
  * Returns the top of the stack, or NULL.
  */
-#define YY_CURRENT_BUFFER ( (yy_buffer_stack) \
-                          ? (yy_buffer_stack)[(yy_buffer_stack_top)] \
+#define YY_CURRENT_BUFFER ( yyg->yy_buffer_stack \
+                          ? yyg->yy_buffer_stack[yyg->yy_buffer_stack_top] \
                           : NULL)
 
 /* Same as previous macro, but useful when we know that the buffer stack is not
  * NULL or when we need an lvalue. For internal use only.
  */
-#define YY_CURRENT_BUFFER_LVALUE (yy_buffer_stack)[(yy_buffer_stack_top)]
+#define YY_CURRENT_BUFFER_LVALUE yyg->yy_buffer_stack[yyg->yy_buffer_stack_top]
 
-/* yy_hold_char holds the character lost when pcap_text is formed. */
-static char yy_hold_char;
-static yy_size_t yy_n_chars;		/* number of characters read into yy_ch_buf */
-yy_size_t pcap_leng;
+void pcap_restart (FILE *input_file ,yyscan_t yyscanner );
+void pcap__switch_to_buffer (YY_BUFFER_STATE new_buffer ,yyscan_t yyscanner );
+YY_BUFFER_STATE pcap__create_buffer (FILE *file,int size ,yyscan_t yyscanner );
+void pcap__delete_buffer (YY_BUFFER_STATE b ,yyscan_t yyscanner );
+void pcap__flush_buffer (YY_BUFFER_STATE b ,yyscan_t yyscanner );
+void pcap_push_buffer_state (YY_BUFFER_STATE new_buffer ,yyscan_t yyscanner );
+void pcap_pop_buffer_state (yyscan_t yyscanner );
 
-/* Points to current character in buffer. */
-static char *yy_c_buf_p = (char *) 0;
-static int yy_init = 0;		/* whether we need to initialize */
-static int yy_start = 0;	/* start state number */
+static void pcap_ensure_buffer_stack (yyscan_t yyscanner );
+static void pcap__load_buffer_state (yyscan_t yyscanner );
+static void pcap__init_buffer (YY_BUFFER_STATE b,FILE *file ,yyscan_t yyscanner );
 
-/* Flag which is used to allow pcap_wrap()'s to do buffer switches
- * instead of setting up a fresh pcap_in.  A bit of a hack ...
- */
-static int yy_did_buffer_switch_on_eof;
+#define YY_FLUSH_BUFFER pcap__flush_buffer(YY_CURRENT_BUFFER ,yyscanner)
 
-void pcap_restart (FILE *input_file  );
-void pcap__switch_to_buffer (YY_BUFFER_STATE new_buffer  );
-YY_BUFFER_STATE pcap__create_buffer (FILE *file,int size  );
-void pcap__delete_buffer (YY_BUFFER_STATE b  );
-void pcap__flush_buffer (YY_BUFFER_STATE b  );
-void pcap_push_buffer_state (YY_BUFFER_STATE new_buffer  );
-void pcap_pop_buffer_state (void );
+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 );
 
-static void pcap_ensure_buffer_stack (void );
-static void pcap__load_buffer_state (void );
-static void pcap__init_buffer (YY_BUFFER_STATE b,FILE *file  );
-
-#define YY_FLUSH_BUFFER pcap__flush_buffer(YY_CURRENT_BUFFER )
-
-YY_BUFFER_STATE pcap__scan_buffer (char *base,yy_size_t size  );
-YY_BUFFER_STATE pcap__scan_string (yyconst char *yy_str  );
-YY_BUFFER_STATE pcap__scan_bytes (yyconst char *bytes,yy_size_t len  );
-
-void *pcap_alloc (yy_size_t  );
-void *pcap_realloc (void *,yy_size_t  );
-void pcap_free (void *  );
+void *pcap_alloc (yy_size_t ,yyscan_t yyscanner );
+void *pcap_realloc (void *,yy_size_t ,yyscan_t yyscanner );
+void pcap_free (void * ,yyscan_t yyscanner );
 
 #define yy_new_buffer pcap__create_buffer
 
 #define yy_set_interactive(is_interactive) \
 	{ \
 	if ( ! YY_CURRENT_BUFFER ){ \
-        pcap_ensure_buffer_stack (); \
+        pcap_ensure_buffer_stack (yyscanner); \
 		YY_CURRENT_BUFFER_LVALUE =    \
-            pcap__create_buffer(pcap_in,YY_BUF_SIZE ); \
+            pcap__create_buffer(yyin,YY_BUF_SIZE ,yyscanner); \
 	} \
 	YY_CURRENT_BUFFER_LVALUE->yy_is_interactive = is_interactive; \
 	}
@@ -353,9 +331,9 @@
 #define yy_set_bol(at_bol) \
 	{ \
 	if ( ! YY_CURRENT_BUFFER ){\
-        pcap_ensure_buffer_stack (); \
+        pcap_ensure_buffer_stack (yyscanner); \
 		YY_CURRENT_BUFFER_LVALUE =    \
-            pcap__create_buffer(pcap_in,YY_BUF_SIZE ); \
+            pcap__create_buffer(yyin,YY_BUF_SIZE ,yyscanner); \
 	} \
 	YY_CURRENT_BUFFER_LVALUE->yy_at_bol = at_bol; \
 	}
@@ -364,33 +342,29 @@
 
 /* Begin user sect3 */
 
-typedef unsigned char YY_CHAR;
+#define pcap_wrap(yyscanner) 1
+#define YY_SKIP_YYWRAP
 
-FILE *pcap_in = (FILE *) 0, *pcap_out = (FILE *) 0;
+typedef unsigned char YY_CHAR;
 
 typedef int yy_state_type;
 
-extern int pcap_lineno;
+#define yytext_ptr yytext_r
 
-int pcap_lineno = 1;
-
-extern char *pcap_text;
-#define yytext_ptr pcap_text
-
-static yy_state_type yy_get_previous_state (void );
-static yy_state_type yy_try_NUL_trans (yy_state_type current_state  );
-static int yy_get_next_buffer (void );
-static void yy_fatal_error (yyconst char msg[]  );
+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 );
 
 /* Done after the current pattern has been matched and before the
- * corresponding action - sets up pcap_text.
+ * corresponding action - sets up yytext.
  */
 #define YY_DO_BEFORE_ACTION \
-	(yytext_ptr) = yy_bp; \
-	pcap_leng = (size_t) (yy_cp - yy_bp); \
-	(yy_hold_char) = *yy_cp; \
+	yyg->yytext_ptr = yy_bp; \
+	yyleng = (size_t) (yy_cp - yy_bp); \
+	yyg->yy_hold_char = *yy_cp; \
 	*yy_cp = '\0'; \
-	(yy_c_buf_p) = yy_cp;
+	yyg->yy_c_buf_p = yy_cp;
 
 #define YY_NUM_RULES 155
 #define YY_END_OF_BUFFER 156
@@ -2692,12 +2666,6 @@
      1463, 1463, 1463
     } ;
 
-static yy_state_type yy_last_accepting_state;
-static char *yy_last_accepting_cpos;
-
-extern int pcap__flex_debug;
-int pcap__flex_debug = 0;
-
 /* The intent behind this definition is that it'll catch
  * any uses of REJECT which flex missed.
  */
@@ -2705,9 +2673,32 @@
 #define yymore() yymore_used_but_not_detected
 #define YY_MORE_ADJ 0
 #define YY_RESTORE_YY_MORE_OFFSET
-char *pcap_text;
 #line 1 "scanner.l"
-#line 2 "scanner.l"
+
+/*
+ * We want a reentrant scanner.
+ */
+/*
+ * And we need to pass the compiler state to the scanner.
+ */
+/*
+ * We don't use input, so don't generate code for it.
+ */
+#define YY_NO_INPUT 1
+/*
+ * We don't use unput, so don't generate code for it.
+ */
+/*
+ * We don't read from the terminal.
+ */
+/*
+ * We want to stop processing when we get to the end of the input.
+ */
+/*
+ * We want to generate code that can be used by a reentrant parser
+ * generated by Bison or Berkeley YACC.
+ */
+#line 45 "scanner.l"
 /*
  * Copyright (c) 1988, 1989, 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1997
  *	The Regents of the University of California.  All rights reserved.
@@ -2729,19 +2720,19 @@
  * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
  */
 
-#ifdef WIN32
-#include <pcap-stdinc.h>
-#else /* WIN32 */
-#if HAVE_INTTYPES_H
-#include <inttypes.h>
-#elif HAVE_STDINT_H
-#include <stdint.h>
+#ifdef _WIN32
+  #include <pcap-stdinc.h>
+#else
+  #if HAVE_INTTYPES_H
+    #include <inttypes.h>
+  #elif HAVE_STDINT_H
+    #include <stdint.h>
+  #endif
+  #ifdef HAVE_SYS_BITYPES_H
+    #include <sys/bitypes.h>
+  #endif
+  #include <sys/types.h>
 #endif
-#ifdef HAVE_SYS_BITYPES_H
-#include <sys/bitypes.h>
-#endif
-#include <sys/types.h>
-#endif /* WIN32 */
 
 #include <ctype.h>
 #include <string.h>
@@ -2749,25 +2740,56 @@
 #include "pcap-int.h"
 
 #include "gencode.h"
-#ifdef INET6
-#ifdef WIN32
-#include <pcap-stdinc.h>
 
-#ifdef __MINGW32__
-#include "ip6_misc.h"
-#endif
-#else /* WIN32 */
+#include "grammar.h"
+
+/*
+ * Earlier versions of Flex don't declare these, so we declare them
+ * ourselves to squelch warnings.
+ */
+int pcap_get_column(yyscan_t);
+void pcap_set_column(int, yyscan_t);
+
+#ifdef INET6
+
+#ifdef _WIN32
+/*
+ * To quote the MSDN page for getaddrinfo() at
+ *
+ *    https://msdn.microsoft.com/en-us/library/windows/desktop/ms738520(v=vs.85).aspx
+ *
+ * "Support for getaddrinfo on Windows 2000 and older versions
+ * The getaddrinfo function was added to the Ws2_32.dll on Windows XP and
+ * later. To execute an application that uses this function on earlier
+ * versions of Windows, then you need to include the Ws2tcpip.h and
+ * Wspiapi.h files. When the Wspiapi.h include file is added, the
+ * getaddrinfo function is defined to the WspiapiGetAddrInfo inline
+ * function in the Wspiapi.h file. At runtime, the WspiapiGetAddrInfo
+ * function is implemented in such a way that if the Ws2_32.dll or the
+ * Wship6.dll (the file containing getaddrinfo in the IPv6 Technology
+ * Preview for Windows 2000) does not include getaddrinfo, then a
+ * version of getaddrinfo is implemented inline based on code in the
+ * Wspiapi.h header file. This inline code will be used on older Windows
+ * platforms that do not natively support the getaddrinfo function."
+ *
+ * We use getaddrinfo(), so we include Wspiapi.h here.  pcap-stdinc.h
+ * includes Ws2tcpip.h, so we don't need to include it ourselves.
+ */
+#include <Wspiapi.h>
+#else /* _WIN32 */
 #include <sys/socket.h>	/* for "struct sockaddr" in "struct addrinfo" */
 #include <netdb.h>	/* for "struct addrinfo" */
-#endif /* WIN32 */
+#endif /* _WIN32 */
 
 /* Workaround for AIX 4.3 */
 #if !defined(AI_NUMERICHOST)
 #define AI_NUMERICHOST 0x04
 #endif
+
 #endif /*INET6*/
+
 #include <pcap/namedb.h>
-#include "tokdefs.h"
+#include "grammar.h"
 
 #ifdef HAVE_OS_PROTO_H
 #include "os-proto.h"
@@ -2776,21 +2798,7 @@
 static int stoi(char *);
 static inline int xdtoi(int);
 
-#ifdef FLEX_SCANNER
-#define YY_NO_INPUT
-#define YY_NO_UNPUT
-static YY_BUFFER_STATE in_buffer;
-#else
-static const char *in_buffer;
-
-#undef getc
-#define getc(fp)  (*in_buffer == 0 ? EOF : *in_buffer++)
-#endif
-
-#define yylval pcap_lval
-extern YYSTYPE yylval;
-
-#line 2791 "scanner.c"
+#line 2802 "scanner.c"
 
 #define INITIAL 0
 
@@ -2802,24 +2810,90 @@
 #include <unistd.h>
 #endif
 
-#ifndef YY_EXTRA_TYPE
-#define YY_EXTRA_TYPE void *
-#endif
+#define YY_EXTRA_TYPE compiler_state_t *
 
-static int yy_init_globals (void );
+/* Holds the entire state of the reentrant scanner. */
+struct yyguts_t
+    {
+
+    /* User-defined. Not touched by flex. */
+    YY_EXTRA_TYPE yyextra_r;
+
+    /* The rest are the same as the globals declared in the non-reentrant scanner. */
+    FILE *yyin_r, *yyout_r;
+    size_t yy_buffer_stack_top; /**< index of top of stack. */
+    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;
+    char *yy_c_buf_p;
+    int yy_init;
+    int yy_start;
+    int yy_did_buffer_switch_on_eof;
+    int yy_start_stack_ptr;
+    int yy_start_stack_depth;
+    int *yy_start_stack;
+    yy_state_type yy_last_accepting_state;
+    char* yy_last_accepting_cpos;
+
+    int yylineno_r;
+    int yy_flex_debug_r;
+
+    char *yytext_r;
+    int yy_more_flag;
+    int yy_more_len;
+
+    YYSTYPE * yylval_r;
+
+    }; /* end struct yyguts_t */
+
+static int yy_init_globals (yyscan_t yyscanner );
+
+    /* This must go here because YYSTYPE and YYLTYPE are included
+     * from bison output in section 1.*/
+    #    define yylval yyg->yylval_r
+    
+int pcap_lex_init (yyscan_t* scanner);
+
+int pcap_lex_init_extra (YY_EXTRA_TYPE user_defined,yyscan_t* scanner);
 
 /* Accessor methods to globals.
    These are made visible to non-reentrant scanners for convenience. */
 
-int pcap_lex_destroy (void );
+int pcap_lex_destroy (yyscan_t yyscanner );
 
-int pcap_get_debug (void );
+int pcap_get_debug (yyscan_t yyscanner );
 
-void pcap_set_debug (int debug_flag  );
+void pcap_set_debug (int debug_flag ,yyscan_t yyscanner );
 
-YY_EXTRA_TYPE pcap_get_extra (void );
+YY_EXTRA_TYPE pcap_get_extra (yyscan_t yyscanner );
 
-void pcap_set_extra (YY_EXTRA_TYPE user_defined  );
+void pcap_set_extra (YY_EXTRA_TYPE user_defined ,yyscan_t yyscanner );
+
+FILE *pcap_get_in (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 );
+
+yy_size_t 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 );
+
+int pcap_get_column  (yyscan_t yyscanner );
+
+void pcap_set_column (int column_no ,yyscan_t yyscanner );
+
+YYSTYPE * pcap_get_lval (yyscan_t yyscanner );
+
+void pcap_set_lval (YYSTYPE * yylval_param ,yyscan_t yyscanner );
 
 /* Macros after this point can all be overridden by user definitions in
  * section 1.
@@ -2827,26 +2901,26 @@
 
 #ifndef YY_SKIP_YYWRAP
 #ifdef __cplusplus
-extern "C" int pcap_wrap (void );
+extern "C" int pcap_wrap (yyscan_t yyscanner );
 #else
-extern int pcap_wrap (void );
+extern int pcap_wrap (yyscan_t yyscanner );
 #endif
 #endif
 
 #ifndef yytext_ptr
-static void yy_flex_strncpy (char *,yyconst char *,int );
+static void yy_flex_strncpy (char *,yyconst char *,int ,yyscan_t yyscanner);
 #endif
 
 #ifdef YY_NEED_STRLEN
-static int yy_flex_strlen (yyconst char * );
+static int yy_flex_strlen (yyconst char * ,yyscan_t yyscanner);
 #endif
 
 #ifndef YY_NO_INPUT
 
 #ifdef __cplusplus
-static int yyinput (void );
+static int yyinput (yyscan_t yyscanner );
 #else
-static int input (void );
+static int input (yyscan_t yyscanner );
 #endif
 
 #endif
@@ -2866,7 +2940,7 @@
 /* This used to be an fputs(), but since the string might contain NUL's,
  * we now use fwrite().
  */
-#define ECHO do { if (fwrite( pcap_text, pcap_leng, 1, pcap_out )) {} } while (0)
+#define ECHO do { if (fwrite( yytext, yyleng, 1, yyout )) {} } while (0)
 #endif
 
 /* Gets input and stuffs it into "buf".  number of characters read, or YY_NULL,
@@ -2879,18 +2953,18 @@
 		int c = '*'; \
 		size_t n; \
 		for ( n = 0; n < max_size && \
-			     (c = getc( pcap_in )) != EOF && c != '\n'; ++n ) \
+			     (c = getc( yyin )) != EOF && c != '\n'; ++n ) \
 			buf[n] = (char) c; \
 		if ( c == '\n' ) \
 			buf[n++] = (char) c; \
-		if ( c == EOF && ferror( pcap_in ) ) \
+		if ( c == EOF && ferror( yyin ) ) \
 			YY_FATAL_ERROR( "input in flex scanner failed" ); \
 		result = n; \
 		} \
 	else \
 		{ \
 		errno=0; \
-		while ( (result = fread(buf, 1, max_size, pcap_in))==0 && ferror(pcap_in)) \
+		while ( (result = fread(buf, 1, max_size, yyin))==0 && ferror(yyin)) \
 			{ \
 			if( errno != EINTR) \
 				{ \
@@ -2898,7 +2972,7 @@
 				break; \
 				} \
 			errno=0; \
-			clearerr(pcap_in); \
+			clearerr(yyin); \
 			} \
 		}\
 \
@@ -2920,7 +2994,7 @@
 
 /* Report a fatal error. */
 #ifndef YY_FATAL_ERROR
-#define YY_FATAL_ERROR(msg) yy_fatal_error( msg )
+#define YY_FATAL_ERROR(msg) yy_fatal_error( msg , yyscanner)
 #endif
 
 /* end tables serialization structures and prototypes */
@@ -2931,12 +3005,14 @@
 #ifndef YY_DECL
 #define YY_DECL_IS_OURS 1
 
-extern int pcap_lex (void);
+extern int pcap_lex \
+               (YYSTYPE * yylval_param ,yyscan_t yyscanner);
 
-#define YY_DECL int pcap_lex (void)
+#define YY_DECL int pcap_lex \
+               (YYSTYPE * yylval_param , yyscan_t yyscanner)
 #endif /* !YY_DECL */
 
-/* Code executed at the beginning of each rule, after pcap_text and pcap_leng
+/* Code executed at the beginning of each rule, after yytext and yyleng
  * have been set up.
  */
 #ifndef YY_USER_ACTION
@@ -2958,59 +3034,62 @@
 	register yy_state_type yy_current_state;
 	register char *yy_cp, *yy_bp;
 	register int yy_act;
-    
-	if ( !(yy_init) )
+    struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
+
+    yylval = yylval_param;
+
+	if ( !yyg->yy_init )
 		{
-		(yy_init) = 1;
+		yyg->yy_init = 1;
 
 #ifdef YY_USER_INIT
 		YY_USER_INIT;
 #endif
 
-		if ( ! (yy_start) )
-			(yy_start) = 1;	/* first start state */
+		if ( ! yyg->yy_start )
+			yyg->yy_start = 1;	/* first start state */
 
-		if ( ! pcap_in )
-			pcap_in = stdin;
+		if ( ! yyin )
+			yyin = stdin;
 
-		if ( ! pcap_out )
-			pcap_out = stdout;
+		if ( ! yyout )
+			yyout = stdout;
 
 		if ( ! YY_CURRENT_BUFFER ) {
-			pcap_ensure_buffer_stack ();
+			pcap_ensure_buffer_stack (yyscanner);
 			YY_CURRENT_BUFFER_LVALUE =
-				pcap__create_buffer(pcap_in,YY_BUF_SIZE );
+				pcap__create_buffer(yyin,YY_BUF_SIZE ,yyscanner);
 		}
 
-		pcap__load_buffer_state( );
+		pcap__load_buffer_state(yyscanner );
 		}
 
 	{
-#line 180 "scanner.l"
+#line 240 "scanner.l"
 
-#line 2989 "scanner.c"
+#line 3071 "scanner.c"
 
 	while ( 1 )		/* loops until end-of-file is reached */
 		{
-		yy_cp = (yy_c_buf_p);
+		yy_cp = yyg->yy_c_buf_p;
 
-		/* Support of pcap_text. */
-		*yy_cp = (yy_hold_char);
+		/* Support of yytext. */
+		*yy_cp = yyg->yy_hold_char;
 
 		/* yy_bp points to the position in yy_ch_buf of the start of
 		 * the current run.
 		 */
 		yy_bp = yy_cp;
 
-		yy_current_state = (yy_start);
+		yy_current_state = yyg->yy_start;
 yy_match:
 		do
 			{
 			register YY_CHAR yy_c = yy_ec[YY_SC_TO_UI(*yy_cp)] ;
 			if ( yy_accept[yy_current_state] )
 				{
-				(yy_last_accepting_state) = yy_current_state;
-				(yy_last_accepting_cpos) = yy_cp;
+				yyg->yy_last_accepting_state = yy_current_state;
+				yyg->yy_last_accepting_cpos = yy_cp;
 				}
 			while ( yy_chk[yy_base[yy_current_state] + yy_c] != yy_current_state )
 				{
@@ -3021,16 +3100,12 @@
 			yy_current_state = yy_nxt[yy_base[yy_current_state] + (unsigned int) yy_c];
 			++yy_cp;
 			}
-		while ( yy_base[yy_current_state] != 7420 );
+		while ( yy_current_state != 1463 );
+		yy_cp = yyg->yy_last_accepting_cpos;
+		yy_current_state = yyg->yy_last_accepting_state;
 
 yy_find_action:
 		yy_act = yy_accept[yy_current_state];
-		if ( yy_act == 0 )
-			{ /* have to back up */
-			yy_cp = (yy_last_accepting_cpos);
-			yy_current_state = (yy_last_accepting_state);
-			yy_act = yy_accept[yy_current_state];
-			}
 
 		YY_DO_BEFORE_ACTION;
 
@@ -3040,267 +3115,267 @@
 	{ /* beginning of action switch */
 			case 0: /* must back up */
 			/* undo the effects of YY_DO_BEFORE_ACTION */
-			*yy_cp = (yy_hold_char);
-			yy_cp = (yy_last_accepting_cpos);
-			yy_current_state = (yy_last_accepting_state);
+			*yy_cp = yyg->yy_hold_char;
+			yy_cp = yyg->yy_last_accepting_cpos;
+			yy_current_state = yyg->yy_last_accepting_state;
 			goto yy_find_action;
 
 case 1:
 YY_RULE_SETUP
-#line 181 "scanner.l"
+#line 241 "scanner.l"
 return DST;
 	YY_BREAK
 case 2:
 YY_RULE_SETUP
-#line 182 "scanner.l"
+#line 242 "scanner.l"
 return SRC;
 	YY_BREAK
 case 3:
 YY_RULE_SETUP
-#line 184 "scanner.l"
+#line 244 "scanner.l"
 return LINK;
 	YY_BREAK
 case 4:
 YY_RULE_SETUP
-#line 185 "scanner.l"
+#line 245 "scanner.l"
 return LINK;
 	YY_BREAK
 case 5:
 YY_RULE_SETUP
-#line 186 "scanner.l"
+#line 246 "scanner.l"
 return ARP;
 	YY_BREAK
 case 6:
 YY_RULE_SETUP
-#line 187 "scanner.l"
+#line 247 "scanner.l"
 return RARP;
 	YY_BREAK
 case 7:
 YY_RULE_SETUP
-#line 188 "scanner.l"
+#line 248 "scanner.l"
 return IP;
 	YY_BREAK
 case 8:
 YY_RULE_SETUP
-#line 189 "scanner.l"
+#line 249 "scanner.l"
 return SCTP;
 	YY_BREAK
 case 9:
 YY_RULE_SETUP
-#line 190 "scanner.l"
+#line 250 "scanner.l"
 return TCP;
 	YY_BREAK
 case 10:
 YY_RULE_SETUP
-#line 191 "scanner.l"
+#line 251 "scanner.l"
 return UDP;
 	YY_BREAK
 case 11:
 YY_RULE_SETUP
-#line 192 "scanner.l"
+#line 252 "scanner.l"
 return ICMP;
 	YY_BREAK
 case 12:
 YY_RULE_SETUP
-#line 193 "scanner.l"
+#line 253 "scanner.l"
 return IGMP;
 	YY_BREAK
 case 13:
 YY_RULE_SETUP
-#line 194 "scanner.l"
+#line 254 "scanner.l"
 return IGRP;
 	YY_BREAK
 case 14:
 YY_RULE_SETUP
-#line 195 "scanner.l"
+#line 255 "scanner.l"
 return PIM;
 	YY_BREAK
 case 15:
 YY_RULE_SETUP
-#line 196 "scanner.l"
+#line 256 "scanner.l"
 return VRRP;
 	YY_BREAK
 case 16:
 YY_RULE_SETUP
-#line 197 "scanner.l"
+#line 257 "scanner.l"
 return CARP;
 	YY_BREAK
 case 17:
 YY_RULE_SETUP
-#line 198 "scanner.l"
+#line 258 "scanner.l"
 return RADIO;
 	YY_BREAK
 case 18:
 YY_RULE_SETUP
-#line 200 "scanner.l"
+#line 260 "scanner.l"
 return IPV6;
 	YY_BREAK
 case 19:
 YY_RULE_SETUP
-#line 201 "scanner.l"
+#line 261 "scanner.l"
 return ICMPV6;
 	YY_BREAK
 case 20:
 YY_RULE_SETUP
-#line 202 "scanner.l"
+#line 262 "scanner.l"
 return AH;
 	YY_BREAK
 case 21:
 YY_RULE_SETUP
-#line 203 "scanner.l"
+#line 263 "scanner.l"
 return ESP;
 	YY_BREAK
 case 22:
 YY_RULE_SETUP
-#line 205 "scanner.l"
+#line 265 "scanner.l"
 return ATALK;
 	YY_BREAK
 case 23:
 YY_RULE_SETUP
-#line 206 "scanner.l"
+#line 266 "scanner.l"
 return AARP;
 	YY_BREAK
 case 24:
 YY_RULE_SETUP
-#line 207 "scanner.l"
+#line 267 "scanner.l"
 return DECNET;
 	YY_BREAK
 case 25:
 YY_RULE_SETUP
-#line 208 "scanner.l"
+#line 268 "scanner.l"
 return LAT;
 	YY_BREAK
 case 26:
 YY_RULE_SETUP
-#line 209 "scanner.l"
+#line 269 "scanner.l"
 return SCA;
 	YY_BREAK
 case 27:
 YY_RULE_SETUP
-#line 210 "scanner.l"
+#line 270 "scanner.l"
 return MOPRC;
 	YY_BREAK
 case 28:
 YY_RULE_SETUP
-#line 211 "scanner.l"
+#line 271 "scanner.l"
 return MOPDL;
 	YY_BREAK
 case 29:
 YY_RULE_SETUP
-#line 213 "scanner.l"
+#line 273 "scanner.l"
 return ISO;
 	YY_BREAK
 case 30:
 YY_RULE_SETUP
-#line 214 "scanner.l"
+#line 274 "scanner.l"
 return ESIS;
 	YY_BREAK
 case 31:
 YY_RULE_SETUP
-#line 215 "scanner.l"
+#line 275 "scanner.l"
 return ESIS;
 	YY_BREAK
 case 32:
 YY_RULE_SETUP
-#line 216 "scanner.l"
+#line 276 "scanner.l"
 return ISIS;
 	YY_BREAK
 case 33:
 YY_RULE_SETUP
-#line 217 "scanner.l"
+#line 277 "scanner.l"
 return ISIS;
 	YY_BREAK
 case 34:
 YY_RULE_SETUP
-#line 218 "scanner.l"
+#line 278 "scanner.l"
 return L1;
 	YY_BREAK
 case 35:
 YY_RULE_SETUP
-#line 219 "scanner.l"
+#line 279 "scanner.l"
 return L2;
 	YY_BREAK
 case 36:
 YY_RULE_SETUP
-#line 220 "scanner.l"
+#line 280 "scanner.l"
 return IIH;
 	YY_BREAK
 case 37:
 YY_RULE_SETUP
-#line 221 "scanner.l"
+#line 281 "scanner.l"
 return LSP;
 	YY_BREAK
 case 38:
 YY_RULE_SETUP
-#line 222 "scanner.l"
+#line 282 "scanner.l"
 return SNP;
 	YY_BREAK
 case 39:
 YY_RULE_SETUP
-#line 223 "scanner.l"
+#line 283 "scanner.l"
 return CSNP;
 	YY_BREAK
 case 40:
 YY_RULE_SETUP
-#line 224 "scanner.l"
+#line 284 "scanner.l"
 return PSNP;
 	YY_BREAK
 case 41:
 YY_RULE_SETUP
-#line 226 "scanner.l"
+#line 286 "scanner.l"
 return CLNP;
 	YY_BREAK
 case 42:
 YY_RULE_SETUP
-#line 228 "scanner.l"
+#line 288 "scanner.l"
 return STP;
 	YY_BREAK
 case 43:
 YY_RULE_SETUP
-#line 230 "scanner.l"
+#line 290 "scanner.l"
 return IPX;
 	YY_BREAK
 case 44:
 YY_RULE_SETUP
-#line 232 "scanner.l"
+#line 292 "scanner.l"
 return NETBEUI;
 	YY_BREAK
 case 45:
 YY_RULE_SETUP
-#line 234 "scanner.l"
+#line 294 "scanner.l"
 return HOST;
 	YY_BREAK
 case 46:
 YY_RULE_SETUP
-#line 235 "scanner.l"
+#line 295 "scanner.l"
 return NET;
 	YY_BREAK
 case 47:
 YY_RULE_SETUP
-#line 236 "scanner.l"
+#line 296 "scanner.l"
 return NETMASK;
 	YY_BREAK
 case 48:
 YY_RULE_SETUP
-#line 237 "scanner.l"
+#line 297 "scanner.l"
 return PORT;
 	YY_BREAK
 case 49:
 YY_RULE_SETUP
-#line 238 "scanner.l"
+#line 298 "scanner.l"
 return PORTRANGE;
 	YY_BREAK
 case 50:
 YY_RULE_SETUP
-#line 239 "scanner.l"
+#line 299 "scanner.l"
 return PROTO;
 	YY_BREAK
 case 51:
 YY_RULE_SETUP
-#line 240 "scanner.l"
+#line 300 "scanner.l"
 {
 #ifdef NO_PROTOCHAIN
-		  bpf_error("%s not supported", pcap_text);
+		  bpf_error(yyextra, "%s not supported", yytext);
 #else
 		  return PROTOCHAIN;
 #endif
@@ -3308,575 +3383,575 @@
 	YY_BREAK
 case 52:
 YY_RULE_SETUP
-#line 248 "scanner.l"
+#line 308 "scanner.l"
 return GATEWAY;
 	YY_BREAK
 case 53:
 YY_RULE_SETUP
-#line 250 "scanner.l"
+#line 310 "scanner.l"
 return TYPE;
 	YY_BREAK
 case 54:
 YY_RULE_SETUP
-#line 251 "scanner.l"
+#line 311 "scanner.l"
 return SUBTYPE;
 	YY_BREAK
 case 55:
 YY_RULE_SETUP
-#line 252 "scanner.l"
+#line 312 "scanner.l"
 return DIR;
 	YY_BREAK
 case 56:
 YY_RULE_SETUP
-#line 253 "scanner.l"
+#line 313 "scanner.l"
 return ADDR1;
 	YY_BREAK
 case 57:
 YY_RULE_SETUP
-#line 254 "scanner.l"
+#line 314 "scanner.l"
 return ADDR2;
 	YY_BREAK
 case 58:
 YY_RULE_SETUP
-#line 255 "scanner.l"
+#line 315 "scanner.l"
 return ADDR3;
 	YY_BREAK
 case 59:
 YY_RULE_SETUP
-#line 256 "scanner.l"
+#line 316 "scanner.l"
 return ADDR4;
 	YY_BREAK
 case 60:
 YY_RULE_SETUP
-#line 257 "scanner.l"
+#line 317 "scanner.l"
 return RA;
 	YY_BREAK
 case 61:
 YY_RULE_SETUP
-#line 258 "scanner.l"
+#line 318 "scanner.l"
 return TA;
 	YY_BREAK
 case 62:
 YY_RULE_SETUP
-#line 260 "scanner.l"
+#line 320 "scanner.l"
 return LESS;
 	YY_BREAK
 case 63:
 YY_RULE_SETUP
-#line 261 "scanner.l"
+#line 321 "scanner.l"
 return GREATER;
 	YY_BREAK
 case 64:
 YY_RULE_SETUP
-#line 262 "scanner.l"
+#line 322 "scanner.l"
 return CBYTE;
 	YY_BREAK
 case 65:
 YY_RULE_SETUP
-#line 263 "scanner.l"
+#line 323 "scanner.l"
 return TK_BROADCAST;
 	YY_BREAK
 case 66:
 YY_RULE_SETUP
-#line 264 "scanner.l"
+#line 324 "scanner.l"
 return TK_MULTICAST;
 	YY_BREAK
 case 67:
 YY_RULE_SETUP
-#line 266 "scanner.l"
+#line 326 "scanner.l"
 return AND;
 	YY_BREAK
 case 68:
 YY_RULE_SETUP
-#line 267 "scanner.l"
+#line 327 "scanner.l"
 return OR;
 	YY_BREAK
 case 69:
 YY_RULE_SETUP
-#line 268 "scanner.l"
+#line 328 "scanner.l"
 return '!';
 	YY_BREAK
 case 70:
 YY_RULE_SETUP
-#line 270 "scanner.l"
+#line 330 "scanner.l"
 return LEN;
 	YY_BREAK
 case 71:
 YY_RULE_SETUP
-#line 271 "scanner.l"
+#line 331 "scanner.l"
 return INBOUND;
 	YY_BREAK
 case 72:
 YY_RULE_SETUP
-#line 272 "scanner.l"
+#line 332 "scanner.l"
 return OUTBOUND;
 	YY_BREAK
 case 73:
 YY_RULE_SETUP
-#line 274 "scanner.l"
+#line 334 "scanner.l"
 return VLAN;
 	YY_BREAK
 case 74:
 YY_RULE_SETUP
-#line 275 "scanner.l"
+#line 335 "scanner.l"
 return MPLS;
 	YY_BREAK
 case 75:
 YY_RULE_SETUP
-#line 276 "scanner.l"
+#line 336 "scanner.l"
 return PPPOED;
 	YY_BREAK
 case 76:
 YY_RULE_SETUP
-#line 277 "scanner.l"
+#line 337 "scanner.l"
 return PPPOES;
 	YY_BREAK
 case 77:
 YY_RULE_SETUP
-#line 278 "scanner.l"
+#line 338 "scanner.l"
 return GENEVE;
 	YY_BREAK
 case 78:
 YY_RULE_SETUP
-#line 280 "scanner.l"
+#line 340 "scanner.l"
 return LANE;
 	YY_BREAK
 case 79:
 YY_RULE_SETUP
-#line 281 "scanner.l"
+#line 341 "scanner.l"
 return LLC;
 	YY_BREAK
 case 80:
 YY_RULE_SETUP
-#line 282 "scanner.l"
+#line 342 "scanner.l"
 return METAC;
 	YY_BREAK
 case 81:
 YY_RULE_SETUP
-#line 283 "scanner.l"
+#line 343 "scanner.l"
 return BCC;
 	YY_BREAK
 case 82:
 YY_RULE_SETUP
-#line 284 "scanner.l"
+#line 344 "scanner.l"
 return OAM;
 	YY_BREAK
 case 83:
 YY_RULE_SETUP
-#line 285 "scanner.l"
+#line 345 "scanner.l"
 return OAMF4;
 	YY_BREAK
 case 84:
 YY_RULE_SETUP
-#line 286 "scanner.l"
+#line 346 "scanner.l"
 return OAMF4EC;
 	YY_BREAK
 case 85:
 YY_RULE_SETUP
-#line 287 "scanner.l"
+#line 347 "scanner.l"
 return OAMF4SC;
 	YY_BREAK
 case 86:
 YY_RULE_SETUP
-#line 288 "scanner.l"
+#line 348 "scanner.l"
 return SC;
 	YY_BREAK
 case 87:
 YY_RULE_SETUP
-#line 289 "scanner.l"
+#line 349 "scanner.l"
 return ILMIC;
 	YY_BREAK
 case 88:
 YY_RULE_SETUP
-#line 290 "scanner.l"
+#line 350 "scanner.l"
 return VPI;
 	YY_BREAK
 case 89:
 YY_RULE_SETUP
-#line 291 "scanner.l"
+#line 351 "scanner.l"
 return VCI;
 	YY_BREAK
 case 90:
 YY_RULE_SETUP
-#line 292 "scanner.l"
+#line 352 "scanner.l"
 return CONNECTMSG;
 	YY_BREAK
 case 91:
 YY_RULE_SETUP
-#line 293 "scanner.l"
+#line 353 "scanner.l"
 return METACONNECT;
 	YY_BREAK
 case 92:
 YY_RULE_SETUP
-#line 295 "scanner.l"
+#line 355 "scanner.l"
 return PF_IFNAME;
 	YY_BREAK
 case 93:
 YY_RULE_SETUP
-#line 296 "scanner.l"
+#line 356 "scanner.l"
 return PF_RSET;
 	YY_BREAK
 case 94:
 YY_RULE_SETUP
-#line 297 "scanner.l"
+#line 357 "scanner.l"
 return PF_RNR;
 	YY_BREAK
 case 95:
 YY_RULE_SETUP
-#line 298 "scanner.l"
+#line 358 "scanner.l"
 return PF_SRNR;
 	YY_BREAK
 case 96:
 YY_RULE_SETUP
-#line 299 "scanner.l"
+#line 359 "scanner.l"
 return PF_REASON;
 	YY_BREAK
 case 97:
 YY_RULE_SETUP
-#line 300 "scanner.l"
+#line 360 "scanner.l"
 return PF_ACTION;
 	YY_BREAK
 case 98:
 YY_RULE_SETUP
-#line 302 "scanner.l"
+#line 362 "scanner.l"
 return FISU;
 	YY_BREAK
 case 99:
 YY_RULE_SETUP
-#line 303 "scanner.l"
+#line 363 "scanner.l"
 return LSSU;
 	YY_BREAK
 case 100:
 YY_RULE_SETUP
-#line 304 "scanner.l"
+#line 364 "scanner.l"
 return LSSU;
 	YY_BREAK
 case 101:
 YY_RULE_SETUP
-#line 305 "scanner.l"
+#line 365 "scanner.l"
 return MSU;
 	YY_BREAK
 case 102:
 YY_RULE_SETUP
-#line 306 "scanner.l"
+#line 366 "scanner.l"
 return HFISU;
 	YY_BREAK
 case 103:
 YY_RULE_SETUP
-#line 307 "scanner.l"
+#line 367 "scanner.l"
 return HLSSU;
 	YY_BREAK
 case 104:
 YY_RULE_SETUP
-#line 308 "scanner.l"
+#line 368 "scanner.l"
 return HMSU;
 	YY_BREAK
 case 105:
 YY_RULE_SETUP
-#line 309 "scanner.l"
+#line 369 "scanner.l"
 return SIO;
 	YY_BREAK
 case 106:
 YY_RULE_SETUP
-#line 310 "scanner.l"
+#line 370 "scanner.l"
 return OPC;
 	YY_BREAK
 case 107:
 YY_RULE_SETUP
-#line 311 "scanner.l"
+#line 371 "scanner.l"
 return DPC;
 	YY_BREAK
 case 108:
 YY_RULE_SETUP
-#line 312 "scanner.l"
+#line 372 "scanner.l"
 return SLS;
 	YY_BREAK
 case 109:
 YY_RULE_SETUP
-#line 313 "scanner.l"
+#line 373 "scanner.l"
 return HSIO;
 	YY_BREAK
 case 110:
 YY_RULE_SETUP
-#line 314 "scanner.l"
+#line 374 "scanner.l"
 return HOPC;
 	YY_BREAK
 case 111:
 YY_RULE_SETUP
-#line 315 "scanner.l"
+#line 375 "scanner.l"
 return HDPC;
 	YY_BREAK
 case 112:
 YY_RULE_SETUP
-#line 316 "scanner.l"
+#line 376 "scanner.l"
 return HSLS;
 	YY_BREAK
 case 113:
 /* rule 113 can match eol */
 YY_RULE_SETUP
-#line 318 "scanner.l"
+#line 378 "scanner.l"
 ;
 	YY_BREAK
 case 114:
 YY_RULE_SETUP
-#line 319 "scanner.l"
-return pcap_text[0];
+#line 379 "scanner.l"
+return yytext[0];
 	YY_BREAK
 case 115:
 YY_RULE_SETUP
-#line 320 "scanner.l"
+#line 380 "scanner.l"
 return GEQ;
 	YY_BREAK
 case 116:
 YY_RULE_SETUP
-#line 321 "scanner.l"
+#line 381 "scanner.l"
 return LEQ;
 	YY_BREAK
 case 117:
 YY_RULE_SETUP
-#line 322 "scanner.l"
+#line 382 "scanner.l"
 return NEQ;
 	YY_BREAK
 case 118:
 YY_RULE_SETUP
-#line 323 "scanner.l"
+#line 383 "scanner.l"
 return '=';
 	YY_BREAK
 case 119:
 YY_RULE_SETUP
-#line 324 "scanner.l"
+#line 384 "scanner.l"
 return LSH;
 	YY_BREAK
 case 120:
 YY_RULE_SETUP
-#line 325 "scanner.l"
+#line 385 "scanner.l"
 return RSH;
 	YY_BREAK
 case 121:
 YY_RULE_SETUP
-#line 326 "scanner.l"
-{ yylval.e = pcap_ether_aton(((char *)pcap_text)+1);
-			  if (yylval.e == NULL)
-				bpf_error("malloc");
+#line 386 "scanner.l"
+{ yylval->e = pcap_ether_aton(((char *)yytext)+1);
+			  if (yylval->e == NULL)
+				bpf_error(yyextra, "malloc");
 			  return AID; }
 	YY_BREAK
 case 122:
 YY_RULE_SETUP
-#line 330 "scanner.l"
-{ yylval.e = pcap_ether_aton((char *)pcap_text);
-			  if (yylval.e == NULL)
-				bpf_error("malloc");
+#line 390 "scanner.l"
+{ yylval->e = pcap_ether_aton((char *)yytext);
+			  if (yylval->e == NULL)
+				bpf_error(yyextra, "malloc");
 			  return EID; }
 	YY_BREAK
 case 123:
 YY_RULE_SETUP
-#line 334 "scanner.l"
-{ yylval.i = stoi((char *)pcap_text); return NUM; }
+#line 394 "scanner.l"
+{ yylval->i = stoi((char *)yytext); return NUM; }
 	YY_BREAK
 case 124:
 YY_RULE_SETUP
-#line 335 "scanner.l"
+#line 395 "scanner.l"
 {
-			yylval.s = sdup((char *)pcap_text); return HID; }
+			yylval->s = sdup(yyextra, (char *)yytext); return HID; }
 	YY_BREAK
 case 125:
 YY_RULE_SETUP
-#line 337 "scanner.l"
+#line 397 "scanner.l"
 {
 #ifdef INET6
 			  struct addrinfo hints, *res;
 			  memset(&hints, 0, sizeof(hints));
 			  hints.ai_family = AF_INET6;
 			  hints.ai_flags = AI_NUMERICHOST;
-			  if (getaddrinfo(pcap_text, NULL, &hints, &res))
-				bpf_error("bogus IPv6 address %s", pcap_text);
+			  if (getaddrinfo(yytext, NULL, &hints, &res))
+				bpf_error(yyextra, "bogus IPv6 address %s", yytext);
 			  else {
 				freeaddrinfo(res);
-				yylval.s = sdup((char *)pcap_text); return HID6;
+				yylval->s = sdup(yyextra, (char *)yytext); return HID6;
 			  }
 #else
-			  bpf_error("IPv6 address %s not supported", pcap_text);
+			  bpf_error(yyextra, "IPv6 address %s not supported", yytext);
 #endif /*INET6*/
 			}
 	YY_BREAK
 case 126:
 YY_RULE_SETUP
-#line 353 "scanner.l"
-{ bpf_error("bogus ethernet address %s", pcap_text); }
+#line 413 "scanner.l"
+{ bpf_error(yyextra, "bogus ethernet address %s", yytext); }
 	YY_BREAK
 case 127:
 YY_RULE_SETUP
-#line 354 "scanner.l"
-{ yylval.i = 0; return NUM; }
+#line 414 "scanner.l"
+{ yylval->i = 0; return NUM; }
 	YY_BREAK
 case 128:
 YY_RULE_SETUP
-#line 355 "scanner.l"
-{ yylval.i = 1; return NUM; }
+#line 415 "scanner.l"
+{ yylval->i = 1; return NUM; }
 	YY_BREAK
 case 129:
 YY_RULE_SETUP
-#line 356 "scanner.l"
-{ yylval.i = 0; return NUM; }
+#line 416 "scanner.l"
+{ yylval->i = 0; return NUM; }
 	YY_BREAK
 case 130:
 YY_RULE_SETUP
-#line 357 "scanner.l"
-{ yylval.i = 3; return NUM; }
+#line 417 "scanner.l"
+{ yylval->i = 3; return NUM; }
 	YY_BREAK
 case 131:
 YY_RULE_SETUP
-#line 358 "scanner.l"
-{ yylval.i = 4; return NUM; }
+#line 418 "scanner.l"
+{ yylval->i = 4; return NUM; }
 	YY_BREAK
 case 132:
 YY_RULE_SETUP
-#line 359 "scanner.l"
-{ yylval.i = 5; return NUM; }
+#line 419 "scanner.l"
+{ yylval->i = 5; return NUM; }
 	YY_BREAK
 case 133:
 YY_RULE_SETUP
-#line 360 "scanner.l"
-{ yylval.i = 8; return NUM; }
+#line 420 "scanner.l"
+{ yylval->i = 8; return NUM; }
 	YY_BREAK
 case 134:
 YY_RULE_SETUP
-#line 361 "scanner.l"
-{ yylval.i = 9; return NUM; }
+#line 421 "scanner.l"
+{ yylval->i = 9; return NUM; }
 	YY_BREAK
 case 135:
 YY_RULE_SETUP
-#line 362 "scanner.l"
-{ yylval.i = 10; return NUM; }
+#line 422 "scanner.l"
+{ yylval->i = 10; return NUM; }
 	YY_BREAK
 case 136:
 YY_RULE_SETUP
-#line 363 "scanner.l"
-{ yylval.i = 11; return NUM; }
+#line 423 "scanner.l"
+{ yylval->i = 11; return NUM; }
 	YY_BREAK
 case 137:
 YY_RULE_SETUP
-#line 364 "scanner.l"
-{ yylval.i = 12; return NUM; }
+#line 424 "scanner.l"
+{ yylval->i = 12; return NUM; }
 	YY_BREAK
 case 138:
 YY_RULE_SETUP
-#line 365 "scanner.l"
-{ yylval.i = 13; return NUM; }
+#line 425 "scanner.l"
+{ yylval->i = 13; return NUM; }
 	YY_BREAK
 case 139:
 YY_RULE_SETUP
-#line 366 "scanner.l"
-{ yylval.i = 14; return NUM; }
+#line 426 "scanner.l"
+{ yylval->i = 14; return NUM; }
 	YY_BREAK
 case 140:
 YY_RULE_SETUP
-#line 367 "scanner.l"
-{ yylval.i = 15; return NUM; }
+#line 427 "scanner.l"
+{ yylval->i = 15; return NUM; }
 	YY_BREAK
 case 141:
 YY_RULE_SETUP
-#line 368 "scanner.l"
-{ yylval.i = 16; return NUM; }
+#line 428 "scanner.l"
+{ yylval->i = 16; return NUM; }
 	YY_BREAK
 case 142:
 YY_RULE_SETUP
-#line 369 "scanner.l"
-{ yylval.i = 17; return NUM; }
+#line 429 "scanner.l"
+{ yylval->i = 17; return NUM; }
 	YY_BREAK
 case 143:
 YY_RULE_SETUP
-#line 370 "scanner.l"
-{ yylval.i = 18; return NUM; }
+#line 430 "scanner.l"
+{ yylval->i = 18; return NUM; }
 	YY_BREAK
 case 144:
 YY_RULE_SETUP
-#line 371 "scanner.l"
-{ yylval.i = 13; return NUM; }
+#line 431 "scanner.l"
+{ yylval->i = 13; return NUM; }
 	YY_BREAK
 case 145:
 YY_RULE_SETUP
-#line 372 "scanner.l"
-{ yylval.i = 0x01; return NUM; }
+#line 432 "scanner.l"
+{ yylval->i = 0x01; return NUM; }
 	YY_BREAK
 case 146:
 YY_RULE_SETUP
-#line 373 "scanner.l"
-{ yylval.i = 0x02; return NUM; }
+#line 433 "scanner.l"
+{ yylval->i = 0x02; return NUM; }
 	YY_BREAK
 case 147:
 YY_RULE_SETUP
-#line 374 "scanner.l"
-{ yylval.i = 0x04; return NUM; }
+#line 434 "scanner.l"
+{ yylval->i = 0x04; return NUM; }
 	YY_BREAK
 case 148:
 YY_RULE_SETUP
-#line 375 "scanner.l"
-{ yylval.i = 0x08; return NUM; }
+#line 435 "scanner.l"
+{ yylval->i = 0x08; return NUM; }
 	YY_BREAK
 case 149:
 YY_RULE_SETUP
-#line 376 "scanner.l"
-{ yylval.i = 0x10; return NUM; }
+#line 436 "scanner.l"
+{ yylval->i = 0x10; return NUM; }
 	YY_BREAK
 case 150:
 YY_RULE_SETUP
-#line 377 "scanner.l"
-{ yylval.i = 0x20; return NUM; }
+#line 437 "scanner.l"
+{ yylval->i = 0x20; return NUM; }
 	YY_BREAK
 case 151:
 YY_RULE_SETUP
-#line 378 "scanner.l"
+#line 438 "scanner.l"
 {
-			 yylval.s = sdup((char *)pcap_text); return ID; }
+			 yylval->s = sdup(yyextra, (char *)yytext); return ID; }
 	YY_BREAK
 case 152:
 YY_RULE_SETUP
-#line 380 "scanner.l"
-{ yylval.s = sdup((char *)pcap_text + 1); return ID; }
+#line 440 "scanner.l"
+{ yylval->s = sdup(yyextra, (char *)yytext + 1); return ID; }
 	YY_BREAK
 case 153:
 YY_RULE_SETUP
-#line 381 "scanner.l"
+#line 441 "scanner.l"
 {
-			bpf_error("illegal token: %s", pcap_text); }
+			bpf_error(yyextra, "illegal token: %s", yytext); }
 	YY_BREAK
 case 154:
 YY_RULE_SETUP
-#line 383 "scanner.l"
-{ bpf_error("illegal char '%c'", *pcap_text); }
+#line 443 "scanner.l"
+{ bpf_error(yyextra, "illegal char '%c'", *yytext); }
 	YY_BREAK
 case 155:
 YY_RULE_SETUP
-#line 384 "scanner.l"
+#line 444 "scanner.l"
 ECHO;
 	YY_BREAK
-#line 3852 "scanner.c"
+#line 3930 "scanner.c"
 case YY_STATE_EOF(INITIAL):
 	yyterminate();
 
 	case YY_END_OF_BUFFER:
 		{
 		/* Amount of text matched not including the EOB char. */
-		int yy_amount_of_matched_text = (int) (yy_cp - (yytext_ptr)) - 1;
+		int yy_amount_of_matched_text = (int) (yy_cp - yyg->yytext_ptr) - 1;
 
 		/* Undo the effects of YY_DO_BEFORE_ACTION. */
-		*yy_cp = (yy_hold_char);
+		*yy_cp = yyg->yy_hold_char;
 		YY_RESTORE_YY_MORE_OFFSET
 
 		if ( YY_CURRENT_BUFFER_LVALUE->yy_buffer_status == YY_BUFFER_NEW )
 			{
 			/* We're scanning a new file or input source.  It's
 			 * possible that this happened because the user
-			 * just pointed pcap_in at a new source and called
+			 * just pointed yyin at a new source and called
 			 * pcap_lex().  If so, then we have to assure
 			 * consistency between YY_CURRENT_BUFFER and our
 			 * globals.  Here is the right place to do so, because
 			 * this is the first action (other than possibly a
 			 * back-up) that will match for the new input source.
 			 */
-			(yy_n_chars) = YY_CURRENT_BUFFER_LVALUE->yy_n_chars;
-			YY_CURRENT_BUFFER_LVALUE->yy_input_file = pcap_in;
+			yyg->yy_n_chars = YY_CURRENT_BUFFER_LVALUE->yy_n_chars;
+			YY_CURRENT_BUFFER_LVALUE->yy_input_file = yyin;
 			YY_CURRENT_BUFFER_LVALUE->yy_buffer_status = YY_BUFFER_NORMAL;
 			}
 
@@ -3887,13 +3962,13 @@
 		 * end-of-buffer state).  Contrast this with the test
 		 * in input().
 		 */
-		if ( (yy_c_buf_p) <= &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[(yy_n_chars)] )
+		if ( yyg->yy_c_buf_p <= &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[yyg->yy_n_chars] )
 			{ /* This was really a NUL. */
 			yy_state_type yy_next_state;
 
-			(yy_c_buf_p) = (yytext_ptr) + yy_amount_of_matched_text;
+			yyg->yy_c_buf_p = yyg->yytext_ptr + yy_amount_of_matched_text;
 
-			yy_current_state = yy_get_previous_state(  );
+			yy_current_state = yy_get_previous_state( yyscanner );
 
 			/* Okay, we're now positioned to make the NUL
 			 * transition.  We couldn't have
@@ -3904,43 +3979,44 @@
 			 * will run more slowly).
 			 */
 
-			yy_next_state = yy_try_NUL_trans( yy_current_state );
+			yy_next_state = yy_try_NUL_trans( yy_current_state , yyscanner);
 
-			yy_bp = (yytext_ptr) + YY_MORE_ADJ;
+			yy_bp = yyg->yytext_ptr + YY_MORE_ADJ;
 
 			if ( yy_next_state )
 				{
 				/* Consume the NUL. */
-				yy_cp = ++(yy_c_buf_p);
+				yy_cp = ++yyg->yy_c_buf_p;
 				yy_current_state = yy_next_state;
 				goto yy_match;
 				}
 
 			else
 				{
-				yy_cp = (yy_c_buf_p);
+				yy_cp = yyg->yy_last_accepting_cpos;
+				yy_current_state = yyg->yy_last_accepting_state;
 				goto yy_find_action;
 				}
 			}
 
-		else switch ( yy_get_next_buffer(  ) )
+		else switch ( yy_get_next_buffer( yyscanner ) )
 			{
 			case EOB_ACT_END_OF_FILE:
 				{
-				(yy_did_buffer_switch_on_eof) = 0;
+				yyg->yy_did_buffer_switch_on_eof = 0;
 
-				if ( pcap_wrap( ) )
+				if ( pcap_wrap(yyscanner ) )
 					{
 					/* Note: because we've taken care in
 					 * yy_get_next_buffer() to have set up
-					 * pcap_text, we can now set up
+					 * yytext, we can now set up
 					 * yy_c_buf_p so that if some total
 					 * hoser (like flex itself) wants to
 					 * call the scanner after we return the
 					 * YY_NULL, it'll still work - another
 					 * YY_NULL will get returned.
 					 */
-					(yy_c_buf_p) = (yytext_ptr) + YY_MORE_ADJ;
+					yyg->yy_c_buf_p = yyg->yytext_ptr + YY_MORE_ADJ;
 
 					yy_act = YY_STATE_EOF(YY_START);
 					goto do_action;
@@ -3948,30 +4024,30 @@
 
 				else
 					{
-					if ( ! (yy_did_buffer_switch_on_eof) )
+					if ( ! yyg->yy_did_buffer_switch_on_eof )
 						YY_NEW_FILE;
 					}
 				break;
 				}
 
 			case EOB_ACT_CONTINUE_SCAN:
-				(yy_c_buf_p) =
-					(yytext_ptr) + yy_amount_of_matched_text;
+				yyg->yy_c_buf_p =
+					yyg->yytext_ptr + yy_amount_of_matched_text;
 
-				yy_current_state = yy_get_previous_state(  );
+				yy_current_state = yy_get_previous_state( yyscanner );
 
-				yy_cp = (yy_c_buf_p);
-				yy_bp = (yytext_ptr) + YY_MORE_ADJ;
+				yy_cp = yyg->yy_c_buf_p;
+				yy_bp = yyg->yytext_ptr + YY_MORE_ADJ;
 				goto yy_match;
 
 			case EOB_ACT_LAST_MATCH:
-				(yy_c_buf_p) =
-				&YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[(yy_n_chars)];
+				yyg->yy_c_buf_p =
+				&YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[yyg->yy_n_chars];
 
-				yy_current_state = yy_get_previous_state(  );
+				yy_current_state = yy_get_previous_state( yyscanner );
 
-				yy_cp = (yy_c_buf_p);
-				yy_bp = (yytext_ptr) + YY_MORE_ADJ;
+				yy_cp = yyg->yy_c_buf_p;
+				yy_bp = yyg->yytext_ptr + YY_MORE_ADJ;
 				goto yy_find_action;
 			}
 		break;
@@ -3992,20 +4068,21 @@
  *	EOB_ACT_CONTINUE_SCAN - continue scanning from current position
  *	EOB_ACT_END_OF_FILE - end of file
  */
-static int yy_get_next_buffer (void)
+static int yy_get_next_buffer (yyscan_t yyscanner)
 {
-    	register char *dest = YY_CURRENT_BUFFER_LVALUE->yy_ch_buf;
-	register char *source = (yytext_ptr);
+    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;
 	int ret_val;
 
-	if ( (yy_c_buf_p) > &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[(yy_n_chars) + 1] )
+	if ( yyg->yy_c_buf_p > &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[yyg->yy_n_chars + 1] )
 		YY_FATAL_ERROR(
 		"fatal flex scanner internal error--end of buffer missed" );
 
 	if ( YY_CURRENT_BUFFER_LVALUE->yy_fill_buffer == 0 )
 		{ /* Don't try to fill the buffer, so this is an EOF. */
-		if ( (yy_c_buf_p) - (yytext_ptr) - YY_MORE_ADJ == 1 )
+		if ( yyg->yy_c_buf_p - yyg->yytext_ptr - YY_MORE_ADJ == 1 )
 			{
 			/* We matched a single character, the EOB, so
 			 * treat this as a final EOF.
@@ -4025,7 +4102,7 @@
 	/* Try to read more data. */
 
 	/* First move last chars to start of buffer. */
-	number_to_move = (int) ((yy_c_buf_p) - (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++);
@@ -4034,7 +4111,7 @@
 		/* don't do the read, it's not guaranteed to return an EOF,
 		 * just force an EOF
 		 */
-		YY_CURRENT_BUFFER_LVALUE->yy_n_chars = (yy_n_chars) = 0;
+		YY_CURRENT_BUFFER_LVALUE->yy_n_chars = yyg->yy_n_chars = 0;
 
 	else
 		{
@@ -4048,7 +4125,7 @@
 			YY_BUFFER_STATE b = YY_CURRENT_BUFFER_LVALUE;
 
 			int yy_c_buf_p_offset =
-				(int) ((yy_c_buf_p) - b->yy_ch_buf);
+				(int) (yyg->yy_c_buf_p - b->yy_ch_buf);
 
 			if ( b->yy_is_our_buffer )
 				{
@@ -4061,7 +4138,7 @@
 
 				b->yy_ch_buf = (char *)
 					/* Include room in for 2 EOB chars. */
-					pcap_realloc((void *) b->yy_ch_buf,b->yy_buf_size + 2  );
+					pcap_realloc((void *) b->yy_ch_buf,b->yy_buf_size + 2 ,yyscanner );
 				}
 			else
 				/* Can't grow it, we don't own it. */
@@ -4071,7 +4148,7 @@
 				YY_FATAL_ERROR(
 				"fatal error - scanner input buffer overflow" );
 
-			(yy_c_buf_p) = &b->yy_ch_buf[yy_c_buf_p_offset];
+			yyg->yy_c_buf_p = &b->yy_ch_buf[yy_c_buf_p_offset];
 
 			num_to_read = YY_CURRENT_BUFFER_LVALUE->yy_buf_size -
 						number_to_move - 1;
@@ -4083,17 +4160,17 @@
 
 		/* Read in more data. */
 		YY_INPUT( (&YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[number_to_move]),
-			(yy_n_chars), num_to_read );
+			yyg->yy_n_chars, num_to_read );
 
-		YY_CURRENT_BUFFER_LVALUE->yy_n_chars = (yy_n_chars);
+		YY_CURRENT_BUFFER_LVALUE->yy_n_chars = yyg->yy_n_chars;
 		}
 
-	if ( (yy_n_chars) == 0 )
+	if ( yyg->yy_n_chars == 0 )
 		{
 		if ( number_to_move == YY_MORE_ADJ )
 			{
 			ret_val = EOB_ACT_END_OF_FILE;
-			pcap_restart(pcap_in  );
+			pcap_restart(yyin  ,yyscanner);
 			}
 
 		else
@@ -4107,39 +4184,40 @@
 	else
 		ret_val = EOB_ACT_CONTINUE_SCAN;
 
-	if ((yy_size_t) ((yy_n_chars) + number_to_move) > YY_CURRENT_BUFFER_LVALUE->yy_buf_size) {
+	if ((yy_size_t) (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 = (yy_n_chars) + number_to_move + ((yy_n_chars) >> 1);
-		YY_CURRENT_BUFFER_LVALUE->yy_ch_buf = (char *) pcap_realloc((void *) YY_CURRENT_BUFFER_LVALUE->yy_ch_buf,new_size  );
+		yy_size_t 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()" );
 	}
 
-	(yy_n_chars) += number_to_move;
-	YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[(yy_n_chars)] = YY_END_OF_BUFFER_CHAR;
-	YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[(yy_n_chars) + 1] = YY_END_OF_BUFFER_CHAR;
+	yyg->yy_n_chars += number_to_move;
+	YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[yyg->yy_n_chars] = YY_END_OF_BUFFER_CHAR;
+	YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[yyg->yy_n_chars + 1] = YY_END_OF_BUFFER_CHAR;
 
-	(yytext_ptr) = &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[0];
+	yyg->yytext_ptr = &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[0];
 
 	return ret_val;
 }
 
 /* yy_get_previous_state - get the state just before the EOB char was reached */
 
-    static yy_state_type yy_get_previous_state (void)
+    static yy_state_type yy_get_previous_state (yyscan_t yyscanner)
 {
 	register yy_state_type yy_current_state;
 	register char *yy_cp;
-    
-	yy_current_state = (yy_start);
+    struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
 
-	for ( yy_cp = (yytext_ptr) + YY_MORE_ADJ; yy_cp < (yy_c_buf_p); ++yy_cp )
+	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);
 		if ( yy_accept[yy_current_state] )
 			{
-			(yy_last_accepting_state) = yy_current_state;
-			(yy_last_accepting_cpos) = yy_cp;
+			yyg->yy_last_accepting_state = yy_current_state;
+			yyg->yy_last_accepting_cpos = yy_cp;
 			}
 		while ( yy_chk[yy_base[yy_current_state] + yy_c] != yy_current_state )
 			{
@@ -4158,16 +4236,17 @@
  * synopsis
  *	next_state = yy_try_NUL_trans( current_state );
  */
-    static yy_state_type yy_try_NUL_trans  (yy_state_type yy_current_state )
+    static yy_state_type yy_try_NUL_trans  (yy_state_type yy_current_state , yyscan_t yyscanner)
 {
 	register int yy_is_jam;
-    	register char *yy_cp = (yy_c_buf_p);
+    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;
 
 	register YY_CHAR yy_c = 1;
 	if ( yy_accept[yy_current_state] )
 		{
-		(yy_last_accepting_state) = yy_current_state;
-		(yy_last_accepting_cpos) = yy_cp;
+		yyg->yy_last_accepting_state = yy_current_state;
+		yyg->yy_last_accepting_cpos = yy_cp;
 		}
 	while ( yy_chk[yy_base[yy_current_state] + yy_c] != yy_current_state )
 		{
@@ -4178,37 +4257,39 @@
 	yy_current_state = yy_nxt[yy_base[yy_current_state] + (unsigned int) yy_c];
 	yy_is_jam = (yy_current_state == 1463);
 
-		return yy_is_jam ? 0 : yy_current_state;
+	(void)yyg;
+	return yy_is_jam ? 0 : yy_current_state;
 }
 
 #ifndef YY_NO_INPUT
 #ifdef __cplusplus
-    static int yyinput (void)
+    static int yyinput (yyscan_t yyscanner)
 #else
-    static int input  (void)
+    static int input  (yyscan_t yyscanner)
 #endif
 
 {
 	int c;
-    
-	*(yy_c_buf_p) = (yy_hold_char);
+    struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
 
-	if ( *(yy_c_buf_p) == YY_END_OF_BUFFER_CHAR )
+	*yyg->yy_c_buf_p = yyg->yy_hold_char;
+
+	if ( *yyg->yy_c_buf_p == YY_END_OF_BUFFER_CHAR )
 		{
 		/* yy_c_buf_p now points to the character we want to return.
 		 * If this occurs *before* the EOB characters, then it's a
 		 * valid NUL; if not, then we've hit the end of the buffer.
 		 */
-		if ( (yy_c_buf_p) < &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[(yy_n_chars)] )
+		if ( yyg->yy_c_buf_p < &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[yyg->yy_n_chars] )
 			/* This was really a NUL. */
-			*(yy_c_buf_p) = '\0';
+			*yyg->yy_c_buf_p = '\0';
 
 		else
 			{ /* need more input */
-			yy_size_t offset = (yy_c_buf_p) - (yytext_ptr);
-			++(yy_c_buf_p);
+			yy_size_t offset = yyg->yy_c_buf_p - yyg->yytext_ptr;
+			++yyg->yy_c_buf_p;
 
-			switch ( yy_get_next_buffer(  ) )
+			switch ( yy_get_next_buffer( yyscanner ) )
 				{
 				case EOB_ACT_LAST_MATCH:
 					/* This happens because yy_g_n_b()
@@ -4222,34 +4303,34 @@
 					 */
 
 					/* Reset buffer status. */
-					pcap_restart(pcap_in );
+					pcap_restart(yyin ,yyscanner);
 
 					/*FALLTHROUGH*/
 
 				case EOB_ACT_END_OF_FILE:
 					{
-					if ( pcap_wrap( ) )
+					if ( pcap_wrap(yyscanner ) )
 						return EOF;
 
-					if ( ! (yy_did_buffer_switch_on_eof) )
+					if ( ! yyg->yy_did_buffer_switch_on_eof )
 						YY_NEW_FILE;
 #ifdef __cplusplus
-					return yyinput();
+					return yyinput(yyscanner);
 #else
-					return input();
+					return input(yyscanner);
 #endif
 					}
 
 				case EOB_ACT_CONTINUE_SCAN:
-					(yy_c_buf_p) = (yytext_ptr) + offset;
+					yyg->yy_c_buf_p = yyg->yytext_ptr + offset;
 					break;
 				}
 			}
 		}
 
-	c = *(unsigned char *) (yy_c_buf_p);	/* cast for 8-bit char's */
-	*(yy_c_buf_p) = '\0';	/* preserve pcap_text */
-	(yy_hold_char) = *++(yy_c_buf_p);
+	c = *(unsigned char *) yyg->yy_c_buf_p;	/* cast for 8-bit char's */
+	*yyg->yy_c_buf_p = '\0';	/* preserve yytext */
+	yyg->yy_hold_char = *++yyg->yy_c_buf_p;
 
 	return c;
 }
@@ -4257,76 +4338,79 @@
 
 /** Immediately switch to a different input stream.
  * @param input_file A readable stream.
- * 
+ * @param yyscanner The scanner object.
  * @note This function does not reset the start condition to @c INITIAL .
  */
-    void pcap_restart  (FILE * input_file )
+    void pcap_restart  (FILE * input_file , yyscan_t yyscanner)
 {
-    
+    struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
+
 	if ( ! YY_CURRENT_BUFFER ){
-        pcap_ensure_buffer_stack ();
+        pcap_ensure_buffer_stack (yyscanner);
 		YY_CURRENT_BUFFER_LVALUE =
-            pcap__create_buffer(pcap_in,YY_BUF_SIZE );
+            pcap__create_buffer(yyin,YY_BUF_SIZE ,yyscanner);
 	}
 
-	pcap__init_buffer(YY_CURRENT_BUFFER,input_file );
-	pcap__load_buffer_state( );
+	pcap__init_buffer(YY_CURRENT_BUFFER,input_file ,yyscanner);
+	pcap__load_buffer_state(yyscanner );
 }
 
 /** Switch to a different input buffer.
  * @param new_buffer The new input buffer.
- * 
+ * @param yyscanner The scanner object.
  */
-    void pcap__switch_to_buffer  (YY_BUFFER_STATE  new_buffer )
+    void pcap__switch_to_buffer  (YY_BUFFER_STATE  new_buffer , yyscan_t yyscanner)
 {
-    
+    struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
+
 	/* TODO. We should be able to replace this entire function body
 	 * with
 	 *		pcap_pop_buffer_state();
 	 *		pcap_push_buffer_state(new_buffer);
      */
-	pcap_ensure_buffer_stack ();
+	pcap_ensure_buffer_stack (yyscanner);
 	if ( YY_CURRENT_BUFFER == new_buffer )
 		return;
 
 	if ( YY_CURRENT_BUFFER )
 		{
 		/* Flush out information for old buffer. */
-		*(yy_c_buf_p) = (yy_hold_char);
-		YY_CURRENT_BUFFER_LVALUE->yy_buf_pos = (yy_c_buf_p);
-		YY_CURRENT_BUFFER_LVALUE->yy_n_chars = (yy_n_chars);
+		*yyg->yy_c_buf_p = yyg->yy_hold_char;
+		YY_CURRENT_BUFFER_LVALUE->yy_buf_pos = yyg->yy_c_buf_p;
+		YY_CURRENT_BUFFER_LVALUE->yy_n_chars = yyg->yy_n_chars;
 		}
 
 	YY_CURRENT_BUFFER_LVALUE = new_buffer;
-	pcap__load_buffer_state( );
+	pcap__load_buffer_state(yyscanner );
 
 	/* We don't actually know whether we did this switch during
 	 * EOF (pcap_wrap()) processing, but the only time this flag
 	 * is looked at is after pcap_wrap() is called, so it's safe
 	 * to go ahead and always set it.
 	 */
-	(yy_did_buffer_switch_on_eof) = 1;
+	yyg->yy_did_buffer_switch_on_eof = 1;
 }
 
-static void pcap__load_buffer_state  (void)
+static void pcap__load_buffer_state  (yyscan_t yyscanner)
 {
-    	(yy_n_chars) = YY_CURRENT_BUFFER_LVALUE->yy_n_chars;
-	(yytext_ptr) = (yy_c_buf_p) = YY_CURRENT_BUFFER_LVALUE->yy_buf_pos;
-	pcap_in = YY_CURRENT_BUFFER_LVALUE->yy_input_file;
-	(yy_hold_char) = *(yy_c_buf_p);
+    struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
+	yyg->yy_n_chars = YY_CURRENT_BUFFER_LVALUE->yy_n_chars;
+	yyg->yytext_ptr = yyg->yy_c_buf_p = YY_CURRENT_BUFFER_LVALUE->yy_buf_pos;
+	yyin = YY_CURRENT_BUFFER_LVALUE->yy_input_file;
+	yyg->yy_hold_char = *yyg->yy_c_buf_p;
 }
 
 /** Allocate and initialize an input buffer state.
  * @param file A readable stream.
  * @param size The character buffer size in bytes. When in doubt, use @c YY_BUF_SIZE.
- * 
+ * @param yyscanner The scanner object.
  * @return the allocated buffer state.
  */
-    YY_BUFFER_STATE pcap__create_buffer  (FILE * file, int  size )
+    YY_BUFFER_STATE pcap__create_buffer  (FILE * file, int  size , yyscan_t yyscanner)
 {
 	YY_BUFFER_STATE b;
     
-	b = (YY_BUFFER_STATE) pcap_alloc(sizeof( struct yy_buffer_state )  );
+	b = (YY_BUFFER_STATE) pcap_alloc(sizeof( struct yy_buffer_state ) ,yyscanner );
 	if ( ! b )
 		YY_FATAL_ERROR( "out of dynamic memory in pcap__create_buffer()" );
 
@@ -4335,24 +4419,25 @@
 	/* yy_ch_buf has to be 2 characters longer than the size given because
 	 * we need to put in 2 end-of-buffer characters.
 	 */
-	b->yy_ch_buf = (char *) pcap_alloc(b->yy_buf_size + 2  );
+	b->yy_ch_buf = (char *) pcap_alloc(b->yy_buf_size + 2 ,yyscanner );
 	if ( ! b->yy_ch_buf )
 		YY_FATAL_ERROR( "out of dynamic memory in pcap__create_buffer()" );
 
 	b->yy_is_our_buffer = 1;
 
-	pcap__init_buffer(b,file );
+	pcap__init_buffer(b,file ,yyscanner);
 
 	return b;
 }
 
 /** Destroy the buffer.
  * @param b a buffer created with pcap__create_buffer()
- * 
+ * @param yyscanner The scanner object.
  */
-    void pcap__delete_buffer (YY_BUFFER_STATE  b )
+    void pcap__delete_buffer (YY_BUFFER_STATE  b , yyscan_t yyscanner)
 {
-    
+    struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
+
 	if ( ! b )
 		return;
 
@@ -4360,21 +4445,22 @@
 		YY_CURRENT_BUFFER_LVALUE = (YY_BUFFER_STATE) 0;
 
 	if ( b->yy_is_our_buffer )
-		pcap_free((void *) b->yy_ch_buf  );
+		pcap_free((void *) b->yy_ch_buf ,yyscanner );
 
-	pcap_free((void *) b  );
+	pcap_free((void *) b ,yyscanner );
 }
 
 /* Initializes or reinitializes a buffer.
  * This function is sometimes called more than once on the same buffer,
  * such as during a pcap_restart() or at EOF.
  */
-    static void pcap__init_buffer  (YY_BUFFER_STATE  b, FILE * file )
+    static void pcap__init_buffer  (YY_BUFFER_STATE  b, FILE * file , yyscan_t yyscanner)
 
 {
 	int oerrno = errno;
-    
-	pcap__flush_buffer(b );
+    struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
+
+	pcap__flush_buffer(b ,yyscanner);
 
 	b->yy_input_file = file;
 	b->yy_fill_buffer = 1;
@@ -4388,18 +4474,19 @@
         b->yy_bs_column = 0;
     }
 
-        b->yy_is_interactive = file ? (isatty( fileno(file) ) > 0) : 0;
+        b->yy_is_interactive = 0;
     
 	errno = oerrno;
 }
 
 /** Discard all buffered characters. On the next scan, YY_INPUT will be called.
  * @param b the buffer state to be flushed, usually @c YY_CURRENT_BUFFER.
- * 
+ * @param yyscanner The scanner object.
  */
-    void pcap__flush_buffer (YY_BUFFER_STATE  b )
+    void pcap__flush_buffer (YY_BUFFER_STATE  b , yyscan_t yyscanner)
 {
-    	if ( ! b )
+    struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
+	if ( ! b )
 		return;
 
 	b->yy_n_chars = 0;
@@ -4417,114 +4504,117 @@
 	b->yy_buffer_status = YY_BUFFER_NEW;
 
 	if ( b == YY_CURRENT_BUFFER )
-		pcap__load_buffer_state( );
+		pcap__load_buffer_state(yyscanner );
 }
 
 /** Pushes the new state onto the stack. The new state becomes
  *  the current state. This function will allocate the stack
  *  if necessary.
  *  @param new_buffer The new state.
- *  
+ *  @param yyscanner The scanner object.
  */
-void pcap_push_buffer_state (YY_BUFFER_STATE new_buffer )
+void pcap_push_buffer_state (YY_BUFFER_STATE new_buffer , yyscan_t yyscanner)
 {
-    	if (new_buffer == NULL)
+    struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
+	if (new_buffer == NULL)
 		return;
 
-	pcap_ensure_buffer_stack();
+	pcap_ensure_buffer_stack(yyscanner);
 
 	/* This block is copied from pcap__switch_to_buffer. */
 	if ( YY_CURRENT_BUFFER )
 		{
 		/* Flush out information for old buffer. */
-		*(yy_c_buf_p) = (yy_hold_char);
-		YY_CURRENT_BUFFER_LVALUE->yy_buf_pos = (yy_c_buf_p);
-		YY_CURRENT_BUFFER_LVALUE->yy_n_chars = (yy_n_chars);
+		*yyg->yy_c_buf_p = yyg->yy_hold_char;
+		YY_CURRENT_BUFFER_LVALUE->yy_buf_pos = yyg->yy_c_buf_p;
+		YY_CURRENT_BUFFER_LVALUE->yy_n_chars = yyg->yy_n_chars;
 		}
 
 	/* Only push if top exists. Otherwise, replace top. */
 	if (YY_CURRENT_BUFFER)
-		(yy_buffer_stack_top)++;
+		yyg->yy_buffer_stack_top++;
 	YY_CURRENT_BUFFER_LVALUE = new_buffer;
 
 	/* copied from pcap__switch_to_buffer. */
-	pcap__load_buffer_state( );
-	(yy_did_buffer_switch_on_eof) = 1;
+	pcap__load_buffer_state(yyscanner );
+	yyg->yy_did_buffer_switch_on_eof = 1;
 }
 
 /** Removes and deletes the top of the stack, if present.
  *  The next element becomes the new top.
- *  
+ *  @param yyscanner The scanner object.
  */
-void pcap_pop_buffer_state (void)
+void pcap_pop_buffer_state (yyscan_t yyscanner)
 {
-    	if (!YY_CURRENT_BUFFER)
+    struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
+	if (!YY_CURRENT_BUFFER)
 		return;
 
-	pcap__delete_buffer(YY_CURRENT_BUFFER );
+	pcap__delete_buffer(YY_CURRENT_BUFFER ,yyscanner);
 	YY_CURRENT_BUFFER_LVALUE = NULL;
-	if ((yy_buffer_stack_top) > 0)
-		--(yy_buffer_stack_top);
+	if (yyg->yy_buffer_stack_top > 0)
+		--yyg->yy_buffer_stack_top;
 
 	if (YY_CURRENT_BUFFER) {
-		pcap__load_buffer_state( );
-		(yy_did_buffer_switch_on_eof) = 1;
+		pcap__load_buffer_state(yyscanner );
+		yyg->yy_did_buffer_switch_on_eof = 1;
 	}
 }
 
 /* Allocates the stack if it does not exist.
  *  Guarantees space for at least one push.
  */
-static void pcap_ensure_buffer_stack (void)
+static void pcap_ensure_buffer_stack (yyscan_t yyscanner)
 {
 	yy_size_t num_to_alloc;
-    
-	if (!(yy_buffer_stack)) {
+    struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
+
+	if (!yyg->yy_buffer_stack) {
 
 		/* First allocation is just for 2 elements, since we don't know if this
 		 * 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;
-		(yy_buffer_stack) = (struct yy_buffer_state**)pcap_alloc
+		yyg->yy_buffer_stack = (struct yy_buffer_state**)pcap_alloc
 								(num_to_alloc * sizeof(struct yy_buffer_state*)
-								);
-		if ( ! (yy_buffer_stack) )
+								, yyscanner);
+		if ( ! yyg->yy_buffer_stack )
 			YY_FATAL_ERROR( "out of dynamic memory in pcap_ensure_buffer_stack()" );
 								  
-		memset((yy_buffer_stack), 0, num_to_alloc * sizeof(struct yy_buffer_state*));
+		memset(yyg->yy_buffer_stack, 0, num_to_alloc * sizeof(struct yy_buffer_state*));
 				
-		(yy_buffer_stack_max) = num_to_alloc;
-		(yy_buffer_stack_top) = 0;
+		yyg->yy_buffer_stack_max = num_to_alloc;
+		yyg->yy_buffer_stack_top = 0;
 		return;
 	}
 
-	if ((yy_buffer_stack_top) >= ((yy_buffer_stack_max)) - 1){
+	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 */;
 
-		num_to_alloc = (yy_buffer_stack_max) + grow_size;
-		(yy_buffer_stack) = (struct yy_buffer_state**)pcap_realloc
-								((yy_buffer_stack),
+		num_to_alloc = yyg->yy_buffer_stack_max + grow_size;
+		yyg->yy_buffer_stack = (struct yy_buffer_state**)pcap_realloc
+								(yyg->yy_buffer_stack,
 								num_to_alloc * sizeof(struct yy_buffer_state*)
-								);
-		if ( ! (yy_buffer_stack) )
+								, yyscanner);
+		if ( ! yyg->yy_buffer_stack )
 			YY_FATAL_ERROR( "out of dynamic memory in pcap_ensure_buffer_stack()" );
 
 		/* zero only the new slots.*/
-		memset((yy_buffer_stack) + (yy_buffer_stack_max), 0, grow_size * sizeof(struct yy_buffer_state*));
-		(yy_buffer_stack_max) = num_to_alloc;
+		memset(yyg->yy_buffer_stack + yyg->yy_buffer_stack_max, 0, grow_size * sizeof(struct yy_buffer_state*));
+		yyg->yy_buffer_stack_max = num_to_alloc;
 	}
 }
 
 /** Setup the input buffer state to scan directly from a user-specified character buffer.
  * @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. 
  */
-YY_BUFFER_STATE pcap__scan_buffer  (char * base, yy_size_t  size )
+YY_BUFFER_STATE pcap__scan_buffer  (char * base, yy_size_t  size , yyscan_t yyscanner)
 {
 	YY_BUFFER_STATE b;
     
@@ -4534,7 +4624,7 @@
 		/* They forgot to leave room for the EOB's. */
 		return 0;
 
-	b = (YY_BUFFER_STATE) pcap_alloc(sizeof( struct yy_buffer_state )  );
+	b = (YY_BUFFER_STATE) pcap_alloc(sizeof( struct yy_buffer_state ) ,yyscanner );
 	if ( ! b )
 		YY_FATAL_ERROR( "out of dynamic memory in pcap__scan_buffer()" );
 
@@ -4548,7 +4638,7 @@
 	b->yy_fill_buffer = 0;
 	b->yy_buffer_status = YY_BUFFER_NEW;
 
-	pcap__switch_to_buffer(b  );
+	pcap__switch_to_buffer(b ,yyscanner );
 
 	return b;
 }
@@ -4556,25 +4646,25 @@
 /** Setup the input buffer state to scan a string. The next call to pcap_lex() will
  * scan from a @e copy of @a str.
  * @param yystr a NUL-terminated string to scan
- * 
+ * @param yyscanner The scanner object.
  * @return the newly allocated buffer state object.
  * @note If you want to scan bytes that may contain NUL values, then use
  *       pcap__scan_bytes() instead.
  */
-YY_BUFFER_STATE pcap__scan_string (yyconst char * yystr )
+YY_BUFFER_STATE pcap__scan_string (yyconst char * yystr , yyscan_t yyscanner)
 {
     
-	return pcap__scan_bytes(yystr,strlen(yystr) );
+	return pcap__scan_bytes(yystr,strlen(yystr) ,yyscanner);
 }
 
 /** Setup the input buffer state to scan the given bytes. The next call to pcap_lex() will
  * scan from a @e copy of @a bytes.
  * @param yybytes the byte buffer to scan
  * @param _yybytes_len the number of bytes in the buffer pointed to by @a bytes.
- * 
+ * @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 )
+YY_BUFFER_STATE pcap__scan_bytes  (yyconst char * yybytes, yy_size_t  _yybytes_len , yyscan_t yyscanner)
 {
 	YY_BUFFER_STATE b;
 	char *buf;
@@ -4583,7 +4673,7 @@
     
 	/* Get memory for full buffer, including space for trailing EOB's. */
 	n = _yybytes_len + 2;
-	buf = (char *) pcap_alloc(n  );
+	buf = (char *) pcap_alloc(n ,yyscanner );
 	if ( ! buf )
 		YY_FATAL_ERROR( "out of dynamic memory in pcap__scan_bytes()" );
 
@@ -4592,7 +4682,7 @@
 
 	buf[_yybytes_len] = buf[_yybytes_len+1] = YY_END_OF_BUFFER_CHAR;
 
-	b = pcap__scan_buffer(buf,n );
+	b = pcap__scan_buffer(buf,n ,yyscanner);
 	if ( ! b )
 		YY_FATAL_ERROR( "bad buffer in pcap__scan_bytes()" );
 
@@ -4608,7 +4698,7 @@
 #define YY_EXIT_FAILURE 2
 #endif
 
-static void yy_fatal_error (yyconst char* msg )
+static void yy_fatal_error (yyconst char* msg , yyscan_t yyscanner)
 {
     	(void) fprintf( stderr, "%s\n", msg );
 	exit( YY_EXIT_FAILURE );
@@ -4620,53 +4710,264 @@
 #define yyless(n) \
 	do \
 		{ \
-		/* Undo effects of setting up pcap_text. */ \
+		/* Undo effects of setting up yytext. */ \
         int yyless_macro_arg = (n); \
         YY_LESS_LINENO(yyless_macro_arg);\
-		pcap_text[pcap_leng] = (yy_hold_char); \
-		(yy_c_buf_p) = pcap_text + yyless_macro_arg; \
-		(yy_hold_char) = *(yy_c_buf_p); \
-		*(yy_c_buf_p) = '\0'; \
-		pcap_leng = yyless_macro_arg; \
+		yytext[yyleng] = yyg->yy_hold_char; \
+		yyg->yy_c_buf_p = yytext + yyless_macro_arg; \
+		yyg->yy_hold_char = *yyg->yy_c_buf_p; \
+		*yyg->yy_c_buf_p = '\0'; \
+		yyleng = yyless_macro_arg; \
 		} \
 	while ( 0 )
 
 /* Accessor  methods (get/set functions) to struct members. */
 
+/** Get the user-defined data for this scanner.
+ * @param yyscanner The scanner object.
+ */
+YY_EXTRA_TYPE pcap_get_extra  (yyscan_t yyscanner)
+{
+    struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
+    return yyextra;
+}
+
+/** Get the current line number.
+ * @param yyscanner The scanner object.
+ */
+int pcap_get_lineno  (yyscan_t yyscanner)
+{
+    struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
+    
+        if (! YY_CURRENT_BUFFER)
+            return 0;
+    
+    return yylineno;
+}
+
+/** Get the current column number.
+ * @param yyscanner The scanner object.
+ */
+int pcap_get_column  (yyscan_t yyscanner)
+{
+    struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
+    
+        if (! YY_CURRENT_BUFFER)
+            return 0;
+    
+    return yycolumn;
+}
+
+/** Get the input stream.
+ * @param yyscanner The scanner object.
+ */
+FILE *pcap_get_in  (yyscan_t yyscanner)
+{
+    struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
+    return yyin;
+}
+
+/** Get the output stream.
+ * @param yyscanner The scanner object.
+ */
+FILE *pcap_get_out  (yyscan_t yyscanner)
+{
+    struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
+    return yyout;
+}
+
+/** Get the length of the current token.
+ * @param yyscanner The scanner object.
+ */
+yy_size_t pcap_get_leng  (yyscan_t yyscanner)
+{
+    struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
+    return yyleng;
+}
+
 /** Get the current token.
- * 
+ * @param yyscanner The scanner object.
  */
 
-int pcap_get_debug  (void)
+char *pcap_get_text  (yyscan_t yyscanner)
 {
-        return pcap__flex_debug;
+    struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
+    return yytext;
 }
 
-void pcap_set_debug (int  bdebug )
+/** Set the user-defined data. This data is never touched by the scanner.
+ * @param user_defined The data to be associated with this scanner.
+ * @param yyscanner The scanner object.
+ */
+void pcap_set_extra (YY_EXTRA_TYPE  user_defined , yyscan_t yyscanner)
 {
-        pcap__flex_debug = bdebug ;
+    struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
+    yyextra = user_defined ;
 }
 
-static int yy_init_globals (void)
+/** Set the current line number.
+ * @param line_number
+ * @param yyscanner The scanner object.
+ */
+void pcap_set_lineno (int  line_number , yyscan_t yyscanner)
 {
-        /* Initialization is the same as for the non-reentrant scanner.
+    struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
+
+        /* lineno is only valid if an input buffer exists. */
+        if (! YY_CURRENT_BUFFER )
+           YY_FATAL_ERROR( "pcap_set_lineno called with no buffer" );
+    
+    yylineno = line_number;
+}
+
+/** Set the current column.
+ * @param line_number
+ * @param yyscanner The scanner object.
+ */
+void pcap_set_column (int  column_no , yyscan_t yyscanner)
+{
+    struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
+
+        /* column is only valid if an input buffer exists. */
+        if (! YY_CURRENT_BUFFER )
+           YY_FATAL_ERROR( "pcap_set_column called with no buffer" );
+    
+    yycolumn = column_no;
+}
+
+/** Set the input stream. This does not discard the current
+ * input buffer.
+ * @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)
+{
+    struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
+    yyin = in_str ;
+}
+
+void pcap_set_out (FILE *  out_str , yyscan_t yyscanner)
+{
+    struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
+    yyout = out_str ;
+}
+
+int pcap_get_debug  (yyscan_t yyscanner)
+{
+    struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
+    return yy_flex_debug;
+}
+
+void pcap_set_debug (int  bdebug , yyscan_t yyscanner)
+{
+    struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
+    yy_flex_debug = bdebug ;
+}
+
+/* Accessor methods for yylval and yylloc */
+
+YYSTYPE * pcap_get_lval  (yyscan_t yyscanner)
+{
+    struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
+    return yylval;
+}
+
+void pcap_set_lval (YYSTYPE *  yylval_param , yyscan_t yyscanner)
+{
+    struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
+    yylval = yylval_param;
+}
+
+/* User-visible API */
+
+/* pcap_lex_init is special because it creates the scanner itself, so it is
+ * the ONLY reentrant function that doesn't take the scanner as the last argument.
+ * That's why we explicitly handle the declaration, instead of using our macros.
+ */
+
+int pcap_lex_init(yyscan_t* ptr_yy_globals)
+
+{
+    if (ptr_yy_globals == NULL){
+        errno = EINVAL;
+        return 1;
+    }
+
+    *ptr_yy_globals = (yyscan_t) pcap_alloc ( sizeof( struct yyguts_t ), NULL );
+
+    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));
+
+    return yy_init_globals ( *ptr_yy_globals );
+}
+
+/* pcap_lex_init_extra has the same functionality as pcap_lex_init, but follows the
+ * convention of taking the scanner as the last argument. Note however, that
+ * this is a *pointer* to a scanner, as it will be allocated by this call (and
+ * is the reason, too, why this function also must handle its own declaration).
+ * The user defined value in the first argument will be available to pcap_alloc in
+ * the yyextra field.
+ */
+
+int pcap_lex_init_extra(YY_EXTRA_TYPE yy_user_defined,yyscan_t* ptr_yy_globals )
+
+{
+    struct yyguts_t dummy_yyguts;
+
+    pcap_set_extra (yy_user_defined, &dummy_yyguts);
+
+    if (ptr_yy_globals == NULL){
+        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 );
+}
+
+static int yy_init_globals (yyscan_t yyscanner)
+{
+    struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
+    /* Initialization is the same as for the non-reentrant scanner.
      * This function is called from pcap_lex_destroy(), so don't allocate here.
      */
 
-    (yy_buffer_stack) = 0;
-    (yy_buffer_stack_top) = 0;
-    (yy_buffer_stack_max) = 0;
-    (yy_c_buf_p) = (char *) 0;
-    (yy_init) = 0;
-    (yy_start) = 0;
+    yyg->yy_buffer_stack = 0;
+    yyg->yy_buffer_stack_top = 0;
+    yyg->yy_buffer_stack_max = 0;
+    yyg->yy_c_buf_p = (char *) 0;
+    yyg->yy_init = 0;
+    yyg->yy_start = 0;
+
+    yyg->yy_start_stack_ptr = 0;
+    yyg->yy_start_stack_depth = 0;
+    yyg->yy_start_stack =  NULL;
 
 /* Defined in main.c */
 #ifdef YY_STDINIT
-    pcap_in = stdin;
-    pcap_out = stdout;
+    yyin = stdin;
+    yyout = stdout;
 #else
-    pcap_in = (FILE *) 0;
-    pcap_out = (FILE *) 0;
+    yyin = (FILE *) 0;
+    yyout = (FILE *) 0;
 #endif
 
     /* For future reference: Set errno on error, since we are called by
@@ -4676,24 +4977,32 @@
 }
 
 /* pcap_lex_destroy is for both reentrant and non-reentrant scanners. */
-int pcap_lex_destroy  (void)
+int pcap_lex_destroy  (yyscan_t yyscanner)
 {
-    
+    struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
+
     /* Pop the buffer stack, destroying each element. */
 	while(YY_CURRENT_BUFFER){
-		pcap__delete_buffer(YY_CURRENT_BUFFER  );
+		pcap__delete_buffer(YY_CURRENT_BUFFER ,yyscanner );
 		YY_CURRENT_BUFFER_LVALUE = NULL;
-		pcap_pop_buffer_state();
+		pcap_pop_buffer_state(yyscanner);
 	}
 
 	/* Destroy the stack itself. */
-	pcap_free((yy_buffer_stack) );
-	(yy_buffer_stack) = NULL;
+	pcap_free(yyg->yy_buffer_stack ,yyscanner);
+	yyg->yy_buffer_stack = NULL;
+
+    /* Destroy the start condition stack. */
+        pcap_free(yyg->yy_start_stack ,yyscanner );
+        yyg->yy_start_stack = NULL;
 
     /* Reset the globals. This is important in a non-reentrant scanner so the next time
      * pcap_lex() is called, initialization will occur. */
-    yy_init_globals( );
+    yy_init_globals( yyscanner);
 
+    /* Destroy the main struct (reentrant only). */
+    pcap_free ( yyscanner , yyscanner );
+    yyscanner = NULL;
     return 0;
 }
 
@@ -4702,7 +5011,7 @@
  */
 
 #ifndef yytext_ptr
-static void yy_flex_strncpy (char* s1, yyconst char * s2, int n )
+static void yy_flex_strncpy (char* s1, yyconst char * s2, int n , yyscan_t yyscanner)
 {
 	register int i;
 	for ( i = 0; i < n; ++i )
@@ -4711,7 +5020,7 @@
 #endif
 
 #ifdef YY_NEED_STRLEN
-static int yy_flex_strlen (yyconst char * s )
+static int yy_flex_strlen (yyconst char * s , yyscan_t yyscanner)
 {
 	register int n;
 	for ( n = 0; s[n]; ++n )
@@ -4721,12 +5030,12 @@
 }
 #endif
 
-void *pcap_alloc (yy_size_t  size )
+void *pcap_alloc (yy_size_t  size , yyscan_t yyscanner)
 {
 	return (void *) malloc( size );
 }
 
-void *pcap_realloc  (void * ptr, yy_size_t  size )
+void *pcap_realloc  (void * ptr, yy_size_t  size , yyscan_t yyscanner)
 {
 	/* The cast to (char *) in the following accommodates both
 	 * implementations that use char* generic pointers, and those
@@ -4738,49 +5047,16 @@
 	return (void *) realloc( (char *) ptr, size );
 }
 
-void pcap_free (void * ptr )
+void pcap_free (void * ptr , yyscan_t yyscanner)
 {
 	free( (char *) ptr );	/* see pcap_realloc() for (char *) cast */
 }
 
 #define YYTABLES_NAME "yytables"
 
-#line 383 "scanner.l"
+#line 443 "scanner.l"
 
 
-void
-lex_init(buf)
-	const char *buf;
-{
-#ifdef FLEX_SCANNER
-	in_buffer = pcap__scan_string(buf);
-#else
-	in_buffer = buf;
-#endif
-}
-
-/*
- * Do any cleanup necessary after parsing.
- */
-void
-lex_cleanup()
-{
-#ifdef FLEX_SCANNER
-	if (in_buffer != NULL)
-		pcap__delete_buffer(in_buffer);
-	in_buffer = NULL;
-#endif
-}
-
-/*
- * Also define a pcap_wrap.  Note that if we're using flex, it will
- * define a macro to map this identifier to pcap_wrap.
- */
-int
-pcap_wrap()
-{
-	return 1;
-}
 
 /* Hex digit to integer. */
 static inline int
diff --git a/scanner.h b/scanner.h
index d95fb84..a8e5b0a 100644
--- a/scanner.h
+++ b/scanner.h
@@ -1,6 +1,364 @@
-/* This is generated by runlex.sh.  Do not edit it. */
+#ifndef pcap_HEADER_H
+#define pcap_HEADER_H 1
+#define pcap_IN_HEADER 1
 
-#ifndef YY_DECL
-#define YY_DECL int yylex(void)
+#line 6 "scanner.h"
+#line 2 "scanner.l"
+/* Must come first for _LARGE_FILE_API on AIX. */
+#ifdef HAVE_CONFIG_H
+#include "config.h"
 #endif
-YY_DECL;
+
+
+
+#line 15 "scanner.h"
+
+#define  YY_INT_ALIGNED short int
+
+/* A lexical scanner generated by flex */
+
+#define FLEX_SCANNER
+#define YY_FLEX_MAJOR_VERSION 2
+#define YY_FLEX_MINOR_VERSION 5
+#define YY_FLEX_SUBMINOR_VERSION 39
+#if YY_FLEX_SUBMINOR_VERSION > 0
+#define FLEX_BETA
+#endif
+
+/* First, we deal with  platform-specific or compiler-specific issues. */
+
+/* begin standard C headers. */
+#include <stdio.h>
+#include <string.h>
+#include <errno.h>
+#include <stdlib.h>
+
+/* end standard C headers. */
+
+/* flex integer type definitions */
+
+#ifndef FLEXINT_H
+#define FLEXINT_H
+
+/* C99 systems have <inttypes.h>. Non-C99 systems may or may not. */
+
+#if defined (__STDC_VERSION__) && __STDC_VERSION__ >= 199901L
+
+/* C99 says to define __STDC_LIMIT_MACROS before including stdint.h,
+ * if you want the limit (max/min) macros for int types. 
+ */
+#ifndef __STDC_LIMIT_MACROS
+#define __STDC_LIMIT_MACROS 1
+#endif
+
+#include <inttypes.h>
+typedef int8_t flex_int8_t;
+typedef uint8_t flex_uint8_t;
+typedef int16_t flex_int16_t;
+typedef uint16_t flex_uint16_t;
+typedef int32_t flex_int32_t;
+typedef uint32_t flex_uint32_t;
+#else
+typedef signed char flex_int8_t;
+typedef short int flex_int16_t;
+typedef int flex_int32_t;
+typedef unsigned char flex_uint8_t; 
+typedef unsigned short int flex_uint16_t;
+typedef unsigned int flex_uint32_t;
+
+/* Limits of integral types. */
+#ifndef INT8_MIN
+#define INT8_MIN               (-128)
+#endif
+#ifndef INT16_MIN
+#define INT16_MIN              (-32767-1)
+#endif
+#ifndef INT32_MIN
+#define INT32_MIN              (-2147483647-1)
+#endif
+#ifndef INT8_MAX
+#define INT8_MAX               (127)
+#endif
+#ifndef INT16_MAX
+#define INT16_MAX              (32767)
+#endif
+#ifndef INT32_MAX
+#define INT32_MAX              (2147483647)
+#endif
+#ifndef UINT8_MAX
+#define UINT8_MAX              (255U)
+#endif
+#ifndef UINT16_MAX
+#define UINT16_MAX             (65535U)
+#endif
+#ifndef UINT32_MAX
+#define UINT32_MAX             (4294967295U)
+#endif
+
+#endif /* ! C99 */
+
+#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
+#define yyconst const
+#else
+#define yyconst
+#endif
+
+/* An opaque pointer. */
+#ifndef YY_TYPEDEF_YY_SCANNER_T
+#define YY_TYPEDEF_YY_SCANNER_T
+typedef void* yyscan_t;
+#endif
+
+/* For convenience, these vars (plus the bison vars far below)
+   are macros in the reentrant scanner. */
+#define yyin yyg->yyin_r
+#define yyout yyg->yyout_r
+#define yyextra yyg->yyextra_r
+#define yyleng yyg->yyleng_r
+#define yytext yyg->yytext_r
+#define yylineno (YY_CURRENT_BUFFER_LVALUE->yy_bs_lineno)
+#define yycolumn (YY_CURRENT_BUFFER_LVALUE->yy_bs_column)
+#define yy_flex_debug yyg->yy_flex_debug_r
+
+/* Size of default input buffer. */
+#ifndef YY_BUF_SIZE
+#ifdef __ia64__
+/* On IA-64, the buffer size is 16k, not 8k.
+ * Moreover, YY_BUF_SIZE is 2*YY_READ_BUF_SIZE in the general case.
+ * Ditto for the __ia64__ case accordingly.
+ */
+#define YY_BUF_SIZE 32768
+#else
+#define YY_BUF_SIZE 16384
+#endif /* __ia64__ */
+#endif
+
+#ifndef YY_TYPEDEF_YY_BUFFER_STATE
+#define YY_TYPEDEF_YY_BUFFER_STATE
+typedef struct yy_buffer_state *YY_BUFFER_STATE;
+#endif
+
+#ifndef YY_TYPEDEF_YY_SIZE_T
+#define YY_TYPEDEF_YY_SIZE_T
+typedef size_t yy_size_t;
+#endif
+
+#ifndef YY_STRUCT_YY_BUFFER_STATE
+#define YY_STRUCT_YY_BUFFER_STATE
+struct yy_buffer_state
+	{
+	FILE *yy_input_file;
+
+	char *yy_ch_buf;		/* input buffer */
+	char *yy_buf_pos;		/* current position in input buffer */
+
+	/* Size of input buffer in bytes, not including room for EOB
+	 * characters.
+	 */
+	yy_size_t yy_buf_size;
+
+	/* Number of characters read into yy_ch_buf, not including EOB
+	 * characters.
+	 */
+	yy_size_t 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
+	 * delete it.
+	 */
+	int yy_is_our_buffer;
+
+	/* Whether this is an "interactive" input source; if so, and
+	 * if we're using stdio for input, then we want to use getc()
+	 * instead of fread(), to make sure we stop fetching input after
+	 * each newline.
+	 */
+	int yy_is_interactive;
+
+	/* Whether we're considered to be at the beginning of a line.
+	 * If so, '^' rules will be active on the next match, otherwise
+	 * not.
+	 */
+	int yy_at_bol;
+
+    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.
+	 */
+	int yy_fill_buffer;
+
+	int yy_buffer_status;
+
+	};
+#endif /* !YY_STRUCT_YY_BUFFER_STATE */
+
+void pcap_restart (FILE *input_file ,yyscan_t yyscanner );
+void pcap__switch_to_buffer (YY_BUFFER_STATE new_buffer ,yyscan_t yyscanner );
+YY_BUFFER_STATE pcap__create_buffer (FILE *file,int size ,yyscan_t yyscanner );
+void pcap__delete_buffer (YY_BUFFER_STATE b ,yyscan_t yyscanner );
+void pcap__flush_buffer (YY_BUFFER_STATE b ,yyscan_t yyscanner );
+void pcap_push_buffer_state (YY_BUFFER_STATE new_buffer ,yyscan_t yyscanner );
+void pcap_pop_buffer_state (yyscan_t yyscanner );
+
+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 );
+
+void *pcap_alloc (yy_size_t ,yyscan_t yyscanner );
+void *pcap_realloc (void *,yy_size_t ,yyscan_t yyscanner );
+void pcap_free (void * ,yyscan_t yyscanner );
+
+/* Begin user sect3 */
+
+#define pcap_wrap(yyscanner) 1
+#define YY_SKIP_YYWRAP
+
+#define yytext_ptr yytext_r
+
+#ifdef YY_HEADER_EXPORT_START_CONDITIONS
+#define INITIAL 0
+
+#endif
+
+#ifndef YY_NO_UNISTD_H
+/* Special case for "unistd.h", since it is non-ANSI. We include it way
+ * down here because we want the user's section 1 to have been scanned first.
+ * The user has a chance to override it with an option.
+ */
+#include <unistd.h>
+#endif
+
+#define YY_EXTRA_TYPE compiler_state_t *
+
+int pcap_lex_init (yyscan_t* scanner);
+
+int pcap_lex_init_extra (YY_EXTRA_TYPE user_defined,yyscan_t* scanner);
+
+/* Accessor methods to globals.
+   These are made visible to non-reentrant scanners for convenience. */
+
+int pcap_lex_destroy (yyscan_t yyscanner );
+
+int pcap_get_debug (yyscan_t yyscanner );
+
+void pcap_set_debug (int debug_flag ,yyscan_t yyscanner );
+
+YY_EXTRA_TYPE pcap_get_extra (yyscan_t yyscanner );
+
+void pcap_set_extra (YY_EXTRA_TYPE user_defined ,yyscan_t yyscanner );
+
+FILE *pcap_get_in (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 );
+
+yy_size_t 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 );
+
+int pcap_get_column  (yyscan_t yyscanner );
+
+void pcap_set_column (int column_no ,yyscan_t yyscanner );
+
+YYSTYPE * pcap_get_lval (yyscan_t yyscanner );
+
+void pcap_set_lval (YYSTYPE * yylval_param ,yyscan_t yyscanner );
+
+/* Macros after this point can all be overridden by user definitions in
+ * section 1.
+ */
+
+#ifndef YY_SKIP_YYWRAP
+#ifdef __cplusplus
+extern "C" int pcap_wrap (yyscan_t yyscanner );
+#else
+extern int pcap_wrap (yyscan_t yyscanner );
+#endif
+#endif
+
+#ifndef yytext_ptr
+static void yy_flex_strncpy (char *,yyconst char *,int ,yyscan_t yyscanner);
+#endif
+
+#ifdef YY_NEED_STRLEN
+static int yy_flex_strlen (yyconst char * ,yyscan_t yyscanner);
+#endif
+
+#ifndef YY_NO_INPUT
+
+#endif
+
+/* Amount of stuff to slurp up with each read. */
+#ifndef YY_READ_BUF_SIZE
+#ifdef __ia64__
+/* On IA-64, the buffer size is 16k, not 8k */
+#define YY_READ_BUF_SIZE 16384
+#else
+#define YY_READ_BUF_SIZE 8192
+#endif /* __ia64__ */
+#endif
+
+/* Number of entries by which start-condition stack grows. */
+#ifndef YY_START_STACK_INCR
+#define YY_START_STACK_INCR 25
+#endif
+
+/* Default declaration of generated scanner - a define so the user can
+ * easily add parameters.
+ */
+#ifndef YY_DECL
+#define YY_DECL_IS_OURS 1
+
+extern int pcap_lex \
+               (YYSTYPE * yylval_param ,yyscan_t yyscanner);
+
+#define YY_DECL int pcap_lex \
+               (YYSTYPE * yylval_param , yyscan_t yyscanner)
+#endif /* !YY_DECL */
+
+/* yy_get_previous_state - get the state just before the EOB char was reached */
+
+#undef YY_NEW_FILE
+#undef YY_FLUSH_BUFFER
+#undef yy_set_bol
+#undef yy_new_buffer
+#undef yy_set_interactive
+#undef YY_DO_BEFORE_ACTION
+
+#ifdef YY_DECL_IS_OURS
+#undef YY_DECL_IS_OURS
+#undef YY_DECL
+#endif
+
+#line 443 "scanner.l"
+
+
+#line 363 "scanner.h"
+#undef pcap_IN_HEADER
+#endif /* pcap_HEADER_H */
diff --git a/scanner.l b/scanner.l
index 72a83f7..1000b7a 100644
--- a/scanner.l
+++ b/scanner.l
@@ -1,3 +1,46 @@
+%top {
+/* Must come first for _LARGE_FILE_API on AIX. */
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+}
+
+/*
+ * We want a reentrant scanner.
+ */
+%option reentrant
+
+/*
+ * And we need to pass the compiler state to the scanner.
+ */
+%option extra-type="compiler_state_t *"
+
+/*
+ * We don't use input, so don't generate code for it.
+ */
+%option noinput
+
+/*
+ * We don't use unput, so don't generate code for it.
+ */
+%option nounput
+
+/*
+ * We don't read from the terminal.
+ */
+%option never-interactive
+
+/*
+ * We want to stop processing when we get to the end of the input.
+ */
+%option noyywrap
+
+/*
+ * We want to generate code that can be used by a reentrant parser
+ * generated by Bison or Berkeley YACC.
+ */
+%option bison-bridge
+
 %{
 /*
  * Copyright (c) 1988, 1989, 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1997
@@ -20,19 +63,19 @@
  * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
  */
 
-#ifdef WIN32
-#include <pcap-stdinc.h>
-#else /* WIN32 */
-#if HAVE_INTTYPES_H
-#include <inttypes.h>
-#elif HAVE_STDINT_H
-#include <stdint.h>
+#ifdef _WIN32
+  #include <pcap-stdinc.h>
+#else
+  #if HAVE_INTTYPES_H
+    #include <inttypes.h>
+  #elif HAVE_STDINT_H
+    #include <stdint.h>
+  #endif
+  #ifdef HAVE_SYS_BITYPES_H
+    #include <sys/bitypes.h>
+  #endif
+  #include <sys/types.h>
 #endif
-#ifdef HAVE_SYS_BITYPES_H
-#include <sys/bitypes.h>
-#endif
-#include <sys/types.h>
-#endif /* WIN32 */
 
 #include <ctype.h>
 #include <string.h>
@@ -40,25 +83,56 @@
 #include "pcap-int.h"
 
 #include "gencode.h"
-#ifdef INET6
-#ifdef WIN32
-#include <pcap-stdinc.h>
 
-#ifdef __MINGW32__
-#include "ip6_misc.h"
-#endif
-#else /* WIN32 */
+#include "grammar.h"
+
+/*
+ * Earlier versions of Flex don't declare these, so we declare them
+ * ourselves to squelch warnings.
+ */
+int pcap_get_column(yyscan_t);
+void pcap_set_column(int, yyscan_t);
+
+#ifdef INET6
+
+#ifdef _WIN32
+/*
+ * To quote the MSDN page for getaddrinfo() at
+ *
+ *    https://msdn.microsoft.com/en-us/library/windows/desktop/ms738520(v=vs.85).aspx
+ *
+ * "Support for getaddrinfo on Windows 2000 and older versions
+ * The getaddrinfo function was added to the Ws2_32.dll on Windows XP and
+ * later. To execute an application that uses this function on earlier
+ * versions of Windows, then you need to include the Ws2tcpip.h and
+ * Wspiapi.h files. When the Wspiapi.h include file is added, the
+ * getaddrinfo function is defined to the WspiapiGetAddrInfo inline
+ * function in the Wspiapi.h file. At runtime, the WspiapiGetAddrInfo
+ * function is implemented in such a way that if the Ws2_32.dll or the
+ * Wship6.dll (the file containing getaddrinfo in the IPv6 Technology
+ * Preview for Windows 2000) does not include getaddrinfo, then a
+ * version of getaddrinfo is implemented inline based on code in the
+ * Wspiapi.h header file. This inline code will be used on older Windows
+ * platforms that do not natively support the getaddrinfo function."
+ *
+ * We use getaddrinfo(), so we include Wspiapi.h here.  pcap-stdinc.h
+ * includes Ws2tcpip.h, so we don't need to include it ourselves.
+ */
+#include <Wspiapi.h>
+#else /* _WIN32 */
 #include <sys/socket.h>	/* for "struct sockaddr" in "struct addrinfo" */
 #include <netdb.h>	/* for "struct addrinfo" */
-#endif /* WIN32 */
+#endif /* _WIN32 */
 
 /* Workaround for AIX 4.3 */
 #if !defined(AI_NUMERICHOST)
 #define AI_NUMERICHOST 0x04
 #endif
+
 #endif /*INET6*/
+
 #include <pcap/namedb.h>
-#include "tokdefs.h"
+#include "grammar.h"
 
 #ifdef HAVE_OS_PROTO_H
 #include "os-proto.h"
@@ -67,20 +141,6 @@
 static int stoi(char *);
 static inline int xdtoi(int);
 
-#ifdef FLEX_SCANNER
-#define YY_NO_INPUT
-#define YY_NO_UNPUT
-static YY_BUFFER_STATE in_buffer;
-#else
-static const char *in_buffer;
-
-#undef getc
-#define getc(fp)  (*in_buffer == 0 ? EOF : *in_buffer++)
-#endif
-
-#define yylval pcap_lval
-extern YYSTYPE yylval;
-
 %}
 
 N		([0-9]+|(0X|0x)[0-9A-Fa-f]+)
@@ -239,7 +299,7 @@
 proto		return PROTO;
 protochain	{
 #ifdef NO_PROTOCHAIN
-		  bpf_error("%s not supported", yytext);
+		  bpf_error(yyextra, "%s not supported", yytext);
 #else
 		  return PROTOCHAIN;
 #endif
@@ -323,17 +383,17 @@
 "=="			return '=';
 "<<"			return LSH;
 ">>"			return RSH;
-${B}			{ yylval.e = pcap_ether_aton(((char *)yytext)+1);
-			  if (yylval.e == NULL)
-				bpf_error("malloc");
+${B}			{ yylval->e = pcap_ether_aton(((char *)yytext)+1);
+			  if (yylval->e == NULL)
+				bpf_error(yyextra, "malloc");
 			  return AID; }
-{MAC}			{ yylval.e = pcap_ether_aton((char *)yytext);
-			  if (yylval.e == NULL)
-				bpf_error("malloc");
+{MAC}			{ yylval->e = pcap_ether_aton((char *)yytext);
+			  if (yylval->e == NULL)
+				bpf_error(yyextra, "malloc");
 			  return EID; }
-{N}			{ yylval.i = stoi((char *)yytext); return NUM; }
+{N}			{ yylval->i = stoi((char *)yytext); return NUM; }
 ({N}\.{N})|({N}\.{N}\.{N})|({N}\.{N}\.{N}\.{N})	{
-			yylval.s = sdup((char *)yytext); return HID; }
+			yylval->s = sdup(yyextra, (char *)yytext); return HID; }
 {V6}			{
 #ifdef INET6
 			  struct addrinfo hints, *res;
@@ -341,80 +401,47 @@
 			  hints.ai_family = AF_INET6;
 			  hints.ai_flags = AI_NUMERICHOST;
 			  if (getaddrinfo(yytext, NULL, &hints, &res))
-				bpf_error("bogus IPv6 address %s", yytext);
+				bpf_error(yyextra, "bogus IPv6 address %s", yytext);
 			  else {
 				freeaddrinfo(res);
-				yylval.s = sdup((char *)yytext); return HID6;
+				yylval->s = sdup(yyextra, (char *)yytext); return HID6;
 			  }
 #else
-			  bpf_error("IPv6 address %s not supported", yytext);
+			  bpf_error(yyextra, "IPv6 address %s not supported", yytext);
 #endif /*INET6*/
 			}
-{B}:+({B}:+)+		{ bpf_error("bogus ethernet address %s", yytext); }
-icmptype		{ yylval.i = 0; return NUM; }
-icmpcode		{ yylval.i = 1; return NUM; }
-icmp-echoreply		{ yylval.i = 0; return NUM; }
-icmp-unreach		{ yylval.i = 3; return NUM; }
-icmp-sourcequench	{ yylval.i = 4; return NUM; }
-icmp-redirect		{ yylval.i = 5; return NUM; }
-icmp-echo		{ yylval.i = 8; return NUM; }
-icmp-routeradvert	{ yylval.i = 9; return NUM; }
-icmp-routersolicit	{ yylval.i = 10; return NUM; }
-icmp-timxceed		{ yylval.i = 11; return NUM; }
-icmp-paramprob		{ yylval.i = 12; return NUM; }
-icmp-tstamp		{ yylval.i = 13; return NUM; }
-icmp-tstampreply	{ yylval.i = 14; return NUM; }
-icmp-ireq		{ yylval.i = 15; return NUM; }
-icmp-ireqreply		{ yylval.i = 16; return NUM; }
-icmp-maskreq		{ yylval.i = 17; return NUM; }
-icmp-maskreply		{ yylval.i = 18; return NUM; }
-tcpflags		{ yylval.i = 13; return NUM; }
-tcp-fin			{ yylval.i = 0x01; return NUM; }
-tcp-syn			{ yylval.i = 0x02; return NUM; }
-tcp-rst			{ yylval.i = 0x04; return NUM; }
-tcp-push		{ yylval.i = 0x08; return NUM; }
-tcp-ack			{ yylval.i = 0x10; return NUM; }
-tcp-urg			{ yylval.i = 0x20; return NUM; }
+{B}:+({B}:+)+		{ bpf_error(yyextra, "bogus ethernet address %s", yytext); }
+icmptype		{ yylval->i = 0; return NUM; }
+icmpcode		{ yylval->i = 1; return NUM; }
+icmp-echoreply		{ yylval->i = 0; return NUM; }
+icmp-unreach		{ yylval->i = 3; return NUM; }
+icmp-sourcequench	{ yylval->i = 4; return NUM; }
+icmp-redirect		{ yylval->i = 5; return NUM; }
+icmp-echo		{ yylval->i = 8; return NUM; }
+icmp-routeradvert	{ yylval->i = 9; return NUM; }
+icmp-routersolicit	{ yylval->i = 10; return NUM; }
+icmp-timxceed		{ yylval->i = 11; return NUM; }
+icmp-paramprob		{ yylval->i = 12; return NUM; }
+icmp-tstamp		{ yylval->i = 13; return NUM; }
+icmp-tstampreply	{ yylval->i = 14; return NUM; }
+icmp-ireq		{ yylval->i = 15; return NUM; }
+icmp-ireqreply		{ yylval->i = 16; return NUM; }
+icmp-maskreq		{ yylval->i = 17; return NUM; }
+icmp-maskreply		{ yylval->i = 18; return NUM; }
+tcpflags		{ yylval->i = 13; return NUM; }
+tcp-fin			{ yylval->i = 0x01; return NUM; }
+tcp-syn			{ yylval->i = 0x02; return NUM; }
+tcp-rst			{ yylval->i = 0x04; return NUM; }
+tcp-push		{ yylval->i = 0x08; return NUM; }
+tcp-ack			{ yylval->i = 0x10; return NUM; }
+tcp-urg			{ yylval->i = 0x20; return NUM; }
 [A-Za-z0-9]([-_.A-Za-z0-9]*[.A-Za-z0-9])? {
-			 yylval.s = sdup((char *)yytext); return ID; }
-"\\"[^ !()\n\t]+	{ yylval.s = sdup((char *)yytext + 1); return ID; }
+			 yylval->s = sdup(yyextra, (char *)yytext); return ID; }
+"\\"[^ !()\n\t]+	{ yylval->s = sdup(yyextra, (char *)yytext + 1); return ID; }
 [^ \[\]\t\n\-_.A-Za-z0-9!<>()&|=]+ {
-			bpf_error("illegal token: %s", yytext); }
-.			{ bpf_error("illegal char '%c'", *yytext); }
+			bpf_error(yyextra, "illegal token: %s", yytext); }
+.			{ bpf_error(yyextra, "illegal char '%c'", *yytext); }
 %%
-void
-lex_init(buf)
-	const char *buf;
-{
-#ifdef FLEX_SCANNER
-	in_buffer = yy_scan_string(buf);
-#else
-	in_buffer = buf;
-#endif
-}
-
-/*
- * Do any cleanup necessary after parsing.
- */
-void
-lex_cleanup()
-{
-#ifdef FLEX_SCANNER
-	if (in_buffer != NULL)
-		yy_delete_buffer(in_buffer);
-	in_buffer = NULL;
-#endif
-}
-
-/*
- * Also define a yywrap.  Note that if we're using flex, it will
- * define a macro to map this identifier to pcap_wrap.
- */
-int
-yywrap()
-{
-	return 1;
-}
 
 /* Hex digit to integer. */
 static inline int
diff --git a/sf-pcap-ng.c b/sf-pcap-ng.c
index e2cac04..0c02829 100644
--- a/sf-pcap-ng.c
+++ b/sf-pcap-ng.c
@@ -30,9 +30,9 @@
 #include "config.h"
 #endif
 
-#ifdef WIN32
+#ifdef _WIN32
 #include <pcap-stdinc.h>
-#else /* WIN32 */
+#else /* _WIN32 */
 #if HAVE_INTTYPES_H
 #include <inttypes.h>
 #elif HAVE_STDINT_H
@@ -42,7 +42,7 @@
 #include <sys/bitypes.h>
 #endif
 #include <sys/types.h>
-#endif /* WIN32 */
+#endif /* _WIN32 */
 
 #include <errno.h>
 #include <memory.h>
@@ -121,6 +121,7 @@
  * that means that this code can't read the file.
  */
 #define PCAP_NG_VERSION_MAJOR	1
+#define PCAP_NG_VERSION_MINOR	0
 
 /*
  * Interface Description Block.
@@ -203,8 +204,10 @@
 
 typedef enum {
 	PASS_THROUGH,
-	SCALE_UP,
-	SCALE_DOWN
+	SCALE_UP_DEC,
+	SCALE_DOWN_DEC,
+	SCALE_UP_BIN,
+	SCALE_DOWN_BIN
 } tstamp_scale_type_t;
 
 /*
@@ -212,14 +215,15 @@
  */
 struct pcap_ng_if {
 	u_int tsresol;			/* time stamp resolution */
-	u_int64_t tsoffset;		/* time stamp offset */
 	tstamp_scale_type_t scale_type;	/* how to scale */
+	u_int scale_factor;		/* time stamp scale factor for power-of-10 tsresol */
+	u_int64_t tsoffset;		/* time stamp offset */
 };
 
 struct pcap_ng_sf {
 	u_int user_tsresol;		/* time stamp resolution requested by the user */
 	bpf_u_int32 ifcount;		/* number of interfaces seen in this capture */
-	bpf_u_int32 ifaces_size;	/* size of arrary below */
+	bpf_u_int32 ifaces_size;	/* size of array below */
 	struct pcap_ng_if *ifaces;	/* array of interface information */
 };
 
@@ -236,13 +240,13 @@
 	amt_read = fread(buf, 1, bytes_to_read, fp);
 	if (amt_read != bytes_to_read) {
 		if (ferror(fp)) {
-			snprintf(errbuf, PCAP_ERRBUF_SIZE,
+			pcap_snprintf(errbuf, PCAP_ERRBUF_SIZE,
 			    "error reading dump file: %s",
 			    pcap_strerror(errno));
 		} else {
 			if (amt_read == 0 && !fail_on_eof)
 				return (0);	/* EOF */
-			snprintf(errbuf, PCAP_ERRBUF_SIZE,
+			pcap_snprintf(errbuf, PCAP_ERRBUF_SIZE,
 			    "truncated dump file; tried to read %lu bytes, only got %lu",
 			    (unsigned long)bytes_to_read,
 			    (unsigned long)amt_read);
@@ -257,6 +261,8 @@
 {
 	int status;
 	struct block_header bhdr;
+	u_char *bdata;
+	size_t data_remaining;
 
 	status = read_bytes(fp, &bhdr, sizeof(bhdr), 0, errbuf);
 	if (status <= 0)
@@ -275,7 +281,7 @@
 	 * memory if we read a malformed file.
 	 */
 	if (bhdr.total_length > 16*1024*1024) {
-		snprintf(errbuf, PCAP_ERRBUF_SIZE,
+		pcap_snprintf(errbuf, PCAP_ERRBUF_SIZE,
 		    "pcap-ng block size %u > maximum %u",
 		    bhdr.total_length, 16*1024*1024);
 		    return (-1);
@@ -287,7 +293,7 @@
 	 */
 	if (bhdr.total_length < sizeof(struct block_header) +
 	    sizeof(struct block_trailer)) {
-		snprintf(errbuf, PCAP_ERRBUF_SIZE,
+		pcap_snprintf(errbuf, PCAP_ERRBUF_SIZE,
 		    "block in pcap-ng dump file has a length of %u < %lu",
 		    bhdr.total_length,
 		    (unsigned long)(sizeof(struct block_header) + sizeof(struct block_trailer)));
@@ -301,11 +307,14 @@
 		/*
 		 * No - make it big enough.
 		 */
-		p->buffer = realloc(p->buffer, bhdr.total_length);
-		if (p->buffer == NULL) {
-			snprintf(errbuf, PCAP_ERRBUF_SIZE, "out of memory");
+		void *bigger_buffer;
+
+		bigger_buffer = realloc(p->buffer, bhdr.total_length);
+		if (bigger_buffer == NULL) {
+			pcap_snprintf(errbuf, PCAP_ERRBUF_SIZE, "out of memory");
 			return (-1);
 		}
+		p->buffer = bigger_buffer;
 	}
 
 	/*
@@ -313,16 +322,16 @@
 	 * of the block.
 	 */
 	memcpy(p->buffer, &bhdr, sizeof(bhdr));
-	if (read_bytes(fp, p->buffer + sizeof(bhdr),
-	    bhdr.total_length - sizeof(bhdr), 1, errbuf) == -1)
+	bdata = (u_char *)p->buffer + sizeof(bhdr);
+	data_remaining = bhdr.total_length - sizeof(bhdr);
+	if (read_bytes(fp, bdata, data_remaining, 1, errbuf) == -1)
 		return (-1);
 
 	/*
 	 * Initialize the cursor.
 	 */
-	cursor->data = p->buffer + sizeof(bhdr);
-	cursor->data_remaining = bhdr.total_length - sizeof(bhdr) -
-	    sizeof(struct block_trailer);
+	cursor->data = bdata;
+	cursor->data_remaining = data_remaining - sizeof(struct block_trailer);
 	cursor->block_type = bhdr.block_type;
 	return (1);
 }
@@ -338,7 +347,7 @@
 	 * the block data.
 	 */
 	if (cursor->data_remaining < chunk_size) {
-		snprintf(errbuf, PCAP_ERRBUF_SIZE,
+		pcap_snprintf(errbuf, PCAP_ERRBUF_SIZE,
 		    "block of type %u in pcap-ng dump file is too short",
 		    cursor->block_type);
 		return (NULL);
@@ -401,7 +410,7 @@
 
 static int
 process_idb_options(pcap_t *p, struct block_cursor *cursor, u_int *tsresol,
-    u_int64_t *tsoffset, char *errbuf)
+    u_int64_t *tsoffset, int *is_binary, char *errbuf)
 {
 	struct option_header *opthdr;
 	void *optvalue;
@@ -439,7 +448,7 @@
 
 		case OPT_ENDOFOPT:
 			if (opthdr->option_length != 0) {
-				snprintf(errbuf, PCAP_ERRBUF_SIZE,
+				pcap_snprintf(errbuf, PCAP_ERRBUF_SIZE,
 				    "Interface Description Block has opt_endofopt option with length %u != 0",
 				    opthdr->option_length);
 				return (-1);
@@ -448,13 +457,13 @@
 
 		case IF_TSRESOL:
 			if (opthdr->option_length != 1) {
-				snprintf(errbuf, PCAP_ERRBUF_SIZE,
+				pcap_snprintf(errbuf, PCAP_ERRBUF_SIZE,
 				    "Interface Description Block has if_tsresol option with length %u != 1",
 				    opthdr->option_length);
 				return (-1);
 			}
 			if (saw_tsresol) {
-				snprintf(errbuf, PCAP_ERRBUF_SIZE,
+				pcap_snprintf(errbuf, PCAP_ERRBUF_SIZE,
 				    "Interface Description Block has more than one if_tsresol option");
 				return (-1);
 			}
@@ -464,11 +473,13 @@
 				/*
 				 * Resolution is negative power of 2.
 				 */
+				*is_binary = 1;
 				*tsresol = 1 << (tsresol_opt & 0x7F);
 			} else {
 				/*
 				 * Resolution is negative power of 10.
 				 */
+				*is_binary = 0;
 				*tsresol = 1;
 				for (i = 0; i < tsresol_opt; i++)
 					*tsresol *= 10;
@@ -478,11 +489,11 @@
 				 * Resolution is too high.
 				 */
 				if (tsresol_opt & 0x80) {
-					snprintf(errbuf, PCAP_ERRBUF_SIZE,
+					pcap_snprintf(errbuf, PCAP_ERRBUF_SIZE,
 					    "Interface Description Block if_tsresol option resolution 2^-%u is too high",
 					    tsresol_opt & 0x7F);
 				} else {
-					snprintf(errbuf, PCAP_ERRBUF_SIZE,
+					pcap_snprintf(errbuf, PCAP_ERRBUF_SIZE,
 					    "Interface Description Block if_tsresol option resolution 10^-%u is too high",
 					    tsresol_opt);
 				}
@@ -492,13 +503,13 @@
 
 		case IF_TSOFFSET:
 			if (opthdr->option_length != 8) {
-				snprintf(errbuf, PCAP_ERRBUF_SIZE,
+				pcap_snprintf(errbuf, PCAP_ERRBUF_SIZE,
 				    "Interface Description Block has if_tsoffset option with length %u != 8",
 				    opthdr->option_length);
 				return (-1);
 			}
 			if (saw_tsoffset) {
-				snprintf(errbuf, PCAP_ERRBUF_SIZE,
+				pcap_snprintf(errbuf, PCAP_ERRBUF_SIZE,
 				    "Interface Description Block has more than one if_tsoffset option");
 				return (-1);
 			}
@@ -523,6 +534,7 @@
 	struct pcap_ng_sf *ps;
 	u_int tsresol;
 	u_int64_t tsoffset;
+	int is_binary;
 
 	ps = p->priv;
 
@@ -538,43 +550,107 @@
 		/*
 		 * We need to grow the array.
 		 */
-		if (ps->ifaces == NULL) {
+		bpf_u_int32 new_ifaces_size;
+		struct pcap_ng_if *new_ifaces;
+
+		if (ps->ifaces_size == 0) {
 			/*
 			 * It's currently empty.
+			 *
+			 * (The Clang static analyzer doesn't do enough,
+			 * err, umm, dataflow *analysis* to realize that
+			 * ps->ifaces_size == 0 if ps->ifaces == NULL,
+			 * and so complains about a possible zero argument
+			 * to realloc(), so we check for the former
+			 * condition to shut it up.
+			 *
+			 * However, it doesn't complain that one of the
+			 * multiplications below could overflow, which is
+			 * a real, albeit extremely unlikely, problem (you'd
+			 * need a pcap-ng file with tens of millions of
+			 * interfaces).)
 			 */
-			ps->ifaces_size = 1;
-			ps->ifaces = malloc(sizeof (struct pcap_ng_if));
+			new_ifaces_size = 1;
+			new_ifaces = malloc(sizeof (struct pcap_ng_if));
 		} else {
 			/*
 			 * It's not currently empty; double its size.
 			 * (Perhaps overkill once we have a lot of interfaces.)
+			 *
+			 * Check for overflow if we double it.
 			 */
-			ps->ifaces_size *= 2;
-			ps->ifaces = realloc(ps->ifaces, ps->ifaces_size * sizeof (struct pcap_ng_if));
+			if (ps->ifaces_size * 2 < ps->ifaces_size) {
+				/*
+				 * The maximum number of interfaces before
+				 * ps->ifaces_size overflows is the largest
+				 * possible 32-bit power of 2, as we do
+				 * size doubling.
+				 */
+				pcap_snprintf(errbuf, PCAP_ERRBUF_SIZE,
+				    "more than %u interfaces in the file",
+				    0x80000000U);
+				return (0);
+			}
+
+			/*
+			 * ps->ifaces_size * 2 doesn't overflow, so it's
+			 * safe to multiply.
+			 */
+			new_ifaces_size = ps->ifaces_size * 2;
+
+			/*
+			 * Now make sure that's not so big that it overflows
+			 * if we multiply by sizeof (struct pcap_ng_if).
+			 *
+			 * That can happen on 32-bit platforms, with a 32-bit
+			 * size_t; it shouldn't happen on 64-bit platforms,
+			 * with a 64-bit size_t, as new_ifaces_size is
+			 * 32 bits.
+			 */
+			if (new_ifaces_size * sizeof (struct pcap_ng_if) < new_ifaces_size) {
+				/*
+				 * As this fails only with 32-bit size_t,
+				 * the multiplication was 32x32->32, and
+				 * the largest 32-bit value that can safely
+				 * be multiplied by sizeof (struct pcap_ng_if)
+				 * without overflow is the largest 32-bit
+				 * (unsigned) value divided by
+				 * sizeof (struct pcap_ng_if).
+				 */
+				pcap_snprintf(errbuf, PCAP_ERRBUF_SIZE,
+				    "more than %u interfaces in the file",
+				    0xFFFFFFFFU / ((u_int)sizeof (struct pcap_ng_if)));
+				return (0);
+			}
+			new_ifaces = realloc(ps->ifaces, new_ifaces_size * sizeof (struct pcap_ng_if));
 		}
-		if (ps->ifaces == NULL) {
+		if (new_ifaces == NULL) {
 			/*
 			 * We ran out of memory.
 			 * Give up.
 			 */
-			snprintf(errbuf, PCAP_ERRBUF_SIZE,
+			pcap_snprintf(errbuf, PCAP_ERRBUF_SIZE,
 			    "out of memory for per-interface information (%u interfaces)",
 			    ps->ifcount);
 			return (0);
 		}
+		ps->ifaces_size = new_ifaces_size;
+		ps->ifaces = new_ifaces;
 	}
 
 	/*
 	 * Set the default time stamp resolution and offset.
 	 */
 	tsresol = 1000000;	/* microsecond resolution */
+	is_binary = 0;		/* which is a power of 10 */
 	tsoffset = 0;		/* absolute timestamps */
 
 	/*
 	 * Now look for various time stamp options, so we know
 	 * how to interpret the time stamps for this interface.
 	 */
-	if (process_idb_options(p, cursor, &tsresol, &tsoffset, errbuf) == -1)
+	if (process_idb_options(p, cursor, &tsresol, &tsoffset, &is_binary,
+	    errbuf) == -1)
 		return (0);
 
 	ps->ifaces[ps->ifcount - 1].tsresol = tsresol;
@@ -584,55 +660,40 @@
 	 * Determine whether we're scaling up or down or not
 	 * at all for this interface.
 	 */
-	switch (p->opt.tstamp_precision) {
-
-	case PCAP_TSTAMP_PRECISION_MICRO:
-		if (tsresol == 1000000) {
+	if (tsresol == ps->user_tsresol) {
+		/*
+		 * The resolution is the resolution the user wants,
+		 * so we don't have to do scaling.
+		 */
+		ps->ifaces[ps->ifcount - 1].scale_type = PASS_THROUGH;
+	} else if (tsresol > ps->user_tsresol) {
+		/*
+		 * The resolution is greater than what the user wants,
+		 * so we have to scale the timestamps down.
+		 */
+		if (is_binary)
+			ps->ifaces[ps->ifcount - 1].scale_type = SCALE_DOWN_BIN;
+		else {
 			/*
-			 * The resolution is 1 microsecond,
-			 * so we don't have to do scaling.
+			 * Calculate the scale factor.
 			 */
-			ps->ifaces[ps->ifcount - 1].scale_type = PASS_THROUGH;
-		} else if (tsresol > 1000000) {
-			/*
-			 * The resolution is greater than
-			 * 1 microsecond, so we have to
-			 * scale the timestamps down.
-			 */
-			ps->ifaces[ps->ifcount - 1].scale_type = SCALE_DOWN;
-		} else {
-			/*
-			 * The resolution is less than 1
-			 * microsecond, so we have to scale
-			 * the timestamps up.
-			 */
-			ps->ifaces[ps->ifcount - 1].scale_type = SCALE_UP;
+			ps->ifaces[ps->ifcount - 1].scale_factor = tsresol/ps->user_tsresol;
+			ps->ifaces[ps->ifcount - 1].scale_type = SCALE_DOWN_DEC;
 		}
-		break;
-
-	case PCAP_TSTAMP_PRECISION_NANO:
-		if (tsresol == 1000000000) {
+	} else {
+		/*
+		 * The resolution is less than what the user wants,
+		 * so we have to scale the timestamps up.
+		 */
+		if (is_binary)
+			ps->ifaces[ps->ifcount - 1].scale_type = SCALE_UP_BIN;
+		else {
 			/*
-			 * The resolution is 1 nanosecond,
-			 * so we don't have to do scaling.
+			 * Calculate the scale factor.
 			 */
-			ps->ifaces[ps->ifcount - 1].scale_type = PASS_THROUGH;
-		} else if (tsresol > 1000000000) {
-			/*
-			 * The resolution is greater than
-			 * 1 nanosecond, so we have to
-			 * scale the timestamps down.
-			 */
-			ps->ifaces[ps->ifcount - 1].scale_type = SCALE_DOWN;
-		} else {
-			/*
-			 * The resolution is less than 1
-			 * nanosecond, so we have to scale
-			 * the timestamps up.
-			 */
-			ps->ifaces[ps->ifcount - 1].scale_type = SCALE_UP;
+			ps->ifaces[ps->ifcount - 1].scale_factor = ps->user_tsresol/tsresol;
+			ps->ifaces[ps->ifcount - 1].scale_type = SCALE_UP_DEC;
 		}
-		break;
 	}
 	return (1);
 }
@@ -693,7 +754,7 @@
 	amt_read = fread(&total_length, 1, sizeof(total_length), fp);
 	if (amt_read < sizeof(total_length)) {
 		if (ferror(fp)) {
-			snprintf(errbuf, PCAP_ERRBUF_SIZE,
+			pcap_snprintf(errbuf, PCAP_ERRBUF_SIZE,
 			    "error reading dump file: %s",
 			    pcap_strerror(errno));
 			*err = 1;
@@ -709,7 +770,7 @@
 	amt_read = fread(&byte_order_magic, 1, sizeof(byte_order_magic), fp);
 	if (amt_read < sizeof(byte_order_magic)) {
 		if (ferror(fp)) {
-			snprintf(errbuf, PCAP_ERRBUF_SIZE,
+			pcap_snprintf(errbuf, PCAP_ERRBUF_SIZE,
 			    "error reading dump file: %s",
 			    pcap_strerror(errno));
 			*err = 1;
@@ -738,7 +799,7 @@
 	 * Check the sanity of the total length.
 	 */
 	if (total_length < sizeof(*bhdrp) + sizeof(*shbp) + sizeof(struct block_trailer)) {
-		snprintf(errbuf, PCAP_ERRBUF_SIZE,
+		pcap_snprintf(errbuf, PCAP_ERRBUF_SIZE,
 		    "Section Header Block in pcap-ng dump file has a length of %u < %lu",
 		    total_length,
 		    (unsigned long)(sizeof(*bhdrp) + sizeof(*shbp) + sizeof(struct block_trailer)));
@@ -773,7 +834,7 @@
 		break;
 
 	default:
-		snprintf(errbuf, PCAP_ERRBUF_SIZE,
+		pcap_snprintf(errbuf, PCAP_ERRBUF_SIZE,
 		    "unknown time stamp resolution %u", precision);
 		free(p);
 		*err = 1;
@@ -799,7 +860,7 @@
 		p->bufsize = total_length;
 	p->buffer = malloc(p->bufsize);
 	if (p->buffer == NULL) {
-		snprintf(errbuf, PCAP_ERRBUF_SIZE, "out of memory");
+		pcap_snprintf(errbuf, PCAP_ERRBUF_SIZE, "out of memory");
 		free(p);
 		*err = 1;
 		return (NULL);
@@ -810,12 +871,12 @@
 	 * of the SHB.
 	 */
 	bhdrp = (struct block_header *)p->buffer;
-	shbp = (struct section_header_block *)(p->buffer + sizeof(struct block_header));
+	shbp = (struct section_header_block *)((u_char *)p->buffer + sizeof(struct block_header));
 	bhdrp->block_type = magic;
 	bhdrp->total_length = total_length;
 	shbp->byte_order_magic = byte_order_magic;
 	if (read_bytes(fp,
-	    p->buffer + (sizeof(magic) + sizeof(total_length) + sizeof(byte_order_magic)),
+	    (u_char *)p->buffer + (sizeof(magic) + sizeof(total_length) + sizeof(byte_order_magic)),
 	    total_length - (sizeof(magic) + sizeof(total_length) + sizeof(byte_order_magic)),
 	    1, errbuf) == -1)
 		goto fail;
@@ -831,10 +892,12 @@
 		 * XXX - we don't care about the section length.
 		 */
 	}
-	if (shbp->major_version != PCAP_NG_VERSION_MAJOR) {
-		snprintf(errbuf, PCAP_ERRBUF_SIZE,
-		    "unknown pcap-ng savefile major version number %u",
-		    shbp->major_version);
+	/* currently only SHB version 1.0 is supported */
+	if (! (shbp->major_version == PCAP_NG_VERSION_MAJOR &&
+	       shbp->minor_version == PCAP_NG_VERSION_MINOR)) {
+		pcap_snprintf(errbuf, PCAP_ERRBUF_SIZE,
+		    "unsupported pcap-ng savefile version %u.%u",
+		    shbp->major_version, shbp->minor_version);
 		goto fail;
 	}
 	p->version_major = shbp->major_version;
@@ -855,7 +918,7 @@
 		status = read_block(fp, p, &cursor, errbuf);
 		if (status == 0) {
 			/* EOF - no IDB in this file */
-			snprintf(errbuf, PCAP_ERRBUF_SIZE,
+			pcap_snprintf(errbuf, PCAP_ERRBUF_SIZE,
 			    "the capture file has no Interface Description Blocks");
 			goto fail;
 		}
@@ -882,10 +945,22 @@
 			}
 
 			/*
+			 * Interface capture length sanity check
+			 */
+			if (idbp->snaplen > MAXIMUM_SNAPLEN) {
+				pcap_snprintf(errbuf, PCAP_ERRBUF_SIZE,
+				    "invalid interface capture length %u, "
+				    "bigger than maximum of %u",
+				    idbp->snaplen, MAXIMUM_SNAPLEN);
+				goto fail;
+			}
+
+			/*
 			 * Try to add this interface.
 			 */
 			if (!add_interface(p, &cursor, errbuf))
 				goto fail;
+
 			goto done;
 
 		case BT_EPB:
@@ -896,7 +971,7 @@
 			 * not valid, as we don't know what link-layer
 			 * encapsulation the packet has.
 			 */
-			snprintf(errbuf, PCAP_ERRBUF_SIZE,
+			pcap_snprintf(errbuf, PCAP_ERRBUF_SIZE,
 			    "the capture file has a packet block before any Interface Description Blocks");
 			goto fail;
 
@@ -1032,7 +1107,7 @@
 			 * and the packet length.
 			 */
 			hdr->caplen = hdr->len;
-			if (hdr->caplen > p->snapshot)
+			if (hdr->caplen > (bpf_u_int32)p->snapshot)
 				hdr->caplen = p->snapshot;
 			t = 0;	/* no time stamps */
 			goto found;
@@ -1093,13 +1168,13 @@
 			 * interfaces?
 			 */
 			if (p->linktype != idbp->linktype) {
-				snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
+				pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
 				    "an interface has a type %u different from the type of the first interface",
 				    idbp->linktype);
 				return (-1);
 			}
-			if (p->snapshot != idbp->snaplen) {
-				snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
+			if ((bpf_u_int32)p->snapshot != idbp->snaplen) {
+				pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
 				    "an interface has a snapshot length %u different from the type of the first interface",
 				    idbp->snaplen);
 				return (-1);
@@ -1151,7 +1226,7 @@
 				/*
 				 * Byte order changes.
 				 */
-				snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
+				pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
 				    "the file has sections with different byte orders");
 				return (-1);
 
@@ -1159,7 +1234,7 @@
 				/*
 				 * Not a valid SHB.
 				 */
-				snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
+				pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
 				    "the file has a section with a bad byte order magic field");
 				return (-1);
 			}
@@ -1169,7 +1244,7 @@
 			 * we handle.
 			 */
 			if (shbp->major_version != PCAP_NG_VERSION_MAJOR) {
-				snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
+				pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
 				    "unknown pcap-ng savefile major version number %u",
 				    shbp->major_version);
 				return (-1);
@@ -1203,7 +1278,7 @@
 		/*
 		 * Yes.  Fail.
 		 */
-		snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
+		pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
 		    "a packet arrived on interface %u, but there's no Interface Description Block for that interface",
 		    interface_id);
 		return (-1);
@@ -1229,11 +1304,71 @@
 		 */
 		break;
 
-	case SCALE_UP:
-	case SCALE_DOWN:
+	case SCALE_UP_DEC:
 		/*
-		 * The interface resolution is different from what the
-		 * user wants; convert the fractions to units of the
+		 * The interface resolution is less than what the user
+		 * wants; scale the fractional part up to the units of
+		 * the resolution the user requested by multiplying by
+		 * the quotient of the user-requested resolution and the
+		 * file-supplied resolution.
+		 *
+		 * Those resolutions are both powers of 10, and the user-
+		 * requested resolution is greater than the file-supplied
+		 * resolution, so the quotient in question is an integer.
+		 * We've calculated that quotient already, so we just
+		 * multiply by it.
+		 */
+		frac *= ps->ifaces[interface_id].scale_factor;
+		break;
+
+	case SCALE_UP_BIN:
+		/*
+		 * The interface resolution is less than what the user
+		 * wants; scale the fractional part up to the units of
+		 * the resolution the user requested by multiplying by
+		 * the quotient of the user-requested resolution and the
+		 * file-supplied resolution.
+		 *
+		 * The file-supplied resolution is a power of 2, so the
+		 * quotient is not an integer, so, in order to do this
+		 * entirely with integer arithmetic, we multiply by the
+		 * user-requested resolution and divide by the file-
+		 * supplied resolution.
+		 *
+		 * XXX - Is there something clever we could do here,
+		 * given that we know that the file-supplied resolution
+		 * is a power of 2?  Doing a multiplication followed by
+		 * a division runs the risk of overflowing, and involves
+		 * two non-simple arithmetic operations.
+		 */
+		frac *= ps->user_tsresol;
+		frac /= ps->ifaces[interface_id].tsresol;
+		break;
+
+	case SCALE_DOWN_DEC:
+		/*
+		 * The interface resolution is greater than what the user
+		 * wants; scale the fractional part up to the units of
+		 * the resolution the user requested by multiplying by
+		 * the quotient of the user-requested resolution and the
+		 * file-supplied resolution.
+		 *
+		 * Those resolutions are both powers of 10, and the user-
+		 * requested resolution is less than the file-supplied
+		 * resolution, so the quotient in question isn't an
+		 * integer, but its reciprocal is, and we can just divide
+		 * by the reciprocal of the quotient.  We've calculated
+		 * the reciprocal of that quotient already, so we must
+		 * divide by it.
+		 */
+		frac /= ps->ifaces[interface_id].scale_factor;
+		break;
+
+
+	case SCALE_DOWN_BIN:
+		/*
+		 * The interface resolution is greater than what the user
+		 * wants; convert the fractional part to units of the
 		 * resolution the user requested by multiplying by the
 		 * quotient of the user-requested resolution and the
 		 * file-supplied resolution.  We do that by multiplying
@@ -1241,24 +1376,39 @@
 		 * file-supplied resolution, as the quotient might not
 		 * fit in an integer.
 		 *
-		 * XXX - if ps->ifaces[interface_id].tsresol is a power
-		 * of 10, we could just multiply by the quotient of
-		 * ps->user_tsresol and ps->ifaces[interface_id].tsresol
-		 * in the scale-up case, and divide by the quotient of
-		 * ps->ifaces[interface_id].tsresol and ps->user_tsresol
-		 * in the scale-down case, as we know those will be integers.
-		 * That would involve fewer arithmetic operations, and
-		 * would run less risk of overflow.
+		 * The file-supplied resolution is a power of 2, so the
+		 * quotient is not an integer, and neither is its
+		 * reciprocal, so, in order to do this entirely with
+		 * integer arithmetic, we multiply by the user-requested
+		 * resolution and divide by the file-supplied resolution.
 		 *
-		 * Is there something clever we could do if
-		 * ps->ifaces[interface_id].tsresol is a power of 2?
+		 * XXX - Is there something clever we could do here,
+		 * given that we know that the file-supplied resolution
+		 * is a power of 2?  Doing a multiplication followed by
+		 * a division runs the risk of overflowing, and involves
+		 * two non-simple arithmetic operations.
 		 */
 		frac *= ps->user_tsresol;
 		frac /= ps->ifaces[interface_id].tsresol;
 		break;
 	}
-	hdr->ts.tv_sec = sec;
-	hdr->ts.tv_usec = frac;
+#ifdef _WIN32
+	/*
+	 * tv_sec and tv_used in the Windows struct timeval are both
+	 * longs.
+	 */
+	hdr->ts.tv_sec = (long)sec;
+	hdr->ts.tv_usec = (long)frac;
+#else
+	/*
+	 * tv_sec in the UN*X struct timeval is a time_t; tv_usec is
+	 * suseconds_t in UN*Xes that work the way the current Single
+	 * UNIX Standard specify - but not all older UN*Xes necessarily
+	 * support that type, so just cast to int.
+	 */
+	hdr->ts.tv_sec = (time_t)sec;
+	hdr->ts.tv_usec = (int)frac;
+#endif
 
 	/*
 	 * Get a pointer to the packet data.
diff --git a/sf-pcap.c b/sf-pcap.c
index eaeddfa..ac305d4 100644
--- a/sf-pcap.c
+++ b/sf-pcap.c
@@ -37,9 +37,9 @@
 #include "config.h"
 #endif
 
-#ifdef WIN32
+#ifdef _WIN32
 #include <pcap-stdinc.h>
-#else /* WIN32 */
+#else /* _WIN32 */
 #if HAVE_INTTYPES_H
 #include <inttypes.h>
 #elif HAVE_STDINT_H
@@ -49,7 +49,7 @@
 #include <sys/bitypes.h>
 #endif
 #include <sys/types.h>
-#endif /* WIN32 */
+#endif /* _WIN32 */
 
 #include <errno.h>
 #include <memory.h>
@@ -70,7 +70,7 @@
 /*
  * Setting O_BINARY on DOS/Windows is a bit tricky
  */
-#if defined(WIN32)
+#if defined(_WIN32)
   #define SET_BINMODE(f)  _setmode(_fileno(f), _O_BINARY)
 #elif defined(MSDOS)
   #if defined(__HIGHC__)
@@ -149,7 +149,7 @@
  */
 pcap_t *
 pcap_check_header(bpf_u_int32 magic, FILE *fp, u_int precision, char *errbuf,
-    int *err)
+		  int *err)
 {
 	struct pcap_file_header hdr;
 	size_t amt_read;
@@ -185,11 +185,11 @@
 	    sizeof(hdr) - sizeof(hdr.magic), fp);
 	if (amt_read != sizeof(hdr) - sizeof(hdr.magic)) {
 		if (ferror(fp)) {
-			snprintf(errbuf, PCAP_ERRBUF_SIZE,
+			pcap_snprintf(errbuf, PCAP_ERRBUF_SIZE,
 			    "error reading dump file: %s",
 			    pcap_strerror(errno));
 		} else {
-			snprintf(errbuf, PCAP_ERRBUF_SIZE,
+			pcap_snprintf(errbuf, PCAP_ERRBUF_SIZE,
 			    "truncated dump file; tried to read %lu file header bytes, only got %lu",
 			    (unsigned long)sizeof(hdr),
 			    (unsigned long)amt_read);
@@ -211,13 +211,36 @@
 	}
 
 	if (hdr.version_major < PCAP_VERSION_MAJOR) {
-		snprintf(errbuf, PCAP_ERRBUF_SIZE,
+		pcap_snprintf(errbuf, PCAP_ERRBUF_SIZE,
 		    "archaic pcap savefile format");
 		*err = 1;
 		return (NULL);
 	}
 
 	/*
+	 * currently only versions 2.[0-4] are supported with
+	 * the exception of 543.0 for DG/UX tcpdump.
+	 */
+	if (! ((hdr.version_major == PCAP_VERSION_MAJOR &&
+		hdr.version_minor <= PCAP_VERSION_MINOR) ||
+	       (hdr.version_major == 543 &&
+		hdr.version_minor == 0))) {
+		pcap_snprintf(errbuf, PCAP_ERRBUF_SIZE,
+			 "unsupported pcap savefile version %u.%u",
+			 hdr.version_major, hdr.version_minor);
+		*err = 1;
+		return NULL;
+	}
+
+	if (hdr.snaplen > MAXIMUM_SNAPLEN) {
+		pcap_snprintf(errbuf, PCAP_ERRBUF_SIZE,
+			 "invalid file capture length %u, bigger than "
+			 "maximum of %u", hdr.snaplen, MAXIMUM_SNAPLEN);
+		*err = 1;
+		return NULL;
+	}
+
+	/*
 	 * OK, this is a good pcap file.
 	 * Allocate a pcap_t for it.
 	 */
@@ -282,7 +305,7 @@
 		break;
 
 	default:
-		snprintf(errbuf, PCAP_ERRBUF_SIZE,
+		pcap_snprintf(errbuf, PCAP_ERRBUF_SIZE,
 		    "unknown time stamp resolution %u", precision);
 		free(p);
 		*err = 1;
@@ -377,7 +400,7 @@
 	}
 	p->buffer = malloc(p->bufsize);
 	if (p->buffer == NULL) {
-		snprintf(errbuf, PCAP_ERRBUF_SIZE, "out of memory");
+		pcap_snprintf(errbuf, PCAP_ERRBUF_SIZE, "out of memory");
 		free(p);
 		*err = 1;
 		return (NULL);
@@ -412,13 +435,13 @@
 	amt_read = fread(&sf_hdr, 1, ps->hdrsize, fp);
 	if (amt_read != ps->hdrsize) {
 		if (ferror(fp)) {
-			snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
+			pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
 			    "error reading dump file: %s",
 			    pcap_strerror(errno));
 			return (-1);
 		} else {
 			if (amt_read != 0) {
-				snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
+				pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
 				    "truncated dump file; tried to read %lu header bytes, only got %lu",
 				    (unsigned long)ps->hdrsize,
 				    (unsigned long)amt_read);
@@ -494,63 +517,93 @@
 		/*
 		 * This can happen due to Solaris 2.3 systems tripping
 		 * over the BUFMOD problem and not setting the snapshot
-		 * correctly in the savefile header.  If the caplen isn't
-		 * grossly wrong, try to salvage.
+		 * correctly in the savefile header.
+		 * This can also happen with a corrupted savefile or a
+		 * savefile built/modified by a fuzz tester.
+		 * If the caplen isn't grossly wrong, try to salvage.
 		 */
-		static u_char *tp = NULL;
-		static size_t tsize = 0;
+		size_t bytes_to_discard;
+		size_t bytes_to_read, bytes_read;
+		char discard_buf[4096];
 
 		if (hdr->caplen > MAXIMUM_SNAPLEN) {
-			snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
-			    "bogus savefile header");
+			pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
+			    "invalid packet capture length %u, bigger than "
+			    "maximum of %u", hdr->caplen, MAXIMUM_SNAPLEN);
 			return (-1);
 		}
 
-		if (tsize < hdr->caplen) {
-			tsize = ((hdr->caplen + 1023) / 1024) * 1024;
-			if (tp != NULL)
-				free((u_char *)tp);
-			tp = (u_char *)malloc(tsize);
-			if (tp == NULL) {
-				tsize = 0;
-				snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
-				    "BUFMOD hack malloc");
-				return (-1);
-			}
-		}
-		amt_read = fread((char *)tp, 1, hdr->caplen, fp);
-		if (amt_read != hdr->caplen) {
+		/*
+		 * XXX - we don't grow the buffer here because some
+		 * program might assume that it will never get packets
+		 * bigger than the snapshot length; for example, it might
+		 * copy data from our buffer to a buffer of its own,
+		 * allocated based on the return value of pcap_snapshot().
+		 *
+		 * Read the first p->bufsize bytes into the buffer.
+		 */
+		amt_read = fread(p->buffer, 1, p->bufsize, fp);
+		if (amt_read != p->bufsize) {
 			if (ferror(fp)) {
-				snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
+				pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
 				    "error reading dump file: %s",
 				    pcap_strerror(errno));
 			} else {
-				snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
+				/*
+				 * Yes, this uses hdr->caplen; technically,
+				 * it's true, because we would try to read
+				 * and discard the rest of those bytes, and
+				 * that would fail because we got EOF before
+				 * the read finished.
+				 */
+				pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
 				    "truncated dump file; tried to read %u captured bytes, only got %lu",
 				    hdr->caplen, (unsigned long)amt_read);
 			}
 			return (-1);
 		}
+
 		/*
-		 * We can only keep up to p->bufsize bytes.  Since
-		 * caplen > p->bufsize is exactly how we got here,
-		 * we know we can only keep the first p->bufsize bytes
-		 * and must drop the remainder.  Adjust caplen accordingly,
-		 * so we don't get confused later as to how many bytes we
-		 * have to play with.
+		 * Now read and discard what's left.
+		 */
+		bytes_to_discard = hdr->caplen - p->bufsize;
+		bytes_read = amt_read;
+		while (bytes_to_discard != 0) {
+			bytes_to_read = bytes_to_discard;
+			if (bytes_to_read > sizeof (discard_buf))
+				bytes_to_read = sizeof (discard_buf);
+			amt_read = fread(discard_buf, 1, bytes_to_read, fp);
+			bytes_read += amt_read;
+			if (amt_read != bytes_to_read) {
+				if (ferror(fp)) {
+					pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
+					    "error reading dump file: %s",
+					    pcap_strerror(errno));
+				} else {
+					pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
+					    "truncated dump file; tried to read %u captured bytes, only got %lu",
+					    hdr->caplen, (unsigned long)bytes_read);
+				}
+				return (-1);
+			}
+			bytes_to_discard -= amt_read;
+		}
+
+		/*
+		 * Adjust caplen accordingly, so we don't get confused later
+		 * as to how many bytes we have to play with.
 		 */
 		hdr->caplen = p->bufsize;
-		memcpy(p->buffer, (char *)tp, p->bufsize);
 	} else {
 		/* read the packet itself */
 		amt_read = fread(p->buffer, 1, hdr->caplen, fp);
 		if (amt_read != hdr->caplen) {
 			if (ferror(fp)) {
-				snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
+				pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
 				    "error reading dump file: %s",
 				    pcap_strerror(errno));
 			} else {
-				snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
+				pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
 				    "truncated dump file; tried to read %u captured bytes, only got %lu",
 				    hdr->caplen, (unsigned long)amt_read);
 			}
@@ -608,7 +661,7 @@
 pcap_setup_dump(pcap_t *p, int linktype, FILE *f, const char *fname)
 {
 
-#if defined(WIN32) || defined(MSDOS)
+#if defined(_WIN32) || defined(MSDOS)
 	/*
 	 * If we're writing to the standard output, put it in binary
 	 * mode, as savefiles are binary files.
@@ -622,7 +675,7 @@
 		setbuf(f, NULL);
 #endif
 	if (sf_write_header(p, f, linktype, p->tzoff, p->snapshot) == -1) {
-		snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "Can't write to %s: %s",
+		pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "Can't write to %s: %s",
 		    fname, pcap_strerror(errno));
 		if (f != stdout)
 			(void)fclose(f);
@@ -645,31 +698,36 @@
 	 * link-layer type, so we can't use it.
 	 */
 	if (!p->activated) {
-		snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
+		pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
 		    "%s: not-yet-activated pcap_t passed to pcap_dump_open",
 		    fname);
 		return (NULL);
 	}
 	linktype = dlt_to_linktype(p->linktype);
 	if (linktype == -1) {
-		snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
+		pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
 		    "%s: link-layer type %d isn't supported in savefiles",
 		    fname, p->linktype);
 		return (NULL);
 	}
 	linktype |= p->linktype_ext;
 
+	if (fname == NULL) {
+		pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
+		    "A null pointer was supplied as the file name");
+		return NULL;
+	}
 	if (fname[0] == '-' && fname[1] == '\0') {
 		f = stdout;
 		fname = "standard output";
 	} else {
-#if !defined(WIN32) && !defined(MSDOS)
+#if !defined(_WIN32) && !defined(MSDOS)
 		f = fopen(fname, "w");
 #else
 		f = fopen(fname, "wb");
 #endif
 		if (f == NULL) {
-			snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "%s: %s",
+			pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "%s: %s",
 			    fname, pcap_strerror(errno));
 			return (NULL);
 		}
@@ -687,7 +745,7 @@
 
 	linktype = dlt_to_linktype(p->linktype);
 	if (linktype == -1) {
-		snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
+		pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
 		    "stream: link-layer type %d isn't supported in savefiles",
 		    p->linktype);
 		return (NULL);
@@ -702,26 +760,32 @@
 {
 	FILE *f;
 	int linktype;
-	int amt_read;
+	size_t amt_read;
 	struct pcap_file_header ph;
 
 	linktype = dlt_to_linktype(p->linktype);
 	if (linktype == -1) {
-		snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
+		pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
 		    "%s: link-layer type %d isn't supported in savefiles",
 		    fname, linktype);
 		return (NULL);
 	}
+
+	if (fname == NULL) {
+		pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
+		    "A null pointer was supplied as the file name");
+		return NULL;
+	}
 	if (fname[0] == '-' && fname[1] == '\0')
 		return (pcap_setup_dump(p, linktype, stdout, "standard output"));
 
-#if !defined(WIN32) && !defined(MSDOS)
+#if !defined(_WIN32) && !defined(MSDOS)
 	f = fopen(fname, "r+");
 #else
 	f = fopen(fname, "rb+");
 #endif
 	if (f == NULL) {
-		snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "%s: %s",
+		pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "%s: %s",
 		    fname, pcap_strerror(errno));
 		return (NULL);
 	}
@@ -732,19 +796,19 @@
 	amt_read = fread(&ph, 1, sizeof (ph), f);
 	if (amt_read != sizeof (ph)) {
 		if (ferror(f)) {
-			snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "%s: %s",
+			pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "%s: %s",
 			    fname, pcap_strerror(errno));
 			fclose(f);
 			return (NULL);
 		} else if (feof(f) && amt_read > 0) {
-			snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
+			pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
 			    "%s: truncated pcap file header", fname);
 			fclose(f);
 			return (NULL);
 		}
 	}
 
-#if defined(WIN32) || defined(MSDOS)
+#if defined(_WIN32) || defined(MSDOS)
 	/*
 	 * We turn off buffering.
 	 * XXX - why?  And why not on the standard output?
@@ -773,7 +837,7 @@
 
 		case TCPDUMP_MAGIC:
 			if (p->opt.tstamp_precision != PCAP_TSTAMP_PRECISION_MICRO) {
-				snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
+				pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
 				    "%s: different time stamp precision, cannot append to file", fname);
 				fclose(f);
 				return (NULL);
@@ -782,7 +846,7 @@
 
 		case NSEC_TCPDUMP_MAGIC:
 			if (p->opt.tstamp_precision != PCAP_TSTAMP_PRECISION_NANO) {
-				snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
+				pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
 				    "%s: different time stamp precision, cannot append to file", fname);
 				fclose(f);
 				return (NULL);
@@ -791,7 +855,7 @@
 
 		case SWAPLONG(TCPDUMP_MAGIC):
 		case SWAPLONG(NSEC_TCPDUMP_MAGIC):
-			snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
+			pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
 			    "%s: different byte order, cannot append to file", fname);
 			fclose(f);
 			return (NULL);
@@ -800,13 +864,13 @@
 		case SWAPLONG(KUZNETZOV_TCPDUMP_MAGIC):
 		case NAVTEL_TCPDUMP_MAGIC:
 		case SWAPLONG(NAVTEL_TCPDUMP_MAGIC):
-			snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
+			pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
 			    "%s: not a pcap file to which we can append", fname);
 			fclose(f);
 			return (NULL);
 
 		default:
-			snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
+			pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
 			    "%s: not a pcap file", fname);
 			fclose(f);
 			return (NULL);
@@ -817,20 +881,20 @@
 		 */
 		if (ph.version_major != PCAP_VERSION_MAJOR ||
 		    ph.version_minor != PCAP_VERSION_MINOR) {
-			snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
+			pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
 			    "%s: version is %u.%u, cannot append to file", fname,
 			    ph.version_major, ph.version_minor);
 			fclose(f);
 			return (NULL);
 		}
-		if (linktype != ph.linktype) {
-			snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
+		if ((bpf_u_int32)linktype != ph.linktype) {
+			pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
 			    "%s: different linktype, cannot append to file", fname);
 			fclose(f);
 			return (NULL);
 		}
-		if (p->snapshot != ph.snaplen) {
-			snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
+		if ((bpf_u_int32)p->snapshot != ph.snaplen) {
+			pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
 			    "%s: different snaplen, cannot append to file", fname);
 			fclose(f);
 			return (NULL);
@@ -840,7 +904,7 @@
 		 * A header isn't present; attempt to write it.
 		 */
 		if (sf_write_header(p, f, linktype, p->tzoff, p->snapshot) == -1) {
-			snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "Can't write to %s: %s",
+			pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "Can't write to %s: %s",
 			    fname, pcap_strerror(errno));
 			(void)fclose(f);
 			return (NULL);
@@ -851,7 +915,7 @@
 	 * Start writing at the end of the file.
 	 */
 	if (fseek(f, 0, SEEK_END) == -1) {
-		snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "Can't seek to end of %s: %s",
+		pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "Can't seek to end of %s: %s",
 		    fname, pcap_strerror(errno));
 		(void)fclose(f);
 		return (NULL);
diff --git a/sockutils.c b/sockutils.c
new file mode 100644
index 0000000..c05ff1a
--- /dev/null
+++ b/sockutils.c
@@ -0,0 +1,1230 @@
+/*
+ * Copyright (c) 2002 - 2003
+ * NetGroup, Politecnico di Torino (Italy)
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the Politecnico di Torino nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+/*
+ * \file sockutils.c
+ *
+ * The goal of this file is to provide a common set of primitives for socket
+ * manipulation.
+ *
+ * Although the socket interface defined in the RFC 2553 (and its updates)
+ * is excellent, there are still differences between the behavior of those
+ * routines on UN*X and Windows, and between UN*Xes.
+ *
+ * These calls provide an interface similar to the socket interface, but
+ * that hides the differences between operating systems.  It does not
+ * attempt to significantly improve on the socket interface in other
+ * ways.
+ */
+
+#include <string.h>	/* for strerror() */
+#include <errno.h>	/* for the errno variable */
+#include <stdio.h>	/* for the stderr file */
+#include <stdlib.h>	/* for malloc() and free() */
+#ifdef HAVE_LIMITS_H
+#include <limits.h>
+#else
+#define INT_MAX		2147483647
+#endif
+
+#include "portability.h"
+#include "sockutils.h"
+
+#ifdef _WIN32
+  /*
+   * Winsock initialization.
+   *
+   * Ask for WinSock 2.2.
+   */
+  #define WINSOCK_MAJOR_VERSION 2
+  #define WINSOCK_MINOR_VERSION 2
+
+  static int sockcount = 0;	/*!< Variable that allows calling the WSAStartup() only one time */
+#endif
+
+/* Some minor differences between UNIX and Win32 */
+#ifdef _WIN32
+  #define SHUT_WR SD_SEND	/* The control code for shutdown() is different in Win32 */
+#endif
+
+/* Size of the buffer that has to keep error messages */
+#define SOCK_ERRBUF_SIZE 1024
+
+/* Constants; used in order to keep strings here */
+#define SOCKET_NO_NAME_AVAILABLE "No name available"
+#define SOCKET_NO_PORT_AVAILABLE "No port available"
+#define SOCKET_NAME_NULL_DAD "Null address (possibly DAD Phase)"
+
+/****************************************************
+ *                                                  *
+ * Locally defined functions                        *
+ *                                                  *
+ ****************************************************/
+
+static int sock_ismcastaddr(const struct sockaddr *saddr);
+
+/****************************************************
+ *                                                  *
+ * Function bodies                                  *
+ *                                                  *
+ ****************************************************/
+
+/*
+ * \brief It retrieves the error message after an error occurred in the socket interface.
+ *
+ * This function is defined because of the different way errors are returned in UNIX
+ * and Win32. This function provides a consistent way to retrieve the error message
+ * (after a socket error occurred) on all the platforms.
+ *
+ * \param caller: a pointer to a user-allocated string which contains a message that has
+ * to be printed *before* the true error message. It could be, for example, 'this error
+ * comes from the recv() call at line 31'. It may be NULL.
+ *
+ * \param errbuf: a pointer to an user-allocated buffer that will contain the complete
+ * error message. This buffer has to be at least 'errbuflen' in length.
+ * It can be NULL; in this case the error cannot be printed.
+ *
+ * \param errbuflen: length of the buffer that will contains the error. The error message cannot be
+ * larger than 'errbuflen - 1' because the last char is reserved for the string terminator.
+ *
+ * \return No return values. The error message is returned in the 'string' parameter.
+ */
+void sock_geterror(const char *caller, char *errbuf, int errbuflen)
+{
+#ifdef _WIN32
+	int retval;
+	int code;
+	TCHAR message[SOCK_ERRBUF_SIZE];	/* It will be char (if we're using ascii) or wchar_t (if we're using unicode) */
+
+	if (errbuf == NULL)
+		return;
+
+	code = GetLastError();
+
+	retval = FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS |
+		FORMAT_MESSAGE_MAX_WIDTH_MASK,
+		NULL, code, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
+		message, sizeof(message) / sizeof(TCHAR), NULL);
+
+	if (retval == 0)
+	{
+		if ((caller) && (*caller))
+			pcap_snprintf(errbuf, errbuflen, "%sUnable to get the exact error message", caller);
+		else
+			pcap_snprintf(errbuf, errbuflen, "Unable to get the exact error message");
+		return;
+	}
+	else
+	{
+		if ((caller) && (*caller))
+			pcap_snprintf(errbuf, errbuflen, "%s%s (code %d)", caller, message, code);
+		else
+			pcap_snprintf(errbuf, errbuflen, "%s (code %d)", message, code);
+	}
+#else
+	char *message;
+
+	if (errbuf == NULL)
+		return;
+
+	message = strerror(errno);
+
+	if ((caller) && (*caller))
+		pcap_snprintf(errbuf, errbuflen, "%s%s (code %d)", caller, message, errno);
+	else
+		pcap_snprintf(errbuf, errbuflen, "%s (code %d)", message, errno);
+#endif
+}
+
+/*
+ * \brief It initializes sockets.
+ *
+ * This function is pretty useless on UNIX, since socket initialization is not required.
+ * However it is required on Win32. In UNIX, this function appears to be completely empty.
+ *
+ * \param errbuf: a pointer to an user-allocated buffer that will contain the complete
+ * error message. This buffer has to be at least 'errbuflen' in length.
+ * It can be NULL; in this case the error cannot be printed.
+ *
+ * \param errbuflen: length of the buffer that will contains the error. The error message cannot be
+ * larger than 'errbuflen - 1' because the last char is reserved for the string terminator.
+ *
+ * \return '0' if everything is fine, '-1' if some errors occurred. The error message is returned
+ * in the 'errbuf' variable.
+ */
+int sock_init(char *errbuf, int errbuflen)
+{
+#ifdef _WIN32
+	if (sockcount == 0)
+	{
+		WSADATA wsaData;			/* helper variable needed to initialize Winsock */
+
+		if (WSAStartup(MAKEWORD(WINSOCK_MAJOR_VERSION,
+		    WINSOCK_MINOR_VERSION), &wsaData) != 0)
+		{
+			if (errbuf)
+				pcap_snprintf(errbuf, errbuflen, "Failed to initialize Winsock\n");
+
+			WSACleanup();
+
+			return -1;
+		}
+	}
+
+	sockcount++;
+#endif
+
+	return 0;
+}
+
+/*
+ * \brief It deallocates sockets.
+ *
+ * This function is pretty useless on UNIX, since socket deallocation is not required.
+ * However it is required on Win32. In UNIX, this function appears to be completely empty.
+ *
+ * \return No error values.
+ */
+void sock_cleanup(void)
+{
+#ifdef _WIN32
+	sockcount--;
+
+	if (sockcount == 0)
+		WSACleanup();
+#endif
+}
+
+/*
+ * \brief It checks if the sockaddr variable contains a multicast address.
+ *
+ * \return '0' if the address is multicast, '-1' if it is not.
+ */
+static int sock_ismcastaddr(const struct sockaddr *saddr)
+{
+	if (saddr->sa_family == PF_INET)
+	{
+		struct sockaddr_in *saddr4 = (struct sockaddr_in *) saddr;
+		if (IN_MULTICAST(ntohl(saddr4->sin_addr.s_addr))) return 0;
+		else return -1;
+	}
+	else
+	{
+		struct sockaddr_in6 *saddr6 = (struct sockaddr_in6 *) saddr;
+		if (IN6_IS_ADDR_MULTICAST(&saddr6->sin6_addr)) return 0;
+		else return -1;
+	}
+}
+
+/*
+ * \brief It initializes a network connection both from the client and the server side.
+ *
+ * In case of a client socket, this function calls socket() and connect().
+ * In the meanwhile, it checks for any socket error.
+ * If an error occurs, it writes the error message into 'errbuf'.
+ *
+ * In case of a server socket, the function calls socket(), bind() and listen().
+ *
+ * This function is usually preceeded by the sock_initaddress().
+ *
+ * \param addrinfo: pointer to an addrinfo variable which will be used to
+ * open the socket and such. This variable is the one returned by the previous call to
+ * sock_initaddress().
+ *
+ * \param server: '1' if this is a server socket, '0' otherwise.
+ *
+ * \param nconn: number of the connections that are allowed to wait into the listen() call.
+ * This value has no meanings in case of a client socket.
+ *
+ * \param errbuf: a pointer to an user-allocated buffer that will contain the complete
+ * error message. This buffer has to be at least 'errbuflen' in length.
+ * It can be NULL; in this case the error cannot be printed.
+ *
+ * \param errbuflen: length of the buffer that will contains the error. The error message cannot be
+ * larger than 'errbuflen - 1' because the last char is reserved for the string terminator.
+ *
+ * \return the socket that has been opened (that has to be used in the following sockets calls)
+ * if everything is fine, '0' if some errors occurred. The error message is returned
+ * in the 'errbuf' variable.
+ */
+SOCKET sock_open(struct addrinfo *addrinfo, int server, int nconn, char *errbuf, int errbuflen)
+{
+	SOCKET sock;
+
+	sock = socket(addrinfo->ai_family, addrinfo->ai_socktype, addrinfo->ai_protocol);
+	if (sock == -1)
+	{
+		sock_geterror("socket(): ", errbuf, errbuflen);
+		return -1;
+	}
+
+
+	/* This is a server socket */
+	if (server)
+	{
+#ifdef BSD
+		/*
+		 * Force the use of IPv6-only addresses; in BSD you can accept both v4 and v6
+		 * connections if you have a "NULL" pointer as the nodename in the getaddrinfo()
+		 * This behavior is not clear in the RFC 2553, so each system implements the
+		 * bind() differently from this point of view
+		 */
+		if (addrinfo->ai_family == PF_INET6)
+		{
+			int on;
+
+			if (setsockopt(sock, IPPROTO_IPV6, IPV6_BINDV6ONLY, (char *)&on, sizeof (int)) == -1)
+			{
+				if (errbuf)
+					pcap_snprintf(errbuf, errbuflen, "setsockopt(IPV6_BINDV6ONLY)");
+				return -1;
+			}
+		}
+#endif
+
+		/* WARNING: if the address is a mcast one, I should place the proper Win32 code here */
+		if (bind(sock, addrinfo->ai_addr, (int) addrinfo->ai_addrlen) != 0)
+		{
+			sock_geterror("bind(): ", errbuf, errbuflen);
+			return -1;
+		}
+
+		if (addrinfo->ai_socktype == SOCK_STREAM)
+			if (listen(sock, nconn) == -1)
+			{
+				sock_geterror("listen(): ", errbuf, errbuflen);
+				return -1;
+			}
+
+		/* server side ended */
+		return sock;
+	}
+	else	/* we're the client */
+	{
+		struct addrinfo *tempaddrinfo;
+		char *errbufptr;
+		size_t bufspaceleft;
+
+		tempaddrinfo = addrinfo;
+		errbufptr = errbuf;
+		bufspaceleft = errbuflen;
+		*errbufptr = 0;
+
+		/*
+		 * We have to loop though all the addinfo returned.
+		 * For instance, we can have both IPv6 and IPv4 addresses, but the service we're trying
+		 * to connect to is unavailable in IPv6, so we have to try in IPv4 as well
+		 */
+		while (tempaddrinfo)
+		{
+
+			if (connect(sock, tempaddrinfo->ai_addr, (int) tempaddrinfo->ai_addrlen) == -1)
+			{
+				size_t msglen;
+				char TmpBuffer[100];
+				char SocketErrorMessage[SOCK_ERRBUF_SIZE];
+
+				/*
+				 * We have to retrieve the error message before any other socket call completes, otherwise
+				 * the error message is lost
+				 */
+				sock_geterror(NULL, SocketErrorMessage, sizeof(SocketErrorMessage));
+
+				/* Returns the numeric address of the host that triggered the error */
+				sock_getascii_addrport((struct sockaddr_storage *) tempaddrinfo->ai_addr, TmpBuffer, sizeof(TmpBuffer), NULL, 0, NI_NUMERICHOST, TmpBuffer, sizeof(TmpBuffer));
+
+				pcap_snprintf(errbufptr, bufspaceleft,
+				    "Is the server properly installed on %s?  connect() failed: %s", TmpBuffer, SocketErrorMessage);
+
+				/* In case more then one 'connect' fails, we manage to keep all the error messages */
+				msglen = strlen(errbufptr);
+
+				errbufptr[msglen] = ' ';
+				errbufptr[msglen + 1] = 0;
+
+				bufspaceleft = bufspaceleft - (msglen + 1);
+				errbufptr += (msglen + 1);
+
+				tempaddrinfo = tempaddrinfo->ai_next;
+			}
+			else
+				break;
+		}
+
+		/*
+		 * Check how we exit from the previous loop
+		 * If tempaddrinfo is equal to NULL, it means that all the connect() failed.
+		 */
+		if (tempaddrinfo == NULL)
+		{
+			closesocket(sock);
+			return -1;
+		}
+		else
+			return sock;
+	}
+}
+
+/*
+ * \brief Closes the present (TCP and UDP) socket connection.
+ *
+ * This function sends a shutdown() on the socket in order to disable send() calls
+ * (while recv() ones are still allowed). Then, it closes the socket.
+ *
+ * \param sock: the socket identifier of the connection that has to be closed.
+ *
+ * \param errbuf: a pointer to an user-allocated buffer that will contain the complete
+ * error message. This buffer has to be at least 'errbuflen' in length.
+ * It can be NULL; in this case the error cannot be printed.
+ *
+ * \param errbuflen: length of the buffer that will contains the error. The error message cannot be
+ * larger than 'errbuflen - 1' because the last char is reserved for the string terminator.
+ *
+ * \return '0' if everything is fine, '-1' if some errors occurred. The error message is returned
+ * in the 'errbuf' variable.
+ */
+int sock_close(SOCKET sock, char *errbuf, int errbuflen)
+{
+	/*
+	 * SHUT_WR: subsequent calls to the send function are disallowed.
+	 * For TCP sockets, a FIN will be sent after all data is sent and
+	 * acknowledged by the Server.
+	 */
+	if (shutdown(sock, SHUT_WR))
+	{
+		sock_geterror("shutdown(): ", errbuf, errbuflen);
+		/* close the socket anyway */
+		closesocket(sock);
+		return -1;
+	}
+
+	closesocket(sock);
+	return 0;
+}
+
+/*
+ * \brief Checks that the address, port and flags given are valids and it returns an 'addrinfo' structure.
+ *
+ * This function basically calls the getaddrinfo() calls, and it performs a set of sanity checks
+ * to control that everything is fine (e.g. a TCP socket cannot have a mcast address, and such).
+ * If an error occurs, it writes the error message into 'errbuf'.
+ *
+ * \param host: a pointer to a string identifying the host. It can be
+ * a host name, a numeric literal address, or NULL or "" (useful
+ * in case of a server socket which has to bind to all addresses).
+ *
+ * \param port: a pointer to a user-allocated buffer containing the network port to use.
+ *
+ * \param hints: an addrinfo variable (passed by reference) containing the flags needed to create the
+ * addrinfo structure appropriately.
+ *
+ * \param addrinfo: it represents the true returning value. This is a pointer to an addrinfo variable
+ * (passed by reference), which will be allocated by this function and returned back to the caller.
+ * This variable will be used in the next sockets calls.
+ *
+ * \param errbuf: a pointer to an user-allocated buffer that will contain the complete
+ * error message. This buffer has to be at least 'errbuflen' in length.
+ * It can be NULL; in this case the error cannot be printed.
+ *
+ * \param errbuflen: length of the buffer that will contains the error. The error message cannot be
+ * larger than 'errbuflen - 1' because the last char is reserved for the string terminator.
+ *
+ * \return '0' if everything is fine, '-1' if some errors occurred. The error message is returned
+ * in the 'errbuf' variable. The addrinfo variable that has to be used in the following sockets calls is
+ * returned into the addrinfo parameter.
+ *
+ * \warning The 'addrinfo' variable has to be deleted by the programmer by calling freeaddrinfo() when
+ * it is no longer needed.
+ *
+ * \warning This function requires the 'hints' variable as parameter. The semantic of this variable is the same
+ * of the one of the corresponding variable used into the standard getaddrinfo() socket function. We suggest
+ * the programmer to look at that function in order to set the 'hints' variable appropriately.
+ */
+int sock_initaddress(const char *host, const char *port,
+    struct addrinfo *hints, struct addrinfo **addrinfo, char *errbuf, int errbuflen)
+{
+	int retval;
+
+	retval = getaddrinfo(host, port, hints, addrinfo);
+	if (retval != 0)
+	{
+		/*
+		 * if the getaddrinfo() fails, you have to use gai_strerror(), instead of using the standard
+		 * error routines (errno) in UNIX; Winsock suggests using the GetLastError() instead.
+		 */
+		if (errbuf)
+		{
+#ifdef _WIN32
+			sock_geterror("getaddrinfo(): ", errbuf, errbuflen);
+#else
+			pcap_snprintf(errbuf, errbuflen, "getaddrinfo() %s", gai_strerror(retval));
+#endif
+		}
+		return -1;
+	}
+	/*
+	 * \warning SOCKET: I should check all the accept() in order to bind to all addresses in case
+	 * addrinfo has more han one pointers
+	 */
+
+	/*
+	 * This software only supports PF_INET and PF_INET6.
+	 *
+	 * XXX - should we just check that at least *one* address is
+	 * either PF_INET or PF_INET6, and, when using the list,
+	 * ignore all addresses that are neither?  (What, no IPX
+	 * support? :-))
+	 */
+	if (((*addrinfo)->ai_family != PF_INET) &&
+	    ((*addrinfo)->ai_family != PF_INET6))
+	{
+		if (errbuf)
+			pcap_snprintf(errbuf, errbuflen, "getaddrinfo(): socket type not supported");
+		return -1;
+	}
+
+	/*
+	 * You can't do multicast (or broadcast) TCP.
+	 */
+	if (((*addrinfo)->ai_socktype == SOCK_STREAM) &&
+	    (sock_ismcastaddr((*addrinfo)->ai_addr) == 0))
+	{
+		if (errbuf)
+			pcap_snprintf(errbuf, errbuflen, "getaddrinfo(): multicast addresses are not valid when using TCP streams");
+		return -1;
+	}
+
+	return 0;
+}
+
+/*
+ * \brief It sends the amount of data contained into 'buffer' on the given socket.
+ *
+ * This function basically calls the send() socket function and it checks that all
+ * the data specified in 'buffer' (of size 'size') will be sent. If an error occurs,
+ * it writes the error message into 'errbuf'.
+ * In case the socket buffer does not have enough space, it loops until all data
+ * has been sent.
+ *
+ * \param socket: the connected socket currently opened.
+ *
+ * \param buffer: a char pointer to a user-allocated buffer in which data is contained.
+ *
+ * \param size: number of bytes that have to be sent.
+ *
+ * \param errbuf: a pointer to an user-allocated buffer that will contain the complete
+ * error message. This buffer has to be at least 'errbuflen' in length.
+ * It can be NULL; in this case the error cannot be printed.
+ *
+ * \param errbuflen: length of the buffer that will contains the error. The error message cannot be
+ * larger than 'errbuflen - 1' because the last char is reserved for the string terminator.
+ *
+ * \return '0' if everything is fine, '-1' if some errors occurred. The error message is returned
+ * in the 'errbuf' variable.
+ */
+int sock_send(SOCKET socket, const char *buffer, int size, char *errbuf, int errbuflen)
+{
+	int nsent;
+
+send:
+#ifdef linux
+	/*
+	 * Another pain... in Linux there's this flag
+	 * MSG_NOSIGNAL
+	 * Requests not to send SIGPIPE on errors on stream-oriented
+	 * sockets when the other end breaks the connection.
+	 * The EPIPE error is still returned.
+	 */
+	nsent = send(socket, buffer, size, MSG_NOSIGNAL);
+#else
+	nsent = send(socket, buffer, size, 0);
+#endif
+
+	if (nsent == -1)
+	{
+		sock_geterror("send(): ", errbuf, errbuflen);
+		return -1;
+	}
+
+	if (nsent != size)
+	{
+		size -= nsent;
+		buffer += nsent;
+		goto send;
+	}
+
+	return 0;
+}
+
+/*
+ * \brief It copies the amount of data contained into 'buffer' into 'tempbuf'.
+ * and it checks for buffer overflows.
+ *
+ * This function basically copies 'size' bytes of data contained into 'buffer'
+ * into 'tempbuf', starting at offset 'offset'. Before that, it checks that the
+ * resulting buffer will not be larger	than 'totsize'. Finally, it updates
+ * the 'offset' variable in order to point to the first empty location of the buffer.
+ *
+ * In case the function is called with 'checkonly' equal to 1, it does not copy
+ * the data into the buffer. It only checks for buffer overflows and it updates the
+ * 'offset' variable. This mode can be useful when the buffer already contains the
+ * data (maybe because the producer writes directly into the target buffer), so
+ * only the buffer overflow check has to be made.
+ * In this case, both 'buffer' and 'tempbuf' can be NULL values.
+ *
+ * This function is useful in case the userland application does not know immediately
+ * all the data it has to write into the socket. This function provides a way to create
+ * the "stream" step by step, appending the new data to the old one. Then, when all the
+ * data has been bufferized, the application can call the sock_send() function.
+ *
+ * \param buffer: a char pointer to a user-allocated buffer that keeps the data
+ * that has to be copied.
+ *
+ * \param size: number of bytes that have to be copied.
+ *
+ * \param tempbuf: user-allocated buffer (of size 'totsize') in which data
+ * has to be copied.
+ *
+ * \param offset: an index into 'tempbuf' which keeps the location of its first
+ * empty location.
+ *
+ * \param totsize: total size of the buffer in which data is being copied.
+ *
+ * \param checkonly: '1' if we do not want to copy data into the buffer and we
+ * want just do a buffer ovreflow control, '0' if data has to be copied as well.
+ *
+ * \param errbuf: a pointer to an user-allocated buffer that will contain the complete
+ * error message. This buffer has to be at least 'errbuflen' in length.
+ * It can be NULL; in this case the error cannot be printed.
+ *
+ * \param errbuflen: length of the buffer that will contains the error. The error message cannot be
+ * larger than 'errbuflen - 1' because the last char is reserved for the string terminator.
+ *
+ * \return '0' if everything is fine, '-1' if some errors occurred. The error message
+ * is returned in the 'errbuf' variable. When the function returns, 'tempbuf' will
+ * have the new string appended, and 'offset' will keep the length of that buffer.
+ * In case of 'checkonly == 1', data is not copied, but 'offset' is updated in any case.
+ *
+ * \warning This function assumes that the buffer in which data has to be stored is
+ * large 'totbuf' bytes.
+ *
+ * \warning In case of 'checkonly', be carefully to call this function *before* copying
+ * the data into the buffer. Otherwise, the control about the buffer overflow is useless.
+ */
+int sock_bufferize(const char *buffer, int size, char *tempbuf, int *offset, int totsize, int checkonly, char *errbuf, int errbuflen)
+{
+	if ((*offset + size) > totsize)
+	{
+		if (errbuf)
+			pcap_snprintf(errbuf, errbuflen, "Not enough space in the temporary send buffer.");
+		return -1;
+	}
+
+	if (!checkonly)
+		memcpy(tempbuf + (*offset), buffer, size);
+
+	(*offset) += size;
+
+	return 0;
+}
+
+/*
+ * \brief It waits on a connected socket and it manages to receive data.
+ *
+ * This function basically calls the recv() socket function and it checks that no
+ * error occurred. If that happens, it writes the error message into 'errbuf'.
+ *
+ * This function changes its behavior according to the 'receiveall' flag: if we
+ * want to receive exactly 'size' byte, it loops on the recv()	until all the requested
+ * data is arrived. Otherwise, it returns the data currently available.
+ *
+ * In case the socket does not have enough data available, it cycles on the recv()
+ * until the requested data (of size 'size') is arrived.
+ * In this case, it blocks until the number of bytes read is equal to 'size'.
+ *
+ * \param sock: the connected socket currently opened.
+ *
+ * \param buffer: a char pointer to a user-allocated buffer in which data has to be stored
+ *
+ * \param size: size of the allocated buffer. WARNING: this indicates the number of bytes
+ * that we are expecting to be read.
+ *
+ * \param receiveall: if '0' (or SOCK_RECEIVEALL_NO), it returns as soon as some data
+ * is ready; otherwise, (or SOCK_RECEIVEALL_YES) it waits until 'size' data has been
+ * received (in case the socket does not have enough data available).
+ *
+ * \param errbuf: a pointer to an user-allocated buffer that will contain the complete
+ * error message. This buffer has to be at least 'errbuflen' in length.
+ * It can be NULL; in this case the error cannot be printed.
+ *
+ * \param errbuflen: length of the buffer that will contains the error. The error message cannot be
+ * larger than 'errbuflen - 1' because the last char is reserved for the string terminator.
+ *
+ * \return the number of bytes read if everything is fine, '-1' if some errors occurred.
+ * The error message is returned in the 'errbuf' variable.
+ */
+
+/*
+ * On UN*X, recv() returns ssize_t.
+ * On Windows, there *is* no ssize_t, and it returns an int.
+ * Define ssize_t as int on Windows so we can use it as the return value
+ * from recv().
+ */
+#ifdef _WIN32
+typedef int ssize_t;
+#endif
+
+int sock_recv(SOCKET sock, void *buffer, size_t size, int receiveall,
+    char *errbuf, int errbuflen)
+{
+	char *bufp = buffer;
+	int remaining;
+	ssize_t nread;
+
+	if (size == 0)
+	{
+		SOCK_ASSERT("I have been requested to read zero bytes", 1);
+		return 0;
+	}
+	if (size > INT_MAX)
+	{
+		pcap_snprintf(errbuf, errbuflen, "Can't read more than %u bytes with sock_recv",
+		    INT_MAX);
+		return -1;
+	}
+
+	bufp = (char *) buffer;
+	remaining = (int) size;
+
+	/*
+	 * We don't use MSG_WAITALL because it's not supported in
+	 * Win32.
+	 */
+	for (;;) {
+		nread = recv(sock, bufp, remaining, 0);
+
+		if (nread == -1)
+		{
+#ifndef _WIN32
+			if (errno == EINTR)
+				return -3;
+#endif
+			sock_geterror("recv(): ", errbuf, errbuflen);
+			return -1;
+		}
+
+		if (nread == 0)
+		{
+			if (errbuf)
+			{
+				pcap_snprintf(errbuf, errbuflen,
+				    "The other host terminated the connection.");
+			}
+			return -1;
+		}
+
+		/*
+		 * Do we want to read the amount requested, or just return
+		 * what we got?
+		 */
+		if (!receiveall)
+		{
+			/*
+			 * Just return what we got.
+			 */
+			return (int) nread;
+		}
+
+		bufp += nread;
+		remaining -= nread;
+
+		if (remaining == 0)
+			return (int) size;
+	}
+}
+
+/*
+ * \brief It discards N bytes that are currently waiting to be read on the current socket.
+ *
+ * This function is useful in case we receive a message we cannot understand (e.g.
+ * wrong version number when receiving a network packet), so that we have to discard all
+ * data before reading a new message.
+ *
+ * This function will read 'size' bytes from the socket and discard them.
+ * It defines an internal buffer in which data will be copied; however, in case
+ * this buffer is not large enough, it will cycle in order to read everything as well.
+ *
+ * \param sock: the connected socket currently opened.
+ *
+ * \param size: number of bytes that have to be discarded.
+ *
+ * \param errbuf: a pointer to an user-allocated buffer that will contain the complete
+ * error message. This buffer has to be at least 'errbuflen' in length.
+ * It can be NULL; in this case the error cannot be printed.
+ *
+ * \param errbuflen: length of the buffer that will contains the error. The error message cannot be
+ * larger than 'errbuflen - 1' because the last char is reserved for the string terminator.
+ *
+ * \return '0' if everything is fine, '-1' if some errors occurred.
+ * The error message is returned in the 'errbuf' variable.
+ */
+int sock_discard(SOCKET sock, int size, char *errbuf, int errbuflen)
+{
+#define TEMP_BUF_SIZE 32768
+
+	char buffer[TEMP_BUF_SIZE];		/* network buffer, to be used when the message is discarded */
+
+	/*
+	 * A static allocation avoids the need of a 'malloc()' each time we want to discard a message
+	 * Our feeling is that a buffer if 32KB is enough for most of the application;
+	 * in case this is not enough, the "while" loop discards the message by calling the
+	 * sockrecv() several times.
+	 * We do not want to create a bigger variable because this causes the program to exit on
+	 * some platforms (e.g. BSD)
+	 */
+	while (size > TEMP_BUF_SIZE)
+	{
+		if (sock_recv(sock, buffer, TEMP_BUF_SIZE, SOCK_RECEIVEALL_YES, errbuf, errbuflen) == -1)
+			return -1;
+
+		size -= TEMP_BUF_SIZE;
+	}
+
+	/*
+	 * If there is still data to be discarded
+	 * In this case, the data can fit into the temporary buffer
+	 */
+	if (size)
+	{
+		if (sock_recv(sock, buffer, size, SOCK_RECEIVEALL_YES, errbuf, errbuflen) == -1)
+			return -1;
+	}
+
+	SOCK_ASSERT("I'm currently discarding data\n", 1);
+
+	return 0;
+}
+
+/*
+ * \brief Checks that one host (identified by the sockaddr_storage structure) belongs to an 'allowed list'.
+ *
+ * This function is useful after an accept() call in order to check if the connecting
+ * host is allowed to connect to me. To do that, we have a buffer that keeps the list of the
+ * allowed host; this function checks the sockaddr_storage structure of the connecting host
+ * against this host list, and it returns '0' is the host is included in this list.
+ *
+ * \param hostlist: pointer to a string that contains the list of the allowed host.
+ *
+ * \param sep: a string that keeps the separators used between the hosts (for example the
+ * space character) in the host list.
+ *
+ * \param from: a sockaddr_storage structure, as it is returned by the accept() call.
+ *
+ * \param errbuf: a pointer to an user-allocated buffer that will contain the complete
+ * error message. This buffer has to be at least 'errbuflen' in length.
+ * It can be NULL; in this case the error cannot be printed.
+ *
+ * \param errbuflen: length of the buffer that will contains the error. The error message cannot be
+ * larger than 'errbuflen - 1' because the last char is reserved for the string terminator.
+ *
+ * \return It returns:
+ * - '1' if the host list is empty
+ * - '0' if the host belongs to the host list (and therefore it is allowed to connect)
+ * - '-1' in case the host does not belong to the host list (and therefore it is not allowed to connect
+ * - '-2' in case or error. The error message is returned in the 'errbuf' variable.
+ */
+int sock_check_hostlist(char *hostlist, const char *sep, struct sockaddr_storage *from, char *errbuf, int errbuflen)
+{
+	/* checks if the connecting host is among the ones allowed */
+	if ((hostlist) && (hostlist[0]))
+	{
+		char *token;					/* temp, needed to separate items into the hostlist */
+		struct addrinfo *addrinfo, *ai_next;
+		char *temphostlist;
+		char *lasts;
+
+		/*
+		 * The problem is that strtok modifies the original variable by putting '0' at the end of each token
+		 * So, we have to create a new temporary string in which the original content is kept
+		 */
+		temphostlist = strdup(hostlist);
+		if (temphostlist == NULL)
+		{
+			sock_geterror("sock_check_hostlist(), malloc() failed", errbuf, errbuflen);
+			return -2;
+		}
+
+		token = pcap_strtok_r(temphostlist, sep, &lasts);
+
+		/* it avoids a warning in the compilation ('addrinfo used but not initialized') */
+		addrinfo = NULL;
+
+		while (token != NULL)
+		{
+			struct addrinfo hints;
+			int retval;
+
+			addrinfo = NULL;
+			memset(&hints, 0, sizeof(struct addrinfo));
+			hints.ai_family = PF_UNSPEC;
+			hints.ai_socktype = SOCK_STREAM;
+
+			retval = getaddrinfo(token, "0", &hints, &addrinfo);
+			if (retval != 0)
+			{
+				if (errbuf)
+					pcap_snprintf(errbuf, errbuflen, "getaddrinfo() %s", gai_strerror(retval));
+
+				SOCK_ASSERT(errbuf, 1);
+
+				/* Get next token */
+				token = pcap_strtok_r(NULL, sep, &lasts);
+				continue;
+			}
+
+			/* ai_next is required to preserve the content of addrinfo, in order to deallocate it properly */
+			ai_next = addrinfo;
+			while (ai_next)
+			{
+				if (sock_cmpaddr(from, (struct sockaddr_storage *) ai_next->ai_addr) == 0)
+				{
+					free(temphostlist);
+					return 0;
+				}
+
+				/*
+				 * If we are here, it means that the current address does not matches
+				 * Let's try with the next one in the header chain
+				 */
+				ai_next = ai_next->ai_next;
+			}
+
+			freeaddrinfo(addrinfo);
+			addrinfo = NULL;
+
+			/* Get next token */
+			token = pcap_strtok_r(NULL, sep, &lasts);
+		}
+
+		if (addrinfo)
+		{
+			freeaddrinfo(addrinfo);
+			addrinfo = NULL;
+		}
+
+		if (errbuf)
+			pcap_snprintf(errbuf, errbuflen, "The host is not in the allowed host list. Connection refused.");
+
+		free(temphostlist);
+		return -1;
+	}
+
+	/* No hostlist, so we have to return 'empty list' */
+	return 1;
+}
+
+/*
+ * \brief Compares two addresses contained into two sockaddr_storage structures.
+ *
+ * This function is useful to compare two addresses, given their internal representation,
+ * i.e. an sockaddr_storage structure.
+ *
+ * The two structures do not need to be sockaddr_storage; you can have both 'sockaddr_in' and
+ * sockaddr_in6, properly acsted in order to be compliant to the function interface.
+ *
+ * This function will return '0' if the two addresses matches, '-1' if not.
+ *
+ * \param first: a sockaddr_storage structure, (for example the one that is returned by an
+ * accept() call), containing the first address to compare.
+ *
+ * \param second: a sockaddr_storage structure containing the second address to compare.
+ *
+ * \return '0' if the addresses are equal, '-1' if they are different.
+ */
+int sock_cmpaddr(struct sockaddr_storage *first, struct sockaddr_storage *second)
+{
+	if (first->ss_family == second->ss_family)
+	{
+		if (first->ss_family == AF_INET)
+		{
+			if (memcmp(&(((struct sockaddr_in *) first)->sin_addr),
+				&(((struct sockaddr_in *) second)->sin_addr),
+				sizeof(struct in_addr)) == 0)
+				return 0;
+		}
+		else /* address family is AF_INET6 */
+		{
+			if (memcmp(&(((struct sockaddr_in6 *) first)->sin6_addr),
+				&(((struct sockaddr_in6 *) second)->sin6_addr),
+				sizeof(struct in6_addr)) == 0)
+				return 0;
+		}
+	}
+
+	return -1;
+}
+
+/*
+ * \brief It gets the address/port the system picked for this socket (on connected sockets).
+ *
+ * It is used to return the address and port the server picked for our socket on the local machine.
+ * It works only on:
+ * - connected sockets
+ * - server sockets
+ *
+ * On unconnected client sockets it does not work because the system dynamically chooses a port
+ * only when the socket calls a send() call.
+ *
+ * \param sock: the connected socket currently opened.
+ *
+ * \param address: it contains the address that will be returned by the function. This buffer
+ * must be properly allocated by the user. The address can be either literal or numeric depending
+ * on the value of 'Flags'.
+ *
+ * \param addrlen: the length of the 'address' buffer.
+ *
+ * \param port: it contains the port that will be returned by the function. This buffer
+ * must be properly allocated by the user.
+ *
+ * \param portlen: the length of the 'port' buffer.
+ *
+ * \param flags: a set of flags (the ones defined into the getnameinfo() standard socket function)
+ * that determine if the resulting address must be in numeric / literal form, and so on.
+ *
+ * \param errbuf: a pointer to an user-allocated buffer that will contain the complete
+ * error message. This buffer has to be at least 'errbuflen' in length.
+ * It can be NULL; in this case the error cannot be printed.
+ *
+ * \param errbuflen: length of the buffer that will contains the error. The error message cannot be
+ * larger than 'errbuflen - 1' because the last char is reserved for the string terminator.
+ *
+ * \return It returns '-1' if this function succeeds, '0' otherwise.
+ * The address and port corresponding are returned back in the buffers 'address' and 'port'.
+ * In any case, the returned strings are '0' terminated.
+ *
+ * \warning If the socket is using a connectionless protocol, the address may not be available
+ * until I/O occurs on the socket.
+ */
+int sock_getmyinfo(SOCKET sock, char *address, int addrlen, char *port, int portlen, int flags, char *errbuf, int errbuflen)
+{
+	struct sockaddr_storage mysockaddr;
+	socklen_t sockaddrlen;
+
+
+	sockaddrlen = sizeof(struct sockaddr_storage);
+
+	if (getsockname(sock, (struct sockaddr *) &mysockaddr, &sockaddrlen) == -1)
+	{
+		sock_geterror("getsockname(): ", errbuf, errbuflen);
+		return 0;
+	}
+	else
+	{
+		/* Returns the numeric address of the host that triggered the error */
+		return sock_getascii_addrport(&mysockaddr, address, addrlen, port, portlen, flags, errbuf, errbuflen);
+	}
+
+	return 0;
+}
+
+/*
+ * \brief It retrieves two strings containing the address and the port of a given 'sockaddr' variable.
+ *
+ * This function is basically an extended version of the inet_ntop(), which does not exist in
+ * Winsock because the same result can be obtained by using the getnameinfo().
+ * However, differently from inet_ntop(), this function is able to return also literal names
+ * (e.g. 'localhost') dependently from the 'Flags' parameter.
+ *
+ * The function accepts a sockaddr_storage variable (which can be returned by several functions
+ * like bind(), connect(), accept(), and more) and it transforms its content into a 'human'
+ * form. So, for instance, it is able to translate an hex address (stored in binary form) into
+ * a standard IPv6 address like "::1".
+ *
+ * The behavior of this function depends on the parameters we have in the 'Flags' variable, which
+ * are the ones allowed in the standard getnameinfo() socket function.
+ *
+ * \param sockaddr: a 'sockaddr_in' or 'sockaddr_in6' structure containing the address that
+ * need to be translated from network form into the presentation form. This structure must be
+ * zero-ed prior using it, and the address family field must be filled with the proper value.
+ * The user must cast any 'sockaddr_in' or 'sockaddr_in6' structures to 'sockaddr_storage' before
+ * calling this function.
+ *
+ * \param address: it contains the address that will be returned by the function. This buffer
+ * must be properly allocated by the user. The address can be either literal or numeric depending
+ * on the value of 'Flags'.
+ *
+ * \param addrlen: the length of the 'address' buffer.
+ *
+ * \param port: it contains the port that will be returned by the function. This buffer
+ * must be properly allocated by the user.
+ *
+ * \param portlen: the length of the 'port' buffer.
+ *
+ * \param flags: a set of flags (the ones defined into the getnameinfo() standard socket function)
+ * that determine if the resulting address must be in numeric / literal form, and so on.
+ *
+ * \param errbuf: a pointer to an user-allocated buffer that will contain the complete
+ * error message. This buffer has to be at least 'errbuflen' in length.
+ * It can be NULL; in this case the error cannot be printed.
+ *
+ * \param errbuflen: length of the buffer that will contains the error. The error message cannot be
+ * larger than 'errbuflen - 1' because the last char is reserved for the string terminator.
+ *
+ * \return It returns '-1' if this function succeeds, '0' otherwise.
+ * The address and port corresponding to the given SockAddr are returned back in the buffers 'address'
+ * and 'port'.
+ * In any case, the returned strings are '0' terminated.
+ */
+int sock_getascii_addrport(const struct sockaddr_storage *sockaddr, char *address, int addrlen, char *port, int portlen, int flags, char *errbuf, int errbuflen)
+{
+	socklen_t sockaddrlen;
+	int retval;					/* Variable that keeps the return value; */
+
+	retval = -1;
+
+#ifdef _WIN32
+	if (sockaddr->ss_family == AF_INET)
+		sockaddrlen = sizeof(struct sockaddr_in);
+	else
+		sockaddrlen = sizeof(struct sockaddr_in6);
+#else
+	sockaddrlen = sizeof(struct sockaddr_storage);
+#endif
+
+	if ((flags & NI_NUMERICHOST) == 0)	/* Check that we want literal names */
+	{
+		if ((sockaddr->ss_family == AF_INET6) &&
+			(memcmp(&((struct sockaddr_in6 *) sockaddr)->sin6_addr, "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0", sizeof(struct in6_addr)) == 0))
+		{
+			if (address)
+				strlcpy(address, SOCKET_NAME_NULL_DAD, addrlen);
+			return retval;
+		}
+	}
+
+	if (getnameinfo((struct sockaddr *) sockaddr, sockaddrlen, address, addrlen, port, portlen, flags) != 0)
+	{
+		/* If the user wants to receive an error message */
+		if (errbuf)
+		{
+			sock_geterror("getnameinfo(): ", errbuf, errbuflen);
+			errbuf[errbuflen - 1] = 0;
+		}
+
+		if (address)
+		{
+			strlcpy(address, SOCKET_NO_NAME_AVAILABLE, addrlen);
+			address[addrlen - 1] = 0;
+		}
+
+		if (port)
+		{
+			strlcpy(port, SOCKET_NO_PORT_AVAILABLE, portlen);
+			port[portlen - 1] = 0;
+		}
+
+		retval = 0;
+	}
+
+	return retval;
+}
+
+/*
+ * \brief It translates an address from the 'presentation' form into the 'network' form.
+ *
+ * This function basically replaces inet_pton(), which does not exist in Winsock because
+ * the same result can be obtained by using the getaddrinfo().
+ * An additional advantage is that 'Address' can be both a numeric address (e.g. '127.0.0.1',
+ * like in inet_pton() ) and a literal name (e.g. 'localhost').
+ *
+ * This function does the reverse job of sock_getascii_addrport().
+ *
+ * \param address: a zero-terminated string which contains the name you have to
+ * translate. The name can be either literal (e.g. 'localhost') or numeric (e.g. '::1').
+ *
+ * \param sockaddr: a user-allocated sockaddr_storage structure which will contains the
+ * 'network' form of the requested address.
+ *
+ * \param addr_family: a constant which can assume the following values:
+ * - 'AF_INET' if we want to ping an IPv4 host
+ * - 'AF_INET6' if we want to ping an IPv6 host
+ * - 'AF_UNSPEC' if we do not have preferences about the protocol used to ping the host
+ *
+ * \param errbuf: a pointer to an user-allocated buffer that will contain the complete
+ * error message. This buffer has to be at least 'errbuflen' in length.
+ * It can be NULL; in this case the error cannot be printed.
+ *
+ * \param errbuflen: length of the buffer that will contains the error. The error message cannot be
+ * larger than 'errbuflen - 1' because the last char is reserved for the string terminator.
+ *
+ * \return '-1' if the translation succeeded, '-2' if there was some non critical error, '0'
+ * otherwise. In case it fails, the content of the SockAddr variable remains unchanged.
+ * A 'non critical error' can occur in case the 'Address' is a literal name, which can be mapped
+ * to several network addresses (e.g. 'foo.bar.com' => '10.2.2.2' and '10.2.2.3'). In this case
+ * the content of the SockAddr parameter will be the address corresponding to the first mapping.
+ *
+ * \warning The sockaddr_storage structure MUST be allocated by the user.
+ */
+int sock_present2network(const char *address, struct sockaddr_storage *sockaddr, int addr_family, char *errbuf, int errbuflen)
+{
+	int retval;
+	struct addrinfo *addrinfo;
+	struct addrinfo hints;
+
+	memset(&hints, 0, sizeof(hints));
+
+	hints.ai_family = addr_family;
+
+	if ((retval = sock_initaddress(address, "22222" /* fake port */, &hints, &addrinfo, errbuf, errbuflen)) == -1)
+		return 0;
+
+	if (addrinfo->ai_family == PF_INET)
+		memcpy(sockaddr, addrinfo->ai_addr, sizeof(struct sockaddr_in));
+	else
+		memcpy(sockaddr, addrinfo->ai_addr, sizeof(struct sockaddr_in6));
+
+	if (addrinfo->ai_next != NULL)
+	{
+		freeaddrinfo(addrinfo);
+
+		if (errbuf)
+			pcap_snprintf(errbuf, errbuflen, "More than one socket requested; using the first one returned");
+		return -2;
+	}
+
+	freeaddrinfo(addrinfo);
+	return -1;
+}
diff --git a/sockutils.h b/sockutils.h
new file mode 100644
index 0000000..f50bbce
--- /dev/null
+++ b/sockutils.h
@@ -0,0 +1,241 @@
+/*
+ * Copyright (c) 2002 - 2003
+ * NetGroup, Politecnico di Torino (Italy)
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the Politecnico di Torino nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+#ifndef __SOCKUTILS_H__
+#define __SOCKUTILS_H__
+
+#if _MSC_VER > 1000
+#pragma once
+#endif
+
+#ifdef _WIN32
+  /* Windows */
+  /*
+   * Prevents a compiler warning in case this was already defined (to
+   * avoid that windows.h includes winsock.h)
+   */
+  #ifdef _WINSOCKAPI_
+    #undef _WINSOCKAPI_
+  #endif
+  /* Need windef.h for defines used in winsock2.h under MingW32 */
+  #ifdef __MINGW32__
+    #include <windef.h>
+  #endif
+  #include <winsock2.h>
+  #include <ws2tcpip.h>
+#else
+  /* UN*X */
+  #include <stdio.h>
+  #include <string.h>	/* for memset() */
+  #include <sys/types.h>
+  #include <sys/socket.h>
+  #include <netdb.h>	/* DNS lookup */
+  #include <unistd.h>	/* close() */
+  #include <errno.h>	/* errno() */
+  #include <netinet/in.h> /* for sockaddr_in, in BSD at least */
+  #include <arpa/inet.h>
+  #include <net/if.h>
+
+  /*!
+   * \brief In Winsock, a socket handle is of type SOCKET; in UN*X, it's
+   * a file descriptor, and therefore a signed integer.
+   * We define SOCKET to be a signed integer on UN*X, so that it can
+   * be used on both platforms.
+   */
+  #ifndef SOCKET
+    #define SOCKET int
+  #endif
+
+  /*!
+   * \brief In Winsock, the error return if socket() fails is INVALID_SOCKET;
+   * in UN*X, it's -1.
+   * We define INVALID_SOCKET to be -1 on UN*X, so that it can be used on
+   * both platforms.
+   */
+  #ifndef INVALID_SOCKET
+    #define INVALID_SOCKET -1
+  #endif
+#endif
+
+/*
+ * MingW headers include this definition, but only for Windows XP and above.
+ * MSDN states that this function is available for most versions on Windows.
+ */
+#if ((defined(__MINGW32__)) && (_WIN32_WINNT < 0x0501))
+int WSAAPI getnameinfo(const struct sockaddr*,socklen_t,char*,DWORD,
+	char*,DWORD,int);
+#endif
+
+/*
+ * \defgroup SockUtils Cross-platform socket utilities (IPv4-IPv6)
+ */
+
+/*
+ * \addtogroup SockUtils
+ * \{
+ */
+
+/*
+ * \defgroup ExportedStruct Exported Structures and Definitions
+ */
+
+/*
+ * \addtogroup ExportedStruct
+ * \{
+ */
+
+/*
+ * Some minor differences between UN*X sockets and and Winsock sockets.
+ */
+#ifdef _WIN32
+  /*
+   * Winsock doesn't have these UN*X types; they're used in the UN*X
+   * sockets API.
+   *
+   * XXX - do we need to worry about UN*Xes so old that *they* don't
+   * have them, either?
+   */
+  typedef int socklen_t;
+#else
+  /*!
+   * \brief In Winsock, the close() call cannot be used on a socket;
+   * closesocket() must be used.
+   * We define closesocket() to be a wrapper around close() on UN*X,
+   * so that it can be used on both platforms.
+   */
+  #define closesocket(a) close(a)
+#endif
+
+/*
+ * \brief DEBUG facility: it prints an error message on the screen (stderr)
+ *
+ * This macro prints the error on the standard error stream (stderr);
+ * if we are working in debug mode (i.e. there is no NDEBUG defined) and we are in
+ * Microsoft Visual C++, the error message will appear on the MSVC console as well.
+ *
+ * When NDEBUG is defined, this macro is empty.
+ *
+ * \param msg: the message you want to print.
+ *
+ * \param expr: 'false' if you want to abort the program, 'true' it you want
+ * to print the message and continue.
+ *
+ * \return No return values.
+ */
+#ifdef NDEBUG
+  #define SOCK_ASSERT(msg, expr) ((void)0)
+#else
+  #include <assert.h>
+  #if (defined(_WIN32) && defined(_MSC_VER))
+    #include <crtdbg.h>				/* for _CrtDbgReport */
+    /* Use MessageBox(NULL, msg, "warning", MB_OK)' instead of the other calls if you want to debug a Win32 service */
+    /* Remember to activate the 'allow service to interact with desktop' flag of the service */
+    #define SOCK_ASSERT(msg, expr) { _CrtDbgReport(_CRT_WARN, NULL, 0, NULL, "%s\n", msg); fprintf(stderr, "%s\n", msg); assert(expr); }
+  #else
+    #define SOCK_ASSERT(msg, expr) { fprintf(stderr, "%s\n", msg); assert(expr); }
+  #endif
+#endif
+
+/****************************************************
+ *                                                  *
+ * Exported functions / definitions                 *
+ *                                                  *
+ ****************************************************/
+
+/* 'checkonly' flag, into the rpsock_bufferize() */
+#define SOCKBUF_CHECKONLY 1
+/* no 'checkonly' flag, into the rpsock_bufferize() */
+#define SOCKBUF_BUFFERIZE 0
+
+/* no 'server' flag; it opens a client socket */
+#define SOCKOPEN_CLIENT 0
+/* 'server' flag; it opens a server socket */
+#define SOCKOPEN_SERVER 1
+
+/* Changes the behaviour of the sock_recv(); it does not wait to receive all data */
+#define SOCK_RECEIVEALL_NO 0
+/* Changes the behaviour of the sock_recv(); it waits to receive all data */
+#define SOCK_RECEIVEALL_YES 1
+
+/*
+ * \}
+ */
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/*
+ * \defgroup ExportedFunc Exported Functions
+ */
+
+/*
+ * \addtogroup ExportedFunc
+ * \{
+ */
+
+int sock_init(char *errbuf, int errbuflen);
+void sock_cleanup(void);
+/* It is 'public' because there are calls (like accept() ) which are not managed from inside the sockutils files */
+void sock_geterror(const char *caller, char *errbuf, int errbufsize);
+int sock_initaddress(const char *address, const char *port,
+    struct addrinfo *hints, struct addrinfo **addrinfo,
+    char *errbuf, int errbuflen);
+int sock_recv(SOCKET socket, void *buffer, size_t size, int receiveall,
+    char *errbuf, int errbuflen);
+SOCKET sock_open(struct addrinfo *addrinfo, int server, int nconn, char *errbuf, int errbuflen);
+int sock_close(SOCKET sock, char *errbuf, int errbuflen);
+
+int sock_send(SOCKET socket, const char *buffer, int size, char *errbuf, int errbuflen);
+int sock_bufferize(const char *buffer, int size, char *tempbuf, int *offset, int totsize, int checkonly, char *errbuf, int errbuflen);
+int sock_discard(SOCKET socket, int size, char *errbuf, int errbuflen);
+int	sock_check_hostlist(char *hostlist, const char *sep, struct sockaddr_storage *from, char *errbuf, int errbuflen);
+int sock_cmpaddr(struct sockaddr_storage *first, struct sockaddr_storage *second);
+
+int sock_getmyinfo(SOCKET sock, char *address, int addrlen, char *port, int portlen, int flags, char *errbuf, int errbuflen);
+
+int sock_getascii_addrport(const struct sockaddr_storage *sockaddr, char *address, int addrlen, char *port, int portlen, int flags, char *errbuf, int errbuflen);
+int sock_present2network(const char *address, struct sockaddr_storage *sockaddr, int addr_family, char *errbuf, int errbuflen);
+
+#ifdef __cplusplus
+}
+#endif
+
+/*
+ * \}
+ */
+
+/*
+ * \}
+ */
+
+#endif
diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt
new file mode 100644
index 0000000..fc7919e
--- /dev/null
+++ b/tests/CMakeLists.txt
@@ -0,0 +1,42 @@
+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/can_set_rfmon_test.c b/tests/can_set_rfmon_test.c
new file mode 100644
index 0000000..f1644e6
--- /dev/null
+++ b/tests/can_set_rfmon_test.c
@@ -0,0 +1,92 @@
+/*
+ * Copyright (c) 1988, 1989, 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1997, 2000
+ *	The Regents of the University of California.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that: (1) source code distributions
+ * retain the above copyright notice and this paragraph in its entirety, (2)
+ * distributions including binary code include the above copyright notice and
+ * this paragraph in its entirety in the documentation or other materials
+ * provided with the distribution, and (3) all advertising materials mentioning
+ * features or use of this software display the following acknowledgement:
+ * ``This product includes software developed by the University of California,
+ * Lawrence Berkeley Laboratory and its contributors.'' Neither the name of
+ * the University nor the names of its contributors may be used to endorse
+ * or promote products derived from this software without specific prior
+ * written permission.
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+ */
+
+#ifndef lint
+static const char copyright[] _U_ =
+    "@(#) Copyright (c) 1988, 1989, 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1997, 2000\n\
+The Regents of the University of California.  All rights reserved.\n";
+#endif
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <stdarg.h>
+
+#include <pcap.h>
+
+static const char *program_name;
+
+/* Forwards */
+static void error(const char *, ...);
+
+int
+main(int argc, char **argv)
+{
+	const char *cp;
+	pcap_t *pd;
+	char ebuf[PCAP_ERRBUF_SIZE];
+	int status;
+
+	if ((cp = strrchr(argv[0], '/')) != NULL)
+		program_name = cp + 1;
+	else
+		program_name = argv[0];
+
+	if (argc != 2) {
+		fprintf(stderr, "Usage: %s <device>\n", program_name);
+		return 2;
+	}
+
+	pd = pcap_create(argv[1], ebuf);
+	if (pd == NULL)
+		error("%s", ebuf);
+	status = pcap_can_set_rfmon(pd);
+	if (status < 0) {
+		if (status == PCAP_ERROR)
+			error("%s: pcap_can_set_rfmon failed: %s", argv[1],
+			    pcap_geterr(pd));
+		else
+			error("%s: pcap_can_set_rfmon failed: %s", argv[1],
+			    pcap_statustostr(status));
+		return 1;
+	}
+	printf("%s: Monitor mode %s be set\n", argv[1], status ? "can" : "cannot");
+	return 0;
+}
+
+/* VARARGS */
+static void
+error(const char *fmt, ...)
+{
+	va_list ap;
+
+	(void)fprintf(stderr, "%s: ", program_name);
+	va_start(ap, fmt);
+	(void)vfprintf(stderr, fmt, ap);
+	va_end(ap);
+	if (*fmt) {
+		fmt += strlen(fmt);
+		if (fmt[-1] != '\n')
+			(void)fputc('\n', stderr);
+	}
+	exit(1);
+	/* NOTREACHED */
+}
diff --git a/tests/capturetest.c b/tests/capturetest.c
index e70e69a..14b1554 100644
--- a/tests/capturetest.c
+++ b/tests/capturetest.c
@@ -20,7 +20,7 @@
  */
 
 #ifndef lint
-static const char copyright[] =
+static const char copyright[] _U_ =
     "@(#) Copyright (c) 1988, 1989, 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1997, 2000\n\
 The Regents of the University of California.  All rights reserved.\n";
 #endif
@@ -30,29 +30,76 @@
 #include <string.h>
 #include <stdarg.h>
 #include <limits.h>
+#ifdef _WIN32
+#include "getopt.h"
+#else
 #include <unistd.h>
+#endif
 #include <errno.h>
 #include <sys/types.h>
-#include <sys/select.h>
-#include <poll.h>
 
 #include <pcap.h>
 
 static char *program_name;
 
+/*
+ * This was introduced by Clang:
+ *
+ *     http://clang.llvm.org/docs/LanguageExtensions.html#has-attribute
+ *
+ * in some version (which version?); it has been picked up by GCC 5.0.
+ */
+#ifndef __has_attribute
+  /*
+   * It's a macro, so you can check whether it's defined to check
+   * whether it's supported.
+   *
+   * If it's not, define it to always return 0, so that we move on to
+   * the fallback checks.
+   */
+  #define __has_attribute(x) 0
+#endif
+
+#if __has_attribute(noreturn) \
+    || (defined(__GNUC__) && ((__GNUC__ * 100 + __GNUC_MINOR__) >= 205)) \
+    || (defined(__SUNPRO_C) && (__SUNPRO_C >= 0x590)) \
+    || (defined(__xlC__) && __xlC__ >= 0x0A01) \
+    || (defined(__HP_aCC) && __HP_aCC >= 61000)
+  /*
+   * Compiler with support for it, or GCC 2.5 and later, or Solaris Studio 12
+   * (Sun C 5.9) and later, or IBM XL C 10.1 and later (do any earlier
+   * versions of XL C support this?), or HP aCC A.06.10 and later.
+   */
+  #define PCAP_NORETURN __attribute((noreturn))
+#elif defined( _MSC_VER )
+  #define PCAP_NORETURN __declspec(noreturn)
+#else
+  #define PCAP_NORETURN
+#endif
+
+#if __has_attribute(__format__) \
+    || (defined(__GNUC__) && ((__GNUC__ * 100 + __GNUC_MINOR__) >= 203)) \
+    || (defined(__xlC__) && __xlC__ >= 0x0A01) \
+    || (defined(__HP_aCC) && __HP_aCC >= 61000)
+  /*
+   * Compiler with support for it, or GCC 2.3 and later, or IBM XL C 10.1
+   * and later (do any earlier versions of XL C support this?),
+   * or HP aCC A.06.10 and later.
+   */
+  #define PCAP_PRINTFLIKE(x,y) __attribute__((__format__(__printf__,x,y)))
+#else
+  #define PCAP_PRINTFLIKE(x,y)
+#endif
+
 /* Forwards */
 static void countme(u_char *, const struct pcap_pkthdr *, const u_char *);
-static void usage(void) __attribute__((noreturn));
-static void error(const char *, ...);
-static void warning(const char *, ...);
+static void PCAP_NORETURN usage(void);
+static void PCAP_NORETURN error(const char *, ...) PCAP_PRINTFLIKE(1, 2);
+static void warning(const char *, ...) PCAP_PRINTFLIKE(1, 2);
 static char *copy_argv(char **);
 
 static pcap_t *pd;
 
-extern int optind;
-extern int opterr;
-extern char *optarg;
-
 int
 main(int argc, char **argv)
 {
diff --git a/tests/filtertest.c b/tests/filtertest.c
index e45db21..d4440eb 100644
--- a/tests/filtertest.c
+++ b/tests/filtertest.c
@@ -34,29 +34,78 @@
 #include <stdlib.h>
 #include <string.h>
 #include <stdarg.h>
+#ifdef _WIN32
+#include "getopt.h"
+#else
 #include <unistd.h>
+#endif
 #include <fcntl.h>
 #include <errno.h>
-#include <arpa/inet.h>
+#ifdef _WIN32
+  #include <winsock2.h>
+  typedef unsigned __int32 in_addr_t;
+#else
+  #include <arpa/inet.h>
+#endif
 #include <sys/types.h>
 #include <sys/stat.h>
 
-#ifndef HAVE___ATTRIBUTE__
-#define __attribute__(x)
+/*
+ * This was introduced by Clang:
+ *
+ *     http://clang.llvm.org/docs/LanguageExtensions.html#has-attribute
+ *
+ * in some version (which version?); it has been picked up by GCC 5.0.
+ */
+#ifndef __has_attribute
+  /*
+   * It's a macro, so you can check whether it's defined to check
+   * whether it's supported.
+   *
+   * If it's not, define it to always return 0, so that we move on to
+   * the fallback checks.
+   */
+  #define __has_attribute(x) 0
+#endif
+
+#if __has_attribute(noreturn) \
+    || (defined(__GNUC__) && ((__GNUC__ * 100 + __GNUC_MINOR__) >= 205)) \
+    || (defined(__SUNPRO_C) && (__SUNPRO_C >= 0x590)) \
+    || (defined(__xlC__) && __xlC__ >= 0x0A01) \
+    || (defined(__HP_aCC) && __HP_aCC >= 61000)
+  /*
+   * Compiler with support for it, or GCC 2.5 and later, or Solaris Studio 12
+   * (Sun C 5.9) and later, or IBM XL C 10.1 and later (do any earlier
+   * versions of XL C support this?), or HP aCC A.06.10 and later.
+   */
+  #define PCAP_NORETURN __attribute((noreturn))
+#elif defined( _MSC_VER )
+  #define PCAP_NORETURN __declspec(noreturn)
+#else
+  #define PCAP_NORETURN
+#endif
+
+#if __has_attribute(__format__) \
+    || (defined(__GNUC__) && ((__GNUC__ * 100 + __GNUC_MINOR__) >= 203)) \
+    || (defined(__xlC__) && __xlC__ >= 0x0A01) \
+    || (defined(__HP_aCC) && __HP_aCC >= 61000)
+  /*
+   * Compiler with support for it, or GCC 2.3 and later, or IBM XL C 10.1
+   * and later (do any earlier versions of XL C support this?),
+   * or HP aCC A.06.10 and later.
+   */
+  #define PCAP_PRINTFLIKE(x,y) __attribute__((__format__(__printf__,x,y)))
+#else
+  #define PCAP_PRINTFLIKE(x,y)
 #endif
 
 static char *program_name;
 
 /* Forwards */
-static void usage(void) __attribute__((noreturn));
-static void error(const char *, ...)
-    __attribute__((noreturn, format (printf, 1, 2)));
-static void warn(const char *, ...)
-    __attribute__((format (printf, 1, 2)));
+static void PCAP_NORETURN usage(void);
+static void PCAP_NORETURN error(const char *, ...) PCAP_PRINTFLIKE(1, 2);
+static void warn(const char *, ...) PCAP_PRINTFLIKE(1, 2);
 
-extern int optind;
-extern int opterr;
-extern char *optarg;
 #ifdef BDEBUG
 int dflag;
 #endif
@@ -194,16 +243,16 @@
 	pcap_t *pd;
 	struct bpf_program fcode;
 
-#ifdef WIN32
+#ifdef _WIN32
 	if(wsockinit() != 0) return 1;
-#endif /* WIN32 */
+#endif /* _WIN32 */
 
 #ifndef BDEBUG
 	dflag = 1;
 #else
 	/* if optimizer debugging is enabled, output DOT graph
 	 * `dflag=4' is equivalent to -dddd to follow -d/-dd/-ddd
-     * convention in tcpdump command line
+	 * convention in tcpdump command line
 	 */
 	dflag = 4;
 #endif
@@ -236,7 +285,7 @@
 			in_addr_t addr;
 
 			addr = inet_addr(optarg);
-			if (addr == INADDR_NONE)
+			if (addr == (in_addr_t)(-1))
 				error("invalid netmask %s", optarg);
 			netmask = addr;
 			break;
diff --git a/tests/findalldevstest.c b/tests/findalldevstest.c
index 6d452f8..5925bf6 100644
--- a/tests/findalldevstest.c
+++ b/tests/findalldevstest.c
@@ -4,10 +4,14 @@
 
 #include <stdlib.h>
 #include <sys/types.h>
-#include <sys/socket.h>
-#include <netinet/in.h>
-#include <arpa/inet.h>
-#include <netdb.h>
+#ifdef _WIN32
+  #include <winsock2.h>
+#else
+  #include <sys/socket.h>
+  #include <netinet/in.h>
+  #include <arpa/inet.h>
+  #include <netdb.h>
+#endif
 
 #include <pcap.h>
 
@@ -63,12 +67,27 @@
 #ifdef INET6
   char ntop_buf[INET6_ADDRSTRLEN];
 #endif
+  const char *sep;
   int status = 1; /* success */
 
   printf("%s\n",d->name);
   if (d->description)
     printf("\tDescription: %s\n",d->description);
-  printf("\tLoopback: %s\n",(d->flags & PCAP_IF_LOOPBACK)?"yes":"no");
+  printf("\tFlags: ");
+  sep = "";
+  if (d->flags & PCAP_IF_UP) {
+    printf("%sUP", sep);
+    sep = ", ";
+  }
+  if (d->flags & PCAP_IF_RUNNING) {
+    printf("%sRUNNING", sep);
+    sep = ", ";
+  }
+  if (d->flags & PCAP_IF_LOOPBACK) {
+    printf("%sLOOPBACK", sep);
+    sep = ", ";
+  }
+  printf("\n");
 
   for(a=d->addresses;a;a=a->next) {
     if (a->addr != NULL)
diff --git a/tests/opentest.c b/tests/opentest.c
index 0c91531..b6d634f 100644
--- a/tests/opentest.c
+++ b/tests/opentest.c
@@ -20,7 +20,7 @@
  */
 
 #ifndef lint
-static const char copyright[] =
+static const char copyright[] _U_ =
     "@(#) Copyright (c) 1988, 1989, 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1997, 2000\n\
 The Regents of the University of California.  All rights reserved.\n";
 #endif
@@ -30,21 +30,70 @@
 #include <stdlib.h>
 #include <string.h>
 #include <stdarg.h>
+#ifdef _WIN32
+#include "getopt.h"
+#else
 #include <unistd.h>
+#endif
 #include <errno.h>
 
 #define MAXIMUM_SNAPLEN		65535
 
 static char *program_name;
 
-/* Forwards */
-static void usage(void) __attribute__((noreturn));
-static void error(const char *, ...);
-static void warning(const char *, ...);
+/*
+ * This was introduced by Clang:
+ *
+ *     http://clang.llvm.org/docs/LanguageExtensions.html#has-attribute
+ *
+ * in some version (which version?); it has been picked up by GCC 5.0.
+ */
+#ifndef __has_attribute
+  /*
+   * It's a macro, so you can check whether it's defined to check
+   * whether it's supported.
+   *
+   * If it's not, define it to always return 0, so that we move on to
+   * the fallback checks.
+   */
+  #define __has_attribute(x) 0
+#endif
 
-extern int optind;
-extern int opterr;
-extern char *optarg;
+#if __has_attribute(noreturn) \
+    || (defined(__GNUC__) && ((__GNUC__ * 100 + __GNUC_MINOR__) >= 205)) \
+    || (defined(__SUNPRO_C) && (__SUNPRO_C >= 0x590)) \
+    || (defined(__xlC__) && __xlC__ >= 0x0A01) \
+    || (defined(__HP_aCC) && __HP_aCC >= 61000)
+  /*
+   * Compiler with support for it, or GCC 2.5 and later, or Solaris Studio 12
+   * (Sun C 5.9) and later, or IBM XL C 10.1 and later (do any earlier
+   * versions of XL C support this?), or HP aCC A.06.10 and later.
+   */
+  #define PCAP_NORETURN __attribute((noreturn))
+#elif defined( _MSC_VER )
+  #define PCAP_NORETURN __declspec(noreturn)
+#else
+  #define PCAP_NORETURN
+#endif
+
+#if __has_attribute(__format__) \
+    || (defined(__GNUC__) && ((__GNUC__ * 100 + __GNUC_MINOR__) >= 203)) \
+    || (defined(__xlC__) && __xlC__ >= 0x0A01) \
+    || (defined(__HP_aCC) && __HP_aCC >= 61000)
+  /*
+   * Compiler with support for it, or GCC 2.3 and later, or IBM XL C 10.1
+   * and later (do any earlier versions of XL C support this?),
+   * or HP aCC A.06.10 and later.
+   */
+  #define PCAP_PRINTFLIKE(x,y) __attribute__((__format__(__printf__,x,y)))
+#else
+  #define PCAP_PRINTFLIKE(x,y)
+#endif
+
+/* Forwards */
+static void PCAP_NORETURN usage(void);
+static void PCAP_NORETURN error(const char *, ...) PCAP_PRINTFLIKE(1, 2);
+static void warning(const char *, ...) PCAP_PRINTFLIKE(1, 2);
 
 int
 main(int argc, char **argv)
@@ -113,10 +162,15 @@
 		}
 	}
 
+	if (device == NULL) {
+		device = pcap_lookupdev(ebuf);
+		if (device == NULL)
+			error("pcap_lookupdev failed: %s", ebuf);
+	}
 	if (useactivate) {
 		pd = pcap_create(device, ebuf);
 		if (pd == NULL)
-			error("%s", ebuf);
+			error("%s: pcap_create failed: %s", device, ebuf);
 		status = pcap_set_snaplen(pd, snaplen);
 		if (status != 0)
 			error("%s: pcap_set_snaplen failed: %s",
@@ -157,7 +211,8 @@
 			 */
 			warning("%s: %s\n(%s)", device,
 			    pcap_statustostr(status), pcap_geterr(pd));
-		}
+		} else
+			printf("%s opened successfully\n", device);
 	} else {
 		*ebuf = '\0';
 		pd = pcap_open_live(device, 65535, 0, 1000, ebuf);
@@ -165,6 +220,8 @@
 			error("%s", ebuf);
 		else if (*ebuf)
 			warning("%s", ebuf);
+		else
+			printf("%s opened successfully\n", device);
 	}
 	pcap_close(pd);
 	exit(status < 0 ? 1 : 0);
diff --git a/tests/reactivatetest.c b/tests/reactivatetest.c
index 9031a64..2e1b7b6 100644
--- a/tests/reactivatetest.c
+++ b/tests/reactivatetest.c
@@ -20,7 +20,7 @@
  */
 
 #ifndef lint
-static const char copyright[] =
+static const char copyright[] _U_ =
     "@(#) Copyright (c) 1988, 1989, 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1997, 2000\n\
 The Regents of the University of California.  All rights reserved.\n";
 #endif
diff --git a/tests/selpolltest.c b/tests/selpolltest.c
index d94fb56..4c1415b 100644
--- a/tests/selpolltest.c
+++ b/tests/selpolltest.c
@@ -20,11 +20,19 @@
  */
 
 #ifndef lint
-static const char copyright[] =
+static const char copyright[] _U_ =
     "@(#) Copyright (c) 1988, 1989, 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1997, 2000\n\
 The Regents of the University of California.  All rights reserved.\n";
 #endif
 
+/*
+ * Tests how select() and poll() behave on the selectable file descriptor
+ * for a pcap_t.
+ *
+ * This would be significantly different on Windows, as it'd test
+ * how WaitForMultipleObjects() would work on the event handle for a
+ * pcap_t.
+ */
 #include <pcap.h>
 #include <stdio.h>
 #include <stdlib.h>
@@ -33,24 +41,73 @@
 #include <unistd.h>
 #include <errno.h>
 #include <sys/types.h>
+#ifdef HAVE_SYS_SELECT_H
 #include <sys/select.h>
+#else
+#include <sys/time.h>	/* older UN*Xes */
+#endif
 #include <poll.h>
 
 char *program_name;
 
+/*
+ * This was introduced by Clang:
+ *
+ *     http://clang.llvm.org/docs/LanguageExtensions.html#has-attribute
+ *
+ * in some version (which version?); it has been picked up by GCC 5.0.
+ */
+#ifndef __has_attribute
+  /*
+   * It's a macro, so you can check whether it's defined to check
+   * whether it's supported.
+   *
+   * If it's not, define it to always return 0, so that we move on to
+   * the fallback checks.
+   */
+  #define __has_attribute(x) 0
+#endif
+
+#if __has_attribute(noreturn) \
+    || (defined(__GNUC__) && ((__GNUC__ * 100 + __GNUC_MINOR__) >= 205)) \
+    || (defined(__SUNPRO_C) && (__SUNPRO_C >= 0x590)) \
+    || (defined(__xlC__) && __xlC__ >= 0x0A01) \
+    || (defined(__HP_aCC) && __HP_aCC >= 61000)
+  /*
+   * Compiler with support for it, or GCC 2.5 and later, or Solaris Studio 12
+   * (Sun C 5.9) and later, or IBM XL C 10.1 and later (do any earlier
+   * versions of XL C support this?), or HP aCC A.06.10 and later.
+   */
+  #define PCAP_NORETURN __attribute((noreturn))
+#elif defined( _MSC_VER )
+  #define PCAP_NORETURN __declspec(noreturn)
+#else
+  #define PCAP_NORETURN
+#endif
+
+#if __has_attribute(__format__) \
+    || (defined(__GNUC__) && ((__GNUC__ * 100 + __GNUC_MINOR__) >= 203)) \
+    || (defined(__xlC__) && __xlC__ >= 0x0A01) \
+    || (defined(__HP_aCC) && __HP_aCC >= 61000)
+  /*
+   * Compiler with support for it, or GCC 2.3 and later, or IBM XL C 10.1
+   * and later (do any earlier versions of XL C support this?),
+   * or HP aCC A.06.10 and later.
+   */
+  #define PCAP_PRINTFLIKE(x,y) __attribute__((__format__(__printf__,x,y)))
+#else
+  #define PCAP_PRINTFLIKE(x,y)
+#endif
+
 /* Forwards */
 static void countme(u_char *, const struct pcap_pkthdr *, const u_char *);
-static void usage(void) __attribute__((noreturn));
-static void error(const char *, ...);
-static void warning(const char *, ...);
+static void PCAP_NORETURN usage(void);
+static void PCAP_NORETURN error(const char *, ...) PCAP_PRINTFLIKE(1, 2);
+static void warning(const char *, ...) PCAP_PRINTFLIKE(1, 2);
 static char *copy_argv(char **);
 
 static pcap_t *pd;
 
-extern int optind;
-extern int opterr;
-extern char *optarg;
-
 int
 main(int argc, char **argv)
 {
diff --git a/tests/valgrindtest.c b/tests/valgrindtest.c
index 72786e4..011fe11 100644
--- a/tests/valgrindtest.c
+++ b/tests/valgrindtest.c
@@ -19,6 +19,30 @@
  * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
  */
 
+/*
+ * This doesn't actually test libpcap itself; it tests whether
+ * valgrind properly handles the APIs libpcap uses.  If it doesn't,
+ * we end up getting patches submitted to "fix" references that
+ * valgrind claims are being made to uninitialized data, when, in
+ * fact, the OS isn't making any such references - or we get
+ * valgrind *not* detecting *actual* incorrect references.
+ *
+ * Both BPF and Linux socket filters aren't handled correctly
+ * by some versions of valgrind.  See valgrind bug 318203 for
+ * Linux:
+ *
+ *	https://bugs.kde.org/show_bug.cgi?id=318203
+ *
+ * and valgrind bug 312989 for OS X:
+ *
+ *	https://bugs.kde.org/show_bug.cgi?id=312989
+ *
+ * The fixes for both of those are checked into the official valgrind
+ * repository.
+ *
+ * The unofficial FreeBSD port has similar issues to the official OS X
+ * port, for similar reasons.
+ */
 #ifndef lint
 static const char copyright[] _U_ =
     "@(#) Copyright (c) 1988, 1989, 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1997, 2000\n\
@@ -72,22 +96,62 @@
 #endif
 
 #include <pcap.h>
-#ifndef HAVE___ATTRIBUTE__
-#define __attribute__(x)
-#endif
 
 static char *program_name;
 
-/* Forwards */
-static void usage(void) __attribute__((noreturn));
-static void error(const char *, ...)
-    __attribute__((noreturn, format (printf, 1, 2)));
-static void warning(const char *, ...)
-    __attribute__((format (printf, 1, 2)));
+/*
+ * This was introduced by Clang:
+ *
+ *     http://clang.llvm.org/docs/LanguageExtensions.html#has-attribute
+ *
+ * in some version (which version?); it has been picked up by GCC 5.0.
+ */
+#ifndef __has_attribute
+  /*
+   * It's a macro, so you can check whether it's defined to check
+   * whether it's supported.
+   *
+   * If it's not, define it to always return 0, so that we move on to
+   * the fallback checks.
+   */
+  #define __has_attribute(x) 0
+#endif
 
-extern int optind;
-extern int opterr;
-extern char *optarg;
+#if __has_attribute(noreturn) \
+    || (defined(__GNUC__) && ((__GNUC__ * 100 + __GNUC_MINOR__) >= 205)) \
+    || (defined(__SUNPRO_C) && (__SUNPRO_C >= 0x590)) \
+    || (defined(__xlC__) && __xlC__ >= 0x0A01) \
+    || (defined(__HP_aCC) && __HP_aCC >= 61000)
+  /*
+   * Compiler with support for it, or GCC 2.5 and later, or Solaris Studio 12
+   * (Sun C 5.9) and later, or IBM XL C 10.1 and later (do any earlier
+   * versions of XL C support this?), or HP aCC A.06.10 and later.
+   */
+  #define PCAP_NORETURN __attribute((noreturn))
+#elif defined( _MSC_VER )
+  #define PCAP_NORETURN __declspec(noreturn)
+#else
+  #define PCAP_NORETURN
+#endif
+
+#if __has_attribute(__format__) \
+    || (defined(__GNUC__) && ((__GNUC__ * 100 + __GNUC_MINOR__) >= 203)) \
+    || (defined(__xlC__) && __xlC__ >= 0x0A01) \
+    || (defined(__HP_aCC) && __HP_aCC >= 61000)
+  /*
+   * Compiler with support for it, or GCC 2.3 and later, or IBM XL C 10.1
+   * and later (do any earlier versions of XL C support this?),
+   * or HP aCC A.06.10 and later.
+   */
+  #define PCAP_PRINTFLIKE(x,y) __attribute__((__format__(__printf__,x,y)))
+#else
+  #define PCAP_PRINTFLIKE(x,y)
+#endif
+
+/* Forwards */
+static void PCAP_NORETURN usage(void);
+static void PCAP_NORETURN error(const char *, ...) PCAP_PRINTFLIKE(1, 2);
+static void warning(const char *, ...) PCAP_PRINTFLIKE(1, 2);
 
 /*
  * On Windows, we need to open the file in binary mode, so that
diff --git a/version.c b/version.c
index 482671d..15f6baf 100644
--- a/version.c
+++ b/version.c
@@ -1 +1,3 @@
-char pcap_version[] = "1.7.4";
+#include <pcap/export-defs.h>
+PCAP_API_DEF
+char pcap_version[] = "1.8.1";
diff --git a/version.h b/version.h
deleted file mode 100644
index a8b2df8..0000000
--- a/version.h
+++ /dev/null
@@ -1 +0,0 @@
-static const char pcap_version_string[] = "libpcap version 1.7.4";